4 * Arne de Bruijn (arne@knoware.nl), 1997
8 #include <linux/config.h>
10 #ifdef CONFIG_NCPFS_PACKET_SIGNING
12 #include <linux/string.h>
13 #include <linux/ncp.h>
14 #include "ncpsign_kernel.h"
16 #define rol32(i,c) (((((i)&0xffffffff)<<c)&0xffffffff)| \
17 (((i)&0xffffffff)>>(32-c)))
18 /* i386: 32-bit, little endian, handles mis-alignment */
20 #define GET_LE32(p) (*(int *)(p))
21 #define PUT_LE32(p,v) { *(int *)(p)=v; }
23 /* from include/ncplib.h */
24 #define BVAL(buf,pos) (((__u8 *)(buf))[pos])
25 #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
26 #define BSET(buf,pos,val) (BVAL(buf,pos) = (val))
29 WVAL_LH(__u8
* buf
, int pos
)
31 return PVAL(buf
, pos
) | PVAL(buf
, pos
+ 1) << 8;
34 DVAL_LH(__u8
* buf
, int pos
)
36 return WVAL_LH(buf
, pos
) | WVAL_LH(buf
, pos
+ 2) << 16;
39 WSET_LH(__u8
* buf
, int pos
, __u16 val
)
41 BSET(buf
, pos
, val
& 0xff);
42 BSET(buf
, pos
+ 1, val
>> 8);
45 DSET_LH(__u8
* buf
, int pos
, __u32 val
)
47 WSET_LH(buf
, pos
, val
& 0xffff);
48 WSET_LH(buf
, pos
+ 2, val
>> 16);
51 #define GET_LE32(p) DVAL_LH(p,0)
52 #define PUT_LE32(p,v) DSET_LH(p,0,v)
55 static void nwsign(char *r_data1
, char *r_data2
, char *outdata
) {
57 unsigned int w0
,w1
,w2
,w3
;
58 static int rbit
[4]={0, 2, 1, 3};
60 unsigned int *data2
=(int *)r_data2
;
62 unsigned int data2
[16];
64 data2
[i
]=GET_LE32(r_data2
+(i
<<2));
67 w1
=GET_LE32(r_data1
+4);
68 w2
=GET_LE32(r_data1
+8);
69 w3
=GET_LE32(r_data1
+12);
71 w0
=rol32(w0
+ ((w1
& w2
) | ((~w1
) & w3
)) + data2
[i
+0],3);
72 w3
=rol32(w3
+ ((w0
& w1
) | ((~w0
) & w2
)) + data2
[i
+1],7);
73 w2
=rol32(w2
+ ((w3
& w0
) | ((~w3
) & w1
)) + data2
[i
+2],11);
74 w1
=rol32(w1
+ ((w2
& w3
) | ((~w2
) & w0
)) + data2
[i
+3],19);
77 w0
=rol32(w0
+ (((w2
| w3
) & w1
) | (w2
& w3
)) + 0x5a827999 + data2
[i
+0],3);
78 w3
=rol32(w3
+ (((w1
| w2
) & w0
) | (w1
& w2
)) + 0x5a827999 + data2
[i
+4],5);
79 w2
=rol32(w2
+ (((w0
| w1
) & w3
) | (w0
& w1
)) + 0x5a827999 + data2
[i
+8],9);
80 w1
=rol32(w1
+ (((w3
| w0
) & w2
) | (w3
& w0
)) + 0x5a827999 + data2
[i
+12],13);
83 w0
=rol32(w0
+ ((w1
^ w2
) ^ w3
) + 0x6ed9eba1 + data2
[rbit
[i
]+0],3);
84 w3
=rol32(w3
+ ((w0
^ w1
) ^ w2
) + 0x6ed9eba1 + data2
[rbit
[i
]+8],9);
85 w2
=rol32(w2
+ ((w3
^ w0
) ^ w1
) + 0x6ed9eba1 + data2
[rbit
[i
]+4],11);
86 w1
=rol32(w1
+ ((w2
^ w3
) ^ w0
) + 0x6ed9eba1 + data2
[rbit
[i
]+12],15);
88 PUT_LE32(outdata
,(w0
+GET_LE32(r_data1
)) & 0xffffffff);
89 PUT_LE32(outdata
+4,(w1
+GET_LE32(r_data1
+4)) & 0xffffffff);
90 PUT_LE32(outdata
+8,(w2
+GET_LE32(r_data1
+8)) & 0xffffffff);
91 PUT_LE32(outdata
+12,(w3
+GET_LE32(r_data1
+12)) & 0xffffffff);
94 /* Make a signature for the current packet and add it at the end of the */
96 void __sign_packet(struct ncp_server
*server
, const char *packet
, size_t size
, __u32 totalsize
, void *sign_buff
) {
97 unsigned char data
[64];
99 memcpy(data
, server
->sign_root
, 8);
100 *(__u32
*)(data
+ 8) = totalsize
;
102 memcpy(data
+ 12, packet
, size
);
103 memset(data
+ 12 + size
, 0, 52 - size
);
105 memcpy(data
+ 12, packet
, 52);
107 nwsign(server
->sign_last
, data
, server
->sign_last
);
108 memcpy(sign_buff
, server
->sign_last
, 8);
111 int sign_verify_reply(struct ncp_server
*server
, const char *packet
, size_t size
, __u32 totalsize
, const void *sign_buff
) {
112 unsigned char data
[64];
113 unsigned char hash
[16];
115 memcpy(data
, server
->sign_root
, 8);
116 *(__u32
*)(data
+ 8) = totalsize
;
118 memcpy(data
+ 12, packet
, size
);
119 memset(data
+ 12 + size
, 0, 52 - size
);
121 memcpy(data
+ 12, packet
, 52);
123 nwsign(server
->sign_last
, data
, hash
);
124 return memcmp(sign_buff
, hash
, 8);
127 #endif /* CONFIG_NCPFS_PACKET_SIGNING */