Commit message: Fix SPA authenticator, checking client-supplied data before using it.  Bug 2571
CVE: CVE-2020-12783
CWE: CWE-125
Vulnerability description: Exim through 4.93 has an out-of-bounds read in the SPA authenticator that could result in SPA/NTLM authentication bypass in auths/spa.c and auths/auth-spa.c.

Project: exim
File: auth-spa.c

copy4 (uschar *out, uint32x x)
{
out[0] = x & 0xFF;
out[1] = (x >> 8) & 0xFF;
out[2] = (x >> 16) & 0xFF;
out[3] = (x >> 24) & 0xFF;
}

Project: exim
File: auth-spa.c

smbhash (uschar *out, uschar *in, uschar *key, int forw)
{
int i;
char outb[64];
char inb[64];
char keyb[64];
uschar key2[8];

str_to_key (key, key2);

for (i = 0; i < 64; i++)
  {
  inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
  keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
  outb[i] = 0;
  }

dohash (outb, inb, keyb, forw);

for (i = 0; i < 8; i++)
  out[i] = 0;

for (i = 0; i < 64; i++)
  if (outb[i])
   out[i / 8] |= (1 << (7 - (i % 8)));
}

Project: exim
File: auth-spa.c

F (uint32x X, uint32x Y, uint32x Z)
{
return (X & Y) | ((~X) & Z);
}

Project: exim
File: auth-spa.c

str_to_key (uschar *str, uschar *key)
{
int i;

key[0] = str[0] >> 1;
key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
key[7] = str[6] & 0x7F;
for (i = 0; i < 8; i++)
    key[i] = (key[i] << 1);
}

Project: exim
File: auth-spa.c

dumpRaw (FILE * fp, uschar *buf, size_t len)
{
int i;

for (i = 0; i < len; ++i)
  fprintf (fp, "%02x ", buf[i]);

fprintf (fp, "\n");
}

Project: exim
File: auth-spa.c

spa_build_auth_response (SPAAuthChallenge * challenge,
                        SPAAuthResponse * response, char *user,
                        char *password)
{
uint8x lmRespData[24];
uint8x ntRespData[24];
char *d = strdup (GetUnicodeString (challenge, uDomain));
char *domain = d;
char *u = strdup (user);
char *p = strchr (u, '@');

if (p)
  {
  domain = p + 1;
  *p = '\0';
  }

spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);

response->bufIndex = 0;
memcpy (response->ident, "NTLMSSP\0\0\0", 8);
SIVAL (&response->msgType, 0, 3);

spa_bytes_add (response, lmResponse, lmRespData, 24);
spa_bytes_add (response, ntResponse, ntRespData, 24);
spa_unicode_add_string (response, uDomain, domain);
spa_unicode_add_string (response, uUser, u);
spa_unicode_add_string (response, uWks, u);
spa_string_add (response, sessionKey, NULL);

response->flags = challenge->flags;

free (d);
free (u);
}

Project: exim
File: auth-spa.c

