├── .gitattributes
├── doc
├── img
│ ├── app.png
│ ├── Userguide.png
│ └── awsconfigure.png
└── tasks.txt
├── src
├── KeyConvert
│ ├── app.rc
│ ├── app.ico
│ ├── Resource.h
│ ├── KeyConvert.h
│ ├── CLRTest
│ │ ├── App.config
│ │ ├── Properties
│ │ │ ├── Settings.settings
│ │ │ ├── Settings.Designer.cs
│ │ │ ├── AssemblyInfo.cs
│ │ │ ├── Resources.Designer.cs
│ │ │ └── Resources.resx
│ │ ├── App.xaml
│ │ ├── App.xaml.cs
│ │ ├── MainWindow.xaml
│ │ ├── MainWindow.xaml.cs
│ │ └── CLRTest.csproj
│ ├── CLR.h
│ ├── AssemblyInfo.cpp
│ ├── CLR.cpp
│ ├── KeyConvert.cpp
│ ├── puttymem.h
│ ├── CLR.sln
│ ├── CLR.vcxproj.filters
│ ├── misc.h
│ ├── sshbn.h
│ ├── CLR.vcxproj
│ ├── sshpubk.cpp
│ ├── sshsha.cpp
│ ├── misc.cpp
│ ├── ssh.h
│ ├── sshmd5.cpp
│ ├── sshsh512.cpp
│ ├── import.cpp
│ └── sshdss.cpp
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── App.xaml.cs
├── App.xaml
├── GameLiftRemotePlus.sln
├── ScalingWindow.xaml
├── SettingsWindow.xaml
├── SettingsWindow.xaml.cs
├── GameLiftRemotePlus.csproj
├── MainWindow.xaml
└── ScalingWindow.xaml.cs
├── CODE_OF_CONDUCT.md
├── .gitignore
├── LICENSE.md
├── THIRD-PARTY-LICENSES_UXADCnx5Bg.txt
├── CONTRIBUTING.md
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/doc/img/app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/amazon-gamelift-remote-plus/HEAD/doc/img/app.png
--------------------------------------------------------------------------------
/doc/img/Userguide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/amazon-gamelift-remote-plus/HEAD/doc/img/Userguide.png
--------------------------------------------------------------------------------
/src/KeyConvert/app.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/amazon-gamelift-remote-plus/HEAD/src/KeyConvert/app.rc
--------------------------------------------------------------------------------
/doc/img/awsconfigure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/amazon-gamelift-remote-plus/HEAD/doc/img/awsconfigure.png
--------------------------------------------------------------------------------
/src/KeyConvert/app.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/amazon-gamelift-remote-plus/HEAD/src/KeyConvert/app.ico
--------------------------------------------------------------------------------
/src/KeyConvert/Resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by app.rc
4 |
--------------------------------------------------------------------------------
/src/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/KeyConvert/KeyConvert.h:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #pragma once
5 |
6 | int KeyConvertNative(char *importPath, char *exportPath);
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace GameLiftRemotePlus
4 | {
5 | ///
6 | /// Interaction logic for App.xaml
7 | ///
8 | public partial class App : Application
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/src/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLR.h:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #pragma once
5 |
6 | namespace CLR {
7 | using namespace System;
8 |
9 | public ref class KeyConvert
10 | {
11 | public:
12 | static int Convert(String ^importPath, String ^exportPath);
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/App.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Configuration;
7 | using System.Data;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 |
12 | namespace CLRTest
13 | {
14 | ///
15 | /// Interaction logic for App.xaml
16 | ///
17 | public partial class App : Application
18 | {
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # temporary directories
2 | bin/
3 | obj/
4 | env/
5 | Debug/
6 | Release/
7 |
8 | # Visual Studio cache directory
9 | .vs/
10 |
11 | # Autogenerated VS solution and project files
12 | *.suo
13 | *.tmp
14 | *.user
15 | *.userprefs
16 | *.pidb
17 | *.booproj
18 | *.svd
19 | *.pdb
20 | *.opendb
21 | *.sdf
22 |
23 | # the autogenerated shortcut to run the latest build in the project root
24 | runlatestversion.lnk
25 |
26 | # the local settings file
27 | setting.txt
28 |
29 | # the AWSSDK files that lives in the build source (build\build.bat will recreate these for you)
30 | src/AWSSDK.*.dll
31 |
32 | # any keys!
33 | *.pem
34 | *.ppk
35 |
36 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/doc/tasks.txt:
--------------------------------------------------------------------------------
1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | SPDX-License-Identifier: MIT-0
3 |
4 |
5 |
6 |
7 | Tasks
8 | ======================================
9 |
10 | Update UI every 30 seconds if no change
11 |
12 | Write full tutorial with README.md file and images
13 |
14 | Fix bug: Running application from other than the executable directory causes PEM for linux instances to download into wrong directory preventing SSH connection because PEM to PPK conversion fails.
15 |
16 | Complete the documentation file
17 |
18 | rename to amazon-gamelift-remote-plus
19 |
20 | Note if Delete Fleet is unavailable that the feature can be enabled in settings.
21 |
22 | 1. Addition of delete button for builds
23 | 1. Code to delete a build when called
24 | 1. Addition of delete button for aliases
25 | 1. Code to delete an alias when called
26 | 1. Complete the documentation file
27 |
--------------------------------------------------------------------------------
/src/KeyConvert/AssemblyInfo.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | using namespace System;
5 | using namespace System::Reflection;
6 | using namespace System::Runtime::CompilerServices;
7 | using namespace System::Runtime::InteropServices;
8 | using namespace System::Security::Permissions;
9 |
10 | [assembly:AssemblyTitleAttribute(L"CLR")];
11 | [assembly:AssemblyDescriptionAttribute(L"")];
12 | [assembly:AssemblyConfigurationAttribute(L"")];
13 | [assembly:AssemblyCompanyAttribute(L"")];
14 | [assembly:AssemblyProductAttribute(L"CLR")];
15 | [assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2021")];
16 | [assembly:AssemblyTrademarkAttribute(L"")];
17 | [assembly:AssemblyCultureAttribute(L"")];
18 |
19 | [assembly:AssemblyVersionAttribute("1.0.*")];
20 |
21 | [assembly:ComVisible(false)];
22 |
23 | [assembly:CLSCompliantAttribute(true)];
24 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLR.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #include "CLR.h"
5 | #include
6 | #include "KeyConvert.h"
7 | //#include
8 |
9 | using namespace CLR;
10 | using namespace msclr::interop;
11 | using namespace System::Text;
12 | using namespace System::Diagnostics;
13 |
14 | int KeyConvert::Convert(String ^importPath, String ^exportPath)
15 | {
16 | char import_path[512] = { 0 };
17 | char export_path[512] = { 0 };
18 |
19 | std::string temp1 = marshal_as(importPath);
20 | strcpy(import_path, temp1.c_str());
21 |
22 | std::string temp2 = marshal_as(exportPath);
23 | strcpy(export_path, temp2.c_str());
24 |
25 | Console::WriteLine("Converting file: " + importPath + " to " + exportPath);
26 |
27 | int result = KeyConvertNative(import_path, export_path);
28 |
29 | return result;
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # LICENSE MIT-0
2 |
3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this
6 | software and associated documentation files (the "Software"), to deal in the Software
7 | without restriction, including without limitation the rights to use, copy, modify,
8 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
12 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
13 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
14 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
15 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
16 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 |
--------------------------------------------------------------------------------
/src/KeyConvert/KeyConvert.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #include "CLR.h"
5 |
6 | #include "tchar.h"
7 |
8 | #include
9 | #define GetCurrentDir _getcwd
10 |
11 | #include "ssh.h"
12 |
13 | int KeyConvertNative(char *importPath, char *exportPath)
14 | {
15 | // idea based on https://stackoverflow.com/questions/29646720
16 |
17 | const char *errmsg_p;
18 | Filename importFilename;
19 | importFilename.path = importPath;
20 | int type = SSH_KEYTYPE_OPENSSH;
21 | char *importPassphrase = NULL;
22 | Filename exportFilename;
23 | exportFilename.path = exportPath;
24 | char *exportPassphrase = NULL;
25 |
26 | ssh2_userkey *key = import_ssh2(&importFilename, type, importPassphrase, &errmsg_p);
27 |
28 | if (errmsg_p != NULL)
29 | {
30 | printf("Error: %s\n", errmsg_p);
31 | return 22; // EINVAL
32 | }
33 |
34 |
35 | int retval = ssh2_save_userkey(&exportFilename, key, exportPassphrase);
36 |
37 | return 0;
38 | }
39 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows;
10 | using System.Windows.Controls;
11 | using System.Windows.Data;
12 | using System.Windows.Documents;
13 | using System.Windows.Input;
14 | using System.Windows.Media;
15 | using System.Windows.Media.Imaging;
16 | using System.Windows.Navigation;
17 | using System.Windows.Shapes;
18 |
19 | using CLR;
20 |
21 | namespace CLRTest
22 | {
23 | ///
24 | /// Interaction logic for MainWindow.xaml
25 | ///
26 | public partial class MainWindow : Window
27 | {
28 | public MainWindow()
29 | {
30 | InitializeComponent();
31 | }
32 |
33 | private void Button_Click(object sender, RoutedEventArgs e)
34 | {
35 | CLR.KeyConvert.Convert("sshtest.pem", "sshtest.ppk");
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace GameLiftRemotePlus.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace CLRTest.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/GameLiftRemotePlus.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.1433
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameLiftRemotePlus", "GameLiftRemotePlus.csproj", "{9D8D86BE-D01C-4E3E-B51C-567FDF93494D}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3} = {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}
9 | EndProjectSection
10 | EndProject
11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CLR", "KeyConvert\CLR.vcxproj", "{86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}"
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|x86 = Debug|x86
16 | Release|x86 = Release|x86
17 | EndGlobalSection
18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
19 | {9D8D86BE-D01C-4E3E-B51C-567FDF93494D}.Debug|x86.ActiveCfg = Debug|Any CPU
20 | {9D8D86BE-D01C-4E3E-B51C-567FDF93494D}.Debug|x86.Build.0 = Debug|Any CPU
21 | {9D8D86BE-D01C-4E3E-B51C-567FDF93494D}.Release|x86.ActiveCfg = Release|Any CPU
22 | {9D8D86BE-D01C-4E3E-B51C-567FDF93494D}.Release|x86.Build.0 = Release|Any CPU
23 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|x86.ActiveCfg = Debug|Win32
24 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|x86.Build.0 = Debug|Win32
25 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Release|x86.ActiveCfg = Release|Win32
26 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Release|x86.Build.0 = Release|Win32
27 | EndGlobalSection
28 | GlobalSection(SolutionProperties) = preSolution
29 | HideSolutionNode = FALSE
30 | EndGlobalSection
31 | GlobalSection(ExtensibilityGlobals) = postSolution
32 | SolutionGuid = {AD8D5B5C-2114-4D0D-9937-BDA21F995006}
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/THIRD-PARTY-LICENSES_UXADCnx5Bg.txt:
--------------------------------------------------------------------------------
1 | ** PuTTY; version 0.74 -- https://www.putty.org/
2 | PuTTY
3 |
4 | Release 0.74
5 |
6 | Build platform: 64-bit x86 Windows
7 | Compiler: clang 11.0.0 (https://github.com/llvm/llvm-project/
8 | bc15bf66dcca76cc06fe71fca35b74dc4d521021), emulating Visual Studio 2013 (12.0),
9 | _MSC_VER=1800
10 | Embedded HTML Help file: yes
11 | Source commit: 014d4fb151369f255b3debed7d15a154fd9036f5
12 |
13 | © 1997-2020 Simon Tatham. All rights reserved.
14 |
15 | PuTTY is copyright 1997-2020 Simon Tatham.
16 |
17 | Portions copyright Robert de Bath, Joris van Rantwijk, Delian Delchev, Andreas
18 | Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, Justin Bradford, Ben
19 | Harris, Malcolm Smith, Ahmad Khalifa, Markus Kuhn, Colin Watson, Christopher
20 | Staite, Lorenz Diener, Christian Brabandt, Jeff Smith, Pavel Kryukov, Maxim
21 | Kuznetsov, Svyatoslav Kuzmich, Nico Williams, Viktor Dukhovni, and CORE SDI
22 | S.A.
23 |
24 | Permission is hereby granted, free of charge, to any person obtaining a copy of
25 | this software and associated documentation files (the "Software"), to deal in
26 | the Software without restriction, including without limitation the rights to
27 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
28 | of the Software, and to permit persons to whom the Software is furnished to do
29 | so, subject to the following conditions:
30 |
31 | The above copyright notice and this permission notice shall be included in all
32 | copies or substantial portions of the Software.
33 |
34 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
38 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/src/KeyConvert/puttymem.h:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | /*
5 | * PuTTY memory-handling header.
6 | */
7 |
8 | #ifndef PUTTY_PUTTYMEM_H
9 | #define PUTTY_PUTTYMEM_H
10 |
11 | #include /* for size_t */
12 | #include /* for memcpy() */
13 |
14 |
15 | /* #define MALLOC_LOG do this if you suspect putty of leaking memory */
16 | #ifdef MALLOC_LOG
17 | #define smalloc(z) (mlog(__FILE__,__LINE__), safemalloc(z,1))
18 | #define snmalloc(z,s) (mlog(__FILE__,__LINE__), safemalloc(z,s))
19 | #define srealloc(y,z) (mlog(__FILE__,__LINE__), saferealloc(y,z,1))
20 | #define snrealloc(y,z,s) (mlog(__FILE__,__LINE__), saferealloc(y,z,s))
21 | #define sfree(z) (mlog(__FILE__,__LINE__), safefree(z))
22 | void mlog(char *, int);
23 | #else
24 | #define smalloc(z) safemalloc(z,1)
25 | #define snmalloc safemalloc
26 | #define srealloc(y,z) saferealloc(y,z,1)
27 | #define snrealloc saferealloc
28 | #define sfree safefree
29 | #endif
30 |
31 | void *safemalloc(size_t, size_t);
32 | void *saferealloc(void *, size_t, size_t);
33 | void safefree(void *);
34 |
35 | /*
36 | * Direct use of smalloc within the code should be avoided where
37 | * possible, in favour of these type-casting macros which ensure
38 | * you don't mistakenly allocate enough space for one sort of
39 | * structure and assign it to a different sort of pointer.
40 | *
41 | * The nasty trick in sresize with sizeof arranges for the compiler,
42 | * in passing, to type-check the expression ((type *)0 == (ptr)), i.e.
43 | * to type-check that the input pointer is a pointer to the correct
44 | * type. The construction sizeof(stuff) ? (b) : (b) looks like a
45 | * violation of the first principle of safe macros, but in fact it's
46 | * OK - although it _expands_ the macro parameter more than once, it
47 | * only _evaluates_ it once, so it's still side-effect safe.
48 | */
49 | #define snew(type) ((type *)snmalloc(1, sizeof(type)))
50 | #define snewn(n, type) ((type *)snmalloc((n), sizeof(type)))
51 | #define sresize(ptr, n, type) \
52 | ((type *)snrealloc(sizeof((type *)0 == (ptr)) ? (ptr) : (ptr), \
53 | (n), sizeof(type)))
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/src/ScalingWindow.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/SettingsWindow.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Delete buttons are an advanced feature which will delete your AWS resources with no confirmation
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 | using System.Runtime.CompilerServices;
7 | using System.Runtime.InteropServices;
8 | using System.Windows;
9 |
10 | // General Information about an assembly is controlled through the following
11 | // set of attributes. Change these attribute values to modify the information
12 | // associated with an assembly.
13 | [assembly: AssemblyTitle("GameLiftRemotePlus")]
14 | [assembly: AssemblyDescription("Utility for Amazon GameLift fleet instances")]
15 | [assembly: AssemblyConfiguration("")]
16 | [assembly: AssemblyCompany("Amazon.com")]
17 | [assembly: AssemblyProduct("GameLiftRemotePlus")]
18 | [assembly: AssemblyCopyright("Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.")]
19 | [assembly: AssemblyTrademark("SPDX-License-Identifier: MIT-0")]
20 | [assembly: AssemblyCulture("")]
21 |
22 | // Setting ComVisible to false makes the types in this assembly not visible
23 | // to COM components. If you need to access a type in this assembly from
24 | // COM, set the ComVisible attribute to true on that type.
25 | [assembly: ComVisible(false)]
26 |
27 | //In order to begin building localizable applications, set
28 | //CultureYouAreCodingWith in your .csproj file
29 | //inside a . For example, if you are using US english
30 | //in your source files, set the to en-US. Then uncomment
31 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
32 | //the line below to match the UICulture setting in the project file.
33 |
34 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
35 |
36 |
37 | [assembly: ThemeInfo(
38 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
39 | //(used if a resource is not found in the page,
40 | // or application resource dictionaries)
41 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
42 | //(used if a resource is not found in the page,
43 | // app, or any theme specific resource dictionaries)
44 | )]
45 |
46 |
47 | // Version information for an assembly consists of the following four values:
48 | //
49 | // Major Version
50 | // Minor Version
51 | // Build Number
52 | // Revision
53 | //
54 | // You can specify all the values or you can default the Build and Revision Numbers
55 | // by using the '*' as shown below:
56 | // [assembly: AssemblyVersion("1.0.*")]
57 | [assembly: AssemblyVersion("1.0.0.0")]
58 | [assembly: AssemblyFileVersion("1.0.0.0")]
59 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | using System.Reflection;
5 | using System.Resources;
6 | using System.Runtime.CompilerServices;
7 | using System.Runtime.InteropServices;
8 | using System.Windows;
9 |
10 | // General Information about an assembly is controlled through the following
11 | // set of attributes. Change these attribute values to modify the information
12 | // associated with an assembly.
13 | [assembly: AssemblyTitle("CLRTest")]
14 | [assembly: AssemblyDescription("")]
15 | [assembly: AssemblyConfiguration("")]
16 | [assembly: AssemblyCompany("")]
17 | [assembly: AssemblyProduct("CLRTest")]
18 | [assembly: AssemblyCopyright("Copyright © 2021")]
19 | [assembly: AssemblyTrademark("")]
20 | [assembly: AssemblyCulture("")]
21 |
22 | // Setting ComVisible to false makes the types in this assembly not visible
23 | // to COM components. If you need to access a type in this assembly from
24 | // COM, set the ComVisible attribute to true on that type.
25 | [assembly: ComVisible(false)]
26 |
27 | //In order to begin building localizable applications, set
28 | //CultureYouAreCodingWith in your .csproj file
29 | //inside a . For example, if you are using US english
30 | //in your source files, set the to en-US. Then uncomment
31 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
32 | //the line below to match the UICulture setting in the project file.
33 |
34 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
35 |
36 |
37 | [assembly: ThemeInfo(
38 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
39 | //(used if a resource is not found in the page,
40 | // or application resource dictionaries)
41 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
42 | //(used if a resource is not found in the page,
43 | // app, or any theme specific resource dictionaries)
44 | )]
45 |
46 |
47 | // Version information for an assembly consists of the following four values:
48 | //
49 | // Major Version
50 | // Minor Version
51 | // Build Number
52 | // Revision
53 | //
54 | // You can specify all the values or you can default the Build and Revision Numbers
55 | // by using the '*' as shown below:
56 | // [assembly: AssemblyVersion("1.0.*")]
57 | [assembly: AssemblyVersion("1.0.0.0")]
58 | [assembly: AssemblyFileVersion("1.0.0.0")]
59 |
--------------------------------------------------------------------------------
/src/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace GameLiftRemotePlus.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GameLiftRemotePlus.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace CLRTest.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CLRTest.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLR.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.1433
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CLR", "CLR.vcxproj", "{86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLRTest", "CLRTest\CLRTest.csproj", "{D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}"
9 | ProjectSection(ProjectDependencies) = postProject
10 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3} = {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}
11 | EndProjectSection
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|Any CPU = Debug|Any CPU
16 | Debug|x64 = Debug|x64
17 | Debug|x86 = Debug|x86
18 | Release|Any CPU = Release|Any CPU
19 | Release|x64 = Release|x64
20 | Release|x86 = Release|x86
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|Any CPU.ActiveCfg = Debug|Win32
24 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|Any CPU.Build.0 = Debug|Win32
25 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|x64.ActiveCfg = Debug|x64
26 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|x64.Build.0 = Debug|x64
27 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|x86.ActiveCfg = Debug|Win32
28 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Debug|x86.Build.0 = Debug|Win32
29 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Release|Any CPU.ActiveCfg = Release|Win32
30 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Release|x64.ActiveCfg = Debug|x64
31 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Release|x64.Build.0 = Debug|x64
32 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Release|x86.ActiveCfg = Release|Win32
33 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}.Release|x86.Build.0 = Release|Win32
34 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Debug|x64.ActiveCfg = Debug|Any CPU
37 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Debug|x64.Build.0 = Debug|Any CPU
38 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Debug|x86.ActiveCfg = Debug|Any CPU
39 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Debug|x86.Build.0 = Debug|Any CPU
40 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Release|x64.ActiveCfg = Debug|Any CPU
43 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Release|x64.Build.0 = Debug|Any CPU
44 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Release|x86.ActiveCfg = Release|Any CPU
45 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}.Release|x86.Build.0 = Release|Any CPU
46 | EndGlobalSection
47 | GlobalSection(SolutionProperties) = preSolution
48 | HideSolutionNode = FALSE
49 | EndGlobalSection
50 | GlobalSection(ExtensibilityGlobals) = postSolution
51 | SolutionGuid = {E2D88A70-6FC7-47D0-B49B-1C1E7514F259}
52 | EndGlobalSection
53 | EndGlobal
54 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *main* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLR.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 |
41 |
42 | Source Files
43 |
44 |
45 | Source Files
46 |
47 |
48 | Source Files
49 |
50 |
51 | Source Files
52 |
53 |
54 | Source Files
55 |
56 |
57 | Source Files
58 |
59 |
60 | Source Files
61 |
62 |
63 | Source Files
64 |
65 |
66 | Source Files
67 |
68 |
69 | Source Files
70 |
71 |
72 | Source Files
73 |
74 |
75 | Source Files
76 |
77 |
78 | Source Files
79 |
80 |
81 | Source Files
82 |
83 |
84 |
85 |
86 | Resource Files
87 |
88 |
89 |
90 |
91 | Resource Files
92 |
93 |
94 |
--------------------------------------------------------------------------------
/src/KeyConvert/misc.h:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #pragma once
5 |
6 | #include
7 | #include "ctype.h"
8 | #include "puttymem.h"
9 | #include "assert.h"
10 |
11 |
12 | struct Filename {
13 | char *path;
14 | };
15 |
16 | typedef struct Filename Filename;
17 |
18 | #define f_open(filename, mode, isprivate) ( fopen((filename)->path, (mode)) )
19 |
20 |
21 |
22 | //32
23 | char *dupstr(const char *s);
24 |
25 |
26 | //51
27 | int toint(unsigned);
28 |
29 | char *fgetline(FILE *fp);
30 | int strstartswith(const char *s, const char *t);
31 | int strendswith(const char *s, const char *t);
32 |
33 | void base64_encode_atom(unsigned char *data, int n, char *out);
34 | int base64_decode_atom(char *atom, unsigned char *out);
35 |
36 |
37 | //78
38 | /* Wipe sensitive data out of memory that's about to be freed. Simpler
39 | * than memset because we don't need the fill char parameter; also
40 | * attempts (by fiddly use of volatile) to inhibit the compiler from
41 | * over-cleverly trying to optimise the memset away because it knows
42 | * the variable is going out of scope. */
43 | void smemclr(void *b, size_t len);
44 |
45 | /* Compare two fixed-length chunks of memory for equality, without
46 | * data-dependent control flow (so an attacker with a very accurate
47 | * stopwatch can't try to guess where the first mismatching byte was).
48 | * Returns 0 for mismatch or 1 for equality (unlike memcmp), hinted at
49 | * by the 'eq' in the name. */
50 | int smemeq(const void *av, const void *bv, size_t len);
51 |
52 |
53 | //117
54 | #ifndef lenof
55 | #define lenof(x) ( (sizeof((x))) / (sizeof(*(x))))
56 | #endif
57 |
58 |
59 | //128
60 | #define GET_32BIT_LSB_FIRST(cp) \
61 | (((unsigned long)(unsigned char)(cp)[0]) | \
62 | ((unsigned long)(unsigned char)(cp)[1] << 8) | \
63 | ((unsigned long)(unsigned char)(cp)[2] << 16) | \
64 | ((unsigned long)(unsigned char)(cp)[3] << 24))
65 |
66 | #define PUT_32BIT_LSB_FIRST(cp, value) ( \
67 | (cp)[0] = (unsigned char)(value), \
68 | (cp)[1] = (unsigned char)((value) >> 8), \
69 | (cp)[2] = (unsigned char)((value) >> 16), \
70 | (cp)[3] = (unsigned char)((value) >> 24) )
71 |
72 | #define GET_16BIT_LSB_FIRST(cp) \
73 | (((unsigned long)(unsigned char)(cp)[0]) | \
74 | ((unsigned long)(unsigned char)(cp)[1] << 8))
75 |
76 | #define PUT_16BIT_LSB_FIRST(cp, value) ( \
77 | (cp)[0] = (unsigned char)(value), \
78 | (cp)[1] = (unsigned char)((value) >> 8) )
79 |
80 | #define GET_32BIT_MSB_FIRST(cp) \
81 | (((unsigned long)(unsigned char)(cp)[0] << 24) | \
82 | ((unsigned long)(unsigned char)(cp)[1] << 16) | \
83 | ((unsigned long)(unsigned char)(cp)[2] << 8) | \
84 | ((unsigned long)(unsigned char)(cp)[3]))
85 |
86 | #define GET_32BIT(cp) GET_32BIT_MSB_FIRST(cp)
87 |
88 | #define PUT_32BIT_MSB_FIRST(cp, value) ( \
89 | (cp)[0] = (unsigned char)((value) >> 24), \
90 | (cp)[1] = (unsigned char)((value) >> 16), \
91 | (cp)[2] = (unsigned char)((value) >> 8), \
92 | (cp)[3] = (unsigned char)(value) )
93 |
94 | #define PUT_32BIT(cp, value) PUT_32BIT_MSB_FIRST(cp, value)
95 |
96 | #define GET_16BIT_MSB_FIRST(cp) \
97 | (((unsigned long)(unsigned char)(cp)[0] << 8) | \
98 | ((unsigned long)(unsigned char)(cp)[1]))
99 |
100 | #define PUT_16BIT_MSB_FIRST(cp, value) ( \
101 | (cp)[0] = (unsigned char)((value) >> 8), \
102 | (cp)[1] = (unsigned char)(value) )
103 |
--------------------------------------------------------------------------------
/src/SettingsWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Text.RegularExpressions;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Data;
13 | using System.Windows.Documents;
14 | using System.Windows.Input;
15 | using System.Windows.Media;
16 | using System.Windows.Media.Imaging;
17 | using System.Windows.Shapes;
18 |
19 | namespace GameLiftRemotePlus
20 | {
21 | public partial class SettingsWindow : Window
22 | {
23 | MainWindow main;
24 | bool init = false;
25 |
26 | public SettingsWindow(MainWindow _main)
27 | {
28 | main = _main;
29 |
30 | InitializeComponent();
31 |
32 | cidrCheckbox.IsChecked = main.useCustomCidr;
33 | customCidrTextBox.Text = main.customCidr;
34 | debugCheckbox.IsChecked = main.useRemoteDebugPort;
35 | debugPortTextBox.Text = main.remoteDebugPort.ToString();
36 | deleteCheckbox.IsChecked = main.showDeleteButtons;
37 | init = true;
38 | Validate();
39 | }
40 |
41 | private void customCidrTextBox_TextChanged(object sender, TextChangedEventArgs e)
42 | {
43 | Validate();
44 | }
45 |
46 | private void debugPortTextBox_TextChanged(object sender, TextChangedEventArgs e)
47 | {
48 | Validate();
49 | }
50 |
51 | private void Validate()
52 | {
53 | if (!init) return;
54 |
55 | if (cidrCheckbox.IsChecked != null) customCidrTextBox.IsEnabled = (bool)cidrCheckbox.IsChecked;
56 | if (debugCheckbox.IsChecked != null) debugPortTextBox.IsEnabled = (bool)debugCheckbox.IsChecked;
57 |
58 | var match = Regex.Match(customCidrTextBox.Text, @"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$", RegexOptions.None);
59 | bool cidrValid = match.Success;
60 |
61 | UInt16 remoteDebugPort;
62 | bool debugPortValid = UInt16.TryParse(debugPortTextBox.Text, out remoteDebugPort);
63 |
64 | ok.IsEnabled = (!customCidrTextBox.IsEnabled || cidrValid) && (!debugPortTextBox.IsEnabled || debugPortValid);
65 | }
66 |
67 | private void ok_Click(object sender, RoutedEventArgs e)
68 | {
69 | main.useCustomCidr = (bool)cidrCheckbox.IsChecked;
70 | if (main.useCustomCidr) main.customCidr = customCidrTextBox.Text;
71 | main.useRemoteDebugPort = (bool)debugCheckbox.IsChecked;
72 | if (main.useRemoteDebugPort) UInt16.TryParse(debugPortTextBox.Text, out main.remoteDebugPort);
73 | main.showDeleteButtons = (bool)deleteCheckbox.IsChecked;
74 | main.SaveSettings();
75 | this.Close();
76 | }
77 |
78 | private void cancel_Click(object sender, RoutedEventArgs e)
79 | {
80 | this.Close();
81 | }
82 |
83 | private void debugCheckbox_Click(object sender, RoutedEventArgs e)
84 | {
85 | Validate();
86 | }
87 |
88 | private void cidrCheckbox_Click(object sender, RoutedEventArgs e)
89 | {
90 | Validate();
91 | }
92 |
93 | private void deleteCheckbox_Click(object sender, RoutedEventArgs e)
94 | {
95 | // don't need to validate the input
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/KeyConvert/sshbn.h:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | /*
5 | * sshbn.h: the assorted conditional definitions of BignumInt and
6 | * multiply/divide macros used throughout the bignum code to treat
7 | * numbers as arrays of the most conveniently sized word for the
8 | * target machine. Exported so that other code (e.g. poly1305) can use
9 | * it too.
10 | */
11 |
12 | /*
13 | * Usage notes:
14 | * * Do not call the DIVMOD_WORD macro with expressions such as array
15 | * subscripts, as some implementations object to this (see below).
16 | * * Note that none of the division methods below will cope if the
17 | * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
18 | * to avoid this case.
19 | * If this condition occurs, in the case of the x86 DIV instruction,
20 | * an overflow exception will occur, which (according to a correspondent)
21 | * will manifest on Windows as something like
22 | * 0xC0000095: Integer overflow
23 | * The C variant won't give the right answer, either.
24 | */
25 |
26 | #if defined __SIZEOF_INT128__
27 | /* gcc and clang both provide a __uint128_t type on 64-bit targets
28 | * (and, when they do, indicate its presence by the above macro),
29 | * using the same 'two machine registers' kind of code generation that
30 | * 32-bit targets use for 64-bit ints. If we have one of these, we can
31 | * use a 64-bit BignumInt and a 128-bit BignumDblInt. */
32 | typedef unsigned __int64 BignumInt;
33 | typedef unsigned __int128 BignumDblInt;
34 | #define BIGNUM_INT_MASK 0xFFFFFFFFFFFFFFFFULL
35 | #define BIGNUM_TOP_BIT 0x8000000000000000ULL
36 | #define BIGNUM_INT_BITS 64
37 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
38 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
39 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
40 | q = n / w; \
41 | r = n % w; \
42 | } while (0)
43 | #elif defined __GNUC__ && defined __i386__
44 | typedef unsigned long BignumInt;
45 | typedef unsigned long long BignumDblInt;
46 | #define BIGNUM_INT_MASK 0xFFFFFFFFUL
47 | #define BIGNUM_TOP_BIT 0x80000000UL
48 | #define BIGNUM_INT_BITS 32
49 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
50 | #define DIVMOD_WORD(q, r, hi, lo, w) \
51 | __asm__("div %2" : \
52 | "=d" (r), "=a" (q) : \
53 | "r" (w), "d" (hi), "a" (lo))
54 | #elif defined _MSC_VER && defined _M_IX86
55 | typedef unsigned __int32 BignumInt;
56 | typedef unsigned __int64 BignumDblInt;
57 | #define BIGNUM_INT_MASK 0xFFFFFFFFUL
58 | #define BIGNUM_TOP_BIT 0x80000000UL
59 | #define BIGNUM_INT_BITS 32
60 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
61 | /* Note: MASM interprets array subscripts in the macro arguments as
62 | * assembler syntax, which gives the wrong answer. Don't supply them.
63 | * */
64 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
65 | __asm mov edx, hi \
66 | __asm mov eax, lo \
67 | __asm div w \
68 | __asm mov r, edx \
69 | __asm mov q, eax \
70 | } while(0)
71 | #elif defined _LP64
72 | /* 64-bit architectures can do 32x32->64 chunks at a time */
73 | typedef unsigned int BignumInt;
74 | typedef unsigned long BignumDblInt;
75 | #define BIGNUM_INT_MASK 0xFFFFFFFFU
76 | #define BIGNUM_TOP_BIT 0x80000000U
77 | #define BIGNUM_INT_BITS 32
78 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
79 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
80 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
81 | q = n / w; \
82 | r = n % w; \
83 | } while (0)
84 | #elif defined _LLP64
85 | /* 64-bit architectures in which unsigned long is 32 bits, not 64 */
86 | typedef unsigned long BignumInt;
87 | typedef unsigned long long BignumDblInt;
88 | #define BIGNUM_INT_MASK 0xFFFFFFFFUL
89 | #define BIGNUM_TOP_BIT 0x80000000UL
90 | #define BIGNUM_INT_BITS 32
91 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
92 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
93 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
94 | q = n / w; \
95 | r = n % w; \
96 | } while (0)
97 | #else
98 | /* Fallback for all other cases */
99 | typedef unsigned short BignumInt;
100 | typedef unsigned long BignumDblInt;
101 | #define BIGNUM_INT_MASK 0xFFFFU
102 | #define BIGNUM_TOP_BIT 0x8000U
103 | #define BIGNUM_INT_BITS 16
104 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
105 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
106 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
107 | q = n / w; \
108 | r = n % w; \
109 | } while (0)
110 | #endif
111 |
112 | #define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
113 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/CLRTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {D9ED1116-D4AE-45C3-9ACE-F0093A2C5A94}
8 | WinExe
9 | CLRTest
10 | CLRTest
11 | v4.7.1
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 | x86
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | 4.0
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | MSBuild:Compile
56 | Designer
57 |
58 |
59 | MSBuild:Compile
60 | Designer
61 |
62 |
63 | App.xaml
64 | Code
65 |
66 |
67 | MainWindow.xaml
68 | Code
69 |
70 |
71 |
72 |
73 | Code
74 |
75 |
76 | True
77 | True
78 | Resources.resx
79 |
80 |
81 | True
82 | Settings.settings
83 | True
84 |
85 |
86 | ResXFileCodeGenerator
87 | Resources.Designer.cs
88 |
89 |
90 | SettingsSingleFileGenerator
91 | Settings.Designer.cs
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | {86e9b45d-cd21-4c0d-9973-3fb0765bfda3}
100 | CLR
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLR.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | 15.0
15 | {86E9B45D-CD21-4C0D-9973-3FB0765BFDA3}
16 | v4.5
17 | ManagedCProj
18 | CLR
19 | 10.0.17763.0
20 |
21 |
22 |
23 | DynamicLibrary
24 | true
25 | v141
26 | true
27 | Unicode
28 |
29 |
30 | DynamicLibrary
31 | false
32 | v141
33 | true
34 | Unicode
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | true
50 |
51 |
52 | false
53 |
54 |
55 |
56 | NotUsing
57 | pch.h
58 | Level3
59 | Disabled
60 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | NotUsing
69 | pch.h
70 | Level3
71 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;%(PreprocessorDefinitions)
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/src/KeyConvert/sshpubk.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #include "misc.h"
5 | #include "ssh.h"
6 |
7 | //981
8 | int base64_lines(int datalen)
9 | {
10 | /* When encoding, we use 64 chars/line, which equals 48 real chars. */
11 | return (datalen + 47) / 48;
12 | }
13 |
14 | void base64_encode(FILE * fp, unsigned char *data, int datalen, int cpl)
15 | {
16 | int linelen = 0;
17 | char out[4];
18 | int n, i;
19 |
20 | while (datalen > 0) {
21 | n = (datalen < 3 ? datalen : 3);
22 | base64_encode_atom(data, n, out);
23 | data += n;
24 | datalen -= n;
25 | for (i = 0; i < 4; i++) {
26 | if (linelen >= cpl) {
27 | linelen = 0;
28 | fputc('\n', fp);
29 | }
30 | fputc(out[i], fp);
31 | linelen++;
32 | }
33 | }
34 | fputc('\n', fp);
35 | }
36 |
37 | //1010
38 | int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
39 | char *passphrase)
40 | {
41 | FILE *fp;
42 | unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted;
43 | int pub_blob_len, priv_blob_len, priv_encrypted_len;
44 | int passlen;
45 | int cipherblk;
46 | int i;
47 | char *cipherstr;
48 | unsigned char priv_mac[20];
49 |
50 | /*
51 | * Fetch the key component blobs.
52 | */
53 | pub_blob = key->alg->public_blob(key->data, &pub_blob_len);
54 | priv_blob = key->alg->private_blob(key->data, &priv_blob_len);
55 | if (!pub_blob || !priv_blob) {
56 | sfree(pub_blob);
57 | sfree(priv_blob);
58 | return 0;
59 | }
60 |
61 | /*
62 | * Determine encryption details, and encrypt the private blob.
63 | */
64 | if (passphrase) {
65 | cipherstr = "aes256-cbc";
66 | cipherblk = 16;
67 | }
68 | else {
69 | cipherstr = "none";
70 | cipherblk = 1;
71 | }
72 | priv_encrypted_len = priv_blob_len + cipherblk - 1;
73 | priv_encrypted_len -= priv_encrypted_len % cipherblk;
74 | priv_blob_encrypted = snewn(priv_encrypted_len, unsigned char);
75 | memset(priv_blob_encrypted, 0, priv_encrypted_len);
76 | memcpy(priv_blob_encrypted, priv_blob, priv_blob_len);
77 | /* Create padding based on the SHA hash of the unpadded blob. This prevents
78 | * too easy a known-plaintext attack on the last block. */
79 | SHA_Simple(priv_blob, priv_blob_len, priv_mac);
80 | assert(priv_encrypted_len - priv_blob_len < 20);
81 | memcpy(priv_blob_encrypted + priv_blob_len, priv_mac,
82 | priv_encrypted_len - priv_blob_len);
83 |
84 | /* Now create the MAC. */
85 | {
86 | unsigned char *macdata;
87 | int maclen;
88 | unsigned char *p;
89 | int namelen = strlen(key->alg->name);
90 | int enclen = strlen(cipherstr);
91 | int commlen = strlen(key->comment);
92 | SHA_State s;
93 | unsigned char mackey[20];
94 | char header[] = "putty-private-key-file-mac-key";
95 |
96 | maclen = (4 + namelen +
97 | 4 + enclen +
98 | 4 + commlen +
99 | 4 + pub_blob_len +
100 | 4 + priv_encrypted_len);
101 | macdata = snewn(maclen, unsigned char);
102 | p = macdata;
103 | #define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
104 | DO_STR(key->alg->name, namelen);
105 | DO_STR(cipherstr, enclen);
106 | DO_STR(key->comment, commlen);
107 | DO_STR(pub_blob, pub_blob_len);
108 | DO_STR(priv_blob_encrypted, priv_encrypted_len);
109 |
110 | SHA_Init(&s);
111 | SHA_Bytes(&s, header, sizeof(header) - 1);
112 | if (passphrase)
113 | SHA_Bytes(&s, passphrase, strlen(passphrase));
114 | SHA_Final(&s, mackey);
115 | hmac_sha1_simple(mackey, 20, macdata, maclen, priv_mac);
116 | smemclr(macdata, maclen);
117 | sfree(macdata);
118 | smemclr(mackey, sizeof(mackey));
119 | smemclr(&s, sizeof(s));
120 | }
121 |
122 | if (passphrase) {
123 | unsigned char key[40];
124 | SHA_State s;
125 |
126 | passlen = strlen(passphrase);
127 |
128 | SHA_Init(&s);
129 | SHA_Bytes(&s, "\0\0\0\0", 4);
130 | SHA_Bytes(&s, passphrase, passlen);
131 | SHA_Final(&s, key + 0);
132 | SHA_Init(&s);
133 | SHA_Bytes(&s, "\0\0\0\1", 4);
134 | SHA_Bytes(&s, passphrase, passlen);
135 | SHA_Final(&s, key + 20);
136 | aes256_encrypt_pubkey(key, priv_blob_encrypted,
137 | priv_encrypted_len);
138 |
139 | smemclr(key, sizeof(key));
140 | smemclr(&s, sizeof(s));
141 | }
142 |
143 | fp = f_open(filename, "w", TRUE);
144 | if (!fp) {
145 | sfree(pub_blob);
146 | smemclr(priv_blob, priv_blob_len);
147 | sfree(priv_blob);
148 | smemclr(priv_blob_encrypted, priv_blob_len);
149 | sfree(priv_blob_encrypted);
150 | return 0;
151 | }
152 | fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name);
153 | fprintf(fp, "Encryption: %s\n", cipherstr);
154 | fprintf(fp, "Comment: %s\n", key->comment);
155 | fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob_len));
156 | base64_encode(fp, pub_blob, pub_blob_len, 64);
157 | fprintf(fp, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));
158 | base64_encode(fp, priv_blob_encrypted, priv_encrypted_len, 64);
159 | fprintf(fp, "Private-MAC: ");
160 | for (i = 0; i < 20; i++)
161 | fprintf(fp, "%02x", priv_mac[i]);
162 | fprintf(fp, "\n");
163 | fclose(fp);
164 |
165 | sfree(pub_blob);
166 | smemclr(priv_blob, priv_blob_len);
167 | sfree(priv_blob);
168 | smemclr(priv_blob_encrypted, priv_blob_len);
169 | sfree(priv_blob_encrypted);
170 | return 1;
171 | }
172 |
173 |
174 | //553
175 | /*
176 | * Magic error return value for when the passphrase is wrong.
177 | */
178 | struct ssh2_userkey ssh2_wrong_passphrase = {
179 | NULL, NULL, NULL
180 | };
181 |
182 |
--------------------------------------------------------------------------------
/src/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/src/KeyConvert/CLRTest/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/src/GameLiftRemotePlus.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {9D8D86BE-D01C-4E3E-B51C-567FDF93494D}
8 | WinExe
9 | Properties
10 | GameLiftRemotePlus
11 | GameLiftRemotePlus
12 | v4.5
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 | $(SolutionDir)..\obj\
17 |
18 |
19 | x86
20 | true
21 | full
22 | false
23 | ..\bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | x86
30 | pdbonly
31 | true
32 | ..\bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 | .\AWSSDK.Core.dll
40 |
41 |
42 | .\AWSSDK.GameLift.dll
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | 4.0
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | MSBuild:Compile
61 | Designer
62 |
63 |
64 | ScalingWindow.xaml
65 |
66 |
67 | SettingsWindow.xaml
68 |
69 |
70 | MSBuild:Compile
71 | Designer
72 |
73 |
74 | App.xaml
75 | Code
76 |
77 |
78 | MainWindow.xaml
79 | Code
80 |
81 |
82 | Designer
83 | MSBuild:Compile
84 |
85 |
86 | Designer
87 | MSBuild:Compile
88 |
89 |
90 |
91 |
92 | Code
93 |
94 |
95 | True
96 | True
97 | Resources.resx
98 |
99 |
100 | True
101 | Settings.settings
102 | True
103 |
104 |
105 | ResXFileCodeGenerator
106 | Resources.Designer.cs
107 |
108 |
109 | SettingsSingleFileGenerator
110 | Settings.Designer.cs
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | {86e9b45d-cd21-4c0d-9973-3fb0765bfda3}
120 | CLR
121 |
122 |
123 |
124 |
125 | powershell "$s=(New-Object -COM WScript.Shell).CreateShortcut('$(SolutionDir)..\runlatestversion.lnk');$s.TargetPath='$(TargetPath)';$s.Save()"
126 |
127 |
128 |
135 |
--------------------------------------------------------------------------------
/src/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/KeyConvert/sshsha.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | /*
5 | * SHA1 hash algorithm. Used in SSH-2 as a MAC, and the transform is
6 | * also used as a `stirring' function for the PuTTY random number
7 | * pool. Implemented directly from the specification by Simon
8 | * Tatham.
9 | */
10 |
11 | #include "ssh.h"
12 |
13 | /* ----------------------------------------------------------------------
14 | * Core SHA algorithm: processes 16-word blocks into a message digest.
15 | */
16 |
17 | #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )
18 |
19 | static void SHA_Core_Init(uint32 h[5])
20 | {
21 | h[0] = 0x67452301;
22 | h[1] = 0xefcdab89;
23 | h[2] = 0x98badcfe;
24 | h[3] = 0x10325476;
25 | h[4] = 0xc3d2e1f0;
26 | }
27 |
28 | void SHATransform(word32 * digest, word32 * block)
29 | {
30 | word32 w[80];
31 | word32 a, b, c, d, e;
32 | int t;
33 |
34 | #ifdef RANDOM_DIAGNOSTICS
35 | {
36 | extern int random_diagnostics;
37 | if (random_diagnostics) {
38 | int i;
39 | printf("SHATransform:");
40 | for (i = 0; i < 5; i++)
41 | printf(" %08x", digest[i]);
42 | printf(" +");
43 | for (i = 0; i < 16; i++)
44 | printf(" %08x", block[i]);
45 | }
46 | }
47 | #endif
48 |
49 | for (t = 0; t < 16; t++)
50 | w[t] = block[t];
51 |
52 | for (t = 16; t < 80; t++) {
53 | word32 tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
54 | w[t] = rol(tmp, 1);
55 | }
56 |
57 | a = digest[0];
58 | b = digest[1];
59 | c = digest[2];
60 | d = digest[3];
61 | e = digest[4];
62 |
63 | for (t = 0; t < 20; t++) {
64 | word32 tmp =
65 | rol(a, 5) + ((b & c) | (d & ~b)) + e + w[t] + 0x5a827999;
66 | e = d;
67 | d = c;
68 | c = rol(b, 30);
69 | b = a;
70 | a = tmp;
71 | }
72 | for (t = 20; t < 40; t++) {
73 | word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1;
74 | e = d;
75 | d = c;
76 | c = rol(b, 30);
77 | b = a;
78 | a = tmp;
79 | }
80 | for (t = 40; t < 60; t++) {
81 | word32 tmp = rol(a,
82 | 5) + ((b & c) | (b & d) | (c & d)) + e + w[t] +
83 | 0x8f1bbcdc;
84 | e = d;
85 | d = c;
86 | c = rol(b, 30);
87 | b = a;
88 | a = tmp;
89 | }
90 | for (t = 60; t < 80; t++) {
91 | word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6;
92 | e = d;
93 | d = c;
94 | c = rol(b, 30);
95 | b = a;
96 | a = tmp;
97 | }
98 |
99 | digest[0] += a;
100 | digest[1] += b;
101 | digest[2] += c;
102 | digest[3] += d;
103 | digest[4] += e;
104 |
105 | #ifdef RANDOM_DIAGNOSTICS
106 | {
107 | extern int random_diagnostics;
108 | if (random_diagnostics) {
109 | int i;
110 | printf(" =");
111 | for (i = 0; i < 5; i++)
112 | printf(" %08x", digest[i]);
113 | printf("\n");
114 | }
115 | }
116 | #endif
117 | }
118 |
119 | /* ----------------------------------------------------------------------
120 | * Outer SHA algorithm: take an arbitrary length byte string,
121 | * convert it into 16-word blocks with the prescribed padding at
122 | * the end, and pass those blocks to the core SHA algorithm.
123 | */
124 |
125 | void SHA_Init(SHA_State * s)
126 | {
127 | SHA_Core_Init(s->h);
128 | s->blkused = 0;
129 | s->lenhi = s->lenlo = 0;
130 | }
131 |
132 | void SHA_Bytes(SHA_State * s, const void *p, int len)
133 | {
134 | const unsigned char *q = (const unsigned char *)p;
135 | uint32 wordblock[16];
136 | uint32 lenw = len;
137 | int i;
138 |
139 | /*
140 | * Update the length field.
141 | */
142 | s->lenlo += lenw;
143 | s->lenhi += (s->lenlo < lenw);
144 |
145 | if (s->blkused && s->blkused + len < 64) {
146 | /*
147 | * Trivial case: just add to the block.
148 | */
149 | memcpy(s->block + s->blkused, q, len);
150 | s->blkused += len;
151 | }
152 | else {
153 | /*
154 | * We must complete and process at least one block.
155 | */
156 | while (s->blkused + len >= 64) {
157 | memcpy(s->block + s->blkused, q, 64 - s->blkused);
158 | q += 64 - s->blkused;
159 | len -= 64 - s->blkused;
160 | /* Now process the block. Gather bytes big-endian into words */
161 | for (i = 0; i < 16; i++) {
162 | wordblock[i] =
163 | (((uint32)s->block[i * 4 + 0]) << 24) |
164 | (((uint32)s->block[i * 4 + 1]) << 16) |
165 | (((uint32)s->block[i * 4 + 2]) << 8) |
166 | (((uint32)s->block[i * 4 + 3]) << 0);
167 | }
168 | SHATransform(s->h, wordblock);
169 | s->blkused = 0;
170 | }
171 | memcpy(s->block, q, len);
172 | s->blkused = len;
173 | }
174 | }
175 |
176 | void SHA_Final(SHA_State * s, unsigned char *output)
177 | {
178 | int i;
179 | int pad;
180 | unsigned char c[64];
181 | uint32 lenhi, lenlo;
182 |
183 | if (s->blkused >= 56)
184 | pad = 56 + 64 - s->blkused;
185 | else
186 | pad = 56 - s->blkused;
187 |
188 | lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
189 | lenlo = (s->lenlo << 3);
190 |
191 | memset(c, 0, pad);
192 | c[0] = 0x80;
193 | SHA_Bytes(s, &c, pad);
194 |
195 | c[0] = (lenhi >> 24) & 0xFF;
196 | c[1] = (lenhi >> 16) & 0xFF;
197 | c[2] = (lenhi >> 8) & 0xFF;
198 | c[3] = (lenhi >> 0) & 0xFF;
199 | c[4] = (lenlo >> 24) & 0xFF;
200 | c[5] = (lenlo >> 16) & 0xFF;
201 | c[6] = (lenlo >> 8) & 0xFF;
202 | c[7] = (lenlo >> 0) & 0xFF;
203 |
204 | SHA_Bytes(s, &c, 8);
205 |
206 | for (i = 0; i < 5; i++) {
207 | output[i * 4] = (s->h[i] >> 24) & 0xFF;
208 | output[i * 4 + 1] = (s->h[i] >> 16) & 0xFF;
209 | output[i * 4 + 2] = (s->h[i] >> 8) & 0xFF;
210 | output[i * 4 + 3] = (s->h[i]) & 0xFF;
211 | }
212 | }
213 |
214 | void SHA_Simple(const void *p, int len, unsigned char *output)
215 | {
216 | SHA_State s;
217 |
218 | SHA_Init(&s);
219 | SHA_Bytes(&s, p, len);
220 | SHA_Final(&s, output);
221 | smemclr(&s, sizeof(s));
222 | }
223 |
224 | /*
225 | * Thin abstraction for things where hashes are pluggable.
226 | */
227 |
228 | static void *sha1_init(void)
229 | {
230 | SHA_State *s;
231 |
232 | s = snew(SHA_State);
233 | SHA_Init(s);
234 | return s;
235 | }
236 |
237 | static void sha1_bytes(void *handle, void *p, int len)
238 | {
239 | SHA_State *s = (SHA_State *)handle;
240 |
241 | SHA_Bytes(s, p, len);
242 | }
243 |
244 | static void sha1_final(void *handle, unsigned char *output)
245 | {
246 | SHA_State *s = (SHA_State *)handle;
247 |
248 | SHA_Final(s, output);
249 | smemclr(s, sizeof(*s));
250 | sfree(s);
251 | }
252 |
253 | const struct ssh_hash ssh_sha1 = {
254 | sha1_init, sha1_bytes, sha1_final, 20, "SHA-1"
255 | };
256 |
257 | //269
258 | static void sha1_key_internal(void *handle, unsigned char *key, int len)
259 | {
260 | SHA_State *keys = (SHA_State *)handle;
261 | unsigned char foo[64];
262 | int i;
263 |
264 | memset(foo, 0x36, 64);
265 | for (i = 0; i < len && i < 64; i++)
266 | foo[i] ^= key[i];
267 | SHA_Init(&keys[0]);
268 | SHA_Bytes(&keys[0], foo, 64);
269 |
270 | memset(foo, 0x5C, 64);
271 | for (i = 0; i < len && i < 64; i++)
272 | foo[i] ^= key[i];
273 | SHA_Init(&keys[1]);
274 | SHA_Bytes(&keys[1], foo, 64);
275 |
276 | smemclr(foo, 64); /* burn the evidence */
277 | }
278 |
279 |
280 | //389
281 | void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
282 | unsigned char *output) {
283 | SHA_State states[2];
284 | unsigned char intermediate[20];
285 |
286 | sha1_key_internal(states, (unsigned char *)key, keylen);
287 | SHA_Bytes(&states[0], data, datalen);
288 | SHA_Final(&states[0], intermediate);
289 |
290 | SHA_Bytes(&states[1], intermediate, 20);
291 | SHA_Final(&states[1], output);
292 | }
293 |
--------------------------------------------------------------------------------
/src/ScalingWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | using Amazon.GameLift;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Text.RegularExpressions;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Input;
11 |
12 | namespace GameLiftRemotePlus
13 | {
14 | public partial class ScalingWindow : Window
15 | {
16 | Amazon.RegionEndpoint currentRegion;
17 | string fleetId;
18 | MainWindow main;
19 | int realMin, realDes, realMax;
20 | bool init = false;
21 |
22 | public ScalingWindow(MainWindow _main, string _fleetId, Amazon.RegionEndpoint _currentRegion)
23 | {
24 | InitializeComponent();
25 |
26 | main = _main;
27 | currentRegion = _currentRegion;
28 | fleetId = _fleetId;
29 |
30 | this.Title = fleetId;
31 |
32 | var config = new AmazonGameLiftConfig();
33 | config.RegionEndpoint = currentRegion;
34 | using (AmazonGameLiftClient aglc = new AmazonGameLiftClient(config))
35 | {
36 | Amazon.GameLift.Model.DescribeFleetCapacityResponse ufcres = aglc.DescribeFleetCapacity(new Amazon.GameLift.Model.DescribeFleetCapacityRequest
37 | {
38 | FleetIds = new List { fleetId }
39 | });
40 |
41 | realMin = ufcres.FleetCapacity[0].InstanceCounts.MINIMUM;
42 | realDes = ufcres.FleetCapacity[0].InstanceCounts.DESIRED;
43 | realMax = ufcres.FleetCapacity[0].InstanceCounts.MAXIMUM;
44 |
45 | minVal.Text = realMin.ToString();
46 | desiredVal.Text = realDes.ToString();
47 | maxVal.Text = realMax.ToString();
48 |
49 | SetSliderBounds();
50 | }
51 | init = true;
52 | }
53 |
54 | private void ParseValues(out int min, out int desired, out int max)
55 | {
56 | if (Int32.TryParse(minVal.Text, out min))
57 | {
58 | minVal.Text = min.ToString();
59 | }
60 | else
61 | {
62 | minVal.Text = "";
63 | min = realMin;
64 | }
65 | if (Int32.TryParse(desiredVal.Text, out desired))
66 | {
67 | desiredVal.Text = desired.ToString();
68 | }
69 | else
70 | {
71 | desiredVal.Text = "";
72 | desired = realDes;
73 | }
74 | if (Int32.TryParse(maxVal.Text, out max))
75 | {
76 | maxVal.Text = max.ToString();
77 | }
78 | else
79 | {
80 | maxVal.Text = "";
81 | max = realMax;
82 | }
83 | }
84 |
85 | private void ok_Click(object sender, RoutedEventArgs e)
86 | {
87 | int min, desired, max;
88 | ParseValues(out min, out desired, out max);
89 |
90 | var config = new AmazonGameLiftConfig();
91 | config.RegionEndpoint = currentRegion;
92 | using (AmazonGameLiftClient aglc = new AmazonGameLiftClient(config))
93 | {
94 | try
95 | {
96 | Amazon.GameLift.Model.UpdateFleetCapacityResponse ufcres = aglc.UpdateFleetCapacity(new Amazon.GameLift.Model.UpdateFleetCapacityRequest
97 | {
98 | MinSize = min,
99 | DesiredInstances = desired,
100 | MaxSize = max,
101 | FleetId = fleetId
102 | });
103 | }
104 | catch (Exception) {
105 | MessageBox.Show(main, "You probably went over your service limits. Reduce your maximum instance count.", "Problem scaling fleet", MessageBoxButton.OK, MessageBoxImage.Error);
106 | }
107 | }
108 | main.RefreshInstanceLabel();
109 | this.Close();
110 | }
111 |
112 | private void cancel_Click(object sender, RoutedEventArgs e)
113 | {
114 | this.Close();
115 | }
116 |
117 | private bool IsTextAllowed(string text)
118 | {
119 | Regex regex = new Regex("^[0-9]+$");
120 | return regex.IsMatch(text);
121 | }
122 |
123 | private void ValidateValue(object sender, TextCompositionEventArgs e)
124 | {
125 | e.Handled = !IsTextAllowed(e.Text);
126 | }
127 |
128 | private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
129 | {
130 | if (e.DataObject.GetDataPresent(typeof(String)))
131 | {
132 | String text = (String)e.DataObject.GetData(typeof(String));
133 | if (!IsTextAllowed(text))
134 | {
135 | e.CancelCommand();
136 | }
137 | }
138 | else
139 | {
140 | e.CancelCommand();
141 | }
142 | }
143 |
144 | private void minVal_TextChanged(object sender, TextChangedEventArgs e)
145 | {
146 | if (init == false) return;
147 | init = false;
148 | int min, desired, max;
149 | ParseValues(out min, out desired, out max);
150 |
151 | realMin = min;
152 |
153 | if (min > desired)
154 | desiredVal.Text = min.ToString();
155 | if (min > max)
156 | maxVal.Text = min.ToString();
157 | if (desired > realDes)
158 | desiredVal.Text = Math.Max(min, realDes).ToString();
159 | if (max > realMax)
160 | maxVal.Text = Math.Max(Math.Max(min, realDes), realMax).ToString();
161 | SetSliderBounds();
162 | init = true;
163 | }
164 |
165 | private void desiredVal_TextChanged(object sender, TextChangedEventArgs e)
166 | {
167 | if (init == false) return;
168 | init = false;
169 | int min, desired, max;
170 | ParseValues(out min, out desired, out max);
171 |
172 | realDes = desired;
173 |
174 | if (min > desired)
175 | minVal.Text = desired.ToString();
176 | if (desired > max)
177 | maxVal.Text = desired.ToString();
178 | if (min < realMin)
179 | minVal.Text = Math.Min(realMin, desired).ToString();
180 | if (max > realMax)
181 | maxVal.Text = Math.Max(desired, realMax).ToString();
182 | SetSliderBounds();
183 | init = true;
184 | }
185 |
186 | private void maxVal_TextChanged(object sender, TextChangedEventArgs e)
187 | {
188 | if (init == false) return;
189 | init = false;
190 | int min, desired, max;
191 | ParseValues(out min, out desired, out max);
192 |
193 | realMax = max;
194 |
195 | if (desired > max)
196 | desiredVal.Text = max.ToString();
197 | if (min > max)
198 | minVal.Text = max.ToString();
199 | if (desired < realDes)
200 | desiredVal.Text = Math.Min(realDes, max).ToString();
201 | if (min < realMin)
202 | minVal.Text = Math.Min(Math.Min(realMin, realDes), max).ToString();
203 | SetSliderBounds();
204 | init = true;
205 | }
206 |
207 | private void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
208 | {
209 | if (init == false) return;
210 | init = false;
211 | int min, desired, max;
212 | ParseValues(out min, out desired, out max);
213 |
214 | desired = (int)slider.Value;
215 | realDes = desired;
216 | desiredVal.Text = desired.ToString();
217 |
218 | if (min > desired)
219 | minVal.Text = desired.ToString();
220 | if (desired > max)
221 | maxVal.Text = desired.ToString();
222 | if (min < realMin)
223 | minVal.Text = Math.Min(realMin, desired).ToString();
224 | if (max > realMax)
225 | maxVal.Text = Math.Max(desired, realMax).ToString();
226 | SetSliderBounds();
227 | init = true;
228 |
229 | }
230 |
231 | private void SetSliderBounds()
232 | {
233 | int min, desired, max;
234 | Int32.TryParse(minVal.Text, out min);
235 | Int32.TryParse(desiredVal.Text, out desired);
236 | Int32.TryParse(maxVal.Text, out max);
237 |
238 | slider.Minimum = Math.Max(0, min - 5);
239 | slider.Value = desired;
240 | slider.Maximum = Math.Max(max, min + 20);
241 | }
242 | }
243 | }
244 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # amazon-gamelift-remote-plus
2 |
3 | ## Introduction
4 |
5 | Users of Amazon GameLift have from time to time requested help accessing fleet instances using Secure Shell (SSH) for fleets running Linux, and Remote Desktop Protocol (RDP) for fleets running Windows. Performing these operations manually each time is laborious, so this tool turns these remote connections into a couple of clicks. More details are given about the features in the Features section below.
6 |
7 | 
8 |
9 | You need this project if:
10 | * You use Amazon GameLift
11 | * You need to connect to fleet instances using SSH or RDP
12 | * You have (or can obtain) credentials to call AWS SDK commands on your fleets
13 | * You are running Windows locally
14 |
15 | ## Building the project
16 |
17 | ### Prerequisites
18 |
19 | You must have Visual Studio 2017 or 2019 installed to build this project from source. Either Community, Professional or Enterprise editions will work. You must have the following features installed:
20 |
21 | * .NET Framework 4.5 targeting pack
22 | * C# Roslyn compiler
23 | * C++/CLI support
24 | * MSBuild
25 | * Platform toolset v141 (or you could open the solution in Visual Studio to upgrade the project files to a later toolset that you have installed.)
26 | * C# and Visual Basic
27 | * Visual Studio C++ Core Features
28 |
29 | These features are all installed if you selected .NET desktop development, and Desktop development with C++ workloads when you installed Visual Studio. Features can be selected in the Visual Studio Installer.
30 |
31 | ### Getting the files
32 |
33 | You must have git installed to clone the repository.
34 |
35 | To clone the project repository, issue this command at the command line. Ensure that you are working in the directory that wish to clone the project into. For example if you are in directory ```C:\dev\``` then the project will end up in the directory ```C:\dev\amazon-gamelift-remote-plus\``` and the build directory will then be ```C:\dev\amazon-gamelift-remote-plus\build\```
36 |
37 | ```bat
38 | git clone https://github.com/awslabs/amazon-gamelift-remote-plus.git
39 | ```
40 |
41 | ### Compiling the binaries
42 |
43 | To build the project, issue these commands at the command line.
44 |
45 | ```bat
46 | cd build
47 | build
48 | run
49 | ```
50 |
51 | The run command will run the application.
52 |
53 | ## Installing credentials
54 |
55 | You may already have credentials set up in your shared credentials file with sufficient permissions to make calls to the AWS GameLift API. If so, you may skip this section. This section assumes that you have no credentials.
56 |
57 | This project calls the Amazon GameLift APIs from code. For these calls to succeed, AWS credentials are required. To obtain credentials, create an IAM user with the following policy, either attaching the policy to the user, or placing the user in a group which has the policy attached.
58 |
59 | ```json
60 | {
61 | "Version": "2012-10-17",
62 | "Statement":
63 | {
64 | "SID": "amazon-gamelift-remote-plus",
65 | "Effect": "Allow",
66 | "Action": [
67 | "gamelift:DeleteAlias",
68 | "gamelift:DeleteBuild",
69 | "gamelift:DeleteFleet",
70 | "gamelift:DescribeFleetAttributes",
71 | "gamelift:DescribeFleetCapacity",
72 | "gamelift:DescribeInstances",
73 | "gamelift:GetInstanceAccess",
74 | "gamelift:ListAliases",
75 | "gamelift:ListBuilds",
76 | "gamelift:UpdateFleetCapacity",
77 | "gamelift:UpdateFleetPortSettings" ],
78 | "Resource": "*"
79 | }
80 | }
81 | ```
82 |
83 | You may choose to prohibit deletion of aliases, builds, and/or fleets by removing the respective actions in the policy, if you only want to use the tool for connecting to instances.
84 |
85 | Create access keys for the IAM user that you created
86 |
87 | 1. Sign in to the AWS Management Console and open the IAM console at .
88 |
89 | 1. In the navigation pane, choose Users.
90 |
91 | 1. Choose the name of the user whose access keys you want to create, and then choose the Security credentials tab.
92 |
93 | 1. In the Access keys section, choose Create access key.
94 |
95 | 1. To view the new access key pair, choose Show. You will not have access to the secret access key again after this dialog box closes. Your credentials will look something like this:
96 |
97 | ```txt
98 | Access key ID: AKIAIOSFODNN7EXAMPLE
99 | Secret access key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
100 | ```
101 |
102 | 1. To download the key pair, choose Download .csv file. Store the keys in a secure location. You will not have access to the secret access key again after this dialog box closes.
103 |
104 | 1. Keep the keys confidential in order to protect your AWS account and never email them. Do not share them outside your organization, even if an inquiry appears to come from AWS or Amazon.com. No one who legitimately represents Amazon will ever ask you for your secret key.
105 |
106 | 1. After you download the .csv file, choose Close. When you create an access key, the key pair is active by default, and you can use the pair right away.
107 |
108 | 1. For general use, the ```aws configure``` command is the fastest way to set up your AWS credentials. It uses the AWS CLI. If you have not already, install the AWS CLI v2 as described in [this section of the documentation](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-windows.html)
109 |
110 | When you enter the ```aws configure``` command, the AWS CLI prompts you for four pieces of information:
111 |
112 | ```txt
113 | Access key ID
114 | Secret access key
115 | AWS Region
116 | Output format
117 | ```
118 |
119 | The AWS CLI stores this information in a profile (a collection of settings) named default in the credentials file. By default, the information in this profile is used when you run an AWS CLI command that doesn't explicitly specify a profile to use. For more information on the credentials file, see Configuration and credential file settings
120 |
121 | The following example shows sample values. Replace them with your own values.
122 |
123 | 
124 |
125 | Default region name is not required, but if supplied, amazon-gamelift-remote-plus uses the default region to set up the region selection box when it starts, meaning that you are viewing the fleets in this region without having to select it. This is great in development when the development environment spans a single region.
126 |
127 | ## User guide - simples!
128 |
129 | 
130 |
131 | ## Features
132 |
133 | 1. Users can select a region and see all the fleets in the region. Fleets are shown with their fleet id, name, and status.
134 |
135 | 1. Selecting a fleet permits the user one-click access to the fleet in the AWS console, using the 'View in Console' button.
136 |
137 | 1. Selecting a fleet permits the user one-click deletion of the fleet, using the 'Delete Fleet' button. The 'Delete Fleet' button is greyed out initially, and may be enabled by means of a setting in the Settings window.
138 |
139 | 1. Selecting a fleet permits opening of a scaling window. The scaling window enables the minimum, desired and maximum number of instances to be set easily using a slider control.
140 |
141 | 1. When a fleet is selected, the current scaling parameters (min, max, desired, idle, active), and a list of instances in the fleet is shown. Fleet instances are shown with their instance id, IP address, and status.
142 |
143 | 1. Selecting a fleet instance permits the user one-click connection to the fleet instance. If necessary, PuTTY is downloaded and installed, the correct ports are opened on the fleet instance to the user's local machine, access credentials are obtained for the instance from GameLift API, the credentials are converted into a usable format, and the correct tool is opened to provide remote access to the instance. This saves users a lot of time over using the command line.
144 |
145 | 1. A setting is provided to open an additional remote debugging port on the fleet if enabled. Check the box and type in a port number. When connecting to an instance, the port specified will be opened, as well as port 22 (for connecting to Linux instances with SSH) or port 3389 (for connecting to Windows instances with Remote Desktop).
146 |
147 | 1. A setting is provided to provide a custom CIDR to open ports for, in the event that a proxy or VPN is in use, for example.
148 |
149 | 1. Aliases in the region may also be shown in a simple drop down list by clicking on it.
150 |
151 | 1. Selecting an alias permits the user one-click access to the alias in the AWS console, using the 'View in Console' button.
152 |
153 | 1. Selecting an alias permits the user one-click deletion of the alias, using the 'Delete Alias' button. The 'Delete Alias' button is greyed out initially, and may be enabled by means of a setting in the Settings window.
154 |
155 | 1. Builds in the region may also be shown in a simple drop down list by clicking on it.
156 |
157 | 1. Selecting a build permits the user one-click access to the build in the AWS console, using the 'View in Console' button. The user is also permitted one-click access to create a fleet from the build in the AWS console, using the 'Create Fleet' button.
158 |
159 | 1. Selecting a build permits the user one-click deletion of the build, using the 'Delete Build' button. The 'Delete Alias' button is greyed out initially, and may be enabled by means of a setting in the Settings window.
160 |
161 | 1. When closing the application, the user is offered the option to close any ports on any fleets that were opened by the utility.
162 |
163 | 1. Any button that is greyed out (not enabled) has an instructional tooltip explaining what is needed.
164 |
--------------------------------------------------------------------------------
/src/KeyConvert/misc.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #include
5 | #include "misc.h"
6 | #include "malloc.h"
7 | #include
8 |
9 |
10 | //177
11 | //void modalfatalbox(char *fmt, ...) {}
12 | #define modalfatalbox printf
13 |
14 | /* 281----------------------------------------------------------------------
15 | * String handling routines.
16 | */
17 |
18 | char *dupstr(const char *s)
19 | {
20 | char *p = NULL;
21 | if (s) {
22 | int len = strlen(s);
23 | p = snewn(len + 1, char);
24 | strcpy(p, s);
25 | }
26 | return p;
27 | }
28 |
29 | //338
30 | int toint(unsigned u)
31 | {
32 | /*
33 | * Convert an unsigned to an int, without running into the
34 | * undefined behaviour which happens by the strict C standard if
35 | * the value overflows. You'd hope that sensible compilers would
36 | * do the sensible thing in response to a cast, but actually I
37 | * don't trust modern compilers not to do silly things like
38 | * assuming that _obviously_ you wouldn't have caused an overflow
39 | * and so they can elide an 'if (i < 0)' test immediately after
40 | * the cast.
41 | *
42 | * Sensible compilers ought of course to optimise this entire
43 | * function into 'just return the input value'!
44 | */
45 | if (u <= (unsigned)INT_MAX)
46 | return (int)u;
47 | else if (u >= (unsigned)INT_MIN) /* wrap in cast _to_ unsigned is OK */
48 | return INT_MIN + (int)(u - (unsigned)INT_MIN);
49 | else
50 | return INT_MIN; /* fallback; should never occur on binary machines */
51 | }
52 |
53 | /*452
54 | * Read an entire line of text from a file. Return a buffer
55 | * malloced to be as big as necessary (caller must free).
56 | */
57 | char *fgetline(FILE *fp)
58 | {
59 | char *ret = snewn(512, char);
60 | int size = 512, len = 0;
61 | while (fgets(ret + len, size - len, fp)) {
62 | len += strlen(ret + len);
63 | if (len > 0 && ret[len - 1] == '\n')
64 | break; /* got a newline, we're done */
65 | size = len + 512;
66 | ret = sresize(ret, size, char);
67 | }
68 | if (len == 0) { /* first fgets returned NULL */
69 | sfree(ret);
70 | return NULL;
71 | }
72 | ret[len] = '\0';
73 | return ret;
74 | }
75 |
76 | /* ----------------------------------------------------------------------
77 | * Core base64 encoding and decoding routines.
78 | */
79 |
80 | void base64_encode_atom(unsigned char *data, int n, char *out)
81 | {
82 | static const char base64_chars[] =
83 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
84 |
85 | unsigned word;
86 |
87 | word = data[0] << 16;
88 | if (n > 1)
89 | word |= data[1] << 8;
90 | if (n > 2)
91 | word |= data[2];
92 | out[0] = base64_chars[(word >> 18) & 0x3F];
93 | out[1] = base64_chars[(word >> 12) & 0x3F];
94 | if (n > 1)
95 | out[2] = base64_chars[(word >> 6) & 0x3F];
96 | else
97 | out[2] = '=';
98 | if (n > 2)
99 | out[3] = base64_chars[word & 0x3F];
100 | else
101 | out[3] = '=';
102 | }
103 |
104 | int base64_decode_atom(char *atom, unsigned char *out)
105 | {
106 | int vals[4];
107 | int i, v, len;
108 | unsigned word;
109 | char c;
110 |
111 | for (i = 0; i < 4; i++) {
112 | c = atom[i];
113 | if (c >= 'A' && c <= 'Z')
114 | v = c - 'A';
115 | else if (c >= 'a' && c <= 'z')
116 | v = c - 'a' + 26;
117 | else if (c >= '0' && c <= '9')
118 | v = c - '0' + 52;
119 | else if (c == '+')
120 | v = 62;
121 | else if (c == '/')
122 | v = 63;
123 | else if (c == '=')
124 | v = -1;
125 | else
126 | return 0; /* invalid atom */
127 | vals[i] = v;
128 | }
129 |
130 | if (vals[0] == -1 || vals[1] == -1)
131 | return 0;
132 | if (vals[2] == -1 && vals[3] != -1)
133 | return 0;
134 |
135 | if (vals[3] != -1)
136 | len = 3;
137 | else if (vals[2] != -1)
138 | len = 2;
139 | else
140 | len = 1;
141 |
142 | word = ((vals[0] << 18) |
143 | (vals[1] << 12) | ((vals[2] & 0x3F) << 6) | (vals[3] & 0x3F));
144 | out[0] = (word >> 16) & 0xFF;
145 | if (len > 1)
146 | out[1] = (word >> 8) & 0xFF;
147 | if (len > 2)
148 | out[2] = word & 0xFF;
149 | return len;
150 | }
151 |
152 |
153 | //678
154 | /* ----------------------------------------------------------------------
155 | * My own versions of malloc, realloc and free. Because I want
156 | * malloc and realloc to bomb out and exit the program if they run
157 | * out of memory, realloc to reliably call malloc if passed a NULL
158 | * pointer, and free to reliably do nothing if passed a NULL
159 | * pointer. We can also put trace printouts in, if we need to; and
160 | * we can also replace the allocator with an ElectricFence-like
161 | * one.
162 | */
163 |
164 | #ifdef MINEFIELD
165 | void *minefield_c_malloc(size_t size);
166 | void minefield_c_free(void *p);
167 | void *minefield_c_realloc(void *p, size_t size);
168 | #endif
169 |
170 | #ifdef MALLOC_LOG
171 | static FILE *fp = NULL;
172 |
173 | static char *mlog_file = NULL;
174 | static int mlog_line = 0;
175 |
176 | void mlog(char *file, int line)
177 | {
178 | mlog_file = file;
179 | mlog_line = line;
180 | if (!fp) {
181 | fp = fopen("putty_mem.log", "w");
182 | setvbuf(fp, NULL, _IONBF, BUFSIZ);
183 | }
184 | if (fp)
185 | fprintf(fp, "%s:%d: ", file, line);
186 | }
187 | #endif
188 |
189 | void *safemalloc(size_t n, size_t size)
190 | {
191 | void *p;
192 |
193 | if (n > INT_MAX / size) {
194 | p = NULL;
195 | }
196 | else {
197 | size *= n;
198 | if (size == 0) size = 1;
199 | #ifdef MINEFIELD
200 | p = minefield_c_malloc(size);
201 | #else
202 | p = malloc(size);
203 | #endif
204 | }
205 |
206 | if (!p) {
207 | char str[200];
208 | #ifdef MALLOC_LOG
209 | sprintf(str, "Out of memory! (%s:%d, size=%d)",
210 | mlog_file, mlog_line, size);
211 | fprintf(fp, "*** %s\n", str);
212 | fclose(fp);
213 | #else
214 | strcpy(str, "Out of memory!");
215 | #endif
216 | modalfatalbox("%s", str);
217 | }
218 | #ifdef MALLOC_LOG
219 | if (fp)
220 | fprintf(fp, "malloc(%d) returns %p\n", size, p);
221 | #endif
222 | return p;
223 | }
224 |
225 | void *saferealloc(void *ptr, size_t n, size_t size)
226 | {
227 | void *p;
228 |
229 | if (n > INT_MAX / size) {
230 | p = NULL;
231 | }
232 | else {
233 | size *= n;
234 | if (!ptr) {
235 | #ifdef MINEFIELD
236 | p = minefield_c_malloc(size);
237 | #else
238 | p = malloc(size);
239 | #endif
240 | }
241 | else {
242 | #ifdef MINEFIELD
243 | p = minefield_c_realloc(ptr, size);
244 | #else
245 | p = realloc(ptr, size);
246 | #endif
247 | }
248 | }
249 |
250 | if (!p) {
251 | char str[200];
252 | #ifdef MALLOC_LOG
253 | sprintf(str, "Out of memory! (%s:%d, size=%d)",
254 | mlog_file, mlog_line, size);
255 | fprintf(fp, "*** %s\n", str);
256 | fclose(fp);
257 | #else
258 | strcpy(str, "Out of memory!");
259 | #endif
260 | modalfatalbox("%s", str);
261 | }
262 | #ifdef MALLOC_LOG
263 | if (fp)
264 | fprintf(fp, "realloc(%p,%d) returns %p\n", ptr, size, p);
265 | #endif
266 | return p;
267 | }
268 |
269 | void safefree(void *ptr)
270 | {
271 | if (ptr) {
272 | #ifdef MALLOC_LOG
273 | if (fp)
274 | fprintf(fp, "free(%p)\n", ptr);
275 | #endif
276 | #ifdef MINEFIELD
277 | minefield_c_free(ptr);
278 | #else
279 | free(ptr);
280 | #endif
281 | }
282 | #ifdef MALLOC_LOG
283 | else if (fp)
284 | fprintf(fp, "freeing null pointer - no action taken\n");
285 | #endif
286 | }
287 |
288 | #ifndef PLATFORM_HAS_SMEMCLR
289 | /* 887
290 | * Securely wipe memory.
291 | *
292 | * The actual wiping is no different from what memset would do: the
293 | * point of 'securely' is to try to be sure over-clever compilers
294 | * won't optimise away memsets on variables that are about to be freed
295 | * or go out of scope. See
296 | * https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/771-BSI.html
297 | *
298 | * Some platforms (e.g. Windows) may provide their own version of this
299 | * function.
300 | */
301 | void smemclr(void *b, size_t n) {
302 | volatile char *vp;
303 |
304 | if (b && n > 0) {
305 | /*
306 | * Zero out the memory.
307 | */
308 | memset(b, 0, n);
309 |
310 | /*
311 | * Perform a volatile access to the object, forcing the
312 | * compiler to admit that the previous memset was important.
313 | *
314 | * This while loop should in practice run for zero iterations
315 | * (since we know we just zeroed the object out), but in
316 | * theory (as far as the compiler knows) it might range over
317 | * the whole object. (If we had just written, say, '*vp =
318 | * *vp;', a compiler could in principle have 'helpfully'
319 | * optimised the memset into only zeroing out the first byte.
320 | * This should be robust.)
321 | */
322 | vp = (volatile char*)b;
323 | while (*vp) vp++;
324 | }
325 | }
326 | #endif
327 |
328 | // Windows implementation
329 | //#include "windows.h"
330 | //void smemclr(void *b, size_t n) {
331 | // if (b && n > 0)
332 | // SecureZeroMemory(b, n);
333 | //}
334 |
335 | // 1023
336 | int smemeq(const void *av, const void *bv, size_t len)
337 | {
338 | const unsigned char *a = (const unsigned char *)av;
339 | const unsigned char *b = (const unsigned char *)bv;
340 | unsigned val = 0;
341 |
342 | while (len-- > 0) {
343 | val |= *a++ ^ *b++;
344 | }
345 | /* Now val is 0 iff we want to return 1, and in the range
346 | * 0x01..0xFF iff we want to return 0. So subtracting from 0x100
347 | * will clear bit 8 iff we want to return 0, and leave it set iff
348 | * we want to return 1, so then we can just shift down. */
349 | return (0x100 - val) >> 8;
350 | }
351 |
352 | int strstartswith(const char *s, const char *t)
353 | {
354 | return !memcmp(s, t, strlen(t));
355 | }
356 |
357 | int strendswith(const char *s, const char *t)
358 | {
359 | size_t slen = strlen(s), tlen = strlen(t);
360 | return slen >= tlen && !strcmp(s + (slen - tlen), t);
361 | }
362 |
--------------------------------------------------------------------------------
/src/KeyConvert/ssh.h:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #include "misc.h"
5 |
6 |
7 | //78
8 | #ifndef BIGNUM_INTERNAL
9 | typedef unsigned __int32 *Bignum; // this is only true if defined _MSC_VER && defined _M_IX86. If retargeting, see sshbn.h
10 | #endif
11 |
12 | struct RSAKey {
13 | int bits;
14 | int bytes;
15 | #ifdef MSCRYPTOAPI
16 | unsigned long exponent;
17 | unsigned char *modulus;
18 | #else
19 | Bignum modulus;
20 | Bignum exponent;
21 | Bignum private_exponent;
22 | Bignum p;
23 | Bignum q;
24 | Bignum iqmp;
25 | #endif
26 | char *comment;
27 | };
28 |
29 | struct dss_key {
30 | Bignum p, q, g, y, x;
31 | };
32 |
33 |
34 | //118
35 | #ifndef PUTTY_UINT32_DEFINED
36 | /* This makes assumptions about the int type. */
37 | typedef unsigned int uint32;
38 | #define PUTTY_UINT32_DEFINED
39 | #endif
40 | typedef uint32 word32;
41 |
42 | // from int64.h
43 | typedef struct {
44 | unsigned long hi, lo;
45 | } uint64;
46 |
47 | /* 134
48 | * SSH2 RSA key exchange functions
49 | */
50 | struct ssh_hash;
51 | void *ssh_rsakex_newkey(char *data, int len);
52 | void ssh_rsakex_freekey(void *key);
53 | int ssh_rsakex_klen(void *key);
54 | //void ssh_rsakex_encrypt(const struct ssh_hash *h, unsigned char *in, int inlen,
55 | // unsigned char *out, int outlen,
56 | // void *key);
57 |
58 | typedef struct {
59 | uint32 h[4];
60 | } MD5_Core_State;
61 |
62 | struct MD5Context {
63 | #ifdef MSCRYPTOAPI
64 | unsigned long hHash;
65 | #else
66 | MD5_Core_State core;
67 | unsigned char block[64];
68 | int blkused;
69 | uint32 lenhi, lenlo;
70 | #endif
71 | };
72 |
73 | void MD5Init(struct MD5Context *context);
74 | void MD5Update(struct MD5Context *context, unsigned char const *buf,
75 | unsigned len);
76 | void MD5Final(unsigned char digest[16], struct MD5Context *context);
77 | void MD5Simple(void const *p, unsigned len, unsigned char output[16]);
78 |
79 | void *hmacmd5_make_context(void);
80 | void hmacmd5_free_context(void *handle);
81 | void hmacmd5_key(void *handle, void const *key, int len);
82 | void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len,
83 | unsigned char *hmac);
84 |
85 |
86 |
87 |
88 | //172
89 | typedef struct {
90 | uint32 h[5];
91 | unsigned char block[64];
92 | int blkused;
93 | uint32 lenhi, lenlo;
94 | } SHA_State;
95 | void SHA_Init(SHA_State * s);
96 | void SHA_Bytes(SHA_State * s, const void *p, int len);
97 | void SHA_Final(SHA_State * s, unsigned char *output);
98 | void SHA_Simple(const void *p, int len, unsigned char *output);
99 |
100 | void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
101 | unsigned char *output);
102 |
103 |
104 |
105 | // 196
106 | typedef struct {
107 | uint64 h[8];
108 | unsigned char block[128];
109 | int blkused;
110 | uint32 len[4];
111 | } SHA512_State;
112 | void SHA512_Init(SHA512_State * s);
113 | void SHA512_Bytes(SHA512_State * s, const void *p, int len);
114 | void SHA512_Final(SHA512_State * s, unsigned char *output);
115 | void SHA512_Simple(const void *p, int len, unsigned char *output);
116 |
117 | struct ssh_cipher {
118 | void *(*make_context)(void);
119 | void(*free_context)(void *);
120 | void(*sesskey) (void *, unsigned char *key); /* for SSH-1 */
121 | void(*encrypt) (void *, unsigned char *blk, int len);
122 | void(*decrypt) (void *, unsigned char *blk, int len);
123 | int blksize;
124 | char *text_name;
125 | };
126 |
127 | struct ssh2_cipher {
128 | void *(*make_context)(void);
129 | void(*free_context)(void *);
130 | void(*setiv) (void *, unsigned char *key); /* for SSH-2 */
131 | void(*setkey) (void *, unsigned char *key);/* for SSH-2 */
132 | void(*encrypt) (void *, unsigned char *blk, int len);
133 | void(*decrypt) (void *, unsigned char *blk, int len);
134 | char *name;
135 | int blksize;
136 | int keylen;
137 | unsigned int flags;
138 | #define SSH_CIPHER_IS_CBC 1
139 | char *text_name;
140 | };
141 |
142 | struct ssh2_ciphers {
143 | int nciphers;
144 | const struct ssh2_cipher *const *list;
145 | };
146 |
147 | struct ssh_mac {
148 | void *(*make_context)(void);
149 | void(*free_context)(void *);
150 | void(*setkey) (void *, unsigned char *key);
151 | /* whole-packet operations */
152 | void(*generate) (void *, unsigned char *blk, int len, unsigned long seq);
153 | int(*verify) (void *, unsigned char *blk, int len, unsigned long seq);
154 | /* partial-packet operations */
155 | void(*start) (void *);
156 | void(*bytes) (void *, unsigned char const *, int);
157 | void(*genresult) (void *, unsigned char *);
158 | int(*verresult) (void *, unsigned char const *);
159 | char *name;
160 | int len;
161 | char *text_name;
162 | };
163 |
164 | struct ssh_hash {
165 | void *(*init)(void); /* also allocates context */
166 | void(*bytes)(void *, void *, int);
167 | void(*final)(void *, unsigned char *); /* also frees context */
168 | int hlen; /* output length in bytes */
169 | char *text_name;
170 | };
171 |
172 | typedef enum { KEXTYPE_DH, KEXTYPE_RSA } kextype;
173 |
174 | struct ssh_kex {
175 | char *name, *groupname;
176 | kextype main_type;
177 | /* For DH */
178 | const unsigned char *pdata, *gdata; /* NULL means group exchange */
179 | int plen, glen;
180 | const struct ssh_hash *hash;
181 | };
182 |
183 | struct ssh_kexes {
184 | int nkexes;
185 | const struct ssh_kex *const *list;
186 | };
187 |
188 | struct ssh_signkey {
189 | void *(*newkey) (char *data, int len);
190 | void(*freekey) (void *key);
191 | char *(*fmtkey) (void *key);
192 | unsigned char *(*public_blob) (void *key, int *len);
193 | unsigned char *(*private_blob) (void *key, int *len);
194 | void *(*createkey) (unsigned char *pub_blob, int pub_len,
195 | unsigned char *priv_blob, int priv_len);
196 | void *(*openssh_createkey) (unsigned char **blob, int *len);
197 | int(*openssh_fmtkey) (void *key, unsigned char *blob, int len);
198 | int(*pubkey_bits) (void *blob, int len);
199 | char *(*fingerprint) (void *key);
200 | int(*verifysig) (void *key, char *sig, int siglen,
201 | char *data, int datalen);
202 | unsigned char *(*sign) (void *key, char *data, int datalen,
203 | int *siglen);
204 | char *name;
205 | char *keytype; /* for host key cache */
206 | };
207 |
208 |
209 |
210 | //313
211 | struct ssh2_userkey {
212 | const struct ssh_signkey *alg; /* the key algorithm */
213 | void *data; /* the key data */
214 | char *comment; /* the key comment */
215 | };
216 |
217 | /* The maximum length of any hash algorithm used in kex. (bytes) */
218 | #define SSH2_KEX_MAX_HASH_LEN (32) /* SHA-256 */
219 |
220 | //extern const struct ssh_cipher ssh_3des;
221 | //extern const struct ssh_cipher ssh_des;
222 | //extern const struct ssh_cipher ssh_blowfish_ssh1;
223 | //extern const struct ssh2_ciphers ssh2_3des;
224 | //extern const struct ssh2_ciphers ssh2_des;
225 | //extern const struct ssh2_ciphers ssh2_aes;
226 | //extern const struct ssh2_ciphers ssh2_blowfish;
227 | //extern const struct ssh2_ciphers ssh2_arcfour;
228 | extern const struct ssh_hash ssh_sha1;
229 | extern const struct ssh_hash ssh_sha256;
230 | //extern const struct ssh_kexes ssh_diffiehellman_group1;
231 | //extern const struct ssh_kexes ssh_diffiehellman_group14;
232 | //extern const struct ssh_kexes ssh_diffiehellman_gex;
233 | //extern const struct ssh_kexes ssh_rsa_kex;
234 | extern const struct ssh_signkey ssh_dss;
235 | extern const struct ssh_signkey ssh_rsa;
236 | //extern const struct ssh_mac ssh_hmac_md5;
237 | //extern const struct ssh_mac ssh_hmac_sha1;
238 | //extern const struct ssh_mac ssh_hmac_sha1_buggy;
239 | //extern const struct ssh_mac ssh_hmac_sha1_96;
240 | //extern const struct ssh_mac ssh_hmac_sha1_96_buggy;
241 | //extern const struct ssh_mac ssh_hmac_sha256;
242 |
243 | void *aes_make_context(void);
244 | void aes_free_context(void *handle);
245 | void aes128_key(void *handle, unsigned char *key);
246 | void aes192_key(void *handle, unsigned char *key);
247 | void aes256_key(void *handle, unsigned char *key);
248 | void aes_iv(void *handle, unsigned char *iv);
249 | void aes_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len);
250 | void aes_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len);
251 |
252 | //370
253 | int random_byte(void);
254 |
255 |
256 | //499
257 | Bignum copybn(Bignum b);
258 | //Bignum bn_power_2(int n);
259 | void bn_restore_invariant(Bignum b);
260 | //Bignum bignum_from_long(unsigned long n);
261 | void freebn(Bignum b);
262 | Bignum modpow(Bignum base, Bignum exp, Bignum mod);
263 | Bignum modmul(Bignum a, Bignum b, Bignum mod);
264 | void decbn(Bignum n);
265 | extern Bignum Zero, One;
266 | Bignum bignum_from_bytes(const unsigned char *data, int nbytes);
267 | int ssh1_read_bignum(const unsigned char *data, int len, Bignum * result);
268 | int bignum_bitcount(Bignum bn);
269 | int ssh1_bignum_length(Bignum bn);
270 | int ssh2_bignum_length(Bignum bn);
271 | int bignum_byte(Bignum bn, int i);
272 | //int bignum_bit(Bignum bn, int i);
273 | void bignum_set_bit(Bignum bn, int i, int value);
274 | int ssh1_write_bignum(void *data, Bignum bn);
275 | //Bignum biggcd(Bignum a, Bignum b);
276 | //unsigned short bignum_mod_short(Bignum number, unsigned short modulus);
277 | //Bignum bignum_add_long(Bignum number, unsigned long addend);
278 | Bignum bigadd(Bignum a, Bignum b);
279 | Bignum bigsub(Bignum a, Bignum b);
280 | Bignum bigmul(Bignum a, Bignum b);
281 | Bignum bigmuladd(Bignum a, Bignum b, Bignum addend);
282 | //Bignum bigdiv(Bignum a, Bignum b);
283 | Bignum bigmod(Bignum a, Bignum b);
284 | Bignum modinv(Bignum number, Bignum modulus);
285 | //Bignum bignum_bitmask(Bignum number);
286 | //Bignum bignum_rshift(Bignum number, int shift);
287 | int bignum_cmp(Bignum a, Bignum b);
288 | //char *bignum_decimal(Bignum x);
289 |
290 |
291 | //552
292 | int base64_lines(int datalen);
293 |
294 |
295 | //554
296 | void base64_encode(FILE *fp, unsigned char *data, int datalen, int cpl);
297 |
298 |
299 | //556
300 | /* ssh2_load_userkey can return this as an error */
301 | extern struct ssh2_userkey ssh2_wrong_passphrase;
302 | #define SSH2_WRONG_PASSPHRASE (&ssh2_wrong_passphrase)
303 |
304 | //566
305 | int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
306 | char *passphrase);
307 |
308 |
309 | //570
310 | enum {
311 | SSH_KEYTYPE_UNOPENABLE,
312 | SSH_KEYTYPE_UNKNOWN,
313 | SSH_KEYTYPE_SSH1, SSH_KEYTYPE_SSH2,
314 | SSH_KEYTYPE_OPENSSH, SSH_KEYTYPE_SSHCOM
315 | };
316 |
317 |
318 | //584
319 | struct ssh2_userkey *import_ssh2(const Filename *filename, int type,
320 | char *passphrase, const char **errmsg_p);
321 |
322 | //593
323 | void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
324 | unsigned char *blk, int len);
325 |
326 | //597
327 | void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk,
328 | int len);
329 |
--------------------------------------------------------------------------------
/src/KeyConvert/sshmd5.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #include "ssh.h"
5 |
6 | /*
7 | * MD5 implementation for PuTTY. Written directly from the spec by
8 | * Simon Tatham.
9 | */
10 |
11 | /* ----------------------------------------------------------------------
12 | * Core MD5 algorithm: processes 16-word blocks into a message digest.
13 | */
14 |
15 | #define F(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) )
16 | #define G(x,y,z) ( ((x) & (z)) | ((~(z)) & (y)) )
17 | #define H(x,y,z) ( (x) ^ (y) ^ (z) )
18 | #define I(x,y,z) ( (y) ^ ( (x) | ~(z) ) )
19 |
20 | #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )
21 |
22 | #define subround(f,w,x,y,z,k,s,ti) \
23 | w = x + rol(w + f(x,y,z) + block[k] + ti, s)
24 |
25 | static void MD5_Core_Init(MD5_Core_State * s)
26 | {
27 | s->h[0] = 0x67452301;
28 | s->h[1] = 0xefcdab89;
29 | s->h[2] = 0x98badcfe;
30 | s->h[3] = 0x10325476;
31 | }
32 |
33 | static void MD5_Block(MD5_Core_State * s, uint32 * block)
34 | {
35 | uint32 a, b, c, d;
36 |
37 | a = s->h[0];
38 | b = s->h[1];
39 | c = s->h[2];
40 | d = s->h[3];
41 |
42 | subround(F, a, b, c, d, 0, 7, 0xd76aa478);
43 | subround(F, d, a, b, c, 1, 12, 0xe8c7b756);
44 | subround(F, c, d, a, b, 2, 17, 0x242070db);
45 | subround(F, b, c, d, a, 3, 22, 0xc1bdceee);
46 | subround(F, a, b, c, d, 4, 7, 0xf57c0faf);
47 | subround(F, d, a, b, c, 5, 12, 0x4787c62a);
48 | subround(F, c, d, a, b, 6, 17, 0xa8304613);
49 | subround(F, b, c, d, a, 7, 22, 0xfd469501);
50 | subround(F, a, b, c, d, 8, 7, 0x698098d8);
51 | subround(F, d, a, b, c, 9, 12, 0x8b44f7af);
52 | subround(F, c, d, a, b, 10, 17, 0xffff5bb1);
53 | subround(F, b, c, d, a, 11, 22, 0x895cd7be);
54 | subround(F, a, b, c, d, 12, 7, 0x6b901122);
55 | subround(F, d, a, b, c, 13, 12, 0xfd987193);
56 | subround(F, c, d, a, b, 14, 17, 0xa679438e);
57 | subround(F, b, c, d, a, 15, 22, 0x49b40821);
58 | subround(G, a, b, c, d, 1, 5, 0xf61e2562);
59 | subround(G, d, a, b, c, 6, 9, 0xc040b340);
60 | subround(G, c, d, a, b, 11, 14, 0x265e5a51);
61 | subround(G, b, c, d, a, 0, 20, 0xe9b6c7aa);
62 | subround(G, a, b, c, d, 5, 5, 0xd62f105d);
63 | subround(G, d, a, b, c, 10, 9, 0x02441453);
64 | subround(G, c, d, a, b, 15, 14, 0xd8a1e681);
65 | subround(G, b, c, d, a, 4, 20, 0xe7d3fbc8);
66 | subround(G, a, b, c, d, 9, 5, 0x21e1cde6);
67 | subround(G, d, a, b, c, 14, 9, 0xc33707d6);
68 | subround(G, c, d, a, b, 3, 14, 0xf4d50d87);
69 | subround(G, b, c, d, a, 8, 20, 0x455a14ed);
70 | subround(G, a, b, c, d, 13, 5, 0xa9e3e905);
71 | subround(G, d, a, b, c, 2, 9, 0xfcefa3f8);
72 | subround(G, c, d, a, b, 7, 14, 0x676f02d9);
73 | subround(G, b, c, d, a, 12, 20, 0x8d2a4c8a);
74 | subround(H, a, b, c, d, 5, 4, 0xfffa3942);
75 | subround(H, d, a, b, c, 8, 11, 0x8771f681);
76 | subround(H, c, d, a, b, 11, 16, 0x6d9d6122);
77 | subround(H, b, c, d, a, 14, 23, 0xfde5380c);
78 | subround(H, a, b, c, d, 1, 4, 0xa4beea44);
79 | subround(H, d, a, b, c, 4, 11, 0x4bdecfa9);
80 | subround(H, c, d, a, b, 7, 16, 0xf6bb4b60);
81 | subround(H, b, c, d, a, 10, 23, 0xbebfbc70);
82 | subround(H, a, b, c, d, 13, 4, 0x289b7ec6);
83 | subround(H, d, a, b, c, 0, 11, 0xeaa127fa);
84 | subround(H, c, d, a, b, 3, 16, 0xd4ef3085);
85 | subround(H, b, c, d, a, 6, 23, 0x04881d05);
86 | subround(H, a, b, c, d, 9, 4, 0xd9d4d039);
87 | subround(H, d, a, b, c, 12, 11, 0xe6db99e5);
88 | subround(H, c, d, a, b, 15, 16, 0x1fa27cf8);
89 | subround(H, b, c, d, a, 2, 23, 0xc4ac5665);
90 | subround(I, a, b, c, d, 0, 6, 0xf4292244);
91 | subround(I, d, a, b, c, 7, 10, 0x432aff97);
92 | subround(I, c, d, a, b, 14, 15, 0xab9423a7);
93 | subround(I, b, c, d, a, 5, 21, 0xfc93a039);
94 | subround(I, a, b, c, d, 12, 6, 0x655b59c3);
95 | subround(I, d, a, b, c, 3, 10, 0x8f0ccc92);
96 | subround(I, c, d, a, b, 10, 15, 0xffeff47d);
97 | subround(I, b, c, d, a, 1, 21, 0x85845dd1);
98 | subround(I, a, b, c, d, 8, 6, 0x6fa87e4f);
99 | subround(I, d, a, b, c, 15, 10, 0xfe2ce6e0);
100 | subround(I, c, d, a, b, 6, 15, 0xa3014314);
101 | subround(I, b, c, d, a, 13, 21, 0x4e0811a1);
102 | subround(I, a, b, c, d, 4, 6, 0xf7537e82);
103 | subround(I, d, a, b, c, 11, 10, 0xbd3af235);
104 | subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
105 | subround(I, b, c, d, a, 9, 21, 0xeb86d391);
106 |
107 | s->h[0] += a;
108 | s->h[1] += b;
109 | s->h[2] += c;
110 | s->h[3] += d;
111 | }
112 |
113 | /* ----------------------------------------------------------------------
114 | * Outer MD5 algorithm: take an arbitrary length byte string,
115 | * convert it into 16-word blocks with the prescribed padding at
116 | * the end, and pass those blocks to the core MD5 algorithm.
117 | */
118 |
119 | #define BLKSIZE 64
120 |
121 | void MD5Init(struct MD5Context *s)
122 | {
123 | MD5_Core_Init(&s->core);
124 | s->blkused = 0;
125 | s->lenhi = s->lenlo = 0;
126 | }
127 |
128 | void MD5Update(struct MD5Context *s, unsigned char const *p, unsigned len)
129 | {
130 | unsigned char *q = (unsigned char *)p;
131 | uint32 wordblock[16];
132 | uint32 lenw = len;
133 | int i;
134 |
135 | /*
136 | * Update the length field.
137 | */
138 | s->lenlo += lenw;
139 | s->lenhi += (s->lenlo < lenw);
140 |
141 | if (s->blkused + len < BLKSIZE) {
142 | /*
143 | * Trivial case: just add to the block.
144 | */
145 | memcpy(s->block + s->blkused, q, len);
146 | s->blkused += len;
147 | }
148 | else {
149 | /*
150 | * We must complete and process at least one block.
151 | */
152 | while (s->blkused + len >= BLKSIZE) {
153 | memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
154 | q += BLKSIZE - s->blkused;
155 | len -= BLKSIZE - s->blkused;
156 | /* Now process the block. Gather bytes little-endian into words */
157 | for (i = 0; i < 16; i++) {
158 | wordblock[i] =
159 | (((uint32)s->block[i * 4 + 3]) << 24) |
160 | (((uint32)s->block[i * 4 + 2]) << 16) |
161 | (((uint32)s->block[i * 4 + 1]) << 8) |
162 | (((uint32)s->block[i * 4 + 0]) << 0);
163 | }
164 | MD5_Block(&s->core, wordblock);
165 | s->blkused = 0;
166 | }
167 | memcpy(s->block, q, len);
168 | s->blkused = len;
169 | }
170 | }
171 |
172 | void MD5Final(unsigned char output[16], struct MD5Context *s)
173 | {
174 | int i;
175 | unsigned pad;
176 | unsigned char c[64];
177 | uint32 lenhi, lenlo;
178 |
179 | if (s->blkused >= 56)
180 | pad = 56 + 64 - s->blkused;
181 | else
182 | pad = 56 - s->blkused;
183 |
184 | lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
185 | lenlo = (s->lenlo << 3);
186 |
187 | memset(c, 0, pad);
188 | c[0] = 0x80;
189 | MD5Update(s, c, pad);
190 |
191 | c[7] = (lenhi >> 24) & 0xFF;
192 | c[6] = (lenhi >> 16) & 0xFF;
193 | c[5] = (lenhi >> 8) & 0xFF;
194 | c[4] = (lenhi >> 0) & 0xFF;
195 | c[3] = (lenlo >> 24) & 0xFF;
196 | c[2] = (lenlo >> 16) & 0xFF;
197 | c[1] = (lenlo >> 8) & 0xFF;
198 | c[0] = (lenlo >> 0) & 0xFF;
199 |
200 | MD5Update(s, c, 8);
201 |
202 | for (i = 0; i < 4; i++) {
203 | output[4 * i + 3] = (s->core.h[i] >> 24) & 0xFF;
204 | output[4 * i + 2] = (s->core.h[i] >> 16) & 0xFF;
205 | output[4 * i + 1] = (s->core.h[i] >> 8) & 0xFF;
206 | output[4 * i + 0] = (s->core.h[i] >> 0) & 0xFF;
207 | }
208 | }
209 |
210 | void MD5Simple(void const *p, unsigned len, unsigned char output[16])
211 | {
212 | struct MD5Context s;
213 |
214 | MD5Init(&s);
215 | MD5Update(&s, (unsigned char const *)p, len);
216 | MD5Final(output, &s);
217 | smemclr(&s, sizeof(s));
218 | }
219 |
220 | /* ----------------------------------------------------------------------
221 | * The above is the MD5 algorithm itself. Now we implement the
222 | * HMAC wrapper on it.
223 | *
224 | * Some of these functions are exported directly, because they are
225 | * useful elsewhere (SOCKS5 CHAP authentication uses HMAC-MD5).
226 | */
227 |
228 | void *hmacmd5_make_context(void)
229 | {
230 | return snewn(3, struct MD5Context);
231 | }
232 |
233 | void hmacmd5_free_context(void *handle)
234 | {
235 | smemclr(handle, 3 * sizeof(struct MD5Context));
236 | sfree(handle);
237 | }
238 |
239 | void hmacmd5_key(void *handle, void const *keyv, int len)
240 | {
241 | struct MD5Context *keys = (struct MD5Context *)handle;
242 | unsigned char foo[64];
243 | unsigned char const *key = (unsigned char const *)keyv;
244 | int i;
245 |
246 | memset(foo, 0x36, 64);
247 | for (i = 0; i < len && i < 64; i++)
248 | foo[i] ^= key[i];
249 | MD5Init(&keys[0]);
250 | MD5Update(&keys[0], foo, 64);
251 |
252 | memset(foo, 0x5C, 64);
253 | for (i = 0; i < len && i < 64; i++)
254 | foo[i] ^= key[i];
255 | MD5Init(&keys[1]);
256 | MD5Update(&keys[1], foo, 64);
257 |
258 | smemclr(foo, 64); /* burn the evidence */
259 | }
260 |
261 | static void hmacmd5_key_16(void *handle, unsigned char *key)
262 | {
263 | hmacmd5_key(handle, key, 16);
264 | }
265 |
266 | static void hmacmd5_start(void *handle)
267 | {
268 | struct MD5Context *keys = (struct MD5Context *)handle;
269 |
270 | keys[2] = keys[0]; /* structure copy */
271 | }
272 |
273 | static void hmacmd5_bytes(void *handle, unsigned char const *blk, int len)
274 | {
275 | struct MD5Context *keys = (struct MD5Context *)handle;
276 | MD5Update(&keys[2], blk, len);
277 | }
278 |
279 | static void hmacmd5_genresult(void *handle, unsigned char *hmac)
280 | {
281 | struct MD5Context *keys = (struct MD5Context *)handle;
282 | struct MD5Context s;
283 | unsigned char intermediate[16];
284 |
285 | s = keys[2]; /* structure copy */
286 | MD5Final(intermediate, &s);
287 | s = keys[1]; /* structure copy */
288 | MD5Update(&s, intermediate, 16);
289 | MD5Final(hmac, &s);
290 | }
291 |
292 | static int hmacmd5_verresult(void *handle, unsigned char const *hmac)
293 | {
294 | unsigned char correct[16];
295 | hmacmd5_genresult(handle, correct);
296 | return smemeq(correct, hmac, 16);
297 | }
298 |
299 | static void hmacmd5_do_hmac_internal(void *handle,
300 | unsigned char const *blk, int len,
301 | unsigned char const *blk2, int len2,
302 | unsigned char *hmac)
303 | {
304 | hmacmd5_start(handle);
305 | hmacmd5_bytes(handle, blk, len);
306 | if (blk2) hmacmd5_bytes(handle, blk2, len2);
307 | hmacmd5_genresult(handle, hmac);
308 | }
309 |
310 | void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len,
311 | unsigned char *hmac)
312 | {
313 | hmacmd5_do_hmac_internal(handle, blk, len, NULL, 0, hmac);
314 | }
315 |
316 | static void hmacmd5_do_hmac_ssh(void *handle, unsigned char const *blk, int len,
317 | unsigned long seq, unsigned char *hmac)
318 | {
319 | unsigned char seqbuf[16];
320 |
321 | PUT_32BIT_MSB_FIRST(seqbuf, seq);
322 | hmacmd5_do_hmac_internal(handle, seqbuf, 4, blk, len, hmac);
323 | }
324 |
325 | static void hmacmd5_generate(void *handle, unsigned char *blk, int len,
326 | unsigned long seq)
327 | {
328 | hmacmd5_do_hmac_ssh(handle, blk, len, seq, blk + len);
329 | }
330 |
331 | static int hmacmd5_verify(void *handle, unsigned char *blk, int len,
332 | unsigned long seq)
333 | {
334 | unsigned char correct[16];
335 | hmacmd5_do_hmac_ssh(handle, blk, len, seq, correct);
336 | return smemeq(correct, blk + len, 16);
337 | }
338 |
339 | const struct ssh_mac ssh_hmac_md5 = {
340 | hmacmd5_make_context, hmacmd5_free_context, hmacmd5_key_16,
341 | hmacmd5_generate, hmacmd5_verify,
342 | hmacmd5_start, hmacmd5_bytes, hmacmd5_genresult, hmacmd5_verresult,
343 | "hmac-md5",
344 | 16,
345 | "HMAC-MD5"
346 | };
347 |
--------------------------------------------------------------------------------
/src/KeyConvert/sshsh512.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | /*
5 | * SHA-512 algorithm as described at
6 | *
7 | * http://csrc.nist.gov/cryptval/shs.html
8 | */
9 |
10 | #include "ssh.h"
11 |
12 | #define BLKSIZE 128
13 |
14 | /*
15 | * Arithmetic implementations. Note that AND, XOR and NOT can
16 | * overlap destination with one source, but the others can't.
17 | */
18 | #define add(r,x,y) ( r.lo = y.lo + x.lo, \
19 | r.hi = y.hi + x.hi + ((uint32)r.lo < (uint32)y.lo) )
20 | #define rorB(r,x,y) ( r.lo = ((uint32)x.hi >> ((y)-32)) | ((uint32)x.lo << (64-(y))), \
21 | r.hi = ((uint32)x.lo >> ((y)-32)) | ((uint32)x.hi << (64-(y))) )
22 | #define rorL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
23 | r.hi = ((uint32)x.hi >> (y)) | ((uint32)x.lo << (32-(y))) )
24 | #define shrB(r,x,y) ( r.lo = (uint32)x.hi >> ((y)-32), r.hi = 0 )
25 | #define shrL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
26 | r.hi = (uint32)x.hi >> (y) )
27 | #define and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )
28 | #define xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )
29 | #define not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )
30 | #define INIT(h,l) { h, l }
31 | #define BUILD(r,h,l) ( r.hi = h, r.lo = l )
32 | #define EXTRACT(h,l,r) ( h = r.hi, l = r.lo )
33 |
34 | /* ----------------------------------------------------------------------
35 | * Core SHA512 algorithm: processes 16-doubleword blocks into a
36 | * message digest.
37 | */
38 |
39 | #define Ch(r,t,x,y,z) ( not(t,x), and(r,t,z), and(t,x,y), xor(r,r,t) )
40 | #define Maj(r,t,x,y,z) ( and(r,x,y), and(t,x,z), xor(r,r,t), \
41 | and(t,y,z), xor(r,r,t) )
42 | #define bigsigma0(r,t,x) ( rorL(r,x,28), rorB(t,x,34), xor(r,r,t), \
43 | rorB(t,x,39), xor(r,r,t) )
44 | #define bigsigma1(r,t,x) ( rorL(r,x,14), rorL(t,x,18), xor(r,r,t), \
45 | rorB(t,x,41), xor(r,r,t) )
46 | #define smallsigma0(r,t,x) ( rorL(r,x,1), rorL(t,x,8), xor(r,r,t), \
47 | shrL(t,x,7), xor(r,r,t) )
48 | #define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), xor(r,r,t), \
49 | shrL(t,x,6), xor(r,r,t) )
50 |
51 | static void SHA512_Core_Init(SHA512_State *s) {
52 | static const uint64 iv[] = {
53 | INIT(0x6a09e667, 0xf3bcc908),
54 | INIT(0xbb67ae85, 0x84caa73b),
55 | INIT(0x3c6ef372, 0xfe94f82b),
56 | INIT(0xa54ff53a, 0x5f1d36f1),
57 | INIT(0x510e527f, 0xade682d1),
58 | INIT(0x9b05688c, 0x2b3e6c1f),
59 | INIT(0x1f83d9ab, 0xfb41bd6b),
60 | INIT(0x5be0cd19, 0x137e2179),
61 | };
62 | int i;
63 | for (i = 0; i < 8; i++)
64 | s->h[i] = iv[i];
65 | }
66 |
67 | static void SHA512_Block(SHA512_State *s, uint64 *block) {
68 | uint64 w[80];
69 | uint64 a, b, c, d, e, f, g, h;
70 | static const uint64 k[] = {
71 | INIT(0x428a2f98, 0xd728ae22), INIT(0x71374491, 0x23ef65cd),
72 | INIT(0xb5c0fbcf, 0xec4d3b2f), INIT(0xe9b5dba5, 0x8189dbbc),
73 | INIT(0x3956c25b, 0xf348b538), INIT(0x59f111f1, 0xb605d019),
74 | INIT(0x923f82a4, 0xaf194f9b), INIT(0xab1c5ed5, 0xda6d8118),
75 | INIT(0xd807aa98, 0xa3030242), INIT(0x12835b01, 0x45706fbe),
76 | INIT(0x243185be, 0x4ee4b28c), INIT(0x550c7dc3, 0xd5ffb4e2),
77 | INIT(0x72be5d74, 0xf27b896f), INIT(0x80deb1fe, 0x3b1696b1),
78 | INIT(0x9bdc06a7, 0x25c71235), INIT(0xc19bf174, 0xcf692694),
79 | INIT(0xe49b69c1, 0x9ef14ad2), INIT(0xefbe4786, 0x384f25e3),
80 | INIT(0x0fc19dc6, 0x8b8cd5b5), INIT(0x240ca1cc, 0x77ac9c65),
81 | INIT(0x2de92c6f, 0x592b0275), INIT(0x4a7484aa, 0x6ea6e483),
82 | INIT(0x5cb0a9dc, 0xbd41fbd4), INIT(0x76f988da, 0x831153b5),
83 | INIT(0x983e5152, 0xee66dfab), INIT(0xa831c66d, 0x2db43210),
84 | INIT(0xb00327c8, 0x98fb213f), INIT(0xbf597fc7, 0xbeef0ee4),
85 | INIT(0xc6e00bf3, 0x3da88fc2), INIT(0xd5a79147, 0x930aa725),
86 | INIT(0x06ca6351, 0xe003826f), INIT(0x14292967, 0x0a0e6e70),
87 | INIT(0x27b70a85, 0x46d22ffc), INIT(0x2e1b2138, 0x5c26c926),
88 | INIT(0x4d2c6dfc, 0x5ac42aed), INIT(0x53380d13, 0x9d95b3df),
89 | INIT(0x650a7354, 0x8baf63de), INIT(0x766a0abb, 0x3c77b2a8),
90 | INIT(0x81c2c92e, 0x47edaee6), INIT(0x92722c85, 0x1482353b),
91 | INIT(0xa2bfe8a1, 0x4cf10364), INIT(0xa81a664b, 0xbc423001),
92 | INIT(0xc24b8b70, 0xd0f89791), INIT(0xc76c51a3, 0x0654be30),
93 | INIT(0xd192e819, 0xd6ef5218), INIT(0xd6990624, 0x5565a910),
94 | INIT(0xf40e3585, 0x5771202a), INIT(0x106aa070, 0x32bbd1b8),
95 | INIT(0x19a4c116, 0xb8d2d0c8), INIT(0x1e376c08, 0x5141ab53),
96 | INIT(0x2748774c, 0xdf8eeb99), INIT(0x34b0bcb5, 0xe19b48a8),
97 | INIT(0x391c0cb3, 0xc5c95a63), INIT(0x4ed8aa4a, 0xe3418acb),
98 | INIT(0x5b9cca4f, 0x7763e373), INIT(0x682e6ff3, 0xd6b2b8a3),
99 | INIT(0x748f82ee, 0x5defb2fc), INIT(0x78a5636f, 0x43172f60),
100 | INIT(0x84c87814, 0xa1f0ab72), INIT(0x8cc70208, 0x1a6439ec),
101 | INIT(0x90befffa, 0x23631e28), INIT(0xa4506ceb, 0xde82bde9),
102 | INIT(0xbef9a3f7, 0xb2c67915), INIT(0xc67178f2, 0xe372532b),
103 | INIT(0xca273ece, 0xea26619c), INIT(0xd186b8c7, 0x21c0c207),
104 | INIT(0xeada7dd6, 0xcde0eb1e), INIT(0xf57d4f7f, 0xee6ed178),
105 | INIT(0x06f067aa, 0x72176fba), INIT(0x0a637dc5, 0xa2c898a6),
106 | INIT(0x113f9804, 0xbef90dae), INIT(0x1b710b35, 0x131c471b),
107 | INIT(0x28db77f5, 0x23047d84), INIT(0x32caab7b, 0x40c72493),
108 | INIT(0x3c9ebe0a, 0x15c9bebc), INIT(0x431d67c4, 0x9c100d4c),
109 | INIT(0x4cc5d4be, 0xcb3e42b6), INIT(0x597f299c, 0xfc657e2a),
110 | INIT(0x5fcb6fab, 0x3ad6faec), INIT(0x6c44198c, 0x4a475817),
111 | };
112 |
113 | int t;
114 |
115 | for (t = 0; t < 16; t++)
116 | w[t] = block[t];
117 |
118 | for (t = 16; t < 80; t++) {
119 | uint64 p, q, r, tmp;
120 | smallsigma1(p, tmp, w[t - 2]);
121 | smallsigma0(q, tmp, w[t - 15]);
122 | add(r, p, q);
123 | add(p, r, w[t - 7]);
124 | add(w[t], p, w[t - 16]);
125 | }
126 |
127 | a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
128 | e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
129 |
130 | for (t = 0; t < 80; t += 8) {
131 | uint64 tmp, p, q, r;
132 |
133 | #define ROUND(j,a,b,c,d,e,f,g,h) \
134 | bigsigma1(p, tmp, e); \
135 | Ch(q, tmp, e, f, g); \
136 | add(r, p, q); \
137 | add(p, r, k[j]) ; \
138 | add(q, p, w[j]); \
139 | add(r, q, h); \
140 | bigsigma0(p, tmp, a); \
141 | Maj(tmp, q, a, b, c); \
142 | add(q, tmp, p); \
143 | add(p, r, d); \
144 | d = p; \
145 | add(h, q, r);
146 |
147 | ROUND(t + 0, a, b, c, d, e, f, g, h);
148 | ROUND(t + 1, h, a, b, c, d, e, f, g);
149 | ROUND(t + 2, g, h, a, b, c, d, e, f);
150 | ROUND(t + 3, f, g, h, a, b, c, d, e);
151 | ROUND(t + 4, e, f, g, h, a, b, c, d);
152 | ROUND(t + 5, d, e, f, g, h, a, b, c);
153 | ROUND(t + 6, c, d, e, f, g, h, a, b);
154 | ROUND(t + 7, b, c, d, e, f, g, h, a);
155 | }
156 |
157 | {
158 | uint64 tmp;
159 | #define UPDATE(state, local) ( tmp = state, add(state, tmp, local) )
160 | UPDATE(s->h[0], a); UPDATE(s->h[1], b);
161 | UPDATE(s->h[2], c); UPDATE(s->h[3], d);
162 | UPDATE(s->h[4], e); UPDATE(s->h[5], f);
163 | UPDATE(s->h[6], g); UPDATE(s->h[7], h);
164 | }
165 | }
166 |
167 | /* ----------------------------------------------------------------------
168 | * Outer SHA512 algorithm: take an arbitrary length byte string,
169 | * convert it into 16-doubleword blocks with the prescribed padding
170 | * at the end, and pass those blocks to the core SHA512 algorithm.
171 | */
172 |
173 | void SHA512_Init(SHA512_State *s) {
174 | int i;
175 | SHA512_Core_Init(s);
176 | s->blkused = 0;
177 | for (i = 0; i < 4; i++)
178 | s->len[i] = 0;
179 | }
180 |
181 | void SHA512_Bytes(SHA512_State *s, const void *p, int len) {
182 | unsigned char *q = (unsigned char *)p;
183 | uint64 wordblock[16];
184 | uint32 lenw = len;
185 | int i;
186 |
187 | /*
188 | * Update the length field.
189 | */
190 | for (i = 0; i < 4; i++) {
191 | s->len[i] += lenw;
192 | lenw = (s->len[i] < lenw);
193 | }
194 |
195 | if (s->blkused && s->blkused + len < BLKSIZE) {
196 | /*
197 | * Trivial case: just add to the block.
198 | */
199 | memcpy(s->block + s->blkused, q, len);
200 | s->blkused += len;
201 | }
202 | else {
203 | /*
204 | * We must complete and process at least one block.
205 | */
206 | while (s->blkused + len >= BLKSIZE) {
207 | memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
208 | q += BLKSIZE - s->blkused;
209 | len -= BLKSIZE - s->blkused;
210 | /* Now process the block. Gather bytes big-endian into words */
211 | for (i = 0; i < 16; i++) {
212 | uint32 h, l;
213 | h = (((uint32)s->block[i * 8 + 0]) << 24) |
214 | (((uint32)s->block[i * 8 + 1]) << 16) |
215 | (((uint32)s->block[i * 8 + 2]) << 8) |
216 | (((uint32)s->block[i * 8 + 3]) << 0);
217 | l = (((uint32)s->block[i * 8 + 4]) << 24) |
218 | (((uint32)s->block[i * 8 + 5]) << 16) |
219 | (((uint32)s->block[i * 8 + 6]) << 8) |
220 | (((uint32)s->block[i * 8 + 7]) << 0);
221 | BUILD(wordblock[i], h, l);
222 | }
223 | SHA512_Block(s, wordblock);
224 | s->blkused = 0;
225 | }
226 | memcpy(s->block, q, len);
227 | s->blkused = len;
228 | }
229 | }
230 |
231 | void SHA512_Final(SHA512_State *s, unsigned char *digest) {
232 | int i;
233 | int pad;
234 | unsigned char c[BLKSIZE];
235 | uint32 len[4];
236 |
237 | if (s->blkused >= BLKSIZE - 16)
238 | pad = (BLKSIZE - 16) + BLKSIZE - s->blkused;
239 | else
240 | pad = (BLKSIZE - 16) - s->blkused;
241 |
242 | for (i = 4; i--;) {
243 | uint32 lenhi = s->len[i];
244 | uint32 lenlo = i > 0 ? s->len[i - 1] : 0;
245 | len[i] = (lenhi << 3) | (lenlo >> (32 - 3));
246 | }
247 |
248 | memset(c, 0, pad);
249 | c[0] = 0x80;
250 | SHA512_Bytes(s, &c, pad);
251 |
252 | for (i = 0; i < 4; i++) {
253 | c[i * 4 + 0] = (len[3 - i] >> 24) & 0xFF;
254 | c[i * 4 + 1] = (len[3 - i] >> 16) & 0xFF;
255 | c[i * 4 + 2] = (len[3 - i] >> 8) & 0xFF;
256 | c[i * 4 + 3] = (len[3 - i] >> 0) & 0xFF;
257 | }
258 |
259 | SHA512_Bytes(s, &c, 16);
260 |
261 | for (i = 0; i < 8; i++) {
262 | uint32 h, l;
263 | EXTRACT(h, l, s->h[i]);
264 | digest[i * 8 + 0] = (h >> 24) & 0xFF;
265 | digest[i * 8 + 1] = (h >> 16) & 0xFF;
266 | digest[i * 8 + 2] = (h >> 8) & 0xFF;
267 | digest[i * 8 + 3] = (h >> 0) & 0xFF;
268 | digest[i * 8 + 4] = (l >> 24) & 0xFF;
269 | digest[i * 8 + 5] = (l >> 16) & 0xFF;
270 | digest[i * 8 + 6] = (l >> 8) & 0xFF;
271 | digest[i * 8 + 7] = (l >> 0) & 0xFF;
272 | }
273 | }
274 |
275 | void SHA512_Simple(const void *p, int len, unsigned char *output) {
276 | SHA512_State s;
277 |
278 | SHA512_Init(&s);
279 | SHA512_Bytes(&s, p, len);
280 | SHA512_Final(&s, output);
281 | smemclr(&s, sizeof(s));
282 | }
283 |
284 | #ifdef TEST
285 |
286 | #include
287 | #include
288 | #include
289 |
290 | int main(void) {
291 | unsigned char digest[64];
292 | int i, j, errors;
293 |
294 | struct {
295 | const char *teststring;
296 | unsigned char digest512[64];
297 | } tests[] = {
298 | { "abc", {
299 | 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
300 | 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
301 | 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
302 | 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
303 | 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
304 | 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
305 | 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
306 | 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
307 | } },
308 | { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
309 | "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", {
310 | 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
311 | 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
312 | 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
313 | 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
314 | 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
315 | 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
316 | 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
317 | 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
318 | } },
319 | { NULL, {
320 | 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
321 | 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
322 | 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
323 | 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
324 | 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
325 | 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
326 | 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
327 | 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b,
328 | } },
329 | };
330 |
331 | errors = 0;
332 |
333 | for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
334 | if (tests[i].teststring) {
335 | SHA512_Simple(tests[i].teststring,
336 | strlen(tests[i].teststring), digest);
337 | }
338 | else {
339 | SHA512_State s;
340 | int n;
341 | SHA512_Init(&s);
342 | for (n = 0; n < 1000000 / 40; n++)
343 | SHA512_Bytes(&s, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
344 | 40);
345 | SHA512_Final(&s, digest);
346 | }
347 | for (j = 0; j < 64; j++) {
348 | if (digest[j] != tests[i].digest512[j]) {
349 | fprintf(stderr,
350 | "\"%s\" digest512 byte %d should be 0x%02x, is 0x%02x\n",
351 | tests[i].teststring, j, tests[i].digest512[j],
352 | digest[j]);
353 | errors++;
354 | }
355 | }
356 |
357 | }
358 |
359 | printf("%d errors\n", errors);
360 |
361 | return 0;
362 | }
363 |
364 | #endif
365 |
--------------------------------------------------------------------------------
/src/KeyConvert/import.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "malloc.h"
9 | #include "ssh.h"
10 |
11 | #include "misc.h"
12 |
13 | /* 112
14 | * Strip trailing CRs and LFs at the end of a line of text.
15 | */
16 | void strip_crlf(char *str)
17 | {
18 | char *p = str + strlen(str);
19 |
20 | while (p > str && (p[-1] == '\r' || p[-1] == '\n'))
21 | *--p = '\0';
22 | }
23 |
24 | /* 123-------------------------------------------------------------------
25 | * Helper routines. (The base64 ones are defined in sshpubk.c.)
26 | */
27 |
28 | #define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \
29 | ((c) >= 'a' && (c) <= 'z') || \
30 | ((c) >= '0' && (c) <= '9') || \
31 | (c) == '+' || (c) == '/' || (c) == '=' \
32 | )
33 |
34 | //151
35 | static int ber_read_id_len(void *source, int sourcelen,
36 | int *id, int *length, int *flags)
37 | {
38 | unsigned char *p = (unsigned char *)source;
39 |
40 | if (sourcelen == 0)
41 | return -1;
42 |
43 | *flags = (*p & 0xE0);
44 | if ((*p & 0x1F) == 0x1F) {
45 | *id = 0;
46 | while (*p & 0x80) {
47 | p++, sourcelen--;
48 | if (sourcelen == 0)
49 | return -1;
50 | *id = (*id << 7) | (*p & 0x7F);
51 | }
52 | p++, sourcelen--;
53 | }
54 | else {
55 | *id = *p & 0x1F;
56 | p++, sourcelen--;
57 | }
58 |
59 | if (sourcelen == 0)
60 | return -1;
61 |
62 | if (*p & 0x80) {
63 | unsigned len;
64 | int n = *p & 0x7F;
65 | p++, sourcelen--;
66 | if (sourcelen < n)
67 | return -1;
68 | len = 0;
69 | while (n--)
70 | len = (len << 8) | (*p++);
71 | sourcelen -= n;
72 | *length = toint(len);
73 | }
74 | else {
75 | *length = *p;
76 | p++, sourcelen--;
77 | }
78 |
79 | return p - (unsigned char *)source;
80 | }
81 |
82 | /* 308----------------------------------------------------------------------
83 | * Code to read and write OpenSSH private keys.
84 | */
85 |
86 | enum { OSSH_DSA, OSSH_RSA };
87 | enum { OSSH_ENC_3DES, OSSH_ENC_AES };
88 | struct openssh_key {
89 | int type;
90 | int encrypted, encryption;
91 | char iv[32];
92 | unsigned char *keyblob;
93 | int keyblob_len, keyblob_size;
94 | };
95 |
96 | static struct openssh_key *load_openssh_key(const Filename *filename,
97 | const char **errmsg_p)
98 | {
99 | struct openssh_key *ret;
100 | FILE *fp = NULL;
101 | char *line = NULL;
102 | char *errmsg, *p;
103 | int headers_done;
104 | char base64_bit[4];
105 | int base64_chars = 0;
106 |
107 | ret = snew(struct openssh_key);
108 | ret->keyblob = NULL;
109 | ret->keyblob_len = ret->keyblob_size = 0;
110 | ret->encrypted = 0;
111 | memset(ret->iv, 0, sizeof(ret->iv));
112 |
113 | fp = f_open(filename, "r", FALSE);
114 | if (!fp) {
115 | errmsg = "unable to open key file";
116 | goto error;
117 | }
118 |
119 | if (!(line = fgetline(fp))) {
120 | errmsg = "unexpected end of file";
121 | goto error;
122 | }
123 | strip_crlf(line);
124 | if (!strstartswith(line, "-----BEGIN ") ||
125 | !strendswith(line, "PRIVATE KEY-----")) {
126 | errmsg = "file does not begin with OpenSSH key header";
127 | goto error;
128 | }
129 | if (!strcmp(line, "-----BEGIN RSA PRIVATE KEY-----"))
130 | ret->type = OSSH_RSA;
131 | else if (!strcmp(line, "-----BEGIN DSA PRIVATE KEY-----"))
132 | ret->type = OSSH_DSA;
133 | else {
134 | errmsg = "unrecognised key type";
135 | goto error;
136 | }
137 | smemclr(line, strlen(line));
138 | sfree(line);
139 | line = NULL;
140 |
141 | headers_done = 0;
142 | while (1) {
143 | if (!(line = fgetline(fp))) {
144 | errmsg = "unexpected end of file";
145 | goto error;
146 | }
147 | strip_crlf(line);
148 | if (strstartswith(line, "-----END ") &&
149 | strendswith(line, "PRIVATE KEY-----")) {
150 | sfree(line);
151 | line = NULL;
152 | break; /* done */
153 | }
154 | if ((p = strchr(line, ':')) != NULL) {
155 | if (headers_done) {
156 | errmsg = "header found in body of key data";
157 | goto error;
158 | }
159 | *p++ = '\0';
160 | while (*p && isspace((unsigned char)*p)) p++;
161 | if (!strcmp(line, "Proc-Type")) {
162 | if (p[0] != '4' || p[1] != ',') {
163 | errmsg = "Proc-Type is not 4 (only 4 is supported)";
164 | goto error;
165 | }
166 | p += 2;
167 | if (!strcmp(p, "ENCRYPTED"))
168 | ret->encrypted = 1;
169 | }
170 | else if (!strcmp(line, "DEK-Info")) {
171 | int i, j, ivlen;
172 |
173 | if (!strncmp(p, "DES-EDE3-CBC,", 13)) {
174 | ret->encryption = OSSH_ENC_3DES;
175 | ivlen = 8;
176 | }
177 | else if (!strncmp(p, "AES-128-CBC,", 12)) {
178 | ret->encryption = OSSH_ENC_AES;
179 | ivlen = 16;
180 | }
181 | else {
182 | errmsg = "unsupported cipher";
183 | goto error;
184 | }
185 | p = strchr(p, ',') + 1;/* always non-NULL, by above checks */
186 | for (i = 0; i < ivlen; i++) {
187 | if (1 != sscanf(p, "%2x", &j)) {
188 | errmsg = "expected more iv data in DEK-Info";
189 | goto error;
190 | }
191 | ret->iv[i] = j;
192 | p += 2;
193 | }
194 | if (*p) {
195 | errmsg = "more iv data than expected in DEK-Info";
196 | goto error;
197 | }
198 | }
199 | }
200 | else {
201 | headers_done = 1;
202 |
203 | p = line;
204 | while (isbase64(*p)) {
205 | base64_bit[base64_chars++] = *p;
206 | if (base64_chars == 4) {
207 | unsigned char out[3];
208 | int len;
209 |
210 | base64_chars = 0;
211 |
212 | len = base64_decode_atom(base64_bit, out);
213 |
214 | if (len <= 0) {
215 | errmsg = "invalid base64 encoding";
216 | goto error;
217 | }
218 |
219 | if (ret->keyblob_len + len > ret->keyblob_size) {
220 | ret->keyblob_size = ret->keyblob_len + len + 256;
221 | ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
222 | unsigned char);
223 | }
224 |
225 | memcpy(ret->keyblob + ret->keyblob_len, out, len);
226 | ret->keyblob_len += len;
227 |
228 | smemclr(out, sizeof(out));
229 | }
230 |
231 | p++;
232 | }
233 | }
234 | smemclr(line, strlen(line));
235 | sfree(line);
236 | line = NULL;
237 | }
238 |
239 | fclose(fp);
240 | fp = NULL;
241 |
242 | if (ret->keyblob_len == 0 || !ret->keyblob) {
243 | errmsg = "key body not present";
244 | goto error;
245 | }
246 |
247 | if (ret->encrypted && ret->keyblob_len % 8 != 0) {
248 | errmsg = "encrypted key blob is not a multiple of cipher block size";
249 | goto error;
250 | }
251 |
252 | smemclr(base64_bit, sizeof(base64_bit));
253 | if (errmsg_p) *errmsg_p = NULL;
254 | return ret;
255 |
256 | error:
257 | if (line) {
258 | smemclr(line, strlen(line));
259 | sfree(line);
260 | line = NULL;
261 | }
262 | smemclr(base64_bit, sizeof(base64_bit));
263 | if (ret) {
264 | if (ret->keyblob) {
265 | smemclr(ret->keyblob, ret->keyblob_size);
266 | sfree(ret->keyblob);
267 | }
268 | smemclr(ret, sizeof(*ret));
269 | sfree(ret);
270 | }
271 | if (errmsg_p) *errmsg_p = errmsg;
272 | if (fp) fclose(fp);
273 | return NULL;
274 | }
275 |
276 |
277 | //513
278 | struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
279 | const char **errmsg_p)
280 | {
281 | struct openssh_key *key = load_openssh_key(filename, errmsg_p);
282 | struct ssh2_userkey *retkey;
283 | unsigned char *p;
284 | int ret, id, len, flags;
285 | int i, num_integers;
286 | struct ssh2_userkey *retval = NULL;
287 | char *errmsg;
288 | unsigned char *blob;
289 | int blobsize = 0, blobptr, privptr;
290 | char *modptr = NULL;
291 | int modlen = 0;
292 |
293 | blob = NULL;
294 |
295 | if (!key)
296 | return NULL;
297 |
298 | if (key->encrypted) {
299 | /*
300 | * Derive encryption key from passphrase and iv/salt:
301 | *
302 | * - let block A equal MD5(passphrase || iv)
303 | * - let block B equal MD5(A || passphrase || iv)
304 | * - block C would be MD5(B || passphrase || iv) and so on
305 | * - encryption key is the first N bytes of A || B
306 | *
307 | * (Note that only 8 bytes of the iv are used for key
308 | * derivation, even when the key is encrypted with AES and
309 | * hence there are 16 bytes available.)
310 | */
311 | struct MD5Context md5c;
312 | unsigned char keybuf[32];
313 |
314 | MD5Init(&md5c);
315 | MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
316 | MD5Update(&md5c, (unsigned char *)key->iv, 8);
317 | MD5Final(keybuf, &md5c);
318 |
319 | MD5Init(&md5c);
320 | MD5Update(&md5c, keybuf, 16);
321 | MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
322 | MD5Update(&md5c, (unsigned char *)key->iv, 8);
323 | MD5Final(keybuf + 16, &md5c);
324 |
325 | /*
326 | * Now decrypt the key blob.
327 | */
328 | if (key->encryption == OSSH_ENC_3DES)
329 | des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv,
330 | key->keyblob, key->keyblob_len);
331 | else {
332 | void *ctx;
333 | assert(key->encryption == OSSH_ENC_AES);
334 | ctx = aes_make_context();
335 | aes128_key(ctx, keybuf);
336 | aes_iv(ctx, (unsigned char *)key->iv);
337 | aes_ssh2_decrypt_blk(ctx, key->keyblob, key->keyblob_len);
338 | aes_free_context(ctx);
339 | }
340 |
341 | smemclr(&md5c, sizeof(md5c));
342 | smemclr(keybuf, sizeof(keybuf));
343 | }
344 |
345 | /*
346 | * Now we have a decrypted key blob, which contains an ASN.1
347 | * encoded private key. We must now untangle the ASN.1.
348 | *
349 | * We expect the whole key blob to be formatted as a SEQUENCE
350 | * (0x30 followed by a length code indicating that the rest of
351 | * the blob is part of the sequence). Within that SEQUENCE we
352 | * expect to see a bunch of INTEGERs. What those integers mean
353 | * depends on the key type:
354 | *
355 | * - For RSA, we expect the integers to be 0, n, e, d, p, q,
356 | * dmp1, dmq1, iqmp in that order. (The last three are d mod
357 | * (p-1), d mod (q-1), inverse of q mod p respectively.)
358 | *
359 | * - For DSA, we expect them to be 0, p, q, g, y, x in that
360 | * order.
361 | */
362 |
363 | p = key->keyblob;
364 |
365 | /* Expect the SEQUENCE header. Take its absence as a failure to
366 | * decrypt, if the key was encrypted. */
367 | ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
368 | p += ret;
369 | if (ret < 0 || id != 16 || len < 0 ||
370 | key->keyblob + key->keyblob_len - p < len) {
371 | errmsg = "ASN.1 decoding failure";
372 | retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
373 | goto error;
374 | }
375 |
376 | /* Expect a load of INTEGERs. */
377 | if (key->type == OSSH_RSA)
378 | num_integers = 9;
379 | else if (key->type == OSSH_DSA)
380 | num_integers = 6;
381 | else
382 | num_integers = 0; /* placate compiler warnings */
383 |
384 | /*
385 | * Space to create key blob in.
386 | */
387 | blobsize = 256 + key->keyblob_len;
388 | blob = snewn(blobsize, unsigned char);
389 | PUT_32BIT(blob, 7);
390 | if (key->type == OSSH_DSA)
391 | memcpy(blob + 4, "ssh-dss", 7);
392 | else if (key->type == OSSH_RSA)
393 | memcpy(blob + 4, "ssh-rsa", 7);
394 | blobptr = 4 + 7;
395 | privptr = -1;
396 |
397 | for (i = 0; i < num_integers; i++) {
398 | ret = ber_read_id_len(p, key->keyblob + key->keyblob_len - p,
399 | &id, &len, &flags);
400 | p += ret;
401 | if (ret < 0 || id != 2 || len < 0 ||
402 | key->keyblob + key->keyblob_len - p < len) {
403 | errmsg = "ASN.1 decoding failure";
404 | retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
405 | goto error;
406 | }
407 |
408 | if (i == 0) {
409 | /*
410 | * The first integer should be zero always (I think
411 | * this is some sort of version indication).
412 | */
413 | if (len != 1 || p[0] != 0) {
414 | errmsg = "version number mismatch";
415 | goto error;
416 | }
417 | }
418 | else if (key->type == OSSH_RSA) {
419 | /*
420 | * Integers 1 and 2 go into the public blob but in the
421 | * opposite order; integers 3, 4, 5 and 8 go into the
422 | * private blob. The other two (6 and 7) are ignored.
423 | */
424 | if (i == 1) {
425 | /* Save the details for after we deal with number 2. */
426 | modptr = (char *)p;
427 | modlen = len;
428 | }
429 | else if (i != 6 && i != 7) {
430 | PUT_32BIT(blob + blobptr, len);
431 | memcpy(blob + blobptr + 4, p, len);
432 | blobptr += 4 + len;
433 | if (i == 2) {
434 | PUT_32BIT(blob + blobptr, modlen);
435 | memcpy(blob + blobptr + 4, modptr, modlen);
436 | blobptr += 4 + modlen;
437 | privptr = blobptr;
438 | }
439 | }
440 | }
441 | else if (key->type == OSSH_DSA) {
442 | /*
443 | * Integers 1-4 go into the public blob; integer 5 goes
444 | * into the private blob.
445 | */
446 | PUT_32BIT(blob + blobptr, len);
447 | memcpy(blob + blobptr + 4, p, len);
448 | blobptr += 4 + len;
449 | if (i == 4)
450 | privptr = blobptr;
451 | }
452 |
453 | /* Skip past the number. */
454 | p += len;
455 | }
456 |
457 | /*
458 | * Now put together the actual key. Simplest way to do this is
459 | * to assemble our own key blobs and feed them to the createkey
460 | * functions; this is a bit faffy but it does mean we get all
461 | * the sanity checks for free.
462 | */
463 | assert(privptr > 0); /* should have bombed by now if not */
464 | retkey = snew(struct ssh2_userkey);
465 | retkey->alg = (key->type == OSSH_RSA ? &ssh_rsa : &ssh_dss);
466 | retkey->data = retkey->alg->createkey(blob, privptr,
467 | blob + privptr, blobptr - privptr);
468 | if (!retkey->data) {
469 | sfree(retkey);
470 | errmsg = "unable to create key data structure";
471 | goto error;
472 | }
473 |
474 | retkey->comment = dupstr("imported-openssh-key");
475 | errmsg = NULL; /* no error */
476 | retval = retkey;
477 |
478 | error:
479 | if (blob) {
480 | smemclr(blob, blobsize);
481 | sfree(blob);
482 | }
483 | smemclr(key->keyblob, key->keyblob_size);
484 | sfree(key->keyblob);
485 | smemclr(key, sizeof(*key));
486 | sfree(key);
487 | if (errmsg_p) *errmsg_p = errmsg;
488 | return retval;
489 | }
490 |
491 | /*
492 | * Import an SSH-2 key.
493 | */
494 | struct ssh2_userkey *import_ssh2(const Filename *filename, int type,
495 | char *passphrase, const char **errmsg_p)
496 | {
497 | if (type == SSH_KEYTYPE_OPENSSH)
498 | return openssh_read(filename, passphrase, errmsg_p);
499 | //if (type == SSH_KEYTYPE_SSHCOM)
500 | // return sshcom_read(filename, passphrase, errmsg_p);
501 | return NULL;
502 | }
--------------------------------------------------------------------------------
/src/KeyConvert/sshdss.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | // SPDX-License-Identifier: MIT-0
3 |
4 | /*
5 | * Digital Signature Standard implementation for PuTTY.
6 | */
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include "ssh.h"
13 | #include "misc.h"
14 |
15 | static void sha_mpint(SHA_State * s, Bignum b)
16 | {
17 | unsigned char lenbuf[4];
18 | int len;
19 | len = (bignum_bitcount(b) + 8) / 8;
20 | PUT_32BIT(lenbuf, len);
21 | SHA_Bytes(s, lenbuf, 4);
22 | while (len-- > 0) {
23 | lenbuf[0] = bignum_byte(b, len);
24 | SHA_Bytes(s, lenbuf, 1);
25 | }
26 | smemclr(lenbuf, sizeof(lenbuf));
27 | }
28 |
29 | static void sha512_mpint(SHA512_State * s, Bignum b)
30 | {
31 | unsigned char lenbuf[4];
32 | int len;
33 | len = (bignum_bitcount(b) + 8) / 8;
34 | PUT_32BIT(lenbuf, len);
35 | SHA512_Bytes(s, lenbuf, 4);
36 | while (len-- > 0) {
37 | lenbuf[0] = bignum_byte(b, len);
38 | SHA512_Bytes(s, lenbuf, 1);
39 | }
40 | smemclr(lenbuf, sizeof(lenbuf));
41 | }
42 |
43 | static void getstring(char **data, int *datalen, char **p, int *length)
44 | {
45 | *p = NULL;
46 | if (*datalen < 4)
47 | return;
48 | *length = toint(GET_32BIT(*data));
49 | if (*length < 0)
50 | return;
51 | *datalen -= 4;
52 | *data += 4;
53 | if (*datalen < *length)
54 | return;
55 | *p = *data;
56 | *data += *length;
57 | *datalen -= *length;
58 | }
59 | static Bignum getmp(char **data, int *datalen)
60 | {
61 | char *p;
62 | int length;
63 | Bignum b;
64 |
65 | getstring(data, datalen, &p, &length);
66 | if (!p)
67 | return NULL;
68 | if (p[0] & 0x80)
69 | return NULL; /* negative mp */
70 | b = bignum_from_bytes((unsigned char *)p, length);
71 | return b;
72 | }
73 |
74 | static Bignum get160(char **data, int *datalen)
75 | {
76 | Bignum b;
77 |
78 | if (*datalen < 20)
79 | return NULL;
80 |
81 | b = bignum_from_bytes((unsigned char *)*data, 20);
82 | *data += 20;
83 | *datalen -= 20;
84 |
85 | return b;
86 | }
87 |
88 | static void dss_freekey(void *key); /* forward reference */
89 |
90 | static void *dss_newkey(char *data, int len)
91 | {
92 | char *p;
93 | int slen;
94 | struct dss_key *dss;
95 |
96 | dss = snew(struct dss_key);
97 | getstring(&data, &len, &p, &slen);
98 |
99 | #ifdef DEBUG_DSS
100 | {
101 | int i;
102 | printf("key:");
103 | for (i = 0; i < len; i++)
104 | printf(" %02x", (unsigned char)(data[i]));
105 | printf("\n");
106 | }
107 | #endif
108 |
109 | if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
110 | sfree(dss);
111 | return NULL;
112 | }
113 | dss->p = getmp(&data, &len);
114 | dss->q = getmp(&data, &len);
115 | dss->g = getmp(&data, &len);
116 | dss->y = getmp(&data, &len);
117 | dss->x = NULL;
118 |
119 | if (!dss->p || !dss->q || !dss->g || !dss->y ||
120 | !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) {
121 | /* Invalid key. */
122 | dss_freekey(dss);
123 | return NULL;
124 | }
125 |
126 | return dss;
127 | }
128 |
129 | static void dss_freekey(void *key)
130 | {
131 | struct dss_key *dss = (struct dss_key *) key;
132 | if (dss->p)
133 | freebn(dss->p);
134 | if (dss->q)
135 | freebn(dss->q);
136 | if (dss->g)
137 | freebn(dss->g);
138 | if (dss->y)
139 | freebn(dss->y);
140 | if (dss->x)
141 | freebn(dss->x);
142 | sfree(dss);
143 | }
144 |
145 | static char *dss_fmtkey(void *key)
146 | {
147 | struct dss_key *dss = (struct dss_key *) key;
148 | char *p;
149 | int len, i, pos, nibbles;
150 | static const char hex[] = "0123456789abcdef";
151 | if (!dss->p)
152 | return NULL;
153 | len = 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
154 | len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
155 | len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
156 | len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
157 | len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
158 | p = snewn(len, char);
159 | if (!p)
160 | return NULL;
161 |
162 | pos = 0;
163 | pos += sprintf(p + pos, "0x");
164 | nibbles = (3 + bignum_bitcount(dss->p)) / 4;
165 | if (nibbles < 1)
166 | nibbles = 1;
167 | for (i = nibbles; i--;)
168 | p[pos++] =
169 | hex[(bignum_byte(dss->p, i / 2) >> (4 * (i % 2))) & 0xF];
170 | pos += sprintf(p + pos, ",0x");
171 | nibbles = (3 + bignum_bitcount(dss->q)) / 4;
172 | if (nibbles < 1)
173 | nibbles = 1;
174 | for (i = nibbles; i--;)
175 | p[pos++] =
176 | hex[(bignum_byte(dss->q, i / 2) >> (4 * (i % 2))) & 0xF];
177 | pos += sprintf(p + pos, ",0x");
178 | nibbles = (3 + bignum_bitcount(dss->g)) / 4;
179 | if (nibbles < 1)
180 | nibbles = 1;
181 | for (i = nibbles; i--;)
182 | p[pos++] =
183 | hex[(bignum_byte(dss->g, i / 2) >> (4 * (i % 2))) & 0xF];
184 | pos += sprintf(p + pos, ",0x");
185 | nibbles = (3 + bignum_bitcount(dss->y)) / 4;
186 | if (nibbles < 1)
187 | nibbles = 1;
188 | for (i = nibbles; i--;)
189 | p[pos++] =
190 | hex[(bignum_byte(dss->y, i / 2) >> (4 * (i % 2))) & 0xF];
191 | p[pos] = '\0';
192 | return p;
193 | }
194 |
195 | static char *dss_fingerprint(void *key)
196 | {
197 | struct dss_key *dss = (struct dss_key *) key;
198 | struct MD5Context md5c;
199 | unsigned char digest[16], lenbuf[4];
200 | char buffer[16 * 3 + 40];
201 | char *ret;
202 | int numlen, i;
203 |
204 | MD5Init(&md5c);
205 | MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-dss", 11);
206 |
207 | #define ADD_BIGNUM(bignum) \
208 | numlen = (bignum_bitcount(bignum)+8)/8; \
209 | PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
210 | for (i = numlen; i-- ;) { \
211 | unsigned char c = bignum_byte(bignum, i); \
212 | MD5Update(&md5c, &c, 1); \
213 | }
214 | ADD_BIGNUM(dss->p);
215 | ADD_BIGNUM(dss->q);
216 | ADD_BIGNUM(dss->g);
217 | ADD_BIGNUM(dss->y);
218 | #undef ADD_BIGNUM
219 |
220 | MD5Final(digest, &md5c);
221 |
222 | sprintf(buffer, "ssh-dss %d ", bignum_bitcount(dss->p));
223 | for (i = 0; i < 16; i++)
224 | sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
225 | digest[i]);
226 | ret = snewn(strlen(buffer) + 1, char);
227 | if (ret)
228 | strcpy(ret, buffer);
229 | return ret;
230 | }
231 |
232 | static int dss_verifysig(void *key, char *sig, int siglen,
233 | char *data, int datalen)
234 | {
235 | struct dss_key *dss = (struct dss_key *) key;
236 | char *p;
237 | int slen;
238 | char hash[20];
239 | Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v;
240 | int ret;
241 |
242 | if (!dss->p)
243 | return 0;
244 |
245 | #ifdef DEBUG_DSS
246 | {
247 | int i;
248 | printf("sig:");
249 | for (i = 0; i < siglen; i++)
250 | printf(" %02x", (unsigned char)(sig[i]));
251 | printf("\n");
252 | }
253 | #endif
254 | /*
255 | * Commercial SSH (2.0.13) and OpenSSH disagree over the format
256 | * of a DSA signature. OpenSSH is in line with RFC 4253:
257 | * it uses a string "ssh-dss", followed by a 40-byte string
258 | * containing two 160-bit integers end-to-end. Commercial SSH
259 | * can't be bothered with the header bit, and considers a DSA
260 | * signature blob to be _just_ the 40-byte string containing
261 | * the two 160-bit integers. We tell them apart by measuring
262 | * the length: length 40 means the commercial-SSH bug, anything
263 | * else is assumed to be RFC-compliant.
264 | */
265 | if (siglen != 40) { /* bug not present; read admin fields */
266 | getstring(&sig, &siglen, &p, &slen);
267 | if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
268 | return 0;
269 | }
270 | sig += 4, siglen -= 4; /* skip yet another length field */
271 | }
272 | r = get160(&sig, &siglen);
273 | s = get160(&sig, &siglen);
274 | if (!r || !s) {
275 | if (r)
276 | freebn(r);
277 | if (s)
278 | freebn(s);
279 | return 0;
280 | }
281 |
282 | if (!bignum_cmp(s, Zero)) {
283 | freebn(r);
284 | freebn(s);
285 | return 0;
286 | }
287 |
288 | /*
289 | * Step 1. w <- s^-1 mod q.
290 | */
291 | w = modinv(s, dss->q);
292 | if (!w) {
293 | freebn(r);
294 | freebn(s);
295 | return 0;
296 | }
297 |
298 | /*
299 | * Step 2. u1 <- SHA(message) * w mod q.
300 | */
301 | SHA_Simple(data, datalen, (unsigned char *)hash);
302 | p = hash;
303 | slen = 20;
304 | sha = get160(&p, &slen);
305 | u1 = modmul(sha, w, dss->q);
306 |
307 | /*
308 | * Step 3. u2 <- r * w mod q.
309 | */
310 | u2 = modmul(r, w, dss->q);
311 |
312 | /*
313 | * Step 4. v <- (g^u1 * y^u2 mod p) mod q.
314 | */
315 | gu1p = modpow(dss->g, u1, dss->p);
316 | yu2p = modpow(dss->y, u2, dss->p);
317 | gu1yu2p = modmul(gu1p, yu2p, dss->p);
318 | v = modmul(gu1yu2p, One, dss->q);
319 |
320 | /*
321 | * Step 5. v should now be equal to r.
322 | */
323 |
324 | ret = !bignum_cmp(v, r);
325 |
326 | freebn(w);
327 | freebn(sha);
328 | freebn(u1);
329 | freebn(u2);
330 | freebn(gu1p);
331 | freebn(yu2p);
332 | freebn(gu1yu2p);
333 | freebn(v);
334 | freebn(r);
335 | freebn(s);
336 |
337 | return ret;
338 | }
339 |
340 | static unsigned char *dss_public_blob(void *key, int *len)
341 | {
342 | struct dss_key *dss = (struct dss_key *) key;
343 | int plen, qlen, glen, ylen, bloblen;
344 | int i;
345 | unsigned char *blob, *p;
346 |
347 | plen = (bignum_bitcount(dss->p) + 8) / 8;
348 | qlen = (bignum_bitcount(dss->q) + 8) / 8;
349 | glen = (bignum_bitcount(dss->g) + 8) / 8;
350 | ylen = (bignum_bitcount(dss->y) + 8) / 8;
351 |
352 | /*
353 | * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total
354 | * 27 + sum of lengths. (five length fields, 20+7=27).
355 | */
356 | bloblen = 27 + plen + qlen + glen + ylen;
357 | blob = snewn(bloblen, unsigned char);
358 | p = blob;
359 | PUT_32BIT(p, 7);
360 | p += 4;
361 | memcpy(p, "ssh-dss", 7);
362 | p += 7;
363 | PUT_32BIT(p, plen);
364 | p += 4;
365 | for (i = plen; i--;)
366 | *p++ = bignum_byte(dss->p, i);
367 | PUT_32BIT(p, qlen);
368 | p += 4;
369 | for (i = qlen; i--;)
370 | *p++ = bignum_byte(dss->q, i);
371 | PUT_32BIT(p, glen);
372 | p += 4;
373 | for (i = glen; i--;)
374 | *p++ = bignum_byte(dss->g, i);
375 | PUT_32BIT(p, ylen);
376 | p += 4;
377 | for (i = ylen; i--;)
378 | *p++ = bignum_byte(dss->y, i);
379 | assert(p == blob + bloblen);
380 | *len = bloblen;
381 | return blob;
382 | }
383 |
384 | static unsigned char *dss_private_blob(void *key, int *len)
385 | {
386 | struct dss_key *dss = (struct dss_key *) key;
387 | int xlen, bloblen;
388 | int i;
389 | unsigned char *blob, *p;
390 |
391 | xlen = (bignum_bitcount(dss->x) + 8) / 8;
392 |
393 | /*
394 | * mpint x, string[20] the SHA of p||q||g. Total 4 + xlen.
395 | */
396 | bloblen = 4 + xlen;
397 | blob = snewn(bloblen, unsigned char);
398 | p = blob;
399 | PUT_32BIT(p, xlen);
400 | p += 4;
401 | for (i = xlen; i--;)
402 | *p++ = bignum_byte(dss->x, i);
403 | assert(p == blob + bloblen);
404 | *len = bloblen;
405 | return blob;
406 | }
407 |
408 | static void *dss_createkey(unsigned char *pub_blob, int pub_len,
409 | unsigned char *priv_blob, int priv_len)
410 | {
411 | struct dss_key *dss;
412 | char *pb = (char *)priv_blob;
413 | char *hash;
414 | int hashlen;
415 | SHA_State s;
416 | unsigned char digest[20];
417 | Bignum ytest;
418 |
419 | dss = (dss_key *)dss_newkey((char *)pub_blob, pub_len);
420 | if (!dss)
421 | return NULL;
422 | dss->x = getmp(&pb, &priv_len);
423 | if (!dss->x) {
424 | dss_freekey(dss);
425 | return NULL;
426 | }
427 |
428 | /*
429 | * Check the obsolete hash in the old DSS key format.
430 | */
431 | hashlen = -1;
432 | getstring(&pb, &priv_len, &hash, &hashlen);
433 | if (hashlen == 20) {
434 | SHA_Init(&s);
435 | sha_mpint(&s, dss->p);
436 | sha_mpint(&s, dss->q);
437 | sha_mpint(&s, dss->g);
438 | SHA_Final(&s, digest);
439 | if (0 != memcmp(hash, digest, 20)) {
440 | dss_freekey(dss);
441 | return NULL;
442 | }
443 | }
444 |
445 | /*
446 | * Now ensure g^x mod p really is y.
447 | */
448 | ytest = modpow(dss->g, dss->x, dss->p);
449 | if (0 != bignum_cmp(ytest, dss->y)) {
450 | dss_freekey(dss);
451 | freebn(ytest);
452 | return NULL;
453 | }
454 | freebn(ytest);
455 |
456 | return dss;
457 | }
458 |
459 | static void *dss_openssh_createkey(unsigned char **blob, int *len)
460 | {
461 | char **b = (char **)blob;
462 | struct dss_key *dss;
463 |
464 | dss = snew(struct dss_key);
465 |
466 | dss->p = getmp(b, len);
467 | dss->q = getmp(b, len);
468 | dss->g = getmp(b, len);
469 | dss->y = getmp(b, len);
470 | dss->x = getmp(b, len);
471 |
472 | if (!dss->p || !dss->q || !dss->g || !dss->y || !dss->x ||
473 | !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) {
474 | /* Invalid key. */
475 | dss_freekey(dss);
476 | return NULL;
477 | }
478 |
479 | return dss;
480 | }
481 |
482 | static int dss_openssh_fmtkey(void *key, unsigned char *blob, int len)
483 | {
484 | struct dss_key *dss = (struct dss_key *) key;
485 | int bloblen, i;
486 |
487 | bloblen =
488 | ssh2_bignum_length(dss->p) +
489 | ssh2_bignum_length(dss->q) +
490 | ssh2_bignum_length(dss->g) +
491 | ssh2_bignum_length(dss->y) +
492 | ssh2_bignum_length(dss->x);
493 |
494 | if (bloblen > len)
495 | return bloblen;
496 |
497 | bloblen = 0;
498 | #define ENC(x) \
499 | PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \
500 | for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i);
501 | ENC(dss->p);
502 | ENC(dss->q);
503 | ENC(dss->g);
504 | ENC(dss->y);
505 | ENC(dss->x);
506 |
507 | return bloblen;
508 | }
509 |
510 | static int dss_pubkey_bits(void *blob, int len)
511 | {
512 | struct dss_key *dss;
513 | int ret;
514 |
515 | dss = (dss_key *)dss_newkey((char *)blob, len);
516 | if (!dss)
517 | return -1;
518 | ret = bignum_bitcount(dss->p);
519 | dss_freekey(dss);
520 |
521 | return ret;
522 | }
523 |
524 | static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
525 | {
526 | /*
527 | * The basic DSS signing algorithm is:
528 | *
529 | * - invent a random k between 1 and q-1 (exclusive).
530 | * - Compute r = (g^k mod p) mod q.
531 | * - Compute s = k^-1 * (hash + x*r) mod q.
532 | *
533 | * This has the dangerous properties that:
534 | *
535 | * - if an attacker in possession of the public key _and_ the
536 | * signature (for example, the host you just authenticated
537 | * to) can guess your k, he can reverse the computation of s
538 | * and work out x = r^-1 * (s*k - hash) mod q. That is, he
539 | * can deduce the private half of your key, and masquerade
540 | * as you for as long as the key is still valid.
541 | *
542 | * - since r is a function purely of k and the public key, if
543 | * the attacker only has a _range of possibilities_ for k
544 | * it's easy for him to work through them all and check each
545 | * one against r; he'll never be unsure of whether he's got
546 | * the right one.
547 | *
548 | * - if you ever sign two different hashes with the same k, it
549 | * will be immediately obvious because the two signatures
550 | * will have the same r, and moreover an attacker in
551 | * possession of both signatures (and the public key of
552 | * course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q,
553 | * and from there deduce x as before.
554 | *
555 | * - the Bleichenbacher attack on DSA makes use of methods of
556 | * generating k which are significantly non-uniformly
557 | * distributed; in particular, generating a 160-bit random
558 | * number and reducing it mod q is right out.
559 | *
560 | * For this reason we must be pretty careful about how we
561 | * generate our k. Since this code runs on Windows, with no
562 | * particularly good system entropy sources, we can't trust our
563 | * RNG itself to produce properly unpredictable data. Hence, we
564 | * use a totally different scheme instead.
565 | *
566 | * What we do is to take a SHA-512 (_big_) hash of the private
567 | * key x, and then feed this into another SHA-512 hash that
568 | * also includes the message hash being signed. That is:
569 | *
570 | * proto_k = SHA512 ( SHA512(x) || SHA160(message) )
571 | *
572 | * This number is 512 bits long, so reducing it mod q won't be
573 | * noticeably non-uniform. So
574 | *
575 | * k = proto_k mod q
576 | *
577 | * This has the interesting property that it's _deterministic_:
578 | * signing the same hash twice with the same key yields the
579 | * same signature.
580 | *
581 | * Despite this determinism, it's still not predictable to an
582 | * attacker, because in order to repeat the SHA-512
583 | * construction that created it, the attacker would have to
584 | * know the private key value x - and by assumption he doesn't,
585 | * because if he knew that he wouldn't be attacking k!
586 | *
587 | * (This trick doesn't, _per se_, protect against reuse of k.
588 | * Reuse of k is left to chance; all it does is prevent
589 | * _excessively high_ chances of reuse of k due to entropy
590 | * problems.)
591 | *
592 | * Thanks to Colin Plumb for the general idea of using x to
593 | * ensure k is hard to guess, and to the Cambridge University
594 | * Computer Security Group for helping to argue out all the
595 | * fine details.
596 | */
597 | struct dss_key *dss = (struct dss_key *) key;
598 | SHA512_State ss;
599 | unsigned char digest[20], digest512[64];
600 | Bignum proto_k, k, gkp, hash, kinv, hxr, r, s;
601 | unsigned char *bytes;
602 | int nbytes, i;
603 |
604 | SHA_Simple(data, datalen, digest);
605 |
606 | /*
607 | * Hash some identifying text plus x.
608 | */
609 | SHA512_Init(&ss);
610 | SHA512_Bytes(&ss, "DSA deterministic k generator", 30);
611 | sha512_mpint(&ss, dss->x);
612 | SHA512_Final(&ss, digest512);
613 |
614 | /*
615 | * Now hash that digest plus the message hash.
616 | */
617 | SHA512_Init(&ss);
618 | SHA512_Bytes(&ss, digest512, sizeof(digest512));
619 | SHA512_Bytes(&ss, digest, sizeof(digest));
620 |
621 | while (1) {
622 | SHA512_State ss2 = ss; /* structure copy */
623 | SHA512_Final(&ss2, digest512);
624 |
625 | smemclr(&ss2, sizeof(ss2));
626 |
627 | /*
628 | * Now convert the result into a bignum, and reduce it mod q.
629 | */
630 | proto_k = bignum_from_bytes(digest512, 64);
631 | k = bigmod(proto_k, dss->q);
632 | freebn(proto_k);
633 | kinv = modinv(k, dss->q); /* k^-1 mod q */
634 | if (!kinv) { /* very unlikely */
635 | freebn(k);
636 | /* Perturb the hash to think of a different k. */
637 | SHA512_Bytes(&ss, "x", 1);
638 | /* Go round and try again. */
639 | continue;
640 | }
641 |
642 | break;
643 | }
644 |
645 | smemclr(&ss, sizeof(ss));
646 |
647 | smemclr(digest512, sizeof(digest512));
648 |
649 | /*
650 | * Now we have k, so just go ahead and compute the signature.
651 | */
652 | gkp = modpow(dss->g, k, dss->p); /* g^k mod p */
653 | r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */
654 | freebn(gkp);
655 |
656 | hash = bignum_from_bytes(digest, 20);
657 | hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */
658 | s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */
659 | freebn(hxr);
660 | freebn(kinv);
661 | freebn(k);
662 | freebn(hash);
663 |
664 | /*
665 | * Signature blob is
666 | *
667 | * string "ssh-dss"
668 | * string two 20-byte numbers r and s, end to end
669 | *
670 | * i.e. 4+7 + 4+40 bytes.
671 | */
672 | nbytes = 4 + 7 + 4 + 40;
673 | bytes = snewn(nbytes, unsigned char);
674 | PUT_32BIT(bytes, 7);
675 | memcpy(bytes + 4, "ssh-dss", 7);
676 | PUT_32BIT(bytes + 4 + 7, 40);
677 | for (i = 0; i < 20; i++) {
678 | bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
679 | bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
680 | }
681 | freebn(r);
682 | freebn(s);
683 |
684 | *siglen = nbytes;
685 | return bytes;
686 | }
687 |
688 | const struct ssh_signkey ssh_dss = {
689 | dss_newkey,
690 | dss_freekey,
691 | dss_fmtkey,
692 | dss_public_blob,
693 | dss_private_blob,
694 | dss_createkey,
695 | dss_openssh_createkey,
696 | dss_openssh_fmtkey,
697 | dss_pubkey_bits,
698 | dss_fingerprint,
699 | dss_verifysig,
700 | dss_sign,
701 | "ssh-dss",
702 | "dss"
703 | };
704 |
--------------------------------------------------------------------------------