tdsasign.c - plan9port - [fork] Plan 9 from user space
HTML git clone git://src.adamsgaard.dk/plan9port
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tdsasign.c (3478B)
---
1 #include <u.h>
2 #include <libc.h>
3 #include <mp.h>
4 #include <libsec.h>
5 #include <auth.h>
6 #include <thread.h>
7 #include <9pclient.h>
8 #include <bio.h>
9
10 void
11 usage(void)
12 {
13 fprint(2, "usage: 9 dsasign [-i id] [-v] key <data\n");
14 threadexitsall("usage");
15 }
16
17 static void doVerify(void);
18 static char *getline(int*);
19
20 char *id;
21 Biobuf b;
22 int nid;
23 char *key;
24
25 void
26 threadmain(int argc, char **argv)
27 {
28 int n, verify;
29 char *text, *p;
30 uchar digest[SHA1dlen];
31 AuthRpc *rpc;
32 Fmt fmt;
33
34 fmtinstall('[', encodefmt);
35 fmtinstall('H', encodefmt);
36
37 verify = 0;
38 id = "";
39 ARGBEGIN{
40 case 'i':
41 id = EARGF(usage());
42 break;
43 case 'v':
44 verify = 1;
45 break;
46 default:
47 usage();
48 }ARGEND
49
50 if(argc != 1)
51 usage();
52 key = argv[0];
53 nid = strlen(id);
54
55 Binit(&b, 0, OREAD);
56 if(verify) {
57 doVerify();
58 threadexitsall(nil);
59 }
60
61 if((rpc = auth_allocrpc()) == nil){
62 fprint(2, "dsasign: auth_allocrpc: %r\n");
63 threadexits("rpc");
64 }
65 key = smprint("proto=dsa role=sign %s", key);
66 if(auth_rpc(rpc, "start", key, strlen(key)) != ARok){
67 fprint(2, "dsasign: auth 'start' failed: %r\n");
68 auth_freerpc(rpc);
69 threadexits("rpc");
70 }
71
72 print("+%s\n", id);
73
74 Binit(&b, 0, OREAD);
75 fmtstrinit(&fmt);
76 while((p = getline(&n)) != nil) {
77 if(p[0] == '-' || p[0] == '+')
78 print("+");
79 print("%s\n", p);
80 fmtprint(&fmt, "%s\n", p);
81 }
82 text = fmtstrflush(&fmt);
83 sha1((uchar*)text, strlen(text), digest, nil);
84
85 if(auth_rpc(rpc, "write", digest, SHA1dlen) != ARok)
86 sysfatal("auth write in sign failed: %r");
87 if(auth_rpc(rpc, "read", nil, 0) != ARok)
88 sysfatal("auth read in sign failed: %r");
89
90 print("-%s %.*H\n", id, rpc->narg, rpc->arg);
91 threadexits(nil);
92 }
93
94 static mpint*
95 keytomp(Attr *a, char *name)
96 {
97 char *p;
98 mpint *m;
99
100 p = _strfindattr(a, name);
101 if(p == nil)
102 sysfatal("missing key attribute %s", name);
103 m = strtomp(p, nil, 16, nil);
104 if(m == nil)
105 sysfatal("malformed key attribute %s=%s", name, p);
106 return m;
107 }
108
109 static void
110 doVerify(void)
111 {
112 char *p;
113 int n, nsig;
114 Fmt fmt;
115 uchar digest[SHA1dlen], sig[1024];
116 char *text;
117 Attr *a;
118 DSAsig dsig;
119 DSApub dkey;
120
121 a = _parseattr(key);
122 if(a == nil)
123 sysfatal("invalid key");
124 dkey.alpha = keytomp(a, "alpha");
125 dkey.key = keytomp(a, "key");
126 dkey.p = keytomp(a, "p");
127 dkey.q = keytomp(a, "q");
128 if(!probably_prime(dkey.p, 20) && !probably_prime(dkey.q, 20))
129 sysfatal("p or q not prime");
130
131 while((p = getline(&n)) != nil)
132 if(p[0] == '+' && strcmp(p+1, id) == 0)
133 goto start;
134 sysfatal("no message found");
135
136 start:
137 fmtstrinit(&fmt);
138 while((p = getline(&n)) != nil) {
139 if(n >= 1+nid+1+16 && p[0] == '-' && strncmp(p+1, id, nid) == 0 && p[1+nid] == ' ') {
140 if((nsig = dec16(sig, sizeof sig, p+1+nid+1, n-(1+nid+1))) != 20+20)
141 sysfatal("malformed signture");
142 goto end;
143 }
144 if(p[0] == '+')
145 p++;
146 fmtprint(&fmt, "%s\n", p);
147 }
148 sysfatal("did not find end of message");
149 return; // silence clang warning
150
151 end:
152 text = fmtstrflush(&fmt);
153 sha1((uchar*)text, strlen(text), digest, nil);
154
155 if(nsig != 40)
156 sysfatal("malformed signature");
157 dsig.r = betomp(sig, 20, nil);
158 dsig.s = betomp(sig+20, 20, nil);
159
160 if(dsaverify(&dkey, &dsig, betomp(digest, sizeof digest, nil)) < 0)
161 sysfatal("signature failed to verify: %r");
162
163 write(1, text, strlen(text));
164 threadexitsall(0);
165 }
166
167 char*
168 getline(int *np)
169 {
170 char *p;
171 int n;
172
173 if((p = Brdline(&b, '\n')) == nil)
174 return nil;
175 n = Blinelen(&b);
176 while(n > 0 && (p[n-1] == '\n' || p[n-1] == ' ' || p[n-1] == '\t'))
177 n--;
178 p[n] = '\0';
179 *np = n;
180 return p;
181 }