diff --git a/libp2p/crypto/chacha20poly1305.nim b/libp2p/crypto/chacha20poly1305.nim new file mode 100644 index 000000000..fc09a2b68 --- /dev/null +++ b/libp2p/crypto/chacha20poly1305.nim @@ -0,0 +1,96 @@ +## Nim-Libp2p +## Copyright (c) 2020 Status Research & Development GmbH +## Licensed under either of +## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +## * MIT license ([LICENSE-MIT](LICENSE-MIT)) +## at your option. +## This file may not be copied, modified, or distributed except according to +## those terms. + +## This module integrates BearSSL ChaCha20+Poly1305 +## +## This module uses unmodified parts of code from +## BearSSL library +## Copyright(C) 2018 Thomas Pornin . + +# RFC @ https://tools.ietf.org/html/rfc7539 + +import bearssl + +const + ChaChaPolyKeySize = 32 + ChaChaPolyNonceSize = 12 + ChaChaPolyTagSize = 16 + +type + ChaChaPoly = object + ChaChaPolyKey* = array[ChaChaPolyKeySize, byte] + ChaChaPolyNonce* = array[ChaChaPolyNonceSize, byte] + ChaChaPolyTag* = array[ChaChaPolyTagSize, byte] + +# bearssl allows us to use optimized versions +# this is reconciled at runtime +# we do this in the global scope / module init + +# try for the best first +var + chachapoly_native_impl: Poly1305Run = poly1305CtmulqGet() + chacha_native_impl: Chacha20Run = chacha20Sse2Get() + +# fall back if not available +if chachapoly_native_impl == nil: + echo "ChaChaPoly could not use the fastest implementation, falling back" + chachapoly_native_impl = poly1305CtmulRun + +if chacha_native_impl == nil: + echo "ChaCha could not use the fastest implementation, falling back" + chacha_native_impl = chacha20CtRun + +echo "ChaCha20Poly1305 global init done." + +proc encrypt*(_: type[ChaChaPoly], + key: var ChaChaPolyKey, + nonce: var ChaChaPolyNonce, + tag: var ChaChaPolyTag, + data: var openarray[byte], + aad: var openarray[byte]) = + chachapoly_native_impl( + addr key[0], + addr nonce[0], + addr data[0], + data.len, + addr aad[0], + aad.len, + addr tag[0], + chacha_native_impl, + #[encrypt]# 1.cint) + +proc decrypt*(_: type[ChaChaPoly], + key: var ChaChaPolyKey, + nonce: var ChaChaPolyNonce, + tag: var ChaChaPolyTag, + data: var openarray[byte], + aad: var openarray[byte]) = + chachapoly_native_impl( + addr key[0], + addr nonce[0], + addr data[0], + data.len, + addr aad[0], + aad.len, + addr tag[0], + chacha_native_impl, + #[decrypt]# 0.cint) + +when isMainModule: + var + key: ChaChaPolyKey + iv: ChaChaPolyNonce + tag: ChaChaPolyTag + data = [0.byte, 1, 2, 3, 4] + aad = [0.byte, 1, 2, 3, 4] + + ChaChaPoly.encrypt(key, iv, tag, data, aad) + assert data != [0.byte, 1, 2, 3, 4] + ChaChaPoly.decrypt(key, iv, tag, data, aad) + assert data == [0.byte, 1, 2, 3, 4]