+ PUT_32BIT(ret, len-4);
+ ret[4] = SSH1_AGENT_RSA_RESPONSE;
+ memcpy(ret+5, response_md5, 16);
+ }
+ break;
+ case SSH2_AGENTC_SIGN_REQUEST:
+ /*
+ * Reply with either SSH2_AGENT_RSA_RESPONSE or
+ * SSH_AGENT_FAILURE, depending on whether we have that key
+ * or not.
+ */
+ {
+ struct ssh2_userkey *key;
+ struct blob b;
+ unsigned char *data, *signature;
+ int datalen, siglen, len;
+
+ b.len = GET_32BIT(p);
+ p += 4;
+ b.blob = p;
+ p += b.len;
+ datalen = GET_32BIT(p);
+ p += 4;
+ data = p;
+ key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
+ if (!key)
+ goto failure;
+ signature = key->alg->sign(key->data, data, datalen, &siglen);
+ len = 5+4+siglen;
+ PUT_32BIT(ret, len-4);
+ ret[4] = SSH2_AGENT_SIGN_RESPONSE;
+ PUT_32BIT(ret+5, siglen);
+ memcpy(ret+5+4, signature, siglen);
+ sfree(signature);
+ }
+ break;
+ case SSH1_AGENTC_ADD_RSA_IDENTITY:
+ /*
+ * Add to the list and return SSH_AGENT_SUCCESS, or
+ * SSH_AGENT_FAILURE if the key was malformed.
+ */
+ {
+ struct RSAKey *key;
+ char *comment;
+ key = smalloc(sizeof(struct RSAKey));
+ memset(key, 0, sizeof(key));
+ p += makekey(p, key, NULL, 1);
+ p += makeprivate(p, key);
+ p += ssh1_read_bignum(p, key->iqmp); /* p^-1 mod q */
+ p += ssh1_read_bignum(p, key->p); /* p */
+ p += ssh1_read_bignum(p, key->q); /* q */
+ comment = smalloc(GET_32BIT(p));
+ if (comment) {
+ memcpy(comment, p+4, GET_32BIT(p));
+ key->comment = comment;
+ }
+ PUT_32BIT(ret, 1);
+ ret[4] = SSH_AGENT_FAILURE;
+ if (add234(rsakeys, key) == key) {
+ keylist_update();
+ ret[4] = SSH_AGENT_SUCCESS;
+ } else {
+ freersakey(key);
+ sfree(key);