// File: /workspace/github_c_makefile_star2_O0/aerospike[P]aerospike-common/src/main/aerospike/crypt_blowfish.c
// Function: BF_set_key
static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
    unsigned char flags)
{
	const char *ptr = key;
	unsigned int bug, i, j;
	BF_word safety, sign, diff, tmp[2];

/*
 * There was a sign extension bug in older revisions of this function.  While
 * we would have liked to simply fix the bug and move on, we have to provide
 * a backwards compatibility feature (essentially the bug) for some systems and
 * a safety measure for some others.  The latter is needed because for certain
 * multiple inputs to the buggy algorithm there exist easily found inputs to
 * the correct algorithm that produce the same hash.  Thus, we optionally
 * deviate from the correct algorithm just enough to avoid such collisions.
 * While the bug itself affected the majority of passwords containing
 * characters with the 8th bit set (although only a percentage of those in a
 * collision-producing way), the anti-collision safety measure affects
 * only a subset of passwords containing the '\xff' character (not even all of
 * those passwords, just some of them).  This character is not found in valid
 * UTF-8 sequences and is rarely used in popular 8-bit character encodings.
 * Thus, the safety measure is unlikely to cause much annoyance, and is a
 * reasonable tradeoff to use when authenticating against existing hashes that
 * are not reliably known to have been computed with the correct algorithm.
 *
 * We use an approach that tries to minimize side-channel leaks of password
 * information - that is, we mostly use fixed-cost bitwise operations instead
 * of branches or table lookups.  (One conditional branch based on password
 * length remains.  It is not part of the bug aftermath, though, and is
 * difficult and possibly unreasonable to avoid given the use of C strings by
 * the caller, which results in similar timing leaks anyway.)
 *
 * For actual implementation, we set an array index in the variable "bug"
 * (0 means no bug, 1 means sign extension bug emulation) and a flag in the
 * variable "safety" (bit 16 is set when the safety measure is requested).
 * Valid combinations of settings are:
 *
 * Prefix "$2a$": bug = 0, safety = 0x10000
 * Prefix "$2x$": bug = 1, safety = 0
 * Prefix "$2y$": bug = 0, safety = 0
 */
	bug = (unsigned int)flags & 1;
	safety = ((BF_word)flags & 2) << 15;

	sign = diff = 0;

	for (i = 0; i < BF_N + 2; i++) {
		tmp[0] = tmp[1] = 0;
		for (j = 0; j < 4; j++) {
			tmp[0] <<= 8;
			tmp[0] |= (unsigned char)*ptr; /* correct */
			tmp[1] <<= 8;
			tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
/*
 * Sign extension in the first char has no effect - nothing to overwrite yet,
 * and those extra 24 bits will be fully shifted out of the 32-bit word.  For
 * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
 * extension in tmp[1] occurs.  Once this flag is set, it remains set.
 */
			if (j)
				sign |= tmp[1] & 0x80;
			if (!*ptr)
				ptr = key;
			else
				ptr++;
		}
		diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */

		expanded[i] = tmp[bug];
		initial[i] = BF_init_state.P[i] ^ tmp[bug];
	}

/*
 * At this point, "diff" is zero iff the correct and buggy algorithms produced
 * exactly the same result.  If so and if "sign" is non-zero, which indicates
 * that there was a non-benign sign extension, this means that we have a
 * collision between the correctly computed hash for this password and a set of
 * passwords that could be supplied to the buggy algorithm.  Our safety measure
 * is meant to protect from such many-buggy to one-correct collisions, by
 * deviating from the correct algorithm in such cases.  Let's check for this.
 */
	diff |= diff >> 16; /* still zero iff exact match */
	diff &= 0xffff; /* ditto */
	diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
	sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
	sign &= ~diff & safety; /* action needed? */

/*
 * If we have determined that we need to deviate from the correct algorithm,
 * flip bit 16 in initial expanded key.  (The choice of 16 is arbitrary, but
 * let's stick to it now.  It came out of the approach we used above, and it's
 * not any worse than any other choice we could make.)
 *
 * It is crucial that we don't do the same to the expanded key used in the main
 * Eksblowfish loop.  By doing it to only one of these two, we deviate from a
 * state that could be directly specified by a password to the buggy algorithm
 * (and to the fully correct one as well, but that's a side-effect).
 */
	initial[0] ^= sign;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movb %cl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movb %al, -0x19(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movzbl -0x19(%rbp), %eax
andl $0x1, %eax
movl %eax, -0x2c(%rbp)
movzbl -0x19(%rbp), %eax
andl $0x2, %eax
shll $0xf, %eax
movl %eax, -0x38(%rbp)
movl $0x0, -0x40(%rbp)
movl $0x0, -0x3c(%rbp)
movl $0x0, -0x30(%rbp)
cmpl $0x12, -0x30(%rbp)
jae 0x1e909
movl $0x0, -0x44(%rbp)
movl $0x0, -0x48(%rbp)
movl $0x0, -0x34(%rbp)
cmpl $0x4, -0x34(%rbp)
jae 0x1e8ba
movl -0x48(%rbp), %eax
shll $0x8, %eax
movl %eax, -0x48(%rbp)
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
orl -0x48(%rbp), %eax
movl %eax, -0x48(%rbp)
movl -0x44(%rbp), %eax
shll $0x8, %eax
movl %eax, -0x44(%rbp)
movq -0x28(%rbp), %rax
movsbl (%rax), %eax
orl -0x44(%rbp), %eax
movl %eax, -0x44(%rbp)
cmpl $0x0, -0x34(%rbp)
je 0x1e88e
movl -0x44(%rbp), %eax
andl $0x80, %eax
orl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movq -0x28(%rbp), %rax
cmpb $0x0, (%rax)
jne 0x1e8a1
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x1e8ad
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x1e8af
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x1e848
movl -0x48(%rbp), %eax
xorl -0x44(%rbp), %eax
orl -0x40(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x2c(%rbp), %eax
movl -0x48(%rbp,%rax,4), %edx
movq -0x10(%rbp), %rax
movl -0x30(%rbp), %ecx
movl %edx, (%rax,%rcx,4)
movl -0x30(%rbp), %eax
movl %eax, %ecx
leaq 0x11ddd(%rip), %rax     # 0x306c0
movl 0x1000(%rax,%rcx,4), %edx
movl -0x2c(%rbp), %eax
xorl -0x48(%rbp,%rax,4), %edx
movq -0x18(%rbp), %rax
movl -0x30(%rbp), %ecx
movl %edx, (%rax,%rcx,4)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x1e829
movl -0x40(%rbp), %eax
shrl $0x10, %eax
orl -0x40(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
andl $0xffff, %eax           # imm = 0xFFFF
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
addl $0xffff, %eax           # imm = 0xFFFF
movl %eax, -0x40(%rbp)
movl -0x3c(%rbp), %eax
shll $0x9, %eax
movl %eax, -0x3c(%rbp)
movl -0x40(%rbp), %eax
xorl $-0x1, %eax
andl -0x38(%rbp), %eax
andl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %ecx
movq -0x18(%rbp), %rax
xorl (%rax), %ecx
movl %ecx, (%rax)
popq %rbp
retq