forked from shadowsocks/shadowsocks-windows
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request shadowsocks#1671 from wongsyrone/master
Add OpenSSL 1.1.0g support due to hardware acceleration
- Loading branch information
Showing
15 changed files
with
693 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
OpenSSL library guide for VS2017 | ||
|
||
# Read NOTES.WIN and NOTES.PERL | ||
|
||
# use Visual Studio native tools command prompt | ||
# use activeperl, install NASM assembler | ||
ppm install dmake | ||
|
||
# Win32 x86 | ||
set PATH=D:\NASM-32;%PATH% | ||
perl Configure VC-WIN32 --release --prefix=C:\Users\home\Downloads\openssl-1.1.0g\x86-build --openssldir=C:\Users\home\Downloads\openssl-1.1.0g\x86-install | ||
nmake | ||
nmake test | ||
# to rebuild | ||
nmake distclean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
192 changes: 192 additions & 0 deletions
192
shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Shadowsocks.Encryption.Exception; | ||
|
||
namespace Shadowsocks.Encryption.AEAD | ||
{ | ||
public class AEADOpenSSLEncryptor | ||
: AEADEncryptor, IDisposable | ||
{ | ||
const int CIPHER_AES = 1; | ||
const int CIPHER_CHACHA20IETFPOLY1305 = 2; | ||
|
||
private byte[] _opensslEncSubkey; | ||
private byte[] _opensslDecSubkey; | ||
|
||
private IntPtr _encryptCtx = IntPtr.Zero; | ||
private IntPtr _decryptCtx = IntPtr.Zero; | ||
|
||
private IntPtr _cipherInfoPtr = IntPtr.Zero; | ||
|
||
public AEADOpenSSLEncryptor(string method, string password) | ||
: base(method, password) | ||
{ | ||
_opensslEncSubkey = new byte[keyLen]; | ||
_opensslDecSubkey = new byte[keyLen]; | ||
} | ||
|
||
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> | ||
{ | ||
{"aes-128-gcm", new EncryptorInfo("aes-128-gcm", 16, 16, 12, 16, CIPHER_AES)}, | ||
{"aes-192-gcm", new EncryptorInfo("aes-192-gcm", 24, 24, 12, 16, CIPHER_AES)}, | ||
{"aes-256-gcm", new EncryptorInfo("aes-256-gcm", 32, 32, 12, 16, CIPHER_AES)}, | ||
{"chacha20-ietf-poly1305", new EncryptorInfo("chacha20-poly1305", 32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)} | ||
}; | ||
|
||
public static List<string> SupportedCiphers() | ||
{ | ||
return new List<string>(_ciphers.Keys); | ||
} | ||
|
||
protected override Dictionary<string, EncryptorInfo> getCiphers() | ||
{ | ||
return _ciphers; | ||
} | ||
|
||
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) | ||
{ | ||
base.InitCipher(salt, isEncrypt, isUdp); | ||
_cipherInfoPtr = OpenSSL.GetCipherInfo(_innerLibName); | ||
if (_cipherInfoPtr == IntPtr.Zero) throw new System.Exception("openssl: cipher not found"); | ||
IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new(); | ||
if (ctx == IntPtr.Zero) throw new System.Exception("openssl: fail to create ctx"); | ||
|
||
if (isEncrypt) | ||
{ | ||
_encryptCtx = ctx; | ||
} | ||
else | ||
{ | ||
_decryptCtx = ctx; | ||
} | ||
|
||
DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey, | ||
isEncrypt ? _opensslEncSubkey : _opensslDecSubkey); | ||
|
||
var ret = OpenSSL.EVP_CipherInit_ex(ctx, _cipherInfoPtr, IntPtr.Zero, null, null, | ||
isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); | ||
if (ret != 1) throw new System.Exception("openssl: fail to init ctx"); | ||
|
||
ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen); | ||
if (ret != 1) throw new System.Exception("openssl: fail to set key length"); | ||
|
||
ret = OpenSSL.EVP_CIPHER_CTX_ctrl(ctx, OpenSSL.EVP_CTRL_AEAD_SET_IVLEN, | ||
nonceLen, IntPtr.Zero); | ||
if (ret != 1) throw new System.Exception("openssl: fail to set AEAD nonce length"); | ||
|
||
ret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero, | ||
isEncrypt ? _opensslEncSubkey : _opensslDecSubkey, | ||
null, | ||
isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); | ||
if (ret != 1) throw new System.Exception("openssl: cannot set key"); | ||
OpenSSL.EVP_CIPHER_CTX_set_padding(ctx, 0); | ||
} | ||
|
||
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) | ||
{ | ||
OpenSSL.SetCtxNonce(_encryptCtx, _encNonce, true); | ||
// buf: all plaintext | ||
// outbuf: ciphertext + tag | ||
int ret; | ||
int tmpLen = 0; | ||
clen = 0; | ||
var tagBuf = new byte[tagLen]; | ||
|
||
ret = OpenSSL.EVP_CipherUpdate(_encryptCtx, ciphertext, out tmpLen, | ||
plaintext, (int) plen); | ||
if (ret != 1) throw new CryptoErrorException("openssl: fail to encrypt AEAD"); | ||
clen += (uint) tmpLen; | ||
// For AEAD cipher, it should not output anything | ||
ret = OpenSSL.EVP_CipherFinal_ex(_encryptCtx, ciphertext, ref tmpLen); | ||
if (ret != 1) throw new CryptoErrorException("openssl: fail to finalize AEAD"); | ||
if (tmpLen > 0) | ||
{ | ||
throw new System.Exception("openssl: fail to finish AEAD"); | ||
} | ||
|
||
OpenSSL.AEADGetTag(_encryptCtx, tagBuf, tagLen); | ||
Array.Copy(tagBuf, 0, ciphertext, clen, tagLen); | ||
clen += (uint) tagLen; | ||
} | ||
|
||
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) | ||
{ | ||
OpenSSL.SetCtxNonce(_decryptCtx, _decNonce, false); | ||
// buf: ciphertext + tag | ||
// outbuf: plaintext | ||
int ret; | ||
int tmpLen = 0; | ||
plen = 0; | ||
|
||
// split tag | ||
byte[] tagbuf = new byte[tagLen]; | ||
Array.Copy(ciphertext, (int) (clen - tagLen), tagbuf, 0, tagLen); | ||
OpenSSL.AEADSetTag(_decryptCtx, tagbuf, tagLen); | ||
|
||
ret = OpenSSL.EVP_CipherUpdate(_decryptCtx, | ||
plaintext, out tmpLen, ciphertext, (int) (clen - tagLen)); | ||
if (ret != 1) throw new CryptoErrorException("openssl: fail to decrypt AEAD"); | ||
plen += (uint) tmpLen; | ||
|
||
// For AEAD cipher, it should not output anything | ||
ret = OpenSSL.EVP_CipherFinal_ex(_decryptCtx, plaintext, ref tmpLen); | ||
if (ret <= 0) | ||
{ | ||
// If this is not successful authenticated | ||
throw new CryptoErrorException(String.Format("ret is {0}", ret)); | ||
} | ||
|
||
if (tmpLen > 0) | ||
{ | ||
throw new System.Exception("openssl: fail to finish AEAD"); | ||
} | ||
} | ||
|
||
#region IDisposable | ||
|
||
private bool _disposed; | ||
|
||
// instance based lock | ||
private readonly object _lock = new object(); | ||
|
||
public override void Dispose() | ||
{ | ||
Dispose(true); | ||
GC.SuppressFinalize(this); | ||
} | ||
|
||
~AEADOpenSSLEncryptor() | ||
{ | ||
Dispose(false); | ||
} | ||
|
||
protected virtual void Dispose(bool disposing) | ||
{ | ||
lock (_lock) | ||
{ | ||
if (_disposed) return; | ||
_disposed = true; | ||
} | ||
|
||
if (disposing) | ||
{ | ||
// free managed objects | ||
} | ||
|
||
// free unmanaged objects | ||
if (_encryptCtx != IntPtr.Zero) | ||
{ | ||
OpenSSL.EVP_CIPHER_CTX_free(_encryptCtx); | ||
_encryptCtx = IntPtr.Zero; | ||
} | ||
|
||
if (_decryptCtx != IntPtr.Zero) | ||
{ | ||
OpenSSL.EVP_CIPHER_CTX_free(_decryptCtx); | ||
_decryptCtx = IntPtr.Zero; | ||
} | ||
} | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.