Browse Source

pycryptoMod added

Shayan 4 years ago
parent
commit
6ecaad37a3
100 changed files with 13495 additions and 8 deletions
  1. 58 2
      .gitignore
  2. 6 6
      command.py
  3. 49 0
      tls/pycryptoMod/AUTHORS.rst
  4. 746 0
      tls/pycryptoMod/Changelog.rst
  5. 29 0
      tls/pycryptoMod/FuturePlans.rst
  6. 281 0
      tls/pycryptoMod/INSTALL.rst
  7. 274 0
      tls/pycryptoMod/LICENSE.rst
  8. 12 0
      tls/pycryptoMod/MANIFEST.in
  9. 75 0
      tls/pycryptoMod/README.rst
  10. 89 0
      tls/pycryptoMod/appveyor.yml
  11. 99 0
      tls/pycryptoMod/bench_monty.py
  12. 423 0
      tls/pycryptoMod/compiler_opt.py
  13. 250 0
      tls/pycryptoMod/lib/Crypto/Cipher/AES.py
  14. 47 0
      tls/pycryptoMod/lib/Crypto/Cipher/AES.pyi
  15. 175 0
      tls/pycryptoMod/lib/Crypto/Cipher/ARC2.py
  16. 35 0
      tls/pycryptoMod/lib/Crypto/Cipher/ARC2.pyi
  17. 137 0
      tls/pycryptoMod/lib/Crypto/Cipher/ARC4.py
  18. 16 0
      tls/pycryptoMod/lib/Crypto/Cipher/ARC4.pyi
  19. 159 0
      tls/pycryptoMod/lib/Crypto/Cipher/Blowfish.py
  20. 35 0
      tls/pycryptoMod/lib/Crypto/Cipher/Blowfish.pyi
  21. 159 0
      tls/pycryptoMod/lib/Crypto/Cipher/CAST.py
  22. 35 0
      tls/pycryptoMod/lib/Crypto/Cipher/CAST.pyi
  23. 286 0
      tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20.py
  24. 25 0
      tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20.pyi
  25. 336 0
      tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20_Poly1305.py
  26. 28 0
      tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20_Poly1305.pyi
  27. 158 0
      tls/pycryptoMod/lib/Crypto/Cipher/DES.py
  28. 35 0
      tls/pycryptoMod/lib/Crypto/Cipher/DES.pyi
  29. 187 0
      tls/pycryptoMod/lib/Crypto/Cipher/DES3.py
  30. 37 0
      tls/pycryptoMod/lib/Crypto/Cipher/DES3.pyi
  31. 239 0
      tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_OAEP.py
  32. 35 0
      tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_OAEP.pyi
  33. 199 0
      tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_v1_5.py
  34. 17 0
      tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_v1_5.pyi
  35. 167 0
      tls/pycryptoMod/lib/Crypto/Cipher/Salsa20.py
  36. 27 0
      tls/pycryptoMod/lib/Crypto/Cipher/Salsa20.pyi
  37. 131 0
      tls/pycryptoMod/lib/Crypto/Cipher/_EKSBlowfish.py
  38. 15 0
      tls/pycryptoMod/lib/Crypto/Cipher/_EKSBlowfish.pyi
  39. 79 0
      tls/pycryptoMod/lib/Crypto/Cipher/__init__.py
  40. 0 0
      tls/pycryptoMod/lib/Crypto/Cipher/__init__.pyi
  41. 293 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_cbc.py
  42. 25 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_cbc.pyi
  43. 650 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ccm.py
  44. 47 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ccm.pyi
  45. 293 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_cfb.py
  46. 26 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_cfb.pyi
  47. 393 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ctr.py
  48. 27 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ctr.pyi
  49. 408 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_eax.py
  50. 45 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_eax.pyi
  51. 218 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ecb.py
  52. 19 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ecb.pyi
  53. 620 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_gcm.py
  54. 45 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_gcm.pyi
  55. 525 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ocb.py
  56. 36 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ocb.pyi
  57. 282 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ofb.py
  58. 25 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_ofb.pyi
  59. 206 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_openpgp.py
  60. 20 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_openpgp.pyi
  61. 392 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_siv.py
  62. 38 0
      tls/pycryptoMod/lib/Crypto/Cipher/_mode_siv.pyi
  63. 247 0
      tls/pycryptoMod/lib/Crypto/Hash/BLAKE2b.py
  64. 31 0
      tls/pycryptoMod/lib/Crypto/Hash/BLAKE2b.pyi
  65. 247 0
      tls/pycryptoMod/lib/Crypto/Hash/BLAKE2s.py
  66. 26 0
      tls/pycryptoMod/lib/Crypto/Hash/BLAKE2s.pyi
  67. 305 0
      tls/pycryptoMod/lib/Crypto/Hash/CMAC.py
  68. 30 0
      tls/pycryptoMod/lib/Crypto/Hash/CMAC.pyi
  69. 213 0
      tls/pycryptoMod/lib/Crypto/Hash/HMAC.py
  70. 25 0
      tls/pycryptoMod/lib/Crypto/Hash/HMAC.pyi
  71. 166 0
      tls/pycryptoMod/lib/Crypto/Hash/MD2.py
  72. 19 0
      tls/pycryptoMod/lib/Crypto/Hash/MD2.pyi
  73. 185 0
      tls/pycryptoMod/lib/Crypto/Hash/MD4.py
  74. 19 0
      tls/pycryptoMod/lib/Crypto/Hash/MD4.pyi
  75. 184 0
      tls/pycryptoMod/lib/Crypto/Hash/MD5.py
  76. 19 0
      tls/pycryptoMod/lib/Crypto/Hash/MD5.pyi
  77. 217 0
      tls/pycryptoMod/lib/Crypto/Hash/Poly1305.py
  78. 24 0
      tls/pycryptoMod/lib/Crypto/Hash/Poly1305.pyi
  79. 26 0
      tls/pycryptoMod/lib/Crypto/Hash/RIPEMD.py
  80. 3 0
      tls/pycryptoMod/lib/Crypto/Hash/RIPEMD.pyi
  81. 169 0
      tls/pycryptoMod/lib/Crypto/Hash/RIPEMD160.py
  82. 19 0
      tls/pycryptoMod/lib/Crypto/Hash/RIPEMD160.pyi
  83. 24 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA.py
  84. 4 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA.pyi
  85. 185 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA1.py
  86. 19 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA1.pyi
  87. 186 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA224.py
  88. 19 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA224.pyi
  89. 185 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA256.py
  90. 18 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA256.pyi
  91. 186 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA384.py
  92. 19 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA384.pyi
  93. 147 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_224.py
  94. 16 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_224.pyi
  95. 147 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_256.py
  96. 16 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_256.pyi
  97. 147 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_384.py
  98. 16 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_384.pyi
  99. 148 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_512.py
  100. 16 0
      tls/pycryptoMod/lib/Crypto/Hash/SHA3_512.pyi

+ 58 - 2
.gitignore

@@ -1,3 +1,13 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
 build/
 develop-eggs/
 dist/
@@ -13,6 +23,7 @@ share/python-wheels/
 *.egg-info/
 .installed.cfg
 *.egg
+MANIFEST
 
 # PyInstaller
 #  Usually these files are written by a python script from a template
@@ -24,18 +35,63 @@ share/python-wheels/
 pip-log.txt
 pip-delete-this-directory.txt
 
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
 
 # Translations
 *.mo
 *.pot
 
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
 
 # Sphinx documentation
 docs/_build/
 
 # PyBuilder
+.pybuilder/
 target/
 
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+#   For a library or package, you might want to ignore these files since the code is
+#   intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
 
 # PEP 582; used by e.g. github.com/David-OConnor/pyflow
 __pypackages__/
@@ -90,6 +146,6 @@ Programs
 .logs
 Player-Data
 local
-tcp/Crypto/
-tcp/Crypto
 
+
+tls/Crypto

+ 6 - 6
command.py

@@ -34,11 +34,11 @@ def install():
 
     
     print(("\n"))
-    os.system("cd tls/pycryptodome && python setup.py install")
-    a = os.popen('cd ./tls/pycryptodome/build && ls').read()
+    os.system("cd tls/pycryptoMod && python setup.py install")
+    a = os.popen('cd ./tls/pycryptoMod/build && ls').read()
     b = a.split("\n")
     if b[1].startswith("lib"):
-        os.system("mv tls/pycryptodome/build/"+b[1]+"/Crypto tls/")
+        os.system("mv tls/pycryptoMod/build/"+b[1]+"/Crypto tls/")
 
 
 def comp(a):
@@ -50,8 +50,8 @@ def comp(a):
 def compCrypto(a):
 
     os.system("rm -rf tls/Crypto")
-    os.system("cd tls/pycryptodome && python setup.py install")
-    a = os.popen('cd ./tls/pycryptodome/build && ls').read()
+    os.system("cd tls/pycryptoMod && python setup.py install")
+    a = os.popen('cd ./tls/pycryptoMod/build && ls').read()
     b = a.split("\n")
     if b[1].startswith("lib"):
-        os.system("mv tls/pycryptodome/build/"+b[1]+"/Crypto tls/")
+        os.system("mv tls/pycryptoMod/build/"+b[1]+"/Crypto tls/")

+ 49 - 0
tls/pycryptoMod/AUTHORS.rst

@@ -0,0 +1,49 @@
+Simon Arneaud
+Nevins Bartolomeo
+Thorsten E. Behrens
+Tim Berners-Lee
+Frédéric Bertolus
+Ian Bicking
+Joris Bontje
+Antoon Bosselaers
+Andrea Bottoni
+Jean-Paul Calderone
+Sergey Chernov
+Geremy Condra
+Jan Dittberner
+Andrew Eland
+Philippe Frycia
+Peter Gutmann
+Hirendra Hindocha
+Nikhil Jhingan
+Sebastian Kayser
+Ryan Kelly
+Andrew M. Kuchling
+Piers Lauder
+Legrandin
+M.-A. Lemburg
+Wim Lewis
+Darsey C. Litzenberger
+Richard Mitchell
+Mark Moraes
+Lim Chee Siang
+Bryan Olson
+Wallace Owen
+Colin Plumb
+Robey Pointer
+Lorenz Quack
+Sebastian Ramacher
+Jeethu Rao
+James P. Rutledge
+Matt Schreiner
+Peter Simmons
+Janne Snabb
+Tom St. Denis
+Anders Sundman
+Paul Swartz
+Fabrizio Tarizzo
+Kevin M. Turner
+Barry A. Warsaw
+Eric Young
+Hannes van Niekerk
+Stefan Seering

+ 746 - 0
tls/pycryptoMod/Changelog.rst

@@ -0,0 +1,746 @@
+Changelog
+=========
+
+3.9.8 (23 June 2020)
+++++++++++++++++++++
+
+Resolved issues
+---------------
+* GH#426: The Shamir's secret sharing implementation is not actually compatible with ``ssss``.
+  Added an optional parameter to enable interoperability.
+* GH#427: Skip altogether loading of ``gmp.dll`` on Windows.
+* GH#420: Fix incorrect CFB decryption when the input and the output are the same buffer.
+
+New features
+------------
+* Speed up Shamir's secret sharing routines. Thanks to ncarve.
+
+3.9.7 (20 February 2020)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+* GH#381: Make notarization possible again on OS X when using wheels.
+  Thanks to Colin Atkinson.
+
+3.9.6 (2 February 2020)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+* Fix building of wheels for OS X by explicitly setting `sysroot` location.
+
+3.9.5 (1 February 2020)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+* RSA OAEP decryption was not verifying that all ``PS`` bytes are zero.
+* GH#372: fixed memory leak for operations that use memoryviews when `cffi` is not installed.
+* Fixed wrong ASN.1 OID for HMAC-SHA512 in PBE2.
+
+New features
+------------
+* Updated Wycheproof test vectors to version 0.8r12.
+
+3.9.4 (18 November 2019)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+* GH#341: Prevent ``key_to_english`` from creating invalid data when fed with
+  keys of length not multiple of 8. Thanks to vstoykovbg.
+* GH#347: Fix blocking RSA signing/decryption when key has very small factor.
+  Thanks to Martijn Pieters.
+
+3.9.3 (12 November 2019)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+* GH#308: Align stack of functions using SSE2 intrinsics to avoid crashes,
+  when compiled with gcc on 32-bit x86 platforms.
+
+3.9.2 (10 November 2019)
+++++++++++++++++++++++++
+
+New features
+------------
+* Add Python 3.8 wheels for Mac.
+
+Resolved issues
+---------------
+* GH#308: Avoid allocating arrays of ``__m128i`` on the stack, to cope with buggy compilers.
+* GH#322: Remove blanket ``-O3`` optimization for gcc and clang, to cope with buggy compilers.
+* GH#337: Fix typing stubs for signatures.
+* GH#338: Deal with gcc installations that don't have ``x86intrin.h``.
+
+3.9.1 (1 November 2019)
+++++++++++++++++++++++++
+
+New features
+------------
+* Add Python 3.8 wheels for Linux and Windows.
+
+Resolved issues
+---------------
+
+* GH#328: minor speed-up when importing RSA.
+
+3.9.0 (27 August 2019)
++++++++++++++++++++++++
+
+New features
+------------
+
+* Add support for loading PEM files encrypted with AES256-CBC.
+* Add support for XChaCha20 and XChaCha20-Poly1305 ciphers.
+* Add support for bcrypt key derivation function (``Crypto.Protocol.KDF.bcrypt``).
+* Add support for left multiplication of an EC point by a scalar.
+* Add support for importing ECC and RSA keys in the new OpenSSH format.
+
+Resolved issues
+---------------
+
+* GH#312: it was not possible to invert an EC point anymore.
+* GH#316: fix printing of DSA keys.
+* GH#317: ``DSA.generate()`` was not always using the ``randfunc`` input.
+* GH#285: the MD2 hash had block size of 64 bytes instead of 16; as result the HMAC construction gave incorrect results.
+
+3.8.2 (30 May 2019)
++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#291: fix strict aliasing problem, emerged with GCC 9.1.
+
+3.8.1 (4 April 2019)
++++++++++++++++++++++++
+
+New features
+------------
+
+* Add support for loading PEM files encrypted with AES192-CBC and AES256-GCM.
+* When importing ECC keys in PEM format, ignore the redundant EC PARAMS section that was included by certain openssl commands.
+
+Resolved issues
+---------------
+
+* ``repr()`` did not work for ``ECC.EccKey`` objects.
+* Fix installation in development mode (``setup install develop`` or ``pip install -e .``).
+* Minimal length for Blowfish cipher is 32 bits, not 40 bits.
+* Various updates to docs.
+
+3.8.0 (23 March 2019)
++++++++++++++++++++++++
+
+New features
+------------
+
+* Speed-up ECC performance. ECDSA is 33 times faster on the NIST P-256 curve.
+* Added support for NIST P-384 and P-521 curves.
+* ``EccKey`` has new methods ``size_in_bits()`` and ``size_in_bytes()``.
+* Support HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, and HMAC-SHA512 in PBE2/PBKDF2.
+
+Resolved issues
+---------------
+
+* DER objects were not rejected if their length field had a leading zero.
+* Allow legacy RC2 ciphers to have 40-bit keys.
+* ASN.1 Object IDs did not allow the value 0 in the path.
+
+Breaks in compatibility
+-----------------------
+
+* ``point_at_infinity()`` becomes an instance method for ``Crypto.PublicKey.ECC.EccKey``, from a static one.
+
+3.7.3 (19 January 2019)
++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#258: False positive on PSS signatures when externally provided salt is too long.
+* Include type stub files for ``Crypto.IO`` and ``Crypto.Util``.
+
+3.7.2 (26 November 2018)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#242: Fixed compilation problem on ARM platforms.
+
+3.7.1 (25 November 2018)
+++++++++++++++++++++++++
+
+New features
+------------
+
+* Added type stubs to enable static type checking with mypy. Thanks to Michael Nix.
+* New ``update_after_digest`` flag for CMAC.
+
+Resolved issues
+---------------
+
+* GH#232: Fixed problem with gcc 4.x when compiling ``ghash_clmul.c``.
+* GH#238: Incorrect digest value produced by CMAC after cloning the object.
+* Method ``update()`` of an EAX cipher object was returning the underlying CMAC object,
+  instead of the EAX object itself.
+* Method ``update()`` of a CMAC object was not throwing an exception after the digest
+  was computed (with ``digest()`` or ``verify()``).
+
+3.7.0 (27 October 2018)
++++++++++++++++++++++++
+
+New features
+------------
+
+* Added support for Poly1305 MAC (with AES and ChaCha20 ciphers for key derivation).
+* Added support for ChaCha20-Poly1305 AEAD cipher.
+* New parameter ``output`` for ``Crypto.Util.strxor.strxor``, ``Crypto.Util.strxor.strxor_c``,
+  ``encrypt`` and ``decrypt`` methods in symmetric ciphers (``Crypto.Cipher`` package).
+  ``output`` is a pre-allocated buffer (a ``bytearray`` or a writeable ``memoryview``)
+  where the result must be stored.
+  This requires less memory for very large payloads; it is also more efficient when
+  encrypting (or decrypting) several small payloads.
+
+Resolved issues
+---------------
+
+* GH#266: AES-GCM hangs when processing more than 4GB at a time on x86 with PCLMULQDQ instruction.
+
+Breaks in compatibility
+-----------------------
+
+* Drop support for Python 3.3.
+* Remove ``Crypto.Util.py3compat.unhexlify`` and ``Crypto.Util.py3compat.hexlify``.
+* With the old Python 2.6, use only ``ctypes`` (and not ``cffi``) to interface to native code.
+
+3.6.6 (17 August 2018)
+++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#198: Fix vulnerability on AESNI ECB with payloads smaller than 16 bytes (CVE-2018-15560).
+
+3.6.5 (12 August 2018)
+++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#187: Fixed incorrect AES encryption/decryption with AES acceleration on x86
+  due to gcc's optimization and strict aliasing rules.
+* GH#188: More prime number candidates than necessary where discarded as composite
+  due to the limited way D values were searched in the Lucas test.
+* Fixed ResouceWarnings and DeprecationWarnings.
+* Workaround for Python 3.7.0 bug on Windows (https://bugs.python.org/issue34108).
+
+3.6.4 (10 July 2018)
++++++++++++++++++++++
+
+New features
+------------
+
+* Build Python 3.7 wheels on Linux, Windows and Mac.
+
+Resolved issues
+---------------
+
+* GH#178: Rename ``_cpuid`` module to make upgrades more robust.
+* More meaningful exceptions in case of mismatch in IV length (CBC/OFB/CFB modes).
+* Fix compilation issues on Solaris 10/11.
+
+3.6.3 (21 June 2018)
++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#175: Fixed incorrect results for CTR encryption/decryption with more than 8 blocks.
+
+3.6.2 (19 June 2018)
++++++++++++++++++++++
+
+New features
+------------
+* ChaCha20 accepts 96 bit nonces (in addition to 64 bit nonces)
+  as defined in RFC7539.
+* Accelerate AES-GCM on x86 using PCLMULQDQ instruction.
+* Accelerate AES-ECB and AES-CTR on x86 by pipelining AESNI instructions.
+* As result of the two improvements above, on x86 (Broadwell):
+
+  - AES-ECB and AES-CTR are 3x faster
+  - AES-GCM is 9x faster
+
+Resolved issues
+---------------
+
+* On Windows, MPIR library was stilled pulled in if renamed to ``gmp.dll``.
+
+Breaks in compatibility
+-----------------------
+
+* In ``Crypto.Util.number``, functions ``floor_div`` and ``exact_div``
+  have been removed. Also, ``ceil_div`` is limited to non-negative terms only.
+
+3.6.1 (15 April 2018)
++++++++++++++++++++++
+
+New features
+------------
+* Added Google Wycheproof tests (https://github.com/google/wycheproof)
+  for RSA, DSA, ECDSA, GCM, SIV, EAX, CMAC.
+* New parameter ``mac_len`` (length of MAC tag) for CMAC.
+
+Resolved issues
+---------------
+
+* In certain circumstances (at counter wrapping, which happens on average after
+  32 GB) AES GCM produced wrong ciphertexts.
+* Method ``encrypt()`` of AES SIV cipher could be still called,
+  whereas only ``encrypt_and_digest()`` is allowed.
+
+3.6.0 (8 April 2018)
+++++++++++++++++++++
+
+New features
+------------
+* Introduced ``export_key`` and deprecated ``exportKey`` for DSA and RSA key
+  objects.
+* Ciphers and hash functions accept ``memoryview`` objects in input.
+* Added support for SHA-512/224 and SHA-512/256.
+
+Resolved issues
+---------------
+
+* Reintroduced ``Crypto.__version__`` variable as in PyCrypto.
+* Fixed compilation problem with MinGW.
+
+3.5.1 (8 March 2018)
+++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#142. Fix mismatch with declaration and definition of addmul128.
+
+3.5.0 (7 March 2018)
+++++++++++++++++++++
+
+New features
+------------
+* Import and export of ECC curves in compressed form.
+* The initial counter for a cipher in CTR mode can be a byte string
+  (in addition to an integer).
+* Faster PBKDF2 for HMAC-based PRFs (at least 20x for short passwords,
+  more for longer passwords). Thanks to Christian Heimes for pointing
+  out the implementation was under-optimized.
+* The salt for PBKDF2 can be either a string or bytes (GH#67).
+* Ciphers and hash functions accept data as `bytearray`, not just
+  binary strings.
+* The old SHA-1 and MD5 hash functions are available even when Python's
+  own `hashlib` does not include them.
+
+Resolved issues
+---------------
+
+* Without libgmp, modular exponentiation (since v3.4.8) crashed
+  on 32-bit big-endian systems.
+
+Breaks in compatibility
+-----------------------
+
+* Removed support for Python < 2.6.
+
+3.4.12 (5 February 2018)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#129. pycryptodomex could only be installed via wheels.
+
+3.4.11 (5 February 2018)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#121. the record list was still not correct due to PEP3147
+  and __pycache__ directories. Thanks again to John O'Brien.
+
+3.4.10 (2 February 2018)
+++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* When creating ElGamal keys, the generator wasn't a square residue:
+  ElGamal encryption done with those keys cannot be secure under
+  the DDH assumption. Thanks to Weikeng Chen.
+
+3.4.9 (1 February 2018)
++++++++++++++++++++++++
+
+New features
+------------
+* More meaningful error messages while importing an ECC key.
+
+Resolved issues
+---------------
+
+* GH#123 and #125. The SSE2 command line switch was not always passed on 32-bit x86 platforms.
+* GH#121. The record list (--record) was not always correctly filled for the
+  pycryptodomex package. Thanks to John W. O'Brien.
+
+3.4.8 (27 January 2018)
++++++++++++++++++++++++
+
+New features
+------------
+
+* Added a native extension in pure C for modular exponentiation, optimized for SSE2 on x86.
+  In the process, we drop support for the arbitrary arithmetic library MPIR
+  on Windows, which is painful to compile and deploy.
+  The custom  modular exponentiation is 130% (160%) slower on an Intel CPU in 32-bit (64-bit) mode,
+  compared to MPIR. Still, that is much faster that CPython's own `pow()` function which
+  is 900% (855%) slower than MPIR. Support for the GMP library on Unix remains.
+* Added support for *manylinux* wheels.
+* Support for Python 3.7.
+
+Resolved issues
+---------------
+
+* The DSA parameter 'p' prime was created with 255 bits cleared
+  (but still with the correct strength).
+* GH#106. Not all docs were included in the tar ball.
+  Thanks to Christopher Hoskin.
+* GH#109. ECDSA verification failed for DER encoded signatures.
+  Thanks to Alastair Houghton.
+* Human-friendly messages for padding errors with ECB and CBC.
+
+3.4.7 (26 August 2017)
+++++++++++++++++++++++
+
+New features
+------------
+
+* API documentation is made with sphinx instead of epydoc.
+* Start using ``importlib`` instead of ``imp`` where available.
+
+Resolved issues
+---------------
+
+* GH#82. Fixed PEM header for RSA/DSA public keys.
+
+3.4.6 (18 May 2017)
++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* GH#65. Keccak, SHA3, SHAKE and the seek functionality for ChaCha20 were
+  not working on big endian machines. Fixed. Thanks to Mike Gilbert.
+* A few fixes in the documentation.
+
+3.4.5 (6 February 2017)
++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* The library can also be compiled using MinGW.
+
+3.4.4 (1 February 2017)
++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* Removed use of ``alloca()``.
+* [Security] Removed implementation of deprecated "quick check" feature of PGP block cipher mode.
+* Improved the performance of ``scrypt`` by converting some Python to C.
+
+3.4.3 (17 October 2016)
++++++++++++++++++++++++
+
+Resolved issues
+---------------
+
+* Undefined warning was raised with libgmp version < 5
+* Forgot inclusion of ``alloca.h``
+* Fixed a warning about type mismatch raised by recent versions of cffi
+
+3.4.2 (8 March 2016)
+++++++++++++++++++++
+
+
+Resolved issues
+---------------
+
+* Fix renaming of package for ``install`` command.
+
+
+3.4.1 (21 February 2016)
+++++++++++++++++++++++++
+
+New features
+------------
+
+* Added option to install the library under the ``Cryptodome`` package
+  (instead of ``Crypto``).
+
+3.4 (7 February 2016)
++++++++++++++++++++++
+
+New features
+------------
+
+* Added ``Crypto.PublicKey.ECC`` module (NIST P-256 curve only), including export/import of ECC keys.
+* Added support for ECDSA (FIPS 186-3 and RFC6979).
+* For CBC/CFB/OFB/CTR cipher objects, ``encrypt()`` and ``decrypt()`` cannot be intermixed.
+* CBC/CFB/OFB, the cipher objects have both ``IV`` and ``iv`` attributes.
+  ``new()`` accepts ``IV`` as well as ``iv`` as parameter.
+* For CFB/OPENPGP cipher object, ``encrypt()`` and ``decrypt()`` do not require the plaintext
+  or ciphertext pieces to have length multiple of the CFB segment size.
+* Added dedicated tests for all cipher modes, including NIST test vectors
+* CTR/CCM/EAX/GCM/SIV/Salsa20/ChaCha20 objects expose the ``nonce`` attribute.
+* For performance reasons, CCM cipher optionally accepted a pre-declaration of
+  the length of the associated data, but never checked if the actual data passed
+  to the cipher really matched that length. Such check is now enforced.
+* CTR cipher objects accept parameter ``nonce`` and possibly ``initial_value`` in
+  alternative to ``counter`` (which is deprecated).
+* All ``iv``/``IV`` and ``nonce`` parameters are optional. If not provided,
+  they will be randomly generated (exception: ``nonce`` for CTR mode in case
+  of block sizes smaller than 16 bytes).
+* Refactored ARC2 cipher.
+* Added ``Crypto.Cipher.DES3.adjust_key_parity()`` function.
+* Added ``RSA.import_key`` as an alias to the deprecated ``RSA.importKey``
+  (same for the ``DSA`` module).
+* Added ``size_in_bits()`` and ``size_in_bytes()`` methods to ``RsaKey``.
+
+Resolved issues
+---------------
+
+* RSA key size is now returned correctly in ``RsaKey.__repr__()`` method (kudos to *hannesv*).
+* CTR mode does not modify anymore ``counter`` parameter passed to ``new()`` method.
+* CTR raises ``OverflowError`` instead of ``ValueError`` when the counter wraps around.
+* PEM files with Windows newlines could not be imported.
+* ``Crypto.IO.PEM`` and ``Crypto.IO.PKCS8`` used to accept empty passphrases.
+* GH#6: NotImplementedError now raised for unsupported methods ``sign``, ``verify``,
+  ``encrypt``, ``decrypt``, ``blind``, ``unblind`` and ``size`` in objects ``RsaKey``, ``DsaKey``,
+  ``ElGamalKey``.
+
+Breaks in compatibility
+-----------------------
+
+* Parameter ``segment_size`` cannot be 0 for the CFB mode.
+* For OCB ciphers, a final call without parameters to ``encrypt`` must end a sequence
+  of calls to ``encrypt`` with data (similarly for ``decrypt``).
+* Key size for ``ARC2``, ``ARC4`` and ``Blowfish`` must be at least 40 bits long (still very weak).
+* DES3 (Triple DES module) does not allow keys that degenerate to Single DES.
+* Removed method ``getRandomNumber`` in ``Crypto.Util.number``.
+* Removed module ``Crypto.pct_warnings``.
+* Removed attribute ``Crypto.PublicKey.RSA.algorithmIdentifier``.
+
+3.3.1 (1 November 2015)
++++++++++++++++++++++++
+
+New features
+------------
+
+* Opt-in for ``update()`` after ``digest()`` for SHA-3, keccak, BLAKE2 hashes
+
+Resolved issues
+---------------
+
+* Removed unused SHA-3 and keccak test vectors, therefore significantly reducing
+  the package from 13MB to 3MB.
+
+Breaks in compatibility
+-----------------------
+
+* Removed method ``copy()`` from BLAKE2 hashes
+* Removed ability to ``update()`` a BLAKE2 hash after the first call to ``(hex)digest()``
+
+3.3 (29 October 2015)
++++++++++++++++++++++
+
+New features
+------------
+
+* Windows wheels bundle the MPIR library
+* Detection of faults occurring during secret RSA operations
+* Detection of non-prime (weak) q value in DSA domain parameters
+* Added original Keccak hash family (b=1600 only).
+  In the process, simplified the C code base for SHA-3.
+* Added SHAKE128 and SHAKE256 (of SHA-3 family)
+
+Resolved issues
+---------------
+
+* GH#3: gcc 4.4.7 unhappy about double typedef
+
+Breaks in compatibility
+-----------------------
+
+* Removed method ``copy()`` from all SHA-3 hashes
+* Removed ability to ``update()`` a SHA-3 hash after the first call to ``(hex)digest()``
+
+3.2.1 (9 September 2015)
+++++++++++++++++++++++++
+
+New features
+------------
+
+* Windows wheels are automatically built on Appveyor
+
+3.2 (6 September 2015)
+++++++++++++++++++++++
+
+New features
+------------
+
+* Added hash functions BLAKE2b and BLAKE2s.
+* Added stream cipher ChaCha20.
+* Added OCB cipher mode.
+* CMAC raises an exception whenever the message length is found to be
+  too large and the chance of collisions not negligeable.
+* New attribute ``oid`` for Hash objects with ASN.1 Object ID
+* Added ``Crypto.Signature.pss`` and ``Crypto.Signature.pkcs1_15``
+* Added NIST test vectors (roughly 1200) for PKCS#1 v1.5 and PSS signatures.
+
+Resolved issues
+---------------
+
+* tomcrypt_macros.h asm error #1
+
+Breaks in compatibility
+-----------------------
+
+* Removed keyword ``verify_x509_cert`` from module method ``importKey`` (RSA and DSA).
+* Reverted to original PyCrypto behavior of method ``verify`` in ``PKCS1_v1_5``
+  and ``PKCS1_PSS``.
+
+3.1 (15 March 2015)
++++++++++++++++++++
+
+New features
+------------
+
+* Speed up execution of Public Key algorithms on PyPy, when backed
+  by the Gnu Multiprecision (GMP) library.
+* GMP headers and static libraries are not required anymore at the time
+  PyCryptodome is built. Instead, the code will automatically use the
+  GMP dynamic library (.so/.DLL) if found in the system at runtime.
+* Reduced the amount of C code by almost 40% (4700 lines).
+  Modularized and simplified all code (C and Python) related to block ciphers.
+  Pycryptodome is now free of CPython extensions.
+* Add support for CI in Windows via Appveyor.
+* RSA and DSA key generation more closely follows FIPS 186-4 (though it is
+  not 100% compliant).
+
+Resolved issues
+---------------
+
+* None
+
+Breaks in compatibility
+-----------------------
+
+* New dependency on ctypes with Python 2.4.
+* The ``counter`` parameter of a CTR mode cipher must be generated via
+  ``Crypto.Util.Counter``. It cannot be a generic callable anymore.
+* Removed the ``Crypto.Random.Fortuna`` package (due to lack of test vectors).
+* Removed the ``Crypto.Hash.new`` function.
+* The ``allow_wraparound`` parameter of ``Crypto.Util.Counter`` is ignored.
+  An exception is always generated if the counter is reused.
+* ``DSA.generate``, ``RSA.generate`` and ``ElGamal.generate`` do not
+  accept the ``progress_func`` parameter anymore.
+* Removed ``Crypto.PublicKey.RSA.RSAImplementation``.
+* Removed ``Crypto.PublicKey.DSA.DSAImplementation``.
+* Removed ambiguous method ``size()`` from RSA, DSA and ElGamal keys.
+
+3.0 (24 June 2014)
+++++++++++++++++++
+
+New features
+------------
+
+* Initial support for PyPy.
+* SHA-3 hash family based on the April 2014 draft of FIPS 202.
+  See modules ``Crypto.Hash.SHA3_224/256/384/512``.
+  Initial Keccak patch by Fabrizio Tarizzo.
+* Salsa20 stream cipher. See module ``Crypto.Cipher.Salsa20``.
+  Patch by Fabrizio Tarizzo.
+* Colin Percival's ``scrypt`` key derivation function (``Crypto.Protocol.KDF.scrypt``).
+* Proper interface to FIPS 186-3 DSA. See module ``Crypto.Signature.DSS``.
+* Deterministic DSA (RFC6979). Again, see ``Crypto.Signature.DSS``.
+* HMAC-based Extract-and-Expand key derivation function
+  (``Crypto.Protocol.KDF.HKDF``, RFC5869).
+* Shamir's Secret Sharing protocol, compatible with *ssss* (128 bits only).
+  See module ``Crypto.Protocol.SecretSharing``.
+* Ability to generate a DSA key given the domain parameters.
+* Ability to test installation with a simple ``python -m Crypto.SelfTest``.
+
+Resolved issues
+---------------
+
+* LP#1193521: ``mpz_powm_sec()`` (and Python) crashed when modulus was odd.
+* Benchmarks work again (they broke when ECB stopped working if
+  an IV was passed. Patch by Richard Mitchell.
+* LP#1178485: removed some catch-all exception handlers.
+  Patch by Richard Mitchell.
+* LP#1209399: Removal of Python wrappers caused HMAC to silently
+  produce the wrong data with SHA-2 algorithms.
+* LP#1279231: remove dead code that does nothing in SHA-2 hashes.
+  Patch by Richard Mitchell.
+* LP#1327081: AESNI code accesses memory beyond buffer end.
+* Stricter checks on ciphertext and plaintext size for textbook RSA
+  (kudos to sharego).
+
+Breaks in compatibility
+-----------------------
+
+* Removed support for Python < 2.4.
+* Removed the following methods from all 3 public key object types (RSA, DSA, ElGamal):
+
+  - ``sign``
+  - ``verify``
+  - ``encrypt``
+  - ``decrypt``
+  - ``blind``
+  - ``unblind``
+
+  Code that uses such methods is doomed anyway. It should be fixed ASAP to
+  use the algorithms available in ``Crypto.Signature`` and ``Crypto.Cipher``.
+* The 3 public key object types (RSA, DSA, ElGamal) are now unpickable.
+* Symmetric ciphers do not have a default mode anymore (used to be ECB).
+  An expression like ``AES.new(key)`` will now fail. If ECB is the desired mode,
+  one has to explicitly use ``AES.new(key, AES.MODE_ECB)``.
+* Unsuccessful verification of a signature will now raise an exception [reverted in 3.2].
+* Removed the ``Crypto.Random.OSRNG`` package.
+* Removed the ``Crypto.Util.winrandom`` module.
+* Removed the ``Crypto.Random.randpool`` module.
+* Removed the ``Crypto.Cipher.XOR`` module.
+* Removed the ``Crypto.Protocol.AllOrNothing`` module.
+* Removed the ``Crypto.Protocol.Chaffing`` module.
+* Removed the parameters ``disabled_shortcut`` and ``overflow`` from ``Crypto.Util.Counter.new``.
+
+Other changes
+-------------
+
+* ``Crypto.Random`` stops being a userspace CSPRNG. It is now a pure wrapper over ``os.urandom``.
+* Added certain resistance against side-channel attacks for GHASH (GCM) and DSA.
+* More test vectors for ``HMAC-RIPEMD-160``.
+* Update ``libtomcrypt`` headers and code to v1.17 (kudos to Richard Mitchell).
+* RSA and DSA keys are checked for consistency as they are imported.
+* Simplified build process by removing autoconf.
+* Speed optimization to PBKDF2.
+* Add support for MSVC.
+* Replaced HMAC code with a BSD implementation. Clarified that starting from the fork,
+  all contributions are released under the BSD license.

+ 29 - 0
tls/pycryptoMod/FuturePlans.rst

@@ -0,0 +1,29 @@
+Future releases will include:
+
+- Update `Crypto.Signature.DSS` to FIPS 186-4
+- Make all hash objects non-copyable and immutable after the first digest
+- Add alias 'segment_bits' to parameter 'segment_size' for CFB
+- Coverage testing
+- Implement AES with bitslicing
+- Add unit tests for PEM I/O
+- Move old ciphers into a Museum submodule
+- Add more ECC curves
+- Import/export of ECC keys with compressed points
+- Add algorithms:
+    - Elliptic Curves (ECIES, ECDH)
+    - Camellia, GOST
+    - Diffie-Hellman
+    - bcrypt
+    - argon2
+    - SRP
+- Add more key management:
+    - Export/import of DSA domain parameters
+    - JWK
+- Add support for CMS/PKCS#7
+- Add support for RNG backed by PKCS#11 and/or KMIP
+- Add support for Format-Preserving Encryption
+- Remove dependency on libtomcrypto headers
+- Speed up (T)DES with a bitsliced implementation
+- Run lint on the C code
+- Add (minimal) support for PGP
+- Add (minimal) support for PKIX / X.509

+ 281 - 0
tls/pycryptoMod/INSTALL.rst

@@ -0,0 +1,281 @@
+Installation
+------------
+
+The installation procedure depends on the package you want the library to be in.
+PyCryptodome can be used as:
+
+ #. **an almost drop-in replacement for the old PyCrypto library**.
+    You install it with::
+
+        pip install pycryptodome
+   
+    In this case, all modules are installed under the ``Crypto`` package.
+    You can test everything is right with::
+		
+         python -m Crypto.SelfTest
+   
+    One must avoid having both PyCrypto and PyCryptodome installed
+    at the same time, as they will interfere with each other.
+
+    This option is therefore recommended only when you are sure that
+    the whole application is deployed in a ``virtualenv``.
+
+ #. **a library independent of the old PyCrypto**.
+    You install it with::
+
+        pip install pycryptodomex
+   
+    You can test everything is right with::
+		
+        python -m Cryptodome.SelfTest
+  
+    In this case, all modules are installed under the ``Cryptodome`` package.
+    PyCrypto and PyCryptodome can coexist.
+
+The procedures below go a bit more in detail, by explaining
+how to setup the environment for compiling the C extensions
+for each OS, and how to install the GMP library.
+
+Compiling in Linux Ubuntu
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. note::
+    If you want to install under the ``Crypto`` package, replace
+    below ``pycryptodomex`` with ``pycryptodome``.
+
+For Python 2.x::
+
+        $ sudo apt-get install build-essential python-dev
+        $ pip install pycryptodomex
+        $ python -m Cryptodome.SelfTest
+
+For Python 3.x::
+
+        $ sudo apt-get install build-essential python3-dev
+        $ pip install pycryptodomex
+        $ python3 -m Cryptodome.SelfTest
+
+For PyPy::
+
+        $ sudo apt-get install build-essential pypy-dev
+        $ pip install pycryptodomex
+        $ pypy -m Cryptodome.SelfTest
+
+Compiling in Linux Fedora
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. note::
+    If you want to install under the ``Crypto`` package, replace
+    below ``pycryptodomex`` with ``pycryptodome``.
+
+For Python 2.x::
+
+        $ sudo yum install gcc gmp python-devel
+        $ pip install pycryptodomex
+        $ python -m Cryptodome.SelfTest
+
+For Python 3.x::
+
+        $ sudo yum install gcc gmp python3-devel
+        $ pip install pycryptodomex
+        $ python3 -m Cryptodome.SelfTest
+
+For PyPy::
+
+        $ sudo yum install gcc gmp pypy-devel
+        $ pip install pycryptodomex
+        $ pypy -m Cryptodome.SelfTest
+
+
+Windows (from sources, Python 2.x, Python <=3.2)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. note::
+    If you want to install under the ``Crypto`` package, replace
+    below ``pycryptodomex`` with ``pycryptodome``.
+
+Windows does not come with a C compiler like most Unix systems.
+The simplest way to compile the *Pycryptodome* extensions from
+source code is to install the minimum set of Visual Studio
+components freely made available by Microsoft.
+
+#. Run Python from the command line and note down its version
+   and whether it is a 32 bit or a 64 bit application.
+
+   For instance, if you see::
+
+        Python 2.7.2+ ... [MSC v.1500 32 bit (Intel)] on win32
+
+   you clearly have Python 2.7 and it is a 32 bit application.
+
+#. **[Only once]** Install `Virtual Clone Drive`_.
+
+#. **[Only once]** Download the ISO image of the
+   `MS SDK for Windows 7 and . NET Framework 3.5 SP1 <http://www.microsoft.com/en-us/download/details.aspx?id=18950>`_.
+   It contains the Visual C++ 2008 compiler.
+   
+   There are three ISO images available: you will need ``GRMSDK_EN_DVD.iso`` if your
+   Windows OS is 32 bits or ``GRMSDKX_EN_DVD.iso`` if 64 bits.
+
+   Mount the ISO with *Virtual Clone Drive* and install the C/C++ compilers and the
+   redistributable only.
+
+#. If your Python is a 64 bit application, open a command prompt and perform the following steps::
+
+        > cd "C:\Program Files\Microsoft SDKs\Windows\v7.0"
+        > cmd /V:ON /K Bin\SetEnv.Cmd /x64 /release
+        > set DISTUTILS_USE_SDK=1
+   
+   Replace ``/x64`` with ``/x86`` if your Python is a 32 bit application.
+
+#. Compile and install PyCryptodome::
+
+        > pip install pycryptodomex --no-use-wheel
+
+#. To make sure everything work fine, run the test suite::
+
+        > python -m Cryptodome.SelfTest
+
+Windows (from sources, Python 3.3 and 3.4)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. note::
+    If you want to install under the ``Crypto`` package, replace
+    below ``pycryptodomex`` with ``pycryptodome``.
+
+Windows does not come with a C compiler like most Unix systems.
+The simplest way to compile the *Pycryptodome* extensions from
+source code is to install the minimum set of Visual Studio
+components freely made available by Microsoft.
+
+#. Run Python from the command line and note down its version
+   and whether it is a 32 bit or a 64 bit application.
+
+   For instance, if you see::
+
+        Python 2.7.2+ ... [MSC v.1500 32 bit (Intel)] on win32
+
+   you clearly have Python 2.7 and it is a 32 bit application.
+
+#. **[Only once]** Install `Virtual Clone Drive <https://www.redfox.bz/virtual-clonedrive.html>`_.
+
+#. **[Only once]** Download the ISO image of the
+   `MS SDK for Windows 7 and . NET Framework 4 <https://www.microsoft.com/en-us/download/details.aspx?id=8442>`_.
+   It contains the Visual C++ 2010 compiler.
+   
+   There are three ISO images available: you will need ``GRMSDK_EN_DVD.iso`` if your
+   Windows OS is 32 bits or ``GRMSDKX_EN_DVD.iso`` if 64 bits.
+
+   Mount the ISO with *Virtual Clone Drive* and install the C/C++ compilers and the
+   redistributable only.
+
+#. If your Python is a 64 bit application, open a command prompt and perform the following steps::
+
+        > cd "C:\Program Files\Microsoft SDKs\Windows\v7.1"
+        > cmd /V:ON /K Bin\SetEnv.Cmd /x64 /release
+        > set DISTUTILS_USE_SDK=1
+   
+   Replace ``/x64`` with ``/x86`` if your Python is a 32 bit application.
+
+#. Compile and install PyCryptodome::
+
+        > pip install pycryptodomex --no-use-wheel
+
+#. To make sure everything work fine, run the test suite::
+
+        > python -m Cryptodome.SelfTest
+
+Windows (from sources, Python 3.5 and newer)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. note::
+    If you want to install under the ``Crypto`` package, replace
+    below ``pycryptodomex`` with ``pycryptodome``.
+
+Windows does not come with a C compiler like most Unix systems.
+The simplest way to compile the *PyCryptodome* extensions from
+source code is to install the minimum set of Visual Studio
+components freely made available by Microsoft.
+
+#. **[Once only]** Download `Build Tools for Visual Studio 2019 <https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019>`_.
+   In the installer, select the *C++ build tools*, the *Windows 10 SDK*, and the latest version of *MSVC v142 x64/x86 build tools*.
+
+#. Compile and install PyCryptodome::
+
+        > pip install pycryptodomex --no-binary :all:
+
+#. To make sure everything work fine, run the test suite::
+
+        > python -m Cryptodome.SelfTest
+
+Documentation
+~~~~~~~~~~~~~
+
+Project documentation is written in reStructuredText and it is stored under ``Doc/src``.
+To publish it as HTML files, you need to install `sphinx <http://www.sphinx-doc.org/en/stable/>`_ and
+use::
+
+    > make -C Doc/ html
+
+It will then be available under ``Doc/_build/html/``.
+
+PGP verification
+~~~~~~~~~~~~~~~~
+
+All source packages and wheels on PyPI are cryptographically signed.
+They can be verified with the following PGP key::
+
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
+ 
+ mQINBFTXjPgBEADc3j7vnma9MXRshBPPXXenVpthQD6lrF/3XaBT2RptSf/viOD+
+ tz85du5XVp+r0SYYGeMNJCQ9NsztxblN/lnKgkfWRmSrB+V6QGS+e3bR5d9OIxzN
+ 7haPxBnyRj//hCT/kKis6fa7N9wtwKBBjbaSX+9vpt7Rrt203sKfcChA4iR3EG89
+ TNQoc/kGGmwk/gyjfU38726v0NOhMKJp2154iQQVZ76hTDk6GkOYHTcPxdkAj4jS
+ Dd74M9sOtoOlyDLHOLcWNnlWGgZjtz0z0qSyFXRSuOfggTxrepWQgKWXXzgVB4Jo
+ 0bhmXPAV8vkX5BoG6zGkYb47NGGvknax6jCvFYTCp1sOmVtf5UTVKPplFm077tQg
+ 0KZNAvEQrdWRIiQ1cCGCoF2Alex3VmVdefHOhNmyY7xAlzpP0c8z1DsgZgMnytNn
+ GPusWeqQVijRxenl+lyhbkb9ZLDq7mOkCRXSze9J2+5aLTJbJu3+Wx6BEyNIHP/f
+ K3E77nXvC0oKaYTbTwEQSBAggAXP+7oQaA0ea2SLO176xJdNfC5lkQEtMMSZI4gN
+ iSqjUxXW2N5qEHHex1atmTtk4W9tQEw030a0UCxzDJMhD0aWFKq7wOxoCQ1q821R
+ vxBH4cfGWdL/1FUcuCMSUlc6fhTM9pvMXgjdEXcoiLSTdaHuVLuqmF/E0wARAQAB
+ tB9MZWdyYW5kaW4gPGhlbGRlcmlqc0BnbWFpbC5jb20+iQI4BBMBAgAiBQJU14z4
+ AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDabO+N4RaZEn7IEACpApha
+ vRwPB+Dv87aEyVmjZ96Nb3mxHdeP2uSmUxAODzoB5oJJ1QL6HRxEVlU8idjdf73H
+ DX39ZC7izD+oYIve9sNwTbKqJCZaTxlTDdgSF1N57eJOlELAy+SqpHtaMJPk7SfJ
+ l/iYoUYxByPLZU1wDwZEDNzt9RCGy3bd/vF/AxWjdUJJPh3E4j5hswvIGSf8/Tp3
+ MDROU1BaNBOd0CLvBHok8/xavwO6Dk/fE4hJhd5uZcEPtd1GJcPq51z2yr7PGUcb
+ oERsKZyG8cgfd7j8qoTd6jMIW6fBVHdxiMxW6/Z45X/vVciQSzzEl/yjPUW42kyr
+ Ib6M16YmnDzp8bl4NNFvvR9uWvOdUkep2Bi8s8kBMJ7G9rHHJcdVy/tP1ECS9Bse
+ hN4v5oJJ4v5mM/MiWRGKykZULWklonpiq6CewYkmXQDMRnjGXhjCWrB6LuSIkIXd
+ gKvDNpJ8yEhAfmpvA4I3laMoof/tSZ7ZuyLSZGLKl6hoNIB13HCn4dnjNBeaXCWX
+ pThgeOWxV6u1fhz4CeC1Hc8WOYr8S7G8P10Ji6owOcj/a1QuCW8XDB2omCTXlhFj
+ zpC9dX8HgmUVnbPNiMjphihbKXoOcunRx4ZvqIa8mnTbI4tHtR0K0tI4MmbpcVOZ
+ 8IFJ0nZJXuZiL57ijLREisPYmHfBHAgmh1j/W7kCDQRU14z4ARAA3QATRgvOSYFh
+ nJOnIz6PO3G9kXWjJ8wvp3yE1/PwwTc3NbVUSNCW14xgM2Ryhn9NVh8iEGtPGmUP
+ 4vu7rvuLC2rBs1joBTyqf0mDghlZrb5ZjXv5LcG9SA6FdAXRU6T+b1G2ychKkhEh
+ d/ulLw/TKLds9zHhE+hkAagLQ5jqjcQN0iX5EYaOukiPUGmnd9fOEGi9YMYtRdrH
+ +3bZxUpsRStLBWJ6auY7Bla8NJOhaWpr5p/ls+mnDWoqf+tXCCps1Da/pfHKYDFc
+ 2VVdyM/VfNny9eaczYpnj5hvIAACWChgGDBwxPh2DGdUfiQi/QqrK96+F7ulqz6V
+ 2exX4CL0cPv5fUpQqSU/0R5WApM9bl2+wljFhoCXlydU9HNn+0GatGzEoo3yrV/m
+ PXv7d6NdZxyOqgxu/ai/z++F2pWUXSBxZN3Gv28boFKQhmtthTcFudNUtQOchhn8
+ Pf/ipVISqrsZorTx9Qx4fPScEWjwbh84Uz20bx0sQs1oYcek2YG5RhEdzqJ6W78R
+ S/dbzlNYMXGdkxB6C63m8oiGvw0hdN/iGVqpNAoldFmjnFqSgKpyPwfLmmdstJ6f
+ xFZdGPnKexCpHbKr9fg50jZRenIGai79qPIiEtCZHIdpeemSrc7TKRPV3H2aMNfG
+ L5HTqcyaM2+QrMtHPMoOFzcjkigLimMAEQEAAYkCHwQYAQIACQUCVNeM+AIbDAAK
+ CRDabO+N4RaZEo7lD/45J6z2wbL8aIudGEL0aY3hfmW3qrUyoHgaw35KsOY9vZwb
+ cZuJe0RlYptOreH/NrbR5SXODfhd2sxYyyvXBOuZh9i7OOBsrAd5UE01GCvToPwh
+ 7IpMV3GSSAB4P8XyJh20tZqiZOYKhmbf29gUDzqAI6GzUa0U8xidUKpW2zqYGZjp
+ wk3RI1fS7tyi/0N8B9tIZF48kbvpFDAjF8w7NSCrgRquAL7zJZIG5o5zXJM/ffF3
+ 67Dnz278MbifdM/HJ+Tj0R0Uvvki9Z61nT653SoUgvILQyC72XI+x0+3GQwsE38a
+ 5aJNZ1NBD3/v+gERQxRfhM5iLFLXK0Xe4K2XFM1g0yN4L4bQPbhSCq88g9Dhmygk
+ XPbBsrK0NKPVnyGyUXM0VpgRbot11hxx02jC3HxS1nlLF+oQdkKFzJAMOU7UbpX/
+ oO+286J1FmpG+fihIbvp1Quq48immtnzTeLZbYCsG4mrM+ySYd0Er0G8TBdAOTiN
+ 3zMbGX0QOO2fOsJ1d980cVjHn5CbAo8C0A/4/R2cXAfpacbvTiNq5BVk9NKa2dNb
+ kmnTStP2qILWmm5ASXlWhOjWNmptvsUcK+8T+uQboLioEv19Ob4j5Irs/OpOuP0K
+ v4woCi9+03HMS42qGSe/igClFO3+gUMZg9PJnTJhuaTbytXhUBgBRUPsS+lQAQ==
+ =DpoI
+ -----END PGP PUBLIC KEY BLOCK-----
+
+.. _pypi: https://pypi.python.org/pypi/pycryptodome
+.. _get-pip.py: https://bootstrap.pypa.io/get-pip.py
+.. _GMP: http://gmplib.org

+ 274 - 0
tls/pycryptoMod/LICENSE.rst

@@ -0,0 +1,274 @@
+The source code in PyCryptodome is partially in the public domain
+and partially released under the BSD 2-Clause license.
+
+In either case, there are minimal if no restrictions on the redistribution,
+modification and usage of the software.
+
+Public domain
+=============
+
+All code originating from  PyCrypto is free and unencumbered software
+released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org>
+
+BSD license
+===========
+
+All direct contributions to PyCryptodome are released under the following
+license. The copyright of each piece belongs to the respective author.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+OCB license
+===========
+
+The OCB cipher mode is patented in the US under patent numbers 7,949,129 and 
+8,321,675. The directory Doc/ocb contains three free licenses for implementors 
+and users. As a general statement, OCB can be freely used for software not meant 
+for military purposes. Contact your attorney for further information.
+
+Apache 2.0 license (Wycheproof)
+===============================
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 12 - 0
tls/pycryptoMod/MANIFEST.in

@@ -0,0 +1,12 @@
+include MANIFEST.in
+include *.rst
+include .separate_namespace
+include setup.py pct-speedtest.py compiler_opt.py setup.cfg
+graft Doc
+prune Doc/_build
+include appveyor.yml appveyor/get_wheels.sh appveyor/install.ps1 appveyor/run_with_env.cmd
+include .travis.yml travis/*.sh
+recursive-include src *.h *.c
+graft src/test
+recursive-exclude src *.pyc
+prune src/test/build

+ 75 - 0
tls/pycryptoMod/README.rst

@@ -0,0 +1,75 @@
+.. image:: https://travis-ci.org/Legrandin/pycryptodome.svg?branch=master
+   :target: https://travis-ci.org/Legrandin/pycryptodome
+
+.. image:: https://ci.appveyor.com/api/projects/status/mbxyqdodw9ylfib9/branch/master?svg=true
+   :target: https://ci.appveyor.com/project/Legrandin/pycryptodome
+
+PyCryptodome
+============
+
+PyCryptodome is a self-contained Python package of low-level
+cryptographic primitives.
+
+It supports Python 2.6 and 2.7, Python 3.4 and newer, and PyPy.
+
+The installation procedure depends on the package you want the library to be in.
+PyCryptodome can be used as:
+
+#. **an almost drop-in replacement for the old PyCrypto library**.
+   You install it with::
+
+       pip install pycryptodome
+   
+   In this case, all modules are installed under the ``Crypto`` package.
+    
+   One must avoid having both PyCrypto and PyCryptodome installed
+   at the same time, as they will interfere with each other.
+
+   This option is therefore recommended only when you are sure that
+   the whole application is deployed in a ``virtualenv``.
+
+#. **a library independent of the old PyCrypto**.
+   You install it with::
+
+       pip install pycryptodomex
+   
+   In this case, all modules are installed under the ``Cryptodome`` package.
+   PyCrypto and PyCryptodome can coexist.
+
+For faster public key operations in Unix, you should install `GMP`_ in your system.
+
+PyCryptodome is a fork of PyCrypto. It brings the following enhancements
+with respect to the last official version of PyCrypto (2.6.1):
+
+* Authenticated encryption modes (GCM, CCM, EAX, SIV, OCB)
+* Accelerated AES on Intel platforms via AES-NI
+* First class support for PyPy
+* Elliptic curves cryptography (NIST P-256, P-384 and P-521 curves only)
+* Better and more compact API (`nonce` and `iv` attributes for ciphers,
+  automatic generation of random nonces and IVs, simplified CTR cipher mode,
+  and more)
+* SHA-3 (including SHAKE XOFs), truncated SHA-512 and BLAKE2 hash algorithms
+* Salsa20 and ChaCha20/XChaCha20 stream ciphers
+* Poly1305 MAC
+* ChaCha20-Poly1305 and XChaCha20-Poly1305 authenticated ciphers
+* scrypt, bcrypt and HKDF derivation functions
+* Deterministic (EC)DSA
+* Password-protected PKCS#8 key containers
+* Shamir's Secret Sharing scheme
+* Random numbers get sourced directly from the OS (and not from a CSPRNG in userspace)
+* Simplified install process, including better support for Windows
+* Cleaner RSA and DSA key generation (largely based on FIPS 186-4)
+* Major clean ups and simplification of the code base
+
+PyCryptodome is not a wrapper to a separate C library like *OpenSSL*.
+To the largest possible extent, algorithms are implemented in pure Python.
+Only the pieces that are extremely critical to performance (e.g. block ciphers)
+are implemented as C extensions.
+
+For more information, see the `homepage`_.
+
+All the code can be downloaded from `GitHub`_.
+
+.. _`homepage`: https://www.pycryptodome.org
+.. _`GMP`: https://gmplib.org
+.. _GitHub: https://github.com/Legrandin/pycryptodome

+ 89 - 0
tls/pycryptoMod/appveyor.yml

@@ -0,0 +1,89 @@
+environment:
+
+  global:
+    # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
+    # /E:ON and /V:ON options are not enabled in the batch script interpreter
+    # See: http://stackoverflow.com/a/13751649/163740
+    WITH_COMPILER: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
+
+  matrix:
+    - PYTHON: "C:\\Python27"
+      PYTHON_VERSION: "2.7.8"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python27-x64"
+      PYTHON_VERSION: "2.7.8"
+      PYTHON_ARCH: "64"
+      WINDOWS_SDK_VERSION: "v7.0"
+
+    - PYTHON: "C:\\Python35"
+      PYTHON_VERSION: "3.5.0"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python35-x64"
+      PYTHON_VERSION: "3.5.0"
+      PYTHON_ARCH: "64"
+
+    - PYTHON: "C:\\Python36"
+      PYTHON_VERSION: "3.6.0"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python36-x64"
+      PYTHON_VERSION: "3.6.0"
+      PYTHON_ARCH: "64"
+
+    - PYTHON: "C:\\Python37"
+      PYTHON_VERSION: "3.7.0"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python37-x64"
+      PYTHON_VERSION: "3.7.0"
+      PYTHON_ARCH: "64"
+
+    - PYTHON: "C:\\Python38"
+      PYTHON_VERSION: "3.8.0"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python38-x64"
+      PYTHON_VERSION: "3.8.0"
+      PYTHON_ARCH: "64"
+
+init:
+  - ECHO "%PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
+
+  - ECHO "Filesystem root:"
+  - ps: "ls \"C:/\""
+
+  - ECHO "Installed SDKs:"
+  - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
+
+  # Prepend newly installed Python to the PATH of this build (this cannot be
+  # done from inside the powershell script as it would require to restart
+  # the parent CMD process).
+  - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
+
+  # Check that we have the expected version and architecture for Python
+  - "python --version"
+  - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
+
+install:
+  - "powershell appveyor\\install.ps1"
+
+#build: off
+
+build_script:
+  - "%WITH_COMPILER% python setup.py build"
+
+test_script:
+  - "dir %PYTHON%"
+  - "%WITH_COMPILER% python setup.py test"
+
+after_test:
+  - "%WITH_COMPILER% python setup.py bdist_wheel"
+
+artifacts:
+  - path: dist\*
+
+#on_success:
+#  - TODO: upload the content of dist/*.whl to a public wheelhouse
+

+ 99 - 0
tls/pycryptoMod/bench_monty.py

@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+
+import time
+from tls.Crypto.PublicKey import RSA
+from tls.Crypto.Math import Numbers
+from tls.Crypto.Math.Numbers import Integer
+from tls.Crypto.Util.number import long_to_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  create_string_buffer,
+                                  c_size_t)
+
+ITER = 100
+
+print(Numbers._implementation)
+
+rsa_pem="""-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA1maRsgBxvk1m1LcQMrN/oAfPq/V5/LkeUL/CdTs/DOe+dOIW
+rvfibUrhgLwg170+qIpsv2+HOA5hPIl5tbBDsgCo/4hWo7EodeNumKdWnzhS0Cjp
+Z1UQALAsGen6UugxFbiTCaq7Hhzx4stjadY31Gd1zkUj6jH2StJ5TLw2XdijXgB+
+07V2lYd/vxAtvrizISSROY5JQxTpNyaSbhOD+Ku1iJvqlU64wMocYsjp2D9BiICV
+xeZF7W0yUV/gxYwTaMrYRpThjaQ2aMb0PmHXybymM93Np671t5vDltSp9I4qmr4I
+NsxFXkNTBTVyKOk9JartRrlS3vrg9XM5vyb1qQIDAQABAoIBACzgr2KJAUYKQZoI
+75UNSYuf1vJxoaUqwpO4b+XGDv6Oi6k/oevh6z1hTS57Moy2CiWRRA4WNEGhkOzx
+Ac7sJF9gD//c8/WzoXp7rqy5akJNsdfsmF6OyZi7R5/s//7Wp1+akPyXBi/ZczA7
+zoVa17jYJyqUAl6FMr6aq9VKGD8wNTjSp+YhtBMdWegjpGJfOb19UY13hPfDqPGQ
+Ydp0l0/0L6HAY97C25fUYeKRp9bnIXCKUineFmwSRjYzcoVOJ/PwiuJ0vBa/0gWw
+KKTYE4ZJRDPVFt+7NfSVrLpeTh0YQ8s8MSm2ZCqF/HJEzlhF+sBxx/Yi5O4SrEP6
+vuqgzQECgYEA/E9vn6XKnJXX3hiy0XVsUQK+Ana2xn63TxmiMJtrrUjD5WCiy9kD
+eTU82igdg9JJGBWOd7mkSAWxVZT9MPaQ4/Vz6ggoZcPHZokmVP7qPePNmFXX6Jdz
+hQx8HD0QcwwaYbIJ91WdoAP/cEuu+o+WPKB0CDYWrv3Dx9eTircemlECgYEA2Yk2
+WXkOdD2KlnZgHNYp23F2XP6dF4Ny5n478thlJXdexRwRDSKCN/41jfC0FlPpZBcF
+7EFTo+p7lhyJVxPBWSOIhJArMe98bdWoo+6TBuAPLisu7+i+HVRaoyHf0x3t7ViG
+JqQOGjHN0G57cgSCrpaFwE2bAZ4dkA27M8Oy99kCgYEAw+HoB0nvwyGSNht2uKcx
+MLOwULlZrUEzj3WXNaV0M1QKwkoEGb6hs7hhRf1e7LiVht01fj3iDQheZNMGvryu
+QEyPcWJj+p3EcRaJa/N8aBAzzdDXjvwF84V91W6TFr6OvMo8colFlrWD2urnLh/L
+w8XOT5Guiqz5Em2LXmZMnAECgYEAuZ1Ksq2Il8arKhd3iyNyM7xssozOnfGbaPDt
+VhkutPlV8/ou0nZPhldyetqXzzVqP+0lMKHNLGA3c66Fwbcpk1Wudu5M7R7bnRxh
++P7olUU5rrtKIYsGLSB89hVBVnKDQbH3RaFWJyO36dFbo74Vg8ML/To6uPahYvlU
+cqbZXoECgYAOybAyRS9vivcYoKywxtI0aU1HHibPrUl3izYLfDxfWgA0S6IGcBg1
+Sx6XG8GYbzkouGb30yjIpn7JB1147DH1oxf8wcHXbAsgNX4IC6rQ1Iwef9P4pORF
+icKO95pcPRhmfzuqfhEu/d/ZYjabao95baBHcrRxEbXZtjg88KVXKg==
+-----END RSA PRIVATE KEY-----
+"""
+
+c_defs = """
+int monty_pow(const uint8_t *base,
+               const uint8_t *exp,
+               const uint8_t *modulus,
+               uint8_t       *out,
+               size_t len,
+               uint64_t seed);
+"""
+
+_raw_montgomery = load_pycryptodome_raw_lib("Crypto.Math._montgomery", c_defs)
+
+key = RSA.import_key(rsa_pem)
+message = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+SIZE = key.size_in_bytes()
+
+# -----------------------------------------------------------------
+start = time.time()
+for x in range(ITER):
+	result_cpython = pow(message, key.d, key.n)
+end = time.time()
+print("CPython =", end-start)
+
+# -----------------------------------------------------------------
+base_b = long_to_bytes(message, SIZE)
+exp_b = long_to_bytes(key.d, SIZE)
+modulus_b = long_to_bytes(key.n, SIZE)
+out = create_string_buffer(SIZE)
+
+start = time.time()
+for _ in range(ITER):
+    _raw_montgomery.monty_pow(
+                base_b,
+                exp_b,
+                modulus_b,
+                out,
+                c_size_t(SIZE),
+                32
+                )
+end = time.time()
+my_time = end-start
+print("Custom modexp =", my_time)
+
+# -----------------------------------------------------------------
+mg = Integer(message)
+md = Integer(key.d)
+mn = Integer(key.n)
+start = time.time()
+for x in range(ITER):
+	result_gmp = pow(mg, md, mn)
+end = time.time()
+gmp_time = end - start
+print("GMP =", gmp_time)
+
+# -----------------------------------------------------------------
+print("%.2f%%" % float((my_time/gmp_time-1)*100), "slower")

+ 423 - 0
tls/pycryptoMod/compiler_opt.py

@@ -0,0 +1,423 @@
+# ===================================================================
+#
+# Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+
+import os
+import sys
+import struct
+import distutils
+from distutils import ccompiler
+from distutils.errors import CCompilerError
+
+
+def test_compilation(program, extra_cc_options=None, extra_libraries=None,
+                     msg=''):
+    """Test if a certain C program can be compiled."""
+
+    # Create a temporary file with the C program
+    if not os.path.exists("build"):
+        os.makedirs("build")
+    fname = os.path.join("build", "test1.c")
+    f = open(fname, 'w')
+    f.write(program)
+    f.close()
+
+    # Name for the temporary executable
+    oname = os.path.join("build", "test1.out")
+
+    debug = bool(os.environ.get('PYCRYPTODOME_DEBUG', None))
+    # Mute the compiler and the linker
+    if msg:
+        print("Testing support for %s" % msg)
+    if not (debug or os.name == 'nt'):
+        old_stdout = os.dup(sys.stdout.fileno())
+        old_stderr = os.dup(sys.stderr.fileno())
+        dev_null = open(os.devnull, "w")
+        os.dup2(dev_null.fileno(), sys.stdout.fileno())
+        os.dup2(dev_null.fileno(), sys.stderr.fileno())
+
+    objects = []
+    try:
+        compiler = ccompiler.new_compiler()
+        distutils.sysconfig.customize_compiler(compiler)
+
+        if compiler.compiler_type in ['msvc']:
+            # Force creation of the manifest file (http://bugs.python.org/issue16296)
+            # as needed by VS2010
+            extra_linker_options = ["/MANIFEST"]
+        else:
+            extra_linker_options = []
+
+        # In Unix, force the linker step to use CFLAGS and not CC alone (see GH#180)
+        if compiler.compiler_type in ['unix']:
+            compiler.set_executables(linker_exe=compiler.compiler)
+
+        objects = compiler.compile([fname], extra_postargs=extra_cc_options)
+        compiler.link_executable(objects, oname, libraries=extra_libraries,
+                                 extra_preargs=extra_linker_options)
+        result = True
+    except (CCompilerError, OSError):
+        result = False
+    for f in objects + [fname, oname]:
+        try:
+            os.remove(f)
+        except OSError:
+            pass
+
+    # Restore stdout and stderr
+    if not (debug or os.name == 'nt'):
+        if old_stdout is not None:
+            os.dup2(old_stdout, sys.stdout.fileno())
+        if old_stderr is not None:
+            os.dup2(old_stderr, sys.stderr.fileno())
+        if dev_null is not None:
+            dev_null.close()
+    if msg:
+        if result:
+            x = ""
+        else:
+            x = " not"
+        print("Target does%s support %s" % (x, msg))
+
+    return result
+
+
+def has_stdint_h():
+    source = """
+    #include <stdint.h>
+    int main(void) {
+        uint32_t u;
+        u = 0;
+        return u + 2;
+    }
+    """
+    return test_compilation(source, msg="stdint.h header")
+
+
+def compiler_supports_uint128():
+    source = """
+    int main(void)
+    {
+        __uint128_t x;
+        return 0;
+    }
+    """
+    return test_compilation(source, msg="128-bit integer")
+
+
+def compiler_has_intrin_h():
+    # Windows
+    source = """
+    #include <intrin.h>
+    int main(void)
+    {
+        int a, b[4];
+        __cpuid(b, a);
+        return 0;
+    }
+    """
+    return test_compilation(source, msg="intrin.h header")
+
+
+def compiler_has_cpuid_h():
+    # UNIX
+    source = """
+    #include <cpuid.h>
+    int main(void)
+    {
+        unsigned int eax, ebx, ecx, edx;
+        __get_cpuid(1, &eax, &ebx, &ecx, &edx);
+        return 0;
+    }
+    """
+    return test_compilation(source, msg="cpuid.h header")
+
+
+def compiler_supports_aesni():
+    source = """
+    #include <wmmintrin.h>
+    __m128i f(__m128i x, __m128i y) {
+        return _mm_aesenc_si128(x, y);
+    }
+    int main(void) {
+        return 0;
+    }
+    """
+
+    if test_compilation(source):
+        return {'extra_cc_options': [], 'extra_macros': []}
+
+    if test_compilation(source, extra_cc_options=['-maes'], msg='AESNI intrinsics'):
+        return {'extra_cc_options': ['-maes'], 'extra_macros': []}
+
+    return False
+
+
+def compiler_supports_clmul():
+    result = {'extra_cc_options': [], 'extra_macros' : ['HAVE_WMMINTRIN_H', 'HAVE_TMMINTRIN_H']}
+
+    source = """
+    #include <wmmintrin.h>
+    #include <tmmintrin.h>
+
+    __m128i f(__m128i x, __m128i y) {
+        return _mm_clmulepi64_si128(x, y, 0x00);
+    }
+
+    __m128i g(__m128i a) {
+        __m128i mask;
+
+        mask = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+        return _mm_shuffle_epi8(a, mask);
+    }
+
+    int main(void) {
+        return 0;
+    }
+    """
+
+    if test_compilation(source):
+        return result
+
+    if test_compilation(source, extra_cc_options=['-mpclmul', '-mssse3'], msg='CLMUL intrinsics'):
+        result['extra_cc_options'].extend(['-mpclmul', '-mssse3'])
+        return result
+
+    return False
+
+
+def compiler_has_posix_memalign():
+    source = """
+    #include <stdlib.h>
+    int main(void) {
+        void *new_mem;
+        int res;
+        res = posix_memalign((void**)&new_mem, 16, 101);
+        return res == 0;
+    }
+    """
+    return test_compilation(source, msg="posix_memalign")
+
+
+def compiler_has_memalign():
+    source = """
+    #include <malloc.h>
+    int main(void) {
+        void *p;
+        p = memalign(16, 101);
+        return p != (void*)0;
+    }
+    """
+    return test_compilation(source, msg="memalign")
+
+
+def compiler_is_clang():
+    source = """
+    #if !defined(__clang__)
+    #error Not clang
+    #endif
+    int main(void)
+    {
+        return 0;
+    }
+    """
+    return test_compilation(source, msg="clang")
+
+
+def compiler_is_gcc():
+    source = """
+    #if defined(__clang__) || !defined(__GNUC__)
+    #error Not GCC
+    #endif
+    int main(void)
+    {
+        return 0;
+    }"""
+    return test_compilation(source, msg="gcc")
+
+
+def support_gcc_realign():
+    source = """
+    void __attribute__((force_align_arg_pointer)) a(void) {}
+    int main(void) { return 0; }
+    """
+    return test_compilation(source, msg="gcc")
+
+
+def compiler_supports_sse2():
+    source = """
+    #include <intrin.h>
+    int main(void)
+    {
+        __m128i r0;
+        int mask;
+        r0 = _mm_set1_epi32(0);
+        mask = _mm_movemask_epi8(r0);
+        return mask;
+    }
+    """
+    if test_compilation(source, msg="SSE2(intrin.h)"):
+        return {'extra_cc_options': [], 'extra_macros': ['HAVE_INTRIN_H', 'USE_SSE2']}
+
+    source = """
+    #include <x86intrin.h>
+    int main(void)
+    {
+        __m128i r0;
+        int mask;
+        r0 = _mm_set1_epi32(0);
+        mask = _mm_movemask_epi8(r0);
+        return mask;
+    }
+    """
+    if test_compilation(source, extra_cc_options=['-msse2'], msg="SSE2(x86intrin.h)"):
+        return {'extra_cc_options': ['-msse2'], 'extra_macros': ['HAVE_X86INTRIN_H', 'USE_SSE2']}
+
+    source = """
+    #include <xmmintrin.h>
+    #include <emmintrin.h>
+    int main(void)
+    {
+        __m128i r0;
+        int mask;
+        r0 = _mm_set1_epi32(0);
+        mask = _mm_movemask_epi8(r0);
+        return mask;
+    }
+    """
+    if test_compilation(source, extra_cc_options=['-msse2'], msg="SSE2(emmintrin.h)"):
+        return {'extra_cc_options': ['-msse2'], 'extra_macros': ['HAVE_EMMINTRIN_H', 'USE_SSE2']}
+
+    return False
+
+
+def remove_extension(extensions, name):
+    idxs = [i for i, x in enumerate(extensions) if x.name == name]
+    if len(idxs) != 1:
+        raise ValueError("There is no or there are multiple extensions named '%s'" % name)
+    del extensions[idxs[0]]
+
+
+def set_compiler_options(package_root, extensions):
+    """Environment specific settings for extension modules.
+
+    This function modifies how each module gets compiled, to
+    match the capabilities of the platform.
+    Also, it removes existing modules when not supported, such as:
+      - AESNI
+      - CLMUL
+    """
+
+    extra_cc_options = []
+    extra_macros = []
+
+    clang = compiler_is_clang()
+    gcc = compiler_is_gcc()
+
+    if has_stdint_h():
+        extra_macros.append(("HAVE_STDINT_H", None))
+
+    # Endianess
+    extra_macros.append(("PYCRYPTO_" + sys.byteorder.upper() + "_ENDIAN", None))
+
+    # System
+    system_bits = 8 * struct.calcsize("P")
+    extra_macros.append(("SYS_BITS", str(system_bits)))
+
+    # Disable any assembly in libtomcrypt files
+    extra_macros.append(("LTC_NO_ASM", None))
+
+    # Native 128-bit integer
+    if compiler_supports_uint128():
+        extra_macros.append(("HAVE_UINT128", None))
+
+    # Auto-detecting CPU features
+    cpuid_h_present = compiler_has_cpuid_h()
+    if cpuid_h_present:
+        extra_macros.append(("HAVE_CPUID_H", None))
+    intrin_h_present = compiler_has_intrin_h()
+    if intrin_h_present:
+        extra_macros.append(("HAVE_INTRIN_H", None))
+
+    # Platform-specific call for getting a block of aligned memory
+    if compiler_has_posix_memalign():
+        extra_macros.append(("HAVE_POSIX_MEMALIGN", None))
+    elif compiler_has_memalign():
+        extra_macros.append(("HAVE_MEMALIGN", None))
+
+    # SSE2
+    sse2_result = compiler_supports_sse2()
+    if sse2_result:
+        extra_cc_options.extend(sse2_result['extra_cc_options'])
+        for macro in sse2_result['extra_macros']:
+            extra_macros.append((macro, None))
+
+    # Compiler specific settings
+    if gcc:
+        # On 32-bit x86 platforms, gcc assumes the stack to be aligned to 16
+        # bytes, but the caller may actually only align it to 4 bytes, which
+        # make functions crash if they use SSE2 intrinsics.
+        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40838
+        if system_bits == 32 and support_gcc_realign():
+            extra_macros.append(("GCC_REALIGN", None))
+
+    # Module-specific options
+
+    # AESNI
+    aesni_result = (cpuid_h_present or intrin_h_present) and compiler_supports_aesni()
+    aesni_mod_name = package_root + ".Cipher._raw_aesni"
+    if aesni_result:
+        print("Compiling support for AESNI instructions")
+        aes_mods = [x for x in extensions if x.name == aesni_mod_name]
+        for x in aes_mods:
+            x.extra_compile_args.extend(aesni_result['extra_cc_options'])
+            for macro in aesni_result['extra_macros']:
+                x.define_macros.append((macro, None))
+    else:
+        print("Warning: compiler does not support AESNI instructions")
+        remove_extension(extensions, aesni_mod_name)
+
+    # CLMUL
+    clmul_result = (cpuid_h_present or intrin_h_present) and compiler_supports_clmul()
+    clmul_mod_name = package_root + ".Hash._ghash_clmul"
+    if clmul_result:
+        print("Compiling support for CLMUL instructions")
+        clmul_mods = [x for x in extensions if x.name == clmul_mod_name]
+        for x in clmul_mods:
+            x.extra_compile_args.extend(clmul_result['extra_cc_options'])
+            for macro in clmul_result['extra_macros']:
+                x.define_macros.append((macro, None))
+    else:
+        print("Warning: compiler does not support CLMUL instructions")
+        remove_extension(extensions, clmul_mod_name)
+
+    for x in extensions:
+        x.extra_compile_args.extend(extra_cc_options)
+        x.define_macros.extend(extra_macros)

+ 250 - 0
tls/pycryptoMod/lib/Crypto/Cipher/AES.py

@@ -0,0 +1,250 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/AES.py : AES
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""
+Module's constants for the modes of operation supported with AES:
+
+:var MODE_ECB: :ref:`Electronic Code Book (ECB) <ecb_mode>`
+:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>`
+:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>`
+:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>`
+:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>`
+:var MODE_OPENPGP:  :ref:`OpenPGP Mode <openpgp_mode>`
+:var MODE_CCM: :ref:`Counter with CBC-MAC (CCM) Mode <ccm_mode>`
+:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
+:var MODE_GCM: :ref:`Galois Counter Mode (GCM) <gcm_mode>`
+:var MODE_SIV: :ref:`Syntethic Initialization Vector (SIV) <siv_mode>`
+:var MODE_OCB: :ref:`Offset Code Book (OCB) <ocb_mode>`
+"""
+
+import sys
+
+from tls.Crypto.Cipher import _create_cipher
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  c_size_t, c_uint8_ptr)
+
+from tls.Crypto.Util import _cpu_features
+from tls.Crypto.Random import get_random_bytes
+
+
+_cproto = """
+        int AES_start_operation(const uint8_t key[],
+                                size_t key_len,
+                                void **pResult);
+        int AES_encrypt(const void *state,
+                        const uint8_t *in,
+                        uint8_t *out,
+                        size_t data_len);
+        int AES_decrypt(const void *state,
+                        const uint8_t *in,
+                        uint8_t *out,
+                        size_t data_len);
+        int AES_stop_operation(void *state);
+        """
+
+
+# Load portable AES
+_raw_aes_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_aes",
+                                         _cproto)
+
+# Try to load AES with AES NI instructions
+try:
+    _raw_aesni_lib = None
+    if _cpu_features.have_aes_ni():
+        _raw_aesni_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_aesni",
+                                                   _cproto.replace("AES",
+                                                                   "AESNI"))
+# _raw_aesni may not have been compiled in
+except OSError:
+    pass
+
+
+def _create_base_cipher(dict_parameters):
+    """This method instantiates and returns a handle to a low-level
+    base cipher. It will absorb named parameters in the process."""
+
+    use_aesni = dict_parameters.pop("use_aesni", True)
+
+    try:
+        key = dict_parameters.pop("key")
+    except KeyError:
+        raise TypeError("Missing 'key' parameter")
+
+    if len(key) not in key_size:
+        raise ValueError("Incorrect AES key length (%d bytes)" % len(key))
+
+    if use_aesni and _raw_aesni_lib:
+        start_operation = _raw_aesni_lib.AESNI_start_operation
+        stop_operation = _raw_aesni_lib.AESNI_stop_operation
+    else:
+        start_operation = _raw_aes_lib.AES_start_operation
+        stop_operation = _raw_aes_lib.AES_stop_operation
+
+    cipher = VoidPointer()
+    result = start_operation(c_uint8_ptr(key),
+                             c_size_t(len(key)),
+                             cipher.address_of())
+    if result:
+        raise ValueError("Error %X while instantiating the AES cipher"
+                         % result)
+    return SmartPointer(cipher.get(), stop_operation)
+
+
+def _derive_Poly1305_key_pair(key, nonce):
+    """Derive a tuple (r, s, nonce) for a Poly1305 MAC.
+    
+    If nonce is ``None``, a new 16-byte nonce is generated.
+    """
+
+    if len(key) != 32:
+        raise ValueError("Poly1305 with AES requires a 32-byte key")
+
+    if nonce is None:
+        nonce = get_random_bytes(16)
+    elif len(nonce) != 16:
+        raise ValueError("Poly1305 with AES requires a 16-byte nonce")
+
+    s = new(key[:16], MODE_ECB).encrypt(nonce)
+    return key[16:], s, nonce
+
+
+def new(key, mode, *args, **kwargs):
+    """Create a new AES cipher.
+
+    :param key:
+        The secret key to use in the symmetric cipher.
+
+        It must be 16, 24 or 32 bytes long (respectively for *AES-128*,
+        *AES-192* or *AES-256*).
+
+        For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes.
+    :type key: bytes/bytearray/memoryview
+
+    :param mode:
+        The chaining mode to use for encryption or decryption.
+        If in doubt, use ``MODE_EAX``.
+    :type mode: One of the supported ``MODE_*`` constants
+
+    :Keyword Arguments:
+        *   **iv** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
+            and ``MODE_OPENPGP`` modes).
+
+            The initialization vector to use for encryption or decryption.
+
+            For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long.
+
+            For ``MODE_OPENPGP`` mode only,
+            it must be 16 bytes long for encryption
+            and 18 bytes for decryption (in the latter case, it is
+            actually the *encrypted* IV which was prefixed to the ciphertext).
+
+            If not provided, a random byte string is generated (you must then
+            read its value with the :attr:`iv` attribute).
+
+        *   **nonce** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``,
+            ``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``).
+
+            A value that must never be reused for any other encryption done
+            with this key (except possibly for ``MODE_SIV``, see below).
+
+            For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no
+            restrictions on its length (recommended: **16** bytes).
+
+            For ``MODE_CCM``, its length must be in the range **[7..13]**.
+            Bear in mind that with CCM there is a trade-off between nonce
+            length and maximum message size. Recommendation: **11** bytes.
+
+            For ``MODE_OCB``, its length must be in the range **[1..15]**
+            (recommended: **15**).
+
+            For ``MODE_CTR``, its length must be in the range **[0..15]**
+            (recommended: **8**).
+            
+            For ``MODE_SIV``, the nonce is optional, if it is not specified,
+            then no nonce is being used, which renders the encryption
+            deterministic.
+
+            If not provided, for modes other than ``MODE_SIV```, a random
+            byte string of the recommended length is used (you must then
+            read its value with the :attr:`nonce` attribute).
+
+        *   **segment_size** (*integer*) --
+            (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
+            are segmented in. It must be a multiple of 8.
+            If not specified, it will be assumed to be 8.
+
+        *   **mac_len** : (*integer*) --
+            (Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``)
+            Length of the authentication tag, in bytes.
+
+            It must be even and in the range **[4..16]**.
+            The recommended value (and the default, if not specified) is **16**.
+
+        *   **msg_len** : (*integer*) --
+            (Only ``MODE_CCM``). Length of the message to (de)cipher.
+            If not specified, ``encrypt`` must be called with the entire message.
+            Similarly, ``decrypt`` can only be called once.
+
+        *   **assoc_len** : (*integer*) --
+            (Only ``MODE_CCM``). Length of the associated data.
+            If not specified, all associated data is buffered internally,
+            which may represent a problem for very large messages.
+
+        *   **initial_value** : (*integer* or *bytes/bytearray/memoryview*) --
+            (Only ``MODE_CTR``).
+            The initial value for the counter. If not present, the cipher will
+            start counting from 0. The value is incremented by one for each block.
+            The counter number is encoded in big endian mode.
+
+        *   **counter** : (*object*) --
+            Instance of ``Crypto.Util.Counter``, which allows full customization
+            of the counter block. This parameter is incompatible to both ``nonce``
+            and ``initial_value``.
+
+        *   **use_aesni** : (*boolean*) --
+            Use Intel AES-NI hardware extensions (default: use if available).
+
+    :Return: an AES object, of the applicable mode.
+    """
+
+    kwargs["add_aes_modes"] = True
+    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
+
+
+MODE_ECB = 1
+MODE_CBC = 2
+MODE_CFB = 3
+MODE_OFB = 5
+MODE_CTR = 6
+MODE_OPENPGP = 7
+MODE_CCM = 8
+MODE_EAX = 9
+MODE_SIV = 10
+MODE_GCM = 11
+MODE_OCB = 12
+
+# Size of a data block (in bytes)
+block_size = 16
+# Size of a key (in bytes)
+key_size = (16, 24, 32)

+ 47 - 0
tls/pycryptoMod/lib/Crypto/Cipher/AES.pyi

@@ -0,0 +1,47 @@
+from typing import Union, Tuple, Optional, Dict
+
+from tls.Crypto.Cipher._mode_ecb import EcbMode
+from tls.Crypto.Cipher._mode_cbc import CbcMode
+from tls.Crypto.Cipher._mode_cfb import CfbMode
+from tls.Crypto.Cipher._mode_ofb import OfbMode
+from tls.Crypto.Cipher._mode_ctr import CtrMode
+from tls.Crypto.Cipher._mode_openpgp import OpenPgpMode
+from tls.Crypto.Cipher._mode_ccm import CcmMode
+from tls.Crypto.Cipher._mode_eax import EaxMode
+from tls.Crypto.Cipher._mode_gcm import GcmMode
+from tls.Crypto.Cipher._mode_siv import SivMode
+from tls.Crypto.Cipher._mode_ocb import OcbMode
+
+AESMode = int
+
+MODE_ECB: AESMode
+MODE_CBC: AESMode
+MODE_CFB: AESMode
+MODE_OFB: AESMode
+MODE_CTR: AESMode
+MODE_OPENPGP: AESMode
+MODE_CCM: AESMode
+MODE_EAX: AESMode
+MODE_GCM: AESMode
+MODE_SIV: AESMode
+MODE_OCB: AESMode
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+        mode: AESMode,
+        iv : Buffer = ...,
+        IV : Buffer = ...,
+        nonce : Buffer = ...,
+        segment_size : int = ...,
+        mac_len : int = ...,
+        assoc_len : int = ...,
+        initial_value : Union[int, Buffer] = ...,
+        counter : Dict = ...,
+        use_aesni : bool = ...) -> \
+        Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode,
+              OpenPgpMode, CcmMode, EaxMode, GcmMode,
+              SivMode, OcbMode]: ...
+
+block_size: int
+key_size: Tuple[int, int, int]

+ 175 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ARC2.py

@@ -0,0 +1,175 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/ARC2.py : ARC2.py
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""
+Module's constants for the modes of operation supported with ARC2:
+
+:var MODE_ECB: :ref:`Electronic Code Book (ECB) <ecb_mode>`
+:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>`
+:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>`
+:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>`
+:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>`
+:var MODE_OPENPGP:  :ref:`OpenPGP Mode <openpgp_mode>`
+:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
+"""
+
+import sys
+
+from tls.Crypto.Cipher import _create_cipher
+from tls.Crypto.Util.py3compat import byte_string
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  c_size_t, c_uint8_ptr)
+
+_raw_arc2_lib = load_pycryptodome_raw_lib(
+                        "Crypto.Cipher._raw_arc2",
+                        """
+                        int ARC2_start_operation(const uint8_t key[],
+                                                 size_t key_len,
+                                                 size_t effective_key_len,
+                                                 void **pResult);
+                        int ARC2_encrypt(const void *state,
+                                         const uint8_t *in,
+                                         uint8_t *out,
+                                         size_t data_len);
+                        int ARC2_decrypt(const void *state,
+                                         const uint8_t *in,
+                                         uint8_t *out,
+                                         size_t data_len);
+                        int ARC2_stop_operation(void *state);
+                        """
+                        )
+
+
+def _create_base_cipher(dict_parameters):
+    """This method instantiates and returns a handle to a low-level
+    base cipher. It will absorb named parameters in the process."""
+
+    try:
+        key = dict_parameters.pop("key")
+    except KeyError:
+        raise TypeError("Missing 'key' parameter")
+
+    effective_keylen = dict_parameters.pop("effective_keylen", 1024)
+
+    if len(key) not in key_size:
+        raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key))
+
+    if not (40 <= effective_keylen <= 1024):
+        raise ValueError("'effective_key_len' must be at least 40 and no larger than 1024 "
+                         "(not %d)" % effective_keylen)
+
+    start_operation = _raw_arc2_lib.ARC2_start_operation
+    stop_operation = _raw_arc2_lib.ARC2_stop_operation
+
+    cipher = VoidPointer()
+    result = start_operation(c_uint8_ptr(key),
+                             c_size_t(len(key)),
+                             c_size_t(effective_keylen),
+                             cipher.address_of())
+    if result:
+        raise ValueError("Error %X while instantiating the ARC2 cipher"
+                         % result)
+
+    return SmartPointer(cipher.get(), stop_operation)
+
+
+def new(key, mode, *args, **kwargs):
+    """Create a new RC2 cipher.
+
+    :param key:
+        The secret key to use in the symmetric cipher.
+        Its length can vary from 5 to 128 bytes; the actual search space
+        (and the cipher strength) can be reduced with the ``effective_keylen`` parameter.
+    :type key: bytes, bytearray, memoryview
+
+    :param mode:
+        The chaining mode to use for encryption or decryption.
+    :type mode: One of the supported ``MODE_*`` constants
+
+    :Keyword Arguments:
+        *   **iv** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
+            and ``MODE_OPENPGP`` modes).
+
+            The initialization vector to use for encryption or decryption.
+
+            For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long.
+
+            For ``MODE_OPENPGP`` mode only,
+            it must be 8 bytes long for encryption
+            and 10 bytes for decryption (in the latter case, it is
+            actually the *encrypted* IV which was prefixed to the ciphertext).
+
+            If not provided, a random byte string is generated (you must then
+            read its value with the :attr:`iv` attribute).
+
+        *   **nonce** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_EAX`` and ``MODE_CTR``).
+
+            A value that must never be reused for any other encryption done
+            with this key.
+
+            For ``MODE_EAX`` there are no
+            restrictions on its length (recommended: **16** bytes).
+
+            For ``MODE_CTR``, its length must be in the range **[0..7]**.
+
+            If not provided for ``MODE_EAX``, a random byte string is generated (you
+            can read it back via the ``nonce`` attribute).
+
+        *   **effective_keylen** (*integer*) --
+            Optional. Maximum strength in bits of the actual key used by the ARC2 algorithm.
+            If the supplied ``key`` parameter is longer (in bits) of the value specified
+            here, it will be weakened to match it.
+            If not specified, no limitation is applied.
+
+        *   **segment_size** (*integer*) --
+            (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
+            are segmented in. It must be a multiple of 8.
+            If not specified, it will be assumed to be 8.
+
+        *   **mac_len** : (*integer*) --
+            (Only ``MODE_EAX``)
+            Length of the authentication tag, in bytes.
+            It must be no longer than 8 (default).
+
+        *   **initial_value** : (*integer*) --
+            (Only ``MODE_CTR``). The initial value for the counter within
+            the counter block. By default it is **0**.
+
+    :Return: an ARC2 object, of the applicable mode.
+    """
+
+    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
+
+MODE_ECB = 1
+MODE_CBC = 2
+MODE_CFB = 3
+MODE_OFB = 5
+MODE_CTR = 6
+MODE_OPENPGP = 7
+MODE_EAX = 9
+
+# Size of a data block (in bytes)
+block_size = 8
+# Size of a key (in bytes)
+key_size = range(5, 128 + 1)

+ 35 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ARC2.pyi

@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+from tls.Crypto.Cipher._mode_ecb import EcbMode
+from tls.Crypto.Cipher._mode_cbc import CbcMode
+from tls.Crypto.Cipher._mode_cfb import CfbMode
+from tls.Crypto.Cipher._mode_ofb import OfbMode
+from tls.Crypto.Cipher._mode_ctr import CtrMode
+from tls.Crypto.Cipher._mode_openpgp import OpenPgpMode
+from tls.Crypto.Cipher._mode_eax import EaxMode
+
+ARC2Mode = int
+
+MODE_ECB: ARC2Mode
+MODE_CBC: ARC2Mode
+MODE_CFB: ARC2Mode
+MODE_OFB: ARC2Mode
+MODE_CTR: ARC2Mode
+MODE_OPENPGP: ARC2Mode
+MODE_EAX: ARC2Mode
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+        mode: ARC2Mode,
+        iv : Buffer = ...,
+        IV : Buffer = ...,
+        nonce : Buffer = ...,
+        segment_size : int = ...,
+        mac_len : int = ...,
+        initial_value : Union[int, Buffer] = ...,
+        counter : Dict = ...) -> \
+        Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: Iterable[int]

+ 137 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ARC4.py

@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/ARC4.py : ARC4
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import b
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+                                  create_string_buffer, get_raw_buffer,
+                                  SmartPointer, c_size_t, c_uint8_ptr)
+
+
+_raw_arc4_lib = load_pycryptodome_raw_lib("Crypto.Cipher._ARC4", """
+                    int ARC4_stream_encrypt(void *rc4State, const uint8_t in[],
+                                            uint8_t out[], size_t len);
+                    int ARC4_stream_init(uint8_t *key, size_t keylen,
+                                         void **pRc4State);
+                    int ARC4_stream_destroy(void *rc4State);
+                    """)
+
+
+class ARC4Cipher:
+    """ARC4 cipher object. Do not create it directly. Use
+    :func:`Crypto.Cipher.ARC4.new` instead.
+    """
+
+    def __init__(self, key, *args, **kwargs):
+        """Initialize an ARC4 cipher object
+
+        See also `new()` at the module level."""
+
+        if len(args) > 0:
+            ndrop = args[0]
+            args = args[1:]
+        else:
+            ndrop = kwargs.pop('drop', 0)
+
+        if len(key) not in key_size:
+            raise ValueError("Incorrect ARC4 key length (%d bytes)" %
+                             len(key))
+
+        self._state = VoidPointer()
+        result = _raw_arc4_lib.ARC4_stream_init(c_uint8_ptr(key),
+                                                c_size_t(len(key)),
+                                                self._state.address_of())
+        if result != 0:
+            raise ValueError("Error %d while creating the ARC4 cipher"
+                             % result)
+        self._state = SmartPointer(self._state.get(),
+                                   _raw_arc4_lib.ARC4_stream_destroy)
+
+        if ndrop > 0:
+            # This is OK even if the cipher is used for decryption,
+            # since encrypt and decrypt are actually the same thing
+            # with ARC4.
+            self.encrypt(b'\x00' * ndrop)
+
+        self.block_size = 1
+        self.key_size = len(key)
+
+    def encrypt(self, plaintext):
+        """Encrypt a piece of data.
+
+        :param plaintext: The data to encrypt, of any size.
+        :type plaintext: bytes, bytearray, memoryview
+        :returns: the encrypted byte string, of equal length as the
+          plaintext.
+        """
+
+        ciphertext = create_string_buffer(len(plaintext))
+        result = _raw_arc4_lib.ARC4_stream_encrypt(self._state.get(),
+                                                   c_uint8_ptr(plaintext),
+                                                   ciphertext,
+                                                   c_size_t(len(plaintext)))
+        if result:
+            raise ValueError("Error %d while encrypting with RC4" % result)
+        return get_raw_buffer(ciphertext)
+
+    def decrypt(self, ciphertext):
+        """Decrypt a piece of data.
+
+        :param ciphertext: The data to decrypt, of any size.
+        :type ciphertext: bytes, bytearray, memoryview
+        :returns: the decrypted byte string, of equal length as the
+          ciphertext.
+        """
+
+        try:
+            return self.encrypt(ciphertext)
+        except ValueError as e:
+            raise ValueError(str(e).replace("enc", "dec"))
+
+
+def new(key, *args, **kwargs):
+    """Create a new ARC4 cipher.
+
+    :param key:
+        The secret key to use in the symmetric cipher.
+        Its length must be in the range ``[5..256]``.
+        The recommended length is 16 bytes.
+    :type key: bytes, bytearray, memoryview
+
+    :Keyword Arguments:
+        *   *drop* (``integer``) --
+            The amount of bytes to discard from the initial part of the keystream.
+            In fact, such part has been found to be distinguishable from random
+            data (while it shouldn't) and also correlated to key.
+
+            The recommended value is 3072_ bytes. The default value is 0.
+
+    :Return: an `ARC4Cipher` object
+
+    .. _3072: http://eprint.iacr.org/2002/067.pdf
+    """
+    return ARC4Cipher(key, *args, **kwargs)
+
+# Size of a data block (in bytes)
+block_size = 1
+# Size of a key (in bytes)
+key_size = range(5, 256+1)

+ 16 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ARC4.pyi

@@ -0,0 +1,16 @@
+from typing import Any, Union, Iterable
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class ARC4Cipher:
+    block_size: int
+    key_size: int
+
+    def __init__(self, key: Buffer, *args: Any, **kwargs: Any) -> None: ...
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    def decrypt(self, ciphertext: Buffer) -> bytes: ...
+
+def new(key: Buffer, drop : int = ...) -> ARC4Cipher: ...
+
+block_size: int
+key_size: Iterable[int]

+ 159 - 0
tls/pycryptoMod/lib/Crypto/Cipher/Blowfish.py

@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/Blowfish.py : Blowfish
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""
+Module's constants for the modes of operation supported with Blowfish:
+
+:var MODE_ECB: :ref:`Electronic Code Book (ECB) <ecb_mode>`
+:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>`
+:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>`
+:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>`
+:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>`
+:var MODE_OPENPGP:  :ref:`OpenPGP Mode <openpgp_mode>`
+:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
+"""
+
+import sys
+
+from tls.Crypto.Cipher import _create_cipher
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_blowfish_lib = load_pycryptodome_raw_lib(
+        "Crypto.Cipher._raw_blowfish",
+        """
+        int Blowfish_start_operation(const uint8_t key[],
+                                     size_t key_len,
+                                     void **pResult);
+        int Blowfish_encrypt(const void *state,
+                             const uint8_t *in,
+                             uint8_t *out,
+                             size_t data_len);
+        int Blowfish_decrypt(const void *state,
+                             const uint8_t *in,
+                             uint8_t *out,
+                             size_t data_len);
+        int Blowfish_stop_operation(void *state);
+        """
+        )
+
+
+def _create_base_cipher(dict_parameters):
+    """This method instantiates and returns a smart pointer to
+    a low-level base cipher. It will absorb named parameters in
+    the process."""
+
+    try:
+        key = dict_parameters.pop("key")
+    except KeyError:
+        raise TypeError("Missing 'key' parameter")
+
+    if len(key) not in key_size:
+        raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key))
+
+    start_operation = _raw_blowfish_lib.Blowfish_start_operation
+    stop_operation = _raw_blowfish_lib.Blowfish_stop_operation
+
+    void_p = VoidPointer()
+    result = start_operation(c_uint8_ptr(key),
+                             c_size_t(len(key)),
+                             void_p.address_of())
+    if result:
+        raise ValueError("Error %X while instantiating the Blowfish cipher"
+                         % result)
+    return SmartPointer(void_p.get(), stop_operation)
+
+
+def new(key, mode, *args, **kwargs):
+    """Create a new Blowfish cipher
+
+    :param key:
+        The secret key to use in the symmetric cipher.
+        Its length can vary from 5 to 56 bytes.
+    :type key: bytes, bytearray, memoryview
+
+    :param mode:
+        The chaining mode to use for encryption or decryption.
+    :type mode: One of the supported ``MODE_*`` constants
+
+    :Keyword Arguments:
+        *   **iv** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
+            and ``MODE_OPENPGP`` modes).
+
+            The initialization vector to use for encryption or decryption.
+
+            For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long.
+
+            For ``MODE_OPENPGP`` mode only,
+            it must be 8 bytes long for encryption
+            and 10 bytes for decryption (in the latter case, it is
+            actually the *encrypted* IV which was prefixed to the ciphertext).
+
+            If not provided, a random byte string is generated (you must then
+            read its value with the :attr:`iv` attribute).
+
+        *   **nonce** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_EAX`` and ``MODE_CTR``).
+
+            A value that must never be reused for any other encryption done
+            with this key.
+
+            For ``MODE_EAX`` there are no
+            restrictions on its length (recommended: **16** bytes).
+
+            For ``MODE_CTR``, its length must be in the range **[0..7]**.
+
+            If not provided for ``MODE_EAX``, a random byte string is generated (you
+            can read it back via the ``nonce`` attribute).
+
+        *   **segment_size** (*integer*) --
+            (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
+            are segmented in. It must be a multiple of 8.
+            If not specified, it will be assumed to be 8.
+
+        *   **mac_len** : (*integer*) --
+            (Only ``MODE_EAX``)
+            Length of the authentication tag, in bytes.
+            It must be no longer than 8 (default).
+
+        *   **initial_value** : (*integer*) --
+            (Only ``MODE_CTR``). The initial value for the counter within
+            the counter block. By default it is **0**.
+
+    :Return: a Blowfish object, of the applicable mode.
+    """
+
+    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
+
+MODE_ECB = 1
+MODE_CBC = 2
+MODE_CFB = 3
+MODE_OFB = 5
+MODE_CTR = 6
+MODE_OPENPGP = 7
+MODE_EAX = 9
+
+# Size of a data block (in bytes)
+block_size = 8
+# Size of a key (in bytes)
+key_size = range(4, 56 + 1)

+ 35 - 0
tls/pycryptoMod/lib/Crypto/Cipher/Blowfish.pyi

@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+from tls.Crypto.Cipher._mode_ecb import EcbMode
+from tls.Crypto.Cipher._mode_cbc import CbcMode
+from tls.Crypto.Cipher._mode_cfb import CfbMode
+from tls.Crypto.Cipher._mode_ofb import OfbMode
+from tls.Crypto.Cipher._mode_ctr import CtrMode
+from tls.Crypto.Cipher._mode_openpgp import OpenPgpMode
+from tls.Crypto.Cipher._mode_eax import EaxMode
+
+BlowfishMode = int
+
+MODE_ECB: BlowfishMode
+MODE_CBC: BlowfishMode
+MODE_CFB: BlowfishMode
+MODE_OFB: BlowfishMode
+MODE_CTR: BlowfishMode
+MODE_OPENPGP: BlowfishMode
+MODE_EAX: BlowfishMode
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+        mode: BlowfishMode,
+        iv : Buffer = ...,
+        IV : Buffer = ...,
+        nonce : Buffer = ...,
+        segment_size : int = ...,
+        mac_len : int = ...,
+        initial_value : Union[int, Buffer] = ...,
+        counter : Dict = ...) -> \
+        Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: Iterable[int]

+ 159 - 0
tls/pycryptoMod/lib/Crypto/Cipher/CAST.py

@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/CAST.py : CAST
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""
+Module's constants for the modes of operation supported with CAST:
+
+:var MODE_ECB: :ref:`Electronic Code Book (ECB) <ecb_mode>`
+:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>`
+:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>`
+:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>`
+:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>`
+:var MODE_OPENPGP:  :ref:`OpenPGP Mode <openpgp_mode>`
+:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
+"""
+
+import sys
+
+from tls.Crypto.Cipher import _create_cipher
+from tls.Crypto.Util.py3compat import byte_string
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  c_size_t, c_uint8_ptr)
+
+_raw_cast_lib = load_pycryptodome_raw_lib(
+                    "Crypto.Cipher._raw_cast",
+                    """
+                    int CAST_start_operation(const uint8_t key[],
+                                             size_t key_len,
+                                             void **pResult);
+                    int CAST_encrypt(const void *state,
+                                     const uint8_t *in,
+                                     uint8_t *out,
+                                     size_t data_len);
+                    int CAST_decrypt(const void *state,
+                                     const uint8_t *in,
+                                     uint8_t *out,
+                                     size_t data_len);
+                    int CAST_stop_operation(void *state);
+                    """)
+
+
+def _create_base_cipher(dict_parameters):
+    """This method instantiates and returns a handle to a low-level
+    base cipher. It will absorb named parameters in the process."""
+
+    try:
+        key = dict_parameters.pop("key")
+    except KeyError:
+        raise TypeError("Missing 'key' parameter")
+
+    if len(key) not in key_size:
+        raise ValueError("Incorrect CAST key length (%d bytes)" % len(key))
+
+    start_operation = _raw_cast_lib.CAST_start_operation
+    stop_operation = _raw_cast_lib.CAST_stop_operation
+
+    cipher = VoidPointer()
+    result = start_operation(c_uint8_ptr(key),
+                             c_size_t(len(key)),
+                             cipher.address_of())
+    if result:
+        raise ValueError("Error %X while instantiating the CAST cipher"
+                         % result)
+
+    return SmartPointer(cipher.get(), stop_operation)
+
+
+def new(key, mode, *args, **kwargs):
+    """Create a new CAST cipher
+
+    :param key:
+        The secret key to use in the symmetric cipher.
+        Its length can vary from 5 to 16 bytes.
+    :type key: bytes, bytearray, memoryview
+
+    :param mode:
+        The chaining mode to use for encryption or decryption.
+    :type mode: One of the supported ``MODE_*`` constants
+
+    :Keyword Arguments:
+        *   **iv** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
+            and ``MODE_OPENPGP`` modes).
+
+            The initialization vector to use for encryption or decryption.
+
+            For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long.
+
+            For ``MODE_OPENPGP`` mode only,
+            it must be 8 bytes long for encryption
+            and 10 bytes for decryption (in the latter case, it is
+            actually the *encrypted* IV which was prefixed to the ciphertext).
+
+            If not provided, a random byte string is generated (you must then
+            read its value with the :attr:`iv` attribute).
+
+        *   **nonce** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_EAX`` and ``MODE_CTR``).
+
+            A value that must never be reused for any other encryption done
+            with this key.
+
+            For ``MODE_EAX`` there are no
+            restrictions on its length (recommended: **16** bytes).
+
+            For ``MODE_CTR``, its length must be in the range **[0..7]**.
+
+            If not provided for ``MODE_EAX``, a random byte string is generated (you
+            can read it back via the ``nonce`` attribute).
+
+        *   **segment_size** (*integer*) --
+            (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
+            are segmented in. It must be a multiple of 8.
+            If not specified, it will be assumed to be 8.
+
+        *   **mac_len** : (*integer*) --
+            (Only ``MODE_EAX``)
+            Length of the authentication tag, in bytes.
+            It must be no longer than 8 (default).
+
+        *   **initial_value** : (*integer*) --
+            (Only ``MODE_CTR``). The initial value for the counter within
+            the counter block. By default it is **0**.
+
+    :Return: a CAST object, of the applicable mode.
+    """
+
+    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
+
+MODE_ECB = 1
+MODE_CBC = 2
+MODE_CFB = 3
+MODE_OFB = 5
+MODE_CTR = 6
+MODE_OPENPGP = 7
+MODE_EAX = 9
+
+# Size of a data block (in bytes)
+block_size = 8
+# Size of a key (in bytes)
+key_size = range(5, 16 + 1)

+ 35 - 0
tls/pycryptoMod/lib/Crypto/Cipher/CAST.pyi

@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+from tls.Crypto.Cipher._mode_ecb import EcbMode
+from tls.Crypto.Cipher._mode_cbc import CbcMode
+from tls.Crypto.Cipher._mode_cfb import CfbMode
+from tls.Crypto.Cipher._mode_ofb import OfbMode
+from tls.Crypto.Cipher._mode_ctr import CtrMode
+from tls.Crypto.Cipher._mode_openpgp import OpenPgpMode
+from tls.Crypto.Cipher._mode_eax import EaxMode
+
+CASTMode = int
+
+MODE_ECB: CASTMode
+MODE_CBC: CASTMode
+MODE_CFB: CASTMode
+MODE_OFB: CASTMode
+MODE_CTR: CASTMode
+MODE_OPENPGP: CASTMode
+MODE_EAX: CASTMode
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+        mode: CASTMode,
+        iv : Buffer = ...,
+        IV : Buffer = ...,
+        nonce : Buffer = ...,
+        segment_size : int = ...,
+        mac_len : int = ...,
+        initial_value : Union[int, Buffer] = ...,
+        counter : Dict = ...) -> \
+        Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size : Iterable[int]

+ 286 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20.py

@@ -0,0 +1,286 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from tls.Crypto.Random import get_random_bytes
+
+from tls.Crypto.Util.py3compat import _copy_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  create_string_buffer,
+                                  get_raw_buffer, VoidPointer,
+                                  SmartPointer, c_size_t,
+                                  c_uint8_ptr, c_ulong,
+                                  is_writeable_buffer)
+
+_raw_chacha20_lib = load_pycryptodome_raw_lib("Crypto.Cipher._chacha20",
+                    """
+                    int chacha20_init(void **pState,
+                                      const uint8_t *key,
+                                      size_t keySize,
+                                      const uint8_t *nonce,
+                                      size_t nonceSize);
+
+                    int chacha20_destroy(void *state);
+
+                    int chacha20_encrypt(void *state,
+                                         const uint8_t in[],
+                                         uint8_t out[],
+                                         size_t len);
+
+                    int chacha20_seek(void *state,
+                                      unsigned long block_high,
+                                      unsigned long block_low,
+                                      unsigned offset);
+                    int hchacha20(  const uint8_t key[32],
+                                    const uint8_t nonce16[16],
+                                    uint8_t subkey[32]);
+                    """)
+
+
+def _HChaCha20(key, nonce):
+
+    assert(len(key) == 32)
+    assert(len(nonce) == 16)
+
+    subkey = bytearray(32)
+    result = _raw_chacha20_lib.hchacha20(
+                c_uint8_ptr(key),
+                c_uint8_ptr(nonce),
+                c_uint8_ptr(subkey))
+    if result:
+        raise ValueError("Error %d when deriving subkey with HChaCha20" % result)
+
+    return subkey
+
+
+class ChaCha20Cipher(object):
+    """ChaCha20 (or XChaCha20) cipher object.
+    Do not create it directly. Use :py:func:`new` instead.
+
+    :var nonce: The nonce with length 8, 12 or 24 bytes
+    :vartype nonce: bytes
+    """
+
+    block_size = 1
+
+    def __init__(self, key, nonce):
+        """Initialize a ChaCha20/XChaCha20 cipher object
+
+        See also `new()` at the module level."""
+
+        # XChaCha20 requires a key derivation with HChaCha20
+        # See 2.3 in https://tools.ietf.org/html/draft-arciszewski-xchacha-03
+        if len(nonce) == 24:
+            key = _HChaCha20(key, nonce[:16])
+            nonce = b'\x00' * 4 + nonce[16:]
+            self._name = "XChaCha20"
+        else:
+            self._name = "ChaCha20"
+
+        self.nonce = _copy_bytes(None, None, nonce)
+
+        self._next = ( self.encrypt, self.decrypt )
+
+        self._state = VoidPointer()
+        result = _raw_chacha20_lib.chacha20_init(
+                        self._state.address_of(),
+                        c_uint8_ptr(key),
+                        c_size_t(len(key)),
+                        self.nonce,
+                        c_size_t(len(nonce)))
+        if result:
+            raise ValueError("Error %d instantiating a %s cipher" % (result,
+                                                                     self._name))
+        self._state = SmartPointer(self._state.get(),
+                                   _raw_chacha20_lib.chacha20_destroy)
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt a piece of data.
+
+        Args:
+          plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size.
+        Keyword Args:
+          output(bytes/bytearray/memoryview): The location where the ciphertext
+            is written to. If ``None``, the ciphertext is returned.
+        Returns:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("Cipher object can only be used for decryption")
+        self._next = ( self.encrypt, )
+        return self._encrypt(plaintext, output)
+
+    def _encrypt(self, plaintext, output):
+        """Encrypt without FSM checks"""
+
+        if output is None:
+            ciphertext = create_string_buffer(len(plaintext))
+        else:
+            ciphertext = output
+
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+
+            if len(plaintext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = _raw_chacha20_lib.chacha20_encrypt(
+                                         self._state.get(),
+                                         c_uint8_ptr(plaintext),
+                                         c_uint8_ptr(ciphertext),
+                                         c_size_t(len(plaintext)))
+        if result:
+            raise ValueError("Error %d while encrypting with %s" % (result, self._name))
+
+        if output is None:
+            return get_raw_buffer(ciphertext)
+        else:
+            return None
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt a piece of data.
+
+        Args:
+          ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size.
+        Keyword Args:
+          output(bytes/bytearray/memoryview): The location where the plaintext
+            is written to. If ``None``, the plaintext is returned.
+        Returns:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("Cipher object can only be used for encryption")
+        self._next = ( self.decrypt, )
+
+        try:
+            return self._encrypt(ciphertext, output)
+        except ValueError as e:
+            raise ValueError(str(e).replace("enc", "dec"))
+
+    def seek(self, position):
+        """Seek to a certain position in the key stream.
+
+        Args:
+          position (integer):
+            The absolute position within the key stream, in bytes.
+        """
+
+        position, offset = divmod(position, 64)
+        block_low = position & 0xFFFFFFFF
+        block_high = position >> 32
+
+        result = _raw_chacha20_lib.chacha20_seek(
+                                                 self._state.get(),
+                                                 c_ulong(block_high),
+                                                 c_ulong(block_low),
+                                                 offset
+                                                 )
+        if result:
+            raise ValueError("Error %d while seeking with %s" % (result, self._name))
+
+
+def _derive_Poly1305_key_pair(key, nonce):
+    """Derive a tuple (r, s, nonce) for a Poly1305 MAC.
+
+    If nonce is ``None``, a new 12-byte nonce is generated.
+    """
+
+    if len(key) != 32:
+        raise ValueError("Poly1305 with ChaCha20 requires a 32-byte key")
+
+    if nonce is None:
+        padded_nonce = nonce = get_random_bytes(12)
+    elif len(nonce) == 8:
+        # See RFC7538, 2.6: [...] ChaCha20 as specified here requires a 96-bit
+        # nonce.  So if the provided nonce is only 64-bit, then the first 32
+        # bits of the nonce will be set to a constant number.
+        # This will usually be zero, but for protocols with multiple senders it may be
+        # different for each sender, but should be the same for all
+        # invocations of the function with the same key by a particular
+        # sender.
+        padded_nonce = b'\x00\x00\x00\x00' + nonce
+    elif len(nonce) == 12:
+        padded_nonce = nonce
+    else:
+        raise ValueError("Poly1305 with ChaCha20 requires an 8- or 12-byte nonce")
+
+    rs = new(key=key, nonce=padded_nonce).encrypt(b'\x00' * 32)
+    return rs[:16], rs[16:], nonce
+
+
+def new(**kwargs):
+    """Create a new ChaCha20 or XChaCha20 cipher
+
+    Keyword Args:
+        key (bytes/bytearray/memoryview): The secret key to use.
+            It must be 32 bytes long.
+        nonce (bytes/bytearray/memoryview): A mandatory value that
+            must never be reused for any other encryption
+            done with this key.
+
+            For ChaCha20, it must be 8 or 12 bytes long.
+
+            For XChaCha20, it must be 24 bytes long.
+
+            If not provided, 8 bytes will be randomly generated
+            (you can find them back in the ``nonce`` attribute).
+
+    :Return: a :class:`Crypto.Cipher.ChaCha20.ChaCha20Cipher` object
+    """
+
+    try:
+        key = kwargs.pop("key")
+    except KeyError as e:
+        raise TypeError("Missing parameter %s" % e)
+
+    nonce = kwargs.pop("nonce", None)
+    if nonce is None:
+        nonce = get_random_bytes(8)
+
+    if len(key) != 32:
+        raise ValueError("ChaCha20/XChaCha20 key must be 32 bytes long")
+
+    if len(nonce) not in (8, 12, 24):
+        raise ValueError("Nonce must be 8/12 bytes(ChaCha20) or 24 bytes (XChaCha20)")
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return ChaCha20Cipher(key, nonce)
+
+# Size of a data block (in bytes)
+block_size = 1
+
+# Size of a key (in bytes)
+key_size = 32

+ 25 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20.pyi

@@ -0,0 +1,25 @@
+from typing import Union, overload
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def _HChaCha20(key: Buffer, nonce: Buffer) -> bytearray: ...
+
+class ChaCha20Cipher:
+    block_size: int
+    nonce: bytes
+
+    def __init__(self, key: Buffer, nonce: Buffer) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    def seek(self, position: int) -> None: ...
+
+def new(key: Buffer, nonce: Buffer = ...) -> ChaCha20Cipher: ...
+
+block_size: int
+key_size: int

+ 336 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20_Poly1305.py

@@ -0,0 +1,336 @@
+# ===================================================================
+#
+# Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from binascii import unhexlify
+
+from tls.Crypto.Cipher import ChaCha20
+from tls.Crypto.Cipher.ChaCha20 import _HChaCha20
+from tls.Crypto.Hash import Poly1305, BLAKE2s
+
+from tls.Crypto.Random import get_random_bytes
+
+from tls.Crypto.Util.number import long_to_bytes
+from tls.Crypto.Util.py3compat import _copy_bytes, bord
+from tls.Crypto.Util._raw_api import is_buffer
+
+
+def _enum(**enums):
+    return type('Enum', (), enums)
+
+
+_CipherStatus = _enum(PROCESSING_AUTH_DATA=1,
+                      PROCESSING_CIPHERTEXT=2,
+                      PROCESSING_DONE=3)
+
+
+class ChaCha20Poly1305Cipher(object):
+    """ChaCha20-Poly1305 and XChaCha20-Poly1305 cipher object.
+    Do not create it directly. Use :py:func:`new` instead.
+
+    :var nonce: The nonce with length 8, 12 or 24 bytes
+    :vartype nonce: byte string
+    """
+
+    def __init__(self, key, nonce):
+        """Initialize a ChaCha20-Poly1305 AEAD cipher object
+
+        See also `new()` at the module level."""
+
+        self.nonce = _copy_bytes(None, None, nonce)
+
+        self._next = (self.update, self.encrypt, self.decrypt, self.digest,
+                      self.verify)
+
+        self._authenticator = Poly1305.new(key=key, nonce=nonce, cipher=ChaCha20)
+
+        self._cipher = ChaCha20.new(key=key, nonce=nonce)
+        self._cipher.seek(64)   # Block counter starts at 1
+
+        self._len_aad = 0
+        self._len_ct = 0
+        self._mac_tag = None
+        self._status = _CipherStatus.PROCESSING_AUTH_DATA
+
+    def update(self, data):
+        """Protect the associated data.
+
+        Associated data (also known as *additional authenticated data* - AAD)
+        is the piece of the message that must stay in the clear, while
+        still allowing the receiver to verify its integrity.
+        An example is packet headers.
+
+        The associated data (possibly split into multiple segments) is
+        fed into :meth:`update` before any call to :meth:`decrypt` or :meth:`encrypt`.
+        If there is no associated data, :meth:`update` is not called.
+
+        :param bytes/bytearray/memoryview assoc_data:
+            A piece of associated data. There are no restrictions on its size.
+        """
+
+        if self.update not in self._next:
+            raise TypeError("update() method cannot be called")
+
+        self._len_aad += len(data)
+        self._authenticator.update(data)
+
+    def _pad_aad(self):
+
+        assert(self._status == _CipherStatus.PROCESSING_AUTH_DATA)
+        if self._len_aad & 0x0F:
+            self._authenticator.update(b'\x00' * (16 - (self._len_aad & 0x0F)))
+        self._status = _CipherStatus.PROCESSING_CIPHERTEXT
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt a piece of data.
+
+        Args:
+          plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size.
+        Keyword Args:
+          output(bytes/bytearray/memoryview): The location where the ciphertext
+            is written to. If ``None``, the ciphertext is returned.
+        Returns:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() method cannot be called")
+
+        if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
+            self._pad_aad()
+
+        self._next = (self.encrypt, self.digest)
+
+        result = self._cipher.encrypt(plaintext, output=output)
+        self._len_ct += len(plaintext)
+        if output is None:
+            self._authenticator.update(result)
+        else:
+            self._authenticator.update(output)
+        return result
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt a piece of data.
+
+        Args:
+          ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size.
+        Keyword Args:
+          output(bytes/bytearray/memoryview): The location where the plaintext
+            is written to. If ``None``, the plaintext is returned.
+        Returns:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() method cannot be called")
+
+        if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
+            self._pad_aad()
+
+        self._next = (self.decrypt, self.verify)
+
+        self._len_ct += len(ciphertext)
+        self._authenticator.update(ciphertext)
+        return self._cipher.decrypt(ciphertext, output=output)
+
+    def _compute_mac(self):
+        """Finalize the cipher (if not done already) and return the MAC."""
+
+        if self._mac_tag:
+            assert(self._status == _CipherStatus.PROCESSING_DONE)
+            return self._mac_tag
+
+        assert(self._status != _CipherStatus.PROCESSING_DONE)
+
+        if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
+            self._pad_aad()
+
+        if self._len_ct & 0x0F:
+            self._authenticator.update(b'\x00' * (16 - (self._len_ct & 0x0F)))
+
+        self._status = _CipherStatus.PROCESSING_DONE
+
+        self._authenticator.update(long_to_bytes(self._len_aad, 8)[::-1])
+        self._authenticator.update(long_to_bytes(self._len_ct, 8)[::-1])
+        self._mac_tag = self._authenticator.digest()
+        return self._mac_tag
+
+    def digest(self):
+        """Compute the *binary* authentication tag (MAC).
+
+        :Return: the MAC tag, as 16 ``bytes``.
+        """
+
+        if self.digest not in self._next:
+            raise TypeError("digest() method cannot be called")
+        self._next = (self.digest,)
+
+        return self._compute_mac()
+
+    def hexdigest(self):
+        """Compute the *printable* authentication tag (MAC).
+
+        This method is like :meth:`digest`.
+
+        :Return: the MAC tag, as a hexadecimal string.
+        """
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def verify(self, received_mac_tag):
+        """Validate the *binary* authentication tag (MAC).
+
+        The receiver invokes this method at the very end, to
+        check if the associated data (if any) and the decrypted
+        messages are valid.
+
+        :param bytes/bytearray/memoryview received_mac_tag:
+            This is the 16-byte *binary* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        if self.verify not in self._next:
+            raise TypeError("verify() cannot be called"
+                            " when encrypting a message")
+        self._next = (self.verify,)
+
+        secret = get_random_bytes(16)
+
+        self._compute_mac()
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret,
+                           data=self._mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret,
+                           data=received_mac_tag)
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Validate the *printable* authentication tag (MAC).
+
+        This method is like :meth:`verify`.
+
+        :param string hex_mac_tag:
+            This is the *printable* MAC.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        self.verify(unhexlify(hex_mac_tag))
+
+    def encrypt_and_digest(self, plaintext):
+        """Perform :meth:`encrypt` and :meth:`digest` in one step.
+
+        :param plaintext: The data to encrypt, of any size.
+        :type plaintext: bytes/bytearray/memoryview
+        :return: a tuple with two ``bytes`` objects:
+
+            - the ciphertext, of equal length as the plaintext
+            - the 16-byte MAC tag
+        """
+
+        return self.encrypt(plaintext), self.digest()
+
+    def decrypt_and_verify(self, ciphertext, received_mac_tag):
+        """Perform :meth:`decrypt` and :meth:`verify` in one step.
+
+        :param ciphertext: The piece of data to decrypt.
+        :type ciphertext: bytes/bytearray/memoryview
+        :param bytes received_mac_tag:
+            This is the 16-byte *binary* MAC, as received from the sender.
+        :return: the decrypted data (as ``bytes``)
+        :raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        plaintext = self.decrypt(ciphertext)
+        self.verify(received_mac_tag)
+        return plaintext
+
+
+def new(**kwargs):
+    """Create a new ChaCha20-Poly1305 or XChaCha20-Poly1305 AEAD cipher.
+
+    :keyword key: The secret key to use. It must be 32 bytes long.
+    :type key: byte string
+
+    :keyword nonce:
+        A value that must never be reused for any other encryption
+        done with this key.
+
+        For ChaCha20-Poly1305, it must be 8 or 12 bytes long.
+
+        For XChaCha20-Poly1305, it must be 24 bytes long.
+
+        If not provided, 12 ``bytes`` will be generated randomly
+        (you can find them back in the ``nonce`` attribute).
+    :type nonce: bytes, bytearray, memoryview
+
+    :Return: a :class:`Crypto.Cipher.ChaCha20.ChaCha20Poly1305Cipher` object
+    """
+
+    try:
+        key = kwargs.pop("key")
+    except KeyError as e:
+        raise TypeError("Missing parameter %s" % e)
+
+        self._len_ct += len(plaintext)
+
+    if len(key) != 32:
+        raise ValueError("Key must be 32 bytes long")
+
+    nonce = kwargs.pop("nonce", None)
+    if nonce is None:
+        nonce = get_random_bytes(12)
+
+    if len(nonce) in (8, 12):
+        pass
+    elif len(nonce) == 24:
+        key = _HChaCha20(key, nonce[:16])
+        nonce = b'\x00\x00\x00\x00' + nonce[16:]
+    else:
+        raise ValueError("Nonce must be 8, 12 or 24 bytes long")
+
+    if not is_buffer(nonce):
+        raise TypeError("nonce must be bytes, bytearray or memoryview")
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return ChaCha20Poly1305Cipher(key, nonce)
+
+
+# Size of a key (in bytes)
+key_size = 32

+ 28 - 0
tls/pycryptoMod/lib/Crypto/Cipher/ChaCha20_Poly1305.pyi

@@ -0,0 +1,28 @@
+from typing import Union, Tuple, overload
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class ChaCha20Poly1305Cipher:
+    nonce: bytes
+
+    def __init__(self, key: Buffer, nonce: Buffer) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, received_mac_tag: Buffer) -> None: ...
+    def hexverify(self, received_mac_tag: str) -> None: ...
+    def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ...
+    def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ...
+
+def new(key: Buffer, nonce: Buffer = ...) -> ChaCha20Poly1305Cipher: ...
+
+block_size: int
+key_size: int

+ 158 - 0
tls/pycryptoMod/lib/Crypto/Cipher/DES.py

@@ -0,0 +1,158 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/DES.py : DES
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""
+Module's constants for the modes of operation supported with Single DES:
+
+:var MODE_ECB: :ref:`Electronic Code Book (ECB) <ecb_mode>`
+:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>`
+:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>`
+:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>`
+:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>`
+:var MODE_OPENPGP:  :ref:`OpenPGP Mode <openpgp_mode>`
+:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
+"""
+
+import sys
+
+from tls.Crypto.Cipher import _create_cipher
+from tls.Crypto.Util.py3compat import byte_string
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  c_size_t, c_uint8_ptr)
+
+_raw_des_lib = load_pycryptodome_raw_lib(
+                "Crypto.Cipher._raw_des",
+                """
+                int DES_start_operation(const uint8_t key[],
+                                        size_t key_len,
+                                        void **pResult);
+                int DES_encrypt(const void *state,
+                                const uint8_t *in,
+                                uint8_t *out,
+                                size_t data_len);
+                int DES_decrypt(const void *state,
+                                const uint8_t *in,
+                                uint8_t *out,
+                                size_t data_len);
+                int DES_stop_operation(void *state);
+                """)
+
+
+def _create_base_cipher(dict_parameters):
+    """This method instantiates and returns a handle to a low-level
+    base cipher. It will absorb named parameters in the process."""
+
+    try:
+        key = dict_parameters.pop("key")
+    except KeyError:
+        raise TypeError("Missing 'key' parameter")
+
+    if len(key) != key_size:
+        raise ValueError("Incorrect DES key length (%d bytes)" % len(key))
+
+    start_operation = _raw_des_lib.DES_start_operation
+    stop_operation = _raw_des_lib.DES_stop_operation
+
+    cipher = VoidPointer()
+    result = start_operation(c_uint8_ptr(key),
+                             c_size_t(len(key)),
+                             cipher.address_of())
+    if result:
+        raise ValueError("Error %X while instantiating the DES cipher"
+                         % result)
+    return SmartPointer(cipher.get(), stop_operation)
+
+
+def new(key, mode, *args, **kwargs):
+    """Create a new DES cipher.
+
+    :param key:
+        The secret key to use in the symmetric cipher.
+        It must be 8 byte long. The parity bits will be ignored.
+    :type key: bytes/bytearray/memoryview
+
+    :param mode:
+        The chaining mode to use for encryption or decryption.
+    :type mode: One of the supported ``MODE_*`` constants
+
+    :Keyword Arguments:
+        *   **iv** (*byte string*) --
+            (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
+            and ``MODE_OPENPGP`` modes).
+
+            The initialization vector to use for encryption or decryption.
+
+            For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long.
+
+            For ``MODE_OPENPGP`` mode only,
+            it must be 8 bytes long for encryption
+            and 10 bytes for decryption (in the latter case, it is
+            actually the *encrypted* IV which was prefixed to the ciphertext).
+
+            If not provided, a random byte string is generated (you must then
+            read its value with the :attr:`iv` attribute).
+
+        *   **nonce** (*byte string*) --
+            (Only applicable for ``MODE_EAX`` and ``MODE_CTR``).
+
+            A value that must never be reused for any other encryption done
+            with this key.
+
+            For ``MODE_EAX`` there are no
+            restrictions on its length (recommended: **16** bytes).
+
+            For ``MODE_CTR``, its length must be in the range **[0..7]**.
+
+            If not provided for ``MODE_EAX``, a random byte string is generated (you
+            can read it back via the ``nonce`` attribute).
+
+        *   **segment_size** (*integer*) --
+            (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
+            are segmented in. It must be a multiple of 8.
+            If not specified, it will be assumed to be 8.
+
+        *   **mac_len** : (*integer*) --
+            (Only ``MODE_EAX``)
+            Length of the authentication tag, in bytes.
+            It must be no longer than 8 (default).
+
+        *   **initial_value** : (*integer*) --
+            (Only ``MODE_CTR``). The initial value for the counter within
+            the counter block. By default it is **0**.
+
+    :Return: a DES object, of the applicable mode.
+    """
+
+    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
+
+MODE_ECB = 1
+MODE_CBC = 2
+MODE_CFB = 3
+MODE_OFB = 5
+MODE_CTR = 6
+MODE_OPENPGP = 7
+MODE_EAX = 9
+
+# Size of a data block (in bytes)
+block_size = 8
+# Size of a key (in bytes)
+key_size = 8

+ 35 - 0
tls/pycryptoMod/lib/Crypto/Cipher/DES.pyi

@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+from tls.Crypto.Cipher._mode_ecb import EcbMode
+from tls.Crypto.Cipher._mode_cbc import CbcMode
+from tls.Crypto.Cipher._mode_cfb import CfbMode
+from tls.Crypto.Cipher._mode_ofb import OfbMode
+from tls.Crypto.Cipher._mode_ctr import CtrMode
+from tls.Crypto.Cipher._mode_openpgp import OpenPgpMode
+from tls.Crypto.Cipher._mode_eax import EaxMode
+
+DESMode = int
+
+MODE_ECB: DESMode
+MODE_CBC: DESMode
+MODE_CFB: DESMode
+MODE_OFB: DESMode
+MODE_CTR: DESMode
+MODE_OPENPGP: DESMode
+MODE_EAX: DESMode
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+        mode: DESMode,
+        iv : Buffer = ...,
+        IV : Buffer = ...,
+        nonce : Buffer = ...,
+        segment_size : int = ...,
+        mac_len : int = ...,
+        initial_value : Union[int, Buffer] = ...,
+        counter : Dict = ...) -> \
+        Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: int

+ 187 - 0
tls/pycryptoMod/lib/Crypto/Cipher/DES3.py

@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/DES3.py : DES3
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""
+Module's constants for the modes of operation supported with Triple DES:
+
+:var MODE_ECB: :ref:`Electronic Code Book (ECB) <ecb_mode>`
+:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>`
+:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>`
+:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>`
+:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>`
+:var MODE_OPENPGP:  :ref:`OpenPGP Mode <openpgp_mode>`
+:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
+"""
+
+import sys
+
+from tls.Crypto.Cipher import _create_cipher
+from tls.Crypto.Util.py3compat import byte_string, bchr, bord, bstr
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  c_size_t)
+
+_raw_des3_lib = load_pycryptodome_raw_lib(
+                    "Crypto.Cipher._raw_des3",
+                    """
+                    int DES3_start_operation(const uint8_t key[],
+                                             size_t key_len,
+                                             void **pResult);
+                    int DES3_encrypt(const void *state,
+                                     const uint8_t *in,
+                                     uint8_t *out,
+                                     size_t data_len);
+                    int DES3_decrypt(const void *state,
+                                     const uint8_t *in,
+                                     uint8_t *out,
+                                     size_t data_len);
+                    int DES3_stop_operation(void *state);
+                    """)
+
+
+def adjust_key_parity(key_in):
+    """Set the parity bits in a TDES key.
+
+    :param key_in: the TDES key whose bits need to be adjusted
+    :type key_in: byte string
+
+    :returns: a copy of ``key_in``, with the parity bits correctly set
+    :rtype: byte string
+
+    :raises ValueError: if the TDES key is not 16 or 24 bytes long
+    :raises ValueError: if the TDES key degenerates into Single DES
+    """
+
+    def parity_byte(key_byte):
+        parity = 1
+        for i in range(1, 8):
+            parity ^= (key_byte >> i) & 1
+        return (key_byte & 0xFE) | parity
+
+    if len(key_in) not in key_size:
+        raise ValueError("Not a valid TDES key")
+
+    key_out = b"".join([ bchr(parity_byte(bord(x))) for x in key_in ])
+
+    if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]:
+        raise ValueError("Triple DES key degenerates to single DES")
+
+    return key_out
+
+
+def _create_base_cipher(dict_parameters):
+    """This method instantiates and returns a handle to a low-level base cipher.
+    It will absorb named parameters in the process."""
+
+    try:
+        key_in = dict_parameters.pop("key")
+    except KeyError:
+        raise TypeError("Missing 'key' parameter")
+
+    key = adjust_key_parity(bstr(key_in))
+
+    start_operation = _raw_des3_lib.DES3_start_operation
+    stop_operation = _raw_des3_lib.DES3_stop_operation
+
+    cipher = VoidPointer()
+    result = start_operation(key,
+                             c_size_t(len(key)),
+                             cipher.address_of())
+    if result:
+        raise ValueError("Error %X while instantiating the TDES cipher"
+                         % result)
+    return SmartPointer(cipher.get(), stop_operation)
+
+
+def new(key, mode, *args, **kwargs):
+    """Create a new Triple DES cipher.
+
+    :param key:
+        The secret key to use in the symmetric cipher.
+        It must be 16 or 24 byte long. The parity bits will be ignored.
+    :type key: bytes/bytearray/memoryview
+
+    :param mode:
+        The chaining mode to use for encryption or decryption.
+    :type mode: One of the supported ``MODE_*`` constants
+
+    :Keyword Arguments:
+        *   **iv** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
+            and ``MODE_OPENPGP`` modes).
+
+            The initialization vector to use for encryption or decryption.
+
+            For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long.
+
+            For ``MODE_OPENPGP`` mode only,
+            it must be 8 bytes long for encryption
+            and 10 bytes for decryption (in the latter case, it is
+            actually the *encrypted* IV which was prefixed to the ciphertext).
+
+            If not provided, a random byte string is generated (you must then
+            read its value with the :attr:`iv` attribute).
+
+        *   **nonce** (*bytes*, *bytearray*, *memoryview*) --
+            (Only applicable for ``MODE_EAX`` and ``MODE_CTR``).
+
+            A value that must never be reused for any other encryption done
+            with this key.
+
+            For ``MODE_EAX`` there are no
+            restrictions on its length (recommended: **16** bytes).
+
+            For ``MODE_CTR``, its length must be in the range **[0..7]**.
+
+            If not provided for ``MODE_EAX``, a random byte string is generated (you
+            can read it back via the ``nonce`` attribute).
+
+        *   **segment_size** (*integer*) --
+            (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
+            are segmented in. It must be a multiple of 8.
+            If not specified, it will be assumed to be 8.
+
+        *   **mac_len** : (*integer*) --
+            (Only ``MODE_EAX``)
+            Length of the authentication tag, in bytes.
+            It must be no longer than 8 (default).
+
+        *   **initial_value** : (*integer*) --
+            (Only ``MODE_CTR``). The initial value for the counter within
+            the counter block. By default it is **0**.
+
+    :Return: a Triple DES object, of the applicable mode.
+    """
+
+    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
+
+MODE_ECB = 1
+MODE_CBC = 2
+MODE_CFB = 3
+MODE_OFB = 5
+MODE_CTR = 6
+MODE_OPENPGP = 7
+MODE_EAX = 9
+
+# Size of a data block (in bytes)
+block_size = 8
+# Size of a key (in bytes)
+key_size = (16, 24)

+ 37 - 0
tls/pycryptoMod/lib/Crypto/Cipher/DES3.pyi

@@ -0,0 +1,37 @@
+from typing import Union, Dict, Tuple
+
+from tls.Crypto.Cipher._mode_ecb import EcbMode
+from tls.Crypto.Cipher._mode_cbc import CbcMode
+from tls.Crypto.Cipher._mode_cfb import CfbMode
+from tls.Crypto.Cipher._mode_ofb import OfbMode
+from tls.Crypto.Cipher._mode_ctr import CtrMode
+from tls.Crypto.Cipher._mode_openpgp import OpenPgpMode
+from tls.Crypto.Cipher._mode_eax import EaxMode
+
+def adjust_key_parity(key_in: bytes) -> bytes: ...
+
+DES3Mode = int
+
+MODE_ECB: DES3Mode
+MODE_CBC: DES3Mode
+MODE_CFB: DES3Mode
+MODE_OFB: DES3Mode
+MODE_CTR: DES3Mode
+MODE_OPENPGP: DES3Mode
+MODE_EAX: DES3Mode
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+        mode: DES3Mode,
+        iv : Buffer = ...,
+        IV : Buffer = ...,
+        nonce : Buffer = ...,
+        segment_size : int = ...,
+        mac_len : int = ...,
+        initial_value : Union[int, Buffer] = ...,
+        counter : Dict = ...) -> \
+        Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: Tuple[int, int]

+ 239 - 0
tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_OAEP.py

@@ -0,0 +1,239 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/PKCS1_OAEP.py : PKCS#1 OAEP
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Signature.pss import MGF1
+import Crypto.Hash.SHA1
+
+from tls.Crypto.Util.py3compat import bord, _copy_bytes
+import Crypto.Util.number
+from   Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes
+from   Crypto.Util.strxor import strxor
+from tls.Crypto import Random
+
+class PKCS1OAEP_Cipher:
+    """Cipher object for PKCS#1 v1.5 OAEP.
+    Do not create directly: use :func:`new` instead."""
+
+    def __init__(self, key, hashAlgo, mgfunc, label, randfunc):
+        """Initialize this PKCS#1 OAEP cipher object.
+
+        :Parameters:
+         key : an RSA key object
+                If a private half is given, both encryption and decryption are possible.
+                If a public half is given, only encryption is possible.
+         hashAlgo : hash object
+                The hash function to use. This can be a module under `Crypto.Hash`
+                or an existing hash object created from any of such modules. If not specified,
+                `Crypto.Hash.SHA1` is used.
+         mgfunc : callable
+                A mask generation function that accepts two parameters: a string to
+                use as seed, and the lenth of the mask to generate, in bytes.
+                If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice).
+         label : bytes/bytearray/memoryview
+                A label to apply to this particular encryption. If not specified,
+                an empty string is used. Specifying a label does not improve
+                security.
+         randfunc : callable
+                A function that returns random bytes.
+
+        :attention: Modify the mask generation function only if you know what you are doing.
+                    Sender and receiver must use the same one.
+        """
+        self._key = key
+
+        if hashAlgo:
+            self._hashObj = hashAlgo
+        else:
+            self._hashObj = Crypto.Hash.SHA1
+
+        if mgfunc:
+            self._mgf = mgfunc
+        else:
+            self._mgf = lambda x,y: MGF1(x,y,self._hashObj)
+
+        self._label = _copy_bytes(None, None, label)
+        self._randfunc = randfunc
+
+    def can_encrypt(self):
+        """Legacy function to check if you can call :meth:`encrypt`.
+
+        .. deprecated:: 3.0"""
+        return self._key.can_encrypt()
+
+    def can_decrypt(self):
+        """Legacy function to check if you can call :meth:`decrypt`.
+
+        .. deprecated:: 3.0"""
+        return self._key.can_decrypt()
+
+    def encrypt(self, message):
+        """Encrypt a message with PKCS#1 OAEP.
+
+        :param message:
+            The message to encrypt, also known as plaintext. It can be of
+            variable length, but not longer than the RSA modulus (in bytes)
+            minus 2, minus twice the hash output size.
+            For instance, if you use RSA 2048 and SHA-256, the longest message
+            you can encrypt is 190 byte long.
+        :type message: bytes/bytearray/memoryview
+
+        :returns: The ciphertext, as large as the RSA modulus.
+        :rtype: bytes
+
+        :raises ValueError:
+            if the message is too long.
+        """
+
+        # See 7.1.1 in RFC3447
+        modBits = Crypto.Util.number.size(self._key.n)
+        k = ceil_div(modBits, 8) # Convert from bits to bytes
+        hLen = self._hashObj.digest_size
+        mLen = len(message)
+
+        # Step 1b
+        ps_len = k - mLen - 2 * hLen - 2
+        if ps_len < 0:
+            raise ValueError("Plaintext is too long.")
+        # Step 2a
+        lHash = self._hashObj.new(self._label).digest()
+        # Step 2b
+        ps = b'\x00' * ps_len
+        # Step 2c
+        db = lHash + ps + b'\x01' + _copy_bytes(None, None, message)
+        # Step 2d
+        ros = self._randfunc(hLen)
+        # Step 2e
+        dbMask = self._mgf(ros, k-hLen-1)
+        # Step 2f
+        maskedDB = strxor(db, dbMask)
+        # Step 2g
+        seedMask = self._mgf(maskedDB, hLen)
+        # Step 2h
+        maskedSeed = strxor(ros, seedMask)
+        # Step 2i
+        em = b'\x00' + maskedSeed + maskedDB
+        # Step 3a (OS2IP)
+        em_int = bytes_to_long(em)
+        # Step 3b (RSAEP)
+        m_int = self._key._encrypt(em_int)
+        # Step 3c (I2OSP)
+        c = long_to_bytes(m_int, k)
+        return c
+
+    def decrypt(self, ciphertext):
+        """Decrypt a message with PKCS#1 OAEP.
+
+        :param ciphertext: The encrypted message.
+        :type ciphertext: bytes/bytearray/memoryview
+
+        :returns: The original message (plaintext).
+        :rtype: bytes
+
+        :raises ValueError:
+            if the ciphertext has the wrong length, or if decryption
+            fails the integrity check (in which case, the decryption
+            key is probably wrong).
+        :raises TypeError:
+            if the RSA key has no private half (i.e. you are trying
+            to decrypt using a public key).
+        """
+
+        # See 7.1.2 in RFC3447
+        modBits = Crypto.Util.number.size(self._key.n)
+        k = ceil_div(modBits,8) # Convert from bits to bytes
+        hLen = self._hashObj.digest_size
+
+        # Step 1b and 1c
+        if len(ciphertext) != k or k<hLen+2:
+            raise ValueError("Ciphertext with incorrect length.")
+        # Step 2a (O2SIP)
+        ct_int = bytes_to_long(ciphertext)
+        # Step 2b (RSADP)
+        m_int = self._key._decrypt(ct_int)
+        # Complete step 2c (I2OSP)
+        em = long_to_bytes(m_int, k)
+        # Step 3a
+        lHash = self._hashObj.new(self._label).digest()
+        # Step 3b
+        y = em[0]
+        # y must be 0, but we MUST NOT check it here in order not to
+        # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
+        maskedSeed = em[1:hLen+1]
+        maskedDB = em[hLen+1:]
+        # Step 3c
+        seedMask = self._mgf(maskedDB, hLen)
+        # Step 3d
+        seed = strxor(maskedSeed, seedMask)
+        # Step 3e
+        dbMask = self._mgf(seed, k-hLen-1)
+        # Step 3f
+        db = strxor(maskedDB, dbMask)
+        # Step 3g
+        one_pos = db[hLen:].find(b'\x01')
+        lHash1 = db[:hLen]
+        invalid = bord(y) | int(one_pos < 0)
+        hash_compare = strxor(lHash1, lHash)
+        for x in hash_compare:
+            invalid |= bord(x)
+        for x in db[hLen:one_pos]:
+            invalid |= bord(x)
+        if invalid != 0:
+            raise ValueError("Incorrect decryption.")
+        # Step 4
+        return db[hLen + one_pos + 1:]
+
+def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None):
+    """Return a cipher object :class:`PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption.
+
+    :param key:
+      The key object to use to encrypt or decrypt the message.
+      Decryption is only possible with a private RSA key.
+    :type key: RSA key object
+
+    :param hashAlgo:
+      The hash function to use. This can be a module under `Crypto.Hash`
+      or an existing hash object created from any of such modules.
+      If not specified, `Crypto.Hash.SHA1` is used.
+    :type hashAlgo: hash object
+
+    :param mgfunc:
+      A mask generation function that accepts two parameters: a string to
+      use as seed, and the lenth of the mask to generate, in bytes.
+      If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice).
+    :type mgfunc: callable
+
+    :param label:
+      A label to apply to this particular encryption. If not specified,
+      an empty string is used. Specifying a label does not improve
+      security.
+    :type label: bytes/bytearray/memoryview
+
+    :param randfunc:
+      A function that returns random bytes.
+      The default is `Random.get_random_bytes`.
+    :type randfunc: callable
+    """
+
+    if randfunc is None:
+        randfunc = Random.get_random_bytes
+    return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc)
+

+ 35 - 0
tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_OAEP.pyi

@@ -0,0 +1,35 @@
+from typing import Optional, Union, Callable, Any, overload
+from typing_extensions import Protocol
+
+from tls.Crypto.PublicKey.RSA import RsaKey
+
+class HashLikeClass(Protocol):
+    digest_size : int
+    def new(self, data: Optional[bytes] = ...) -> Any: ...
+
+class HashLikeModule(Protocol):
+    digest_size : int
+    @staticmethod
+    def new(data: Optional[bytes] = ...) -> Any: ...
+
+HashLike = Union[HashLikeClass, HashLikeModule]
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class PKCS1OAEP_Cipher:
+    def __init__(self,
+                 key: RsaKey,
+                 hashAlgo: HashLike,
+                 mgfunc: Callable[[bytes, int], bytes],
+                 label: Buffer,
+                 randfunc: Callable[[int], bytes]) -> None: ...
+    def can_encrypt(self) -> bool: ...
+    def can_decrypt(self) -> bool: ...
+    def encrypt(self, message: Buffer) -> bytes: ...
+    def decrypt(self, ciphertext: Buffer) -> bytes: ...
+
+def new(key: RsaKey,
+        hashAlgo: Optional[HashLike] = ...,
+        mgfunc: Optional[Callable[[bytes, int], bytes]] = ...,
+        label: Optional[Buffer] = ...,
+        randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS1OAEP_Cipher: ...

+ 199 - 0
tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_v1_5.py

@@ -0,0 +1,199 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/PKCS1-v1_5.py : PKCS#1 v1.5
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__all__ = [ 'new', 'PKCS115_Cipher' ]
+
+from tls.Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes
+from tls.Crypto.Util.py3compat import bord, _copy_bytes
+import Crypto.Util.number
+from tls.Crypto import Random
+
+class PKCS115_Cipher:
+    """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption.
+    Do not instantiate directly. Use :func:`Crypto.Cipher.PKCS1_v1_5.new` instead."""
+
+    def __init__(self, key, randfunc):
+        """Initialize this PKCS#1 v1.5 cipher object.
+
+        :Parameters:
+         key : an RSA key object
+          If a private half is given, both encryption and decryption are possible.
+          If a public half is given, only encryption is possible.
+         randfunc : callable
+          Function that returns random bytes.
+        """
+
+        self._key = key
+        self._randfunc = randfunc
+
+    def can_encrypt(self):
+        """Return True if this cipher object can be used for encryption."""
+        return self._key.can_encrypt()
+
+    def can_decrypt(self):
+        """Return True if this cipher object can be used for decryption."""
+        return self._key.can_decrypt()
+
+    def encrypt(self, message):
+        """Produce the PKCS#1 v1.5 encryption of a message.
+
+        This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in
+        `section 7.2.1 of RFC8017
+        <https://tools.ietf.org/html/rfc8017#page-28>`_.
+
+        :param message:
+            The message to encrypt, also known as plaintext. It can be of
+            variable length, but not longer than the RSA modulus (in bytes) minus 11.
+        :type message: bytes/bytearray/memoryview
+
+        :Returns: A byte string, the ciphertext in which the message is encrypted.
+            It is as long as the RSA modulus (in bytes).
+
+        :Raises ValueError:
+            If the RSA key length is not sufficiently long to deal with the given
+            message.
+        """
+
+        # See 7.2.1 in RFC8017
+        modBits = Crypto.Util.number.size(self._key.n)
+        k = ceil_div(modBits,8) # Convert from bits to bytes
+        mLen = len(message)
+
+        # Step 1
+        if mLen > k - 11:
+            raise ValueError("Plaintext is too long.")
+        # Step 2a
+        ps = []
+        while len(ps) != k - mLen - 3:
+            new_byte = self._randfunc(1)
+            if bord(new_byte[0]) == 0x00:
+                continue
+            ps.append(new_byte)
+        ps = b"".join(ps)
+        assert(len(ps) == k - mLen - 3)
+        # Step 2b
+        em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message)
+        # Step 3a (OS2IP)
+        em_int = bytes_to_long(em)
+        # Step 3b (RSAEP)
+        m_int = self._key._encrypt(em_int)
+        # Step 3c (I2OSP)
+        c = long_to_bytes(m_int, k)
+        return c
+
+    def decrypt(self, ciphertext, sentinel):
+        r"""Decrypt a PKCS#1 v1.5 ciphertext.
+
+        This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in
+        `section 7.2.2 of RFC8017
+        <https://tools.ietf.org/html/rfc8017#page-29>`_.
+
+        :param ciphertext:
+            The ciphertext that contains the message to recover.
+        :type ciphertext: bytes/bytearray/memoryview
+
+        :param sentinel:
+            The object to return whenever an error is detected.
+        :type sentinel: any type
+
+        :Returns: A byte string. It is either the original message or the ``sentinel`` (in case of an error).
+
+        :Raises ValueError:
+            If the ciphertext length is incorrect
+        :Raises TypeError:
+            If the RSA key has no private half (i.e. it cannot be used for
+            decyption).
+
+        .. warning::
+            You should **never** let the party who submitted the ciphertext know that
+            this function returned the ``sentinel`` value.
+            Armed with such knowledge (for a fair amount of carefully crafted but invalid ciphertexts),
+            an attacker is able to recontruct the plaintext of any other encryption that were carried out
+            with the same RSA public key (see `Bleichenbacher's`__ attack).
+
+            In general, it should not be possible for the other party to distinguish
+            whether processing at the server side failed because the value returned
+            was a ``sentinel`` as opposed to a random, invalid message.
+
+            In fact, the second option is not that unlikely: encryption done according to PKCS#1 v1.5
+            embeds no good integrity check. There is roughly one chance
+            in 2\ :sup:`16` for a random ciphertext to be returned as a valid message
+            (although random looking).
+
+            It is therefore advisabled to:
+
+            1. Select as ``sentinel`` a value that resembles a plausable random, invalid message.
+            2. Not report back an error as soon as you detect a ``sentinel`` value.
+               Put differently, you should not explicitly check if the returned value is the ``sentinel`` or not.
+            3. Cover all possible errors with a single, generic error indicator.
+            4. Embed into the definition of ``message`` (at the protocol level) a digest (e.g. ``SHA-1``).
+               It is recommended for it to be the rightmost part ``message``.
+            5. Where possible, monitor the number of errors due to ciphertexts originating from the same party,
+               and slow down the rate of the requests from such party (or even blacklist it altogether).
+
+            **If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.**
+
+            .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps
+
+        """
+
+        # See 7.2.1 in RFC3447
+        modBits = Crypto.Util.number.size(self._key.n)
+        k = ceil_div(modBits,8) # Convert from bits to bytes
+
+        # Step 1
+        if len(ciphertext) != k:
+            raise ValueError("Ciphertext with incorrect length.")
+        # Step 2a (O2SIP)
+        ct_int = bytes_to_long(ciphertext)
+        # Step 2b (RSADP)
+        m_int = self._key._decrypt(ct_int)
+        # Complete step 2c (I2OSP)
+        em = long_to_bytes(m_int, k)
+        # Step 3
+        sep = em.find(b'\x00', 2)
+        if  not em.startswith(b'\x00\x02') or sep < 10:
+            return sentinel
+        # Step 4
+        return em[sep + 1:]
+
+
+def new(key, randfunc=None):
+    """Create a cipher for performing PKCS#1 v1.5 encryption or decryption.
+
+    :param key:
+      The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object.
+      Decryption is only possible if *key* is a private RSA key.
+    :type key: RSA key object
+
+    :param randfunc:
+      Function that return random bytes.
+      The default is :func:`Crypto.Random.get_random_bytes`.
+    :type randfunc: callable
+
+    :returns: A cipher object `PKCS115_Cipher`.
+    """
+
+    if randfunc is None:
+        randfunc = Random.get_random_bytes
+    return PKCS115_Cipher(key, randfunc)
+

+ 17 - 0
tls/pycryptoMod/lib/Crypto/Cipher/PKCS1_v1_5.pyi

@@ -0,0 +1,17 @@
+from typing import Callable, Union, Any, Optional
+
+from tls.Crypto.PublicKey.RSA import RsaKey
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class PKCS115_Cipher:
+    def __init__(self,
+                 key: RsaKey,
+                 randfunc: Callable[[int], bytes]) -> None: ...
+    def can_encrypt(self) -> bool: ...
+    def can_decrypt(self) -> bool: ...
+    def encrypt(self, message: Buffer) -> bytes: ...
+    def decrypt(self, ciphertext: Buffer) -> bytes: ...
+
+def new(key: Buffer,
+        randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ...

+ 167 - 0
tls/pycryptoMod/lib/Crypto/Cipher/Salsa20.py

@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/Salsa20.py : Salsa20 stream cipher (http://cr.yp.to/snuffle.html)
+#
+# Contributed by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>.
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import _copy_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  create_string_buffer,
+                                  get_raw_buffer, VoidPointer,
+                                  SmartPointer, c_size_t,
+                                  c_uint8_ptr, is_writeable_buffer)
+
+from tls.Crypto.Random import get_random_bytes
+
+_raw_salsa20_lib = load_pycryptodome_raw_lib("Crypto.Cipher._Salsa20",
+                    """
+                    int Salsa20_stream_init(uint8_t *key, size_t keylen,
+                                            uint8_t *nonce, size_t nonce_len,
+                                            void **pSalsaState);
+                    int Salsa20_stream_destroy(void *salsaState);
+                    int Salsa20_stream_encrypt(void *salsaState,
+                                               const uint8_t in[],
+                                               uint8_t out[], size_t len);
+                    """)
+
+
+class Salsa20Cipher:
+    """Salsa20 cipher object. Do not create it directly. Use :py:func:`new`
+    instead.
+
+    :var nonce: The nonce with length 8
+    :vartype nonce: byte string
+    """
+
+    def __init__(self, key, nonce):
+        """Initialize a Salsa20 cipher object
+
+        See also `new()` at the module level."""
+
+        if len(key) not in key_size:
+            raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key))
+
+        if len(nonce) != 8:
+            raise ValueError("Incorrect nonce length for Salsa20 (%d bytes)" %
+                             len(nonce))
+
+        self.nonce = _copy_bytes(None, None, nonce)
+
+        self._state = VoidPointer()
+        result = _raw_salsa20_lib.Salsa20_stream_init(
+                        c_uint8_ptr(key),
+                        c_size_t(len(key)),
+                        c_uint8_ptr(nonce),
+                        c_size_t(len(nonce)),
+                        self._state.address_of())
+        if result:
+            raise ValueError("Error %d instantiating a Salsa20 cipher")
+        self._state = SmartPointer(self._state.get(),
+                                   _raw_salsa20_lib.Salsa20_stream_destroy)
+
+        self.block_size = 1
+        self.key_size = len(key)
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt a piece of data.
+
+        Args:
+          plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size.
+        Keyword Args:
+          output(bytes/bytearray/memoryview): The location where the ciphertext
+            is written to. If ``None``, the ciphertext is returned.
+        Returns:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+        
+        if output is None:
+            ciphertext = create_string_buffer(len(plaintext))
+        else:
+            ciphertext = output
+           
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+        
+            if len(plaintext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = _raw_salsa20_lib.Salsa20_stream_encrypt(
+                                         self._state.get(),
+                                         c_uint8_ptr(plaintext),
+                                         c_uint8_ptr(ciphertext),
+                                         c_size_t(len(plaintext)))
+        if result:
+            raise ValueError("Error %d while encrypting with Salsa20" % result)
+
+        if output is None:
+            return get_raw_buffer(ciphertext)
+        else:
+            return None
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt a piece of data.
+        
+        Args:
+          ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size.
+        Keyword Args:
+          output(bytes/bytearray/memoryview): The location where the plaintext
+            is written to. If ``None``, the plaintext is returned.
+        Returns:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        try:
+            return self.encrypt(ciphertext, output=output)
+        except ValueError as e:
+            raise ValueError(str(e).replace("enc", "dec"))
+
+
+def new(key, nonce=None):
+    """Create a new Salsa20 cipher
+
+    :keyword key: The secret key to use. It must be 16 or 32 bytes long.
+    :type key: bytes/bytearray/memoryview
+
+    :keyword nonce:
+        A value that must never be reused for any other encryption
+        done with this key. It must be 8 bytes long.
+
+        If not provided, a random byte string will be generated (you can read
+        it back via the ``nonce`` attribute of the returned object).
+    :type nonce: bytes/bytearray/memoryview
+
+    :Return: a :class:`Crypto.Cipher.Salsa20.Salsa20Cipher` object
+    """
+
+    if nonce is None:
+        nonce = get_random_bytes(8)
+
+    return Salsa20Cipher(key, nonce)
+
+# Size of a data block (in bytes)
+block_size = 1
+
+# Size of a key (in bytes)
+key_size = (16, 32)
+

+ 27 - 0
tls/pycryptoMod/lib/Crypto/Cipher/Salsa20.pyi

@@ -0,0 +1,27 @@
+from typing import Union, Tuple, Optional, overload
+
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class Salsa20Cipher:
+    nonce: bytes
+    block_size: int
+    key_size: int
+
+    def __init__(self,
+                 key: Buffer,
+                 nonce: Buffer) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+
+def new(key: Buffer, nonce: Optional[Buffer] = ...) -> Salsa20Cipher: ...
+
+block_size: int
+key_size: Tuple[int, int]
+

+ 131 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_EKSBlowfish.py

@@ -0,0 +1,131 @@
+# ===================================================================
+#
+# Copyright (c) 2019, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+import sys
+
+from tls.Crypto.Cipher import _create_cipher
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer, c_size_t,
+                                  c_uint8_ptr, c_uint)
+
+_raw_blowfish_lib = load_pycryptodome_raw_lib(
+        "Crypto.Cipher._raw_eksblowfish",
+        """
+        int EKSBlowfish_start_operation(const uint8_t key[],
+                                        size_t key_len,
+                                        const uint8_t salt[16],
+                                        size_t salt_len,
+                                        unsigned cost,
+                                        unsigned invert,
+                                        void **pResult);
+        int EKSBlowfish_encrypt(const void *state,
+                                const uint8_t *in,
+                                uint8_t *out,
+                                size_t data_len);
+        int EKSBlowfish_decrypt(const void *state,
+                                const uint8_t *in,
+                                uint8_t *out,
+                                size_t data_len);
+        int EKSBlowfish_stop_operation(void *state);
+        """
+        )
+
+
+def _create_base_cipher(dict_parameters):
+    """This method instantiates and returns a smart pointer to
+    a low-level base cipher. It will absorb named parameters in
+    the process."""
+
+    try:
+        key = dict_parameters.pop("key")
+        salt = dict_parameters.pop("salt")
+        cost = dict_parameters.pop("cost")
+    except KeyError as e:
+        raise TypeError("Missing EKSBlowfish parameter: " + str(e))
+    invert = dict_parameters.pop("invert", True)
+
+    if len(key) not in key_size:
+        raise ValueError("Incorrect EKSBlowfish key length (%d bytes)" % len(key))
+
+    start_operation = _raw_blowfish_lib.EKSBlowfish_start_operation
+    stop_operation = _raw_blowfish_lib.EKSBlowfish_stop_operation
+
+    void_p = VoidPointer()
+    result = start_operation(c_uint8_ptr(key),
+                             c_size_t(len(key)),
+                             c_uint8_ptr(salt),
+                             c_size_t(len(salt)),
+                             c_uint(cost),
+                             c_uint(int(invert)),
+                             void_p.address_of())
+    if result:
+        raise ValueError("Error %X while instantiating the EKSBlowfish cipher"
+                         % result)
+    return SmartPointer(void_p.get(), stop_operation)
+
+
+def new(key, mode, salt, cost, invert):
+    """Create a new EKSBlowfish cipher
+    
+    Args:
+
+      key (bytes, bytearray, memoryview):
+        The secret key to use in the symmetric cipher.
+        Its length can vary from 0 to 72 bytes.
+
+      mode (one of the supported ``MODE_*`` constants):
+        The chaining mode to use for encryption or decryption.
+
+      salt (bytes, bytearray, memoryview):
+        The salt that bcrypt uses to thwart rainbow table attacks
+
+      cost (integer):
+        The complexity factor in bcrypt
+
+      invert (bool):
+        If ``False``, in the inner loop use ``ExpandKey`` first over the salt
+        and then over the key, as defined in
+        the `original bcrypt specification <https://www.usenix.org/legacy/events/usenix99/provos/provos_html/node4.html>`_.
+        If ``True``, reverse the order, as in the first implementation of
+        `bcrypt` in OpenBSD.
+
+    :Return: an EKSBlowfish object
+    """
+
+    kwargs = { 'salt':salt, 'cost':cost, 'invert':invert }
+    return _create_cipher(sys.modules[__name__], key, mode, **kwargs)
+
+
+MODE_ECB = 1
+
+# Size of a data block (in bytes)
+block_size = 8
+# Size of a key (in bytes)
+key_size = range(0, 72 + 1)

+ 15 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_EKSBlowfish.pyi

@@ -0,0 +1,15 @@
+from typing import Union, Iterable
+
+from tls.Crypto.Cipher._mode_ecb import EcbMode
+
+MODE_ECB: int
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+        mode: int,
+	salt: Buffer,
+	cost: int) -> EcbMode: ...
+
+block_size: int
+key_size: Iterable[int]

+ 79 - 0
tls/pycryptoMod/lib/Crypto/Cipher/__init__.py

@@ -0,0 +1,79 @@
+#
+# A block cipher is instantiated as a combination of:
+# 1. A base cipher (such as AES)
+# 2. A mode of operation (such as CBC)
+#
+# Both items are implemented as C modules.
+#
+# The API of #1 is (replace "AES" with the name of the actual cipher):
+# - AES_start_operaion(key) --> base_cipher_state
+# - AES_encrypt(base_cipher_state, in, out, length)
+# - AES_decrypt(base_cipher_state, in, out, length)
+# - AES_stop_operation(base_cipher_state)
+#
+# Where base_cipher_state is AES_State, a struct with BlockBase (set of
+# pointers to encrypt/decrypt/stop) followed by cipher-specific data.
+#
+# The API of #2 is (replace "CBC" with the name of the actual mode):
+# - CBC_start_operation(base_cipher_state) --> mode_state
+# - CBC_encrypt(mode_state, in, out, length)
+# - CBC_decrypt(mode_state, in, out, length)
+# - CBC_stop_operation(mode_state)
+#
+# where mode_state is a a pointer to base_cipher_state plus mode-specific data.
+
+import os
+
+from tls.Crypto.Cipher._mode_ecb import _create_ecb_cipher
+from tls.Crypto.Cipher._mode_cbc import _create_cbc_cipher
+from tls.Crypto.Cipher._mode_cfb import _create_cfb_cipher
+from tls.Crypto.Cipher._mode_ofb import _create_ofb_cipher
+from tls.Crypto.Cipher._mode_ctr import _create_ctr_cipher
+from tls.Crypto.Cipher._mode_openpgp import _create_openpgp_cipher
+from tls.Crypto.Cipher._mode_ccm import _create_ccm_cipher
+from tls.Crypto.Cipher._mode_eax import _create_eax_cipher
+from tls.Crypto.Cipher._mode_siv import _create_siv_cipher
+from tls.Crypto.Cipher._mode_gcm import _create_gcm_cipher
+from tls.Crypto.Cipher._mode_ocb import _create_ocb_cipher
+
+_modes = { 1:_create_ecb_cipher,
+           2:_create_cbc_cipher,
+           3:_create_cfb_cipher,
+           5:_create_ofb_cipher,
+           6:_create_ctr_cipher,
+           7:_create_openpgp_cipher,
+           9:_create_eax_cipher
+           }
+
+_extra_modes = { 8:_create_ccm_cipher,
+                10:_create_siv_cipher,
+                11:_create_gcm_cipher,
+                12:_create_ocb_cipher
+                }
+
+def _create_cipher(factory, key, mode, *args, **kwargs):
+
+    kwargs["key"] = key
+
+    modes = dict(_modes)
+    if kwargs.pop("add_aes_modes", False):
+        modes.update(_extra_modes)
+    if not mode in modes:
+        raise ValueError("Mode not supported")
+
+    if args:
+        if mode in (8, 9, 10, 11, 12):
+            if len(args) > 1:
+                raise TypeError("Too many arguments for this mode")
+            kwargs["nonce"] = args[0]
+        elif mode in (2, 3, 5, 7):
+            if len(args) > 1:
+                raise TypeError("Too many arguments for this mode")
+            kwargs["IV"] = args[0]
+        elif mode == 6:
+            if len(args) > 0:
+                raise TypeError("Too many arguments for this mode")
+        elif mode == 1:
+            raise TypeError("IV is not meaningful for the ECB mode")
+
+    return modes[mode](factory, **kwargs)

+ 0 - 0
tls/pycryptoMod/lib/Crypto/Cipher/__init__.pyi


+ 293 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_cbc.py

@@ -0,0 +1,293 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+Ciphertext Block Chaining (CBC) mode.
+"""
+
+__all__ = ['CbcMode']
+
+from tls.Crypto.Util.py3compat import _copy_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+                                  create_string_buffer, get_raw_buffer,
+                                  SmartPointer, c_size_t, c_uint8_ptr,
+                                  is_writeable_buffer)
+
+from tls.Crypto.Random import get_random_bytes
+
+raw_cbc_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_cbc", """
+                int CBC_start_operation(void *cipher,
+                                        const uint8_t iv[],
+                                        size_t iv_len,
+                                        void **pResult);
+                int CBC_encrypt(void *cbcState,
+                                const uint8_t *in,
+                                uint8_t *out,
+                                size_t data_len);
+                int CBC_decrypt(void *cbcState,
+                                const uint8_t *in,
+                                uint8_t *out,
+                                size_t data_len);
+                int CBC_stop_operation(void *state);
+                """
+                )
+
+
+class CbcMode(object):
+    """*Cipher-Block Chaining (CBC)*.
+
+    Each of the ciphertext blocks depends on the current
+    and all previous plaintext blocks.
+
+    An Initialization Vector (*IV*) is required.
+
+    See `NIST SP800-38A`_ , Section 6.2 .
+
+    .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, block_cipher, iv):
+        """Create a new block cipher, configured in CBC mode.
+
+        :Parameters:
+          block_cipher : C pointer
+            A smart pointer to the low-level block cipher instance.
+
+          iv : bytes/bytearray/memoryview
+            The initialization vector to use for encryption or decryption.
+            It is as long as the cipher block.
+
+            **The IV must be unpredictable**. Ideally it is picked randomly.
+
+            Reusing the *IV* for encryptions performed with the same key
+            compromises confidentiality.
+        """
+
+        self._state = VoidPointer()
+        result = raw_cbc_lib.CBC_start_operation(block_cipher.get(),
+                                                 c_uint8_ptr(iv),
+                                                 c_size_t(len(iv)),
+                                                 self._state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating the CBC mode"
+                             % result)
+
+        # Ensure that object disposal of this Python object will (eventually)
+        # free the memory allocated by the raw library for the cipher mode
+        self._state = SmartPointer(self._state.get(),
+                                   raw_cbc_lib.CBC_stop_operation)
+
+        # Memory allocated for the underlying block cipher is now owed
+        # by the cipher mode
+        block_cipher.release()
+
+        self.block_size = len(iv)
+        """The block size of the underlying cipher, in bytes."""
+
+        self.iv = _copy_bytes(None, None, iv)
+        """The Initialization Vector originally used to create the object.
+        The value does not change."""
+
+        self.IV = self.iv
+        """Alias for `iv`"""
+
+        self._next = [ self.encrypt, self.decrypt ]
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        That also means that you cannot reuse an object for encrypting
+        or decrypting other data with the same key.
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            Its lenght must be multiple of the cipher block size.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() cannot be called after decrypt()")
+        self._next = [ self.encrypt ]
+        
+        if output is None:
+            ciphertext = create_string_buffer(len(plaintext))
+        else:
+            ciphertext = output
+            
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+        
+            if len(plaintext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_cbc_lib.CBC_encrypt(self._state.get(),
+                                         c_uint8_ptr(plaintext),
+                                         c_uint8_ptr(ciphertext),
+                                         c_size_t(len(plaintext)))
+        if result:
+            if result == 3:
+                raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
+            raise ValueError("Error %d while encrypting in CBC mode" % result)
+
+        if output is None:
+            return get_raw_buffer(ciphertext)
+        else:
+            return None
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            Its length must be multiple of the cipher block size.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() cannot be called after encrypt()")
+        self._next = [ self.decrypt ]
+        
+        if output is None:
+            plaintext = create_string_buffer(len(ciphertext))
+        else:
+            plaintext = output
+
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+            
+            if len(ciphertext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_cbc_lib.CBC_decrypt(self._state.get(),
+                                         c_uint8_ptr(ciphertext),
+                                         c_uint8_ptr(plaintext),
+                                         c_size_t(len(ciphertext)))
+        if result:
+            if result == 3:
+                raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
+            raise ValueError("Error %d while decrypting in CBC mode" % result)
+
+        if output is None:
+            return get_raw_buffer(plaintext)
+        else:
+            return None
+
+
+def _create_cbc_cipher(factory, **kwargs):
+    """Instantiate a cipher object that performs CBC encryption/decryption.
+
+    :Parameters:
+      factory : module
+        The underlying block cipher, a module from ``Crypto.Cipher``.
+
+    :Keywords:
+      iv : bytes/bytearray/memoryview
+        The IV to use for CBC.
+
+      IV : bytes/bytearray/memoryview
+        Alias for ``iv``.
+
+    Any other keyword will be passed to the underlying block cipher.
+    See the relevant documentation for details (at least ``key`` will need
+    to be present).
+    """
+
+    cipher_state = factory._create_base_cipher(kwargs)
+    iv = kwargs.pop("IV", None)
+    IV = kwargs.pop("iv", None)
+
+    if (None, None) == (iv, IV):
+        iv = get_random_bytes(factory.block_size)
+    if iv is not None:
+        if IV is not None:
+            raise TypeError("You must either use 'iv' or 'IV', not both")
+    else:
+        iv = IV
+
+    if len(iv) != factory.block_size:
+        raise ValueError("Incorrect IV length (it must be %d bytes long)" %
+                factory.block_size)
+
+    if kwargs:
+        raise TypeError("Unknown parameters for CBC: %s" % str(kwargs))
+
+    return CbcMode(cipher_state, iv)

+ 25 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_cbc.pyi

@@ -0,0 +1,25 @@
+from typing import Union, overload
+
+from tls.Crypto.Util._raw_api import SmartPointer
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['CbcMode']
+
+class CbcMode(object):
+    block_size: int
+    iv: Buffer
+    IV: Buffer
+
+    def __init__(self,
+                 block_cipher: SmartPointer,
+                 iv: Buffer) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+

+ 650 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ccm.py

@@ -0,0 +1,650 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+Counter with CBC-MAC (CCM) mode.
+"""
+
+__all__ = ['CcmMode']
+
+import struct
+from binascii import unhexlify
+
+from tls.Crypto.Util.py3compat import (byte_string, bord,
+                                   _copy_bytes)
+from tls.Crypto.Util._raw_api import is_writeable_buffer
+
+from tls.Crypto.Util.strxor import strxor
+from tls.Crypto.Util.number import long_to_bytes
+
+from tls.Crypto.Hash import BLAKE2s
+from tls.Crypto.Random import get_random_bytes
+
+
+def enum(**enums):
+    return type('Enum', (), enums)
+
+MacStatus = enum(NOT_STARTED=0, PROCESSING_AUTH_DATA=1, PROCESSING_PLAINTEXT=2)
+
+
+class CcmMode(object):
+    """Counter with CBC-MAC (CCM).
+
+    This is an Authenticated Encryption with Associated Data (`AEAD`_) mode.
+    It provides both confidentiality and authenticity.
+
+    The header of the message may be left in the clear, if needed, and it will
+    still be subject to authentication. The decryption step tells the receiver
+    if the message comes from a source that really knowns the secret key.
+    Additionally, decryption detects if any part of the message - including the
+    header - has been modified or corrupted.
+
+    This mode requires a nonce. The nonce shall never repeat for two
+    different messages encrypted with the same key, but it does not need
+    to be random.
+    Note that there is a trade-off between the size of the nonce and the
+    maximum size of a single message you can encrypt.
+
+    It is important to use a large nonce if the key is reused across several
+    messages and the nonce is chosen randomly.
+
+    It is acceptable to us a short nonce if the key is only used a few times or
+    if the nonce is taken from a counter.
+
+    The following table shows the trade-off when the nonce is chosen at
+    random. The column on the left shows how many messages it takes
+    for the keystream to repeat **on average**. In practice, you will want to
+    stop using the key way before that.
+
+    +--------------------+---------------+-------------------+
+    | Avg. # of messages |    nonce      |     Max. message  |
+    | before keystream   |    size       |     size          |
+    | repeats            |    (bytes)    |     (bytes)       |
+    +====================+===============+===================+
+    |       2^52         |      13       |        64K        |
+    +--------------------+---------------+-------------------+
+    |       2^48         |      12       |        16M        |
+    +--------------------+---------------+-------------------+
+    |       2^44         |      11       |         4G        |
+    +--------------------+---------------+-------------------+
+    |       2^40         |      10       |         1T        |
+    +--------------------+---------------+-------------------+
+    |       2^36         |       9       |        64P        |
+    +--------------------+---------------+-------------------+
+    |       2^32         |       8       |        16E        |
+    +--------------------+---------------+-------------------+
+
+    This mode is only available for ciphers that operate on 128 bits blocks
+    (e.g. AES but not TDES).
+
+    See `NIST SP800-38C`_ or RFC3610_.
+
+    .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf
+    .. _RFC3610: https://tools.ietf.org/html/rfc3610
+    .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, factory, key, nonce, mac_len, msg_len, assoc_len,
+                 cipher_params):
+
+        self.block_size = factory.block_size
+        """The block size of the underlying cipher, in bytes."""
+
+        self.nonce = _copy_bytes(None, None, nonce)
+        """The nonce used for this cipher instance"""
+
+        self._factory = factory
+        self._key = _copy_bytes(None, None, key)
+        self._mac_len = mac_len
+        self._msg_len = msg_len
+        self._assoc_len = assoc_len
+        self._cipher_params = cipher_params
+
+        self._mac_tag = None  # Cache for MAC tag
+
+        if self.block_size != 16:
+            raise ValueError("CCM mode is only available for ciphers"
+                             " that operate on 128 bits blocks")
+
+        # MAC tag length (Tlen)
+        if mac_len not in (4, 6, 8, 10, 12, 14, 16):
+            raise ValueError("Parameter 'mac_len' must be even"
+                             " and in the range 4..16 (not %d)" % mac_len)
+
+        # Nonce value
+        if not (nonce and 7 <= len(nonce) <= 13):
+            raise ValueError("Length of parameter 'nonce' must be"
+                             " in the range 7..13 bytes")
+
+        # Create MAC object (the tag will be the last block
+        # bytes worth of ciphertext)
+        self._mac = self._factory.new(key,
+                                      factory.MODE_CBC,
+                                      iv=b'\x00' * 16,
+                                      **cipher_params)
+        self._mac_status = MacStatus.NOT_STARTED
+        self._t = None
+
+        # Allowed transitions after initialization
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        # Cumulative lengths
+        self._cumul_assoc_len = 0
+        self._cumul_msg_len = 0
+
+        # Cache for unaligned associated data/plaintext.
+        # This is a list with byte strings, but when the MAC starts,
+        # it will become a binary string no longer than the block size.
+        self._cache = []
+
+        # Start CTR cipher, by formatting the counter (A.3)
+        q = 15 - len(nonce)  # length of Q, the encoded message length
+        self._cipher = self._factory.new(key,
+                                         self._factory.MODE_CTR,
+                                         nonce=struct.pack("B", q - 1) + self.nonce,
+                                         **cipher_params)
+
+        # S_0, step 6 in 6.1 for j=0
+        self._s_0 = self._cipher.encrypt(b'\x00' * 16)
+
+        # Try to start the MAC
+        if None not in (assoc_len, msg_len):
+            self._start_mac()
+
+    def _start_mac(self):
+
+        assert(self._mac_status == MacStatus.NOT_STARTED)
+        assert(None not in (self._assoc_len, self._msg_len))
+        assert(isinstance(self._cache, list))
+
+        # Formatting control information and nonce (A.2.1)
+        q = 15 - len(self.nonce)  # length of Q, the encoded message length
+        flags = (64 * (self._assoc_len > 0) + 8 * ((self._mac_len - 2) // 2) +
+                 (q - 1))
+        b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q)
+
+        # Formatting associated data (A.2.2)
+        # Encoded 'a' is concatenated with the associated data 'A'
+        assoc_len_encoded = b''
+        if self._assoc_len > 0:
+            if self._assoc_len < (2 ** 16 - 2 ** 8):
+                enc_size = 2
+            elif self._assoc_len < (2 ** 32):
+                assoc_len_encoded = b'\xFF\xFE'
+                enc_size = 4
+            else:
+                assoc_len_encoded = b'\xFF\xFF'
+                enc_size = 8
+            assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size)
+
+        # b_0 and assoc_len_encoded must be processed first
+        self._cache.insert(0, b_0)
+        self._cache.insert(1, assoc_len_encoded)
+
+        # Process all the data cached so far
+        first_data_to_mac = b"".join(self._cache)
+        self._cache = b""
+        self._mac_status = MacStatus.PROCESSING_AUTH_DATA
+        self._update(first_data_to_mac)
+
+    def _pad_cache_and_update(self):
+
+        assert(self._mac_status != MacStatus.NOT_STARTED)
+        assert(len(self._cache) < self.block_size)
+
+        # Associated data is concatenated with the least number
+        # of zero bytes (possibly none) to reach alignment to
+        # the 16 byte boundary (A.2.3)
+        len_cache = len(self._cache)
+        if len_cache > 0:
+            self._update(b'\x00' * (self.block_size - len_cache))
+
+    def update(self, assoc_data):
+        """Protect associated data
+
+        If there is any associated data, the caller has to invoke
+        this function one or more times, before using
+        ``decrypt`` or ``encrypt``.
+
+        By *associated data* it is meant any data (e.g. packet headers) that
+        will not be encrypted and will be transmitted in the clear.
+        However, the receiver is still able to detect any modification to it.
+        In CCM, the *associated data* is also called
+        *additional authenticated data* (AAD).
+
+        If there is no associated data, this method must not be called.
+
+        The caller may split associated data in segments of any size, and
+        invoke this method multiple times, each time with the next segment.
+
+        :Parameters:
+          assoc_data : bytes/bytearray/memoryview
+            A piece of associated data. There are no restrictions on its size.
+        """
+
+        if self.update not in self._next:
+            raise TypeError("update() can only be called"
+                            " immediately after initialization")
+
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        self._cumul_assoc_len += len(assoc_data)
+        if self._assoc_len is not None and \
+           self._cumul_assoc_len > self._assoc_len:
+            raise ValueError("Associated data is too long")
+
+        self._update(assoc_data)
+        return self
+
+    def _update(self, assoc_data_pt=b""):
+        """Update the MAC with associated data or plaintext
+           (without FSM checks)"""
+
+        # If MAC has not started yet, we just park the data into a list.
+        # If the data is mutable, we create a copy and store that instead.
+        if self._mac_status == MacStatus.NOT_STARTED:
+            if is_writeable_buffer(assoc_data_pt):
+                assoc_data_pt = _copy_bytes(None, None, assoc_data_pt)
+            self._cache.append(assoc_data_pt)
+            return
+
+        assert(len(self._cache) < self.block_size)
+
+        if len(self._cache) > 0:
+            filler = min(self.block_size - len(self._cache),
+                         len(assoc_data_pt))
+            self._cache += _copy_bytes(None, filler, assoc_data_pt)
+            assoc_data_pt = _copy_bytes(filler, None, assoc_data_pt)
+
+            if len(self._cache) < self.block_size:
+                return
+
+            # The cache is exactly one block
+            self._t = self._mac.encrypt(self._cache)
+            self._cache = b""
+
+        update_len = len(assoc_data_pt) // self.block_size * self.block_size
+        self._cache = _copy_bytes(update_len, None, assoc_data_pt)
+        if update_len > 0:
+            self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:]
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        This method can be called only **once** if ``msg_len`` was
+        not passed at initialization.
+
+        If ``msg_len`` was given, the data to encrypt can be broken
+        up in two or more pieces and `encrypt` can be called
+        multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() can only be called after"
+                            " initialization or an update()")
+        self._next = [self.encrypt, self.digest]
+
+        # No more associated data allowed from now
+        if self._assoc_len is None:
+            assert(isinstance(self._cache, list))
+            self._assoc_len = sum([len(x) for x in self._cache])
+            if self._msg_len is not None:
+                self._start_mac()
+        else:
+            if self._cumul_assoc_len < self._assoc_len:
+                raise ValueError("Associated data is too short")
+
+        # Only once piece of plaintext accepted if message length was
+        # not declared in advance
+        if self._msg_len is None:
+            self._msg_len = len(plaintext)
+            self._start_mac()
+            self._next = [self.digest]
+
+        self._cumul_msg_len += len(plaintext)
+        if self._cumul_msg_len > self._msg_len:
+            raise ValueError("Message is too long")
+
+        if self._mac_status == MacStatus.PROCESSING_AUTH_DATA:
+            # Associated data is concatenated with the least number
+            # of zero bytes (possibly none) to reach alignment to
+            # the 16 byte boundary (A.2.3)
+            self._pad_cache_and_update()
+            self._mac_status = MacStatus.PROCESSING_PLAINTEXT
+
+        self._update(plaintext)
+        return self._cipher.encrypt(plaintext, output=output)
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt data with the key set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        This method can be called only **once** if ``msg_len`` was
+        not passed at initialization.
+
+        If ``msg_len`` was given, the data to decrypt can be
+        broken up in two or more pieces and `decrypt` can be
+        called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() can only be called"
+                            " after initialization or an update()")
+        self._next = [self.decrypt, self.verify]
+
+        # No more associated data allowed from now
+        if self._assoc_len is None:
+            assert(isinstance(self._cache, list))
+            self._assoc_len = sum([len(x) for x in self._cache])
+            if self._msg_len is not None:
+                self._start_mac()
+        else:
+            if self._cumul_assoc_len < self._assoc_len:
+                raise ValueError("Associated data is too short")
+
+        # Only once piece of ciphertext accepted if message length was
+        # not declared in advance
+        if self._msg_len is None:
+            self._msg_len = len(ciphertext)
+            self._start_mac()
+            self._next = [self.verify]
+
+        self._cumul_msg_len += len(ciphertext)
+        if self._cumul_msg_len > self._msg_len:
+            raise ValueError("Message is too long")
+
+        if self._mac_status == MacStatus.PROCESSING_AUTH_DATA:
+            # Associated data is concatenated with the least number
+            # of zero bytes (possibly none) to reach alignment to
+            # the 16 byte boundary (A.2.3)
+            self._pad_cache_and_update()
+            self._mac_status = MacStatus.PROCESSING_PLAINTEXT
+
+        # Encrypt is equivalent to decrypt with the CTR mode
+        plaintext = self._cipher.encrypt(ciphertext, output=output)
+        if output is None:
+            self._update(plaintext)
+        else:
+            self._update(output)
+        return plaintext
+
+    def digest(self):
+        """Compute the *binary* MAC tag.
+
+        The caller invokes this function at the very end.
+
+        This method returns the MAC that shall be sent to the receiver,
+        together with the ciphertext.
+
+        :Return: the MAC, as a byte string.
+        """
+
+        if self.digest not in self._next:
+            raise TypeError("digest() cannot be called when decrypting"
+                            " or validating a message")
+        self._next = [self.digest]
+        return self._digest()
+
+    def _digest(self):
+        if self._mac_tag:
+            return self._mac_tag
+
+        if self._assoc_len is None:
+            assert(isinstance(self._cache, list))
+            self._assoc_len = sum([len(x) for x in self._cache])
+            if self._msg_len is not None:
+                self._start_mac()
+        else:
+            if self._cumul_assoc_len < self._assoc_len:
+                raise ValueError("Associated data is too short")
+
+        if self._msg_len is None:
+            self._msg_len = 0
+            self._start_mac()
+
+        if self._cumul_msg_len != self._msg_len:
+            raise ValueError("Message is too short")
+
+        # Both associated data and payload are concatenated with the least
+        # number of zero bytes (possibly none) that align it to the
+        # 16 byte boundary (A.2.2 and A.2.3)
+        self._pad_cache_and_update()
+
+        # Step 8 in 6.1 (T xor MSB_Tlen(S_0))
+        self._mac_tag = strxor(self._t, self._s_0)[:self._mac_len]
+
+        return self._mac_tag
+
+    def hexdigest(self):
+        """Compute the *printable* MAC tag.
+
+        This method is like `digest`.
+
+        :Return: the MAC, as a hexadecimal string.
+        """
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def verify(self, received_mac_tag):
+        """Validate the *binary* MAC tag.
+
+        The caller invokes this function at the very end.
+
+        This method checks if the decrypted message is indeed valid
+        (that is, if the key is correct) and it has not been
+        tampered with while in transit.
+
+        :Parameters:
+          received_mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        if self.verify not in self._next:
+            raise TypeError("verify() cannot be called"
+                            " when encrypting a message")
+        self._next = [self.verify]
+
+        self._digest()
+        secret = get_random_bytes(16)
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Validate the *printable* MAC tag.
+
+        This method is like `verify`.
+
+        :Parameters:
+          hex_mac_tag : string
+            This is the *printable* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        self.verify(unhexlify(hex_mac_tag))
+
+    def encrypt_and_digest(self, plaintext, output=None):
+        """Perform encrypt() and digest() in one step.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+            a tuple with two items:
+
+            - the ciphertext, as ``bytes``
+            - the MAC tag, as ``bytes``
+
+            The first item becomes ``None`` when the ``output`` parameter
+            specified a location for the result.
+        """
+
+        return self.encrypt(plaintext, output=output), self.digest()
+
+    def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None):
+        """Perform decrypt() and verify() in one step.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+          received_mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+            parameter specified a location for the result.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        plaintext = self.decrypt(ciphertext, output=output)
+        self.verify(received_mac_tag)
+        return plaintext
+
+
+def _create_ccm_cipher(factory, **kwargs):
+    """Create a new block cipher, configured in CCM mode.
+
+    :Parameters:
+      factory : module
+        A symmetric cipher module from `Crypto.Cipher` (like
+        `Crypto.Cipher.AES`).
+
+    :Keywords:
+      key : bytes/bytearray/memoryview
+        The secret key to use in the symmetric cipher.
+
+      nonce : bytes/bytearray/memoryview
+        A value that must never be reused for any other encryption.
+
+        Its length must be in the range ``[7..13]``.
+        11 or 12 bytes are reasonable values in general. Bear in
+        mind that with CCM there is a trade-off between nonce length and
+        maximum message size.
+
+        If not specified, a 11 byte long random string is used.
+
+      mac_len : integer
+        Length of the MAC, in bytes. It must be even and in
+        the range ``[4..16]``. The default is 16.
+
+      msg_len : integer
+        Length of the message to (de)cipher.
+        If not specified, ``encrypt`` or ``decrypt`` may only be called once.
+
+      assoc_len : integer
+        Length of the associated data.
+        If not specified, all data is internally buffered.
+    """
+
+    try:
+        key = key = kwargs.pop("key")
+    except KeyError as e:
+        raise TypeError("Missing parameter: " + str(e))
+
+    nonce = kwargs.pop("nonce", None)  # N
+    if nonce is None:
+        nonce = get_random_bytes(11)
+    mac_len = kwargs.pop("mac_len", factory.block_size)
+    msg_len = kwargs.pop("msg_len", None)      # p
+    assoc_len = kwargs.pop("assoc_len", None)  # a
+    cipher_params = dict(kwargs)
+
+    return CcmMode(factory, key, nonce, mac_len, msg_len,
+                   assoc_len, cipher_params)

+ 47 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ccm.pyi

@@ -0,0 +1,47 @@
+from types import ModuleType
+from typing import Union, overload, Dict, Tuple, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['CcmMode']
+
+class CcmMode(object):
+    block_size: int
+    nonce: bytes
+
+    def __init__(self,
+                 factory: ModuleType,
+                 key: Buffer,
+                 nonce: Buffer,
+                 mac_len: int,
+                 msg_len: int,
+                 assoc_len: int,
+                 cipher_params: Dict) -> None: ...
+    
+    def update(self, assoc_data: Buffer) -> CcmMode: ...
+
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, received_mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer) -> Tuple[bytes, bytes]: ...
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer,
+                           output: Buffer) -> Tuple[None, bytes]: ...
+    def decrypt_and_verify(self,
+                           ciphertext: Buffer,
+                           received_mac_tag: Buffer,
+                           output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ...

+ 293 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_cfb.py

@@ -0,0 +1,293 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/mode_cfb.py : CFB mode
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""
+Counter Feedback (CFB) mode.
+"""
+
+__all__ = ['CfbMode']
+
+from tls.Crypto.Util.py3compat import _copy_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+                                  create_string_buffer, get_raw_buffer,
+                                  SmartPointer, c_size_t, c_uint8_ptr,
+                                  is_writeable_buffer)
+
+from tls.Crypto.Random import get_random_bytes
+
+raw_cfb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_cfb","""
+                    int CFB_start_operation(void *cipher,
+                                            const uint8_t iv[],
+                                            size_t iv_len,
+                                            size_t segment_len, /* In bytes */
+                                            void **pResult);
+                    int CFB_encrypt(void *cfbState,
+                                    const uint8_t *in,
+                                    uint8_t *out,
+                                    size_t data_len);
+                    int CFB_decrypt(void *cfbState,
+                                    const uint8_t *in,
+                                    uint8_t *out,
+                                    size_t data_len);
+                    int CFB_stop_operation(void *state);"""
+                    )
+
+
+class CfbMode(object):
+    """*Cipher FeedBack (CFB)*.
+
+    This mode is similar to CFB, but it transforms
+    the underlying block cipher into a stream cipher.
+
+    Plaintext and ciphertext are processed in *segments*
+    of **s** bits. The mode is therefore sometimes
+    labelled **s**-bit CFB.
+
+    An Initialization Vector (*IV*) is required.
+
+    See `NIST SP800-38A`_ , Section 6.3.
+
+    .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, block_cipher, iv, segment_size):
+        """Create a new block cipher, configured in CFB mode.
+
+        :Parameters:
+          block_cipher : C pointer
+            A smart pointer to the low-level block cipher instance.
+
+          iv : bytes/bytearray/memoryview
+            The initialization vector to use for encryption or decryption.
+            It is as long as the cipher block.
+
+            **The IV must be unpredictable**. Ideally it is picked randomly.
+
+            Reusing the *IV* for encryptions performed with the same key
+            compromises confidentiality.
+
+          segment_size : integer
+            The number of bytes the plaintext and ciphertext are segmented in.
+        """
+
+        self._state = VoidPointer()
+        result = raw_cfb_lib.CFB_start_operation(block_cipher.get(),
+                                                 c_uint8_ptr(iv),
+                                                 c_size_t(len(iv)),
+                                                 c_size_t(segment_size),
+                                                 self._state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating the CFB mode" % result)
+
+        # Ensure that object disposal of this Python object will (eventually)
+        # free the memory allocated by the raw library for the cipher mode
+        self._state = SmartPointer(self._state.get(),
+                                   raw_cfb_lib.CFB_stop_operation)
+
+        # Memory allocated for the underlying block cipher is now owed
+        # by the cipher mode
+        block_cipher.release()
+
+        self.block_size = len(iv)
+        """The block size of the underlying cipher, in bytes."""
+
+        self.iv = _copy_bytes(None, None, iv)
+        """The Initialization Vector originally used to create the object.
+        The value does not change."""
+
+        self.IV = self.iv
+        """Alias for `iv`"""
+
+        self._next = [ self.encrypt, self.decrypt ]
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() cannot be called after decrypt()")
+        self._next = [ self.encrypt ]
+        
+        if output is None:
+            ciphertext = create_string_buffer(len(plaintext))
+        else:
+            ciphertext = output
+            
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+        
+            if len(plaintext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_cfb_lib.CFB_encrypt(self._state.get(),
+                                         c_uint8_ptr(plaintext),
+                                         c_uint8_ptr(ciphertext),
+                                         c_size_t(len(plaintext)))
+        if result:
+            raise ValueError("Error %d while encrypting in CFB mode" % result)
+
+        if output is None:
+            return get_raw_buffer(ciphertext)
+        else:
+            return None
+
+    def decrypt(self, ciphertext,  output=None):
+        """Decrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() cannot be called after encrypt()")
+        self._next = [ self.decrypt ]
+        
+        if output is None:
+            plaintext = create_string_buffer(len(ciphertext))
+        else:
+            plaintext = output
+
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+            
+            if len(ciphertext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+        
+        result = raw_cfb_lib.CFB_decrypt(self._state.get(),
+                                         c_uint8_ptr(ciphertext),
+                                         c_uint8_ptr(plaintext),
+                                         c_size_t(len(ciphertext)))
+        if result:
+            raise ValueError("Error %d while decrypting in CFB mode" % result)
+
+        if output is None:
+            return get_raw_buffer(plaintext)
+        else:
+            return None
+
+
+def _create_cfb_cipher(factory, **kwargs):
+    """Instantiate a cipher object that performs CFB encryption/decryption.
+
+    :Parameters:
+      factory : module
+        The underlying block cipher, a module from ``Crypto.Cipher``.
+
+    :Keywords:
+      iv : bytes/bytearray/memoryview
+        The IV to use for CFB.
+
+      IV : bytes/bytearray/memoryview
+        Alias for ``iv``.
+
+      segment_size : integer
+        The number of bit the plaintext and ciphertext are segmented in.
+        If not present, the default is 8.
+
+    Any other keyword will be passed to the underlying block cipher.
+    See the relevant documentation for details (at least ``key`` will need
+    to be present).
+    """
+
+    cipher_state = factory._create_base_cipher(kwargs)
+
+    iv = kwargs.pop("IV", None)
+    IV = kwargs.pop("iv", None)
+
+    if (None, None) == (iv, IV):
+        iv = get_random_bytes(factory.block_size)
+    if iv is not None:
+        if IV is not None:
+            raise TypeError("You must either use 'iv' or 'IV', not both")
+    else:
+        iv = IV
+
+    if len(iv) != factory.block_size:
+        raise ValueError("Incorrect IV length (it must be %d bytes long)" %
+                factory.block_size)
+
+    segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8)
+    if segment_size_bytes == 0 or rem != 0:
+        raise ValueError("'segment_size' must be positive and multiple of 8 bits")
+
+    if kwargs:
+        raise TypeError("Unknown parameters for CFB: %s" % str(kwargs))
+    return CfbMode(cipher_state, iv, segment_size_bytes)

+ 26 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_cfb.pyi

@@ -0,0 +1,26 @@
+from typing import Union, overload
+
+from tls.Crypto.Util._raw_api import SmartPointer
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['CfbMode']
+
+
+class CfbMode(object):
+    block_size: int
+    iv: Buffer
+    IV: Buffer
+    
+    def __init__(self,
+                 block_cipher: SmartPointer,
+                 iv: Buffer,
+                 segment_size: int) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...

+ 393 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ctr.py

@@ -0,0 +1,393 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/mode_ctr.py : CTR mode
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""
+Counter (CTR) mode.
+"""
+
+__all__ = ['CtrMode']
+
+import struct
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+                                  create_string_buffer, get_raw_buffer,
+                                  SmartPointer, c_size_t, c_uint8_ptr,
+                                  is_writeable_buffer)
+
+from tls.Crypto.Random import get_random_bytes
+from tls.Crypto.Util.py3compat import _copy_bytes, is_native_int
+from tls.Crypto.Util.number import long_to_bytes
+
+raw_ctr_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ctr", """
+                    int CTR_start_operation(void *cipher,
+                                            uint8_t   initialCounterBlock[],
+                                            size_t    initialCounterBlock_len,
+                                            size_t    prefix_len,
+                                            unsigned  counter_len,
+                                            unsigned  littleEndian,
+                                            void **pResult);
+                    int CTR_encrypt(void *ctrState,
+                                    const uint8_t *in,
+                                    uint8_t *out,
+                                    size_t data_len);
+                    int CTR_decrypt(void *ctrState,
+                                    const uint8_t *in,
+                                    uint8_t *out,
+                                    size_t data_len);
+                    int CTR_stop_operation(void *ctrState);"""
+                                        )
+
+
+class CtrMode(object):
+    """*CounTeR (CTR)* mode.
+
+    This mode is very similar to ECB, in that
+    encryption of one block is done independently of all other blocks.
+
+    Unlike ECB, the block *position* contributes to the encryption
+    and no information leaks about symbol frequency.
+
+    Each message block is associated to a *counter* which
+    must be unique across all messages that get encrypted
+    with the same key (not just within the same message).
+    The counter is as big as the block size.
+
+    Counters can be generated in several ways. The most
+    straightword one is to choose an *initial counter block*
+    (which can be made public, similarly to the *IV* for the
+    other modes) and increment its lowest **m** bits by one
+    (modulo *2^m*) for each block. In most cases, **m** is
+    chosen to be half the block size.
+
+    See `NIST SP800-38A`_, Section 6.5 (for the mode) and
+    Appendix B (for how to manage the *initial counter block*).
+
+    .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, block_cipher, initial_counter_block,
+                 prefix_len, counter_len, little_endian):
+        """Create a new block cipher, configured in CTR mode.
+
+        :Parameters:
+          block_cipher : C pointer
+            A smart pointer to the low-level block cipher instance.
+
+          initial_counter_block : bytes/bytearray/memoryview
+            The initial plaintext to use to generate the key stream.
+
+            It is as large as the cipher block, and it embeds
+            the initial value of the counter.
+
+            This value must not be reused.
+            It shall contain a nonce or a random component.
+            Reusing the *initial counter block* for encryptions
+            performed with the same key compromises confidentiality.
+
+          prefix_len : integer
+            The amount of bytes at the beginning of the counter block
+            that never change.
+
+          counter_len : integer
+            The length in bytes of the counter embedded in the counter
+            block.
+
+          little_endian : boolean
+            True if the counter in the counter block is an integer encoded
+            in little endian mode. If False, it is big endian.
+        """
+
+        if len(initial_counter_block) == prefix_len + counter_len:
+            self.nonce = _copy_bytes(None, prefix_len, initial_counter_block)
+            """Nonce; not available if there is a fixed suffix"""
+
+        self._state = VoidPointer()
+        result = raw_ctr_lib.CTR_start_operation(block_cipher.get(),
+                                                 c_uint8_ptr(initial_counter_block),
+                                                 c_size_t(len(initial_counter_block)),
+                                                 c_size_t(prefix_len),
+                                                 counter_len,
+                                                 little_endian,
+                                                 self._state.address_of())
+        if result:
+            raise ValueError("Error %X while instantiating the CTR mode"
+                             % result)
+
+        # Ensure that object disposal of this Python object will (eventually)
+        # free the memory allocated by the raw library for the cipher mode
+        self._state = SmartPointer(self._state.get(),
+                                   raw_ctr_lib.CTR_stop_operation)
+
+        # Memory allocated for the underlying block cipher is now owed
+        # by the cipher mode
+        block_cipher.release()
+
+        self.block_size = len(initial_counter_block)
+        """The block size of the underlying cipher, in bytes."""
+
+        self._next = [self.encrypt, self.decrypt]
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() cannot be called after decrypt()")
+        self._next = [self.encrypt]
+        
+        if output is None:
+            ciphertext = create_string_buffer(len(plaintext))
+        else:
+            ciphertext = output
+            
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+        
+            if len(plaintext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_ctr_lib.CTR_encrypt(self._state.get(),
+                                         c_uint8_ptr(plaintext),
+                                         c_uint8_ptr(ciphertext),
+                                         c_size_t(len(plaintext)))
+        if result:
+            if result == 0x60002:
+                raise OverflowError("The counter has wrapped around in"
+                                    " CTR mode")
+            raise ValueError("Error %X while encrypting in CTR mode" % result)
+        
+        if output is None:
+            return get_raw_buffer(ciphertext)
+        else:
+            return None
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() cannot be called after encrypt()")
+        self._next = [self.decrypt]
+        
+        if output is None:
+            plaintext = create_string_buffer(len(ciphertext))
+        else:
+            plaintext = output
+
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+            
+            if len(ciphertext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+
+        result = raw_ctr_lib.CTR_decrypt(self._state.get(),
+                                         c_uint8_ptr(ciphertext),
+                                         c_uint8_ptr(plaintext),
+                                         c_size_t(len(ciphertext)))
+        if result:
+            if result == 0x60002:
+                raise OverflowError("The counter has wrapped around in"
+                                    " CTR mode")
+            raise ValueError("Error %X while decrypting in CTR mode" % result)
+        
+        if output is None:
+            return get_raw_buffer(plaintext)
+        else:
+            return None
+
+
+def _create_ctr_cipher(factory, **kwargs):
+    """Instantiate a cipher object that performs CTR encryption/decryption.
+
+    :Parameters:
+      factory : module
+        The underlying block cipher, a module from ``Crypto.Cipher``.
+
+    :Keywords:
+      nonce : bytes/bytearray/memoryview
+        The fixed part at the beginning of the counter block - the rest is
+        the counter number that gets increased when processing the next block.
+        The nonce must be such that no two messages are encrypted under the
+        same key and the same nonce.
+
+        The nonce must be shorter than the block size (it can have
+        zero length; the counter is then as long as the block).
+
+        If this parameter is not present, a random nonce will be created with
+        length equal to half the block size. No random nonce shorter than
+        64 bits will be created though - you must really think through all
+        security consequences of using such a short block size.
+
+      initial_value : posive integer or bytes/bytearray/memoryview
+        The initial value for the counter. If not present, the cipher will
+        start counting from 0. The value is incremented by one for each block.
+        The counter number is encoded in big endian mode.
+
+      counter : object
+        Instance of ``Crypto.Util.Counter``, which allows full customization
+        of the counter block. This parameter is incompatible to both ``nonce``
+        and ``initial_value``.
+
+    Any other keyword will be passed to the underlying block cipher.
+    See the relevant documentation for details (at least ``key`` will need
+    to be present).
+    """
+
+    cipher_state = factory._create_base_cipher(kwargs)
+
+    counter = kwargs.pop("counter", None)
+    nonce = kwargs.pop("nonce", None)
+    initial_value = kwargs.pop("initial_value", None)
+    if kwargs:
+        raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs))
+
+    if counter is not None and (nonce, initial_value) != (None, None):
+            raise TypeError("'counter' and 'nonce'/'initial_value'"
+                            " are mutually exclusive")
+
+    if counter is None:
+        # Crypto.Util.Counter is not used
+        if nonce is None:
+            if factory.block_size < 16:
+                raise TypeError("Impossible to create a safe nonce for short"
+                                " block sizes")
+            nonce = get_random_bytes(factory.block_size // 2)
+        else:
+            if len(nonce) >= factory.block_size:
+                raise ValueError("Nonce is too long")
+        
+        # What is not nonce is counter
+        counter_len = factory.block_size - len(nonce)
+
+        if initial_value is None:
+            initial_value = 0
+
+        if is_native_int(initial_value):
+            if (1 << (counter_len * 8)) - 1 < initial_value:
+                raise ValueError("Initial counter value is too large")
+            initial_counter_block = nonce + long_to_bytes(initial_value, counter_len)
+        else:
+            if len(initial_value) != counter_len:
+                raise ValueError("Incorrect length for counter byte string (%d bytes, expected %d)" % (len(initial_value), counter_len))
+            initial_counter_block = nonce + initial_value
+
+        return CtrMode(cipher_state,
+                       initial_counter_block,
+                       len(nonce),                     # prefix
+                       counter_len,
+                       False)                          # little_endian
+
+    # Crypto.Util.Counter is used
+
+    # 'counter' used to be a callable object, but now it is
+    # just a dictionary for backward compatibility.
+    _counter = dict(counter)
+    try:
+        counter_len = _counter.pop("counter_len")
+        prefix = _counter.pop("prefix")
+        suffix = _counter.pop("suffix")
+        initial_value = _counter.pop("initial_value")
+        little_endian = _counter.pop("little_endian")
+    except KeyError:
+        raise TypeError("Incorrect counter object"
+                        " (use Crypto.Util.Counter.new)")
+
+    # Compute initial counter block
+    words = []
+    while initial_value > 0:
+        words.append(struct.pack('B', initial_value & 255))
+        initial_value >>= 8
+    words += [ b'\x00' ] * max(0, counter_len - len(words))
+    if not little_endian:
+        words.reverse()
+    initial_counter_block = prefix + b"".join(words) + suffix
+
+    if len(initial_counter_block) != factory.block_size:
+        raise ValueError("Size of the counter block (%d bytes) must match"
+                         " block size (%d)" % (len(initial_counter_block),
+                                               factory.block_size))
+
+    return CtrMode(cipher_state, initial_counter_block,
+                   len(prefix), counter_len, little_endian)

+ 27 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ctr.pyi

@@ -0,0 +1,27 @@
+from typing import Union, overload
+
+from tls.Crypto.Util._raw_api import SmartPointer
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['CtrMode']
+
+class CtrMode(object):
+    block_size: int
+    nonce: bytes
+
+    def __init__(self,
+                 block_cipher: SmartPointer,
+                 initial_counter_block: Buffer,
+                 prefix_len: int,
+                 counter_len: int,
+                 little_endian: bool) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+

+ 408 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_eax.py

@@ -0,0 +1,408 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+EAX mode.
+"""
+
+__all__ = ['EaxMode']
+
+import struct
+from binascii import unhexlify
+
+from tls.Crypto.Util.py3compat import byte_string, bord, _copy_bytes
+
+from tls.Crypto.Util._raw_api import is_buffer
+
+from tls.Crypto.Util.strxor import strxor
+from tls.Crypto.Util.number import long_to_bytes, bytes_to_long
+
+from tls.Crypto.Hash import CMAC, BLAKE2s
+from tls.Crypto.Random import get_random_bytes
+
+
+class EaxMode(object):
+    """*EAX* mode.
+
+    This is an Authenticated Encryption with Associated Data
+    (`AEAD`_) mode. It provides both confidentiality and authenticity.
+
+    The header of the message may be left in the clear, if needed,
+    and it will still be subject to authentication.
+
+    The decryption step tells the receiver if the message comes
+    from a source that really knowns the secret key.
+    Additionally, decryption detects if any part of the message -
+    including the header - has been modified or corrupted.
+
+    This mode requires a *nonce*.
+
+    This mode is only available for ciphers that operate on 64 or
+    128 bits blocks.
+
+    There are no official standards defining EAX.
+    The implementation is based on `a proposal`__ that
+    was presented to NIST.
+
+    .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
+    .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, factory, key, nonce, mac_len, cipher_params):
+        """EAX cipher mode"""
+
+        self.block_size = factory.block_size
+        """The block size of the underlying cipher, in bytes."""
+
+        self.nonce = _copy_bytes(None, None, nonce)
+        """The nonce originally used to create the object."""
+
+        self._mac_len = mac_len
+        self._mac_tag = None  # Cache for MAC tag
+
+        # Allowed transitions after initialization
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        # MAC tag length
+        if not (4 <= self._mac_len <= self.block_size):
+            raise ValueError("Parameter 'mac_len' must not be larger than %d"
+                             % self.block_size)
+
+        # Nonce cannot be empty and must be a byte string
+        if len(self.nonce) == 0:
+            raise ValueError("Nonce cannot be empty in EAX mode")
+        if not is_buffer(nonce):
+            raise TypeError("nonce must be bytes, bytearray or memoryview")
+
+        self._omac = [
+                CMAC.new(key,
+                         b'\x00' * (self.block_size - 1) + struct.pack('B', i),
+                         ciphermod=factory,
+                         cipher_params=cipher_params)
+                for i in range(0, 3)
+                ]
+
+        # Compute MAC of nonce
+        self._omac[0].update(self.nonce)
+        self._signer = self._omac[1]
+
+        # MAC of the nonce is also the initial counter for CTR encryption
+        counter_int = bytes_to_long(self._omac[0].digest())
+        self._cipher = factory.new(key,
+                                   factory.MODE_CTR,
+                                   initial_value=counter_int,
+                                   nonce=b"",
+                                   **cipher_params)
+
+    def update(self, assoc_data):
+        """Protect associated data
+
+        If there is any associated data, the caller has to invoke
+        this function one or more times, before using
+        ``decrypt`` or ``encrypt``.
+
+        By *associated data* it is meant any data (e.g. packet headers) that
+        will not be encrypted and will be transmitted in the clear.
+        However, the receiver is still able to detect any modification to it.
+
+        If there is no associated data, this method must not be called.
+
+        The caller may split associated data in segments of any size, and
+        invoke this method multiple times, each time with the next segment.
+
+        :Parameters:
+          assoc_data : bytes/bytearray/memoryview
+            A piece of associated data. There are no restrictions on its size.
+        """
+
+        if self.update not in self._next:
+            raise TypeError("update() can only be called"
+                                " immediately after initialization")
+
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        self._signer.update(assoc_data)
+        return self
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() can only be called after"
+                            " initialization or an update()")
+        self._next = [self.encrypt, self.digest]
+        ct = self._cipher.encrypt(plaintext, output=output)
+        if output is None:
+            self._omac[2].update(ct)
+        else:
+            self._omac[2].update(output)
+        return ct
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() can only be called"
+                            " after initialization or an update()")
+        self._next = [self.decrypt, self.verify]
+        self._omac[2].update(ciphertext)
+        return self._cipher.decrypt(ciphertext, output=output)
+
+    def digest(self):
+        """Compute the *binary* MAC tag.
+
+        The caller invokes this function at the very end.
+
+        This method returns the MAC that shall be sent to the receiver,
+        together with the ciphertext.
+
+        :Return: the MAC, as a byte string.
+        """
+
+        if self.digest not in self._next:
+            raise TypeError("digest() cannot be called when decrypting"
+                                " or validating a message")
+        self._next = [self.digest]
+
+        if not self._mac_tag:
+            tag = b'\x00' * self.block_size
+            for i in range(3):
+                tag = strxor(tag, self._omac[i].digest())
+            self._mac_tag = tag[:self._mac_len]
+
+        return self._mac_tag
+
+    def hexdigest(self):
+        """Compute the *printable* MAC tag.
+
+        This method is like `digest`.
+
+        :Return: the MAC, as a hexadecimal string.
+        """
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def verify(self, received_mac_tag):
+        """Validate the *binary* MAC tag.
+
+        The caller invokes this function at the very end.
+
+        This method checks if the decrypted message is indeed valid
+        (that is, if the key is correct) and it has not been
+        tampered with while in transit.
+
+        :Parameters:
+          received_mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Raises MacMismatchError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        if self.verify not in self._next:
+            raise TypeError("verify() cannot be called"
+                                " when encrypting a message")
+        self._next = [self.verify]
+
+        if not self._mac_tag:
+            tag = b'\x00' * self.block_size
+            for i in range(3):
+                tag = strxor(tag, self._omac[i].digest())
+            self._mac_tag = tag[:self._mac_len]
+
+        secret = get_random_bytes(16)
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Validate the *printable* MAC tag.
+
+        This method is like `verify`.
+
+        :Parameters:
+          hex_mac_tag : string
+            This is the *printable* MAC, as received from the sender.
+        :Raises MacMismatchError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        self.verify(unhexlify(hex_mac_tag))
+
+    def encrypt_and_digest(self, plaintext, output=None):
+        """Perform encrypt() and digest() in one step.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+            a tuple with two items:
+
+            - the ciphertext, as ``bytes``
+            - the MAC tag, as ``bytes``
+
+            The first item becomes ``None`` when the ``output`` parameter
+            specified a location for the result.
+        """
+
+        return self.encrypt(plaintext, output=output), self.digest()
+
+    def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None):
+        """Perform decrypt() and verify() in one step.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+          received_mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+            parameter specified a location for the result.
+        :Raises MacMismatchError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        pt = self.decrypt(ciphertext, output=output)
+        self.verify(received_mac_tag)
+        return pt
+
+
+def _create_eax_cipher(factory, **kwargs):
+    """Create a new block cipher, configured in EAX mode.
+
+    :Parameters:
+      factory : module
+        A symmetric cipher module from `Crypto.Cipher` (like
+        `Crypto.Cipher.AES`).
+
+    :Keywords:
+      key : bytes/bytearray/memoryview
+        The secret key to use in the symmetric cipher.
+
+      nonce : bytes/bytearray/memoryview
+        A value that must never be reused for any other encryption.
+        There are no restrictions on its length, but it is recommended to use
+        at least 16 bytes.
+
+        The nonce shall never repeat for two different messages encrypted with
+        the same key, but it does not need to be random.
+
+        If not specified, a 16 byte long random string is used.
+
+      mac_len : integer
+        Length of the MAC, in bytes. It must be no larger than the cipher
+        block bytes (which is the default).
+    """
+
+    try:
+        key = kwargs.pop("key")
+        nonce = kwargs.pop("nonce", None)
+        if nonce is None:
+            nonce = get_random_bytes(16)
+        mac_len = kwargs.pop("mac_len", factory.block_size)
+    except KeyError as e:
+        raise TypeError("Missing parameter: " + str(e))
+
+    return EaxMode(factory, key, nonce, mac_len, kwargs)

+ 45 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_eax.pyi

@@ -0,0 +1,45 @@
+from types import ModuleType
+from typing import Any, Union, Tuple, Dict, overload, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['EaxMode']
+
+class EaxMode(object):
+    block_size: int
+    nonce: bytes
+    
+    def __init__(self,
+                 factory: ModuleType,
+                 key: Buffer,
+                 nonce: Buffer,
+                 mac_len: int,
+                 cipher_params: Dict) -> None: ...
+    
+    def update(self, assoc_data: Buffer) -> EaxMode: ...
+
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, received_mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer) -> Tuple[bytes, bytes]: ...
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer,
+                           output: Buffer) -> Tuple[None, bytes]: ...
+    def decrypt_and_verify(self,
+                           ciphertext: Buffer,
+                           received_mac_tag: Buffer,
+                           output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ...

+ 218 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ecb.py

@@ -0,0 +1,218 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/mode_ecb.py : ECB mode
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""
+Electronic Code Book (ECB) mode.
+"""
+
+__all__ = [ 'EcbMode' ]
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, create_string_buffer,
+                                  get_raw_buffer, SmartPointer,
+                                  c_size_t, c_uint8_ptr,
+                                  is_writeable_buffer)
+
+raw_ecb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ecb", """
+                    int ECB_start_operation(void *cipher,
+                                            void **pResult);
+                    int ECB_encrypt(void *ecbState,
+                                    const uint8_t *in,
+                                    uint8_t *out,
+                                    size_t data_len);
+                    int ECB_decrypt(void *ecbState,
+                                    const uint8_t *in,
+                                    uint8_t *out,
+                                    size_t data_len);
+                    int ECB_stop_operation(void *state);
+                    """
+                                        )
+
+
+class EcbMode(object):
+    """*Electronic Code Book (ECB)*.
+
+    This is the simplest encryption mode. Each of the plaintext blocks
+    is directly encrypted into a ciphertext block, independently of
+    any other block.
+
+    This mode is dangerous because it exposes frequency of symbols
+    in your plaintext. Other modes (e.g. *CBC*) should be used instead.
+
+    See `NIST SP800-38A`_ , Section 6.1.
+
+    .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, block_cipher):
+        """Create a new block cipher, configured in ECB mode.
+
+        :Parameters:
+          block_cipher : C pointer
+            A smart pointer to the low-level block cipher instance.
+        """
+
+        self._state = VoidPointer()
+        result = raw_ecb_lib.ECB_start_operation(block_cipher.get(),
+                                                 self._state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating the ECB mode"
+                             % result)
+
+        # Ensure that object disposal of this Python object will (eventually)
+        # free the memory allocated by the raw library for the cipher
+        # mode
+        self._state = SmartPointer(self._state.get(),
+                                   raw_ecb_lib.ECB_stop_operation)
+
+        # Memory allocated for the underlying block cipher is now owned
+        # by the cipher mode
+        block_cipher.release()
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key set at initialization.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            The length must be multiple of the cipher block length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if output is None:
+            ciphertext = create_string_buffer(len(plaintext))
+        else:
+            ciphertext = output
+            
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+        
+            if len(plaintext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_ecb_lib.ECB_encrypt(self._state.get(),
+                                         c_uint8_ptr(plaintext),
+                                         c_uint8_ptr(ciphertext),
+                                         c_size_t(len(plaintext)))
+        if result:
+            if result == 3:
+                raise ValueError("Data must be aligned to block boundary in ECB mode")
+            raise ValueError("Error %d while encrypting in ECB mode" % result)
+        
+        if output is None:
+            return get_raw_buffer(ciphertext)
+        else:
+            return None
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt data with the key set at initialization.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            The length must be multiple of the cipher block length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+        
+        if output is None:
+            plaintext = create_string_buffer(len(ciphertext))
+        else:
+            plaintext = output
+
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+            
+            if len(ciphertext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_ecb_lib.ECB_decrypt(self._state.get(),
+                                         c_uint8_ptr(ciphertext),
+                                         c_uint8_ptr(plaintext),
+                                         c_size_t(len(ciphertext)))
+        if result:
+            if result == 3:
+                raise ValueError("Data must be aligned to block boundary in ECB mode")
+            raise ValueError("Error %d while decrypting in ECB mode" % result)
+
+        if output is None:
+            return get_raw_buffer(plaintext)
+        else:
+            return None
+
+
+def _create_ecb_cipher(factory, **kwargs):
+    """Instantiate a cipher object that performs ECB encryption/decryption.
+
+    :Parameters:
+      factory : module
+        The underlying block cipher, a module from ``Crypto.Cipher``.
+
+    All keywords are passed to the underlying block cipher.
+    See the relevant documentation for details (at least ``key`` will need
+    to be present"""
+
+    cipher_state = factory._create_base_cipher(kwargs)
+    if kwargs:
+        raise TypeError("Unknown parameters for ECB: %s" % str(kwargs))
+    return EcbMode(cipher_state)

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ecb.pyi

@@ -0,0 +1,19 @@
+from typing import Union, overload
+
+from tls.Crypto.Util._raw_api import SmartPointer
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = [ 'EcbMode' ]
+
+class EcbMode(object):
+    def __init__(self, block_cipher: SmartPointer) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+

+ 620 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_gcm.py

@@ -0,0 +1,620 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+Galois/Counter Mode (GCM).
+"""
+
+__all__ = ['GcmMode']
+
+from binascii import unhexlify
+
+from tls.Crypto.Util.py3compat import bord, _copy_bytes
+
+from tls.Crypto.Util._raw_api import is_buffer
+
+from tls.Crypto.Util.number import long_to_bytes, bytes_to_long
+from tls.Crypto.Hash import BLAKE2s
+from tls.Crypto.Random import get_random_bytes
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+                                  create_string_buffer, get_raw_buffer,
+                                  SmartPointer, c_size_t, c_uint8_ptr)
+
+from tls.Crypto.Util import _cpu_features
+
+
+# C API by module implementing GHASH
+_ghash_api_template = """
+    int ghash_%imp%(uint8_t y_out[16],
+                    const uint8_t block_data[],
+                    size_t len,
+                    const uint8_t y_in[16],
+                    const void *exp_key);
+    int ghash_expand_%imp%(const uint8_t h[16],
+                           void **ghash_tables);
+    int ghash_destroy_%imp%(void *ghash_tables);
+"""
+
+def _build_impl(lib, postfix):
+    from collections import namedtuple
+
+    funcs = ( "ghash", "ghash_expand", "ghash_destroy" )
+    GHASH_Imp = namedtuple('_GHash_Imp', funcs)
+    try:
+        imp_funcs = [ getattr(lib, x + "_" + postfix) for x in funcs ]
+    except AttributeError:      # Make sphinx stop complaining with its mocklib
+        imp_funcs = [ None ] * 3
+    params = dict(zip(funcs, imp_funcs))
+    return GHASH_Imp(**params)
+
+
+def _get_ghash_portable():
+    api = _ghash_api_template.replace("%imp%", "portable")
+    lib = load_pycryptodome_raw_lib("Crypto.Hash._ghash_portable", api)
+    result = _build_impl(lib, "portable")
+    return result
+_ghash_portable = _get_ghash_portable()
+
+
+def _get_ghash_clmul():
+    """Return None if CLMUL implementation is not available"""
+
+    if not _cpu_features.have_clmul():
+        return None
+    try:
+        api = _ghash_api_template.replace("%imp%", "clmul")
+        lib = load_pycryptodome_raw_lib("Crypto.Hash._ghash_clmul", api)
+        result = _build_impl(lib, "clmul")
+    except OSError:
+        result = None
+    return result
+_ghash_clmul = _get_ghash_clmul()
+
+
+class _GHASH(object):
+    """GHASH function defined in NIST SP 800-38D, Algorithm 2.
+
+    If X_1, X_2, .. X_m are the blocks of input data, the function
+    computes:
+
+       X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H
+
+    in the Galois field GF(2^256) using the reducing polynomial
+    (x^128 + x^7 + x^2 + x + 1).
+    """
+
+    def __init__(self, subkey, ghash_c):
+        assert len(subkey) == 16
+
+        self.ghash_c = ghash_c
+
+        self._exp_key = VoidPointer()
+        result = ghash_c.ghash_expand(c_uint8_ptr(subkey),
+                                      self._exp_key.address_of())
+        if result:
+            raise ValueError("Error %d while expanding the GHASH key" % result)
+
+        self._exp_key = SmartPointer(self._exp_key.get(),
+                                     ghash_c.ghash_destroy)
+
+        # create_string_buffer always returns a string of zeroes
+        self._last_y = create_string_buffer(16)
+
+    def update(self, block_data):
+        assert len(block_data) % 16 == 0
+
+        result = self.ghash_c.ghash(self._last_y,
+                                    c_uint8_ptr(block_data),
+                                    c_size_t(len(block_data)),
+                                    self._last_y,
+                                    self._exp_key.get())
+        if result:
+            raise ValueError("Error %d while updating GHASH" % result)
+
+        return self
+
+    def digest(self):
+        return get_raw_buffer(self._last_y)
+
+
+def enum(**enums):
+    return type('Enum', (), enums)
+
+
+MacStatus = enum(PROCESSING_AUTH_DATA=1, PROCESSING_CIPHERTEXT=2)
+
+
+class GcmMode(object):
+    """Galois Counter Mode (GCM).
+
+    This is an Authenticated Encryption with Associated Data (`AEAD`_) mode.
+    It provides both confidentiality and authenticity.
+
+    The header of the message may be left in the clear, if needed, and it will
+    still be subject to authentication. The decryption step tells the receiver
+    if the message comes from a source that really knowns the secret key.
+    Additionally, decryption detects if any part of the message - including the
+    header - has been modified or corrupted.
+
+    This mode requires a *nonce*.
+
+    This mode is only available for ciphers that operate on 128 bits blocks
+    (e.g. AES but not TDES).
+
+    See `NIST SP800-38D`_.
+
+    .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+    .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, factory, key, nonce, mac_len, cipher_params, ghash_c):
+
+        self.block_size = factory.block_size
+        if self.block_size != 16:
+            raise ValueError("GCM mode is only available for ciphers"
+                             " that operate on 128 bits blocks")
+
+        if len(nonce) == 0:
+            raise ValueError("Nonce cannot be empty")
+        
+        if not is_buffer(nonce):
+            raise TypeError("Nonce must be bytes, bytearray or memoryview")
+
+        # See NIST SP 800 38D, 5.2.1.1
+        if len(nonce) > 2**64 - 1:
+            raise ValueError("Nonce exceeds maximum length")
+
+
+        self.nonce = _copy_bytes(None, None, nonce)
+        """Nonce"""
+
+        self._factory = factory
+        self._key = _copy_bytes(None, None, key)
+        self._tag = None  # Cache for MAC tag
+
+        self._mac_len = mac_len
+        if not (4 <= mac_len <= 16):
+            raise ValueError("Parameter 'mac_len' must be in the range 4..16")
+
+        # Allowed transitions after initialization
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        self._no_more_assoc_data = False
+
+        # Length of associated data
+        self._auth_len = 0
+
+        # Length of the ciphertext or plaintext
+        self._msg_len = 0
+
+        # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H
+        # See also Algorithm 5 (decryption)
+        hash_subkey = factory.new(key,
+                                  self._factory.MODE_ECB,
+                                  **cipher_params
+                                  ).encrypt(b'\x00' * 16)
+
+        # Step 2 - Compute J0
+        if len(self.nonce) == 12:
+            j0 = self.nonce + b"\x00\x00\x00\x01"
+        else:
+            fill = (16 - (len(nonce) % 16)) % 16 + 8
+            ghash_in = (self.nonce +
+                        b'\x00' * fill +
+                        long_to_bytes(8 * len(nonce), 8))
+            j0 = _GHASH(hash_subkey, ghash_c).update(ghash_in).digest()
+
+        # Step 3 - Prepare GCTR cipher for encryption/decryption
+        nonce_ctr = j0[:12]
+        iv_ctr = (bytes_to_long(j0) + 1) & 0xFFFFFFFF
+        self._cipher = factory.new(key,
+                                   self._factory.MODE_CTR,
+                                   initial_value=iv_ctr,
+                                   nonce=nonce_ctr,
+                                   **cipher_params)
+
+        # Step 5 - Bootstrat GHASH
+        self._signer = _GHASH(hash_subkey, ghash_c)
+
+        # Step 6 - Prepare GCTR cipher for GMAC
+        self._tag_cipher = factory.new(key,
+                                       self._factory.MODE_CTR,
+                                       initial_value=j0,
+                                       nonce=b"",
+                                       **cipher_params)
+
+        # Cache for data to authenticate
+        self._cache = b""
+
+        self._status = MacStatus.PROCESSING_AUTH_DATA
+
+    def update(self, assoc_data):
+        """Protect associated data
+
+        If there is any associated data, the caller has to invoke
+        this function one or more times, before using
+        ``decrypt`` or ``encrypt``.
+
+        By *associated data* it is meant any data (e.g. packet headers) that
+        will not be encrypted and will be transmitted in the clear.
+        However, the receiver is still able to detect any modification to it.
+        In GCM, the *associated data* is also called
+        *additional authenticated data* (AAD).
+
+        If there is no associated data, this method must not be called.
+
+        The caller may split associated data in segments of any size, and
+        invoke this method multiple times, each time with the next segment.
+
+        :Parameters:
+          assoc_data : bytes/bytearray/memoryview
+            A piece of associated data. There are no restrictions on its size.
+        """
+
+        if self.update not in self._next:
+            raise TypeError("update() can only be called"
+                            " immediately after initialization")
+
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        self._update(assoc_data)
+        self._auth_len += len(assoc_data)
+
+        # See NIST SP 800 38D, 5.2.1.1
+        if self._auth_len > 2**64 - 1:
+            raise ValueError("Additional Authenticated Data exceeds maximum length")
+
+        return self
+
+    def _update(self, data):
+        assert(len(self._cache) < 16)
+
+        if len(self._cache) > 0:
+            filler = min(16 - len(self._cache), len(data))
+            self._cache += _copy_bytes(None, filler, data)
+            data = data[filler:]
+
+            if len(self._cache) < 16:
+                return
+
+            # The cache is exactly one block
+            self._signer.update(self._cache)
+            self._cache = b""
+
+        update_len = len(data) // 16 * 16
+        self._cache = _copy_bytes(update_len, None, data)
+        if update_len > 0:
+            self._signer.update(data[:update_len])
+
+    def _pad_cache_and_update(self):
+        assert(len(self._cache) < 16)
+
+        # The authenticated data A is concatenated to the minimum
+        # number of zero bytes (possibly none) such that the
+        # - ciphertext C is aligned to the 16 byte boundary.
+        #   See step 5 in section 7.1
+        # - ciphertext C is aligned to the 16 byte boundary.
+        #   See step 6 in section 7.2
+        len_cache = len(self._cache)
+        if len_cache > 0:
+            self._update(b'\x00' * (16 - len_cache))
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() can only be called after"
+                            " initialization or an update()")
+        self._next = [self.encrypt, self.digest]
+
+        ciphertext = self._cipher.encrypt(plaintext, output=output)
+
+        if self._status == MacStatus.PROCESSING_AUTH_DATA:
+            self._pad_cache_and_update()
+            self._status = MacStatus.PROCESSING_CIPHERTEXT
+
+        self._update(ciphertext if output is None else output)
+        self._msg_len += len(plaintext)
+
+        # See NIST SP 800 38D, 5.2.1.1
+        if self._msg_len > 2**39 - 256:
+            raise ValueError("Plaintext exceeds maximum length")
+
+        return ciphertext
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() can only be called"
+                            " after initialization or an update()")
+        self._next = [self.decrypt, self.verify]
+
+        if self._status == MacStatus.PROCESSING_AUTH_DATA:
+            self._pad_cache_and_update()
+            self._status = MacStatus.PROCESSING_CIPHERTEXT
+
+        self._update(ciphertext)
+        self._msg_len += len(ciphertext)
+
+        return self._cipher.decrypt(ciphertext, output=output)
+
+    def digest(self):
+        """Compute the *binary* MAC tag in an AEAD mode.
+
+        The caller invokes this function at the very end.
+
+        This method returns the MAC that shall be sent to the receiver,
+        together with the ciphertext.
+
+        :Return: the MAC, as a byte string.
+        """
+
+        if self.digest not in self._next:
+            raise TypeError("digest() cannot be called when decrypting"
+                            " or validating a message")
+        self._next = [self.digest]
+
+        return self._compute_mac()
+
+    def _compute_mac(self):
+        """Compute MAC without any FSM checks."""
+
+        if self._tag:
+            return self._tag
+
+        # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S
+        self._pad_cache_and_update()
+        self._update(long_to_bytes(8 * self._auth_len, 8))
+        self._update(long_to_bytes(8 * self._msg_len, 8))
+        s_tag = self._signer.digest()
+
+        # Step 6 - Compute T
+        self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len]
+
+        return self._tag
+
+    def hexdigest(self):
+        """Compute the *printable* MAC tag.
+
+        This method is like `digest`.
+
+        :Return: the MAC, as a hexadecimal string.
+        """
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def verify(self, received_mac_tag):
+        """Validate the *binary* MAC tag.
+
+        The caller invokes this function at the very end.
+
+        This method checks if the decrypted message is indeed valid
+        (that is, if the key is correct) and it has not been
+        tampered with while in transit.
+
+        :Parameters:
+          received_mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        if self.verify not in self._next:
+            raise TypeError("verify() cannot be called"
+                            " when encrypting a message")
+        self._next = [self.verify]
+
+        secret = get_random_bytes(16)
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret,
+                           data=self._compute_mac())
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret,
+                           data=received_mac_tag)
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Validate the *printable* MAC tag.
+
+        This method is like `verify`.
+
+        :Parameters:
+          hex_mac_tag : string
+            This is the *printable* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        self.verify(unhexlify(hex_mac_tag))
+
+    def encrypt_and_digest(self, plaintext, output=None):
+        """Perform encrypt() and digest() in one step.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+            a tuple with two items:
+
+            - the ciphertext, as ``bytes``
+            - the MAC tag, as ``bytes``
+
+            The first item becomes ``None`` when the ``output`` parameter
+            specified a location for the result.
+        """
+
+        return self.encrypt(plaintext, output=output), self.digest()
+
+    def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None):
+        """Perform decrypt() and verify() in one step.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+          received_mac_tag : byte string
+            This is the *binary* MAC, as received from the sender.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+            parameter specified a location for the result.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        plaintext = self.decrypt(ciphertext, output=output)
+        self.verify(received_mac_tag)
+        return plaintext
+
+
+def _create_gcm_cipher(factory, **kwargs):
+    """Create a new block cipher, configured in Galois Counter Mode (GCM).
+
+    :Parameters:
+      factory : module
+        A block cipher module, taken from `Crypto.Cipher`.
+        The cipher must have block length of 16 bytes.
+        GCM has been only defined for `Crypto.Cipher.AES`.
+
+    :Keywords:
+      key : bytes/bytearray/memoryview
+        The secret key to use in the symmetric cipher.
+        It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*)
+        or 32 (e.g. *AES-256*) bytes long.
+
+      nonce : bytes/bytearray/memoryview
+        A value that must never be reused for any other encryption.
+
+        There are no restrictions on its length,
+        but it is recommended to use at least 16 bytes.
+
+        The nonce shall never repeat for two
+        different messages encrypted with the same key,
+        but it does not need to be random.
+
+        If not provided, a 16 byte nonce will be randomly created.
+
+      mac_len : integer
+        Length of the MAC, in bytes.
+        It must be no larger than 16 bytes (which is the default).
+    """
+
+    try:
+        key = kwargs.pop("key")
+    except KeyError as e:
+        raise TypeError("Missing parameter:" + str(e))
+
+    nonce = kwargs.pop("nonce", None)
+    if nonce is None:
+        nonce = get_random_bytes(16)
+    mac_len = kwargs.pop("mac_len", 16)
+
+    # Not documented - only used for testing
+    use_clmul = kwargs.pop("use_clmul", True)
+    if use_clmul and _ghash_clmul:
+        ghash_c = _ghash_clmul
+    else:
+        ghash_c = _ghash_portable
+
+    return GcmMode(factory, key, nonce, mac_len, kwargs, ghash_c)

+ 45 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_gcm.pyi

@@ -0,0 +1,45 @@
+from types import ModuleType
+from typing import Union, Tuple, Dict, overload, Optional
+
+__all__ = ['GcmMode']
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class GcmMode(object):
+    block_size: int
+    nonce: Buffer
+    
+    def __init__(self,
+                 factory: ModuleType,
+                 key: Buffer,
+                 nonce: Buffer,
+                 mac_len: int,
+                 cipher_params: Dict) -> None: ...
+    
+    def update(self, assoc_data: Buffer) -> GcmMode: ...
+
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, received_mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer) -> Tuple[bytes, bytes]: ...
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer,
+                           output: Buffer) -> Tuple[None, bytes]: ...
+    def decrypt_and_verify(self,
+                           ciphertext: Buffer,
+                           received_mac_tag: Buffer,
+                           output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ...

+ 525 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ocb.py

@@ -0,0 +1,525 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+Offset Codebook (OCB) mode.
+
+OCB is Authenticated Encryption with Associated Data (AEAD) cipher mode
+designed by Prof. Phillip Rogaway and specified in `RFC7253`_.
+
+The algorithm provides both authenticity and privacy, it is very efficient,
+it uses only one key and it can be used in online mode (so that encryption
+or decryption can start before the end of the message is available).
+
+This module implements the third and last variant of OCB (OCB3) and it only
+works in combination with a 128-bit block symmetric cipher, like AES.
+
+OCB is patented in US but `free licenses`_ exist for software implementations
+meant for non-military purposes.
+
+Example:
+    >>> from tls.Crypto.Cipher import AES
+    >>> from tls.Crypto.Random import get_random_bytes
+    >>>
+    >>> key = get_random_bytes(32)
+    >>> cipher = AES.new(key, AES.MODE_OCB)
+    >>> plaintext = b"Attack at dawn"
+    >>> ciphertext, mac = cipher.encrypt_and_digest(plaintext)
+    >>> # Deliver cipher.nonce, ciphertext and mac
+    ...
+    >>> cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
+    >>> try:
+    >>>     plaintext = cipher.decrypt_and_verify(ciphertext, mac)
+    >>> except ValueError:
+    >>>     print "Invalid message"
+    >>> else:
+    >>>     print plaintext
+
+:undocumented: __package__
+
+.. _RFC7253: http://www.rfc-editor.org/info/rfc7253
+.. _free licenses: http://web.cs.ucdavis.edu/~rogaway/ocb/license.htm
+"""
+
+import struct
+from binascii import unhexlify
+
+from tls.Crypto.Util.py3compat import bord, _copy_bytes
+from tls.Crypto.Util.number import long_to_bytes, bytes_to_long
+from tls.Crypto.Util.strxor import strxor
+
+from tls.Crypto.Hash import BLAKE2s
+from tls.Crypto.Random import get_random_bytes
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+                                  create_string_buffer, get_raw_buffer,
+                                  SmartPointer, c_size_t, c_uint8_ptr,
+                                  is_buffer)
+
+_raw_ocb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ocb", """
+                                    int OCB_start_operation(void *cipher,
+                                        const uint8_t *offset_0,
+                                        size_t offset_0_len,
+                                        void **pState);
+                                    int OCB_encrypt(void *state,
+                                        const uint8_t *in,
+                                        uint8_t *out,
+                                        size_t data_len);
+                                    int OCB_decrypt(void *state,
+                                        const uint8_t *in,
+                                        uint8_t *out,
+                                        size_t data_len);
+                                    int OCB_update(void *state,
+                                        const uint8_t *in,
+                                        size_t data_len);
+                                    int OCB_digest(void *state,
+                                        uint8_t *tag,
+                                        size_t tag_len);
+                                    int OCB_stop_operation(void *state);
+                                    """)
+
+
+class OcbMode(object):
+    """Offset Codebook (OCB) mode.
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, factory, nonce, mac_len, cipher_params):
+
+        if factory.block_size != 16:
+            raise ValueError("OCB mode is only available for ciphers"
+                             " that operate on 128 bits blocks")
+
+        self.block_size = 16
+        """The block size of the underlying cipher, in bytes."""
+
+        self.nonce = _copy_bytes(None, None, nonce)
+        """Nonce used for this session."""
+        if len(nonce) not in range(1, 16):
+            raise ValueError("Nonce must be at most 15 bytes long")
+        if not is_buffer(nonce):
+            raise TypeError("Nonce must be bytes, bytearray or memoryview")
+
+        self._mac_len = mac_len
+        if not 8 <= mac_len <= 16:
+            raise ValueError("MAC tag must be between 8 and 16 bytes long")
+
+        # Cache for MAC tag
+        self._mac_tag = None
+
+        # Cache for unaligned associated data
+        self._cache_A = b""
+
+        # Cache for unaligned ciphertext/plaintext
+        self._cache_P = b""
+
+        # Allowed transitions after initialization
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        # Compute Offset_0
+        params_without_key = dict(cipher_params)
+        key = params_without_key.pop("key")
+        nonce = (struct.pack('B', self._mac_len << 4 & 0xFF) +
+                 b'\x00' * (14 - len(nonce)) +
+                 b'\x01' + self.nonce)
+
+        bottom_bits = bord(nonce[15]) & 0x3F    # 6 bits, 0..63
+        top_bits = bord(nonce[15]) & 0xC0       # 2 bits
+
+        ktop_cipher = factory.new(key,
+                                  factory.MODE_ECB,
+                                  **params_without_key)
+        ktop = ktop_cipher.encrypt(struct.pack('15sB',
+                                               nonce[:15],
+                                               top_bits))
+
+        stretch = ktop + strxor(ktop[:8], ktop[1:9])    # 192 bits
+        offset_0 = long_to_bytes(bytes_to_long(stretch) >>
+                                 (64 - bottom_bits), 24)[8:]
+
+        # Create low-level cipher instance
+        raw_cipher = factory._create_base_cipher(cipher_params)
+        if cipher_params:
+            raise TypeError("Unknown keywords: " + str(cipher_params))
+
+        self._state = VoidPointer()
+        result = _raw_ocb_lib.OCB_start_operation(raw_cipher.get(),
+                                                  offset_0,
+                                                  c_size_t(len(offset_0)),
+                                                  self._state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating the OCB mode"
+                             % result)
+
+        # Ensure that object disposal of this Python object will (eventually)
+        # free the memory allocated by the raw library for the cipher mode
+        self._state = SmartPointer(self._state.get(),
+                                   _raw_ocb_lib.OCB_stop_operation)
+
+        # Memory allocated for the underlying block cipher is now owed
+        # by the cipher mode
+        raw_cipher.release()
+
+    def _update(self, assoc_data, assoc_data_len):
+        result = _raw_ocb_lib.OCB_update(self._state.get(),
+                                         c_uint8_ptr(assoc_data),
+                                         c_size_t(assoc_data_len))
+        if result:
+            raise ValueError("Error %d while computing MAC in OCB mode" % result)
+
+    def update(self, assoc_data):
+        """Process the associated data.
+
+        If there is any associated data, the caller has to invoke
+        this method one or more times, before using
+        ``decrypt`` or ``encrypt``.
+
+        By *associated data* it is meant any data (e.g. packet headers) that
+        will not be encrypted and will be transmitted in the clear.
+        However, the receiver shall still able to detect modifications.
+
+        If there is no associated data, this method must not be called.
+
+        The caller may split associated data in segments of any size, and
+        invoke this method multiple times, each time with the next segment.
+
+        :Parameters:
+          assoc_data : bytes/bytearray/memoryview
+            A piece of associated data.
+        """
+
+        if self.update not in self._next:
+            raise TypeError("update() can only be called"
+                            " immediately after initialization")
+
+        self._next = [self.encrypt, self.decrypt, self.digest,
+                      self.verify, self.update]
+
+        if len(self._cache_A) > 0:
+            filler = min(16 - len(self._cache_A), len(assoc_data))
+            self._cache_A += _copy_bytes(None, filler, assoc_data)
+            assoc_data = assoc_data[filler:]
+
+            if len(self._cache_A) < 16:
+                return self
+
+            # Clear the cache, and proceeding with any other aligned data
+            self._cache_A, seg = b"", self._cache_A
+            self.update(seg)
+
+        update_len = len(assoc_data) // 16 * 16
+        self._cache_A = _copy_bytes(update_len, None, assoc_data)
+        self._update(assoc_data, update_len)
+        return self
+
+    def _transcrypt_aligned(self, in_data, in_data_len,
+                            trans_func, trans_desc):
+
+        out_data = create_string_buffer(in_data_len)
+        result = trans_func(self._state.get(),
+                            in_data,
+                            out_data,
+                            c_size_t(in_data_len))
+        if result:
+            raise ValueError("Error %d while %sing in OCB mode"
+                             % (result, trans_desc))
+        return get_raw_buffer(out_data)
+
+    def _transcrypt(self, in_data, trans_func, trans_desc):
+        # Last piece to encrypt/decrypt
+        if in_data is None:
+            out_data = self._transcrypt_aligned(self._cache_P,
+                                                len(self._cache_P),
+                                                trans_func,
+                                                trans_desc)
+            self._cache_P = b""
+            return out_data
+
+        # Try to fill up the cache, if it already contains something
+        prefix = b""
+        if len(self._cache_P) > 0:
+            filler = min(16 - len(self._cache_P), len(in_data))
+            self._cache_P += _copy_bytes(None, filler, in_data)
+            in_data = in_data[filler:]
+
+            if len(self._cache_P) < 16:
+                # We could not manage to fill the cache, so there is certainly
+                # no output yet.
+                return b""
+
+            # Clear the cache, and proceeding with any other aligned data
+            prefix = self._transcrypt_aligned(self._cache_P,
+                                              len(self._cache_P),
+                                              trans_func,
+                                              trans_desc)
+            self._cache_P = b""
+
+        # Process data in multiples of the block size
+        trans_len = len(in_data) // 16 * 16
+        result = self._transcrypt_aligned(c_uint8_ptr(in_data),
+                                          trans_len,
+                                          trans_func,
+                                          trans_desc)
+        if prefix:
+            result = prefix + result
+
+        # Left-over
+        self._cache_P = _copy_bytes(trans_len, None, in_data)
+
+        return result
+
+    def encrypt(self, plaintext=None):
+        """Encrypt the next piece of plaintext.
+
+        After the entire plaintext has been passed (but before `digest`),
+        you **must** call this method one last time with no arguments to collect
+        the final piece of ciphertext.
+
+        If possible, use the method `encrypt_and_digest` instead.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The next piece of data to encrypt or ``None`` to signify
+            that encryption has finished and that any remaining ciphertext
+            has to be produced.
+        :Return:
+            the ciphertext, as a byte string.
+            Its length may not match the length of the *plaintext*.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() can only be called after"
+                            " initialization or an update()")
+
+        if plaintext is None:
+            self._next = [self.digest]
+        else:
+            self._next = [self.encrypt]
+        return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt")
+
+    def decrypt(self, ciphertext=None):
+        """Decrypt the next piece of ciphertext.
+
+        After the entire ciphertext has been passed (but before `verify`),
+        you **must** call this method one last time with no arguments to collect
+        the remaining piece of plaintext.
+
+        If possible, use the method `decrypt_and_verify` instead.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The next piece of data to decrypt or ``None`` to signify
+            that decryption has finished and that any remaining plaintext
+            has to be produced.
+        :Return:
+            the plaintext, as a byte string.
+            Its length may not match the length of the *ciphertext*.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() can only be called after"
+                            " initialization or an update()")
+
+        if ciphertext is None:
+            self._next = [self.verify]
+        else:
+            self._next = [self.decrypt]
+        return self._transcrypt(ciphertext,
+                                _raw_ocb_lib.OCB_decrypt,
+                                "decrypt")
+
+    def _compute_mac_tag(self):
+
+        if self._mac_tag is not None:
+            return
+
+        if self._cache_A:
+            self._update(self._cache_A, len(self._cache_A))
+            self._cache_A = b""
+
+        mac_tag = create_string_buffer(16)
+        result = _raw_ocb_lib.OCB_digest(self._state.get(),
+                                         mac_tag,
+                                         c_size_t(len(mac_tag))
+                                         )
+        if result:
+            raise ValueError("Error %d while computing digest in OCB mode"
+                             % result)
+        self._mac_tag = get_raw_buffer(mac_tag)[:self._mac_len]
+
+    def digest(self):
+        """Compute the *binary* MAC tag.
+
+        Call this method after the final `encrypt` (the one with no arguments)
+        to obtain the MAC tag.
+
+        The MAC tag is needed by the receiver to determine authenticity
+        of the message.
+
+        :Return: the MAC, as a byte string.
+        """
+
+        if self.digest not in self._next:
+            raise TypeError("digest() cannot be called now for this cipher")
+
+        assert(len(self._cache_P) == 0)
+
+        self._next = [self.digest]
+
+        if self._mac_tag is None:
+            self._compute_mac_tag()
+
+        return self._mac_tag
+
+    def hexdigest(self):
+        """Compute the *printable* MAC tag.
+
+        This method is like `digest`.
+
+        :Return: the MAC, as a hexadecimal string.
+        """
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def verify(self, received_mac_tag):
+        """Validate the *binary* MAC tag.
+
+        Call this method after the final `decrypt` (the one with no arguments)
+        to check if the message is authentic and valid.
+
+        :Parameters:
+          received_mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        if self.verify not in self._next:
+            raise TypeError("verify() cannot be called now for this cipher")
+
+        assert(len(self._cache_P) == 0)
+
+        self._next = [self.verify]
+
+        if self._mac_tag is None:
+            self._compute_mac_tag()
+
+        secret = get_random_bytes(16)
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Validate the *printable* MAC tag.
+
+        This method is like `verify`.
+
+        :Parameters:
+          hex_mac_tag : string
+            This is the *printable* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        self.verify(unhexlify(hex_mac_tag))
+
+    def encrypt_and_digest(self, plaintext):
+        """Encrypt the message and create the MAC tag in one step.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The entire message to encrypt.
+        :Return:
+            a tuple with two byte strings:
+
+            - the encrypted data
+            - the MAC
+        """
+
+        return self.encrypt(plaintext) + self.encrypt(), self.digest()
+
+    def decrypt_and_verify(self, ciphertext, received_mac_tag):
+        """Decrypted the message and verify its authenticity in one step.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The entire message to decrypt.
+          received_mac_tag : byte string
+            This is the *binary* MAC, as received from the sender.
+
+        :Return: the decrypted data (byte string).
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        plaintext = self.decrypt(ciphertext) + self.decrypt()
+        self.verify(received_mac_tag)
+        return plaintext
+
+
+def _create_ocb_cipher(factory, **kwargs):
+    """Create a new block cipher, configured in OCB mode.
+
+    :Parameters:
+      factory : module
+        A symmetric cipher module from `Crypto.Cipher`
+        (like `Crypto.Cipher.AES`).
+
+    :Keywords:
+      nonce : bytes/bytearray/memoryview
+        A  value that must never be reused for any other encryption.
+        Its length can vary from 1 to 15 bytes.
+        If not specified, a random 15 bytes long nonce is generated.
+
+      mac_len : integer
+        Length of the MAC, in bytes.
+        It must be in the range ``[8..16]``.
+        The default is 16 (128 bits).
+
+    Any other keyword will be passed to the underlying block cipher.
+    See the relevant documentation for details (at least ``key`` will need
+    to be present).
+    """
+
+    try:
+        nonce = kwargs.pop("nonce", None)
+        if nonce is None:
+            nonce = get_random_bytes(15)
+        mac_len = kwargs.pop("mac_len", 16)
+    except KeyError as e:
+        raise TypeError("Keyword missing: " + str(e))
+
+    return OcbMode(factory, nonce, mac_len, kwargs)

+ 36 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ocb.pyi

@@ -0,0 +1,36 @@
+from types import ModuleType
+from typing import Union, Any, Optional, Tuple, Dict, overload
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class OcbMode(object):
+    block_size: int
+    nonce: Buffer
+
+    def __init__(self,
+                 factory: ModuleType,
+                 nonce: Buffer,
+                 mac_len: int,
+                 cipher_params: Dict) -> None: ...
+    
+    def update(self, assoc_data: Buffer) -> OcbMode: ...
+
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, received_mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+    def encrypt_and_digest(self,
+                           plaintext: Buffer) -> Tuple[bytes, bytes]: ...
+    def decrypt_and_verify(self,
+                           ciphertext: Buffer,
+                           received_mac_tag: Buffer) -> bytes: ...

+ 282 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ofb.py

@@ -0,0 +1,282 @@
+# -*- coding: utf-8 -*-
+#
+#  Cipher/mode_ofb.py : OFB mode
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""
+Output Feedback (CFB) mode.
+"""
+
+__all__ = ['OfbMode']
+
+from tls.Crypto.Util.py3compat import _copy_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+                                  create_string_buffer, get_raw_buffer,
+                                  SmartPointer, c_size_t, c_uint8_ptr,
+                                  is_writeable_buffer)
+
+from tls.Crypto.Random import get_random_bytes
+
+raw_ofb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ofb", """
+                        int OFB_start_operation(void *cipher,
+                                                const uint8_t iv[],
+                                                size_t iv_len,
+                                                void **pResult);
+                        int OFB_encrypt(void *ofbState,
+                                        const uint8_t *in,
+                                        uint8_t *out,
+                                        size_t data_len);
+                        int OFB_decrypt(void *ofbState,
+                                        const uint8_t *in,
+                                        uint8_t *out,
+                                        size_t data_len);
+                        int OFB_stop_operation(void *state);
+                        """
+                                        )
+
+
+class OfbMode(object):
+    """*Output FeedBack (OFB)*.
+
+    This mode is very similar to CBC, but it
+    transforms the underlying block cipher into a stream cipher.
+
+    The keystream is the iterated block encryption of the
+    previous ciphertext block.
+
+    An Initialization Vector (*IV*) is required.
+
+    See `NIST SP800-38A`_ , Section 6.4.
+
+    .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, block_cipher, iv):
+        """Create a new block cipher, configured in OFB mode.
+
+        :Parameters:
+          block_cipher : C pointer
+            A smart pointer to the low-level block cipher instance.
+
+          iv : bytes/bytearray/memoryview
+            The initialization vector to use for encryption or decryption.
+            It is as long as the cipher block.
+
+            **The IV must be a nonce, to to be reused for any other
+            message**. It shall be a nonce or a random value.
+
+            Reusing the *IV* for encryptions performed with the same key
+            compromises confidentiality.
+        """
+
+        self._state = VoidPointer()
+        result = raw_ofb_lib.OFB_start_operation(block_cipher.get(),
+                                                 c_uint8_ptr(iv),
+                                                 c_size_t(len(iv)),
+                                                 self._state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating the OFB mode"
+                             % result)
+
+        # Ensure that object disposal of this Python object will (eventually)
+        # free the memory allocated by the raw library for the cipher mode
+        self._state = SmartPointer(self._state.get(),
+                                   raw_ofb_lib.OFB_stop_operation)
+
+        # Memory allocated for the underlying block cipher is now owed
+        # by the cipher mode
+        block_cipher.release()
+
+        self.block_size = len(iv)
+        """The block size of the underlying cipher, in bytes."""
+
+        self.iv = _copy_bytes(None, None, iv)
+        """The Initialization Vector originally used to create the object.
+        The value does not change."""
+
+        self.IV = self.iv
+        """Alias for `iv`"""
+
+        self._next = [ self.encrypt, self.decrypt ]
+
+    def encrypt(self, plaintext, output=None):
+        """Encrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() cannot be called after decrypt()")
+        self._next = [ self.encrypt ]
+        
+        if output is None:
+            ciphertext = create_string_buffer(len(plaintext))
+        else:
+            ciphertext = output
+            
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+        
+            if len(plaintext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_ofb_lib.OFB_encrypt(self._state.get(),
+                                         c_uint8_ptr(plaintext),
+                                         c_uint8_ptr(ciphertext),
+                                         c_size_t(len(plaintext)))
+        if result:
+            raise ValueError("Error %d while encrypting in OFB mode" % result)
+
+        if output is None:
+            return get_raw_buffer(ciphertext)
+        else:
+            return None
+
+    def decrypt(self, ciphertext, output=None):
+        """Decrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            It can be of any length.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext is written to.
+            If ``None``, the plaintext is returned.
+        :Return:
+          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+          Otherwise, ``None``.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() cannot be called after encrypt()")
+        self._next = [ self.decrypt ]
+        
+        if output is None:
+            plaintext = create_string_buffer(len(ciphertext))
+        else:
+            plaintext = output
+
+            if not is_writeable_buffer(output):
+                raise TypeError("output must be a bytearray or a writeable memoryview")
+            
+            if len(ciphertext) != len(output):
+                raise ValueError("output must have the same length as the input"
+                                 "  (%d bytes)" % len(plaintext))
+
+        result = raw_ofb_lib.OFB_decrypt(self._state.get(),
+                                         c_uint8_ptr(ciphertext),
+                                         c_uint8_ptr(plaintext),
+                                         c_size_t(len(ciphertext)))
+        if result:
+            raise ValueError("Error %d while decrypting in OFB mode" % result)
+
+        if output is None:
+            return get_raw_buffer(plaintext)
+        else:
+            return None
+
+
+def _create_ofb_cipher(factory, **kwargs):
+    """Instantiate a cipher object that performs OFB encryption/decryption.
+
+    :Parameters:
+      factory : module
+        The underlying block cipher, a module from ``Crypto.Cipher``.
+
+    :Keywords:
+      iv : bytes/bytearray/memoryview
+        The IV to use for OFB.
+
+      IV : bytes/bytearray/memoryview
+        Alias for ``iv``.
+
+    Any other keyword will be passed to the underlying block cipher.
+    See the relevant documentation for details (at least ``key`` will need
+    to be present).
+    """
+
+    cipher_state = factory._create_base_cipher(kwargs)
+    iv = kwargs.pop("IV", None)
+    IV = kwargs.pop("iv", None)
+
+    if (None, None) == (iv, IV):
+        iv = get_random_bytes(factory.block_size)
+    if iv is not None:
+        if IV is not None:
+            raise TypeError("You must either use 'iv' or 'IV', not both")
+    else:
+        iv = IV
+
+    if len(iv) != factory.block_size:
+        raise ValueError("Incorrect IV length (it must be %d bytes long)" %
+                factory.block_size)
+
+    if kwargs:
+        raise TypeError("Unknown parameters for OFB: %s" % str(kwargs))
+
+    return OfbMode(cipher_state, iv)

+ 25 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_ofb.pyi

@@ -0,0 +1,25 @@
+from typing import Union, overload
+
+from tls.Crypto.Util._raw_api import SmartPointer
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['OfbMode']
+
+class OfbMode(object):
+    block_size: int
+    iv: Buffer
+    IV: Buffer
+    
+    def __init__(self,
+                 block_cipher: SmartPointer,
+                 iv: Buffer) -> None: ...
+    @overload
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+    @overload
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+    @overload
+    def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+

+ 206 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_openpgp.py

@@ -0,0 +1,206 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+OpenPGP mode.
+"""
+
+__all__ = ['OpenPgpMode']
+
+from tls.Crypto.Util.py3compat import _copy_bytes
+from tls.Crypto.Random import get_random_bytes
+
+class OpenPgpMode(object):
+    """OpenPGP mode.
+
+    This mode is a variant of CFB, and it is only used in PGP and
+    OpenPGP_ applications. If in doubt, use another mode.
+
+    An Initialization Vector (*IV*) is required.
+
+    Unlike CFB, the *encrypted* IV (not the IV itself) is
+    transmitted to the receiver.
+
+    The IV is a random data block. For legacy reasons, two of its bytes are
+    duplicated to act as a checksum for the correctness of the key, which is now
+    known to be insecure and is ignored. The encrypted IV is therefore 2 bytes
+    longer than the clean IV.
+
+    .. _OpenPGP: http://tools.ietf.org/html/rfc4880
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, factory, key, iv, cipher_params):
+
+        #: The block size of the underlying cipher, in bytes.
+        self.block_size = factory.block_size
+
+        self._done_first_block = False  # True after the first encryption
+
+        # Instantiate a temporary cipher to process the IV
+        IV_cipher = factory.new(
+                        key,
+                        factory.MODE_CFB,
+                        IV=b'\x00' * self.block_size,
+                        segment_size=self.block_size * 8,
+                        **cipher_params)
+
+        iv = _copy_bytes(None, None, iv)
+
+        # The cipher will be used for...
+        if len(iv) == self.block_size:
+            # ... encryption
+            self._encrypted_IV = IV_cipher.encrypt(iv + iv[-2:])
+        elif len(iv) == self.block_size + 2:
+            # ... decryption
+            self._encrypted_IV = iv
+            # Last two bytes are for a deprecated "quick check" feature that
+            # should not be used. (https://eprint.iacr.org/2005/033)
+            iv = IV_cipher.decrypt(iv)[:-2]
+        else:
+            raise ValueError("Length of IV must be %d or %d bytes"
+                             " for MODE_OPENPGP"
+                             % (self.block_size, self.block_size + 2))
+
+        self.iv = self.IV = iv
+
+        # Instantiate the cipher for the real PGP data
+        self._cipher = factory.new(
+                            key,
+                            factory.MODE_CFB,
+                            IV=self._encrypted_IV[-self.block_size:],
+                            segment_size=self.block_size * 8,
+                            **cipher_params)
+
+    def encrypt(self, plaintext):
+        """Encrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have encrypted a message
+        you cannot encrypt (or decrypt) another message using the same
+        object.
+
+        The data to encrypt can be broken up in two or
+        more pieces and `encrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.encrypt(a) + c.encrypt(b)
+
+        is equivalent to:
+
+             >>> c.encrypt(a+b)
+
+        This function does not add any padding to the plaintext.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+
+        :Return:
+            the encrypted data, as a byte string.
+            It is as long as *plaintext* with one exception:
+            when encrypting the first message chunk,
+            the encypted IV is prepended to the returned ciphertext.
+        """
+
+        res = self._cipher.encrypt(plaintext)
+        if not self._done_first_block:
+            res = self._encrypted_IV + res
+            self._done_first_block = True
+        return res
+
+    def decrypt(self, ciphertext):
+        """Decrypt data with the key and the parameters set at initialization.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        The data to decrypt can be broken up in two or
+        more pieces and `decrypt` can be called multiple times.
+
+        That is, the statement:
+
+            >>> c.decrypt(a) + c.decrypt(b)
+
+        is equivalent to:
+
+             >>> c.decrypt(a+b)
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+
+        :Return: the decrypted data (byte string).
+        """
+
+        return self._cipher.decrypt(ciphertext)
+
+
+def _create_openpgp_cipher(factory, **kwargs):
+    """Create a new block cipher, configured in OpenPGP mode.
+
+    :Parameters:
+      factory : module
+        The module.
+
+    :Keywords:
+      key : bytes/bytearray/memoryview
+        The secret key to use in the symmetric cipher.
+
+      IV : bytes/bytearray/memoryview
+        The initialization vector to use for encryption or decryption.
+
+        For encryption, the IV must be as long as the cipher block size.
+
+        For decryption, it must be 2 bytes longer (it is actually the
+        *encrypted* IV which was prefixed to the ciphertext).
+    """
+
+    iv = kwargs.pop("IV", None)
+    IV = kwargs.pop("iv", None)
+
+    if (None, None) == (iv, IV):
+        iv = get_random_bytes(factory.block_size)
+    if iv is not None:
+        if IV is not None:
+            raise TypeError("You must either use 'iv' or 'IV', not both")
+    else:
+        iv = IV
+
+    try:
+        key = kwargs.pop("key")
+    except KeyError as e:
+        raise TypeError("Missing component: " + str(e))
+
+    return OpenPgpMode(factory, key, iv, kwargs)

+ 20 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_openpgp.pyi

@@ -0,0 +1,20 @@
+from types import ModuleType
+from typing import Union, Dict
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['OpenPgpMode']
+
+class OpenPgpMode(object):
+    block_size: int
+    iv: Union[bytes, bytearray, memoryview]
+    IV: Union[bytes, bytearray, memoryview]
+    
+    def __init__(self,
+                 factory: ModuleType,
+                 key: Buffer,
+                 iv: Buffer,
+                 cipher_params: Dict) -> None: ...
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+

+ 392 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_siv.py

@@ -0,0 +1,392 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+Synthetic Initialization Vector (SIV) mode.
+"""
+
+__all__ = ['SivMode']
+
+from binascii import hexlify, unhexlify
+
+from tls.Crypto.Util.py3compat import bord, _copy_bytes
+
+from tls.Crypto.Util._raw_api import is_buffer
+
+from tls.Crypto.Util.number import long_to_bytes, bytes_to_long
+from tls.Crypto.Protocol.KDF import _S2V
+from tls.Crypto.Hash import BLAKE2s
+from tls.Crypto.Random import get_random_bytes
+
+
+class SivMode(object):
+    """Synthetic Initialization Vector (SIV).
+
+    This is an Authenticated Encryption with Associated Data (`AEAD`_) mode.
+    It provides both confidentiality and authenticity.
+
+    The header of the message may be left in the clear, if needed, and it will
+    still be subject to authentication. The decryption step tells the receiver
+    if the message comes from a source that really knowns the secret key.
+    Additionally, decryption detects if any part of the message - including the
+    header - has been modified or corrupted.
+
+    Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a
+    nonce is not catastrophic for the confidentiality of the message. The only
+    effect is that an attacker can tell when the same plaintext (and same
+    associated data) is protected with the same key.
+
+    The length of the MAC is fixed to the block size of the underlying cipher.
+    The key size is twice the length of the key of the underlying cipher.
+
+    This mode is only available for AES ciphers.
+
+    +--------------------+---------------+-------------------+
+    |      Cipher        | SIV MAC size  |   SIV key length  |
+    |                    |    (bytes)    |     (bytes)       |
+    +====================+===============+===================+
+    |    AES-128         |      16       |        32         |
+    +--------------------+---------------+-------------------+
+    |    AES-192         |      16       |        48         |
+    +--------------------+---------------+-------------------+
+    |    AES-256         |      16       |        64         |
+    +--------------------+---------------+-------------------+
+
+    See `RFC5297`_ and the `original paper`__.
+
+    .. _RFC5297: https://tools.ietf.org/html/rfc5297
+    .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
+    .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf
+
+    :undocumented: __init__
+    """
+
+    def __init__(self, factory, key, nonce, kwargs):
+
+        self.block_size = factory.block_size
+        """The block size of the underlying cipher, in bytes."""
+
+        self._factory = factory
+
+        self._cipher_params = kwargs
+
+        if len(key) not in (32, 48, 64):
+            raise ValueError("Incorrect key length (%d bytes)" % len(key))
+
+        if nonce is not None:
+            if not is_buffer(nonce):
+                raise TypeError("When provided, the nonce must be bytes, bytearray or memoryview")
+
+            if len(nonce) == 0:
+                raise ValueError("When provided, the nonce must be non-empty")
+
+            self.nonce = _copy_bytes(None, None, nonce)
+            """Public attribute is only available in case of non-deterministic
+            encryption."""
+
+        subkey_size = len(key) // 2
+
+        self._mac_tag = None  # Cache for MAC tag
+        self._kdf = _S2V(key[:subkey_size],
+                         ciphermod=factory,
+                         cipher_params=self._cipher_params)
+        self._subkey_cipher = key[subkey_size:]
+
+        # Purely for the purpose of verifying that cipher_params are OK
+        factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs)
+
+        # Allowed transitions after initialization
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+    def _create_ctr_cipher(self, v):
+        """Create a new CTR cipher from V in SIV mode"""
+
+        v_int = bytes_to_long(v)
+        q = v_int & 0xFFFFFFFFFFFFFFFF7FFFFFFF7FFFFFFF
+        return self._factory.new(
+                    self._subkey_cipher,
+                    self._factory.MODE_CTR,
+                    initial_value=q,
+                    nonce=b"",
+                    **self._cipher_params)
+
+    def update(self, component):
+        """Protect one associated data component
+
+        For SIV, the associated data is a sequence (*vector*) of non-empty
+        byte strings (*components*).
+
+        This method consumes the next component. It must be called
+        once for each of the components that constitue the associated data.
+
+        Note that the components have clear boundaries, so that:
+
+            >>> cipher.update(b"builtin")
+            >>> cipher.update(b"securely")
+
+        is not equivalent to:
+
+            >>> cipher.update(b"built")
+            >>> cipher.update(b"insecurely")
+
+        If there is no associated data, this method must not be called.
+
+        :Parameters:
+          component : bytes/bytearray/memoryview
+            The next associated data component.
+        """
+
+        if self.update not in self._next:
+            raise TypeError("update() can only be called"
+                                " immediately after initialization")
+
+        self._next = [self.update, self.encrypt, self.decrypt,
+                      self.digest, self.verify]
+
+        return self._kdf.update(component)
+
+    def encrypt(self, plaintext):
+        """
+        For SIV, encryption and MAC authentication must take place at the same
+        point. This method shall not be used.
+
+        Use `encrypt_and_digest` instead.
+        """
+
+        raise TypeError("encrypt() not allowed for SIV mode."
+                        " Use encrypt_and_digest() instead.")
+
+    def decrypt(self, ciphertext):
+        """
+        For SIV, decryption and verification must take place at the same
+        point. This method shall not be used.
+
+        Use `decrypt_and_verify` instead.
+        """
+
+        raise TypeError("decrypt() not allowed for SIV mode."
+                        " Use decrypt_and_verify() instead.")
+
+    def digest(self):
+        """Compute the *binary* MAC tag.
+
+        The caller invokes this function at the very end.
+
+        This method returns the MAC that shall be sent to the receiver,
+        together with the ciphertext.
+
+        :Return: the MAC, as a byte string.
+        """
+
+        if self.digest not in self._next:
+            raise TypeError("digest() cannot be called when decrypting"
+                            " or validating a message")
+        self._next = [self.digest]
+        if self._mac_tag is None:
+            self._mac_tag = self._kdf.derive()
+        return self._mac_tag
+
+    def hexdigest(self):
+        """Compute the *printable* MAC tag.
+
+        This method is like `digest`.
+
+        :Return: the MAC, as a hexadecimal string.
+        """
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def verify(self, received_mac_tag):
+        """Validate the *binary* MAC tag.
+
+        The caller invokes this function at the very end.
+
+        This method checks if the decrypted message is indeed valid
+        (that is, if the key is correct) and it has not been
+        tampered with while in transit.
+
+        :Parameters:
+          received_mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        if self.verify not in self._next:
+            raise TypeError("verify() cannot be called"
+                            " when encrypting a message")
+        self._next = [self.verify]
+
+        if self._mac_tag is None:
+            self._mac_tag = self._kdf.derive()
+
+        secret = get_random_bytes(16)
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Validate the *printable* MAC tag.
+
+        This method is like `verify`.
+
+        :Parameters:
+          hex_mac_tag : string
+            This is the *printable* MAC, as received from the sender.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        self.verify(unhexlify(hex_mac_tag))
+
+    def encrypt_and_digest(self, plaintext, output=None):
+        """Perform encrypt() and digest() in one step.
+
+        :Parameters:
+          plaintext : bytes/bytearray/memoryview
+            The piece of data to encrypt.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the ciphertext must be written to.
+            If ``None``, the ciphertext is returned.
+        :Return:
+            a tuple with two items:
+
+            - the ciphertext, as ``bytes``
+            - the MAC tag, as ``bytes``
+
+            The first item becomes ``None`` when the ``output`` parameter
+            specified a location for the result.
+        """
+        
+        if self.encrypt not in self._next:
+            raise TypeError("encrypt() can only be called after"
+                            " initialization or an update()")
+
+        self._next = [ self.digest ]
+
+        # Compute V (MAC)
+        if hasattr(self, 'nonce'):
+            self._kdf.update(self.nonce)
+        self._kdf.update(plaintext)
+        self._mac_tag = self._kdf.derive()
+        
+        cipher = self._create_ctr_cipher(self._mac_tag)
+
+        return cipher.encrypt(plaintext, output=output), self._mac_tag
+
+    def decrypt_and_verify(self, ciphertext, mac_tag, output=None):
+        """Perform decryption and verification in one step.
+
+        A cipher object is stateful: once you have decrypted a message
+        you cannot decrypt (or encrypt) another message with the same
+        object.
+
+        You cannot reuse an object for encrypting
+        or decrypting other data with the same key.
+
+        This function does not remove any padding from the plaintext.
+
+        :Parameters:
+          ciphertext : bytes/bytearray/memoryview
+            The piece of data to decrypt.
+            It can be of any length.
+          mac_tag : bytes/bytearray/memoryview
+            This is the *binary* MAC, as received from the sender.
+        :Keywords:
+          output : bytearray/memoryview
+            The location where the plaintext must be written to.
+            If ``None``, the plaintext is returned.
+        :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+            parameter specified a location for the result.
+        :Raises ValueError:
+            if the MAC does not match. The message has been tampered with
+            or the key is incorrect.
+        """
+
+        if self.decrypt not in self._next:
+            raise TypeError("decrypt() can only be called"
+                            " after initialization or an update()")
+        self._next = [ self.verify ]
+
+        # Take the MAC and start the cipher for decryption
+        self._cipher = self._create_ctr_cipher(mac_tag)
+
+        plaintext = self._cipher.decrypt(ciphertext, output=output)
+
+        if hasattr(self, 'nonce'):
+            self._kdf.update(self.nonce)
+        self._kdf.update(plaintext if output is None else output)
+        self.verify(mac_tag)
+        
+        return plaintext
+
+
+def _create_siv_cipher(factory, **kwargs):
+    """Create a new block cipher, configured in
+    Synthetic Initializaton Vector (SIV) mode.
+
+    :Parameters:
+
+      factory : object
+        A symmetric cipher module from `Crypto.Cipher`
+        (like `Crypto.Cipher.AES`).
+
+    :Keywords:
+
+      key : bytes/bytearray/memoryview
+        The secret key to use in the symmetric cipher.
+        It must be 32, 48 or 64 bytes long.
+        If AES is the chosen cipher, the variants *AES-128*,
+        *AES-192* and or *AES-256* will be used internally.
+
+      nonce : bytes/bytearray/memoryview
+        For deterministic encryption, it is not present.
+
+        Otherwise, it is a value that must never be reused
+        for encrypting message under this key.
+
+        There are no restrictions on its length,
+        but it is recommended to use at least 16 bytes.
+    """
+
+    try:
+        key = kwargs.pop("key")
+    except KeyError as e:
+        raise TypeError("Missing parameter: " + str(e))
+
+    nonce = kwargs.pop("nonce", None)
+
+    return SivMode(factory, key, nonce, kwargs)

+ 38 - 0
tls/pycryptoMod/lib/Crypto/Cipher/_mode_siv.pyi

@@ -0,0 +1,38 @@
+from types import ModuleType
+from typing import Union, Tuple, Dict, Optional, overload
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+__all__ = ['SivMode']
+
+class SivMode(object):
+    block_size: int
+    nonce: bytes
+    
+    def __init__(self,
+                 factory: ModuleType,
+                 key: Buffer,
+                 nonce: Buffer,
+                 kwargs: Dict) -> None: ...
+    
+    def update(self, component: Buffer) -> SivMode: ...
+
+    def encrypt(self, plaintext: Buffer) -> bytes: ...
+    def decrypt(self, plaintext: Buffer) -> bytes: ...
+
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, received_mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer) -> Tuple[bytes, bytes]: ...
+    @overload
+    def encrypt_and_digest(self,
+                           plaintext: Buffer,
+                           output: Buffer) -> Tuple[None, bytes]: ...
+    def decrypt_and_verify(self,
+                           ciphertext: Buffer,
+                           received_mac_tag: Buffer,
+                           output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ...

+ 247 - 0
tls/pycryptoMod/lib/Crypto/Hash/BLAKE2b.py

@@ -0,0 +1,247 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from binascii import unhexlify
+
+from tls.Crypto.Util.py3compat import bord, tobytes
+
+from tls.Crypto.Random import get_random_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_blake2b_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2b",
+                        """
+                        int blake2b_init(void **state,
+                                         const uint8_t *key,
+                                         size_t key_size,
+                                         size_t digest_size);
+                        int blake2b_destroy(void *state);
+                        int blake2b_update(void *state,
+                                           const uint8_t *buf,
+                                           size_t len);
+                        int blake2b_digest(const void *state,
+                                           uint8_t digest[64]);
+                        int blake2b_copy(const void *src, void *dst);
+                        """)
+
+
+class BLAKE2b_Hash(object):
+    """A BLAKE2b hash object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 64
+
+    def __init__(self, data, key, digest_bytes, update_after_digest):
+
+        # The size of the resulting hash in bytes.
+        self.digest_size = digest_bytes
+
+        self._update_after_digest = update_after_digest
+        self._digest_done = False
+
+        # See https://tools.ietf.org/html/rfc7693
+        if digest_bytes in (20, 32, 48, 64) and not key:
+            self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes)
+
+        state = VoidPointer()
+        result = _raw_blake2b_lib.blake2b_init(state.address_of(),
+                                               c_uint8_ptr(key),
+                                               c_size_t(len(key)),
+                                               c_size_t(digest_bytes)
+                                               )
+        if result:
+            raise ValueError("Error %d while instantiating BLAKE2b" % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_blake2b_lib.blake2b_destroy)
+        if data:
+            self.update(data)
+
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (bytes/bytearray/memoryview): The next chunk of the message being hashed.
+        """
+
+        if self._digest_done and not self._update_after_digest:
+            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+        result = _raw_blake2b_lib.blake2b_update(self._state.get(),
+                                                 c_uint8_ptr(data),
+                                                 c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while hashing BLAKE2b data" % result)
+        return self
+
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(64)
+        result = _raw_blake2b_lib.blake2b_digest(self._state.get(),
+                                                 bfr)
+        if result:
+            raise ValueError("Error %d while creating BLAKE2b digest" % result)
+
+        self._digest_done = True
+
+        return get_raw_buffer(bfr)[:self.digest_size]
+
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in tuple(self.digest())])
+
+
+    def verify(self, mac_tag):
+        """Verify that a given **binary** MAC (computed by another party)
+        is valid.
+
+        Args:
+          mac_tag (bytes/bytearray/memoryview): the expected MAC of the message.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        secret = get_random_bytes(16)
+
+        mac1 = new(digest_bits=160, key=secret, data=mac_tag)
+        mac2 = new(digest_bits=160, key=secret, data=self.digest())
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+
+    def hexverify(self, hex_mac_tag):
+        """Verify that a given **printable** MAC (computed by another party)
+        is valid.
+
+        Args:
+            hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        self.verify(unhexlify(tobytes(hex_mac_tag)))
+
+
+    def new(self, **kwargs):
+        """Return a new instance of a BLAKE2b hash object.
+        See :func:`new`.
+        """
+
+        if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
+            kwargs["digest_bytes"] = self.digest_size
+
+        return new(**kwargs)
+
+
+def new(**kwargs):
+    """Create a new hash object.
+
+    Args:
+        data (bytes/bytearray/memoryview):
+            Optional. The very first chunk of the message to hash.
+            It is equivalent to an early call to :meth:`BLAKE2b_Hash.update`.
+        digest_bytes (integer):
+            Optional. The size of the digest, in bytes (1 to 64). Default is 64.
+        digest_bits (integer):
+            Optional and alternative to ``digest_bytes``.
+            The size of the digest, in bits (8 to 512, in steps of 8).
+            Default is 512.
+        key (bytes/bytearray/memoryview):
+            Optional. The key to use to compute the MAC (1 to 64 bytes).
+            If not specified, no key will be used.
+        update_after_digest (boolean):
+            Optional. By default, a hash object cannot be updated anymore after
+            the digest is computed. When this flag is ``True``, such check
+            is no longer enforced.
+
+    Returns:
+        A :class:`BLAKE2b_Hash` hash object
+    """
+
+    data = kwargs.pop("data", None)
+    update_after_digest = kwargs.pop("update_after_digest", False)
+
+    digest_bytes = kwargs.pop("digest_bytes", None)
+    digest_bits = kwargs.pop("digest_bits", None)
+    if None not in (digest_bytes, digest_bits):
+        raise TypeError("Only one digest parameter must be provided")
+    if (None, None) == (digest_bytes, digest_bits):
+        digest_bytes = 64
+    if digest_bytes is not None:
+        if not (1 <= digest_bytes <= 64):
+            raise ValueError("'digest_bytes' not in range 1..64")
+    else:
+        if not (8 <= digest_bits <= 512) or (digest_bits % 8):
+            raise ValueError("'digest_bytes' not in range 8..512, "
+                             "with steps of 8")
+        digest_bytes = digest_bits // 8
+
+    key = kwargs.pop("key", b"")
+    if len(key) > 64:
+        raise ValueError("BLAKE2s key cannot exceed 64 bytes")
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest)

+ 31 - 0
tls/pycryptoMod/lib/Crypto/Hash/BLAKE2b.pyi

@@ -0,0 +1,31 @@
+from typing import Any, Union
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class BLAKE2b_Hash(object):
+    block_size: int
+    digest_size: int
+    oid: str
+
+    def __init__(self,
+                 data: Buffer,
+		 key: Buffer,
+		 digest_bytes: bytes,
+		 update_after_digest: bool) -> None: ...
+    def update(self, data: Buffer) -> BLAKE2b_Hash: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+    def new(self,
+            data: Buffer = ...,
+	    digest_bytes: int = ...,
+	    digest_bits: int = ...,
+	    key: Buffer = ...,
+	    update_after_digest: bool = ...) -> BLAKE2b_Hash: ...
+
+def new(data: Buffer = ...,
+	digest_bytes: int = ...,
+	digest_bits: int = ...,
+	key: Buffer = ...,
+	update_after_digest: bool = ...) -> BLAKE2b_Hash: ...

+ 247 - 0
tls/pycryptoMod/lib/Crypto/Hash/BLAKE2s.py

@@ -0,0 +1,247 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from binascii import unhexlify
+
+from tls.Crypto.Util.py3compat import bord, tobytes
+
+from tls.Crypto.Random import get_random_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_blake2s_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2s",
+                        """
+                        int blake2s_init(void **state,
+                                         const uint8_t *key,
+                                         size_t key_size,
+                                         size_t digest_size);
+                        int blake2s_destroy(void *state);
+                        int blake2s_update(void *state,
+                                           const uint8_t *buf,
+                                           size_t len);
+                        int blake2s_digest(const void *state,
+                                           uint8_t digest[32]);
+                        int blake2s_copy(const void *src, void *dst);
+                        """)
+
+
+class BLAKE2s_Hash(object):
+    """A BLAKE2s hash object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 32
+
+    def __init__(self, data, key, digest_bytes, update_after_digest):
+
+        # The size of the resulting hash in bytes.
+        self.digest_size = digest_bytes
+
+        self._update_after_digest = update_after_digest
+        self._digest_done = False
+
+        # See https://tools.ietf.org/html/rfc7693
+        if digest_bytes in (16, 20, 28, 32) and not key:
+            self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes)
+
+        state = VoidPointer()
+        result = _raw_blake2s_lib.blake2s_init(state.address_of(),
+                                               c_uint8_ptr(key),
+                                               c_size_t(len(key)),
+                                               c_size_t(digest_bytes)
+                                               )
+        if result:
+            raise ValueError("Error %d while instantiating BLAKE2s" % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_blake2s_lib.blake2s_destroy)
+        if data:
+            self.update(data)
+
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        if self._digest_done and not self._update_after_digest:
+            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+        result = _raw_blake2s_lib.blake2s_update(self._state.get(),
+                                                 c_uint8_ptr(data),
+                                                 c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while hashing BLAKE2s data" % result)
+        return self
+
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(32)
+        result = _raw_blake2s_lib.blake2s_digest(self._state.get(),
+                                                 bfr)
+        if result:
+            raise ValueError("Error %d while creating BLAKE2s digest" % result)
+
+        self._digest_done = True
+
+        return get_raw_buffer(bfr)[:self.digest_size]
+
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in tuple(self.digest())])
+
+
+    def verify(self, mac_tag):
+        """Verify that a given **binary** MAC (computed by another party)
+        is valid.
+
+        Args:
+          mac_tag (byte string/byte array/memoryview): the expected MAC of the message.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        secret = get_random_bytes(16)
+
+        mac1 = new(digest_bits=160, key=secret, data=mac_tag)
+        mac2 = new(digest_bits=160, key=secret, data=self.digest())
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+
+    def hexverify(self, hex_mac_tag):
+        """Verify that a given **printable** MAC (computed by another party)
+        is valid.
+
+        Args:
+            hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        self.verify(unhexlify(tobytes(hex_mac_tag)))
+
+
+    def new(self, **kwargs):
+        """Return a new instance of a BLAKE2s hash object.
+        See :func:`new`.
+        """
+
+        if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
+            kwargs["digest_bytes"] = self.digest_size
+
+        return new(**kwargs)
+
+
+def new(**kwargs):
+    """Create a new hash object.
+
+    Args:
+        data (byte string/byte array/memoryview):
+            Optional. The very first chunk of the message to hash.
+            It is equivalent to an early call to :meth:`BLAKE2s_Hash.update`.
+        digest_bytes (integer):
+            Optional. The size of the digest, in bytes (1 to 32). Default is 32.
+        digest_bits (integer):
+            Optional and alternative to ``digest_bytes``.
+            The size of the digest, in bits (8 to 256, in steps of 8).
+            Default is 256.
+        key (byte string):
+            Optional. The key to use to compute the MAC (1 to 64 bytes).
+            If not specified, no key will be used.
+        update_after_digest (boolean):
+            Optional. By default, a hash object cannot be updated anymore after
+            the digest is computed. When this flag is ``True``, such check
+            is no longer enforced.
+
+    Returns:
+        A :class:`BLAKE2s_Hash` hash object
+    """
+
+    data = kwargs.pop("data", None)
+    update_after_digest = kwargs.pop("update_after_digest", False)
+
+    digest_bytes = kwargs.pop("digest_bytes", None)
+    digest_bits = kwargs.pop("digest_bits", None)
+    if None not in (digest_bytes, digest_bits):
+        raise TypeError("Only one digest parameter must be provided")
+    if (None, None) == (digest_bytes, digest_bits):
+        digest_bytes = 32
+    if digest_bytes is not None:
+        if not (1 <= digest_bytes <= 32):
+            raise ValueError("'digest_bytes' not in range 1..32")
+    else:
+        if not (8 <= digest_bits <= 256) or (digest_bits % 8):
+            raise ValueError("'digest_bytes' not in range 8..256, "
+                             "with steps of 8")
+        digest_bytes = digest_bits // 8
+
+    key = kwargs.pop("key", b"")
+    if len(key) > 32:
+        raise ValueError("BLAKE2s key cannot exceed 32 bytes")
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest)

+ 26 - 0
tls/pycryptoMod/lib/Crypto/Hash/BLAKE2s.pyi

@@ -0,0 +1,26 @@
+from typing import Any, Union
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class BLAKE2s_Hash(object):
+    block_size: int
+    digest_size: int
+    oid: str
+
+    def __init__(self,
+                 data: Buffer,
+		 key: Buffer,
+		 digest_bytes: bytes,
+		 update_after_digest: bool) -> None: ...
+    def update(self, data: Buffer) -> BLAKE2s_Hash: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+    def new(self, **kwargs: Any) -> BLAKE2s_Hash: ...
+
+def new(data: Buffer = ...,
+	digest_bytes: int = ...,
+	digest_bits: int = ...,
+	key: Buffer = ...,
+	update_after_digest: bool = ...) -> BLAKE2s_Hash: ...

+ 305 - 0
tls/pycryptoMod/lib/Crypto/Hash/CMAC.py

@@ -0,0 +1,305 @@
+# -*- coding: utf-8 -*-
+#
+# Hash/CMAC.py - Implements the CMAC algorithm
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+import sys
+from binascii import unhexlify
+
+from tls.Crypto.Hash import BLAKE2s
+from tls.Crypto.Util.strxor import strxor
+from tls.Crypto.Util.number import long_to_bytes, bytes_to_long
+from tls.Crypto.Util.py3compat import bord, tobytes, _copy_bytes
+from tls.Crypto.Random import get_random_bytes
+
+if sys.version_info[:2] == (2, 6):
+    memoryview = bytes
+
+# The size of the authentication tag produced by the MAC.
+digest_size = None
+
+
+def _shift_bytes(bs, xor_lsb=0):
+    num = (bytes_to_long(bs) << 1) ^ xor_lsb
+    return long_to_bytes(num, len(bs))[-len(bs):]
+
+
+class CMAC(object):
+    """A CMAC hash object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar digest_size: the size in bytes of the resulting MAC tag
+    :vartype digest_size: integer
+    """
+
+    digest_size = None
+
+    def __init__(self, key, msg, ciphermod, cipher_params, mac_len,
+                 update_after_digest):
+
+        self.digest_size = mac_len
+
+        self._key = _copy_bytes(None, None, key)
+        self._factory = ciphermod
+        self._cipher_params = cipher_params
+        self._block_size = bs = ciphermod.block_size
+        self._mac_tag = None
+        self._update_after_digest = update_after_digest
+
+        # Section 5.3 of NIST SP 800 38B and Appendix B
+        if bs == 8:
+            const_Rb = 0x1B
+            self._max_size = 8 * (2 ** 21)
+        elif bs == 16:
+            const_Rb = 0x87
+            self._max_size = 16 * (2 ** 48)
+        else:
+            raise TypeError("CMAC requires a cipher with a block size"
+                            " of 8 or 16 bytes, not %d" % bs)
+
+        # Compute sub-keys
+        zero_block = b'\x00' * bs
+        self._ecb = ciphermod.new(key,
+                                  ciphermod.MODE_ECB,
+                                  **self._cipher_params)
+        L = self._ecb.encrypt(zero_block)
+        if bord(L[0]) & 0x80:
+            self._k1 = _shift_bytes(L, const_Rb)
+        else:
+            self._k1 = _shift_bytes(L)
+        if bord(self._k1[0]) & 0x80:
+            self._k2 = _shift_bytes(self._k1, const_Rb)
+        else:
+            self._k2 = _shift_bytes(self._k1)
+
+        # Initialize CBC cipher with zero IV
+        self._cbc = ciphermod.new(key,
+                                  ciphermod.MODE_CBC,
+                                  zero_block,
+                                  **self._cipher_params)
+
+        # Cache for outstanding data to authenticate
+        self._cache = bytearray(bs)
+        self._cache_n = 0
+
+        # Last piece of ciphertext produced
+        self._last_ct = zero_block
+
+        # Last block that was encrypted with AES
+        self._last_pt = None
+
+        # Counter for total message size
+        self._data_size = 0
+
+        if msg:
+            self.update(msg)
+
+    def update(self, msg):
+        """Authenticate the next chunk of message.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of data
+        """
+
+        if self._mac_tag is not None and not self._update_after_digest:
+            raise TypeError("update() cannot be called after digest() or verify()")
+
+        self._data_size += len(msg)
+        bs = self._block_size
+
+        if self._cache_n > 0:
+            filler = min(bs - self._cache_n, len(msg))
+            self._cache[self._cache_n:self._cache_n+filler] = msg[:filler]
+            self._cache_n += filler
+
+            if self._cache_n < bs:
+                return self
+
+            msg = memoryview(msg)[filler:]
+            self._update(self._cache)
+            self._cache_n = 0
+
+        remain = len(msg) % bs
+        if remain > 0:
+            self._update(msg[:-remain])
+            self._cache[:remain] = msg[-remain:]
+        else:
+            self._update(msg)
+        self._cache_n = remain
+        return self
+
+    def _update(self, data_block):
+        """Update a block aligned to the block boundary"""
+        
+        bs = self._block_size
+        assert len(data_block) % bs == 0
+
+        if len(data_block) == 0:
+            return
+
+        ct = self._cbc.encrypt(data_block)
+        if len(data_block) == bs:
+            second_last = self._last_ct
+        else:
+            second_last = ct[-bs*2:-bs]
+        self._last_ct = ct[-bs:]
+        self._last_pt = strxor(second_last, data_block[-bs:])
+
+    def copy(self):
+        """Return a copy ("clone") of the CMAC object.
+
+        The copy will have the same internal state as the original CMAC
+        object.
+        This can be used to efficiently compute the MAC tag of byte
+        strings that share a common initial substring.
+
+        :return: An :class:`CMAC`
+        """
+
+        obj = self.__new__(CMAC)
+        obj.__dict__ = self.__dict__.copy()
+        obj._cbc = self._factory.new(self._key,
+                                     self._factory.MODE_CBC,
+                                     self._last_ct,
+                                     **self._cipher_params)
+        obj._cache = self._cache[:]
+        obj._last_ct = self._last_ct[:]
+        return obj
+
+    def digest(self):
+        """Return the **binary** (non-printable) MAC tag of the message
+        that has been authenticated so far.
+
+        :return: The MAC tag, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bs = self._block_size
+
+        if self._mac_tag is not None and not self._update_after_digest:
+            return self._mac_tag
+
+        if self._data_size > self._max_size:
+            raise ValueError("MAC is unsafe for this message")
+
+        if self._cache_n == 0 and self._data_size > 0:
+            # Last block was full
+            pt = strxor(self._last_pt, self._k1)
+        else:
+            # Last block is partial (or message length is zero)
+            partial = self._cache[:]
+            partial[self._cache_n:] = b'\x80' + b'\x00' * (bs - self._cache_n - 1)
+            pt = strxor(strxor(self._last_ct, partial), self._k2)
+
+        self._mac_tag = self._ecb.encrypt(pt)[:self.digest_size]
+
+        return self._mac_tag
+
+    def hexdigest(self):
+        """Return the **printable** MAC tag of the message authenticated so far.
+
+        :return: The MAC tag, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x)
+                        for x in tuple(self.digest())])
+
+    def verify(self, mac_tag):
+        """Verify that a given **binary** MAC (computed by another party)
+        is valid.
+
+        Args:
+          mac_tag (byte string/byte array/memoryview): the expected MAC of the message.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        secret = get_random_bytes(16)
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Return the **printable** MAC tag of the message authenticated so far.
+
+        :return: The MAC tag, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        self.verify(unhexlify(tobytes(hex_mac_tag)))
+
+
+def new(key, msg=None, ciphermod=None, cipher_params=None, mac_len=None,
+        update_after_digest=False):
+    """Create a new MAC object.
+
+    Args:
+        key (byte string/byte array/memoryview):
+            key for the CMAC object.
+            The key must be valid for the underlying cipher algorithm.
+            For instance, it must be 16 bytes long for AES-128.
+        ciphermod (module):
+            A cipher module from :mod:`Crypto.Cipher`.
+            The cipher's block size has to be 128 bits,
+            like :mod:`Crypto.Cipher.AES`, to reduce the probability
+            of collisions.
+        msg (byte string/byte array/memoryview):
+            Optional. The very first chunk of the message to authenticate.
+            It is equivalent to an early call to `CMAC.update`. Optional.
+        cipher_params (dict):
+            Optional. A set of parameters to use when instantiating a cipher
+            object.
+        mac_len (integer):
+            Length of the MAC, in bytes.
+            It must be at least 4 bytes long.
+            The default (and recommended) length matches the size of a cipher block.
+        update_after_digest (boolean):
+            Optional. By default, a hash object cannot be updated anymore after
+            the digest is computed. When this flag is ``True``, such check
+            is no longer enforced.
+    Returns:
+        A :class:`CMAC` object
+    """
+
+    if ciphermod is None:
+        raise TypeError("ciphermod must be specified (try AES)")
+
+    cipher_params = {} if cipher_params is None else dict(cipher_params)
+
+    if mac_len is None:
+        mac_len = ciphermod.block_size
+    
+    if mac_len < 4:
+        raise ValueError("MAC tag length must be at least 4 bytes long")
+    
+    if mac_len > ciphermod.block_size:
+        raise ValueError("MAC tag length cannot be larger than a cipher block (%d) bytes" % ciphermod.block_size)
+
+    return CMAC(key, msg, ciphermod, cipher_params, mac_len,
+                update_after_digest)

+ 30 - 0
tls/pycryptoMod/lib/Crypto/Hash/CMAC.pyi

@@ -0,0 +1,30 @@
+from types import ModuleType
+from typing import Union, Dict
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+digest_size: int
+
+class CMAC(object):
+    digest_size: int
+
+    def __init__(self,
+		 key: Buffer,
+                 msg: Buffer,
+		 ciphermod: ModuleType,
+		 cipher_params: dict,
+                 mac_len: int, update_after_digest: bool) -> None: ...
+    def update(self, data: Buffer) -> CMAC: ...
+    def copy(self) -> CMAC: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+
+def new(key: Buffer,
+        msg: Buffer = ...,
+	ciphermod: ModuleType = ...,
+	cipher_params: Dict = ...,
+	mac_len: int = ...,
+        update_after_digest: bool = ...) -> CMAC: ...

+ 213 - 0
tls/pycryptoMod/lib/Crypto/Hash/HMAC.py

@@ -0,0 +1,213 @@
+#
+# HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord, tobytes, _memoryview
+
+from binascii import unhexlify
+
+from tls.Crypto.Hash import MD5
+from tls.Crypto.Hash import BLAKE2s
+from tls.Crypto.Util.strxor import strxor
+from tls.Crypto.Random import get_random_bytes
+
+__all__ = ['new', 'HMAC']
+
+
+class HMAC(object):
+    """An HMAC hash object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar digest_size: the size in bytes of the resulting MAC tag
+    :vartype digest_size: integer
+    """
+
+    def __init__(self, key, msg=b"", digestmod=None):
+
+        if digestmod is None:
+            digestmod = MD5
+
+        if msg is None:
+            msg = b""
+
+        # Size of the MAC tag
+        self.digest_size = digestmod.digest_size
+
+        self._digestmod = digestmod
+
+        if isinstance(key, _memoryview):
+            key = key.tobytes()
+
+        try:
+            if len(key) <= digestmod.block_size:
+                # Step 1 or 2
+                key_0 = key + b"\x00" * (digestmod.block_size - len(key))
+            else:
+                # Step 3
+                hash_k = digestmod.new(key).digest()
+                key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k))
+        except AttributeError:
+            # Not all hash types have "block_size"
+            raise ValueError("Hash type incompatible to HMAC")
+
+        # Step 4
+        key_0_ipad = strxor(key_0, b"\x36" * len(key_0))
+
+        # Start step 5 and 6
+        self._inner = digestmod.new(key_0_ipad)
+        self._inner.update(msg)
+
+        # Step 7
+        key_0_opad = strxor(key_0, b"\x5c" * len(key_0))
+
+        # Start step 8 and 9
+        self._outer = digestmod.new(key_0_opad)
+
+    def update(self, msg):
+        """Authenticate the next chunk of message.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of data
+        """
+
+        self._inner.update(msg)
+        return self
+
+    def _pbkdf2_hmac_assist(self, first_digest, iterations):
+        """Carry out the expensive inner loop for PBKDF2-HMAC"""
+
+        result = self._digestmod._pbkdf2_hmac_assist(
+                                    self._inner,
+                                    self._outer,
+                                    first_digest,
+                                    iterations)
+        return result
+
+    def copy(self):
+        """Return a copy ("clone") of the HMAC object.
+
+        The copy will have the same internal state as the original HMAC
+        object.
+        This can be used to efficiently compute the MAC tag of byte
+        strings that share a common initial substring.
+
+        :return: An :class:`HMAC`
+        """
+
+        new_hmac = HMAC(b"fake key", digestmod=self._digestmod)
+
+        # Syncronize the state
+        new_hmac._inner = self._inner.copy()
+        new_hmac._outer = self._outer.copy()
+
+        return new_hmac
+
+    def digest(self):
+        """Return the **binary** (non-printable) MAC tag of the message
+        authenticated so far.
+
+        :return: The MAC tag digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        frozen_outer_hash = self._outer.copy()
+        frozen_outer_hash.update(self._inner.digest())
+        return frozen_outer_hash.digest()
+
+    def verify(self, mac_tag):
+        """Verify that a given **binary** MAC (computed by another party)
+        is valid.
+
+        Args:
+          mac_tag (byte string/byte string/memoryview): the expected MAC of the message.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        secret = get_random_bytes(16)
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexdigest(self):
+        """Return the **printable** MAC tag of the message authenticated so far.
+
+        :return: The MAC tag, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x)
+                        for x in tuple(self.digest())])
+
+    def hexverify(self, hex_mac_tag):
+        """Verify that a given **printable** MAC (computed by another party)
+        is valid.
+
+        Args:
+            hex_mac_tag (string): the expected MAC of the message,
+                as a hexadecimal string.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        self.verify(unhexlify(tobytes(hex_mac_tag)))
+
+
+def new(key, msg=b"", digestmod=None):
+    """Create a new MAC object.
+
+    Args:
+        key (bytes/bytearray/memoryview):
+            key for the MAC object.
+            It must be long enough to match the expected security level of the
+            MAC.
+        msg (bytes/bytearray/memoryview):
+            Optional. The very first chunk of the message to authenticate.
+            It is equivalent to an early call to :meth:`HMAC.update`.
+        digestmod (module):
+            The hash to use to implement the HMAC.
+            Default is :mod:`Crypto.Hash.MD5`.
+
+    Returns:
+        An :class:`HMAC` object
+    """
+
+    return HMAC(key, msg, digestmod)

+ 25 - 0
tls/pycryptoMod/lib/Crypto/Hash/HMAC.pyi

@@ -0,0 +1,25 @@
+from types import ModuleType
+from typing import Union, Dict
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+digest_size: int
+
+class HMAC(object):
+    digest_size: int
+
+    def __init__(self,
+		 key: Buffer,
+                 msg: Buffer,
+		 digestmod: ModuleType) -> None: ...
+    def update(self, msg: Buffer) -> HMAC: ...
+    def copy(self) -> HMAC: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+
+def new(key: Buffer,
+        msg: Buffer = ...,
+	digestmod: ModuleType = ...) -> HMAC: ...

+ 166 - 0
tls/pycryptoMod/lib/Crypto/Hash/MD2.py

@@ -0,0 +1,166 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_md2_lib = load_pycryptodome_raw_lib(
+                        "Crypto.Hash._MD2",
+                        """
+                        int md2_init(void **shaState);
+                        int md2_destroy(void *shaState);
+                        int md2_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int md2_digest(const void *shaState,
+                                          uint8_t digest[20]);
+                        int md2_copy(const void *src, void *dst);
+                        """)
+
+
+class MD2Hash(object):
+    """An MD2 hash object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 16
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 16
+    # ASN.1 Object ID
+    oid = "1.2.840.113549.2.2"
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_md2_lib.md2_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating MD2"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_md2_lib.md2_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        result = _raw_md2_lib.md2_update(self._state.get(),
+                                         c_uint8_ptr(data),
+                                         c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while instantiating MD2"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_md2_lib.md2_digest(self._state.get(),
+                                         bfr)
+        if result:
+            raise ValueError("Error %d while instantiating MD2"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :return: A hash object of the same type
+        """
+
+        clone = MD2Hash()
+        result = _raw_md2_lib.md2_copy(self._state.get(),
+                                       clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying MD2" % result)
+        return clone
+
+    def new(self, data=None):
+        return MD2Hash(data)
+
+
+def new(data=None):
+    """Create a new hash object.
+
+    :parameter data:
+        Optional. The very first chunk of the message to hash.
+        It is equivalent to an early call to :meth:`MD2Hash.update`.
+    :type data: bytes/bytearray/memoryview
+
+    :Return: A :class:`MD2Hash` hash object
+    """
+
+    return MD2Hash().new(data)
+
+# The size of the resulting hash in bytes.
+digest_size = MD2Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = MD2Hash.block_size

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Hash/MD2.pyi

@@ -0,0 +1,19 @@
+from typing import Union
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class MD4Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+
+    def __init__(self, data: Buffer = ...) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> MD4Hash: ...
+    def new(self, data: Buffer = ...) -> MD4Hash: ...
+
+def new(data: Buffer = ...) -> MD4Hash: ...
+digest_size: int
+block_size: int

+ 185 - 0
tls/pycryptoMod/lib/Crypto/Hash/MD4.py

@@ -0,0 +1,185 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.
+
+    >>> from tls.Crypto.Hash import MD4
+    >>>
+    >>> h = MD4.new()
+    >>> h.update(b'Hello')
+    >>> print h.hexdigest()
+
+MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.
+This algorithm is insecure. Do not use it for new designs.
+
+.. _RFC1320: http://tools.ietf.org/html/rfc1320
+"""
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_md4_lib = load_pycryptodome_raw_lib(
+                        "Crypto.Hash._MD4",
+                        """
+                        int md4_init(void **shaState);
+                        int md4_destroy(void *shaState);
+                        int md4_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int md4_digest(const void *shaState,
+                                          uint8_t digest[20]);
+                        int md4_copy(const void *src, void *dst);
+                        """)
+
+
+class MD4Hash(object):
+    """Class that implements an MD4 hash
+    """
+
+    #: The size of the resulting hash in bytes.
+    digest_size = 16
+    #: The internal block size of the hash algorithm in bytes.
+    block_size = 64
+    #: ASN.1 Object ID
+    oid = "1.2.840.113549.2.4"
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_md4_lib.md4_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating MD4"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_md4_lib.md4_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Repeated calls are equivalent to a single call with the concatenation
+        of all the arguments. In other words:
+
+           >>> m.update(a); m.update(b)
+
+        is equivalent to:
+
+           >>> m.update(a+b)
+
+        :Parameters:
+          data : byte string/byte array/memoryview
+            The next chunk of the message being hashed.
+        """
+
+        result = _raw_md4_lib.md4_update(self._state.get(),
+                                         c_uint8_ptr(data),
+                                         c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while instantiating MD4"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that
+        has been hashed so far.
+
+        This method does not change the state of the hash object.
+        You can continue updating the object after calling this function.
+
+        :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
+         characters, including null bytes.
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_md4_lib.md4_digest(self._state.get(),
+                                         bfr)
+        if result:
+            raise ValueError("Error %d while instantiating MD4"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been
+        hashed so far.
+
+        This method does not change the state of the hash object.
+
+        :Return: A string of 2* `digest_size` characters. It contains only
+         hexadecimal ASCII digits.
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :Return: A hash object of the same type
+        """
+
+        clone = MD4Hash()
+        result = _raw_md4_lib.md4_copy(self._state.get(),
+                                       clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying MD4" % result)
+        return clone
+
+    def new(self, data=None):
+        return MD4Hash(data)
+
+
+def new(data=None):
+    """Return a fresh instance of the hash object.
+
+    :Parameters:
+       data : byte string/byte array/memoryview
+        The very first chunk of the message to hash.
+        It is equivalent to an early call to `MD4Hash.update()`.
+        Optional.
+
+    :Return: A `MD4Hash` object
+    """
+    return MD4Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = MD4Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = MD4Hash.block_size

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Hash/MD4.pyi

@@ -0,0 +1,19 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class MD4Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+
+    def __init__(self, data: Optional[Buffer] = ...) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> MD4Hash: ...
+    def new(self, data: Optional[Buffer] = ...) -> MD4Hash: ...
+
+def new(data: Optional[Buffer] = ...) -> MD4Hash: ...
+digest_size: int
+block_size: int

+ 184 - 0
tls/pycryptoMod/lib/Crypto/Hash/MD5.py

@@ -0,0 +1,184 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import *
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_md5_lib = load_pycryptodome_raw_lib("Crypto.Hash._MD5",
+                        """
+                        #define MD5_DIGEST_SIZE 16
+
+                        int MD5_init(void **shaState);
+                        int MD5_destroy(void *shaState);
+                        int MD5_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int MD5_digest(const void *shaState,
+                                          uint8_t digest[MD5_DIGEST_SIZE]);
+                        int MD5_copy(const void *src, void *dst);
+
+                        int MD5_pbkdf2_hmac_assist(const void *inner,
+                                            const void *outer,
+                                            const uint8_t first_digest[MD5_DIGEST_SIZE],
+                                            uint8_t final_digest[MD5_DIGEST_SIZE],
+                                            size_t iterations);
+                        """)
+
+class MD5Hash(object):
+    """A MD5 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 16
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 64
+    # ASN.1 Object ID
+    oid = "1.2.840.113549.2.5"
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_md5_lib.MD5_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating MD5"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_md5_lib.MD5_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        result = _raw_md5_lib.MD5_update(self._state.get(),
+                                         c_uint8_ptr(data),
+                                         c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while instantiating MD5"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_md5_lib.MD5_digest(self._state.get(),
+                                           bfr)
+        if result:
+            raise ValueError("Error %d while instantiating MD5"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :return: A hash object of the same type
+        """
+
+        clone = MD5Hash()
+        result = _raw_md5_lib.MD5_copy(self._state.get(),
+                                         clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying MD5" % result)
+        return clone
+
+    def new(self, data=None):
+        """Create a fresh SHA-1 hash object."""
+
+        return MD5Hash(data)
+
+
+def new(data=None):
+    """Create a new hash object.
+
+    :parameter data:
+        Optional. The very first chunk of the message to hash.
+        It is equivalent to an early call to :meth:`MD5Hash.update`.
+    :type data: byte string/byte array/memoryview
+
+    :Return: A :class:`MD5Hash` hash object
+    """
+    return MD5Hash().new(data)
+
+# The size of the resulting hash in bytes.
+digest_size = 16
+
+# The internal block size of the hash algorithm in bytes.
+block_size = 64
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+    """Compute the expensive inner loop in PBKDF-HMAC."""
+
+    assert len(first_digest) == digest_size
+    assert iterations > 0
+
+    bfr = create_string_buffer(digest_size);
+    result = _raw_md5_lib.MD5_pbkdf2_hmac_assist(
+                    inner._state.get(),
+                    outer._state.get(),
+                    first_digest,
+                    bfr,
+                    c_size_t(iterations))
+
+    if result:
+        raise ValueError("Error %d with PBKDF2-HMAC assis for MD5" % result)
+
+    return get_raw_buffer(bfr)

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Hash/MD5.pyi

@@ -0,0 +1,19 @@
+from typing import Union
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class MD5Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+
+    def __init__(self, data: Buffer = ...) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> MD5Hash: ...
+    def new(self, data: Buffer = ...) -> MD5Hash: ...
+
+def new(data: Buffer = ...) -> MD5Hash: ...
+digest_size: int
+block_size: int

+ 217 - 0
tls/pycryptoMod/lib/Crypto/Hash/Poly1305.py

@@ -0,0 +1,217 @@
+# -*- coding: utf-8 -*-
+#
+# Hash/Poly1305.py - Implements the Poly1305 MAC
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from binascii import unhexlify
+
+from tls.Crypto.Util.py3compat import bord, tobytes, _copy_bytes
+
+from tls.Crypto.Hash import BLAKE2s
+from tls.Crypto.Random import get_random_bytes
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+
+_raw_poly1305 = load_pycryptodome_raw_lib("Crypto.Hash._poly1305",
+                        """
+                        int poly1305_init(void **state,
+                                          const uint8_t *r,
+                                          size_t r_len,
+                                          const uint8_t *s,
+                                          size_t s_len);
+                        int poly1305_destroy(void *state);
+                        int poly1305_update(void *state,
+                                            const uint8_t *in,
+                                            size_t len);
+                        int poly1305_digest(const void *state,
+                                            uint8_t *digest,
+                                            size_t len);
+                        """)
+
+
+class Poly1305_MAC(object):
+    """An Poly1305 MAC object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar digest_size: the size in bytes of the resulting MAC tag
+    :vartype digest_size: integer
+    """
+
+    digest_size = 16
+
+    def __init__(self, r, s, data):
+
+        if len(r) != 16:
+            raise ValueError("Parameter r is not 16 bytes long")
+        if len(s) != 16:
+            raise ValueError("Parameter s is not 16 bytes long")
+
+        self._mac_tag = None
+
+        state = VoidPointer()
+        result = _raw_poly1305.poly1305_init(state.address_of(),
+                                             c_uint8_ptr(r),
+                                             c_size_t(len(r)),
+                                             c_uint8_ptr(s),
+                                             c_size_t(len(s))
+                                             )
+        if result:
+            raise ValueError("Error %d while instantiating Poly1305" % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_poly1305.poly1305_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Authenticate the next chunk of message.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of data
+        """
+
+        if self._mac_tag:
+            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+        result = _raw_poly1305.poly1305_update(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while hashing Poly1305 data" % result)
+        return self
+
+    def copy(self):
+        raise NotImplementedError()
+
+    def digest(self):
+        """Return the **binary** (non-printable) MAC tag of the message
+        authenticated so far.
+
+        :return: The MAC tag digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        if self._mac_tag:
+            return self._mac_tag
+        
+        bfr = create_string_buffer(16)
+        result = _raw_poly1305.poly1305_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(len(bfr)))
+        if result:
+            raise ValueError("Error %d while creating Poly1305 digest" % result)
+
+        self._mac_tag = get_raw_buffer(bfr)
+        return self._mac_tag
+
+    def hexdigest(self):
+        """Return the **printable** MAC tag of the message authenticated so far.
+
+        :return: The MAC tag, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x)
+                        for x in tuple(self.digest())])
+
+    def verify(self, mac_tag):
+        """Verify that a given **binary** MAC (computed by another party)
+        is valid.
+
+        Args:
+          mac_tag (byte string/byte string/memoryview): the expected MAC of the message.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        secret = get_random_bytes(16)
+
+        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
+        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
+
+        if mac1.digest() != mac2.digest():
+            raise ValueError("MAC check failed")
+
+    def hexverify(self, hex_mac_tag):
+        """Verify that a given **printable** MAC (computed by another party)
+        is valid.
+
+        Args:
+            hex_mac_tag (string): the expected MAC of the message,
+                as a hexadecimal string.
+
+        Raises:
+            ValueError: if the MAC does not match. It means that the message
+                has been tampered with or that the MAC key is incorrect.
+        """
+
+        self.verify(unhexlify(tobytes(hex_mac_tag)))
+
+
+
+def new(**kwargs):
+    """Create a new Poly1305 MAC object.
+
+    Args:
+        key (bytes/bytearray/memoryview):
+            The 32-byte key for the Poly1305 object.
+        cipher (module from ``Crypto.Cipher``):
+            The cipher algorithm to use for deriving the Poly1305
+            key pair *(r, s)*.
+            It can only be ``Crypto.Cipher.AES`` or ``Crypto.Cipher.ChaCha20``.
+        nonce (bytes/bytearray/memoryview):
+            Optional. The non-repeatable value to use for the MAC of this message.
+            It must be 16 bytes long for ``AES`` and 8 or 12 bytes for ``ChaCha20``.
+            If not passed, a random nonce is created; you will find it in the
+            ``nonce`` attribute of the new object.
+        data (bytes/bytearray/memoryview):
+            Optional. The very first chunk of the message to authenticate.
+            It is equivalent to an early call to ``update()``.
+
+    Returns:
+        A :class:`Poly1305_MAC` object
+    """
+
+    cipher = kwargs.pop("cipher", None)
+    if not hasattr(cipher, '_derive_Poly1305_key_pair'):
+        raise ValueError("Parameter 'cipher' must be AES or ChaCha20")
+
+    cipher_key = kwargs.pop("key", None)
+    if cipher_key is None:
+        raise TypeError("You must pass a parameter 'key'")
+
+    nonce = kwargs.pop("nonce", None)
+    data = kwargs.pop("data", None)
+    
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    r, s, nonce = cipher._derive_Poly1305_key_pair(cipher_key, nonce)
+    
+    new_mac = Poly1305_MAC(r, s, data)
+    new_mac.nonce = _copy_bytes(None, None, nonce)  # nonce may still be just a memoryview
+    return new_mac

+ 24 - 0
tls/pycryptoMod/lib/Crypto/Hash/Poly1305.pyi

@@ -0,0 +1,24 @@
+from types import ModuleType
+from typing import Union
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class Poly1305_MAC(object):
+    block_size: int
+    digest_size: int
+    oid: str
+
+    def __init__(self,
+                 r : int,
+                 s : int,
+                 data : Buffer) -> None: ...
+    def update(self, data: Buffer) -> Poly1305_MAC: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def verify(self, mac_tag: Buffer) -> None: ...
+    def hexverify(self, hex_mac_tag: str) -> None: ...
+
+def new(key: Buffer,
+        cipher: ModuleType,
+        nonce: Buffer = ...,
+        data: Buffer = ...) -> Poly1305_MAC: ...

+ 26 - 0
tls/pycryptoMod/lib/Crypto/Hash/RIPEMD.py

@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+# This file exists for backward compatibility with old code that refers to
+# Crypto.Hash.RIPEMD
+
+"""Deprecated alias for `Crypto.Hash.RIPEMD160`"""
+
+from tls.Crypto.Hash.RIPEMD160 import new, block_size, digest_size

+ 3 - 0
tls/pycryptoMod/lib/Crypto/Hash/RIPEMD.pyi

@@ -0,0 +1,3 @@
+# This file exists for backward compatibility with old code that refers to
+# Crypto.Hash.SHA
+

+ 169 - 0
tls/pycryptoMod/lib/Crypto/Hash/RIPEMD160.py

@@ -0,0 +1,169 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_ripemd160_lib = load_pycryptodome_raw_lib(
+                        "Crypto.Hash._RIPEMD160",
+                        """
+                        int ripemd160_init(void **shaState);
+                        int ripemd160_destroy(void *shaState);
+                        int ripemd160_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int ripemd160_digest(const void *shaState,
+                                          uint8_t digest[20]);
+                        int ripemd160_copy(const void *src, void *dst);
+                        """)
+
+
+class RIPEMD160Hash(object):
+    """A RIPEMD-160 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 20
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 64
+    # ASN.1 Object ID
+    oid = "1.3.36.3.2.1"
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_ripemd160_lib.ripemd160_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating RIPEMD160"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_ripemd160_lib.ripemd160_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        result = _raw_ripemd160_lib.ripemd160_update(self._state.get(),
+                                                     c_uint8_ptr(data),
+                                                     c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while instantiating ripemd160"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_ripemd160_lib.ripemd160_digest(self._state.get(),
+                                                     bfr)
+        if result:
+            raise ValueError("Error %d while instantiating ripemd160"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :return: A hash object of the same type
+        """
+
+        clone = RIPEMD160Hash()
+        result = _raw_ripemd160_lib.ripemd160_copy(self._state.get(),
+                                                   clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying ripemd160" % result)
+        return clone
+
+    def new(self, data=None):
+        """Create a fresh RIPEMD-160 hash object."""
+
+        return RIPEMD160Hash(data)
+
+
+def new(data=None):
+    """Create a new hash object.
+
+    :parameter data:
+        Optional. The very first chunk of the message to hash.
+        It is equivalent to an early call to :meth:`RIPEMD160Hash.update`.
+    :type data: byte string/byte array/memoryview
+
+    :Return: A :class:`RIPEMD160Hash` hash object
+    """
+
+    return RIPEMD160Hash().new(data)
+
+# The size of the resulting hash in bytes.
+digest_size = RIPEMD160Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = RIPEMD160Hash.block_size

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Hash/RIPEMD160.pyi

@@ -0,0 +1,19 @@
+from typing import Union
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class RIPEMD160Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+
+    def __init__(self, data: Buffer = ...) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> RIPEMD160Hash: ...
+    def new(self, data: Buffer = ...) -> RIPEMD160Hash: ...
+
+def new(data: Buffer = ...) -> RIPEMD160Hash: ...
+digest_size: int
+block_size: int

+ 24 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA.py

@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+# This file exists for backward compatibility with old code that refers to
+# Crypto.Hash.SHA
+
+from tls.Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size

+ 4 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA.pyi

@@ -0,0 +1,4 @@
+# This file exists for backward compatibility with old code that refers to
+# Crypto.Hash.SHA
+
+from tls.Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size

+ 185 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA1.py

@@ -0,0 +1,185 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import *
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_sha1_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA1",
+                        """
+                        #define SHA1_DIGEST_SIZE 20
+
+                        int SHA1_init(void **shaState);
+                        int SHA1_destroy(void *shaState);
+                        int SHA1_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int SHA1_digest(const void *shaState,
+                                          uint8_t digest[SHA1_DIGEST_SIZE]);
+                        int SHA1_copy(const void *src, void *dst);
+
+                        int SHA1_pbkdf2_hmac_assist(const void *inner,
+                                            const void *outer,
+                                            const uint8_t first_digest[SHA1_DIGEST_SIZE],
+                                            uint8_t final_digest[SHA1_DIGEST_SIZE],
+                                            size_t iterations);
+                        """)
+
+class SHA1Hash(object):
+    """A SHA-1 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 20
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 64
+    # ASN.1 Object ID
+    oid = "1.3.14.3.2.26"
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_sha1_lib.SHA1_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating SHA1"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_sha1_lib.SHA1_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        result = _raw_sha1_lib.SHA1_update(self._state.get(),
+                                           c_uint8_ptr(data),
+                                           c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while instantiating SHA1"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_sha1_lib.SHA1_digest(self._state.get(),
+                                           bfr)
+        if result:
+            raise ValueError("Error %d while instantiating SHA1"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :return: A hash object of the same type
+        """
+
+        clone = SHA1Hash()
+        result = _raw_sha1_lib.SHA1_copy(self._state.get(),
+                                         clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying SHA1" % result)
+        return clone
+
+    def new(self, data=None):
+        """Create a fresh SHA-1 hash object."""
+
+        return SHA1Hash(data)
+
+
+def new(data=None):
+    """Create a new hash object.
+
+    :parameter data:
+        Optional. The very first chunk of the message to hash.
+        It is equivalent to an early call to :meth:`SHA1Hash.update`.
+    :type data: byte string/byte array/memoryview
+
+    :Return: A :class:`SHA1Hash` hash object
+    """
+    return SHA1Hash().new(data)
+
+
+# The size of the resulting hash in bytes.
+digest_size = SHA1Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = SHA1Hash.block_size
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+    """Compute the expensive inner loop in PBKDF-HMAC."""
+
+    assert len(first_digest) == digest_size
+    assert iterations > 0
+
+    bfr = create_string_buffer(digest_size);
+    result = _raw_sha1_lib.SHA1_pbkdf2_hmac_assist(
+                    inner._state.get(),
+                    outer._state.get(),
+                    first_digest,
+                    bfr,
+                    c_size_t(iterations))
+
+    if result:
+        raise ValueError("Error %d with PBKDF2-HMAC assis for SHA1" % result)
+
+    return get_raw_buffer(bfr)

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA1.pyi

@@ -0,0 +1,19 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA1Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+
+    def __init__(self, data: Optional[Buffer] = ...) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> SHA1Hash: ...
+    def new(self, data: Optional[Buffer] = ...) -> SHA1Hash: ...
+
+def new(data: Optional[Buffer] = ...) -> SHA1Hash: ...
+digest_size: int
+block_size: int

+ 186 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA224.py

@@ -0,0 +1,186 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_sha224_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA224",
+                        """
+                        int SHA224_init(void **shaState);
+                        int SHA224_destroy(void *shaState);
+                        int SHA224_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int SHA224_digest(const void *shaState,
+                                          uint8_t *digest,
+                                          size_t digest_size);
+                        int SHA224_copy(const void *src, void *dst);
+
+                        int SHA224_pbkdf2_hmac_assist(const void *inner,
+                                            const void *outer,
+                                            const uint8_t *first_digest,
+                                            uint8_t *final_digest,
+                                            size_t iterations,
+                                            size_t digest_size);
+                        """)
+
+class SHA224Hash(object):
+    """A SHA-224 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 28
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 64
+    # ASN.1 Object ID
+    oid = '2.16.840.1.101.3.4.2.4'
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_sha224_lib.SHA224_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating SHA224"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_sha224_lib.SHA224_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        result = _raw_sha224_lib.SHA224_update(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while hashing data with SHA224"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_sha224_lib.SHA224_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(self.digest_size))
+        if result:
+            raise ValueError("Error %d while making SHA224 digest"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :return: A hash object of the same type
+        """
+
+        clone = SHA224Hash()
+        result = _raw_sha224_lib.SHA224_copy(self._state.get(),
+                                             clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying SHA224" % result)
+        return clone
+
+    def new(self, data=None):
+        """Create a fresh SHA-224 hash object."""
+
+        return SHA224Hash(data)
+
+
+def new(data=None):
+    """Create a new hash object.
+
+    :parameter data:
+        Optional. The very first chunk of the message to hash.
+        It is equivalent to an early call to :meth:`SHA224Hash.update`.
+    :type data: byte string/byte array/memoryview
+
+    :Return: A :class:`SHA224Hash` hash object
+    """
+    return SHA224Hash().new(data)
+
+
+# The size of the resulting hash in bytes.
+digest_size = SHA224Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = SHA224Hash.block_size
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+    """Compute the expensive inner loop in PBKDF-HMAC."""
+
+    assert iterations > 0
+
+    bfr = create_string_buffer(len(first_digest));
+    result = _raw_sha224_lib.SHA224_pbkdf2_hmac_assist(
+                    inner._state.get(),
+                    outer._state.get(),
+                    first_digest,
+                    bfr,
+                    c_size_t(iterations),
+                    c_size_t(len(first_digest)))
+
+    if result:
+        raise ValueError("Error %d with PBKDF2-HMAC assist for SHA224" % result)
+
+    return get_raw_buffer(bfr)

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA224.pyi

@@ -0,0 +1,19 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA224Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+
+    def __init__(self, data: Optional[Buffer] = ...) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> SHA224Hash: ...
+    def new(self, data: Optional[Buffer] = ...) -> SHA224Hash: ...
+
+def new(data: Optional[Buffer] = ...) -> SHA224Hash: ...
+digest_size: int
+block_size: int

+ 185 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA256.py

@@ -0,0 +1,185 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_sha256_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA256",
+                        """
+                        int SHA256_init(void **shaState);
+                        int SHA256_destroy(void *shaState);
+                        int SHA256_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int SHA256_digest(const void *shaState,
+                                          uint8_t *digest,
+                                          size_t digest_size);
+                        int SHA256_copy(const void *src, void *dst);
+
+                        int SHA256_pbkdf2_hmac_assist(const void *inner,
+                                            const void *outer,
+                                            const uint8_t *first_digest,
+                                            uint8_t *final_digest,
+                                            size_t iterations,
+                                            size_t digest_size);
+                        """)
+
+class SHA256Hash(object):
+    """A SHA-256 hash object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 32
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 64
+    # ASN.1 Object ID
+    oid = "2.16.840.1.101.3.4.2.1"
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_sha256_lib.SHA256_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating SHA256"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_sha256_lib.SHA256_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        result = _raw_sha256_lib.SHA256_update(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while hashing data with SHA256"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_sha256_lib.SHA256_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(self.digest_size))
+        if result:
+            raise ValueError("Error %d while making SHA256 digest"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :return: A hash object of the same type
+        """
+
+        clone = SHA256Hash()
+        result = _raw_sha256_lib.SHA256_copy(self._state.get(),
+                                             clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying SHA256" % result)
+        return clone
+
+    def new(self, data=None):
+        """Create a fresh SHA-256 hash object."""
+
+        return SHA256Hash(data)
+
+def new(data=None):
+    """Create a new hash object.
+
+    :parameter data:
+        Optional. The very first chunk of the message to hash.
+        It is equivalent to an early call to :meth:`SHA256Hash.update`.
+    :type data: byte string/byte array/memoryview
+
+    :Return: A :class:`SHA256Hash` hash object
+    """
+
+    return SHA256Hash().new(data)
+
+
+# The size of the resulting hash in bytes.
+digest_size = SHA256Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = SHA256Hash.block_size
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+    """Compute the expensive inner loop in PBKDF-HMAC."""
+
+    assert iterations > 0
+
+    bfr = create_string_buffer(len(first_digest));
+    result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist(
+                    inner._state.get(),
+                    outer._state.get(),
+                    first_digest,
+                    bfr,
+                    c_size_t(iterations),
+                    c_size_t(len(first_digest)))
+
+    if result:
+        raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result)
+
+    return get_raw_buffer(bfr)

+ 18 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA256.pyi

@@ -0,0 +1,18 @@
+from typing import Union, Optional
+
+
+class SHA256Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+    def __init__(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> None: ...
+    def update(self, data: Union[bytes, bytearray, memoryview]) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> SHA256Hash: ...
+    def new(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ...
+
+def new(data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ...
+
+digest_size: int
+block_size: int

+ 186 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA384.py

@@ -0,0 +1,186 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+_raw_sha384_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA384",
+                        """
+                        int SHA384_init(void **shaState);
+                        int SHA384_destroy(void *shaState);
+                        int SHA384_update(void *hs,
+                                          const uint8_t *buf,
+                                          size_t len);
+                        int SHA384_digest(const void *shaState,
+                                          uint8_t *digest,
+                                          size_t digest_size);
+                        int SHA384_copy(const void *src, void *dst);
+
+                        int SHA384_pbkdf2_hmac_assist(const void *inner,
+                                            const void *outer,
+                                            const uint8_t *first_digest,
+                                            uint8_t *final_digest,
+                                            size_t iterations,
+                                            size_t digest_size);
+                        """)
+
+class SHA384Hash(object):
+    """A SHA-384 hash object.
+    Do not instantiate directly. Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar block_size: the size in bytes of the internal message block,
+                      input to the compression function
+    :vartype block_size: integer
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 48
+    # The internal block size of the hash algorithm in bytes.
+    block_size = 128
+    # ASN.1 Object ID
+    oid = '2.16.840.1.101.3.4.2.2'
+
+    def __init__(self, data=None):
+        state = VoidPointer()
+        result = _raw_sha384_lib.SHA384_init(state.address_of())
+        if result:
+            raise ValueError("Error %d while instantiating SHA384"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_sha384_lib.SHA384_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        result = _raw_sha384_lib.SHA384_update(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while hashing data with SHA384"
+                             % result)
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_sha384_lib.SHA384_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(self.digest_size))
+        if result:
+            raise ValueError("Error %d while making SHA384 digest"
+                             % result)
+
+        return get_raw_buffer(bfr)
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def copy(self):
+        """Return a copy ("clone") of the hash object.
+
+        The copy will have the same internal state as the original hash
+        object.
+        This can be used to efficiently compute the digests of strings that
+        share a common initial substring.
+
+        :return: A hash object of the same type
+        """
+
+        clone = SHA384Hash()
+        result = _raw_sha384_lib.SHA384_copy(self._state.get(),
+                                             clone._state.get())
+        if result:
+            raise ValueError("Error %d while copying SHA384" % result)
+        return clone
+
+    def new(self, data=None):
+        """Create a fresh SHA-384 hash object."""
+
+        return SHA384Hash(data)
+
+
+def new(data=None):
+    """Create a new hash object.
+
+    :parameter data:
+        Optional. The very first chunk of the message to hash.
+        It is equivalent to an early call to :meth:`SHA384Hash.update`.
+    :type data: byte string/byte array/memoryview
+
+    :Return: A :class:`SHA384Hash` hash object
+    """
+
+    return SHA384Hash().new(data)
+
+
+# The size of the resulting hash in bytes.
+digest_size = SHA384Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = SHA384Hash.block_size
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+    """Compute the expensive inner loop in PBKDF-HMAC."""
+
+    assert iterations > 0
+
+    bfr = create_string_buffer(len(first_digest));
+    result = _raw_sha384_lib.SHA384_pbkdf2_hmac_assist(
+                    inner._state.get(),
+                    outer._state.get(),
+                    first_digest,
+                    bfr,
+                    c_size_t(iterations),
+                    c_size_t(len(first_digest)))
+
+    if result:
+        raise ValueError("Error %d with PBKDF2-HMAC assist for SHA384" % result)
+
+    return get_raw_buffer(bfr)

+ 19 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA384.pyi

@@ -0,0 +1,19 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA384Hash(object):
+    digest_size: int
+    block_size: int
+    oid: str
+
+    def __init__(self, data: Optional[Buffer] = ...) -> None: ...
+    def update(self, data: Buffer) -> None: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def copy(self) -> SHA384Hash: ...
+    def new(self, data: Optional[Buffer] = ...) -> SHA384Hash: ...
+
+def new(data: Optional[Buffer] = ...) -> SHA384Hash: ...
+digest_size: int
+block_size: int

+ 147 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_224.py

@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+from tls.Crypto.Hash.keccak import _raw_keccak_lib
+
+class SHA3_224_Hash(object):
+    """A SHA3-224 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 28
+
+    # ASN.1 Object ID
+    oid = "2.16.840.1.101.3.4.2.7"
+
+    def __init__(self, data, update_after_digest):
+        self._update_after_digest = update_after_digest
+        self._digest_done = False
+
+        state = VoidPointer()
+        result = _raw_keccak_lib.keccak_init(state.address_of(),
+                                             c_size_t(self.digest_size * 2),
+                                             0x06)
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/224"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_keccak_lib.keccak_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        if self._digest_done and not self._update_after_digest:
+            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+        result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while updating SHA-3/224"
+                             % result)
+        return self
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        self._digest_done = True
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_keccak_lib.keccak_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(self.digest_size))
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/224"
+                             % result)
+
+        self._digest_value = get_raw_buffer(bfr)
+        return self._digest_value
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def new(self):
+        """Create a fresh SHA3-224 hash object."""
+
+        return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+    """Create a new hash object.
+
+    Args:
+        data (byte string/byte array/memoryview):
+            The very first chunk of the message to hash.
+            It is equivalent to an early call to :meth:`update`.
+        update_after_digest (boolean):
+            Whether :meth:`digest` can be followed by another :meth:`update`
+            (default: ``False``).
+
+    :Return: A :class:`SHA3_224_Hash` hash object
+    """
+
+    data = kwargs.pop("data", None)
+    update_after_digest = kwargs.pop("update_after_digest", False)
+    if len(args) == 1:
+        if data:
+            raise ValueError("Initial data for hash specified twice")
+        data = args[0]
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return SHA3_224_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_224_Hash.digest_size

+ 16 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_224.pyi

@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_224_Hash(object):
+    digest_size: int
+    oid: str
+    def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+    def update(self, data: Buffer) -> SHA3_224_Hash: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def new(self) -> SHA3_224_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_224_Hash: ...
+
+digest_size: int

+ 147 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_256.py

@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+from tls.Crypto.Hash.keccak import _raw_keccak_lib
+
+class SHA3_256_Hash(object):
+    """A SHA3-256 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 32
+
+    # ASN.1 Object ID
+    oid = "2.16.840.1.101.3.4.2.8"
+
+    def __init__(self, data, update_after_digest):
+        self._update_after_digest = update_after_digest
+        self._digest_done = False
+
+        state = VoidPointer()
+        result = _raw_keccak_lib.keccak_init(state.address_of(),
+                                             c_size_t(self.digest_size * 2),
+                                             0x06)
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/256"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_keccak_lib.keccak_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        if self._digest_done and not self._update_after_digest:
+            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+        result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while updating SHA-3/256"
+                             % result)
+        return self
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        self._digest_done = True
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_keccak_lib.keccak_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(self.digest_size))
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/256"
+                             % result)
+
+        self._digest_value = get_raw_buffer(bfr)
+        return self._digest_value
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def new(self):
+        """Create a fresh SHA3-256 hash object."""
+
+        return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+    """Create a new hash object.
+
+    Args:
+        data (byte string/byte array/memoryview):
+            The very first chunk of the message to hash.
+            It is equivalent to an early call to :meth:`update`.
+        update_after_digest (boolean):
+            Whether :meth:`digest` can be followed by another :meth:`update`
+            (default: ``False``).
+
+    :Return: A :class:`SHA3_256_Hash` hash object
+    """
+
+    data = kwargs.pop("data", None)
+    update_after_digest = kwargs.pop("update_after_digest", False)
+    if len(args) == 1:
+        if data:
+            raise ValueError("Initial data for hash specified twice")
+        data = args[0]
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return SHA3_256_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_256_Hash.digest_size

+ 16 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_256.pyi

@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_256_Hash(object):
+    digest_size: int
+    oid: str
+    def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+    def update(self, data: Buffer) -> SHA3_256_Hash: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def new(self) -> SHA3_256_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_256_Hash: ...
+
+digest_size: int

+ 147 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_384.py

@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+from tls.Crypto.Hash.keccak import _raw_keccak_lib
+
+class SHA3_384_Hash(object):
+    """A SHA3-384 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 48
+
+    # ASN.1 Object ID
+    oid = "2.16.840.1.101.3.4.2.9"
+
+    def __init__(self, data, update_after_digest):
+        self._update_after_digest = update_after_digest
+        self._digest_done = False
+
+        state = VoidPointer()
+        result = _raw_keccak_lib.keccak_init(state.address_of(),
+                                             c_size_t(self.digest_size * 2),
+                                             0x06)
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/384"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_keccak_lib.keccak_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        if self._digest_done and not self._update_after_digest:
+            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+        result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while updating SHA-3/384"
+                             % result)
+        return self
+
+    def digest(self):
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        self._digest_done = True
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_keccak_lib.keccak_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(self.digest_size))
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/384"
+                             % result)
+
+        self._digest_value = get_raw_buffer(bfr)
+        return self._digest_value
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def new(self):
+        """Create a fresh SHA3-384 hash object."""
+
+        return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+    """Create a new hash object.
+
+    Args:
+        data (byte string/byte array/memoryview):
+            The very first chunk of the message to hash.
+            It is equivalent to an early call to :meth:`update`.
+        update_after_digest (boolean):
+            Whether :meth:`digest` can be followed by another :meth:`update`
+            (default: ``False``).
+
+    :Return: A :class:`SHA3_384_Hash` hash object
+    """
+
+    data = kwargs.pop("data", None)
+    update_after_digest = kwargs.pop("update_after_digest", False)
+    if len(args) == 1:
+        if data:
+            raise ValueError("Initial data for hash specified twice")
+        data = args[0]
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return SHA3_384_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_384_Hash.digest_size

+ 16 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_384.pyi

@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_384_Hash(object):
+    digest_size: int
+    oid: str
+    def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+    def update(self, data: Buffer) -> SHA3_384_Hash: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def new(self) -> SHA3_384_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_384_Hash: ...
+
+digest_size: int

+ 148 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_512.py

@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain.  To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from tls.Crypto.Util.py3compat import bord
+
+from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
+                                  VoidPointer, SmartPointer,
+                                  create_string_buffer,
+                                  get_raw_buffer, c_size_t,
+                                  c_uint8_ptr)
+
+from tls.Crypto.Hash.keccak import _raw_keccak_lib
+
+class SHA3_512_Hash(object):
+    """A SHA3-512 hash object.
+    Do not instantiate directly.
+    Use the :func:`new` function.
+
+    :ivar oid: ASN.1 Object ID
+    :vartype oid: string
+
+    :ivar digest_size: the size in bytes of the resulting hash
+    :vartype digest_size: integer
+    """
+
+    # The size of the resulting hash in bytes.
+    digest_size = 64
+
+    # ASN.1 Object ID
+    oid = "2.16.840.1.101.3.4.2.10"
+
+    def __init__(self, data, update_after_digest):
+        self._update_after_digest = update_after_digest
+        self._digest_done = False
+
+        state = VoidPointer()
+        result = _raw_keccak_lib.keccak_init(state.address_of(),
+                                             c_size_t(self.digest_size * 2),
+                                             0x06)
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/512"
+                             % result)
+        self._state = SmartPointer(state.get(),
+                                   _raw_keccak_lib.keccak_destroy)
+        if data:
+            self.update(data)
+
+    def update(self, data):
+        """Continue hashing of a message by consuming the next chunk of data.
+
+        Args:
+            data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+        """
+
+        if self._digest_done and not self._update_after_digest:
+            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+        result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+                                               c_uint8_ptr(data),
+                                               c_size_t(len(data)))
+        if result:
+            raise ValueError("Error %d while updating SHA-3/512"
+                             % result)
+        return self
+
+    def digest(self):
+
+        """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Binary form.
+        :rtype: byte string
+        """
+
+        self._digest_done = True
+
+        bfr = create_string_buffer(self.digest_size)
+        result = _raw_keccak_lib.keccak_digest(self._state.get(),
+                                               bfr,
+                                               c_size_t(self.digest_size))
+        if result:
+            raise ValueError("Error %d while instantiating SHA-3/512"
+                             % result)
+
+        self._digest_value = get_raw_buffer(bfr)
+        return self._digest_value
+
+    def hexdigest(self):
+        """Return the **printable** digest of the message that has been hashed so far.
+
+        :return: The hash digest, computed over the data processed so far.
+                 Hexadecimal encoded.
+        :rtype: string
+        """
+
+        return "".join(["%02x" % bord(x) for x in self.digest()])
+
+    def new(self):
+        """Create a fresh SHA3-512 hash object."""
+
+        return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+    """Create a new hash object.
+
+    Args:
+        data (byte string/byte array/memoryview):
+            The very first chunk of the message to hash.
+            It is equivalent to an early call to :meth:`update`.
+        update_after_digest (boolean):
+            Whether :meth:`digest` can be followed by another :meth:`update`
+            (default: ``False``).
+
+    :Return: A :class:`SHA3_512_Hash` hash object
+    """
+
+    data = kwargs.pop("data", None)
+    update_after_digest = kwargs.pop("update_after_digest", False)
+    if len(args) == 1:
+        if data:
+            raise ValueError("Initial data for hash specified twice")
+        data = args[0]
+
+    if kwargs:
+        raise TypeError("Unknown parameters: " + str(kwargs))
+
+    return SHA3_512_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_512_Hash.digest_size

+ 16 - 0
tls/pycryptoMod/lib/Crypto/Hash/SHA3_512.pyi

@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_512_Hash(object):
+    digest_size: int
+    oid: str
+    def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+    def update(self, data: Buffer) -> SHA3_512_Hash: ...
+    def digest(self) -> bytes: ...
+    def hexdigest(self) -> str: ...
+    def new(self) -> SHA3_512_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_512_Hash: ...
+
+digest_size: int

Some files were not shown because too many files changed in this diff