Skip to content

Commit 4de68fe

Browse files
committed
native plugin
fix import flags Show native state in ToString for NM HUD Old unity support
1 parent 482bd26 commit 4de68fe

39 files changed

+621
-3
lines changed

Assets/Mirror/Transports/Encryption/EncryptedConnection.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Security.Cryptography;
3+
using Mirror.Transports.Encryption.Native;
34
using System.Text;
45
using Org.BouncyCastle.Crypto;
56
using Org.BouncyCastle.Crypto.Agreement;
@@ -131,6 +132,7 @@ enum State
131132
* The client does this, since the fin is not acked explicitly, but by receiving data to decrypt
132133
*/
133134
private readonly bool _sendsFirst;
135+
private byte[] _keyRaw;
134136

135137
public EncryptedConnection(EncryptionCredentials credentials,
136138
bool isClient,
@@ -363,6 +365,18 @@ private ArraySegment<byte> Encrypt(ArraySegment<byte> plaintext)
363365
#endif
364366
// Resize the static buffer to fit
365367
EnsureSize(ref _tmpCryptBuffer, outSize);
368+
369+
if (AesGCMEncryptionNative.IsSupported)
370+
{
371+
ArraySegment<byte> nativeRes = AesGCMEncryptionNative.Encrypt(_keyRaw, _nonce, plaintext, new ArraySegment<byte>(_tmpCryptBuffer));
372+
if (nativeRes.Count == 0)
373+
{
374+
_error(TransportError.Unexpected, $"Native Encryption failed. Please check STDERR (or editor log) for the error.");
375+
return new ArraySegment<byte>();
376+
}
377+
return nativeRes;
378+
}
379+
366380
int resultLen;
367381
try
368382
{
@@ -411,6 +425,16 @@ private ArraySegment<byte> Decrypt(ArraySegment<byte> ciphertext)
411425
#endif
412426
// Resize the static buffer to fit
413427
EnsureSize(ref _tmpCryptBuffer, outSize);
428+
if (AesGCMEncryptionNative.IsSupported)
429+
{
430+
var nativeRes = AesGCMEncryptionNative.Decrypt(_keyRaw, ReceiveNonce, ciphertext, new ArraySegment<byte>(_tmpCryptBuffer));
431+
if (nativeRes.Count == 0)
432+
{
433+
_error(TransportError.Unexpected, $"Native Encryption failed. Please check STDERR (or editor log) for the error.");
434+
return new ArraySegment<byte>();
435+
}
436+
return nativeRes;
437+
}
414438
int resultLen;
415439
try
416440
{
@@ -537,12 +561,12 @@ private void CompleteExchange(ArraySegment<byte> remotePubKeyRaw, byte[] salt)
537561
Hkdf.Init(new HkdfParameters(sharedSecret, salt, HkdfInfo));
538562

539563
// Allocate a buffer for the output key
540-
byte[] keyRaw = new byte[KeyLength];
564+
_keyRaw = new byte[KeyLength];
541565

542566
// Generate the output keying material
543-
Hkdf.GenerateBytes(keyRaw, 0, keyRaw.Length);
567+
Hkdf.GenerateBytes(_keyRaw, 0, _keyRaw.Length);
544568

545-
KeyParameter key = new KeyParameter(keyRaw);
569+
KeyParameter key = new KeyParameter(_keyRaw);
546570

547571
// generate a starting nonce
548572
_nonce = GenerateSecureBytes(NonceSize);

Assets/Mirror/Transports/Encryption/EncryptionTransport.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using Mirror.Transports.Encryption.Native;
34
using UnityEngine;
45
using UnityEngine.Profiling;
56
using UnityEngine.Serialization;
@@ -38,6 +39,11 @@ public enum ValidationMode
3839
public string EncryptionPublicKeyFingerprint => _credentials?.PublicKeyFingerprint;
3940
public byte[] EncryptionPublicKey => _credentials?.PublicKeySerialized;
4041

42+
43+
public override string ToString()
44+
{
45+
return $"EncryptionTransport(native: {AesGCMEncryptionNative.IsSupported})";
46+
}
4147
private void ServerRemoveFromPending(EncryptedConnection con)
4248
{
4349
for (int i = 0; i < _serverPendingConnections.Count; i++)

Assets/Mirror/Transports/Encryption/Native.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Security;
4+
using UnityEngine;
5+
namespace Mirror.Transports.Encryption.Native
6+
{
7+
public class AesGCMEncryptionNative
8+
{
9+
[SuppressUnmanagedCodeSecurity]
10+
[DllImport("rusty_mirror_encryption", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
11+
private static extern byte is_supported();
12+
13+
[SuppressUnmanagedCodeSecurity]
14+
[DllImport("rusty_mirror_encryption", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
15+
private static extern uint aes_gcm_encrypt(
16+
UIntPtr key, uint key_size,
17+
UIntPtr nonce, uint nonce_size,
18+
UIntPtr data, uint data_in_size, uint data_capacity);
19+
20+
[SuppressUnmanagedCodeSecurity]
21+
[DllImport("rusty_mirror_encryption", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
22+
private static extern uint aes_gcm_decrypt(
23+
UIntPtr key, uint key_size,
24+
UIntPtr nonce, uint nonce_size,
25+
UIntPtr data, uint data_size);
26+
27+
private static bool _supported;
28+
static AesGCMEncryptionNative()
29+
{
30+
try
31+
{
32+
_supported = is_supported() == 1;
33+
}
34+
catch (Exception e)
35+
{
36+
// TODO: silent?
37+
Debug.LogWarning($"Native AES GCM is not supported: {e}");
38+
}
39+
}
40+
public static bool IsSupported => _supported;
41+
public static unsafe ArraySegment<byte> Encrypt(byte[] key, byte[] nonce, ArraySegment<byte> plaintext, ArraySegment<byte> dataOut)
42+
{
43+
Array.Copy(plaintext.Array, plaintext.Offset, dataOut.Array, dataOut.Offset ,plaintext.Count);
44+
fixed (byte* keyPtr = key)
45+
{
46+
fixed (byte* noncePtr = nonce)
47+
{
48+
fixed (byte* dataPtr = dataOut.Array)
49+
{
50+
UIntPtr data = ((UIntPtr)dataPtr) + dataOut.Offset;
51+
uint resultLength = aes_gcm_encrypt(
52+
(UIntPtr)keyPtr, (uint)key.Length,
53+
(UIntPtr)noncePtr, (uint)nonce.Length,
54+
data, (uint)plaintext.Count, (uint)dataOut.Count);
55+
return new ArraySegment<byte>(dataOut.Array, dataOut.Offset, (int)resultLength);
56+
}
57+
}
58+
}
59+
}
60+
61+
public static unsafe ArraySegment<byte> Decrypt(byte[] key, byte[] nonce, ArraySegment<byte> ciphertext, ArraySegment<byte> dataOut)
62+
{
63+
Array.Copy(ciphertext.Array, ciphertext.Offset, dataOut.Array, dataOut.Offset, ciphertext.Count);
64+
fixed (byte* keyPtr = key)
65+
{
66+
fixed (byte* noncePtr = nonce)
67+
{
68+
fixed (byte* dataPtr = dataOut.Array)
69+
{
70+
UIntPtr data = ((UIntPtr)dataPtr) + dataOut.Offset;
71+
uint resultLength = aes_gcm_decrypt(
72+
(UIntPtr)keyPtr, (uint)key.Length,
73+
(UIntPtr)noncePtr, (uint)nonce.Length,
74+
data, (uint)ciphertext.Count);
75+
return new ArraySegment<byte>(dataOut.Array, dataOut.Offset, (int)resultLength);
76+
}
77+
}
78+
}
79+
}
80+
}
81+
}

Assets/Mirror/Transports/Encryption/Native/AesGCMEncryptionNative.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Robin Rolf
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Assets/Mirror/Transports/Encryption/Native/LICENSE.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# [RustyMirrorEncryption](https://github.com/imerr/RustyMirrorEncryption)
2+
A tiny native library for hardware accelerated AES-GCM encryption and decryption for the EncryptionTransport in [Mirror](https://github.com/MirrorNetworking/Mirror)
3+
4+
Uses [RustCryptos aes_gcm crate](https://github.com/RustCrypto/AEADs/tree/master/aes-gcm) crate

Assets/Mirror/Transports/Encryption/Native/README.md.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Mirror/Transports/Encryption/Native/aarch64-apple-darwin.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)