spa_smb_nt_encrypt (uschar * passwd, uschar * c8, uschar * p24)
{
uschar p21[21];

memset (p21, '\0', 21);

E_md4hash (passwd, p21);
SMBOWFencrypt (p21, c8, p24);

#ifdef DEBUG_PASSWORD
DEBUG_X (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
dump_data (100, CS  p21, 16);
dump_data (100, CS  c8, 8);
dump_data (100, CS  p24, 24);
#endif
}

Project: exim
File: auth-spa.c

dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
{
fprintf (fp, "NTLM Response:\n");
fprintf (fp, "      Ident = %s\n", response->ident);
fprintf (fp, "      mType = %d\n", IVAL (&response->msgType, 0));
fprintf (fp, "     LmResp = ");
DumpBuffer (fp, response, lmResponse);
fprintf (fp, "     NTResp = ");
DumpBuffer (fp, response, ntResponse);
fprintf (fp, "     Domain = %s\n", GetUnicodeString (response, uDomain));
fprintf (fp, "       User = %s\n", GetUnicodeString (response, uUser));
fprintf (fp, "        Wks = %s\n", GetUnicodeString (response, uWks));
fprintf (fp, "       sKey = ");
DumpBuffer (fp, response, sessionKey);
fprintf (fp, "      Flags = %08x\n", IVAL (&response->flags, 0));
}

Project: exim
File: auth-spa.c

nt_lm_owf_gen (char *pwd, uschar nt_p16[16], uschar p16[16])
{
char passwd[130];

memset (passwd, '\0', 130);
safe_strcpy (passwd, pwd, sizeof (passwd) - 1);

/* Calculate the MD4 hash (NT compatible) of the password */
memset (nt_p16, '\0', 16);
E_md4hash (US passwd, nt_p16);

#ifdef DEBUG_PASSWORD
DEBUG_X (100, ("nt_lm_owf_gen: pwd, nt#\n"));
dump_data (120, passwd, strlen (passwd));
dump_data (100, CS  nt_p16, 16);
#endif

/* Mangle the passwords into Lanman format */
passwd[14] = '\0';
strupper (passwd);

/* Calculate the SMB (lanman) hash functions of the password */

memset (p16, '\0', 16);
E_P16 (US passwd, US p16);

#ifdef DEBUG_PASSWORD
DEBUG_X (100, ("nt_lm_owf_gen: pwd, lm#\n"));
dump_data (120, passwd, strlen (passwd));
dump_data (100, CS  p16, 16);
#endif
/* clear out local copy of user's password (just being paranoid). */
memset (passwd, '\0', sizeof (passwd));
}

Project: exim
File: auth-spa.c

skip_multibyte_char (char c)
{
/* bogus if to get rid of unused compiler warning */
if (c)
  return 0;
else
  return 0;
}

Project: exim
File: auth-spa.c

spa_build_auth_response (SPAAuthChallenge * challenge,
                        SPAAuthResponse * response, char *user,
                        char *password)
{
uint8x lmRespData[24];
uint8x ntRespData[24];
uint32x cf = IVAL(&challenge->flags, 0);
char *u = strdup (user);
char *p = strchr (u, '@');
char *d = NULL;
char *domain;

if (p)
  {
  domain = p + 1;
  *p = '\0';
  }

else domain = d = strdup((cf & 0x1)?
  CCS GetUnicodeString(challenge, uDomain) :
  CCS GetString(challenge, uDomain));

spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);

response->bufIndex = 0;
memcpy (response->ident, "NTLMSSP\0\0\0", 8);
SIVAL (&response->msgType, 0, 3);

spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);

if (cf & 0x1) {      /* Unicode Text */
     spa_unicode_add_string (response, uDomain, domain);
     spa_unicode_add_string (response, uUser, u);
     spa_unicode_add_string (response, uWks, u);
} else {             /* OEM Text */
     spa_string_add (response, uDomain, domain);
     spa_string_add (response, uUser, u);
     spa_string_add (response, uWks, u);
}

spa_string_add (response, sessionKey, NULL);
response->flags = challenge->flags;

if (d != NULL) free (d);
free (u);
}

Project: exim
File: auth-spa.c

concat (char *out, char *in1, char *in2, int l1, int l2)
{
while (l1--)
  *out++ = *in1++;
while (l2--)
  *out++ = *in2++;
}

Project: exim
File: auth-spa.c

dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
{
fprintf (fp, "NTLM Request:\n");
fprintf (fp, "      Ident = %s\n", request->ident);
fprintf (fp, "      mType = %d\n", IVAL (&request->msgType, 0));
fprintf (fp, "      Flags = %08x\n", IVAL (&request->flags, 0));
fprintf (fp, "       User = %s\n", GetString (request, user));
fprintf (fp, "     Domain = %s\n", GetString (request, domain));
}

Project: exim
File: auth-spa.c

