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>
15 #include "ncpsign_kernel.h"
17 /* i386: 32-bit, little endian, handles mis-alignment */
19 #define GET_LE32(p) (*(const int *)(p))
20 #define PUT_LE32(p,v) { *(int *)(p)=v; }
22 /* from include/ncplib.h */
23 #define BVAL(buf,pos) (((const __u8 *)(buf))[pos])
24 #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
25 #define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val))
28 WVAL_LH(const __u8
* buf
, int pos
)
30 return PVAL(buf
, pos
) | PVAL(buf
, pos
+ 1) << 8;
33 DVAL_LH(const __u8
* buf
, int pos
)
35 return WVAL_LH(buf
, pos
) | WVAL_LH(buf
, pos
+ 2) << 16;
38 WSET_LH(__u8
* buf
, int pos
, __u16 val
)
40 BSET(buf
, pos
, val
& 0xff);
41 BSET(buf
, pos
+ 1, val
>> 8);
44 DSET_LH(__u8
* buf
, int pos
, __u32 val
)
46 WSET_LH(buf
, pos
, val
& 0xffff);
47 WSET_LH(buf
, pos
+ 2, val
>> 16);
50 #define GET_LE32(p) DVAL_LH(p,0)
51 #define PUT_LE32(p,v) DSET_LH(p,0,v)
54 static void nwsign(char *r_data1
, char *r_data2
, char *outdata
) {
56 unsigned int w0
,w1
,w2
,w3
;
57 static int rbit
[4]={0, 2, 1, 3};
59 unsigned int *data2
=(unsigned int *)r_data2
;
61 unsigned int data2
[16];
63 data2
[i
]=GET_LE32(r_data2
+(i
<<2));
66 w1
=GET_LE32(r_data1
+4);
67 w2
=GET_LE32(r_data1
+8);
68 w3
=GET_LE32(r_data1
+12);
70 w0
=rol32(w0
+ ((w1
& w2
) | ((~w1
) & w3
)) + data2
[i
+0],3);
71 w3
=rol32(w3
+ ((w0
& w1
) | ((~w0
) & w2
)) + data2
[i
+1],7);
72 w2
=rol32(w2
+ ((w3
& w0
) | ((~w3
) & w1
)) + data2
[i
+2],11);
73 w1
=rol32(w1
+ ((w2
& w3
) | ((~w2
) & w0
)) + data2
[i
+3],19);
76 w0
=rol32(w0
+ (((w2
| w3
) & w1
) | (w2
& w3
)) + 0x5a827999 + data2
[i
+0],3);
77 w3
=rol32(w3
+ (((w1
| w2
) & w0
) | (w1
& w2
)) + 0x5a827999 + data2
[i
+4],5);
78 w2
=rol32(w2
+ (((w0
| w1
) & w3
) | (w0
& w1
)) + 0x5a827999 + data2
[i
+8],9);
79 w1
=rol32(w1
+ (((w3
| w0
) & w2
) | (w3
& w0
)) + 0x5a827999 + data2
[i
+12],13);
82 w0
=rol32(w0
+ ((w1
^ w2
) ^ w3
) + 0x6ed9eba1 + data2
[rbit
[i
]+0],3);
83 w3
=rol32(w3
+ ((w0
^ w1
) ^ w2
) + 0x6ed9eba1 + data2
[rbit
[i
]+8],9);
84 w2
=rol32(w2
+ ((w3
^ w0
) ^ w1
) + 0x6ed9eba1 + data2
[rbit
[i
]+4],11);
85 w1
=rol32(w1
+ ((w2
^ w3
) ^ w0
) + 0x6ed9eba1 + data2
[rbit
[i
]+12],15);
87 PUT_LE32(outdata
,(w0
+GET_LE32(r_data1
)) & 0xffffffff);
88 PUT_LE32(outdata
+4,(w1
+GET_LE32(r_data1
+4)) & 0xffffffff);
89 PUT_LE32(outdata
+8,(w2
+GET_LE32(r_data1
+8)) & 0xffffffff);
90 PUT_LE32(outdata
+12,(w3
+GET_LE32(r_data1
+12)) & 0xffffffff);
93 /* Make a signature for the current packet and add it at the end of the */
95 void __sign_packet(struct ncp_server
*server
, const char *packet
, size_t size
, __u32 totalsize
, void *sign_buff
) {
96 unsigned char data
[64];
98 memcpy(data
, server
->sign_root
, 8);
99 *(__u32
*)(data
+ 8) = totalsize
;
101 memcpy(data
+ 12, packet
, size
);
102 memset(data
+ 12 + size
, 0, 52 - size
);
104 memcpy(data
+ 12, packet
, 52);
106 nwsign(server
->sign_last
, data
, server
->sign_last
);
107 memcpy(sign_buff
, server
->sign_last
, 8);
110 int sign_verify_reply(struct ncp_server
*server
, const char *packet
, size_t size
, __u32 totalsize
, const void *sign_buff
) {
111 unsigned char data
[64];
112 unsigned char hash
[16];
114 memcpy(data
, server
->sign_root
, 8);
115 *(__u32
*)(data
+ 8) = totalsize
;
117 memcpy(data
+ 12, packet
, size
);
118 memset(data
+ 12 + size
, 0, 52 - size
);
120 memcpy(data
+ 12, packet
, 52);
122 nwsign(server
->sign_last
, data
, hash
);
123 return memcmp(sign_buff
, hash
, 8);
126 #endif /* CONFIG_NCPFS_PACKET_SIGNING */