- case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
- /*
- * Reply with SSH_AGENT_RSA_IDENTITIES_ANSWER.
- */
- {
- enum234 e;
- struct RSAKey *key;
- int len, nkeys;
-
- /*
- * Count up the number and length of keys we hold.
- */
- len = nkeys = 0;
- for (key = first234(rsakeys, &e); key; key = next234(&e)) {
- 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 ((ret = malloc(len)) != NULL) {
- PUT_32BIT(ret, len-4);
- ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER;
- PUT_32BIT(ret+5, nkeys);
- p = ret + 5 + 4;
- for (key = first234(rsakeys, &e); key; key = next234(&e)) {
- PUT_32BIT(p, ssh1_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 SSH_AGENTC_RSA_CHALLENGE:
- /*
- * Reply with either SSH_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;
- if ((ret = malloc(len)) != NULL) {
- PUT_32BIT(ret, len-4);
- ret[4] = SSH_AGENT_RSA_RESPONSE;
- memcpy(ret+5, response_md5, 16);
- }
- }
- break;
-#if 0 /* FIXME: implement these */
- case SSH_AGENTC_ADD_RSA_IDENTITY:
- /*
- * Add to the list and return SSH_AGENT_SUCCESS, or
- * SSH_AGENT_FAILURE if the key was malformed.
- */
- break;
- case SSH_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.
- */
- break;
-#endif
- default:
- failure:
- /*
- * Unrecognised message. Return SSH_AGENT_FAILURE.
- */
- if ((ret = malloc(5)) != NULL) {
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_FAILURE;
- }
- break;
- }
+ 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;