1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <auth.h> 4*219b2ee8SDavid du Colombier #include "authsrv.h" 5*219b2ee8SDavid du Colombier 6*219b2ee8SDavid du Colombier /* 7*219b2ee8SDavid du Colombier * compute the key verification checksum 8*219b2ee8SDavid du Colombier */ 9*219b2ee8SDavid du Colombier void 10*219b2ee8SDavid du Colombier checksum(char key[], char csum[]) { 11*219b2ee8SDavid du Colombier uchar buf[8]; 12*219b2ee8SDavid du Colombier 13*219b2ee8SDavid du Colombier memset(buf, 0, 8); 14*219b2ee8SDavid du Colombier encrypt(key, buf, 8); 15*219b2ee8SDavid du Colombier sprint(csum, "C %.2ux%.2ux%.2ux", buf[0], buf[1], buf[2], buf[3]); 16*219b2ee8SDavid du Colombier } 17*219b2ee8SDavid du Colombier 18*219b2ee8SDavid du Colombier /* 19*219b2ee8SDavid du Colombier * compute the proper response. We encrypt the ascii of 20*219b2ee8SDavid du Colombier * challenge number, with trailing binary zero fill. 21*219b2ee8SDavid du Colombier * This process was derived empirically. 22*219b2ee8SDavid du Colombier * this was copied from inet's guard. 23*219b2ee8SDavid du Colombier */ 24*219b2ee8SDavid du Colombier char * 25*219b2ee8SDavid du Colombier netresp(char *key, long chal, char *answer) 26*219b2ee8SDavid du Colombier { 27*219b2ee8SDavid du Colombier uchar buf[8]; 28*219b2ee8SDavid du Colombier 29*219b2ee8SDavid du Colombier memset(buf, 0, 8); 30*219b2ee8SDavid du Colombier sprint((char *)buf, "%lud", chal); 31*219b2ee8SDavid du Colombier if(encrypt(key, buf, 8) < 0) 32*219b2ee8SDavid du Colombier error("can't encrypt response"); 33*219b2ee8SDavid du Colombier chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]; 34*219b2ee8SDavid du Colombier sprint(answer, "%.8lux", chal); 35*219b2ee8SDavid du Colombier 36*219b2ee8SDavid du Colombier return answer; 37*219b2ee8SDavid du Colombier } 38*219b2ee8SDavid du Colombier 39*219b2ee8SDavid du Colombier char * 40*219b2ee8SDavid du Colombier netdecimal(char *answer) 41*219b2ee8SDavid du Colombier { 42*219b2ee8SDavid du Colombier int i; 43*219b2ee8SDavid du Colombier 44*219b2ee8SDavid du Colombier for(i = 0; answer[i]; i++) 45*219b2ee8SDavid du Colombier switch(answer[i]){ 46*219b2ee8SDavid du Colombier case 'a': case 'b': case 'c': 47*219b2ee8SDavid du Colombier answer[i] = '2'; 48*219b2ee8SDavid du Colombier break; 49*219b2ee8SDavid du Colombier case 'd': case 'e': case 'f': 50*219b2ee8SDavid du Colombier answer[i] = '3'; 51*219b2ee8SDavid du Colombier break; 52*219b2ee8SDavid du Colombier } 53*219b2ee8SDavid du Colombier return answer; 54*219b2ee8SDavid du Colombier } 55*219b2ee8SDavid du Colombier 56*219b2ee8SDavid du Colombier int 57*219b2ee8SDavid du Colombier netcheck(void *key, long chal, char *response) 58*219b2ee8SDavid du Colombier { 59*219b2ee8SDavid du Colombier char answer[32], *p; 60*219b2ee8SDavid du Colombier int i; 61*219b2ee8SDavid du Colombier 62*219b2ee8SDavid du Colombier if(smartcheck(key, chal, response)) 63*219b2ee8SDavid du Colombier return 1; 64*219b2ee8SDavid du Colombier 65*219b2ee8SDavid du Colombier if(p = strchr(response, '\n')) 66*219b2ee8SDavid du Colombier *p = '\0'; 67*219b2ee8SDavid du Colombier netresp(key, chal, answer); 68*219b2ee8SDavid du Colombier 69*219b2ee8SDavid du Colombier /* 70*219b2ee8SDavid du Colombier * check for hex response -- securenet mode 1 or 5 71*219b2ee8SDavid du Colombier */ 72*219b2ee8SDavid du Colombier for(i = 0; response[i]; i++) 73*219b2ee8SDavid du Colombier if(response[i] >= 'A' && response[i] <= 'Z') 74*219b2ee8SDavid du Colombier response[i] -= 'A' - 'a'; 75*219b2ee8SDavid du Colombier if(strcmp(answer, response) == 0) 76*219b2ee8SDavid du Colombier return 1; 77*219b2ee8SDavid du Colombier 78*219b2ee8SDavid du Colombier /* 79*219b2ee8SDavid du Colombier * check for decimal response -- securenet mode 0 or 4 80*219b2ee8SDavid du Colombier */ 81*219b2ee8SDavid du Colombier return strcmp(netdecimal(answer), response) == 0; 82*219b2ee8SDavid du Colombier } 83*219b2ee8SDavid du Colombier 84*219b2ee8SDavid du Colombier int 85*219b2ee8SDavid du Colombier smartcheck(void *key, long chal, char *response) 86*219b2ee8SDavid du Colombier { 87*219b2ee8SDavid du Colombier uchar buf[2*8]; 88*219b2ee8SDavid du Colombier int i, c, cslo, cshi; 89*219b2ee8SDavid du Colombier 90*219b2ee8SDavid du Colombier sprint((char*)buf, "%lud ", chal); 91*219b2ee8SDavid du Colombier cslo = 0x52; 92*219b2ee8SDavid du Colombier cshi = cslo; 93*219b2ee8SDavid du Colombier for(i = 0; i < 8; i++){ 94*219b2ee8SDavid du Colombier c = buf[i]; 95*219b2ee8SDavid du Colombier if(c >= '0' && c <= '9') 96*219b2ee8SDavid du Colombier c -= '0'; 97*219b2ee8SDavid du Colombier cslo += c; 98*219b2ee8SDavid du Colombier if(cslo > 0xff) 99*219b2ee8SDavid du Colombier cslo -= 0xff; 100*219b2ee8SDavid du Colombier cshi += cslo; 101*219b2ee8SDavid du Colombier if(cshi > 0xff) 102*219b2ee8SDavid du Colombier cshi -= 0xff; 103*219b2ee8SDavid du Colombier buf[i] = c | (cshi & 0xf0); 104*219b2ee8SDavid du Colombier } 105*219b2ee8SDavid du Colombier 106*219b2ee8SDavid du Colombier encrypt(key, buf, 8); 107*219b2ee8SDavid du Colombier for(i = 0; i < 8; i++) 108*219b2ee8SDavid du Colombier if(response[i] != buf[i] % 10 + '0') 109*219b2ee8SDavid du Colombier return 0; 110*219b2ee8SDavid du Colombier return 1; 111*219b2ee8SDavid du Colombier } 112