plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

dsasign.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 }