├── VERSION ├── .gitignore ├── tfstream.c ├── tfc_io.c ├── tfe.h ├── tfctrapi.c ├── xstrlcat.c ├── tfcrypt_defs.h ├── tftweakapi.c ├── Makefile ├── tfprng.h ├── skein.h ├── COPYRIGHT ├── base64.h ├── tfctr.c ├── tfe.c ├── getpasswd.h ├── tfc_say.c ├── tfecb.c ├── tfprng.c ├── tfcbc.c ├── tfpcbc.c ├── README ├── tfcore.h ├── tfc_vars.c ├── tfc_bench.c ├── skein.c ├── tfc_conf.c ├── mhexdump.c ├── tfdef.h ├── tfc_conv.c ├── getpasswd.c ├── tfc_base64.c ├── tfc_random.c ├── tfxts.c ├── tfc_signal.c ├── base64.c ├── tfc_misc.c ├── tfcrypt.h ├── tfc_skein.c ├── tfenc.c ├── tfdec.c ├── tfc_error.c └── tfcrypt.c /VERSION: -------------------------------------------------------------------------------- 1 | 71 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _* 2 | *.swp 3 | *.o 4 | *.out 5 | *.key 6 | *.diff 7 | *.patch 8 | tags 9 | tfcrypt 10 | tfcrypt.upx 11 | sksum 12 | tfbench 13 | base64 14 | -------------------------------------------------------------------------------- /tfstream.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | #include "tfe.h" 4 | 5 | void tf_stream_crypt(struct tfe_stream *tfe, void *out, const void *in, size_t sz) 6 | { 7 | tfe_emit(out, sz, tfe); 8 | xor_block(out, in, sz); 9 | } 10 | -------------------------------------------------------------------------------- /tfc_io.c: -------------------------------------------------------------------------------- 1 | #include "tfcrypt.h" 2 | 3 | size_t xread(int fd, void *data, size_t szdata) 4 | { 5 | size_t x; 6 | 7 | do { 8 | errno = 0; 9 | x = (size_t)read(fd, data, szdata); 10 | } while (x == NOSIZE && errno == EINTR); 11 | 12 | return x; 13 | } 14 | 15 | size_t xwrite(int fd, const void *data, size_t szdata) 16 | { 17 | size_t x; 18 | 19 | do { 20 | errno = 0; 21 | x = (size_t)write(fd, data, szdata); 22 | } while (x == NOSIZE && errno == EINTR); 23 | 24 | return x; 25 | } 26 | -------------------------------------------------------------------------------- /tfe.h: -------------------------------------------------------------------------------- 1 | #ifndef _TF_STREAM_CIPHER_DEFS 2 | #define _TF_STREAM_CIPHER_DEFS 3 | 4 | #include "tfdef.h" 5 | 6 | struct tfe_stream { 7 | TF_UNIT_TYPE key[TF_NR_KEY_UNITS]; 8 | TF_UNIT_TYPE iv[TF_NR_BLOCK_UNITS]; 9 | TF_BYTE_TYPE tmp[TF_BLOCK_SIZE]; 10 | size_t tidx; 11 | }; 12 | 13 | void tfe_init(struct tfe_stream *tfe, const void *key); 14 | void tfe_init_iv(struct tfe_stream *tfe, const void *key, const void *iv); 15 | void tfe_emit(void *dst, size_t szdst, struct tfe_stream *tfe); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /tfctrapi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | 4 | void tf_ctr_set(void *ctr, const void *sctr, size_t sctrsz) 5 | { 6 | TF_UNIT_TYPE usctr[TF_NR_BLOCK_UNITS]; 7 | TF_UNIT_TYPE *uctr = ctr; 8 | 9 | data_to_words(uctr, TF_BLOCK_SIZE); 10 | 11 | memset(usctr, 0, TF_BLOCK_SIZE); 12 | memcpy(usctr, sctr, sctrsz > TF_BLOCK_SIZE ? TF_BLOCK_SIZE : sctrsz); 13 | data_to_words(usctr, TF_BLOCK_SIZE); 14 | 15 | ctr_add(uctr, TF_NR_BLOCK_UNITS, usctr, TF_NR_BLOCK_UNITS); 16 | memset(usctr, 0, TF_BLOCK_SIZE); 17 | } 18 | -------------------------------------------------------------------------------- /xstrlcat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t xstrlcpy(char *dst, const char *src, size_t size) 4 | { 5 | size_t len, srclen; 6 | srclen = strlen(src); 7 | if (size-- <= 0) return srclen; 8 | len = (size < srclen) ? size : srclen; 9 | memmove(dst, src, len); 10 | dst[len] = '\0'; 11 | return srclen; 12 | } 13 | 14 | size_t xstrlcat(char *dst, const char *src, size_t size) 15 | { 16 | size_t dstlen = strnlen(dst, size); 17 | if (dstlen == size) return dstlen + strlen(src); 18 | return dstlen + xstrlcpy(dst+dstlen, src, size-dstlen); 19 | } 20 | -------------------------------------------------------------------------------- /tfcrypt_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef _TFCRYPT_DEFAULTS_HEADER 2 | #define _TFCRYPT_DEFAULTS_HEADER 3 | 4 | /* 5uouFzawL37Un6RtVqWbv0SOX48ew/xntAG5sNaOSlk= */ 5 | 6 | size_t nr_turns = 262144; 7 | int ctr_mode = TFC_MODE_XTS; 8 | size_t macbits = TF_MAX_BITS; 9 | size_t tfc_saltsz = 32; 10 | tfc_byte tfc_salt[TFC_MAX_SALT] = { 11 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 12 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 13 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 14 | 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 15 | }; 16 | tfc_yesno do_full_key = NO; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /tftweakapi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | #include "tfcore.h" 4 | 5 | void tf_tweak_set(void *key, const void *tweak) 6 | { 7 | TF_UNIT_TYPE *ukey = key; 8 | TF_UNIT_TYPE *twe = ukey+TF_TWEAK_WORD1; 9 | TF_UNIT_TYPE c = THREEFISH_CONST; 10 | size_t x; 11 | 12 | for (x = 0; x < TF_NR_BLOCK_UNITS; x++) c ^= ukey[x]; 13 | ukey[x] = c; 14 | 15 | if (!tweak) { 16 | memset(twe, 0, (TF_NR_TWEAK_UNITS+1)*TF_SIZE_UNIT); 17 | return; 18 | } 19 | 20 | memcpy(twe, tweak, TF_NR_TWEAK_UNITS*TF_SIZE_UNIT); 21 | data_to_words(twe, TF_NR_TWEAK_UNITS*TF_SIZE_UNIT); 22 | ukey[TF_TWEAK_WORD3] = ukey[TF_TWEAK_WORD1] ^ ukey[TF_TWEAK_WORD2]; 23 | } 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION:=$(shell cat VERSION) 2 | override CFLAGS+=-D_TFCRYPT_VERSION=\"$(VERSION)\" -Wall 3 | UPX=upx 4 | 5 | ifneq (,$(DEBUG)) 6 | override CFLAGS+=-O0 -g 7 | else 8 | override CFLAGS+=-O3 9 | endif 10 | 11 | ifneq (,$(STATIC)) 12 | override LDFLAGS+=-static 13 | endif 14 | 15 | ifneq (,$(STRIP)) 16 | override LDFLAGS+=-s 17 | endif 18 | 19 | SRCS = $(wildcard *.c) 20 | HDRS = $(wildcard *.h) 21 | OBJS = $(SRCS:.c=.o) 22 | 23 | all: tfcrypt 24 | 25 | %.o: %.c VERSION $(HDRS) 26 | $(CC) $(CFLAGS) -c -o $@ $< 27 | 28 | tfcrypt: $(OBJS) 29 | $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ 30 | 31 | tfcrypt.upx: $(OBJS) 32 | $(CC) $(CFLAGS) $(LDFLAGS) -static -s $(OBJS) -o $@ 33 | $(UPX) --best $@ 34 | 35 | clean: 36 | rm -f $(OBJS) tfcrypt tfcrypt.upx 37 | -------------------------------------------------------------------------------- /tfprng.h: -------------------------------------------------------------------------------- 1 | #ifndef _TF_PRNG_DEFINITIONS_HEADER 2 | #define _TF_PRNG_DEFINITIONS_HEADER 3 | 4 | #include 5 | #include "tfdef.h" 6 | 7 | #define TF_PRNG_KEY_SIZE TF_KEY_SIZE 8 | #define TF_PRNG_SIZE_UNIT TF_SIZE_UNIT 9 | #define TF_PRNG_RANGE(C, T, S, D) (S + C / ((T)~0 / (D - S + 1) + 1)) 10 | 11 | size_t tf_prng_datasize(void); 12 | void tf_prng_seedkey_r(void *sdata, const void *skey); 13 | void tf_prng_seedkey(const void *skey); 14 | void tf_prng_genrandom_r(void *sdata, void *result, size_t need); 15 | void tf_prng_genrandom(void *result, size_t need); 16 | void tf_prng_seed_r(void *sdata, TF_UNIT_TYPE seed); 17 | void tf_prng_seed(TF_UNIT_TYPE seed); 18 | TF_UNIT_TYPE tf_prng_random_r(void *sdata); 19 | TF_UNIT_TYPE tf_prng_random(void); 20 | TF_UNIT_TYPE tf_prng_range_r(void *sdata, TF_UNIT_TYPE s, TF_UNIT_TYPE d); 21 | TF_UNIT_TYPE tf_prng_range(TF_UNIT_TYPE s, TF_UNIT_TYPE d); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /skein.h: -------------------------------------------------------------------------------- 1 | #ifndef _THREEFISH_SKEIN_DEFINITIONS_HEADER 2 | #define _THREEFISH_SKEIN_DEFINITIONS_HEADER 3 | 4 | #include "tfdef.h" 5 | 6 | #define SKEIN_VERSION 1 7 | #define SKEIN_ID 0x33414853 8 | 9 | #define SKEIN_BLOCK_CFG ((TF_UNIT_TYPE)4 << 56) 10 | #define SKEIN_BLOCK_MSG ((TF_UNIT_TYPE)48 << 56) 11 | #define SKEIN_BLOCK_OUT ((TF_UNIT_TYPE)63 << 56) 12 | #define SKEIN_FLAG_FIRST ((TF_UNIT_TYPE)1 << 62) 13 | #define SKEIN_FLAG_LAST ((TF_UNIT_TYPE)1 << 63) 14 | 15 | #define SKEIN_DIGEST_SIZE TF_BLOCK_SIZE 16 | 17 | struct skein { 18 | TF_UNIT_TYPE key[TF_NR_KEY_UNITS]; 19 | TF_BYTE_TYPE carry_block[TF_BLOCK_SIZE]; 20 | size_t carry_bytes; 21 | size_t bits; 22 | }; 23 | 24 | void skein_init_key(struct skein *sk, const void *ukey, size_t bits); 25 | void skein_init(struct skein *sk, size_t bits); 26 | void skein_update(struct skein *sk, const void *msg, size_t msgsz); 27 | void skein_final(void *result, struct skein *sk); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | The tfcrypt program is copyrighted: 2 | 3 | Copyright © 2012-2019 Andrey Rys. 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /base64.h: -------------------------------------------------------------------------------- 1 | #ifndef _BASE64_H 2 | #define _BASE64_H 3 | 4 | enum base64_decodestep { 5 | estep_a, estep_b, estep_c, estep_d 6 | }; 7 | 8 | struct base64_decodestate { 9 | enum base64_decodestep step; 10 | char plainchar; 11 | size_t count; 12 | }; 13 | 14 | enum base64_encodestep { 15 | dstep_a, dstep_b, dstep_c 16 | }; 17 | 18 | struct base64_encodestate { 19 | enum base64_encodestep step; 20 | char result; 21 | size_t count; 22 | }; 23 | 24 | int base64_decode_value(signed char value_in); 25 | void base64_init_decodestate(struct base64_decodestate *state_in); 26 | 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); 27 | void base64_init_encodestate(struct base64_encodestate *state_in); 28 | char base64_encode_value(char value_in); 29 | size_t base64_encode_block(const char *plaintext_in, size_t length_in, char *code_out, struct base64_encodestate *state_in); 30 | size_t base64_encode_blockend(char *code_out, struct base64_encodestate *state_in); 31 | 32 | size_t base64_decode(char *output, size_t outputl, const char *input, size_t inputl); 33 | size_t base64_encode(char *output, const char *input, size_t inputl); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /tfctr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | 4 | void tf_ctr_crypt(const void *key, void *ctr, void *out, const void *in, size_t sz) 5 | { 6 | const TF_BYTE_TYPE *uin = in; 7 | TF_BYTE_TYPE *uout = out; 8 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 9 | TF_UNIT_TYPE *uctr = ctr; 10 | const TF_UNIT_TYPE *ukey = key; 11 | size_t sl = sz, i; 12 | 13 | if (sl >= TF_BLOCK_SIZE) { 14 | do { 15 | memcpy(x, uin, TF_BLOCK_SIZE); 16 | uin += TF_BLOCK_SIZE; 17 | data_to_words(x, TF_BLOCK_SIZE); 18 | 19 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 20 | tf_encrypt_rawblk(y, uctr, ukey); 21 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 22 | 23 | data_to_words(y, TF_BLOCK_SIZE); 24 | memcpy(uout, y, TF_BLOCK_SIZE); 25 | uout += TF_BLOCK_SIZE; 26 | } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 27 | } 28 | 29 | if (sl) { 30 | memset(x, 0, TF_BLOCK_SIZE); 31 | memcpy(x, uin, sl); 32 | data_to_words(x, TF_BLOCK_SIZE); 33 | 34 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 35 | tf_encrypt_rawblk(y, uctr, ukey); 36 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 37 | 38 | data_to_words(y, TF_BLOCK_SIZE); 39 | memcpy(uout, y, sl); 40 | } 41 | 42 | memset(x, 0, TF_BLOCK_SIZE); 43 | memset(y, 0, TF_BLOCK_SIZE); 44 | } 45 | -------------------------------------------------------------------------------- /tfe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | #include "tfe.h" 4 | 5 | void tfe_init_iv(struct tfe_stream *tfe, const void *key, const void *iv) 6 | { 7 | memset(tfe, 0, sizeof(struct tfe_stream)); 8 | memcpy(tfe->key, key, TF_KEY_SIZE); 9 | if (iv) memcpy(tfe->iv, iv, TF_BLOCK_SIZE); 10 | tfe->tidx = 0; 11 | } 12 | 13 | void tfe_init(struct tfe_stream *tfe, const void *key) 14 | { 15 | tfe_init_iv(tfe, key, NULL); 16 | } 17 | 18 | void tfe_emit(void *dst, size_t szdst, struct tfe_stream *tfe) 19 | { 20 | TF_BYTE_TYPE *udst = dst; 21 | size_t sz = szdst, trem; 22 | 23 | if (!dst && szdst == 0) { 24 | memset(tfe, 0, sizeof(struct tfe_stream)); 25 | return; 26 | } 27 | 28 | if (tfe->tidx > 0) { 29 | trem = TF_BLOCK_SIZE-tfe->tidx; 30 | 31 | if (szdst <= trem) { 32 | memcpy(udst, &tfe->tmp[tfe->tidx], szdst); 33 | tfe->tidx += szdst; 34 | if (tfe->tidx >= TF_BLOCK_SIZE) tfe->tidx = 0; 35 | return; 36 | } 37 | 38 | memcpy(udst, &tfe->tmp[tfe->tidx], trem); 39 | udst += trem; 40 | sz -= trem; 41 | tfe->tidx = 0; 42 | } 43 | 44 | if (sz >= TF_BLOCK_SIZE) { 45 | do { 46 | tf_encrypt_rawblk(tfe->iv, tfe->iv, tfe->key); 47 | memcpy(udst, tfe->iv, TF_BLOCK_SIZE); 48 | data_to_words(udst, TF_BLOCK_SIZE); 49 | udst += TF_BLOCK_SIZE; 50 | } while ((sz -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 51 | } 52 | 53 | if (sz) { 54 | tf_encrypt_rawblk(tfe->iv, tfe->iv, tfe->key); 55 | memcpy(tfe->tmp, tfe->iv, TF_BLOCK_SIZE); 56 | data_to_words(tfe->tmp, TF_BLOCK_SIZE); 57 | memcpy(udst, tfe->tmp, sz); 58 | tfe->tidx = sz; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /getpasswd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #ifndef _GETPASSWD_H 30 | #define _GETPASSWD_H 31 | 32 | #define GETP_NOECHO 1 33 | #define GETP_NOINTERP 2 34 | #define GETP_WAITFILL 4 35 | 36 | struct getpasswd_state; 37 | struct termios; 38 | 39 | typedef int (*getpasswd_filt)(struct getpasswd_state *, char, size_t); 40 | 41 | struct getpasswd_state { 42 | char *passwd; 43 | size_t pwlen; 44 | const char *echo; 45 | char maskchar; 46 | getpasswd_filt charfilter; 47 | int fd; 48 | int efd; 49 | int error; 50 | struct termios *sanetty; 51 | int flags; 52 | size_t retn; 53 | }; 54 | 55 | size_t xgetpasswd(struct getpasswd_state *getps); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /tfc_say.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | void tfc_vfsay(FILE *where, tfc_yesno addnl, const char *fmt, va_list ap) 32 | { 33 | if (!strcmp(fmt, "\n")) { 34 | fputc('\n', where); 35 | return; 36 | } 37 | 38 | vfprintf(where, fmt, ap); 39 | if (addnl) fputc('\n', where); 40 | fflush(where); 41 | } 42 | 43 | void tfc_nfsay(FILE *where, const char *fmt, ...) 44 | { 45 | va_list ap; 46 | 47 | va_start(ap, fmt); 48 | tfc_vfsay(where, NO, fmt, ap); 49 | va_end(ap); 50 | } 51 | 52 | void tfc_esay(const char *fmt, ...) 53 | { 54 | va_list ap; 55 | 56 | va_start(ap, fmt); 57 | tfc_vfsay(stderr, YES, fmt, ap); 58 | va_end(ap); 59 | } 60 | 61 | void tfc_say(const char *fmt, ...) 62 | { 63 | va_list ap; 64 | 65 | va_start(ap, fmt); 66 | tfc_vfsay(stdout, YES, fmt, ap); 67 | va_end(ap); 68 | } 69 | -------------------------------------------------------------------------------- /tfecb.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | 4 | void tf_ecb_encrypt(const void *key, void *out, const void *in, size_t sz) 5 | { 6 | const TF_BYTE_TYPE *uin = in; 7 | TF_BYTE_TYPE *uout = out; 8 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 9 | const TF_UNIT_TYPE *ukey = key; 10 | size_t sl = sz, i; 11 | 12 | if (sl >= TF_BLOCK_SIZE) { 13 | do { 14 | memcpy(x, uin, TF_BLOCK_SIZE); 15 | uin += TF_BLOCK_SIZE; 16 | data_to_words(x, TF_BLOCK_SIZE); 17 | 18 | tf_encrypt_rawblk(y, x, ukey); 19 | 20 | data_to_words(y, TF_BLOCK_SIZE); 21 | memcpy(uout, y, TF_BLOCK_SIZE); 22 | uout += TF_BLOCK_SIZE; 23 | } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 24 | } 25 | 26 | if (sl) { 27 | memset(x, 0, TF_BLOCK_SIZE); 28 | memcpy(x, uin, sl); 29 | data_to_words(x, TF_BLOCK_SIZE); 30 | 31 | memset(y, 0, TF_BLOCK_SIZE); 32 | tf_encrypt_rawblk(y, y, ukey); 33 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 34 | 35 | data_to_words(y, TF_BLOCK_SIZE); 36 | memcpy(uout, y, sl); 37 | } 38 | 39 | memset(x, 0, TF_BLOCK_SIZE); 40 | memset(y, 0, TF_BLOCK_SIZE); 41 | } 42 | 43 | void tf_ecb_decrypt(const void *key, void *out, const void *in, size_t sz) 44 | { 45 | const TF_BYTE_TYPE *uin = in; 46 | TF_BYTE_TYPE *uout = out; 47 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 48 | const TF_UNIT_TYPE *ukey = key; 49 | size_t sl = sz, i; 50 | 51 | if (sl >= TF_BLOCK_SIZE) { 52 | do { 53 | memcpy(x, uin, TF_BLOCK_SIZE); 54 | uin += TF_BLOCK_SIZE; 55 | data_to_words(x, TF_BLOCK_SIZE); 56 | 57 | tf_decrypt_rawblk(y, x, ukey); 58 | 59 | data_to_words(y, TF_BLOCK_SIZE); 60 | memcpy(uout, y, TF_BLOCK_SIZE); 61 | uout += TF_BLOCK_SIZE; 62 | } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 63 | } 64 | 65 | if (sl) { 66 | memset(x, 0, TF_BLOCK_SIZE); 67 | memcpy(x, uin, sl); 68 | data_to_words(x, TF_BLOCK_SIZE); 69 | 70 | memset(y, 0, TF_BLOCK_SIZE); 71 | tf_decrypt_rawblk(y, y, ukey); 72 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 73 | 74 | data_to_words(y, TF_BLOCK_SIZE); 75 | memcpy(uout, y, sl); 76 | } 77 | 78 | memset(x, 0, TF_BLOCK_SIZE); 79 | memset(y, 0, TF_BLOCK_SIZE); 80 | } 81 | -------------------------------------------------------------------------------- /tfprng.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfe.h" 3 | #include "tfprng.h" 4 | 5 | struct tf_prng_data { 6 | struct tfe_stream tfe; 7 | short init; 8 | }; 9 | 10 | struct tf_prng_data tf_prng_sdata; 11 | 12 | size_t tf_prng_datasize(void) 13 | { 14 | return sizeof(struct tf_prng_data); 15 | } 16 | 17 | void tf_prng_seedkey_r(void *sdata, const void *skey) 18 | { 19 | TF_UNIT_TYPE k[TF_NR_KEY_UNITS]; 20 | struct tf_prng_data *rprng = sdata; 21 | 22 | memset(rprng, 0, tf_prng_datasize()); 23 | if (!skey) return; 24 | 25 | memcpy(k, skey, TF_KEY_SIZE); 26 | tfe_init(&rprng->tfe, k); 27 | rprng->init = 1; 28 | 29 | memset(k, 0, TF_KEY_SIZE); 30 | } 31 | 32 | void tf_prng_seedkey(const void *skey) 33 | { 34 | tf_prng_seedkey_r(&tf_prng_sdata, skey); 35 | } 36 | 37 | void tf_prng_genrandom_r(void *sdata, void *result, size_t need) 38 | { 39 | struct tf_prng_data *rprng = sdata; 40 | memset(result, 0, need); 41 | tfe_emit(result, need, &rprng->tfe); 42 | } 43 | 44 | void tf_prng_genrandom(void *result, size_t need) 45 | { 46 | tf_prng_genrandom_r(&tf_prng_sdata, result, need); 47 | } 48 | 49 | void tf_prng_seed_r(void *sdata, TF_UNIT_TYPE seed) 50 | { 51 | TF_UNIT_TYPE k[TF_NR_KEY_UNITS]; 52 | struct tf_prng_data *rprng = sdata; 53 | size_t x; 54 | 55 | memset(rprng, 0, tf_prng_datasize()); 56 | for (x = 0; x < TF_NR_KEY_UNITS; x++) k[x] = seed; 57 | tfe_init(&rprng->tfe, k); 58 | rprng->init = 1; 59 | 60 | memset(k, 0, TF_KEY_SIZE); 61 | } 62 | 63 | void tf_prng_seed(TF_UNIT_TYPE seed) 64 | { 65 | tf_prng_seed_r(&tf_prng_sdata, seed); 66 | } 67 | 68 | TF_UNIT_TYPE tf_prng_random_r(void *sdata) 69 | { 70 | struct tf_prng_data *rprng = sdata; 71 | TF_UNIT_TYPE r; 72 | 73 | if (!rprng->init) return 0; 74 | 75 | tfe_emit(&r, sizeof(r), &rprng->tfe); 76 | return r; 77 | } 78 | 79 | TF_UNIT_TYPE tf_prng_random(void) 80 | { 81 | return tf_prng_random_r(&tf_prng_sdata); 82 | } 83 | 84 | TF_UNIT_TYPE tf_prng_range_r(void *sdata, TF_UNIT_TYPE s, TF_UNIT_TYPE d) 85 | { 86 | TF_UNIT_TYPE c = tf_prng_random_r(sdata); 87 | if (d <= s) return s; 88 | return TF_PRNG_RANGE(c, TF_UNIT_TYPE, s, d); 89 | } 90 | 91 | TF_UNIT_TYPE tf_prng_range(TF_UNIT_TYPE s, TF_UNIT_TYPE d) 92 | { 93 | return tf_prng_range_r(&tf_prng_sdata, s, d); 94 | } 95 | -------------------------------------------------------------------------------- /tfcbc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | 4 | void tf_cbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz) 5 | { 6 | const TF_BYTE_TYPE *uin = in; 7 | TF_BYTE_TYPE *uout = out; 8 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 9 | TF_UNIT_TYPE *uiv = iv; 10 | const TF_UNIT_TYPE *ukey = key; 11 | size_t sl = sz, i; 12 | 13 | if (sl >= TF_BLOCK_SIZE) { 14 | do { 15 | memcpy(x, uin, TF_BLOCK_SIZE); 16 | uin += TF_BLOCK_SIZE; 17 | data_to_words(x, TF_BLOCK_SIZE); 18 | 19 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ uiv[i]; 20 | tf_encrypt_rawblk(x, y, ukey); 21 | memcpy(iv, x, TF_BLOCK_SIZE); 22 | 23 | data_to_words(x, TF_BLOCK_SIZE); 24 | memcpy(uout, x, TF_BLOCK_SIZE); 25 | uout += TF_BLOCK_SIZE; 26 | } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 27 | } 28 | 29 | if (sl) { 30 | memset(x, 0, TF_BLOCK_SIZE); 31 | memcpy(x, uin, sl); 32 | data_to_words(x, TF_BLOCK_SIZE); 33 | 34 | ctr_inc(uiv, TF_NR_BLOCK_UNITS); 35 | tf_encrypt_rawblk(y, uiv, ukey); 36 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 37 | 38 | data_to_words(y, TF_BLOCK_SIZE); 39 | memcpy(uout, y, sl); 40 | } 41 | 42 | memset(x, 0, TF_BLOCK_SIZE); 43 | memset(y, 0, TF_BLOCK_SIZE); 44 | } 45 | 46 | void tf_cbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz) 47 | { 48 | const TF_BYTE_TYPE *uin = in; 49 | TF_BYTE_TYPE *uout = out; 50 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS], t[TF_NR_BLOCK_UNITS]; 51 | TF_UNIT_TYPE *uiv = iv; 52 | const TF_UNIT_TYPE *ukey = key; 53 | size_t sl = sz, i; 54 | 55 | if (sl >= TF_BLOCK_SIZE) { 56 | do { 57 | memcpy(x, uin, TF_BLOCK_SIZE); 58 | uin += TF_BLOCK_SIZE; 59 | data_to_words(x, TF_BLOCK_SIZE); 60 | 61 | memcpy(t, x, TF_BLOCK_SIZE); 62 | tf_decrypt_rawblk(y, x, ukey); 63 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= uiv[i]; 64 | memcpy(iv, t, TF_BLOCK_SIZE); 65 | 66 | data_to_words(y, TF_BLOCK_SIZE); 67 | memcpy(uout, y, TF_BLOCK_SIZE); 68 | uout += TF_BLOCK_SIZE; 69 | } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 70 | } 71 | 72 | if (sl) { 73 | memset(x, 0, TF_BLOCK_SIZE); 74 | memcpy(x, uin, sl); 75 | data_to_words(x, TF_BLOCK_SIZE); 76 | 77 | ctr_inc(uiv, TF_NR_BLOCK_UNITS); 78 | tf_encrypt_rawblk(y, uiv, ukey); 79 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 80 | 81 | data_to_words(y, TF_BLOCK_SIZE); 82 | memcpy(uout, y, sl); 83 | } 84 | 85 | memset(t, 0, TF_BLOCK_SIZE); 86 | memset(x, 0, TF_BLOCK_SIZE); 87 | memset(y, 0, TF_BLOCK_SIZE); 88 | } 89 | -------------------------------------------------------------------------------- /tfpcbc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | 4 | void tf_pcbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz) 5 | { 6 | const TF_BYTE_TYPE *uin = (const TF_BYTE_TYPE *)in; 7 | TF_BYTE_TYPE *uout = (TF_BYTE_TYPE *)out; 8 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 9 | TF_UNIT_TYPE *uiv = (TF_UNIT_TYPE *)iv; 10 | const TF_UNIT_TYPE *ukey = (const TF_UNIT_TYPE *)key; 11 | size_t sl = sz, i; 12 | 13 | if (sl >= TF_BLOCK_SIZE) { 14 | do { 15 | memcpy(x, uin, TF_BLOCK_SIZE); 16 | uin += TF_BLOCK_SIZE; 17 | data_to_words(x, TF_BLOCK_SIZE); 18 | 19 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ uiv[i]; 20 | tf_encrypt_rawblk(y, y, ukey); 21 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) uiv[i] = y[i] ^ x[i]; 22 | 23 | data_to_words(y, TF_BLOCK_SIZE); 24 | memcpy(uout, y, TF_BLOCK_SIZE); 25 | uout += TF_BLOCK_SIZE; 26 | } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 27 | } 28 | 29 | if (sl) { 30 | memset(x, 0, TF_BLOCK_SIZE); 31 | memcpy(x, uin, sl); 32 | data_to_words(x, TF_BLOCK_SIZE); 33 | 34 | ctr_inc(uiv, TF_NR_BLOCK_UNITS); 35 | tf_encrypt_rawblk(y, uiv, ukey); 36 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 37 | 38 | data_to_words(y, TF_BLOCK_SIZE); 39 | memcpy(uout, y, sl); 40 | } 41 | 42 | memset(x, 0, TF_BLOCK_SIZE); 43 | memset(y, 0, TF_BLOCK_SIZE); 44 | } 45 | 46 | void tf_pcbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz) 47 | { 48 | const TF_BYTE_TYPE *uin = (const TF_BYTE_TYPE *)in; 49 | TF_BYTE_TYPE *uout = (TF_BYTE_TYPE *)out; 50 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 51 | TF_UNIT_TYPE *uiv = (TF_UNIT_TYPE *)iv; 52 | const TF_UNIT_TYPE *ukey = (const TF_UNIT_TYPE *)key; 53 | size_t sl = sz, i; 54 | 55 | if (sl >= TF_BLOCK_SIZE) { 56 | do { 57 | memcpy(x, uin, TF_BLOCK_SIZE); 58 | uin += TF_BLOCK_SIZE; 59 | data_to_words(x, TF_BLOCK_SIZE); 60 | 61 | tf_decrypt_rawblk(y, x, ukey); 62 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= uiv[i]; 63 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) uiv[i] = y[i] ^ x[i]; 64 | 65 | data_to_words(y, TF_BLOCK_SIZE); 66 | memcpy(uout, y, TF_BLOCK_SIZE); 67 | uout += TF_BLOCK_SIZE; 68 | } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE); 69 | } 70 | 71 | if (sl) { 72 | memset(x, 0, TF_BLOCK_SIZE); 73 | memcpy(x, uin, sl); 74 | data_to_words(x, TF_BLOCK_SIZE); 75 | 76 | ctr_inc(uiv, TF_NR_BLOCK_UNITS); 77 | tf_encrypt_rawblk(y, uiv, ukey); 78 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 79 | 80 | data_to_words(y, TF_BLOCK_SIZE); 81 | memcpy(uout, y, sl); 82 | } 83 | 84 | memset(x, 0, TF_BLOCK_SIZE); 85 | memset(y, 0, TF_BLOCK_SIZE); 86 | } 87 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | tfcrypt -- high security Threefish encryption tool. 2 | 3 | tfcrypt is a modern, dd(1)-like raw data manipulation tool with embedded strong encryption. 4 | It has precise IO layer inside which can be used to encrypt files, disks and other media, 5 | as well as to manipulate raw data directly, dd(1) style. 6 | 7 | tfcrypt uses Skein and Threefish - public domain SHA3 candidate from famous, 8 | well recognised cryptographer Bruce Schneier, author of famous, still uncracked 9 | Blowfish and Twofish ciphers, which are in use still up to today. 10 | 11 | tfcrypt is actually a frontend for Threefish with (by default) XTS mode of operation. 12 | As a key it uses either password or keyfile, which is then hashed many times 13 | with Skein hash function. 14 | 15 | This program is incompatible with older, "tf1024" tfcrypt version. This version aims to 16 | provide a portable encryption tool to encrypt fixed media such as disks and archive files, 17 | as well as to provide decades long privacy for encrypted data. 18 | Supported modes of operation: CTR, ECB, CBC, XTS and arbitrary long keystream. 19 | 20 | Additionally, this version provides a way to virtually "extend" key size to 1280 bits, 21 | by enabling "fullkey" option or changing "do_full_key" default setting in tfcrypt_defs.h. 22 | In this mode, tweak is ignored, and filled with extended key material. 23 | 24 | THREEFISH NOTES 25 | 26 | Please note that this encryption software includes Threefish cipher, which is terribly 27 | slow on 32 bit systems. This way, it cannot be efficiently used on pure 32 bit machines. 28 | 29 | Threefish contained here is stripped off of it's tweak property, thus, it is turned into a 30 | regular block cipher. To add tweakability, XTS modes of operation is used. 31 | Default wide block size is 4096 bytes. 32 | 33 | SKEIN NOTES 34 | 35 | Unlike "tf1024" implementation, this Skein's MAC feature simply copies user rawkey into 36 | Skein structure context without preprocessing as defined by official Skein implementation. 37 | If you never used MAC feature, then you will get the same hashes as the official Skein. 38 | If you did, then possibly you used it together with encryption. Since this implementation 39 | employs longer key lengths, it's anyway time to move. 40 | 41 | Author believes that there is no problem with just copying raw MAC key versus preprocessing. 42 | A preprocessing is already done by separate Skein sequential invocations on the user long 43 | key material. The code becomes simpler and easier to understand. 44 | 45 | Apart from that, the Skein implementation here is fully conformant to the official one. 46 | 47 | TODO 48 | 49 | Add test vectors from older version, as well as test data for all modes of operation there. 50 | 51 | LICENSE 52 | 53 | This tfcrypt, unlike it's previous version, is copyrighted: 54 | 55 | Copyright (C) Andrey Rys , 2012-2019. 56 | 57 | It maybe freely used by anyone who agrees to the terms and conditions of the MIT license. 58 | 59 | tfcipher code parts used are public domain, and maybe reused freely without license. 60 | -------------------------------------------------------------------------------- /tfcore.h: -------------------------------------------------------------------------------- 1 | #ifndef _THREEFISH_CIPHER_CORE_HEADER 2 | #define _THREEFISH_CIPHER_CORE_HEADER 3 | 4 | #ifndef _THREEFISH_CIPHER_DEFINITIONS_HEADER 5 | #error Threefish definitions header is required! Include tfdef.h first. 6 | #endif 7 | 8 | #define ROL(x, s, max) ((x << s) | (x >> (-s & (max-1)))) 9 | #define ROR(x, s, max) ((x >> s) | (x << (-s & (max-1)))) 10 | 11 | #define KE_MIX(x, y, k1, k2, sl) \ 12 | do { \ 13 | x += k1; \ 14 | y += x; \ 15 | y += k2; \ 16 | x = ROL(x, sl, TF_UNIT_BITS); \ 17 | x ^= y; \ 18 | } while (0) 19 | 20 | #define BE_MIX(x, y, sl) \ 21 | do { \ 22 | x += y; \ 23 | y = ROL(y, sl, TF_UNIT_BITS); \ 24 | y ^= x; \ 25 | } while (0) 26 | 27 | #define KD_MIX(x, y, k1, k2, sr) \ 28 | do { \ 29 | x ^= y; \ 30 | x = ROR(x, sr, TF_UNIT_BITS); \ 31 | y -= x; \ 32 | y -= k2; \ 33 | x -= k1; \ 34 | } while (0) 35 | 36 | #define BD_MIX(x, y, sr) \ 37 | do { \ 38 | y ^= x; \ 39 | y = ROR(y, sr, TF_UNIT_BITS); \ 40 | x -= y; \ 41 | } while (0) 42 | 43 | #define THREEFISH_CONST 0x1bd11bdaa9fc1a22ULL 44 | 45 | #if defined(TF_256BITS) 46 | enum tf_rotations { 47 | TFS_KS01 = 14, TFS_KS02 = 16, TFS_KS03 = 25, TFS_KS04 = 33, 48 | TFS_BS01 = 52, TFS_BS02 = 57, TFS_BS03 = 23, TFS_BS04 = 40, 49 | TFS_BS05 = 5, TFS_BS06 = 37, TFS_BS07 = 46, TFS_BS08 = 12, 50 | TFS_BS09 = 58, TFS_BS10 = 22, TFS_BS11 = 32, TFS_BS12 = 32, 51 | }; 52 | #elif defined(TF_512BITS) 53 | enum tf_rotations { 54 | TFS_KS01 = 46, TFS_KS02 = 36, TFS_KS03 = 19, TFS_KS04 = 37, 55 | TFS_KS05 = 39, TFS_KS06 = 30, TFS_KS07 = 34, TFS_KS08 = 24, 56 | TFS_BS01 = 33, TFS_BS02 = 27, TFS_BS03 = 14, TFS_BS04 = 42, 57 | TFS_BS05 = 17, TFS_BS06 = 49, TFS_BS07 = 36, TFS_BS08 = 39, 58 | TFS_BS09 = 44, TFS_BS10 = 9, TFS_BS11 = 54, TFS_BS12 = 56, 59 | TFS_BS13 = 13, TFS_BS14 = 50, TFS_BS15 = 10, TFS_BS16 = 17, 60 | TFS_BS17 = 25, TFS_BS18 = 29, TFS_BS19 = 39, TFS_BS20 = 43, 61 | TFS_BS21 = 8, TFS_BS22 = 35, TFS_BS23 = 56, TFS_BS24 = 22, 62 | }; 63 | #elif defined(TF_1024BITS) 64 | enum tf_rotations { 65 | TFS_KS01 = 24, TFS_KS02 = 13, TFS_KS03 = 8, TFS_KS04 = 47, 66 | TFS_KS05 = 8, TFS_KS06 = 17, TFS_KS07 = 22, TFS_KS08 = 37, 67 | TFS_KS09 = 41, TFS_KS10 = 9, TFS_KS11 = 37, TFS_KS12 = 31, 68 | TFS_KS13 = 12, TFS_KS14 = 47, TFS_KS15 = 44, TFS_KS16 = 30, 69 | TFS_BS01 = 38, TFS_BS02 = 19, TFS_BS03 = 10, TFS_BS04 = 55, 70 | TFS_BS05 = 49, TFS_BS06 = 18, TFS_BS07 = 23, TFS_BS08 = 52, 71 | TFS_BS09 = 33, TFS_BS10 = 4, TFS_BS11 = 51, TFS_BS12 = 13, 72 | TFS_BS13 = 34, TFS_BS14 = 41, TFS_BS15 = 59, TFS_BS16 = 17, 73 | TFS_BS17 = 5, TFS_BS18 = 20, TFS_BS19 = 48, TFS_BS20 = 41, 74 | TFS_BS21 = 47, TFS_BS22 = 28, TFS_BS23 = 16, TFS_BS24 = 25, 75 | TFS_BS25 = 16, TFS_BS26 = 34, TFS_BS27 = 56, TFS_BS28 = 51, 76 | TFS_BS29 = 4, TFS_BS30 = 53, TFS_BS31 = 42, TFS_BS32 = 41, 77 | TFS_BS33 = 31, TFS_BS34 = 44, TFS_BS35 = 47, TFS_BS36 = 46, 78 | TFS_BS37 = 19, TFS_BS38 = 42, TFS_BS39 = 44, TFS_BS40 = 25, 79 | TFS_BS41 = 9, TFS_BS42 = 48, TFS_BS43 = 35, TFS_BS44 = 52, 80 | TFS_BS45 = 23, TFS_BS46 = 31, TFS_BS47 = 37, TFS_BS48 = 20, 81 | }; 82 | #else 83 | #error No cipher was defined! Aborting build. 84 | #endif 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /tfc_vars.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | #include "tfcrypt_defs.h" 31 | 32 | char *progname; 33 | int exitcode; 34 | pid_t progpid; 35 | 36 | tfc_byte key[TF_KEY_SIZE], ctr[TF_BLOCK_SIZE], xtskey[TF_KEY_SIZE], mackey[TF_FROM_BITS(TF_MAX_BITS)], tweak[TF_TWEAK_SIZE]; 37 | struct skein sk; 38 | struct tfe_stream tfe; 39 | tfc_byte srcblk[TFC_BLKSIZE], dstblk[TFC_BLKSIZE], *pblk; 40 | tfc_byte macvrfy[SKEIN_DIGEST_SIZE], macresult[SKEIN_DIGEST_SIZE]; 41 | tfc_byte tmpdata[TFC_TMPSIZE]; 42 | 43 | char *randsource = TFC_DEFAULT_RANDSOURCE; 44 | 45 | tfc_fsize iseek_blocks, iseek, oseek, maxlen = NOFSIZE, ftrunc_dfd = NOFSIZE; 46 | tfc_fsize total_processed_src, total_processed_dst, total_written_dst; 47 | tfc_fsize delta_processed; 48 | tfc_fsize genrandom_nr_bytes, genzero_nr_bytes; 49 | tfc_fsize rdpos = NOFSIZE; 50 | tfc_fsize maxkeylen = NOFSIZE, keyoffset; 51 | int sfd, kfd = -1, dfd = 1; 52 | struct stat s_stat; 53 | size_t blksize = TFC_BLKSIZE, xtsblocks = TFC_XTSBLOCKS; 54 | char pwdask[512], pwdagain[512]; 55 | 56 | size_t lio, lrem, ldone, lblock; 57 | size_t ctrsz = NOSIZE; 58 | 59 | struct sigaction sigact; 60 | 61 | size_t sksum_turns; 62 | 63 | int do_edcrypt = TFC_DO_ENCRYPT, do_stop, quiet, error_action; 64 | int counter_opt, mackey_opt, do_mac, do_outfmt = TFC_OUTFMT_B64, rawkey; 65 | int idx, write_flags; 66 | tfc_yesno catch_all_errors, ignore_seek_errors, password, overwrite_source, do_fsync, do_pad, do_ftrunc = TFC_NO_FTRUNC; 67 | tfc_yesno do_preserve_time, do_stats_in_gibs, do_statline_dynamic = YES, do_less_stats, show_pid, read_only; 68 | tfc_yesno no_repeat, do_full_hexdump = YES, verbose, statline_was_shown, show_secrets, show_when_done; 69 | char *srcfname = TFC_STDIN_NAME, *dstfname = TFC_STDOUT_NAME, *do_mac_file, *counter_file, *sksum_hashlist_file; 70 | char *saltf, *genkeyf, *mackeyf, *tweakf; 71 | char *pw_prompt, *mac_pw_prompt; 72 | tfc_useconds status_timer, bench_timer; 73 | tfc_useconds total_time, current_time, delta_time; 74 | 75 | struct getpasswd_state getps; 76 | -------------------------------------------------------------------------------- /tfc_bench.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | void do_benchmark(tfc_useconds useconds, double dseconds) 32 | { 33 | size_t x, lblock; 34 | 35 | for (x = 1; x < NSIG; x++) signal(x, SIG_IGN); 36 | memset(&sigact, 0, sizeof(sigact)); 37 | sigact.sa_flags = SA_RESTART; 38 | sigact.sa_handler = print_crypt_status; 39 | sigaction(SIGINT, &sigact, NULL); 40 | sigaction(SIGTERM, &sigact, NULL); 41 | sigaction(SIGTSTP, &sigact, NULL); 42 | sigaction(SIGALRM, &sigact, NULL); 43 | setup_next_alarm(useconds); 44 | memset(&sigact, 0, sizeof(struct sigaction)); 45 | 46 | tfc_getcurtime(&delta_time); 47 | 48 | tfc_getrandom(key, sizeof(key)); 49 | tfc_getrandom(ctr, sizeof(ctr)); 50 | if (do_mac != NO) { 51 | tfc_getrandom(mackey, sizeof(mackey)); 52 | skein_init_key(&sk, mackey, macbits); 53 | } 54 | if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr); 55 | if (ctr_mode == TFC_MODE_XTS) tfc_getrandom(xtskey, sizeof(xtskey)); 56 | 57 | tfc_nfsay(stdout, "%s: doing %s benchmark for %.4f seconds ... ", tfc_format_pid(progname), tfc_modename(ctr_mode), dseconds); 58 | 59 | do_stop = NO; 60 | while (1) { 61 | if (do_stop) break; 62 | 63 | lblock = blk_len_adj(NOFSIZE, total_processed_src, blksize); 64 | total_processed_src += lblock; 65 | 66 | if (do_mac != NO) skein_update(&sk, srcblk, lblock); 67 | 68 | if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, srcblk, srcblk, lblock); 69 | else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, srcblk, srcblk, lblock); 70 | else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_ENCRYPT) 71 | tf_xts_encrypt(key, xtskey, ctr, srcblk, srcblk, lblock, xtsblocks); 72 | else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_DECRYPT) 73 | tf_xts_decrypt(key, xtskey, ctr, srcblk, srcblk, lblock, xtsblocks); 74 | else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_ENCRYPT) 75 | tf_ecb_encrypt(key, srcblk, srcblk, lblock); 76 | else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_DECRYPT) 77 | tf_ecb_decrypt(key, srcblk, srcblk, lblock); 78 | else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_ENCRYPT) 79 | tf_cbc_encrypt(key, ctr, srcblk, srcblk, lblock); 80 | else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_DECRYPT) 81 | tf_cbc_decrypt(key, ctr, srcblk, srcblk, lblock); 82 | else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_ENCRYPT) 83 | tf_pcbc_encrypt(key, ctr, srcblk, srcblk, lblock); 84 | else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_DECRYPT) 85 | tf_pcbc_decrypt(key, ctr, srcblk, srcblk, lblock); 86 | 87 | delta_processed += lblock; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /skein.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | #include "tfcore.h" 4 | #include "skein.h" 5 | 6 | static inline void puthash(TF_BYTE_TYPE *dst, const TF_UNIT_TYPE *src, size_t l) 7 | { 8 | size_t n; 9 | for (n = 0; n < l; n++) dst[n] = (TF_BYTE_TYPE)(src[n>>3] >> (TF_SIZE_UNIT*(n&7))); 10 | } 11 | 12 | static void skein_process_blk(struct skein *sk, const TF_BYTE_TYPE *in, size_t szin, size_t l) 13 | { 14 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 15 | size_t i; 16 | 17 | do { 18 | sk->key[TF_TWEAK_WORD1] += l; 19 | 20 | memcpy(x, in, TF_BLOCK_SIZE); 21 | data_to_words(x, TF_BLOCK_SIZE); 22 | in += TF_BLOCK_SIZE; 23 | 24 | sk->key[TF_NR_KEY_UNITS-1-3] = THREEFISH_CONST; 25 | for (i = 0; i < TF_NR_KEY_UNITS-1-3; i++) 26 | sk->key[TF_NR_KEY_UNITS-1-3] ^= sk->key[i]; 27 | sk->key[TF_TWEAK_WORD3] = sk->key[TF_TWEAK_WORD1] ^ sk->key[TF_TWEAK_WORD2]; 28 | 29 | tf_encrypt_rawblk(y, x, sk->key); 30 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) sk->key[i] = y[i] ^ x[i]; 31 | 32 | sk->key[TF_TWEAK_WORD2] &= ~SKEIN_FLAG_FIRST; 33 | } while (--szin); 34 | } 35 | 36 | void skein_init_key(struct skein *sk, const void *ukey, size_t bits) 37 | { 38 | TF_UNIT_TYPE cfg[TF_NR_BLOCK_UNITS]; 39 | 40 | memset(sk, 0, sizeof(struct skein)); 41 | 42 | if (ukey) { 43 | memcpy(sk->key, ukey, TF_FROM_BITS(TF_MAX_BITS)); 44 | data_to_words(sk->key, TF_FROM_BITS(TF_MAX_BITS)); 45 | } 46 | 47 | sk->bits = bits; 48 | sk->carry_bytes = 0; 49 | 50 | memset(cfg, 0, sizeof(cfg)); 51 | cfg[0] = TF_SWAP_FUNC(((TF_UNIT_TYPE)SKEIN_VERSION << 32) + (TF_UNIT_TYPE)SKEIN_ID); 52 | cfg[1] = TF_SWAP_FUNC(bits); 53 | 54 | sk->key[TF_TWEAK_WORD1] = 0; 55 | sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_CFG | SKEIN_FLAG_FIRST | SKEIN_FLAG_LAST; 56 | 57 | skein_process_blk(sk, (TF_BYTE_TYPE *)cfg, 1, 32); 58 | 59 | sk->key[TF_TWEAK_WORD1] = 0; 60 | sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_MSG | SKEIN_FLAG_FIRST; 61 | } 62 | 63 | void skein_init(struct skein *sk, size_t bits) 64 | { 65 | skein_init_key(sk, NULL, bits); 66 | } 67 | 68 | void skein_update(struct skein *sk, const void *msg, size_t msgsz) 69 | { 70 | const TF_BYTE_TYPE *umsg = msg; 71 | size_t n; 72 | 73 | if (msgsz + sk->carry_bytes > TF_BLOCK_SIZE) { 74 | if (sk->carry_bytes) { 75 | n = TF_BLOCK_SIZE - sk->carry_bytes; 76 | if (n) { 77 | memcpy(&sk->carry_block[sk->carry_bytes], umsg, n); 78 | msgsz -= n; 79 | umsg += n; 80 | sk->carry_bytes += n; 81 | } 82 | skein_process_blk(sk, sk->carry_block, 1, TF_BLOCK_SIZE); 83 | sk->carry_bytes = 0; 84 | } 85 | 86 | if (msgsz > TF_BLOCK_SIZE) { 87 | n = (msgsz-1) / TF_BLOCK_SIZE; 88 | skein_process_blk(sk, umsg, n, TF_BLOCK_SIZE); 89 | msgsz -= n * TF_BLOCK_SIZE; 90 | umsg += n * TF_BLOCK_SIZE; 91 | } 92 | } 93 | 94 | if (msgsz) { 95 | memcpy(&sk->carry_block[sk->carry_bytes], umsg, msgsz); 96 | sk->carry_bytes += msgsz; 97 | } 98 | } 99 | 100 | void skein_final(void *result, struct skein *sk) 101 | { 102 | TF_BYTE_TYPE *uresult = result; 103 | TF_UNIT_TYPE key[TF_NR_BLOCK_UNITS], *X; 104 | size_t i, b, n; 105 | 106 | if (sk->carry_bytes < TF_BLOCK_SIZE) 107 | memset(sk->carry_block+sk->carry_bytes, 0, TF_BLOCK_SIZE-sk->carry_bytes); 108 | sk->key[TF_TWEAK_WORD2] |= SKEIN_FLAG_LAST; 109 | skein_process_blk(sk, sk->carry_block, 1, sk->carry_bytes); 110 | 111 | b = (sk->bits + 7) / 8; 112 | 113 | memset(sk->carry_block, 0, sizeof(sk->carry_block)); 114 | memcpy(key, sk->key, sizeof(key)); 115 | 116 | for (i = 0; (i * TF_BLOCK_SIZE) < b; i++) { 117 | X = (TF_UNIT_TYPE *)sk->carry_block; 118 | X[0] = TF_SWAP_FUNC((TF_UNIT_TYPE)i); 119 | sk->key[TF_TWEAK_WORD1] = 0; 120 | sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_OUT | SKEIN_FLAG_FIRST | SKEIN_FLAG_LAST; 121 | sk->carry_bytes = 0; 122 | 123 | skein_process_blk(sk, sk->carry_block, 1, TF_SIZE_UNIT); 124 | n = b-(i*TF_BLOCK_SIZE); 125 | if (n >= TF_BLOCK_SIZE) n = TF_BLOCK_SIZE; 126 | puthash(uresult+(i*TF_BLOCK_SIZE), sk->key, n); 127 | memcpy(sk->key, key, TF_BLOCK_SIZE); 128 | } 129 | 130 | memset(sk, 0, sizeof(struct skein)); 131 | } 132 | -------------------------------------------------------------------------------- /tfc_conf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | void read_defaults(const char *path, tfc_yesno noerr) 32 | { 33 | static char ln[4096]; 34 | char *s, *d, *t, *stoi; 35 | FILE *f; 36 | tfc_yesno valid = NO; 37 | 38 | f = fopen(path, "r"); 39 | if (!f) { 40 | if (noerr == YES) return; 41 | xerror(NO, NO, YES, "%s", path); 42 | } 43 | 44 | while (1) { 45 | memset(ln, 0, sizeof(ln)); 46 | if (xfgets(ln, sizeof(ln), f) != YES) break; 47 | 48 | if (valid == NO) { 49 | if (!strcmp(ln, "# tfcrypt.defs")) valid = YES; 50 | continue; 51 | } 52 | 53 | if (str_empty(ln) || ln[0] == '#') continue; 54 | 55 | s = ln; 56 | d = strchr(s, '='); 57 | if (!d) continue; 58 | *d = 0; d++; 59 | 60 | /* yay! GOTO hell! You'll "like" it! */ 61 | _spc1: t = strchr(s, ' '); 62 | if (!t) goto _spc2; 63 | *t = 0; goto _spc1; 64 | _spc2: t = strchr(d, ' '); 65 | if (!t) goto _nspc; 66 | *t = 0; d = t+1; goto _spc2; 67 | _nspc: 68 | if (!strcmp(s, "nr_turns")) { 69 | nr_turns = strtoul(d, &stoi, 10); 70 | if (!str_empty(stoi)) xerror(NO, YES, YES, "[%s] nr_turns=%s: invalid number of turns", path, d); 71 | } 72 | else if (!strcmp(s, "ctr_mode")) { 73 | if (!strcasecmp(d, "ctr")) 74 | ctr_mode = TFC_MODE_CTR; 75 | else if (!strcasecmp(d, "stream")) 76 | ctr_mode = TFC_MODE_STREAM; 77 | else if (!strcasecmp(d, "cbc")) 78 | ctr_mode = TFC_MODE_CBC; 79 | else if (!strcasecmp(d, "pcbc")) 80 | ctr_mode = TFC_MODE_PCBC; 81 | else if (!strcasecmp(d, "ecb")) 82 | ctr_mode = TFC_MODE_ECB; 83 | else if (!strcasecmp(d, "xts")) 84 | ctr_mode = TFC_MODE_XTS; 85 | else xerror(NO, YES, YES, "[%s] ctr_mode=%s: invalid mode of operation", path, d); 86 | } 87 | else if (!strcmp(s, "tfc_salt")) { 88 | memset(tfc_salt, 0, TFC_MAX_SALT); 89 | tfc_saltsz = base64_decode((char *)tfc_salt, TFC_MAX_SALT, d, strlen(d)); 90 | } 91 | else if (!strcmp(s, "macbits")) { 92 | macbits = strtoul(d, &stoi, 10); 93 | if (macbits == 0 || !str_empty(stoi) || macbits < 8 94 | || macbits > TF_MAX_BITS || macbits % 8) 95 | xerror(NO, YES, YES, "[%s] macbits=%s: invalid MAC bits setting", path, d); 96 | } 97 | else if (!strcmp(s, "do_full_key")) { 98 | if (!strcasecmp(d, "yes")) do_full_key = YES; 99 | else if (!strcasecmp(d, "no")) do_full_key = NO; 100 | } 101 | else xerror(NO, YES, YES, "[%s] %s: unknown keyword", path, s); 102 | } 103 | 104 | memset(ln, 0, sizeof(ln)); 105 | fclose(f); 106 | } 107 | 108 | void hash_defaults(char *uhash, size_t szuhash) 109 | { 110 | struct skein sk; 111 | char shash[56]; 112 | const char *mode; 113 | tfc_byte hash[TF_FROM_BITS(256)]; 114 | 115 | skein_init(&sk, 256); 116 | 117 | skein_update(&sk, tfc_salt, tfc_saltsz); 118 | 119 | memset(shash, 0, sizeof(shash)); 120 | sprintf(shash, "%zu", nr_turns); 121 | skein_update(&sk, shash, strlen(shash)); 122 | 123 | mode = tfc_modename(ctr_mode); 124 | skein_update(&sk, mode, strlen(mode)); 125 | 126 | memset(shash, 0, sizeof(shash)); 127 | sprintf(shash, "%zu", macbits); 128 | skein_update(&sk, shash, strlen(shash)); 129 | 130 | skein_update(&sk, do_full_key ? "1" : "0", 1); 131 | 132 | skein_final(hash, &sk); 133 | memset(shash, 0, sizeof(shash)); 134 | base64_encode(shash, (const char *)hash, sizeof(hash)); 135 | memset(hash, 0, sizeof(hash)); 136 | 137 | xstrlcpy(uhash, shash, szuhash); 138 | } 139 | -------------------------------------------------------------------------------- /mhexdump.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #undef MACHINE_16BIT 37 | #undef MACHINE_32BIT 38 | #undef MACHINE_64BIT 39 | 40 | #if UINTPTR_MAX == UINT32_MAX 41 | #define MACHINE_32BIT 42 | #elif UINTPTR_MAX == UINT64_MAX 43 | #define MACHINE_64BIT 44 | #elif UINTPTR_MAX == UINT16_MAX 45 | #define MACHINE_16BIT 46 | #endif 47 | 48 | struct mhexdump_args { 49 | const void *data; 50 | size_t szdata; 51 | int group; 52 | int hexgroup; 53 | int hexstr; 54 | int addaddr; 55 | int newline; 56 | FILE *fp; 57 | int closef; 58 | }; 59 | 60 | #if defined(MACHINE_32BIT) 61 | #define ADDRFMT "%08x: " 62 | #define paddr (mha->addaddr == 2 ? (uint32_t)P+(x*mha->group) : (x*mha->group)) 63 | #elif defined(MACHINE_64BIT) 64 | #define ADDRFMT "%016lx: " 65 | #define paddr (mha->addaddr == 2 ? (uint64_t)P+(x*mha->group) : (x*mha->group)) 66 | #elif defined(MACHINE_16BIT) 67 | #define ADDRFMT "%04x: " 68 | #define paddr (mha->addaddr == 2 ? (uint16_t)P+(x*mha->group) : (x*mha->group)) 69 | #else 70 | #error No machine word size detected! 71 | #endif 72 | 73 | #define BYTEOUT ((unsigned char)P[y+(x*mha->group)]) 74 | 75 | int fmhexdump(const struct mhexdump_args *mha) 76 | { 77 | const unsigned char *P = mha->data; 78 | int x, y; 79 | 80 | if (!mha->fp || !mha->data || mha->szdata == 0) return 0; 81 | 82 | for (x = 0; x < mha->szdata/mha->group; x++) { 83 | if (mha->addaddr) fprintf(mha->fp, ADDRFMT, paddr); 84 | for (y = 0; y < mha->group; y++) { 85 | fprintf(mha->fp, "%02hhx", BYTEOUT); 86 | if (((y+1) % mha->hexgroup) == 0 && (y != (mha->group)-1)) fputc(' ', mha->fp); 87 | } 88 | if (mha->hexstr) fprintf(mha->fp, " "); 89 | if (mha->hexstr) for (y = 0; y < mha->group; y++) { 90 | if (isprint(BYTEOUT)) fprintf(mha->fp, "%c", BYTEOUT); 91 | else fputc('.', mha->fp); 92 | } 93 | if (mha->szdata/mha->group == 1 && mha->szdata-mha->group == 0) { 94 | if (mha->newline) fputc('\n', mha->fp); 95 | } 96 | else fputc('\n', mha->fp); 97 | } 98 | if (mha->szdata-(x*mha->group) == 0) goto _ret; 99 | 100 | if (mha->addaddr) fprintf(mha->fp, ADDRFMT, paddr); 101 | for (y = 0; y < mha->szdata-(x*mha->group); y++) { 102 | fprintf(mha->fp, "%02hhx", BYTEOUT); 103 | if (((y+1) % mha->hexgroup) == 0) fputc(' ', mha->fp); 104 | } 105 | if (mha->hexstr) for (; y < mha->group; y++) { 106 | fprintf(mha->fp, " "); 107 | if (((y+1) % mha->hexgroup) == 0 && (y != mha->group-1)) fputc(' ', mha->fp); 108 | } 109 | if (mha->hexstr) fprintf(mha->fp, " "); 110 | if (mha->hexstr) for (y = 0; y < mha->szdata-(x*mha->group); y++) { 111 | if (isprint(BYTEOUT)) fprintf(mha->fp, "%c", BYTEOUT); 112 | else fputc('.', mha->fp); 113 | } 114 | 115 | if (mha->newline) fputc('\n', mha->fp); 116 | 117 | _ret: fflush(mha->fp); 118 | if (mha->closef) fclose(mha->fp); 119 | return 1; 120 | } 121 | 122 | #undef BYTEOUT 123 | 124 | int xmhexdump(int to, const void *data, size_t szdata, int hgroup, int hexstr, int newline) 125 | { 126 | struct mhexdump_args mha; 127 | 128 | if (hgroup == 0) hgroup = 16; 129 | 130 | memset(&mha, 0, sizeof(struct mhexdump_args)); 131 | mha.fp = (to == 2) ? stderr : stdout; 132 | mha.closef = 0; 133 | mha.data = data; 134 | mha.szdata = szdata; 135 | mha.group = hgroup; 136 | mha.hexgroup = hgroup; 137 | mha.hexstr = hexstr; 138 | mha.addaddr = 0; 139 | mha.newline = newline; 140 | 141 | return fmhexdump(&mha); 142 | } 143 | -------------------------------------------------------------------------------- /tfdef.h: -------------------------------------------------------------------------------- 1 | #ifndef _THREEFISH_CIPHER_DEFINITIONS_HEADER 2 | #define _THREEFISH_CIPHER_DEFINITIONS_HEADER 3 | 4 | #ifndef _DEFAULT_SOURCE 5 | #define _DEFAULT_SOURCE 6 | #endif 7 | 8 | #ifndef _BSD_SOURCE 9 | #define _BSD_SOURCE 10 | #endif 11 | 12 | /* config block */ 13 | /* #define TF_256BITS */ 14 | /* #define TF_512BITS */ 15 | #define TF_1024BITS 16 | /* #define TF_NO_ENDIAN */ 17 | /* #define TF_BIG_ENDIAN */ 18 | 19 | #include 20 | #include 21 | #ifndef TF_NO_ENDIAN 22 | #include 23 | #else 24 | #undef TF_BIG_ENDIAN 25 | #endif 26 | 27 | #define TF_UNIT_TYPE uint64_t 28 | 29 | #ifdef TF_BIG_ENDIAN 30 | #define TF_SWAP_FUNC htobe64 31 | #else 32 | #define TF_SWAP_FUNC htole64 33 | #endif 34 | 35 | #if defined(TF_256BITS) 36 | #define TF_NR_BLOCK_BITS 256 37 | #define TF_NR_KEY_BITS 512 38 | #define TF_NR_BLOCK_UNITS 4 39 | #define TF_NR_KEY_UNITS 8 40 | #define IRR_POLY_CONST 0x425 41 | #elif defined(TF_512BITS) 42 | #define TF_NR_BLOCK_BITS 512 43 | #define TF_NR_KEY_BITS 768 44 | #define TF_NR_BLOCK_UNITS 8 45 | #define TF_NR_KEY_UNITS 12 46 | #define IRR_POLY_CONST 0x125 47 | #elif defined(TF_1024BITS) 48 | #define TF_NR_BLOCK_BITS 1024 49 | #define TF_NR_KEY_BITS 1280 50 | #define TF_NR_BLOCK_UNITS 16 51 | #define TF_NR_KEY_UNITS 20 52 | #define IRR_POLY_CONST 0x80043 53 | #else 54 | #error Please edit tfdef.h include file and select at least one cipher! 55 | #endif 56 | 57 | #define TF_BYTE_TYPE uint8_t 58 | #define TF_SIZE_UNIT (sizeof(TF_UNIT_TYPE)) 59 | #define TF_BLOCK_SIZE (TF_SIZE_UNIT * TF_NR_BLOCK_UNITS) 60 | #define TF_KEY_SIZE (TF_SIZE_UNIT * TF_NR_KEY_UNITS) 61 | 62 | #define TF_NR_TWEAK_UNITS 2 63 | #define TF_NR_TWEAK_BITS 128 64 | #define TF_TWEAK_SIZE (TF_SIZE_UNIT * TF_NR_TWEAK_UNITS) 65 | #define TF_TWEAKEY_SIZE (TF_KEY_SIZE - (2 * TF_TWEAK_SIZE)) 66 | #define TF_NR_TWEAKEY_BITS (TF_NR_KEY_BITS - (2 * TF_NR_TWEAK_BITS)) 67 | #define TF_TWEAK_WORD1 (TF_NR_KEY_UNITS-3) 68 | #define TF_TWEAK_WORD2 (TF_NR_KEY_UNITS-2) 69 | #define TF_TWEAK_WORD3 (TF_NR_KEY_UNITS-1) 70 | 71 | #define TF_TO_BITS(x) ((x) * 8) 72 | #define TF_FROM_BITS(x) ((x) / 8) 73 | #define TF_MAX_BITS TF_NR_BLOCK_BITS 74 | #define TF_UNIT_BITS (TF_SIZE_UNIT * 8) 75 | 76 | #define TF_TO_BLOCKS(x) ((x) / TF_BLOCK_SIZE) 77 | #define TF_FROM_BLOCKS(x) ((x) * TF_BLOCK_SIZE) 78 | #define TF_BLOCKS_TO_BYTES(x) TF_FROM_BLOCKS(x) 79 | #define TF_BLOCKS_FROM_BYTES(x) TF_TO_BLOCKS(x) 80 | 81 | static inline void data_to_words(void *p, size_t l) 82 | { 83 | #ifndef TF_NO_ENDIAN 84 | size_t idx; 85 | TF_UNIT_TYPE *P = p; 86 | TF_UNIT_TYPE t; 87 | 88 | for (idx = 0; idx < (l/sizeof(TF_UNIT_TYPE)); idx++) { 89 | t = TF_SWAP_FUNC(P[idx]); 90 | P[idx] = t; 91 | } 92 | #endif 93 | } 94 | 95 | static inline void xor_block(void *dst, const void *src, size_t sz) 96 | { 97 | const size_t *sx = (const size_t *)src; 98 | const TF_BYTE_TYPE *usx = (const TF_BYTE_TYPE *)src; 99 | size_t *dx = (size_t *)dst; 100 | TF_BYTE_TYPE *udx = (TF_BYTE_TYPE *)dst; 101 | size_t sl = sz; 102 | 103 | for (sl = 0; sl < (sz / sizeof(size_t)); sl++) dx[sl] ^= sx[sl]; 104 | if (sz - (sl * sizeof(size_t))) for (sl *= sizeof(size_t); sl < sz; sl++) udx[sl] ^= usx[sl]; 105 | } 106 | 107 | static inline void ctr_inc(TF_UNIT_TYPE *x, size_t xl) 108 | { 109 | size_t z; 110 | 111 | for (z = 0; z < xl; z++) { 112 | x[z] = ((x[z] + (TF_UNIT_TYPE)1) & ((TF_UNIT_TYPE)~0)); 113 | if (x[z]) break; 114 | } 115 | } 116 | 117 | static inline void ctr_add(TF_UNIT_TYPE *x, size_t xl, const TF_UNIT_TYPE *y, size_t yl) 118 | { 119 | size_t z, cf; 120 | TF_UNIT_TYPE t; 121 | 122 | for (z = 0, cf = 0; z < xl; z++) { 123 | t = x[z] + (z >= yl ? (TF_UNIT_TYPE)0 : y[z]) + cf; 124 | if (cf) cf = (x[z] >= t ? 1 : 0); 125 | else cf = (x[z] > t ? 1 : 0); 126 | x[z] = t; 127 | } 128 | } 129 | 130 | struct tfe_stream; 131 | 132 | #define tf_convkey(k) do { data_to_words(k, TF_KEY_SIZE); } while (0) 133 | 134 | void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K); 135 | void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K); 136 | 137 | void tf_encrypt_block(const void *key, void *out, const void *in); 138 | void tf_decrypt_block(const void *key, void *out, const void *in); 139 | 140 | void tf_ctr_set(void *ctr, const void *sctr, size_t sctrsz); 141 | void tf_ctr_crypt(const void *key, void *ctr, void *out, const void *in, size_t sz); 142 | 143 | void tf_tweak_set(void *key, const void *tweak); 144 | 145 | void tf_stream_crypt(struct tfe_stream *tfe, void *out, const void *in, size_t sz); 146 | void tf_ecb_encrypt(const void *key, void *out, const void *in, size_t sz); 147 | void tf_ecb_decrypt(const void *key, void *out, const void *in, size_t sz); 148 | void tf_cbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz); 149 | void tf_cbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz); 150 | void tf_pcbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz); 151 | void tf_pcbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz); 152 | void tf_xts_encrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi); 153 | void tf_xts_decrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi); 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /tfc_conv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | static const char *tfc_size_scale[] = {"B", "K", "M", "G", "T", "P"}; 32 | 33 | void tfc_data_to_words64(void *data, size_t szdata) 34 | { 35 | #ifndef TF_NO_ENDIAN 36 | size_t idx; 37 | uint64_t *d = data; 38 | uint64_t t; 39 | 40 | for (idx = 0; idx < (szdata/sizeof(uint64_t)); idx++) { 41 | #ifdef TF_BIG_ENDIAN 42 | t = htobe64(d[idx]); 43 | #else 44 | t = htole64(d[idx]); 45 | #endif 46 | d[idx] = t; 47 | } 48 | #endif 49 | } 50 | 51 | static tfc_yesno tfc_is_number(const char *s) 52 | { 53 | char *p; 54 | if (!s || str_empty(s)) return NO; 55 | strtol(s, &p, 10); 56 | return str_empty(p) ? YES : NO; 57 | } 58 | 59 | tfc_fsize tfc_humanfsize(const char *s, char **stoi) 60 | { 61 | char pfx[2], T[2], N[48], *ss; 62 | int base = 10; 63 | size_t l; 64 | tfc_fsize gbgib = 0, ret = 0; 65 | 66 | if (!s) return 0; 67 | 68 | memset(N, 0, sizeof(N)); 69 | memset(pfx, 0, sizeof(pfx)); 70 | memset(T, 0, sizeof(T)); 71 | 72 | if (!strncmp(s, "0x", 2)) { 73 | s += 2; 74 | base = 16; 75 | } 76 | else if (s[0] == '0') base = 0; 77 | 78 | l = strnlen(s, sizeof(N)-1); 79 | memcpy(N, s, l); 80 | 81 | ss = strchr(N, ':'); 82 | if (ss && ss[1] && (ss[1] == '+' || ss[1] == '-' || ss[1] == '*' || ss[1] == '/')) { 83 | ss[0] = 0; 84 | l = strnlen(N, sizeof(N)-1); 85 | } 86 | 87 | if (base == 16) goto _nopfx; 88 | 89 | pfx[0] = N[l-1]; 90 | if (tfc_is_number(pfx) == NO) N[l-1] = 0; 91 | 92 | _nopfx: 93 | *stoi = NULL; 94 | if (tfc_is_number(pfx) || pfx[0] == 'B' || pfx[0] == 'c') ret = strtoull(N, stoi, base); 95 | else if (pfx[0] == 'W') ret = strtoull(N, stoi, base)*2; 96 | else if (pfx[0] == 'I') ret = strtoull(N, stoi, base)*4; 97 | else if (pfx[0] == 'L') ret = strtoull(N, stoi, base)*8; 98 | else if (pfx[0] == 'e') ret = strtoull(N, stoi, base)*TF_BLOCK_SIZE; 99 | else if (pfx[0] == 'y') ret = strtoull(N, stoi, base)*TF_FROM_BITS(TFC_KEY_BITS); 100 | else if (pfx[0] == 'x') ret = strtoull(N, stoi, base)*TF_FROM_BITS(TFC_KEY_BITS)*2; 101 | else if (pfx[0] == 'E') ret = strtoull(N, stoi, base)*blksize; 102 | else if (pfx[0] == 'b' || pfx[0] == 's') ret = strtoull(N, stoi, base)*512; 103 | else if (pfx[0] == 'p' || pfx[0] == 'S') ret = strtoull(N, stoi, base)*4096; 104 | else if (pfx[0] == 'k' || pfx[0] == 'K') { 105 | gbgib = do_stats_in_gibs == YES ? 1000 : 1024; 106 | } 107 | else if (pfx[0] == 'm' || pfx[0] == 'M') { 108 | gbgib = do_stats_in_gibs == YES ? 1000 * 1000 : 1024 * 1024; 109 | } 110 | else if (pfx[0] == 'g' || pfx[0] == 'G') { 111 | gbgib = do_stats_in_gibs == YES ? 1000 * 1000 * 1000 : 1024 * 1024 * 1024; 112 | } 113 | else if (pfx[0] == 'T') { 114 | gbgib = do_stats_in_gibs == YES ? 1000000000000ULL : 1099511627776ULL; 115 | } 116 | else if (pfx[0] == 'P') { 117 | gbgib = do_stats_in_gibs == YES ? 1000000000000000ULL : 1125899906842624ULL; 118 | } 119 | else ret = strtoull(N, stoi, base); 120 | if (gbgib) ret = strtoull(N, stoi, base) * gbgib; 121 | 122 | return ret; 123 | } 124 | 125 | const char *tfc_getscale(int scale) 126 | { 127 | return scale >= TFC_ARRAY_SIZE(tfc_size_scale) ? 128 | tfc_size_scale[TFC_ARRAY_SIZE(tfc_size_scale)-1] : tfc_size_scale[scale]; 129 | } 130 | 131 | void tfc_describescale(tfc_fsize num, double *w, int *scale) 132 | { 133 | tfc_fsize gbgib = (do_stats_in_gibs == YES) ? 1000 : 1024; 134 | 135 | if (num <= gbgib) { 136 | *w = num; 137 | *scale = 0; 138 | } 139 | else if ((num > gbgib) 140 | && (num <= gbgib * gbgib)) { 141 | *w = (double)num / gbgib; 142 | *scale = 1; 143 | } 144 | else if ((num > gbgib * gbgib) 145 | && (num <= gbgib * gbgib * gbgib)) { 146 | *w = (double)num / (gbgib * gbgib); 147 | *scale = 2; 148 | } 149 | else if ((num > gbgib * gbgib * gbgib) 150 | && (num <= gbgib * gbgib * gbgib * gbgib)) { 151 | *w = (double)num / (gbgib * gbgib * gbgib); 152 | *scale = 3; 153 | } 154 | else if ((num > gbgib * gbgib * gbgib * gbgib) 155 | && num <= gbgib * gbgib * gbgib * gbgib * gbgib) { 156 | *w = (double)num/ (gbgib * gbgib * gbgib * gbgib); 157 | *scale = 4; 158 | } 159 | else { 160 | *w = (double)num / (gbgib * gbgib * gbgib * gbgib * gbgib); 161 | *scale = 5; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /getpasswd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "getpasswd.h" 38 | 39 | size_t xgetpasswd(struct getpasswd_state *getps) 40 | { 41 | char c; 42 | int tty_opened = 0, x; 43 | int clear; 44 | struct termios s, t; 45 | size_t l, echolen = 0; 46 | 47 | if (!getps) return ((size_t)-1); 48 | 49 | /* 50 | * Both stdin and stderr point to same fd. This cannot happen. 51 | * This only means that getps was memzero'd. 52 | * Do not blame user for that, just fix it. 53 | */ 54 | if ((getps->fd == 0 && getps->efd == 0) || getps->efd == -1) getps->efd = 2; 55 | 56 | if (getps->fd == -1) { 57 | if ((getps->fd = open("/dev/tty", O_RDONLY|O_NOCTTY)) == -1) getps->fd = 0; 58 | else tty_opened = 1; 59 | } 60 | 61 | memset(&t, 0, sizeof(struct termios)); 62 | memset(&s, 0, sizeof(struct termios)); 63 | if (tcgetattr(getps->fd, &t) == -1) { 64 | getps->error = errno; 65 | return ((size_t)-1); 66 | } 67 | s = t; 68 | if (getps->sanetty) memcpy(getps->sanetty, &s, sizeof(struct termios)); 69 | cfmakeraw(&t); 70 | t.c_iflag |= ICRNL; 71 | if (tcsetattr(getps->fd, TCSANOW, &t) == -1) { 72 | getps->error = errno; 73 | return ((size_t)-1); 74 | } 75 | 76 | if (getps->echo) { 77 | echolen = strlen(getps->echo); 78 | if (write(getps->efd, getps->echo, echolen) == -1) { 79 | getps->error = errno; 80 | l = ((size_t)-1); 81 | goto _xerr; 82 | } 83 | } 84 | 85 | l = 0; x = 0; 86 | memset(getps->passwd, 0, getps->pwlen); 87 | while (1) { 88 | clear = 1; 89 | if (read(getps->fd, &c, sizeof(char)) == -1) { 90 | getps->error = errno; 91 | l = ((size_t)-1); 92 | goto _xerr; 93 | } 94 | if (getps->charfilter) { 95 | x = getps->charfilter(getps, c, l); 96 | if (x == 0) { 97 | clear = 0; 98 | goto _newl; 99 | } 100 | else if (x == 2) continue; 101 | else if (x == 3) goto _erase; 102 | else if (x == 4) goto _delete; 103 | else if (x == 5) break; 104 | else if (x == 6) { 105 | clear = 0; 106 | l = getps->retn; 107 | memset(getps->passwd, 0, getps->pwlen); 108 | goto _err; 109 | } 110 | } 111 | if (l >= getps->pwlen && (getps->flags & GETP_WAITFILL)) clear = 0; 112 | 113 | if (c == '\x7f' 114 | || (c == '\x08' && !(getps->flags & GETP_NOINTERP))) { /* Backspace / ^H */ 115 | _erase: if (l == 0) continue; 116 | clear = 0; 117 | l--; 118 | if (!(getps->flags & GETP_NOECHO)) { 119 | if (write(getps->efd, "\x08\033[1X", sizeof("\x08\033[1X")-1) == -1) { 120 | getps->error = errno; 121 | l = ((size_t)-1); 122 | goto _xerr; 123 | } 124 | } 125 | } 126 | else if (!(getps->flags & GETP_NOINTERP) 127 | && (c == '\x15' || c == '\x17')) { /* ^U / ^W */ 128 | _delete: clear = 0; 129 | l = 0; 130 | memset(getps->passwd, 0, getps->pwlen); 131 | if (write(getps->efd, "\033[2K\033[0G", sizeof("\033[2K\033[0G")-1) == -1) { 132 | getps->error = errno; 133 | l = ((size_t)-1); 134 | goto _xerr; 135 | } 136 | if (getps->echo) { 137 | if (write(getps->efd, getps->echo, echolen) == -1) { 138 | getps->error = errno; 139 | l = ((size_t)-1); 140 | goto _xerr; 141 | } 142 | } 143 | } 144 | _newl: if (c == '\n' 145 | || c == '\r' 146 | || (!(getps->flags & GETP_NOINTERP) && c == '\x04')) break; 147 | if (clear) { 148 | *(getps->passwd+l) = c; 149 | l++; 150 | if (!(getps->flags & GETP_NOECHO)) { 151 | if (getps->maskchar && 152 | write(getps->efd, &getps->maskchar, 153 | sizeof(char)) == -1) { 154 | getps->error = errno; 155 | l = ((size_t)-1); 156 | goto _xerr; 157 | } 158 | } 159 | } 160 | if (l >= getps->pwlen && !(getps->flags & GETP_WAITFILL)) break; 161 | }; 162 | 163 | _err: if (write(getps->efd, "\r\n", sizeof("\r\n")-1) == -1) { 164 | getps->error = errno; 165 | l = ((size_t)-1); 166 | } 167 | if (x != 6) *(getps->passwd+l) = 0; 168 | 169 | _xerr: if (tcsetattr(getps->fd, TCSANOW, &s) == -1) { 170 | if (getps->error == 0) { 171 | getps->error = errno; 172 | l = ((size_t)-1); 173 | } 174 | } 175 | 176 | if (tty_opened) close(getps->fd); 177 | 178 | return l; 179 | } 180 | -------------------------------------------------------------------------------- /tfc_base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | enum { TFB64_STOP1 = 1, TFB64_STOPF }; 32 | 33 | void do_edbase64(char **fargv) 34 | { 35 | struct base64_decodestate dstate; 36 | struct base64_encodestate estate; 37 | size_t lread = 0; 38 | 39 | sfd = 0; dfd = 1; 40 | 41 | if (fargv[0]) { 42 | if (!strcmp(fargv[0], "-")) sfd = 0; 43 | else { 44 | sfd = xopen(fargv[0], O_RDONLY | O_LARGEFILE); 45 | if (do_preserve_time) if (fstat(sfd, &s_stat) == -1) 46 | xerror(YES, NO, YES, "stat(%s)", fargv[0]); 47 | } 48 | if (sfd == -1) xerror(NO, NO, YES, "%s", fargv[0]); 49 | } 50 | 51 | if (fargv[0] && fargv[1]) { 52 | if (!strcmp(fargv[1], "-")) dfd = 1; 53 | else dfd = xopen(fargv[1], O_WRONLY | O_CREAT | O_LARGEFILE | write_flags); 54 | } 55 | 56 | if (do_edcrypt == TFC_DO_ENCRYPT) { 57 | memset(&estate, 0, sizeof(struct base64_encodestate)); 58 | base64_init_encodestate(&estate); 59 | } 60 | else if (do_edcrypt == TFC_DO_DECRYPT) { 61 | memset(&dstate, 0, sizeof(struct base64_decodestate)); 62 | base64_init_decodestate(&dstate); 63 | } 64 | 65 | errno = 0; 66 | do_stop = NO; 67 | while (1) { 68 | if (do_stop) break; 69 | pblk = srcblk; 70 | lblock = lrem = do_edcrypt == TFC_DO_DECRYPT ? TFC_B64_DWIDTH : TFC_B64_EWIDTH; 71 | ldone = 0; 72 | if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); 73 | _again: lio = xread(sfd, pblk, lrem); 74 | if (lio == 0) do_stop = TFB64_STOP1; 75 | if (lio != NOSIZE) ldone += lio; 76 | else { 77 | if (errno != EIO && catch_all_errors != YES) 78 | xerror(NO, NO, NO, "%s", fargv[0]); 79 | switch (error_action) { 80 | case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", fargv[0]); goto _again; break; 81 | case TFC_ERRACT_SYNC: 82 | case TFC_ERRACT_LSYNC: 83 | xerror(YES, NO, NO, "%s", fargv[0]); 84 | lio = ldone = lrem = lblock; 85 | memset(srcblk, 0, lio); 86 | if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR); 87 | else lseek(sfd, rdpos + lio, SEEK_SET); 88 | break; 89 | default: xerror(NO, NO, NO, "%s", fargv[0]); break; 90 | } 91 | } 92 | if (lio && lio < lrem) { 93 | pblk += lio; 94 | lrem -= lio; 95 | goto _again; 96 | } 97 | 98 | if (do_edcrypt == TFC_DO_ENCRYPT) { 99 | estate.count = 0; 100 | base64_encode_block((const char *)srcblk, ldone, (char *)dstblk, &estate); 101 | lread = ldone; 102 | ldone = estate.count; 103 | } 104 | else if (do_edcrypt == TFC_DO_DECRYPT) { 105 | dstate.count = 0; 106 | base64_decode_block((const char *)srcblk, ldone, (char *)dstblk, sizeof(dstblk), &dstate); 107 | ldone = dstate.count; 108 | } 109 | 110 | pblk = dstblk; 111 | if (ldone == 0) { 112 | do_stop = TFB64_STOPF; 113 | break; 114 | } 115 | lrem = ldone; 116 | ldone = 0; 117 | _wagain: lio = xwrite(dfd, pblk, lrem); 118 | if (lio != NOSIZE) ldone += lio; 119 | else xerror(NO, NO, NO, "%s", fargv[1]); 120 | if (do_edcrypt == TFC_DO_ENCRYPT) { 121 | size_t t; 122 | if (lread >= lblock || do_stop == TFB64_STOPF) { 123 | t = xwrite(dfd, "\n", 1); 124 | if (t != NOSIZE) lio += t; 125 | else lio = NOSIZE; 126 | } 127 | } 128 | if (lio != NOSIZE) ldone += lio; 129 | else xerror(NO, NO, NO, "%s", fargv[1]); 130 | if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", fargv[1]); 131 | if (lio < lrem) { 132 | pblk += lio; 133 | lrem -= lio; 134 | goto _wagain; 135 | } 136 | } 137 | 138 | if (do_edcrypt == TFC_DO_ENCRYPT && do_stop == TFB64_STOP1) { 139 | size_t t = estate.count; 140 | pblk = dstblk + estate.count; 141 | base64_encode_blockend((char *)dstblk, &estate); 142 | lrem = estate.count - t; 143 | ldone = 0; 144 | do_stop = TFB64_STOPF; 145 | goto _wagain; 146 | } 147 | 148 | memset(&estate, 0, sizeof(struct base64_encodestate)); 149 | memset(&dstate, 0, sizeof(struct base64_decodestate)); 150 | xexit(0); 151 | } 152 | 153 | static void base64_eprint(FILE *where, struct base64_encodestate *estate, const char *input, size_t inputl) 154 | { 155 | static char t[256]; 156 | ssize_t ix = inputl; 157 | 158 | while (ix > 0) { 159 | memset(t, 0, sizeof(t)); 160 | estate->count = 0; 161 | base64_encode_block(input, ix > 128 ? 128 : ix, t, estate); 162 | ix -= 128; 163 | if (ix < 128) base64_encode_blockend(t, estate); 164 | fprintf(where, "%s", t); 165 | fflush(where); 166 | } 167 | 168 | memset(t, 0, sizeof(t)); 169 | } 170 | 171 | void tfc_printbase64(FILE *where, const void *p, size_t n, tfc_yesno nl) 172 | { 173 | struct base64_encodestate estate; 174 | memset(&estate, 0, sizeof(struct base64_encodestate)); 175 | base64_eprint(where, &estate, (const char *)p, n); 176 | if (nl) tfc_nfsay(where, "\n"); 177 | } 178 | -------------------------------------------------------------------------------- /tfc_random.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | static void print_crypt_status_genrnd(int signal) 32 | { 33 | print_crypt_status(signal); 34 | } 35 | 36 | static void exit_sigterm_genrnd(int signal) 37 | { 38 | exit_sigterm(signal); 39 | } 40 | 41 | static void get_urandom(const char *src, void *buf, size_t size) 42 | { 43 | tfc_byte *ubuf = buf; 44 | int fd = -1; 45 | size_t sz = size, rd; 46 | 47 | if (src == NULL) fd = -1; 48 | else fd = open(src, O_RDONLY); 49 | 50 | if (fd == -1) fd = open("/dev/urandom", O_RDONLY); 51 | if (fd == -1) fd = open("/dev/arandom", O_RDONLY); 52 | if (fd == -1) fd = open("/dev/prandom", O_RDONLY); 53 | if (fd == -1) fd = open("/dev/srandom", O_RDONLY); 54 | if (fd == -1) fd = open("/dev/random", O_RDONLY); 55 | if (fd == -1) xerror(NO, YES, YES, "random source is required (tried %s)", src); 56 | 57 | _again: rd = xread(fd, ubuf, sz); 58 | if (rd < sz && rd != NOSIZE) { 59 | ubuf += rd; 60 | sz -= rd; 61 | goto _again; 62 | } 63 | 64 | xclose(fd); 65 | } 66 | 67 | static tfc_yesno tfc_random_initialised; 68 | 69 | static void tfc_initrandom(const char *rndsrc) 70 | { 71 | tfc_byte k[TF_KEY_SIZE]; 72 | 73 | if (tfc_random_initialised == YES) return; 74 | 75 | get_urandom(rndsrc, k, TF_KEY_SIZE); 76 | tf_prng_seedkey(k); 77 | memset(k, 0, TF_KEY_SIZE); 78 | 79 | tfc_random_initialised = YES; 80 | } 81 | 82 | void tfc_finirandom(void) 83 | { 84 | tf_prng_seedkey(NULL); 85 | tfc_random_initialised = NO; 86 | } 87 | 88 | void tfc_getrandom(void *buf, size_t sz) 89 | { 90 | if (tfc_random_initialised == NO) tfc_initrandom(randsource); 91 | tf_prng_genrandom(buf, sz); 92 | } 93 | 94 | void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes) 95 | { 96 | static tfc_fsize wrpos = NOFSIZE; 97 | int fd, x; 98 | size_t lblock, lio, lrem; 99 | tfc_byte *pblk; 100 | 101 | for (x = 1; x < NSIG; x++) signal(x, SIG_IGN); 102 | memset(&sigact, 0, sizeof(sigact)); 103 | sigact.sa_flags = SA_RESTART; 104 | sigact.sa_handler = print_crypt_status; 105 | sigaction(SIGUSR1, &sigact, NULL); 106 | sigaction(SIGALRM, &sigact, NULL); 107 | if (status_timer) setup_next_alarm(status_timer > 1000000 ? 1000000 : status_timer); 108 | sigact.sa_handler = change_status_width; 109 | sigaction(SIGQUIT, &sigact, NULL); 110 | sigact.sa_handler = change_status_timer; 111 | sigaction(SIGUSR2, &sigact, NULL); 112 | if (quiet == NO) { 113 | sigact.sa_handler = print_crypt_status_genrnd; 114 | sigaction(SIGINT, &sigact, NULL); 115 | sigaction(SIGTERM, &sigact, NULL); 116 | sigaction(SIGTSTP, &sigact, NULL); 117 | } 118 | else { 119 | sigact.sa_handler = exit_sigterm_genrnd; 120 | sigaction(SIGINT, &sigact, NULL); 121 | sigaction(SIGTERM, &sigact, NULL); 122 | sigact.sa_handler = handle_sigtstp; 123 | sigaction(SIGTSTP, &sigact, NULL); 124 | } 125 | memset(&sigact, 0, sizeof(struct sigaction)); 126 | 127 | tfc_getcurtime(&delta_time); 128 | 129 | if (do_less_stats) do_less_stats = NO; 130 | else do_less_stats = YES; 131 | 132 | if (!foutname) { 133 | fd = 1; 134 | foutname = TFC_STDOUT_NAME; 135 | } 136 | else if (!strcmp(foutname, "-")) { 137 | fd = 1; 138 | foutname = TFC_STDOUT_NAME; 139 | } 140 | else fd = xopen(foutname, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags); 141 | 142 | if (offset) { 143 | if (lseek(fd, offset, SEEK_SET) == -1) 144 | xerror(ignore_seek_errors, NO, NO, "%s: seek failed", foutname); 145 | } 146 | 147 | if (do_edcrypt == TFC_DO_PLAIN) memset(srcblk, 0, sizeof(srcblk)); 148 | 149 | if (verbose) tfc_nfsay(stderr, "%s: writing %lld bytes to %s ... ", 150 | tfc_format_pid(progname), nrbytes, foutname); 151 | 152 | errno = 0; 153 | do_stop = NO; 154 | while (1) { 155 | if (do_stop) break; 156 | pblk = srcblk; 157 | lblock = lrem = blk_len_adj(nrbytes, total_processed_src, blksize); 158 | 159 | if (do_edcrypt != TFC_DO_PLAIN) tfc_getrandom(srcblk, lblock); 160 | 161 | if (error_action == TFC_ERRACT_SYNC) wrpos = tfc_fdgetpos(fd); 162 | _wagain: lio = xwrite(fd, pblk, lrem); 163 | if (lio == NOSIZE) { 164 | if (errno != EIO && catch_all_errors != YES) 165 | xerror(NO, NO, YES, "%s", foutname); 166 | switch (error_action) { 167 | case TFC_ERRACT_CONT: xerror(YES, NO, YES, "%s", foutname); goto _wagain; break; 168 | case TFC_ERRACT_SYNC: 169 | case TFC_ERRACT_LSYNC: 170 | xerror(YES, NO, YES, "%s", foutname); 171 | if (wrpos == NOFSIZE) lseek(fd, lblock, SEEK_CUR); 172 | else lseek(fd, wrpos + lblock, SEEK_SET); 173 | break; 174 | default: xerror(NO, NO, YES, "%s", foutname); break; 175 | } 176 | } 177 | if (do_fsync && fsync(fd) == -1) xerror(NO, NO, YES, "%s", foutname); 178 | if (lio < lrem) { 179 | pblk += lio; 180 | lrem -= lio; 181 | goto _wagain; 182 | } 183 | 184 | total_processed_src += lblock; 185 | delta_processed += lblock; 186 | total_processed_dst = total_processed_src; 187 | if (total_processed_src >= nrbytes) break; 188 | } 189 | 190 | if (verbose) tfc_esay("done!"); 191 | if (verbose || status_timer) { 192 | print_crypt_status(TFC_SIGSTAT); 193 | tfc_esay("\n"); 194 | } 195 | 196 | xclose(fd); 197 | xexit(0); 198 | } 199 | -------------------------------------------------------------------------------- /tfxts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tfdef.h" 3 | 4 | static inline void xts_mult_x(TF_UNIT_TYPE *x) 5 | { 6 | size_t i, t, tt; 7 | 8 | for (i = t = 0; i < TF_NR_BLOCK_UNITS; i++) { 9 | tt = x[i] >> (TF_UNIT_BITS-1); 10 | x[i] = ((x[i] << 1) | t) & ((TF_UNIT_TYPE)~0); 11 | t = tt; 12 | } 13 | if (tt) x[0] ^= IRR_POLY_CONST; 14 | } 15 | 16 | static void xts_encrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz) 17 | { 18 | const TF_BYTE_TYPE *uin = in; 19 | TF_BYTE_TYPE *uout = out; 20 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 21 | TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS]; 22 | TF_UNIT_TYPE *uctr = ctr; 23 | const TF_UNIT_TYPE *ukeyx = keyx, *ukeyz = keyz; 24 | size_t sl = sz, i; 25 | 26 | tf_encrypt_rawblk(tctr, uctr, ukeyz); 27 | 28 | if (sl >= (TF_BLOCK_SIZE * 2)) { 29 | do { 30 | _last: memcpy(x, uin, TF_BLOCK_SIZE); 31 | uin += TF_BLOCK_SIZE; 32 | data_to_words(x, TF_BLOCK_SIZE); 33 | 34 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 35 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ tctr[i]; 36 | tf_encrypt_rawblk(x, y, ukeyx); 37 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i]; 38 | 39 | xts_mult_x(tctr); 40 | 41 | data_to_words(x, TF_BLOCK_SIZE); 42 | memcpy(uout, x, TF_BLOCK_SIZE); 43 | uout += TF_BLOCK_SIZE; 44 | } while ((sl -= TF_BLOCK_SIZE) >= (TF_BLOCK_SIZE * 2)); 45 | } 46 | 47 | if (sl) { 48 | if (sl-TF_BLOCK_SIZE == 0) goto _last; 49 | if (sl < TF_BLOCK_SIZE) { 50 | memset(x, 0, TF_BLOCK_SIZE); 51 | memcpy(x, uin, sl); 52 | data_to_words(x, TF_BLOCK_SIZE); 53 | 54 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 55 | tf_encrypt_rawblk(y, uctr, ukeyx); 56 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 57 | 58 | data_to_words(y, TF_BLOCK_SIZE); 59 | memcpy(uout, y, sl); 60 | 61 | goto _done; 62 | } 63 | 64 | memcpy(x, uin, TF_BLOCK_SIZE); 65 | uin += TF_BLOCK_SIZE; 66 | data_to_words(x, TF_BLOCK_SIZE); 67 | 68 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 69 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ tctr[i]; 70 | tf_encrypt_rawblk(x, y, ukeyx); 71 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i]; 72 | 73 | memcpy(y, x, TF_BLOCK_SIZE); 74 | sl -= TF_BLOCK_SIZE; 75 | 76 | xts_mult_x(tctr); 77 | 78 | tf_encrypt_rawblk(tctr, uctr, ukeyz); 79 | 80 | memcpy(x, uin, sl); 81 | data_to_words(x, sl); 82 | 83 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i]; 84 | tf_encrypt_rawblk(x, x, ukeyx); 85 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i]; 86 | 87 | data_to_words(x, TF_BLOCK_SIZE); 88 | memcpy(uout, x, TF_BLOCK_SIZE); 89 | uout += TF_BLOCK_SIZE; 90 | 91 | data_to_words(y, TF_BLOCK_SIZE); 92 | memcpy(uout, y, sl); 93 | } 94 | 95 | _done: memset(tctr, 0, TF_BLOCK_SIZE); 96 | memset(x, 0, TF_BLOCK_SIZE); 97 | memset(y, 0, TF_BLOCK_SIZE); 98 | } 99 | 100 | void tf_xts_encrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi) 101 | { 102 | const TF_BYTE_TYPE *uin = in; 103 | TF_BYTE_TYPE *uout = out; 104 | size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi); 105 | 106 | if (sl >= sx) { 107 | do { 108 | xts_encrypt(keyx, keyz, ctr, uout, uin, sx); 109 | uout += sx; 110 | uin += sx; 111 | } while ((sl -= sx) >= sx); 112 | } 113 | 114 | if (sl) xts_encrypt(keyx, keyz, ctr, uout, uin, sl); 115 | } 116 | 117 | static void xts_decrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz) 118 | { 119 | const TF_BYTE_TYPE *uin = in; 120 | TF_BYTE_TYPE *uout = out, *s, *d; 121 | TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS]; 122 | TF_UNIT_TYPE tctr[TF_NR_BLOCK_UNITS], zctr[TF_NR_BLOCK_UNITS]; 123 | TF_UNIT_TYPE *uctr = ctr; 124 | const TF_UNIT_TYPE *ukeyx = keyx, *ukeyz = keyz; 125 | size_t sl = sz, i; 126 | 127 | tf_encrypt_rawblk(tctr, uctr, ukeyz); 128 | 129 | if (sl >= (TF_BLOCK_SIZE * 2)) { 130 | do { 131 | _last: memcpy(x, uin, TF_BLOCK_SIZE); 132 | uin += TF_BLOCK_SIZE; 133 | data_to_words(x, TF_BLOCK_SIZE); 134 | 135 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 136 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ tctr[i]; 137 | tf_decrypt_rawblk(x, y, ukeyx); 138 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i]; 139 | 140 | xts_mult_x(tctr); 141 | 142 | data_to_words(x, TF_BLOCK_SIZE); 143 | memcpy(uout, x, TF_BLOCK_SIZE); 144 | uout += TF_BLOCK_SIZE; 145 | } while ((sl -= TF_BLOCK_SIZE) >= (TF_BLOCK_SIZE * 2)); 146 | } 147 | 148 | if (sl) { 149 | if (sl-TF_BLOCK_SIZE == 0) goto _last; 150 | if (sl < TF_BLOCK_SIZE) { 151 | memset(x, 0, TF_BLOCK_SIZE); 152 | memcpy(x, uin, sl); 153 | data_to_words(x, TF_BLOCK_SIZE); 154 | 155 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 156 | tf_encrypt_rawblk(y, uctr, ukeyx); 157 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i]; 158 | 159 | data_to_words(y, TF_BLOCK_SIZE); 160 | memcpy(uout, y, sl); 161 | 162 | goto _done; 163 | } 164 | 165 | memcpy(x, uin, TF_BLOCK_SIZE); 166 | uin += TF_BLOCK_SIZE; 167 | data_to_words(x, TF_BLOCK_SIZE); 168 | 169 | ctr_inc(uctr, TF_NR_BLOCK_UNITS); 170 | memcpy(zctr, tctr, TF_BLOCK_SIZE); 171 | xts_mult_x(tctr); 172 | 173 | tf_encrypt_rawblk(tctr, uctr, ukeyz); 174 | 175 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i]; 176 | tf_decrypt_rawblk(x, x, ukeyx); 177 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) x[i] ^= tctr[i]; 178 | 179 | sl -= TF_BLOCK_SIZE; 180 | memcpy(y, uin, sl); 181 | data_to_words(y, sl); 182 | 183 | s = (TF_BYTE_TYPE *)y; 184 | d = (TF_BYTE_TYPE *)x; 185 | memcpy(s+sl, d+sl, TF_BLOCK_SIZE-sl); 186 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= zctr[i]; 187 | tf_decrypt_rawblk(y, y, ukeyx); 188 | for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= zctr[i]; 189 | 190 | data_to_words(y, TF_BLOCK_SIZE); 191 | memcpy(uout, y, TF_BLOCK_SIZE); 192 | uout += TF_BLOCK_SIZE; 193 | 194 | data_to_words(x, TF_BLOCK_SIZE); 195 | memcpy(uout, x, sl); 196 | } 197 | 198 | _done: memset(tctr, 0, TF_BLOCK_SIZE); 199 | memset(zctr, 0, TF_BLOCK_SIZE); 200 | memset(x, 0, TF_BLOCK_SIZE); 201 | memset(y, 0, TF_BLOCK_SIZE); 202 | } 203 | 204 | void tf_xts_decrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi) 205 | { 206 | const TF_BYTE_TYPE *uin = in; 207 | TF_BYTE_TYPE *uout = out; 208 | size_t sl = sz, sx = TF_BLOCKS_TO_BYTES(bpi); 209 | 210 | if (sl >= sx) { 211 | do { 212 | xts_decrypt(keyx, keyz, ctr, uout, uin, sx); 213 | uout += sx; 214 | uin += sx; 215 | } while ((sl -= sx) >= sx); 216 | } 217 | 218 | if (sl) xts_decrypt(keyx, keyz, ctr, uout, uin, sl); 219 | } 220 | -------------------------------------------------------------------------------- /tfc_signal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | void exit_sigterm(int signal) 32 | { 33 | tfc_esay("\n"); 34 | xexit(0); 35 | } 36 | 37 | void handle_sigtstp(int signal) 38 | { 39 | if (signal == SIGTSTP) { 40 | tfc_useconds freeze_start, freeze_end; 41 | 42 | tfc_getcurtime(&freeze_start); 43 | kill(getpid(), SIGSTOP); 44 | tfc_getcurtime(&freeze_end); 45 | total_time -= (freeze_end - freeze_start); 46 | } 47 | } 48 | 49 | void print_crypt_status(int signal) 50 | { 51 | tfc_fsize wr_speed; 52 | double seconds, human_totalproc_src, human_totalproc_dst, human_totalwrit_dst, human_wr_speed; 53 | int src_scale_idx, dst_scale_idx, wri_scale_idx, wr_speed_scale; 54 | const char *oper_mode, *inplace; 55 | static tfc_yesno last; 56 | tfc_yesno finished = NO; 57 | 58 | if (last == YES) return; 59 | if (signal == TFC_SIGLAST) { 60 | last = YES; 61 | finished = YES; 62 | } 63 | 64 | switch (do_edcrypt) { 65 | case TFC_DO_ENCRYPT: oper_mode = "encrypted"; break; 66 | case TFC_DO_DECRYPT: oper_mode = "decrypted"; break; 67 | default: 68 | if (ctr_mode == TFC_MODE_PLAIN) oper_mode = "written"; 69 | else if (ctr_mode == TFC_MODE_XOR) oper_mode = "xored"; 70 | else if (ctr_mode == TFC_MODE_SKSUM) oper_mode = "hashed"; 71 | else oper_mode = NULL; 72 | break; 73 | } 74 | 75 | if (signal == SIGINT || signal == SIGTERM) { 76 | do_stop = YES; 77 | } 78 | 79 | tfc_getcurtime(¤t_time); 80 | total_time += (current_time - delta_time); 81 | seconds = TFC_UTODSECS(current_time - delta_time); 82 | wr_speed = delta_processed / seconds; 83 | tfc_describescale(total_processed_src, &human_totalproc_src, &src_scale_idx); 84 | tfc_describescale(total_processed_dst, &human_totalproc_dst, &dst_scale_idx); 85 | tfc_describescale(total_written_dst, &human_totalwrit_dst, &wri_scale_idx); 86 | tfc_describescale(wr_speed, &human_wr_speed, &wr_speed_scale); 87 | 88 | if (bench_timer) { 89 | tfc_say("done!"); 90 | tfc_say("%s %s benchmark results:", tfc_format_pid(progname), tfc_modename(ctr_mode)); 91 | tfc_nfsay(stdout, "%s %llu (%.2f%s) bytes, " 92 | "avg. speed %llu (%.2f%s) B/s, time %.4fs.", 93 | oper_mode, 94 | total_processed_src, human_totalproc_src, tfc_getscale(src_scale_idx), 95 | wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale), seconds); 96 | xexit(0); 97 | } 98 | 99 | if (do_statline_dynamic == YES) inplace = "\033[2K\r"; 100 | else inplace = ""; 101 | 102 | if (do_less_stats == YES) { 103 | tfc_nfsay(stderr, "%s%s%s:" 104 | " %s %.2f%s," 105 | " %.2f%s B/s @%s", 106 | inplace, (finished && show_when_done) ? "finished: " : "", tfc_format_pid(progname), 107 | oper_mode, 108 | human_totalproc_dst, tfc_getscale(dst_scale_idx), 109 | human_wr_speed, tfc_getscale(wr_speed_scale), tfc_format_time(total_time)); 110 | } 111 | else { 112 | if (ctr_mode <= TFC_MODE_PLAIN) tfc_nfsay(stderr, "%s%s%s: read: %llu (%.2f%s)," 113 | " %s %llu (%.2f%s) bytes," 114 | " (%llu (%.2f%s) B/s), time %s", 115 | inplace, (finished && show_when_done) ? "finished: " : "", tfc_format_pid(progname), 116 | total_processed_src, human_totalproc_src, tfc_getscale(src_scale_idx), 117 | oper_mode, 118 | total_processed_dst, human_totalproc_dst, tfc_getscale(dst_scale_idx), 119 | wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale), tfc_format_time(total_time)); 120 | else tfc_nfsay(stderr, "%s%s%s: read: %llu (%.2f%s)," 121 | " %s %s %llu (%.2f%s) bytes," 122 | " written %llu (%.2f%s) bytes," 123 | " (%llu (%.2f%s) B/s), time %s", 124 | inplace, (finished && show_when_done) ? "finished: " : "", tfc_format_pid(progname), 125 | total_processed_src, human_totalproc_src, tfc_getscale(src_scale_idx), 126 | tfc_modename(ctr_mode), oper_mode, 127 | total_processed_dst, human_totalproc_dst, tfc_getscale(dst_scale_idx), 128 | total_written_dst, human_totalwrit_dst, tfc_getscale(wri_scale_idx), 129 | wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale), tfc_format_time(total_time)); 130 | } 131 | 132 | if (do_stop == NO && do_statline_dynamic == NO) tfc_esay("\n"); 133 | else if (signal == TFC_SIGLAST || signal == TFC_SIGERR) tfc_esay("\n"); 134 | statline_was_shown = YES; 135 | 136 | if ((signal == SIGINT || signal == SIGTERM) && do_stop == YES) exit_sigterm(signal); 137 | 138 | delta_processed = 0; 139 | tfc_getcurtime(&delta_time); 140 | 141 | handle_sigtstp(signal); 142 | 143 | if (status_timer) setup_next_alarm(status_timer); 144 | } 145 | 146 | void change_status_width(int signal) 147 | { 148 | if (do_less_stats == YES) do_less_stats = NO; 149 | else if (do_less_stats == NO) do_less_stats = YES; 150 | } 151 | 152 | void change_status_timer(int signal) 153 | { 154 | static tfc_useconds reset_timer; 155 | tfc_useconds t; 156 | 157 | tfc_getcurtime(&t); 158 | if (reset_timer && (t - reset_timer) < TFC_DTOUSECS(0.1)) status_timer = 0; 159 | reset_timer = t; 160 | 161 | if (status_timer == 0) status_timer = TFC_DTOUSECS(0.25); 162 | else status_timer *= 2; 163 | 164 | if (verbose) tfc_esay("%s: status timer was changed to %.2fs", 165 | tfc_format_pid(progname), TFC_UTODSECS(status_timer)); 166 | setup_next_alarm(status_timer); 167 | } 168 | 169 | void setup_next_alarm(tfc_useconds useconds) 170 | { 171 | struct itimerval it; 172 | 173 | memset(&it, 0, sizeof(struct itimerval)); 174 | it.it_value.tv_sec = useconds / 1000000; 175 | it.it_value.tv_usec = useconds % 1000000; 176 | setitimer(ITIMER_REAL, &it, NULL); 177 | } 178 | -------------------------------------------------------------------------------- /base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * base64.c: libb64 compressed code. Public domain. 3 | * See http://libb64.sourceforge.net/ for original code and infos. 4 | * 5 | * Modified and fixed by Lynx 03Jun2016: 6 | * - Single TU, minimal external dependencies 7 | * - Stream operation, no newline insertions 8 | * - Fixed code style to pure K&R 9 | * - Fixed integer overflows and fixed size types 10 | * - Fixed out of bounds access in base64_decode_block 11 | * - Force specify output size for output buffer when decoding 12 | * - Fixed signed/unsigned issue on ARM 13 | * - Added generic memory converter wrappers which do not expose internals 14 | * - All functions calculate number of processed characters and return them to caller 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | enum base64_decodestep { 21 | estep_a, estep_b, estep_c, estep_d 22 | }; 23 | 24 | struct base64_decodestate { 25 | enum base64_decodestep step; 26 | char plainchar; 27 | size_t count; 28 | }; 29 | 30 | enum base64_encodestep { 31 | dstep_a, dstep_b, dstep_c 32 | }; 33 | 34 | struct base64_encodestate { 35 | enum base64_encodestep step; 36 | char result; 37 | size_t count; 38 | }; 39 | 40 | int base64_decode_value(signed char value_in) 41 | { 42 | static const signed char decoding[] = { 43 | 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, 44 | -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 45 | 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 46 | 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 47 | }; 48 | static const char decoding_size = sizeof(decoding); 49 | if (value_in < 43) return -1; 50 | value_in -= 43; 51 | if (value_in >= decoding_size) return -1; 52 | return decoding[(int)value_in]; 53 | } 54 | 55 | void base64_init_decodestate(struct base64_decodestate *state_in) 56 | { 57 | state_in->step = estep_a; 58 | state_in->plainchar = 0; 59 | state_in->count = 0; 60 | } 61 | 62 | #define CHECK_BOUNDS do { if (plainchar-plaintext_out >= plaintext_outl) goto _ret; } while (0) 63 | 64 | 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) 65 | { 66 | const char *codechar = code_in; 67 | char *plainchar = plaintext_out; 68 | int fragment; 69 | 70 | *plainchar = state_in->plainchar; 71 | 72 | switch (state_in->step) { 73 | while (1) { 74 | case estep_a: 75 | do { 76 | if (codechar == code_in+length_in) { 77 | state_in->step = estep_a; 78 | state_in->plainchar = *plainchar; 79 | state_in->count += (plainchar - plaintext_out); 80 | return plainchar - plaintext_out; 81 | } 82 | fragment = base64_decode_value(*codechar++); 83 | } while (fragment < 0); 84 | *plainchar = (fragment & 0x3f) << 2; 85 | case estep_b: 86 | do { 87 | if (codechar == code_in+length_in) { 88 | state_in->step = estep_b; 89 | state_in->plainchar = *plainchar; 90 | state_in->count += (plainchar - plaintext_out); 91 | return plainchar - plaintext_out; 92 | } 93 | fragment = base64_decode_value(*codechar++); 94 | } while (fragment < 0); 95 | *plainchar++ |= (fragment & 0x30) >> 4; 96 | CHECK_BOUNDS; 97 | *plainchar = (fragment & 0x0f) << 4; 98 | case estep_c: 99 | do { 100 | if (codechar == code_in+length_in) { 101 | state_in->step = estep_c; 102 | state_in->plainchar = *plainchar; 103 | state_in->count += (plainchar - plaintext_out); 104 | return plainchar - plaintext_out; 105 | } 106 | fragment = base64_decode_value(*codechar++); 107 | } while (fragment < 0); 108 | *plainchar++ |= (fragment & 0x3c) >> 2; 109 | CHECK_BOUNDS; 110 | *plainchar = (fragment & 0x03) << 6; 111 | case estep_d: 112 | do { 113 | if (codechar == code_in+length_in) { 114 | state_in->step = estep_d; 115 | state_in->plainchar = *plainchar; 116 | state_in->count += (plainchar - plaintext_out); 117 | return plainchar - plaintext_out; 118 | } 119 | fragment = base64_decode_value(*codechar++); 120 | } while (fragment < 0); 121 | *plainchar++ |= (fragment & 0x3f); 122 | } 123 | } 124 | 125 | _ret: state_in->count += (plainchar - plaintext_out); 126 | return plainchar - plaintext_out; 127 | } 128 | 129 | void base64_init_encodestate(struct base64_encodestate *state_in) 130 | { 131 | state_in->step = dstep_a; 132 | state_in->result = 0; 133 | state_in->count = 0; 134 | } 135 | 136 | char base64_encode_value(char value_in) 137 | { 138 | static const char *encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 139 | if (value_in > 63) return '='; 140 | return encoding[(int)value_in]; 141 | } 142 | 143 | size_t base64_encode_block(const char *plaintext_in, size_t length_in, char *code_out, struct base64_encodestate *state_in) 144 | { 145 | const char *plainchar = plaintext_in; 146 | const char *const plaintextend = plaintext_in + length_in; 147 | char *codechar = code_out; 148 | char result; 149 | char fragment; 150 | 151 | result = state_in->result; 152 | 153 | switch (state_in->step) { 154 | while (1) { 155 | case dstep_a: 156 | if (plainchar == plaintextend) { 157 | state_in->result = result; 158 | state_in->step = dstep_a; 159 | state_in->count += (codechar - code_out); 160 | return codechar - code_out; 161 | } 162 | fragment = *plainchar++; 163 | result = (fragment & 0xfc) >> 2; 164 | *codechar++ = base64_encode_value(result); 165 | result = (fragment & 0x03) << 4; 166 | case dstep_b: 167 | if (plainchar == plaintextend) { 168 | state_in->result = result; 169 | state_in->step = dstep_b; 170 | state_in->count += (codechar - code_out); 171 | return codechar - code_out; 172 | } 173 | fragment = *plainchar++; 174 | result |= (fragment & 0xf0) >> 4; 175 | *codechar++ = base64_encode_value(result); 176 | result = (fragment & 0x0f) << 2; 177 | case dstep_c: 178 | if (plainchar == plaintextend) { 179 | state_in->result = result; 180 | state_in->step = dstep_c; 181 | state_in->count += (codechar - code_out); 182 | return codechar - code_out; 183 | } 184 | fragment = *plainchar++; 185 | result |= (fragment & 0xc0) >> 6; 186 | *codechar++ = base64_encode_value(result); 187 | result = (fragment & 0x3f) >> 0; 188 | *codechar++ = base64_encode_value(result); 189 | } 190 | } 191 | /* control should not reach here */ 192 | state_in->count += (codechar - code_out); 193 | return codechar - code_out; 194 | } 195 | 196 | size_t base64_encode_blockend(char *code_out, struct base64_encodestate *state_in) 197 | { 198 | char *codechar = code_out + state_in->count; 199 | 200 | switch (state_in->step) { 201 | case dstep_b: 202 | *codechar++ = base64_encode_value(state_in->result); 203 | *codechar++ = '='; 204 | *codechar++ = '='; 205 | state_in->count += 3; 206 | break; 207 | case dstep_c: 208 | *codechar++ = base64_encode_value(state_in->result); 209 | *codechar++ = '='; 210 | state_in->count += 2; 211 | break; 212 | case dstep_a: 213 | break; 214 | } 215 | 216 | return codechar - code_out; 217 | } 218 | 219 | /* Process single block of memory */ 220 | size_t base64_decode(char *output, size_t outputl, const char *input, size_t inputl) 221 | { 222 | struct base64_decodestate dstate; 223 | size_t r; 224 | 225 | base64_init_decodestate(&dstate); 226 | base64_decode_block(input, inputl, output, outputl, &dstate); 227 | 228 | r = dstate.count; 229 | memset(&dstate, 0, sizeof(struct base64_decodestate)); 230 | 231 | return r; 232 | } 233 | 234 | size_t base64_encode(char *output, const char *input, size_t inputl) 235 | { 236 | struct base64_encodestate estate; 237 | size_t r; 238 | 239 | base64_init_encodestate(&estate); 240 | base64_encode_block(input, inputl, output, &estate); 241 | base64_encode_blockend(output, &estate); 242 | 243 | r = estate.count; 244 | memset(&estate, 0, sizeof(struct base64_encodestate)); 245 | 246 | return r; 247 | } 248 | -------------------------------------------------------------------------------- /tfc_misc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | size_t blk_len_adj(tfc_fsize filelen, tfc_fsize read_already, size_t blklen) 32 | { 33 | if (filelen == NOFSIZE) return blklen; 34 | return ((filelen - read_already) >= blklen) ? blklen : (filelen - read_already); 35 | } 36 | 37 | tfc_yesno xor_shrink(void *dst, size_t szdst, const void *src, size_t szsrc) 38 | { 39 | unsigned char *udst = dst; 40 | const unsigned char *usrc = src; 41 | size_t x, y; 42 | 43 | if ((szsrc % szdst) != 0) return NO; 44 | if (szdst >= szsrc) { 45 | if (szdst == szsrc) { 46 | memmove(dst, src, szsrc); 47 | return YES; 48 | } 49 | return NO; 50 | } 51 | 52 | memset(dst, 0, szdst); 53 | for (x = 0; x < (szsrc / szdst); x++) { 54 | for (y = 0; y < szdst; y++) udst[y] ^= usrc[(x*szdst)+y]; 55 | } 56 | 57 | return YES; 58 | } 59 | 60 | tfc_yesno str_empty(const char *str) 61 | { 62 | if (!*str) return YES; 63 | return NO; 64 | } 65 | 66 | int xxopen(tfc_yesno noerr, const char *pathname, int flags) 67 | { 68 | int r; 69 | 70 | if ((flags & O_WRONLY || flags & O_RDWR)) { 71 | if (read_only == YES) flags = O_RDONLY; 72 | else flags |= write_flags; 73 | } 74 | 75 | flags |= O_LARGEFILE; 76 | r = open(pathname, flags, 0666); 77 | if (noerr == NO && r == -1) xerror(NO, NO, YES, "%s", pathname); 78 | return r; 79 | } 80 | 81 | int xopen(const char *pathname, int flags) 82 | { 83 | return xxopen(NO, pathname, flags); 84 | } 85 | 86 | void xclose(int fd) 87 | { 88 | if (fd < 3) return; 89 | if (close(fd) == -1) xerror(YES, NO, NO, "close(%d)", fd); 90 | } 91 | 92 | const char *tfc_modename(int mode) 93 | { 94 | switch (mode) { 95 | case TFC_MODE_CTR: return "CTR"; 96 | case TFC_MODE_STREAM: return "STREAM"; 97 | case TFC_MODE_XTS: return "XTS"; 98 | case TFC_MODE_ECB: return "ECB"; 99 | case TFC_MODE_CBC: return "CBC"; 100 | case TFC_MODE_PCBC: return "PCBC"; 101 | } 102 | 103 | return NULL; 104 | } 105 | 106 | tfc_yesno tfc_is_freestream(int mode) 107 | { 108 | switch (mode) { 109 | case TFC_MODE_PLAIN: 110 | case TFC_MODE_XOR: 111 | case TFC_MODE_STREAM: return YES; 112 | } 113 | 114 | return NO; 115 | } 116 | 117 | void tfc_getcurtime(tfc_useconds *tx) 118 | { 119 | struct timespec t; 120 | memset(&t, 0, sizeof(t)); 121 | 122 | clock_gettime(CLOCK_MONOTONIC, &t); 123 | *tx = (tfc_useconds)t.tv_sec * 1000000 + (t.tv_nsec / 1000); 124 | 125 | memset(&t, 0, sizeof(t)); 126 | } 127 | 128 | char *tfc_format_time(tfc_useconds t) 129 | { 130 | tfc_useconds secs, dsecs; 131 | unsigned days, hours, minutes, seconds; 132 | static char r[128]; 133 | 134 | secs = (tfc_useconds)TFC_UTODSECS(t); 135 | dsecs = (tfc_useconds)(t - (secs * 1000000)); 136 | 137 | days = secs / 86400; 138 | hours = (secs / 3600) % 24; 139 | minutes = (secs / 60) % 60; 140 | seconds = secs % 60; 141 | 142 | if (days > 0) sprintf(r, "%ud,%02u:%02u:%02u.%04u", days, hours, minutes, seconds, (unsigned)(dsecs / 100)); 143 | else if (hours > 0) sprintf(r, "%02u:%02u:%02u.%04u", hours, minutes, seconds, (unsigned)(dsecs / 100)); 144 | else if (minutes > 0) sprintf(r, "%02u:%02u.%04u", minutes, seconds, (unsigned)(dsecs / 100)); 145 | else sprintf(r, "%02u.%04u", seconds, (unsigned)(dsecs / 100)); 146 | 147 | return r; 148 | } 149 | 150 | char *tfc_format_pid(const char *str) 151 | { 152 | static char r[128]; 153 | size_t n; 154 | 155 | n = xstrlcpy(r, str, sizeof(r)); 156 | if (show_pid == YES && sizeof(r)-n >= 22) sprintf(r+n, "[%lu]", (unsigned long)progpid); 157 | 158 | return r; 159 | } 160 | 161 | tfc_fsize tfc_fdsize(int fd) 162 | { 163 | off_t l, cur; 164 | 165 | cur = lseek(fd, 0L, SEEK_CUR); 166 | l = lseek(fd, 0L, SEEK_SET); 167 | if (l == -1) return NOFSIZE; 168 | l = lseek(fd, 0L, SEEK_END); 169 | if (l == -1) return NOFSIZE; 170 | lseek(fd, cur, SEEK_SET); 171 | 172 | return (tfc_fsize)l; 173 | } 174 | 175 | tfc_fsize tfc_fdgetpos(int fd) 176 | { 177 | off_t t; 178 | 179 | t = lseek(fd, 0L, SEEK_CUR); 180 | if (t == (off_t)-1) return NOFSIZE; 181 | return (tfc_fsize)t; 182 | } 183 | 184 | tfc_fsize tfc_fnamesize(char *fname, tfc_yesno noexit) 185 | { 186 | int fnmfd; 187 | tfc_fsize ret; 188 | char *s, T[2]; 189 | 190 | if (!fname) return 0; 191 | 192 | s = strchr(fname, ':'); 193 | if (s && s[1] && (s[1] == '+' || s[1] == '-' || s[1] == '*' || s[1] == '/')) { 194 | memcpy(T, s, 2); 195 | memset(s, 0, 2); 196 | } 197 | 198 | fnmfd = xxopen(YES, fname, O_RDONLY); 199 | if (s) memcpy(s, T, 2); 200 | if (fnmfd == -1) { 201 | xerror(noexit, NO, YES, "%s", fname); 202 | return NOFSIZE; 203 | } 204 | ret = tfc_fdsize(fnmfd); 205 | if (ret == NOFSIZE) { 206 | xerror(noexit, NO, YES, "%s: not a seekable file", fname); 207 | return ret; 208 | } 209 | xclose(fnmfd); 210 | 211 | return ret; 212 | } 213 | 214 | tfc_fsize tfc_modifysize(tfc_fsize szmodify, const char *szspec) 215 | { 216 | tfc_fsize t; 217 | const char *s; 218 | char *stoi, c; 219 | 220 | if (szmodify == NOFSIZE) return NOFSIZE; 221 | if (!szspec) return szmodify; 222 | s = szspec; 223 | 224 | if (*s != ':') return szmodify; 225 | s++; 226 | if (!(*s == '+' || *s == '-' || *s == '*' || *s == '/')) return szmodify; 227 | c = *s; 228 | s++; 229 | if (strchr(s, '/') || strchr(s, '.')) return szmodify; 230 | 231 | t = tfc_humanfsize(s, &stoi); 232 | if (!str_empty(stoi)) return szmodify; 233 | 234 | switch (c) { 235 | case '+': szmodify += t; break; 236 | case '-': szmodify -= t; break; 237 | case '*': szmodify *= t; break; 238 | case '/': szmodify /= t; break; 239 | default: break; 240 | } 241 | 242 | return szmodify; 243 | } 244 | 245 | void fcopy_matime(int fd, const struct stat *st) 246 | { 247 | struct timeval times[2]; 248 | 249 | times[1].tv_sec = times[0].tv_sec = st->st_mtime; 250 | times[1].tv_usec = times[0].tv_usec = 0; 251 | if (futimes(fd, times) == -1) xerror(YES, NO, YES, "futimes(%d)", fd); 252 | } 253 | 254 | static void char_to_nul(char *s, size_t l, int c) 255 | { 256 | while (*s && l) { if (*s == c) { *s = 0; break; } s++; l--; } 257 | } 258 | 259 | tfc_yesno xfgets(char *s, size_t n, FILE *f) 260 | { 261 | memset(s, 0, n); 262 | 263 | if (fgets(s, (int)n, f) == s) { 264 | char_to_nul(s, n, '\n'); 265 | return YES; 266 | } 267 | 268 | return NO; 269 | } 270 | 271 | tfc_yesno isbase64(const char *s) 272 | { 273 | while (*s) { 274 | if (*s >= 'g' && *s <= 'z') return YES; 275 | if (*s >= 'G' && *s <= 'Z') return YES; 276 | if (*s == '+' || *s == '/' || *s == '=') return YES; 277 | s++; 278 | } 279 | return NO; 280 | } 281 | 282 | static int chrbin(char x) 283 | { 284 | if (x >= '0' && x <= '9') 285 | return x - '0'; 286 | if (x >= 'A' && x <= 'F') 287 | return x - 'A' + 10; 288 | if (x >= 'a' && x <= 'f') 289 | return x - 'a' + 10; 290 | return 0; 291 | } 292 | 293 | void hex2bin(void *d, const char *s) 294 | { 295 | const char *S = s; 296 | char *D = d; 297 | int x = 0; 298 | 299 | while (*s) { 300 | if ((s-S) % 2) { 301 | x = (x << 4) ^ chrbin(*s); 302 | *D = x; D++; 303 | } 304 | else x = chrbin(*s); 305 | s++; 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /tfcrypt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #ifndef _TFCRYPT_H 30 | #define _TFCRYPT_H 31 | 32 | #ifndef _DEFAULT_SOURCE 33 | #define _DEFAULT_SOURCE 34 | #endif 35 | #ifndef _BSD_SOURCE 36 | #define _BSD_SOURCE 37 | #endif 38 | #ifndef _XOPEN_SOURCE 39 | #define _XOPEN_SOURCE 700 40 | #endif 41 | #ifndef _LARGEFILE64_SOURCE 42 | #define _LARGEFILE64_SOURCE 43 | #endif 44 | #ifndef _FILE_OFFSET_BITS 45 | #define _FILE_OFFSET_BITS 64 46 | #endif 47 | 48 | #ifndef _TFCRYPT_VERSION 49 | #error Version number may help you to identify missing functionality. 50 | #endif 51 | 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | 68 | typedef void (*sighandler_t)(int); 69 | 70 | #include "base64.h" 71 | #include "getpasswd.h" 72 | #include "tfdef.h" 73 | #include "skein.h" 74 | #include "tfe.h" 75 | #include "tfprng.h" 76 | 77 | typedef short tfc_yesno; 78 | typedef TF_BYTE_TYPE tfc_byte; 79 | typedef unsigned long long tfc_fsize; 80 | typedef unsigned long long tfc_useconds; 81 | 82 | #ifndef TFC_BLKSIZE 83 | #define TFC_BLKSIZE 65536 84 | #endif 85 | 86 | #ifndef TFC_MAX_SALT 87 | #define TFC_MAX_SALT (2048 + TF_KEY_SIZE) 88 | #endif 89 | 90 | #ifndef TFC_XTSBLOCKS 91 | #define TFC_XTSBLOCKS 32 92 | #endif 93 | 94 | #ifndef TFC_B64_WIDTH 95 | #define TFC_B64_WIDTH 76 96 | #endif 97 | #define TFC_B64_EWIDTH (TFC_B64_WIDTH - (TFC_B64_WIDTH / 4)) 98 | #define TFC_B64_DWIDTH TFC_BLKSIZE 99 | 100 | #define NOSIZE ((size_t)-1) 101 | #define NOFSIZE ((tfc_fsize)-1) 102 | #define TFC_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 103 | 104 | #define TFC_KEY_BITS (do_full_key == NO ? TF_MAX_BITS : TF_NR_KEY_BITS) 105 | 106 | #define TFC_ASCII_TFC_MAC_FOURCC "%TF" 107 | #define TFC_ASCII_TFC_MAC_FOURCC_LEN (sizeof(TFC_ASCII_TFC_MAC_FOURCC)-1) 108 | 109 | #define TFC_U(x) ((unsigned)x) 110 | #define TFC_DTOUSECS(x) ((x) * 1000000.0) 111 | #define TFC_UTODSECS(x) ((x) / 1000000.0) 112 | 113 | #define TFC_DEFAULT_RANDSOURCE "/dev/urandom" 114 | #define TFC_STDIN_NAME "(stdin)" 115 | #define TFC_STDOUT_NAME "(stdout)" 116 | 117 | #define TFC_TMPSIZE (TF_BLOCK_SIZE * 4) 118 | 119 | int xmhexdump(int to, const void *data, size_t szdata, int hgroup, int hexstr, int newline); 120 | #define mhexdump(data, szdata, group, newline) xmhexdump(1, data, szdata, group, do_full_hexdump, newline) 121 | #define mehexdump(data, szdata, group, newline) xmhexdump(2, data, szdata, group, do_full_hexdump, newline) 122 | 123 | size_t xstrlcpy(char *dst, const char *src, size_t size); 124 | size_t xstrlcat(char *dst, const char *src, size_t size); 125 | 126 | extern size_t nr_turns; 127 | extern int ctr_mode; 128 | extern size_t macbits; 129 | extern size_t tfc_saltsz; 130 | extern tfc_byte tfc_salt[TFC_MAX_SALT]; 131 | extern tfc_yesno do_full_key; 132 | 133 | extern char *progname; 134 | extern int exitcode; 135 | extern pid_t progpid; 136 | extern tfc_byte key[TF_KEY_SIZE], ctr[TF_BLOCK_SIZE], xtskey[TF_KEY_SIZE], mackey[TF_FROM_BITS(TF_MAX_BITS)], tweak[TF_TWEAK_SIZE]; 137 | extern struct skein sk; 138 | extern struct tfe_stream tfe; 139 | extern tfc_byte srcblk[TFC_BLKSIZE], dstblk[TFC_BLKSIZE], *pblk; 140 | extern tfc_byte macvrfy[SKEIN_DIGEST_SIZE], macresult[SKEIN_DIGEST_SIZE]; 141 | extern tfc_byte tmpdata[TFC_TMPSIZE]; 142 | extern char *randsource; 143 | extern tfc_fsize iseek_blocks, iseek, oseek, maxlen, ftrunc_dfd; 144 | extern tfc_fsize total_processed_src, total_processed_dst, total_written_dst; 145 | extern tfc_fsize delta_processed; 146 | extern tfc_fsize genrandom_nr_bytes, genzero_nr_bytes; 147 | extern tfc_fsize rdpos; 148 | extern tfc_fsize maxkeylen, keyoffset; 149 | extern int sfd, kfd, dfd; 150 | extern struct stat s_stat; 151 | extern size_t blksize, xtsblocks; 152 | extern char pwdask[512], pwdagain[512]; 153 | extern size_t lio, lrem, ldone, lblock; 154 | extern size_t ctrsz; 155 | extern struct sigaction sigact; 156 | extern size_t sksum_turns; 157 | extern int do_edcrypt, do_stop, quiet, error_action; 158 | extern int counter_opt, mackey_opt, do_mac, do_outfmt, rawkey; 159 | extern int idx, write_flags; 160 | extern tfc_yesno catch_all_errors, ignore_seek_errors, password, overwrite_source, do_fsync, do_pad, do_ftrunc; 161 | extern tfc_yesno do_preserve_time, do_stats_in_gibs, do_statline_dynamic, do_less_stats, show_pid, read_only; 162 | extern tfc_yesno no_repeat, do_full_hexdump, verbose, statline_was_shown, show_secrets, show_when_done; 163 | extern char *srcfname, *dstfname, *do_mac_file, *counter_file, *sksum_hashlist_file; 164 | extern char *saltf, *genkeyf, *mackeyf, *tweakf; 165 | extern char *pw_prompt, *mac_pw_prompt; 166 | extern tfc_useconds status_timer, bench_timer; 167 | extern tfc_useconds total_time, current_time, delta_time; 168 | extern struct getpasswd_state getps; 169 | 170 | size_t xread(int fd, void *data, size_t szdata); 171 | size_t xwrite(int fd, const void *data, size_t szdata); 172 | 173 | void xerror(tfc_yesno noexit, tfc_yesno noerrno, tfc_yesno nostats, const char *fmt, ...); 174 | void xexit(int status); 175 | void usage(void); 176 | 177 | void tfc_vfsay(FILE *where, tfc_yesno addnl, const char *fmt, va_list ap); 178 | void tfc_nfsay(FILE *where, const char *fmt, ...); 179 | void tfc_esay(const char *fmt, ...); 180 | void tfc_say(const char *fmt, ...); 181 | 182 | void tfc_printbase64(FILE *where, const void *p, size_t n, tfc_yesno nl); 183 | void tfc_data_to_words64(void *data, size_t szdata); 184 | tfc_fsize tfc_humanfsize(const char *s, char **stoi); 185 | const char *tfc_getscale(int scale); 186 | void tfc_describescale(tfc_fsize num, double *w, int *scale); 187 | size_t blk_len_adj(tfc_fsize filelen, tfc_fsize read_already, size_t blklen); 188 | tfc_yesno xor_shrink(void *dst, size_t szdst, const void *src, size_t szsrc); 189 | tfc_yesno str_empty(const char *str); 190 | int xxopen(tfc_yesno noerr, const char *pathname, int flags); 191 | int xopen(const char *pathname, int flags); 192 | void xclose(int fd); 193 | const char *tfc_modename(int mode); 194 | tfc_yesno tfc_is_freestream(int mode); 195 | void tfc_getcurtime(tfc_useconds *tx); 196 | char *tfc_format_time(tfc_useconds t); 197 | char *tfc_format_pid(const char *str); 198 | tfc_fsize tfc_fdsize(int fd); 199 | tfc_fsize tfc_fdgetpos(int fd); 200 | tfc_fsize tfc_fnamesize(char *fname, tfc_yesno noexit); 201 | tfc_fsize tfc_modifysize(tfc_fsize szmodify, const char *szspec); 202 | void fcopy_matime(int fd, const struct stat *st); 203 | tfc_yesno xfgets(char *s, size_t n, FILE *f); 204 | tfc_yesno isbase64(const char *s); 205 | void hex2bin(void *d, const char *s); 206 | void tfc_finirandom(void); 207 | void tfc_getrandom(void *buf, size_t sz); 208 | void exit_sigterm(int signal); 209 | void handle_sigtstp(int signal); 210 | void print_crypt_status(int signal); 211 | void change_status_width(int signal); 212 | void change_status_timer(int signal); 213 | void setup_next_alarm(tfc_useconds useconds); 214 | void skein(void *hash, size_t bits, const void *key, const void *data, size_t szdata); 215 | tfc_yesno skeinfd(void *hash, size_t bits, const void *key, int fd, tfc_fsize offset, tfc_fsize readto); 216 | 217 | void read_defaults(const char *path, tfc_yesno noerr); 218 | void hash_defaults(char *uhash, size_t szuhash); 219 | 220 | void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes); 221 | void do_edbase64(char **fargv); 222 | void do_sksum(char *spec, char **fargv); 223 | void do_benchmark(tfc_useconds useconds, double dseconds); 224 | 225 | enum { NO, YES }; 226 | 227 | enum { TFC_ERRACT_EXIT, TFC_ERRACT_CONT, TFC_ERRACT_SYNC, TFC_ERRACT_LSYNC }; 228 | enum { TFC_DO_PLAIN, TFC_DO_ENCRYPT, TFC_DO_DECRYPT }; 229 | enum { TFC_MAC_DROP2 = -2, TFC_MAC_DROP = -1, TFC_MAC_SIGN = 1, TFC_MAC_VRFY, TFC_MAC_JUST_VRFY, TFC_MAC_JUST_VRFY2 }; 230 | enum { TFC_MACKEY_RAWKEY = 1, TFC_MACKEY_PASSWORD, TFC_MACKEY_FILE }; 231 | enum { TFC_RAWKEY_KEYFILE = 1, TFC_RAWKEY_ASKSTR, TFC_RAWKEY_ASKHEX }; 232 | enum { TFC_OUTFMT_HEX = 1, TFC_OUTFMT_B64, TFC_OUTFMT_RAW }; 233 | enum { 234 | TFC_MODE_SKSUM = -3, TFC_MODE_XOR = -2, TFC_MODE_PLAIN = -1, TFC_MODE_CTR = 1, 235 | TFC_MODE_STREAM, TFC_MODE_XTS, TFC_MODE_ECB, TFC_MODE_CBC, TFC_MODE_PCBC 236 | }; 237 | enum { TFC_CTR_SHOW = 1, TFC_CTR_HEAD, TFC_CTR_RAND, TFC_CTR_ZERO, TFC_CTR_SSET }; 238 | enum { TFC_NO_FTRUNC, TFC_DO_FTRUNC, TFC_FTRUNC_TAIL }; 239 | enum { TFC_SIGLAST = -2, TFC_SIGERR = -1, TFC_SIGSTAT = 0 }; 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /tfc_skein.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | #include "tfcore.h" 31 | 32 | static void exit_sigterm_skein(int signal) 33 | { 34 | exit_sigterm(signal); 35 | } 36 | 37 | void skein(void *hash, size_t bits, const void *key, const void *data, size_t szdata) 38 | { 39 | struct skein sk; 40 | 41 | if (key) skein_init_key(&sk, key, bits); 42 | else skein_init(&sk, bits); 43 | skein_update(&sk, data, szdata); 44 | skein_final(hash, &sk); 45 | } 46 | 47 | tfc_yesno skeinfd(void *hash, size_t bits, const void *key, int fd, tfc_fsize offset, tfc_fsize readto) 48 | { 49 | static tfc_byte skblk[TFC_BLKSIZE]; 50 | 51 | struct skein sk; 52 | tfc_byte *pblk; 53 | size_t ldone, lblock, lrem, lio; 54 | tfc_fsize total = 0; 55 | 56 | if (ctr_mode == TFC_MODE_SKSUM) total_processed_src = total_processed_dst = delta_processed = 0; 57 | 58 | if (fd == -1) goto _fail; 59 | if (fd > 2) { 60 | if (readto == NOFSIZE) { 61 | readto = tfc_fdsize(fd); 62 | if (readto == NOFSIZE) goto _fail; 63 | } 64 | if (offset != 0 && offset != NOFSIZE) { 65 | if (lseek(fd, (off_t)offset, SEEK_SET) == -1) { 66 | if (ignore_seek_errors == NO) goto _fail; 67 | } 68 | } 69 | } 70 | 71 | if (key) skein_init_key(&sk, key, bits); 72 | else skein_init(&sk, bits); 73 | 74 | errno = 0; 75 | do_stop = NO; 76 | while (1) { 77 | if (do_stop) break; 78 | pblk = skblk; 79 | lblock = lrem = blk_len_adj(readto, total, TFC_BLKSIZE); 80 | ldone = 0; 81 | if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(fd); 82 | _again: lio = xread(fd, pblk, lrem); 83 | if (lio == 0) do_stop = YES; 84 | if (lio != NOSIZE) ldone += lio; 85 | else { 86 | if (errno != EIO && catch_all_errors != YES) goto _fail; 87 | switch (error_action) { 88 | case TFC_ERRACT_CONT: xerror(YES, NO, NO, "skeinfd: %d", fd); goto _again; break; 89 | case TFC_ERRACT_SYNC: 90 | case TFC_ERRACT_LSYNC: 91 | xerror(YES, NO, NO, "skeinfd: %d", fd); 92 | lio = lrem = ldone = lblock; 93 | total += lio; 94 | memset(skblk, 0, lio); 95 | if (rdpos == NOFSIZE) lseek(fd, lio, SEEK_CUR); 96 | else lseek(fd, rdpos + lio, SEEK_SET); 97 | break; 98 | default: goto _fail; break; 99 | } 100 | } 101 | if (lio && lio < lrem) { 102 | pblk += lio; 103 | lrem -= lio; 104 | goto _again; 105 | } 106 | total += ldone; 107 | if (ctr_mode == TFC_MODE_SKSUM) { 108 | total_processed_src = total_processed_dst = total; 109 | delta_processed += ldone; 110 | } 111 | skein_update(&sk, skblk, ldone); 112 | if (readto != NOFSIZE && total >= readto) break; 113 | } 114 | 115 | if (fd > 2) lseek(fd, (off_t)readto, SEEK_SET); 116 | 117 | skein_final(hash, &sk); 118 | if (ctr_mode == TFC_MODE_SKSUM) { 119 | if (verbose || status_timer) { 120 | print_crypt_status(TFC_SIGSTAT); 121 | tfc_esay("\n"); 122 | } 123 | total_processed_src = total_processed_dst = delta_processed = 0; 124 | } 125 | memset(skblk, 0, TFC_BLKSIZE); 126 | return YES; 127 | 128 | _fail: 129 | memset(&sk, 0, sizeof(struct skein)); 130 | memset(hash, 0, SKEIN_DIGEST_SIZE); 131 | memset(skblk, 0, TFC_BLKSIZE); 132 | return NO; 133 | } 134 | 135 | void do_sksum(char *spec, char **fargv) 136 | { 137 | static char sksblk[TFC_BLKSIZE / 2], tmp[TFC_TMPSIZE]; 138 | tfc_byte hash[SKEIN_DIGEST_SIZE]; 139 | int fd = -1; 140 | int x = 0, xx; 141 | size_t bits; 142 | 143 | if (macbits < TF_MAX_BITS) { 144 | bits = macbits; 145 | goto _dothat; 146 | } 147 | 148 | if (!strcmp(spec, "sksum")) { 149 | bits = TF_MAX_BITS; 150 | goto _dothat; 151 | } 152 | 153 | if ((sscanf(spec, "sk%zusum", &bits) < 1)) { 154 | bits = TF_MAX_BITS; 155 | } 156 | 157 | if (bits < 8 || bits > TF_MAX_BITS) { 158 | xerror(NO, YES, YES, 159 | "%u: invalid bits number specified!\n" 160 | "tfcrypt supports from 8 to %u bits, divisible by 8.", 161 | bits, TFC_U(TF_MAX_BITS)); 162 | } 163 | 164 | if (!bits || bits % 8) { 165 | xerror(NO, YES, YES, 166 | "%u: invalid bits number specified!\n" 167 | "Number of bits must start from 8 and be divisible by 8.", 168 | bits, TFC_U(TF_MAX_BITS)); 169 | } 170 | 171 | _dothat: 172 | do_edcrypt = TFC_DO_PLAIN; 173 | ctr_mode = TFC_MODE_SKSUM; 174 | 175 | for (x = 1; x < NSIG; x++) signal(x, SIG_IGN); 176 | memset(&sigact, 0, sizeof(sigact)); 177 | sigact.sa_flags = SA_RESTART; 178 | sigact.sa_handler = print_crypt_status; 179 | sigaction(SIGUSR1, &sigact, NULL); 180 | sigaction(SIGALRM, &sigact, NULL); 181 | sigact.sa_handler = change_status_width; 182 | sigaction(SIGQUIT, &sigact, NULL); 183 | sigact.sa_handler = change_status_timer; 184 | sigaction(SIGUSR2, &sigact, NULL); 185 | sigact.sa_handler = exit_sigterm_skein; 186 | sigaction(SIGINT, &sigact, NULL); 187 | sigaction(SIGTERM, &sigact, NULL); 188 | sigact.sa_handler = handle_sigtstp; 189 | sigaction(SIGTSTP, &sigact, NULL); 190 | memset(&sigact, 0, sizeof(struct sigaction)); 191 | 192 | tfc_getcurtime(&delta_time); 193 | 194 | if (sksum_hashlist_file) { 195 | FILE *f; 196 | char *s, *d, *t, *shash, *fname; 197 | int failed = 0, totaltested = 0; 198 | 199 | if (!strcmp(sksum_hashlist_file, "-")) f = stdin; 200 | else f = fopen(sksum_hashlist_file, "r"); 201 | if (!f) xerror(NO, NO, YES, "%s", sksum_hashlist_file); 202 | 203 | while (1) { 204 | memset(sksblk, 0, sizeof(sksblk)); 205 | if (xfgets(sksblk, sizeof(sksblk), f) != YES) break; 206 | 207 | s = d = sksblk; t = NULL; 208 | shash = fname = NULL; 209 | while ((s = strtok_r(d, "\t", &t))) { 210 | if (d) d = NULL; 211 | 212 | if (!shash) shash = s; 213 | else if (shash && !fname) fname = s; 214 | } 215 | 216 | if (!shash || !fname) { 217 | xerror(YES, NO, YES, "invalid string %s", sksblk); 218 | exitcode = 2; 219 | continue; 220 | } 221 | 222 | s = strchr(shash, ' '); 223 | if (s && s[1] == ' ') *s = 0; 224 | 225 | fd = xxopen(YES, fname, O_RDONLY | O_LARGEFILE); 226 | if (fd == -1) { 227 | xerror(YES, NO, YES, "%s", fname); 228 | exitcode = 1; 229 | continue; 230 | } 231 | 232 | if (status_timer) setup_next_alarm(status_timer > 1000000 ? 1000000 : status_timer); 233 | if (skeinfd(hash, bits, mackey_opt ? mackey : NULL, fd, iseek, maxlen) != YES) { 234 | xerror(YES, NO, YES, "%s", fname); 235 | exitcode = 1; 236 | continue; 237 | } 238 | xclose(fd); 239 | if (sksum_turns > 1) { 240 | size_t y; 241 | for (y = 0; y < sksum_turns; y++) 242 | skein(hash, bits, mackey_opt ? mackey : NULL, hash, TF_FROM_BITS(bits)); 243 | } 244 | if (isbase64(shash)) base64_decode(tmp, sizeof(tmp), shash, strlen(shash)); 245 | else hex2bin(tmp, shash); 246 | 247 | if (!memcmp(hash, tmp, TF_FROM_BITS(bits))) { 248 | tfc_say("%s: OK", fname); 249 | } 250 | else { 251 | tfc_say("%s: FAILED", fname); 252 | failed++; 253 | } 254 | memset(tmp, 0, sizeof(tmp)); 255 | memset(sksblk, 0, sizeof(sksblk)); 256 | totaltested++; 257 | } 258 | 259 | fclose(f); 260 | if (failed) { 261 | tfc_esay("%s: WARNING: %u of %u computed checksums did NOT match", 262 | tfc_format_pid(progname), failed, totaltested); 263 | exitcode = 1; 264 | } 265 | xexit(exitcode); 266 | } 267 | 268 | for (xx = 0; fargv[xx]; xx++); 269 | if (xx == 0) { 270 | fd = 0; 271 | x = 0; 272 | goto _dohash; 273 | } 274 | 275 | for (x = 0; fargv[x] && xx; x++) { 276 | if (!strcmp(fargv[x], "-")) fd = 0; 277 | else fd = xxopen(YES, fargv[x], O_RDONLY | O_LARGEFILE); 278 | if (fd == -1) { 279 | xerror(YES, NO, YES, "%s", fargv[x]); 280 | exitcode = 1; 281 | continue; 282 | } 283 | 284 | _dohash: if (status_timer) setup_next_alarm(status_timer > 1000000 ? 1000000 : status_timer); 285 | if (skeinfd(hash, bits, mackey_opt ? mackey : NULL, fd, iseek, maxlen) != YES) { 286 | xerror(YES, NO, YES, "%s", fargv[x]); 287 | exitcode = 1; 288 | continue; 289 | } 290 | xclose(fd); 291 | if (sksum_turns > 1) { 292 | size_t y; 293 | for (y = 0; y < sksum_turns; y++) skein(hash, bits, mackey_opt ? mackey : NULL, hash, TF_FROM_BITS(bits)); 294 | } 295 | if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stdout, hash, TF_FROM_BITS(bits), 0); 296 | else if (do_outfmt == TFC_OUTFMT_RAW) xwrite(1, hash, TF_FROM_BITS(bits)); 297 | else mhexdump(hash, TF_FROM_BITS(bits), TF_FROM_BITS(bits), 0); 298 | if (do_outfmt != TFC_OUTFMT_RAW) { 299 | if (quiet == NO || xx > 1) tfc_say("\t%s", fargv[x] ? fargv[x] : "-"); 300 | else tfc_say("\n"); 301 | } 302 | } 303 | 304 | memset(hash, 0, SKEIN_DIGEST_SIZE); 305 | xexit(exitcode); 306 | } 307 | -------------------------------------------------------------------------------- /tfenc.c: -------------------------------------------------------------------------------- 1 | #include "tfdef.h" 2 | #include "tfcore.h" 3 | 4 | #if defined(TF_256BITS) 5 | 6 | #define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6) \ 7 | do { \ 8 | KE_MIX(Y, X, k1 + k2, k3, TFS_KS01); \ 9 | KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS02); \ 10 | \ 11 | BE_MIX(X, T, TFS_BS01); BE_MIX(Z, Y, TFS_BS02); \ 12 | BE_MIX(X, Y, TFS_BS03); BE_MIX(Z, T, TFS_BS04); \ 13 | BE_MIX(X, T, TFS_BS05); BE_MIX(Z, Y, TFS_BS06); \ 14 | } while (0) 15 | 16 | #define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6) \ 17 | do { \ 18 | KE_MIX(Y, X, k1 + k2, k3, TFS_KS03); \ 19 | KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS04); \ 20 | \ 21 | BE_MIX(X, T, TFS_BS07); BE_MIX(Z, Y, TFS_BS08); \ 22 | BE_MIX(X, Y, TFS_BS09); BE_MIX(Z, T, TFS_BS10); \ 23 | BE_MIX(X, T, TFS_BS11); BE_MIX(Z, Y, TFS_BS12); \ 24 | } while (0) 25 | 26 | void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K) 27 | { 28 | TF_UNIT_TYPE X, Y, Z, T; 29 | TF_UNIT_TYPE K0, K1, K2, K3; 30 | TF_UNIT_TYPE K4, T0, T1, T2; 31 | 32 | X = I[0]; Y = I[1]; Z = I[2]; T = I[3]; 33 | 34 | K0 = K[0]; K1 = K[1]; K2 = K[2]; K3 = K[3]; 35 | K4 = K[4]; T0 = K[5]; T1 = K[6]; T2 = K[7]; 36 | 37 | PROCESS_BLOCKP( 0,K1,T0,K0,K3,K2,T1); 38 | PROCESS_BLOCKN( 1,K2,T1,K1,K4,K3,T2); 39 | PROCESS_BLOCKP( 2,K3,T2,K2,K0,K4,T0); 40 | PROCESS_BLOCKN( 3,K4,T0,K3,K1,K0,T1); 41 | 42 | PROCESS_BLOCKP( 4,K0,T1,K4,K2,K1,T2); 43 | PROCESS_BLOCKN( 5,K1,T2,K0,K3,K2,T0); 44 | PROCESS_BLOCKP( 6,K2,T0,K1,K4,K3,T1); 45 | PROCESS_BLOCKN( 7,K3,T1,K2,K0,K4,T2); 46 | 47 | PROCESS_BLOCKP( 8,K4,T2,K3,K1,K0,T0); 48 | PROCESS_BLOCKN( 9,K0,T0,K4,K2,K1,T1); 49 | PROCESS_BLOCKP(10,K1,T1,K0,K3,K2,T2); 50 | PROCESS_BLOCKN(11,K2,T2,K1,K4,K3,T0); 51 | 52 | PROCESS_BLOCKP(12,K3,T0,K2,K0,K4,T1); 53 | PROCESS_BLOCKN(13,K4,T1,K3,K1,K0,T2); 54 | PROCESS_BLOCKP(14,K0,T2,K4,K2,K1,T0); 55 | PROCESS_BLOCKN(15,K1,T0,K0,K3,K2,T1); 56 | 57 | PROCESS_BLOCKP(16,K2,T1,K1,K4,K3,T2); 58 | PROCESS_BLOCKN(17,K3,T2,K2,K0,K4,T0); 59 | 60 | O[0] = X + K3; O[1] = Y + K4 + T0; O[2] = Z + K0 + T1; O[3] = T + K1 + 18; 61 | } 62 | 63 | #elif defined(TF_512BITS) 64 | 65 | #define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \ 66 | do { \ 67 | KE_MIX(Y, X, k1, k2, TFS_KS01); KE_MIX(T, Z, k3, k4, TFS_KS02); \ 68 | KE_MIX(W, E, k5 + k6, k7, TFS_KS03); \ 69 | KE_MIX(N, V, k8 + x, k9 + k10, TFS_KS04); \ 70 | \ 71 | BE_MIX(Z, Y, TFS_BS01); BE_MIX(E, N, TFS_BS02); \ 72 | BE_MIX(V, W, TFS_BS03); BE_MIX(X, T, TFS_BS04); \ 73 | BE_MIX(E, Y, TFS_BS05); BE_MIX(V, T, TFS_BS06); \ 74 | BE_MIX(X, W, TFS_BS07); BE_MIX(Z, N, TFS_BS08); \ 75 | BE_MIX(V, Y, TFS_BS09); BE_MIX(X, N, TFS_BS10); \ 76 | BE_MIX(Z, W, TFS_BS11); BE_MIX(E, T, TFS_BS12); \ 77 | } while (0) 78 | 79 | #define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \ 80 | do { \ 81 | KE_MIX(Y, X, k1, k2, TFS_KS05); KE_MIX(T, Z, k3, k4, TFS_KS06); \ 82 | KE_MIX(W, E, k5 + k6, k7, TFS_KS07); \ 83 | KE_MIX(N, V, k8 + x, k9 + k10, TFS_KS08); \ 84 | \ 85 | BE_MIX(Z, Y, TFS_BS13); BE_MIX(E, N, TFS_BS14); \ 86 | BE_MIX(V, W, TFS_BS15); BE_MIX(X, T, TFS_BS16); \ 87 | BE_MIX(E, Y, TFS_BS17); BE_MIX(V, T, TFS_BS18); \ 88 | BE_MIX(X, W, TFS_BS19); BE_MIX(Z, N, TFS_BS20); \ 89 | BE_MIX(V, Y, TFS_BS21); BE_MIX(X, N, TFS_BS22); \ 90 | BE_MIX(Z, W, TFS_BS23); BE_MIX(E, T, TFS_BS24); \ 91 | } while (0) 92 | 93 | void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K) 94 | { 95 | TF_UNIT_TYPE X, Y, Z, T; 96 | TF_UNIT_TYPE E, W, V, N; 97 | TF_UNIT_TYPE K0, K1, K2, K3; 98 | TF_UNIT_TYPE K4, K5, K6, K7; 99 | TF_UNIT_TYPE K8, T0, T1, T2; 100 | 101 | X = I[0]; Y = I[1]; Z = I[2]; T = I[3]; 102 | E = I[4]; W = I[5]; V = I[6]; N = I[7]; 103 | 104 | K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3]; 105 | K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7]; 106 | K8 = K[ 8]; T0 = K[ 9]; T1 = K[10]; T2 = K[11]; 107 | 108 | PROCESS_BLOCKP( 0,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1); 109 | PROCESS_BLOCKN( 1,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2); 110 | PROCESS_BLOCKP( 2,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0); 111 | PROCESS_BLOCKN( 3,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1); 112 | 113 | PROCESS_BLOCKP( 4,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2); 114 | PROCESS_BLOCKN( 5,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0); 115 | PROCESS_BLOCKP( 6,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1); 116 | PROCESS_BLOCKN( 7,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2); 117 | 118 | PROCESS_BLOCKP( 8,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0); 119 | PROCESS_BLOCKN( 9,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1); 120 | PROCESS_BLOCKP(10,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2); 121 | PROCESS_BLOCKN(11,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0); 122 | 123 | PROCESS_BLOCKP(12,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1); 124 | PROCESS_BLOCKN(13,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2); 125 | PROCESS_BLOCKP(14,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0); 126 | PROCESS_BLOCKN(15,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1); 127 | 128 | PROCESS_BLOCKP(16,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2); 129 | PROCESS_BLOCKN(17,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0); 130 | 131 | O[0] = X + K0; O[1] = Y + K1; O[2] = Z + K2; O[3] = T + K3; 132 | O[4] = E + K4; O[5] = W + K5 + T0; O[6] = V + K6 + T1; O[7] = N + K7 + 18; 133 | } 134 | 135 | #elif defined(TF_1024BITS) 136 | 137 | #define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\ 138 | do { \ 139 | KE_MIX(Y, X, k1, k2, TFS_KS01); KE_MIX(T, Z, k3, k4, TFS_KS02); \ 140 | KE_MIX(W, E, k5, k6, TFS_KS03); KE_MIX(N, V, k7, k8, TFS_KS04); \ 141 | KE_MIX(U, P, k9, k10, TFS_KS05); KE_MIX(Q, M, k11, k12, TFS_KS06); \ 142 | KE_MIX(B, A, k13 + k14, k15, TFS_KS07); \ 143 | KE_MIX(L, H, k16 + x, k17 + k18, TFS_KS08); \ 144 | \ 145 | BE_MIX(X, U, TFS_BS01); BE_MIX(Z, B, TFS_BS02); \ 146 | BE_MIX(V, Q, TFS_BS03); BE_MIX(E, L, TFS_BS04); \ 147 | BE_MIX(M, N, TFS_BS05); BE_MIX(A, T, TFS_BS06); \ 148 | BE_MIX(H, W, TFS_BS07); BE_MIX(P, Y, TFS_BS08); \ 149 | BE_MIX(X, N, TFS_BS09); BE_MIX(Z, W, TFS_BS10); \ 150 | BE_MIX(E, T, TFS_BS11); BE_MIX(V, Y, TFS_BS12); \ 151 | BE_MIX(A, L, TFS_BS13); BE_MIX(H, B, TFS_BS14); \ 152 | BE_MIX(P, Q, TFS_BS15); BE_MIX(M, U, TFS_BS16); \ 153 | BE_MIX(X, L, TFS_BS17); BE_MIX(Z, Q, TFS_BS18); \ 154 | BE_MIX(V, B, TFS_BS19); BE_MIX(E, U, TFS_BS20); \ 155 | BE_MIX(H, Y, TFS_BS21); BE_MIX(P, W, TFS_BS22); \ 156 | BE_MIX(M, T, TFS_BS23); BE_MIX(A, N, TFS_BS24); \ 157 | } while (0) 158 | 159 | #define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\ 160 | do { \ 161 | KE_MIX(Y, X, k1, k2, TFS_KS09); KE_MIX(T, Z, k3, k4, TFS_KS10); \ 162 | KE_MIX(W, E, k5, k6, TFS_KS11); KE_MIX(N, V, k7, k8, TFS_KS12); \ 163 | KE_MIX(U, P, k9, k10, TFS_KS13); KE_MIX(Q, M, k11, k12, TFS_KS14); \ 164 | KE_MIX(B, A, k13 + k14, k15, TFS_KS15); \ 165 | KE_MIX(L, H, k16 + x, k17 + k18, TFS_KS16); \ 166 | \ 167 | BE_MIX(X, U, TFS_BS25); BE_MIX(Z, B, TFS_BS26); \ 168 | BE_MIX(V, Q, TFS_BS27); BE_MIX(E, L, TFS_BS28); \ 169 | BE_MIX(M, N, TFS_BS29); BE_MIX(A, T, TFS_BS30); \ 170 | BE_MIX(H, W, TFS_BS31); BE_MIX(P, Y, TFS_BS32); \ 171 | BE_MIX(X, N, TFS_BS33); BE_MIX(Z, W, TFS_BS34); \ 172 | BE_MIX(E, T, TFS_BS35); BE_MIX(V, Y, TFS_BS36); \ 173 | BE_MIX(A, L, TFS_BS37); BE_MIX(H, B, TFS_BS38); \ 174 | BE_MIX(P, Q, TFS_BS39); BE_MIX(M, U, TFS_BS40); \ 175 | BE_MIX(X, L, TFS_BS41); BE_MIX(Z, Q, TFS_BS42); \ 176 | BE_MIX(V, B, TFS_BS43); BE_MIX(E, U, TFS_BS44); \ 177 | BE_MIX(H, Y, TFS_BS45); BE_MIX(P, W, TFS_BS46); \ 178 | BE_MIX(M, T, TFS_BS47); BE_MIX(A, N, TFS_BS48); \ 179 | } while (0) 180 | 181 | void tf_encrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K) 182 | { 183 | TF_UNIT_TYPE X, Y, Z, T; 184 | TF_UNIT_TYPE E, W, V, N; 185 | TF_UNIT_TYPE P, U, M, Q; 186 | TF_UNIT_TYPE A, B, H, L; 187 | TF_UNIT_TYPE K0, K1, K2, K3; 188 | TF_UNIT_TYPE K4, K5, K6, K7; 189 | TF_UNIT_TYPE K8, K9, K10, K11; 190 | TF_UNIT_TYPE K12, K13, K14, K15; 191 | TF_UNIT_TYPE K16, T0, T1, T2; 192 | 193 | X = I[ 0]; Y = I[ 1]; Z = I[ 2]; T = I[ 3]; 194 | E = I[ 4]; W = I[ 5]; V = I[ 6]; N = I[ 7]; 195 | P = I[ 8]; U = I[ 9]; M = I[10]; Q = I[11]; 196 | A = I[12]; B = I[13]; H = I[14]; L = I[15]; 197 | 198 | K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3]; 199 | K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7]; 200 | K8 = K[ 8]; K9 = K[ 9]; K10 = K[10]; K11 = K[11]; 201 | K12 = K[12]; K13 = K[13]; K14 = K[14]; K15 = K[15]; 202 | K16 = K[16]; T0 = K[17]; T1 = K[18]; T2 = K[19]; 203 | 204 | PROCESS_BLOCKP( 0, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T0,K12,K15,K14, T1); 205 | PROCESS_BLOCKN( 1, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T1,K13,K16,K15, T2); 206 | PROCESS_BLOCKP( 2, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T2,K14, K0,K16, T0); 207 | PROCESS_BLOCKN( 3, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16, T0,K15, K1, K0, T1); 208 | 209 | PROCESS_BLOCKP( 4, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0, T1,K16, K2, K1, T2); 210 | PROCESS_BLOCKN( 5, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, T2, K0, K3, K2, T0); 211 | PROCESS_BLOCKP( 6, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, T0, K1, K4, K3, T1); 212 | PROCESS_BLOCKN( 7, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, T1, K2, K5, K4, T2); 213 | 214 | PROCESS_BLOCKP( 8, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, T2, K3, K6, K5, T0); 215 | PROCESS_BLOCKN( 9,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, T0, K4, K7, K6, T1); 216 | PROCESS_BLOCKP(10,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, T1, K5, K8, K7, T2); 217 | PROCESS_BLOCKN(11,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, T2, K6, K9, K8, T0); 218 | 219 | PROCESS_BLOCKP(12,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, T0, K7,K10, K9, T1); 220 | PROCESS_BLOCKN(13,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, T1, K8,K11,K10, T2); 221 | PROCESS_BLOCKP(14,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, T2, K9,K12,K11, T0); 222 | PROCESS_BLOCKN(15,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11, T0,K10,K13,K12, T1); 223 | 224 | PROCESS_BLOCKP(16, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12, T1,K11,K14,K13, T2); 225 | PROCESS_BLOCKN(17, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T2,K12,K15,K14, T0); 226 | PROCESS_BLOCKP(18, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T0,K13,K16,K15, T1); 227 | PROCESS_BLOCKN(19, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T1,K14, K0,K16, T2); 228 | 229 | O[0] = X + K3; O[1] = Y + K4; O[2] = Z + K5; O[3] = T + K6; 230 | O[4] = E + K7; O[5] = W + K8; O[6] = V + K9; O[7] = N + K10; 231 | O[8] = P + K11; O[9] = U + K12; O[10] = M + K13; O[11] = Q + K14; 232 | O[12] = A + K15; O[13] = B + K16 + T2; O[14] = H + K0 + T0; O[15] = L + K1 + 20; 233 | } 234 | 235 | #endif 236 | -------------------------------------------------------------------------------- /tfdec.c: -------------------------------------------------------------------------------- 1 | #include "tfdef.h" 2 | #include "tfcore.h" 3 | 4 | #if defined(TF_256BITS) 5 | 6 | #define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6) \ 7 | do { \ 8 | BD_MIX(Z, Y, TFS_BS06); BD_MIX(X, T, TFS_BS05); \ 9 | BD_MIX(Z, T, TFS_BS04); BD_MIX(X, Y, TFS_BS03); \ 10 | BD_MIX(Z, Y, TFS_BS02); BD_MIX(X, T, TFS_BS01); \ 11 | \ 12 | KD_MIX(T, Z, k4 + x, k5 + k6, TFS_KS02); \ 13 | KD_MIX(Y, X, k1 + k2, k3, TFS_KS01); \ 14 | } while (0) 15 | 16 | #define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6) \ 17 | do { \ 18 | BD_MIX(Z, Y, TFS_BS12); BD_MIX(X, T, TFS_BS11); \ 19 | BD_MIX(Z, T, TFS_BS10); BD_MIX(X, Y, TFS_BS09); \ 20 | BD_MIX(Z, Y, TFS_BS08); BD_MIX(X, T, TFS_BS07); \ 21 | \ 22 | KD_MIX(T, Z, k4 + x, k5 + k6, TFS_KS04); \ 23 | KD_MIX(Y, X, k1 + k2, k3, TFS_KS03); \ 24 | } while (0) 25 | 26 | void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K) 27 | { 28 | TF_UNIT_TYPE X, Y, Z, T; 29 | TF_UNIT_TYPE K0, K1, K2, K3; 30 | TF_UNIT_TYPE K4, T0, T1, T2; 31 | 32 | X = I[0]; Y = I[1]; Z = I[2]; T = I[3]; 33 | 34 | K0 = K[0]; K1 = K[1]; K2 = K[2]; K3 = K[3]; 35 | K4 = K[4]; T0 = K[5]; T1 = K[6]; T2 = K[7]; 36 | 37 | X -= K3; Y -= K4 + T0; Z -= K0 + T1; T -= K1 + 18; 38 | 39 | PROCESS_BLOCKN(17,K3,T2,K2,K0,K4,T0); 40 | PROCESS_BLOCKP(16,K2,T1,K1,K4,K3,T2); 41 | 42 | PROCESS_BLOCKN(15,K1,T0,K0,K3,K2,T1); 43 | PROCESS_BLOCKP(14,K0,T2,K4,K2,K1,T0); 44 | PROCESS_BLOCKN(13,K4,T1,K3,K1,K0,T2); 45 | PROCESS_BLOCKP(12,K3,T0,K2,K0,K4,T1); 46 | 47 | PROCESS_BLOCKN(11,K2,T2,K1,K4,K3,T0); 48 | PROCESS_BLOCKP(10,K1,T1,K0,K3,K2,T2); 49 | PROCESS_BLOCKN( 9,K0,T0,K4,K2,K1,T1); 50 | PROCESS_BLOCKP( 8,K4,T2,K3,K1,K0,T0); 51 | 52 | PROCESS_BLOCKN( 7,K3,T1,K2,K0,K4,T2); 53 | PROCESS_BLOCKP( 6,K2,T0,K1,K4,K3,T1); 54 | PROCESS_BLOCKN( 5,K1,T2,K0,K3,K2,T0); 55 | PROCESS_BLOCKP( 4,K0,T1,K4,K2,K1,T2); 56 | 57 | PROCESS_BLOCKN( 3,K4,T0,K3,K1,K0,T1); 58 | PROCESS_BLOCKP( 2,K3,T2,K2,K0,K4,T0); 59 | PROCESS_BLOCKN( 1,K2,T1,K1,K4,K3,T2); 60 | PROCESS_BLOCKP( 0,K1,T0,K0,K3,K2,T1); 61 | 62 | O[0] = X; O[1] = Y; O[2] = Z; O[3] = T; 63 | } 64 | 65 | #elif defined(TF_512BITS) 66 | 67 | #define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \ 68 | do { \ 69 | BD_MIX(E, T, TFS_BS12); BD_MIX(Z, W, TFS_BS11); \ 70 | BD_MIX(X, N, TFS_BS10); BD_MIX(V, Y, TFS_BS09); \ 71 | BD_MIX(Z, N, TFS_BS08); BD_MIX(X, W, TFS_BS07); \ 72 | BD_MIX(V, T, TFS_BS06); BD_MIX(E, Y, TFS_BS05); \ 73 | BD_MIX(X, T, TFS_BS04); BD_MIX(V, W, TFS_BS03); \ 74 | BD_MIX(E, N, TFS_BS02); BD_MIX(Z, Y, TFS_BS01); \ 75 | \ 76 | KD_MIX(N, V, k8 + x, k9 + k10, TFS_KS04); \ 77 | KD_MIX(W, E, k5 + k6, k7, TFS_KS03); \ 78 | KD_MIX(T, Z, k3, k4, TFS_KS02); KD_MIX(Y, X, k1, k2, TFS_KS01); \ 79 | } while (0) 80 | 81 | #define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10) \ 82 | do { \ 83 | BD_MIX(E, T, TFS_BS24); BD_MIX(Z, W, TFS_BS23); \ 84 | BD_MIX(X, N, TFS_BS22); BD_MIX(V, Y, TFS_BS21); \ 85 | BD_MIX(Z, N, TFS_BS20); BD_MIX(X, W, TFS_BS19); \ 86 | BD_MIX(V, T, TFS_BS18); BD_MIX(E, Y, TFS_BS17); \ 87 | BD_MIX(X, T, TFS_BS16); BD_MIX(V, W, TFS_BS15); \ 88 | BD_MIX(E, N, TFS_BS14); BD_MIX(Z, Y, TFS_BS13); \ 89 | \ 90 | KD_MIX(N, V, k8 + x, k9 + k10, TFS_KS08); \ 91 | KD_MIX(W, E, k5 + k6, k7, TFS_KS07); \ 92 | KD_MIX(T, Z, k3, k4, TFS_KS06); KD_MIX(Y, X, k1, k2, TFS_KS05); \ 93 | } while (0) 94 | 95 | void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K) 96 | { 97 | TF_UNIT_TYPE X, Y, Z, T; 98 | TF_UNIT_TYPE E, W, V, N; 99 | TF_UNIT_TYPE K0, K1, K2, K3; 100 | TF_UNIT_TYPE K4, K5, K6, K7; 101 | TF_UNIT_TYPE K8, T0, T1, T2; 102 | 103 | X = I[0]; Y = I[1]; Z = I[2]; T = I[3]; 104 | E = I[4]; W = I[5]; V = I[6]; N = I[7]; 105 | 106 | K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3]; 107 | K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7]; 108 | K8 = K[ 8]; T0 = K[ 9]; T1 = K[10]; T2 = K[11]; 109 | 110 | X -= K0; Y -= K1; Z -= K2; T -= K3; 111 | E -= K4; W -= K5 + T0; V -= K6 + T1; N -= K7 + 18; 112 | 113 | PROCESS_BLOCKN(17,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0); 114 | PROCESS_BLOCKP(16,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2); 115 | 116 | PROCESS_BLOCKN(15,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1); 117 | PROCESS_BLOCKP(14,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0); 118 | PROCESS_BLOCKN(13,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2); 119 | PROCESS_BLOCKP(12,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1); 120 | 121 | PROCESS_BLOCKN(11,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0); 122 | PROCESS_BLOCKP(10,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2); 123 | PROCESS_BLOCKN( 9,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1); 124 | PROCESS_BLOCKP( 8,K0,K8,K2,K1,K4,T2,K3,K6,K5,T0); 125 | 126 | PROCESS_BLOCKN( 7,K8,K7,K1,K0,K3,T1,K2,K5,K4,T2); 127 | PROCESS_BLOCKP( 6,K7,K6,K0,K8,K2,T0,K1,K4,K3,T1); 128 | PROCESS_BLOCKN( 5,K6,K5,K8,K7,K1,T2,K0,K3,K2,T0); 129 | PROCESS_BLOCKP( 4,K5,K4,K7,K6,K0,T1,K8,K2,K1,T2); 130 | 131 | PROCESS_BLOCKN( 3,K4,K3,K6,K5,K8,T0,K7,K1,K0,T1); 132 | PROCESS_BLOCKP( 2,K3,K2,K5,K4,K7,T2,K6,K0,K8,T0); 133 | PROCESS_BLOCKN( 1,K2,K1,K4,K3,K6,T1,K5,K8,K7,T2); 134 | PROCESS_BLOCKP( 0,K1,K0,K3,K2,K5,T0,K4,K7,K6,T1); 135 | 136 | O[0] = X; O[1] = Y; O[2] = Z; O[3] = T; 137 | O[4] = E; O[5] = W; O[6] = V; O[7] = N; 138 | } 139 | 140 | #elif defined(TF_1024BITS) 141 | 142 | #define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\ 143 | do { \ 144 | BD_MIX(A, N, TFS_BS24); BD_MIX(M, T, TFS_BS23); \ 145 | BD_MIX(P, W, TFS_BS22); BD_MIX(H, Y, TFS_BS21); \ 146 | BD_MIX(E, U, TFS_BS20); BD_MIX(V, B, TFS_BS19); \ 147 | BD_MIX(Z, Q, TFS_BS18); BD_MIX(X, L, TFS_BS17); \ 148 | BD_MIX(M, U, TFS_BS16); BD_MIX(P, Q, TFS_BS15); \ 149 | BD_MIX(H, B, TFS_BS14); BD_MIX(A, L, TFS_BS13); \ 150 | BD_MIX(V, Y, TFS_BS12); BD_MIX(E, T, TFS_BS11); \ 151 | BD_MIX(Z, W, TFS_BS10); BD_MIX(X, N, TFS_BS09); \ 152 | BD_MIX(P, Y, TFS_BS08); BD_MIX(H, W, TFS_BS07); \ 153 | BD_MIX(A, T, TFS_BS06); BD_MIX(M, N, TFS_BS05); \ 154 | BD_MIX(E, L, TFS_BS04); BD_MIX(V, Q, TFS_BS03); \ 155 | BD_MIX(Z, B, TFS_BS02); BD_MIX(X, U, TFS_BS01); \ 156 | \ 157 | KD_MIX(L, H, k16 + x, k17 + k18, TFS_KS08); \ 158 | KD_MIX(B, A, k13 + k14, k15, TFS_KS07); \ 159 | KD_MIX(Q, M, k11, k12, TFS_KS06); KD_MIX(U, P, k9, k10, TFS_KS05); \ 160 | KD_MIX(N, V, k7, k8, TFS_KS04); KD_MIX(W, E, k5, k6, TFS_KS03); \ 161 | KD_MIX(T, Z, k3, k4, TFS_KS02); KD_MIX(Y, X, k1, k2, TFS_KS01); \ 162 | } while (0) 163 | 164 | #define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,k17,k18)\ 165 | do { \ 166 | BD_MIX(A, N, TFS_BS48); BD_MIX(M, T, TFS_BS47); \ 167 | BD_MIX(P, W, TFS_BS46); BD_MIX(H, Y, TFS_BS45); \ 168 | BD_MIX(E, U, TFS_BS44); BD_MIX(V, B, TFS_BS43); \ 169 | BD_MIX(Z, Q, TFS_BS42); BD_MIX(X, L, TFS_BS41); \ 170 | BD_MIX(M, U, TFS_BS40); BD_MIX(P, Q, TFS_BS39); \ 171 | BD_MIX(H, B, TFS_BS38); BD_MIX(A, L, TFS_BS37); \ 172 | BD_MIX(V, Y, TFS_BS36); BD_MIX(E, T, TFS_BS35); \ 173 | BD_MIX(Z, W, TFS_BS34); BD_MIX(X, N, TFS_BS33); \ 174 | BD_MIX(P, Y, TFS_BS32); BD_MIX(H, W, TFS_BS31); \ 175 | BD_MIX(A, T, TFS_BS30); BD_MIX(M, N, TFS_BS29); \ 176 | BD_MIX(E, L, TFS_BS28); BD_MIX(V, Q, TFS_BS27); \ 177 | BD_MIX(Z, B, TFS_BS26); BD_MIX(X, U, TFS_BS25); \ 178 | \ 179 | KD_MIX(L, H, k16 + x, k17 + k18, TFS_KS16); \ 180 | KD_MIX(B, A, k13 + k14, k15, TFS_KS15); \ 181 | KD_MIX(Q, M, k11, k12, TFS_KS14); KD_MIX(U, P, k9, k10, TFS_KS13); \ 182 | KD_MIX(N, V, k7, k8, TFS_KS12); KD_MIX(W, E, k5, k6, TFS_KS11); \ 183 | KD_MIX(T, Z, k3, k4, TFS_KS10); KD_MIX(Y, X, k1, k2, TFS_KS09); \ 184 | } while (0) 185 | 186 | void tf_decrypt_rawblk(TF_UNIT_TYPE *O, const TF_UNIT_TYPE *I, const TF_UNIT_TYPE *K) 187 | { 188 | TF_UNIT_TYPE X, Y, Z, T; 189 | TF_UNIT_TYPE E, W, V, N; 190 | TF_UNIT_TYPE P, U, M, Q; 191 | TF_UNIT_TYPE A, B, H, L; 192 | TF_UNIT_TYPE K0, K1, K2, K3; 193 | TF_UNIT_TYPE K4, K5, K6, K7; 194 | TF_UNIT_TYPE K8, K9, K10, K11; 195 | TF_UNIT_TYPE K12, K13, K14, K15; 196 | TF_UNIT_TYPE K16, T0, T1, T2; 197 | 198 | X = I[ 0]; Y = I[ 1]; Z = I[ 2]; T = I[ 3]; 199 | E = I[ 4]; W = I[ 5]; V = I[ 6]; N = I[ 7]; 200 | P = I[ 8]; U = I[ 9]; M = I[10]; Q = I[11]; 201 | A = I[12]; B = I[13]; H = I[14]; L = I[15]; 202 | 203 | K0 = K[ 0]; K1 = K[ 1]; K2 = K[ 2]; K3 = K[ 3]; 204 | K4 = K[ 4]; K5 = K[ 5]; K6 = K[ 6]; K7 = K[ 7]; 205 | K8 = K[ 8]; K9 = K[ 9]; K10 = K[10]; K11 = K[11]; 206 | K12 = K[12]; K13 = K[13]; K14 = K[14]; K15 = K[15]; 207 | K16 = K[16]; T0 = K[17]; T1 = K[18]; T2 = K[19]; 208 | 209 | X -= K3; Y -= K4; Z -= K5; T -= K6; 210 | E -= K7; W -= K8; V -= K9; N -= K10; 211 | P -= K11; U -= K12; M -= K13; Q -= K14; 212 | A -= K15; B -= K16 + T2; H -= K0 + T0; L -= K1 + 20; 213 | 214 | PROCESS_BLOCKN(19, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T1,K14, K0,K16, T2); 215 | PROCESS_BLOCKP(18, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T0,K13,K16,K15, T1); 216 | PROCESS_BLOCKN(17, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T2,K12,K15,K14, T0); 217 | PROCESS_BLOCKP(16, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12, T1,K11,K14,K13, T2); 218 | 219 | PROCESS_BLOCKN(15,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11, T0,K10,K13,K12, T1); 220 | PROCESS_BLOCKP(14,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, K7,K10, T2, K9,K12,K11, T0); 221 | PROCESS_BLOCKN(13,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, K6, K9, T1, K8,K11,K10, T2); 222 | PROCESS_BLOCKP(12,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, K5, K8, T0, K7,K10, K9, T1); 223 | 224 | PROCESS_BLOCKN(11,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, K4, K7, T2, K6, K9, K8, T0); 225 | PROCESS_BLOCKP(10,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, K3, K6, T1, K5, K8, K7, T2); 226 | PROCESS_BLOCKN( 9,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, K2, K5, T0, K4, K7, K6, T1); 227 | PROCESS_BLOCKP( 8, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, K1, K4, T2, K3, K6, K5, T0); 228 | 229 | PROCESS_BLOCKN( 7, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, K0, K3, T1, K2, K5, K4, T2); 230 | PROCESS_BLOCKP( 6, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0,K16, K2, T0, K1, K4, K3, T1); 231 | PROCESS_BLOCKN( 5, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16,K15, K1, T2, K0, K3, K2, T0); 232 | PROCESS_BLOCKP( 4, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15,K14, K0, T1,K16, K2, K1, T2); 233 | 234 | PROCESS_BLOCKN( 3, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14,K13,K16, T0,K15, K1, K0, T1); 235 | PROCESS_BLOCKP( 2, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13,K12,K15, T2,K14, K0,K16, T0); 236 | PROCESS_BLOCKN( 1, K2, K1, K4, K3, K6, K5, K8, K7,K10, K9,K12,K11,K14, T1,K13,K16,K15, T2); 237 | PROCESS_BLOCKP( 0, K1, K0, K3, K2, K5, K4, K7, K6, K9, K8,K11,K10,K13, T0,K12,K15,K14, T1); 238 | 239 | O[0] = X; O[1] = Y; O[2] = Z; O[3] = T; 240 | O[4] = E; O[5] = W; O[6] = V; O[7] = N; 241 | O[8] = P; O[9] = U; O[10] = M; O[11] = Q; 242 | O[12] = A; O[13] = B; O[14] = H; O[15] = L; 243 | } 244 | 245 | #endif 246 | -------------------------------------------------------------------------------- /tfc_error.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | void xerror(tfc_yesno noexit, tfc_yesno noerrno, tfc_yesno nostats, const char *fmt, ...) 32 | { 33 | va_list ap; 34 | char *s; 35 | 36 | if (quiet) goto _do_sil_exit; 37 | 38 | va_start(ap, fmt); 39 | 40 | if (noexit == YES && (statline_was_shown == YES && do_statline_dynamic == YES)) tfc_esay("\n"); 41 | 42 | tfc_nfsay(stderr, "%s: ", tfc_format_pid(progname)); 43 | tfc_vfsay(stderr, NO, fmt, ap); 44 | if (errno && noerrno == NO) { 45 | s = strerror(errno); 46 | tfc_esay(": %s", s); 47 | } 48 | else tfc_esay("\n"); 49 | 50 | va_end(ap); 51 | 52 | if (nostats == NO) { 53 | print_crypt_status(TFC_SIGERR); 54 | } 55 | 56 | _do_sil_exit: 57 | if (noexit == YES) { 58 | errno = 0; 59 | return; 60 | } 61 | 62 | xexit(2); 63 | } 64 | 65 | void xexit(int status) 66 | { 67 | if (status > 1) goto _do_clean_and_exit; 68 | 69 | if (do_ftrunc > TFC_NO_FTRUNC) { 70 | if (do_ftrunc == TFC_FTRUNC_TAIL) ftrunc_dfd = total_processed_dst; 71 | if (ftruncate(dfd, (off_t)ftrunc_dfd) == -1) xerror(YES, NO, YES, "ftruncate(%d)", dfd); 72 | } 73 | if (do_preserve_time) fcopy_matime(dfd, &s_stat); 74 | 75 | _do_clean_and_exit: 76 | xclose(sfd); 77 | xclose(dfd); 78 | 79 | memset(srcblk, 0, sizeof(srcblk)); 80 | memset(dstblk, 0, sizeof(dstblk)); 81 | 82 | memset(key, 0, sizeof(key)); 83 | memset(ctr, 0, sizeof(ctr)); 84 | memset(mackey, 0, sizeof(mackey)); 85 | memset(xtskey, 0, sizeof(xtskey)); 86 | memset(tweak, 0, sizeof(tweak)); 87 | memset(&sk, 0, sizeof(struct skein)); 88 | memset(&tfe, 0, sizeof(struct tfe_stream)); 89 | 90 | tfc_finirandom(); 91 | 92 | memset(macvrfy, 0, sizeof(macvrfy)); 93 | memset(macresult, 0, sizeof(macresult)); 94 | 95 | memset(tmpdata, 0, sizeof(tmpdata)); 96 | memset(&getps, 0, sizeof(struct getpasswd_state)); 97 | memset(pwdask, 0, sizeof(pwdask)); 98 | memset(pwdagain, 0, sizeof(pwdagain)); 99 | 100 | exit(status); 101 | } 102 | 103 | void usage(void) 104 | { 105 | tfc_yesno is_embedded_prog = NO; 106 | 107 | if (optopt == 'V') { 108 | tfc_say("tfcrypt toolkit, version %s.", _TFCRYPT_VERSION); 109 | if (do_edcrypt != TFC_DO_PLAIN) { 110 | char shash[64]; 111 | 112 | hash_defaults(shash, sizeof(shash)); 113 | tfc_say("Defaults hash: %s", shash); 114 | memset(shash, 0, sizeof(shash)); 115 | } 116 | xexit(0); 117 | } 118 | 119 | if (!strcmp(progname, "iotool")) { 120 | is_embedded_prog = YES; 121 | tfc_say("usage: %s [-E how] [-l length] [-O opts] [-aqvw] [-V secs] [source] [output]", progname); 122 | tfc_say("\n"); 123 | tfc_say("%s: do dd-like input/output, writing source to output whole or partially.", progname); 124 | tfc_say(" -E how: how to behave on I/O errors (both src or dst):"); 125 | tfc_say(" exit: print error if not quiet, then exit,"); 126 | tfc_say(" cont: print error if not quiet, then continue,"); 127 | tfc_say(" no action to pad missing data is attempted."); 128 | tfc_say(" may be dangerous when working with block devices."); 129 | tfc_say(" sync: print error if not quiet, then continue,"); 130 | tfc_say(" pad missing data block with zeroes."); 131 | tfc_say(" lsync: same as sync, but does not use SEEK_SET logic,"); 132 | tfc_say(" lsync uses only relative seek operations, and does not prequery"); 133 | tfc_say(" the current file position for exact offsets, which maybe unsafe."); 134 | tfc_say(" For this reason, it is HIGHLY recommended to use sync instead!"); 135 | tfc_say(" Note that both sync and lsync work only with read errors!"); 136 | tfc_say(" default error action is exit with printing status if not quiet."); 137 | tfc_say(" -E xall: turn on error actions above for all errors, not just EIO errors."); 138 | tfc_say(" -E xseek: ignore positioning and other seek related errors."); 139 | tfc_say(" Multiple -E specifiers may be given in separate options."); 140 | tfc_say(" -a: shortcut of -O xtime."); 141 | tfc_say(" -l length: read only these first bytes of source."); 142 | tfc_say(" -O opts: set options (comma separated list):"); 143 | tfc_say(" ro: open all files only for reading, even those intended for writing,"); 144 | tfc_say(" sync: request a synchronous I/O for a output,"); 145 | tfc_say(" fsync: on each write() call a corresponding fsync(fd),"); 146 | tfc_say(" trunc: open(O_WRONLY) will truncate output file to zero size."); 147 | tfc_say(" append: open(O_APPEND) will append data to output file."); 148 | tfc_say(" pad: pad incomplete (l.t. %u bytes) block with zeroes.", TFC_U(TF_BLOCK_SIZE)); 149 | tfc_say(" xtime: copy timestamps from source to destination files."); 150 | tfc_say(" gibsize: use SI units of size: 1k = 1000. Applies only to size prefixes."); 151 | tfc_say(" Computers convention is to use 1024, whereas SI/hdd measure in 1000."); 152 | tfc_say(" plainstats: force status line to be plain: no fancy dynamic stuff."); 153 | tfc_say(" Dynamic line works well only on VT100 compatible ttys, and"); 154 | tfc_say(" when the whole status line width is smaller than tty width."); 155 | tfc_say(" statless: emit less information in status line (only processed data)."); 156 | tfc_say(" iobs=val: set IO block size value. Must not exceed %u bytes.", TFC_U(TFC_BLKSIZE)); 157 | tfc_say(" nobuf: disable IO buffering, write as soon as data received (only for stream ciphers!)"); 158 | tfc_say(" iseek=val: seek source file/device by these val bytes."); 159 | tfc_say(" oseek=val: seek destination file/device by these val bytes."); 160 | tfc_say(" ioseek=val: seek both source and destination."); 161 | tfc_say(" ioseek is equal to iseek and oseek."); 162 | tfc_say(" count=val: process only these val bytes, both input and output."); 163 | tfc_say(" ftrunc=val: truncate output file to these val bytes before closing it."); 164 | tfc_say(" ftrunc=tail: truncate output's tail, leaving only processed data."); 165 | tfc_say(" -w: overwrite source file. If not file, ignored."); 166 | tfc_say(" -q: always be quiet, never tell anything (except when signaled)."); 167 | tfc_say(" -v: print number of read and written encrypted bytes, and explain stages."); 168 | tfc_say(" -V seconds: activate timer that will repeatedly print statistics to stderr."); 169 | tfc_say("\n"); 170 | } 171 | else if ((strlen(progname) <= 9) 172 | && ((!strcmp(progname, "sksum")) 173 | || ((!memcmp(progname, "sk", 2)) 174 | && (!memcmp(progname+3, "sum", 3) 175 | || !memcmp(progname+4, "sum", 3) 176 | || !memcmp(progname+5, "sum", 3) 177 | || !memcmp(progname+6, "sum", 3))))) { 178 | is_embedded_prog = YES; 179 | tfc_say("usage: %s [-AW] [-D BITS] [-n TURNS] [-l length] [-c ] [-U ] [source] ...", progname); 180 | tfc_say("\n"); 181 | tfc_say("%s: calculate and print Skein hashsum of stream.", progname); 182 | tfc_say(" -D BITS: specify bits as it was skBITSsum."); 183 | tfc_say(" -n TURNS: number of turns to perform in Skein function."); 184 | tfc_say(" sksum defaults to just one in all modes."); 185 | tfc_say(" -A: format checksum in base64 rather than in binary hex."); 186 | tfc_say(" -W: output raw binary checksum and remove filename(s) from output."); 187 | tfc_say(" -H: output small hexdump (hex string and ASCII printable characters)."); 188 | tfc_say(" -l length: read only these first bytes of source."); 189 | tfc_say(" -c : read hashes list from file and check them."); 190 | tfc_say(" -U : read Skein MAC key from file."); 191 | tfc_say("multiple sources can be given in cmdline, and if one of"); 192 | tfc_say("them is specified as \"-\", then reads are performed from stdin."); 193 | tfc_say("\n"); 194 | } 195 | else if (!strcmp(progname, "base64")) { 196 | is_embedded_prog = YES; 197 | tfc_say("usage: %s [-ed] [source] [output]", progname); 198 | tfc_say("\n"); 199 | tfc_say("tfcrypt embedded base64 encoder/decoder."); 200 | tfc_say(" -e: encode stream into base64."); 201 | tfc_say(" -d: decode base64 stream."); 202 | tfc_say("no error checking is performed."); 203 | tfc_say("\n"); 204 | } 205 | else if (!strcmp(progname, "xor")) { 206 | is_embedded_prog = YES; 207 | tfc_say("usage: %s [sourceX] [sourceY] [output]", progname); 208 | tfc_say("\n"); 209 | tfc_say("tfcrypt embedded high performance XOR tool."); 210 | tfc_say("It does XOR (multiply modulo 2) of each byte from sourceX"); 211 | tfc_say("each byte of sourceY and writes output."); 212 | tfc_say("If filenames omitted, it is assumed to operate over"); 213 | tfc_say("standard in to standard out."); 214 | tfc_say("If any of source files is shorter than another,"); 215 | tfc_say("then output is truncated to length of the shortest one."); 216 | tfc_say("\n"); 217 | tfc_say("No error checking is performed."); 218 | tfc_say("Please use iotool options there."); 219 | tfc_say("\n"); 220 | } 221 | else if (!strcmp(progname, "tfbench")) { 222 | is_embedded_prog = YES; 223 | tfc_say("usage: %s seconds", progname); 224 | tfc_say("do an in-memory random data benchmark of Threefish."); 225 | tfc_say("\n"); 226 | } 227 | 228 | if (is_embedded_prog) { 229 | tfc_say("This program is physical part of tfcrypt toolkit."); 230 | tfc_say("(see it's version with %s -V)", progname); 231 | tfc_say("Please note that other tfcrypt options are either ignored there,"); 232 | tfc_say("or result of using them is undefined and it's not a bug."); 233 | 234 | xexit(1); 235 | } 236 | 237 | tfc_say("usage: %s [opts] [--] [key] [source] [output]", progname); 238 | tfc_say("\n"); 239 | tfc_say("tfcrypt toolkit: encrypt streams with Threefish in CTR mode,"); 240 | tfc_say("calculate and check Skein hashsums, generate CSPRNG quality random data,"); 241 | tfc_say("convert encrypted data into ASCII format to ease transmission."); 242 | tfc_say("\n"); 243 | tfc_say(" -e, -d: encrypt, decrypt (it maybe required)."); 244 | tfc_say(" -L : load tfcrypt defaults from file."); 245 | tfc_say(" defaults is text file which defines salt, nr_turns and default mode."); 246 | tfc_say(" -s : load tfcrypt salt from file."); 247 | tfc_say(" -s disable: disable key salting at all."); 248 | tfc_say(" -p: instead of using key, ask for password."); 249 | tfc_say(" -k: use raw (%u byte) key instead of deriving it from arbitrary data.", TFC_U(TF_KEY_SIZE)); 250 | tfc_say(" -z: ask for key in plain C string form through password asker."); 251 | tfc_say(" -x: ask for key in hex string form through password asker."); 252 | tfc_say(" -K : generate key from keyfile or password and write it to file."); 253 | tfc_say(" -t : use (raw) tweak from file."); 254 | tfc_say(" -w: overwrite source file. If not file, ignored."); 255 | tfc_say(" -n TURNS: number of turns to perform in Skein function."); 256 | tfc_say(" Default is always defined when building tfcrypt."); 257 | tfc_say(" -C mode: mode of operation: CTR, STREAM, XTS, ECB, CBC."); 258 | tfc_say(" Default encryption mode can be changed when building tfcrypt."); 259 | tfc_say(" -c opt: initial CTR value initialisation mode:"); 260 | tfc_say(" show: do default action, then dump CTR value to stderr,"); 261 | tfc_say(" head: when decrypting, read CTR from beginning of stream,"); 262 | tfc_say(" rand: generate random CTR and write it to beginning of stream,"); 263 | tfc_say(" zero: assume zero CTR is used, do not read from and write it to stream,"); 264 | tfc_say(" hexc:nr[,hexc:nr,...]: construct counter from given pattern."); 265 | tfc_say(" Example: \"ff:124,08:2,80:2\" will fill counter first with 124 0xff bytes,"); 266 | tfc_say(" then with 2 0x08 bytes, then 2 0x80 bytes. To fill with zeroes, it is"); 267 | tfc_say(" simple to specify just a \"0:128\" as a pattern. Note that bytes that"); 268 | tfc_say(" exceed CTR space will be just dropped, and any unused bytes are set to zeroes."); 269 | tfc_say(" : read CTR from given file (both when encrypting/decrypting)."); 270 | tfc_say(" default is to derive CTR from user provided password or keyfile with"); 271 | tfc_say(" a single Skein function turn over derived, %u byte raw key", TFC_U(TF_KEY_SIZE)); 272 | tfc_say(" -q: always be quiet, never tell anything (except when signaled)."); 273 | tfc_say(" -v: print number of read and written encrypted bytes, and explain stages."); 274 | tfc_say(" -V seconds: activate timer that will repeatedly print statistics to stderr."); 275 | tfc_say(" -a: shortcut of -O xtime."); 276 | tfc_say(" -g: same as '-e -C stream -c rand' or '-d -C stream -c head', depending on mode."); 277 | tfc_say(" -j: same as '-e -C ctr -c rand' or '-d -C ctr -c head', depending on mode."); 278 | tfc_say(" -l length: read only these first bytes of source."); 279 | tfc_say(" -r : specify random source instead of /dev/urandom."); 280 | tfc_say(" -R nr_bytes: generate nr_bytes of random bytes suitable for use as key data."); 281 | tfc_say(" -R also supports these aliases specified instead of nr_bytes:"); 282 | tfc_say(" cbs: output fixed maximum crypt block size (%u bytes),", TFC_U(TF_BLOCK_SIZE)); 283 | tfc_say(" ks: output fixed maximum crypt key size (%u bytes)", TFC_U(TF_KEY_SIZE)); 284 | tfc_say(" xks: output fixed maximum crypt XTS key size (%u bytes)", TFC_U(TF_KEY_SIZE*2)); 285 | tfc_say(" iobs: output %s builtin block size TFC_BLKSIZE (%u bytes),", progname, TFC_U(TFC_BLKSIZE)); 286 | tfc_say(" if nr_bytes is not a valid number or alias, this string will be"); 287 | tfc_say(" used to attempt to open it as file, and examine it's size."); 288 | tfc_say(" Then this examined size will be set as nr_bytes to output."); 289 | tfc_say(" -Z nr_bytes: like -R, but emit zero stream instead of random."); 290 | tfc_say(" -D MACBITS: specify bit width of a MAC signature."); 291 | tfc_say(" -U key/pwd/: read Skein MAC key from file."); 292 | tfc_say(" key: use primary encryption rawkey as a MAC key."); 293 | tfc_say(" pwd: ask for password string that will be used as MAC key."); 294 | tfc_say(" -S MAC: append MAC signature to end of file:"); 295 | tfc_say(" MAC: embed MAC signature into file itself at the end,"); 296 | tfc_say(" : write a detached MAC signature into separate ,"); 297 | tfc_say(" -: write a detached MAC signature to stdout."); 298 | tfc_say(" useful only with variable length files! For block devices,"); 299 | tfc_say(" specify a separate file name to save signature to: -S file."); 300 | tfc_say(" -A: format raw binary data, like MAC signature or Skein hash, in base64."); 301 | tfc_say(" -W: output pure binary data, and disable any strings addition in Skein."); 302 | tfc_say(" -H: output small hexdump (hex string and ASCII printable characters)."); 303 | tfc_say(" -M MAC: verify attached MAC signature when decrypting a file:"); 304 | tfc_say(" MAC: embed MAC signature into file itself at the end,"); 305 | tfc_say(" : write a detached MAC signature into separate ,"); 306 | tfc_say(" -: read a detached MAC signature from stdin,"); 307 | tfc_say(" drop: do not verify attached MAC, if any, and drop it from output."); 308 | tfc_say(" -m: just verify MAC provided with -M. Do not write output file."); 309 | tfc_say(" -u: almost same as -m, but turns on MAC pre-test mode, when verified"); 310 | tfc_say(" signature enables writing output file. It is useful when decrypting small texts."); 311 | tfc_say(" The source must be a seekable file, otherwise this mode will be disabled."); 312 | tfc_say(" In this mode, decryption is done twice and verification done once."); 313 | tfc_say(" Both -m and -u options must be specified after -M."); 314 | tfc_say(" -E how: how to behave on I/O errors (both src or dst):"); 315 | tfc_say(" exit: print error if not quiet, then exit,"); 316 | tfc_say(" cont: print error if not quiet, then continue,"); 317 | tfc_say(" no action to pad missing data is attempted."); 318 | tfc_say(" may be dangerous when working with block devices."); 319 | tfc_say(" sync: print error if not quiet, then continue,"); 320 | tfc_say(" pad missing data block with zeroes."); 321 | tfc_say(" lsync: same as sync, but does not use SEEK_SET logic,"); 322 | tfc_say(" lsync uses only relative seek operations, and does not prequery"); 323 | tfc_say(" the current file position for exact offsets, which maybe unsafe."); 324 | tfc_say(" For this reason, it is HIGHLY recommended to use sync instead!"); 325 | tfc_say(" Note that both sync and lsync work only with read errors!"); 326 | tfc_say(" default error action is exit with printing status if not quiet."); 327 | tfc_say(" -E xall: turn on error actions above for all errors, not just EIO errors."); 328 | tfc_say(" -E xseek: ignore positioning and other seek related errors."); 329 | tfc_say(" Multiple -E specifiers may be given in separate options."); 330 | tfc_say(" -o logfile: redirect all messages to logfile instead of stderr."); 331 | tfc_say(" -O opts: set options (comma separated list):"); 332 | tfc_say(" ro: open all files only for reading, even those intended for writing,"); 333 | tfc_say(" sync: request a synchronous I/O for a output,"); 334 | tfc_say(" fsync: on each write() call a corresponding fsync(fd),"); 335 | tfc_say(" trunc: open(O_WRONLY) will truncate output file to zero size."); 336 | tfc_say(" append: open(O_APPEND) will append data to output file."); 337 | tfc_say(" pad: pad incomplete (l.t. %u bytes) block with zeroes.", TFC_U(TF_BLOCK_SIZE)); 338 | tfc_say(" xtime: copy timestamps from source to destination files."); 339 | tfc_say(" gibsize: use SI units of size: 1k = 1000. Applies only to size prefixes."); 340 | tfc_say(" Computers convention is to use 1024, whereas SI/hdd measure in 1000."); 341 | tfc_say(" plainstats: force status line to be plain: no fancy dynamic stuff."); 342 | tfc_say(" Dynamic line works well only on VT100 compatible ttys, and"); 343 | tfc_say(" when the whole status line width is smaller than tty width."); 344 | tfc_say(" statless: emit less information in status line (only processed data)."); 345 | tfc_say(" norepeat: do not ask for any possible password confirmations."); 346 | tfc_say(" showsecrets: show passwords in plaintext instead of masking them."); 347 | tfc_say(" finished: add \"finished\" word before status line when work is finished."); 348 | tfc_say(" pid: show %s's process id near it's name in error messages, logs etc.", progname); 349 | tfc_say(" readloops=val: when seekable source ends, reading continues from it's beginning again."); 350 | tfc_say(" prompt=str: set main password prompts to this string."); 351 | tfc_say(" macprompt=str: set MAC password prompts to this string."); 352 | tfc_say(" shorthex: with -H, do not print printable characters, dump only hex string."); 353 | tfc_say(" logfile: (same as -o) redirect all messages to logfile instead of stderr."); 354 | tfc_say(" iobs=val: set IO block size value. Must not exceed %u bytes.", TFC_U(TFC_BLKSIZE)); 355 | tfc_say(" nobuf: disable IO buffering, write as soon as data received (only for stream ciphers!)"); 356 | tfc_say(" xtsblocks=val: use these nr of TF blocks per XTS block. Default is %u.", TFC_U(TFC_XTSBLOCKS)); 357 | tfc_say(" iseek=val: seek source file/device by these val bytes."); 358 | tfc_say(" Initial counter is adjusted automatically."); 359 | tfc_say(" ixseek=val: rawseek source file/device by these val bytes."); 360 | tfc_say(" Do not adjust initial counter automatically."); 361 | tfc_say(" ictr=val: Increment initial counter by this val blocks."); 362 | tfc_say(" The size of each block is %u bytes.", TFC_U(TF_BLOCK_SIZE)); 363 | tfc_say(" ictr option is valid only for CTR and CTR like modes."); 364 | tfc_say(" ixctr=val: Increment initial counter by this val bytes."); 365 | tfc_say(" Internally this number is translated into number of %u byte blocks.", TFC_U(TF_BLOCK_SIZE)); 366 | tfc_say(" oseek=val: seek destination file/device by these val bytes."); 367 | tfc_say(" ioseek=val: seek both source and destination."); 368 | tfc_say(" ioseek is equal to iseek and oseek."); 369 | tfc_say(" count=val: process only these val bytes, both input and output."); 370 | tfc_say(" ftrunc=val: truncate output file to these val bytes before closing it."); 371 | tfc_say(" ftrunc=tail: truncate output's tail, leaving only processed data."); 372 | tfc_say(" xkey=val: take only val bytes from user keyfile."); 373 | tfc_say(" okey=val: seek the key before reading it (usually a device)."); 374 | tfc_say(" xctr=val: specify size in bytes of initial counter prepended or read."); 375 | tfc_say(" fullkey: occupy tweak space by key space, extending key size by 256 bits."); 376 | tfc_say(" -P: plain IO mode: disable encryption/decryption code at all."); 377 | tfc_say(" -X: XOR IO mode: same as -P but do XOR of two streams."); 378 | tfc_say("\n"); 379 | tfc_say("Default is to ask for password, then encrypt stdin into stdout."); 380 | tfc_say("Some cmdline parameters may be mutually exclusive, or they can"); 381 | tfc_say("generate errors or behave abnormally. Please understand that some"); 382 | tfc_say("dumb mode error checking may be not performed well, and please read"); 383 | tfc_say("the README included within package and this help text carefully."); 384 | tfc_say("\n"); 385 | 386 | xexit(1); 387 | } 388 | -------------------------------------------------------------------------------- /tfcrypt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tfcrypt -- high security Threefish encryption tool. 3 | * 4 | * tfcrypt is copyrighted: 5 | * Copyright (C) 2012-2019 Andrey Rys. All rights reserved. 6 | * 7 | * tfcrypt is licensed to you under the terms of std. MIT/X11 license: 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining 10 | * a copy of this software and associated documentation files (the 11 | * "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, 13 | * distribute, sublicense, and/or sell copies of the Software, and to 14 | * permit persons to whom the Software is furnished to do so, subject to 15 | * the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be 18 | * included in all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include "tfcrypt.h" 30 | 31 | static tfc_byte svctr[TF_BLOCK_SIZE]; 32 | static tfc_fsize rwd, do_read_loops, loopcnt; 33 | static tfc_yesno unbuffered; 34 | 35 | static void open_log(const char *logfile) 36 | { 37 | int fd; 38 | tfc_yesno ro; 39 | 40 | if (!strcmp(logfile, "-")) return; 41 | 42 | ro = read_only; 43 | read_only = NO; 44 | fd = xopen(logfile, O_WRONLY | O_CREAT | O_LARGEFILE | O_TRUNC); 45 | read_only = ro; 46 | xclose(2); 47 | if (dup2(fd, 2) == -1) xexit(2); 48 | xclose(fd); 49 | do_statline_dynamic = NO; 50 | } 51 | 52 | static int getps_filter(struct getpasswd_state *getps, char chr, size_t pos) 53 | { 54 | if (chr == '\x03') { 55 | getps->retn = ((size_t)-2); 56 | return 6; 57 | } 58 | return 1; 59 | } 60 | 61 | static int getps_hex_filter(struct getpasswd_state *getps, char chr, size_t pos) 62 | { 63 | if (chr == '\x03') { 64 | getps->retn = ((size_t)-2); 65 | return 6; 66 | } 67 | if (chr >= '0' && chr <= '9') return 1; 68 | if (chr >= 'a' && chr <= 'f') return 1; 69 | if (chr >= 'A' && chr <= 'F') return 1; 70 | if (chr == '\x7f' || chr == '\x08' 71 | || chr == '\x15' || chr == '\x17') return 1; 72 | return 0; 73 | } 74 | 75 | static inline int isctrlchr(int c) 76 | { 77 | if (c == 9) return 0; 78 | if (c >= 0 && c <= 31) return 1; 79 | if (c == 127) return 1; 80 | return 0; 81 | } 82 | 83 | static int getps_plain_filter(struct getpasswd_state *getps, char chr, size_t pos) 84 | { 85 | int x; 86 | 87 | x = getps_filter(getps, chr, pos); 88 | if (x != 1) return x; 89 | 90 | if (pos < getps->pwlen && !isctrlchr(chr)) 91 | write(getps->efd, &chr, sizeof(char)); 92 | return 1; 93 | } 94 | 95 | static int getps_plain_hex_filter(struct getpasswd_state *getps, char chr, size_t pos) 96 | { 97 | int x; 98 | 99 | x = getps_hex_filter(getps, chr, pos); 100 | if (x != 1) return x; 101 | 102 | if (pos < getps->pwlen && !isctrlchr(chr)) 103 | write(getps->efd, &chr, sizeof(char)); 104 | return 1; 105 | } 106 | 107 | static void make_hint(void *hint, size_t szhint, const void *data, size_t szdata) 108 | { 109 | char t[TF_FROM_BITS(TF_MAX_BITS)]; 110 | 111 | skein(t, TF_MAX_BITS, NULL, data, szdata); 112 | xor_shrink(hint, szhint, t, sizeof(t)); 113 | memset(t, 0, sizeof(t)); 114 | } 115 | 116 | static void raw_say_hint(void *hint, size_t szhint, const void *data, size_t szdata, const char *prompt) 117 | { 118 | make_hint(hint, szhint, data, szdata); 119 | if (prompt) tfc_nfsay(stderr, "%s: ", prompt); 120 | mehexdump(hint, szhint, szhint, 1); 121 | memset(hint, 0, szhint); 122 | } 123 | 124 | static void say_hint(const void *data, size_t szdata, const char *prompt) 125 | { 126 | char t[TF_SIZE_UNIT]; 127 | raw_say_hint(t, TF_SIZE_UNIT, data, szdata, prompt); 128 | /* t[] is erased (automatically) */ 129 | } 130 | 131 | int main(int argc, char **argv) 132 | { 133 | tfc_yesno flipfd; 134 | int c; 135 | double td; 136 | char *s, *d, *t, *stoi; 137 | size_t x, n; 138 | 139 | progpid = getpid(); 140 | progname = basename(argv[0]); 141 | 142 | if (!isatty(2)) do_statline_dynamic = NO; 143 | 144 | s = (char *)srcblk; 145 | d = getenv("HOME"); 146 | if (!d) d = ""; 147 | n = PATH_MAX > sizeof(srcblk) ? sizeof(srcblk) : PATH_MAX; 148 | if (xstrlcpy(s, d, n) >= n) goto _baddfname; 149 | if (xstrlcat(s, "/.tfcrypt.defs", n) >= n) goto _baddfname; 150 | read_defaults(s, YES); 151 | _baddfname: 152 | memset(s, 0, n); 153 | 154 | if (!strcmp(progname, "iotool")) { 155 | do_edcrypt = TFC_DO_PLAIN; 156 | ctr_mode = TFC_MODE_PLAIN; 157 | } 158 | 159 | if (!strcmp(progname, "xor")) { 160 | do_edcrypt = TFC_DO_PLAIN; 161 | ctr_mode = TFC_MODE_XOR; 162 | /* xor: default to stdin if invoked without args */ 163 | kfd = 0; 164 | } 165 | 166 | opterr = 0; 167 | while ((c = getopt(argc, argv, "L:s:aU:C:r:K:t:PXkzxc:l:qedn:vV:pwE:o:O:S:AmuM:R:Z:WHD:gj")) != -1) { 168 | switch (c) { 169 | case 'L': 170 | read_defaults(optarg, NO); 171 | break; 172 | case 's': 173 | saltf = optarg; 174 | break; 175 | case 'r': 176 | randsource = optarg; 177 | break; 178 | case 'j': 179 | case 'g': 180 | if (c == 'j') ctr_mode = TFC_MODE_CTR; 181 | else if (c == 'g') ctr_mode = TFC_MODE_STREAM; 182 | if (do_edcrypt == TFC_DO_DECRYPT) counter_opt = TFC_CTR_HEAD; 183 | else if (do_edcrypt == TFC_DO_ENCRYPT) counter_opt = TFC_CTR_RAND; 184 | else xerror(NO, YES, YES, "plain mode was selected with -%c, cannot continue", c); 185 | break; 186 | case 'c': 187 | if (!strcasecmp(optarg, "show")) 188 | counter_opt = TFC_CTR_SHOW; 189 | else if (!strcasecmp(optarg, "head")) 190 | counter_opt = TFC_CTR_HEAD; 191 | else if (!strcasecmp(optarg, "rand")) 192 | counter_opt = TFC_CTR_RAND; 193 | else if (!strcasecmp(optarg, "zero")) 194 | counter_opt = TFC_CTR_ZERO; 195 | else if (strchr(optarg, ':')) { 196 | char *ss, chr; 197 | 198 | counter_opt = TFC_CTR_SSET; 199 | n = sizeof(ctr); 200 | 201 | s = d = optarg; t = NULL; 202 | while ((s = strtok_r(d, ",", &t))) { 203 | if (d) d = NULL; 204 | 205 | if (n == 0) break; 206 | ss = strchr(s, ':'); 207 | if (!ss) continue; 208 | *ss = 0; ss++; 209 | chr = (char)strtoul(s, &stoi, 16); 210 | if (!str_empty(stoi)) continue; 211 | x = (size_t)strtoul(ss, &stoi, 10); 212 | if (!str_empty(stoi)) continue; 213 | if (x > n) x = n; 214 | memset(ctr+(sizeof(ctr)-n), (int)chr, x); 215 | n -= x; 216 | } 217 | } 218 | else counter_file = sksum_hashlist_file = optarg; 219 | break; 220 | case 'C': 221 | if (!strcasecmp(optarg, "ctr")) 222 | ctr_mode = TFC_MODE_CTR; 223 | else if (!strcasecmp(optarg, "stream")) 224 | ctr_mode = TFC_MODE_STREAM; 225 | else if (!strcasecmp(optarg, "cbc")) 226 | ctr_mode = TFC_MODE_CBC; 227 | else if (!strcasecmp(optarg, "pcbc")) 228 | ctr_mode = TFC_MODE_PCBC; 229 | else if (!strcasecmp(optarg, "ecb")) 230 | ctr_mode = TFC_MODE_ECB; 231 | else if (!strcasecmp(optarg, "xts")) 232 | ctr_mode = TFC_MODE_XTS; 233 | else xerror(NO, YES, YES, "%s: invalid mode of operation", optarg); 234 | break; 235 | case 'P': 236 | case 'X': 237 | do_edcrypt = TFC_DO_PLAIN; 238 | if (c == 'X') { 239 | ctr_mode = TFC_MODE_XOR; 240 | /* xor: default to stdin if invoked without args */ 241 | kfd = 0; 242 | } 243 | else ctr_mode = TFC_MODE_PLAIN; 244 | break; 245 | case 'e': 246 | if (do_edcrypt != TFC_DO_PLAIN) do_edcrypt = TFC_DO_ENCRYPT; 247 | break; 248 | case 'd': 249 | if (do_edcrypt != TFC_DO_PLAIN) do_edcrypt = TFC_DO_DECRYPT; 250 | break; 251 | case 'D': 252 | macbits = strtoul(optarg, &stoi, 10); 253 | if (macbits == 0 || !str_empty(stoi) || macbits < 8 254 | || macbits > TF_MAX_BITS || macbits % 8) 255 | xerror(NO, YES, YES, "%s: invalid MAC bits setting", optarg); 256 | break; 257 | case 'n': 258 | nr_turns = sksum_turns = strtoul(optarg, &stoi, 10); 259 | if (!str_empty(stoi)) xerror(NO, YES, YES, "%s: invalid number of turns", optarg); 260 | break; 261 | case 'U': 262 | if (!strcasecmp(optarg, "key")) 263 | mackey_opt = TFC_MACKEY_RAWKEY; 264 | else if (!strcasecmp(optarg, "pwd")) 265 | mackey_opt = TFC_MACKEY_PASSWORD; 266 | else { 267 | mackey_opt = TFC_MACKEY_FILE; 268 | mackeyf = optarg; 269 | } 270 | break; 271 | case 'p': 272 | password = YES; 273 | break; 274 | case 'k': 275 | rawkey = TFC_RAWKEY_KEYFILE; 276 | break; 277 | case 'z': 278 | rawkey = TFC_RAWKEY_ASKSTR; 279 | break; 280 | case 'x': 281 | rawkey = TFC_RAWKEY_ASKHEX; 282 | break; 283 | case 'K': 284 | verbose = YES; 285 | genkeyf = optarg; 286 | break; 287 | case 't': 288 | tweakf = optarg; 289 | do_full_key = NO; 290 | break; 291 | case 'l': 292 | if (maxlen != NOFSIZE) break; 293 | 294 | maxlen = tfc_humanfsize(optarg, &stoi); 295 | if (!str_empty(stoi)) { 296 | maxlen = tfc_fnamesize(optarg, YES); 297 | maxlen = tfc_modifysize(maxlen, strchr(optarg, ':')); 298 | if (maxlen == NOFSIZE) xerror(NO, YES, YES, 299 | "%s: invalid count value", optarg); 300 | } 301 | else maxlen = tfc_modifysize(maxlen, strchr(optarg, ':')); 302 | if (counter_opt == TFC_CTR_HEAD) 303 | maxlen += TF_BLOCK_SIZE; 304 | break; 305 | case 'w': 306 | overwrite_source = YES; 307 | break; 308 | case 'E': 309 | if (!strcmp(optarg, "xall")) { 310 | catch_all_errors = YES; 311 | break; 312 | } 313 | if (!strcmp(optarg, "xseek")) { 314 | ignore_seek_errors = YES; 315 | break; 316 | } 317 | if (!strcmp(optarg, "exit")) 318 | error_action = TFC_ERRACT_EXIT; 319 | else if (!strncmp(optarg, "cont", 4)) 320 | error_action = TFC_ERRACT_CONT; 321 | else if (!strcmp(optarg, "sync")) 322 | error_action = TFC_ERRACT_SYNC; 323 | else if (!strcmp(optarg, "lsync")) 324 | error_action = TFC_ERRACT_LSYNC; 325 | else xerror(NO, YES, YES, "invalid error action %s specified", optarg); 326 | break; 327 | case 'o': 328 | open_log(optarg); 329 | break; 330 | case 'O': 331 | s = d = optarg; t = NULL; 332 | while ((s = strtok_r(d, ",", &t))) { 333 | if (d) d = NULL; 334 | if (!strcmp(s, "sync")) 335 | write_flags |= O_SYNC; 336 | else if (!strcmp(s, "trunc")) 337 | write_flags |= O_TRUNC; 338 | else if (!strcmp(s, "append")) 339 | write_flags |= O_APPEND; 340 | else if (!strcmp(s, "fsync")) 341 | do_fsync = YES; 342 | else if (!strcmp(s, "pad")) 343 | do_pad = YES; 344 | else if (!strcmp(s, "ro")) 345 | read_only = YES; 346 | else if (!strcmp(s, "rw")) 347 | read_only = NO; 348 | else if (!strcmp(s, "xtime")) 349 | do_preserve_time = YES; 350 | else if (!strcmp(s, "gibsize")) 351 | do_stats_in_gibs = YES; 352 | else if (!strcmp(s, "plainstats")) 353 | do_statline_dynamic = NO; 354 | else if (!strcmp(s, "statless")) 355 | do_less_stats = YES; 356 | else if (!strcmp(s, "norepeat")) 357 | no_repeat = YES; 358 | else if (!strncmp(s, "prompt", 6) && *(s+6) == '=') 359 | pw_prompt = s+7; 360 | else if (!strncmp(s, "macprompt", 9) && *(s+9) == '=') 361 | mac_pw_prompt = s+10; 362 | else if (!strcmp(s, "shorthex")) 363 | do_full_hexdump = NO; 364 | else if (!strcmp(s, "fullkey")) 365 | do_full_key = YES; 366 | else if (!strcmp(s, "showsecrets")) 367 | show_secrets = YES; 368 | else if (!strcmp(s, "finished")) 369 | show_when_done = YES; 370 | else if (!strcmp(s, "pid")) 371 | show_pid = YES; 372 | else if (!strcmp(s, "nobuf")) { 373 | if (!tfc_is_freestream(ctr_mode)) xerror(NO, YES, YES, 374 | "cannot activate unbuffered mode for non-stream cipher mode %s!", 375 | tfc_modename(ctr_mode)); 376 | else unbuffered = YES; 377 | } 378 | else if (!strncmp(s, "readloops", 9) && *(s+9) == '=') { 379 | do_read_loops = tfc_humanfsize(s+10, &stoi); 380 | if (!str_empty(stoi)) do_read_loops = NOSIZE; 381 | } 382 | else if (!strncmp(s, "logfile", 7) && *(s+7) == '=') 383 | open_log(s+8); 384 | else if (!strncmp(s, "iobs", 4) && *(s+4) == '=') { 385 | s += 5; 386 | blksize = (size_t)tfc_humanfsize(s, &stoi); 387 | if (!str_empty(stoi)) { 388 | blksize = (size_t)tfc_fnamesize(s, YES); 389 | blksize = (size_t)tfc_modifysize((tfc_fsize)blksize, strchr(s, ':')); 390 | if (blksize == NOSIZE) xerror(NO, YES, YES, 391 | "%s: invalid block size value", s); 392 | } 393 | else blksize = (size_t)tfc_modifysize((tfc_fsize)blksize, strchr(s, ':')); 394 | if (!tfc_is_freestream(ctr_mode) && blksize < TF_BLOCK_SIZE) xerror(NO, YES, YES, 395 | "%s: block size is lesser than TF_BLOCK_SIZE (%u bytes)", s, TFC_U(TF_BLOCK_SIZE)); 396 | if (blksize > TFC_BLKSIZE) xerror(NO, YES, YES, 397 | "%s: block size exceeds %u bytes", 398 | s, TFC_U(TFC_BLKSIZE)); 399 | } 400 | else if (!strncmp(s, "xtsblocks", 9) && *(s+9) == '=') { 401 | s += 10; 402 | xtsblocks = (size_t)tfc_humanfsize(s, &stoi); 403 | if (!str_empty(stoi)) { 404 | xtsblocks = (size_t)tfc_fnamesize(s, YES); 405 | xtsblocks = (size_t)tfc_modifysize((tfc_fsize)xtsblocks, strchr(s, ':')); 406 | if (xtsblocks == NOSIZE) xerror(NO, YES, YES, 407 | "%s: invalid blocks per xts block value", s); 408 | } 409 | else xtsblocks = (size_t)tfc_modifysize((tfc_fsize)xtsblocks, strchr(s, ':')); 410 | if (TFC_BLKSIZE % xtsblocks) xerror(NO, YES, YES, 411 | "%s: nr of blocks per xts block is not round to %u bytes", 412 | s, TFC_U(TFC_BLKSIZE)); 413 | if ((xtsblocks * TF_BLOCK_SIZE) > TFC_BLKSIZE) xerror(NO, YES, YES, 414 | "%s: nr of blocks per xts block exceeds %u bytes", 415 | s, TFC_U(TFC_BLKSIZE)); 416 | } 417 | else if (!strncmp(s, "iseek", 5) && *(s+5) == '=') { 418 | s += 6; 419 | iseek = tfc_humanfsize(s, &stoi); 420 | if (!str_empty(stoi)) { 421 | iseek = tfc_fnamesize(s, YES); 422 | iseek = tfc_modifysize(iseek, strchr(s, ':')); 423 | if (iseek == NOFSIZE) xerror(NO, YES, YES, 424 | "%s: invalid iseek value", s); 425 | } 426 | else iseek = tfc_modifysize(iseek, strchr(s, ':')); 427 | if (do_edcrypt != TFC_DO_PLAIN && iseek % TF_BLOCK_SIZE) 428 | xerror(NO, YES, YES, 429 | "%s: not round to TF block size " 430 | "of %u bytes", 431 | s, TFC_U(TF_BLOCK_SIZE)); 432 | iseek_blocks = iseek / TF_BLOCK_SIZE; 433 | } 434 | else if (!strncmp(s, "ixseek", 6) && *(s+6) == '=') { 435 | s += 7; 436 | iseek = tfc_humanfsize(s, &stoi); 437 | if (!str_empty(stoi)) { 438 | iseek = tfc_fnamesize(s, YES); 439 | iseek = tfc_modifysize(iseek, strchr(s, ':')); 440 | if (iseek == NOFSIZE) xerror(NO, YES, YES, 441 | "%s: invalid ixseek value", s); 442 | } 443 | else iseek = tfc_modifysize(iseek, strchr(s, ':')); 444 | } 445 | else if (!strncmp(s, "ictr", 4) && *(s+4) == '=') { 446 | s += 5; 447 | iseek_blocks = tfc_humanfsize(s, &stoi); 448 | if (!str_empty(stoi)) { 449 | iseek_blocks = tfc_fnamesize(s, YES); 450 | if (iseek_blocks == NOFSIZE) 451 | xerror(NO, YES, YES, 452 | "%s: invalid ictr value", s); 453 | iseek_blocks /= TF_BLOCK_SIZE; 454 | iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':')); 455 | } 456 | else iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':')); 457 | } 458 | else if (!strncmp(s, "ixctr", 5) && *(s+5) == '=') { 459 | s += 6; 460 | iseek_blocks = tfc_humanfsize(s, &stoi); 461 | if (!str_empty(stoi)) { 462 | iseek_blocks = tfc_fnamesize(s, YES); 463 | iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':')); 464 | if (iseek_blocks == NOFSIZE) 465 | xerror(NO, YES, YES, 466 | "%s: invalid ixctr value", s); 467 | } 468 | else iseek_blocks = tfc_modifysize(iseek_blocks, strchr(s, ':')); 469 | if (iseek_blocks % TF_BLOCK_SIZE) 470 | xerror(NO, YES, YES, 471 | "%s: not round to TF block size " 472 | "of %u bytes", s, TFC_U(TF_BLOCK_SIZE)); 473 | iseek_blocks /= TF_BLOCK_SIZE; 474 | } 475 | else if (!strncmp(s, "oseek", 5) && *(s+5) == '=') { 476 | s += 6; 477 | oseek = tfc_humanfsize(s, &stoi); 478 | if (!str_empty(stoi)) { 479 | oseek = tfc_fnamesize(s, YES); 480 | oseek = tfc_modifysize(oseek, strchr(s, ':')); 481 | if (oseek == NOFSIZE) xerror(NO, YES, YES, 482 | "%s: invalid oseek value", s); 483 | } 484 | else oseek = tfc_modifysize(oseek, strchr(s, ':')); 485 | } 486 | else if (!strncmp(s, "ioseek", 6) && *(s+6) == '=') { 487 | s += 7; 488 | 489 | iseek = tfc_humanfsize(s, &stoi); 490 | if (!str_empty(stoi)) { 491 | iseek = tfc_fnamesize(s, YES); 492 | iseek = tfc_modifysize(iseek, strchr(s, ':')); 493 | if (iseek == NOFSIZE) xerror(NO, YES, YES, 494 | "%s: invalid iseek value", s); 495 | } 496 | else iseek = tfc_modifysize(iseek, strchr(s, ':')); 497 | if (do_edcrypt != TFC_DO_PLAIN && iseek % TF_BLOCK_SIZE) 498 | xerror(NO, YES, YES, 499 | "%s: not round to TF block size " 500 | "of %u bytes", 501 | s, TFC_U(TF_BLOCK_SIZE)); 502 | iseek_blocks = iseek / TF_BLOCK_SIZE; 503 | 504 | oseek = tfc_humanfsize(s, &stoi); 505 | if (!str_empty(stoi)) { 506 | oseek = tfc_fnamesize(s, YES); 507 | oseek = tfc_modifysize(oseek, strchr(s, ':')); 508 | if (oseek == NOFSIZE) xerror(NO, YES, YES, 509 | "%s: invalid oseek value", s); 510 | } 511 | else oseek = tfc_modifysize(oseek, strchr(s, ':')); 512 | } 513 | else if (!strncmp(s, "count", 5) && *(s+5) == '=') { 514 | s += 6; 515 | maxlen = tfc_humanfsize(s, &stoi); 516 | if (!str_empty(stoi)) { 517 | maxlen = tfc_fnamesize(s, YES); 518 | maxlen = tfc_modifysize(maxlen, strchr(s, ':')); 519 | if (maxlen == NOFSIZE) xerror(NO, YES, YES, 520 | "%s: invalid count value", s); 521 | } 522 | else maxlen = tfc_modifysize(maxlen, strchr(s, ':')); 523 | if (counter_opt == TFC_CTR_HEAD) 524 | maxlen += TF_BLOCK_SIZE; 525 | } 526 | else if (!strncmp(s, "ftrunc", 6) && *(s+6) == '=') { 527 | s += 7; 528 | if (!strcmp(s, "tail")) { 529 | do_ftrunc = TFC_FTRUNC_TAIL; 530 | ftrunc_dfd = NOFSIZE; 531 | } 532 | else { 533 | do_ftrunc = TFC_DO_FTRUNC; 534 | ftrunc_dfd = tfc_humanfsize(s, &stoi); 535 | if (!str_empty(stoi)) { 536 | ftrunc_dfd = tfc_fnamesize(s, YES); 537 | ftrunc_dfd = tfc_modifysize(ftrunc_dfd, strchr(s, ':')); 538 | if (ftrunc_dfd == NOFSIZE) xerror(NO, YES, YES, 539 | "%s: invalid ftrunc value", s); 540 | } 541 | else ftrunc_dfd = tfc_modifysize(ftrunc_dfd, strchr(s, ':')); 542 | } 543 | } 544 | else if (!strncmp(s, "xkey", 4) && *(s+4) == '=') { 545 | s += 5; 546 | maxkeylen = tfc_humanfsize(s, &stoi); 547 | if (!str_empty(stoi)) { 548 | maxkeylen = tfc_fnamesize(s, YES); 549 | maxkeylen = tfc_modifysize(maxkeylen, strchr(s, ':')); 550 | if (maxkeylen == NOSIZE) 551 | xerror(NO, YES, YES, 552 | "%s: invalid key length value", s); 553 | } 554 | else maxkeylen = tfc_modifysize(maxkeylen, strchr(s, ':')); 555 | } 556 | else if (!strncmp(s, "okey", 4) && *(s+4) == '=') { 557 | s += 5; 558 | keyoffset = tfc_humanfsize(s, &stoi); 559 | if (!str_empty(stoi)) { 560 | keyoffset = tfc_fnamesize(s, YES); 561 | keyoffset = tfc_modifysize(keyoffset, strchr(s, ':')); 562 | if (keyoffset == NOFSIZE) 563 | xerror(NO, YES, YES, 564 | "%s: invalid key offset value", s); 565 | } 566 | else keyoffset = tfc_modifysize(keyoffset, strchr(s, ':')); 567 | } 568 | else if (!strncmp(s, "xctr", 4) && *(s+4) == '=') { 569 | s += 5; 570 | ctrsz = tfc_humanfsize(s, &stoi); 571 | if (!str_empty(stoi)) { 572 | ctrsz = (size_t)tfc_fnamesize(s, YES); 573 | ctrsz = (size_t)tfc_modifysize((tfc_fsize)ctrsz, strchr(s, ':')); 574 | if (ctrsz == NOSIZE) 575 | xerror(NO, YES, YES, 576 | "%s: invalid counter length value", s); 577 | } 578 | else ctrsz = (size_t)tfc_modifysize((tfc_fsize)ctrsz, strchr(s, ':')); 579 | if (ctrsz > TF_BLOCK_SIZE) 580 | xerror(NO, YES, YES, "%s: counter size cannot exceed TF block size", s); 581 | } 582 | else xerror(NO, YES, YES, "invalid option %s", s); 583 | } 584 | break; 585 | case 'S': 586 | do_mac = TFC_MAC_SIGN; 587 | if (strcasecmp(optarg, "mac") != 0) 588 | do_mac_file = optarg; 589 | break; 590 | case 'M': 591 | do_mac = TFC_MAC_VRFY; 592 | if (!strcasecmp(optarg, "drop")) 593 | do_mac = TFC_MAC_DROP; 594 | else if (strcasecmp(optarg, "mac") != 0) 595 | do_mac_file = optarg; 596 | break; 597 | case 'm': 598 | case 'u': 599 | if (do_mac != TFC_MAC_VRFY) 600 | xerror(NO, YES, YES, "signature source was not specified"); 601 | do_mac = TFC_MAC_JUST_VRFY; 602 | if (c == 'u') do_mac = TFC_MAC_JUST_VRFY2; 603 | break; 604 | case 'R': 605 | case 'Z': 606 | if (maxlen != NOFSIZE) { 607 | if (c == 'Z') genzero_nr_bytes = maxlen; 608 | else genrandom_nr_bytes = maxlen; 609 | } 610 | else { 611 | tfc_fsize t; 612 | if (!strcasecmp(optarg, "cbs")) 613 | t = TF_BLOCK_SIZE; 614 | else if (!strcasecmp(optarg, "ks")) 615 | t = TF_FROM_BITS(TFC_KEY_BITS); 616 | else if (!strcasecmp(optarg, "xks")) 617 | t = TF_FROM_BITS(TFC_KEY_BITS) * 2; 618 | else if (!strcasecmp(optarg, "iobs")) 619 | t = blksize; 620 | else { 621 | t = tfc_humanfsize(optarg, &stoi); 622 | if (!str_empty(stoi)) { 623 | t = tfc_fnamesize(optarg, NO); 624 | t = tfc_modifysize(t, strchr(optarg, ':')); 625 | } 626 | else t = tfc_modifysize(t, strchr(optarg, ':')); 627 | } 628 | if (c == 'Z') genzero_nr_bytes = maxlen = t; 629 | else genrandom_nr_bytes = maxlen = t; 630 | } 631 | break; 632 | case 'a': 633 | do_preserve_time = YES; 634 | break; 635 | case 'A': 636 | do_outfmt = TFC_OUTFMT_B64; 637 | break; 638 | case 'W': 639 | do_outfmt = TFC_OUTFMT_RAW; 640 | break; 641 | case 'H': 642 | do_outfmt = TFC_OUTFMT_HEX; 643 | break; 644 | case 'q': 645 | quiet = YES; 646 | verbose = NO; 647 | do_full_hexdump = NO; 648 | status_timer = 0; 649 | break; 650 | case 'v': 651 | verbose = YES; 652 | break; 653 | case 'V': 654 | td = strtod(optarg, &stoi); 655 | status_timer = TFC_DTOUSECS(td); 656 | if (status_timer <= TFC_DTOUSECS(0) || !str_empty(stoi)) status_timer = 0; 657 | break; 658 | default: 659 | usage(); 660 | break; 661 | } 662 | } 663 | 664 | if (!strcmp(progname, "tfbench")) { 665 | if (!*(argv+optind)) usage(); 666 | 667 | td = strtod(*(argv+optind), &stoi); 668 | if (td <= TFC_DTOUSECS(0) || !str_empty(stoi)) 669 | xerror(NO, YES, YES, 670 | "%s: invalid benchmark time in seconds", *(argv+optind)); 671 | bench_timer = TFC_DTOUSECS(td); 672 | do_benchmark(bench_timer, td); 673 | } 674 | if (genrandom_nr_bytes) { 675 | ctr_mode = TFC_MODE_STREAM; 676 | do_edcrypt = TFC_DO_ENCRYPT; 677 | gen_write_bytes(*(argv+optind), oseek, genrandom_nr_bytes); 678 | } 679 | if (genzero_nr_bytes) { 680 | ctr_mode = TFC_MODE_PLAIN; 681 | do_edcrypt = TFC_DO_PLAIN; 682 | gen_write_bytes(*(argv+optind), oseek, genzero_nr_bytes); 683 | } 684 | 685 | if (rawkey && password) 686 | xerror(NO, YES, YES, "Cannot use rawkey and hashing password!"); 687 | if (do_edcrypt == TFC_DO_ENCRYPT && do_mac >= TFC_MAC_VRFY) 688 | xerror(NO, YES, YES, "Cannot encrypt and verify signature!"); 689 | if (do_edcrypt == TFC_DO_DECRYPT && do_mac == TFC_MAC_SIGN) 690 | xerror(NO, YES, YES, "Cannot decrypt and calculate signature!"); 691 | if (do_edcrypt == TFC_DO_DECRYPT && counter_opt == TFC_CTR_RAND) 692 | xerror(NO, YES, YES, "Cannot decrypt and embed a generated CTR into file!"); 693 | if (do_edcrypt == TFC_DO_ENCRYPT && counter_opt == TFC_CTR_HEAD) 694 | xerror(NO, YES, YES, "Cannot encrypt and read CTR from source!"); 695 | if (overwrite_source && counter_opt == TFC_CTR_RAND) 696 | xerror(NO, YES, YES, "Cannot embed a CTR into file when overwriting it!"); 697 | if (do_edcrypt == TFC_DO_PLAIN 698 | && (do_mac || saltf || rawkey || mackey_opt || counter_opt || counter_file)) 699 | xerror(NO, YES, YES, "Encryption facility is disabled when in plain IO mode."); 700 | 701 | errno = 0; 702 | do_stop = NO; 703 | 704 | if (saltf) { 705 | int saltfd; 706 | 707 | memset(tfc_salt, 0, TFC_MAX_SALT); 708 | tfc_saltsz = 0; 709 | if (!strcasecmp(saltf, "disable")) goto _nosalt; 710 | 711 | if (!strcmp(saltf, "-")) saltfd = 0; 712 | else saltfd = xopen(saltf, O_RDONLY | O_LARGEFILE); 713 | lio = xread(saltfd, tfc_salt, TFC_MAX_SALT - TF_FROM_BITS(TFC_KEY_BITS)); 714 | if (lio == NOSIZE) xerror(NO, NO, YES, "%s", saltf); 715 | tfc_saltsz = lio; 716 | xclose(saltfd); 717 | } 718 | 719 | _nosalt: 720 | if (mackey_opt == TFC_MACKEY_FILE && mackeyf) { 721 | int mkfd = -1; 722 | tfc_yesno do_stop; 723 | 724 | if (!strcmp(mackeyf, "-")) mkfd = 0; 725 | else mkfd = xopen(mackeyf, O_RDONLY | O_LARGEFILE); 726 | 727 | skein_init(&sk, TFC_KEY_BITS); 728 | 729 | do_stop = NO; 730 | while (1) { 731 | if (do_stop) break; 732 | pblk = tmpdata; 733 | ldone = 0; 734 | lrem = lblock = sizeof(tmpdata); 735 | if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(mkfd); 736 | _mkragain: lio = xread(mkfd, pblk, lrem); 737 | if (lio == 0 && do_stop == NO) do_stop = YES; 738 | if (lio != NOSIZE) ldone += lio; 739 | else { 740 | if (errno != EIO && catch_all_errors != YES) 741 | xerror(NO, NO, NO, "%s", mackeyf); 742 | switch (error_action) { 743 | case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", mackeyf); goto _mkragain; break; 744 | case TFC_ERRACT_SYNC: 745 | case TFC_ERRACT_LSYNC: 746 | xerror(YES, NO, NO, "%s", mackeyf); 747 | lio = ldone = lrem = lblock; 748 | memset(tmpdata, 0, lio); 749 | if (rdpos == NOFSIZE) lseek(mkfd, lio, SEEK_CUR); 750 | else lseek(mkfd, rdpos + lio, SEEK_SET); 751 | break; 752 | default: xerror(NO, NO, NO, "%s", mackeyf); break; 753 | } 754 | } 755 | if (lio && lio < lrem) { 756 | pblk += lio; 757 | lrem -= lio; 758 | goto _mkragain; 759 | } 760 | 761 | skein_update(&sk, tmpdata, ldone); 762 | } 763 | 764 | skein_final(mackey, &sk); 765 | 766 | xclose(mkfd); 767 | } 768 | else if (mackey_opt == TFC_MACKEY_PASSWORD) { 769 | memset(&getps, 0, sizeof(struct getpasswd_state)); 770 | getps.fd = getps.efd = -1; 771 | getps.passwd = pwdask; 772 | getps.pwlen = sizeof(pwdask)-1; 773 | getps.echo = mac_pw_prompt ? mac_pw_prompt : "Enter MAC password: "; 774 | getps.charfilter = (show_secrets == YES) ? getps_plain_filter : getps_filter; 775 | getps.maskchar = (show_secrets == YES) ? 0 : 'x'; 776 | getps.flags = GETP_WAITFILL; 777 | n = xgetpasswd(&getps); 778 | if (n == NOSIZE) xerror(NO, NO, YES, "getting MAC password"); 779 | if (n == ((size_t)-2)) xexit(1); 780 | if (verbose) say_hint(pwdask, n, "MAC password hint"); 781 | skein(mackey, TF_MAX_BITS, NULL, pwdask, n); 782 | } 783 | 784 | 785 | if ((strlen(progname) <= 9) 786 | && ((!strcmp(progname, "sksum")) 787 | || ((!memcmp(progname, "sk", 2)) 788 | && (!memcmp(progname+3, "sum", 3) 789 | || !memcmp(progname+4, "sum", 3) 790 | || !memcmp(progname+5, "sum", 3) 791 | || !memcmp(progname+6, "sum", 3))))) 792 | do_sksum(progname, argv+optind); 793 | if (!strcmp(progname, "base64")) do_edbase64(argv+optind); 794 | 795 | idx = optind; 796 | 797 | if (argv[idx]) { 798 | if ((do_edcrypt == TFC_DO_PLAIN && ctr_mode == TFC_MODE_PLAIN) 799 | || password 800 | || rawkey > TFC_RAWKEY_KEYFILE) goto _nokeyfd; 801 | if (!strcmp(argv[idx], "-")) kfd = 0; 802 | else kfd = xopen(argv[idx], O_RDONLY | O_LARGEFILE); 803 | 804 | if (do_edcrypt == TFC_DO_PLAIN && ctr_mode == TFC_MODE_XOR) { 805 | /* out: don't erase kfname if xor */ 806 | idx++; 807 | goto _nokeyfd; 808 | } 809 | 810 | lio = strnlen(argv[idx], PATH_MAX); 811 | memset(argv[idx], '*', lio); 812 | 813 | idx++; 814 | } 815 | else password = YES; 816 | 817 | errno = 0; 818 | if (do_full_key == NO && tweakf) { 819 | int twfd; 820 | 821 | if (!strcmp(tweakf, "-")) twfd = 0; 822 | else twfd = open(tweakf, O_RDONLY | O_LARGEFILE); 823 | if (twfd == -1) xerror(NO, NO, YES, "%s", tweakf); 824 | lio = ldone = xread(twfd, tweak, TF_TWEAK_SIZE); 825 | if (lio == NOSIZE) xerror(NO, NO, YES, "%s", tweakf); 826 | if (ldone < TF_TWEAK_SIZE) 827 | xerror(NO, NO, YES, "%s: %zu bytes tweak required", tweakf, TF_TWEAK_SIZE); 828 | xclose(twfd); 829 | } 830 | 831 | _nokeyfd: 832 | errno = 0; 833 | if (argv[idx]) { 834 | if (!strcmp(argv[idx], "-") && kfd) sfd = 0; 835 | else { 836 | sfd = xopen(argv[idx], O_RDONLY | O_LARGEFILE); 837 | if (do_preserve_time) if (fstat(sfd, &s_stat) == -1) 838 | xerror(YES, NO, YES, "stat(%s)", argv[idx]); 839 | } 840 | 841 | if ((do_mac >= TFC_MAC_VRFY || do_mac <= TFC_MAC_DROP) && !do_mac_file) { 842 | maxlen = tfc_fdsize(sfd); 843 | if (maxlen == NOFSIZE) 844 | xerror(NO, YES, YES, 845 | "Cannot verify embedded MAC with non-seekable source!"); 846 | maxlen -= TF_FROM_BITS(macbits); 847 | } 848 | srcfname = argv[idx]; 849 | idx++; 850 | } 851 | 852 | if (!do_mac_file && (do_mac >= TFC_MAC_VRFY && sfd == 0)) 853 | xerror(NO, YES, YES, "Cannot verify embedded MAC with non-seekable source!"); 854 | 855 | if (ctrsz == NOSIZE) ctrsz = TF_BLOCK_SIZE; 856 | if (ctrsz > TF_BLOCK_SIZE) ctrsz = TF_BLOCK_SIZE; 857 | 858 | if (ctr_mode == TFC_MODE_ECB) goto _ctrskip1; 859 | errno = 0; 860 | if (counter_file) { 861 | int ctrfd; 862 | 863 | if (!strcmp(counter_file, "-")) ctrfd = 0; 864 | else ctrfd = xopen(counter_file, O_RDONLY | O_LARGEFILE); 865 | lio = xread(ctrfd, ctr, ctrsz); 866 | if (lio == NOSIZE) xerror(NO, NO, YES, "%s", counter_file); 867 | if (lio < ctrsz) xerror(NO, YES, YES, "counter file is too small (%zu)!", lio); 868 | xclose(ctrfd); 869 | } 870 | else if (counter_opt == TFC_CTR_HEAD) { 871 | pblk = ctr; 872 | ldone = 0; 873 | lrem = lblock = ctrsz; 874 | if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); 875 | _ctrragain: lio = xread(sfd, pblk, lrem); 876 | if (lio != NOSIZE) ldone += lio; 877 | else { 878 | if (errno != EIO && catch_all_errors != YES) 879 | xerror(NO, NO, NO, "%s", srcfname); 880 | switch (error_action) { 881 | case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ctrragain; break; 882 | case TFC_ERRACT_SYNC: 883 | case TFC_ERRACT_LSYNC: 884 | xerror(YES, NO, NO, "%s", srcfname); 885 | lio = ldone = lrem = lblock; 886 | memset(ctr, 0, lio); 887 | if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR); 888 | else lseek(sfd, rdpos + lio, SEEK_SET); 889 | break; 890 | default: xerror(NO, NO, NO, "%s", srcfname); break; 891 | } 892 | } 893 | if (lio && lio < lrem) { 894 | pblk += lio; 895 | lrem -= lio; 896 | goto _ctrragain; 897 | } 898 | total_processed_src += ldone; 899 | } 900 | 901 | _ctrskip1: 902 | if (iseek) { 903 | if (counter_opt == TFC_CTR_HEAD && ctr_mode != TFC_MODE_ECB) 904 | iseek += ctrsz; 905 | if (lseek(sfd, iseek, SEEK_SET) == -1) 906 | xerror(ignore_seek_errors, NO, NO, "%s: seek failed", srcfname); 907 | } 908 | 909 | if (do_edcrypt == TFC_DO_PLAIN) goto _plain; 910 | 911 | if (verbose) tfc_esay("%s: hashing password", tfc_format_pid(progname)); 912 | 913 | if (rawkey == TFC_RAWKEY_KEYFILE) { 914 | tfc_yesno xtskeyset = NO; 915 | 916 | pblk = key; 917 | _xts2key: ldone = 0; 918 | lrem = lblock = TF_FROM_BITS(TFC_KEY_BITS); 919 | if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(kfd); 920 | _keyragain: lio = xread(kfd, pblk, lrem); 921 | if (lio != NOSIZE) ldone += lio; 922 | else { 923 | if (errno != EIO && catch_all_errors != YES) 924 | xerror(NO, NO, NO, "reading key"); 925 | switch (error_action) { 926 | case TFC_ERRACT_CONT: xerror(YES, NO, NO, "reading key"); goto _keyragain; break; 927 | case TFC_ERRACT_SYNC: 928 | case TFC_ERRACT_LSYNC: 929 | xerror(YES, NO, NO, "reading key"); 930 | lio = ldone = lrem = lblock; 931 | memset(key, 0, lio); 932 | if (rdpos == NOFSIZE) lseek(kfd, lio, SEEK_CUR); 933 | else lseek(kfd, rdpos + lio, SEEK_SET); 934 | break; 935 | default: xerror(NO, NO, NO, "reading key"); break; 936 | } 937 | } 938 | if (lio && lio < lrem) { 939 | pblk += lio; 940 | lrem -= lio; 941 | goto _keyragain; 942 | } 943 | if (ldone < lblock) xerror(NO, YES, YES, "rawkey too small! (%zu)", ldone); 944 | 945 | if (ctr_mode == TFC_MODE_XTS) { 946 | if (xtskeyset == NO) { 947 | pblk = xtskey; 948 | xtskeyset = YES; 949 | goto _xts2key; 950 | } 951 | } 952 | } 953 | else if (rawkey == TFC_RAWKEY_ASKSTR) { 954 | tfc_yesno xtskeyset = NO; 955 | 956 | pblk = key; n = sizeof(key); 957 | _xts2keyaskstr: memset(&getps, 0, sizeof(struct getpasswd_state)); 958 | getps.fd = getps.efd = -1; 959 | getps.passwd = (char *)pblk; 960 | getps.pwlen = n; 961 | getps.echo = pw_prompt ? pw_prompt : "Enter rawkey (str): "; 962 | getps.charfilter = (show_secrets == YES) ? getps_plain_filter : getps_filter; 963 | getps.maskchar = (show_secrets == YES) ? 0 : 'x'; 964 | getps.flags = GETP_WAITFILL; 965 | n = xgetpasswd(&getps); 966 | if (n == NOSIZE) xerror(NO, NO, YES, "getting string rawkey"); 967 | if (n == ((size_t)-2)) xexit(1); 968 | if (verbose) say_hint(pblk, n, "Raw string key hint"); 969 | if (ctr_mode == TFC_MODE_XTS) { 970 | if (xtskeyset == NO) { 971 | pblk = xtskey; n = sizeof(xtskey); 972 | xtskeyset = YES; 973 | goto _xts2keyaskstr; 974 | } 975 | } 976 | } 977 | else if (rawkey == TFC_RAWKEY_ASKHEX) { 978 | tfc_yesno xtskeyset = NO; 979 | 980 | pblk = key; 981 | _rawkey_hex_again: 982 | memset(&getps, 0, sizeof(struct getpasswd_state)); 983 | getps.fd = getps.efd = -1; 984 | getps.passwd = pwdask; 985 | getps.pwlen = (TF_FROM_BITS(TFC_KEY_BITS)*2); 986 | getps.echo = pw_prompt ? pw_prompt : "Enter rawkey (hex): "; 987 | getps.charfilter = (show_secrets == YES) ? getps_plain_hex_filter : getps_hex_filter; 988 | getps.maskchar = (show_secrets == YES) ? 0 : 'x'; 989 | getps.flags = GETP_WAITFILL; 990 | n = xgetpasswd(&getps); 991 | if (n == NOSIZE) xerror(NO, NO, YES, "getting hex rawkey"); 992 | if (n == ((size_t)-2)) xexit(1); 993 | if (n % 2) { 994 | tfc_esay("Please input even number of hex digits!"); 995 | goto _rawkey_hex_again; 996 | } 997 | hex2bin(pblk, pwdask); 998 | memset(pwdask, 0, sizeof(pwdask)); 999 | if (verbose) say_hint(pblk, n/2, "Raw hex key hint"); 1000 | if (ctr_mode == TFC_MODE_XTS) { 1001 | if (xtskeyset == NO) { 1002 | pblk = xtskey; 1003 | xtskeyset = YES; 1004 | goto _rawkey_hex_again; 1005 | } 1006 | } 1007 | } 1008 | else if (password) { 1009 | _pwdagain: memset(&getps, 0, sizeof(struct getpasswd_state)); 1010 | getps.fd = getps.efd = -1; 1011 | getps.passwd = pwdask; 1012 | getps.pwlen = sizeof(pwdask)-1; 1013 | getps.echo = pw_prompt ? pw_prompt : "Enter password: "; 1014 | getps.charfilter = (show_secrets == YES) ? getps_plain_filter : getps_filter; 1015 | getps.maskchar = (show_secrets == YES) ? 0 : 'x'; 1016 | getps.flags = GETP_WAITFILL; 1017 | n = xgetpasswd(&getps); 1018 | if (n == NOSIZE) xerror(NO, NO, YES, "getting password"); 1019 | if (n == ((size_t)-2)) xexit(1); 1020 | if (do_edcrypt == TFC_DO_ENCRYPT && no_repeat == NO) { 1021 | getps.fd = getps.efd = -1; 1022 | getps.passwd = pwdagain; 1023 | getps.pwlen = sizeof(pwdagain)-1; 1024 | getps.echo = "Enter it again: "; 1025 | getps.flags = GETP_WAITFILL; 1026 | n = xgetpasswd(&getps); 1027 | if (n == NOSIZE) xerror(NO, NO, YES, "getting password again"); 1028 | if (n == ((size_t)-2)) xexit(1); 1029 | if (strncmp(pwdask, pwdagain, sizeof(pwdagain)-1) != 0) { 1030 | tfc_esay("Passwords are different, try again"); 1031 | goto _pwdagain; 1032 | } 1033 | } 1034 | if (verbose) say_hint(pwdask, n, "Password hint"); 1035 | skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, pwdask, n); 1036 | memset(pwdask, 0, sizeof(pwdask)); 1037 | memset(pwdagain, 0, sizeof(pwdagain)); 1038 | } 1039 | else { 1040 | if (skeinfd(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, kfd, keyoffset, maxkeylen) != YES) 1041 | xerror(NO, NO, YES, "hashing key"); 1042 | } 1043 | 1044 | if (rawkey == NO) { 1045 | if (tfc_saltsz > 0) { 1046 | memcpy(tfc_salt+tfc_saltsz, key, TF_FROM_BITS(TFC_KEY_BITS)); 1047 | skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, tfc_salt, tfc_saltsz+TF_FROM_BITS(TFC_KEY_BITS)); 1048 | } 1049 | if (nr_turns > 1) for (x = 0; x < nr_turns; x++) 1050 | skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS)); 1051 | memset(tfc_salt, 0, TFC_MAX_SALT); 1052 | } 1053 | 1054 | if (ctr_mode == TFC_MODE_XTS && rawkey == NO) { 1055 | skein(xtskey, TF_NR_KEY_BITS, mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS)); 1056 | } 1057 | 1058 | if (genkeyf) { 1059 | int krfd; 1060 | tfc_yesno xtskeyset = NO; 1061 | 1062 | pblk = key; 1063 | if (!strcmp(genkeyf, "-")) krfd = 1; 1064 | else krfd = xopen(genkeyf, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags); 1065 | _xts2genkey: if (xwrite(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == NOSIZE) xerror(NO, NO, YES, "%s", genkeyf); 1066 | if (do_fsync && fsync(krfd) == -1) xerror(NO, NO, YES, "%s", genkeyf); 1067 | if (verbose && xtskeyset == NO) { 1068 | tfc_esay("%s: password hashing done", tfc_format_pid(progname)); 1069 | tfc_esay("%s: rawkey written to %s.", tfc_format_pid(progname), genkeyf); 1070 | tfc_esay("%s: Have a nice day!", tfc_format_pid(progname)); 1071 | } 1072 | 1073 | if (ctr_mode == TFC_MODE_XTS) { 1074 | if (xtskeyset == NO) { 1075 | pblk = xtskey; 1076 | xtskeyset = YES; 1077 | goto _xts2genkey; 1078 | } 1079 | } 1080 | 1081 | fchmod(krfd, 0600); 1082 | xclose(krfd); 1083 | xexit(0); 1084 | } 1085 | 1086 | if (do_mac != NO) { 1087 | if (mackey_opt == TFC_MACKEY_RAWKEY) skein(mackey, TF_MAX_BITS, key, key, TF_FROM_BITS(TFC_KEY_BITS)); 1088 | if (verbose) tfc_esay("%s: doing MAC calculation, processing speed " 1089 | "will be slower.", tfc_format_pid(progname)); 1090 | if (mackey_opt) skein_init_key(&sk, mackey, macbits); 1091 | else skein_init(&sk, macbits); 1092 | } 1093 | 1094 | if (!counter_file && counter_opt <= TFC_CTR_SHOW && ctr_mode != TFC_MODE_ECB) { 1095 | skein(ctr, TF_TO_BITS(ctrsz), mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS)); 1096 | } 1097 | 1098 | tf_convkey(key); 1099 | if (ctr_mode == TFC_MODE_XTS) tf_convkey(xtskey); 1100 | if (do_full_key == NO) { 1101 | if (!tweakf) skein(tweak, TF_NR_TWEAK_BITS, NULL, key, TF_FROM_BITS(TFC_KEY_BITS)); 1102 | tf_tweak_set(key, tweak); 1103 | } 1104 | if (ctr_mode == TFC_MODE_ECB) goto _ctrskip2; 1105 | 1106 | if (counter_opt == TFC_CTR_ZERO) memset(ctr, 0, ctrsz); 1107 | 1108 | tfc_data_to_words64(&iseek_blocks, sizeof(iseek_blocks)); 1109 | tf_ctr_set(ctr, &iseek_blocks, sizeof(iseek_blocks)); 1110 | if (do_mac == TFC_MAC_JUST_VRFY2) memcpy(svctr, ctr, TF_BLOCK_SIZE); 1111 | 1112 | if (counter_opt == TFC_CTR_SHOW) { 1113 | switch (do_outfmt) { 1114 | case TFC_OUTFMT_B64: tfc_printbase64(stderr, ctr, ctrsz, YES); break; 1115 | case TFC_OUTFMT_RAW: xwrite(2, ctr, ctrsz); break; 1116 | case TFC_OUTFMT_HEX: mehexdump(ctr, ctrsz, ctrsz, YES); break; 1117 | } 1118 | } 1119 | else if (counter_opt == TFC_CTR_RAND) tfc_getrandom(ctr, ctrsz); 1120 | 1121 | _ctrskip2: 1122 | if (kfd != -1) { 1123 | xclose(kfd); 1124 | kfd = -1; 1125 | } 1126 | if (verbose) tfc_esay("%s: password hashing done", tfc_format_pid(progname)); 1127 | 1128 | if (overwrite_source && srcfname) argv[idx] = srcfname; 1129 | 1130 | _plain: 1131 | if (argv[idx]) { 1132 | if (!strcmp(argv[idx], "-")) dfd = 1; 1133 | else dfd = xxopen(YES, argv[idx], O_RDWR | O_LARGEFILE | write_flags); 1134 | if (dfd == -1) dfd = xopen(argv[idx], O_WRONLY | O_CREAT | O_LARGEFILE | write_flags); 1135 | dstfname = argv[idx]; 1136 | idx++; 1137 | } 1138 | 1139 | if (oseek) { 1140 | if (lseek(dfd, oseek, SEEK_SET) == -1) 1141 | xerror(ignore_seek_errors, NO, NO, "%s: seek failed", dstfname); 1142 | } 1143 | 1144 | for (x = 1; x < NSIG; x++) signal(x, SIG_IGN); 1145 | memset(&sigact, 0, sizeof(sigact)); 1146 | sigact.sa_flags = SA_RESTART; 1147 | sigact.sa_handler = print_crypt_status; 1148 | sigaction(SIGUSR1, &sigact, NULL); 1149 | sigaction(SIGALRM, &sigact, NULL); 1150 | if (status_timer) setup_next_alarm(status_timer > 1000000 ? 1000000 : status_timer); 1151 | sigact.sa_handler = change_status_width; 1152 | sigaction(SIGQUIT, &sigact, NULL); 1153 | sigact.sa_handler = change_status_timer; 1154 | sigaction(SIGUSR2, &sigact, NULL); 1155 | if (quiet == NO) { 1156 | sigact.sa_handler = print_crypt_status; 1157 | sigaction(SIGINT, &sigact, NULL); 1158 | sigaction(SIGTERM, &sigact, NULL); 1159 | sigaction(SIGTSTP, &sigact, NULL); 1160 | } 1161 | else { 1162 | sigact.sa_handler = exit_sigterm; 1163 | sigaction(SIGINT, &sigact, NULL); 1164 | sigaction(SIGTERM, &sigact, NULL); 1165 | sigact.sa_handler = handle_sigtstp; 1166 | sigaction(SIGTSTP, &sigact, NULL); 1167 | } 1168 | memset(&sigact, 0, sizeof(struct sigaction)); 1169 | 1170 | tfc_getcurtime(&delta_time); 1171 | 1172 | errno = 0; 1173 | if (counter_opt == TFC_CTR_RAND && ctr_mode != TFC_MODE_ECB) { 1174 | pblk = ctr; 1175 | lio = lrem = ctrsz; 1176 | ldone = 0; 1177 | _ctrwagain: lio = xwrite(dfd, pblk, lrem); 1178 | if (lio != NOSIZE) ldone += lio; 1179 | else xerror(NO, NO, NO, "%s", dstfname); 1180 | if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname); 1181 | if (lio < lrem) { 1182 | pblk += lio; 1183 | lrem -= lio; 1184 | goto _ctrwagain; 1185 | } 1186 | total_written_dst += ldone; 1187 | total_processed_dst += ldone; 1188 | delta_processed += ldone; 1189 | } 1190 | 1191 | if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr); 1192 | 1193 | if (do_mac == TFC_MAC_JUST_VRFY2) { 1194 | rwd = tfc_fdgetpos(sfd); 1195 | if (rwd == NOFSIZE) { 1196 | tfc_esay("%s: WARNING: input is not seekable, disabling MAC testing mode", tfc_format_pid(progname)); 1197 | do_mac = TFC_MAC_VRFY; 1198 | } 1199 | goto _nodecrypt_again_vrfy2; 1200 | 1201 | _decrypt_again_vrfy2: 1202 | if (lseek(sfd, (off_t)rwd, SEEK_SET) == ((off_t)-1)) { 1203 | xerror(ignore_seek_errors, NO, YES, "MAC testing seek failed"); 1204 | } 1205 | total_processed_src = rwd; 1206 | memcpy(ctr, svctr, TF_BLOCK_SIZE); 1207 | if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr); 1208 | memset(svctr, 0, TF_BLOCK_SIZE); 1209 | } 1210 | 1211 | #define FLFD(x, y) (flipfd ? y : x) 1212 | _nodecrypt_again_vrfy2: 1213 | loopcnt = 1; 1214 | errno = 0; 1215 | do_stop = NO; 1216 | flipfd = NO; 1217 | while (1) { 1218 | if (do_stop) break; 1219 | if (ctr_mode == TFC_MODE_XOR) flipfd = NO; 1220 | pblk = srcblk; 1221 | _nextblk: ldone = 0; 1222 | lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize); 1223 | if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(FLFD(sfd, kfd)); 1224 | _ragain: lio = xread(FLFD(sfd, kfd), pblk, lrem); 1225 | if (lio == 0) { 1226 | if ((do_read_loops != 0 && FLFD(sfd, kfd) != 0) && (loopcnt < do_read_loops)) { 1227 | lseek(FLFD(sfd, kfd), 0L, SEEK_SET); 1228 | loopcnt++; 1229 | goto _ragain; 1230 | } 1231 | 1232 | do_stop = YES; 1233 | } 1234 | if (lio != NOSIZE) ldone += lio; 1235 | else { 1236 | if (errno != EIO && catch_all_errors != YES) 1237 | xerror(NO, NO, NO, "%s", srcfname); 1238 | switch (error_action) { 1239 | case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ragain; break; 1240 | case TFC_ERRACT_SYNC: 1241 | case TFC_ERRACT_LSYNC: 1242 | xerror(YES, NO, NO, "%s", srcfname); 1243 | lio = ldone = lrem = lblock; 1244 | memset(srcblk, 0, lio); 1245 | if (rdpos == NOFSIZE) lseek(FLFD(sfd, kfd), lio, SEEK_CUR); 1246 | else lseek(FLFD(sfd, kfd), rdpos + lio, SEEK_SET); 1247 | break; 1248 | default: xerror(NO, NO, NO, "%s", srcfname); break; 1249 | } 1250 | } 1251 | if (unbuffered == NO && lio && lio < lrem) { 1252 | pblk += lio; 1253 | lrem -= lio; 1254 | goto _ragain; 1255 | } 1256 | total_processed_src += ldone; 1257 | 1258 | if (do_pad && (ldone % TF_BLOCK_SIZE)) { 1259 | size_t orig = ldone; 1260 | ldone += (TF_BLOCK_SIZE - (ldone % TF_BLOCK_SIZE)); 1261 | if (ldone > blksize) ldone = blksize; 1262 | memset(srcblk+orig, 0, sizeof(srcblk)-orig); 1263 | } 1264 | 1265 | if (ctr_mode == TFC_MODE_XOR && flipfd == NO) { 1266 | if (do_stop) blksize = ldone; 1267 | flipfd = YES; 1268 | pblk = dstblk; 1269 | goto _nextblk; 1270 | } 1271 | 1272 | if (do_mac == TFC_MAC_SIGN) skein_update(&sk, srcblk, ldone); 1273 | 1274 | if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, dstblk, srcblk, ldone); 1275 | else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, dstblk, srcblk, ldone); 1276 | else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_ENCRYPT) 1277 | tf_xts_encrypt(key, xtskey, ctr, dstblk, srcblk, ldone, xtsblocks); 1278 | else if (ctr_mode == TFC_MODE_XTS && do_edcrypt == TFC_DO_DECRYPT) 1279 | tf_xts_decrypt(key, xtskey, ctr, dstblk, srcblk, ldone, xtsblocks); 1280 | else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_ENCRYPT) 1281 | tf_ecb_encrypt(key, dstblk, srcblk, ldone); 1282 | else if (ctr_mode == TFC_MODE_ECB && do_edcrypt == TFC_DO_DECRYPT) 1283 | tf_ecb_decrypt(key, dstblk, srcblk, ldone); 1284 | else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_ENCRYPT) 1285 | tf_cbc_encrypt(key, ctr, dstblk, srcblk, ldone); 1286 | else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_DECRYPT) 1287 | tf_cbc_decrypt(key, ctr, dstblk, srcblk, ldone); 1288 | else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_ENCRYPT) 1289 | tf_pcbc_encrypt(key, ctr, dstblk, srcblk, ldone); 1290 | else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_DECRYPT) 1291 | tf_pcbc_decrypt(key, ctr, dstblk, srcblk, ldone); 1292 | 1293 | else if (ctr_mode == TFC_MODE_PLAIN) 1294 | memcpy(dstblk, srcblk, ldone); 1295 | 1296 | else if (ctr_mode == TFC_MODE_XOR) 1297 | xor_block(dstblk, srcblk, ldone); 1298 | 1299 | if (do_mac >= TFC_MAC_VRFY) skein_update(&sk, dstblk, ldone); 1300 | if (do_mac >= TFC_MAC_JUST_VRFY) goto _nowrite; 1301 | 1302 | pblk = dstblk; 1303 | lrem = ldone; 1304 | ldone = 0; 1305 | _wagain: lio = xwrite(dfd, pblk, lrem); 1306 | if (lio != NOSIZE) ldone += lio; 1307 | else xerror(NO, NO, NO, "%s", dstfname); 1308 | if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname); 1309 | if (lio < lrem) { 1310 | pblk += lio; 1311 | lrem -= lio; 1312 | goto _wagain; 1313 | } 1314 | total_written_dst += ldone; 1315 | _nowrite: total_processed_dst += ldone; 1316 | delta_processed += ldone; 1317 | 1318 | if (maxlen != NOFSIZE && total_processed_src >= maxlen) { 1319 | do_stop = YES; 1320 | break; 1321 | } 1322 | } 1323 | 1324 | if (verbose && status_timer && do_statline_dynamic == YES && statline_was_shown == YES) tfc_esay("\n"); 1325 | 1326 | errno = 0; 1327 | if (do_mac >= TFC_MAC_VRFY) { 1328 | if (!do_mac_file) { 1329 | pblk = macvrfy; 1330 | ldone = 0; 1331 | lrem = lblock = TF_FROM_BITS(macbits); 1332 | if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); 1333 | _macragain: lio = xread(sfd, pblk, lrem); 1334 | if (lio != NOSIZE) ldone += lio; 1335 | else { 1336 | if (errno != EIO && catch_all_errors != YES) 1337 | xerror(NO, NO, NO, "%s", srcfname); 1338 | switch (error_action) { 1339 | case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _macragain; break; 1340 | case TFC_ERRACT_SYNC: 1341 | case TFC_ERRACT_LSYNC: 1342 | xerror(YES, NO, NO, "%s", srcfname); 1343 | lio = ldone = lrem = lblock; 1344 | memset(macvrfy, 0, lio); 1345 | if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR); 1346 | else lseek(sfd, rdpos + lio, SEEK_SET); 1347 | break; 1348 | default: xerror(NO, NO, NO, "%s", srcfname); break; 1349 | } 1350 | } 1351 | if (lio && lio < lrem) { 1352 | pblk += lio; 1353 | lrem -= lio; 1354 | goto _macragain; 1355 | } 1356 | total_processed_src += ldone; 1357 | } 1358 | else { 1359 | int mfd; 1360 | 1361 | if (!strcmp(do_mac_file, "-")) mfd = 0; 1362 | else mfd = xopen(do_mac_file, O_RDONLY | O_LARGEFILE); 1363 | lio = ldone = xread(mfd, tmpdata, sizeof(tmpdata)); 1364 | if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file); 1365 | if (!memcmp(tmpdata, TFC_ASCII_TFC_MAC_FOURCC, TFC_ASCII_TFC_MAC_FOURCC_LEN)) { 1366 | memmove(tmpdata, tmpdata+TFC_ASCII_TFC_MAC_FOURCC_LEN, 1367 | sizeof(tmpdata)-TFC_ASCII_TFC_MAC_FOURCC_LEN); 1368 | lio = TF_FROM_BITS(macbits); 1369 | base64_decode((char *)macvrfy, lio, (char *)tmpdata, sizeof(tmpdata)); 1370 | } 1371 | else memcpy(macvrfy, tmpdata, TF_FROM_BITS(macbits)); 1372 | xclose(mfd); 1373 | } 1374 | 1375 | if (ldone < TF_FROM_BITS(macbits)) { 1376 | if (quiet == NO) tfc_esay("%s: short signature (%zu), " 1377 | "not verifying", tfc_format_pid(progname), ldone); 1378 | exitcode = 1; 1379 | goto _shortmac; 1380 | } 1381 | 1382 | skein_final(macresult, &sk); 1383 | 1384 | if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits)); 1385 | else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, tmpdata, macvrfy, TF_FROM_BITS(macbits)); 1386 | else if (ctr_mode == TFC_MODE_XTS) tf_xts_decrypt(key, xtskey, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits), xtsblocks); 1387 | else if (ctr_mode == TFC_MODE_ECB) tf_ecb_decrypt(key, tmpdata, macvrfy, TF_FROM_BITS(macbits)); 1388 | else if (ctr_mode == TFC_MODE_CBC) tf_cbc_decrypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits)); 1389 | else if (ctr_mode == TFC_MODE_PCBC) tf_pcbc_decrypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits)); 1390 | 1391 | if (!memcmp(tmpdata, macresult, TF_FROM_BITS(macbits))) { 1392 | if (quiet == NO) { 1393 | tfc_esay("%s: signature is good", tfc_format_pid(progname)); 1394 | if (verbose) { 1395 | if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stderr, macresult, TF_FROM_BITS(macbits), YES); 1396 | else mehexdump(macresult, TF_FROM_BITS(macbits), TF_FROM_BITS(macbits), YES); 1397 | } 1398 | } 1399 | if (do_mac == TFC_MAC_JUST_VRFY2) { 1400 | if (verbose) tfc_esay("%s: -u: MAC signature is valid, proceeding with decrypting it again", tfc_format_pid(progname)); 1401 | maxlen = total_processed_src - SKEIN_DIGEST_SIZE; 1402 | do_mac = TFC_MAC_DROP2; 1403 | goto _decrypt_again_vrfy2; 1404 | } 1405 | } 1406 | else { 1407 | if (quiet == NO) { 1408 | tfc_esay("%s: signature is BAD: " 1409 | "wrong password, key, mode, or file is not signed", tfc_format_pid(progname)); 1410 | if (do_mac == TFC_MAC_JUST_VRFY2) tfc_esay("%s: -u: MAC signature is invalid, not decrypting it again", tfc_format_pid(progname)); 1411 | } 1412 | exitcode = 1; 1413 | } 1414 | 1415 | _shortmac: memset(macvrfy, 0, sizeof(macvrfy)); 1416 | memset(macresult, 0, sizeof(macresult)); 1417 | memset(tmpdata, 0, sizeof(tmpdata)); 1418 | } 1419 | else if (do_mac == TFC_MAC_SIGN) { 1420 | skein_final(macresult, &sk); 1421 | 1422 | if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits)); 1423 | else if (ctr_mode == TFC_MODE_STREAM) tf_stream_crypt(&tfe, tmpdata, macresult, TF_FROM_BITS(macbits)); 1424 | else if (ctr_mode == TFC_MODE_XTS) tf_xts_encrypt(key, xtskey, ctr, tmpdata, macresult, TF_FROM_BITS(macbits), xtsblocks); 1425 | else if (ctr_mode == TFC_MODE_ECB) tf_ecb_encrypt(key, tmpdata, macresult, TF_FROM_BITS(macbits)); 1426 | else if (ctr_mode == TFC_MODE_CBC) tf_cbc_encrypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits)); 1427 | else if (ctr_mode == TFC_MODE_PCBC) tf_pcbc_encrypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits)); 1428 | memset(macresult, 0, sizeof(macresult)); 1429 | 1430 | if (!do_mac_file) { 1431 | pblk = tmpdata; 1432 | lio = lrem = TF_FROM_BITS(macbits); 1433 | ldone = 0; 1434 | _macwagain: lio = xwrite(dfd, pblk, lrem); 1435 | if (lio != NOSIZE) ldone += lio; 1436 | else xerror(NO, NO, NO, "%s", dstfname); 1437 | if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname); 1438 | if (lio < lrem) { 1439 | pblk += lio; 1440 | lrem -= lio; 1441 | goto _macwagain; 1442 | } 1443 | total_written_dst += ldone; 1444 | total_processed_dst += ldone; 1445 | delta_processed += ldone; 1446 | } 1447 | else { 1448 | int mfd; 1449 | 1450 | if (!strcmp(do_mac_file, "-")) mfd = 1; 1451 | else mfd = xopen(do_mac_file, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags); 1452 | if (do_outfmt == TFC_OUTFMT_B64) { 1453 | memcpy(macvrfy, tmpdata, TF_FROM_BITS(macbits)); 1454 | memset(tmpdata, 0, TFC_TMPSIZE); 1455 | memcpy(tmpdata, TFC_ASCII_TFC_MAC_FOURCC, TFC_ASCII_TFC_MAC_FOURCC_LEN); 1456 | base64_encode((char *)tmpdata+TFC_ASCII_TFC_MAC_FOURCC_LEN, (char *)macvrfy, TF_FROM_BITS(macbits)); 1457 | lrem = strnlen((char *)tmpdata, sizeof(tmpdata)); 1458 | if (lrem) { 1459 | tmpdata[lrem] = '\n'; 1460 | lrem++; 1461 | } 1462 | lio = xwrite(mfd, tmpdata, lrem); 1463 | } 1464 | else lio = xwrite(mfd, tmpdata, TF_FROM_BITS(macbits)); 1465 | if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file); 1466 | if (do_fsync && fsync(mfd) == -1) xerror(NO, NO, YES, "%s", do_mac_file); 1467 | xclose(mfd); 1468 | } 1469 | 1470 | memset(macvrfy, 0, sizeof(macvrfy)); 1471 | memset(macresult, 0, sizeof(macresult)); 1472 | memset(tmpdata, 0, sizeof(tmpdata)); 1473 | } 1474 | else if (do_mac == TFC_MAC_DROP2) total_processed_src += SKEIN_DIGEST_SIZE; 1475 | 1476 | if (verbose || status_timer || (do_stop == YES && quiet == NO)) print_crypt_status(TFC_SIGLAST); 1477 | 1478 | xexit(exitcode); 1479 | return -1; 1480 | } 1481 | --------------------------------------------------------------------------------