
# Copyright 2015-2024 Rivoreo

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
# IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.


XTEA_DELTA=0x9e3779b9
XTEA_NROUNDS=32

# Usage: xtea_crypt <v1-var-name> <v2-var-name> <key-part-1> ... <key-part-4>
xtea_crypt() {
	local k sum=0 i=0
	while [ $i -lt $XTEA_NROUNDS ]; do
		eval "k=\${$(((sum&3)+3))}"
		eval "$1=\$((($1+(((($2<<4)^($2>>5))+$2)^(sum+k)))&0xffffffff))"
		sum=$((sum+XTEA_DELTA))
		eval "k=\${$((((sum>>11)&3)+3))}"
		eval "$2=\$((($2+(((($1<<4)^($1>>5))+$1)^(sum+k)))&0xffffffff))"
		i=$((i+1))
	done
}

# Usage: xtea_ctr_crypt <key-in-hex-without-0x> <output-format> <nonce> [<padding-size>]
xtea_ctr_crypt() {
	if [ ${#1} != 32 ]; then
		echo "Incorrect key size" 1>&2
		return 255
	fi
	local key="$1" cut="????????????????????????" key_parts=
	while [ -n "$key" ]; do
		key_parts="$key_parts 0x${key%$cut}"
		cut="${cut%????????}"
		key="${key#????????}"
	done
	local padding_size
	[ $# = 4 ] && padding_size=$4 || padding_size=0
	local i block_bytes
	local counter=$3 buffer v1 v2 c
	while
		i=$padding_size
		block_bytes=
		while [ $i -lt 8 ] && read n; do
			i=$((i+1))
			block_bytes="$block_bytes 0x$n"
		done
		[ -n "$block_bytes" ]
	do
		buffer="`printf %016x $counter`"
		v1=0x${buffer%????????}
		v2=0x${buffer#????????}
		counter=$((counter+1))
		xtea_crypt v1 v2 $key_parts
		i=$padding_size
		for n in $block_bytes; do
			if [ $i -lt 4 ]; then
				c=$(((v1>>((3-i)*8))&255))
			else
				c=$(((v2>>((7-i)*8))&255))
			fi
			printf "$2" $((n^c))
			i=$((i+1))
		done
		padding_size=0
	done
}