spa_smb_encrypt (uschar * passwd, uschar * c8, uschar * p24)
{
uschar p14[15], p21[21];

memset (p21, '\0', 21);
memset (p14, '\0', 14);
StrnCpy (CS  p14, CS  passwd, 14);

strupper (CS  p14);
E_P16 (p14, p21);

SMBOWFencrypt (p21, c8, p24);

#ifdef DEBUG_PASSWORD
DEBUG_X (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
dump_data (100, CS  p21, 16);
dump_data (100, CS  c8, 8);
dump_data (100, CS  p24, 24);
#endif
}

Project: exim
File: auth-spa.c

D_P16 (uschar *p14, uschar *in, uschar *out)
{
smbhash (out, in, p14, 0);
smbhash (out + 8, in + 8, p14 + 7, 0);
}

Project: exim
File: auth-spa.c

NTLMSSPOWFencrypt (uschar passwd[8], uschar * ntlmchalresp, uschar p24[24])
{
uschar p21[21];

memset (p21, '\0', 21);
memcpy (p21, passwd, 8);
memset (p21 + 8, 0xbd, 8);

E_P24 (p21, ntlmchalresp, p24);
#ifdef DEBUG_PASSWORD
DEBUG_X (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
dump_data (100, CS  p21, 21);
dump_data (100, CS  ntlmchalresp, 8);
dump_data (100, CS  p24, 24);
#endif
}

Project: exim
File: auth-spa.c

E_md4hash (uschar * passwd, uschar * p16)
{
int len;
int16x wpwd[129];

/* Password cannot be longer than 128 characters */
len = strlen (CS  passwd);
if (len > 128)
  len = 128;
/* Password must be converted to NT unicode */
_my_mbstowcs (wpwd, passwd, len);
wpwd[len] = 0;               /* Ensure string is null terminated */
/* Calculate length in bytes */
len = _my_wcslen (wpwd) * sizeof (int16x);

mdfour (p16, US wpwd, len);
}

Project: exim
File: auth-spa.c

safe_strcpy (char *dest, const char *src, size_t maxlength)
{
size_t len;

if (!dest)
  {
  DEBUG_X (0, ("ERROR: NULL dest in safe_strcpy\n"));
  return NULL;
  }

if (!src)
  {
  *dest = 0;
  return dest;
  }

len = strlen (src);

if (len > maxlength)
  {
  DEBUG_X (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
	    (int) (len - maxlength), src));
  len = maxlength;
  }

memcpy (dest, src, len);
dest[len] = 0;
return dest;
}

Project: exim
File: auth-spa.c

E_P16 (uschar *p14, uschar *p16)
{
uschar sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
smbhash (p16, sp8, p14, 1);
smbhash (p16 + 8, sp8, p14 + 7, 1);
}

Project: exim
File: auth-spa.c

_my_mbstowcs (int16x * dst, uschar * src, int len)
{
int i;
int16x val;

for (i = 0; i < len; i++)
  {
  val = *src;
  SSVAL (dst, 0, val);
  dst++;
  src++;
  if (val == 0)
   break;
  }
return i;
}

Project: exim
File: auth-spa.c

E_P24 (uschar *p21, uschar *c8, uschar *p24)
{
smbhash (p24, c8, p21, 1);
smbhash (p24 + 8, c8, p21 + 7, 1);
smbhash (p24 + 16, c8, p21 + 14, 1);
}

Project: exim
File: auth-spa.c

spa_mdfour64 (uint32x * M)
{
int j;
uint32x AA, BB, CC, DD;
uint32x X[16];

for (j = 0; j < 16; j++)
  X[j] = M[j];

AA = A;
BB = B;
CC = C;
DD = D;

ROUND1 (A, B, C, D, 0, 3);
ROUND1 (D, A, B, C, 1, 7);
ROUND1 (C, D, A, B, 2, 11);
ROUND1 (B, C, D, A, 3, 19);
ROUND1 (A, B, C, D, 4, 3);
ROUND1 (D, A, B, C, 5, 7);
ROUND1 (C, D, A, B, 6, 11);
ROUND1 (B, C, D, A, 7, 19);
ROUND1 (A, B, C, D, 8, 3);
ROUND1 (D, A, B, C, 9, 7);
ROUND1 (C, D, A, B, 10, 11);
ROUND1 (B, C, D, A, 11, 19);
ROUND1 (A, B, C, D, 12, 3);
ROUND1 (D, A, B, C, 13, 7);
ROUND1 (C, D, A, B, 14, 11);
ROUND1 (B, C, D, A, 15, 19);

ROUND2 (A, B, C, D, 0, 3);
ROUND2 (D, A, B, C, 4, 5);
ROUND2 (C, D, A, B, 8, 9);
ROUND2 (B, C, D, A, 12, 13);
ROUND2 (A, B, C, D, 1, 3);
ROUND2 (D, A, B, C, 5, 5);
ROUND2 (C, D, A, B, 9, 9);
ROUND2 (B, C, D, A, 13, 13);
ROUND2 (A, B, C, D, 2, 3);
ROUND2 (D, A, B, C, 6, 5);
ROUND2 (C, D, A, B, 10, 9);
ROUND2 (B, C, D, A, 14, 13);
ROUND2 (A, B, C, D, 3, 3);
ROUND2 (D, A, B, C, 7, 5);
ROUND2 (C, D, A, B, 11, 9);
ROUND2 (B, C, D, A, 15, 13);

ROUND3 (A, B, C, D, 0, 3);
ROUND3 (D, A, B, C, 8, 9);
ROUND3 (C, D, A, B, 4, 11);
ROUND3 (B, C, D, A, 12, 15);
ROUND3 (A, B, C, D, 2, 3);
ROUND3 (D, A, B, C, 10, 9);
ROUND3 (C, D, A, B, 6, 11);
ROUND3 (B, C, D, A, 14, 15);
ROUND3 (A, B, C, D, 1, 3);
ROUND3 (D, A, B, C, 9, 9);
ROUND3 (C, D, A, B, 5, 11);
ROUND3 (B, C, D, A, 13, 15);
ROUND3 (A, B, C, D, 3, 3);
ROUND3 (D, A, B, C, 11, 9);
ROUND3 (C, D, A, B, 7, 11);
ROUND3 (B, C, D, A, 15, 15);

A += AA;
B += BB;
C += CC;
D += DD;

A &= 0xFFFFFFFF;
B &= 0xFFFFFFFF;
C &= 0xFFFFFFFF;
D &= 0xFFFFFFFF;

for (j = 0; j < 16; j++)
  X[j] = 0;
}

Project: exim
File: auth-spa.c

spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
{
char *u = strdup (user);
char *p = strchr (u, '@');

if (p)
  {
  if (!domain)
   domain = p + 1;
  *p = '\0';
  }

request->bufIndex = 0;
memcpy (request->ident, "NTLMSSP\0\0\0", 8);
SIVAL (&request->msgType, 0, 1);
SIVAL (&request->flags, 0, 0x0000b207);      /* have to figure out what these mean */
spa_string_add (request, user, u);
spa_string_add (request, domain, domain);
free (u);
}

Project: exim
File: auth-spa.c

strToUnicode (char *p)
{
static uschar buf[1024];
size_t l = strlen (p);
int i = 0;

assert (l * 2 < sizeof buf);

while (l--)
  {
  buf[i++] = *p++;
  buf[i++] = 0;
  }

return buf;
}

Project: exim
File: auth-spa.c

StrnCpy (char *dest, const char *src, size_t n)
{
char *d = dest;
if (!dest)
  return (NULL);
if (!src)
  {
  *dest = 0;
  return (dest);
  }
while (n-- && (*d++ = *src++));
*d = 0;
return (dest);
}

Project: exim
File: auth-spa.c

spa_base64_to_bits (char *out, int outlength, const char *in)
/* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
{
int len = 0;
uschar digit1, digit2, digit3, digit4;

if (in[0] == '+' && in[1] == ' ')
  in += 2;
if (*in == '\r')
  return (0);

do
  {
  if (len >= outlength)                   /* Added by PH */
    return -1;                          /* Added by PH */
  digit1 = in[0];
  if (DECODE64 (digit1) == BAD)
    return -1;
  digit2 = in[1];
  if (DECODE64 (digit2) == BAD)
    return -1;
  digit3 = in[2];
  if (digit3 != '=' && DECODE64 (digit3) == BAD)
    return -1;
  digit4 = in[3];
  if (digit4 != '=' && DECODE64 (digit4) == BAD)
    return -1;
  in += 4;
  *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
  ++len;
  if (digit3 != '=')
    {
    if (len >= outlength)                   /* Added by PH */
      return -1;                          /* Added by PH */
    *out++ =
      ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
    ++len;
    if (digit4 != '=')
      {
      if (len >= outlength)                   /* Added by PH */
	return -1;                          /* Added by PH */
      *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
      ++len;
      }
    }
  }
