]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/auth/factotum/ecdsa.c
mpc: constant expression folding
[plan9front.git] / sys / src / cmd / auth / factotum / ecdsa.c
1 #include "dat.h"
2
3 enum {
4         CHaveKey,
5         CHaveText,
6         Maxphase
7 };
8
9 static ECdomain dom;
10
11 static char *phasenames[] = {
12         "CHaveKey",
13         "CHaveText",
14 };
15
16 struct State {
17         ECpriv p;
18         uchar buf[100];
19         int n;
20 };
21
22 static int
23 decryptkey(Fsstate *fss, char *key, char *password)
24 {
25         uchar keyenc[53], hash[32];
26         AESstate s;
27         State *st;
28
29         if(base58dec(key, keyenc, 53) < 0)
30                 return failure(fss, "invalid base58");
31         sha2_256((uchar *)password, strlen(password), hash, nil);
32         sha2_256(hash, 32, hash, nil);
33         setupAESstate(&s, hash, 32, keyenc+37);
34         aesCBCdecrypt(keyenc, 37, &s);
35         if(keyenc[0] != 0x80)
36                 return RpcNeedkey;
37         sha2_256(keyenc, 33, hash, nil);
38         sha2_256(hash, 32, hash, nil);
39         if(memcmp(keyenc + 33, hash, 4) != 0)
40                 return RpcNeedkey;
41         st = fss->ps;
42         st->p.d = betomp(keyenc + 1, 32, nil);
43         st->p.x = mpnew(0);
44         st->p.y = mpnew(0);
45         ecmul(&dom, dom.G, st->p.d, &st->p);
46         return RpcOk;
47 }
48
49 static int
50 ecdsainit(Proto *, Fsstate *fss)
51 {
52         int iscli;
53         Key *k;
54         Keyinfo ki;
55         int ret;
56         char *key, *password;
57         Attr *attr;
58
59         if(dom.p == nil){
60                 dom.p = strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", nil, 16, nil);
61                 dom.a = uitomp(0, nil);
62                 dom.b = uitomp(7, nil);
63                 dom.n = strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", nil, 16, nil);
64                 dom.h = uitomp(1, nil);
65                 dom.G = strtoec(&dom, "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", nil, nil);
66         }
67         fss->ps = nil;
68         if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)
69                 return failure(fss, nil);
70         if(iscli==0)
71                 return failure(fss, "ecdsa server unimplemented");
72         mkkeyinfo(&ki, fss, nil);
73         ret = findkey(&k, &ki, "key? !password?");
74         if(ret == RpcOk){
75                 key = _strfindattr(k->attr, "key");
76                 password = _strfindattr(k->privattr, "!password");
77
78         }else{
79                 if(!_strfindattr(fss->attr, "dom"))
80                         return ret;
81                 attr = _copyattr(fss->attr);
82                 _delattr(attr, "key");
83                 mkkeyinfo(&ki, fss, attr);
84                 ret = findkey(&k, &ki, "dom? !password?");
85                 if(ret != RpcOk)
86                         return ret;
87                 key = _strfindattr(fss->attr, "key");
88                 password = _strfindattr(k->privattr, "!password");
89         }
90         if(key == nil || password == nil)
91                 return RpcNeedkey;
92         fss->ps = emalloc(sizeof(State));
93         ret = decryptkey(fss, key, password);
94         if(ret != RpcOk)
95                 return ret;
96         
97         setattrs(fss->attr, k->attr);
98         fss->phasename = phasenames;
99         fss->maxphase = Maxphase;
100         fss->phase = CHaveKey;
101         return RpcOk;
102 }
103
104 static void
105 derencode(mpint *r, mpint *s, uchar *buf, int *n)
106 {
107         uchar rk[33], sk[33];
108         int rl, sl;
109         
110         mptobe(r, rk, 32, nil);
111         mptobe(s, sk, 32, nil);
112         rl = (mpsignif(r) + 7)/8;
113         sl = (mpsignif(s) + 7)/8;
114         if(rk[0] & 0x80){
115                 memmove(rk + 1, rk, 32);
116                 rk[0] = 0;
117                 rl++;
118         }
119         if(sk[0] & 0x80){
120                 memmove(sk + 1, sk, 32);
121                 sk[0] = 0;
122                 sl++;
123         }
124         buf[0] = 0x30;
125         buf[1] = 4 + rl + sl;
126         buf[2] = 0x02;
127         buf[3] = rl;
128         memmove(buf + 4, rk, rl);
129         buf[4 + rl] = 0x02;
130         buf[5 + rl] = sl;
131         memmove(buf + 6 + rl, sk, sl);
132         *n = 6 + rl + sl;
133 }
134
135 static int
136 ecdsawrite(Fsstate *fss, void *va, uint n)
137 {
138         State *st;
139         mpint *r, *s;
140         
141         st = fss->ps;
142         switch(fss->phase){
143         default:
144                 return phaseerror(fss, "write");
145         case CHaveKey:
146                 r = mpnew(0);
147                 s = mpnew(0);
148                 ecdsasign(&dom, &st->p, va, n, r, s);
149                 derencode(r, s, st->buf, &st->n);
150                 mpfree(r);
151                 mpfree(s);
152                 fss->phase = CHaveText;
153                 return RpcOk;
154         }
155 }
156
157 static int
158 ecdsaread(Fsstate *fss, void *va, uint *n)
159 {
160         State *st;
161         
162         st = fss->ps;
163         switch(fss->phase){
164         default:
165                 return phaseerror(fss, "read");
166         case CHaveText:
167                 if(*n > st->n)
168                         *n = st->n;
169                 memcpy(va, st->buf, *n);
170                 fss->phase = Established;
171                 return RpcOk;
172         }
173 }
174
175 static void
176 ecdsaclose(Fsstate *fss)
177 {
178         State *st;
179         
180         st = fss->ps;
181         if(st == nil)
182                 return;
183         if(st->p.x != nil){
184                 mpfree(st->p.x);
185                 mpfree(st->p.y);
186                 mpfree(st->p.d);
187         }
188         free(st);
189         fss->ps = nil;
190 }
191
192 Proto ecdsa = {
193         .name = "ecdsa",
194         .init = ecdsainit,
195         .read = ecdsaread,
196         .write = ecdsawrite,
197         .close = ecdsaclose,
198         .addkey = replacekey,
199         .keyprompt= "key? !password?",
200 };