xref: /plan9/sys/src/cmd/ssh1/msg.c (revision 63afb9a5d3f910047231762bcce0ee49fed3d07c)
1*63afb9a5SDavid du Colombier #include "ssh.h"
2*63afb9a5SDavid du Colombier 
3*63afb9a5SDavid du Colombier static ulong sum32(ulong, void*, int);
4*63afb9a5SDavid du Colombier 
5*63afb9a5SDavid du Colombier char *msgnames[] =
6*63afb9a5SDavid du Colombier {
7*63afb9a5SDavid du Colombier /* 0 */
8*63afb9a5SDavid du Colombier 	"SSH_MSG_NONE",
9*63afb9a5SDavid du Colombier 	"SSH_MSG_DISCONNECT",
10*63afb9a5SDavid du Colombier 	"SSH_SMSG_PUBLIC_KEY",
11*63afb9a5SDavid du Colombier 	"SSH_CMSG_SESSION_KEY",
12*63afb9a5SDavid du Colombier 	"SSH_CMSG_USER",
13*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_RHOSTS",
14*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_RSA",
15*63afb9a5SDavid du Colombier 	"SSH_SMSG_AUTH_RSA_CHALLENGE",
16*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_RSA_RESPONSE",
17*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_PASSWORD",
18*63afb9a5SDavid du Colombier 
19*63afb9a5SDavid du Colombier /* 10 */
20*63afb9a5SDavid du Colombier 	"SSH_CMSG_REQUEST_PTY",
21*63afb9a5SDavid du Colombier 	"SSH_CMSG_WINDOW_SIZE",
22*63afb9a5SDavid du Colombier 	"SSH_CMSG_EXEC_SHELL",
23*63afb9a5SDavid du Colombier 	"SSH_CMSG_EXEC_CMD",
24*63afb9a5SDavid du Colombier 	"SSH_SMSG_SUCCESS",
25*63afb9a5SDavid du Colombier 	"SSH_SMSG_FAILURE",
26*63afb9a5SDavid du Colombier 	"SSH_CMSG_STDIN_DATA",
27*63afb9a5SDavid du Colombier 	"SSH_SMSG_STDOUT_DATA",
28*63afb9a5SDavid du Colombier 	"SSH_SMSG_STDERR_DATA",
29*63afb9a5SDavid du Colombier 	"SSH_CMSG_EOF",
30*63afb9a5SDavid du Colombier 
31*63afb9a5SDavid du Colombier /* 20 */
32*63afb9a5SDavid du Colombier 	"SSH_SMSG_EXITSTATUS",
33*63afb9a5SDavid du Colombier 	"SSH_MSG_CHANNEL_OPEN_CONFIRMATION",
34*63afb9a5SDavid du Colombier 	"SSH_MSG_CHANNEL_OPEN_FAILURE",
35*63afb9a5SDavid du Colombier 	"SSH_MSG_CHANNEL_DATA",
36*63afb9a5SDavid du Colombier 	"SSH_MSG_CHANNEL_INPUT_EOF",
37*63afb9a5SDavid du Colombier 	"SSH_MSG_CHANNEL_OUTPUT_CLOSED",
38*63afb9a5SDavid du Colombier 	"SSH_MSG_UNIX_DOMAIN_X11_FORWARDING (obsolete)",
39*63afb9a5SDavid du Colombier 	"SSH_SMSG_X11_OPEN",
40*63afb9a5SDavid du Colombier 	"SSH_CMSG_PORT_FORWARD_REQUEST",
41*63afb9a5SDavid du Colombier 	"SSH_MSG_PORT_OPEN",
42*63afb9a5SDavid du Colombier 
43*63afb9a5SDavid du Colombier /* 30 */
44*63afb9a5SDavid du Colombier 	"SSH_CMSG_AGENT_REQUEST_FORWARDING",
45*63afb9a5SDavid du Colombier 	"SSH_SMSG_AGENT_OPEN",
46*63afb9a5SDavid du Colombier 	"SSH_MSG_IGNORE",
47*63afb9a5SDavid du Colombier 	"SSH_CMSG_EXIT_CONFIRMATION",
48*63afb9a5SDavid du Colombier 	"SSH_CMSG_X11_REQUEST_FORWARDING",
49*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_RHOSTS_RSA",
50*63afb9a5SDavid du Colombier 	"SSH_MSG_DEBUG",
51*63afb9a5SDavid du Colombier 	"SSH_CMSG_REQUEST_COMPRESSION",
52*63afb9a5SDavid du Colombier 	"SSH_CMSG_MAX_PACKET_SIZE",
53*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_TIS",
54*63afb9a5SDavid du Colombier 
55*63afb9a5SDavid du Colombier /* 40 */
56*63afb9a5SDavid du Colombier 	"SSH_SMSG_AUTH_TIS_CHALLENGE",
57*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_TIS_RESPONSE",
58*63afb9a5SDavid du Colombier 	"SSH_CMSG_AUTH_KERBEROS",
59*63afb9a5SDavid du Colombier 	"SSH_SMSG_AUTH_KERBEROS_RESPONSE",
60*63afb9a5SDavid du Colombier 	"SSH_CMSG_HAVE_KERBEROS_TGT"
61*63afb9a5SDavid du Colombier };
62*63afb9a5SDavid du Colombier 
63*63afb9a5SDavid du Colombier void
badmsg(Msg * m,int want)64*63afb9a5SDavid du Colombier badmsg(Msg *m, int want)
65*63afb9a5SDavid du Colombier {
66*63afb9a5SDavid du Colombier 	char *s, buf[20+ERRMAX];
67*63afb9a5SDavid du Colombier 
68*63afb9a5SDavid du Colombier 	if(m==nil){
69*63afb9a5SDavid du Colombier 		snprint(buf, sizeof buf, "<early eof: %r>");
70*63afb9a5SDavid du Colombier 		s = buf;
71*63afb9a5SDavid du Colombier 	}else{
72*63afb9a5SDavid du Colombier 		snprint(buf, sizeof buf, "<unknown type %d>", m->type);
73*63afb9a5SDavid du Colombier 		s = buf;
74*63afb9a5SDavid du Colombier 		if(0 <= m->type && m->type < nelem(msgnames))
75*63afb9a5SDavid du Colombier 			s = msgnames[m->type];
76*63afb9a5SDavid du Colombier 	}
77*63afb9a5SDavid du Colombier 	if(want)
78*63afb9a5SDavid du Colombier 		error("got %s message expecting %s", s, msgnames[want]);
79*63afb9a5SDavid du Colombier 	error("got unexpected %s message", s);
80*63afb9a5SDavid du Colombier }
81*63afb9a5SDavid du Colombier 
82*63afb9a5SDavid du Colombier Msg*
allocmsg(Conn * c,int type,int len)83*63afb9a5SDavid du Colombier allocmsg(Conn *c, int type, int len)
84*63afb9a5SDavid du Colombier {
85*63afb9a5SDavid du Colombier 	uchar *p;
86*63afb9a5SDavid du Colombier 	Msg *m;
87*63afb9a5SDavid du Colombier 
88*63afb9a5SDavid du Colombier 	if(len > 256*1024)
89*63afb9a5SDavid du Colombier 		abort();
90*63afb9a5SDavid du Colombier 
91*63afb9a5SDavid du Colombier 	m = (Msg*)emalloc(sizeof(Msg)+4+8+1+len+4);
92*63afb9a5SDavid du Colombier 	setmalloctag(m, getcallerpc(&c));
93*63afb9a5SDavid du Colombier 	p = (uchar*)&m[1];
94*63afb9a5SDavid du Colombier 	m->c = c;
95*63afb9a5SDavid du Colombier 	m->bp = p;
96*63afb9a5SDavid du Colombier 	m->ep = p+len;
97*63afb9a5SDavid du Colombier 	m->wp = p;
98*63afb9a5SDavid du Colombier 	m->type = type;
99*63afb9a5SDavid du Colombier 	return m;
100*63afb9a5SDavid du Colombier }
101*63afb9a5SDavid du Colombier 
102*63afb9a5SDavid du Colombier void
unrecvmsg(Conn * c,Msg * m)103*63afb9a5SDavid du Colombier unrecvmsg(Conn *c, Msg *m)
104*63afb9a5SDavid du Colombier {
105*63afb9a5SDavid du Colombier 	debug(DBG_PROTO, "unreceived %s len %ld\n", msgnames[m->type], m->ep - m->rp);
106*63afb9a5SDavid du Colombier 	free(c->unget);
107*63afb9a5SDavid du Colombier 	c->unget = m;
108*63afb9a5SDavid du Colombier }
109*63afb9a5SDavid du Colombier 
110*63afb9a5SDavid du Colombier static Msg*
recvmsg0(Conn * c)111*63afb9a5SDavid du Colombier recvmsg0(Conn *c)
112*63afb9a5SDavid du Colombier {
113*63afb9a5SDavid du Colombier 	int pad;
114*63afb9a5SDavid du Colombier 	uchar *p, buf[4];
115*63afb9a5SDavid du Colombier 	ulong crc, crc0, len;
116*63afb9a5SDavid du Colombier 	Msg *m;
117*63afb9a5SDavid du Colombier 
118*63afb9a5SDavid du Colombier 	if(c->unget){
119*63afb9a5SDavid du Colombier 		m = c->unget;
120*63afb9a5SDavid du Colombier 		c->unget = nil;
121*63afb9a5SDavid du Colombier 		return m;
122*63afb9a5SDavid du Colombier 	}
123*63afb9a5SDavid du Colombier 
124*63afb9a5SDavid du Colombier 	if(readn(c->fd[0], buf, 4) != 4){
125*63afb9a5SDavid du Colombier 		werrstr("short net read: %r");
126*63afb9a5SDavid du Colombier 		return nil;
127*63afb9a5SDavid du Colombier 	}
128*63afb9a5SDavid du Colombier 
129*63afb9a5SDavid du Colombier 	len = LONG(buf);
130*63afb9a5SDavid du Colombier 	if(len > 256*1024){
131*63afb9a5SDavid du Colombier 		werrstr("packet size far too big: %.8lux", len);
132*63afb9a5SDavid du Colombier 		return nil;
133*63afb9a5SDavid du Colombier 	}
134*63afb9a5SDavid du Colombier 
135*63afb9a5SDavid du Colombier 	pad = 8 - len%8;
136*63afb9a5SDavid du Colombier 
137*63afb9a5SDavid du Colombier 	m = (Msg*)emalloc(sizeof(Msg)+pad+len);
138*63afb9a5SDavid du Colombier 	setmalloctag(m, getcallerpc(&c));
139*63afb9a5SDavid du Colombier 	m->c = c;
140*63afb9a5SDavid du Colombier 	m->bp = (uchar*)&m[1];
141*63afb9a5SDavid du Colombier 	m->ep = m->bp + pad+len-4;	/* -4: don't include crc */
142*63afb9a5SDavid du Colombier 	m->rp = m->bp;
143*63afb9a5SDavid du Colombier 
144*63afb9a5SDavid du Colombier 	if(readn(c->fd[0], m->bp, pad+len) != pad+len){
145*63afb9a5SDavid du Colombier 		werrstr("short net read: %r");
146*63afb9a5SDavid du Colombier 		free(m);
147*63afb9a5SDavid du Colombier 		return nil;
148*63afb9a5SDavid du Colombier 	}
149*63afb9a5SDavid du Colombier 
150*63afb9a5SDavid du Colombier 	if(c->cipher)
151*63afb9a5SDavid du Colombier 		c->cipher->decrypt(c->cstate, m->bp, len+pad);
152*63afb9a5SDavid du Colombier 
153*63afb9a5SDavid du Colombier 	crc = sum32(0, m->bp, pad+len-4);
154*63afb9a5SDavid du Colombier 	p = m->bp + pad+len-4;
155*63afb9a5SDavid du Colombier 	crc0 = LONG(p);
156*63afb9a5SDavid du Colombier 	if(crc != crc0){
157*63afb9a5SDavid du Colombier 		werrstr("bad crc %#lux != %#lux (packet length %lud)", crc, crc0, len);
158*63afb9a5SDavid du Colombier 		free(m);
159*63afb9a5SDavid du Colombier 		return nil;
160*63afb9a5SDavid du Colombier 	}
161*63afb9a5SDavid du Colombier 
162*63afb9a5SDavid du Colombier 	m->rp += pad;
163*63afb9a5SDavid du Colombier 	m->type = *m->rp++;
164*63afb9a5SDavid du Colombier 
165*63afb9a5SDavid du Colombier 	return m;
166*63afb9a5SDavid du Colombier }
167*63afb9a5SDavid du Colombier 
168*63afb9a5SDavid du Colombier Msg*
recvmsg(Conn * c,int type)169*63afb9a5SDavid du Colombier recvmsg(Conn *c, int type)
170*63afb9a5SDavid du Colombier {
171*63afb9a5SDavid du Colombier 	Msg *m;
172*63afb9a5SDavid du Colombier 
173*63afb9a5SDavid du Colombier 	while((m = recvmsg0(c)) != nil){
174*63afb9a5SDavid du Colombier 		debug(DBG_PROTO, "received %s len %ld\n", msgnames[m->type], m->ep - m->rp);
175*63afb9a5SDavid du Colombier 		if(m->type != SSH_MSG_DEBUG && m->type != SSH_MSG_IGNORE)
176*63afb9a5SDavid du Colombier 			break;
177*63afb9a5SDavid du Colombier 		if(m->type == SSH_MSG_DEBUG)
178*63afb9a5SDavid du Colombier 			debug(DBG_PROTO, "remote DEBUG: %s\n", getstring(m));
179*63afb9a5SDavid du Colombier 		free(m);
180*63afb9a5SDavid du Colombier 	}
181*63afb9a5SDavid du Colombier 	if(type == 0){
182*63afb9a5SDavid du Colombier 		/* no checking */
183*63afb9a5SDavid du Colombier 	}else if(type == -1){
184*63afb9a5SDavid du Colombier 		/* must not be nil */
185*63afb9a5SDavid du Colombier 		if(m == nil)
186*63afb9a5SDavid du Colombier 			error(Ehangup);
187*63afb9a5SDavid du Colombier 	}else{
188*63afb9a5SDavid du Colombier 		/* must be given type */
189*63afb9a5SDavid du Colombier 		if(m==nil || m->type!=type)
190*63afb9a5SDavid du Colombier 			badmsg(m, type);
191*63afb9a5SDavid du Colombier 	}
192*63afb9a5SDavid du Colombier 	setmalloctag(m, getcallerpc(&c));
193*63afb9a5SDavid du Colombier 	return m;
194*63afb9a5SDavid du Colombier }
195*63afb9a5SDavid du Colombier 
196*63afb9a5SDavid du Colombier int
sendmsg(Msg * m)197*63afb9a5SDavid du Colombier sendmsg(Msg *m)
198*63afb9a5SDavid du Colombier {
199*63afb9a5SDavid du Colombier 	int i, pad;
200*63afb9a5SDavid du Colombier 	uchar *p;
201*63afb9a5SDavid du Colombier 	ulong datalen, len, crc;
202*63afb9a5SDavid du Colombier 	Conn *c;
203*63afb9a5SDavid du Colombier 
204*63afb9a5SDavid du Colombier 	datalen = m->wp - m->bp;
205*63afb9a5SDavid du Colombier 	len = datalen + 5;
206*63afb9a5SDavid du Colombier 	pad = 8 - len%8;
207*63afb9a5SDavid du Colombier 
208*63afb9a5SDavid du Colombier 	debug(DBG_PROTO, "sending %s len %lud\n", msgnames[m->type], datalen);
209*63afb9a5SDavid du Colombier 
210*63afb9a5SDavid du Colombier 	p = m->bp;
211*63afb9a5SDavid du Colombier 	memmove(m->bp+4+pad+1, m->bp, datalen);	/* slide data to correct position */
212*63afb9a5SDavid du Colombier 
213*63afb9a5SDavid du Colombier 	PLONG(p, len);
214*63afb9a5SDavid du Colombier 	p += 4;
215*63afb9a5SDavid du Colombier 
216*63afb9a5SDavid du Colombier 	if(m->c->cstate){
217*63afb9a5SDavid du Colombier 		for(i=0; i<pad; i++)
218*63afb9a5SDavid du Colombier 			*p++ = fastrand();
219*63afb9a5SDavid du Colombier 	}else{
220*63afb9a5SDavid du Colombier 		memset(p, 0, pad);
221*63afb9a5SDavid du Colombier 		p += pad;
222*63afb9a5SDavid du Colombier 	}
223*63afb9a5SDavid du Colombier 
224*63afb9a5SDavid du Colombier 	*p++ = m->type;
225*63afb9a5SDavid du Colombier 
226*63afb9a5SDavid du Colombier 	/* data already in position */
227*63afb9a5SDavid du Colombier 	p += datalen;
228*63afb9a5SDavid du Colombier 
229*63afb9a5SDavid du Colombier 	crc = sum32(0, m->bp+4, pad+1+datalen);
230*63afb9a5SDavid du Colombier 	PLONG(p, crc);
231*63afb9a5SDavid du Colombier 	p += 4;
232*63afb9a5SDavid du Colombier 
233*63afb9a5SDavid du Colombier 	c = m->c;
234*63afb9a5SDavid du Colombier 	qlock(c);
235*63afb9a5SDavid du Colombier 	if(c->cstate)
236*63afb9a5SDavid du Colombier 		c->cipher->encrypt(c->cstate, m->bp+4, len+pad);
237*63afb9a5SDavid du Colombier 
238*63afb9a5SDavid du Colombier 	if(write(c->fd[1], m->bp, p - m->bp) != p-m->bp){
239*63afb9a5SDavid du Colombier 		qunlock(c);
240*63afb9a5SDavid du Colombier 		free(m);
241*63afb9a5SDavid du Colombier 		return -1;
242*63afb9a5SDavid du Colombier 	}
243*63afb9a5SDavid du Colombier 	qunlock(c);
244*63afb9a5SDavid du Colombier 	free(m);
245*63afb9a5SDavid du Colombier 	return 0;
246*63afb9a5SDavid du Colombier }
247*63afb9a5SDavid du Colombier 
248*63afb9a5SDavid du Colombier uchar
getbyte(Msg * m)249*63afb9a5SDavid du Colombier getbyte(Msg *m)
250*63afb9a5SDavid du Colombier {
251*63afb9a5SDavid du Colombier 	if(m->rp >= m->ep)
252*63afb9a5SDavid du Colombier 		error(Edecode);
253*63afb9a5SDavid du Colombier 	return *m->rp++;
254*63afb9a5SDavid du Colombier }
255*63afb9a5SDavid du Colombier 
256*63afb9a5SDavid du Colombier ushort
getshort(Msg * m)257*63afb9a5SDavid du Colombier getshort(Msg *m)
258*63afb9a5SDavid du Colombier {
259*63afb9a5SDavid du Colombier 	ushort x;
260*63afb9a5SDavid du Colombier 
261*63afb9a5SDavid du Colombier 	if(m->rp+2 > m->ep)
262*63afb9a5SDavid du Colombier 		error(Edecode);
263*63afb9a5SDavid du Colombier 
264*63afb9a5SDavid du Colombier 	x = SHORT(m->rp);
265*63afb9a5SDavid du Colombier 	m->rp += 2;
266*63afb9a5SDavid du Colombier 	return x;
267*63afb9a5SDavid du Colombier }
268*63afb9a5SDavid du Colombier 
269*63afb9a5SDavid du Colombier ulong
getlong(Msg * m)270*63afb9a5SDavid du Colombier getlong(Msg *m)
271*63afb9a5SDavid du Colombier {
272*63afb9a5SDavid du Colombier 	ulong x;
273*63afb9a5SDavid du Colombier 
274*63afb9a5SDavid du Colombier 	if(m->rp+4 > m->ep)
275*63afb9a5SDavid du Colombier 		error(Edecode);
276*63afb9a5SDavid du Colombier 
277*63afb9a5SDavid du Colombier 	x = LONG(m->rp);
278*63afb9a5SDavid du Colombier 	m->rp += 4;
279*63afb9a5SDavid du Colombier 	return x;
280*63afb9a5SDavid du Colombier }
281*63afb9a5SDavid du Colombier 
282*63afb9a5SDavid du Colombier char*
getstring(Msg * m)283*63afb9a5SDavid du Colombier getstring(Msg *m)
284*63afb9a5SDavid du Colombier {
285*63afb9a5SDavid du Colombier 	char *p;
286*63afb9a5SDavid du Colombier 	ulong len;
287*63afb9a5SDavid du Colombier 
288*63afb9a5SDavid du Colombier 	/* overwrites length to make room for NUL */
289*63afb9a5SDavid du Colombier 	len = getlong(m);
290*63afb9a5SDavid du Colombier 	if(m->rp+len > m->ep)
291*63afb9a5SDavid du Colombier 		error(Edecode);
292*63afb9a5SDavid du Colombier 	p = (char*)m->rp-1;
293*63afb9a5SDavid du Colombier 	memmove(p, m->rp, len);
294*63afb9a5SDavid du Colombier 	p[len] = '\0';
295*63afb9a5SDavid du Colombier 	return p;
296*63afb9a5SDavid du Colombier }
297*63afb9a5SDavid du Colombier 
298*63afb9a5SDavid du Colombier void*
getbytes(Msg * m,int n)299*63afb9a5SDavid du Colombier getbytes(Msg *m, int n)
300*63afb9a5SDavid du Colombier {
301*63afb9a5SDavid du Colombier 	uchar *p;
302*63afb9a5SDavid du Colombier 
303*63afb9a5SDavid du Colombier 	if(m->rp+n > m->ep)
304*63afb9a5SDavid du Colombier 		error(Edecode);
305*63afb9a5SDavid du Colombier 	p = m->rp;
306*63afb9a5SDavid du Colombier 	m->rp += n;
307*63afb9a5SDavid du Colombier 	return p;
308*63afb9a5SDavid du Colombier }
309*63afb9a5SDavid du Colombier 
310*63afb9a5SDavid du Colombier mpint*
getmpint(Msg * m)311*63afb9a5SDavid du Colombier getmpint(Msg *m)
312*63afb9a5SDavid du Colombier {
313*63afb9a5SDavid du Colombier 	int n;
314*63afb9a5SDavid du Colombier 
315*63afb9a5SDavid du Colombier 	n = (getshort(m)+7)/8;	/* getshort returns # bits */
316*63afb9a5SDavid du Colombier 	return betomp(getbytes(m, n), n, nil);
317*63afb9a5SDavid du Colombier }
318*63afb9a5SDavid du Colombier 
319*63afb9a5SDavid du Colombier RSApub*
getRSApub(Msg * m)320*63afb9a5SDavid du Colombier getRSApub(Msg *m)
321*63afb9a5SDavid du Colombier {
322*63afb9a5SDavid du Colombier 	RSApub *key;
323*63afb9a5SDavid du Colombier 
324*63afb9a5SDavid du Colombier 	getlong(m);
325*63afb9a5SDavid du Colombier 	key = rsapuballoc();
326*63afb9a5SDavid du Colombier 	if(key == nil)
327*63afb9a5SDavid du Colombier 		error(Ememory);
328*63afb9a5SDavid du Colombier 	key->ek = getmpint(m);
329*63afb9a5SDavid du Colombier 	key->n = getmpint(m);
330*63afb9a5SDavid du Colombier 	setmalloctag(key, getcallerpc(&m));
331*63afb9a5SDavid du Colombier 	return key;
332*63afb9a5SDavid du Colombier }
333*63afb9a5SDavid du Colombier 
334*63afb9a5SDavid du Colombier void
putbyte(Msg * m,uchar x)335*63afb9a5SDavid du Colombier putbyte(Msg *m, uchar x)
336*63afb9a5SDavid du Colombier {
337*63afb9a5SDavid du Colombier 	if(m->wp >= m->ep)
338*63afb9a5SDavid du Colombier 		error(Eencode);
339*63afb9a5SDavid du Colombier 	*m->wp++ = x;
340*63afb9a5SDavid du Colombier }
341*63afb9a5SDavid du Colombier 
342*63afb9a5SDavid du Colombier void
putshort(Msg * m,ushort x)343*63afb9a5SDavid du Colombier putshort(Msg *m, ushort x)
344*63afb9a5SDavid du Colombier {
345*63afb9a5SDavid du Colombier 	if(m->wp+2 > m->ep)
346*63afb9a5SDavid du Colombier 		error(Eencode);
347*63afb9a5SDavid du Colombier 	PSHORT(m->wp, x);
348*63afb9a5SDavid du Colombier 	m->wp += 2;
349*63afb9a5SDavid du Colombier }
350*63afb9a5SDavid du Colombier 
351*63afb9a5SDavid du Colombier void
putlong(Msg * m,ulong x)352*63afb9a5SDavid du Colombier putlong(Msg *m, ulong x)
353*63afb9a5SDavid du Colombier {
354*63afb9a5SDavid du Colombier 	if(m->wp+4 > m->ep)
355*63afb9a5SDavid du Colombier 		error(Eencode);
356*63afb9a5SDavid du Colombier 	PLONG(m->wp, x);
357*63afb9a5SDavid du Colombier 	m->wp += 4;
358*63afb9a5SDavid du Colombier }
359*63afb9a5SDavid du Colombier 
360*63afb9a5SDavid du Colombier void
putstring(Msg * m,char * s)361*63afb9a5SDavid du Colombier putstring(Msg *m, char *s)
362*63afb9a5SDavid du Colombier {
363*63afb9a5SDavid du Colombier 	int len;
364*63afb9a5SDavid du Colombier 
365*63afb9a5SDavid du Colombier 	len = strlen(s);
366*63afb9a5SDavid du Colombier 	putlong(m, len);
367*63afb9a5SDavid du Colombier 	putbytes(m, s, len);
368*63afb9a5SDavid du Colombier }
369*63afb9a5SDavid du Colombier 
370*63afb9a5SDavid du Colombier void
putbytes(Msg * m,void * a,long n)371*63afb9a5SDavid du Colombier putbytes(Msg *m, void *a, long n)
372*63afb9a5SDavid du Colombier {
373*63afb9a5SDavid du Colombier 	if(m->wp+n > m->ep)
374*63afb9a5SDavid du Colombier 		error(Eencode);
375*63afb9a5SDavid du Colombier 	memmove(m->wp, a, n);
376*63afb9a5SDavid du Colombier 	m->wp += n;
377*63afb9a5SDavid du Colombier }
378*63afb9a5SDavid du Colombier 
379*63afb9a5SDavid du Colombier void
putmpint(Msg * m,mpint * b)380*63afb9a5SDavid du Colombier putmpint(Msg *m, mpint *b)
381*63afb9a5SDavid du Colombier {
382*63afb9a5SDavid du Colombier 	int bits, n;
383*63afb9a5SDavid du Colombier 
384*63afb9a5SDavid du Colombier 	bits = mpsignif(b);
385*63afb9a5SDavid du Colombier 	putshort(m, bits);
386*63afb9a5SDavid du Colombier 	n = (bits+7)/8;
387*63afb9a5SDavid du Colombier 	if(m->wp+n > m->ep)
388*63afb9a5SDavid du Colombier 		error(Eencode);
389*63afb9a5SDavid du Colombier 	mptobe(b, m->wp, n, nil);
390*63afb9a5SDavid du Colombier 	m->wp += n;
391*63afb9a5SDavid du Colombier }
392*63afb9a5SDavid du Colombier 
393*63afb9a5SDavid du Colombier void
putRSApub(Msg * m,RSApub * key)394*63afb9a5SDavid du Colombier putRSApub(Msg *m, RSApub *key)
395*63afb9a5SDavid du Colombier {
396*63afb9a5SDavid du Colombier 	putlong(m, mpsignif(key->n));
397*63afb9a5SDavid du Colombier 	putmpint(m, key->ek);
398*63afb9a5SDavid du Colombier 	putmpint(m, key->n);
399*63afb9a5SDavid du Colombier }
400*63afb9a5SDavid du Colombier 
401*63afb9a5SDavid du Colombier static ulong crctab[256];
402*63afb9a5SDavid du Colombier 
403*63afb9a5SDavid du Colombier static void
initsum32(void)404*63afb9a5SDavid du Colombier initsum32(void)
405*63afb9a5SDavid du Colombier {
406*63afb9a5SDavid du Colombier 	ulong crc, poly;
407*63afb9a5SDavid du Colombier 	int i, j;
408*63afb9a5SDavid du Colombier 
409*63afb9a5SDavid du Colombier 	poly = 0xEDB88320;
410*63afb9a5SDavid du Colombier 	for(i = 0; i < 256; i++){
411*63afb9a5SDavid du Colombier 		crc = i;
412*63afb9a5SDavid du Colombier 		for(j = 0; j < 8; j++){
413*63afb9a5SDavid du Colombier 			if(crc & 1)
414*63afb9a5SDavid du Colombier 				crc = (crc >> 1) ^ poly;
415*63afb9a5SDavid du Colombier 			else
416*63afb9a5SDavid du Colombier 				crc >>= 1;
417*63afb9a5SDavid du Colombier 		}
418*63afb9a5SDavid du Colombier 		crctab[i] = crc;
419*63afb9a5SDavid du Colombier 	}
420*63afb9a5SDavid du Colombier }
421*63afb9a5SDavid du Colombier 
422*63afb9a5SDavid du Colombier static ulong
sum32(ulong lcrc,void * buf,int n)423*63afb9a5SDavid du Colombier sum32(ulong lcrc, void *buf, int n)
424*63afb9a5SDavid du Colombier {
425*63afb9a5SDavid du Colombier 	static int first=1;
426*63afb9a5SDavid du Colombier 	uchar *s = buf;
427*63afb9a5SDavid du Colombier 	ulong crc = lcrc;
428*63afb9a5SDavid du Colombier 
429*63afb9a5SDavid du Colombier 	if(first){
430*63afb9a5SDavid du Colombier 		first=0;
431*63afb9a5SDavid du Colombier 		initsum32();
432*63afb9a5SDavid du Colombier 	}
433*63afb9a5SDavid du Colombier 	while(n-- > 0)
434*63afb9a5SDavid du Colombier 		crc = crctab[(crc^*s++)&0xff] ^ (crc>>8);
435*63afb9a5SDavid du Colombier 	return crc;
436*63afb9a5SDavid du Colombier }
437*63afb9a5SDavid du Colombier 
438*63afb9a5SDavid du Colombier mpint*
rsapad(mpint * b,int n)439*63afb9a5SDavid du Colombier rsapad(mpint *b, int n)
440*63afb9a5SDavid du Colombier {
441*63afb9a5SDavid du Colombier 	int i, pad, nbuf;
442*63afb9a5SDavid du Colombier 	uchar buf[2560];
443*63afb9a5SDavid du Colombier 	mpint *c;
444*63afb9a5SDavid du Colombier 
445*63afb9a5SDavid du Colombier 	if(n > sizeof buf)
446*63afb9a5SDavid du Colombier 		error("buffer too small in rsapad");
447*63afb9a5SDavid du Colombier 
448*63afb9a5SDavid du Colombier 	nbuf = (mpsignif(b)+7)/8;
449*63afb9a5SDavid du Colombier 	pad = n - nbuf;
450*63afb9a5SDavid du Colombier 	assert(pad >= 3);
451*63afb9a5SDavid du Colombier 	mptobe(b, buf, nbuf, nil);
452*63afb9a5SDavid du Colombier 	memmove(buf+pad, buf, nbuf);
453*63afb9a5SDavid du Colombier 
454*63afb9a5SDavid du Colombier 	buf[0] = 0;
455*63afb9a5SDavid du Colombier 	buf[1] = 2;
456*63afb9a5SDavid du Colombier 	for(i=2; i<pad-1; i++)
457*63afb9a5SDavid du Colombier 		buf[i]=1+fastrand()%255;
458*63afb9a5SDavid du Colombier 	buf[pad-1] = 0;
459*63afb9a5SDavid du Colombier 	c = betomp(buf, n, nil);
460*63afb9a5SDavid du Colombier 	memset(buf, 0, sizeof buf);
461*63afb9a5SDavid du Colombier 	return c;
462*63afb9a5SDavid du Colombier }
463*63afb9a5SDavid du Colombier 
464*63afb9a5SDavid du Colombier mpint*
rsaunpad(mpint * b)465*63afb9a5SDavid du Colombier rsaunpad(mpint *b)
466*63afb9a5SDavid du Colombier {
467*63afb9a5SDavid du Colombier 	int i, n;
468*63afb9a5SDavid du Colombier 	uchar buf[2560];
469*63afb9a5SDavid du Colombier 
470*63afb9a5SDavid du Colombier 	n = (mpsignif(b)+7)/8;
471*63afb9a5SDavid du Colombier 	if(n > sizeof buf)
472*63afb9a5SDavid du Colombier 		error("buffer too small in rsaunpad");
473*63afb9a5SDavid du Colombier 	mptobe(b, buf, n, nil);
474*63afb9a5SDavid du Colombier 
475*63afb9a5SDavid du Colombier 	/* the initial zero has been eaten by the betomp -> mptobe sequence */
476*63afb9a5SDavid du Colombier 	if(buf[0] != 2)
477*63afb9a5SDavid du Colombier 		error("bad data in rsaunpad");
478*63afb9a5SDavid du Colombier 	for(i=1; i<n; i++)
479*63afb9a5SDavid du Colombier 		if(buf[i]==0)
480*63afb9a5SDavid du Colombier 			break;
481*63afb9a5SDavid du Colombier 	return betomp(buf+i, n-i, nil);
482*63afb9a5SDavid du Colombier }
483*63afb9a5SDavid du Colombier 
484*63afb9a5SDavid du Colombier void
mptoberjust(mpint * b,uchar * buf,int len)485*63afb9a5SDavid du Colombier mptoberjust(mpint *b, uchar *buf, int len)
486*63afb9a5SDavid du Colombier {
487*63afb9a5SDavid du Colombier 	int n;
488*63afb9a5SDavid du Colombier 
489*63afb9a5SDavid du Colombier 	n = mptobe(b, buf, len, nil);
490*63afb9a5SDavid du Colombier 	assert(n >= 0);
491*63afb9a5SDavid du Colombier 	if(n < len){
492*63afb9a5SDavid du Colombier 		len -= n;
493*63afb9a5SDavid du Colombier 		memmove(buf+len, buf, n);
494*63afb9a5SDavid du Colombier 		memset(buf, 0, len);
495*63afb9a5SDavid du Colombier 	}
496*63afb9a5SDavid du Colombier }
497*63afb9a5SDavid du Colombier 
498*63afb9a5SDavid du Colombier mpint*
rsaencryptbuf(RSApub * key,uchar * buf,int nbuf)499*63afb9a5SDavid du Colombier rsaencryptbuf(RSApub *key, uchar *buf, int nbuf)
500*63afb9a5SDavid du Colombier {
501*63afb9a5SDavid du Colombier 	int n;
502*63afb9a5SDavid du Colombier 	mpint *a, *b, *c;
503*63afb9a5SDavid du Colombier 
504*63afb9a5SDavid du Colombier 	n = (mpsignif(key->n)+7)/8;
505*63afb9a5SDavid du Colombier 	a = betomp(buf, nbuf, nil);
506*63afb9a5SDavid du Colombier 	b = rsapad(a, n);
507*63afb9a5SDavid du Colombier 	mpfree(a);
508*63afb9a5SDavid du Colombier 	c = rsaencrypt(key, b, nil);
509*63afb9a5SDavid du Colombier 	mpfree(b);
510*63afb9a5SDavid du Colombier 	return c;
511*63afb9a5SDavid du Colombier }
512*63afb9a5SDavid du Colombier 
513