while (*in && *in != '\r' && digit4 != '=');

return len;
}

Project: exim
File: auth-spa.c

SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24])
{
uschar p21[21];

memset (p21, '\0', 21);

memcpy (p21, passwd, 16);
E_P24 (p21, c8, p24);
}

Project: exim
File: auth-spa.c

spa_bits_to_base64 (uschar *out, const uschar *in, int inlen)
/* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
{
for (; inlen >= 3; inlen -= 3)
  {
  *out++ = base64digits[in[0] >> 2];
  *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
  *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
  *out++ = base64digits[in[2] & 0x3f];
  in += 3;
  }
if (inlen > 0)
  {
  uschar fragment;

  *out++ = base64digits[in[0] >> 2];
  fragment = (in[0] << 4) & 0x30;
  if (inlen > 1)
     fragment |= in[1] >> 4;
  *out++ = base64digits[fragment];
  *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
  *out++ = '=';
  }
*out = '\0';
}

Project: exim
File: auth-spa.c

lshift (char *d, int count, int n)
{
char out[64];
for (int i = 0; i < n; i++)
  out[i] = d[(i + count) % n];
for (int i = 0; i < n; i++)
  d[i] = out[i];
}

Project: exim
File: auth-spa.c

xor (char *out, char *in1, char *in2, int n)
{
for (int i = 0; i < n; i++)
  out[i] = in1[i] ^ in2[i];
}

Project: exim
File: auth-spa.c

strupper (char *s)
{
while (*s)
  {
   size_t skip = skip_multibyte_char (*s);
   if (skip != 0)
     s += skip;
   else
     {
       if (islower ((uschar)(*s)))
	 *s = toupper (*s);
       s++;
     }
  }
}

Project: exim
File: auth-spa.c

H (uint32x X, uint32x Y, uint32x Z)
{
return X ^ Y ^ Z;
}

Project: exim
File: auth-spa.c

toString (char *p, size_t len)
{
static uschar buf[1024];

assert (len + 1 < sizeof buf);

memcpy (buf, p, len);
buf[len] = 0;
return buf;
}

Project: exim
File: auth-spa.c

permute (char *out, char *in, uschar * p, int n)
{
for (int i = 0; i < n; i++)
  out[i] = in[p[i] - 1];
}

Project: exim
File: auth-spa.c

G (uint32x X, uint32x Y, uint32x Z)
{
return (X & Y) | (X & Z) | (Y & Z);
}

Project: exim
File: auth-spa.c

unicodeToString (char *p, size_t len)
{
int i;
static char buf[1024];

assert (len + 1 < sizeof buf);

for (i = 0; i < len; ++i)
  {
  buf[i] = *p & 0x7f;
  p += 2;
  }

buf[i] = '\0';
return buf;
}

Project: exim
File: auth-spa.c

spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
{
char chalstr[8];
int i;
int p = (int)getpid();
int random_seed = (int)time(NULL) ^ ((p << 16) | p);

request = request;  /* Added by PH to stop compilers whinging */

