Files
ncpfs/lib/ndscrypt.c
ncpfs archive import 82706139bf Import ncpfs 2.2.1
2026-04-28 20:39:59 +02:00

306 lines
11 KiB
C

/*
NDS client for ncpfs
Copyright (C) 1997 Arne de Bruijn
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Revision history:
0.00 1997 Arne de Bruijn
Initial release.
0.01 1997 Petr Vandrovec <vandrove@vc.cvut.cz>
Remove shuffle.
*/
#include <string.h>
#include "ndscrypt.h"
#include <ncp/ncplib.h>
static unsigned int rol16(unsigned int i, int c) {
return ((i << c) & 65535) | ((unsigned int)(i & 65535) >> (16 - c));
}
static unsigned int ror16(unsigned int i, int c) {
return ((unsigned int)(i & 65535) >> c) | ((i << (16 - c)) & 65535);
}
static unsigned char nwcryptdata[256]={
0xD9,0x78,0xF9,0xC4,0x19,0xDD,0xB5,0xED,0x28,0xE9,0xFD,0x79,
0x4A,0xA0,0xD8,0x9D,0xC6,0x7E,0x37,0x83,0x2B,0x76,0x53,0x8E,
0x62,0x4C,0x64,0x88,0x44,0x8B,0xFB,0xA2,0x17,0x9A,0x59,0xF5,
0x87,0xB3,0x4F,0x13,0x61,0x45,0x6D,0x8D,0x09,0x81,0x7D,0x32,
0xBD,0x8F,0x40,0xEB,0x86,0xB7,0x7B,0x0B,0xF0,0x95,0x21,0x22,
0x5C,0x6B,0x4E,0x82,0x54,0xD6,0x65,0x93,0xCE,0x60,0xB2,0x1C,
0x73,0x56,0xC0,0x14,0xA7,0x8C,0xF1,0xDC,0x12,0x75,0xCA,0x1F,
0x3B,0xBE,0xE4,0xD1,0x42,0x3D,0xD4,0x30,0xA3,0x3C,0xB6,0x26,
0x6F,0xBF,0x0E,0xDA,0x46,0x69,0x07,0x57,0x27,0xF2,0x1D,0x9B,
0xBC,0x94,0x43,0x03,0xF8,0x11,0xC7,0xF6,0x90,0xEF,0x3E,0xE7,
0x06,0xC3,0xD5,0x2F,0xC8,0x66,0x1E,0xD7,0x08,0xE8,0xEA,0xDE,
0x80,0x52,0xEE,0xF7,0x84,0xAA,0x72,0xAC,0x35,0x4D,0x6A,0x2A,
0x96,0x1A,0xD2,0x71,0x5A,0x15,0x49,0x74,0x4B,0x9F,0xD0,0x5E,
0x04,0x18,0xA4,0xEC,0xC2,0xE0,0x41,0x6E,0x0F,0x51,0xCB,0xCC,
0x24,0x91,0xAF,0x50,0xA1,0xF4,0x70,0x39,0x99,0x7C,0x3A,0x85,
0x23,0xB8,0xB4,0x7A,0xFC,0x02,0x36,0x5B,0x25,0x55,0x97,0x31,
0x2D,0x5D,0xFA,0x98,0xE3,0x8A,0x92,0xAE,0x05,0xDF,0x29,0x10,
0x67,0x6C,0xBA,0xC9,0xD3,0x00,0xE6,0xCF,0xE1,0x9E,0xA8,0x2C,
0x63,0x16,0x01,0x3F,0x58,0xE2,0x89,0xA9,0x0D,0x38,0x34,0x1B,
0xAB,0x33,0xFF,0xB0,0xBB,0x48,0x0C,0x5F,0xB9,0xB1,0xCD,0x2E,
0xC5,0xF3,0xDB,0x47,0xE5,0xA5,0x9C,0x77,0x0A,0xA6,0x20,0x68,
0xFE,0x7F,0xC1,0xAD};
#if 0
static unsigned char shuffle_table[32]=
{0x48,0x93,0x46,0x67,0x98,0x3D,0xE6,0x8D,
0xB7,0x10,0x7A,0x26,0x5A,0xB9,0xB1,0x35,
0x6B,0x0F,0xD5,0x70,0xAE,0xFB,0xAD,0x11,
0xF4,0x47,0xDC,0xA7,0xEC,0xCF,0x50,0xC0};
static unsigned char shuffle_table2[256] =
{0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8,
0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9,
0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6,
0x0,0x7,0x3,0x8,0x2,0x9,0x3,0xF,0x7,0xF,0xC,0xF,0x6,0x4,0xA,0x0,
0x2,0x3,0xA,0xB,0xD,0x8,0x3,0xA,0x1,0x7,0xC,0xF,0x1,0x8,0x9,0xD,
0x9,0x1,0x9,0x4,0xE,0x4,0xC,0x5,0x5,0xC,0x8,0xB,0x2,0x3,0x9,0xE,
0x7,0x7,0x6,0x9,0xE,0xF,0xC,0x8,0xD,0x1,0xA,0x6,0xE,0xD,0x0,0x7,
0x7,0xA,0x0,0x1,0xF,0x5,0x4,0xB,0x7,0xB,0xE,0xC,0x9,0x5,0xD,0x1,
0xB,0xD,0x1,0x3,0x5,0xD,0xE,0x6,0x3,0x0,0xB,0xB,0xF,0x3,0x6,0x4,
0x9,0xD,0xA,0x3,0x1,0x4,0x9,0x4,0x8,0x3,0xB,0xE,0x5,0x0,0x5,0x2,
0xC,0xB,0xD,0x5,0xD,0x5,0xD,0x2,0xD,0x9,0xA,0xC,0xA,0x0,0xB,0x3,
0x5,0x3,0x6,0x9,0x5,0x1,0xE,0xE,0x0,0xE,0x8,0x2,0xD,0x2,0x2,0x0,
0x4,0xF,0x8,0x5,0x9,0x6,0x8,0x6,0xB,0xA,0xB,0xF,0x0,0x7,0x2,0x8,
0xC,0x7,0x3,0xA,0x1,0x4,0x2,0x5,0xF,0x7,0xA,0xC,0xE,0x5,0x9,0x3,
0xE,0x7,0x1,0x2,0xE,0x1,0xF,0x4,0xA,0x6,0xC,0x6,0xF,0x4,0x3,0x0,
0xC,0x0,0x3,0x6,0xF,0x8,0x7,0xB,0x2,0xD,0xC,0x6,0xA,0xA,0x8,0xD};
#endif
static unsigned char nwhashdata[256] =
{0xBD,0x56,0xEA,0xF2,0xA2,0xF1,0xAC,0x2A,0xB0,0x93,0xD1,0x9C,
0x1B,0x33,0xFD,0xD0,0x30,0x04,0xB6,0xDC,0x7D,0xDF,0x32,0x4B,
0xF7,0xCB,0x45,0x9B,0x31,0xBB,0x21,0x5A,0x41,0x9F,0xE1,0xD9,
0x4A,0x4D,0x9E,0xDA,0xA0,0x68,0x2C,0xC3,0x27,0x5F,0x80,0x36,
0x3E,0xEE,0xFB,0x95,0x1A,0xFE,0xCE,0xA8,0x34,0xA9,0x13,0xF0,
0xA6,0x3F,0xD8,0x0C,0x78,0x24,0xAF,0x23,0x52,0xC1,0x67,0x17,
0xF5,0x66,0x90,0xE7,0xE8,0x07,0xB8,0x60,0x48,0xE6,0x1E,0x53,
0xF3,0x92,0xA4,0x72,0x8C,0x08,0x15,0x6E,0x86,0x00,0x84,0xFA,
0xF4,0x7F,0x8A,0x42,0x19,0xF6,0xDB,0xCD,0x14,0x8D,0x50,0x12,
0xBA,0x3C,0x06,0x4E,0xEC,0xB3,0x35,0x11,0xA1,0x88,0x8E,0x2B,
0x94,0x99,0xB7,0x71,0x74,0xD3,0xE4,0xBF,0x3A,0xDE,0x96,0x0E,
0xBC,0x0A,0xED,0x77,0xFC,0x37,0x6B,0x03,0x79,0x89,0x62,0xC6,
0xD7,0xC0,0xD2,0x7C,0x6A,0x8B,0x22,0xA3,0x5B,0x05,0x5D,0x02,
0x75,0xD5,0x61,0xE3,0x18,0x8F,0x55,0x51,0xAD,0x1F,0x0B,0x5E,
0x85,0xE5,0xC2,0x57,0x63,0xCA,0x3D,0x6C,0xB4,0xC5,0xCC,0x70,
0xB2,0x91,0x59,0x0D,0x47,0x20,0xC8,0x4F,0x58,0xE0,0x01,0xE2,
0x16,0x38,0xC4,0x6F,0x3B,0x0F,0x65,0x46,0xBE,0x7E,0x2D,0x7B,
0x82,0xF9,0x40,0xB5,0x1D,0x73,0xF8,0xEB,0x26,0xC7,0x87,0x97,
0x25,0x54,0xB1,0x28,0xAA,0x98,0x9D,0xA5,0x64,0x6D,0x7A,0xD4,
0x10,0x81,0x44,0xEF,0x49,0xD6,0xAE,0x2E,0xDD,0x76,0x5C,0x2F,
0xA7,0x1C,0xC9,0x09,0x69,0x9A,0x83,0xCF,0x29,0x39,0xB9,0xE9,
0x4C,0xFF,0x43,0xAB};
void nwencrypt(const unsigned short *cryptbuf, const char *in, char *out) {
int i, j;
register unsigned int i1, i2, i3, i4;
const unsigned short *p;
i1 = WVAL_LH(in, 0);
i2 = WVAL_LH(in, 2);
i3 = WVAL_LH(in, 4);
i4 = WVAL_LH(in, 6);
p = cryptbuf;
for (j = 3; j; j--) {
for (i = (j == 2) ? 6 : 5; i; i--) {
i1 = rol16(i1 + (*p++) + (i4 & i3) + (~i4 & i2), 1);
i2 = rol16(i2 + (*p++) + (i1 & i4) + (~i1 & i3), 2);
i3 = rol16(i3 + (*p++) + (i2 & i1) + (~i2 & i4), 3);
i4 = rol16(i4 + (*p++) + (i3 & i2) + (~i3 & i1), 5);
}
if (j > 1) {
i1 += cryptbuf[i4 & 63];
i2 += cryptbuf[i1 & 63];
i3 += cryptbuf[i2 & 63];
i4 += cryptbuf[i3 & 63];
}
}
WSET_LH(out, 0, i1);
WSET_LH(out, 2, i2);
WSET_LH(out, 4, i3);
WSET_LH(out, 6, i4);
}
void nwdecrypt(const unsigned short *cryptbuf, const char *in, char *out) {
int i, j;
const unsigned short *p;
register unsigned int i1, i2, i3, i4;
i1 = WVAL_LH(in, 0);
i2 = WVAL_LH(in, 2);
i3 = WVAL_LH(in, 4);
i4 = WVAL_LH(in, 6);
p = cryptbuf + 64;
for (j = 3; j; j--) {
for (i = (j == 2) ? 6 : 5; i; i--) {
i4 = ror16(i4, 5) - (~i3 & i1) - (i3 & i2) - (*--p);
i3 = ror16(i3, 3) - (~i2 & i4) - (i2 & i1) - (*--p);
i2 = ror16(i2, 2) - (~i1 & i3) - (i1 & i4) - (*--p);
i1 = ror16(i1, 1) - (~i4 & i2) - (i4 & i3) - (*--p);
}
if (j > 1) {
i4 -= cryptbuf[i3 & 63];
i3 -= cryptbuf[i2 & 63];
i2 -= cryptbuf[i1 & 63];
i1 -= cryptbuf[i4 & 63];
}
}
WSET_LH(out, 0, i1);
WSET_LH(out, 2, i2);
WSET_LH(out, 4, i3);
WSET_LH(out, 6, i4);
}
void nwcryptinit(unsigned short *scryptbuf, const char *key) {
int i;
unsigned char cryptbuf[128], *p;
memcpy(cryptbuf, key, 8);
for (i = 0; i < 120; i++)
cryptbuf[i + 8] =
nwcryptdata[(unsigned char)(cryptbuf[i] + cryptbuf[i + 7]) & 255];
cryptbuf[128 - 8] = nwcryptdata[(unsigned char)cryptbuf[128 - 8] & 255];
for (i = 127 - 8; i >= 0; i--)
cryptbuf[i] = nwcryptdata[(unsigned char)cryptbuf[i + 1] ^
(unsigned char)cryptbuf[i + 8]];
for (i = 0, p = cryptbuf; i < 64; i++, p += 2)
scryptbuf[i] = (*p) | (*(p+1)) << 8;
}
void nwencryptblock(const char *cryptkey, const char *buf, int buflen,
char *outbuf) {
int i;
char nhash[8];
unsigned short cryptbuf[64];
nwcryptinit(cryptbuf, cryptkey);
memset(nhash, 0, 8);
while (buflen >= 8) {
for (i = 0; i < 8; i++, buf++)
nhash[i] ^= *buf;
nwencrypt(cryptbuf, nhash, nhash);
memcpy(outbuf, nhash, 8);
outbuf += 8;
buflen -= 8;
}
memset(cryptbuf, 0, sizeof(cryptbuf));
}
void nwdecryptblock(const char *cryptkey, const char *buf, int buflen,
char *outbuf) {
int i;
char nhash[16], *p;
unsigned short cryptbuf[64];
nwcryptinit(cryptbuf, cryptkey);
memset(nhash, 0, 16);
p = nhash;
while (buflen >= 8) {
memcpy(p, buf, 8);
p = nhash + 8 - (p - nhash);
nwdecrypt(cryptbuf, buf, outbuf);
for (i = 0; i < 8; i++, outbuf++)
*outbuf ^= p[i];
buf += 8;
buflen -= 8;
}
memset(cryptbuf, 0, sizeof(cryptbuf));
}
void nwhash1(char *hash, int hashlen, const char *data, int datalen) {
unsigned char *hp, *hp1, *hend, c;
const unsigned char *dp;
hp1 = (hp = (unsigned char *)hash) + 1;
hend = hp + hashlen;
dp = (const unsigned char *)data;
while (datalen--) {
*hp = nwhashdata[*hp1 ^ *hp] ^ *dp++;
hp = hp1++;
if (hp1 == hend)
hp1 = (unsigned char *)hash;
}
while (hp-- > (unsigned char *)hash) {
hp1 = (unsigned char *)hash;
c = *hp1++;
while (*(hp1 - 1) = *hp1, ++hp1 < (unsigned char *)hash + hashlen);
*(hp1 - 1) = c;
}
}
void nwhash2(char *hashbuf, char c) {
int i, j;
char *p = hashbuf + hashbuf[0x40];
p[0x20] = p[0x00] ^ (p[0x10] = c);
hashbuf[0x41] = (p[0x30] ^= nwhashdata[(unsigned char)(c ^ hashbuf[0x41])]);
if (!(hashbuf[0x40] = (hashbuf[0x40] + 1) & 15)) {
c = 0;
for (i = 18; i; i--)
for (j = 48, p = hashbuf; j; j--)
c = (*(p++) ^= nwhashdata[((unsigned char)c + j) & 255]);
}
}
void nwhash2block(char *hashbuf, const char *data, int datalen) {
while (datalen--)
nwhash2(hashbuf, *data++);
}
void nwhash2end(char *hashbuf) {
int i, j;
for(j = i = 16 - hashbuf[0x40]; j; j--)
nwhash2(hashbuf, i);
for(i = 0x30; i < 0x40; i++)
nwhash2(hashbuf, hashbuf[i]);
}
#if 0
void shuffle(const char *objid, const char *pwd, char *out) {
unsigned char temp[32];
int i, j, k;
i = strlen(pwd);
memset(temp, 0, 32);
for (j = 0; j < i; j++)
temp[j & 31] ^= pwd[j];
if (i)
for (j = i; j < 32; j += i) {
temp[j++] = shuffle_table[j];
k = 32 - j;
memcpy(temp + j, pwd, (k > i) ? i : k);
}
for (i = 0; i < 32; i++)
temp[i] ^= objid[i & 3];
j = 0;
for (k = 0; k < 2; k++)
for (i = 0; i < 32; i++)
(char)j += temp[i] = (temp[i] + j) ^
(temp[(i + j) & 31] - shuffle_table[i]);
for (i = 0; i < 16; i++)
out[i] = shuffle_table2[temp[i * 2]] |
(shuffle_table2[temp[i * 2 + 1]] << 4);
}
#endif