Files
mxaccess/analysis/decompiled/aaServicesContractIAuthenticateASB/ArchestrAServices.ASBContract/SysAuthParameters.cs
T
Joseph Doherty fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Initial project state: .NET reference, design, Rust port (M0+M1), evidence
Layout:
- src/                    .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
                          MxAsbClient, probes, tests, harnesses. Executable spec.
- design/                 Architectural plan for the Rust port (M0–M6), error
                          model, protocol invariants, risks (R1–R16), adversarial
                          review log (review.md).
- rust/                   Rust workspace. M0 skeleton + M1 codec parity.
                          mxaccess-codec: 215 unit tests + 2 cross-implementation
                          parity tests (byte-identical against .NET reference).
                          Other crates are M0 stubs awaiting M2+.
- captures/               Frida + netsh + pcap evidence per CLAUDE.md
                          ("captures are evidence, not throwaway logs").
- analysis/               Decompiled C# (frida/proxy/decompiled-*),
                          Ghidra exports for native DLLs (`exports/` only —
                          working state at `projects/` and AVEVA's input
                          binaries at `input/` are gitignored).
- docs/                   Reverse-engineering reference docs.
- tools/                  Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
                          Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/      Rust CI: fmt + build + test + clippy on Windows.
- LICENSE                 MIT (Joseph Doherty, 2026).

Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly

Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 06:21:00 -04:00

250 lines
8.5 KiB
C#

