Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libskey / skeysubr.c
1 /* $FreeBSD: src/lib/libskey/skeysubr.c,v 1.9.6.1 2000/07/20 20:13:42 obrien Exp $ */
2
3 #include <err.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <fcntl.h>
8 #include <termios.h>
9 #include <signal.h>
10
11 #include "skey.h"
12 #include "mdx.h"
13
14 /* Crunch a key:
15  * concatenate the seed and the password, run through MDX and
16  * collapse to 64 bits. This is defined as the user's starting key.
17  */
18 int
19 keycrunch(result,seed,passwd)
20 char *result;   /* 8-byte result */
21 const char *seed;     /* Seed, any length */
22 const char *passwd;   /* Password, any length */
23 {
24         char *buf;
25         MDX_CTX md;
26         u_int32_t results[4];
27         unsigned int buflen;
28
29         buflen = strlen(seed) + strlen(passwd);
30         if((buf = malloc(buflen+1)) == NULL)
31                 return -1;
32         strcpy(buf,seed);
33         strcat(buf,passwd);
34
35         /* Crunch the key through MD[45] */
36         sevenbit(buf);
37         MDXInit(&md);
38         MDXUpdate(&md,(unsigned char *)buf,buflen);
39         MDXFinal((unsigned char *)results,&md);
40         free(buf);
41
42         results[0] ^= results[2];
43         results[1] ^= results[3];
44
45         memcpy(result,(char *)results,8);
46
47         return 0;
48 }
49
50 /* The one-way function f(). Takes 8 bytes and returns 8 bytes in place */
51 void
52 f(x)
53 char *x;
54 {
55         MDX_CTX md;
56         u_int32_t results[4];
57
58         MDXInit(&md);
59         MDXUpdate(&md,(unsigned char *)x,8);
60         MDXFinal((unsigned char *)results,&md);
61         /* Fold 128 to 64 bits */
62         results[0] ^= results[2];
63         results[1] ^= results[3];
64
65         memcpy(x,(char *)results,8);
66 }
67
68 /* Strip trailing cr/lf from a line of text */
69 void
70 rip(buf)
71 char *buf;
72 {
73         buf[strcspn(buf, "\r\n")] = 0;
74 }
75
76 static struct termios saved_ttymode;
77
78 static void interrupt __P((int));
79
80 static void interrupt(sig)
81 int sig;
82 {
83         tcsetattr(0, TCSANOW, &saved_ttymode);
84         err(1, "interrupted by signal %s", sys_siglist[sig]);
85 }
86
87 char *
88 readpass(buf,n)
89 char *buf;
90 int n;
91 {
92         struct termios noecho_ttymode;
93         void (*oldsig) __P((int));
94
95         /* Save normal line editing modes */
96         tcgetattr(0, &saved_ttymode);
97         if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
98                 signal(SIGINT, interrupt);
99
100         /* Turn off echoing */
101         tcgetattr(0, &noecho_ttymode);
102         noecho_ttymode.c_lflag &= ~ECHO;
103         tcsetattr(0, TCSANOW, &noecho_ttymode);
104         fgets(buf,n,stdin);
105         rip(buf);
106
107         /* Restore previous tty modes */
108         tcsetattr(0, TCSANOW, &saved_ttymode);
109         if (oldsig != SIG_IGN)
110                 signal(SIGINT, oldsig);
111
112         /*
113         after the secret key is taken from the keyboard, the line feed is
114         written to standard error instead of standard output.  That means that
115         anyone using the program from a terminal won't notice, but capturing
116         standard output will get the key words without a newline in front of
117         them.
118         */
119         fprintf(stderr, "\n");
120         fflush(stderr);
121         sevenbit(buf);
122
123         return buf;
124 }
125
126 void
127 sevenbit(s)
128 char *s;
129 {
130         /* make sure there are only 7 bit code in the line*/
131         while(*s){
132                 *s &= 0x7f;
133                 s++;
134         }
135 }