- if (i < 0)
- die("error waiting for reply: %s", strerror(errno));
-
- /* --- A reply should be waiting now --- */
-
- {
- struct sockaddr_in sin;
- int slen = sizeof(sin);
- unsigned char buff[256];
- int answer;
-
- /* --- Read the reply data --- */
-
- if (recvfrom(fd, (char *)buff, sizeof(buff), 0,
- (struct sockaddr *)&sin, &slen) < 0)
- die("error reading server's reply: %s", strerror(errno));
-
- IF_TRACING(TRACE_CLIENT, {
- struct hostent *h = gethostbyaddr((char *)&sin.sin_addr,
- sizeof(sin.sin_addr), AF_INET);
- trace(TRACE_CLIENT, "client: reply received from %s port %i",
- h ? h->h_name : inet_ntoa(sin.sin_addr),
- ntohs(sin.sin_port));
- })
-
- /* --- Verify the sender --- *
- *
- * This is more to avoid confusion than for security: an active
- * attacker is quite capable of forging the source address. We rely
- * on the checksum in the reply packet for authentication.
- */
-
- for (i = 0; i < n_serv; i++) {
- if (sin.sin_addr.s_addr == serv[i].sin_addr.s_addr &&
- sin.sin_port == serv[i].sin_port)
- break;
- }
- if (i >= n_serv) {
- T( trace(TRACE_CLIENT, "client: reply from unknown host"); )
- continue;
- }
-
- /* --- Unpack and verify the response --- */
-
- answer = crypt_unpackReply(buff, sk, t, pid);
- if (answer < 0) {
- T( trace(TRACE_CLIENT,
- "client: invalid or corrupt reply packet"); )
- continue;
- }
- return (answer);
- }
+
+ /* --- Unpack the key --- */
+
+ p = key_getattr(&f, k, "sig");
+ if (!p || strcmp(p, "dsa") == 0) {
+ dh_pub dp;
+ kp = key_fetchinit(dh_pubfetch, 0, &dp);
+ if (key_fetch(kp, k)) goto fail_1;
+ if ((g.g = group_prime(&dp.dp)) == 0) goto fail_1;
+ g.p = G_CREATE(g.g);
+ if (G_FROMINT(g.g, g.p, dp.y)) goto fail_2;
+ } else if (strcmp(p, "ecdsa") == 0) {
+ ec_pub ep;
+ ec_info ei;
+ kp = key_fetchinit(ec_pubfetch, 0, &ep);
+ if (key_fetch(kp, k)) goto fail_1;
+ if (ec_getinfo(&ei, ep.cstr)) goto fail_1;
+ g.g = group_ec(&ei);
+ g.p = G_CREATE(g.g);
+ if (G_FROMEC(g.g, g.p, &ep.p)) goto fail_2;
+ } else
+ goto fail_0;
+
+ /* --- Unpack the response --- */
+
+ h = GH_INIT(g.h);
+ GH_HASH(h, buff, rqlen);
+ buf_init(&b, rbuff, sz);
+ if (buf_ensure(&b, g.h->hashsz)) goto fail_3;
+ if (memcmp(BCUR(&b), GH_DONE(h, 0), g.h->hashsz) != 0) goto fail_3;
+ BSTEP(&b, g.h->hashsz);
+ if ((ans = buf_getbyte(&b)) < 0) goto fail_3;
+ GH_DESTROY(h);
+
+ /* --- Verify the signature --- */
+
+ h = gdsa_beginhash(&g);
+ GH_HASH(h, BBASE(&b), BLEN(&b));
+ gdsa_endhash(&g, h);
+ s.r = s.s = 0;
+ if ((s.r = buf_getmp(&b)) == 0 ||
+ (s.s = buf_getmp(&b)) == 0)
+ goto fail_4;
+ if (gdsa_verify(&g, &s, GH_DONE(h, 0)))
+ goto fail_4;
+
+ mp_drop(s.r); mp_drop(s.s);
+ GH_DESTROY(h);
+ G_DESTROY(g.g, g.p);
+ G_DESTROYGROUP(g.g);
+ key_fetchdone(kp);
+ key_close(&f);
+ return (ans);
+
+ /* --- Tidy up and try again --- */
+
+ fail_4:
+ mp_drop(s.r); mp_drop(s.s);
+ fail_3:
+ GH_DESTROY(h);
+ G_DESTROY(g.g, g.p);
+ fail_2:
+ G_DESTROYGROUP(g.g);
+ fail_1:
+ key_fetchdone(kp);
+ fail_0:
+ continue;