#define TRACE
using System;
using System.Diagnostics;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using ArchestrAServices.Common;
namespace ArchestrAServices.ASBContract;
public class SysAuthParameters
{
public string ASBSolutionName;
public bool ASBSolutionValid;
public int DH_KeySize;
public int DH_SecretSize;
public BigInteger DH_p;
public BigInteger DH_g;
private string m_SysAuthPassphrase;
private byte[] m_SysAuthCertificate;
public uint ConnectionLifetime;
public string SaltValue;
public string hashAlgorithm;
public int PasswordIterations;
public string InitialVector;
public int KeySize;
private static string RegKeyRelativePath = string.Empty;
public static int DH_KeySize_Dft = 1024;
public static int DH_SecretSize_Dft = 160;
public static string DH_passphrase_Dft = Environment.MachineName;
public static uint ConnectionLifetime_Dft = 60000u;
public static string SaltValue_Dft = "s@1tValue";
public static string hashAlgorithm_Dft = CngAlgorithm.MD5.ToString();
public static int PasswordIterations_Dft = 1;
public static string InitialVector_Dft = "ba172e9941be138b";
public static int KeySize_Dft = 256;
private static string s_DECIMAL768 = "1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919";
private static byte[] s_OAKLEY768 = new byte[96]
{
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
244, 76, 66, 233, 166, 58, 54, 32, 255, 255,
255, 255, 255, 255, 255, 255
};
private static string s_DECIMAL1024 = "179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194";
private static byte[] s_OAKLEY1024 = new byte[128]
{
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
244, 76, 66, 233, 166, 55, 237, 107, 11, 255,
92, 182, 244, 6, 183, 237, 238, 56, 107, 251,
90, 137, 159, 165, 174, 159, 36, 17, 124, 75,
31, 230, 73, 40, 102, 81, 236, 230, 83, 129,
255, 255, 255, 255, 255, 255, 255, 255
};
private static string s_DECIMAL1536 = "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919";
private static byte[] s_OAKLEY1536 = new byte[192]
{
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
244, 76, 66, 233, 166, 55, 237, 107, 11, 255,
92, 182, 244, 6, 183, 237, 238, 56, 107, 251,
90, 137, 159, 165, 174, 159, 36, 17, 124, 75,
31, 230, 73, 40, 102, 81, 236, 228, 91, 61,
194, 0, 124, 184, 161, 99, 191, 5, 152, 218,
72, 54, 28, 85, 211, 154, 105, 22, 63, 168,
253, 36, 207, 95, 131, 101, 93, 35, 220, 163,
173, 150, 28, 98, 243, 86, 32, 133, 82, 187,
158, 213, 41, 7, 112, 150, 150, 109, 103, 12,
53, 78, 74, 188, 152, 4, 241, 116, 108, 8,
202, 35, 115, 39, 255, 255, 255, 255, 255, 255,
255, 255
};
public string DH_passphrase
{
get
{
return m_SysAuthPassphrase;
}
set
{
ResetToDefaults();
m_SysAuthPassphrase = value;
ASBSolutionValid = true;
}
}
public byte[] DH_certificate => m_SysAuthCertificate;
public SysAuthParameters(string asbSolutionName = null)
{
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "SysAuthParameters constructor with asbSolutionName = {0}", string.IsNullOrEmpty(asbSolutionName) ? "<null>" : asbSolutionName);
ASBSolutionName = asbSolutionName;
ASBSolutionValid = false;
ResetToDefaults();
LoadASBSolution();
}
public void ResetToDefaults()
{
ASBSolutionValid = false;
DH_KeySize = DH_KeySize_Dft;
DH_SecretSize = DH_SecretSize_Dft;
m_SysAuthPassphrase = DH_passphrase_Dft;
m_SysAuthCertificate = null;
ConnectionLifetime = ConnectionLifetime_Dft;
SaltValue = SaltValue_Dft;
hashAlgorithm = hashAlgorithm_Dft;
PasswordIterations = PasswordIterations_Dft;
InitialVector = InitialVector_Dft;
KeySize = KeySize_Dft;
GenerateKey();
}
private void LoadASBSolution()
{
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution entry");
try
{
if (string.IsNullOrEmpty(ASBSolutionName))
{
ASBSolutionName = SvcUtilities.ReadKeyValue(string.Empty, "DefaultASBSolution");
if (string.IsNullOrEmpty(ASBSolutionName))
{
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, "LoadASBSolution: Unable to get default ASB solution name");
ASBSolutionValid = false;
}
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution created with empty solution name, resetting to default '{0}'", string.IsNullOrEmpty(ASBSolutionName) ? "<null>" : ASBSolutionName);
}
ASBSolutionValid = false;
if (!string.IsNullOrEmpty(ASBSolutionName))
{
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution: Using solution {0}", ASBSolutionName);
if (string.IsNullOrEmpty(RegistryHandler.GetSolutionPassphrase(ASBSolutionName, out var passphrase)) && !string.IsNullOrEmpty(passphrase))
{
DH_passphrase = passphrase;
}
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "Certificate")) != null)
{
m_SysAuthCertificate = Encoding.UTF8.GetBytes(passphrase);
}
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "saltValue")) != null)
{
SaltValue = passphrase;
}
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "HashAlgorthim")) != null)
{
hashAlgorithm = passphrase;
}
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution: Using hashAlgorithm {0}", hashAlgorithm);
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "passowordIterations")) != null)
{
PasswordIterations = int.Parse(passphrase);
}
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "initailizationVector")) != null)
{
InitialVector = passphrase;
}
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "keySize")) != null)
{
int.TryParse(passphrase, out KeySize);
}
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "Prime")) != null)
{
BigInteger.TryParse(passphrase, out DH_p);
}
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "Generator")) != null)
{
BigInteger.TryParse(passphrase, out DH_g);
}
ASBSolutionValid = true;
}
}
catch (Exception ex)
{
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, "LoadASBSolution: Exception caught: {0}", ex.Message);
ASBSolutionValid = false;
}
}
private void GenerateKey()
{
if (DH_KeySize == 768)
{
BigInteger.TryParse(s_DECIMAL768, out DH_p);
}
else if (DH_KeySize == 1024)
{
BigInteger.TryParse(s_DECIMAL1024, out DH_p);
}
else
{
if (DH_KeySize != 1536)
{
throw new ArgumentException("Invalid bit size.");
}
BigInteger.TryParse(s_DECIMAL1536, out DH_p);
}
DH_g = new BigInteger(22);
}
}