xref: /inferno-os/appl/cmd/netkey.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement Netkey;
2
3include "sys.m";
4	sys: Sys;
5
6include "draw.m";
7
8include "keyring.m";
9	keyring: Keyring;
10
11Netkey: module
12{
13	init:	fn(nil: ref Draw->Context, nil: list of string);
14};
15
16ANAMELEN: con 28;
17DESKEYLEN: con 7;
18
19init(nil: ref Draw->Context, args: list of string)
20{
21	sys = load Sys Sys->PATH;
22	keyring = load Keyring Keyring->PATH;
23
24	if(len args > 1){
25		sys->fprint(sys->fildes(2), "usage: netkey\n");
26		raise "fail:usage";
27	}
28	(pw, err) := readconsline("Password: ", 1);
29	if(err != nil){
30		sys->fprint(sys->fildes(2), "netkey: %s\n", err);
31		raise "fail:error";
32	}
33	if(pw != nil)
34		while((chal := readconsline("challenge: ", 0).t0) != nil)
35			sys->print("response: %s\n", netcrypt(passtokey(pw), string int chal));
36}
37
38readconsline(prompt: string, raw: int): (string, string)
39{
40	fd := sys->open("/dev/cons", Sys->ORDWR);
41	if(fd == nil)
42		return (nil, sys->sprint("can't open cons: %r"));
43	sys->fprint(fd, "%s", prompt);
44	fdctl: ref Sys->FD;
45	if(raw){
46		fdctl = sys->open("/dev/consctl", sys->OWRITE);
47		if(fdctl == nil || sys->fprint(fdctl, "rawon") < 0)
48			return (nil, sys->sprint("can't open consctl: %r"));
49	}
50	line := array[256] of byte;
51	o := 0;
52	err: string;
53	buf := array[1] of byte;
54  Read:
55	while((r := sys->read(fd, buf, len buf)) > 0){
56		c := int buf[0];
57		case c {
58		16r7F =>
59			err = "interrupt";
60			break Read;
61		'\b' =>
62			if(o > 0)
63				o--;
64		'\n' or '\r' or 16r4 =>
65			break Read;
66		* =>
67			if(o > len line){
68				err = "line too long";
69				break Read;
70			}
71			line[o++] = byte c;
72		}
73	}
74	if(r < 0)
75		err = sys->sprint("can't read cons: %r");
76	if(raw){
77		sys->fprint(fdctl, "rawoff");
78		sys->fprint(fd, "\n");
79	}
80	if(err != nil)
81		return (nil, err);
82	return (string line[0:o], err);
83}
84
85#
86# duplicates auth9 but keeps this self-contained
87#
88
89netcrypt(key: array of byte, chal: string): string
90{
91	buf := array[8] of {* => byte 0};
92	a := array of byte chal;
93	if(len a > 7)
94		a = a[0:7];
95	buf[0:] = a;
96	encrypt(key, buf, len buf);
97	return sys->sprint("%.2ux%.2ux%.2ux%.2ux", int buf[0], int buf[1], int buf[2], int buf[3]);
98}
99
100passtokey(p: string): array of byte
101{
102	a := array of byte p;
103	n := len a;
104	if(n >= ANAMELEN)
105		n = ANAMELEN-1;
106	buf := array[ANAMELEN] of {* => byte ' '};
107	buf[0:] = a[0:n];
108	buf[n] = byte 0;
109	key := array[DESKEYLEN] of {* => byte 0};
110	t := 0;
111	for(;;){
112		for(i := 0; i < DESKEYLEN; i++)
113			key[i] = byte ((int buf[t+i] >> i) + (int buf[t+i+1] << (8 - (i+1))));
114		if(n <= 8)
115			return key;
116		n -= 8;
117		t += 8;
118		if(n < 8){
119			t -= 8 - n;
120			n = 8;
121		}
122		encrypt(key, buf[t:], 8);
123	}
124}
125
126parity := array[] of {
127	byte 16r01, byte 16r02, byte 16r04, byte 16r07, byte 16r08, byte 16r0b, byte 16r0d, byte 16r0e,
128	byte 16r10, byte 16r13, byte 16r15, byte 16r16, byte 16r19, byte 16r1a, byte 16r1c, byte 16r1f,
129	byte 16r20, byte 16r23, byte 16r25, byte 16r26, byte 16r29, byte 16r2a, byte 16r2c, byte 16r2f,
130	byte 16r31, byte 16r32, byte 16r34, byte 16r37, byte 16r38, byte 16r3b, byte 16r3d, byte 16r3e,
131	byte 16r40, byte 16r43, byte 16r45, byte 16r46, byte 16r49, byte 16r4a, byte 16r4c, byte 16r4f,
132	byte 16r51, byte 16r52, byte 16r54, byte 16r57, byte 16r58, byte 16r5b, byte 16r5d, byte 16r5e,
133	byte 16r61, byte 16r62, byte 16r64, byte 16r67, byte 16r68, byte 16r6b, byte 16r6d, byte 16r6e,
134	byte 16r70, byte 16r73, byte 16r75, byte 16r76, byte 16r79, byte 16r7a, byte 16r7c, byte 16r7f,
135	byte 16r80, byte 16r83, byte 16r85, byte 16r86, byte 16r89, byte 16r8a, byte 16r8c, byte 16r8f,
136	byte 16r91, byte 16r92, byte 16r94, byte 16r97, byte 16r98, byte 16r9b, byte 16r9d, byte 16r9e,
137	byte 16ra1, byte 16ra2, byte 16ra4, byte 16ra7, byte 16ra8, byte 16rab, byte 16rad, byte 16rae,
138	byte 16rb0, byte 16rb3, byte 16rb5, byte 16rb6, byte 16rb9, byte 16rba, byte 16rbc, byte 16rbf,
139	byte 16rc1, byte 16rc2, byte 16rc4, byte 16rc7, byte 16rc8, byte 16rcb, byte 16rcd, byte 16rce,
140	byte 16rd0, byte 16rd3, byte 16rd5, byte 16rd6, byte 16rd9, byte 16rda, byte 16rdc, byte 16rdf,
141	byte 16re0, byte 16re3, byte 16re5, byte 16re6, byte 16re9, byte 16rea, byte 16rec, byte 16ref,
142	byte 16rf1, byte 16rf2, byte 16rf4, byte 16rf7, byte 16rf8, byte 16rfb, byte 16rfd, byte 16rfe,
143};
144
145des56to64(k56: array of byte): array of byte
146{
147	k64 := array[8] of byte;
148	hi := (int k56[0]<<24)|(int k56[1]<<16)|(int k56[2]<<8)|int k56[3];
149	lo := (int k56[4]<<24)|(int k56[5]<<16)|(int k56[6]<<8);
150
151	k64[0] = parity[(hi>>25)&16r7f];
152	k64[1] = parity[(hi>>18)&16r7f];
153	k64[2] = parity[(hi>>11)&16r7f];
154	k64[3] = parity[(hi>>4)&16r7f];
155	k64[4] = parity[((hi<<3)|int ((big lo & big 16rFFFFFFFF)>>29))&16r7f];	# watch the sign extension
156	k64[5] = parity[(lo>>22)&16r7f];
157	k64[6] = parity[(lo>>15)&16r7f];
158	k64[7] = parity[(lo>>8)&16r7f];
159	return k64;
160}
161
162encrypt(key: array of byte, data: array of byte, n: int)
163{
164	ds := keyring->dessetup(des56to64(key), nil);
165	keyring->desecb(ds, data, n, Keyring->Encrypt);
166}
167