URI:
       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 }