1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
35979f962SDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include "authcmdlib.h"
5219b2ee8SDavid du Colombier
6219b2ee8SDavid du Colombier /*
7219b2ee8SDavid du Colombier * compute the key verification checksum
8219b2ee8SDavid du Colombier */
9219b2ee8SDavid du Colombier void
checksum(char key[],char csum[])10219b2ee8SDavid du Colombier checksum(char key[], char csum[]) {
11219b2ee8SDavid du Colombier uchar buf[8];
12219b2ee8SDavid du Colombier
13219b2ee8SDavid du Colombier memset(buf, 0, 8);
14219b2ee8SDavid du Colombier encrypt(key, buf, 8);
157dd7cddfSDavid du Colombier sprint(csum, "C %.2ux%.2ux%.2ux%.2ux", buf[0], buf[1], buf[2], buf[3]);
16219b2ee8SDavid du Colombier }
17219b2ee8SDavid du Colombier
18219b2ee8SDavid du Colombier /*
19219b2ee8SDavid du Colombier * compute the proper response. We encrypt the ascii of
20219b2ee8SDavid du Colombier * challenge number, with trailing binary zero fill.
21219b2ee8SDavid du Colombier * This process was derived empirically.
22219b2ee8SDavid du Colombier * this was copied from inet's guard.
23219b2ee8SDavid du Colombier */
24219b2ee8SDavid du Colombier char *
netresp(char * key,long chal,char * answer)25219b2ee8SDavid du Colombier netresp(char *key, long chal, char *answer)
26219b2ee8SDavid du Colombier {
27219b2ee8SDavid du Colombier uchar buf[8];
28219b2ee8SDavid du Colombier
29219b2ee8SDavid du Colombier memset(buf, 0, 8);
30*f54edc78SDavid du Colombier snprint((char *)buf, sizeof buf, "%lud", chal);
31219b2ee8SDavid du Colombier if(encrypt(key, buf, 8) < 0)
32219b2ee8SDavid du Colombier error("can't encrypt response");
33219b2ee8SDavid du Colombier chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
34219b2ee8SDavid du Colombier sprint(answer, "%.8lux", chal);
35219b2ee8SDavid du Colombier
36219b2ee8SDavid du Colombier return answer;
37219b2ee8SDavid du Colombier }
38219b2ee8SDavid du Colombier
39219b2ee8SDavid du Colombier char *
netdecimal(char * answer)40219b2ee8SDavid du Colombier netdecimal(char *answer)
41219b2ee8SDavid du Colombier {
42219b2ee8SDavid du Colombier int i;
43219b2ee8SDavid du Colombier
44219b2ee8SDavid du Colombier for(i = 0; answer[i]; i++)
45219b2ee8SDavid du Colombier switch(answer[i]){
46219b2ee8SDavid du Colombier case 'a': case 'b': case 'c':
47219b2ee8SDavid du Colombier answer[i] = '2';
48219b2ee8SDavid du Colombier break;
49219b2ee8SDavid du Colombier case 'd': case 'e': case 'f':
50219b2ee8SDavid du Colombier answer[i] = '3';
51219b2ee8SDavid du Colombier break;
52219b2ee8SDavid du Colombier }
53219b2ee8SDavid du Colombier return answer;
54219b2ee8SDavid du Colombier }
55219b2ee8SDavid du Colombier
56219b2ee8SDavid du Colombier int
netcheck(void * key,long chal,char * response)57219b2ee8SDavid du Colombier netcheck(void *key, long chal, char *response)
58219b2ee8SDavid du Colombier {
59219b2ee8SDavid du Colombier char answer[32], *p;
60219b2ee8SDavid du Colombier int i;
61219b2ee8SDavid du Colombier
62219b2ee8SDavid du Colombier if(smartcheck(key, chal, response))
63219b2ee8SDavid du Colombier return 1;
64219b2ee8SDavid du Colombier
65219b2ee8SDavid du Colombier if(p = strchr(response, '\n'))
66219b2ee8SDavid du Colombier *p = '\0';
67219b2ee8SDavid du Colombier netresp(key, chal, answer);
68219b2ee8SDavid du Colombier
69219b2ee8SDavid du Colombier /*
70219b2ee8SDavid du Colombier * check for hex response -- securenet mode 1 or 5
71219b2ee8SDavid du Colombier */
72219b2ee8SDavid du Colombier for(i = 0; response[i]; i++)
73219b2ee8SDavid du Colombier if(response[i] >= 'A' && response[i] <= 'Z')
74219b2ee8SDavid du Colombier response[i] -= 'A' - 'a';
75219b2ee8SDavid du Colombier if(strcmp(answer, response) == 0)
76219b2ee8SDavid du Colombier return 1;
77219b2ee8SDavid du Colombier
78219b2ee8SDavid du Colombier /*
79219b2ee8SDavid du Colombier * check for decimal response -- securenet mode 0 or 4
80219b2ee8SDavid du Colombier */
81219b2ee8SDavid du Colombier return strcmp(netdecimal(answer), response) == 0;
82219b2ee8SDavid du Colombier }
83219b2ee8SDavid du Colombier
84219b2ee8SDavid du Colombier int
smartcheck(void * key,long chal,char * response)85219b2ee8SDavid du Colombier smartcheck(void *key, long chal, char *response)
86219b2ee8SDavid du Colombier {
87219b2ee8SDavid du Colombier uchar buf[2*8];
88219b2ee8SDavid du Colombier int i, c, cslo, cshi;
89219b2ee8SDavid du Colombier
90*f54edc78SDavid du Colombier snprint((char*)buf, sizeof buf, "%lud ", chal);
91219b2ee8SDavid du Colombier cslo = 0x52;
92219b2ee8SDavid du Colombier cshi = cslo;
93219b2ee8SDavid du Colombier for(i = 0; i < 8; i++){
94219b2ee8SDavid du Colombier c = buf[i];
95219b2ee8SDavid du Colombier if(c >= '0' && c <= '9')
96219b2ee8SDavid du Colombier c -= '0';
97219b2ee8SDavid du Colombier cslo += c;
98219b2ee8SDavid du Colombier if(cslo > 0xff)
99219b2ee8SDavid du Colombier cslo -= 0xff;
100219b2ee8SDavid du Colombier cshi += cslo;
101219b2ee8SDavid du Colombier if(cshi > 0xff)
102219b2ee8SDavid du Colombier cshi -= 0xff;
103219b2ee8SDavid du Colombier buf[i] = c | (cshi & 0xf0);
104219b2ee8SDavid du Colombier }
105219b2ee8SDavid du Colombier
106219b2ee8SDavid du Colombier encrypt(key, buf, 8);
107219b2ee8SDavid du Colombier for(i = 0; i < 8; i++)
108219b2ee8SDavid du Colombier if(response[i] != buf[i] % 10 + '0')
109219b2ee8SDavid du Colombier return 0;
110219b2ee8SDavid du Colombier return 1;
111219b2ee8SDavid du Colombier }
112