diff options
author | rsc <devnull@localhost> | 2005-02-13 18:04:00 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-02-13 18:04:00 +0000 |
commit | ce94dbe662155bd60d6839b5e8c82ad708667bcd (patch) | |
tree | 0c405ef046615640061cc6080b9fee516c5c80f8 /src/cmd/auth/factotum/rsa.c | |
parent | ea77b9ce7c579a2e625806dc01104d5f6929cc43 (diff) | |
download | plan9port-ce94dbe662155bd60d6839b5e8c82ad708667bcd.tar.gz plan9port-ce94dbe662155bd60d6839b5e8c82ad708667bcd.tar.bz2 plan9port-ce94dbe662155bd60d6839b5e8c82ad708667bcd.zip |
add ssh-agent via factotum
Diffstat (limited to 'src/cmd/auth/factotum/rsa.c')
-rw-r--r-- | src/cmd/auth/factotum/rsa.c | 148 |
1 files changed, 111 insertions, 37 deletions
diff --git a/src/cmd/auth/factotum/rsa.c b/src/cmd/auth/factotum/rsa.c index 327dbc5b..34ddb784 100644 --- a/src/cmd/auth/factotum/rsa.c +++ b/src/cmd/auth/factotum/rsa.c @@ -4,65 +4,116 @@ /* * RSA authentication. * - * Client: + * Encrypt/Decrypt: * start n=xxx ek=xxx * write msg - * read decrypt(msg) + * read encrypt/decrypt(msg) * * Sign (PKCS #1 using hash=sha1 or hash=md5) * start n=xxx ek=xxx * write hash(msg) * read signature(hash(msg)) * + * Verify: + * start n=xxx ek=xxx + * write hash(msg) + * write signature(hash(msg)) + * read ok or fail + * * all numbers are hexadecimal biginits parsable with strtomp. * must be lower case for attribute matching in start. */ static int -rsaclient(Conv *c) +xrsadecrypt(Conv *c) { - char *chal; - mpint *m; + char *txt, buf[4096], *role; + int n, ret; + mpint *m, *mm; Key *k; + RSApriv *key; + + ret = -1; + txt = nil; + m = nil; + mm = nil; + /* fetch key */ + c->state = "keylookup"; k = keylookup("%A", c->attr); if(k == nil) - return -1; - c->state = "read challenge"; - if(convreadm(c, &chal) < 0){ - keyclose(k); - return -1; + goto out; + key = k->priv; + + /* make sure have private half if needed */ + role = strfindattr(c->attr, "role"); + if(strcmp(role, "decrypt") == 0 && !key->c2){ + werrstr("missing private half of key -- cannot decrypt"); + goto out; } - if(strlen(chal) < 32){ - badchal: - free(chal); - convprint(c, "bad challenge"); - keyclose(k); - return -1; + + /* read text */ + c->state = "read"; + if((n=convreadm(c, &txt)) < 0) + goto out; + if(n < 32){ + convprint(c, "data too short"); + goto out; } - m = strtomp(chal, nil, 16, nil); + + /* encrypt/decrypt */ + m = betomp(txt, n, nil); if(m == nil) - goto badchal; - free(chal); - m = rsadecrypt(k->priv, m, m); - convprint(c, "%B", m); + goto out; + if(strcmp(role, "decrypt") == 0) + mm = rsadecrypt(key, m, m); + else + mm = rsaencrypt(&key->pub, m, nil); + if(mm == nil) + goto out; + n = mptobe(m, buf, sizeof buf, nil); + + /* send response */ + c->state = "write"; + convwrite(c, buf, n); + ret = 0; + +out: mpfree(m); + mpfree(mm); keyclose(k); - return 0; + free(txt); + return ret; } static int xrsasign(Conv *c) { - char *hash; - int dlen, n; + char *hash, *role; + int dlen, n, ret; DigestAlg *hashfn; Key *k; + RSApriv *key; uchar sig[1024], digest[64]; + char *sig2; + ret = -1; + + /* fetch key */ + c->state = "keylookup"; k = keylookup("%A", c->attr); if(k == nil) - return -1; + goto out; + + /* make sure have private half if needed */ + key = k->priv; + role = strfindattr(c->attr, "role"); + if(strcmp(role, "sign") == 0 && !key->c2){ + werrstr("missing private half of key -- cannot sign"); + goto out; + } + + /* get hash type from key */ hash = strfindattr(k->attr, "hash"); if(hash == nil) hash = "sha1"; @@ -74,20 +125,38 @@ xrsasign(Conv *c) dlen = MD5dlen; }else{ werrstr("unknown hash function %s", hash); - return -1; + goto out; } - c->state = "read data"; - if((n=convread(c, digest, dlen)) < 0){ - keyclose(k); - return -1; + + /* read hash */ + c->state = "read hash"; + if((n=convread(c, digest, dlen)) < 0) + goto out; + + if(strcmp(role, "sign") == 0){ + /* sign */ + if((n=rsasign(key, hashfn, digest, dlen, sig, sizeof sig)) < 0) + goto out; + + /* write */ + convwrite(c, sig, n); + }else{ + /* read signature */ + if((n = convreadm(c, &sig2)) < 0) + goto out; + + /* verify */ + if(rsaverify(&key->pub, hashfn, digest, dlen, (uchar*)sig2, n) == 0) + convprint(c, "ok"); + else + convprint(c, "signature does not verify"); + free(sig2); } - memset(sig, 0xAA, sizeof sig); - n = rsasign(k->priv, hashfn, digest, dlen, sig, sizeof sig); + ret = 0; + +out: keyclose(k); - if(n < 0) - return -1; - convwrite(c, sig, n); - return 0; + return ret; } /* @@ -119,6 +188,9 @@ readrsapriv(Key *k) || (priv->pub.n=strtomp(a, nil, 16, nil))==nil) goto Error; strlwr(a); + if(k->privattr == nil) /* only public half */ + return priv; + if((a=strfindattr(k->privattr, "!p"))==nil || (priv->p=strtomp(a, nil, 16, nil))==nil) goto Error; @@ -177,8 +249,10 @@ rsaclose(Key *k) static Role rsaroles[] = { - "client", rsaclient, "sign", xrsasign, + "verify", xrsasign, /* public operation */ + "decrypt", xrsadecrypt, + "encrypt", xrsadecrypt, /* public operation */ 0 }; |