/* Ensure challenge data is cleared, in case it isn't all used. This
patch added by PH on suggestion of Russell King */

memset(challenge, 0, sizeof(SPAAuthChallenge));

challenge->bufIndex = 0;
memcpy (challenge->ident, "NTLMSSP\0", 8);
SIVAL (&challenge->msgType, 0, 2);
SIVAL (&challenge->flags, 0, 0x00008201);
SIVAL (&challenge->uDomain.len, 0, 0x0000);
SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
SIVAL (&challenge->uDomain.offset, 0, 0x00002800);

/* generate eight pseudo random bytes (method ripped from host.c) */

for(i=0;i<8;i++)
  {
  chalstr[i] = (uschar)(random_seed >> 16) % 256;
  random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
  }

memcpy(challenge->challengeData,chalstr,8);
}

Project: exim
File: auth-spa.c

copy64 (uint32x * M, uschar *in)
{
int i;

for (i = 0; i < 16; i++)
  M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
    (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
}

Project: exim
File: auth-spa.c

mdfour (uschar *out, uschar *in, int n)
{
uschar buf[128];
uint32x M[16];
uint32x b = n * 8;
int i;

A = 0x67452301;
B = 0xefcdab89;
C = 0x98badcfe;
D = 0x10325476;

while (n > 64)
  {
  copy64 (M, in);
  spa_mdfour64 (M);
  in += 64;
  n -= 64;
  }

for (i = 0; i < 128; i++)
  buf[i] = 0;
memcpy (buf, in, n);
buf[n] = 0x80;

if (n <= 55)
  {
  copy4 (buf + 56, b);
  copy64 (M, buf);
  spa_mdfour64 (M);
  }
else
  {
  copy4 (buf + 120, b);
  copy64 (M, buf);
  spa_mdfour64 (M);
  copy64 (M, buf + 64);
  spa_mdfour64 (M);
  }

for (i = 0; i < 128; i++)
  buf[i] = 0;
copy64 (M, buf);

copy4 (out, A);
copy4 (out + 4, B);
copy4 (out + 8, C);
copy4 (out + 12, D);

A = B = C = D = 0;
}

Project: exim
File: auth-spa.c

lshift_a (uint32x x, int s)
{
x &= 0xFFFFFFFF;
return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
}

Project: exim
File: auth-spa.c

dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
{
fprintf (fp, "NTLM Challenge:\n");
fprintf (fp, "      Ident = %s\n", challenge->ident);
fprintf (fp, "      mType = %d\n", IVAL (&challenge->msgType, 0));
fprintf (fp, "     Domain = %s\n", GetUnicodeString (challenge, uDomain));
fprintf (fp, "      Flags = %08x\n", IVAL (&challenge->flags, 0));
fprintf (fp, "  Challenge = ");
dumpRaw (fp, challenge->challengeData, 8);
}

Project: exim
File: auth-spa.c

dohash (char *out, char *in, char *key, int forw)
{
int i, j, k;
char pk1[56];
char c[28];
char d[28];
char cd[56];
char ki[16][48];
char pd1[64];
char l[32], r[32];
char rl[64];

permute (pk1, key, perm1, 56);

for (i = 0; i < 28; i++)
  c[i] = pk1[i];
for (i = 0; i < 28; i++)
  d[i] = pk1[i + 28];

for (i = 0; i < 16; i++)
  {
  lshift (c, sc[i], 28);
  lshift (d, sc[i], 28);

  concat (cd, c, d, 28, 28);
  permute (ki[i], cd, perm2, 48);
  }

permute (pd1, in, perm3, 64);

for (j = 0; j < 32; j++)
  {
  l[j] = pd1[j];
  r[j] = pd1[j + 32];
  }

for (i = 0; i < 16; i++)
  {
  char er[48];
  char erk[48];
  char b[8][6];
  char cb[32];
  char pcb[32];
  char r2[32];

  permute (er, r, perm4, 48);

  xor (erk, er, ki[forw ? i : 15 - i], 48);

  for (j = 0; j < 8; j++)
   for (k = 0; k < 6; k++)
     b[j][k] = erk[j * 6 + k];

  for (j = 0; j < 8; j++)
   {
   int m, n;
   m = (b[j][0] << 1) | b[j][5];

   n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];

   for (k = 0; k < 4; k++)
     b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
   }

  for (j = 0; j < 8; j++)
   for (k = 0; k < 4; k++)
     cb[j * 4 + k] = b[j][k];
  permute (pcb, cb, perm5, 32);

  xor (r2, l, pcb, 32);

  for (j = 0; j < 32; j++)
   l[j] = r[j];

  for (j = 0; j < 32; j++)
   r[j] = r2[j];
  }

concat (rl, r, l, 32, 32);

permute (out, rl, perm6, 64);
}

Project: exim
File: auth-spa.c

_my_wcslen (int16x * str)
{
int len = 0;
while (*str++ != 0)
  len++;
return len;
}