2 * pageant.c: cross-platform code to implement Pageant.
14 * We need this to link with the RSA code, because rsaencrypt()
15 * pads its data with random bytes. Since we only use rsadecrypt()
16 * and the signing functions, which are deterministic, this should
19 * If it _is_ called, there is a _serious_ problem, because it
20 * won't generate true random numbers. So we must scream, panic,
21 * and exit immediately if that should happen.
25 modalfatalbox("Internal error: attempt to use random numbers in Pageant");
27 return 0; /* unreachable, but placate optimiser */
31 * rsakeys stores SSH-1 RSA keys. ssh2keys stores all SSH-2 keys.
33 static tree234 *rsakeys, *ssh2keys;
36 * Blob structure for passing to the asymmetric SSH-2 key compare
37 * function, prototyped here.
40 const unsigned char *blob;
43 static int cmpkeys_ssh2_asymm(void *av, void *bv);
46 * Key comparison function for the 2-3-4 tree of RSA keys.
48 static int cmpkeys_rsa(void *av, void *bv)
50 struct RSAKey *a = (struct RSAKey *) av;
51 struct RSAKey *b = (struct RSAKey *) bv;
58 * Compare by length of moduli.
60 alen = bignum_bitcount(am);
61 blen = bignum_bitcount(bm);
67 * Now compare by moduli themselves.
69 alen = (alen + 7) / 8; /* byte count */
72 abyte = bignum_byte(am, alen);
73 bbyte = bignum_byte(bm, alen);
76 else if (abyte < bbyte)
86 * Key comparison function for the 2-3-4 tree of SSH-2 keys.
88 static int cmpkeys_ssh2(void *av, void *bv)
90 struct ssh2_userkey *a = (struct ssh2_userkey *) av;
91 struct ssh2_userkey *b = (struct ssh2_userkey *) bv;
94 unsigned char *ablob, *bblob;
98 * Compare purely by public blob.
100 ablob = a->alg->public_blob(a->data, &alen);
101 bblob = b->alg->public_blob(b->data, &blen);
104 for (i = 0; i < alen && i < blen; i++) {
105 if (ablob[i] < bblob[i]) {
108 } else if (ablob[i] > bblob[i]) {
113 if (c == 0 && i < alen)
114 c = +1; /* a is longer */
115 if (c == 0 && i < blen)
116 c = -1; /* a is longer */
125 * Key comparison function for looking up a blob in the 2-3-4 tree
128 static int cmpkeys_ssh2_asymm(void *av, void *bv)
130 struct blob *a = (struct blob *) av;
131 struct ssh2_userkey *b = (struct ssh2_userkey *) bv;
134 const unsigned char *ablob;
135 unsigned char *bblob;
139 * Compare purely by public blob.
143 bblob = b->alg->public_blob(b->data, &blen);
146 for (i = 0; i < alen && i < blen; i++) {
147 if (ablob[i] < bblob[i]) {
150 } else if (ablob[i] > bblob[i]) {
155 if (c == 0 && i < alen)
156 c = +1; /* a is longer */
157 if (c == 0 && i < blen)
158 c = -1; /* a is longer */
166 * Create an SSH-1 key list in a malloc'ed buffer; return its
169 void *pageant_make_keylist1(int *length)
173 unsigned char *blob, *p, *ret;
177 * Count up the number and length of keys we hold.
181 for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
183 blob = rsa_public_blob(key, &bloblen);
186 len += 4 + strlen(key->comment);
189 /* Allocate the buffer. */
190 p = ret = snewn(len, unsigned char);
191 if (length) *length = len;
195 for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
196 blob = rsa_public_blob(key, &bloblen);
197 memcpy(p, blob, bloblen);
200 PUT_32BIT(p, strlen(key->comment));
201 memcpy(p + 4, key->comment, strlen(key->comment));
202 p += 4 + strlen(key->comment);
205 assert(p - ret == len);
210 * Create an SSH-2 key list in a malloc'ed buffer; return its
213 void *pageant_make_keylist2(int *length)
215 struct ssh2_userkey *key;
217 unsigned char *blob, *p, *ret;
221 * Count up the number and length of keys we hold.
225 for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {
227 len += 4; /* length field */
228 blob = key->alg->public_blob(key->data, &bloblen);
231 len += 4 + strlen(key->comment);
234 /* Allocate the buffer. */
235 p = ret = snewn(len, unsigned char);
236 if (length) *length = len;
239 * Packet header is the obvious five bytes, plus four
240 * bytes for the key count.
244 for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {
245 blob = key->alg->public_blob(key->data, &bloblen);
246 PUT_32BIT(p, bloblen);
248 memcpy(p, blob, bloblen);
251 PUT_32BIT(p, strlen(key->comment));
252 memcpy(p + 4, key->comment, strlen(key->comment));
253 p += 4 + strlen(key->comment);
256 assert(p - ret == len);
260 void *pageant_handle_msg(const void *msg, int msglen, int *outlen)
262 const unsigned char *p = msg;
263 const unsigned char *msgend;
264 unsigned char *ret = snewn(AGENT_MAX_MSGLEN, unsigned char);
270 * Get the message type.
277 case SSH1_AGENTC_REQUEST_RSA_IDENTITIES:
279 * Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
285 ret[4] = SSH1_AGENT_RSA_IDENTITIES_ANSWER;
286 keylist = pageant_make_keylist1(&len);
287 if (len + 5 > AGENT_MAX_MSGLEN) {
291 PUT_32BIT(ret, len + 1);
292 memcpy(ret + 5, keylist, len);
296 case SSH2_AGENTC_REQUEST_IDENTITIES:
298 * Reply with SSH2_AGENT_IDENTITIES_ANSWER.
304 ret[4] = SSH2_AGENT_IDENTITIES_ANSWER;
305 keylist = pageant_make_keylist2(&len);
306 if (len + 5 > AGENT_MAX_MSGLEN) {
310 PUT_32BIT(ret, len + 1);
311 memcpy(ret + 5, keylist, len);
315 case SSH1_AGENTC_RSA_CHALLENGE:
317 * Reply with either SSH1_AGENT_RSA_RESPONSE or
318 * SSH_AGENT_FAILURE, depending on whether we have that key
322 struct RSAKey reqkey, *key;
323 Bignum challenge, response;
324 unsigned char response_source[48], response_md5[16];
325 struct MD5Context md5c;
329 i = ssh1_read_bignum(p, msgend - p, &reqkey.exponent);
333 i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus);
335 freebn(reqkey.exponent);
339 i = ssh1_read_bignum(p, msgend - p, &challenge);
341 freebn(reqkey.exponent);
342 freebn(reqkey.modulus);
347 freebn(reqkey.exponent);
348 freebn(reqkey.modulus);
352 memcpy(response_source + 32, p, 16);
356 (key = find234(rsakeys, &reqkey, NULL)) == NULL) {
357 freebn(reqkey.exponent);
358 freebn(reqkey.modulus);
362 response = rsadecrypt(challenge, key);
363 for (i = 0; i < 32; i++)
364 response_source[i] = bignum_byte(response, 31 - i);
367 MD5Update(&md5c, response_source, 48);
368 MD5Final(response_md5, &md5c);
369 smemclr(response_source, 48); /* burn the evidence */
370 freebn(response); /* and that evidence */
371 freebn(challenge); /* yes, and that evidence */
372 freebn(reqkey.exponent); /* and free some memory ... */
373 freebn(reqkey.modulus); /* ... while we're at it. */
376 * Packet is the obvious five byte header, plus sixteen
380 PUT_32BIT(ret, len - 4);
381 ret[4] = SSH1_AGENT_RSA_RESPONSE;
382 memcpy(ret + 5, response_md5, 16);
385 case SSH2_AGENTC_SIGN_REQUEST:
387 * Reply with either SSH2_AGENT_SIGN_RESPONSE or
388 * SSH_AGENT_FAILURE, depending on whether we have that key
392 struct ssh2_userkey *key;
394 const unsigned char *data;
395 unsigned char *signature;
396 int datalen, siglen, len;
400 b.len = toint(GET_32BIT(p));
401 if (b.len < 0 || b.len > msgend - (p+4))
408 datalen = toint(GET_32BIT(p));
410 if (datalen < 0 || datalen > msgend - p)
413 key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
416 signature = key->alg->sign(key->data, (const char *)data,
418 len = 5 + 4 + siglen;
419 PUT_32BIT(ret, len - 4);
420 ret[4] = SSH2_AGENT_SIGN_RESPONSE;
421 PUT_32BIT(ret + 5, siglen);
422 memcpy(ret + 5 + 4, signature, siglen);
426 case SSH1_AGENTC_ADD_RSA_IDENTITY:
428 * Add to the list and return SSH_AGENT_SUCCESS, or
429 * SSH_AGENT_FAILURE if the key was malformed.
436 key = snew(struct RSAKey);
437 memset(key, 0, sizeof(struct RSAKey));
439 n = makekey(p, msgend - p, key, NULL, 1);
447 n = makeprivate(p, msgend - p, key);
455 n = ssh1_read_bignum(p, msgend - p, &key->iqmp); /* p^-1 mod q */
463 n = ssh1_read_bignum(p, msgend - p, &key->p); /* p */
471 n = ssh1_read_bignum(p, msgend - p, &key->q); /* q */
484 commentlen = toint(GET_32BIT(p));
486 if (commentlen < 0 || commentlen > msgend - p) {
492 comment = snewn(commentlen+1, char);
494 memcpy(comment, p + 4, commentlen);
495 comment[commentlen] = '\0';
496 key->comment = comment;
499 ret[4] = SSH_AGENT_FAILURE;
500 if (add234(rsakeys, key) == key) {
502 ret[4] = SSH_AGENT_SUCCESS;
509 case SSH2_AGENTC_ADD_IDENTITY:
511 * Add to the list and return SSH_AGENT_SUCCESS, or
512 * SSH_AGENT_FAILURE if the key was malformed.
515 struct ssh2_userkey *key;
524 alglen = toint(GET_32BIT(p));
526 if (alglen < 0 || alglen > msgend - p)
528 alg = (const char *)p;
531 key = snew(struct ssh2_userkey);
532 /* Add further algorithm names here. */
533 if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))
535 else if (alglen == 7 && !memcmp(alg, "ssh-dss", 7))
537 else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp256", 19))
538 key->alg = &ssh_ecdsa_nistp256;
539 else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp384", 19))
540 key->alg = &ssh_ecdsa_nistp384;
541 else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp521", 19))
542 key->alg = &ssh_ecdsa_nistp521;
548 bloblen = msgend - p;
549 key->data = key->alg->openssh_createkey(&p, &bloblen);
556 * p has been advanced by openssh_createkey, but
557 * certainly not _beyond_ the end of the buffer.
562 key->alg->freekey(key->data);
566 commlen = toint(GET_32BIT(p));
569 if (commlen < 0 || commlen > msgend - p) {
570 key->alg->freekey(key->data);
574 comment = snewn(commlen + 1, char);
576 memcpy(comment, p, commlen);
577 comment[commlen] = '\0';
579 key->comment = comment;
582 ret[4] = SSH_AGENT_FAILURE;
583 if (add234(ssh2keys, key) == key) {
585 ret[4] = SSH_AGENT_SUCCESS;
587 key->alg->freekey(key->data);
593 case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
595 * Remove from the list and return SSH_AGENT_SUCCESS, or
596 * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
600 struct RSAKey reqkey, *key;
603 n = makekey(p, msgend - p, &reqkey, NULL, 0);
607 key = find234(rsakeys, &reqkey, NULL);
608 freebn(reqkey.exponent);
609 freebn(reqkey.modulus);
611 ret[4] = SSH_AGENT_FAILURE;
613 del234(rsakeys, key);
617 ret[4] = SSH_AGENT_SUCCESS;
621 case SSH2_AGENTC_REMOVE_IDENTITY:
623 * Remove from the list and return SSH_AGENT_SUCCESS, or
624 * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
628 struct ssh2_userkey *key;
633 b.len = toint(GET_32BIT(p));
636 if (b.len < 0 || b.len > msgend - p)
641 key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
646 ret[4] = SSH_AGENT_FAILURE;
648 del234(ssh2keys, key);
650 key->alg->freekey(key->data);
652 ret[4] = SSH_AGENT_SUCCESS;
656 case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
658 * Remove all SSH-1 keys. Always returns success.
663 while ((rkey = index234(rsakeys, 0)) != NULL) {
664 del234(rsakeys, rkey);
671 ret[4] = SSH_AGENT_SUCCESS;
674 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
676 * Remove all SSH-2 keys. Always returns success.
679 struct ssh2_userkey *skey;
681 while ((skey = index234(ssh2keys, 0)) != NULL) {
682 del234(ssh2keys, skey);
683 skey->alg->freekey(skey->data);
689 ret[4] = SSH_AGENT_SUCCESS;
695 * Unrecognised message. Return SSH_AGENT_FAILURE.
698 ret[4] = SSH_AGENT_FAILURE;
702 *outlen = 4 + GET_32BIT(ret);
706 void *pageant_failure_msg(int *outlen)
708 unsigned char *ret = snewn(5, unsigned char);
710 ret[4] = SSH_AGENT_FAILURE;
715 void pageant_init(void)
717 rsakeys = newtree234(cmpkeys_rsa);
718 ssh2keys = newtree234(cmpkeys_ssh2);
721 struct RSAKey *pageant_nth_ssh1_key(int i)
723 return index234(rsakeys, i);
726 struct ssh2_userkey *pageant_nth_ssh2_key(int i)
728 return index234(ssh2keys, i);
731 int pageant_count_ssh1_keys(void)
733 return count234(rsakeys);
736 int pageant_count_ssh2_keys(void)
738 return count234(ssh2keys);
741 int pageant_add_ssh1_key(struct RSAKey *rkey)
743 return add234(rsakeys, rkey) != rkey;
746 int pageant_add_ssh2_key(struct ssh2_userkey *skey)
748 return add234(ssh2keys, skey) != skey;
751 int pageant_delete_ssh1_key(struct RSAKey *rkey)
753 struct RSAKey *deleted = del234(rsakeys, rkey);
756 assert(deleted == rkey);
760 int pageant_delete_ssh2_key(struct ssh2_userkey *skey)
762 struct ssh2_userkey *deleted = del234(ssh2keys, skey);
765 assert(deleted == skey);
769 /* ----------------------------------------------------------------------
774 * Coroutine macros similar to, but simplified from, those in ssh.c.
776 #define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
777 #define crFinish(z) } *crLine = 0; return (z); }
778 #define crGetChar(c) do \
781 *crLine =__LINE__; return 1; case __LINE__:; \
784 (c) = (unsigned char)*data++; \
787 struct pageant_conn_state {
788 const struct plug_function_table *fn;
789 /* the above variable absolutely *must* be the first in this structure */
793 void (*logfn)(void *logctx, const char *fmt, ...);
794 unsigned char lenbuf[4], pktbuf[AGENT_MAX_MSGLEN];
797 int crLine; /* for coroutine in pageant_conn_receive */
800 static int pageant_conn_closing(Plug plug, const char *error_msg,
801 int error_code, int calling_back)
803 struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
804 if (error_msg && pc->logfn)
805 pc->logfn(pc->logctx, "Pageant connection socket: %s", error_msg);
806 sk_close(pc->connsock);
811 static void pageant_conn_sent(Plug plug, int bufsize)
813 /* struct pageant_conn_state *pc = (struct pageant_conn_state *)plug; */
816 * We do nothing here, because we expect that there won't be a
817 * need to throttle and unthrottle the connection to an agent -
818 * clients will typically not send many requests, and will wait
819 * until they receive each reply before sending a new request.
823 static int pageant_conn_receive(Plug plug, int urgent, char *data, int len)
825 struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
832 while (pc->got < 4) {
834 pc->lenbuf[pc->got++] = c;
837 pc->len = GET_32BIT(pc->lenbuf);
839 pc->real_packet = (pc->len < AGENT_MAX_MSGLEN-4);
841 while (pc->got < pc->len) {
844 pc->pktbuf[pc->got] = c;
852 if (pc->real_packet) {
853 reply = pageant_handle_msg(pc->pktbuf, pc->len, &replylen);
855 reply = pageant_failure_msg(&replylen);
857 sk_write(pc->connsock, reply, replylen);
858 smemclr(reply, replylen);
865 struct pageant_listen_state {
866 const struct plug_function_table *fn;
867 /* the above variable absolutely *must* be the first in this structure */
871 void (*logfn)(void *logctx, const char *fmt, ...);
874 static int pageant_listen_closing(Plug plug, const char *error_msg,
875 int error_code, int calling_back)
877 struct pageant_listen_state *pl = (struct pageant_listen_state *)plug;
878 if (error_msg && pl->logfn)
879 pl->logfn(pl->logctx, "Pageant listening socket: %s", error_msg);
880 sk_close(pl->listensock);
881 pl->listensock = NULL;
885 static int pageant_listen_accepting(Plug plug,
886 accept_fn_t constructor, accept_ctx_t ctx)
888 static const struct plug_function_table connection_fn_table = {
889 NULL, /* no log function, because that's for outgoing connections */
890 pageant_conn_closing,
891 pageant_conn_receive,
893 NULL /* no accepting function, because we've already done it */
895 struct pageant_listen_state *pl = (struct pageant_listen_state *)plug;
896 struct pageant_conn_state *pc;
899 pc = snew(struct pageant_conn_state);
900 pc->fn = &connection_fn_table;
901 pc->logfn = pl->logfn;
902 pc->logctx = pl->logctx;
905 pc->connsock = constructor(ctx, (Plug) pc);
906 if ((err = sk_socket_error(pc->connsock)) != NULL) {
907 sk_close(pc->connsock);
912 sk_set_frozen(pc->connsock, 0);
914 /* FIXME: can we get any useful peer id info? */
916 pl->logfn(pl->logctx, "Pageant socket connected");
921 struct pageant_listen_state *pageant_listener_new
922 (void *logctx, void (*logfn)(void *logctx, const char *fmt, ...))
924 static const struct plug_function_table listener_fn_table = {
925 NULL, /* no log function, because that's for outgoing connections */
926 pageant_listen_closing,
927 NULL, /* no receive function on a listening socket */
928 NULL, /* no sent function on a listening socket */
929 pageant_listen_accepting
932 struct pageant_listen_state *pl = snew(struct pageant_listen_state);
933 pl->fn = &listener_fn_table;
936 pl->listensock = NULL;
940 void pageant_listener_got_socket(struct pageant_listen_state *pl, Socket sock)
942 pl->listensock = sock;
945 void pageant_listener_free(struct pageant_listen_state *pl)
948 sk_close(pl->listensock);