p += ssh1_read_bignum(p, key->iqmp);	 p += ssh1_read_bignum(p, key->p);	 p += ssh1_read_bignum(p, key->q);	 comment = smalloc(GET_32BIT(p));
p += ssh1_read_bignum(p, &key->iqmp);	 p += ssh1_read_bignum(p, &key->p);	 p += ssh1_read_bignum(p, &key->q);	 commentlen = GET_32BIT(p); comment = smalloc(commentlen+1);
static void answer_msg(void *msg){    unsigned char *p = msg;    unsigned char *ret = msg;    int type;    /*     * Get the message type.     */    type = p[4];    p += 5;    switch (type) {      case SSH1_AGENTC_REQUEST_RSA_IDENTITIES:	/*	 * Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.	 */	{	    struct RSAKey *key;	    int len, nkeys;	    int i;	    /*	     * Count up the number and length of keys we hold.	     */	    len = nkeys = 0;	    for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {		nkeys++;		len += 4;	       /* length field */		len += ssh1_bignum_length(key->exponent);		len += ssh1_bignum_length(key->modulus);		len += 4 + strlen(key->comment);	    }	    /*	     * Packet header is the obvious five bytes, plus four	     * bytes for the key count.	     */	    len += 5 + 4;	    if (len > AGENT_MAX_MSGLEN)		goto failure;	       /* aaargh! too much stuff! */	    PUT_32BIT(ret, len - 4);	    ret[4] = SSH1_AGENT_RSA_IDENTITIES_ANSWER;	    PUT_32BIT(ret + 5, nkeys);	    p = ret + 5 + 4;	    for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {		PUT_32BIT(p, bignum_bitcount(key->modulus));		p += 4;		p += ssh1_write_bignum(p, key->exponent);		p += ssh1_write_bignum(p, key->modulus);		PUT_32BIT(p, strlen(key->comment));		memcpy(p + 4, key->comment, strlen(key->comment));		p += 4 + strlen(key->comment);	    }	}	break;      case SSH2_AGENTC_REQUEST_IDENTITIES:	/*	 * Reply with SSH2_AGENT_IDENTITIES_ANSWER.	 */	{	    struct ssh2_userkey *key;	    int len, nkeys;	    unsigned char *blob;	    int bloblen;	    int i;	    /*	     * Count up the number and length of keys we hold.	     */	    len = nkeys = 0;	    for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {		nkeys++;		len += 4;	       /* length field */		blob = key->alg->public_blob(key->data, &bloblen);		len += bloblen;		sfree(blob);		len += 4 + strlen(key->comment);	    }	    /*	     * Packet header is the obvious five bytes, plus four	     * bytes for the key count.	     */	    len += 5 + 4;	    if (len > AGENT_MAX_MSGLEN)		goto failure;	       /* aaargh! too much stuff! */	    PUT_32BIT(ret, len - 4);	    ret[4] = SSH2_AGENT_IDENTITIES_ANSWER;	    PUT_32BIT(ret + 5, nkeys);	    p = ret + 5 + 4;	    for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {		blob = key->alg->public_blob(key->data, &bloblen);		PUT_32BIT(p, bloblen);		p += 4;		memcpy(p, blob, bloblen);		p += bloblen;		sfree(blob);		PUT_32BIT(p, strlen(key->comment));		memcpy(p + 4, key->comment, strlen(key->comment));		p += 4 + strlen(key->comment);	    }	}	break;      case SSH1_AGENTC_RSA_CHALLENGE:	/*	 * Reply with either SSH1_AGENT_RSA_RESPONSE or	 * SSH_AGENT_FAILURE, depending on whether we have that key	 * or not.	 */	{	    struct RSAKey reqkey, *key;	    Bignum challenge, response;	    unsigned char response_source[48], response_md5[16];	    struct MD5Context md5c;	    int i, len;	    p += 4;	    p += ssh1_read_bignum(p, &reqkey.exponent);	    p += ssh1_read_bignum(p, &reqkey.modulus);	    p += ssh1_read_bignum(p, &challenge);	    memcpy(response_source + 32, p, 16);	    p += 16;	    if (GET_32BIT(p) != 1 ||		(key = find234(rsakeys, &reqkey, NULL)) == NULL) {		freebn(reqkey.exponent);		freebn(reqkey.modulus);		freebn(challenge);		goto failure;	    }	    response = rsadecrypt(challenge, key);	    for (i = 0; i < 32; i++)		response_source[i] = bignum_byte(response, 31 - i);	    MD5Init(&md5c);	    MD5Update(&md5c, response_source, 48);	    MD5Final(response_md5, &md5c);	    memset(response_source, 0, 48);	/* burn the evidence */	    freebn(response);	       /* and that evidence */	    freebn(challenge);	       /* yes, and that evidence */	    freebn(reqkey.exponent);   /* and free some memory ... */	    freebn(reqkey.modulus);    /* ... while we're at it. */	    /*	     * Packet is the obvious five byte header, plus sixteen	     * bytes of MD5.	     */	    len = 5 + 16;	    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);	    }	}	break;      case SSH2_AGENTC_ADD_IDENTITY:	/*	 * Add to the list and return SSH_AGENT_SUCCESS, or	 * SSH_AGENT_FAILURE if the key was malformed.	 */	{	    struct ssh2_userkey *key;	    char *comment, *alg;	    int alglen, commlen;	    int bloblen;	    key = smalloc(sizeof(struct ssh2_userkey));	    alglen = GET_32BIT(p);	    p += 4;	    alg = p;	    p += alglen;	    /* Add further algorithm names here. */	    if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))		key->alg = &ssh_rsa;	    else {		sfree(key);		goto failure;	    }	    bloblen =		GET_32BIT((unsigned char *) msg) - (p -						    (unsigned char *) msg -						    4);	    key->data = key->alg->openssh_createkey(&p, &bloblen);	    if (!key->data) {		sfree(key);		goto failure;	    }	    commlen = GET_32BIT(p);	    p += 4;	    comment = smalloc(commlen + 1);	    if (comment) {		memcpy(comment, p, commlen);		comment[commlen] = '\0';	    }	    key->comment = comment;	    PUT_32BIT(ret, 1);	    ret[4] = SSH_AGENT_FAILURE;	    if (add234(ssh2keys, key) == key) {		keylist_update();		ret[4] = SSH_AGENT_SUCCESS;	    } else {		key->alg->freekey(key->data);		sfree(key->comment);		sfree(key);	    }	}	break;      case SSH1_AGENTC_REMOVE_RSA_IDENTITY:	/*	 * Remove from the list and return SSH_AGENT_SUCCESS, or	 * perhaps SSH_AGENT_FAILURE if it wasn't in the list to	 * start with.	 */	{	    struct RSAKey reqkey, *key;	    p += makekey(p, &reqkey, NULL, 0);	    key = find234(rsakeys, &reqkey, NULL);	    freebn(reqkey.exponent);	    freebn(reqkey.modulus);	    PUT_32BIT(ret, 1);	    ret[4] = SSH_AGENT_FAILURE;	    if (key) {		del234(rsakeys, key);		keylist_update();		freersakey(key);		sfree(key);		ret[4] = SSH_AGENT_SUCCESS;	    }	}	break;      case SSH2_AGENTC_REMOVE_IDENTITY:	/*	 * Remove from the list and return SSH_AGENT_SUCCESS, or	 * perhaps SSH_AGENT_FAILURE if it wasn't in the list to	 * start with.	 */	{	    struct ssh2_userkey *key;	    struct blob b;	    b.len = GET_32BIT(p);	    p += 4;	    b.blob = p;	    p += b.len;	    key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);	    if (!key)		goto failure;	    PUT_32BIT(ret, 1);	    ret[4] = SSH_AGENT_FAILURE;	    if (key) {		del234(ssh2keys, key);		keylist_update();		key->alg->freekey(key->data);		sfree(key);		ret[4] = SSH_AGENT_SUCCESS;	    }	}	break;      case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:	/*	 * Remove all SSH1 keys. Always returns success.	 */	{	    struct RSAKey *rkey;	    while ((rkey = index234(rsakeys, 0)) != NULL) {		del234(rsakeys, rkey);		freersakey(rkey);		sfree(rkey);	    }	    keylist_update();	    PUT_32BIT(ret, 1);	    ret[4] = SSH_AGENT_SUCCESS;	}	break;      case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:	/*	 * Remove all SSH2 keys. Always returns success.	 */	{	    struct ssh2_userkey *skey;	    while ((skey = index234(ssh2keys, 0)) != NULL) {		del234(ssh2keys, skey);		skey->alg->freekey(skey->data);		sfree(skey);	    }	    keylist_update();	    PUT_32BIT(ret, 1);	    ret[4] = SSH_AGENT_SUCCESS;	}	break;      default:      failure:	/*	 * Unrecognised message. Return SSH_AGENT_FAILURE.	 */	PUT_32BIT(ret, 1);	ret[4] = SSH_AGENT_FAILURE;	break;    }}