diff options
author | Marvin W <git@larma.de> | 2021-05-14 19:26:05 +0200 |
---|---|---|
committer | Marvin W <git@larma.de> | 2021-05-14 19:26:05 +0200 |
commit | 6399892bf2c53fc3701438c752718638baff8e27 (patch) | |
tree | f2d60570240109e5f65f1250807ce90812b484f2 /crypto-vala/src/cipher_converter.vala | |
parent | bec73ed3714fc89627392b1dfc74d1b919dbe355 (diff) | |
download | dino-6399892bf2c53fc3701438c752718638baff8e27.tar.gz dino-6399892bf2c53fc3701438c752718638baff8e27.zip |
Move crypto-vala to shared library
Diffstat (limited to 'crypto-vala/src/cipher_converter.vala')
-rw-r--r-- | crypto-vala/src/cipher_converter.vala | 102 |
1 files changed, 102 insertions, 0 deletions
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)"); + } + } +} +} |