From 6399892bf2c53fc3701438c752718638baff8e27 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Fri, 14 May 2021 19:26:05 +0200 Subject: Move crypto-vala to shared library --- crypto-vala/src/cipher_converter.vala | 102 ++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 crypto-vala/src/cipher_converter.vala (limited to 'crypto-vala/src/cipher_converter.vala') diff --git a/crypto-vala/src/cipher_converter.vala b/crypto-vala/src/cipher_converter.vala new file mode 100644 index 00000000..b2b52c5a --- /dev/null +++ b/crypto-vala/src/cipher_converter.vala @@ -0,0 +1,102 @@ +using GLib; + +namespace Crypto { +public abstract class SymmetricCipherConverter : Converter, Object { + internal SymmetricCipher cipher; + internal size_t attached_taglen; + + public abstract ConverterResult convert(uint8[] inbuf, uint8[] outbuf, ConverterFlags flags, out size_t bytes_read, out size_t bytes_written) throws IOError; + + public uint8[] get_tag(size_t taglen) throws Error { + return cipher.get_tag(taglen); + } + + public void check_tag(uint8[] tag) throws Error { + cipher.check_tag(tag); + } + + public void reset() { + try { + cipher.reset(); + } catch (Crypto.Error e) { + warning(@"$(e.domain) error while resetting cipher: $(e.message)"); + } + } +} + +public class SymmetricCipherEncrypter : SymmetricCipherConverter { + public SymmetricCipherEncrypter(owned SymmetricCipher cipher, size_t attached_taglen = 0) { + this.cipher = (owned) cipher; + this.attached_taglen = attached_taglen; + } + + public override ConverterResult convert(uint8[] inbuf, uint8[] outbuf, ConverterFlags flags, out size_t bytes_read, out size_t bytes_written) throws IOError { + if (inbuf.length > outbuf.length) { + throw new IOError.NO_SPACE("CipherConverter needs at least the size of input as output space"); + } + if ((flags & ConverterFlags.INPUT_AT_END) != 0 && inbuf.length + attached_taglen > outbuf.length) { + throw new IOError.NO_SPACE("CipherConverter needs additional output space to attach tag"); + } + try { + if (inbuf.length > 0) { + cipher.encrypt(outbuf, inbuf); + } + bytes_read = inbuf.length; + bytes_written = inbuf.length; + if ((flags & ConverterFlags.INPUT_AT_END) != 0) { + if (attached_taglen > 0) { + Memory.copy((uint8*)outbuf + inbuf.length, get_tag(attached_taglen), attached_taglen); + bytes_written = inbuf.length + attached_taglen; + } + return ConverterResult.FINISHED; + } + if ((flags & ConverterFlags.FLUSH) != 0) { + return ConverterResult.FLUSHED; + } + return ConverterResult.CONVERTED; + } catch (Crypto.Error e) { + throw new IOError.FAILED(@"$(e.domain) error while decrypting: $(e.message)"); + } + } +} + +public class SymmetricCipherDecrypter : SymmetricCipherConverter { + public SymmetricCipherDecrypter(owned SymmetricCipher cipher, size_t attached_taglen = 0) { + this.cipher = (owned) cipher; + this.attached_taglen = attached_taglen; + } + + public override ConverterResult convert(uint8[] inbuf, uint8[] outbuf, ConverterFlags flags, out size_t bytes_read, out size_t bytes_written) throws IOError { + if (inbuf.length > outbuf.length + attached_taglen) { + throw new IOError.NO_SPACE("CipherConverter needs at least the size of input as output space"); + } + if ((flags & ConverterFlags.INPUT_AT_END) != 0 && inbuf.length < attached_taglen) { + throw new IOError.PARTIAL_INPUT("CipherConverter needs additional input to read tag"); + } else if ((flags & ConverterFlags.INPUT_AT_END) == 0 && inbuf.length < attached_taglen + 1) { + throw new IOError.PARTIAL_INPUT("CipherConverter needs additional input to make sure to not accidentally read tag"); + } + try { + inbuf.length -= (int) attached_taglen; + if (inbuf.length > 0) { + cipher.decrypt(outbuf, inbuf); + } + bytes_read = inbuf.length; + bytes_written = inbuf.length; + inbuf.length += (int) attached_taglen; + if ((flags & ConverterFlags.INPUT_AT_END) != 0) { + if (attached_taglen > 0) { + check_tag(inbuf[(inbuf.length - attached_taglen):inbuf.length]); + bytes_read = inbuf.length; + } + return ConverterResult.FINISHED; + } + if ((flags & ConverterFlags.FLUSH) != 0) { + return ConverterResult.FLUSHED; + } + return ConverterResult.CONVERTED; + } catch (Crypto.Error e) { + throw new IOError.FAILED(@"$(e.domain) error while decrypting: $(e.message)"); + } + } +} +} -- cgit v1.2.3-54-g00ecf