--- /dev/null
+_*
+*.swp
+*.o
+*.out
+*.key
+*.diff
+*.patch
+tags
+tfcrypt
+tfcrypt.upx
+sksum
+tfbench
+tfbase64
--- /dev/null
+The tfcrypt program is copyrighted:
+
+Copyright © 2012-2018 Andrey Rys.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+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.
--- /dev/null
+VERSION:=$(shell cat VERSION)
+override CFLAGS+=-D_TFCRYPT_VERSION=\"$(VERSION)\" -Wall
+UPX=upx
+
+ifneq (,$(DEBUG))
+override CFLAGS+=-O0 -g
+else
+override CFLAGS+=-O3
+endif
+
+ifneq (,$(STATIC))
+override LDFLAGS+=-static
+endif
+
+ifneq (,$(STRIP))
+override LDFLAGS+=-s
+endif
+
+SRCS = $(wildcard *.c)
+HDRS = $(wildcard *.h)
+OBJS = $(SRCS:.c=.o)
+
+all: tfcrypt
+
+%.o: %.c VERSION $(HDRS)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+tfcrypt: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+tfcrypt.upx: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -static -s $(OBJS) -o $@
+ $(UPX) --best $@
+
+clean:
+ rm -f $(OBJS) tfcrypt tfcrypt.upx
--- /dev/null
+tfcrypt -- high security Threefish encryption tool.
+
+tfcrypt is a modern, dd(1)-like raw data manipulation tool with embedded strong encryption.
+It has precise IO layer inside which can be used to encrypt files, disks and other media,
+as well as to manipulate raw data directly, dd(1) style.
+
+tfcrypt uses Skein and Threefish - public domain SHA3 candidate from famous,
+well recognised cryptographer Bruce Schneier, author of famous, still uncracked
+Blowfish and Twofish ciphers, which are in use still up to today.
+
+tfcrypt is actually a frontend for Threefish with (by default) XTS mode of operation.
+As a key it uses either password or keyfile, which is then hashed many times
+with Skein hash function. Default key length is 1280 bits (160 bytes).
+
+This program is incompatible with older, "tf1024" tfcrypt version. This version aims to
+provide a portable encryption tool to encrypt fixed media such as disks and archive files,
+as well as to provide decades long privacy for encrypted data. That's why it uses 1024 bit
+encryption and, unlike older version, extends key size to 1280 bits, eliminates tweak feature
+from Threefish and uses either XTS (by default) or OCB modes of operation instead,
+to encrypt fixed media in a secure undetectable way.
+
+Supported modes of operation: CTR, ECB, CBC, XTS, OCB and arbitrary long keystream.
+OCB mode does not use Skein hash function to hash and verify message, instead, it does
+a single pass crypt and verify, thus, it is faster than other modes when both crypt and verify.
+
+THREEFISH NOTES
+
+Please note that this encryption software includes Threefish cipher, which is terribly
+slow on 32 bit systems. This way, it cannot be efficiently used on pure 32 bit machines.
+
+Threefish contained here is stripped off of it's tweak property, thus, it is turned into a
+regular block cipher. To add tweakability, either XTS or OCB modes of operation are used.
+Default wide block size is 4096 bytes. Author strongly believes that Threefish _may_ be subject
+to related key attacks when used in a tweaked mode, so this property is easy to remove.
+Because tweak occupied another 192 bits of key material, these 192 bits are added to effective
+key length. Another key word is extracted from the sum of all the user key words, thus,
+another 64 bits. Total +256 additional bits of key = 1280 key bits.
+
+SKEIN NOTES
+
+Unlike "tf1024" implementation, this Skein's MAC feature simply copies user rawkey into
+Skein structure context without preprocessing as defined by official Skein implementation.
+If you never used MAC feature, then you will get the same hashes as the official Skein.
+If you did, then possibly you used it together with encryption. Since this implementation
+employs longer key lengths, it's anyway time to move.
+
+Author believes that there is no problem with just copying raw MAC key versus preprocessing.
+A preprocessing is already done by separate Skein sequential invocations on the user long
+key material. The code becomes simpler and easier to understand.
+
+Apart from that, the Skein implementation here is fully conformant to the official one.
+
+TODO
+
+Add test vectors from older version, as well as test data for all modes of operation there.
+
+LICENSE
+
+This tfcrypt, unlike it's previous version, is copyrighted:
+
+ Copyright (C) Andrey Rys <rys@lynxlynx.ru>, 2012-2018.
+
+It maybe freely used by anyone who agrees to the terms and conditions of the MIT license.
+
+tfcipher code parts used are public domain, and maybe reused freely without license.
--- /dev/null
+/*
+ * base64.c: libb64 compressed code. Public domain.
+ * See http://libb64.sourceforge.net/ for original code and infos.
+ *
+ * Modified and fixed by Lynx <lynx@lynxlynx.ru> 03Jun2016:
+ * - Single TU, minimal external dependencies
+ * - Stream operation, no newline insertions
+ * - Fixed code style to pure K&R
+ * - Fixed integer overflows and fixed size types
+ * - Fixed out of bounds access in base64_decode_block
+ * - Force specify output size for output buffer when decoding
+ * - Fixed signed/unsigned issue on ARM
+ * - Added generic memory converter wrappers which do not expose internals
+ * - All functions calculate number of processed characters and return them to caller
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+enum base64_decodestep {
+ estep_a, estep_b, estep_c, estep_d
+};
+
+struct base64_decodestate {
+ enum base64_decodestep step;
+ char plainchar;
+ size_t count;
+};
+
+enum base64_encodestep {
+ dstep_a, dstep_b, dstep_c
+};
+
+struct base64_encodestate {
+ enum base64_encodestep step;
+ char result;
+ size_t count;
+};
+
+int base64_decode_value(signed char value_in)
+{
+ static const signed char decoding[] = {
+ 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1,
+ -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+ static const char decoding_size = sizeof(decoding);
+ if (value_in < 43) return -1;
+ value_in -= 43;
+ if (value_in >= decoding_size) return -1;
+ return decoding[(int)value_in];
+}
+
+void base64_init_decodestate(struct base64_decodestate *state_in)
+{
+ state_in->step = estep_a;
+ state_in->plainchar = 0;
+ state_in->count = 0;
+}
+
+#define CHECK_BOUNDS do { if (plainchar-plaintext_out >= plaintext_outl) goto _ret; } while (0)
+
+size_t base64_decode_block(const char *code_in, size_t length_in, char *plaintext_out, size_t plaintext_outl, struct base64_decodestate *state_in)
+{
+ const char *codechar = code_in;
+ char *plainchar = plaintext_out;
+ int fragment;
+
+ *plainchar = state_in->plainchar;
+
+ switch (state_in->step) {
+ while (1) {
+ case estep_a:
+ do {
+ if (codechar == code_in+length_in) {
+ state_in->step = estep_a;
+ state_in->plainchar = *plainchar;
+ state_in->count += (plainchar - plaintext_out);
+ return plainchar - plaintext_out;
+ }
+ fragment = base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar = (fragment & 0x3f) << 2;
+ case estep_b:
+ do {
+ if (codechar == code_in+length_in) {
+ state_in->step = estep_b;
+ state_in->plainchar = *plainchar;
+ state_in->count += (plainchar - plaintext_out);
+ return plainchar - plaintext_out;
+ }
+ fragment = base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar++ |= (fragment & 0x30) >> 4;
+ CHECK_BOUNDS;
+ *plainchar = (fragment & 0x0f) << 4;
+ case estep_c:
+ do {
+ if (codechar == code_in+length_in) {
+ state_in->step = estep_c;
+ state_in->plainchar = *plainchar;
+ state_in->count += (plainchar - plaintext_out);
+ return plainchar - plaintext_out;
+ }
+ fragment = base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar++ |= (fragment & 0x3c) >> 2;
+ CHECK_BOUNDS;
+ *plainchar = (fragment & 0x03) << 6;
+ case estep_d:
+ do {
+ if (codechar == code_in+length_in) {
+ state_in->step = estep_d;
+ state_in->plainchar = *plainchar;
+ state_in->count += (plainchar - plaintext_out);
+ return plainchar - plaintext_out;
+ }
+ fragment = base64_decode_value(*codechar++);
+ } while (fragment < 0);
+ *plainchar++ |= (fragment & 0x3f);
+ }
+ }
+
+_ret: state_in->count += (plainchar - plaintext_out);
+ return plainchar - plaintext_out;
+}
+
+void base64_init_encodestate(struct base64_encodestate *state_in)
+{
+ state_in->step = dstep_a;
+ state_in->result = 0;
+ state_in->count = 0;
+}
+
+char base64_encode_value(char value_in)
+{
+ static const char *encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ if (value_in > 63) return '=';
+ return encoding[(int)value_in];
+}
+
+size_t base64_encode_block(const char *plaintext_in, size_t length_in, char *code_out, struct base64_encodestate *state_in)
+{
+ const char *plainchar = plaintext_in;
+ const char *const plaintextend = plaintext_in + length_in;
+ char *codechar = code_out;
+ char result;
+ char fragment;
+
+ result = state_in->result;
+
+ switch (state_in->step) {
+ while (1) {
+ case dstep_a:
+ if (plainchar == plaintextend) {
+ state_in->result = result;
+ state_in->step = dstep_a;
+ state_in->count += (codechar - code_out);
+ return codechar - code_out;
+ }
+ fragment = *plainchar++;
+ result = (fragment & 0xfc) >> 2;
+ *codechar++ = base64_encode_value(result);
+ result = (fragment & 0x03) << 4;
+ case dstep_b:
+ if (plainchar == plaintextend) {
+ state_in->result = result;
+ state_in->step = dstep_b;
+ state_in->count += (codechar - code_out);
+ return codechar - code_out;
+ }
+ fragment = *plainchar++;
+ result |= (fragment & 0xf0) >> 4;
+ *codechar++ = base64_encode_value(result);
+ result = (fragment & 0x0f) << 2;
+ case dstep_c:
+ if (plainchar == plaintextend) {
+ state_in->result = result;
+ state_in->step = dstep_c;
+ state_in->count += (codechar - code_out);
+ return codechar - code_out;
+ }
+ fragment = *plainchar++;
+ result |= (fragment & 0xc0) >> 6;
+ *codechar++ = base64_encode_value(result);
+ result = (fragment & 0x3f) >> 0;
+ *codechar++ = base64_encode_value(result);
+ }
+ }
+ /* control should not reach here */
+ state_in->count += (codechar - code_out);
+ return codechar - code_out;
+}
+
+size_t base64_encode_blockend(char *code_out, struct base64_encodestate *state_in)
+{
+ char *codechar = code_out + state_in->count;
+
+ switch (state_in->step) {
+ case dstep_b:
+ *codechar++ = base64_encode_value(state_in->result);
+ *codechar++ = '=';
+ *codechar++ = '=';
+ state_in->count += 3;
+ break;
+ case dstep_c:
+ *codechar++ = base64_encode_value(state_in->result);
+ *codechar++ = '=';
+ state_in->count += 2;
+ break;
+ case dstep_a:
+ break;
+ }
+
+ return codechar - code_out;
+}
+
+/* Process single block of memory */
+size_t base64_decode(char *output, size_t outputl, const char *input, size_t inputl)
+{
+ struct base64_decodestate dstate;
+ size_t r;
+
+ base64_init_decodestate(&dstate);
+ base64_decode_block(input, inputl, output, outputl, &dstate);
+
+ r = dstate.count;
+ memset(&dstate, 0, sizeof(struct base64_decodestate));
+
+ return r;
+}
+
+size_t base64_encode(char *output, const char *input, size_t inputl)
+{
+ struct base64_encodestate estate;
+ size_t r;
+
+ base64_init_encodestate(&estate);
+ base64_encode_block(input, inputl, output, &estate);
+ base64_encode_blockend(output, &estate);
+
+ r = estate.count;
+ memset(&estate, 0, sizeof(struct base64_encodestate));
+
+ return r;
+}
--- /dev/null
+#ifndef _BASE64_H
+#define _BASE64_H
+
+enum base64_decodestep {
+ estep_a, estep_b, estep_c, estep_d
+};
+
+struct base64_decodestate {
+ enum base64_decodestep step;
+ char plainchar;
+ size_t count;
+};
+
+enum base64_encodestep {
+ dstep_a, dstep_b, dstep_c
+};
+
+struct base64_encodestate {
+ enum base64_encodestep step;
+ char result;
+ size_t count;
+};
+
+int base64_decode_value(signed char value_in);
+void base64_init_decodestate(struct base64_decodestate *state_in);
+size_t base64_decode_block(const char *code_in, size_t length_in, char *plaintext_out, size_t plaintext_outl, struct base64_decodestate *state_in);
+void base64_init_encodestate(struct base64_encodestate *state_in);
+char base64_encode_value(char value_in);
+size_t base64_encode_block(const char *plaintext_in, size_t length_in, char *code_out, struct base64_encodestate *state_in);
+size_t base64_encode_blockend(char *code_out, struct base64_encodestate *state_in);
+
+size_t base64_decode(char *output, size_t outputl, const char *input, size_t inputl);
+size_t base64_encode(char *output, const char *input, size_t inputl);
+
+#endif
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "getpasswd.h"
+
+size_t xgetpasswd(struct getpasswd_state *getps)
+{
+ char c;
+ int tty_opened = 0, x;
+ int clear;
+ struct termios s, t;
+ size_t l, echolen = 0;
+
+ if (!getps) return ((size_t)-1);
+
+ /*
+ * Both stdin and stderr point to same fd. This cannot happen.
+ * This only means that getps was memzero'd.
+ * Do not blame user for that, just fix it.
+ */
+ if ((getps->fd == 0 && getps->efd == 0) || getps->efd == -1) getps->efd = 2;
+
+ if (getps->fd == -1) {
+ if ((getps->fd = open("/dev/tty", O_RDONLY|O_NOCTTY)) == -1) getps->fd = 0;
+ else tty_opened = 1;
+ }
+
+ memset(&t, 0, sizeof(struct termios));
+ memset(&s, 0, sizeof(struct termios));
+ if (tcgetattr(getps->fd, &t) == -1) {
+ getps->error = errno;
+ return ((size_t)-1);
+ }
+ s = t;
+ if (getps->sanetty) memcpy(getps->sanetty, &s, sizeof(struct termios));
+ cfmakeraw(&t);
+ t.c_iflag |= ICRNL;
+ if (tcsetattr(getps->fd, TCSANOW, &t) == -1) {
+ getps->error = errno;
+ return ((size_t)-1);
+ }
+
+ if (getps->echo) {
+ echolen = strlen(getps->echo);
+ if (write(getps->efd, getps->echo, echolen) == -1) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ goto _xerr;
+ }
+ }
+
+ l = 0; x = 0;
+ memset(getps->passwd, 0, getps->pwlen);
+ while (1) {
+ clear = 1;
+ if (read(getps->fd, &c, sizeof(char)) == -1) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ goto _xerr;
+ }
+ if (getps->charfilter) {
+ x = getps->charfilter(getps, c, l);
+ if (x == 0) {
+ clear = 0;
+ goto _newl;
+ }
+ else if (x == 2) continue;
+ else if (x == 3) goto _erase;
+ else if (x == 4) goto _delete;
+ else if (x == 5) break;
+ else if (x == 6) {
+ clear = 0;
+ l = getps->retn;
+ memset(getps->passwd, 0, getps->pwlen);
+ goto _err;
+ }
+ }
+ if (l >= getps->pwlen && (getps->flags & GETP_WAITFILL)) clear = 0;
+
+ if (c == '\x7f'
+ || (c == '\x08' && !(getps->flags & GETP_NOINTERP))) { /* Backspace / ^H */
+_erase: if (l == 0) continue;
+ clear = 0;
+ l--;
+ if (!(getps->flags & GETP_NOECHO)) {
+ if (write(getps->efd, "\x08\033[1X", sizeof("\x08\033[1X")-1) == -1) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ goto _xerr;
+ }
+ }
+ }
+ else if (!(getps->flags & GETP_NOINTERP)
+ && (c == '\x15' || c == '\x17')) { /* ^U / ^W */
+_delete: clear = 0;
+ l = 0;
+ memset(getps->passwd, 0, getps->pwlen);
+ if (write(getps->efd, "\033[2K\033[0G", sizeof("\033[2K\033[0G")-1) == -1) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ goto _xerr;
+ }
+ if (getps->echo) {
+ if (write(getps->efd, getps->echo, echolen) == -1) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ goto _xerr;
+ }
+ }
+ }
+_newl: if (c == '\n'
+ || c == '\r'
+ || (!(getps->flags & GETP_NOINTERP) && c == '\x04')) break;
+ if (clear) {
+ *(getps->passwd+l) = c;
+ l++;
+ if (!(getps->flags & GETP_NOECHO)) {
+ if (getps->maskchar &&
+ write(getps->efd, &getps->maskchar,
+ sizeof(char)) == -1) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ goto _xerr;
+ }
+ }
+ }
+ if (l >= getps->pwlen && !(getps->flags & GETP_WAITFILL)) break;
+ };
+
+_err: if (write(getps->efd, "\r\n", sizeof("\r\n")-1) == -1) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ }
+ if (x != 6) *(getps->passwd+l) = 0;
+
+_xerr: if (tcsetattr(getps->fd, TCSANOW, &s) == -1) {
+ if (getps->error == 0) {
+ getps->error = errno;
+ l = ((size_t)-1);
+ }
+ }
+
+ if (tty_opened) close(getps->fd);
+
+ return l;
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#ifndef _GETPASSWD_H
+#define _GETPASSWD_H
+
+#define GETP_NOECHO 1
+#define GETP_NOINTERP 2
+#define GETP_WAITFILL 4
+
+struct getpasswd_state;
+struct termios;
+
+typedef int (*getpasswd_filt)(struct getpasswd_state *, char, size_t);
+
+struct getpasswd_state {
+ char *passwd;
+ size_t pwlen;
+ const char *echo;
+ char maskchar;
+ getpasswd_filt charfilter;
+ int fd;
+ int efd;
+ int error;
+ struct termios *sanetty;
+ int flags;
+ size_t retn;
+};
+
+size_t xgetpasswd(struct getpasswd_state *getps);
+
+#endif
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdint.h>
+
+struct mhexdump_args {
+ const void *data;
+ size_t szdata;
+ int group;
+ int hexgroup;
+ int hexstr;
+ int addaddr;
+ int newline;
+ FILE *fp;
+ int closef;
+};
+
+#if SIZE_MAX == 0xffffffff
+#define ADDRFMT "%08x: "
+#define paddr (mha->addaddr == 2 ? (uint32_t)P+(x*mha->group) : (x*mha->group))
+#else
+#define ADDRFMT "%016lx: "
+#define paddr (mha->addaddr == 2 ? (uint64_t)P+(x*mha->group) : (x*mha->group))
+#endif
+
+#define BYTEOUT ((unsigned char)P[y+(x*mha->group)])
+
+int fmhexdump(const struct mhexdump_args *mha)
+{
+ const unsigned char *P = mha->data;
+ int x, y;
+
+ if (!mha->fp || !mha->data || mha->szdata == 0) return 0;
+
+ for (x = 0; x < mha->szdata/mha->group; x++) {
+ if (mha->addaddr) fprintf(mha->fp, ADDRFMT, paddr);
+ for (y = 0; y < mha->group; y++) {
+ fprintf(mha->fp, "%02hhx", BYTEOUT);
+ if (((y+1) % mha->hexgroup) == 0 && (y != (mha->group)-1)) fputc(' ', mha->fp);
+ }
+ if (mha->hexstr) fprintf(mha->fp, " ");
+ if (mha->hexstr) for (y = 0; y < mha->group; y++) {
+ if (isprint(BYTEOUT)) fprintf(mha->fp, "%c", BYTEOUT);
+ else fputc('.', mha->fp);
+ }
+ if (mha->szdata/mha->group == 1 && mha->szdata-mha->group == 0) {
+ if (mha->newline) fputc('\n', mha->fp);
+ }
+ else fputc('\n', mha->fp);
+ }
+ if (mha->szdata-(x*mha->group) == 0) goto _ret;
+
+ if (mha->addaddr) fprintf(mha->fp, ADDRFMT, paddr);
+ for (y = 0; y < mha->szdata-(x*mha->group); y++) {
+ fprintf(mha->fp, "%02hhx", BYTEOUT);
+ if (((y+1) % mha->hexgroup) == 0) fputc(' ', mha->fp);
+ }
+ if (mha->hexstr) for (; y < mha->group; y++) {
+ fprintf(mha->fp, " ");
+ if (((y+1) % mha->hexgroup) == 0 && (y != mha->group-1)) fputc(' ', mha->fp);
+ }
+ if (mha->hexstr) fprintf(mha->fp, " ");
+ if (mha->hexstr) for (y = 0; y < mha->szdata-(x*mha->group); y++) {
+ if (isprint(BYTEOUT)) fprintf(mha->fp, "%c", BYTEOUT);
+ else fputc('.', mha->fp);
+ }
+
+ if (mha->newline) fputc('\n', mha->fp);
+
+_ret: fflush(mha->fp);
+ if (mha->closef) fclose(mha->fp);
+ return 1;
+}
+
+#undef BYTEOUT
+
+int xmhexdump(int to, const void *data, size_t szdata, int hgroup, int hexstr, int newline)
+{
+ struct mhexdump_args mha;
+
+ if (hgroup == 0) hgroup = 16;
+
+ memset(&mha, 0, sizeof(struct mhexdump_args));
+ mha.fp = (to == 2) ? stderr : stdout;
+ mha.closef = 0;
+ mha.data = data;
+ mha.szdata = szdata;
+ mha.group = hgroup;
+ mha.hexgroup = hgroup;
+ mha.hexstr = hexstr;
+ mha.addaddr = 0;
+ mha.newline = newline;
+
+ return fmhexdump(&mha);
+}
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+#include "tfcore.h"
+#include "skein.h"
+
+static inline void puthash(TF_BYTE_TYPE *dst, const TF_UNIT_TYPE *src, size_t l)
+{
+ size_t n;
+ for (n = 0; n < l; n++) dst[n] = (TF_BYTE_TYPE)(src[n>>3] >> (TF_SIZE_UNIT*(n&7)));
+}
+
+static void skein_process_blk(struct skein *sk, const TF_BYTE_TYPE *in, size_t szin, size_t l)
+{
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ size_t i;
+
+ do {
+ sk->key[TF_TWEAK_WORD1] += l;
+
+ memcpy(x, in, TF_BLOCK_SIZE);
+ data_to_words(x, TF_BLOCK_SIZE);
+ in += TF_BLOCK_SIZE;
+
+ sk->key[TF_NR_KEY_UNITS-1-3] = THREEFISH_CONST;
+ for (i = 0; i < TF_NR_KEY_UNITS-1-3; i++)
+ sk->key[TF_NR_KEY_UNITS-1-3] ^= sk->key[i];
+ sk->key[TF_TWEAK_WORD3] = sk->key[TF_TWEAK_WORD1] ^ sk->key[TF_TWEAK_WORD2];
+
+ tf_encrypt_rawblk(y, x, sk->key);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) sk->key[i] = y[i] ^ x[i];
+
+ sk->key[TF_TWEAK_WORD2] &= ~SKEIN_FLAG_FIRST;
+ } while (--szin);
+}
+
+void skein_init_key(struct skein *sk, const void *ukey, size_t bits)
+{
+ TF_UNIT_TYPE cfg[TF_NR_BLOCK_UNITS];
+
+ memset(sk, 0, sizeof(struct skein));
+
+ if (ukey) {
+ memcpy(sk->key, ukey, TF_FROM_BITS(TF_MAX_BITS));
+ data_to_words(sk->key, TF_FROM_BITS(TF_MAX_BITS));
+ }
+
+ sk->bits = bits;
+ sk->carry_bytes = 0;
+
+ memset(cfg, 0, sizeof(cfg));
+ cfg[0] = TF_SWAP_FUNC(((TF_UNIT_TYPE)SKEIN_VERSION << 32) + (TF_UNIT_TYPE)SKEIN_ID);
+ cfg[1] = TF_SWAP_FUNC(bits);
+
+ sk->key[TF_TWEAK_WORD1] = 0;
+ sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_CFG | SKEIN_FLAG_FIRST | SKEIN_FLAG_LAST;
+
+ skein_process_blk(sk, (TF_BYTE_TYPE *)cfg, 1, 32);
+
+ sk->key[TF_TWEAK_WORD1] = 0;
+ sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_MSG | SKEIN_FLAG_FIRST;
+}
+
+void skein_init(struct skein *sk, size_t bits)
+{
+ skein_init_key(sk, NULL, bits);
+}
+
+void skein_update(struct skein *sk, const void *msg, size_t msgsz)
+{
+ const TF_BYTE_TYPE *umsg = msg;
+ size_t n;
+
+ if (msgsz + sk->carry_bytes > TF_BLOCK_SIZE) {
+ if (sk->carry_bytes) {
+ n = TF_BLOCK_SIZE - sk->carry_bytes;
+ if (n) {
+ memcpy(&sk->carry_block[sk->carry_bytes], umsg, n);
+ msgsz -= n;
+ umsg += n;
+ sk->carry_bytes += n;
+ }
+ skein_process_blk(sk, sk->carry_block, 1, TF_BLOCK_SIZE);
+ sk->carry_bytes = 0;
+ }
+
+ if (msgsz > TF_BLOCK_SIZE) {
+ n = (msgsz-1) / TF_BLOCK_SIZE;
+ skein_process_blk(sk, umsg, n, TF_BLOCK_SIZE);
+ msgsz -= n * TF_BLOCK_SIZE;
+ umsg += n * TF_BLOCK_SIZE;
+ }
+ }
+
+ if (msgsz) {
+ memcpy(&sk->carry_block[sk->carry_bytes], umsg, msgsz);
+ sk->carry_bytes += msgsz;
+ }
+}
+
+void skein_final(void *result, struct skein *sk)
+{
+ TF_BYTE_TYPE *uresult = result;
+ TF_UNIT_TYPE key[TF_NR_BLOCK_UNITS], *X;
+ size_t i, b, n;
+
+ if (sk->carry_bytes < TF_BLOCK_SIZE)
+ memset(sk->carry_block+sk->carry_bytes, 0, TF_BLOCK_SIZE-sk->carry_bytes);
+ sk->key[TF_TWEAK_WORD2] |= SKEIN_FLAG_LAST;
+ skein_process_blk(sk, sk->carry_block, 1, sk->carry_bytes);
+
+ b = (sk->bits + 7) / 8;
+
+ memset(sk->carry_block, 0, sizeof(sk->carry_block));
+ memcpy(key, sk->key, sizeof(key));
+
+ for (i = 0; (i * TF_BLOCK_SIZE) < b; i++) {
+ X = (TF_UNIT_TYPE *)sk->carry_block;
+ X[0] = TF_SWAP_FUNC((TF_UNIT_TYPE)i);
+ sk->key[TF_TWEAK_WORD1] = 0;
+ sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_OUT | SKEIN_FLAG_FIRST | SKEIN_FLAG_LAST;
+ sk->carry_bytes = 0;
+
+ skein_process_blk(sk, sk->carry_block, 1, TF_SIZE_UNIT);
+ n = b-(i*TF_BLOCK_SIZE);
+ if (n >= TF_BLOCK_SIZE) n = TF_BLOCK_SIZE;
+ puthash(uresult+(i*TF_BLOCK_SIZE), sk->key, n);
+ memcpy(sk->key, key, TF_BLOCK_SIZE);
+ }
+
+ memset(sk, 0, sizeof(struct skein));
+}
--- /dev/null
+#ifndef _THREEFISH_SKEIN_DEFINITIONS_HEADER
+#define _THREEFISH_SKEIN_DEFINITIONS_HEADER
+
+#include "tfdef.h"
+
+#define SKEIN_VERSION 1
+#define SKEIN_ID 0x33414853
+
+#define SKEIN_BLOCK_CFG ((TF_UNIT_TYPE)4 << 56)
+#define SKEIN_BLOCK_MSG ((TF_UNIT_TYPE)48 << 56)
+#define SKEIN_BLOCK_OUT ((TF_UNIT_TYPE)63 << 56)
+#define SKEIN_FLAG_FIRST ((TF_UNIT_TYPE)1 << 62)
+#define SKEIN_FLAG_LAST ((TF_UNIT_TYPE)1 << 63)
+
+#define SKEIN_DIGEST_SIZE TF_BLOCK_SIZE
+
+struct skein {
+ TF_UNIT_TYPE key[TF_NR_KEY_UNITS];
+ TF_BYTE_TYPE carry_block[TF_BLOCK_SIZE];
+ size_t carry_bytes;
+ size_t bits;
+};
+
+void skein_init_key(struct skein *sk, const void *ukey, size_t bits);
+void skein_init(struct skein *sk, size_t bits);
+void skein_update(struct skein *sk, const void *msg, size_t msgsz);
+void skein_final(void *result, struct skein *sk);
+
+#endif
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+void do_edbase64(char **fargv)
+{
+ struct base64_decodestate dstate;
+ struct base64_encodestate estate;
+ size_t lread = 0;
+
+ sfd = 0; dfd = 1;
+
+ if (fargv[0]) {
+ if (!strcmp(fargv[0], "-")) sfd = 0;
+ else {
+ sfd = open(fargv[0], O_RDONLY | O_LARGEFILE);
+ if (do_preserve_time) if (fstat(sfd, &s_stat) == -1)
+ xerror(YES, NO, YES, "stat(%s)", fargv[0]);
+ }
+ if (sfd == -1) xerror(NO, NO, YES, "%s", fargv[0]);
+ }
+
+ if (fargv[0] && fargv[1]) {
+ if (!strcmp(fargv[1], "-")) dfd = 1;
+ else dfd = open(fargv[1], O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
+ if (dfd == -1) xerror(NO, NO, YES, "%s", fargv[1]);
+ }
+
+ if (do_edcrypt == TFC_DO_ENCRYPT) {
+ memset(&estate, 0, sizeof(struct base64_encodestate));
+ base64_init_encodestate(&estate);
+ }
+ else if (do_edcrypt == TFC_DO_DECRYPT) {
+ memset(&dstate, 0, sizeof(struct base64_decodestate));
+ base64_init_decodestate(&dstate);
+ }
+
+ errno = 0;
+ do_stop = NO;
+ while (1) {
+ if (do_stop) break;
+ pblk = srcblk;
+ lblock = lrem = do_edcrypt == TFC_DO_DECRYPT ? TFC_B64_DWIDTH : TFC_B64_EWIDTH;
+ ldone = 0;
+_again: lio = read(sfd, pblk, lrem);
+ if (lio == 0) do_stop = YES;
+ if (lio != NOSIZE) ldone += lio;
+ else {
+ if (errno != EIO && catch_all_errors != YES)
+ xerror(NO, NO, NO, "%s", fargv[0]);
+ switch (error_action) {
+ case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", fargv[0]); goto _again; break;
+ case TFC_ERRACT_SYNC:
+ xerror(YES, NO, NO, "%s", fargv[0]);
+ lio = ldone = lrem = lblock;
+ memset(srcblk, 0, lio);
+ lseek(sfd, lio, SEEK_CUR);
+ break;
+ default: xerror(NO, NO, NO, "%s", fargv[0]); break;
+ }
+ }
+ if (lio && lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _again;
+ }
+
+ if (do_edcrypt == TFC_DO_ENCRYPT) {
+ estate.count = 0;
+ base64_encode_block((const char *)srcblk, ldone, (char *)dstblk, &estate);
+ lread = ldone;
+ ldone = estate.count;
+ }
+ else if (do_edcrypt == TFC_DO_DECRYPT) {
+ dstate.count = 0;
+ base64_decode_block((const char *)srcblk, ldone, (char *)dstblk, sizeof(dstblk), &dstate);
+ ldone = dstate.count;
+ }
+
+ pblk = dstblk;
+ if (ldone == 0) {
+ do_stop = TFC_STOP_FULL;
+ break;
+ }
+ lrem = ldone;
+ ldone = 0;
+_wagain: lio = write(dfd, pblk, lrem);
+ if (lio != NOSIZE) ldone += lio;
+ else xerror(NO, NO, NO, "%s", fargv[1]);
+ if (do_edcrypt == TFC_DO_ENCRYPT) {
+ size_t t;
+ if (lread >= lblock || do_stop == TFC_STOP_FULL) {
+ t = write(dfd, "\n", 1);
+ if (t != NOSIZE) lio += t;
+ else lio = NOSIZE;
+ }
+ }
+ if (lio != NOSIZE) ldone += lio;
+ else xerror(NO, NO, NO, "%s", fargv[1]);
+ if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", fargv[1]);
+ if (lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _wagain;
+ }
+ }
+
+ if (do_edcrypt == TFC_DO_ENCRYPT && do_stop == TFC_STOP_BEGAN) {
+ size_t t = estate.count;
+ pblk = dstblk + estate.count;
+ base64_encode_blockend((char *)dstblk, &estate);
+ lrem = estate.count - t;
+ ldone = 0;
+ do_stop = TFC_STOP_FULL;
+ goto _wagain;
+ }
+
+ memset(&estate, 0, sizeof(struct base64_encodestate));
+ memset(&dstate, 0, sizeof(struct base64_decodestate));
+ if (do_preserve_time) fcopy_matime(dfd, &s_stat);
+ xexit(0);
+}
+
+static void base64_eprint(FILE *where, struct base64_encodestate *estate, const char *input, size_t inputl)
+{
+ static char t[256];
+ ssize_t ix = inputl;
+
+ while (ix > 0) {
+ memset(t, 0, sizeof(t));
+ estate->count = 0;
+ base64_encode_block(input, ix > 128 ? 128 : ix, t, estate);
+ ix -= 128;
+ if (ix < 128) base64_encode_blockend(t, estate);
+ fprintf(where, "%s", t);
+ fflush(where);
+ }
+
+ memset(t, 0, sizeof(t));
+}
+
+void tfc_printbase64(FILE *where, const void *p, size_t n, tfc_yesno nl)
+{
+ struct base64_encodestate estate;
+ memset(&estate, 0, sizeof(struct base64_encodestate));
+ base64_eprint(where, &estate, (const char *)p, n);
+ if (nl) tfc_nfsay(where, "\n");
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+void do_benchmark(tfc_useconds useconds, double dseconds)
+{
+ size_t x, lblock;
+
+ for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_handler = print_crypt_status;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+ sigaction(SIGTSTP, &sigact, NULL);
+ sigaction(SIGALRM, &sigact, NULL);
+ setup_next_alarm(useconds);
+ memset(&sigact, 0, sizeof(struct sigaction));
+
+ tfc_getcurtime(&delta_time);
+
+ tfc_getrandom(key, sizeof(key));
+ tfc_getrandom(ctr, sizeof(ctr));
+ if (do_mac != NO) {
+ tfc_getrandom(mackey, sizeof(mackey));
+ if (ctr_mode < TFC_MODE_OCB) skein_init_key(&sk, mackey, macbits);
+ }
+ if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr);
+ if (ctr_mode == TFC_MODE_XTS) tfc_getrandom(xtskey, sizeof(xtskey));
+
+ tfc_nfsay(stdout, "%s: doing %s benchmark for %.4f seconds ... ", progname, tfc_modename(ctr_mode), dseconds);
+
+ do_stop = NO;
+ while (1) {
+ if (do_stop) break;
+
+ lblock = blk_len_adj(NOFSIZE, total_processed_src, blksize);
+ total_processed_src += lblock;
+
+ if (do_mac != NO && ctr_mode < TFC_MODE_OCB)
+ skein_update(&sk, srcblk, lblock);
+
+ if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, srcblk, srcblk, lblock);
+ else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, srcblk, srcblk, lblock);
+ else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_xts_encrypt(key, xtskey, ctr, srcblk, srcblk, lblock, xtsblocks);
+ else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_DECRYPT)
+ tf_xts_decrypt(key, xtskey, ctr, srcblk, srcblk, lblock, xtsblocks);
+ else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_ecb_encrypt(key, srcblk, srcblk, lblock);
+ else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_DECRYPT)
+ tf_ecb_decrypt(key, srcblk, srcblk, lblock);
+ else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_cbc_encrypt(key, ctr, srcblk, srcblk, lblock);
+ else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_DECRYPT)
+ tf_cbc_decrypt(key, ctr, srcblk, srcblk, lblock);
+
+ else if (ctr_mode == TFC_MODE_OCB && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_ocb_encrypt(key, ctr, srcblk, do_mac ? macresult : NULL, srcblk, lblock, xtsblocks);
+ else if (ctr_mode == TFC_MODE_OCB && do_edcrypt == TFC_DO_DECRYPT)
+ tf_ocb_decrypt(key, ctr, srcblk, do_mac ? macresult : NULL, srcblk, lblock, xtsblocks);
+
+ delta_processed += lblock;
+ }
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+static const char *tfc_size_scale[] = {"B", "K", "M", "G", "T", "P"};
+
+void tfc_data_to_words64(void *data, size_t szdata)
+{
+#ifndef TF_NO_ENDIAN
+ size_t idx;
+ uint64_t *d = data;
+ uint64_t t;
+
+ for (idx = 0; idx < (szdata/sizeof(uint64_t)); idx++) {
+#ifdef TF_BIG_ENDIAN
+ t = htobe64(d[idx]);
+#else
+ t = htole64(d[idx]);
+#endif
+ d[idx] = t;
+ }
+#endif
+}
+
+static tfc_yesno tfc_is_number(const char *s)
+{
+ char *p;
+ if (!s || str_empty(s)) return NO;
+ strtol(s, &p, 10);
+ return str_empty(p) ? YES : NO;
+}
+
+tfc_fsize tfc_humanfsize(const char *s, char **stoi)
+{
+ char pfx[2], T[2], N[48], *ss;
+ int base = 10;
+ size_t l;
+ tfc_fsize gbgib = 0, ret = 0;
+
+ if (!s) return 0;
+
+ memset(N, 0, sizeof(N));
+ memset(pfx, 0, sizeof(pfx));
+ memset(T, 0, sizeof(T));
+
+ if (!strncmp(s, "0x", 2)) {
+ s += 2;
+ base = 16;
+ }
+ else if (s[0] == '0') base = 0;
+
+ l = strnlen(s, sizeof(N)-1);
+ memcpy(N, s, l);
+
+ ss = strchr(N, ':');
+ if (ss && ss[1] && (ss[1] == '+' || ss[1] == '-' || ss[1] == '*' || ss[1] == '/')) {
+ ss[0] = 0;
+ l = strnlen(N, sizeof(N)-1);
+ }
+
+ if (base == 16) goto _nopfx;
+
+ pfx[0] = N[l-1];
+ if (tfc_is_number(pfx) == NO) N[l-1] = 0;
+
+_nopfx:
+ *stoi = NULL;
+ if (tfc_is_number(pfx) || pfx[0] == 'B' || pfx[0] == 'c') ret = strtoull(N, stoi, base);
+ else if (pfx[0] == 'W') ret = strtoull(N, stoi, base)*2;
+ else if (pfx[0] == 'I') ret = strtoull(N, stoi, base)*4;
+ else if (pfx[0] == 'L') ret = strtoull(N, stoi, base)*8;
+ else if (pfx[0] == 'e') ret = strtoull(N, stoi, base)*TF_BLOCK_SIZE;
+ else if (pfx[0] == 'y') ret = strtoull(N, stoi, base)*TF_FROM_BITS(TFC_KEY_BITS);
+ else if (pfx[0] == 'x') ret = strtoull(N, stoi, base)*TF_FROM_BITS(TFC_KEY_BITS)*2;
+ else if (pfx[0] == 'E') ret = strtoull(N, stoi, base)*blksize;
+ else if (pfx[0] == 'b' || pfx[0] == 's') ret = strtoull(N, stoi, base)*512;
+ else if (pfx[0] == 'p' || pfx[0] == 'S') ret = strtoull(N, stoi, base)*4096;
+ else if (pfx[0] == 'k' || pfx[0] == 'K') {
+ gbgib = do_stats_in_gibs == YES ? 1000 : 1024;
+ }
+ else if (pfx[0] == 'm' || pfx[0] == 'M') {
+ gbgib = do_stats_in_gibs == YES ? 1000 * 1000 : 1024 * 1024;
+ }
+ else if (pfx[0] == 'g' || pfx[0] == 'G') {
+ gbgib = do_stats_in_gibs == YES ? 1000 * 1000 * 1000 : 1024 * 1024 * 1024;
+ }
+ else if (pfx[0] == 'T') {
+ gbgib = do_stats_in_gibs == YES ? 1000000000000ULL : 1099511627776ULL;
+ }
+ else if (pfx[0] == 'P') {
+ gbgib = do_stats_in_gibs == YES ? 1000000000000000ULL : 1125899906842624ULL;
+ }
+ else ret = strtoull(N, stoi, base);
+ if (gbgib) ret = strtoull(N, stoi, base) * gbgib;
+
+ return ret;
+}
+
+const char *tfc_getscale(int scale)
+{
+ return scale >= TFC_ARRAY_SIZE(tfc_size_scale) ?
+ tfc_size_scale[TFC_ARRAY_SIZE(tfc_size_scale)-1] : tfc_size_scale[scale];
+}
+
+void tfc_describescale(tfc_fsize num, double *w, int *scale)
+{
+ tfc_fsize gbgib = (do_stats_in_gibs == YES) ? 1000 : 1024;
+
+ if (num <= gbgib) {
+ *w = num;
+ *scale = 0;
+ }
+ else if ((num > gbgib)
+ && (num <= gbgib * gbgib)) {
+ *w = (double)num / gbgib;
+ *scale = 1;
+ }
+ else if ((num > gbgib * gbgib)
+ && (num <= gbgib * gbgib * gbgib)) {
+ *w = (double)num / (gbgib * gbgib);
+ *scale = 2;
+ }
+ else if ((num > gbgib * gbgib * gbgib)
+ && (num <= gbgib * gbgib * gbgib * gbgib)) {
+ *w = (double)num / (gbgib * gbgib * gbgib);
+ *scale = 3;
+ }
+ else if ((num > gbgib * gbgib * gbgib * gbgib)
+ && num <= gbgib * gbgib * gbgib * gbgib * gbgib) {
+ *w = (double)num/ (gbgib * gbgib * gbgib * gbgib);
+ *scale = 4;
+ }
+ else {
+ *w = (double)num / (gbgib * gbgib * gbgib * gbgib * gbgib);
+ *scale = 5;
+ }
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+void xerror(tfc_yesno noexit, tfc_yesno noerrno, tfc_yesno nostats, const char *fmt, ...)
+{
+ va_list ap;
+ char *s;
+
+ if (quiet) goto _ex;
+
+ va_start(ap, fmt);
+
+ if (statline_was_shown == YES && do_statline_dynamic == YES) tfc_esay("\n");
+
+ tfc_nfsay(stderr, "%s: ", progname);
+ tfc_vfsay(stderr, NO, fmt, ap);
+ if (errno && noerrno == NO) {
+ s = strerror(errno);
+ tfc_esay(": %s", s);
+ }
+ else tfc_esay("\n");
+
+ va_end(ap);
+
+ if (nostats == NO) print_crypt_status(-1);
+
+_ex:
+ if (noexit == YES) {
+ errno = 0;
+ return;
+ }
+
+ xexit(2);
+}
+
+void xexit(int status)
+{
+ memset(srcblk, 0, sizeof(srcblk));
+ memset(dstblk, 0, sizeof(dstblk));
+
+ memset(key, 0, sizeof(key));
+ memset(ctr, 0, sizeof(ctr));
+ memset(mackey, 0, sizeof(mackey));
+ memset(xtskey, 0, sizeof(xtskey));
+ memset(&sk, 0, sizeof(struct skein));
+ memset(&tfe, 0, sizeof(struct tfe_stream));
+
+ tfc_finirandom();
+
+ memset(macvrfy, 0, sizeof(macvrfy));
+ memset(macresult, 0, sizeof(macresult));
+
+ memset(tmpdata, 0, sizeof(tmpdata));
+ memset(&getps, 0, sizeof(struct getpasswd_state));
+ memset(pwdask, 0, sizeof(pwdask));
+ memset(pwdagain, 0, sizeof(pwdagain));
+
+ exit(status);
+}
+
+void usage(void)
+{
+ tfc_yesno is_embedded_prog = NO;
+
+ if (optopt == 'V') {
+ tfc_say("tfcrypt toolkit, version %s.", _TFCRYPT_VERSION);
+ xexit(0);
+ }
+
+ if ((strlen(progname) <= 9)
+ && ((!strcmp(progname, "sksum"))
+ || ((!memcmp(progname, "sk", 2))
+ && (!memcmp(progname+3, "sum", 3)
+ || !memcmp(progname+4, "sum", 3)
+ || !memcmp(progname+5, "sum", 3)
+ || !memcmp(progname+6, "sum", 3))))) {
+ is_embedded_prog = YES;
+ tfc_say("usage: %s [-AW] [-D BITS] [-n TURNS] [-l length] [-c <file>] [-U <file>] [source] ...", progname);
+ tfc_say("\n");
+ tfc_say("%s: calculate and print Skein hashsum of stream.", progname);
+ tfc_say(" -D BITS: specify bits as it was skBITSsum.");
+ tfc_say(" -n TURNS: number of turns to perform in Skein function.");
+ tfc_say(" sksum defaults to just one in all modes.");
+ tfc_say(" -A: format checksum in base64 rather than in binary hex.");
+ tfc_say(" -W: output raw binary checksum and remove filename(s) from output.");
+ tfc_say(" -H: output small hexdump (hex string and ASCII printable characters).");
+ tfc_say(" -l length: read only these first bytes of source.");
+ tfc_say(" -c <file>: read hashes list from file and check them.");
+ tfc_say(" -U <file>: read Skein MAC key from file.");
+ tfc_say("multiple sources can be given in cmdline, and if one of");
+ tfc_say("them is specified as \"-\", then reads are performed from stdin.");
+ tfc_say("\n");
+ }
+ else if (!strcmp(progname, "base64")) {
+ is_embedded_prog = YES;
+ tfc_say("usage: %s [-ed] [source] [output]", progname);
+ tfc_say("\n");
+ tfc_say("tfcrypt embedded base64 encoder/decoder.");
+ tfc_say(" -e: encode stream into base64.");
+ tfc_say(" -d: decode base64 stream.");
+ tfc_say("no error checking is performed.");
+ tfc_say("\n");
+ }
+ else if (!strcmp(progname, "tfbench")) {
+ is_embedded_prog = YES;
+ tfc_say("usage: %s seconds", progname);
+ tfc_say("do an in-memory random data benchmark of Threefish.");
+ tfc_say("\n");
+ }
+
+ if (is_embedded_prog) {
+ tfc_say("This program is physical part of tfcrypt toolkit.");
+ tfc_say("(see it's version with %s -V)", progname);
+ tfc_say("Please note that other tfcrypt options are either ignored there,");
+ tfc_say("or result of using them is undefined and it's not a bug.");
+
+ xexit(1);
+ }
+
+ tfc_say("usage: %s [opts] [--] [key] [source] [output]", progname);
+ tfc_say("\n");
+ tfc_say("tfcrypt toolkit: encrypt streams with Threefish in CTR mode,");
+ tfc_say("calculate and check Skein hashsums, generate CSPRNG quality random data,");
+ tfc_say("convert encrypted data into ASCII format to ease transmission.");
+ tfc_say("\n");
+ tfc_say(" -e, -d: encrypt, decrypt (it maybe required).");
+ tfc_say(" -p: instead of using key, ask for password.");
+ tfc_say(" -k: use raw (%u byte) key instead of deriving it from arbitrary data.", TFC_U(TF_KEY_SIZE));
+ tfc_say(" -z: ask for key in plain C string form through password asker.");
+ tfc_say(" -x: ask for key in hex string form through password asker.");
+ tfc_say(" -K <file>: generate key from keyfile or password and write it to file.");
+ tfc_say(" -T: enable tfcrypt1 old mode (useful only for old encryptions).");
+ tfc_say(" -t <file>: use tweak from file (useful only for old encryptions).");
+ tfc_say(" -w: overwrite source file. If not file, ignored.");
+ tfc_say(" -n TURNS: number of turns to perform in Skein function.");
+ tfc_say(" Default is always defined when building tfcrypt.");
+ tfc_say(" -C mode: mode of operation: CTR, STREAM, XTS, ECB, CBC, OCB.");
+ tfc_say(" Default encryption mode can be changed when building tfcrypt.");
+ tfc_say(" -c opt: initial CTR value initialisation mode:");
+ tfc_say(" show: do default action, then dump CTR value to stderr,");
+ tfc_say(" head: when decrypting, read CTR from beginning of stream,");
+ tfc_say(" rand: generate random CTR and write it to beginning of stream,");
+ tfc_say(" <file>: read CTR from given file (both when encrypting/decrypting).");
+ tfc_say(" default is to derive CTR from user provided password or keyfile with");
+ tfc_say(" a single Skein function turn over derived, %u byte raw key", TFC_U(TF_KEY_SIZE));
+ tfc_say(" -q: always be quiet, never tell anything (except when signaled).");
+ tfc_say(" -v: print number of read and written encrypted bytes, and explain stages.");
+ tfc_say(" -V seconds: activate timer that will repeatedly print statistics to stderr.");
+ tfc_say(" -a: shortcut of -O xtime.");
+ tfc_say(" -r <file>: specify random source instead of /dev/urandom.");
+ tfc_say(" -R nr_bytes: generate nr_bytes of random bytes suitable for use as key data.");
+ tfc_say(" -R also supports these aliases specified instead of nr_bytes:");
+ tfc_say(" cbs: output fixed maximum crypt block size (%u bytes),", TFC_U(TF_BLOCK_SIZE));
+ tfc_say(" ks: output fixed maximum crypt key size (%u bytes)", TFC_U(TF_KEY_SIZE));
+ tfc_say(" xks: output fixed maximum crypt XTS key size (%u bytes)", TFC_U(TF_KEY_SIZE*2));
+ tfc_say(" iobs: output %s builtin block size TFC_BLKSIZE (%u bytes),", progname, TFC_U(TFC_BLKSIZE));
+ tfc_say(" if nr_bytes is not a valid number or alias, this string will be");
+ tfc_say(" used to attempt to open it as file, and examine it's size.");
+ tfc_say(" Then this examined size will be set as nr_bytes to output.");
+ tfc_say(" -Z nr_bytes: like -R, but emit zero stream instead of random.");
+ tfc_say(" -D MACBITS: specify bit width of a MAC signature.");
+ tfc_say(" -U key/pwd/<file>: read Skein MAC key from file.");
+ tfc_say(" key: use primary encryption rawkey as a MAC key.");
+ tfc_say(" pwd: ask for password string that will be used as MAC key.");
+ tfc_say(" -S MAC: append MAC signature to end of file:");
+ tfc_say(" MAC: embed MAC signature into file itself at the end,");
+ tfc_say(" <file>: write a detached MAC signature into separate <file>,");
+ tfc_say(" -: write a detached MAC signature to stdout.");
+ tfc_say(" useful only with variable length files! For block devices,");
+ tfc_say(" specify a separate file name to save signature to: -S file.");
+ tfc_say(" -A: format raw binary data, like MAC signature or Skein hash, in base64.");
+ tfc_say(" -W: output pure binary data, and disable any strings addition in Skein.");
+ tfc_say(" -H: output small hexdump (hex string and ASCII printable characters).");
+ tfc_say(" -M MAC: verify attached MAC signature when decrypting a file:");
+ tfc_say(" MAC: embed MAC signature into file itself at the end,");
+ tfc_say(" <file>: write a detached MAC signature into separate <file>,");
+ tfc_say(" -: read a detached MAC signature from stdin,");
+ tfc_say(" drop: do not verify attached MAC, if any, and drop it from output.");
+ tfc_say(" -m: just verify MAC provided with -M. Do not write output file.");
+ tfc_say(" This option must be specified after -M.");
+ tfc_say(" -E how: how to behave on I/O errors (both src or dst):");
+ tfc_say(" exit: print error if not quiet, then exit,");
+ tfc_say(" cont: print error if not quiet, then continue,");
+ tfc_say(" no action to pad missing data is attempted.");
+ tfc_say(" may be dangerous when working with block devices.");
+ tfc_say(" sync: print error if not quiet, then continue.");
+ tfc_say(" pad missing data block with zeroes.");
+ tfc_say(" note that sync works only with read errors!");
+ tfc_say(" default error action is exit with printing status if not quiet.");
+ tfc_say(" -E xall: turn on error actions above for all errors, not just EIO errors.");
+ tfc_say(" This must be a separate option given before usual -E how option.");
+ tfc_say(" -O opts: set options (comma separated list):");
+ tfc_say(" sync: request a synchronous I/O for a output,");
+ tfc_say(" fsync: on each write() call a corresponding fsync(fd),");
+ tfc_say(" trunc: open(O_WRONLY) will truncate output file to zero size.");
+ tfc_say(" pad: pad incomplete (l.t. %u bytes) block with zeroes.", TFC_U(TF_BLOCK_SIZE));
+ tfc_say(" xtime: copy timestamps from source to destination files.");
+ tfc_say(" gibsize: use SI units of size: 1k = 1000. Applies only to size prefixes.");
+ tfc_say(" Computers convention is to use 1024, whereas SI/hdd measure in 1000.");
+ tfc_say(" plainstats: force status line to be plain: no fancy dynamic stuff.");
+ tfc_say(" Dynamic line works well only on VT100 compatible ttys, and");
+ tfc_say(" when the whole status line width is smaller than tty width.");
+ tfc_say(" statless: emit less information in status line (only processed data).");
+ tfc_say(" norepeat: do not ask for any possible password confirmations.");
+ tfc_say(" prompt=str: set main password prompts to this string.");
+ tfc_say(" macprompt=str: set MAC password prompts to this string.");
+ tfc_say(" shorthex: with -H, do not print printable characters, dump only hex string.");
+ tfc_say(" iobs=val: set IO block size value. Must not exceed %u bytes.", TFC_U(TFC_BLKSIZE));
+ tfc_say(" xtsblocks=val: use these nr of TF blocks per XTS block. Default is %u.", TFC_U(TFC_XTSBLOCKS));
+ tfc_say(" iseek=val: seek source file/device by these val bytes.");
+ tfc_say(" Initial counter is adjusted automatically.");
+ tfc_say(" ixseek=val: rawseek source file/device by these val bytes.");
+ tfc_say(" Do not adjust initial counter automatically.");
+ tfc_say(" ictr=val: Increment initial counter by this val blocks.");
+ tfc_say(" The size of each block is %u bytes.", TFC_U(TF_BLOCK_SIZE));
+ tfc_say(" ictr option is valid only for CTR and CTR like modes.");
+ tfc_say(" ixctr=val: Increment initial counter by this val bytes.");
+ tfc_say(" Internally this number is translated into number of %u byte blocks.", TFC_U(TF_BLOCK_SIZE));
+ tfc_say(" oseek=val: seek destination file/device by these val bytes.");
+ tfc_say(" count=val: process only these val bytes, both input and output.");
+ tfc_say(" xkey=val: take only val bytes from user keyfile.");
+ tfc_say(" xctr=val: specify size in bytes of initial counter prepended or read.");
+ tfc_say(" -P: plain IO mode: disable encryption/decryption code at all.");
+ tfc_say("\n");
+ tfc_say("Default is to ask for password, then encrypt stdin into stdout.");
+ tfc_say("Some cmdline parameters may be mutually exclusive, or they can");
+ tfc_say("generate errors or behave abnormally. Please understand that some");
+ tfc_say("dumb mode error checking may be not performed well, and please read");
+ tfc_say("the README included within package and this help text carefully.");
+ tfc_say("\n");
+
+ xexit(1);
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+size_t blk_len_adj(tfc_fsize filelen, tfc_fsize read_already, size_t blklen)
+{
+ if (filelen == NOFSIZE) return blklen;
+ return ((filelen - read_already) >= blklen) ? blklen : (filelen - read_already);
+}
+
+tfc_yesno xor_shrink(void *dst, size_t szdst, const void *src, size_t szsrc)
+{
+ unsigned char *udst = dst;
+ const unsigned char *usrc = src;
+ size_t x, y;
+
+ if ((szsrc % szdst) != 0) return NO;
+ if (szdst >= szsrc) {
+ if (szdst == szsrc) {
+ memmove(dst, src, szsrc);
+ return YES;
+ }
+ return NO;
+ }
+
+ memset(dst, 0, szdst);
+ for (x = 0; x < (szsrc / szdst); x++) {
+ for (y = 0; y < szdst; y++) udst[y] ^= usrc[(x*szdst)+y];
+ }
+
+ return YES;
+}
+
+tfc_yesno str_empty(const char *str)
+{
+ if (!*str) return YES;
+ return NO;
+}
+
+void xclose(int fd)
+{
+ if (fd < 3) return;
+ if (close(fd) == -1) xerror(YES, NO, NO, "close(%d)", fd);
+}
+
+const char *tfc_modename(int mode)
+{
+ switch (mode) {
+ case TFC_MODE_CTR: return "CTR";
+ case TFC_MODE_STREAM: return "STREAM";
+ case TFC_MODE_XTS: return "XTS";
+ case TFC_MODE_ECB: return "ECB";
+ case TFC_MODE_CBC: return "CBC";
+ case TFC_MODE_OCB: return "OCB";
+ }
+
+ return NULL;
+}
+
+void tfc_getcurtime(tfc_useconds *tx)
+{
+ struct timeval t;
+ memset(&t, 0, sizeof(t));
+
+ gettimeofday(&t, NULL);
+ *tx = t.tv_sec * 1000000 + t.tv_usec;
+
+ memset(&t, 0, sizeof(t));
+}
+
+tfc_fsize tfc_fdsize(int fd)
+{
+ off_t l, cur;
+
+ cur = lseek(fd, 0L, SEEK_CUR);
+ l = lseek(fd, 0L, SEEK_SET);
+ if (l == -1) return -1;
+ l = lseek(fd, 0L, SEEK_END);
+ if (l == -1) return -1;
+ lseek(fd, cur, SEEK_SET);
+
+ return (tfc_fsize)l;
+}
+
+tfc_fsize tfc_fnamesize(char *fname, tfc_yesno noexit)
+{
+ int fnmfd;
+ tfc_fsize ret;
+ char *s, T[2];
+
+ if (!fname) return 0;
+
+ s = strchr(fname, ':');
+ if (s && s[1] && (s[1] == '+' || s[1] == '-' || s[1] == '*' || s[1] == '/')) {
+ memcpy(T, s, 2);
+ memset(s, 0, 2);
+ }
+
+ fnmfd = open(fname, O_RDONLY);
+ if (s) memcpy(s, T, 2);
+ if (fnmfd == -1) {
+ xerror(noexit, NO, YES, "%s", fname);
+ return NOFSIZE;
+ }
+ ret = tfc_fdsize(fnmfd);
+ if (ret == NOFSIZE) {
+ xerror(noexit, NO, YES, "%s: not a seekable file", fname);
+ return ret;
+ }
+ xclose(fnmfd);
+
+ return ret;
+}
+
+tfc_fsize tfc_modifysize(tfc_fsize szmodify, const char *szspec)
+{
+ tfc_fsize t;
+ const char *s;
+ char *stoi, c;
+
+ if (szmodify == NOFSIZE) return NOFSIZE;
+ if (!szspec) return szmodify;
+ s = szspec;
+
+ if (*s != ':') return szmodify;
+ s++;
+ if (!(*s == '+' || *s == '-' || *s == '*' || *s == '/')) return szmodify;
+ c = *s;
+ s++;
+ if (strchr(s, '/') || strchr(s, '.')) return szmodify;
+
+ t = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) return szmodify;
+
+ switch (c) {
+ case '+': szmodify += t; break;
+ case '-': szmodify -= t; break;
+ case '*': szmodify *= t; break;
+ case '/': szmodify /= t; break;
+ default: break;
+ }
+
+ return szmodify;
+}
+
+void fcopy_matime(int fd, const struct stat *st)
+{
+ struct timeval times[2];
+
+ times[1].tv_sec = times[0].tv_sec = st->st_mtime;
+ times[1].tv_usec = times[0].tv_usec = 0;
+ if (futimes(fd, times) == -1) xerror(YES, NO, YES, "futimes(%d)", fd);
+}
+
+static void char_to_nul(char *s, size_t l, int c)
+{
+ while (*s && l) { if (*s == c) { *s = 0; break; } s++; l--; }
+}
+
+tfc_yesno xfgets(char *s, size_t n, FILE *f)
+{
+ memset(s, 0, n);
+
+ if (fgets(s, (int)n, f) == s) {
+ char_to_nul(s, n, '\n');
+ return YES;
+ }
+
+ return NO;
+}
+
+tfc_yesno isbase64(const char *s)
+{
+ while (*s) {
+ if (*s >= 'g' && *s <= 'z') return YES;
+ if (*s >= 'G' && *s <= 'Z') return YES;
+ if (*s == '+' || *s == '/' || *s == '=') return YES;
+ s++;
+ }
+ return NO;
+}
+
+static int chrbin(char x)
+{
+ if (x >= '0' && x <= '9')
+ return x - '0';
+ if (x >= 'A' && x <= 'F')
+ return x - 'A' + 10;
+ if (x >= 'a' && x <= 'f')
+ return x - 'a' + 10;
+ return 0;
+}
+
+void hex2bin(void *d, const char *s)
+{
+ const char *S = s;
+ char *D = d;
+ int x = 0;
+
+ while (*s) {
+ if ((s-S) % 2) {
+ x = (x << 4) ^ chrbin(*s);
+ *D = x; D++;
+ }
+ else x = chrbin(*s);
+ s++;
+ }
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+static void get_urandom(const char *src, void *buf, size_t size)
+{
+ tfc_byte *ubuf = buf;
+ int fd = -1;
+ size_t sz = size, rd;
+
+ if (src == NULL) fd = -1;
+ else fd = open(src, O_RDONLY);
+
+ if (fd == -1) fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1) fd = open("/dev/arandom", O_RDONLY);
+ if (fd == -1) fd = open("/dev/prandom", O_RDONLY);
+ if (fd == -1) fd = open("/dev/srandom", O_RDONLY);
+ if (fd == -1) fd = open("/dev/random", O_RDONLY);
+ if (fd == -1) xerror(NO, YES, YES, "random source is required (tried %s)", src);
+
+_again: rd = read(fd, ubuf, sz);
+ if (rd < sz && rd != NOSIZE) {
+ ubuf += rd;
+ sz -= rd;
+ goto _again;
+ }
+
+ xclose(fd);
+}
+
+static tfc_yesno tfc_random_initialised;
+
+static void tfc_initrandom(const char *rndsrc)
+{
+ tfc_byte k[TF_KEY_SIZE];
+
+ if (tfc_random_initialised == YES) return;
+
+ get_urandom(rndsrc, k, TF_KEY_SIZE);
+ tf_prng_seedkey(k);
+ memset(k, 0, TF_KEY_SIZE);
+
+ tfc_random_initialised = YES;
+}
+
+void tfc_finirandom(void)
+{
+ tf_prng_seedkey(NULL);
+ tfc_random_initialised = NO;
+}
+
+void tfc_getrandom(void *buf, size_t sz)
+{
+ if (tfc_random_initialised == NO) tfc_initrandom(randsource);
+ tf_prng_genrandom(buf, sz);
+}
+
+void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes)
+{
+ int fd, x;
+ size_t lblock;
+
+ for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_handler = print_crypt_status;
+ sigaction(SIGUSR1, &sigact, NULL);
+ sigaction(SIGTSTP, &sigact, NULL);
+ sigaction(SIGALRM, &sigact, NULL);
+ if (status_timer) setup_next_alarm(status_timer);
+ sigact.sa_handler = change_status_width;
+ sigaction(SIGQUIT, &sigact, NULL);
+ sigact.sa_handler = change_status_timer;
+ sigaction(SIGUSR2, &sigact, NULL);
+ if (quiet == NO) {
+ sigact.sa_handler = print_crypt_status;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+ }
+ else {
+ sigact.sa_handler = exit_sigterm;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+ }
+ memset(&sigact, 0, sizeof(struct sigaction));
+
+ tfc_getcurtime(&delta_time);
+
+ if (do_less_stats) do_less_stats = NO;
+ else do_less_stats = YES;
+
+ if (!foutname) {
+ fd = 1;
+ foutname = TFC_STDOUT_NAME;
+ }
+ else if (!strcmp(foutname, "-")) {
+ fd = 1;
+ foutname = TFC_STDOUT_NAME;
+ }
+ else fd = open(foutname, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
+ if (fd == -1) xerror(NO, NO, YES, "%s", foutname);
+
+ if (offset) {
+ if (lseek(fd, offset, SEEK_SET) == -1)
+ xerror(YES, NO, NO, "%s: seek failed", foutname);
+ }
+
+ if (ctr_mode == TFC_MODE_PLAIN) memset(srcblk, 0, sizeof(srcblk));
+
+ if (verbose) tfc_nfsay(stderr, "%s: writing %lld bytes to %s ... ",
+ progname, nrbytes, foutname);
+
+ errno = 0;
+ do_stop = NO;
+ while (1) {
+ if (do_stop) break;
+ lblock = blk_len_adj(nrbytes, total_processed_src, sizeof(srcblk));
+
+ if (ctr_mode != TFC_MODE_PLAIN) tfc_getrandom(srcblk, lblock);
+
+ if (write(fd, srcblk, lblock) == -1)
+ xerror(NO, NO, YES, "%s", foutname);
+ if (do_fsync && fsync(fd) == -1) xerror(NO, NO, YES, "%s", foutname);
+
+ total_processed_src += lblock;
+ delta_processed += lblock;
+ total_processed_dst = total_processed_src;
+ if (total_processed_src >= nrbytes) break;
+ }
+
+ if (verbose) tfc_esay("done!");
+ if (verbose || status_timer) print_crypt_status(0);
+
+ xclose(fd);
+ xexit(0);
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+void tfc_vfsay(FILE *where, tfc_yesno addnl, const char *fmt, va_list ap)
+{
+ if (!strcmp(fmt, "\n")) {
+ fputc('\n', where);
+ return;
+ }
+
+ vfprintf(where, fmt, ap);
+ if (addnl) fputc('\n', where);
+ fflush(where);
+}
+
+void tfc_nfsay(FILE *where, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ tfc_vfsay(where, NO, fmt, ap);
+ va_end(ap);
+}
+
+void tfc_esay(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ tfc_vfsay(stderr, YES, fmt, ap);
+ va_end(ap);
+}
+
+void tfc_say(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ tfc_vfsay(stdout, YES, fmt, ap);
+ va_end(ap);
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+void exit_sigterm(int signal)
+{
+ xexit(0);
+}
+
+void print_crypt_status(int signal)
+{
+ tfc_fsize wr_speed;
+ double seconds, human_totalproc_src, human_totalproc_dst, human_wr_speed;
+ int src_scale_idx, dst_scale_idx, wr_speed_scale;
+ const char *oper_mode, *inplace;
+ static tfc_yesno last, was_sigint;
+
+ if (last == YES) return;
+ if (signal == 0) last = YES;
+
+ switch (do_edcrypt) {
+ case TFC_DO_ENCRYPT: oper_mode = "encrypted"; break;
+ case TFC_DO_DECRYPT: oper_mode = "decrypted"; break;
+ default:
+ if (ctr_mode == TFC_MODE_PLAIN) oper_mode = "written";
+ else if (ctr_mode == TFC_MODE_SKSUM) oper_mode = "hashed";
+ else oper_mode = NULL;
+ break;
+ }
+
+ if (signal == SIGINT || signal == SIGTERM) {
+ if (signal == SIGINT) was_sigint = YES;
+ if (do_stop == TFC_STOP_FULL) xexit(0);
+ do_stop = TFC_STOP_FULL;
+ status_timer = 0;
+ verbose = NO;
+ if (bench_timer) goto _out;
+ return;
+ }
+
+_out: tfc_getcurtime(¤t_time);
+ seconds = TFC_UTODSECS(current_time - delta_time);
+ wr_speed = delta_processed / seconds;
+ tfc_describescale(total_processed_src, &human_totalproc_src, &src_scale_idx);
+ tfc_describescale(total_processed_dst, &human_totalproc_dst, &dst_scale_idx);
+ tfc_describescale(wr_speed, &human_wr_speed, &wr_speed_scale);
+
+ if (bench_timer) {
+ tfc_say("done!");
+ tfc_say("%s %s benchmark results:", progname, tfc_modename(ctr_mode));
+ tfc_nfsay(stdout, "%s %llu (%.2f%s) bytes, "
+ "avg. speed %llu (%.2f%s) B/s, time %.4fs.",
+ oper_mode,
+ total_processed_src, human_totalproc_src, tfc_getscale(src_scale_idx),
+ wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale),
+ TFC_UTODSECS(current_time - delta_time));
+ if (was_sigint == NO) tfc_esay("\n");
+ xexit(0);
+ }
+
+ if (do_statline_dynamic == YES) inplace = "\033[2K\r";
+ else inplace = "";
+
+ if (do_less_stats == YES) {
+ tfc_nfsay(stderr, "%s%s:"
+ " %s %.2f%s,"
+ " %.2f%s B/s",
+ inplace, progname,
+ oper_mode,
+ human_totalproc_dst, tfc_getscale(dst_scale_idx),
+ human_wr_speed, tfc_getscale(wr_speed_scale));
+ }
+ else {
+ if (ctr_mode <= TFC_MODE_PLAIN) tfc_nfsay(stderr, "%s%s: read: %llu (%.2f%s),"
+ " %s %llu (%.2f%s) bytes,"
+ " (%llu (%.2f%s) B/s)",
+ inplace, progname,
+ total_processed_src, human_totalproc_src, tfc_getscale(src_scale_idx),
+ oper_mode,
+ total_processed_dst, human_totalproc_dst, tfc_getscale(dst_scale_idx),
+ wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale));
+ else tfc_nfsay(stderr, "%s%s: read: %llu (%.2f%s),"
+ " %s %s %llu (%.2f%s) bytes,"
+ " (%llu (%.2f%s) B/s)",
+ inplace, progname,
+ total_processed_src, human_totalproc_src, tfc_getscale(src_scale_idx),
+ tfc_modename(ctr_mode), oper_mode,
+ total_processed_dst, human_totalproc_dst, tfc_getscale(dst_scale_idx),
+ wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale));
+ }
+
+ if ((do_statline_dynamic == NO || last == YES || signal == -1) && was_sigint == NO) tfc_esay("\n");
+ statline_was_shown = YES;
+
+ delta_processed = 0;
+ tfc_getcurtime(&delta_time);
+
+ if (signal == SIGTSTP) {
+ tfc_esay("stopping.");
+ kill(getpid(), SIGSTOP);
+ }
+
+ if (status_timer) setup_next_alarm(status_timer);
+}
+
+void change_status_width(int signal)
+{
+ if (do_less_stats == YES) do_less_stats = NO;
+ else if (do_less_stats == NO) do_less_stats = YES;
+}
+
+void change_status_timer(int signal)
+{
+ static tfc_useconds reset_timer;
+ tfc_useconds t;
+
+ tfc_getcurtime(&t);
+ if (reset_timer && (t - reset_timer) < TFC_DTOUSECS(0.1)) status_timer = 0;
+ reset_timer = t;
+
+ if (status_timer == 0) status_timer = TFC_DTOUSECS(0.25);
+ else status_timer *= 2;
+
+ if (verbose) tfc_esay("%s: status timer was changed to %.2fs",
+ progname, TFC_UTODSECS(status_timer));
+ setup_next_alarm(status_timer);
+}
+
+void setup_next_alarm(tfc_useconds useconds)
+{
+ struct itimerval it;
+
+ memset(&it, 0, sizeof(struct itimerval));
+ it.it_value.tv_sec = useconds / 1000000;
+ it.it_value.tv_usec = useconds % 1000000;
+ setitimer(ITIMER_REAL, &it, NULL);
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+#include "tfcore.h"
+
+void skein(void *hash, size_t bits, const void *key, const void *data, size_t szdata)
+{
+ struct skein sk;
+
+ if (key) skein_init_key(&sk, key, bits);
+ else skein_init(&sk, bits);
+ skein_update(&sk, data, szdata);
+ skein_final(hash, &sk);
+}
+
+void tf_key_tweak_compat(void *key)
+{
+ TF_UNIT_TYPE *ukey = key, c = THREEFISH_CONST;
+ size_t x;
+
+ for (x = 0; x < TF_NR_BLOCK_UNITS; x++) c ^= ukey[x];
+ ukey[x] = c;
+ ukey[TF_TWEAK_WORD3] = ukey[TF_TWEAK_WORD1] ^ ukey[TF_TWEAK_WORD2];
+}
+
+tfc_yesno skeinfd(void *hash, size_t bits, const void *key, int fd, tfc_fsize readto)
+{
+ static tfc_byte skblk[TFC_BLKSIZE];
+
+ struct skein sk;
+ tfc_byte *pblk;
+ size_t ldone, lblock, lrem, lio;
+ tfc_fsize total = 0;
+ tfc_yesno stop;
+
+ if (ctr_mode == TFC_MODE_SKSUM) total_processed_src = total_processed_dst = delta_processed = 0;
+
+ if (fd == -1) goto _fail;
+ if (fd > 2 && readto == NOFSIZE) {
+ readto = tfc_fdsize(fd);
+ if (readto == NOFSIZE) goto _fail;
+ }
+
+ if (key) skein_init_key(&sk, key, bits);
+ else skein_init(&sk, bits);
+
+ errno = 0;
+ stop = NO;
+ while (1) {
+ if (stop) break;
+ pblk = skblk;
+ lblock = lrem = blk_len_adj(readto, total, TFC_BLKSIZE);
+ ldone = 0;
+_again: lio = read(fd, pblk, lrem);
+ if (lio == 0) stop = YES;
+ if (lio != NOSIZE) ldone += lio;
+ else {
+ if (errno != EIO && catch_all_errors != YES) goto _fail;
+ switch (error_action) {
+ case TFC_ERRACT_CONT: xerror(YES, NO, NO, "skeinfd: %d", fd); goto _again; break;
+ case TFC_ERRACT_SYNC:
+ xerror(YES, NO, NO, "skeinfd: %d", fd);
+ lio = lrem = ldone = lblock;
+ total += lio;
+ memset(skblk, 0, lio);
+ lseek(fd, lio, SEEK_CUR);
+ break;
+ default: goto _fail; break;
+ }
+ }
+ if (lio && lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _again;
+ }
+ total += ldone;
+ if (ctr_mode == TFC_MODE_SKSUM) {
+ total_processed_src = total_processed_dst = total;
+ delta_processed += ldone;
+ }
+ skein_update(&sk, skblk, ldone);
+ if (readto != NOFSIZE && total >= readto) break;
+ }
+
+ if (fd > 2) lseek(fd, (off_t)readto, SEEK_SET);
+
+ skein_final(hash, &sk);
+ if (ctr_mode == TFC_MODE_SKSUM) {
+ if (verbose || status_timer) print_crypt_status(-1);
+ total_processed_src = total_processed_dst = delta_processed = 0;
+ }
+ memset(skblk, 0, TFC_BLKSIZE);
+ return YES;
+
+_fail:
+ memset(&sk, 0, sizeof(struct skein));
+ memset(hash, 0, SKEIN_DIGEST_SIZE);
+ memset(skblk, 0, TFC_BLKSIZE);
+ return NO;
+}
+
+void do_sksum(char *spec, char **fargv)
+{
+ static char sksblk[TFC_BLKSIZE / 2], tmp[TFC_TMPSIZE];
+ tfc_byte hash[SKEIN_DIGEST_SIZE];
+ int fd = -1;
+ int x = 0, xx;
+ size_t bits;
+
+ if (macbits < TF_MAX_BITS) {
+ bits = macbits;
+ goto _dothat;
+ }
+
+ if (!strcmp(spec, "sksum")) {
+ bits = TF_MAX_BITS;
+ goto _dothat;
+ }
+
+ if ((sscanf(spec, "sk%zusum", &bits) < 1)) {
+ bits = TF_MAX_BITS;
+ }
+
+ if (bits < 8 || bits > TF_MAX_BITS) {
+ xerror(NO, YES, YES,
+ "%u: invalid bits number specified!\n"
+ "tfcrypt supports from 8 to %u bits, divisible by 8.",
+ bits, TFC_U(TF_MAX_BITS));
+ }
+
+ if (!bits || bits % 8) {
+ xerror(NO, YES, YES,
+ "%u: invalid bits number specified!\n"
+ "Number of bits must start from 8 and be divisible by 8.",
+ bits, TFC_U(TF_MAX_BITS));
+ }
+
+_dothat:
+ do_edcrypt = TFC_DO_PLAIN;
+ ctr_mode = TFC_MODE_SKSUM;
+
+ for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_handler = print_crypt_status;
+ sigaction(SIGUSR1, &sigact, NULL);
+ sigaction(SIGTSTP, &sigact, NULL);
+ sigaction(SIGALRM, &sigact, NULL);
+ sigact.sa_handler = change_status_width;
+ sigaction(SIGQUIT, &sigact, NULL);
+ sigact.sa_handler = change_status_timer;
+ sigaction(SIGUSR2, &sigact, NULL);
+ sigact.sa_handler = exit_sigterm;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+ memset(&sigact, 0, sizeof(struct sigaction));
+
+ tfc_getcurtime(&delta_time);
+
+ if (sksum_hashlist_file) {
+ FILE *f;
+ char *s, *d, *t, *shash, *fname;
+ int failed = 0, totaltested = 0;
+
+ if (!strcmp(sksum_hashlist_file, "-")) f = stdin;
+ else f = fopen(sksum_hashlist_file, "r");
+ if (!f) xerror(NO, NO, YES, "%s", sksum_hashlist_file);
+
+ while (1) {
+ memset(sksblk, 0, sizeof(sksblk));
+ x = xfgets(sksblk, sizeof(sksblk), f);
+ if (x == 0) break;
+
+ s = d = sksblk; t = NULL;
+ shash = fname = NULL;
+ while ((s = strtok_r(d, "\t", &t))) {
+ if (d) d = NULL;
+
+ if (!shash) shash = s;
+ else if (shash && !fname) fname = s;
+ }
+
+ if (!shash || !fname) {
+ xerror(YES, NO, YES, "invalid string %s", sksblk);
+ exitcode = 2;
+ continue;
+ }
+
+ s = strchr(shash, ' ');
+ if (s && s[1] == ' ') *s = 0;
+
+ fd = open(fname, O_RDONLY | O_LARGEFILE);
+ if (fd == -1) {
+ xerror(YES, NO, YES, "%s", fname);
+ exitcode = 1;
+ continue;
+ }
+
+ if (status_timer) setup_next_alarm(status_timer);
+ if (skeinfd(hash, bits, mackey_opt ? mackey : NULL, fd, maxlen) != YES) {
+ xerror(YES, NO, YES, "%s", fname);
+ exitcode = 1;
+ continue;
+ }
+ xclose(fd);
+ if (sksum_turns > 1) {
+ size_t y;
+ for (y = 0; y < sksum_turns; y++)
+ skein(hash, bits, mackey_opt ? mackey : NULL, hash, TF_FROM_BITS(bits));
+ }
+ if (isbase64(shash)) base64_decode(tmp, sizeof(tmp), shash, strlen(shash));
+ else hex2bin(tmp, shash);
+
+ if (!memcmp(hash, tmp, TF_FROM_BITS(bits))) {
+ tfc_say("%s: OK", fname);
+ }
+ else {
+ tfc_say("%s: FAILED", fname);
+ failed++;
+ }
+ memset(tmp, 0, sizeof(tmp));
+ memset(sksblk, 0, sizeof(sksblk));
+ totaltested++;
+ }
+
+ fclose(f);
+ if (failed) {
+ tfc_esay("%s: WARNING: %u of %u computed checksums did NOT match",
+ progname, failed, totaltested);
+ exitcode = 1;
+ }
+ xexit(exitcode);
+ }
+
+ for (xx = 0; fargv[xx]; xx++);
+ if (xx == 0) {
+ fd = 0;
+ x = 0;
+ goto _dohash;
+ }
+
+ for (x = 0; fargv[x] && xx; x++) {
+ if (!strcmp(fargv[x], "-")) fd = 0;
+ else fd = open(fargv[x], O_RDONLY | O_LARGEFILE);
+ if (fd == -1) {
+ xerror(YES, NO, YES, "%s", fargv[x]);
+ exitcode = 1;
+ continue;
+ }
+
+_dohash: if (status_timer) setup_next_alarm(status_timer);
+ if (skeinfd(hash, bits, mackey_opt ? mackey : NULL, fd, maxlen) != YES) {
+ xerror(YES, NO, YES, "%s", fargv[x]);
+ exitcode = 1;
+ continue;
+ }
+ xclose(fd);
+ if (sksum_turns > 1) {
+ size_t y;
+ for (y = 0; y < sksum_turns; y++) skein(hash, bits, mackey_opt ? mackey : NULL, hash, TF_FROM_BITS(bits));
+ }
+ if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stdout, hash, TF_FROM_BITS(bits), 0);
+ else if (do_outfmt == TFC_OUTFMT_RAW) write(1, hash, TF_FROM_BITS(bits));
+ else mhexdump(hash, TF_FROM_BITS(bits), TF_FROM_BITS(bits), 0);
+ if (do_outfmt != TFC_OUTFMT_RAW) {
+ if (quiet == NO || xx > 1) tfc_say("\t%s", fargv[x] ? fargv[x] : "-");
+ else tfc_say("\n");
+ }
+ }
+
+ memset(hash, 0, SKEIN_DIGEST_SIZE);
+ xexit(exitcode);
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+char *progname;
+int exitcode;
+
+size_t nr_turns = TFC_NR_TURNS;
+int ctr_mode = TFC_CTR_MODE;
+size_t macbits = TF_MAX_BITS;
+
+tfc_byte key[TF_KEY_SIZE], ctr[TF_BLOCK_SIZE], xtskey[TF_KEY_SIZE], mackey[TF_FROM_BITS(TF_MAX_BITS)];
+struct skein sk;
+struct tfe_stream tfe;
+tfc_byte srcblk[TFC_BLKSIZE], dstblk[TFC_BLKSIZE], *pblk;
+tfc_byte macvrfy[SKEIN_DIGEST_SIZE], macresult[SKEIN_DIGEST_SIZE];
+tfc_byte tmpdata[TFC_TMPSIZE];
+
+char *randsource = TFC_DEFAULT_RANDSOURCE;
+
+tfc_fsize iseek_blocks, iseek, oseek, maxlen = NOFSIZE;
+tfc_fsize total_processed_src, total_processed_dst;
+tfc_fsize delta_processed;
+tfc_fsize genrandom_nr_bytes, genzero_nr_bytes;
+int sfd, kfd = -1, dfd = 1;
+struct stat s_stat;
+size_t blksize = TFC_BLKSIZE, xtsblocks = TFC_XTSBLOCKS;
+char pwdask[512], pwdagain[512];
+
+size_t lio, lrem, ldone, lblock;
+size_t maxkeylen = NOSIZE, ctrsz = NOSIZE;
+
+struct sigaction sigact;
+
+size_t sksum_turns;
+
+int do_edcrypt = TFC_DO_ENCRYPT, do_stop, quiet, error_action;
+int counter_opt, mackey_opt, do_mac, do_outfmt = TFC_OUTFMT_B64, rawkey;
+int idx, write_flags;
+tfc_yesno catch_all_errors, password, overwrite_source, do_fsync, do_pad, do_tfcrypt1;
+tfc_yesno do_preserve_time, do_stats_in_gibs, do_statline_dynamic = YES, do_less_stats;
+tfc_yesno no_repeat, do_full_hexdump = YES, verbose, statline_was_shown;
+char *srcfname = TFC_STDIN_NAME, *dstfname = TFC_STDOUT_NAME, *do_mac_file, *counter_file, *sksum_hashlist_file;
+char *genkeyf, *mackeyf, *tweakf;
+char *pw_prompt, *mac_pw_prompt;
+tfc_useconds status_timer, bench_timer;
+tfc_useconds current_time, delta_time;
+
+struct getpasswd_state getps;
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+
+void tf_cbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uiv = iv;
+ const TF_UNIT_TYPE *ukey = key;
+ size_t sl = sz, i;
+
+ if (sl >= TF_BLOCK_SIZE) {
+ do {
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ uiv[i];
+ tf_encrypt_rawblk(x, y, ukey);
+ memcpy(iv, x, TF_BLOCK_SIZE);
+
+ data_to_words(x, TF_BLOCK_SIZE);
+ memcpy(uout, x, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sl) {
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uiv, TF_NR_BLOCK_UNITS);
+ tf_encrypt_rawblk(y, uiv, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+ }
+
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
+
+void tf_cbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS], t[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uiv = iv;
+ const TF_UNIT_TYPE *ukey = key;
+ size_t sl = sz, i;
+
+ if (sl >= TF_BLOCK_SIZE) {
+ do {
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ memcpy(t, x, TF_BLOCK_SIZE);
+ tf_decrypt_rawblk(y, x, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= uiv[i];
+ memcpy(iv, t, TF_BLOCK_SIZE);
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sl) {
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uiv, TF_NR_BLOCK_UNITS);
+ tf_encrypt_rawblk(y, uiv, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+ }
+
+ memset(t, 0, TF_BLOCK_SIZE);
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
--- /dev/null
+#ifndef _THREEFISH_CIPHER_CORE_HEADER
+#define _THREEFISH_CIPHER_CORE_HEADER
+
+#ifndef _THREEFISH_CIPHER_DEFINITIONS_HEADER
+#error Threefish definitions header is required! Include tfdef.h first.
+#endif
+
+#define ROL(x, s, max) ((x << s) | (x >> (-s & (max-1))))
+#define ROR(x, s, max) ((x >> s) | (x << (-s & (max-1))))
+
+#define KE_MIX(x, y, k1, k2, sl) \
+ do { \
+ x += k1; \
+ y += x; \
+ y += k2; \
+ x = ROL(x, sl, TF_UNIT_BITS); \
+ x ^= y; \
+ } while (0)
+
+#define BE_MIX(x, y, sl) \
+ do { \
+ x += y; \
+ y = ROL(y, sl, TF_UNIT_BITS); \
+ y ^= x; \
+ } while (0)
+
+#define KD_MIX(x, y, k1, k2, sr) \
+ do { \
+ x ^= y; \
+ x = ROR(x, sr, TF_UNIT_BITS); \
+ y -= x; \
+ y -= k2; \
+ x -= k1; \
+ } while (0)
+
+#define BD_MIX(x, y, sr) \
+ do { \
+ y ^= x; \
+ y = ROR(y, sr, TF_UNIT_BITS); \
+ x -= y; \
+ } while (0)
+
+#define THREEFISH_CONST 0x1bd11bdaa9fc1a22ULL
+
+#if defined(TF_256BITS)
+enum tf_rotations {
+ TFS_KS01 = 14, TFS_KS02 = 16, TFS_KS03 = 25, TFS_KS04 = 33,
+ TFS_BS01 = 52, TFS_BS02 = 57, TFS_BS03 = 23, TFS_BS04 = 40,
+ TFS_BS05 = 5, TFS_BS06 = 37, TFS_BS07 = 46, TFS_BS08 = 12,
+ TFS_BS09 = 58, TFS_BS10 = 22, TFS_BS11 = 32, TFS_BS12 = 32,
+};
+#elif defined(TF_512BITS)
+enum tf_rotations {
+ TFS_KS01 = 46, TFS_KS02 = 36, TFS_KS03 = 19, TFS_KS04 = 37,
+ TFS_KS05 = 39, TFS_KS06 = 30, TFS_KS07 = 34, TFS_KS08 = 24,
+ TFS_BS01 = 33, TFS_BS02 = 27, TFS_BS03 = 14, TFS_BS04 = 42,
+ TFS_BS05 = 17, TFS_BS06 = 49, TFS_BS07 = 36, TFS_BS08 = 39,
+ TFS_BS09 = 44, TFS_BS10 = 9, TFS_BS11 = 54, TFS_BS12 = 56,
+ TFS_BS13 = 13, TFS_BS14 = 50, TFS_BS15 = 10, TFS_BS16 = 17,
+ TFS_BS17 = 25, TFS_BS18 = 29, TFS_BS19 = 39, TFS_BS20 = 43,
+ TFS_BS21 = 8, TFS_BS22 = 35, TFS_BS23 = 56, TFS_BS24 = 22,
+};
+#elif defined(TF_1024BITS)
+enum tf_rotations {
+ TFS_KS01 = 24, TFS_KS02 = 13, TFS_KS03 = 8, TFS_KS04 = 47,
+ TFS_KS05 = 8, TFS_KS06 = 17, TFS_KS07 = 22, TFS_KS08 = 37,
+ TFS_KS09 = 41, TFS_KS10 = 9, TFS_KS11 = 37, TFS_KS12 = 31,
+ TFS_KS13 = 12, TFS_KS14 = 47, TFS_KS15 = 44, TFS_KS16 = 30,
+ TFS_BS01 = 38, TFS_BS02 = 19, TFS_BS03 = 10, TFS_BS04 = 55,
+ TFS_BS05 = 49, TFS_BS06 = 18, TFS_BS07 = 23, TFS_BS08 = 52,
+ TFS_BS09 = 33, TFS_BS10 = 4, TFS_BS11 = 51, TFS_BS12 = 13,
+ TFS_BS13 = 34, TFS_BS14 = 41, TFS_BS15 = 59, TFS_BS16 = 17,
+ TFS_BS17 = 5, TFS_BS18 = 20, TFS_BS19 = 48, TFS_BS20 = 41,
+ TFS_BS21 = 47, TFS_BS22 = 28, TFS_BS23 = 16, TFS_BS24 = 25,
+ TFS_BS25 = 16, TFS_BS26 = 34, TFS_BS27 = 56, TFS_BS28 = 51,
+ TFS_BS29 = 4, TFS_BS30 = 53, TFS_BS31 = 42, TFS_BS32 = 41,
+ TFS_BS33 = 31, TFS_BS34 = 44, TFS_BS35 = 47, TFS_BS36 = 46,
+ TFS_BS37 = 19, TFS_BS38 = 42, TFS_BS39 = 44, TFS_BS40 = 25,
+ TFS_BS41 = 9, TFS_BS42 = 48, TFS_BS43 = 35, TFS_BS44 = 52,
+ TFS_BS45 = 23, TFS_BS46 = 31, TFS_BS47 = 37, TFS_BS48 = 20,
+};
+#else
+#error No cipher was defined! Aborting build.
+#endif
+
+#endif
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include "tfcrypt.h"
+
+static int getps_filter(struct getpasswd_state *getps, char chr, size_t pos)
+{
+ if (chr == '\x03') {
+ getps->retn = ((size_t)-2);
+ return 6;
+ }
+ return 1;
+}
+
+static int getps_hex_filter(struct getpasswd_state *getps, char chr, size_t pos)
+{
+ if (chr == '\x03') {
+ getps->retn = ((size_t)-2);
+ return 6;
+ }
+ if (chr >= '0' && chr <= '9') return 1;
+ if (chr >= 'a' && chr <= 'f') return 1;
+ if (chr >= 'A' && chr <= 'F') return 1;
+ if (chr == '\x7f' || chr == '\x08'
+ || chr == '\x15' || chr == '\x17') return 1;
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ double td;
+ char *s, *d, *t, *stoi;
+ size_t x, n;
+
+ progname = basename(argv[0]);
+
+ if (!isatty(2)) do_statline_dynamic = NO;
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, "aU:C:r:K:t:TPkzxc:l:qedn:vV:pwE:O:S:AmM:R:Z:WHD:")) != -1) {
+ switch (c) {
+ case 'r':
+ randsource = optarg;
+ break;
+ case 'c':
+ if (!strcasecmp(optarg, "show"))
+ counter_opt = TFC_CTR_SHOW;
+ else if (!strcasecmp(optarg, "head"))
+ counter_opt = TFC_CTR_HEAD;
+ else if (!strcasecmp(optarg, "rand"))
+ counter_opt = TFC_CTR_RAND;
+ else counter_file = sksum_hashlist_file = optarg;
+ break;
+ case 'C':
+ if (!strcasecmp(optarg, "ctr"))
+ ctr_mode = TFC_MODE_CTR;
+ else if (!strcasecmp(optarg, "stream"))
+ ctr_mode = TFC_MODE_STREAM;
+ else if (!strcasecmp(optarg, "cbc"))
+ ctr_mode = TFC_MODE_CBC;
+ else if (!strcasecmp(optarg, "ecb"))
+ ctr_mode = TFC_MODE_ECB;
+ else if (!strcasecmp(optarg, "xts"))
+ ctr_mode = TFC_MODE_XTS;
+ else if (!strcasecmp(optarg, "ocb"))
+ ctr_mode = TFC_MODE_OCB;
+ else xerror(NO, YES, YES, "%s: invalid mode of operation", optarg);
+ break;
+ case 'P':
+ do_edcrypt = TFC_DO_PLAIN;
+ password = YES;
+ ctr_mode = TFC_MODE_PLAIN;
+ break;
+ case 'e':
+ do_edcrypt = TFC_DO_ENCRYPT;
+ break;
+ case 'd':
+ do_edcrypt = TFC_DO_DECRYPT;
+ break;
+ case 'D':
+ macbits = strtoul(optarg, &stoi, 10);
+ if (macbits == 0 || !str_empty(stoi) || macbits < 8
+ || macbits > TF_MAX_BITS || macbits % 8)
+ xerror(NO, YES, YES, "%s: invalid MAC bits setting", optarg);
+ break;
+ case 'n':
+ nr_turns = sksum_turns = strtoul(optarg, &stoi, 10);
+ if (!str_empty(stoi)) xerror(NO, YES, YES, "%s: invalid number of turns", optarg);
+ break;
+ case 'U':
+ if (!strcasecmp(optarg, "key"))
+ mackey_opt = TFC_MACKEY_RAWKEY;
+ else if (!strcasecmp(optarg, "pwd"))
+ mackey_opt = TFC_MACKEY_PASSWORD;
+ else {
+ mackey_opt = TFC_MACKEY_FILE;
+ mackeyf = optarg;
+ }
+ break;
+ case 'p':
+ password = YES;
+ break;
+ case 'k':
+ rawkey = TFC_RAWKEY_KEYFILE;
+ break;
+ case 'z':
+ rawkey = TFC_RAWKEY_ASKSTR;
+ break;
+ case 'x':
+ rawkey = TFC_RAWKEY_ASKHEX;
+ break;
+ case 'K':
+ verbose = YES;
+ genkeyf = optarg;
+ break;
+ case 't':
+ tweakf = optarg;
+ break;
+ case 'T':
+ do_tfcrypt1 = YES;
+ break;
+ case 'l':
+ if (maxlen != NOFSIZE) break;
+
+ maxlen = tfc_humanfsize(optarg, &stoi);
+ if (!str_empty(stoi)) {
+ maxlen = tfc_fnamesize(optarg, YES);
+ maxlen = tfc_modifysize(maxlen, strchr(optarg, ':'));
+ if (maxlen == NOFSIZE) xerror(NO, YES, YES,
+ "%s: invalid count value", optarg);
+ }
+ else maxlen = tfc_modifysize(maxlen, strchr(optarg, ':'));
+ if (counter_opt == TFC_CTR_HEAD)
+ maxlen += TF_BLOCK_SIZE;
+ break;
+ case 'w':
+ overwrite_source = YES;
+ break;
+ case 'E':
+ if (!strcmp(optarg, "xall")) {
+ catch_all_errors = YES;
+ break;
+ }
+ if (!strcmp(optarg, "exit"))
+ error_action = TFC_ERRACT_EXIT;
+ else if (!strncmp(optarg, "cont", 4))
+ error_action = TFC_ERRACT_CONT;
+ else if (!strcmp(optarg, "sync"))
+ error_action = TFC_ERRACT_SYNC;
+ else xerror(NO, YES, YES, "invalid error action %s specified", optarg);
+ break;
+ case 'O':
+ s = d = optarg; t = NULL;
+ while ((s = strtok_r(d, ",", &t))) {
+ if (d) d = NULL;
+ if (!strcmp(s, "sync"))
+ write_flags |= O_SYNC;
+ else if (!strcmp(s, "trunc"))
+ write_flags |= O_TRUNC;
+ else if (!strcmp(s, "fsync"))
+ do_fsync = YES;
+ else if (!strcmp(s, "pad"))
+ do_pad = YES;
+ else if (!strcmp(s, "xtime"))
+ do_preserve_time = YES;
+ else if (!strcmp(s, "gibsize"))
+ do_stats_in_gibs = YES;
+ else if (!strcmp(s, "plainstats"))
+ do_statline_dynamic = NO;
+ else if (!strcmp(s, "statless"))
+ do_less_stats = YES;
+ else if (!strcmp(s, "norepeat"))
+ no_repeat = YES;
+ else if (!strncmp(s, "prompt", 6) && *(s+6) == '=')
+ pw_prompt = s+7;
+ else if (!strncmp(s, "macprompt", 9) && *(s+9) == '=')
+ mac_pw_prompt = s+10;
+ else if (!strcmp(s, "shorthex"))
+ do_full_hexdump = NO;
+ else if (!strncmp(s, "iobs", 4) && *(s+4) == '=') {
+ s += 5;
+ blksize = (size_t)tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ blksize = (size_t)tfc_fnamesize(s, YES);
+ blksize = (size_t)tfc_modifysize((tfc_fsize)blksize, strchr(s, ':'));
+ if (blksize == NOSIZE) xerror(NO, YES, YES,
+ "%s: invalid block size value", s);
+ }
+ else blksize = (size_t)tfc_modifysize((tfc_fsize)blksize, strchr(s, ':'));
+ if (blksize < TF_BLOCK_SIZE) xerror(NO, YES, YES,
+ "%s: block size is lesser than TF_BLOCK_SIZE (%u bytes)", s, TFC_U(TF_BLOCK_SIZE));
+ if (blksize > TFC_BLKSIZE) xerror(NO, YES, YES,
+ "%s: block size exceeds %u bytes",
+ s, TFC_U(TFC_BLKSIZE));
+ }
+ else if (!strncmp(s, "xtsblocks", 9) && *(s+9) == '=') {
+ s += 10;
+ xtsblocks = (size_t)tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ xtsblocks = (size_t)tfc_fnamesize(s, YES);
+ xtsblocks = (size_t)tfc_modifysize((tfc_fsize)xtsblocks, strchr(s, ':'));
+ if (xtsblocks == NOSIZE) xerror(NO, YES, YES,
+ "%s: invalid blocks per xts block value", s);
+ }
+ else xtsblocks = (size_t)tfc_modifysize((tfc_fsize)xtsblocks, strchr(s, ':'));
+ if (TFC_BLKSIZE % xtsblocks) xerror(NO, YES, YES,
+ "%s: nr of blocks per xts block is not round to %u bytes",
+ s, TFC_U(TFC_BLKSIZE));
+ if ((xtsblocks * TF_BLOCK_SIZE) > TFC_BLKSIZE) xerror(NO, YES, YES,
+ "%s: nr of blocks per xts block exceeds %u bytes",
+ s, TFC_U(TFC_BLKSIZE));
+ }
+ else if (!strncmp(s, "iseek", 5) && *(s+5) == '=') {
+ s += 6;
+ iseek = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ iseek = tfc_fnamesize(s, YES);
+ iseek = tfc_modifysize(iseek, strchr(s, ':'));
+ if (iseek == NOFSIZE) xerror(NO, YES, YES,
+ "%s: invalid iseek value", s);
+ }
+ else iseek = tfc_modifysize(iseek, strchr(s, ':'));
+ if (ctr_mode != TFC_MODE_PLAIN && iseek % TF_BLOCK_SIZE)
+ xerror(NO, YES, YES,
+ "%s: not round to TF block size "
+ "of %u bytes",
+ s, TFC_U(TF_BLOCK_SIZE));
+ iseek_blocks = iseek / TF_BLOCK_SIZE;
+ }
+ else if (!strncmp(s, "ixseek", 6) && *(s+6) == '=') {
+ s += 7;
+ iseek = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ iseek = tfc_fnamesize(s, YES);
+ iseek = tfc_modifysize(iseek, strchr(s, ':'));
+ if (iseek == NOFSIZE) xerror(NO, YES, YES,
+ "%s: invalid ixseek value", s);
+ }
+ else iseek = tfc_modifysize(iseek, strchr(s, ':'));
+ }
+ else if (!strncmp(s, "ictr", 4) && *(s+4) == '=') {
+ s += 5;
+ iseek_blocks = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ iseek_blocks = tfc_fnamesize(s, YES);
+ if (iseek_blocks == NOFSIZE)
+ xerror(NO, YES, YES,
+ "%s: invalid ictr value", s);
+ iseek_blocks /= TF_BLOCK_SIZE;
+ iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':'));
+ }
+ else iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':'));
+ }
+ else if (!strncmp(s, "ixctr", 5) && *(s+5) == '=') {
+ s += 6;
+ iseek_blocks = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ iseek_blocks = tfc_fnamesize(s, YES);
+ iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':'));
+ if (iseek_blocks == NOFSIZE)
+ xerror(NO, YES, YES,
+ "%s: invalid ixctr value", s);
+ }
+ else iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':'));
+ if (iseek_blocks % TF_BLOCK_SIZE)
+ xerror(NO, YES, YES,
+ "%s: not round to TF block size "
+ "of %u bytes", s, TFC_U(TF_BLOCK_SIZE));
+ iseek_blocks /= TF_BLOCK_SIZE;
+ }
+ else if (!strncmp(s, "oseek", 5) && *(s+5) == '=') {
+ s += 6;
+ oseek = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ oseek = tfc_fnamesize(s, YES);
+ oseek = tfc_modifysize(oseek, strchr(s, ':'));
+ if (oseek == NOFSIZE) xerror(NO, YES, YES,
+ "%s: invalid oseek value", s);
+ }
+ else oseek = tfc_modifysize(oseek, strchr(s, ':'));
+ }
+ else if (!strncmp(s, "count", 5) && *(s+5) == '=') {
+ s += 6;
+ maxlen = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ maxlen = tfc_fnamesize(s, YES);
+ maxlen = tfc_modifysize(maxlen, strchr(s, ':'));
+ if (maxlen == NOFSIZE) xerror(NO, YES, YES,
+ "%s: invalid count value", s);
+ }
+ else maxlen = tfc_modifysize(maxlen, strchr(s, ':'));
+ if (counter_opt == TFC_CTR_HEAD)
+ maxlen += TF_BLOCK_SIZE;
+ }
+ else if (!strncmp(s, "xkey", 4) && *(s+4) == '=') {
+ s += 5;
+ maxkeylen = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ maxkeylen = (size_t)tfc_fnamesize(s, YES);
+ maxkeylen = (size_t)tfc_modifysize((tfc_fsize)maxkeylen, strchr(s, ':'));
+ if (maxkeylen == NOSIZE)
+ xerror(NO, YES, YES,
+ "%s: invalid key length value", s);
+ }
+ else maxkeylen = (size_t)tfc_modifysize((tfc_fsize)maxkeylen, strchr(s, ':'));
+ }
+ else if (!strncmp(s, "xctr", 4) && *(s+4) == '=') {
+ s += 5;
+ ctrsz = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ ctrsz = (size_t)tfc_fnamesize(s, YES);
+ ctrsz = (size_t)tfc_modifysize((tfc_fsize)ctrsz, strchr(s, ':'));
+ if (ctrsz == NOSIZE)
+ xerror(NO, YES, YES,
+ "%s: invalid counter length value", s);
+ }
+ else ctrsz = (size_t)tfc_modifysize((tfc_fsize)ctrsz, strchr(s, ':'));
+ if (ctrsz > TF_BLOCK_SIZE)
+ xerror(NO, YES, YES, "%s: counter size cannot exceed TF block size", s);
+ }
+ else xerror(NO, YES, YES, "invalid option %s", s);
+ }
+ break;
+ case 'S':
+ do_mac = TFC_MAC_SIGN;
+ if (strcasecmp(optarg, "mac") != 0)
+ do_mac_file = optarg;
+ break;
+ case 'M':
+ do_mac = TFC_MAC_VRFY;
+ if (!strcasecmp(optarg, "drop"))
+ do_mac = TFC_MAC_DROP;
+ else if (strcasecmp(optarg, "mac") != 0)
+ do_mac_file = optarg;
+ break;
+ case 'm':
+ if (do_mac != TFC_MAC_VRFY)
+ xerror(NO, YES, YES, "signature source was not specified");
+ do_mac = TFC_MAC_JUST_VRFY;
+ break;
+ case 'R':
+ case 'Z':
+ if (maxlen != NOFSIZE) {
+ if (c == 'Z') genzero_nr_bytes = maxlen;
+ else genrandom_nr_bytes = maxlen;
+ }
+ else {
+ tfc_fsize t;
+ if (!strcasecmp(optarg, "cbs"))
+ t = TF_BLOCK_SIZE;
+ else if (!strcasecmp(optarg, "ks"))
+ t = TF_FROM_BITS(TFC_KEY_BITS);
+ else if (!strcasecmp(optarg, "xks"))
+ t = TF_FROM_BITS(TFC_KEY_BITS) * 2;
+ else if (!strcasecmp(optarg, "iobs"))
+ t = blksize;
+ else {
+ t = tfc_humanfsize(optarg, &stoi);
+ if (!str_empty(stoi)) {
+ t = tfc_fnamesize(optarg, NO);
+ t = tfc_modifysize(t, strchr(optarg, ':'));
+ }
+ else t = tfc_modifysize(t, strchr(optarg, ':'));
+ }
+ if (c == 'Z') genzero_nr_bytes = maxlen = t;
+ else genrandom_nr_bytes = maxlen = t;
+ }
+ break;
+ case 'a':
+ do_preserve_time = YES;
+ break;
+ case 'A':
+ do_outfmt = TFC_OUTFMT_B64;
+ break;
+ case 'W':
+ do_outfmt = TFC_OUTFMT_RAW;
+ break;
+ case 'H':
+ do_outfmt = TFC_OUTFMT_HEX;
+ break;
+ case 'q':
+ quiet = YES;
+ verbose = NO;
+ status_timer = 0;
+ break;
+ case 'v':
+ verbose = YES;
+ break;
+ case 'V':
+ td = strtod(optarg, &stoi);
+ status_timer = TFC_DTOUSECS(td);
+ if (status_timer <= TFC_DTOUSECS(0) || !str_empty(stoi)) status_timer = 0;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (!strcmp(progname, "tfbench")) {
+ if (!*(argv+optind)) usage();
+
+ td = strtod(*(argv+optind), &stoi);
+ if (td <= TFC_DTOUSECS(0) || !str_empty(stoi))
+ xerror(NO, YES, YES,
+ "%s: invalid benchmark time in seconds", *(argv+optind));
+ bench_timer = TFC_DTOUSECS(td);
+ do_benchmark(bench_timer, td);
+ }
+ if (genrandom_nr_bytes) {
+ ctr_mode = TFC_MODE_STREAM;
+ do_edcrypt = TFC_DO_ENCRYPT;
+ gen_write_bytes(*(argv+optind), oseek, genrandom_nr_bytes);
+ }
+ if (genzero_nr_bytes) {
+ ctr_mode = TFC_MODE_PLAIN;
+ do_edcrypt = TFC_DO_PLAIN;
+ gen_write_bytes(*(argv+optind), oseek, genzero_nr_bytes);
+ }
+
+ if (rawkey && password)
+ xerror(NO, YES, YES, "Cannot use rawkey and hashing password!");
+ if (do_edcrypt == TFC_DO_ENCRYPT && do_mac >= TFC_MAC_VRFY)
+ xerror(NO, YES, YES, "Cannot encrypt and verify signature!");
+ if (do_edcrypt == TFC_DO_DECRYPT && do_mac == TFC_MAC_SIGN)
+ xerror(NO, YES, YES, "Cannot decrypt and calculate signature!");
+ if (do_edcrypt == TFC_DO_DECRYPT && counter_opt == TFC_CTR_RAND)
+ xerror(NO, YES, YES, "Cannot decrypt and embed a generated CTR into file!");
+ if (do_edcrypt == TFC_DO_ENCRYPT && counter_opt == TFC_CTR_HEAD)
+ xerror(NO, YES, YES, "Cannot encrypt and read CTR from source!");
+ if (overwrite_source && counter_opt == TFC_CTR_RAND)
+ xerror(NO, YES, YES, "Cannot embed a CTR into file when overwriting it!");
+ if (tweakf && do_tfcrypt1 == NO)
+ xerror(NO, YES, YES, "Use -T with -t tweakfile to enable old tfcrypt mode!");
+ if (ctr_mode == TFC_MODE_PLAIN
+ && (do_edcrypt || do_mac || rawkey
+ || mackey_opt || counter_opt || counter_file))
+ xerror(NO, YES, YES, "Encryption facility is disabled when in plain IO mode.");
+
+ errno = 0;
+ do_stop = NO;
+
+ if (mackey_opt == TFC_MACKEY_FILE && mackeyf) {
+ int mkfd = -1;
+ tfc_yesno do_stop;
+
+ if (!strcmp(mackeyf, "-")) mkfd = 0;
+ else mkfd = open(mackeyf, O_RDONLY | O_LARGEFILE);
+ if (mkfd == -1) xerror(NO, NO, YES, "%s", mackeyf);
+
+ skein_init(&sk, TFC_KEY_BITS);
+
+ do_stop = NO;
+ while (1) {
+ if (do_stop) break;
+ pblk = tmpdata;
+ ldone = 0;
+ lrem = lblock = sizeof(tmpdata);
+_mkragain: lio = read(mkfd, pblk, lrem);
+ if (lio == 0) do_stop = YES;
+ if (lio != NOSIZE) ldone += lio;
+ else {
+ if (errno != EIO && catch_all_errors != YES)
+ xerror(NO, NO, NO, "%s", mackeyf);
+ switch (error_action) {
+ case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", mackeyf); goto _mkragain; break;
+ case TFC_ERRACT_SYNC:
+ xerror(YES, NO, NO, "%s", mackeyf);
+ lio = ldone = lrem = lblock;
+ memset(tmpdata, 0, lio);
+ lseek(mkfd, lio, SEEK_CUR);
+ break;
+ default: xerror(NO, NO, NO, "%s", mackeyf); break;
+ }
+ }
+ if (lio && lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _mkragain;
+ }
+
+ skein_update(&sk, tmpdata, ldone);
+ }
+
+ skein_final(mackey, &sk);
+
+ xclose(mkfd);
+ }
+ else if (mackey_opt == TFC_MACKEY_PASSWORD) {
+ memset(&getps, 0, sizeof(struct getpasswd_state));
+ getps.fd = getps.efd = -1;
+ getps.passwd = pwdask;
+ getps.pwlen = sizeof(pwdask)-1;
+ getps.echo = mac_pw_prompt ? mac_pw_prompt : "Enter MAC password: ";
+ getps.charfilter = getps_filter;
+ getps.maskchar = 'x';
+ getps.flags = GETP_WAITFILL;
+ n = xgetpasswd(&getps);
+ if (n == NOSIZE) xerror(NO, NO, YES, "getting MAC password");
+ if (n == ((size_t)-2)) xexit(1);
+ skein(mackey, TF_MAX_BITS, NULL, pwdask, n);
+ if (verbose) {
+ skein(tmpdata, TF_MAX_BITS, NULL, mackey, TF_FROM_BITS(TF_MAX_BITS));
+ xor_shrink(tmpdata+TF_FROM_BITS(TF_MAX_BITS), TF_SIZE_UNIT, tmpdata, TF_FROM_BITS(TF_MAX_BITS));
+ tfc_nfsay(stderr, "MAC password hint: ");
+ mehexdump(tmpdata+TF_FROM_BITS(TF_MAX_BITS), TF_SIZE_UNIT, TF_SIZE_UNIT, 1);
+ memset(tmpdata, 0, sizeof(tmpdata));
+ }
+ }
+
+
+ if ((strlen(progname) <= 9)
+ && ((!strcmp(progname, "sksum"))
+ || ((!memcmp(progname, "sk", 2))
+ && (!memcmp(progname+3, "sum", 3)
+ || !memcmp(progname+4, "sum", 3)
+ || !memcmp(progname+5, "sum", 3)
+ || !memcmp(progname+6, "sum", 3)))))
+ do_sksum(progname, argv+optind);
+ if (!strcmp(progname, "tfbase64")) do_edbase64(argv+optind);
+
+ idx = optind;
+
+ if (argv[idx]) {
+ if (password || rawkey > TFC_RAWKEY_KEYFILE) goto _nokeyfd;
+ if (!strcmp(argv[idx], "-")) kfd = 0;
+ else kfd = open(argv[idx], O_RDONLY | O_LARGEFILE);
+ if (kfd == -1) xerror(NO, NO, YES, "%s", argv[idx]);
+
+ lio = strnlen(argv[idx], PATH_MAX);
+ memset(argv[idx], '*', lio);
+
+ idx++;
+ }
+ else password = YES;
+
+ errno = 0;
+ if (do_tfcrypt1 == YES && tweakf) {
+ int twfd;
+
+ if (!strcmp(tweakf, "-")) twfd = 0;
+ else twfd = open(tweakf, O_RDONLY | O_LARGEFILE);
+ if (twfd == -1) xerror(NO, NO, YES, "%s", tweakf);
+ lio = ldone = read(twfd, key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_SIZE_UNIT);
+ if (lio == NOSIZE) xerror(NO, NO, YES, "%s", tweakf);
+ if (ldone < 2*TF_SIZE_UNIT)
+ xerror(NO, NO, YES, "%s: %zu bytes tweak required", tweakf, 2*TF_SIZE_UNIT);
+ xclose(twfd);
+ }
+
+_nokeyfd:
+ errno = 0;
+ if (argv[idx]) {
+ if (!strcmp(argv[idx], "-") && kfd) sfd = 0;
+ else {
+ sfd = open(argv[idx], O_RDONLY | O_LARGEFILE);
+ if (do_preserve_time) if (fstat(sfd, &s_stat) == -1)
+ xerror(YES, NO, YES, "stat(%s)", argv[idx]);
+ }
+ if (sfd == -1) xerror(NO, NO, YES, "%s", argv[idx]);
+
+ if (do_edcrypt == TFC_DO_DECRYPT && do_mac != NO && maxlen != NOFSIZE) {
+ if (verbose) tfc_esay("%s: disabling signature verification on "
+ "requested partial decryption.", progname);
+ do_mac = NO;
+ }
+
+ if ((do_mac >= TFC_MAC_VRFY || do_mac == TFC_MAC_DROP) && !do_mac_file) {
+ maxlen = tfc_fdsize(sfd);
+ if (maxlen == NOFSIZE)
+ xerror(NO, YES, YES,
+ "Cannot verify embedded MAC with non-seekable source!");
+ maxlen -= TF_FROM_BITS(macbits);
+ }
+ srcfname = argv[idx];
+ idx++;
+ }
+
+ if (!do_mac_file && (do_mac >= TFC_MAC_VRFY && sfd == 0))
+ xerror(NO, YES, YES, "Cannot verify embedded MAC with non-seekable source!");
+
+ if (ctrsz == NOSIZE) ctrsz = TF_BLOCK_SIZE;
+ if (ctrsz > TF_BLOCK_SIZE) ctrsz = TF_BLOCK_SIZE;
+
+ if (ctr_mode == TFC_MODE_ECB) goto _ctrskip1;
+ errno = 0;
+ if (counter_file) {
+ int ctrfd;
+
+ if (!strcmp(counter_file, "-")) ctrfd = 0;
+ else ctrfd = open(counter_file, O_RDONLY | O_LARGEFILE);
+ if (ctrfd == -1) xerror(NO, NO, YES, "%s", counter_file);
+ lio = read(ctrfd, ctr, ctrsz);
+ if (lio == NOSIZE) xerror(NO, NO, YES, "%s", counter_file);
+ if (lio < ctrsz) xerror(NO, YES, YES, "counter file is too small (%zu)!", lio);
+ xclose(ctrfd);
+ }
+ else if (counter_opt == TFC_CTR_HEAD) {
+ pblk = ctr;
+ ldone = 0;
+ lrem = lblock = ctrsz;
+_ctrragain: lio = read(sfd, pblk, lrem);
+ if (lio != NOSIZE) ldone += lio;
+ else {
+ if (errno != EIO && catch_all_errors != YES)
+ xerror(NO, NO, NO, "%s", srcfname);
+ switch (error_action) {
+ case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ctrragain; break;
+ case TFC_ERRACT_SYNC:
+ xerror(YES, NO, NO, "%s", srcfname);
+ lio = ldone = lrem = lblock;
+ memset(ctr, 0, lio);
+ lseek(sfd, lio, SEEK_CUR);
+ break;
+ default: xerror(NO, NO, NO, "%s", srcfname); break;
+ }
+ }
+ if (lio && lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _ctrragain;
+ }
+ total_processed_src += ldone;
+ }
+
+_ctrskip1:
+ if (iseek) {
+ if (counter_opt == TFC_CTR_HEAD && ctr_mode != TFC_MODE_ECB)
+ iseek += ctrsz;
+ if (lseek(sfd, iseek, SEEK_SET) == -1)
+ xerror(YES, NO, NO, "%s: seek failed", srcfname);
+ }
+
+ if (ctr_mode == TFC_MODE_PLAIN) goto _plain;
+
+ if (verbose) tfc_esay("%s: hashing password", progname);
+
+ if (rawkey == TFC_RAWKEY_KEYFILE) {
+ tfc_yesno xtskeyset = NO;
+
+ pblk = key;
+_xts2key: ldone = 0;
+ lrem = lblock = TF_FROM_BITS(TFC_KEY_BITS);
+_keyragain: lio = read(kfd, pblk, lrem);
+ if (lio != NOSIZE) ldone += lio;
+ else {
+ if (errno != EIO && catch_all_errors != YES)
+ xerror(NO, NO, NO, "reading key");
+ switch (error_action) {
+ case TFC_ERRACT_CONT: xerror(YES, NO, NO, "reading key"); goto _keyragain; break;
+ case TFC_ERRACT_SYNC:
+ xerror(YES, NO, NO, "reading key");
+ lio = ldone = lrem = lblock;
+ memset(key, 0, lio);
+ lseek(kfd, lio, SEEK_CUR);
+ break;
+ default: xerror(NO, NO, NO, "reading key"); break;
+ }
+ }
+ if (lio && lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _keyragain;
+ }
+ if (ldone < lblock) xerror(NO, YES, YES, "rawkey too small! (%zu)", ldone);
+
+ if (ctr_mode == TFC_MODE_XTS) {
+ if (xtskeyset == NO) {
+ pblk = xtskey;
+ xtskeyset = YES;
+ goto _xts2key;
+ }
+ }
+ }
+ else if (rawkey == TFC_RAWKEY_ASKSTR) {
+ tfc_yesno xtskeyset = NO;
+
+ pblk = key; n = sizeof(key);
+_xts2keyaskstr: memset(&getps, 0, sizeof(struct getpasswd_state));
+ getps.fd = getps.efd = -1;
+ getps.passwd = (char *)pblk;
+ getps.pwlen = n;
+ getps.echo = pw_prompt ? pw_prompt : "Enter rawkey (str): ";
+ getps.charfilter = getps_filter;
+ getps.maskchar = 'x';
+ getps.flags = GETP_WAITFILL;
+ n = xgetpasswd(&getps);
+ if (n == NOSIZE) xerror(NO, NO, YES, "getting string rawkey");
+ if (n == ((size_t)-2)) xexit(1);
+ if (ctr_mode == TFC_MODE_XTS) {
+ if (xtskeyset == NO) {
+ pblk = xtskey; n = sizeof(xtskey);
+ xtskeyset = YES;
+ goto _xts2keyaskstr;
+ }
+ }
+ }
+ else if (rawkey == TFC_RAWKEY_ASKHEX) {
+ tfc_yesno xtskeyset = NO;
+
+ pblk = key;
+_rawkey_hex_again:
+ memset(&getps, 0, sizeof(struct getpasswd_state));
+ getps.fd = getps.efd = -1;
+ getps.passwd = pwdask;
+ getps.pwlen = (TF_FROM_BITS(TFC_KEY_BITS)*2);
+ getps.echo = pw_prompt ? pw_prompt : "Enter rawkey (hex): ";
+ getps.charfilter = getps_hex_filter;
+ getps.maskchar = 'x';
+ getps.flags = GETP_WAITFILL;
+ n = xgetpasswd(&getps);
+ if (n == NOSIZE) xerror(NO, NO, YES, "getting hex rawkey");
+ if (n == ((size_t)-2)) xexit(1);
+ if (n % 2) {
+ tfc_esay("Please input even number of hex digits!");
+ goto _rawkey_hex_again;
+ }
+ hex2bin(pblk, pwdask);
+ memset(pwdask, 0, sizeof(pwdask));
+ if (ctr_mode == TFC_MODE_XTS) {
+ if (xtskeyset == NO) {
+ pblk = xtskey;
+ xtskeyset = YES;
+ goto _rawkey_hex_again;
+ }
+ }
+ }
+ else if (password) {
+_pwdagain: memset(&getps, 0, sizeof(struct getpasswd_state));
+ getps.fd = getps.efd = -1;
+ getps.passwd = pwdask;
+ getps.pwlen = sizeof(pwdask)-1;
+ getps.echo = pw_prompt ? pw_prompt : "Enter password: ";
+ getps.charfilter = getps_filter;
+ getps.maskchar = 'x';
+ getps.flags = GETP_WAITFILL;
+ n = xgetpasswd(&getps);
+ if (n == NOSIZE) xerror(NO, NO, YES, "getting password");
+ if (n == ((size_t)-2)) xexit(1);
+ if (do_edcrypt == TFC_DO_ENCRYPT && no_repeat == NO) {
+ getps.fd = getps.efd = -1;
+ getps.passwd = pwdagain;
+ getps.pwlen = sizeof(pwdagain)-1;
+ getps.echo = "Enter it again: ";
+ getps.flags = GETP_WAITFILL;
+ n = xgetpasswd(&getps);
+ if (n == NOSIZE) xerror(NO, NO, YES, "getting password again");
+ if (n == ((size_t)-2)) xexit(1);
+ if (strncmp(pwdask, pwdagain, sizeof(pwdagain)-1) != 0) {
+ tfc_esay("Passwords are different, try again");
+ goto _pwdagain;
+ }
+ }
+ skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, pwdask, n);
+ memset(pwdask, 0, sizeof(pwdask));
+ memset(pwdagain, 0, sizeof(pwdagain));
+ }
+ else {
+ if (skeinfd(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, kfd, maxkeylen) != YES)
+ xerror(NO, NO, YES, "hashing key");
+ }
+
+ if (nr_turns > 1 && rawkey == NO) {
+ for (x = 0; x < nr_turns; x++)
+ skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
+ }
+
+ if (ctr_mode == TFC_MODE_XTS && rawkey == NO) {
+ skein(xtskey, TF_NR_KEY_BITS, mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
+ }
+
+ if (genkeyf) {
+ int krfd;
+ tfc_yesno xtskeyset = NO;
+
+ pblk = key;
+ if (!strcmp(genkeyf, "-")) krfd = 1;
+ else krfd = open(genkeyf, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
+ if (krfd == -1) xerror(NO, NO, YES, "%s", genkeyf);
+_xts2genkey: if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO, NO, YES, "%s", genkeyf);
+ if (do_fsync && fsync(krfd) == -1) xerror(NO, NO, YES, "%s", genkeyf);
+ if (verbose && xtskeyset == NO) {
+ tfc_esay("%s: password hashing done", progname);
+ tfc_esay("%s: rawkey written to %s.", progname, genkeyf);
+ tfc_esay("%s: Have a nice day!", progname);
+ }
+
+ if (ctr_mode == TFC_MODE_XTS) {
+ if (xtskeyset == NO) {
+ pblk = xtskey;
+ xtskeyset = YES;
+ goto _xts2genkey;
+ }
+ }
+
+ fchmod(krfd, 0600);
+ xclose(krfd);
+ xexit(0);
+ }
+
+ if (iseek_blocks && (do_edcrypt == TFC_DO_DECRYPT && do_mac != NO)) {
+ if (verbose) tfc_esay("%s: disabling signature verification on "
+ "requested partial decryption.", progname);
+ do_mac = NO;
+ }
+
+ if (do_mac != NO) {
+ if (mackey_opt == TFC_MACKEY_RAWKEY) skein(mackey, TF_MAX_BITS, key, key, TF_FROM_BITS(TFC_KEY_BITS));
+ if (ctr_mode < TFC_MODE_OCB) {
+ if (verbose) tfc_esay("%s: doing MAC calculation, processing speed "
+ "will be slower.", progname);
+ if (mackey_opt) skein_init_key(&sk, mackey, macbits);
+ else skein_init(&sk, macbits);
+ }
+ }
+
+ if (!counter_file && counter_opt <= TFC_CTR_SHOW && ctr_mode != TFC_MODE_ECB) {
+ skein(ctr, TF_TO_BITS(ctrsz), mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
+ }
+
+ tf_convkey(key);
+ if (ctr_mode == TFC_MODE_XTS) tf_convkey(xtskey);
+ if (do_tfcrypt1 == YES) {
+ if (!tweakf) skein(key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_UNIT_BITS, NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
+ tf_key_tweak_compat(key);
+ }
+ if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr);
+ if (ctr_mode == TFC_MODE_ECB) goto _ctrskip2;
+ tfc_data_to_words64(&iseek_blocks, sizeof(iseek_blocks));
+ tf_ctr_set(ctr, &iseek_blocks, sizeof(iseek_blocks));
+
+ switch (counter_opt) {
+ case TFC_CTR_SHOW:
+ switch (do_outfmt) {
+ case TFC_OUTFMT_B64: tfc_printbase64(stderr, ctr, ctrsz, YES); break;
+ case TFC_OUTFMT_RAW: write(2, ctr, ctrsz); break;
+ case TFC_OUTFMT_HEX: mhexdump(ctr, ctrsz, ctrsz, YES); break;
+ }
+ break;
+ case TFC_CTR_RAND: tfc_getrandom(ctr, ctrsz); break;
+ }
+
+_ctrskip2:
+ if (kfd != -1) {
+ xclose(kfd);
+ kfd = -1;
+ }
+ if (verbose) tfc_esay("%s: password hashing done", progname);
+
+ if (overwrite_source && srcfname) argv[idx] = srcfname;
+
+_plain:
+ if (argv[idx]) {
+ if (!strcmp(argv[idx], "-")) dfd = 1;
+ else dfd = open(argv[idx], O_RDWR | O_LARGEFILE | write_flags, 0666);
+ if (dfd == -1) {
+ dfd = open(argv[idx], O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
+ if (dfd == -1) xerror(NO, NO, YES, "%s", argv[idx]);
+ }
+ dstfname = argv[idx];
+ idx++;
+ }
+
+ if (oseek) {
+ if (lseek(dfd, oseek, SEEK_SET) == -1)
+ xerror(YES, NO, NO, "%s: seek failed", dstfname);
+ }
+
+ for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_handler = print_crypt_status;
+ sigaction(SIGUSR1, &sigact, NULL);
+ sigaction(SIGTSTP, &sigact, NULL);
+ sigaction(SIGALRM, &sigact, NULL);
+ if (status_timer) setup_next_alarm(status_timer);
+ sigact.sa_handler = change_status_width;
+ sigaction(SIGQUIT, &sigact, NULL);
+ sigact.sa_handler = change_status_timer;
+ sigaction(SIGUSR2, &sigact, NULL);
+ if (quiet == NO) {
+ sigact.sa_handler = print_crypt_status;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+ }
+ else {
+ sigact.sa_handler = exit_sigterm;
+ sigaction(SIGINT, &sigact, NULL);
+ sigaction(SIGTERM, &sigact, NULL);
+ }
+ memset(&sigact, 0, sizeof(struct sigaction));
+
+ tfc_getcurtime(&delta_time);
+
+ errno = 0;
+ if (counter_opt == TFC_CTR_RAND && ctr_mode != TFC_MODE_ECB) {
+ pblk = ctr;
+ lio = lrem = ctrsz;
+ ldone = 0;
+_ctrwagain: lio = write(dfd, pblk, lrem);
+ if (lio != NOSIZE) ldone += lio;
+ else xerror(NO, NO, NO, "%s", dstfname);
+ if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
+ if (lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _ctrwagain;
+ }
+ total_processed_dst += ldone;
+ delta_processed += ldone;
+ }
+
+ errno = 0;
+ do_stop = NO;
+ while (1) {
+ if (do_stop) break;
+ pblk = srcblk;
+ ldone = 0;
+ lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize);
+_ragain: lio = read(sfd, pblk, lrem);
+ if (lio == 0) do_stop = TFC_STOP_BEGAN;
+ if (lio != NOSIZE) ldone += lio;
+ else {
+ if (errno != EIO && catch_all_errors != YES)
+ xerror(NO, NO, NO, "%s", srcfname);
+ switch (error_action) {
+ case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ragain; break;
+ case TFC_ERRACT_SYNC:
+ xerror(YES, NO, NO, "%s", srcfname);
+ lio = ldone = lrem = lblock;
+ memset(srcblk, 0, lio);
+ lseek(sfd, lio, SEEK_CUR);
+ break;
+ default: xerror(NO, NO, NO, "%s", srcfname); break;
+ }
+ }
+ if (lio && lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _ragain;
+ }
+ total_processed_src += ldone;
+
+ if (do_pad && (ldone % TF_BLOCK_SIZE)) {
+ size_t orig = ldone;
+ ldone += (TF_BLOCK_SIZE - (ldone % TF_BLOCK_SIZE));
+ if (ldone > blksize) ldone = blksize;
+ memset(srcblk+orig, 0, sizeof(srcblk)-orig);
+ }
+
+ if (do_mac == TFC_MAC_SIGN && ctr_mode < TFC_MODE_OCB)
+ skein_update(&sk, srcblk, ldone);
+
+ if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, dstblk, srcblk, ldone);
+ else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, dstblk, srcblk, ldone);
+ else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_xts_encrypt(key, xtskey, ctr, dstblk, srcblk, ldone, xtsblocks);
+ else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_DECRYPT)
+ tf_xts_decrypt(key, xtskey, ctr, dstblk, srcblk, ldone, xtsblocks);
+ else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_ecb_encrypt(key, dstblk, srcblk, ldone);
+ else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_DECRYPT)
+ tf_ecb_decrypt(key, dstblk, srcblk, ldone);
+ else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_cbc_encrypt(key, ctr, dstblk, srcblk, ldone);
+ else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_DECRYPT)
+ tf_cbc_decrypt(key, ctr, dstblk, srcblk, ldone);
+
+ else if (ctr_mode == TFC_MODE_OCB && do_edcrypt == TFC_DO_ENCRYPT)
+ tf_ocb_encrypt(key, ctr, dstblk, do_mac == TFC_MAC_SIGN ? macresult : NULL, srcblk, ldone, xtsblocks);
+ else if (ctr_mode == TFC_MODE_OCB && do_edcrypt == TFC_DO_DECRYPT)
+ tf_ocb_decrypt(key, ctr, dstblk, do_mac >= TFC_MAC_VRFY ? macresult : NULL, srcblk, ldone, xtsblocks);
+
+ else if (ctr_mode == TFC_MODE_PLAIN)
+ memcpy(dstblk, srcblk, ldone);
+
+ if (do_mac >= TFC_MAC_VRFY && ctr_mode < TFC_MODE_OCB)
+ skein_update(&sk, dstblk, ldone);
+ if (do_mac == TFC_MAC_JUST_VRFY) goto _nowrite;
+
+ pblk = dstblk;
+ lrem = ldone;
+ ldone = 0;
+_wagain: lio = write(dfd, pblk, lrem);
+ if (lio != NOSIZE) ldone += lio;
+ else xerror(NO, NO, NO, "%s", dstfname);
+ if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
+ if (lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _wagain;
+ }
+_nowrite: total_processed_dst += ldone;
+ delta_processed += ldone;
+
+ if (maxlen != NOFSIZE && total_processed_src >= maxlen) break;
+ }
+
+ if (do_stop == TFC_STOP_FULL) goto _nomac;
+
+ errno = 0;
+ if (do_mac >= TFC_MAC_VRFY) {
+ if (!do_mac_file) {
+ pblk = macvrfy;
+ ldone = 0;
+ lrem = lblock = TF_FROM_BITS(macbits);
+_macragain: lio = read(sfd, pblk, lrem);
+ if (lio != NOSIZE) ldone += lio;
+ else {
+ if (errno != EIO && catch_all_errors != YES)
+ xerror(NO, NO, NO, "%s", srcfname);
+ switch (error_action) {
+ case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _macragain; break;
+ case TFC_ERRACT_SYNC:
+ xerror(YES, NO, NO, "%s", srcfname);
+ lio = ldone = lrem = lblock;
+ memset(macvrfy, 0, lio);
+ lseek(sfd, lio, SEEK_CUR);
+ break;
+ default: xerror(NO, NO, NO, "%s", srcfname); break;
+ }
+ }
+ if (lio && lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _macragain;
+ }
+ total_processed_src += ldone;
+ }
+ else {
+ int mfd;
+
+ if (!strcmp(do_mac_file, "-")) mfd = 0;
+ else mfd = open(do_mac_file, O_RDONLY | O_LARGEFILE);
+ if (mfd == -1) xerror(YES, NO, NO, "%s", do_mac_file);
+ lio = ldone = read(mfd, tmpdata, sizeof(tmpdata));
+ if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
+ if (!memcmp(tmpdata, TFC_ASCII_TFC_MAC_FOURCC, TFC_ASCII_TFC_MAC_FOURCC_LEN)) {
+ memmove(tmpdata, tmpdata+TFC_ASCII_TFC_MAC_FOURCC_LEN,
+ sizeof(tmpdata)-TFC_ASCII_TFC_MAC_FOURCC_LEN);
+ lio = TF_FROM_BITS(macbits);
+ base64_decode((char *)macvrfy, lio, (char *)tmpdata, sizeof(tmpdata));
+ }
+ else memcpy(macvrfy, tmpdata, TF_FROM_BITS(macbits));
+ xclose(mfd);
+ }
+
+ if (ldone < TF_FROM_BITS(macbits)) {
+ if (quiet == NO) tfc_esay("%s: short signature (%zu), "
+ "not verifying", progname, ldone);
+ exitcode = 1;
+ goto _shortmac;
+ }
+
+ if (ctr_mode < TFC_MODE_OCB) skein_final(macresult, &sk);
+ else skein(macresult, macbits, mackey, macresult, TF_FROM_BITS(macbits));
+
+ if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, tmpdata, macvrfy, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_XTS) tf_xts_decrypt(key, xtskey, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits), xtsblocks);
+ else if (ctr_mode == TFC_MODE_ECB) tf_ecb_decrypt(key, tmpdata, macvrfy, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_CBC) tf_cbc_decrypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_OCB) tf_ocb_decrypt(key, ctr, tmpdata, NULL, macvrfy, TF_FROM_BITS(macbits), xtsblocks);
+
+ if (!memcmp(tmpdata, macresult, TF_FROM_BITS(macbits))) {
+ if (quiet == NO) {
+ tfc_esay("%s: signature is good", progname);
+ if (verbose) {
+ if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stderr, macresult, TF_FROM_BITS(macbits), YES);
+ else mhexdump(macresult, TF_FROM_BITS(macbits), TF_FROM_BITS(macbits), YES);
+ }
+ }
+ }
+ else {
+ if (quiet == NO) tfc_esay("%s: signature is BAD: "
+ "wrong password, key, mode, or file is not signed", progname);
+ exitcode = 1;
+ }
+
+_shortmac: memset(macvrfy, 0, sizeof(macvrfy));
+ memset(macresult, 0, sizeof(macresult));
+ memset(tmpdata, 0, sizeof(tmpdata));
+ }
+
+ else if (do_mac == TFC_MAC_SIGN) {
+ if (ctr_mode < TFC_MODE_OCB) skein_final(macresult, &sk);
+ else skein(macresult, macbits, mackey, macresult, TF_FROM_BITS(macbits));
+
+ if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, tmpdata, macresult, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_XTS) tf_xts_encrypt(key, xtskey, ctr, tmpdata, macresult, TF_FROM_BITS(macbits), xtsblocks);
+ else if (ctr_mode == TFC_MODE_ECB) tf_ecb_encrypt(key, tmpdata, macresult, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_CBC) tf_cbc_encrypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits));
+ else if (ctr_mode == TFC_MODE_OCB) tf_ocb_encrypt(key, ctr, tmpdata, NULL, macresult, TF_FROM_BITS(macbits), xtsblocks);
+ memset(macresult, 0, sizeof(macresult));
+
+ if (!do_mac_file) {
+ pblk = tmpdata;
+ lio = lrem = TF_FROM_BITS(macbits);
+ ldone = 0;
+_macwagain: lio = write(dfd, pblk, lrem);
+ if (lio != NOSIZE) ldone += lio;
+ else xerror(NO, NO, NO, "%s", dstfname);
+ if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
+ if (lio < lrem) {
+ pblk += lio;
+ lrem -= lio;
+ goto _macwagain;
+ }
+ total_processed_dst += ldone;
+ delta_processed += ldone;
+ }
+ else {
+ int mfd;
+
+ if (!strcmp(do_mac_file, "-")) mfd = 1;
+ else mfd = open(do_mac_file, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
+ if (mfd == -1) xerror(YES, NO, NO, "%s", do_mac_file);
+ if (do_outfmt == TFC_OUTFMT_B64) {
+ memcpy(macvrfy, tmpdata, TF_FROM_BITS(macbits));
+ memset(tmpdata, 0, TFC_TMPSIZE);
+ memcpy(tmpdata, TFC_ASCII_TFC_MAC_FOURCC, TFC_ASCII_TFC_MAC_FOURCC_LEN);
+ base64_encode((char *)tmpdata+TFC_ASCII_TFC_MAC_FOURCC_LEN, (char *)macvrfy, TF_FROM_BITS(macbits));
+ lrem = strnlen((char *)tmpdata, sizeof(tmpdata));
+ if (lrem) {
+ tmpdata[lrem] = '\n';
+ lrem++;
+ }
+ lio = write(mfd, tmpdata, lrem);
+ }
+ else lio = write(mfd, tmpdata, TF_FROM_BITS(macbits));
+ if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
+ if (do_fsync && fsync(mfd) == -1) xerror(NO, NO, YES, "%s", do_mac_file);
+ xclose(mfd);
+ }
+
+ memset(macvrfy, 0, sizeof(macvrfy));
+ memset(macresult, 0, sizeof(macresult));
+ memset(tmpdata, 0, sizeof(tmpdata));
+ }
+
+_nomac:
+ if (verbose || status_timer || do_stop == TFC_STOP_FULL) print_crypt_status(0);
+
+ if (do_preserve_time) fcopy_matime(dfd, &s_stat);
+ xclose(sfd);
+ xclose(dfd);
+
+ xexit(exitcode);
+ return -1;
+}
--- /dev/null
+/*
+ * tfcrypt -- high security Threefish encryption tool.
+ *
+ * tfcrypt is copyrighted:
+ * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ *
+ * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#ifndef _TFCRYPT_H
+#define _TFCRYPT_H
+
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 700
+#endif
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+
+#ifndef _TFCRYPT_VERSION
+#error Version number may help you to identify missing functionality.
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <stdint.h>
+
+typedef void (*sighandler_t)(int);
+
+#include "base64.h"
+#include "getpasswd.h"
+#include "tfdef.h"
+#include "skein.h"
+#include "tfe.h"
+#include "tfprng.h"
+
+typedef short tfc_yesno;
+typedef TF_BYTE_TYPE tfc_byte;
+typedef unsigned long long tfc_fsize;
+typedef unsigned long long tfc_useconds;
+
+#ifndef TFC_NR_TURNS
+#define TFC_NR_TURNS 262144
+#endif
+
+#ifndef TFC_CTR_MODE
+#define TFC_CTR_MODE TFC_MODE_XTS
+#endif
+
+#ifndef TFC_BLKSIZE
+#define TFC_BLKSIZE 65536
+#endif
+
+#ifndef TFC_XTSBLOCKS
+#define TFC_XTSBLOCKS 32
+#endif
+
+#ifndef TFC_B64_WIDTH
+#define TFC_B64_WIDTH 76
+#endif
+#define TFC_B64_EWIDTH (TFC_B64_WIDTH - (TFC_B64_WIDTH / 4))
+#define TFC_B64_DWIDTH TFC_BLKSIZE
+
+#define NOSIZE ((size_t)-1)
+#define NOFSIZE ((tfc_fsize)-1)
+#define TFC_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+#define TFC_KEY_BITS (do_tfcrypt1 == YES ? TF_MAX_BITS : TF_NR_KEY_BITS)
+
+#define TFC_ASCII_TFC_MAC_FOURCC "%TF"
+#define TFC_ASCII_TFC_MAC_FOURCC_LEN (sizeof(TFC_ASCII_TFC_MAC_FOURCC)-1)
+
+#define TFC_U(x) ((unsigned)x)
+#define TFC_DTOUSECS(x) ((x) * 1000000.0)
+#define TFC_UTODSECS(x) ((x) / 1000000.0)
+
+#define TFC_DEFAULT_RANDSOURCE "/dev/urandom"
+#define TFC_STDIN_NAME "(stdin)"
+#define TFC_STDOUT_NAME "(stdout)"
+
+#define TFC_TMPSIZE (TF_BLOCK_SIZE * 4)
+
+int xmhexdump(int to, const void *data, size_t szdata, int hgroup, int hexstr, int newline);
+#define mhexdump(data, szdata, group, newline) xmhexdump(1, data, szdata, group, do_full_hexdump, newline)
+#define mehexdump(data, szdata, group, newline) xmhexdump(2, data, szdata, group, do_full_hexdump, newline)
+
+extern char *progname;
+extern int exitcode;
+extern size_t nr_turns;
+extern int ctr_mode;
+extern size_t macbits;
+extern tfc_byte key[TF_KEY_SIZE], ctr[TF_BLOCK_SIZE], xtskey[TF_KEY_SIZE], mackey[TF_FROM_BITS(TF_MAX_BITS)];
+extern struct skein sk;
+extern struct tfe_stream tfe;
+extern tfc_byte srcblk[TFC_BLKSIZE], dstblk[TFC_BLKSIZE], *pblk;
+extern tfc_byte macvrfy[SKEIN_DIGEST_SIZE], macresult[SKEIN_DIGEST_SIZE];
+extern tfc_byte tmpdata[TFC_TMPSIZE];
+extern char *randsource;
+extern tfc_fsize iseek_blocks, iseek, oseek, maxlen;
+extern tfc_fsize total_processed_src, total_processed_dst;
+extern tfc_fsize delta_processed;
+extern tfc_fsize genrandom_nr_bytes, genzero_nr_bytes;
+extern int sfd, kfd, dfd;
+extern struct stat s_stat;
+extern size_t blksize, xtsblocks;
+extern char pwdask[512], pwdagain[512];
+extern size_t lio, lrem, ldone, lblock;
+extern size_t maxkeylen, ctrsz;
+extern struct sigaction sigact;
+extern size_t sksum_turns;
+extern int do_edcrypt, do_stop, quiet, error_action;
+extern int counter_opt, mackey_opt, do_mac, do_outfmt, rawkey;
+extern int idx, write_flags;
+extern tfc_yesno catch_all_errors, password, overwrite_source, do_fsync, do_pad, do_tfcrypt1;
+extern tfc_yesno do_preserve_time, do_stats_in_gibs, do_statline_dynamic, do_less_stats;
+extern tfc_yesno no_repeat, do_full_hexdump, verbose, statline_was_shown;
+extern char *srcfname, *dstfname, *do_mac_file, *counter_file, *sksum_hashlist_file;
+extern char *genkeyf, *mackeyf, *tweakf;
+extern char *pw_prompt, *mac_pw_prompt;
+extern tfc_useconds status_timer, bench_timer;
+extern tfc_useconds current_time, delta_time;
+extern struct getpasswd_state getps;
+
+void xerror(tfc_yesno noexit, tfc_yesno noerrno, tfc_yesno nostats, const char *fmt, ...);
+void xexit(int status);
+void usage(void);
+
+void tfc_vfsay(FILE *where, tfc_yesno addnl, const char *fmt, va_list ap);
+void tfc_nfsay(FILE *where, const char *fmt, ...);
+void tfc_esay(const char *fmt, ...);
+void tfc_say(const char *fmt, ...);
+
+void tfc_printbase64(FILE *where, const void *p, size_t n, tfc_yesno nl);
+void tfc_data_to_words64(void *data, size_t szdata);
+tfc_fsize tfc_humanfsize(const char *s, char **stoi);
+const char *tfc_getscale(int scale);
+void tfc_describescale(tfc_fsize num, double *w, int *scale);
+size_t blk_len_adj(tfc_fsize filelen, tfc_fsize read_already, size_t blklen);
+tfc_yesno xor_shrink(void *dst, size_t szdst, const void *src, size_t szsrc);
+tfc_yesno str_empty(const char *str);
+void xclose(int fd);
+const char *tfc_modename(int mode);
+void tfc_getcurtime(tfc_useconds *tx);
+tfc_fsize tfc_fdsize(int fd);
+tfc_fsize tfc_fnamesize(char *fname, tfc_yesno noexit);
+tfc_fsize tfc_modifysize(tfc_fsize szmodify, const char *szspec);
+void fcopy_matime(int fd, const struct stat *st);
+tfc_yesno xfgets(char *s, size_t n, FILE *f);
+tfc_yesno isbase64(const char *s);
+void hex2bin(void *d, const char *s);
+void tfc_finirandom(void);
+void tfc_getrandom(void *buf, size_t sz);
+void exit_sigterm(int signal);
+void print_crypt_status(int signal);
+void change_status_width(int signal);
+void change_status_timer(int signal);
+void setup_next_alarm(tfc_useconds useconds);
+void skein(void *hash, size_t bits, const void *key, const void *data, size_t szdata);
+void tf_key_tweak_compat(void *key);
+tfc_yesno skeinfd(void *hash, size_t bits, const void *key, int fd, tfc_fsize readto);
+
+void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes);
+void do_edbase64(char **fargv);
+void do_sksum(char *spec, char **fargv);
+void do_benchmark(tfc_useconds useconds, double dseconds);
+
+enum { NO, YES };
+
+enum { TFC_ERRACT_EXIT, TFC_ERRACT_CONT, TFC_ERRACT_SYNC };
+enum { TFC_STOP_BEGAN = 1, TFC_STOP_FULL };
+enum { TFC_DO_PLAIN, TFC_DO_ENCRYPT, TFC_DO_DECRYPT };
+enum { TFC_MAC_DROP = -1, TFC_MAC_SIGN = 1, TFC_MAC_VRFY, TFC_MAC_JUST_VRFY };
+enum { TFC_MACKEY_RAWKEY = 1, TFC_MACKEY_PASSWORD, TFC_MACKEY_FILE };
+enum { TFC_RAWKEY_KEYFILE = 1, TFC_RAWKEY_ASKSTR, TFC_RAWKEY_ASKHEX };
+enum { TFC_OUTFMT_HEX = 1, TFC_OUTFMT_B64, TFC_OUTFMT_RAW };
+enum {
+ TFC_MODE_SKSUM = -2, TFC_MODE_PLAIN = -1, TFC_MODE_CTR = 1,
+ TFC_MODE_STREAM, TFC_MODE_XTS, TFC_MODE_ECB, TFC_MODE_CBC, TFC_MODE_OCB
+};
+enum { TFC_CTR_SHOW = 1, TFC_CTR_HEAD, TFC_CTR_RAND };
+
+#endif
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+
+void tf_ctr_crypt(const void *key, void *ctr, void *out, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uctr = ctr;
+ const TF_UNIT_TYPE *ukey = key;
+ size_t sl = sz, i;
+
+ if (sl >= TF_BLOCK_SIZE) {
+ do {
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ tf_encrypt_rawblk(y, uctr, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sl) {
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ tf_encrypt_rawblk(y, uctr, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+ }
+
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+
+void tf_ctr_set(void *ctr, const void *sctr, size_t sctrsz)
+{
+ TF_UNIT_TYPE usctr[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uctr = ctr;
+
+ memset(usctr, 0, TF_BLOCK_SIZE);
+ memcpy(usctr, sctr, sctrsz > TF_BLOCK_SIZE ? TF_BLOCK_SIZE : sctrsz);
+ ctr_add(uctr, usctr, TF_NR_BLOCK_UNITS);
+ data_to_words(uctr, TF_BLOCK_SIZE);
+ memset(usctr, 0, TF_BLOCK_SIZE);
+}
--- /dev/null
+#include "tfdef.h"
+#include "tfcore.h"
+
+#if defined(TF_256BITS)
+
+#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6) \
+ do { \
+ BD_MIX(Z, Y, TFS_BS06); BD_MIX(X, T, TFS_BS05); \
+ BD_MIX(Z, T, TFS_BS04); BD_MIX(X, Y, TFS_BS03); \
+ BD_MIX(Z, Y, TFS_BS02); BD_MIX(X, T, TFS_BS01); \
+ \
+ KD_MIX(T, Z, k4 + x, k5 + k6, TFS_KS02); \
+ KD_MIX(Y, X, k1 + k2, k3, TFS_KS01); \
+ } while (0)
+
+#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6) \
+ do { \
+ BD_MIX(Z, Y, TFS_BS12); BD_MIX(X, T, TFS_BS11); \
+ BD_MIX(Z, T, TFS_BS10); BD_MIX(X, Y, TFS_BS09); \
+ BD_MIX(Z, Y, TFS_BS08); BD_MIX(X, T, TFS_BS07); \
+ \
+ KD_MIX(T, Z, k4 + x, k5 + k6, TFS_KS04); \
+ KD_MIX(Y, X, k1 + k2, k3, TFS_KS03); \
+ } while (0)
+
+void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K)
+{
+ TF_UNIT_TYPE X, Y, Z, T;
+ TF_UNIT_TYPE K0, K1, K2, K3;
+ TF_UNIT_TYPE K4, T0, T1, T2;
+
+ X = I[0]; Y = I[1]; Z = I[2]; T = I[3];
+
+ K0 = K[0]; K1 = K[1]; K2 = K[2]; K3 = K[3];
+ K4 = K[4]; T0 = K[5]; T1 = K[6]; T2 = K[7];
+
+ X -= K3; Y -= K4 + T0; Z -= K0 + T1; T -= K1 + 18;
+
+ PROCESS_BLOCKN(17,K3,T2,K2,K0,K4,T0);
+ PROCESS_BLOCKP(16,K2,T1,K1,K4,K3,T2);
+
+ PROCESS_BLOCKN(15,K1,T0,K0,K3,K2,T1);
+ PROCESS_BLOCKP(14,K0,T2,K4,K2,K1,T0);
+ PROCESS_BLOCKN(13,K4,T1,K3,K1,K0,T2);
+ PROCESS_BLOCKP(12,K3,T0,K2,K0,K4,T1);
+
+ PROCESS_BLOCKN(11,K2,T2,K1,K4,K3,T0);
+ PROCESS_BLOCKP(10,K1,T1,K0,K3,K2,T2);
+ PROCESS_BLOCKN( 9,K0,T0,K4,K2,K1,T1);
+ PROCESS_BLOCKP( 8,K4,T2,K3,K1,K0,T0);
+
+ PROCESS_BLOCKN( 7,K3,T1,K2,K0,K4,T2);
+ PROCESS_BLOCKP( 6,K2,T0,K1,K4,K3,T1);
+ PROCESS_BLOCKN( 5,K1,T2,K0,K3,K2,T0);
+ PROCESS_BLOCKP( 4,K0,T1,K4,K2,K1,T2);
+
+ PROCESS_BLOCKN( 3,K4,T0,K3,K1,K0,T1);
+ PROCESS_BLOCKP( 2,K3,T2,K2,K0,K4,T0);
+ PROCESS_BLOCKN( 1,K2,T1,K1,K4,K3,T2);
+ PROCESS_BLOCKP( 0,K1,T0,K0,K3,K2,T1);
+
+ O[0] = X; O[1] = Y; O[2] = Z; O[3] = T;
+}
+
+#elif defined(TF_512BITS)
+
+#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \
+ do { \
+ BD_MIX(E, T, TFS_BS12); BD_MIX(Z, W, TFS_BS11); \
+ BD_MIX(X, N, TFS_BS10); BD_MIX(V, Y, TFS_BS09); \
+ BD_MIX(Z, N, TFS_BS08); BD_MIX(X, W, TFS_BS07); \
+ BD_MIX(V, T, TFS_BS06); BD_MIX(E, Y, TFS_BS05); \
+ BD_MIX(X, T, TFS_BS04); BD_MIX(V, W, TFS_BS03); \
+ BD_MIX(E, N, TFS_BS02); BD_MIX(Z, Y, TFS_BS01); \
+ \
+ KD_MIX(N, V, k8 + x, k9 + k10, TFS_KS04); \
+ KD_MIX(W, E, k5 + k6, k7, TFS_KS03); \
+ KD_MIX(T, Z, k3, k4, TFS_KS02); KD_MIX(Y, X, k1, k2, TFS_KS01); \
+ } while (0)
+
+#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \
+ do { \
+ BD_MIX(E, T, TFS_BS24); BD_MIX(Z, W, TFS_BS23); \
+ BD_MIX(X, N, TFS_BS22); BD_MIX(V, Y, TFS_BS21); \
+ BD_MIX(Z, N, TFS_BS20); BD_MIX(X, W, TFS_BS19); \
+ BD_MIX(V, T, TFS_BS18); BD_MIX(E, Y, TFS_BS17); \
+ BD_MIX(X, T, TFS_BS16); BD_MIX(V, W, TFS_BS15); \
+ BD_MIX(E, N, TFS_BS14); BD_MIX(Z, Y, TFS_BS13); \
+ \
+ KD_MIX(N, V, k8 + x, k9 + k10, TFS_KS08); \
+ KD_MIX(W, E, k5 + k6, k7, TFS_KS07); \
+ KD_MIX(T, Z, k3, k4, TFS_KS06); KD_MIX(Y, X, k1, k2, TFS_KS05); \
+ } while (0)
+
+void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K)
+{
+ TF_UNIT_TYPE X, Y, Z, T;
+ TF_UNIT_TYPE E, W, V, N;
+ TF_UNIT_TYPE K0, K1, K2, K3;
+ TF_UNIT_TYPE K4, K5, K6, K7;
+ TF_UNIT_TYPE K8, T0, T1, T2;
+
+ X = I[0]; Y = I[1]; Z = I[2]; T = I[3];
+ E = I[4]; W = I[5]; V = I[6]; N = I[7];
+
+ K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3];
+ K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7];
+ K8 = K[ 8]; T0 = K[ 9]; T1 = K[10]; T2 = K[11];
+
+ X -= K0; Y -= K1; Z -= K2; T -= K3;
+ E -= K4; W -= K5 + T0; V -= K6 + T1; N -= K7 + 18;
+
+ PROCESS_BLOCKN(17,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0);
+ PROCESS_BLOCKP(16,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2);
+
+ PROCESS_BLOCKN(15,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1);
+ PROCESS_BLOCKP(14,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0);
+ PROCESS_BLOCKN(13,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2);
+ PROCESS_BLOCKP(12,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1);
+
+ PROCESS_BLOCKN(11,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0);
+ PROCESS_BLOCKP(10,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2);
+ PROCESS_BLOCKN( 9,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1);
+ PROCESS_BLOCKP( 8,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0);
+
+ PROCESS_BLOCKN( 7,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2);
+ PROCESS_BLOCKP( 6,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1);
+ PROCESS_BLOCKN( 5,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0);
+ PROCESS_BLOCKP( 4,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2);
+
+ PROCESS_BLOCKN( 3,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1);
+ PROCESS_BLOCKP( 2,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0);
+ PROCESS_BLOCKN( 1,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2);
+ PROCESS_BLOCKP( 0,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1);
+
+ O[0] = X; O[1] = Y; O[2] = Z; O[3] = T;
+ O[4] = E; O[5] = W; O[6] = V; O[7] = N;
+}
+
+#elif defined(TF_1024BITS)
+
+#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\
+ do { \
+ BD_MIX(A, N, TFS_BS24); BD_MIX(M, T, TFS_BS23); \
+ BD_MIX(P, W, TFS_BS22); BD_MIX(H, Y, TFS_BS21); \
+ BD_MIX(E, U, TFS_BS20); BD_MIX(V, B, TFS_BS19); \
+ BD_MIX(Z, Q, TFS_BS18); BD_MIX(X, L, TFS_BS17); \
+ BD_MIX(M, U, TFS_BS16); BD_MIX(P, Q, TFS_BS15); \
+ BD_MIX(H, B, TFS_BS14); BD_MIX(A, L, TFS_BS13); \
+ BD_MIX(V, Y, TFS_BS12); BD_MIX(E, T, TFS_BS11); \
+ BD_MIX(Z, W, TFS_BS10); BD_MIX(X, N, TFS_BS09); \
+ BD_MIX(P, Y, TFS_BS08); BD_MIX(H, W, TFS_BS07); \
+ BD_MIX(A, T, TFS_BS06); BD_MIX(M, N, TFS_BS05); \
+ BD_MIX(E, L, TFS_BS04); BD_MIX(V, Q, TFS_BS03); \
+ BD_MIX(Z, B, TFS_BS02); BD_MIX(X, U, TFS_BS01); \
+ \
+ KD_MIX(L, H, k16 + x, k17 + k18, TFS_KS08); \
+ KD_MIX(B, A, k13 + k14, k15, TFS_KS07); \
+ KD_MIX(Q, M, k11, k12, TFS_KS06); KD_MIX(U, P, k9, k10, TFS_KS05); \
+ KD_MIX(N, V, k7, k8, TFS_KS04); KD_MIX(W, E, k5, k6, TFS_KS03); \
+ KD_MIX(T, Z, k3, k4, TFS_KS02); KD_MIX(Y, X, k1, k2, TFS_KS01); \
+ } while (0)
+
+#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\
+ do { \
+ BD_MIX(A, N, TFS_BS48); BD_MIX(M, T, TFS_BS47); \
+ BD_MIX(P, W, TFS_BS46); BD_MIX(H, Y, TFS_BS45); \
+ BD_MIX(E, U, TFS_BS44); BD_MIX(V, B, TFS_BS43); \
+ BD_MIX(Z, Q, TFS_BS42); BD_MIX(X, L, TFS_BS41); \
+ BD_MIX(M, U, TFS_BS40); BD_MIX(P, Q, TFS_BS39); \
+ BD_MIX(H, B, TFS_BS38); BD_MIX(A, L, TFS_BS37); \
+ BD_MIX(V, Y, TFS_BS36); BD_MIX(E, T, TFS_BS35); \
+ BD_MIX(Z, W, TFS_BS34); BD_MIX(X, N, TFS_BS33); \
+ BD_MIX(P, Y, TFS_BS32); BD_MIX(H, W, TFS_BS31); \
+ BD_MIX(A, T, TFS_BS30); BD_MIX(M, N, TFS_BS29); \
+ BD_MIX(E, L, TFS_BS28); BD_MIX(V, Q, TFS_BS27); \
+ BD_MIX(Z, B, TFS_BS26); BD_MIX(X, U, TFS_BS25); \
+ \
+ KD_MIX(L, H, k16 + x, k17 + k18, TFS_KS16); \
+ KD_MIX(B, A, k13 + k14, k15, TFS_KS15); \
+ KD_MIX(Q, M, k11, k12, TFS_KS14); KD_MIX(U, P, k9, k10, TFS_KS13); \
+ KD_MIX(N, V, k7, k8, TFS_KS12); KD_MIX(W, E, k5, k6, TFS_KS11); \
+ KD_MIX(T, Z, k3, k4, TFS_KS10); KD_MIX(Y, X, k1, k2, TFS_KS09); \
+ } while (0)
+
+void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K)
+{
+ TF_UNIT_TYPE X, Y, Z, T;
+ TF_UNIT_TYPE E, W, V, N;
+ TF_UNIT_TYPE P, U, M, Q;
+ TF_UNIT_TYPE A, B, H, L;
+ TF_UNIT_TYPE K0, K1, K2, K3;
+ TF_UNIT_TYPE K4, K5, K6, K7;
+ TF_UNIT_TYPE K8, K9, K10, K11;
+ TF_UNIT_TYPE K12, K13, K14, K15;
+ TF_UNIT_TYPE K16, T0, T1, T2;
+
+ X = I[ 0]; Y = I[ 1]; Z = I[ 2]; T = I[ 3];
+ E = I[ 4]; W = I[ 5]; V = I[ 6]; N = I[ 7];
+ P = I[ 8]; U = I[ 9]; M = I[10]; Q = I[11];
+ A = I[12]; B = I[13]; H = I[14]; L = I[15];
+
+ K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3];
+ K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7];
+ K8 = K[ 8]; K9 = K[ 9]; K10 = K[10]; K11 = K[11];
+ K12 = K[12]; K13 = K[13]; K14 = K[14]; K15 = K[15];
+ K16 = K[16]; T0 = K[17]; T1 = K[18]; T2 = K[19];
+
+ X -= K3; Y -= K4; Z -= K5; T -= K6;
+ E -= K7; W -= K8; V -= K9; N -= K10;
+ P -= K11; U -= K12; M -= K13; Q -= K14;
+ A -= K15; B -= K16 + T2; H -= K0 + T0; L -= K1 + 20;
+
+ PROCESS_BLOCKN(19, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T1,K14, K0,K16, T2);
+ PROCESS_BLOCKP(18, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T0,K13,K16,K15, T1);
+ PROCESS_BLOCKN(17, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T2,K12,K15,K14, T0);
+ PROCESS_BLOCKP(16, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12, T1,K11,K14,K13, T2);
+
+ PROCESS_BLOCKN(15,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11, T0,K10,K13,K12, T1);
+ PROCESS_BLOCKP(14,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, T2, K9,K12,K11, T0);
+ PROCESS_BLOCKN(13,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, T1, K8,K11,K10, T2);
+ PROCESS_BLOCKP(12,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, T0, K7,K10, K9, T1);
+
+ PROCESS_BLOCKN(11,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, T2, K6, K9, K8, T0);
+ PROCESS_BLOCKP(10,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, T1, K5, K8, K7, T2);
+ PROCESS_BLOCKN( 9,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, T0, K4, K7, K6, T1);
+ PROCESS_BLOCKP( 8, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, T2, K3, K6, K5, T0);
+
+ PROCESS_BLOCKN( 7, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, T1, K2, K5, K4, T2);
+ PROCESS_BLOCKP( 6, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, T0, K1, K4, K3, T1);
+ PROCESS_BLOCKN( 5, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, T2, K0, K3, K2, T0);
+ PROCESS_BLOCKP( 4, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0, T1,K16, K2, K1, T2);
+
+ PROCESS_BLOCKN( 3, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16, T0,K15, K1, K0, T1);
+ PROCESS_BLOCKP( 2, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T2,K14, K0,K16, T0);
+ PROCESS_BLOCKN( 1, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T1,K13,K16,K15, T2);
+ PROCESS_BLOCKP( 0, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T0,K12,K15,K14, T1);
+
+ O[0] = X; O[1] = Y; O[2] = Z; O[3] = T;
+ O[4] = E; O[5] = W; O[6] = V; O[7] = N;
+ O[8] = P; O[9] = U; O[10] = M; O[11] = Q;
+ O[12] = A; O[13] = B; O[14] = H; O[15] = L;
+}
+
+#endif
--- /dev/null
+#ifndef _THREEFISH_CIPHER_DEFINITIONS_HEADER
+#define _THREEFISH_CIPHER_DEFINITIONS_HEADER
+
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE
+#endif
+
+/* config block */
+/* #define TF_256BITS */
+/* #define TF_512BITS */
+#define TF_1024BITS
+/* #define TF_NO_ENDIAN */
+/* #define TF_BIG_ENDIAN */
+
+#include <stddef.h>
+#include <stdint.h>
+#ifndef TF_NO_ENDIAN
+#include <sys/param.h>
+#else
+#undef TF_BIG_ENDIAN
+#endif
+
+#define TF_UNIT_TYPE uint64_t
+
+#ifdef TF_BIG_ENDIAN
+#define TF_SWAP_FUNC htobe64
+#else
+#define TF_SWAP_FUNC htole64
+#endif
+
+#if defined(TF_256BITS)
+#define TF_NR_BLOCK_BITS 256
+#define TF_NR_KEY_BITS 512
+#define TF_NR_BLOCK_UNITS 4
+#define TF_NR_KEY_UNITS 8
+#define IRR_POLY_CONST 0x425
+#elif defined(TF_512BITS)
+#define TF_NR_BLOCK_BITS 512
+#define TF_NR_KEY_BITS 768
+#define TF_NR_BLOCK_UNITS 8
+#define TF_NR_KEY_UNITS 12
+#define IRR_POLY_CONST 0x125
+#elif defined(TF_1024BITS)
+#define TF_NR_BLOCK_BITS 1024
+#define TF_NR_KEY_BITS 1280
+#define TF_NR_BLOCK_UNITS 16
+#define TF_NR_KEY_UNITS 20
+#define IRR_POLY_CONST 0x80043
+#else
+#error Please edit tfdef.h include file and select at least one cipher!
+#endif
+
+#define TF_BYTE_TYPE uint8_t
+#define TF_SIZE_UNIT (sizeof(TF_UNIT_TYPE))
+#define TF_BLOCK_SIZE (TF_SIZE_UNIT * TF_NR_BLOCK_UNITS)
+#define TF_KEY_SIZE (TF_SIZE_UNIT * TF_NR_KEY_UNITS)
+
+#define TF_TWEAK_WORD1 (TF_NR_KEY_UNITS-3)
+#define TF_TWEAK_WORD2 (TF_NR_KEY_UNITS-2)
+#define TF_TWEAK_WORD3 (TF_NR_KEY_UNITS-1)
+
+#define TF_TO_BITS(x) ((x) * 8)
+#define TF_FROM_BITS(x) ((x) / 8)
+#define TF_MAX_BITS TF_NR_BLOCK_BITS
+#define TF_UNIT_BITS (TF_SIZE_UNIT * 8)
+
+#define TF_TO_BLOCKS(x) ((x) / TF_BLOCK_SIZE)
+#define TF_FROM_BLOCKS(x) ((x) * TF_BLOCK_SIZE)
+#define TF_BLOCKS_TO_BYTES(x) TF_FROM_BLOCKS(x)
+#define TF_BLOCKS_FROM_BYTES(x) TF_TO_BLOCKS(x)
+
+static inline void data_to_words(void *p, size_t l)
+{
+#ifndef TF_NO_ENDIAN
+ size_t idx;
+ TF_UNIT_TYPE *P = p;
+ TF_UNIT_TYPE t;
+
+ for (idx = 0; idx < (l/sizeof(TF_UNIT_TYPE)); idx++) {
+ t = TF_SWAP_FUNC(P[idx]);
+ P[idx] = t;
+ }
+#endif
+}
+
+static inline void ctr_inc(TF_UNIT_TYPE *x, size_t l)
+{
+ size_t i;
+
+ for (i = 0; i < l; i++) {
+ x[i] = ((x[i] + (TF_UNIT_TYPE)1) & ((TF_UNIT_TYPE)~0));
+ if (x[i]) break;
+ }
+}
+
+static inline void ctr_add(TF_UNIT_TYPE *x, const TF_UNIT_TYPE *y, size_t l)
+{
+ size_t i, f = 0;
+ TF_UNIT_TYPE t;
+
+ for (i = 0; i < l; i++) {
+ t = x[i];
+ x[i] += y[i]; x[i] &= ((TF_UNIT_TYPE)~0);
+ if (x[i] < t) {
+_again: f++;
+ t = x[f-i];
+ x[f-i]++;
+ if (x[f-i] < t) goto _again;
+ else f = 0;
+ }
+ }
+}
+
+struct tfe_stream;
+
+#define tf_convkey(k) do { data_to_words(k, TF_KEY_SIZE); } while (0)
+
+void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K);
+void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K);
+
+void tf_encrypt_block(const void *key, void *out, const void *in);
+void tf_decrypt_block(const void *key, void *out, const void *in);
+
+void tf_ctr_set(void *ctr, const void *sctr, size_t sctrsz);
+void tf_ctr_crypt(const void *key, void *ctr, void *out, const void *in, size_t sz);
+void tf_stream_crypt(struct tfe_stream *tfe, void *out, const void *in, size_t sz);
+void tf_ecb_encrypt(const void *key, void *out, const void *in, size_t sz);
+void tf_ecb_decrypt(const void *key, void *out, const void *in, size_t sz);
+void tf_cbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz);
+void tf_cbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz);
+void tf_xts_encrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi);
+void tf_xts_decrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi);
+void tf_ocb_encrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz, size_t bpi);
+void tf_ocb_decrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz, size_t bpi);
+
+#endif
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+#include "tfe.h"
+
+void tfe_init_iv(struct tfe_stream *tfe, const void *key, const void *iv)
+{
+ memset(tfe, 0, sizeof(struct tfe_stream));
+ memcpy(tfe->key, key, TF_KEY_SIZE);
+ data_to_words(tfe->key, TF_KEY_SIZE);
+ if (iv) {
+ memcpy(tfe->iv, iv, TF_BLOCK_SIZE);
+ data_to_words(tfe->iv, TF_BLOCK_SIZE);
+ }
+ tfe->carry_bytes = 0;
+}
+
+void tfe_init(struct tfe_stream *tfe, const void *key)
+{
+ tfe_init_iv(tfe, key, NULL);
+}
+
+void tfe_emit(void *dst, size_t szdst, struct tfe_stream *tfe)
+{
+ TF_BYTE_TYPE *udst = dst;
+ size_t sz = szdst;
+
+ if (!dst && szdst == 0) {
+ memset(tfe, 0, sizeof(struct tfe_stream));
+ return;
+ }
+
+ if (tfe->carry_bytes > 0) {
+ if (tfe->carry_bytes > szdst) {
+ memcpy(udst, tfe->carry_block, szdst);
+ memmove(tfe->carry_block, tfe->carry_block+szdst, tfe->carry_bytes-szdst);
+ tfe->carry_bytes -= szdst;
+ return;
+ }
+
+ memcpy(udst, tfe->carry_block, tfe->carry_bytes);
+ udst += tfe->carry_bytes;
+ sz -= tfe->carry_bytes;
+ tfe->carry_bytes = 0;
+ }
+
+ if (sz >= TF_BLOCK_SIZE) {
+ do {
+ tf_encrypt_rawblk(tfe->iv, tfe->iv, tfe->key);
+ memcpy(udst, tfe->iv, TF_BLOCK_SIZE);
+ data_to_words(udst, TF_BLOCK_SIZE);
+ udst += TF_BLOCK_SIZE;
+ } while ((sz -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sz) {
+ tf_encrypt_rawblk(tfe->iv, tfe->iv, tfe->key);
+ memcpy(udst, tfe->iv, sz);
+ data_to_words(udst, TF_BLOCK_SIZE);
+ udst = (TF_BYTE_TYPE *)tfe->iv;
+ tfe->carry_bytes = TF_BLOCK_SIZE-sz;
+ memcpy(tfe->carry_block, udst+sz, tfe->carry_bytes);
+ }
+}
--- /dev/null
+#ifndef _TF_STREAM_CIPHER_DEFS
+#define _TF_STREAM_CIPHER_DEFS
+
+#include "tfdef.h"
+
+struct tfe_stream {
+ TF_UNIT_TYPE key[TF_NR_KEY_UNITS];
+ TF_UNIT_TYPE iv[TF_NR_BLOCK_UNITS];
+ TF_BYTE_TYPE carry_block[TF_BLOCK_SIZE];
+ size_t carry_bytes;
+};
+
+void tfe_init(struct tfe_stream *tfe, const void *key);
+void tfe_init_iv(struct tfe_stream *tfe, const void *key, const void *iv);
+void tfe_emit(void *dst, size_t szdst, struct tfe_stream *tfe);
+
+#endif
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+
+void tf_ecb_encrypt(const void *key, void *out, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ const TF_UNIT_TYPE *ukey = key;
+ size_t sl = sz, i;
+
+ if (sl >= TF_BLOCK_SIZE) {
+ do {
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ tf_encrypt_rawblk(y, x, ukey);
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sl) {
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ memset(y, 0, TF_BLOCK_SIZE);
+ tf_encrypt_rawblk(y, y, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+ }
+
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
+
+void tf_ecb_decrypt(const void *key, void *out, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ const TF_UNIT_TYPE *ukey = key;
+ size_t sl = sz, i;
+
+ if (sl >= TF_BLOCK_SIZE) {
+ do {
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ tf_decrypt_rawblk(y, x, ukey);
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sl) {
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ memset(y, 0, TF_BLOCK_SIZE);
+ tf_decrypt_rawblk(y, y, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+ }
+
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
--- /dev/null
+#include "tfdef.h"
+#include "tfcore.h"
+
+#if defined(TF_256BITS)
+
+#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6) \
+ do { \
+ KE_MIX(Y, X, k1 + k2, k3, TFS_KS01); \
+ KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS02); \
+ \
+ BE_MIX(X, T, TFS_BS01); BE_MIX(Z, Y, TFS_BS02); \
+ BE_MIX(X, Y, TFS_BS03); BE_MIX(Z, T, TFS_BS04); \
+ BE_MIX(X, T, TFS_BS05); BE_MIX(Z, Y, TFS_BS06); \
+ } while (0)
+
+#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6) \
+ do { \
+ KE_MIX(Y, X, k1 + k2, k3, TFS_KS03); \
+ KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS04); \
+ \
+ BE_MIX(X, T, TFS_BS07); BE_MIX(Z, Y, TFS_BS08); \
+ BE_MIX(X, Y, TFS_BS09); BE_MIX(Z, T, TFS_BS10); \
+ BE_MIX(X, T, TFS_BS11); BE_MIX(Z, Y, TFS_BS12); \
+ } while (0)
+
+void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K)
+{
+ TF_UNIT_TYPE X, Y, Z, T;
+ TF_UNIT_TYPE K0, K1, K2, K3;
+ TF_UNIT_TYPE K4, T0, T1, T2;
+
+ X = I[0]; Y = I[1]; Z = I[2]; T = I[3];
+
+ K0 = K[0]; K1 = K[1]; K2 = K[2]; K3 = K[3];
+ K4 = K[4]; T0 = K[5]; T1 = K[6]; T2 = K[7];
+
+ PROCESS_BLOCKP( 0,K1,T0,K0,K3,K2,T1);
+ PROCESS_BLOCKN( 1,K2,T1,K1,K4,K3,T2);
+ PROCESS_BLOCKP( 2,K3,T2,K2,K0,K4,T0);
+ PROCESS_BLOCKN( 3,K4,T0,K3,K1,K0,T1);
+
+ PROCESS_BLOCKP( 4,K0,T1,K4,K2,K1,T2);
+ PROCESS_BLOCKN( 5,K1,T2,K0,K3,K2,T0);
+ PROCESS_BLOCKP( 6,K2,T0,K1,K4,K3,T1);
+ PROCESS_BLOCKN( 7,K3,T1,K2,K0,K4,T2);
+
+ PROCESS_BLOCKP( 8,K4,T2,K3,K1,K0,T0);
+ PROCESS_BLOCKN( 9,K0,T0,K4,K2,K1,T1);
+ PROCESS_BLOCKP(10,K1,T1,K0,K3,K2,T2);
+ PROCESS_BLOCKN(11,K2,T2,K1,K4,K3,T0);
+
+ PROCESS_BLOCKP(12,K3,T0,K2,K0,K4,T1);
+ PROCESS_BLOCKN(13,K4,T1,K3,K1,K0,T2);
+ PROCESS_BLOCKP(14,K0,T2,K4,K2,K1,T0);
+ PROCESS_BLOCKN(15,K1,T0,K0,K3,K2,T1);
+
+ PROCESS_BLOCKP(16,K2,T1,K1,K4,K3,T2);
+ PROCESS_BLOCKN(17,K3,T2,K2,K0,K4,T0);
+
+ O[0] = X + K3; O[1] = Y + K4 + T0; O[2] = Z + K0 + T1; O[3] = T + K1 + 18;
+}
+
+#elif defined(TF_512BITS)
+
+#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \
+ do { \
+ KE_MIX(Y, X, k1, k2, TFS_KS01); KE_MIX(T, Z, k3, k4, TFS_KS02); \
+ KE_MIX(W, E, k5 + k6, k7, TFS_KS03); \
+ KE_MIX(N, V, k8 + x, k9 + k10, TFS_KS04); \
+ \
+ BE_MIX(Z, Y, TFS_BS01); BE_MIX(E, N, TFS_BS02); \
+ BE_MIX(V, W, TFS_BS03); BE_MIX(X, T, TFS_BS04); \
+ BE_MIX(E, Y, TFS_BS05); BE_MIX(V, T, TFS_BS06); \
+ BE_MIX(X, W, TFS_BS07); BE_MIX(Z, N, TFS_BS08); \
+ BE_MIX(V, Y, TFS_BS09); BE_MIX(X, N, TFS_BS10); \
+ BE_MIX(Z, W, TFS_BS11); BE_MIX(E, T, TFS_BS12); \
+ } while (0)
+
+#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \
+ do { \
+ KE_MIX(Y, X, k1, k2, TFS_KS05); KE_MIX(T, Z, k3, k4, TFS_KS06); \
+ KE_MIX(W, E, k5 + k6, k7, TFS_KS07); \
+ KE_MIX(N, V, k8 + x, k9 + k10, TFS_KS08); \
+ \
+ BE_MIX(Z, Y, TFS_BS13); BE_MIX(E, N, TFS_BS14); \
+ BE_MIX(V, W, TFS_BS15); BE_MIX(X, T, TFS_BS16); \
+ BE_MIX(E, Y, TFS_BS17); BE_MIX(V, T, TFS_BS18); \
+ BE_MIX(X, W, TFS_BS19); BE_MIX(Z, N, TFS_BS20); \
+ BE_MIX(V, Y, TFS_BS21); BE_MIX(X, N, TFS_BS22); \
+ BE_MIX(Z, W, TFS_BS23); BE_MIX(E, T, TFS_BS24); \
+ } while (0)
+
+void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K)
+{
+ TF_UNIT_TYPE X, Y, Z, T;
+ TF_UNIT_TYPE E, W, V, N;
+ TF_UNIT_TYPE K0, K1, K2, K3;
+ TF_UNIT_TYPE K4, K5, K6, K7;
+ TF_UNIT_TYPE K8, T0, T1, T2;
+
+ X = I[0]; Y = I[1]; Z = I[2]; T = I[3];
+ E = I[4]; W = I[5]; V = I[6]; N = I[7];
+
+ K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3];
+ K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7];
+ K8 = K[ 8]; T0 = K[ 9]; T1 = K[10]; T2 = K[11];
+
+ PROCESS_BLOCKP( 0,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1);
+ PROCESS_BLOCKN( 1,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2);
+ PROCESS_BLOCKP( 2,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0);
+ PROCESS_BLOCKN( 3,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1);
+
+ PROCESS_BLOCKP( 4,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2);
+ PROCESS_BLOCKN( 5,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0);
+ PROCESS_BLOCKP( 6,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1);
+ PROCESS_BLOCKN( 7,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2);
+
+ PROCESS_BLOCKP( 8,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0);
+ PROCESS_BLOCKN( 9,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1);
+ PROCESS_BLOCKP(10,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2);
+ PROCESS_BLOCKN(11,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0);
+
+ PROCESS_BLOCKP(12,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1);
+ PROCESS_BLOCKN(13,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2);
+ PROCESS_BLOCKP(14,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0);
+ PROCESS_BLOCKN(15,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1);
+
+ PROCESS_BLOCKP(16,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2);
+ PROCESS_BLOCKN(17,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0);
+
+ O[0] = X + K0; O[1] = Y + K1; O[2] = Z + K2; O[3] = T + K3;
+ O[4] = E + K4; O[5] = W + K5 + T0; O[6] = V + K6 + T1; O[7] = N + K7 + 18;
+}
+
+#elif defined(TF_1024BITS)
+
+#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\
+ do { \
+ KE_MIX(Y, X, k1, k2, TFS_KS01); KE_MIX(T, Z, k3, k4, TFS_KS02); \
+ KE_MIX(W, E, k5, k6, TFS_KS03); KE_MIX(N, V, k7, k8, TFS_KS04); \
+ KE_MIX(U, P, k9, k10, TFS_KS05); KE_MIX(Q, M, k11, k12, TFS_KS06); \
+ KE_MIX(B, A, k13 + k14, k15, TFS_KS07); \
+ KE_MIX(L, H, k16 + x, k17 + k18, TFS_KS08); \
+ \
+ BE_MIX(X, U, TFS_BS01); BE_MIX(Z, B, TFS_BS02); \
+ BE_MIX(V, Q, TFS_BS03); BE_MIX(E, L, TFS_BS04); \
+ BE_MIX(M, N, TFS_BS05); BE_MIX(A, T, TFS_BS06); \
+ BE_MIX(H, W, TFS_BS07); BE_MIX(P, Y, TFS_BS08); \
+ BE_MIX(X, N, TFS_BS09); BE_MIX(Z, W, TFS_BS10); \
+ BE_MIX(E, T, TFS_BS11); BE_MIX(V, Y, TFS_BS12); \
+ BE_MIX(A, L, TFS_BS13); BE_MIX(H, B, TFS_BS14); \
+ BE_MIX(P, Q, TFS_BS15); BE_MIX(M, U, TFS_BS16); \
+ BE_MIX(X, L, TFS_BS17); BE_MIX(Z, Q, TFS_BS18); \
+ BE_MIX(V, B, TFS_BS19); BE_MIX(E, U, TFS_BS20); \
+ BE_MIX(H, Y, TFS_BS21); BE_MIX(P, W, TFS_BS22); \
+ BE_MIX(M, T, TFS_BS23); BE_MIX(A, N, TFS_BS24); \
+ } while (0)
+
+#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\
+ do { \
+ KE_MIX(Y, X, k1, k2, TFS_KS09); KE_MIX(T, Z, k3, k4, TFS_KS10); \
+ KE_MIX(W, E, k5, k6, TFS_KS11); KE_MIX(N, V, k7, k8, TFS_KS12); \
+ KE_MIX(U, P, k9, k10, TFS_KS13); KE_MIX(Q, M, k11, k12, TFS_KS14); \
+ KE_MIX(B, A, k13 + k14, k15, TFS_KS15); \
+ KE_MIX(L, H, k16 + x, k17 + k18, TFS_KS16); \
+ \
+ BE_MIX(X, U, TFS_BS25); BE_MIX(Z, B, TFS_BS26); \
+ BE_MIX(V, Q, TFS_BS27); BE_MIX(E, L, TFS_BS28); \
+ BE_MIX(M, N, TFS_BS29); BE_MIX(A, T, TFS_BS30); \
+ BE_MIX(H, W, TFS_BS31); BE_MIX(P, Y, TFS_BS32); \
+ BE_MIX(X, N, TFS_BS33); BE_MIX(Z, W, TFS_BS34); \
+ BE_MIX(E, T, TFS_BS35); BE_MIX(V, Y, TFS_BS36); \
+ BE_MIX(A, L, TFS_BS37); BE_MIX(H, B, TFS_BS38); \
+ BE_MIX(P, Q, TFS_BS39); BE_MIX(M, U, TFS_BS40); \
+ BE_MIX(X, L, TFS_BS41); BE_MIX(Z, Q, TFS_BS42); \
+ BE_MIX(V, B, TFS_BS43); BE_MIX(E, U, TFS_BS44); \
+ BE_MIX(H, Y, TFS_BS45); BE_MIX(P, W, TFS_BS46); \
+ BE_MIX(M, T, TFS_BS47); BE_MIX(A, N, TFS_BS48); \
+ } while (0)
+
+void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K)
+{
+ TF_UNIT_TYPE X, Y, Z, T;
+ TF_UNIT_TYPE E, W, V, N;
+ TF_UNIT_TYPE P, U, M, Q;
+ TF_UNIT_TYPE A, B, H, L;
+ TF_UNIT_TYPE K0, K1, K2, K3;
+ TF_UNIT_TYPE K4, K5, K6, K7;
+ TF_UNIT_TYPE K8, K9, K10, K11;
+ TF_UNIT_TYPE K12, K13, K14, K15;
+ TF_UNIT_TYPE K16, T0, T1, T2;
+
+ X = I[ 0]; Y = I[ 1]; Z = I[ 2]; T = I[ 3];
+ E = I[ 4]; W = I[ 5]; V = I[ 6]; N = I[ 7];
+ P = I[ 8]; U = I[ 9]; M = I[10]; Q = I[11];
+ A = I[12]; B = I[13]; H = I[14]; L = I[15];
+
+ K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3];
+ K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7];
+ K8 = K[ 8]; K9 = K[ 9]; K10 = K[10]; K11 = K[11];
+ K12 = K[12]; K13 = K[13]; K14 = K[14]; K15 = K[15];
+ K16 = K[16]; T0 = K[17]; T1 = K[18]; T2 = K[19];
+
+ PROCESS_BLOCKP( 0, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T0,K12,K15,K14, T1);
+ PROCESS_BLOCKN( 1, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T1,K13,K16,K15, T2);
+ PROCESS_BLOCKP( 2, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T2,K14, K0,K16, T0);
+ PROCESS_BLOCKN( 3, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16, T0,K15, K1, K0, T1);
+
+ PROCESS_BLOCKP( 4, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0, T1,K16, K2, K1, T2);
+ PROCESS_BLOCKN( 5, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, T2, K0, K3, K2, T0);
+ PROCESS_BLOCKP( 6, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, T0, K1, K4, K3, T1);
+ PROCESS_BLOCKN( 7, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, T1, K2, K5, K4, T2);
+
+ PROCESS_BLOCKP( 8, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, T2, K3, K6, K5, T0);
+ PROCESS_BLOCKN( 9,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, T0, K4, K7, K6, T1);
+ PROCESS_BLOCKP(10,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, T1, K5, K8, K7, T2);
+ PROCESS_BLOCKN(11,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, T2, K6, K9, K8, T0);
+
+ PROCESS_BLOCKP(12,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, T0, K7,K10, K9, T1);
+ PROCESS_BLOCKN(13,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, T1, K8,K11,K10, T2);
+ PROCESS_BLOCKP(14,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, T2, K9,K12,K11, T0);
+ PROCESS_BLOCKN(15,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11, T0,K10,K13,K12, T1);
+
+ PROCESS_BLOCKP(16, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12, T1,K11,K14,K13, T2);
+ PROCESS_BLOCKN(17, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T2,K12,K15,K14, T0);
+ PROCESS_BLOCKP(18, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T0,K13,K16,K15, T1);
+ PROCESS_BLOCKN(19, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T1,K14, K0,K16, T2);
+
+ O[0] = X + K3; O[1] = Y + K4; O[2] = Z + K5; O[3] = T + K6;
+ O[4] = E + K7; O[5] = W + K8; O[6] = V + K9; O[7] = N + K10;
+ O[8] = P + K11; O[9] = U + K12; O[10] = M + K13; O[11] = Q + K14;
+ O[12] = A + K15; O[13] = B + K16 + T2; O[14] = H + K0 + T0; O[15] = L + K1 + 20;
+}
+
+#endif
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+
+static inline void ocb_block(TF_UNIT_TYPE *x, int tag)
+{
+ TF_UNIT_TYPE c = (x[0] >> (TF_UNIT_BITS-1));
+ size_t i;
+
+ if (tag) goto _tag;
+ for (i = 0; i < TF_NR_BLOCK_UNITS-1; i++)
+ x[i] = ((x[i] << 1) | (x[i+1] >> (TF_UNIT_BITS-1)));
+ x[TF_NR_BLOCK_UNITS-1] = ((x[i-1] << 1) ^ (c*IRR_POLY_CONST));
+ return;
+
+_tag: for (i = 0; i < TF_NR_BLOCK_UNITS-1; i++)
+ x[i] ^= ((x[i] << 1) | (x[i+1] >> (TF_UNIT_BITS-1)));
+ x[TF_NR_BLOCK_UNITS-1] ^= ((x[i-1] << 1) ^ (c*IRR_POLY_CONST));
+}
+
+static void ocb_encrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out, *s, *d;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS], c[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uctr = ctr, *utag = tag;
+ const TF_UNIT_TYPE *ukey = key;
+ size_t sl = sz, i;
+
+ tf_encrypt_rawblk(tctr, uctr, ukey);
+ if (tag) {
+ memcpy(c, tag, TF_BLOCK_SIZE);
+ data_to_words(c, TF_BLOCK_SIZE);
+ }
+
+ if (sl >= TF_BLOCK_SIZE) {
+ do {
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ ocb_block(tctr, 0);
+ if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= x[i];
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+ tf_encrypt_rawblk(y, x, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= tctr[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sl) {
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ ocb_block(tctr, 0);
+ memset(x, 0, TF_BLOCK_SIZE);
+ x[TF_NR_BLOCK_UNITS-1] = (TF_TO_BITS(sl));
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+ tf_encrypt_rawblk(y, x, ukey);
+
+ memcpy(x, uin, sl);
+ data_to_words(x, sl);
+ s = (TF_BYTE_TYPE *)x; d = (TF_BYTE_TYPE *)y;
+ memcpy(s+sl, d+sl, TF_BLOCK_SIZE-sl);
+ if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= x[i];
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= y[i];
+
+ data_to_words(x, sl);
+ memcpy(uout, x, sl);
+ }
+
+ if (!tag) goto _done;
+
+ ocb_block(tctr, 1);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] = tctr[i] ^ c[i];
+ tf_encrypt_rawblk(y, x, ukey);
+ data_to_words(y, TF_BLOCK_SIZE);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) utag[i] ^= y[i];
+
+_done: memset(tctr, 0, TF_BLOCK_SIZE);
+ memset(c, 0, TF_BLOCK_SIZE);
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
+
+void tf_ocb_encrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz, size_t bpi)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi);
+
+ if (sl >= sx) {
+ do {
+ ocb_encrypt(key, ctr, uout, tag, uin, sx);
+ uout += sx;
+ uin += sx;
+ } while ((sl -= sx) >= sx);
+ }
+
+ if (sl) ocb_encrypt(key, ctr, uout, tag, uin, sl);
+}
+
+static void ocb_decrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS], c[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uctr = ctr, *utag = tag;
+ const TF_UNIT_TYPE *ukey = key;
+ size_t sl = sz, i;
+
+ tf_encrypt_rawblk(tctr, uctr, ukey);
+ if (tag) {
+ memcpy(c, tag, TF_BLOCK_SIZE);
+ data_to_words(c, TF_BLOCK_SIZE);
+ }
+
+ if (sl >= TF_BLOCK_SIZE) {
+ do {
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ ocb_block(tctr, 0);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+ tf_decrypt_rawblk(y, x, ukey);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= tctr[i];
+ if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= y[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+ }
+
+ if (sl) {
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ ocb_block(tctr, 0);
+ memset(x, 0, TF_BLOCK_SIZE);
+ x[TF_NR_BLOCK_UNITS-1] = (TF_TO_BITS(sl));
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+ tf_encrypt_rawblk(y, x, ukey);
+
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, sl);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= y[i];
+ if (tag) for (i = 0; i < TF_NR_BLOCK_UNITS; i++) c[i] ^= x[i];
+
+ data_to_words(x, sl);
+ memcpy(uout, x, sl);
+ }
+
+ if (!tag) goto _done;
+
+ ocb_block(tctr, 1);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] = tctr[i] ^ c[i];
+ tf_encrypt_rawblk(y, x, ukey);
+ data_to_words(y, TF_BLOCK_SIZE);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) utag[i] ^= y[i];
+
+_done: memset(tctr, 0, TF_BLOCK_SIZE);
+ memset(c, 0, TF_BLOCK_SIZE);
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
+
+void tf_ocb_decrypt(const void *key, void *ctr, void *out, void *tag, const void *in, size_t sz, size_t bpi)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi);
+
+ if (sl >= sx) {
+ do {
+ ocb_decrypt(key, ctr, uout, tag, uin, sx);
+ uout += sx;
+ uin += sx;
+ } while ((sl -= sx) >= sx);
+ }
+
+ if (sl) ocb_decrypt(key, ctr, uout, tag, uin, sl);
+}
--- /dev/null
+#include <string.h>
+#include "tfe.h"
+#include "tfprng.h"
+
+struct tf_prng_data {
+ struct tfe_stream tfe;
+ short init;
+};
+
+struct tf_prng_data tf_prng_sdata;
+
+size_t tf_prng_datasize(void)
+{
+ return sizeof(struct tf_prng_data);
+}
+
+void tf_prng_seedkey_r(void *sdata, const void *skey)
+{
+ TF_UNIT_TYPE k[TF_NR_KEY_UNITS];
+ struct tf_prng_data *rprng = sdata;
+
+ memset(rprng, 0, sizeof(struct tf_prng_data));
+ if (!skey) return;
+
+ memcpy(k, skey, TF_KEY_SIZE);
+ tfe_init(&rprng->tfe, k);
+ rprng->init = 1;
+
+ memset(k, 0, TF_KEY_SIZE);
+}
+
+void tf_prng_seedkey(const void *skey)
+{
+ tf_prng_seedkey_r(&tf_prng_sdata, skey);
+}
+
+void tf_prng_genrandom_r(void *sdata, void *result, size_t need)
+{
+ struct tf_prng_data *rprng = sdata;
+ memset(result, 0, need);
+ tfe_emit(result, need, &rprng->tfe);
+}
+
+void tf_prng_genrandom(void *result, size_t need)
+{
+ tf_prng_genrandom_r(&tf_prng_sdata, result, need);
+}
+
+void tf_prng_seed_r(void *sdata, TF_UNIT_TYPE seed)
+{
+ TF_UNIT_TYPE k[TF_NR_KEY_UNITS];
+ struct tf_prng_data *rprng = sdata;
+ size_t x;
+
+ memset(rprng, 0, sizeof(struct tf_prng_data));
+ for (x = 0; x < TF_NR_KEY_UNITS; x++) k[x] = seed;
+ tfe_init(&rprng->tfe, k);
+ rprng->init = 1;
+
+ memset(k, 0, TF_KEY_SIZE);
+}
+
+void tf_prng_seed(TF_UNIT_TYPE seed)
+{
+ tf_prng_seed_r(&tf_prng_sdata, seed);
+}
+
+TF_UNIT_TYPE tf_prng_random_r(void *sdata)
+{
+ struct tf_prng_data *rprng = sdata;
+ TF_UNIT_TYPE r;
+
+ if (!rprng->init) return 0;
+
+ tfe_emit(&r, sizeof(r), &rprng->tfe);
+ return r;
+}
+
+TF_UNIT_TYPE tf_prng_random(void)
+{
+ return tf_prng_random_r(&tf_prng_sdata);
+}
+
+TF_UNIT_TYPE tf_prng_range_r(void *sdata, TF_UNIT_TYPE s, TF_UNIT_TYPE d)
+{
+ TF_UNIT_TYPE c = tf_prng_random_r(sdata);
+ if (d <= s) return s;
+ return s + c / ((TF_UNIT_TYPE)~0 / (d - s + 1) + 1);
+}
+
+TF_UNIT_TYPE tf_prng_range(TF_UNIT_TYPE s, TF_UNIT_TYPE d)
+{
+ return tf_prng_range_r(&tf_prng_sdata, s, d);
+}
+
+void tf_prng_srand(unsigned seed)
+{
+ tf_prng_seed((TF_UNIT_TYPE)seed);
+}
+
+int tf_prng_rand(void)
+{
+ return (int)tf_prng_range(0, (TF_UNIT_TYPE)TF_PRNG_LEGACY_RAND_MAX);
+}
--- /dev/null
+#ifndef _TF_PRNG_DEFINITIONS_HEADER
+#define _TF_PRNG_DEFINITIONS_HEADER
+
+#include <stdlib.h>
+#include "tfdef.h"
+
+#define TF_PRNG_KEY_SIZE TF_KEY_SIZE
+#define TF_PRNG_SIZE_UNIT TF_SIZE_UNIT
+
+#define TF_PRNG_LEGACY_RAND_MAX RAND_MAX
+
+size_t tf_prng_datasize(void);
+void tf_prng_seedkey_r(void *sdata, const void *skey);
+void tf_prng_seedkey(const void *skey);
+void tf_prng_genrandom_r(void *sdata, void *result, size_t need);
+void tf_prng_genrandom(void *result, size_t need);
+void tf_prng_seed_r(void *sdata, TF_UNIT_TYPE seed);
+void tf_prng_seed(TF_UNIT_TYPE seed);
+TF_UNIT_TYPE tf_prng_random_r(void *sdata);
+TF_UNIT_TYPE tf_prng_random(void);
+TF_UNIT_TYPE tf_prng_range_r(void *sdata, TF_UNIT_TYPE s, TF_UNIT_TYPE d);
+TF_UNIT_TYPE tf_prng_range(TF_UNIT_TYPE s, TF_UNIT_TYPE d);
+void tf_prng_srand(unsigned seed);
+int tf_prng_rand(void);
+
+#endif
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+#include "tfe.h"
+
+void tf_stream_crypt(struct tfe_stream *tfe, void *out, const void *in, size_t sz)
+{
+ const TF_UNIT_TYPE *uin = in;
+ TF_UNIT_TYPE *uout = out;
+ const TF_BYTE_TYPE *uuin = in;
+ TF_BYTE_TYPE *uuout = out;
+ size_t n, z, x;
+
+ switch (TF_SIZE_UNIT) {
+ case 2: n = 1; break;
+ case 4: n = 2; break;
+ case 8: n = 3; break;
+ }
+
+ tfe_emit(out, sz, tfe);
+ for (z = 0; z < (sz >> n); z++) uout[z] ^= uin[z];
+ if (sz - (z << n)) for (x = (z << n); x < sz; x++) uuout[x] ^= uuin[x];
+}
--- /dev/null
+#include <string.h>
+#include "tfdef.h"
+
+static inline void xts_mult_x(TF_UNIT_TYPE *x)
+{
+ size_t i, t, tt;
+
+ for (i = t = 0; i < TF_NR_BLOCK_UNITS; i++) {
+ tt = x[i] >> (TF_UNIT_BITS-1);
+ x[i] = ((x[i] << 1) | t) & ((TF_UNIT_TYPE)~0);
+ t = tt;
+ }
+ if (tt) x[0] ^= IRR_POLY_CONST;
+}
+
+static void xts_encrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uctr = ctr;
+ const TF_UNIT_TYPE *ukeyx = keyx, *ukeyz = keyz;
+ size_t sl = sz, i;
+
+ tf_encrypt_rawblk(tctr, uctr, ukeyz);
+
+ if (sl >= (TF_BLOCK_SIZE * 2)) {
+ do {
+_last: memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ tctr[i];
+ tf_encrypt_rawblk(x, y, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+
+ xts_mult_x(tctr);
+
+ data_to_words(x, TF_BLOCK_SIZE);
+ memcpy(uout, x, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= (TF_BLOCK_SIZE * 2));
+ }
+
+ if (sl) {
+ if (sl-TF_BLOCK_SIZE == 0) goto _last;
+ if (sl < TF_BLOCK_SIZE) {
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ tf_encrypt_rawblk(y, uctr, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+
+ goto _done;
+ }
+
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ tctr[i];
+ tf_encrypt_rawblk(x, y, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+
+ memcpy(y, x, TF_BLOCK_SIZE);
+ sl -= TF_BLOCK_SIZE;
+
+ xts_mult_x(tctr);
+
+ tf_encrypt_rawblk(tctr, uctr, ukeyz);
+
+ memcpy(x, uin, sl);
+ data_to_words(x, sl);
+
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+ tf_encrypt_rawblk(x, x, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+
+ data_to_words(x, TF_BLOCK_SIZE);
+ memcpy(uout, x, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+ }
+
+_done: memset(tctr, 0, TF_BLOCK_SIZE);
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
+
+void tf_xts_encrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi);
+
+ if (sl >= sx) {
+ do {
+ xts_encrypt(keyx, keyz, ctr, uout, uin, sx);
+ uout += sx;
+ uin += sx;
+ } while ((sl -= sx) >= sx);
+ }
+
+ if (sl) xts_encrypt(keyx, keyz, ctr, uout, uin, sl);
+}
+
+static void xts_decrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out, *s, *d;
+ TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS], zctr[TF_NR_BLOCK_UNITS];
+ TF_UNIT_TYPE *uctr = ctr;
+ const TF_UNIT_TYPE *ukeyx = keyx, *ukeyz = keyz;
+ size_t sl = sz, i;
+
+ tf_encrypt_rawblk(tctr, uctr, ukeyz);
+
+ if (sl >= (TF_BLOCK_SIZE * 2)) {
+ do {
+_last: memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ tctr[i];
+ tf_decrypt_rawblk(x, y, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+
+ xts_mult_x(tctr);
+
+ data_to_words(x, TF_BLOCK_SIZE);
+ memcpy(uout, x, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+ } while ((sl -= TF_BLOCK_SIZE) >= (TF_BLOCK_SIZE * 2));
+ }
+
+ if (sl) {
+ if (sl-TF_BLOCK_SIZE == 0) goto _last;
+ if (sl < TF_BLOCK_SIZE) {
+ memset(x, 0, TF_BLOCK_SIZE);
+ memcpy(x, uin, sl);
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ tf_encrypt_rawblk(y, uctr, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, sl);
+
+ goto _done;
+ }
+
+ memcpy(x, uin, TF_BLOCK_SIZE);
+ uin += TF_BLOCK_SIZE;
+ data_to_words(x, TF_BLOCK_SIZE);
+
+ ctr_inc(uctr, TF_NR_BLOCK_UNITS);
+ memcpy(zctr, tctr, TF_BLOCK_SIZE);
+ xts_mult_x(tctr);
+
+ tf_encrypt_rawblk(tctr, uctr, ukeyz);
+
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+ tf_decrypt_rawblk(x, x, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i];
+
+ sl -= TF_BLOCK_SIZE;
+ memcpy(y, uin, sl);
+ data_to_words(y, sl);
+
+ s = (TF_BYTE_TYPE *)y;
+ d = (TF_BYTE_TYPE *)x;
+ memcpy(s+sl, d+sl, TF_BLOCK_SIZE-sl);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= zctr[i];
+ tf_decrypt_rawblk(y, y, ukeyx);
+ for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= zctr[i];
+
+ data_to_words(y, TF_BLOCK_SIZE);
+ memcpy(uout, y, TF_BLOCK_SIZE);
+ uout += TF_BLOCK_SIZE;
+
+ data_to_words(x, TF_BLOCK_SIZE);
+ memcpy(uout, x, sl);
+ }
+
+_done: memset(tctr, 0, TF_BLOCK_SIZE);
+ memset(zctr, 0, TF_BLOCK_SIZE);
+ memset(x, 0, TF_BLOCK_SIZE);
+ memset(y, 0, TF_BLOCK_SIZE);
+}
+
+void tf_xts_decrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi)
+{
+ const TF_BYTE_TYPE *uin = in;
+ TF_BYTE_TYPE *uout = out;
+ size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi);
+
+ if (sl >= sx) {
+ do {
+ xts_decrypt(keyx, keyz, ctr, uout, uin, sx);
+ uout += sx;
+ uin += sx;
+ } while ((sl -= sx) >= sx);
+ }
+
+ if (sl) xts_decrypt(keyx, keyz, ctr, uout, uin, sl);
+}