4 * Arne de Bruijn (arne@knoware.nl), 1997
9 #ifdef CONFIG_NCPFS_PACKET_SIGNING
11 #include <linux/string.h>
12 #include <linux/ncp.h>
13 #include <linux/bitops.h>
14 #include "ncpsign_kernel.h"
16 /* i386: 32-bit, little endian, handles mis-alignment */
18 #define GET_LE32(p) (*(int *)(p))
19 #define PUT_LE32(p,v) { *(int *)(p)=v; }
21 /* from include/ncplib.h */
22 #define BVAL(buf,pos) (((__u8 *)(buf))[pos])
23 #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
24 #define BSET(buf,pos,val) (BVAL(buf,pos) = (val))
27 WVAL_LH(__u8
* buf
, int pos
)
29 return PVAL(buf
, pos
) | PVAL(buf
, pos
+ 1) << 8;
32 DVAL_LH(__u8
* buf
, int pos
)
34 return WVAL_LH(buf
, pos
) | WVAL_LH(buf
, pos
+ 2) << 16;
37 WSET_LH(__u8
* buf
, int pos
, __u16 val
)
39 BSET(buf
, pos
, val
& 0xff);
40 BSET(buf
, pos
+ 1, val
>> 8);
43 DSET_LH(__u8
* buf
, int pos
, __u32 val
)
45 WSET_LH(buf
, pos
, val
& 0xffff);
46 WSET_LH(buf
, pos
+ 2, val
>> 16);
49 #define GET_LE32(p) DVAL_LH(p,0)
50 #define PUT_LE32(p,v) DSET_LH(p,0,v)
53 static void nwsign(char *r_data1
, char *r_data2
, char *outdata
) {
55 unsigned int w0
,w1
,w2
,w3
;
56 static int rbit
[4]={0, 2, 1, 3};
58 unsigned int *data2
=(int *)r_data2
;
60 unsigned int data2
[16];
62 data2
[i
]=GET_LE32(r_data2
+(i
<<2));
65 w1
=GET_LE32(r_data1
+4);
66 w2
=GET_LE32(r_data1
+8);
67 w3
=GET_LE32(r_data1
+12);
69 w0
=rol32(w0
+ ((w1
& w2
) | ((~w1
) & w3
)) + data2
[i
+0],3);
70 w3
=rol32(w3
+ ((w0
& w1
) | ((~w0
) & w2
)) + data2
[i
+1],7);
71 w2
=rol32(w2
+ ((w3
& w0
) | ((~w3
) & w1
)) + data2
[i
+2],11);
72 w1
=rol32(w1
+ ((w2
& w3
) | ((~w2
) & w0
)) + data2
[i
+3],19);
75 w0
=rol32(w0
+ (((w2
| w3
) & w1
) | (w2
& w3
)) + 0x5a827999 + data2
[i
+0],3);
76 w3
=rol32(w3
+ (((w1
| w2
) & w0
) | (w1
& w2
)) + 0x5a827999 + data2
[i
+4],5);
77 w2
=rol32(w2
+ (((w0
| w1
) & w3
) | (w0
& w1
)) + 0x5a827999 + data2
[i
+8],9);
78 w1
=rol32(w1
+ (((w3
| w0
) & w2
) | (w3
& w0
)) + 0x5a827999 + data2
[i
+12],13);
81 w0
=rol32(w0
+ ((w1
^ w2
) ^ w3
) + 0x6ed9eba1 + data2
[rbit
[i
]+0],3);
82 w3
=rol32(w3
+ ((w0
^ w1
) ^ w2
) + 0x6ed9eba1 + data2
[rbit
[i
]+8],9);
83 w2
=rol32(w2
+ ((w3
^ w0
) ^ w1
) + 0x6ed9eba1 + data2
[rbit
[i
]+4],11);
84 w1
=rol32(w1
+ ((w2
^ w3
) ^ w0
) + 0x6ed9eba1 + data2
[rbit
[i
]+12],15);
86 PUT_LE32(outdata
,(w0
+GET_LE32(r_data1
)) & 0xffffffff);
87 PUT_LE32(outdata
+4,(w1
+GET_LE32(r_data1
+4)) & 0xffffffff);
88 PUT_LE32(outdata
+8,(w2
+GET_LE32(r_data1
+8)) & 0xffffffff);
89 PUT_LE32(outdata
+12,(w3
+GET_LE32(r_data1
+12)) & 0xffffffff);
92 /* Make a signature for the current packet and add it at the end of the */
94 void __sign_packet(struct ncp_server
*server
, const char *packet
, size_t size
, __u32 totalsize
, void *sign_buff
) {
95 unsigned char data
[64];
97 memcpy(data
, server
->sign_root
, 8);
98 *(__u32
*)(data
+ 8) = totalsize
;
100 memcpy(data
+ 12, packet
, size
);
101 memset(data
+ 12 + size
, 0, 52 - size
);
103 memcpy(data
+ 12, packet
, 52);
105 nwsign(server
->sign_last
, data
, server
->sign_last
);
106 memcpy(sign_buff
, server
->sign_last
, 8);
109 int sign_verify_reply(struct ncp_server
*server
, const char *packet
, size_t size
, __u32 totalsize
, const void *sign_buff
) {
110 unsigned char data
[64];
111 unsigned char hash
[16];
113 memcpy(data
, server
->sign_root
, 8);
114 *(__u32
*)(data
+ 8) = totalsize
;
116 memcpy(data
+ 12, packet
, size
);
117 memset(data
+ 12 + size
, 0, 52 - size
);
119 memcpy(data
+ 12, packet
, 52);
121 nwsign(server
->sign_last
, data
, hash
);
122 return memcmp(sign_buff
, hash
, 8);
125 #endif /* CONFIG_NCPFS_PACKET_SIGNING */