From deengert at gmail.com Wed Apr 1 00:10:08 2015 From: deengert at gmail.com (Douglas E Engert) Date: Tue, 31 Mar 2015 08:10:08 -0500 Subject: Wanted: smartcard with ECDSA support In-Reply-To: References: Message-ID: <551A9CB0.6060103@gmail.com> On 3/31/2015 4:23 AM, Thomas Calderon wrote: > Hi list, > > I have no idea if Damien Miller had the time to work on that. > > I have an initial patch to authenticate using PKCS#11 and ECDSA keys. > This requires OpenSSL 1.0.2, prior OpenSSL versions do not expose the > required interfaces to override the signature function pointer for ECDSA. > The only limitation is that the OpenSSL API misses some cleanup function > (finish, for instance), hence I have yet to find a way to properly free the > PKCS#11 resources. OpenSC, engine_opensc and libp11 versions on github can use OpenSSL-1.0.2 with ECDSA. They have the similar problems with memory leaks and ECDSA. But they do work, if you can live with the memory leaks,for example to sign a certificate request with ECDSA. > > Is this a contribution you might be interested in ? Any OpenSSL code to call PKCS#11 directly and eliminate the need for the engine_opensc would welcome. > > > Cheers, > > Thomas Calderon > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > -- Douglas E. Engert From calderon.thomas at gmail.com Wed Apr 1 03:02:42 2015 From: calderon.thomas at gmail.com (Thomas Calderon) Date: Tue, 31 Mar 2015 18:02:42 +0200 Subject: Wanted: smartcard with ECDSA support In-Reply-To: <551A9CB0.6060103@gmail.com> References: <551A9CB0.6060103@gmail.com> Message-ID: On Tue, Mar 31, 2015 at 3:10 PM, Douglas E Engert wrote: > > > On 3/31/2015 4:23 AM, Thomas Calderon wrote: > >> Hi list, >> >> I have no idea if Damien Miller had the time to work on that. >> >> I have an initial patch to authenticate using PKCS#11 and ECDSA keys. >> This requires OpenSSL 1.0.2, prior OpenSSL versions do not expose the >> required interfaces to override the signature function pointer for ECDSA. >> The only limitation is that the OpenSSL API misses some cleanup function >> (finish, for instance), hence I have yet to find a way to properly free >> the >> PKCS#11 resources. >> > > OpenSC, engine_opensc and libp11 versions on github can use OpenSSL-1.0.2 > with ECDSA. > They have the similar problems with memory leaks and ECDSA. But they do > work, > if you can live with the memory leaks,for example to sign a certificate > request > with ECDSA. Well this might be an issue to have the code integrated upstream in OpenSSH. It is a shame that there isn't a clean way to do it. I will try to think of a better approach. In the meantime, I'll integrate it as cleanly as possible and submit it as it is so we can keep a trace of it. > > > >> Is this a contribution you might be interested in ? >> > > Any OpenSSL code to call PKCS#11 directly and eliminate the need for the > engine_opensc > would welcome. > > Sure, the same approach can be used in PKI scenarios to generate a CSR and sign it in an OpenSSL context. > >> >> Cheers, >> >> Thomas Calderon >> _______________________________________________ >> openssh-unix-dev mailing list >> openssh-unix-dev at mindrot.org >> https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev >> >> > -- > > Douglas E. Engert > > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > From deengert at gmail.com Wed Apr 1 03:47:35 2015 From: deengert at gmail.com (Douglas E Engert) Date: Tue, 31 Mar 2015 11:47:35 -0500 Subject: Wanted: smartcard with ECDSA support In-Reply-To: References: <551A9CB0.6060103@gmail.com> Message-ID: <551ACFA7.4090506@gmail.com> On 3/31/2015 11:02 AM, Thomas Calderon wrote: > > > On Tue, Mar 31, 2015 at 3:10 PM, Douglas E Engert > wrote: > > > > On 3/31/2015 4:23 AM, Thomas Calderon wrote: > > Hi list, > > I have no idea if Damien Miller had the time to work on that. > > I have an initial patch to authenticate using PKCS#11 and ECDSA keys. > This requires OpenSSL 1.0.2, prior OpenSSL versions do not expose the > required interfaces to override the signature function pointer for ECDSA. > The only limitation is that the OpenSSL API misses some cleanup function > (finish, for instance), hence I have yet to find a way to properly free the > PKCS#11 resources. > > > OpenSC, engine_opensc and libp11 versions on github can use OpenSSL-1.0.2 with ECDSA. > They have the similar problems with memory leaks and ECDSA. But they do work, > if you can live with the memory leaks,for example to sign a certificate request > with ECDSA. > > > Well this might be an issue to have the code integrated upstream in OpenSSH. > It is a shame that there isn't a clean way to do it. I will try to think of a better approach. > In the meantime, I'll integrate it as cleanly as possible and submit it as it is so we can keep a trace of it. > > > > > Is this a contribution you might be interested in ? > > > Any OpenSSL code to call PKCS#11 directly and eliminate the need for the engine_opensc > would welcome. > > > Sure, the same approach can be used in PKI scenarios to generate a CSR and sign it in an OpenSSL context. I am on the OpenSC, OpenSSL and OpenSSH lists. When I responded to you I was thinking the message was from the OpenSSL list, thus the comments about PKCS#11 and OpenSSL. Sorry about the confusion. You are right in that the OpenSSL does miss some cleanup for ECC.See OpenSSL bug report on ECC METHOD code committed and comment on no init and finish: http://rt.openssl.org/Ticket/Display.html?id=2459#txn-50343 > > > > Cheers, > > Thomas Calderon > _________________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/__mailman/listinfo/openssh-unix-__dev > > > -- > > Douglas E. Engert > > > _________________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/__mailman/listinfo/openssh-unix-__dev > > -- Douglas E. Engert From mfriedl at gmail.com Wed Apr 1 04:25:33 2015 From: mfriedl at gmail.com (Markus Friedl) Date: Tue, 31 Mar 2015 19:25:33 +0200 Subject: Wanted: smartcard with ECDSA support In-Reply-To: References: Message-ID: <961045BD-68C0-4617-9004-D6C17662ADB3@gmail.com> Pedro has a working patch that I plan to integrate in the near future. It uses his recent cardos 5 code in opensc. > Am 31.03.2015 um 11:23 schrieb Thomas Calderon : > > Hi list, > > I have no idea if Damien Miller had the time to work on that. > > I have an initial patch to authenticate using PKCS#11 and ECDSA keys. > This requires OpenSSL 1.0.2, prior OpenSSL versions do not expose the > required interfaces to override the signature function pointer for ECDSA. > The only limitation is that the OpenSSL API misses some cleanup function > (finish, for instance), hence I have yet to find a way to properly free the > PKCS#11 resources. > > Is this a contribution you might be interested in ? > > > Cheers, > > Thomas Calderon > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev From pedro at ambientworks.net Wed Apr 1 05:26:05 2015 From: pedro at ambientworks.net (Pedro Martelletto) Date: Tue, 31 Mar 2015 20:26:05 +0200 Subject: Wanted: smartcard with ECDSA support In-Reply-To: <961045BD-68C0-4617-9004-D6C17662ADB3@gmail.com> References: <961045BD-68C0-4617-9004-D6C17662ADB3@gmail.com> Message-ID: <20150331182603.GA12390@triangle.ambientworks.net> Hi, Here's a copy of the mail sent to Markus, Damien and Miod back in December. It is also available at the following URL: http://ambientworks.net/ecdsa-ssh.txt The OpenSC work mentioned by Markus can be found at: https://github.com/OpenSC/OpenSC/pull/283 -p. >From pedro at ambientworks.net Thu Dec 18 18:05:54 2014 Return-Path: Received: from triangle.ambientworks.net (ambientworks.net. [195.154.11.238]) by mx.google.com with ESMTPSA id dp8sm25399482wib.20.2014.12.18.09.05.53 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Dec 2014 09:05:54 -0800 (PST) Date: Thu, 18 Dec 2014 18:05:09 +0100 From: pedro martelletto To: djm at openbsd.org, miod at openbsd.org, markus at openbsd.org Subject: PKCS#11 ECDSA support in OpenSSH, and related LibreSSL changes Message-ID: <20141218170508.GA25923 at triangle.ambientworks.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline Hi Damien and Miod, I have recently worked with Markus on implementing PKCS#11 ECDSA support in OpenSSH. In order to do this, we needed to be able to wrap ECDSA key objects, providing them with a customised callback for signing. This, however, wasn't possible due to the definition of ECDSA_METHOD not being exported by LibreSSL. We then looked around and found this OpenSSL bug report [1] which, after remaining inactive for years, was finally updated yesterday, 2014-12-17. As can be seen in the commits linked from the bug report [2,3], the course taken by OpenSSL was diferent than the one adopted by LibreSSL [4]. Whether or not OpenSSL's decision makes sense, I am not sure. It would arguably make sense though, for the sake of a similar API, for LibreSSL to provide the same set of functions. In the first of the three patches inlined below, I took the interim decision of reverting Miod's commit to expose ECDSA_METHOD, with the understanding that it would be best to copy the OpenSSL commits verbatim and leave any merging decisions up to you. The second diff consists of an amalgamation of the two OpenSSL commits [2,3]. Finally, the third diff implements the PKCS#11 ECDSA bits in OpenSSH. Warm regards and season's greetings! :) -p. [1] http://rt.openssl.org/Ticket/Display.html?id=2459&user=guest&pass=guest [2] https://github.com/openssl/openssl/commit/94c2f77a [3] https://github.com/openssl/openssl/commit/387b844f [4] http://freshbsd.org/commit/openbsd/1c8c6abf87634651e430450659b62b34a2cb63aa commit 1623ab45684d7bd034001d518d70ec250de7d398 Author: pedro martelletto Date: Thu Dec 18 17:13:19 2014 +0100 Revert "Make the ECDSA_SIG bowels public. This matches RSA_SIG and DSA_SIG, and we" This reverts commit 7075e35e197bdac9ca93b09442bc1b2436fc94e8. diff --git lib/libssl/src/crypto/ecdsa/ecdsa.h lib/libssl/src/crypto/ecdsa/ecdsa.h index ad716c2..a29e5f6 100644 --- lib/libssl/src/crypto/ecdsa/ecdsa.h +++ lib/libssl/src/crypto/ecdsa/ecdsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ecdsa.h,v 1.3 2014/11/17 20:25:50 miod Exp $ */ +/* $OpenBSD: ecdsa.h,v 1.2 2014/06/12 15:49:29 deraadt Exp $ */ /** * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions * \author Written by Nils Larsch for the OpenSSL project @@ -75,36 +75,11 @@ extern "C" { #endif -typedef struct ECDSA_SIG_st ECDSA_SIG; - -struct ecdsa_method { - const char *name; - ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len, - const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey); - int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, - BIGNUM **r); - int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, - const ECDSA_SIG *sig, EC_KEY *eckey); -#if 0 - int (*init)(EC_KEY *eckey); - int (*finish)(EC_KEY *eckey); -#endif - int flags; - char *app_data; -}; - -/* If this flag is set the ECDSA method is FIPS compliant and can be used - * in FIPS mode. This is set in the validated module method. If an - * application sets this flag in its own methods it is its responsibility - * to ensure the result is compliant. - */ - -#define ECDSA_FLAG_FIPS_METHOD 0x1 - -struct ECDSA_SIG_st { +typedef struct ECDSA_SIG_st + { BIGNUM *r; BIGNUM *s; -}; + } ECDSA_SIG; /** Allocates and initialize a ECDSA_SIG structure * \return pointer to a ECDSA_SIG structure or NULL if an error occurred diff --git lib/libssl/src/crypto/ecdsa/ecs_locl.h lib/libssl/src/crypto/ecdsa/ecs_locl.h index e47f679..ceae6a2 100644 --- lib/libssl/src/crypto/ecdsa/ecs_locl.h +++ lib/libssl/src/crypto/ecdsa/ecs_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ecs_locl.h,v 1.3 2014/11/17 20:25:50 miod Exp $ */ +/* $OpenBSD: ecs_locl.h,v 1.2 2014/06/12 15:49:29 deraadt Exp $ */ /* * Written by Nils Larsch for the OpenSSL project */ @@ -65,6 +65,31 @@ extern "C" { #endif +struct ecdsa_method + { + const char *name; + ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len, + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey); + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, + BIGNUM **r); + int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); +#if 0 + int (*init)(EC_KEY *eckey); + int (*finish)(EC_KEY *eckey); +#endif + int flags; + char *app_data; + }; + +/* If this flag is set the ECDSA method is FIPS compliant and can be used + * in FIPS mode. This is set in the validated module method. If an + * application sets this flag in its own methods it is its responsibility + * to ensure the result is compliant. + */ + +#define ECDSA_FLAG_FIPS_METHOD 0x1 + typedef struct ecdsa_data_st { /* EC_KEY_METH_DATA part */ int (*init)(EC_KEY *); commit d5a744b7d8b98997f0f69be3afbcde5b369f2634 Author: pedro martelletto Date: Thu Dec 18 10:43:16 2014 +0100 Add functions to set ECDSA_METHOD structure. From OpenSSL commits 94c2f77a and 387b844f, issue #2459: "Add various functions to allocate and set the fields of an ECDSA_METHOD structure." diff --git lib/libssl/src/crypto/ecdsa/ecdsa.h lib/libssl/src/crypto/ecdsa/ecdsa.h index a29e5f6..a495984 100644 --- lib/libssl/src/crypto/ecdsa/ecdsa.h +++ lib/libssl/src/crypto/ecdsa/ecdsa.h @@ -229,6 +229,74 @@ int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg); void *ECDSA_get_ex_data(EC_KEY *d, int idx); +/** Allocates and initialize a ECDSA_METHOD structure + * \param ecdsa_method pointer to ECDSA_METHOD to copy. (May be NULL) + * \return pointer to a ECDSA_METHOD structure or NULL if an error occurred + */ + +ECDSA_METHOD *ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_method); + +/** frees a ECDSA_METHOD structure + * \param ecdsa_method pointer to the ECDSA_METHOD structure + */ +void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method); + +/** Sets application specific data in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param app application specific data to set + */ + +void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app); + +/** Returns application specific data from a ECDSA_METHOD structure + * \param ecdsa_method pointer to ECDSA_METHOD structure + * \return pointer to application specific data. + */ + + +void * ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method); + +/** Set the ECDSA_do_sign function in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param ecdsa_do_sign a funtion of type ECDSA_do_sign + */ + +void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method, + ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len, + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey)); + +/** Set the ECDSA_sign_setup function in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param ecdsa_sign_setup a funtion of type ECDSA_sign_setup + */ + +void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method, + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, + BIGNUM **r)); + +/** Set the ECDSA_do_verify function in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param ecdsa_do_verify a funtion of type ECDSA_do_verify + */ + +void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method, + int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey)); + +void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags); + +/** Set the flags field in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param flags flags value to set + */ + +void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name); + +/** Set the name field in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param name name to set + */ + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. @@ -242,6 +310,7 @@ void ERR_load_ECDSA_strings(void); #define ECDSA_F_ECDSA_DATA_NEW_METHOD 100 #define ECDSA_F_ECDSA_DO_SIGN 101 #define ECDSA_F_ECDSA_DO_VERIFY 102 +#define ECDSA_F_ECDSA_METHOD_NEW 105 #define ECDSA_F_ECDSA_SIGN_SETUP 103 /* Reason codes. */ diff --git lib/libssl/src/crypto/ecdsa/ecs_err.c lib/libssl/src/crypto/ecdsa/ecs_err.c index 721b53c..1400f34 100644 --- lib/libssl/src/crypto/ecdsa/ecs_err.c +++ lib/libssl/src/crypto/ecdsa/ecs_err.c @@ -77,6 +77,7 @@ static ERR_STRING_DATA ECDSA_str_functs[]= {ERR_FUNC(ECDSA_F_ECDSA_DATA_NEW_METHOD), "ECDSA_DATA_NEW_METHOD"}, {ERR_FUNC(ECDSA_F_ECDSA_DO_SIGN), "ECDSA_do_sign"}, {ERR_FUNC(ECDSA_F_ECDSA_DO_VERIFY), "ECDSA_do_verify"}, +{ERR_FUNC(ECDSA_F_ECDSA_METHOD_NEW), "ECDSA_METHOD_new"}, {ERR_FUNC(ECDSA_F_ECDSA_SIGN_SETUP), "ECDSA_sign_setup"}, {0,NULL} }; diff --git lib/libssl/src/crypto/ecdsa/ecs_lib.c lib/libssl/src/crypto/ecdsa/ecs_lib.c index a92d611..38756fa 100644 --- lib/libssl/src/crypto/ecdsa/ecs_lib.c +++ lib/libssl/src/crypto/ecdsa/ecs_lib.c @@ -266,3 +266,76 @@ void *ECDSA_get_ex_data(EC_KEY *d, int idx) return NULL; return(CRYPTO_get_ex_data(&ecdsa->ex_data,idx)); } + +ECDSA_METHOD *ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_meth) + { + ECDSA_METHOD *ret; + + ret = malloc(sizeof(ECDSA_METHOD)); + if (ret == NULL) + { + ECDSAerr(ECDSA_F_ECDSA_METHOD_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (ecdsa_meth) + *ret = *ecdsa_meth; + else + { + ret->ecdsa_sign_setup = 0; + ret->ecdsa_do_sign = 0; + ret->ecdsa_do_verify = 0; + ret->name = NULL; + ret->flags = 0; + } + ret->flags |= ECDSA_METHOD_FLAG_ALLOCATED; + return ret; + } + + +void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method, + ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len, + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey)) + { + ecdsa_method->ecdsa_do_sign = ecdsa_do_sign; + } + +void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method, + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, + BIGNUM **r)) + { + ecdsa_method->ecdsa_sign_setup = ecdsa_sign_setup; + } + +void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method, + int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey)) + { + ecdsa_method->ecdsa_do_verify = ecdsa_do_verify; + } + +void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags) + { + ecdsa_method->flags = flags | ECDSA_METHOD_FLAG_ALLOCATED; + } + +void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name) + { + ecdsa_method->name = name; + } + +void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method) + { + if (ecdsa_method->flags & ECDSA_METHOD_FLAG_ALLOCATED) + free(ecdsa_method); + } + +void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app) + { + ecdsa_method->app_data = app; + } + +void * ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method) + { + return ecdsa_method->app_data; + } diff --git lib/libssl/src/crypto/ecdsa/ecs_locl.h lib/libssl/src/crypto/ecdsa/ecs_locl.h index ceae6a2..b1cf71e 100644 --- lib/libssl/src/crypto/ecdsa/ecs_locl.h +++ lib/libssl/src/crypto/ecdsa/ecs_locl.h @@ -79,9 +79,14 @@ struct ecdsa_method int (*finish)(EC_KEY *eckey); #endif int flags; - char *app_data; + void *app_data; }; +/* The ECDSA_METHOD was allocated and can be freed */ + +#define ECDSA_METHOD_FLAG_ALLOCATED 0x2 + + /* If this flag is set the ECDSA method is FIPS compliant and can be used * in FIPS mode. This is set in the validated module method. If an * application sets this flag in its own methods it is its responsibility commit b9051ac84c79c2659f01367db90680183845d9ae Author: pedro martelletto Date: Thu Dec 18 13:48:05 2014 +0100 Implement PKCS#11 ECDSA support in SSH Most of the changes take place in ssh-pkcs11.c, which has been instrumented on loading ECDSA keys. Minor changes were reflected in other files such as ssh-pkcs11-client.c and ssh-pkcs11-helper.c. Finally, this change also adds ECDSA support for ssh-keygen conversions. Joint work with Markus Friedl. diff --git usr.bin/ssh/ssh-keygen.c usr.bin/ssh/ssh-keygen.c index 9031683..1a89153 100644 --- usr.bin/ssh/ssh-keygen.c +++ usr.bin/ssh/ssh-keygen.c @@ -343,7 +343,10 @@ do_convert_to_pem(Key *k) fatal("PEM_write_DSAPublicKey failed"); break; #endif - /* XXX ECDSA? */ + case KEY_ECDSA: + if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) + fatal("PEM_write_EC_PUBKEY failed"); + break; default: fatal("%s: unsupported key type %s", __func__, key_type(k)); } @@ -623,6 +626,7 @@ do_convert_from_pem(Key **k, int *private) #ifdef notyet DSA *dsa; #endif + EC_KEY *ec; if ((fp = fopen(identity_file, "r")) == NULL) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); @@ -642,8 +646,17 @@ do_convert_from_pem(Key **k, int *private) fclose(fp); return; } - /* XXX ECDSA */ #endif + if ((ec = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL)) != NULL) { + *k = key_new(KEY_UNSPEC); + (*k)->type = KEY_ECDSA; + (*k)->ecdsa = ec; + (*k)->ecdsa_nid = key_ecdsa_key_to_nid(ec); + if ((*k)->ecdsa_nid < 0) + fatal("%s: couldn't get curve nid", __func__); + fclose(fp); + return; + } fatal("%s: unrecognised raw private key format", __func__); } diff --git usr.bin/ssh/ssh-pkcs11-client.c usr.bin/ssh/ssh-pkcs11-client.c index 2dc5f17..d2f2aa9 100644 --- usr.bin/ssh/ssh-pkcs11-client.c +++ usr.bin/ssh/ssh-pkcs11-client.c @@ -1,6 +1,7 @@ /* $OpenBSD: ssh-pkcs11-client.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. + * Copyright (c) 2014 Pedro Martelletto. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,6 +25,7 @@ #include #include +#include #include #include "pathnames.h" @@ -97,8 +99,7 @@ pkcs11_terminate(void) } static int -pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - int padding) +rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) { Key key; u_char *blob, *signature = NULL; @@ -133,16 +134,98 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, return (ret); } -/* redirect the private key encrypt operation to the ssh-pkcs11-helper */ static int -wrap_key(RSA *rsa) +ecdsa_sign_setup(EC_KEY *ec, BN_CTX *ctx, BIGNUM **kinvp, BIGNUM **rp) { - static RSA_METHOD helper_rsa; + error("%s called, returning -1", __func__); + return (-1); +} + +static ECDSA_SIG * +ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, + const BIGNUM *rp, EC_KEY *ec) +{ + Key key; + u_char *blob, *signature = NULL; + u_int blen, slen = 0; + ECDSA_SIG *ret = NULL; + Buffer msg; + + key.type = KEY_ECDSA; + key.ecdsa = ec; + key.ecdsa_nid = sshkey_ecdsa_key_to_nid(ec); + if (key.ecdsa_nid < 0) { + error("%s: couldn't get curve nid", __func__); + return (NULL); + } + if (key_to_blob(&key, &blob, &blen) == 0) + return (NULL); + buffer_init(&msg); + buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); + buffer_put_string(&msg, blob, blen); + buffer_put_string(&msg, dgst, dgst_len); + buffer_put_int(&msg, 0); + free(blob); + send_msg(&msg); + buffer_clear(&msg); + + if (recv_msg(&msg) == SSH2_AGENT_SIGN_RESPONSE) { + signature = buffer_get_string(&msg, &slen); + if (signature == NULL) { + error("%s: buffer_get_string failed", __func__); + goto out; + } + ret = d2i_ECDSA_SIG(NULL, (const u_char **)&signature, slen); + free(signature); + } +out: + buffer_free(&msg); + return (ret); +} + +static int +ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, + EC_KEY *ec) +{ + error("%s called, returning -1", __func__); + return (-1); +} + +static RSA_METHOD helper_rsa; +static ECDSA_METHOD *helper_ecdsa; + +/* redirect private key crypto operations to the ssh-pkcs11-helper */ +static void +wrap_key(Key *k) +{ + if (k->type == KEY_RSA) + RSA_set_method(k->rsa, &helper_rsa); + else if (k->type == KEY_ECDSA) + ECDSA_set_method(k->ecdsa, helper_ecdsa); + else + fatal("%s: unknown key type", __func__); +} + +static int +pkcs11_start_helper_methods(void) +{ + if (helper_ecdsa != NULL) + return (0); + + helper_ecdsa = ECDSA_METHOD_new(NULL); + if (helper_ecdsa == NULL) { + error("ECDSA_METHOD_new() failed"); + return (-1); + } + + ECDSA_METHOD_set_sign_setup(helper_ecdsa, ecdsa_sign_setup); + ECDSA_METHOD_set_sign(helper_ecdsa, ecdsa_do_sign); + ECDSA_METHOD_set_verify(helper_ecdsa, ecdsa_do_verify); memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa)); helper_rsa.name = "ssh-pkcs11-helper"; - helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt; - RSA_set_method(rsa, &helper_rsa); + helper_rsa.rsa_priv_enc = rsa_encrypt; + return (0); } @@ -151,6 +234,11 @@ pkcs11_start_helper(void) { int pair[2]; + if (pkcs11_start_helper_methods() == -1) { + error("pkcs11_start_helper_methods failed"); + return (-1); + } + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { error("socketpair: %s", strerror(errno)); return (-1); @@ -203,7 +291,7 @@ pkcs11_add_provider(char *name, char *pin, Key ***keysp) blob = buffer_get_string(&msg, &blen); free(buffer_get_string(&msg, NULL)); k = key_from_blob(blob, blen); - wrap_key(k->rsa); + wrap_key(k); (*keysp)[i] = k; free(blob); } diff --git usr.bin/ssh/ssh-pkcs11-helper.c usr.bin/ssh/ssh-pkcs11-helper.c index 3c2a0f2..64282de 100644 --- usr.bin/ssh/ssh-pkcs11-helper.c +++ usr.bin/ssh/ssh-pkcs11-helper.c @@ -175,13 +175,26 @@ process_sign(void) #ifdef WITH_OPENSSL int ret; - slen = RSA_size(key->rsa); - signature = xmalloc(slen); - if ((ret = RSA_private_encrypt(dlen, data, signature, - found->rsa, RSA_PKCS1_PADDING)) != -1) { - slen = ret; - ok = 0; - } + if (key->type == KEY_RSA) { + slen = RSA_size(key->rsa); + signature = xmalloc(slen); + ret = RSA_private_encrypt(dlen, data, signature, + found->rsa, RSA_PKCS1_PADDING); + if (ret != -1) { + slen = ret; + ok = 0; + } + } else if (key->type == KEY_ECDSA) { + slen = ECDSA_size(key->ecdsa); + signature = xmalloc(slen); + /* "The parameter type is ignored." */ + ret = ECDSA_sign(-1, data, dlen, signature, + &slen, found->ecdsa); + if (ret != -1) + ok = 0; + } else + error("%s: don't know how to sign with key " + "type %d", __func__, (int)key->type); #endif /* WITH_OPENSSL */ } key_free(key); diff --git usr.bin/ssh/ssh-pkcs11.c usr.bin/ssh/ssh-pkcs11.c index 11a3370..e7ad949 100644 --- usr.bin/ssh/ssh-pkcs11.c +++ usr.bin/ssh/ssh-pkcs11.c @@ -1,6 +1,7 @@ /* $OpenBSD: ssh-pkcs11.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. + * Copyright (c) 2014 Pedro Martelletto. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -23,6 +24,7 @@ #include #include +#include #include #define CRYPTOKI_COMPAT @@ -60,6 +62,7 @@ struct pkcs11_key { CK_ULONG slotidx; int (*orig_finish)(RSA *rsa); RSA_METHOD rsa_method; + ECDSA_METHOD *ecdsa_method; char *keyid; int keyid_len; }; @@ -210,40 +213,27 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, return (ret); } -/* openssl callback doing the actual signing operation */ static int -pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - int padding) +pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) { - struct pkcs11_key *k11; struct pkcs11_slotinfo *si; CK_FUNCTION_LIST *f; - CK_OBJECT_HANDLE obj; - CK_ULONG tlen = 0; - CK_RV rv; - CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; - CK_BBOOL true_val = CK_TRUE; - CK_MECHANISM mech = { - CKM_RSA_PKCS, NULL_PTR, 0 - }; - CK_ATTRIBUTE key_filter[] = { - {CKA_CLASS, &private_key_class, sizeof(private_key_class) }, - {CKA_ID, NULL, 0}, - {CKA_SIGN, &true_val, sizeof(true_val) } - }; + CK_OBJECT_HANDLE obj; + CK_RV rv; + CK_OBJECT_CLASS private_key_class; + CK_BBOOL true_val; + CK_MECHANISM mech; + CK_ATTRIBUTE key_filter[3]; char *pin, prompt[1024]; - int rval = -1; - if ((k11 = RSA_get_app_data(rsa)) == NULL) { - error("RSA_get_app_data failed for rsa %p", rsa); - return (-1); - } if (!k11->provider || !k11->provider->valid) { - error("no pkcs11 (valid) provider for rsa %p", rsa); + error("no pkcs11 (valid) provider found"); return (-1); } + f = k11->provider->function_list; si = &k11->provider->slotinfo[k11->slotidx]; + if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { if (!pkcs11_interactive) { error("need pin"); @@ -263,23 +253,75 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, free(pin); si->logged_in = 1; } + + memset(&key_filter, 0, sizeof(key_filter)); + private_key_class = CKO_PRIVATE_KEY; + key_filter[0].type = CKA_CLASS; + key_filter[0].pValue = &private_key_class; + key_filter[0].ulValueLen = sizeof(private_key_class); + + key_filter[1].type = CKA_ID; key_filter[1].pValue = k11->keyid; key_filter[1].ulValueLen = k11->keyid_len; + + true_val = CK_TRUE; + key_filter[2].type = CKA_SIGN; + key_filter[2].pValue = &true_val; + key_filter[2].ulValueLen = sizeof(true_val); + /* try to find object w/CKA_SIGN first, retry w/o */ if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 && pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) { error("cannot find private key"); - } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { + return (-1); + } + + memset(&mech, 0, sizeof(mech)); + mech.mechanism = mech_type; + mech.pParameter = NULL_PTR; + mech.ulParameterLen = 0; + + if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { error("C_SignInit failed: %lu", rv); - } else { - /* XXX handle CKR_BUFFER_TOO_SMALL */ - tlen = RSA_size(rsa); - rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen); - if (rv == CKR_OK) - rval = tlen; - else - error("C_Sign failed: %lu", rv); + return (-1); + } + + return (0); +} + +/* openssl callback doing the actual signing operation */ +static int +pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, + int padding) +{ + struct pkcs11_key *k11; + struct pkcs11_slotinfo *si; + CK_FUNCTION_LIST *f; + CK_ULONG tlen = 0; + CK_RV rv; + int rval = -1; + + if ((k11 = RSA_get_app_data(rsa)) == NULL) { + error("RSA_get_app_data failed for rsa %p", rsa); + return (-1); + } + + if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) { + error("pkcs11_get_key failed"); + return (-1); } + + f = k11->provider->function_list; + si = &k11->provider->slotinfo[k11->slotidx]; + tlen = RSA_size(rsa); + + /* XXX handle CKR_BUFFER_TOO_SMALL */ + rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen); + if (rv == CKR_OK) + rval = tlen; + else + error("C_Sign failed: %lu", rv); + return (rval); } @@ -317,6 +359,132 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, return (0); } +/* ~*kingdom of unimplemented callbacks*~ */ + +static void * +ecdsa_k11_dup(void *k11) +{ + fatal("%s called", __func__); +} + +static void +ecdsa_k11_free(void *k11) +{ + fatal("%s called", __func__); +} + +static void +ecdsa_k11_clear_free(void *k11) +{ + fatal("%s called", __func__); +} + +static int +ecdsa_sign_setup(EC_KEY *ec, BN_CTX *ctx, BIGNUM **kinvp, BIGNUM **rp) +{ + error("%s called, returning -1", __func__); + return (-1); +} + +/* openssl callback doing the actual signing operation */ +static ECDSA_SIG * +ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, + const BIGNUM *rp, EC_KEY *ec) +{ + struct pkcs11_key *k11; + struct pkcs11_slotinfo *si; + CK_FUNCTION_LIST *f; + CK_ULONG siglen = 0; + CK_RV rv; + ECDSA_SIG *ret = NULL; + u_char *sig; + const u_char *cp; + + if ((k11 = EC_KEY_get_key_method_data(ec, ecdsa_k11_dup, ecdsa_k11_free, + ecdsa_k11_clear_free)) == NULL) { + error("EC_KEY_get_key_method_data failed for ec %p", ec); + return (NULL); + } + + if (pkcs11_get_key(k11, CKM_ECDSA) == -1) { + error("pkcs11_get_key failed"); + return (NULL); + } + + f = k11->provider->function_list; + si = &k11->provider->slotinfo[k11->slotidx]; + + siglen = ECDSA_size(ec); + sig = xmalloc(siglen); + + /* XXX handle CKR_BUFFER_TOO_SMALL */ + rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen); + if (rv == CKR_OK) { + cp = sig; + ret = d2i_ECDSA_SIG(NULL, &cp, siglen); + } else + error("C_Sign failed: %lu", rv); + + free(sig); + + return (ret); +} + +static int +ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, + EC_KEY *ec) +{ + error("%s called, returning -1", __func__); + return (-1); +} + +static ECDSA_METHOD *ecdsa_method; + +static int +pkcs11_ecdsa_start_wrapper(void) +{ + if (ecdsa_method != NULL) + return (0); + + ecdsa_method = ECDSA_METHOD_new(NULL); + if (ecdsa_method == NULL) { + error("ECDSA_METHOD_new() failed"); + return (-1); + } + + ECDSA_METHOD_set_sign_setup(ecdsa_method, ecdsa_sign_setup); + ECDSA_METHOD_set_sign(ecdsa_method, ecdsa_do_sign); + ECDSA_METHOD_set_verify(ecdsa_method, ecdsa_do_verify); + + return (0); +} + +static int +pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) +{ + struct pkcs11_key *k11; + + if (pkcs11_ecdsa_start_wrapper() == -1) + return (-1); + + k11 = xcalloc(1, sizeof(*k11)); + k11->provider = provider; + provider->refcount++; /* provider referenced by ECDSA key */ + k11->slotidx = slotidx; + /* identify key object on smartcard */ + k11->keyid_len = keyid_attrib->ulValueLen; + k11->keyid = xmalloc(k11->keyid_len); + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + k11->ecdsa_method = ecdsa_method; + + ECDSA_set_method(ec, k11->ecdsa_method); + EC_KEY_insert_key_method_data(ec, k11, ecdsa_k11_dup, ecdsa_k11_free, + ecdsa_k11_clear_free); + + return (0); +} + /* remove trailing spaces */ static void rmspace(u_char *buf, size_t len) @@ -370,46 +538,6 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) return (0); } -/* - * lookup public keys for token in slot identified by slotidx, - * add 'wrapped' public keys to the 'keysp' array and increment nkeys. - * keysp points to an (possibly empty) array with *nkeys keys. - */ -static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG, - CK_ATTRIBUTE [], CK_ATTRIBUTE [3], Key ***, int *) - __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE)))); - -static int -pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, - Key ***keysp, int *nkeys) -{ - CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - CK_ATTRIBUTE pubkey_filter[] = { - { CKA_CLASS, &pubkey_class, sizeof(pubkey_class) } - }; - CK_ATTRIBUTE cert_filter[] = { - { CKA_CLASS, &cert_class, sizeof(cert_class) } - }; - CK_ATTRIBUTE pubkey_attribs[] = { - { CKA_ID, NULL, 0 }, - { CKA_MODULUS, NULL, 0 }, - { CKA_PUBLIC_EXPONENT, NULL, 0 } - }; - CK_ATTRIBUTE cert_attribs[] = { - { CKA_ID, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, - { CKA_VALUE, NULL, 0 } - }; - - if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs, - keysp, nkeys) < 0 || - pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs, - keysp, nkeys) < 0) - return (-1); - return (0); -} - static int pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) { @@ -421,114 +549,522 @@ pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) return (0); } -static int -pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], - Key ***keysp, int *nkeys) +static Key * +pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) { - Key *key; - RSA *rsa; - X509 *x509; + CK_ATTRIBUTE key_attr[3]; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; + EC_KEY *ec = NULL; + EC_GROUP *group = NULL; + Key *key = NULL; + const unsigned char *attrp = NULL; + int i; + int nid; + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; + key_attr[1].type = CKA_EC_POINT; + key_attr[2].type = CKA_EC_PARAMS; + + session = p->slotinfo[slotidx].session; + f = p->function_list; + + /* figure out size of the attributes */ + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); + } + + /* check that none of the attributes are zero length */ + if (key_attr[0].ulValueLen == 0 || + key_attr[1].ulValueLen == 0 || + key_attr[2].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ + for (i = 0; i < 3; i++) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, public point and curve parameters of EC key */ + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; + } + + ec = EC_KEY_new(); + if (ec == NULL) { + error("EC_KEY_new failed"); + goto fail; + } + + attrp = key_attr[2].pValue; + group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); + if (group == NULL || EC_KEY_set_group(ec, group) == 0) { + error("d2i_ECPKParameters failed"); + goto fail; + } + + if (key_attr[1].ulValueLen <= 2) { + error("CKA_EC_POINT too small"); + goto fail; + } + + attrp = (const unsigned char *)key_attr[1].pValue + 2; + if (o2i_ECPublicKey(&ec, &attrp, key_attr[1].ulValueLen - 2) == NULL) { + error("o2i_ECPublicKey failed"); + goto fail; + } + + nid = sshkey_ecdsa_key_to_nid(ec); + if (nid < 0) { + error("couldn't get curve nid"); + goto fail; + } + + if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) + goto fail; + + key = key_new(KEY_UNSPEC); + if (key == NULL) { + error("key_new failed"); + goto fail; + } + + key->ecdsa = ec; + key->ecdsa_nid = nid; + key->type = KEY_ECDSA; + key->flags |= SSHKEY_FLAG_EXT; + ec = NULL; /* now owned by key */ + +fail: + for (i = 0; i < 3; i++) + free(key_attr[i].pValue); + if (ec) + EC_KEY_free(ec); + if (group) + EC_GROUP_free(group); + + return (key); +} + +static Key * +pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) +{ + CK_ATTRIBUTE key_attr[3]; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; + RSA *rsa = NULL; + Key *key = NULL; + int i; + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; + key_attr[1].type = CKA_MODULUS; + key_attr[2].type = CKA_PUBLIC_EXPONENT; + + session = p->slotinfo[slotidx].session; + f = p->function_list; + + /* figure out size of the attributes */ + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); + } + + /* check that none of the attributes are zero length */ + if (key_attr[0].ulValueLen == 0 || + key_attr[1].ulValueLen == 0 || + key_attr[2].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ + for (i = 0; i < 3; i++) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, modulus and public exponent of RSA key */ + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; + } + + rsa = RSA_new(); + if (rsa == NULL) { + error("RSA_new failed"); + goto fail; + } + + rsa->n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); + rsa->e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); + if (rsa->n == NULL || rsa->e == NULL) { + error("BN_bin2bn failed"); + goto fail; + } + + if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) + goto fail; + + key = key_new(KEY_UNSPEC); + if (key == NULL) { + error("key_new failed"); + goto fail; + } + + key->rsa = rsa; + key->type = KEY_RSA; + key->flags |= SSHKEY_FLAG_EXT; + rsa = NULL; /* now owned by key */ + +fail: + for (i = 0; i < 3; i++) + free(key_attr[i].pValue); + if (rsa) + RSA_free(rsa); + + return (key); +} + +static Key * +pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) +{ + CK_ATTRIBUTE cert_attr[3]; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; + X509 *x509 = NULL; EVP_PKEY *evp; - int i; - const u_char *cp; - CK_RV rv; - CK_OBJECT_HANDLE obj; - CK_ULONG nfound; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f; + RSA *rsa = NULL; + EC_KEY *ec = NULL; + Key *key = NULL; + int i; + int nid; + const u_char *cp; + + memset(&cert_attr, 0, sizeof(cert_attr)); + cert_attr[0].type = CKA_ID; + cert_attr[1].type = CKA_SUBJECT; + cert_attr[2].type = CKA_VALUE; + session = p->slotinfo[slotidx].session; f = p->function_list; + + /* figure out size of the attributes */ + rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); + } + + /* check that none of the attributes are zero length */ + if (cert_attr[0].ulValueLen == 0 || + cert_attr[1].ulValueLen == 0 || + cert_attr[2].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ + for (i = 0; i < 3; i++) + cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); + + /* retrieve ID, subject and value of certificate */ + rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; + } + + x509 = X509_new(); + if (x509 == NULL) { + error("x509_new failed"); + goto fail; + } + + cp = cert_attr[2].pValue; + if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) { + error("d2i_x509 failed"); + goto fail; + } + + evp = X509_get_pubkey(x509); + if (evp == NULL) { + error("X509_get_pubkey failed"); + goto fail; + } + + if (evp->type == EVP_PKEY_RSA) { + if (evp->pkey.rsa == NULL) { + error("invalid x509; no rsa key"); + goto fail; + } + if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) == NULL) { + error("RSAPublicKey_dup failed"); + goto fail; + } + + if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) + goto fail; + + key = key_new(KEY_UNSPEC); + if (key == NULL) { + error("key_new failed"); + goto fail; + } + + key->rsa = rsa; + key->type = KEY_RSA; + key->flags |= SSHKEY_FLAG_EXT; + rsa = NULL; /* now owned by key */ + } else if (evp->type == EVP_PKEY_EC) { + if (evp->pkey.ec == NULL) { + error("invalid x509; no ec key"); + goto fail; + } + if ((ec = EC_KEY_dup(evp->pkey.ec)) == NULL) { + error("EC_KEY_dup failed"); + goto fail; + } + + nid = sshkey_ecdsa_key_to_nid(ec); + if (nid < 0) { + error("couldn't get curve nid"); + goto fail; + } + + if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) + goto fail; + + key = key_new(KEY_UNSPEC); + if (key == NULL) { + error("key_new failed"); + goto fail; + } + + key->ecdsa = ec; + key->ecdsa_nid = nid; + key->type = KEY_ECDSA; + key->flags |= SSHKEY_FLAG_EXT; + ec = NULL; /* now owned by key */ + } else + error("unknown certificate key type"); + +fail: + for (i = 0; i < 3; i++) + free(cert_attr[i].pValue); + if (x509) + X509_free(x509); + if (rsa) + RSA_free(rsa); + if (ec) + EC_KEY_free(ec); + + return (key); +} + +/* + * lookup certificates for token in slot identified by slotidx, + * add 'wrapped' public keys to the 'keysp' array and increment nkeys. + * keysp points to an (possibly empty) array with *nkeys keys. + */ +static int +pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, + int *nkeys) +{ + Key *key = NULL; + CK_OBJECT_CLASS key_class; + CK_ATTRIBUTE key_attr[1]; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; + CK_OBJECT_HANDLE obj; + CK_ULONG n = 0; + int ret = -1; + + memset(&key_attr, 0, sizeof(key_attr)); + memset(&obj, 0, sizeof(obj)); + + key_class = CKO_CERTIFICATE; + key_attr[0].type = CKA_CLASS; + key_attr[0].pValue = &key_class; + key_attr[0].ulValueLen = sizeof(key_class); + session = p->slotinfo[slotidx].session; - /* setup a filter the looks for public keys */ - if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) { + f = p->function_list; + + rv = f->C_FindObjectsInit(session, key_attr, 1); + if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); - return (-1); + goto fail; } + while (1) { - /* XXX 3 attributes in attribs[] */ - for (i = 0; i < 3; i++) { - attribs[i].pValue = NULL; - attribs[i].ulValueLen = 0; + CK_CERTIFICATE_TYPE ck_cert_type; + + rv = f->C_FindObjects(session, &obj, 1, &n); + if (rv != CKR_OK) { + error("C_FindObjects failed: %lu", rv); + goto fail; } - if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK - || nfound == 0) + if (n == 0) break; - /* found a key, so figure out size of the attributes */ - if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) - != CKR_OK) { + + memset(&ck_cert_type, 0, sizeof(ck_cert_type)); + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_CERTIFICATE_TYPE; + key_attr[0].pValue = &ck_cert_type; + key_attr[0].ulValueLen = sizeof(ck_cert_type); + + rv = f->C_GetAttributeValue(session, obj, key_attr, 1); + if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); - continue; + goto fail; + } + + switch (ck_cert_type) { + case CKC_X_509: + key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj); + break; + default: + /* XXX print key type? */ + error("skipping unsupported certificate type"); } - /* check that none of the attributes are zero length */ - if (attribs[0].ulValueLen == 0 || - attribs[1].ulValueLen == 0 || - attribs[2].ulValueLen == 0) { + + if (key == NULL) { + error("failed to fetch key"); continue; } - /* allocate buffers for attributes */ - for (i = 0; i < 3; i++) - attribs[i].pValue = xmalloc(attribs[i].ulValueLen); - /* - * retrieve ID, modulus and public exponent of RSA key, - * or ID, subject and value for certificates. - */ - rsa = NULL; - if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) - != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - } else if (attribs[1].type == CKA_MODULUS ) { - if ((rsa = RSA_new()) == NULL) { - error("RSA_new failed"); - } else { - rsa->n = BN_bin2bn(attribs[1].pValue, - attribs[1].ulValueLen, NULL); - rsa->e = BN_bin2bn(attribs[2].pValue, - attribs[2].ulValueLen, NULL); - } + + if (pkcs11_key_included(keysp, nkeys, key)) { + key_free(key); } else { - cp = attribs[2].pValue; - if ((x509 = X509_new()) == NULL) { - error("X509_new failed"); - } else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen) - == NULL) { - error("d2i_X509 failed"); - } else if ((evp = X509_get_pubkey(x509)) == NULL || - evp->type != EVP_PKEY_RSA || - evp->pkey.rsa == NULL) { - debug("X509_get_pubkey failed or no rsa"); - } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) - == NULL) { - error("RSAPublicKey_dup"); - } - if (x509) - X509_free(x509); + /* expand key array and add key */ + *keysp = xrealloc(*keysp, *nkeys + 1, sizeof(Key *)); + (*keysp)[*nkeys] = key; + *nkeys = *nkeys + 1; + debug("have %d keys", *nkeys); } - if (rsa && rsa->n && rsa->e && - pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { - key = key_new(KEY_UNSPEC); - key->rsa = rsa; - key->type = KEY_RSA; - key->flags |= SSHKEY_FLAG_EXT; - if (pkcs11_key_included(keysp, nkeys, key)) { - key_free(key); - } else { - /* expand key array and add key */ - *keysp = xrealloc(*keysp, *nkeys + 1, - sizeof(Key *)); - (*keysp)[*nkeys] = key; - *nkeys = *nkeys + 1; - debug("have %d keys", *nkeys); - } - } else if (rsa) { - RSA_free(rsa); + } + + ret = 0; +fail: + rv = f->C_FindObjectsFinal(session); + if (rv != CKR_OK) { + error("C_FindObjectsFinal failed: %lu", rv); + ret = -1; + } + + return (ret); +} + +/* + * lookup public keys for token in slot identified by slotidx, + * add 'wrapped' public keys to the 'keysp' array and increment nkeys. + * keysp points to an (possibly empty) array with *nkeys keys. + */ +static int +pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, + int *nkeys) +{ + Key *key = NULL; + CK_OBJECT_CLASS key_class; + CK_ATTRIBUTE key_attr[1]; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; + CK_OBJECT_HANDLE obj; + CK_ULONG n = 0; + int ret = -1; + + memset(&key_attr, 0, sizeof(key_attr)); + memset(&obj, 0, sizeof(obj)); + + key_class = CKO_PUBLIC_KEY; + key_attr[0].type = CKA_CLASS; + key_attr[0].pValue = &key_class; + key_attr[0].ulValueLen = sizeof(key_class); + + session = p->slotinfo[slotidx].session; + f = p->function_list; + + rv = f->C_FindObjectsInit(session, key_attr, 1); + if (rv != CKR_OK) { + error("C_FindObjectsInit failed: %lu", rv); + goto fail; + } + + while (1) { + CK_KEY_TYPE ck_key_type; + + rv = f->C_FindObjects(session, &obj, 1, &n); + if (rv != CKR_OK) { + error("C_FindObjects failed: %lu", rv); + goto fail; + } + if (n == 0) + break; + + memset(&ck_key_type, 0, sizeof(ck_key_type)); + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_KEY_TYPE; + key_attr[0].pValue = &ck_key_type; + key_attr[0].ulValueLen = sizeof(ck_key_type); + + rv = f->C_GetAttributeValue(session, obj, key_attr, 1); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; + } + + switch (ck_key_type) { + case CKK_RSA: + key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); + break; + case CKK_ECDSA: + key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); + break; + default: + /* XXX print key type? */ + error("skipping unsupported key type"); + } + + if (key == NULL) { + error("failed to fetch key"); + continue; + } + + if (pkcs11_key_included(keysp, nkeys, key)) { + key_free(key); + } else { + /* expand key array and add key */ + *keysp = xrealloc(*keysp, *nkeys + 1, sizeof(Key *)); + (*keysp)[*nkeys] = key; + *nkeys = *nkeys + 1; + debug("have %d keys", *nkeys); } - for (i = 0; i < 3; i++) - free(attribs[i].pValue); } - if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK) + + ret = 0; +fail: + rv = f->C_FindObjectsFinal(session); + if (rv != CKR_OK) { error("C_FindObjectsFinal failed: %lu", rv); - return (0); + ret = -1; + } + + return (ret); } #ifdef HAVE_DLOPEN @@ -620,8 +1156,10 @@ pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) token->label, token->manufacturerID, token->model, token->serialNumber, token->flags); /* open session, login with pin and retrieve public keys */ - if (pkcs11_open_session(p, i, pin) == 0) + if (pkcs11_open_session(p, i, pin) == 0) { pkcs11_fetch_keys(p, i, keyp, &nkeys); + pkcs11_fetch_certs(p, i, keyp, &nkeys); + } } if (nkeys > 0) { TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); diff --git usr.bin/ssh/sshkey.h usr.bin/ssh/sshkey.h index 4127db2..b351f45 100644 --- usr.bin/ssh/sshkey.h +++ usr.bin/ssh/sshkey.h @@ -32,6 +32,7 @@ #include #include #include +#include #else /* OPENSSL */ #define RSA void #define DSA void From djm at mindrot.org Wed Apr 1 10:14:21 2015 From: djm at mindrot.org (Damien Miller) Date: Wed, 1 Apr 2015 10:14:21 +1100 (AEDT) Subject: Wanted: smartcard with ECDSA support In-Reply-To: References: Message-ID: On Tue, 31 Mar 2015, Thomas Calderon wrote: > Hi list, > > I have no idea if Damien Miller had the time to work on that. > > I have an initial patch to authenticate using PKCS#11 and ECDSA keys. > This requires OpenSSL 1.0.2, prior OpenSSL versions do not expose the > required interfaces to override the signature function pointer for ECDSA. > The only limitation is that the OpenSSL API misses some cleanup function > (finish, for instance), hence I have yet to find a way to properly free the > PKCS#11 resources. > > Is this a contribution you might be interested in ? There's another ECDSA-for-PKCS#11 patch floating around too, but yes. I never found ECDSA-capable smartcards. Donations of a couple are still welcome. -d From calderon.thomas at gmail.com Wed Apr 1 08:34:59 2015 From: calderon.thomas at gmail.com (Thomas Calderon) Date: Tue, 31 Mar 2015 23:34:59 +0200 Subject: Wanted: smartcard with ECDSA support In-Reply-To: <20150331182603.GA12390@triangle.ambientworks.net> References: <961045BD-68C0-4617-9004-D6C17662ADB3@gmail.com> <20150331182603.GA12390@triangle.ambientworks.net> Message-ID: Hi Pedro, hi Markus, Haha ! Great that you guys had already worked on supporting other signature mechanisms ! In any case, coding an alternative version allowed me to understand how the PKCS#11 support was implemented in OpenSSH. We followed a similar approach, but I made it work with fewer modifications to ssh-pkcs11.c but it is less complete. I saw that you split the code to isolate pkcs11 functions by the type of object that should be fetched, it makes more sense and improve code readability. I will try your version tomorrow and look more closely at differences. I will also check if we can manipulate the CCRYPTO_ex_data as pointed by Douglas to have a valid freeing mechanism. Cheers, Thomas On Tue, Mar 31, 2015 at 8:26 PM, Pedro Martelletto wrote: > Hi, > > Here's a copy of the mail sent to Markus, Damien and Miod back in > December. It is also available at the following URL: > > http://ambientworks.net/ecdsa-ssh.txt > > The OpenSC work mentioned by Markus can be found at: > > https://github.com/OpenSC/OpenSC/pull/283 > > -p. > > From pedro at ambientworks.net Thu Dec 18 18:05:54 2014 > Return-Path: > Received: from triangle.ambientworks.net (ambientworks.net. > [195.154.11.238]) > by mx.google.com with ESMTPSA id dp8sm25399482wib.20.2014.12. > 18.09.05.53 > (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); > Thu, 18 Dec 2014 09:05:54 -0800 (PST) > Date: Thu, 18 Dec 2014 18:05:09 +0100 > From: pedro martelletto > To: djm at openbsd.org, miod at openbsd.org, markus at openbsd.org > Subject: PKCS#11 ECDSA support in OpenSSH, and related LibreSSL changes > Message-ID: <20141218170508.GA25923 at triangle.ambientworks.net> > MIME-Version: 1.0 > Content-Type: text/plain; charset=us-ascii; format=flowed > Content-Disposition: inline > > Hi Damien and Miod, > > I have recently worked with Markus on implementing PKCS#11 ECDSA support > in OpenSSH. In order to do this, we needed to be able to wrap ECDSA key > objects, providing them with a customised callback for signing. This, > however, wasn't possible due to the definition of ECDSA_METHOD not being > exported by LibreSSL. We then looked around and found this OpenSSL bug > report [1] which, after remaining inactive for years, was finally > updated yesterday, 2014-12-17. > > As can be seen in the commits linked from the bug report [2,3], the > course taken by OpenSSL was diferent than the one adopted by LibreSSL [4]. > Whether or not OpenSSL's decision makes sense, I am not sure. It would > arguably make sense though, for the sake of a similar API, for LibreSSL > to provide the same set of functions. > > In the first of the three patches inlined below, I took the interim > decision of reverting Miod's commit to expose ECDSA_METHOD, with the > understanding that it would be best to copy the OpenSSL commits verbatim > and leave any merging decisions up to you. > > The second diff consists of an amalgamation of the two OpenSSL commits > [2,3]. Finally, the third diff implements the PKCS#11 ECDSA bits in > OpenSSH. > > Warm regards and season's greetings! :) > > -p. > > [1] http://rt.openssl.org/Ticket/Display.html?id=2459&user= > guest&pass=guest > [2] https://github.com/openssl/openssl/commit/94c2f77a > [3] https://github.com/openssl/openssl/commit/387b844f > [4] http://freshbsd.org/commit/openbsd/1c8c6abf87634651e430450659b62b > 34a2cb63aa > > commit 1623ab45684d7bd034001d518d70ec250de7d398 > Author: pedro martelletto > Date: Thu Dec 18 17:13:19 2014 +0100 > > Revert "Make the ECDSA_SIG bowels public. This matches RSA_SIG and > DSA_SIG, and we" > This reverts commit 7075e35e197bdac9ca93b09442bc1b2436fc94e8. > > diff --git lib/libssl/src/crypto/ecdsa/ecdsa.h > lib/libssl/src/crypto/ecdsa/ecdsa.h > index ad716c2..a29e5f6 100644 > --- lib/libssl/src/crypto/ecdsa/ecdsa.h > +++ lib/libssl/src/crypto/ecdsa/ecdsa.h > @@ -1,4 +1,4 @@ > -/* $OpenBSD: ecdsa.h,v 1.3 2014/11/17 20:25:50 miod Exp $ */ > +/* $OpenBSD: ecdsa.h,v 1.2 2014/06/12 15:49:29 deraadt Exp $ */ > /** > * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA > functions > * \author Written by Nils Larsch for the OpenSSL project > @@ -75,36 +75,11 @@ > extern "C" { > #endif > > -typedef struct ECDSA_SIG_st ECDSA_SIG; > - > -struct ecdsa_method { > - const char *name; > - ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int > dgst_len, - const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey); > - int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, > - BIGNUM **r); > - int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, - > const ECDSA_SIG *sig, EC_KEY *eckey); > -#if 0 > - int (*init)(EC_KEY *eckey); > - int (*finish)(EC_KEY *eckey); > -#endif > - int flags; > - char *app_data; > -}; > - > -/* If this flag is set the ECDSA method is FIPS compliant and can be used > - * in FIPS mode. This is set in the validated module method. If an > - * application sets this flag in its own methods it is its responsibility > - * to ensure the result is compliant. > - */ > - > -#define ECDSA_FLAG_FIPS_METHOD 0x1 > - > -struct ECDSA_SIG_st { > +typedef struct ECDSA_SIG_st > + { > BIGNUM *r; > BIGNUM *s; > -}; > + } ECDSA_SIG; > > /** Allocates and initialize a ECDSA_SIG structure > * \return pointer to a ECDSA_SIG structure or NULL if an error occurred > diff --git lib/libssl/src/crypto/ecdsa/ecs_locl.h > lib/libssl/src/crypto/ecdsa/ecs_locl.h > index e47f679..ceae6a2 100644 > --- lib/libssl/src/crypto/ecdsa/ecs_locl.h > +++ lib/libssl/src/crypto/ecdsa/ecs_locl.h > @@ -1,4 +1,4 @@ > -/* $OpenBSD: ecs_locl.h,v 1.3 2014/11/17 20:25:50 miod Exp $ */ > +/* $OpenBSD: ecs_locl.h,v 1.2 2014/06/12 15:49:29 deraadt Exp $ */ > /* > * Written by Nils Larsch for the OpenSSL project > */ > @@ -65,6 +65,31 @@ > extern "C" { > #endif > > +struct ecdsa_method + { > + const char *name; > + ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int > dgst_len, + const BIGNUM *inv, const BIGNUM *rp, EC_KEY > *eckey); > + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, > + BIGNUM **r); > + int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, + > const ECDSA_SIG *sig, EC_KEY *eckey); > +#if 0 > + int (*init)(EC_KEY *eckey); > + int (*finish)(EC_KEY *eckey); > +#endif > + int flags; > + char *app_data; > + }; > + > +/* If this flag is set the ECDSA method is FIPS compliant and can be used > + * in FIPS mode. This is set in the validated module method. If an > + * application sets this flag in its own methods it is its responsibility > + * to ensure the result is compliant. > + */ > + > +#define ECDSA_FLAG_FIPS_METHOD 0x1 > + > typedef struct ecdsa_data_st { > /* EC_KEY_METH_DATA part */ > int (*init)(EC_KEY *); > > commit d5a744b7d8b98997f0f69be3afbcde5b369f2634 > Author: pedro martelletto > Date: Thu Dec 18 10:43:16 2014 +0100 > > Add functions to set ECDSA_METHOD structure. > From OpenSSL commits 94c2f77a and 387b844f, issue #2459: > "Add various functions to allocate and set the fields of an > ECDSA_METHOD > structure." > > diff --git lib/libssl/src/crypto/ecdsa/ecdsa.h > lib/libssl/src/crypto/ecdsa/ecdsa.h > index a29e5f6..a495984 100644 > --- lib/libssl/src/crypto/ecdsa/ecdsa.h > +++ lib/libssl/src/crypto/ecdsa/ecdsa.h > @@ -229,6 +229,74 @@ int ECDSA_set_ex_data(EC_KEY *d, int idx, > void *arg); > void *ECDSA_get_ex_data(EC_KEY *d, int idx); > > > +/** Allocates and initialize a ECDSA_METHOD structure > + * \param ecdsa_method pointer to ECDSA_METHOD to copy. (May be NULL) > + * \return pointer to a ECDSA_METHOD structure or NULL if an error > occurred > + */ > + > +ECDSA_METHOD *ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_method); > + > +/** frees a ECDSA_METHOD structure > + * \param ecdsa_method pointer to the ECDSA_METHOD structure > + */ > +void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method); > + > +/** Sets application specific data in the ECDSA_METHOD > + * \param ecdsa_method pointer to existing ECDSA_METHOD > + * \param app application specific data to set > + */ > + > +void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app); > + > +/** Returns application specific data from a ECDSA_METHOD structure > + * \param ecdsa_method pointer to ECDSA_METHOD structure > + * \return pointer to application specific data. > + */ > + > + > +void * ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method); > + > +/** Set the ECDSA_do_sign function in the ECDSA_METHOD > + * \param ecdsa_method pointer to existing ECDSA_METHOD > + * \param ecdsa_do_sign a funtion of type ECDSA_do_sign > + */ > + > +void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method, > + ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int > dgst_len, > + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey)); > + > +/** Set the ECDSA_sign_setup function in the ECDSA_METHOD > + * \param ecdsa_method pointer to existing ECDSA_METHOD > + * \param ecdsa_sign_setup a funtion of type ECDSA_sign_setup > + */ > + > +void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method, > + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, > + BIGNUM **r)); > + > +/** Set the ECDSA_do_verify function in the ECDSA_METHOD > + * \param ecdsa_method pointer to existing ECDSA_METHOD > + * \param ecdsa_do_verify a funtion of type ECDSA_do_verify > + */ > + > +void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method, > + int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, > + const ECDSA_SIG *sig, EC_KEY *eckey)); > + > +void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags); > + > +/** Set the flags field in the ECDSA_METHOD > + * \param ecdsa_method pointer to existing ECDSA_METHOD > + * \param flags flags value to set > + */ > + > +void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name); > + > +/** Set the name field in the ECDSA_METHOD > + * \param ecdsa_method pointer to existing ECDSA_METHOD > + * \param name name to set > + */ > + > /* BEGIN ERROR CODES */ > /* The following lines are auto generated by the script mkerr.pl. Any > changes > * made after this point may be overwritten when the script is next run. > @@ -242,6 +310,7 @@ void ERR_load_ECDSA_strings(void); > #define ECDSA_F_ECDSA_DATA_NEW_METHOD 100 > #define ECDSA_F_ECDSA_DO_SIGN 101 > #define ECDSA_F_ECDSA_DO_VERIFY 102 > +#define ECDSA_F_ECDSA_METHOD_NEW 105 > #define ECDSA_F_ECDSA_SIGN_SETUP 103 > > /* Reason codes. */ > diff --git lib/libssl/src/crypto/ecdsa/ecs_err.c > lib/libssl/src/crypto/ecdsa/ecs_err.c > index 721b53c..1400f34 100644 > --- lib/libssl/src/crypto/ecdsa/ecs_err.c > +++ lib/libssl/src/crypto/ecdsa/ecs_err.c > @@ -77,6 +77,7 @@ static ERR_STRING_DATA ECDSA_str_functs[]= > {ERR_FUNC(ECDSA_F_ECDSA_DATA_NEW_METHOD), "ECDSA_DATA_NEW_METHOD"}, > {ERR_FUNC(ECDSA_F_ECDSA_DO_SIGN), "ECDSA_do_sign"}, > {ERR_FUNC(ECDSA_F_ECDSA_DO_VERIFY), "ECDSA_do_verify"}, > +{ERR_FUNC(ECDSA_F_ECDSA_METHOD_NEW), "ECDSA_METHOD_new"}, > {ERR_FUNC(ECDSA_F_ECDSA_SIGN_SETUP), "ECDSA_sign_setup"}, > {0,NULL} > }; > diff --git lib/libssl/src/crypto/ecdsa/ecs_lib.c > lib/libssl/src/crypto/ecdsa/ecs_lib.c > index a92d611..38756fa 100644 > --- lib/libssl/src/crypto/ecdsa/ecs_lib.c > +++ lib/libssl/src/crypto/ecdsa/ecs_lib.c > @@ -266,3 +266,76 @@ void *ECDSA_get_ex_data(EC_KEY *d, int idx) > return NULL; > return(CRYPTO_get_ex_data(&ecdsa->ex_data,idx)); > } > + > +ECDSA_METHOD *ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_meth) > + { > + ECDSA_METHOD *ret; > + > + ret = malloc(sizeof(ECDSA_METHOD)); > + if (ret == NULL) > + { > + ECDSAerr(ECDSA_F_ECDSA_METHOD_NEW, ERR_R_MALLOC_FAILURE); > + return NULL; > + } > + > + if (ecdsa_meth) > + *ret = *ecdsa_meth; > + else > + { > + ret->ecdsa_sign_setup = 0; > + ret->ecdsa_do_sign = 0; > + ret->ecdsa_do_verify = 0; > + ret->name = NULL; > + ret->flags = 0; > + } > + ret->flags |= ECDSA_METHOD_FLAG_ALLOCATED; > + return ret; > + } > + > + > +void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method, > + ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int > dgst_len, > + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey)) > + { > + ecdsa_method->ecdsa_do_sign = ecdsa_do_sign; > + } > + > +void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method, > + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, > + BIGNUM **r)) > + { > + ecdsa_method->ecdsa_sign_setup = ecdsa_sign_setup; > + } > + > +void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method, > + int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, > + const ECDSA_SIG *sig, EC_KEY *eckey)) > + { > + ecdsa_method->ecdsa_do_verify = ecdsa_do_verify; > + } > + > +void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags) > + { > + ecdsa_method->flags = flags | ECDSA_METHOD_FLAG_ALLOCATED; > + } > + > +void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name) > + { > + ecdsa_method->name = name; > + } > + > +void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method) > + { > + if (ecdsa_method->flags & ECDSA_METHOD_FLAG_ALLOCATED) > + free(ecdsa_method); > + } > + > +void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app) > + { > + ecdsa_method->app_data = app; > + } > + > +void * ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method) > + { > + return ecdsa_method->app_data; > + } > diff --git lib/libssl/src/crypto/ecdsa/ecs_locl.h > lib/libssl/src/crypto/ecdsa/ecs_locl.h > index ceae6a2..b1cf71e 100644 > --- lib/libssl/src/crypto/ecdsa/ecs_locl.h > +++ lib/libssl/src/crypto/ecdsa/ecs_locl.h > @@ -79,9 +79,14 @@ struct ecdsa_method > int (*finish)(EC_KEY *eckey); > #endif > int flags; > - char *app_data; > + void *app_data; > }; > > +/* The ECDSA_METHOD was allocated and can be freed */ > + > +#define ECDSA_METHOD_FLAG_ALLOCATED 0x2 > + > + > /* If this flag is set the ECDSA method is FIPS compliant and can be used > * in FIPS mode. This is set in the validated module method. If an > * application sets this flag in its own methods it is its responsibility > > commit b9051ac84c79c2659f01367db90680183845d9ae > Author: pedro martelletto > Date: Thu Dec 18 13:48:05 2014 +0100 > > Implement PKCS#11 ECDSA support in SSH > Most of the changes take place in ssh-pkcs11.c, which has been > instrumented on > loading ECDSA keys. Minor changes were reflected in other files such as > ssh-pkcs11-client.c and ssh-pkcs11-helper.c. Finally, this change also > adds > ECDSA support for ssh-keygen conversions. > Joint work with Markus Friedl. > > diff --git usr.bin/ssh/ssh-keygen.c usr.bin/ssh/ssh-keygen.c > index 9031683..1a89153 100644 > --- usr.bin/ssh/ssh-keygen.c > +++ usr.bin/ssh/ssh-keygen.c > @@ -343,7 +343,10 @@ do_convert_to_pem(Key *k) > fatal("PEM_write_DSAPublicKey failed"); > break; > #endif > - /* XXX ECDSA? */ > + case KEY_ECDSA: > + if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) > + fatal("PEM_write_EC_PUBKEY failed"); > + break; > default: > fatal("%s: unsupported key type %s", __func__, > key_type(k)); > } > @@ -623,6 +626,7 @@ do_convert_from_pem(Key **k, int *private) > #ifdef notyet > DSA *dsa; > #endif > + EC_KEY *ec; > > if ((fp = fopen(identity_file, "r")) == NULL) > fatal("%s: %s: %s", __progname, identity_file, > strerror(errno)); > @@ -642,8 +646,17 @@ do_convert_from_pem(Key **k, int *private) > fclose(fp); > return; > } > - /* XXX ECDSA */ > #endif > + if ((ec = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL)) != NULL) { > + *k = key_new(KEY_UNSPEC); > + (*k)->type = KEY_ECDSA; > + (*k)->ecdsa = ec; > + (*k)->ecdsa_nid = key_ecdsa_key_to_nid(ec); > + if ((*k)->ecdsa_nid < 0) > + fatal("%s: couldn't get curve nid", __func__); > + fclose(fp); > + return; > + } > fatal("%s: unrecognised raw private key format", __func__); > } > > diff --git usr.bin/ssh/ssh-pkcs11-client.c usr.bin/ssh/ssh-pkcs11-client.c > index 2dc5f17..d2f2aa9 100644 > --- usr.bin/ssh/ssh-pkcs11-client.c > +++ usr.bin/ssh/ssh-pkcs11-client.c > @@ -1,6 +1,7 @@ > /* $OpenBSD: ssh-pkcs11-client.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */ > /* > * Copyright (c) 2010 Markus Friedl. All rights reserved. > + * Copyright (c) 2014 Pedro Martelletto. All rights reserved. > * > * Permission to use, copy, modify, and distribute this software for any > * purpose with or without fee is hereby granted, provided that the above > @@ -24,6 +25,7 @@ > #include > #include > > +#include > #include > > #include "pathnames.h" > @@ -97,8 +99,7 @@ pkcs11_terminate(void) > } > > static int > -pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA > *rsa, > - int padding) > +rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int > padding) > { > Key key; > u_char *blob, *signature = NULL; > @@ -133,16 +134,98 @@ pkcs11_rsa_private_encrypt(int flen, const u_char > *from, u_char *to, RSA *rsa, > return (ret); > } > > -/* redirect the private key encrypt operation to the ssh-pkcs11-helper */ > static int > -wrap_key(RSA *rsa) > +ecdsa_sign_setup(EC_KEY *ec, BN_CTX *ctx, BIGNUM **kinvp, BIGNUM **rp) > { > - static RSA_METHOD helper_rsa; > + error("%s called, returning -1", __func__); > + return (-1); > +} > + > +static ECDSA_SIG * > +ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, > + const BIGNUM *rp, EC_KEY *ec) > +{ > + Key key; > + u_char *blob, *signature = NULL; > + u_int blen, slen = 0; > + ECDSA_SIG *ret = NULL; > + Buffer msg; > + > + key.type = KEY_ECDSA; > + key.ecdsa = ec; > + key.ecdsa_nid = sshkey_ecdsa_key_to_nid(ec); > + if (key.ecdsa_nid < 0) { > + error("%s: couldn't get curve nid", __func__); > + return (NULL); > + } > + if (key_to_blob(&key, &blob, &blen) == 0) > + return (NULL); > + buffer_init(&msg); > + buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); > + buffer_put_string(&msg, blob, blen); > + buffer_put_string(&msg, dgst, dgst_len); > + buffer_put_int(&msg, 0); > + free(blob); > + send_msg(&msg); > + buffer_clear(&msg); > + > + if (recv_msg(&msg) == SSH2_AGENT_SIGN_RESPONSE) { > + signature = buffer_get_string(&msg, &slen); > + if (signature == NULL) { > + error("%s: buffer_get_string failed", __func__); > + goto out; > + } > + ret = d2i_ECDSA_SIG(NULL, (const u_char **)&signature, > slen); > + free(signature); > + } > +out: > + buffer_free(&msg); > + return (ret); > +} > + > +static int > +ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG > *sig, > + EC_KEY *ec) > +{ > + error("%s called, returning -1", __func__); > + return (-1); > +} > + > +static RSA_METHOD helper_rsa; > +static ECDSA_METHOD *helper_ecdsa; > + > +/* redirect private key crypto operations to the ssh-pkcs11-helper */ > +static void > +wrap_key(Key *k) > +{ > + if (k->type == KEY_RSA) > + RSA_set_method(k->rsa, &helper_rsa); > + else if (k->type == KEY_ECDSA) > + ECDSA_set_method(k->ecdsa, helper_ecdsa); > + else > + fatal("%s: unknown key type", __func__); > +} > + > +static int > +pkcs11_start_helper_methods(void) > +{ > + if (helper_ecdsa != NULL) > + return (0); > + > + helper_ecdsa = ECDSA_METHOD_new(NULL); > + if (helper_ecdsa == NULL) { > + error("ECDSA_METHOD_new() failed"); > + return (-1); > + } > + > + ECDSA_METHOD_set_sign_setup(helper_ecdsa, ecdsa_sign_setup); > + ECDSA_METHOD_set_sign(helper_ecdsa, ecdsa_do_sign); > + ECDSA_METHOD_set_verify(helper_ecdsa, ecdsa_do_verify); > > memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa)); > helper_rsa.name = "ssh-pkcs11-helper"; > - helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt; > - RSA_set_method(rsa, &helper_rsa); > + helper_rsa.rsa_priv_enc = rsa_encrypt; > + > return (0); > } > > @@ -151,6 +234,11 @@ pkcs11_start_helper(void) > { > int pair[2]; > > + if (pkcs11_start_helper_methods() == -1) { > + error("pkcs11_start_helper_methods failed"); > + return (-1); > + } > + > if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { > error("socketpair: %s", strerror(errno)); > return (-1); > @@ -203,7 +291,7 @@ pkcs11_add_provider(char *name, char *pin, Key > ***keysp) > blob = buffer_get_string(&msg, &blen); > free(buffer_get_string(&msg, NULL)); > k = key_from_blob(blob, blen); > - wrap_key(k->rsa); > + wrap_key(k); > (*keysp)[i] = k; > free(blob); > } > diff --git usr.bin/ssh/ssh-pkcs11-helper.c usr.bin/ssh/ssh-pkcs11-helper.c > index 3c2a0f2..64282de 100644 > --- usr.bin/ssh/ssh-pkcs11-helper.c > +++ usr.bin/ssh/ssh-pkcs11-helper.c > @@ -175,13 +175,26 @@ process_sign(void) > #ifdef WITH_OPENSSL > int ret; > > - slen = RSA_size(key->rsa); > - signature = xmalloc(slen); > - if ((ret = RSA_private_encrypt(dlen, data, > signature, > - found->rsa, RSA_PKCS1_PADDING)) != -1) { > - slen = ret; > - ok = 0; > - } > + if (key->type == KEY_RSA) { > + slen = RSA_size(key->rsa); > + signature = xmalloc(slen); > + ret = RSA_private_encrypt(dlen, data, > signature, > + found->rsa, RSA_PKCS1_PADDING); > + if (ret != -1) { > + slen = ret; > + ok = 0; > + } > + } else if (key->type == KEY_ECDSA) { > + slen = ECDSA_size(key->ecdsa); > + signature = xmalloc(slen); > + /* "The parameter type is ignored." */ > + ret = ECDSA_sign(-1, data, dlen, signature, > + &slen, found->ecdsa); > + if (ret != -1) > + ok = 0; > + } else > + error("%s: don't know how to sign with key > " > + "type %d", __func__, (int)key->type); > #endif /* WITH_OPENSSL */ > } > key_free(key); > diff --git usr.bin/ssh/ssh-pkcs11.c usr.bin/ssh/ssh-pkcs11.c > index 11a3370..e7ad949 100644 > --- usr.bin/ssh/ssh-pkcs11.c > +++ usr.bin/ssh/ssh-pkcs11.c > @@ -1,6 +1,7 @@ > /* $OpenBSD: ssh-pkcs11.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */ > /* > * Copyright (c) 2010 Markus Friedl. All rights reserved. > + * Copyright (c) 2014 Pedro Martelletto. All rights reserved. > * > * Permission to use, copy, modify, and distribute this software for any > * purpose with or without fee is hereby granted, provided that the above > @@ -23,6 +24,7 @@ > #include > #include > > +#include > #include > > #define CRYPTOKI_COMPAT > @@ -60,6 +62,7 @@ struct pkcs11_key { > CK_ULONG slotidx; > int (*orig_finish)(RSA *rsa); > RSA_METHOD rsa_method; > + ECDSA_METHOD *ecdsa_method; > char *keyid; > int keyid_len; > }; > @@ -210,40 +213,27 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG > slotidx, CK_ATTRIBUTE *attr, > return (ret); > } > > -/* openssl callback doing the actual signing operation */ > static int > -pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA > *rsa, > - int padding) > +pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) > { > - struct pkcs11_key *k11; > struct pkcs11_slotinfo *si; > CK_FUNCTION_LIST *f; > - CK_OBJECT_HANDLE obj; > - CK_ULONG tlen = 0; > - CK_RV rv; > - CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; > - CK_BBOOL true_val = CK_TRUE; > - CK_MECHANISM mech = { > - CKM_RSA_PKCS, NULL_PTR, 0 > - }; > - CK_ATTRIBUTE key_filter[] = { > - {CKA_CLASS, &private_key_class, sizeof(private_key_class) > }, > - {CKA_ID, NULL, 0}, > - {CKA_SIGN, &true_val, sizeof(true_val) } > - }; > + CK_OBJECT_HANDLE obj; > + CK_RV rv; > + CK_OBJECT_CLASS private_key_class; > + CK_BBOOL true_val; > + CK_MECHANISM mech; > + CK_ATTRIBUTE key_filter[3]; > char *pin, prompt[1024]; > - int rval = -1; > > - if ((k11 = RSA_get_app_data(rsa)) == NULL) { > - error("RSA_get_app_data failed for rsa %p", rsa); > - return (-1); > - } > if (!k11->provider || !k11->provider->valid) { > - error("no pkcs11 (valid) provider for rsa %p", rsa); > + error("no pkcs11 (valid) provider found"); > return (-1); > } > + > f = k11->provider->function_list; > si = &k11->provider->slotinfo[k11->slotidx]; > + > if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { > if (!pkcs11_interactive) { > error("need pin"); > @@ -263,23 +253,75 @@ pkcs11_rsa_private_encrypt(int flen, const u_char > *from, u_char *to, RSA *rsa, > free(pin); > si->logged_in = 1; > } > + > + memset(&key_filter, 0, sizeof(key_filter)); > + private_key_class = CKO_PRIVATE_KEY; > + key_filter[0].type = CKA_CLASS; > + key_filter[0].pValue = &private_key_class; > + key_filter[0].ulValueLen = sizeof(private_key_class); > + > + key_filter[1].type = CKA_ID; > key_filter[1].pValue = k11->keyid; > key_filter[1].ulValueLen = k11->keyid_len; > + > + true_val = CK_TRUE; > + key_filter[2].type = CKA_SIGN; > + key_filter[2].pValue = &true_val; > + key_filter[2].ulValueLen = sizeof(true_val); > + > /* try to find object w/CKA_SIGN first, retry w/o */ > if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) > < 0 && > pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) > < 0) { > error("cannot find private key"); > - } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != > CKR_OK) { > + return (-1); > + } > + > + memset(&mech, 0, sizeof(mech)); > + mech.mechanism = mech_type; > + mech.pParameter = NULL_PTR; > + mech.ulParameterLen = 0; > + > + if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { > error("C_SignInit failed: %lu", rv); > - } else { > - /* XXX handle CKR_BUFFER_TOO_SMALL */ > - tlen = RSA_size(rsa); > - rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, > &tlen); > - if (rv == CKR_OK) - rval = tlen; > - else - error("C_Sign failed: %lu", rv); > + return (-1); > + } > + > + return (0); > +} > + > +/* openssl callback doing the actual signing operation */ > +static int > +pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA > *rsa, > + int padding) > +{ > + struct pkcs11_key *k11; > + struct pkcs11_slotinfo *si; > + CK_FUNCTION_LIST *f; > + CK_ULONG tlen = 0; > + CK_RV rv; > + int rval = -1; > + > + if ((k11 = RSA_get_app_data(rsa)) == NULL) { > + error("RSA_get_app_data failed for rsa %p", rsa); > + return (-1); > + } > + > + if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) { > + error("pkcs11_get_key failed"); > + return (-1); > } > + > + f = k11->provider->function_list; > + si = &k11->provider->slotinfo[k11->slotidx]; > + tlen = RSA_size(rsa); > + > + /* XXX handle CKR_BUFFER_TOO_SMALL */ > + rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen); > + if (rv == CKR_OK) > + rval = tlen; > + else > + error("C_Sign failed: %lu", rv); > + > return (rval); > } > > @@ -317,6 +359,132 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, > CK_ULONG slotidx, > return (0); > } > > +/* ~*kingdom of unimplemented callbacks*~ */ > + > +static void * > +ecdsa_k11_dup(void *k11) > +{ > + fatal("%s called", __func__); > +} > + > +static void > +ecdsa_k11_free(void *k11) > +{ > + fatal("%s called", __func__); > +} > + > +static void > +ecdsa_k11_clear_free(void *k11) > +{ > + fatal("%s called", __func__); > +} > + > +static int > +ecdsa_sign_setup(EC_KEY *ec, BN_CTX *ctx, BIGNUM **kinvp, BIGNUM **rp) > +{ > + error("%s called, returning -1", __func__); > + return (-1); > +} > + > +/* openssl callback doing the actual signing operation */ > +static ECDSA_SIG * > +ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, > + const BIGNUM *rp, EC_KEY *ec) > +{ > + struct pkcs11_key *k11; > + struct pkcs11_slotinfo *si; > + CK_FUNCTION_LIST *f; > + CK_ULONG siglen = 0; > + CK_RV rv; > + ECDSA_SIG *ret = NULL; > + u_char *sig; > + const u_char *cp; > + > + if ((k11 = EC_KEY_get_key_method_data(ec, ecdsa_k11_dup, > ecdsa_k11_free, > + ecdsa_k11_clear_free)) == NULL) { > + error("EC_KEY_get_key_method_data failed for ec %p", ec); > + return (NULL); > + } > + > + if (pkcs11_get_key(k11, CKM_ECDSA) == -1) { > + error("pkcs11_get_key failed"); > + return (NULL); > + } > + > + f = k11->provider->function_list; > + si = &k11->provider->slotinfo[k11->slotidx]; > + > + siglen = ECDSA_size(ec); > + sig = xmalloc(siglen); > + > + /* XXX handle CKR_BUFFER_TOO_SMALL */ > + rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, > &siglen); > + if (rv == CKR_OK) { > + cp = sig; > + ret = d2i_ECDSA_SIG(NULL, &cp, siglen); > + } else > + error("C_Sign failed: %lu", rv); > + > + free(sig); > + > + return (ret); > +} > + > +static int > +ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG > *sig, > + EC_KEY *ec) > +{ > + error("%s called, returning -1", __func__); > + return (-1); > +} > + > +static ECDSA_METHOD *ecdsa_method; > + > +static int > +pkcs11_ecdsa_start_wrapper(void) > +{ > + if (ecdsa_method != NULL) > + return (0); > + > + ecdsa_method = ECDSA_METHOD_new(NULL); > + if (ecdsa_method == NULL) { > + error("ECDSA_METHOD_new() failed"); > + return (-1); > + } > + > + ECDSA_METHOD_set_sign_setup(ecdsa_method, ecdsa_sign_setup); > + ECDSA_METHOD_set_sign(ecdsa_method, ecdsa_do_sign); > + ECDSA_METHOD_set_verify(ecdsa_method, ecdsa_do_verify); > + > + return (0); > +} > + > +static int > +pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, > + CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) > +{ > + struct pkcs11_key *k11; > + > + if (pkcs11_ecdsa_start_wrapper() == -1) > + return (-1); > + > + k11 = xcalloc(1, sizeof(*k11)); > + k11->provider = provider; > + provider->refcount++; /* provider referenced by ECDSA key */ > + k11->slotidx = slotidx; > + /* identify key object on smartcard */ > + k11->keyid_len = keyid_attrib->ulValueLen; > + k11->keyid = xmalloc(k11->keyid_len); > + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); > + k11->ecdsa_method = ecdsa_method; > + > + ECDSA_set_method(ec, k11->ecdsa_method); > + EC_KEY_insert_key_method_data(ec, k11, ecdsa_k11_dup, > ecdsa_k11_free, > + ecdsa_k11_clear_free); > + > + return (0); > +} > + > /* remove trailing spaces */ > static void > rmspace(u_char *buf, size_t len) > @@ -370,46 +538,6 @@ pkcs11_open_session(struct pkcs11_provider *p, > CK_ULONG slotidx, char *pin) > return (0); > } > > -/* > - * lookup public keys for token in slot identified by slotidx, > - * add 'wrapped' public keys to the 'keysp' array and increment nkeys. > - * keysp points to an (possibly empty) array with *nkeys keys. > - */ > -static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG, > - CK_ATTRIBUTE [], CK_ATTRIBUTE [3], Key ***, int *) > - __attribute__((__bounded__(__minbytes__,4, 3 * > sizeof(CK_ATTRIBUTE)))); > - > -static int > -pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, > - Key ***keysp, int *nkeys) > -{ > - CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; > - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; > - CK_ATTRIBUTE pubkey_filter[] = { > - { CKA_CLASS, &pubkey_class, sizeof(pubkey_class) } > - }; > - CK_ATTRIBUTE cert_filter[] = { > - { CKA_CLASS, &cert_class, sizeof(cert_class) } > - }; > - CK_ATTRIBUTE pubkey_attribs[] = { > - { CKA_ID, NULL, 0 }, > - { CKA_MODULUS, NULL, 0 }, > - { CKA_PUBLIC_EXPONENT, NULL, 0 } > - }; > - CK_ATTRIBUTE cert_attribs[] = { > - { CKA_ID, NULL, 0 }, > - { CKA_SUBJECT, NULL, 0 }, > - { CKA_VALUE, NULL, 0 } > - }; > - > - if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, > pubkey_attribs, > - keysp, nkeys) < 0 || > - pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs, > - keysp, nkeys) < 0) > - return (-1); > - return (0); > -} > - > static int > pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) > { > @@ -421,114 +549,522 @@ pkcs11_key_included(Key ***keysp, int *nkeys, Key > *key) > return (0); > } > > -static int > -pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, > - CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], > - Key ***keysp, int *nkeys) > +static Key * > +pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, > + CK_OBJECT_HANDLE *obj) > { > - Key *key; > - RSA *rsa; > - X509 *x509; > + CK_ATTRIBUTE key_attr[3]; > + CK_SESSION_HANDLE session; > + CK_FUNCTION_LIST *f = NULL; > + CK_RV rv; > + EC_KEY *ec = NULL; > + EC_GROUP *group = NULL; > + Key *key = NULL; > + const unsigned char *attrp = NULL; > + int i; > + int nid; > + > + memset(&key_attr, 0, sizeof(key_attr)); > + key_attr[0].type = CKA_ID; > + key_attr[1].type = CKA_EC_POINT; > + key_attr[2].type = CKA_EC_PARAMS; > + > + session = p->slotinfo[slotidx].session; > + f = p->function_list; > + > + /* figure out size of the attributes */ > + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); > + if (rv != CKR_OK) { > + error("C_GetAttributeValue failed: %lu", rv); > + return (NULL); > + } > + > + /* check that none of the attributes are zero length */ > + if (key_attr[0].ulValueLen == 0 || > + key_attr[1].ulValueLen == 0 || > + key_attr[2].ulValueLen == 0) { > + error("invalid attribute length"); > + return (NULL); > + } > + > + /* allocate buffers for attributes */ > + for (i = 0; i < 3; i++) > + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); > + > + /* retrieve ID, public point and curve parameters of EC key */ > + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); > + if (rv != CKR_OK) { > + error("C_GetAttributeValue failed: %lu", rv); > + goto fail; > + } > + > + ec = EC_KEY_new(); > + if (ec == NULL) { > + error("EC_KEY_new failed"); > + goto fail; > + } > + > + attrp = key_attr[2].pValue; > + group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); > + if (group == NULL || EC_KEY_set_group(ec, group) == 0) { > + error("d2i_ECPKParameters failed"); > + goto fail; > + } > + > + if (key_attr[1].ulValueLen <= 2) { > + error("CKA_EC_POINT too small"); > + goto fail; > + } > + > + attrp = (const unsigned char *)key_attr[1].pValue + 2; > + if (o2i_ECPublicKey(&ec, &attrp, key_attr[1].ulValueLen - 2) == > NULL) { > + error("o2i_ECPublicKey failed"); > + goto fail; > + } > + > + nid = sshkey_ecdsa_key_to_nid(ec); > + if (nid < 0) { > + error("couldn't get curve nid"); > + goto fail; > + } > + > + if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) > + goto fail; > + > + key = key_new(KEY_UNSPEC); > + if (key == NULL) { > + error("key_new failed"); > + goto fail; > + } > + > + key->ecdsa = ec; > + key->ecdsa_nid = nid; > + key->type = KEY_ECDSA; > + key->flags |= SSHKEY_FLAG_EXT; > + ec = NULL; /* now owned by key */ > + > +fail: > + for (i = 0; i < 3; i++) > + free(key_attr[i].pValue); > + if (ec) > + EC_KEY_free(ec); > + if (group) > + EC_GROUP_free(group); > + > + return (key); > +} > + > +static Key * > +pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, > + CK_OBJECT_HANDLE *obj) > +{ > + CK_ATTRIBUTE key_attr[3]; > + CK_SESSION_HANDLE session; > + CK_FUNCTION_LIST *f = NULL; > + CK_RV rv; > + RSA *rsa = NULL; > + Key *key = NULL; > + int i; > + > + memset(&key_attr, 0, sizeof(key_attr)); > + key_attr[0].type = CKA_ID; > + key_attr[1].type = CKA_MODULUS; > + key_attr[2].type = CKA_PUBLIC_EXPONENT; > + > + session = p->slotinfo[slotidx].session; > + f = p->function_list; > + > + /* figure out size of the attributes */ > + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); > + if (rv != CKR_OK) { > + error("C_GetAttributeValue failed: %lu", rv); > + return (NULL); > + } > + > + /* check that none of the attributes are zero length */ > + if (key_attr[0].ulValueLen == 0 || > + key_attr[1].ulValueLen == 0 || > + key_attr[2].ulValueLen == 0) { > + error("invalid attribute length"); > + return (NULL); > + } > + > + /* allocate buffers for attributes */ > + for (i = 0; i < 3; i++) > + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); > + > + /* retrieve ID, modulus and public exponent of RSA key */ > + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); > + if (rv != CKR_OK) { > + error("C_GetAttributeValue failed: %lu", rv); > + goto fail; > + } > + > + rsa = RSA_new(); > + if (rsa == NULL) { > + error("RSA_new failed"); > + goto fail; > + } > + > + rsa->n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, > NULL); > + rsa->e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, > NULL); > + if (rsa->n == NULL || rsa->e == NULL) { > + error("BN_bin2bn failed"); > + goto fail; > + } > + > + if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) > + goto fail; > + > + key = key_new(KEY_UNSPEC); > + if (key == NULL) { > + error("key_new failed"); > + goto fail; > + } > + > + key->rsa = rsa; > + key->type = KEY_RSA; > + key->flags |= SSHKEY_FLAG_EXT; > + rsa = NULL; /* now owned by key */ > + > +fail: > + for (i = 0; i < 3; i++) > + free(key_attr[i].pValue); > + if (rsa) > + RSA_free(rsa); > + > + return (key); > +} > + > +static Key * > +pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, > + CK_OBJECT_HANDLE *obj) > +{ > + CK_ATTRIBUTE cert_attr[3]; > + CK_SESSION_HANDLE session; > + CK_FUNCTION_LIST *f = NULL; > + CK_RV rv; > + X509 *x509 = NULL; > EVP_PKEY *evp; > - int i; > - const u_char *cp; > - CK_RV rv; > - CK_OBJECT_HANDLE obj; > - CK_ULONG nfound; > - CK_SESSION_HANDLE session; > - CK_FUNCTION_LIST *f; > + RSA *rsa = NULL; > + EC_KEY *ec = NULL; > + Key *key = NULL; > + int i; > + int nid; > + const u_char *cp; > + > + memset(&cert_attr, 0, sizeof(cert_attr)); > + cert_attr[0].type = CKA_ID; > + cert_attr[1].type = CKA_SUBJECT; > + cert_attr[2].type = CKA_VALUE; > > + session = p->slotinfo[slotidx].session; > f = p->function_list; > + > + /* figure out size of the attributes */ > + rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); > + if (rv != CKR_OK) { > + error("C_GetAttributeValue failed: %lu", rv); > + return (NULL); > + } > + > + /* check that none of the attributes are zero length */ > + if (cert_attr[0].ulValueLen == 0 || > + cert_attr[1].ulValueLen == 0 || > + cert_attr[2].ulValueLen == 0) { > + error("invalid attribute length"); > + return (NULL); > + } > + > + /* allocate buffers for attributes */ > + for (i = 0; i < 3; i++) > + cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); > + > + /* retrieve ID, subject and value of certificate */ > + rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); > + if (rv != CKR_OK) { > + error("C_GetAttributeValue failed: %lu", rv); > + goto fail; > + } > + > + x509 = X509_new(); > + if (x509 == NULL) { > + error("x509_new failed"); > + goto fail; > + } > + > + cp = cert_attr[2].pValue; > + if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) { > + error("d2i_x509 failed"); > + goto fail; > + } > + > + evp = X509_get_pubkey(x509); > + if (evp == NULL) { > + error("X509_get_pubkey failed"); > + goto fail; > + } > + > + if (evp->type == EVP_PKEY_RSA) { > + if (evp->pkey.rsa == NULL) { > + error("invalid x509; no rsa key"); > + goto fail; > + } > + if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) == NULL) { > + error("RSAPublicKey_dup failed"); > + goto fail; > + } > + > + if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) > + goto fail; > + > + key = key_new(KEY_UNSPEC); > + if (key == NULL) { > + error("key_new failed"); > + goto fail; > + } > + > + key->rsa = rsa; > + key->type = KEY_RSA; > + key->flags |= SSHKEY_FLAG_EXT; > + rsa = NULL; /* now owned by key */ > + } else if (evp->type == EVP_PKEY_EC) { > + if (evp->pkey.ec == NULL) { > + error("invalid x509; no ec key"); > + goto fail; > + } > + if ((ec = EC_KEY_dup(evp->pkey.ec)) == NULL) { > + error("EC_KEY_dup failed"); > + goto fail; > + } > + > + nid = sshkey_ecdsa_key_to_nid(ec); > + if (nid < 0) { > + error("couldn't get curve nid"); > + goto fail; > + } > + > + if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) > + goto fail; > + > + key = key_new(KEY_UNSPEC); > + if (key == NULL) { > + error("key_new failed"); > + goto fail; > + } > + > + key->ecdsa = ec; > + key->ecdsa_nid = nid; > + key->type = KEY_ECDSA; > + key->flags |= SSHKEY_FLAG_EXT; > + ec = NULL; /* now owned by key */ > + } else > + error("unknown certificate key type"); > + > +fail: > + for (i = 0; i < 3; i++) > + free(cert_attr[i].pValue); > + if (x509) > + X509_free(x509); > + if (rsa) > + RSA_free(rsa); > + if (ec) > + EC_KEY_free(ec); > + > + return (key); > +} > + > +/* > + * lookup certificates for token in slot identified by slotidx, > + * add 'wrapped' public keys to the 'keysp' array and increment nkeys. > + * keysp points to an (possibly empty) array with *nkeys keys. > + */ > +static int > +pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, Key > ***keysp, > + int *nkeys) > +{ > + Key *key = NULL; > + CK_OBJECT_CLASS key_class; > + CK_ATTRIBUTE key_attr[1]; > + CK_SESSION_HANDLE session; > + CK_FUNCTION_LIST *f = NULL; > + CK_RV rv; > + CK_OBJECT_HANDLE obj; > + CK_ULONG n = 0; > + int ret = -1; > + > + memset(&key_attr, 0, sizeof(key_attr)); > + memset(&obj, 0, sizeof(obj)); > + > + key_class = CKO_CERTIFICATE; > + key_attr[0].type = CKA_CLASS; > + key_attr[0].pValue = &key_class; > + key_attr[0].ulValueLen = sizeof(key_class); > + > session = p->slotinfo[slotidx].session; > - /* setup a filter the looks for public keys */ > - if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) { > + f = p->function_list; > + > + rv = f->C_FindObjectsInit(session, key_attr, 1); > + if (rv != CKR_OK) { > error("C_FindObjectsInit failed: %lu", rv); > - return (-1); > + goto fail; > } > + > while (1) { > - /* XXX 3 attributes in attribs[] */ > - for (i = 0; i < 3; i++) { > - attribs[i].pValue = NULL; > - attribs[i].ulValueLen = 0; > + CK_CERTIFICATE_TYPE ck_cert_type; > + > + rv = f->C_FindObjects(session, &obj, 1, &n); > + if (rv != CKR_OK) { > + error("C_FindObjects failed: %lu", rv); > + goto fail; > } > - if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != > CKR_OK > - || nfound == 0) > + if (n == 0) > break; > - /* found a key, so figure out size of the attributes */ > - if ((rv = f->C_GetAttributeValue(session, obj, attribs, > 3)) > - != CKR_OK) { > + > + memset(&ck_cert_type, 0, sizeof(ck_cert_type)); > + memset(&key_attr, 0, sizeof(key_attr)); > + key_attr[0].type = CKA_CERTIFICATE_TYPE; > + key_attr[0].pValue = &ck_cert_type; > + key_attr[0].ulValueLen = sizeof(ck_cert_type); > + > + rv = f->C_GetAttributeValue(session, obj, key_attr, 1); > + if (rv != CKR_OK) { > error("C_GetAttributeValue failed: %lu", rv); > - continue; > + goto fail; > + } > + > + switch (ck_cert_type) { > + case CKC_X_509: > + key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj); > + break; > + default: > + /* XXX print key type? */ > + error("skipping unsupported certificate type"); > } > - /* check that none of the attributes are zero length */ > - if (attribs[0].ulValueLen == 0 || > - attribs[1].ulValueLen == 0 || > - attribs[2].ulValueLen == 0) { > + > + if (key == NULL) { > + error("failed to fetch key"); > continue; > } > - /* allocate buffers for attributes */ > - for (i = 0; i < 3; i++) > - attribs[i].pValue = xmalloc(attribs[i].ulValueLen) > ; > - /* > - * retrieve ID, modulus and public exponent of RSA key, > - * or ID, subject and value for certificates. > - */ > - rsa = NULL; > - if ((rv = f->C_GetAttributeValue(session, obj, attribs, > 3)) > - != CKR_OK) { > - error("C_GetAttributeValue failed: %lu", rv); > - } else if (attribs[1].type == CKA_MODULUS ) { > - if ((rsa = RSA_new()) == NULL) { > - error("RSA_new failed"); > - } else { > - rsa->n = BN_bin2bn(attribs[1].pValue, > - attribs[1].ulValueLen, NULL); > - rsa->e = BN_bin2bn(attribs[2].pValue, > - attribs[2].ulValueLen, NULL); > - } > + > + if (pkcs11_key_included(keysp, nkeys, key)) { > + key_free(key); > } else { > - cp = attribs[2].pValue; > - if ((x509 = X509_new()) == NULL) { > - error("X509_new failed"); > - } else if (d2i_X509(&x509, &cp, > attribs[2].ulValueLen) > - == NULL) { > - error("d2i_X509 failed"); > - } else if ((evp = X509_get_pubkey(x509)) == NULL || > - evp->type != EVP_PKEY_RSA || > - evp->pkey.rsa == NULL) { > - debug("X509_get_pubkey failed or no rsa"); > - } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) > - == NULL) { > - error("RSAPublicKey_dup"); > - } > - if (x509) > - X509_free(x509); > + /* expand key array and add key */ > + *keysp = xrealloc(*keysp, *nkeys + 1, sizeof(Key > *)); > + (*keysp)[*nkeys] = key; > + *nkeys = *nkeys + 1; > + debug("have %d keys", *nkeys); > } > - if (rsa && rsa->n && rsa->e && > - pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { > - key = key_new(KEY_UNSPEC); > - key->rsa = rsa; > - key->type = KEY_RSA; > - key->flags |= SSHKEY_FLAG_EXT; > - if (pkcs11_key_included(keysp, nkeys, key)) { > - key_free(key); > - } else { > - /* expand key array and add key */ > - *keysp = xrealloc(*keysp, *nkeys + 1, > - sizeof(Key *)); > - (*keysp)[*nkeys] = key; > - *nkeys = *nkeys + 1; > - debug("have %d keys", *nkeys); > - } > - } else if (rsa) { > - RSA_free(rsa); > + } > + > + ret = 0; > +fail: > + rv = f->C_FindObjectsFinal(session); > + if (rv != CKR_OK) { > + error("C_FindObjectsFinal failed: %lu", rv); > + ret = -1; > + } > + > + return (ret); > +} > + > +/* > + * lookup public keys for token in slot identified by slotidx, > + * add 'wrapped' public keys to the 'keysp' array and increment nkeys. > + * keysp points to an (possibly empty) array with *nkeys keys. > + */ > +static int > +pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key > ***keysp, > + int *nkeys) > +{ > + Key *key = NULL; > + CK_OBJECT_CLASS key_class; > + CK_ATTRIBUTE key_attr[1]; > + CK_SESSION_HANDLE session; > + CK_FUNCTION_LIST *f = NULL; > + CK_RV rv; > + CK_OBJECT_HANDLE obj; > + CK_ULONG n = 0; > + int ret = -1; > + > + memset(&key_attr, 0, sizeof(key_attr)); > + memset(&obj, 0, sizeof(obj)); > + > + key_class = CKO_PUBLIC_KEY; > + key_attr[0].type = CKA_CLASS; > + key_attr[0].pValue = &key_class; > + key_attr[0].ulValueLen = sizeof(key_class); > + > + session = p->slotinfo[slotidx].session; > + f = p->function_list; > + > + rv = f->C_FindObjectsInit(session, key_attr, 1); > + if (rv != CKR_OK) { > + error("C_FindObjectsInit failed: %lu", rv); > + goto fail; > + } > + > + while (1) { > + CK_KEY_TYPE ck_key_type; > + > + rv = f->C_FindObjects(session, &obj, 1, &n); > + if (rv != CKR_OK) { > + error("C_FindObjects failed: %lu", rv); > + goto fail; > + } > + if (n == 0) > + break; > + > + memset(&ck_key_type, 0, sizeof(ck_key_type)); > + memset(&key_attr, 0, sizeof(key_attr)); > + key_attr[0].type = CKA_KEY_TYPE; > + key_attr[0].pValue = &ck_key_type; > + key_attr[0].ulValueLen = sizeof(ck_key_type); > + > + rv = f->C_GetAttributeValue(session, obj, key_attr, 1); > + if (rv != CKR_OK) { > + error("C_GetAttributeValue failed: %lu", rv); > + goto fail; > + } > + > + switch (ck_key_type) { > + case CKK_RSA: > + key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); > + break; > + case CKK_ECDSA: > + key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); > + break; > + default: > + /* XXX print key type? */ > + error("skipping unsupported key type"); > + } > + > + if (key == NULL) { > + error("failed to fetch key"); > + continue; > + } > + > + if (pkcs11_key_included(keysp, nkeys, key)) { > + key_free(key); > + } else { > + /* expand key array and add key */ > + *keysp = xrealloc(*keysp, *nkeys + 1, sizeof(Key > *)); > + (*keysp)[*nkeys] = key; > + *nkeys = *nkeys + 1; > + debug("have %d keys", *nkeys); > } > - for (i = 0; i < 3; i++) > - free(attribs[i].pValue); > } > - if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK) > + > + ret = 0; > +fail: > + rv = f->C_FindObjectsFinal(session); > + if (rv != CKR_OK) { > error("C_FindObjectsFinal failed: %lu", rv); > - return (0); > + ret = -1; > + } > + > + return (ret); > } > > #ifdef HAVE_DLOPEN > @@ -620,8 +1156,10 @@ pkcs11_add_provider(char *provider_id, char *pin, > Key ***keyp) > token->label, token->manufacturerID, token->model, > token->serialNumber, token->flags); > /* open session, login with pin and retrieve public keys */ > - if (pkcs11_open_session(p, i, pin) == 0) > + if (pkcs11_open_session(p, i, pin) == 0) { > pkcs11_fetch_keys(p, i, keyp, &nkeys); > + pkcs11_fetch_certs(p, i, keyp, &nkeys); From deengert at gmail.com Wed Apr 1 12:54:11 2015 From: deengert at gmail.com (Douglas E Engert) Date: Tue, 31 Mar 2015 20:54:11 -0500 Subject: Wanted: smartcard with ECDSA support In-Reply-To: References: Message-ID: <551B4FC3.1020408@gmail.com> On 3/31/2015 6:14 PM, Damien Miller wrote: > On Tue, 31 Mar 2015, Thomas Calderon wrote: > >> Hi list, >> >> I have no idea if Damien Miller had the time to work on that. >> >> I have an initial patch to authenticate using PKCS#11 and ECDSA keys. >> This requires OpenSSL 1.0.2, prior OpenSSL versions do not expose the >> required interfaces to override the signature function pointer for ECDSA. >> The only limitation is that the OpenSSL API misses some cleanup function >> (finish, for instance), hence I have yet to find a way to properly free the >> PKCS#11 resources. >> >> Is this a contribution you might be interested in ? > > There's another ECDSA-for-PKCS#11 patch floating around too, but yes. > > I never found ECDSA-capable smartcards. Donations of a couple are > still welcome. (Ask Yubico and Smartcard-HSM as they sell the cards in small numbers, and the user can configure them.) Newer NIST PIV cards,(But not in the field yet) Oberthur and GemAlto among others. Yubico NEO with PIV applet, https://developers.yubico.com/yubico-piv-tool/YubiKey_NEO_PIV_introduction.html Smartcard-HSM: http://www.smartcard-hsm.com/2014/08/22/using-smartcard-hsm-with-ecc-and-opensc.html myeid has some support, check the web. All of the above are supported by OpenSC's ECDSA. (The PIV cards can also do ECDH.) > > -d > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > . > -- Douglas E. Engert From aixtools at gmail.com Wed Apr 1 23:37:59 2015 From: aixtools at gmail.com (Michael Felt) Date: Wed, 1 Apr 2015 14:37:59 +0200 Subject: FYI: SSH1 now disabled at compile-time by default In-Reply-To: <1725770.eLHRcz5pDi@pintsize.usersys.redhat.com> References: <5194613.qjudOLPiy3@pintsize.usersys.redhat.com> <20150327131547.GH21893@greenie.muc.de> <1725770.eLHRcz5pDi@pintsize.usersys.redhat.com> Message-ID: I mentioned extensions because I had a few and saw them die. the 40-bit ssl is the web interface for power5 (the so-called ASMI https interface). These ports have no access to "outside", on a separate lan segment. my desktop, not acting as router, can connect to non-Natted and NATted segments. re: use of a stunnel - how does this turn 40-bit https into >40-bit https. Sounds like a man-in-the-middle I do not want to know about (but should learn about just the same - aka the sand is not so deep I can bury my head completely :) On Mar 27, 2015 2:37 PM, "Hubert Kario" wrote: > On Friday 27 March 2015 14:15:47 Gert Doering wrote: > > Hi, > > > > On Fri, Mar 27, 2015 at 12:53:05PM +0100, Hubert Kario wrote: > > > On Thursday 26 March 2015 11:19:28 Michael Felt wrote: > > > > Experience: I have some hardware, on an internal network - that only > > > > supports 40-bit ssl. I am forced to continue to use FF v17 because > that > > > > was > > > > the last browser to provide SSL40-bit support. My security is > weakened > > > > because I cannot update that browser, and I continue to lose plugins > > > > because they do not support FF17 anymore. All other browsers stopped > > > > support earlier as well. > > > > > > Please put the device behind a stunnel and don't put yourself at risk. > > > > I don't think Michael is accessing that device over the Internet - but > even > > *in house* some devices force you to jump through such hoops. > > the fact that he mentions usage of extensions, I'm not so sure he uses it > only > for internal out-of-band management sites... > > > Like, old HP ILO that you can't get updates for, that insist on using > SSL, > > but then fail to interoperate with recent browsers. So what are you > going > > to do? "Throw away a perfectly working and secure machine, because its > > out of band interface is crap" or "keep around an old and insecure > browser"? > > such interfaces should be on a network of their own, as such you should go > through a router to be able to connect to them. On same router you can put > the > stunnel or a redirect to other machine that does the tunneling to make sure > the insecure connections from trusted network are not routed over regular > network (be it company internal or Internet) > > > Same thing with needing sshv1 to access old network gear where even sshv1 > > was an achievement. "Throw away gear that does its job perfectly well, > > but has no sshv2 for *management*" or "keep around an ssh v1 capable > > client"? > > If you depend on hardware like this, you should have support* for it. > Exactly > because issues like this. > > * - where "support" means that either you have other people responsible > for > fixing it or that you can hire other people to fix it as the need arises > -- > Regards, > Hubert Kario From hkario at redhat.com Thu Apr 2 00:05:56 2015 From: hkario at redhat.com (Hubert Kario) Date: Wed, 01 Apr 2015 15:05:56 +0200 Subject: FYI: SSH1 now disabled at compile-time by default In-Reply-To: References: <1725770.eLHRcz5pDi@pintsize.usersys.redhat.com> Message-ID: <4670512.txzuGUQWMF@pintsize.usersys.redhat.com> On Wednesday 01 April 2015 14:37:59 Michael Felt wrote: > re: use of a stunnel - how does this turn 40-bit https into >40-bit https. > Sounds like a man-in-the-middle I do not want to know about (but should > learn about just the same - aka the sand is not so deep I can bury my head > completely :) Yes, it is literally a "man in the middle", the point is, that this man is *you*, and as such, you can trust him, at least as much as you can trust the server itself It's the same way a reverse proxy turns a local HTTP server running on port 8080 (or any other for that matter) into a proper HTTPS server. Or in other words, it's to turn something like this: | trusted network here client .-,( ),-. __ _ .-( )-. router server [__]|=| ---->( internet )-------> __________ ------> ____ __ /::/|_| SSLv2 '-( ).-' SSLv2 [...__...?] SSLv2 | | |==| '-.( ).-' |____| | | /::::/ |__| into something like this: | trusted network here client .-,( ),-. __ _ .-( )-. router server [__]|=| ---->( internet )-------> __________ ------> ____ __ /::/|_| TLS1.2 '-( ).-' TLS1.2 [...__...?] SSLv2 | | |==| '-.( ).-' ? |____| | | stunnel /::::/ |__| (diagram taken from http://unix.stackexchange.com/a/126638) -- Regards, Hubert Kario Quality Engineer, QE BaseOS Security team Web: www.cz.redhat.com Red Hat Czech s.r.o., Purky?ova 99/71, 612 45, Brno, Czech Republic -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: This is a digitally signed message part. URL: From aixtools at gmail.com Thu Apr 2 00:40:36 2015 From: aixtools at gmail.com (Michael Felt) Date: Wed, 1 Apr 2015 15:40:36 +0200 Subject: FYI: SSH1 now disabled at compile-time by default In-Reply-To: <4670512.txzuGUQWMF@pintsize.usersys.redhat.com> References: <1725770.eLHRcz5pDi@pintsize.usersys.redhat.com> <4670512.txzuGUQWMF@pintsize.usersys.redhat.com> Message-ID: Ok - thanks. stunnel is something 'useful' to study. Hopefully I will not have to hit my head against the wall too often. That said - is there (an official) way to disable ssh1 in the server (e.g., --without-ssh1 Disable support for SSH protocol 1) but keep support in the client? That is how I would like to package it as of today. And I expect, (read hope) that even though support is compiled in, I could still disable it - by default - in the client via ssh_config. Michael p.s. Hubert - my apologies for the double send, forgot reply-to-all. On Wed, Apr 1, 2015 at 3:05 PM, Hubert Kario wrote: > On Wednesday 01 April 2015 14:37:59 Michael Felt wrote: > > re: use of a stunnel - how does this turn 40-bit https into >40-bit > https. > > Sounds like a man-in-the-middle I do not want to know about (but should > > learn about just the same - aka the sand is not so deep I can bury my > head > > completely :) > > Yes, it is literally a "man in the middle", the point is, that this man is > *you*, and as such, you can trust him, at least as much as you can trust > the > server itself > > It's the same way a reverse proxy turns a local HTTP server running on port > 8080 (or any other for that matter) into a proper HTTPS server. > > > Or in other words, it's to turn something like this: > > > > | trusted network here > client .-,( ),-. > __ _ .-( )-. router server > [__]|=| ---->( internet )-------> __________ ------> ____ __ > /::/|_| SSLv2 '-( ).-' SSLv2 [...__...?] SSLv2 | | |==| > '-.( ).-' |____| | | > /::::/ |__| > > > > into something like this: > > | trusted network here > client .-,( ),-. > __ _ .-( )-. router server > [__]|=| ---->( internet )-------> __________ ------> ____ __ > /::/|_| TLS1.2 '-( ).-' TLS1.2 [...__...?] SSLv2 | | |==| > '-.( ).-' ? |____| | | > stunnel /::::/ |__| > > > > (diagram taken from http://unix.stackexchange.com/a/126638) > -- > Regards, > Hubert Kario > Quality Engineer, QE BaseOS Security team > Web: www.cz.redhat.com > Red Hat Czech s.r.o., Purky?ova 99/71, 612 45, Brno, Czech Republic > From dan at doxpara.com Thu Apr 2 05:13:34 2015 From: dan at doxpara.com (Dan Kaminsky) Date: Wed, 1 Apr 2015 11:13:34 -0700 Subject: FYI: SSH1 now disabled at compile-time by default In-Reply-To: References: <1725770.eLHRcz5pDi@pintsize.usersys.redhat.com> <4670512.txzuGUQWMF@pintsize.usersys.redhat.com> Message-ID: It is disabled by default in the client, in the sense that you need to actually run ssh -1. If you didn't I'd be on the side of the pitchforks saying why are we subjecting all these clients to downgrade attack risk. --Dan On Wed, Apr 1, 2015 at 6:40 AM, Michael Felt wrote: > Ok - thanks. stunnel is something 'useful' to study. Hopefully I will not > have to hit my head against the wall too often. > > That said - is there (an official) way to disable ssh1 in the server > (e.g., --without-ssh1 Disable support for SSH protocol 1) but > keep support in the client? > > That is how I would like to package it as of today. > > And I expect, (read hope) that even though support is compiled in, I could > still disable it - by default - in the client via ssh_config. > > Michael > > p.s. Hubert - my apologies for the double send, forgot reply-to-all. > > On Wed, Apr 1, 2015 at 3:05 PM, Hubert Kario wrote: > > > On Wednesday 01 April 2015 14:37:59 Michael Felt wrote: > > > re: use of a stunnel - how does this turn 40-bit https into >40-bit > > https. > > > Sounds like a man-in-the-middle I do not want to know about (but should > > > learn about just the same - aka the sand is not so deep I can bury my > > head > > > completely :) > > > > Yes, it is literally a "man in the middle", the point is, that this man > is > > *you*, and as such, you can trust him, at least as much as you can trust > > the > > server itself > > > > It's the same way a reverse proxy turns a local HTTP server running on > port > > 8080 (or any other for that matter) into a proper HTTPS server. > > > > > > Or in other words, it's to turn something like this: > > > > > > > > | trusted network here > > client .-,( ),-. > > __ _ .-( )-. router server > > [__]|=| ---->( internet )-------> __________ ------> ____ __ > > /::/|_| SSLv2 '-( ).-' SSLv2 [...__...?] SSLv2 | | |==| > > '-.( ).-' |____| | | > > /::::/ |__| > > > > > > > > into something like this: > > > > | trusted network here > > client .-,( ),-. > > __ _ .-( )-. router server > > [__]|=| ---->( internet )-------> __________ ------> ____ __ > > /::/|_| TLS1.2 '-( ).-' TLS1.2 [...__...?] SSLv2 | | |==| > > '-.( ).-' ? |____| | | > > stunnel /::::/ |__| > > > > > > > > (diagram taken from http://unix.stackexchange.com/a/126638) > > -- > > Regards, > > Hubert Kario > > Quality Engineer, QE BaseOS Security team > > Web: www.cz.redhat.com > > Red Hat Czech s.r.o., Purky?ova 99/71, 612 45, Brno, Czech Republic > > > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > From aixtools at gmail.com Thu Apr 2 08:45:15 2015 From: aixtools at gmail.com (Michael Felt) Date: Wed, 1 Apr 2015 23:45:15 +0200 Subject: What did I miss when building openssh? cannot generate ecdsa key Message-ID: I am assuming this is a user error (and the bug, if any is in configure not telling me how to activate it). I regularly see a message: Could not load host key: /etc/ssh/ssh_host_ecdsa_key And, obviously, I have never made the key before. I tried the following: ./ssh-keygen -t ecdsa -fssh_host_esdsa_key -N "" unknown key type ecdsa However, the syntax says it is a known type root at x064:[/data/prj/openbsd/openssh/openssh-6.8p1]./ssh-keygen -? unknown option -- ? usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] [-N new_passphrase] [-C comment] [-f output_keyfile] ... What did I miss? regards, Michael Felt p.s. make check|tests - they all passed. p.p.s. - this is built against an ancient openssl, so maybe the problem is there. OpenSSH_6.8p1, OpenSSL 0.9.8k 25 Mar 2009 And, yes - I know I newer openssl is much better, but this is taking a system where it is at - i.e., I assume openssl is not yet upgraded. will be trying against openssl-1.something tomorrow. From scott_n at xypro.com Thu Apr 2 08:53:13 2015 From: scott_n at xypro.com (Scott Neugroschl) Date: Wed, 1 Apr 2015 21:53:13 +0000 Subject: What did I miss when building openssh? cannot generate ecdsa key In-Reply-To: References: Message-ID: I think that you're right about the OpenSSL. ISTR that ECC didn't appear until the 1.0.0 series. -----Original Message----- From: openssh-unix-dev [mailto:openssh-unix-dev-bounces+scott_n=xypro.com at mindrot.org] On Behalf Of Michael Felt Sent: Wednesday, April 01, 2015 2:45 PM To: OpenSSH Devel List Subject: What did I miss when building openssh? cannot generate ecdsa key I am assuming this is a user error (and the bug, if any is in configure not telling me how to activate it). I regularly see a message: Could not load host key: /etc/ssh/ssh_host_ecdsa_key And, obviously, I have never made the key before. I tried the following: ./ssh-keygen -t ecdsa -fssh_host_esdsa_key -N "" unknown key type ecdsa However, the syntax says it is a known type root at x064:[/data/prj/openbsd/openssh/openssh-6.8p1]./ssh-keygen -? unknown option -- ? usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] [-N new_passphrase] [-C comment] [-f output_keyfile] ... What did I miss? regards, Michael Felt p.s. make check|tests - they all passed. p.p.s. - this is built against an ancient openssl, so maybe the problem is there. OpenSSH_6.8p1, OpenSSL 0.9.8k 25 Mar 2009 And, yes - I know I newer openssl is much better, but this is taking a system where it is at - i.e., I assume openssl is not yet upgraded. will be trying against openssl-1.something tomorrow. _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev at mindrot.org https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev From mancha1 at zoho.com Thu Apr 2 09:22:46 2015 From: mancha1 at zoho.com (mancha) Date: Wed, 1 Apr 2015 22:22:46 +0000 Subject: What did I miss when building openssh? cannot generate ecdsa key In-Reply-To: References: Message-ID: <20150401222246.GA9674@zoho.com> On Wed, Apr 01, 2015 at 09:53:13PM +0000, Scott Neugroschl wrote: > I think that you're right about the OpenSSL. ISTR that ECC didn't > appear until the 1.0.0 series. > > -----Original Message----- From: openssh-unix-dev > [mailto:openssh-unix-dev-bounces+scott_n=xypro.com at mindrot.org] On > Behalf Of Michael Felt Sent: Wednesday, April 01, 2015 2:45 PM To: > OpenSSH Devel List Subject: What did I miss when building openssh? > cannot generate ecdsa key > > I am assuming this is a user error (and the bug, if any is in > configure not telling me how to activate it). > > I regularly see a message: Could not load host key: > /etc/ssh/ssh_host_ecdsa_key > > And, obviously, I have never made the key before. > > I tried the following: ./ssh-keygen -t ecdsa -fssh_host_esdsa_key -N > "" unknown key type ecdsa > > However, the syntax says it is a known type > > root at x064:[/data/prj/openbsd/openssh/openssh-6.8p1]./ssh-keygen -? > unknown option -- ? usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa > | ed25519 | rsa | rsa1] [-N new_passphrase] [-C comment] [-f > output_keyfile] ... > > What did I miss? > > regards, Michael Felt > > p.s. make check|tests - they all passed. > > p.p.s. - this is built against an ancient openssl, so maybe the > problem is there. OpenSSH_6.8p1, OpenSSL 0.9.8k 25 Mar 2009 > > And, yes - I know I newer openssl is much better, but this is taking a > system where it is at - i.e., I assume openssl is not yet upgraded. > will be trying against openssl-1.something tomorrow. Actually, you should be OK with OpenSSL 0.9.8 (as long as it's post 0.9.8f, iirc). Try compiling and running the attached. --mancha -------------- next part -------------- /* gcc -o ecc ecc.c -lcrypto -lssl */ #include #include #include #include #include #include int main () { EC_KEY *ecdh = NULL; const EVP_MD *md; ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ecdh = EC_KEY_new_by_curve_name(NID_secp384r1); ecdh = EC_KEY_new_by_curve_name(NID_secp521r1); md = EVP_sha256(); md = EVP_sha384(); md = EVP_sha512(); return 0; } -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 819 bytes Desc: not available URL: From scott_n at xypro.com Thu Apr 2 09:49:23 2015 From: scott_n at xypro.com (Scott Neugroschl) Date: Wed, 1 Apr 2015 22:49:23 +0000 Subject: What did I miss when building openssh? cannot generate ecdsa key In-Reply-To: <20150401222246.GA9674@zoho.com> References: <20150401222246.GA9674@zoho.com> Message-ID: On Wed, Apr 01, 2015 at 09:53:13PM +0000, Scott Neugroschl wrote: SN> I think that you're right about the OpenSSL. ISTR that ECC didn't SN> appear until the 1.0.0 series. mancha>Actually, you should be OK with OpenSSL 0.9.8 (as long as it's post 0.9.8f, iirc). You're right. I went back and checked release notes. ECDSA was available in the 0.9.8 series. My mistake. Sorry. From djm at mindrot.org Thu Apr 2 13:30:55 2015 From: djm at mindrot.org (Damien Miller) Date: Thu, 2 Apr 2015 13:30:55 +1100 (AEDT) Subject: What did I miss when building openssh? cannot generate ecdsa key In-Reply-To: References: Message-ID: Yes, your OpenSSL probably lacks EC support. You shouldn't see the "Could not load host key" unless there is a Hostkey line in sshd_config referencing that key. On Wed, 1 Apr 2015, Michael Felt wrote: > I am assuming this is a user error (and the bug, if any is in configure not > telling me how to activate it). > > I regularly see a message: > Could not load host key: /etc/ssh/ssh_host_ecdsa_key > > And, obviously, I have never made the key before. > > I tried the following: > ./ssh-keygen -t ecdsa -fssh_host_esdsa_key -N "" > unknown key type ecdsa > > However, the syntax says it is a known type > > root at x064:[/data/prj/openbsd/openssh/openssh-6.8p1]./ssh-keygen -? > unknown option -- ? > usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] > [-N new_passphrase] [-C comment] [-f output_keyfile] > ... > > What did I miss? > > regards, > Michael Felt > > p.s. make check|tests - they all passed. > > p.p.s. - this is built against an ancient openssl, so maybe the problem is > there. > OpenSSH_6.8p1, OpenSSL 0.9.8k 25 Mar 2009 > > And, yes - I know I newer openssl is much better, but this is taking a > system where it is at - i.e., I assume openssl is not yet upgraded. will be > trying against openssl-1.something tomorrow. > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > From bryan at shatow.net Sat Apr 4 12:03:34 2015 From: bryan at shatow.net (Bryan Drewery) Date: Fri, 3 Apr 2015 20:03:34 -0500 Subject: [PATCH] Fix spelling of TEST_SSH_SSHD_CONFOPTS and TEST_SSH_SSH_CONFOPTS Message-ID: <1428109414-75135-1-git-send-email-bryan@shatow.net> --- regress/README.regress | 2 +- regress/test-exec.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/regress/README.regress b/regress/README.regress index 82e4cc7..9b99bda 100644 --- a/regress/README.regress +++ b/regress/README.regress @@ -31,7 +31,7 @@ TEST_SHELL: shell used for running the test scripts. TEST_SSH_PORT: TCP port to be used for the listening tests. TEST_SSH_SSH_CONFOPTS: Configuration directives to be added to ssh_config before running each test. -TEST_SSH_SSHD_CONFOTPS: Configuration directives to be added to sshd_config +TEST_SSH_SSHD_CONFOPTS: Configuration directives to be added to sshd_config before running each test. diff --git a/regress/test-exec.sh b/regress/test-exec.sh index 0f76662..114e129 100644 --- a/regress/test-exec.sh +++ b/regress/test-exec.sh @@ -444,7 +444,7 @@ Host * EOF if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then - trace "adding ssh_config option $TEST_SSH_SSHD_CONFOPTS" + trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS" echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config fi -- 2.3.4 From pgut001 at cs.auckland.ac.nz Tue Apr 7 00:29:52 2015 From: pgut001 at cs.auckland.ac.nz (Peter Gutmann) Date: Mon, 6 Apr 2015 14:29:52 +0000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST Message-ID: <9A043F3CF02CD34C8E74AC1594475C73AAFDBAC3@uxcn10-tdc05.UoA.auckland.ac.nz> I've had a report from a user that "SSH-2.0-OpenSSH_6.6.1_hpn13v11 FreeBSD-20140420" is sending an invalid SSH_MSG_USERAUTH_INFO_REQUEST. Checking against the server in question, it first sends a valid request (empty name, empty instruction, empty language, single prompt for a password): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 00 00 00 28 50 61 73 73 77 6f 72 64 20 66 6f 72 ...(Password for [...] to which I reply with a SSH_MSG_USERAUTH_INFO_RESPONSE. The server then sends a second SSH_MSG_USERAUTH_INFO_REQUEST consisting of 16 bytes of zeros: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ for which, even if you ignore the fact that it fails a data-validity check, I'm not sure how you're supposed to respond, since it's asked for zero responses to its authentication request. Peter. From dtucker at zip.com.au Tue Apr 7 09:12:34 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Tue, 7 Apr 2015 09:12:34 +1000 Subject: [PATCH] Fix spelling of TEST_SSH_SSHD_CONFOPTS and TEST_SSH_SSH_CONFOPTS In-Reply-To: <1428109414-75135-1-git-send-email-bryan@shatow.net> References: <1428109414-75135-1-git-send-email-bryan@shatow.net> Message-ID: Applied, thanks. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From dtucker at zip.com.au Tue Apr 7 10:39:37 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Tue, 7 Apr 2015 10:39:37 +1000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST In-Reply-To: <9A043F3CF02CD34C8E74AC1594475C73AAFDBAC3@uxcn10-tdc05.UoA.auckland.ac.nz> References: <9A043F3CF02CD34C8E74AC1594475C73AAFDBAC3@uxcn10-tdc05.UoA.auckland.ac.nz> Message-ID: On Tue, Apr 7, 2015 at 12:29 AM, Peter Gutmann wrote: > I've had a report from a user that "SSH-2.0-OpenSSH_6.6.1_hpn13v11 > FreeBSD-20140420" is sending an invalid SSH_MSG_USERAUTH_INFO_REQUEST. > That's a vendor-modified version of OpenSSH. Assuming it corresponds to what's in FreeBSD head, there's about a thousand lines of changes. Browsing through the diffs I don't see anything that could obviously cause it, but I am far from sure. Can you reproduce the problem with an unmodified version from openssh.com? Failing that, can you get the server-side debug output from a failing connection (ie /path/to/sshd -ddd)? Thanks. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From pgut001 at cs.auckland.ac.nz Tue Apr 7 13:36:10 2015 From: pgut001 at cs.auckland.ac.nz (Peter Gutmann) Date: Tue, 7 Apr 2015 03:36:10 +0000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST Message-ID: <9A043F3CF02CD34C8E74AC1594475C73AAFDC84B@uxcn10-tdc05.UoA.auckland.ac.nz> Darren Tucker writes: >That's a vendor-modified version of OpenSSH. Assuming it corresponds to >what's in FreeBSD head, there's about a thousand lines of changes. Ugh. >Can you reproduce the problem with an unmodified version from openssh.com? >Failing that, can you get the server-side debug output from a failing >connection (ie /path/to/sshd -ddd)? I've cc'd this to the person who reported it in case he can shed more light on the specifics, in the meantime here's the level 3 debug output that he provided me with (this was previously posted to a public mailing list so I'm assuming it's not sensitive): debug2: load_server_config: filename /etc/ssh/sshd_config debug2: load_server_config: done config len = 188 debug2: parse_server_config: config /etc/ssh/sshd_config len 188 debug3: /etc/ssh/sshd_config:129 setting Subsystem sftp /usr/libexec/sftp-server debug1: HPN Buffer Size: 65536 debug1: sshd version OpenSSH_6.6.1p1_hpn13v11 FreeBSD-20140420, OpenSSL 1.0.1j-freebsd 15 Oct 2014 debug3: Incorrect RSA1 identifier debug1: key_parse_private2: missing begin marker debug1: read PEM private key done: type RSA debug3: Incorrect RSA1 identifier debug3: Could not load "/etc/ssh/ssh_host_rsa_key" as a RSA1 public key debug1: private host key: #0 type 1 RSA debug3: Incorrect RSA1 identifier debug1: key_parse_private2: missing begin marker debug1: read PEM private key done: type DSA debug3: Incorrect RSA1 identifier debug3: Could not load "/etc/ssh/ssh_host_dsa_key" as a RSA1 public key debug1: private host key: #1 type 2 DSA debug3: Incorrect RSA1 identifier debug1: key_parse_private2: missing begin marker debug1: read PEM private key done: type ECDSA debug3: Incorrect RSA1 identifier debug3: Could not load "/etc/ssh/ssh_host_ecdsa_key" as a RSA1 public key debug1: private host key: #2 type 3 ECDSA debug3: Incorrect RSA1 identifier debug3: Incorrect RSA1 identifier debug3: Could not load "/etc/ssh/ssh_host_ed25519_key" as a RSA1 public key debug1: private host key: #3 type 4 ED25519 debug1: rexec_argv[0]='/usr/sbin/sshd' debug1: rexec_argv[1]='-Dddd' debug1: rexec_argv[2]='-p' debug1: rexec_argv[3]='1887' debug2: fd 3 setting O_NONBLOCK debug3: ssh_sock_set_v6only: set socket 3 IPV6_V6ONLY debug1: Bind to port 1887 on ::. debug1: Server TCP RWIN socket size: 65536 debug1: HPN Buffer Size: 65536 Server listening on :: port 1887. debug2: fd 4 setting O_NONBLOCK debug1: Bind to port 1887 on 0.0.0.0. debug1: Server TCP RWIN socket size: 65536 debug1: HPN Buffer Size: 65536 Server listening on 0.0.0.0 port 1887. debug1: fd 5 clearing O_NONBLOCK debug1: Server will not fork when running in debugging mode. debug3: send_rexec_state: entering fd = 8 config len 188 debug3: ssh_msg_send: type 0 debug3: send_rexec_state: done debug1: rexec start in 5 out 5 newsock 5 pipe -1 sock 8 debug1: inetd sockets after dupping: 3, 3 debug1: res_init() Connection from ::1 port 50860 on ::1 port 1887 debug1: HPN Disabled: 0, HPN Buffer Size: 65536 debug1: Client protocol version 2.0; client software version cryptlib debug1: no match: cryptlib debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_6.6.1_hpn13v11 FreeBSD-20140420 debug2: fd 3 setting O_NONBLOCK debug3: ssh_sandbox_init: preparing capsicum sandbox debug2: Network child is on pid 43805 debug3: preauth child monitor started debug3: privsep user:group 22:22 [preauth] debug1: permanently_set_uid: 22/22 [preauth] debug1: list_hostkey_types: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ssh-ed25519 [preauth] debug1: SSH2_MSG_KEXINIT sent [preauth] debug1: SSH2_MSG_KEXINIT received [preauth] debug2: kex_parse_kexinit: curve25519-sha256 at libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1 [preauth] debug2: kex_parse_kexinit: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ssh-ed25519 [preauth] debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm at openssh.com,aes256-gcm at openssh.com,chacha20-poly1305 at openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc at lysator.liu.se [preauth] debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm at openssh.com,aes256-gcm at openssh.com,chacha20-poly1305 at openssh.com,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc at lysator.liu.se [preauth] debug2: kex_parse_kexinit: hmac-md5-etm at openssh.com,hmac-sha1-etm at openssh.com,umac-64-etm at openssh.com,umac-128-etm at openssh.com,hmac-sha2-256-etm at openssh.com,hmac-sha2-512-etm at openssh.com,hmac-ripemd160-etm at openssh.com,hmac-sha1-96-etm at openssh.com,hmac-md5-96-etm at openssh.com,hmac-md5,hmac-sha1,umac-64 at openssh.com,umac-128 at openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160 at openssh.com,hmac-sha1-96,hmac-md5-96 [preauth] debug2: kex_parse_kexinit: hmac-md5-etm at openssh.com,hmac-sha1-etm at openssh.com,umac-64-etm at openssh.com,umac-128-etm at openssh.com,hmac-sha2-256-etm at openssh.com,hmac-sha2-512-etm at openssh.com,hmac-ripemd160-etm at openssh.com,hmac-sha1-96-etm at openssh.com,hmac-md5-96-etm at openssh.com,hmac-md5,hmac-sha1,umac-64 at openssh.com,umac-128 at openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160 at openssh.com,hmac-sha1-96,hmac-md5-96 [preauth] debug2: kex_parse_kexinit: none,zlib at openssh.com [preauth] debug2: kex_parse_kexinit: none,zlib at openssh.com [preauth] debug2: kex_parse_kexinit: [preauth] debug2: kex_parse_kexinit: [preauth] debug2: kex_parse_kexinit: first_kex_follows 0 [preauth] debug2: kex_parse_kexinit: reserved 0 [preauth] debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256 [preauth] debug2: kex_parse_kexinit: ssh-rsa [preauth] debug2: kex_parse_kexinit: 3des-cbc [preauth] debug2: kex_parse_kexinit: 3des-cbc [preauth] debug2: kex_parse_kexinit: hmac-sha2-256 [preauth] debug2: kex_parse_kexinit: hmac-sha2-256 [preauth] debug2: kex_parse_kexinit: none [preauth] debug2: kex_parse_kexinit: none [preauth] debug2: kex_parse_kexinit: [preauth] debug2: kex_parse_kexinit: [preauth] debug2: kex_parse_kexinit: first_kex_follows 0 [preauth] debug2: kex_parse_kexinit: reserved 0 [preauth] debug2: mac_setup: setup hmac-sha2-256 [preauth] debug1: kex: client->server 3des-cbc hmac-sha2-256 none [preauth] debug2: mac_setup: setup hmac-sha2-256 [preauth] debug1: kex: server->client 3des-cbc hmac-sha2-256 none [preauth] debug1: SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received [preauth] debug3: mm_request_send entering: type 0 [preauth] debug3: mm_choose_dh: waiting for MONITOR_ANS_MODULI [preauth] debug3: mm_request_receive_expect entering: type 1 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 0 debug3: mm_answer_moduli: got parameters: 1024 1024 8192 debug3: mm_request_send entering: type 1 debug2: monitor_read: 0 used once, disabling now debug3: mm_choose_dh: remaining 0 [preauth] debug1: SSH2_MSG_KEX_DH_GEX_GROUP sent [preauth] debug2: bits set: 532/1024 [preauth] debug1: expecting SSH2_MSG_KEX_DH_GEX_INIT [preauth] debug2: bits set: 507/1024 [preauth] debug3: mm_key_sign entering [preauth] debug3: mm_request_send entering: type 6 [preauth] debug3: mm_key_sign: waiting for MONITOR_ANS_SIGN [preauth] debug3: mm_request_receive_expect entering: type 7 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 6 debug3: mm_answer_sign debug3: mm_answer_sign: signature 0x8040858c0(271) debug3: mm_request_send entering: type 7 debug2: monitor_read: 6 used once, disabling now debug1: SSH2_MSG_KEX_DH_GEX_REPLY sent [preauth] debug2: kex_derive_keys [preauth] debug2: set_newkeys: mode 1 [preauth] debug1: SSH2_MSG_NEWKEYS sent [preauth] debug1: expecting SSH2_MSG_NEWKEYS [preauth] debug2: set_newkeys: mode 0 [preauth] debug1: SSH2_MSG_NEWKEYS received [preauth] debug1: KEX done [preauth] debug3: Trying to reverse map address ::1. [preauth] debug1: userauth-request for user admin service ssh-connection method password [preauth] debug1: attempt 0 failures 0 [preauth] debug3: mm_getpwnamallow entering [preauth] debug3: mm_request_send entering: type 8 [preauth] debug3: mm_getpwnamallow: waiting for MONITOR_ANS_PWNAM [preauth] debug3: mm_request_receive_expect entering: type 9 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 8 debug3: mm_answer_pwnamallow debug3: Trying to reverse map address ::1. debug2: parse_server_config: config reprocess config len 188 debug3: mm_answer_pwnamallow: sending MONITOR_ANS_PWNAM: 1 debug3: mm_request_send entering: type 9 debug2: monitor_read: 8 used once, disabling now debug2: input_userauth_request: setting up authctxt for admin [preauth] debug3: mm_start_pam entering [preauth] debug3: mm_request_send entering: type 100 [preauth] debug3: mm_inform_authserv entering [preauth] debug3: mm_request_send entering: type 4 [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 100 debug1: PAM: initializing for "admin" debug1: PAM: setting PAM_RHOST to "localhost" debug2: monitor_read: 100 used once, disabling now debug2: Unrecognized authentication method name: password [preauth] debug3: userauth_finish: failure partial=0 next methods="publickey,keyboard-interactive" [preauth] debug1: userauth-request for user admin service ssh-connection method keyboard-interactive [preauth] debug1: attempt 1 failures 1 [preauth] debug2: input_userauth_request: try method keyboard-interactive [preauth] debug1: keyboard-interactive devs [preauth] debug1: auth2_challenge: user=admin devs= [preauth] debug1: kbdint_alloc: devices 'pam' [preauth] debug2: auth2_challenge_start: devices pam [preauth] debug2: kbdint_next_device: devices [preauth] debug1: auth2_challenge_start: trying authentication method 'pam' [preauth] debug3: mm_sshpam_init_ctx [preauth] debug3: mm_request_send entering: type 104 [preauth] debug3: mm_sshpam_init_ctx: waiting for MONITOR_ANS_PAM_INIT_CTX [preauth] debug3: mm_request_receive_expect entering: type 105 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 4 debug3: mm_answer_authserv: service=ssh-connection, style= debug2: monitor_read: 4 used once, disabling now debug3: mm_request_receive entering debug3: monitor_read: checking request 104 debug3: mm_answer_pam_init_ctx debug3: PAM: sshpam_init_ctx entering debug3: mm_request_send entering: type 105 debug3: mm_sshpam_query [preauth] debug3: mm_request_send entering: type 106 [preauth] debug3: mm_sshpam_query: waiting for MONITOR_ANS_PAM_QUERY [preauth] debug3: mm_request_receive_expect entering: type 107 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 106 debug3: mm_answer_pam_query debug3: PAM: sshpam_query entering debug3: ssh_msg_recv entering debug3: PAM: sshpam_thread_conv entering, 1 messages debug3: ssh_msg_send: type 1 debug3: ssh_msg_recv entering debug3: mm_request_send entering: type 107 debug3: mm_sshpam_query: pam_query returned 0 [preauth] Postponed keyboard-interactive for admin from ::1 port 50860 ssh2 [preauth] debug3: mm_sshpam_respond [preauth] debug3: mm_request_send entering: type 108 [preauth] debug3: mm_sshpam_respond: waiting for MONITOR_ANS_PAM_RESPOND [preauth] debug3: mm_request_receive_expect entering: type 109 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 108 debug3: mm_answer_pam_respond debug2: PAM: sshpam_respond entering, 1 responses debug3: ssh_msg_send: type 6 debug3: mm_request_send entering: type 109 debug3: mm_sshpam_respond: pam_respond returned 1 [preauth] debug3: mm_sshpam_query [preauth] debug3: mm_request_send entering: type 106 [preauth] debug3: mm_sshpam_query: waiting for MONITOR_ANS_PAM_QUERY [preauth] debug3: mm_request_receive_expect entering: type 107 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 106 debug3: mm_answer_pam_query debug3: PAM: sshpam_query entering debug3: ssh_msg_recv entering debug1: do_pam_account: called debug3: PAM: do_pam_account pam_acct_mgmt = 0 (success) debug3: ssh_msg_send: type 0 debug3: PAM: import_environments entering debug3: sshpam_password_change_required 0 debug3: PAM: num env strings 0 debug1: PAM: num PAM env strings 0 debug3: mm_request_send entering: type 107 debug3: mm_sshpam_query: pam_query returned 0 [preauth] Postponed keyboard-interactive/pam for admin from ::1 port 50860 ssh2 [preauth] Received disconnect from ::1: 10: [preauth] debug1: do_cleanup [preauth] debug3: PAM: sshpam_thread_cleanup entering [preauth] debug1: monitor_read_log: child log fd closed debug3: mm_request_receive entering debug1: do_cleanup debug1: PAM: cleanup debug3: PAM: sshpam_thread_cleanup entering debug1: Killing privsep child 43805 Peter. From dtucker at zip.com.au Tue Apr 7 14:56:26 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Tue, 7 Apr 2015 14:56:26 +1000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST In-Reply-To: <9A043F3CF02CD34C8E74AC1594475C73AAFDBAC3@uxcn10-tdc05.UoA.auckland.ac.nz> References: <9A043F3CF02CD34C8E74AC1594475C73AAFDBAC3@uxcn10-tdc05.UoA.auckland.ac.nz> Message-ID: OK, I can see similar behaviour on Linux with 6.8p1 with PAM enabled. This is the debug output from a slightly modified openssh client: debug1: Next authentication method: keyboard-interactive debug2: userauth_kbdint debug2: we sent a keyboard-interactive packet, wait for reply debug2: input_userauth_info_req debug1: input_userauth_info_req: name '' instructions '' lang '' debug2: input_userauth_info_req: num_prompts 1 Password: debug2: input_userauth_info_req debug1: input_userauth_info_req: name '' instructions '' lang '' debug2: input_userauth_info_req: num_prompts 0 debug1: Enabling compression at level 6. On Tue, Apr 7, 2015 at 12:29 AM, Peter Gutmann wrote: > > to which I reply with a SSH_MSG_USERAUTH_INFO_RESPONSE. The server then > sends > a second SSH_MSG_USERAUTH_INFO_REQUEST consisting of 16 bytes of zeros: > > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ > > for which, even if you ignore the fact that it fails a data-validity check, > Assuming that's the whole packet, I think that's a zero-prompt USERAUTH_INFO_REQUEST packet containing empty name, instructions and language strings. What do you mean by "fails a data-validity check"? If it was just the prompt part of the packet, what's in the name and instruction fields? I'm not sure how you're supposed to respond, since it's asked for zero > responses to its authentication request. > Zero prompts is specifically allowed by RFC4256 section 3.2: " The num-prompts field may be `0', in which case there will be no prompt/echo fields in the message, but the client SHOULD still display the name and instruction fields (as described below)." In my case, those strings are empty, so sshd probably shouldn't generate them (I'll dig into why they get generated) but it seems like a valid (if pointless) protocol message to me. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From pgut001 at cs.auckland.ac.nz Tue Apr 7 15:08:16 2015 From: pgut001 at cs.auckland.ac.nz (Peter Gutmann) Date: Tue, 7 Apr 2015 05:08:16 +0000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST Message-ID: <9A043F3CF02CD34C8E74AC1594475C73AAFDC933@uxcn10-tdc05.UoA.auckland.ac.nz> Darren Tucker writes: >Assuming that's the whole packet, I think that's a zero-prompt >USERAUTH_INFO_REQUEST packet containing empty name, instructions and language >strings. What do you mean by "fails a data-validity check"? My code checks for sane values in the fields in the packet, so it rejects it as malformed before it gets to the interesting philosophical issue of how to send a response to a request for zero responses. >If it was just the prompt part of the packet, what's in the name and >instruction fields? Nothing. All fields are empty, so if you take this (RFC 4256): byte SSH_MSG_USERAUTH_INFO_REQUEST [0] string name (ISO-10646 UTF-8) [0] string instruction (ISO-10646 UTF-8) [0] string language tag (as defined in [RFC-3066]) [0] int num-prompts string prompt[1] (ISO-10646 UTF-8) boolean echo[1] ... string prompt[num-prompts] (ISO-10646 UTF-8) boolean echo[num-prompts] and set all fields to empty, you get 16 bytes of zeros (marked up above). >Zero prompts is specifically allowed by RFC4256 section 3.2: > >" The num-prompts field may be `0', in which case there will be no > prompt/echo fields in the message, but the client SHOULD still > display the name and instruction fields (as described below)." Sure, but since they're also empty there's nothing to display. So it's really a case of "what do you do in response to a request for zero responses?". I'm not sure if promulgating koans was a goal of OpenSSH. Peter. From dtucker at zip.com.au Tue Apr 7 15:36:28 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Tue, 7 Apr 2015 15:36:28 +1000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST In-Reply-To: <9A043F3CF02CD34C8E74AC1594475C73AAFDC933@uxcn10-tdc05.UoA.auckland.ac.nz> References: <9A043F3CF02CD34C8E74AC1594475C73AAFDC933@uxcn10-tdc05.UoA.auckland.ac.nz> Message-ID: On Tue, Apr 7, 2015 at 3:08 PM, Peter Gutmann wrote: > Darren Tucker writes: > [...] > My code checks for sane values in the fields in the packet, so it rejects > it > as malformed before it gets to the interesting philosophical issue of how > to > send a response to a request for zero responses. IMO it's not malformed, see below. >If it was just the prompt part of the packet, what's in the name and > >instruction fields? > > Nothing. All fields are empty, That's explicitly allowed by RFC4256. In addition to allowing zero prompts, section 3.2 also says: "The language tag is deprecated and SHOULD be the empty string." and "The name and instruction fields MAY be empty strings; the client MUST be prepared to handle this correctly. The prompt field(s) MUST NOT be empty strings." > >Zero prompts is specifically allowed by RFC4256 section 3.2: > [...] > Sure, but since they're also empty there's nothing to display. So it's really > a case of "what do you do in response to a request for zero responses?". Do what it says in RFC4256 section 3.4? "In the case that the server sends a `0' num-prompts field in the request message, the client MUST send a response message with a `0' num-responses field to complete the exchange." I'm not sure if promulgating koans was a goal of OpenSSH. I'd like to think one of the goals was implementing the RFCs :-) -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From shurd at sasktel.net Tue Apr 7 15:47:04 2015 From: shurd at sasktel.net (Stephen Hurd) Date: Mon, 06 Apr 2015 22:47:04 -0700 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST In-Reply-To: <9A043F3CF02CD34C8E74AC1594475C73AAFDC84B@uxcn10-tdc05.UoA.auckland.ac.nz> References: <9A043F3CF02CD34C8E74AC1594475C73AAFDC84B@uxcn10-tdc05.UoA.auckland.ac.nz> Message-ID: <55236F58.3020402@sasktel.net> Peter Gutmann wrote: > Darren Tucker writes: > >> That's a vendor-modified version of OpenSSH. Assuming it corresponds to >> what's in FreeBSD head, there's about a thousand lines of changes. > Ugh. > >> Can you reproduce the problem with an unmodified version from openssh.com? >> Failing that, can you get the server-side debug output from a failing >> connection (ie /path/to/sshd -ddd)? > I've cc'd this to the person who reported it in case he can shed more light on > the specifics, in the meantime here's the level 3 debug output that he > provided me with (this was previously posted to a public mailing list so I'm > assuming it's not sensitive): The problem was originally reported via IRC against "a couple different Linux distros", and I found I could reproduce with my FreeBSD 11 box so I added a local patch to work around it, sent it to the reporter who confirmed that it solved his issue. I can try to find out the specific distros, though I suspect they have vendor patches as well. His system also had all the CBC ciphers disabled by default, including the mandatory 3des-cbc and recommended aes128-cbc, so I suspect a reaction to some padding oracle attack (I don't really keep up) was involved on his systems. It seems that Cryptlib only does CBC, so I had to walk him through re-enabling those. From dtucker at zip.com.au Tue Apr 7 17:11:02 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Tue, 7 Apr 2015 17:11:02 +1000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST In-Reply-To: <55236F58.3020402@sasktel.net> References: <9A043F3CF02CD34C8E74AC1594475C73AAFDC84B@uxcn10-tdc05.UoA.auckland.ac.nz> <55236F58.3020402@sasktel.net> Message-ID: Hi Stephen. I accidentally dropped you off the thread by replying to an earlier post. The TL;DR is that I think OpenSSH's behaviour is RFC-compliant although not optimal. You can read the rest of the thread here: http://lists.mindrot.org/pipermail/openssh-unix-dev/2015-April/033789.html On Tue, Apr 7, 2015 at 3:47 PM, Stephen Hurd wrote: > > The problem was originally reported via IRC against "a couple different > Linux distros", and I found I could reproduce with my FreeBSD 11 box so > I added a local patch to work around it, sent it to the reporter who > confirmed that it solved his issue. I can try to find out the specific > distros, though I suspect they have vendor patches as well. > I suspect the behaviour will be present in any system with UsePAM=yes and KbdInteractiveAuthentication=yes (or ChallengeResponseAuthentication=yes, from which KbdInteractiveAuthentication gets its default value). I also suspect you can work around it by setting KbdInteractiveAuthentication=no and PasswordAuthentication=yes, assuming your PAM modules are simple enough that this works. > His system also had all the CBC ciphers disabled by default, including > the mandatory 3des-cbc and recommended aes128-cbc, so I suspect a > reaction to some padding oracle attack (I don't really keep up) was > involved on his systems. It seems that Cryptlib only does CBC, so I had > to walk him through re-enabling those. FWIW I don't think the ciphers have any impact on this behaviour. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From bryan at shatow.net Thu Apr 9 11:44:42 2015 From: bryan at shatow.net (Bryan Drewery) Date: Wed, 08 Apr 2015 20:44:42 -0500 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> Message-ID: <5525D98A.2040302@shatow.net> On 3/1/2015 2:54 AM, Damien Miller wrote: > On Sat, 28 Feb 2015, The Doctor wrote: > >> When will it be added in? > > It's already committed. It's in git now and will be in the next snapshot. > >>> Is this an error that breaks the connection or a warning? >> >> Break the connection; in this case Tera Type. > > It seems to be crashing on a valid, but unexpected extension message, do > you know what identification tera type sends in its ssh banner? I recently upgraded to 6.8 and ran into this. It breaks the client. >From the server: debug1: Client protocol version 2.0; client software version TTSSH/2.72 Win32 [...] debug1: userauth-request for user bryan service ssh-connection method none [preauth] debug1: attempt 0 failures 0 [preauth] debug3: mm_getpwnamallow entering [preauth] debug3: mm_request_send entering: type 8 [preauth] debug3: mm_getpwnamallow: waiting for MONITOR_ANS_PWNAM [preauth] debug3: mm_request_receive_expect entering: type 9 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 8 debug3: mm_answer_pwnamallow debug2: parse_server_config: config reprocess config len 895 debug3: mm_answer_pwnamallow: sending MONITOR_ANS_PWNAM: 1 debug3: mm_request_send entering: type 9 debug2: monitor_read: 8 used once, disabling now debug2: input_userauth_request: setting up authctxt for bryan [preauth] debug3: mm_start_pam entering [preauth] debug3: mm_request_send entering: type 100 [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 100 debug1: PAM: initializing for "bryan" debug1: PAM: setting PAM_RHOST to "10.10.1.139" debug2: monitor_read: 100 used once, disabling now debug3: mm_inform_authserv entering [preauth] debug3: mm_request_send entering: type 4 [preauth] debug2: input_userauth_request: try method none [preauth] debug3: userauth_finish: failure partial=0 next methods="publickey" [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 4 debug3: mm_answer_authserv: service=ssh-connection, style= debug2: monitor_read: 4 used once, disabling now debug1: userauth-request for user bryan service ssh-connection method publickey [preauth] debug1: attempt 1 failures 0 [preauth] debug2: input_userauth_request: try method publickey [preauth] debug1: test whether pkalg/pkblob are acceptable [preauth] debug3: mm_key_allowed entering [preauth] debug3: mm_request_send entering: type 22 [preauth] debug3: mm_key_allowed: waiting for MONITOR_ANS_KEYALLOWED [preauth] debug3: mm_request_receive_expect entering: type 23 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 22 debug3: mm_answer_keyallowed entering debug3: mm_answer_keyallowed: key_from_blob: 0x802417700 debug1: trying public key file /home/bryan/.ssh/authorized_keys debug1: fd 4 clearing O_NONBLOCK debug1: matching key found: file /home/bryan/.ssh/authorized_keys, line 4 RSA SHA256:dQqAcgPQW0Ed1okUiBpnvSQZESVxPhYLIojRchyLlDI debug3: mm_answer_keyallowed: key 0x802417700 is allowed debug3: mm_request_send entering: type 23 debug2: userauth_pubkey: authenticated 0 pkalg ssh-rsa [preauth] Postponed publickey for bryan from 10.10.1.139 port 56694 ssh2 [preauth] debug1: userauth-request for user bryan service ssh-connection method publickey [preauth] debug1: attempt 2 failures 0 [preauth] debug2: input_userauth_request: try method publickey [preauth] debug3: mm_key_allowed entering [preauth] debug3: mm_request_send entering: type 22 [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 22 debug3: mm_answer_keyallowed entering debug3: mm_answer_keyallowed: key_from_blob: 0x802417700 debug1: trying public key file /home/bryan/.ssh/authorized_keys debug1: fd 4 clearing O_NONBLOCK debug1: matching key found: file /home/bryan/.ssh/authorized_keys, line 4 RSA SHA256:dQqAcgPQW0Ed1okUiBpnvSQZESVxPhYLIojRchyLlDI debug3: mm_answer_keyallowed: key 0x802417700 is allowed debug3: mm_request_send entering: type 23 debug3: mm_key_allowed: waiting for MONITOR_ANS_KEYALLOWED [preauth] debug3: mm_request_receive_expect entering: type 23 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_key_verify entering [preauth] debug3: mm_request_send entering: type 24 [preauth] debug3: mm_request_receive entering debug3: monitor_read: checking request 24 debug3: mm_answer_keyverify: key 0x802417700 signature verified debug3: mm_request_send entering: type 25 debug3: mm_request_receive_expect entering: type 102 debug3: mm_request_receive entering debug1: do_pam_account: called debug3: PAM: do_pam_account pam_acct_mgmt = 0 (success) debug3: mm_request_send entering: type 103 Accepted publickey for bryan from 10.10.1.139 port 56694 ssh2: RSA SHA256:dQqAcgPQW0Ed1okUiBpnvSQZESVxPhYLIojRchyLlDI debug1: monitor_child_preauth: bryan has been authenticated by privileged process debug3: mm_get_keystate: Waiting for new keys debug3: mm_request_receive_expect entering: type 26 debug3: mm_request_receive entering debug3: mm_get_keystate: GOT new keys debug3: mm_key_verify: waiting for MONITOR_ANS_KEYVERIFY [preauth] debug3: mm_request_receive_expect entering: type 25 [preauth] debug3: mm_request_receive entering [preauth] debug2: userauth_pubkey: authenticated 1 pkalg ssh-rsa [preauth] debug3: mm_do_pam_account entering [preauth] debug3: mm_request_send entering: type 102 [preauth] debug3: mm_request_receive_expect entering: type 103 [preauth] debug3: mm_request_receive entering [preauth] debug3: mm_do_pam_account returning 1 [preauth] debug3: mm_request_send entering: type 26 [preauth] debug3: mm_send_keystate: Finished sending state [preauth] debug1: monitor_read_log: child log fd closed debug3: mm_share_sync: Share sync debug3: mm_share_sync: Share sync end debug3: ssh_sandbox_parent_finish: finished debug3: BSM audit: typ 0 rc 0 "successful login bryan" debug3: BSM audit: writing audit new record debug1: PAM: establishing credentials debug3: PAM: opening session User child is on pid 6898 debug1: PAM: establishing credentials debug3: monitor_apply_keystate: packet_set_state debug2: set_newkeys: mode 0 debug2: set_newkeys: mode 1 debug1: ssh_packet_set_postauth: called debug3: ssh_packet_set_state: done debug3: notify_hostkeys: key 0: ssh-rsa SHA256:49N81LHTBvQeb52F/b7fICshFKcCEtLDJHOCpvFmCdk debug3: notify_hostkeys: key 1: ssh-dss SHA256:VGPUUhN/shyBqAH6N/vG3X13M3lk7cW85y5t1Wr6mOU debug3: notify_hostkeys: key 2: ecdsa-sha2-nistp256 SHA256:UuD5mFrooZ5dYY0aCBlZfZuCBdJdcN3o4l/pHIHqHI0 debug3: notify_hostkeys: key 3: ssh-ed25519 SHA256:bIqXphhx6R/cUgrjt2LQ64ubon8yQ6tECES8sym8qVU debug3: notify_hostkeys: sent 4 hostkeys debug1: Entering interactive session for SSH2. debug2: fd 9 setting O_NONBLOCK debug2: fd 10 setting O_NONBLOCK debug1: server_init_dispatch_20 debug1: server_input_channel_open: ctype session rchan 0 win 131072 max 32768 debug1: input_session_request debug1: channel 0: new [server-session] debug2: session_new: allocate (allocated 0 max 10) debug3: session_unused: session id 0 unused debug1: session_new: session 0 debug1: session_open: channel 0 debug1: session_open: session 0: link with channel 0 debug1: server_input_channel_open: confirm session Received disconnect from 10.10.1.139: 11: Unexpected SSH2 message(80) on current stage(6) Disconnected from 10.10.1.139 debug1: do_cleanup debug3: PAM: sshpam_thread_cleanup entering debug3: mm_request_receive entering mm_request_receive: socket closed debug1: do_cleanup debug1: PAM: cleanup debug1: PAM: closing session debug1: PAM: deleting credentials debug3: PAM: sshpam_thread_cleanup entering debug1: audit_event: unhandled event 12 From bryan at shatow.net Thu Apr 9 12:28:53 2015 From: bryan at shatow.net (Bryan Drewery) Date: Wed, 08 Apr 2015 21:28:53 -0500 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <5525D98A.2040302@shatow.net> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> Message-ID: <5525E3E5.2090604@shatow.net> On 4/8/2015 8:44 PM, Bryan Drewery wrote: > On 3/1/2015 2:54 AM, Damien Miller wrote: >> On Sat, 28 Feb 2015, The Doctor wrote: >> >>> When will it be added in? >> >> It's already committed. It's in git now and will be in the next snapshot. >> >>>> Is this an error that breaks the connection or a warning? >>> >>> Break the connection; in this case Tera Type. >> >> It seems to be crashing on a valid, but unexpected extension message, do >> you know what identification tera type sends in its ssh banner? > > I recently upgraded to 6.8 and ran into this. It breaks the client. > > From the server: > > debug1: Client protocol version 2.0; client software version TTSSH/2.72 > Win32 > [...] > Received disconnect from 10.10.1.139: 11: Unexpected SSH2 message(80) on > current stage(6) It seems that Tera Term has fixed this but not yet released a build with it. http://en.sourceforge.jp/ticket/browse.php?group_id=1412&tid=35010 http://en.sourceforge.jp/projects/ttssh2/scm/svn/commits/5829 This patch fixes it in OpenSSH for me: https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff Regards, Bryan Drewery From dtucker at zip.com.au Thu Apr 9 12:39:58 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Thu, 9 Apr 2015 12:39:58 +1000 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <5525D98A.2040302@shatow.net> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> Message-ID: On Thu, Apr 9, 2015 at 11:44 AM, Bryan Drewery wrote: > > Received disconnect from 10.10.1.139: 11: Unexpected SSH2 message(80) on > current stage(6) > Message type 80 is SSH_MSG_GLOBAL_REQUEST, and RFC4254 section 4 says "Note that both the client and server MAY send global requests at any time, and the receiver MUST respond appropriately." Any idea what the message is? It'd be nice if the client showed the whole packet, but failing that you could build a server with "./configure --with-cflags=-DPACKET_DEBUG" then pick the packet out of the server-side debug logs. The only global message I can think of is the protocol keepalives, in which case you could try setting "ClientAliveInterval 0" in sshd_config to see if that helps. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From dtucker at zip.com.au Thu Apr 9 12:56:01 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Thu, 9 Apr 2015 12:56:01 +1000 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <5525E3E5.2090604@shatow.net> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> Message-ID: On Thu, Apr 9, 2015 at 12:28 PM, Bryan Drewery wrote: > > It seems that Tera Term has fixed this but not yet released a build with > it. > > http://en.sourceforge.jp/ticket/browse.php?group_id=1412&tid=35010 > http://en.sourceforge.jp/projects/ttssh2/scm/svn/commits/5829 Reading that change it looks like Tera Term before that change would also crash when ClientAliveInterval is enabled on the server? This patch fixes it in OpenSSH for me: > https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff > -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From bryan at shatow.net Thu Apr 9 13:07:57 2015 From: bryan at shatow.net (Bryan Drewery) Date: Wed, 08 Apr 2015 22:07:57 -0500 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> Message-ID: <5525ED0D.5080902@shatow.net> On 4/8/2015 9:56 PM, Darren Tucker wrote: > On Thu, Apr 9, 2015 at 12:28 PM, Bryan Drewery > wrote: > > It seems that Tera Term has fixed this but not yet released a build > with it. > > http://en.sourceforge.jp/ticket/browse.php?group_id=1412&tid=35010 > http://en.sourceforge.jp/projects/ttssh2/scm/svn/commits/5829 > > > Reading that change it looks like Tera Term before that change would > also crash when ClientAliveInterval is enabled on the server? I see what you're saying but I am unable to create any error by enabling ClientAliveInterval. I set it to 1 and get no errors on the client. sshd debugging: debug2: channel 0: request keepalive at openssh.com confirm 1 debug2: tcpwinsz: 65700 for connection: 3 debug2: tcpwinsz: 65700 for connection: 3 debug1: Got 100/16 for keepalive debug2: tcpwinsz: 65700 for connection: 3 debug2: channel 0: request keepalive at openssh.com confirm 1 debug2: tcpwinsz: 65700 for connection: 3 debug2: tcpwinsz: 65700 for connection: 3 debug1: Got 100/17 for keepalive debug2: tcpwinsz: 65700 for connection: 3 debug2: channel 0: request keepalive at openssh.com confirm 1 debug2: tcpwinsz: 65700 for connection: 3 debug2: tcpwinsz: 65700 for connection: 3 debug1: Got 100/18 for keepalive debug2: tcpwinsz: 65700 for connection: 3 debug2: channel 0: request keepalive at openssh.com confirm 1 debug2: tcpwinsz: 65700 for connection: 3 debug2: tcpwinsz: 65700 for connection: 3 debug1: Got 100/19 for keepalive debug2: tcpwinsz: 65700 for connection: 3 I think it just ignores the SSH2_MSG_GLOBAL_REQUEST packets once it is fully connected. Seeing them before the full connection is unexpected to it as the error seems to imply (Unexpected... on current stage). I don't see anything in ssh.c handling keepalive messages. > > This patch fixes it in OpenSSH for me: > https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff > > From dtucker at zip.com.au Thu Apr 9 14:02:47 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Thu, 9 Apr 2015 14:02:47 +1000 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <5525ED0D.5080902@shatow.net> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> <5525ED0D.5080902@shatow.net> Message-ID: On Thu, Apr 9, 2015 at 1:07 PM, Bryan Drewery wrote: > On 4/8/2015 9:56 PM, Darren Tucker wrote:ading that change it looks like > Tera Term before that change would > > also crash when ClientAliveInterval is enabled on the server? > > I see what you're saying but I am unable to create any error by enabling > ClientAliveInterval. I set it to 1 and get no errors on the client. sshd > debugging: > > debug2: channel 0: request keepalive at openssh.com confirm 1 > Those are channel requests not global requests. sshd does this in serverloop.c: if ((channel_id = channel_find_open()) == -1) { packet_start(SSH2_MSG_GLOBAL_REQUEST); packet_put_cstring("keepalive at openssh.com"); packet_put_char(1); /* boolean: want reply */ } else { channel_request_start(channel_id, "keepalive at openssh.com", 1); } and Tera Term seems to handle the channel requests just fine. Presumably if you could get a connection with no active channels (ie the equivalent of ssh -N) then perhaps it'd have a problem, or perhaps that's not even possible with that client. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From djm at mindrot.org Thu Apr 9 14:22:51 2015 From: djm at mindrot.org (Damien Miller) Date: Thu, 9 Apr 2015 14:22:51 +1000 (AEST) Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> Message-ID: On Thu, 9 Apr 2015, Darren Tucker wrote: > Any idea what the message is? It'd be nice if the client showed the whole > packet, but failing that you could build a server with "./configure > --with-cflags=-DPACKET_DEBUG" then pick the packet out of the server-side > debug logs. It's almost certainly the recently-added hostkeys at openssh.com hostkey rotation extension. -d From ras at anzio.com Thu Apr 9 15:54:21 2015 From: ras at anzio.com (Bob Rasmussen) Date: Wed, 8 Apr 2015 22:54:21 -0700 (PDT) Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> Message-ID: I agree it is hostkey rotation, as described in the change notes for version 6.8 of SSH. I ran into the same thing with Anzio, our own terminal emulator (SSH client). We also have a fix available, but not packaged into an installer. On Thu, 9 Apr 2015, Damien Miller wrote: > On Thu, 9 Apr 2015, Darren Tucker wrote: > >> Any idea what the message is? It'd be nice if the client showed the whole >> packet, but failing that you could build a server with "./configure >> --with-cflags=-DPACKET_DEBUG" then pick the packet out of the server-side >> debug logs. > > It's almost certainly the recently-added hostkeys at openssh.com hostkey > rotation extension. > > -d > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > Regards, ....Bob Rasmussen, President, Rasmussen Software, Inc. personal e-mail: ras at anzio.com company e-mail: rsi at anzio.com voice: (US) 503-624-0360 (9:00-6:00 Pacific Time) fax: (US) 503-624-0760 web: http://www.anzio.com street address: Rasmussen Software, Inc. 10240 SW Nimbus, Suite L9 Portland, OR 97223 USA From michael at grendel.net Thu Apr 9 19:17:58 2015 From: michael at grendel.net (Michael Handler) Date: Thu, 9 Apr 2015 02:17:58 -0700 Subject: [PATCH] ssh-keyscan also emits the port used for key retrieval, if non-default Message-ID: If you invoke ssh-keyscan with a non-default port via -p, it won't log that port data in the hostname portion of the key data it prints out. -------------- next part -------------- diff --git a/ssh-keyscan.c b/ssh-keyscan.c index c5fb3b5..d4fc7d7 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -305,7 +305,11 @@ keyprint(con *c, struct sshkey *key) if (hash_hosts && (host = host_hash(host, NULL, 0)) == NULL) fatal("host_hash failed"); - fprintf(stdout, "%s ", host); + if (ssh_port != SSH_DEFAULT_PORT) { + fprintf(stdout, "%s:%d ", host, ssh_port); + } else { + fprintf(stdout, "%s ", host); + } sshkey_write(key, stdout); fputs("\n", stdout); } @@ -488,7 +492,7 @@ congreet(int s) confree(s); return; } - fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); + fprintf(stderr, "# %s:%d %s\n", c->c_name, ssh_port, chop(buf)); n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); From bryan at shatow.net Fri Apr 10 00:57:50 2015 From: bryan at shatow.net (Bryan Drewery) Date: Thu, 09 Apr 2015 09:57:50 -0500 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> Message-ID: <5526936E.1030501@shatow.net> On 4/8/2015 11:22 PM, Damien Miller wrote: > On Thu, 9 Apr 2015, Darren Tucker wrote: > >> Any idea what the message is? It'd be nice if the client showed the whole >> packet, but failing that you could build a server with "./configure >> --with-cflags=-DPACKET_DEBUG" then pick the packet out of the server-side >> debug logs. > > It's almost certainly the recently-added hostkeys at openssh.com hostkey > rotation extension. > Yup. My patch disables for TTSSH*. Given the client has a fix they need to release, I don't think it is critical to add support into OpenSSH for working around it. Unless more clients show the issue then I think it, or changes to the hostkey support, should be considered. Either way I provided a patch if anyone else wants to workaround it for now. Regards, Bryan Drewery From sue at iwmt.org Fri Apr 10 05:45:56 2015 From: sue at iwmt.org (IWAMOTO Kouichi) Date: Fri, 10 Apr 2015 04:45:56 +0900 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <5525E3E5.2090604@shatow.net> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> Message-ID: <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> On Wed, 08 Apr 2015 21:28:53 -0500 Bryan Drewery wrote: > This patch fixes it in OpenSSH for me: > > https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff In this change, hostkey rotation is not used if Tera Term supports it in future. Could you change a modification to the compat.c as follows? --- compat.c.orig 2015-03-17 14:49:20.000000000 +0900 +++ compat.c 2015-04-09 18:35:16.000000000 +0900 @@ -167,6 +167,17 @@ SSH_BUG_SCANNER }, { "Probe-*", SSH_BUG_PROBE }, + { "TTSSH/1.5.*," + "TeraTerm SSH*," + "TTSSH/2.1*," + "TTSSH/2.2*," + "TTSSH/2.3*," + "TTSSH/2.4*," + "TTSSH/2.5*," + "TTSSH/2.6*," + "TTSSH/2.70*," + "TTSSH/2.71*," + "TTSSH/2.72*", SSH_BUG_HOSTKEYS }, { NULL, 0 } }; -- IWAMOTO Kouichi (sue at iwmt.org/sue at postfix.jp/sue at TeraTerm.Net) From bryan at shatow.net Fri Apr 10 06:18:23 2015 From: bryan at shatow.net (Bryan Drewery) Date: Thu, 09 Apr 2015 15:18:23 -0500 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> Message-ID: <5526DE8F.9070202@shatow.net> On 4/9/2015 2:45 PM, IWAMOTO Kouichi wrote: > On Wed, 08 Apr 2015 21:28:53 -0500 > Bryan Drewery wrote: > >> This patch fixes it in OpenSSH for me: >> >> https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff > > In this change, hostkey rotation is not used if Tera Term supports it in future. > Could you change a modification to the compat.c as follows? > Very good point. A poor oversight on my part. I've updated the patch. Thanks, Bryan Drewery From djm at mindrot.org Fri Apr 10 10:09:01 2015 From: djm at mindrot.org (Damien Miller) Date: Fri, 10 Apr 2015 10:09:01 +1000 (AEST) Subject: [PATCH] ssh-keyscan also emits the port used for key retrieval, if non-default In-Reply-To: References: Message-ID: On Thu, 9 Apr 2015, Michael Handler wrote: > If you invoke ssh-keyscan with a non-default port via -p, it won't log > that port data in the hostname portion of the key data it prints out. Thanks, I committed a slightly different patch using the existing put_host_port() function: diff --git a/ssh-keyscan.c b/ssh-keyscan.c index c5fb3b5..7955d72 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -299,15 +299,18 @@ static void keyprint(con *c, struct sshkey *key) { char *host = c->c_output_name ? c->c_output_name : c->c_name; + char *hostport = NULL; if (!key) return; if (hash_hosts && (host = host_hash(host, NULL, 0)) == NULL) fatal("host_hash failed"); - fprintf(stdout, "%s ", host); + hostport = put_host_port(host, ssh_port); + fprintf(stdout, "%s ", hostport); sshkey_write(key, stdout); fputs("\n", stdout); + free(hostport); } static int @@ -488,7 +491,7 @@ congreet(int s) confree(s); return; } - fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); + fprintf(stderr, "# %s:%d %s\n", c->c_name, ssh_port, chop(buf)); n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); From djm at mindrot.org Fri Apr 10 10:16:55 2015 From: djm at mindrot.org (Damien Miller) Date: Fri, 10 Apr 2015 10:16:55 +1000 (AEST) Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> Message-ID: On Fri, 10 Apr 2015, IWAMOTO Kouichi wrote: > On Wed, 08 Apr 2015 21:28:53 -0500 > Bryan Drewery wrote: > > > This patch fixes it in OpenSSH for me: > > > > https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff > > In this change, hostkey rotation is not used if Tera Term supports it in future. > Could you change a modification to the compat.c as follows? so, something like: Index: compat.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/compat.c,v retrieving revision 1.88 diff -u -p -r1.88 compat.c --- compat.c 7 Apr 2015 23:00:42 -0000 1.88 +++ compat.c 10 Apr 2015 00:15:27 -0000 @@ -165,6 +165,17 @@ compat_datafellows(const char *version) SSH_BUG_SCANNER }, { "Probe-*", SSH_BUG_PROBE }, + { "TTSSH/1.5.*," + "TeraTerm SSH*," + "TTSSH/2.1*," + "TTSSH/2.2*," + "TTSSH/2.3*," + "TTSSH/2.4*," + "TTSSH/2.5*," + "TTSSH/2.6*," + "TTSSH/2.70*," + "TTSSH/2.71*," + "TTSSH/2.72*", SSH_BUG_HOSTKEYS }, { NULL, 0 } }; Index: compat.h =================================================================== RCS file: /cvs/src/usr.bin/ssh/compat.h,v retrieving revision 1.46 diff -u -p -r1.46 compat.h --- compat.h 19 Jan 2015 20:20:20 -0000 1.46 +++ compat.h 10 Apr 2015 00:15:27 -0000 @@ -60,6 +60,7 @@ #define SSH_NEW_OPENSSH 0x04000000 #define SSH_BUG_DYNAMIC_RPORT 0x08000000 #define SSH_BUG_CURVE25519PAD 0x10000000 +#define SSH_BUG_HOSTKEYS 0x20000000 void enable_compat13(void); void enable_compat20(void); Index: sshd.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/sshd.c,v retrieving revision 1.445 diff -u -p -r1.445 sshd.c --- sshd.c 31 Mar 2015 22:55:24 -0000 1.445 +++ sshd.c 10 Apr 2015 00:15:27 -0000 @@ -891,6 +891,8 @@ notify_hostkeys(struct ssh *ssh) int i, nkeys, r; char *fp; + if ((compat & SSH_BUG_HOSTKEYS) != 0) + return; if ((buf = sshbuf_new()) == NULL) fatal("%s: sshbuf_new", __func__); for (i = nkeys = 0; i < options.num_host_key_files; i++) { From dtucker at zip.com.au Fri Apr 10 10:35:04 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Fri, 10 Apr 2015 10:35:04 +1000 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> Message-ID: <20150410003504.GA28738@gate.dtucker.net> On Fri, Apr 10, 2015 at 04:45:56AM +0900, IWAMOTO Kouichi wrote: > On Wed, 08 Apr 2015 21:28:53 -0500 > Bryan Drewery wrote: > > > This patch fixes it in OpenSSH for me: > > > > https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff > > In this change, hostkey rotation is not used if Tera Term supports it in future. > Could you change a modification to the compat.c as follows? > > --- compat.c.orig 2015-03-17 14:49:20.000000000 +0900 > +++ compat.c 2015-04-09 18:35:16.000000000 +0900 > @@ -167,6 +167,17 @@ > SSH_BUG_SCANNER }, > { "Probe-*", > SSH_BUG_PROBE }, > + { "TTSSH/1.5.*," > + "TeraTerm SSH*," Should this match all of TTSSH/1.* rather than just 1.5? Also for tidiness I'd rather keep the TTSSH entries grouped together and have the compat check with the rest of the hostkey notification code rather than inline with the main code. Does this still work? Also, we're nearly out of bug bits, we might have to order some more :-) Index: compat.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/compat.c,v retrieving revision 1.88 diff -u -p -r1.88 compat.c --- compat.c 7 Apr 2015 23:00:42 -0000 1.88 +++ compat.c 10 Apr 2015 00:21:23 -0000 @@ -165,6 +165,17 @@ compat_datafellows(const char *version) SSH_BUG_SCANNER }, { "Probe-*", SSH_BUG_PROBE }, + { "TeraTerm SSH*," + "TTSSH/1.5.*," + "TTSSH/2.1*," + "TTSSH/2.2*," + "TTSSH/2.3*," + "TTSSH/2.4*," + "TTSSH/2.5*," + "TTSSH/2.6*," + "TTSSH/2.70*," + "TTSSH/2.71*," + "TTSSH/2.72*", SSH_BUG_HOSTKEYS }, { NULL, 0 } }; Index: compat.h =================================================================== RCS file: /cvs/src/usr.bin/ssh/compat.h,v retrieving revision 1.46 diff -u -p -r1.46 compat.h --- compat.h 19 Jan 2015 20:20:20 -0000 1.46 +++ compat.h 10 Apr 2015 00:21:23 -0000 @@ -60,6 +60,7 @@ #define SSH_NEW_OPENSSH 0x04000000 #define SSH_BUG_DYNAMIC_RPORT 0x08000000 #define SSH_BUG_CURVE25519PAD 0x10000000 +#define SSH_BUG_HOSTKEYS 0x20000000 void enable_compat13(void); void enable_compat20(void); Index: sshd.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/sshd.c,v retrieving revision 1.445 diff -u -p -r1.445 sshd.c --- sshd.c 31 Mar 2015 22:55:24 -0000 1.445 +++ sshd.c 10 Apr 2015 00:21:23 -0000 @@ -891,6 +891,10 @@ notify_hostkeys(struct ssh *ssh) int i, nkeys, r; char *fp; + /* Some clients cannot cope with the hostkeys message, skip those. */ + if (datafellows & SSH_BUG_HOSTKEYS) + return; + if ((buf = sshbuf_new()) == NULL) fatal("%s: sshbuf_new", __func__); for (i = nkeys = 0; i < options.num_host_key_files; i++) { -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From dtucker at zip.com.au Fri Apr 10 10:57:31 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Fri, 10 Apr 2015 10:57:31 +1000 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> Message-ID: <20150410005731.GA5335@gate.dtucker.net> On Fri, Apr 10, 2015 at 10:16:55AM +1000, Damien Miller wrote: [...] > so, something like: Heh, mails crossed in transit. Yep, pretty much like that. > + { "TTSSH/1.5.*," > + "TeraTerm SSH*," I'd put those in the opposite order to group the "TTSSH" entries all together, but ok dtucker either way. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From djm at mindrot.org Fri Apr 10 12:06:14 2015 From: djm at mindrot.org (Damien Miller) Date: Fri, 10 Apr 2015 12:06:14 +1000 (AEST) Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: <20150410003504.GA28738@gate.dtucker.net> References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> <20150410003504.GA28738@gate.dtucker.net> Message-ID: ok djm On Fri, 10 Apr 2015, Darren Tucker wrote: > On Fri, Apr 10, 2015 at 04:45:56AM +0900, IWAMOTO Kouichi wrote: > > On Wed, 08 Apr 2015 21:28:53 -0500 > > Bryan Drewery wrote: > > > > > This patch fixes it in OpenSSH for me: > > > > > > https://people.freebsd.org/~bdrewery/patches/ttssh-host-keys.diff > > > > In this change, hostkey rotation is not used if Tera Term supports it in future. > > Could you change a modification to the compat.c as follows? > > > > --- compat.c.orig 2015-03-17 14:49:20.000000000 +0900 > > +++ compat.c 2015-04-09 18:35:16.000000000 +0900 > > @@ -167,6 +167,17 @@ > > SSH_BUG_SCANNER }, > > { "Probe-*", > > SSH_BUG_PROBE }, > > + { "TTSSH/1.5.*," > > + "TeraTerm SSH*," > > Should this match all of TTSSH/1.* rather than just 1.5? Also for > tidiness I'd rather keep the TTSSH entries grouped together and have the > compat check with the rest of the hostkey notification code rather than > inline with the main code. Does this still work? > > Also, we're nearly out of bug bits, we might have to order some more :-) > > Index: compat.c > =================================================================== > RCS file: /cvs/src/usr.bin/ssh/compat.c,v > retrieving revision 1.88 > diff -u -p -r1.88 compat.c > --- compat.c 7 Apr 2015 23:00:42 -0000 1.88 > +++ compat.c 10 Apr 2015 00:21:23 -0000 > @@ -165,6 +165,17 @@ compat_datafellows(const char *version) > SSH_BUG_SCANNER }, > { "Probe-*", > SSH_BUG_PROBE }, > + { "TeraTerm SSH*," > + "TTSSH/1.5.*," > + "TTSSH/2.1*," > + "TTSSH/2.2*," > + "TTSSH/2.3*," > + "TTSSH/2.4*," > + "TTSSH/2.5*," > + "TTSSH/2.6*," > + "TTSSH/2.70*," > + "TTSSH/2.71*," > + "TTSSH/2.72*", SSH_BUG_HOSTKEYS }, > { NULL, 0 } > }; > > Index: compat.h > =================================================================== > RCS file: /cvs/src/usr.bin/ssh/compat.h,v > retrieving revision 1.46 > diff -u -p -r1.46 compat.h > --- compat.h 19 Jan 2015 20:20:20 -0000 1.46 > +++ compat.h 10 Apr 2015 00:21:23 -0000 > @@ -60,6 +60,7 @@ > #define SSH_NEW_OPENSSH 0x04000000 > #define SSH_BUG_DYNAMIC_RPORT 0x08000000 > #define SSH_BUG_CURVE25519PAD 0x10000000 > +#define SSH_BUG_HOSTKEYS 0x20000000 > > void enable_compat13(void); > void enable_compat20(void); > Index: sshd.c > =================================================================== > RCS file: /cvs/src/usr.bin/ssh/sshd.c,v > retrieving revision 1.445 > diff -u -p -r1.445 sshd.c > --- sshd.c 31 Mar 2015 22:55:24 -0000 1.445 > +++ sshd.c 10 Apr 2015 00:21:23 -0000 > @@ -891,6 +891,10 @@ notify_hostkeys(struct ssh *ssh) > int i, nkeys, r; > char *fp; > > + /* Some clients cannot cope with the hostkeys message, skip those. */ > + if (datafellows & SSH_BUG_HOSTKEYS) > + return; > + > if ((buf = sshbuf_new()) == NULL) > fatal("%s: sshbuf_new", __func__); > for (i = nkeys = 0; i < options.num_host_key_files; i++) { > > -- > Darren Tucker (dtucker at zip.com.au) > GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 > Good judgement comes with experience. Unfortunately, the experience > usually comes from bad judgement. > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > From dtucker at zip.com.au Fri Apr 10 15:17:25 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Fri, 10 Apr 2015 15:17:25 +1000 Subject: Tera Term, Unexpected SSH2 message(80) on current stage(6) [was Re: SAP-2015-3-1 issues] In-Reply-To: References: <20150228160815.GA16450@doctor.nl2k.ab.ca> <20150228201628.GA2032@doctor.nl2k.ab.ca> <5525D98A.2040302@shatow.net> <5525E3E5.2090604@shatow.net> <20150410044556.653aff56c69b87c1ddcdea4c@iwmt.org> <20150410003504.GA28738@gate.dtucker.net> Message-ID: On Fri, Apr 10, 2015 at 12:06 PM, Damien Miller wrote: > ok djm committed. thanks to all. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From john.m.olsson at ericsson.com Fri Apr 10 19:18:45 2015 From: john.m.olsson at ericsson.com (John Olsson M) Date: Fri, 10 Apr 2015 11:18:45 +0200 Subject: Does portable OpenSSH support PAM_USER change? Message-ID: <55279575.2080802@ericsson.com> Hi, A simple question with perhaps a not so simple answer. :) Does portable OpenSSH support that a PAM module changes the user during login? That is, what we would like to achieve is that if user "foo" stored in an AA server like LDAP provides correct credentials (username + password) that user should end up in a shell process running as local user "bar" instead (and not be able to escape out to a process running as "foo"). Or is PAM the wrong tool for this? Should this be done using NSS instead? /John From boleslaw.tokarski at gmail.com Fri Apr 10 20:57:15 2015 From: boleslaw.tokarski at gmail.com (=?UTF-8?Q?Boles=C5=82aw_Tokarski?=) Date: Fri, 10 Apr 2015 12:57:15 +0200 Subject: ssh-keygen support for ssh-agent Message-ID: Hello, I am in a PoC of setting up a SSH CA for the SSH host keys. The idea is to add an SSH CA service that would generate SSH certificates for servers that we install automatically. This way, we would be sure that if a server presents itself with a certificate signed with the CA, it belongs to us, and is no MitM. I settled on a GnuPG smartcard to go with the SSH CA. This would secure the private key material from remote attack, and the smartcard itself is protected by a PIN. The smartcard is supported by opensc-pkcs11.so, and it works nicely with ssh authentication, with native ssh-agent with "ssh-add -s opensc-pksc11.so", with gpg-agent's ssh agent support, and it neatly generates SSH certificates with "ssh-keygen -D opensc-pkcs11.so". Now, my design assumed that the SSH CA would only require PIN entering on its PIN-pad after, say, a reboot. ssh-agent works like this for ssh authentication - it keeps the card open until it's removed or the machine gets turned off. Unfortunately, ssh-keygen cannot currently utilize ssh-agent for generating host certificates. It opens the smartcard with the pkcs11 library on its own, requests the PIN for every signature, and closes the card. Of course, I could use a card reader that doesn't have a PIN-pad. I guess I could issue "echo 1234 |ssh-keygen -D opensc-pkcs11.so". Or I could totally resign from using a smartcard. But then, the same happens if I use a password-protected private key as the CA - I get prompted for the key password on each run. All of those approaches are not ideal, to say the least. What I need is a process that keeps the smartcard open, so that it's possible to only enter the PIN once. This is done for ssh in ssh-agent. Would it be possible to add ssh-agent support to ssh-keygen? Best regards, Boles?aw Tokarski From djm at mindrot.org Sat Apr 11 13:52:17 2015 From: djm at mindrot.org (Damien Miller) Date: Sat, 11 Apr 2015 13:52:17 +1000 (AEST) Subject: ssh-keygen support for ssh-agent In-Reply-To: References: Message-ID: Agent support for ssh-keygen isn't a bad idea - could you please file a feature request at https://bugzilla.mindrot.org/ so we don't forget it? -d On Fri, 10 Apr 2015, Boles?aw Tokarski wrote: > Hello, > > I am in a PoC of setting up a SSH CA for the SSH host keys. The idea is to > add an SSH CA service that would generate SSH certificates for servers that > we install automatically. This way, we would be sure that if a server > presents itself with a certificate signed with the CA, it belongs to us, > and is no MitM. > > I settled on a GnuPG smartcard to go with the SSH CA. This would secure the > private key material from remote attack, and the smartcard itself is > protected by a PIN. The smartcard is supported by opensc-pkcs11.so, and it > works nicely with ssh authentication, with native ssh-agent with "ssh-add > -s opensc-pksc11.so", with gpg-agent's ssh agent support, and it neatly > generates SSH certificates with "ssh-keygen -D opensc-pkcs11.so". > > Now, my design assumed that the SSH CA would only require PIN entering on > its PIN-pad after, say, a reboot. ssh-agent works like this for ssh > authentication - it keeps the card open until it's removed or the machine > gets turned off. Unfortunately, ssh-keygen cannot currently utilize > ssh-agent for generating host certificates. It opens the smartcard with the > pkcs11 library on its own, requests the PIN for every signature, and closes > the card. > > Of course, I could use a card reader that doesn't have a PIN-pad. I guess I > could issue "echo 1234 |ssh-keygen -D opensc-pkcs11.so". Or I could totally > resign from using a smartcard. But then, the same happens if I use a > password-protected private key as the CA - I get prompted for the key > password on each run. All of those approaches are not ideal, to say the > least. > > What I need is a process that keeps the smartcard open, so that it's > possible to only enter the PIN once. This is done for ssh in ssh-agent. > Would it be possible to add ssh-agent support to ssh-keygen? > > Best regards, > Boles?aw Tokarski > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev > From ryan_cox at byu.edu Tue Apr 14 03:54:50 2015 From: ryan_cox at byu.edu (Ryan Cox) Date: Mon, 13 Apr 2015 11:54:50 -0600 Subject: [PATCH] Optionally allow pam_setcred to override gid Message-ID: <552C02EA.3010406@byu.edu> I would like to allow pam_setcred/pam_sm_setcred to override the gid that is normally set for a user. Currently the openssh code calls do_pam_setcred then it sets the gid to the user's gid as listed in /etc/passwd, LDAP, or whatever regardless of what the pam module set it to. I would instead like a pam module to be able to set the gid with setgid() and not have it overwritten by openssh. I wrote a patch that does just that by comparing getgid() before and after calling do_pam_setcred. If the gid changes it sets pw->gid to the new gid, which is used in later functions. I don't know if this is considered the proper way to achieve that behavior in a safe way but it seemed logical to me. The behavior is optional; PermitGidOverride=no is the default. As for the reasoning, this is for a scheduled environment using Slurm. I am developing a pam module that "adopts" ssh processes into the appropriate batch job on the node. Users can launch jobs via Slurm that run with their gid as one of their supplementary groups. As part of the adoption of the ssh process, I would like to set the ssh process's gid equal to that of the job it is being adopted into. Ryan -------------- next part -------------- A non-text attachment was scrubbed... Name: openssh_permit_gid_override.diff Type: text/x-patch Size: 8651 bytes Desc: not available URL: From rsbecker at nexbridge.com Tue Apr 14 05:34:26 2015 From: rsbecker at nexbridge.com (Randall S. Becker) Date: Mon, 13 Apr 2015 15:34:26 -0400 Subject: [Compile Issue] netcat.c on HP NonStop Message-ID: <00ab01d07620$da485970$8ed90c50$@nexbridge.com> Greetings, I am porting the openssh-portable 6.8 release to the HP NonStop (NSE) platform. Prior versions were no real problem, with minor tweeks. However, with the inclusion of regress/netcat.c, which depends on arpa/telnet.h, we have an issue. Unfortunately, the platform does not have this file, nor anything like it - telnet is done rather differently. We do have a version of netcat (0.7.1 a.k.a. "really old") ported. Is there a reasonably documentable way to configure the regression tests so that this dependency is either not executed or uses an installed version? Cheers, Randall -- Brief whoami: NonStop&UNIX developer since approximately UNIX(421664400)/NonStop(211288444200000000) -- In my real life, I talk too much. From tim at multitalents.net Tue Apr 14 07:28:58 2015 From: tim at multitalents.net (Tim Rice) Date: Mon, 13 Apr 2015 14:28:58 -0700 (PDT) Subject: [Compile Issue] netcat.c on HP NonStop In-Reply-To: <00ab01d07620$da485970$8ed90c50$@nexbridge.com> References: <00ab01d07620$da485970$8ed90c50$@nexbridge.com> Message-ID: On Mon, 13 Apr 2015, Randall S. Becker wrote: > Greetings, > > I am porting the openssh-portable 6.8 release to the HP NonStop (NSE) > platform. Prior versions were no real problem, with minor tweeks. However, > with the inclusion of regress/netcat.c, which depends on arpa/telnet.h, we > have an issue. Unfortunately, the platform does not have this file, nor > anything like it - telnet is done rather differently. See if you can find the include file that has the telnet protocol defines WILL, WONT, DO, DONT, and IAC. Then we should be able to come up with a patch. > We do have a version > of netcat (0.7.1 a.k.a. "really old") ported. Is there a reasonably > documentable way to configure the regression tests so that this dependency > is either not executed or uses an installed version? netcat is now included because of all the issues with various versions out there. Let's get the included version of netcat workign on your platform. > > Cheers, > Randall > > -- Brief whoami: NonStop&UNIX developer since approximately > UNIX(421664400)/NonStop(211288444200000000) > -- In my real life, I talk too much. -- Tim Rice Multitalents tim at multitalents.net From djm at mindrot.org Tue Apr 14 08:27:14 2015 From: djm at mindrot.org (Damien Miller) Date: Tue, 14 Apr 2015 08:27:14 +1000 (AEST) Subject: [Compile Issue] netcat.c on HP NonStop In-Reply-To: <00ab01d07620$da485970$8ed90c50$@nexbridge.com> References: <00ab01d07620$da485970$8ed90c50$@nexbridge.com> Message-ID: On Mon, 13 Apr 2015, Randall S. Becker wrote: > Greetings, > > I am porting the openssh-portable 6.8 release to the HP NonStop (NSE) > platform. Prior versions were no real problem, with minor tweeks. However, > with the inclusion of regress/netcat.c, which depends on arpa/telnet.h, we > have an issue. Unfortunately, the platform does not have this file, nor > anything like it - telnet is done rather differently. We do have a version > of netcat (0.7.1 a.k.a. "really old") ported. Is there a reasonably > documentable way to configure the regression tests so that this dependency > is either not executed or uses an installed version? We only need a few of the constants from that header, and they are fixed values for the telnet protocol so we can just include them directly. Could you please try this patch? diff --git a/regress/netcat.c b/regress/netcat.c index 1a9fc87..6234ba0 100644 --- a/regress/netcat.c +++ b/regress/netcat.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -63,6 +62,13 @@ # endif #endif +/* Telnet options from arpa/telnet.h */ +#define IAC 255 +#define DONT 254 +#define DO 253 +#define WONT 252 +#define WILL 251 + #ifndef SUN_LEN #define SUN_LEN(su) \ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) From rsbecker at nexbridge.com Tue Apr 14 09:14:01 2015 From: rsbecker at nexbridge.com (Randall S. Becker) Date: Mon, 13 Apr 2015 19:14:01 -0400 Subject: [Compile Issue] netcat.c on HP NonStop In-Reply-To: References: <00ab01d07620$da485970$8ed90c50$@nexbridge.com> Message-ID: <00eb01d0763f$87789bf0$9669d3d0$@nexbridge.com> On April 13, 2015 6:27 PM, Damien Miller wrote: > On Mon, 13 Apr 2015, Randall S. Becker wrote: > > > Greetings, > > > > I am porting the openssh-portable 6.8 release to the HP NonStop (NSE) > > platform. Prior versions were no real problem, with minor tweeks. > > However, with the inclusion of regress/netcat.c, which depends on > > arpa/telnet.h, we have an issue. Unfortunately, the platform does not > > have this file, nor anything like it - telnet is done rather > > differently. We do have a version of netcat (0.7.1 a.k.a. "really > > old") ported. Is there a reasonably documentable way to configure the > > regression tests so that this dependency is either not executed or uses an > installed version? > > We only need a few of the constants from that header, and they are fixed > values for the telnet protocol so we can just include them directly. > > Could you please try this patch? > > diff --git a/regress/netcat.c b/regress/netcat.c index 1a9fc87..6234ba0 100644 > --- a/regress/netcat.c > +++ b/regress/netcat.c > @@ -42,7 +42,6 @@ > #include > #include > #include > -#include > > #include > #include > @@ -63,6 +62,13 @@ > # endif > #endif > > +/* Telnet options from arpa/telnet.h */ > +#define IAC 255 > +#define DONT 254 > +#define DO 253 > +#define WONT 252 > +#define WILL 251 > + > #ifndef SUN_LEN > #define SUN_LEN(su) \ > (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) I have wrapped the changes in our platform's __TANDEM #define. (patch below) There's a bit more to it, unfortunately, but the patches were helpful. Still missing are: POLLNVAL, POLLHUP, IPTOS_PREC_CRITIC_ECP, IPTOS_PREC_INTERNETCONTROL, IPTOS_PREC_NETCONTROL - which are just not appropriate to the platform. I have #ifdef'd around those and tested. The version in regress/netcat.c is radically different from the 0.7.1 version we have as a port - some comparisons there are not too practical. The test failures with my workaround fail are as follows, but I suspect are completely unrelated - possibly our non-standard SSH ports: run test connect.sh ... ssh connect with protocol 1 failed ssh connect with protocol 2 failed I don't think this is a regression from 6.7 in our environment. Cheers, Randall diff --git a/regress/netcat.c b/regress/netcat.c index 1a9fc87..2c8d301 100644 --- a/regress/netcat.c +++ b/regress/netcat.c @@ -42,7 +42,23 @@ #include #include #include +#if defined __TANDEM +#include +/* Telnet options from arpa/telnet.h */ +#define IAC 255 +#define DONT 254 +#define DO 253 +#define WONT 252 +#define WILL 251 + +# ifndef SUN_LEN +# define SUN_LEN(su) \ + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) +# endif + +#else #include +#endif #include #include @@ -868,21 +884,30 @@ readwrite(int net_fd) /* treat socket error conditions */ for (n = 0; n < 4; n++) { +#if defined __TANDEM + if (pfd[n].revents & (POLLERR)) { +#else if (pfd[n].revents & (POLLERR|POLLNVAL)) { +#endif pfd[n].fd = -1; } } /* reading is possible after HUP */ if (pfd[POLL_STDIN].events & POLLIN && +#if ! defined __TANDEM pfd[POLL_STDIN].revents & POLLHUP && +#endif ! (pfd[POLL_STDIN].revents & POLLIN)) pfd[POLL_STDIN].fd = -1; if (pfd[POLL_NETIN].events & POLLIN && +#if ! defined __TANDEM pfd[POLL_NETIN].revents & POLLHUP && +#endif ! (pfd[POLL_NETIN].revents & POLLIN)) pfd[POLL_NETIN].fd = -1; +#if ! defined __TANDEM if (pfd[POLL_NETOUT].revents & POLLHUP) { if (Nflag) shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); @@ -891,6 +916,7 @@ readwrite(int net_fd) /* if HUP, stop watching stdout */ if (pfd[POLL_STDOUT].revents & POLLHUP) pfd[POLL_STDOUT].fd = -1; +#endif /* if no net out, stop watching stdin */ if (pfd[POLL_NETOUT].fd == -1) pfd[POLL_STDIN].fd = -1; @@ -1244,7 +1270,9 @@ map_tos(char *s, int *val) { "af41", IPTOS_DSCP_AF41 }, { "af42", IPTOS_DSCP_AF42 }, { "af43", IPTOS_DSCP_AF43 }, +#if ! defined __TANDEM { "critical", IPTOS_PREC_CRITIC_ECP }, +#endif { "cs0", IPTOS_DSCP_CS0 }, { "cs1", IPTOS_DSCP_CS1 }, { "cs2", IPTOS_DSCP_CS2 }, @@ -1254,9 +1282,13 @@ map_tos(char *s, int *val) { "cs6", IPTOS_DSCP_CS6 }, { "cs7", IPTOS_DSCP_CS7 }, { "ef", IPTOS_DSCP_EF }, +#if ! defined __TANDEM { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, +#endif { "lowdelay", IPTOS_LOWDELAY }, +#if ! defined __TANDEM { "netcontrol", IPTOS_PREC_NETCONTROL }, +#endif { "reliability", IPTOS_RELIABILITY }, { "throughput", IPTOS_THROUGHPUT }, { NULL, -1 }, From pgut001 at cs.auckland.ac.nz Tue Apr 14 22:23:29 2015 From: pgut001 at cs.auckland.ac.nz (Peter Gutmann) Date: Tue, 14 Apr 2015 12:23:29 +0000 Subject: OpenSSH 6.6.x sends invalid SSH_MSG_USERAUTH_INFO_REQUEST Message-ID: <9A043F3CF02CD34C8E74AC1594475C73AAFEFD5F@uxcn10-5.UoA.auckland.ac.nz> Darren Tucker writes: >That's explicitly allowed by RFC4256. In addition to allowing zero prompts, >section 3.2 also says: > > "The language tag is deprecated and SHOULD be the empty string." > >and > > "The name and instruction fields MAY be empty strings; the client MUST > be prepared to handle this correctly. The prompt field(s) MUST NOT > be empty strings." In this case the prompts are empty strings. There's no name, no instructions, and no prompts. (It also depends on what you call an empty string, is it a string of length zero or an absent string? Both are means of encoding the empty string). >Do what it says in RFC4256 section 3.4? > > "In the case that the server sends a `0' num-prompts field in the > request message, the client MUST send a response message with a `0' > num-responses field to complete the exchange." Ah, OK, so it's a prompts issue hidden in the responses section of the docs (and one that appears to contradict what's in the previous section)... it does kinda beg the question though as to why a server would request zero responses for a request. (And one more thing to add to my evil-tricks-to-play-on-peers to see how many I can crash when I'm bored :-). Peter. From yuri at rawbw.com Wed Apr 15 16:48:18 2015 From: yuri at rawbw.com (Yuri) Date: Tue, 14 Apr 2015 23:48:18 -0700 Subject: Is ssh supposed to run commands in terminal? Message-ID: <552E09B2.90904@rawbw.com> I noticed that this command returns NO through ssh: > $ ssh user at host "if [ -t 1 ]; then echo YES; else echo NO; fi" > NO and YES when run locally (of course): > $ if [ -t 1 ]; then echo YES; else echo NO; fi > YES I can't find any command line option related to running command remotely in terminal. I think users intuitively expect commands to be run in terminal. Is something broken with my ssh setup? ssh on FreeBSD 10.1 Yuri From christian.kandeler at theqtcompany.com Wed Apr 15 17:49:06 2015 From: christian.kandeler at theqtcompany.com (Christian Kandeler) Date: Wed, 15 Apr 2015 09:49:06 +0200 Subject: Is ssh supposed to run commands in terminal? In-Reply-To: <552E09B2.90904@rawbw.com> References: <552E09B2.90904@rawbw.com> Message-ID: <552E17F2.6020800@theqtcompany.com> On 04/15/2015 08:48 AM, Yuri wrote: > I noticed that this command returns NO through ssh: > > $ ssh user at host "if [ -t 1 ]; then echo YES; else echo NO; fi" > > NO > and YES when run locally (of course): > > $ if [ -t 1 ]; then echo YES; else echo NO; fi > > YES > > I can't find any command line option related to running command remotely > in terminal. -o RequestTTY=yes I think users intuitively expect commands to be run in > terminal. > Is something broken with my ssh setup? > > ssh on FreeBSD 10.1 > > Yuri > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev From naddy at mips.inka.de Wed Apr 15 20:38:38 2015 From: naddy at mips.inka.de (Christian Weisgerber) Date: Wed, 15 Apr 2015 10:38:38 +0000 (UTC) Subject: Is ssh supposed to run commands in terminal? References: <552E09B2.90904@rawbw.com> Message-ID: On 2015-04-15, Yuri wrote: > I can't find any command line option related to running command remotely > in terminal. -t, -T The term you are looking for is "tty". > I think users intuitively expect commands to be run in > terminal. Historically, the idea was that users expect ssh(1) to behave like rsh(1), which did not allocate a tty. -- Christian "naddy" Weisgerber naddy at mips.inka.de From mmn at hethane.se Sat Apr 18 03:58:29 2015 From: mmn at hethane.se (Mikael Nordfeldth) Date: Fri, 17 Apr 2015 19:58:29 +0200 Subject: Private key (-i key_file) percent_expand problem when path contains percent sign (%) Message-ID: <553149C5.5090109@hethane.se> I have problems ssh:ing with my private key when the user's. I run Debian Jessie, with (other than whatever Debian has done) non-modified OpenSSH: $ aptitude show openssh-client |grep Version: Version: 1:6.7p1-3 The problem is I get this fatal error without a remote connection being made: $ ssh user at example.com percent_expand: unknown key %/ My $HOME is "/srv/www/example.com/%". If I give the full path to the directory with the -i parameter I get the same error. If I provide a relative path, with `pwd` equal to $HOME, it works just fine: $ pwd /srv/www/kulturhusfestivalen.se/% $ ssh -i /srv/www/example.com/%/.ssh/id_rsa user at example.com percent_expand: unknown key %/ $ ssh -i .ssh/id_rsa user at example.com The authenticity of host 'example.com'... So it boils down to the -i parsing with a percent sign (which doesn't expand) it seems. Anyone else experiencing this or can reproduce it? -- Mikael Nordfeldth XMPP/mail: mmn at hethane.se OpenPGP fpr: AE68 9813 0B7C FCE3 B2FA 727B C7CE 635B B52E 9B31 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From pcastellazzi at netlabs.com.uy Fri Apr 17 16:58:26 2015 From: pcastellazzi at netlabs.com.uy (Pablo Castellazzi) Date: Fri, 17 Apr 2015 03:58:26 -0300 Subject: OpenSSH and syslog Message-ID: <3ECDA3B9-2951-4967-9CAC-FCF4F4D46BDB@netlabs.com.uy> Hello. Today i found an interesting problem related to OpenSSH. If you open enough connections to /dev/log which your current logger can?t handle, you can?t logging remotely using SSH which is blocked waiting for access to /dev/log. To reproduce this problem i used CentOS 6 and 7 with the following script: #!/bin/bash for i in (1..500); do (yes | logger) & done For CentOS 6, 50 is enough to cause rsyslog to stop accepting connections. It?s a known limitation described here: http://www.rsyslog.com/doc/v8-stable/configuration/modules/imuxsock.html For CentOS 7, the limit is around 450, i believe is for the same reason (but with systems this time), but i did not check. I am not sure if this is a problem or a feature. I guess under some circumstances it would be appropriate to deny access if you can?t record it. On the other hand it makes too difficult to access cloud system which are under stress. I would like to hear your thoughts about how should we handle this issue. It comes to mind some form of asynchronous logging or may be a timeout and a configuration option to make it non fatal. Best Regards. Pablo Castellazzi. -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 1727 bytes Desc: not available URL: From yuri at rawbw.com Sat Apr 18 08:55:33 2015 From: yuri at rawbw.com (Yuri) Date: Fri, 17 Apr 2015 15:55:33 -0700 Subject: Is ssh supposed to run commands in terminal? In-Reply-To: <552E17F2.6020800@theqtcompany.com> References: <552E09B2.90904@rawbw.com> <552E17F2.6020800@theqtcompany.com> Message-ID: <55318F65.10202@rawbw.com> On 04/15/2015 00:49, Christian Kandeler wrote: > > -o RequestTTY=yes Thanks, this works. However, with this option ssh alters the output of all commands: it adds CR=0x0d in front of every NL=0x0a. This doesn't happen without this option. Why is sshd adding CR? I think the only effect of running in the terminal is the term flag that the process sees on the stdin and stdout (in shell it is [ -t 1 ]). The process is supposed to detect the terminal caps and print the output accordingly. I even verified that this is sshd is doing it and not the cat command by writing the C program printing newlines. Yuri From djm at mindrot.org Sat Apr 18 09:58:03 2015 From: djm at mindrot.org (Damien Miller) Date: Sat, 18 Apr 2015 09:58:03 +1000 (AEST) Subject: OpenSSH and syslog In-Reply-To: <3ECDA3B9-2951-4967-9CAC-FCF4F4D46BDB@netlabs.com.uy> References: <3ECDA3B9-2951-4967-9CAC-FCF4F4D46BDB@netlabs.com.uy> Message-ID: On Fri, 17 Apr 2015, Pablo Castellazzi wrote: > Hello. > > Today i found an interesting problem related to OpenSSH. If you open > enough connections to /dev/log which your current logger can?t handle, > you can?t logging remotely using SSH which is blocked waiting for > access to /dev/log. OpenSSH just calls syslog(), so the blocking behaviour is in libc. -d From gert at greenie.muc.de Sat Apr 18 23:39:18 2015 From: gert at greenie.muc.de (Gert Doering) Date: Sat, 18 Apr 2015 15:39:18 +0200 Subject: Is ssh supposed to run commands in terminal? In-Reply-To: <55318F65.10202@rawbw.com> References: <552E09B2.90904@rawbw.com> <552E17F2.6020800@theqtcompany.com> <55318F65.10202@rawbw.com> Message-ID: <20150418133918.GS382@greenie.muc.de> Hi, On Fri, Apr 17, 2015 at 03:55:33PM -0700, Yuri wrote: > On 04/15/2015 00:49, Christian Kandeler wrote: > > > >-o RequestTTY=yes > > > Thanks, this works. > > However, with this option ssh alters the output of all commands: it adds > CR=0x0d in front of every NL=0x0a. This doesn't happen without this option. > Why is sshd adding CR? You requested a tty, you got a tty, and that's what ttys are doing unless you run "stty -ocrnl" first (inside the remote shell, running inside the tty). gert -- USENET is *not* the non-clickable part of WWW! //www.muc.de/~gert/ Gert Doering - Munich, Germany gert at greenie.muc.de fax: +49-89-35655025 gert at net.informatik.tu-muenchen.de From keisial at gmail.com Mon Apr 20 04:56:42 2015 From: keisial at gmail.com (=?ISO-8859-1?Q?=C1ngel_Gonz=E1lez?=) Date: Sun, 19 Apr 2015 20:56:42 +0200 Subject: Private key (-i key_file) percent_expand problem when path contains percent sign (%) In-Reply-To: <553149C5.5090109@hethane.se> References: <553149C5.5090109@hethane.se> Message-ID: <5533FA6A.5030307@gmail.com> On 17/04/15 19:58, Mikael Nordfeldth wrote: > So it boils down to the -i parsing with a percent sign (which doesn't > expand) it seems. Anyone else experiencing this or can reproduce it? Yes, openssh doesn't like a % in the -i parameter: - If you provide a %, inside load_public_identity_files it attempts to treat it as an expand sequence, and thus fails. - If you provide a %% (which expands to a single %), then the stat(2) done before add_identity_file() makes it to fail, and such path doesn't even reach load_public_identity_files. As a workaround, you can provide the key file with the -o option: ssh -o IdentityFile=/srv/www/example.com/%%/.ssh/id_rsa user at example.com The following patch makes ssh to ignore the stat failure if the -i argument contains a % character: diff --git a/ssh.c b/ssh.c index 0ad82f0..e0c574f 100644 --- a/ssh.c +++ b/ssh.c @@ -705,7 +705,7 @@ main(int ac, char **av) options.gss_deleg_creds = 1; break; case 'i': - if (stat(optarg, &st) < 0) { + if (stat(optarg, &st) < 0 && strchr(optarg, '%') == NULL) { fprintf(stderr, "Warning: Identity file %s " "not accessible: %s.\n", optarg, strerror(errno)); From djm at mindrot.org Mon Apr 20 10:35:45 2015 From: djm at mindrot.org (Damien Miller) Date: Mon, 20 Apr 2015 10:35:45 +1000 (AEST) Subject: Private key (-i key_file) percent_expand problem when path contains percent sign (%) In-Reply-To: <553149C5.5090109@hethane.se> References: <553149C5.5090109@hethane.se> Message-ID: Hi, Could you please file a bug at https://bugzilla.mindrot.org/ ? We should handle this case a bit better... -d On Fri, 17 Apr 2015, Mikael Nordfeldth wrote: > I have problems ssh:ing with my private key when the user's. > > I run Debian Jessie, with (other than whatever Debian has done) > non-modified OpenSSH: > > $ aptitude show openssh-client |grep Version: > Version: 1:6.7p1-3 > > The problem is I get this fatal error without a remote connection being > made: > > $ ssh user at example.com > percent_expand: unknown key %/ > > My $HOME is "/srv/www/example.com/%". > > If I give the full path to the directory with the -i parameter I get the > same error. If I provide a relative path, with `pwd` equal to $HOME, it > works just fine: > > $ pwd > /srv/www/kulturhusfestivalen.se/% > $ ssh -i /srv/www/example.com/%/.ssh/id_rsa user at example.com > percent_expand: unknown key %/ > $ ssh -i .ssh/id_rsa user at example.com > The authenticity of host 'example.com'... > > So it boils down to the -i parsing with a percent sign (which doesn't > expand) it seems. Anyone else experiencing this or can reproduce it? > > -- > Mikael Nordfeldth > XMPP/mail: mmn at hethane.se > OpenPGP fpr: AE68 9813 0B7C FCE3 B2FA 727B C7CE 635B B52E 9B31 > > From cary.fitzhugh at gmail.com Wed Apr 22 09:43:46 2015 From: cary.fitzhugh at gmail.com (Cary FitzHugh) Date: Tue, 21 Apr 2015 19:43:46 -0400 Subject: Determining the reverse port tunnels Message-ID: Hi all, If I were to connect to a system with a command like this: ssh -R *:0:localhost:3000 user at server Is there any way for openssh to tell my shell what ports it opened for me? i.e. what port on server is my localhost:3000 exposed to? I know that there is a stderr / stdout printout of the port, but wonder if there is a way to know in my shell. Maybe an env var? Maybe some grepping of netstat? Thanks! Cary FitzHugh From djm at mindrot.org Wed Apr 22 11:31:57 2015 From: djm at mindrot.org (Damien Miller) Date: Wed, 22 Apr 2015 11:31:57 +1000 (AEST) Subject: Determining the reverse port tunnels In-Reply-To: References: Message-ID: On Tue, 21 Apr 2015, Cary FitzHugh wrote: > Hi all, > > If I were to connect to a system with a command like this: > > ssh -R *:0:localhost:3000 user at server > > Is there any way for openssh to tell my shell what ports it opened for me? > > i.e. what port on server is my localhost:3000 exposed to? > > I know that there is a stderr / stdout printout of the port, but wonder if > there is a way to know in my shell. Maybe an env var? Maybe some grepping > of netstat? At the moment, the only way is to use the multiplexing support. E.g. $ ssh -nNfS -oControlPath=~/.ssh/ctl-%r@%h:%p 127.0.0.1 $ ssh -oControlPath=~/.ssh/ctl-%r@%h:%p -O forward -R 0:127.0.0.1:9999 127.0.0.1 Allocated port 27313 for mux remote forward to 127.0.0.1:9999 Allocated port 27313 for remote forward to 127.0.0.1:9999 27313 The double logging is a bug - patch below. In general, it's unreliable to put the port number in an environment variable because the remote shell session is separate to the forwardings and may be establised before they are set up. -d Index: mux.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/mux.c,v retrieving revision 1.50 diff -u -p -r1.50 mux.c --- mux.c 20 Jan 2015 23:14:00 -0000 1.50 +++ mux.c 22 Apr 2015 01:30:43 -0000 @@ -592,7 +594,7 @@ mux_confirm_remote_forward(int type, u_i if (type == SSH2_MSG_REQUEST_SUCCESS) { if (rfwd->listen_port == 0) { rfwd->allocated_port = packet_get_int(); - logit("Allocated port %u for mux remote forward" + debug("Allocated port %u for mux remote forward" " to %s:%d", rfwd->allocated_port, rfwd->connect_host, rfwd->connect_port); buffer_put_int(&out, MUX_S_REMOTE_PORT); @@ -1703,7 +1716,7 @@ mux_client_forward(int fd, int cancel_fl if (cancel_flag) fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__); fwd->allocated_port = buffer_get_int(&m); - logit("Allocated port %u for remote forward to %s:%d", + verbose("Allocated port %u for remote forward to %s:%d", fwd->allocated_port, fwd->connect_host ? fwd->connect_host : "", fwd->connect_port); From dtucker at zip.com.au Wed Apr 22 11:31:46 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Wed, 22 Apr 2015 11:31:46 +1000 Subject: Determining the reverse port tunnels In-Reply-To: References: Message-ID: On Wed, Apr 22, 2015 at 9:43 AM, Cary FitzHugh wrote: > Hi all, > > If I were to connect to a system with a command like this: > > ssh -R *:0:localhost:3000 user at server > > Is there any way for openssh to tell my shell what ports it opened for me? > > i.e. what port on server is my localhost:3000 exposed to? > > I know that there is a stderr / stdout printout of the port, but wonder if > there is a way to know in my shell. Maybe an env var? There's no general way to do this: port forwards can be added and deleted at any time but the environment variables can only be set and shell startup time. > Maybe some grepping of netstat? > The parent process ID of your shell is the sshd that's listening, so something like this should work: lsof -p $PPID | grep LISTEN or the equivalent with netstat if your platform can map port numbers to PIDs. The cleanest solution is probably using a control socket which returns the port number to the client., something like ssh -N -MS /tmp/ctl yourserver & port=`ssh -S /tmp/ctl -O forward -R 0:127.0.0.1:22 yourserver` ssh -S /tmp/ctl yourserver command --port $port ssh -S /tmp/ctl -O exit yourserver -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From reubenhwk at gmail.com Thu Apr 23 00:42:15 2015 From: reubenhwk at gmail.com (Reuben Hawkins) Date: Wed, 22 Apr 2015 07:42:15 -0700 Subject: shared private key Message-ID: Hi SSH-devs, This may be a bit off topic for this list, but.... Would it be ok to share a private key in an installer script so long as the corresponding public key is setup like this... command="cat ~/.ssh/id_rsa.pub" ssh-rsa AAAA... I'm looking for a secure way to get a user to share their public key through SSH which can be invoked from an installer on another host...for example... # ssh-keyscan server.local > .ssh/known_hosts # ssh -i hardcoded_private_key server.local > .ssh/authorized_keys Of course in this installer the key fingerprints will be examined by the user before any keys are actually put in known hosts and authorized_keys. Is this secure? Is there a better way? Thanks in advance, Reuben From keisial at gmail.com Thu Apr 23 03:55:24 2015 From: keisial at gmail.com (=?windows-1252?Q?=C1ngel_Gonz=E1lez?=) Date: Wed, 22 Apr 2015 19:55:24 +0200 Subject: shared private key In-Reply-To: References: Message-ID: <5537E08C.4040807@gmail.com> On 22/04/15 16:42, Reuben Hawkins wrote: > Hi SSH-devs, > > This may be a bit off topic for this list, but.... > > Would it be ok to share a private key in an installer script so long > as the corresponding public key is setup like this... > > command="cat ~/.ssh/id_rsa.pub" ssh-rsa AAAA... You would also need at least no-port-forwarding I'd add all available restricting options. > I'm looking for a secure way to get a user to share their public key > through SSH which can be invoked from an installer on another > host...for example... > > # ssh-keyscan server.local> .ssh/known_hosts > # ssh -i hardcoded_private_key server.local> .ssh/authorized_keys > > Of course in this installer the key fingerprints will be examined by > the user before any keys are actually put in known hosts and > authorized_keys. > > Is this secure? Is there a better way? I see no obvious flaw. Everything depends on the integrity of the server, but you already knew that? PS: Why ssh-keyscan? You can hardcode it directly in the known_hosts of .ssh or /etc From reubenhwk at gmail.com Thu Apr 23 05:13:41 2015 From: reubenhwk at gmail.com (Reuben Hawkins) Date: Wed, 22 Apr 2015 12:13:41 -0700 Subject: non-openssl build fixes Message-ID: The attached patches fixes and cleans up the build when configured with --without-openssl. Summary: * Fix KEX_SERVER_ENCRYPT macro in myproposal.h * Fix unresolved symbols in ssh-keygen.c * Isolate openssl code and extend WITH_OPENSSL wrappers around it * Make ed25519 default key type in ssh-keygen when configured --without-openssl -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-myproposal.h-fix-newline-in-KEX_SERVER_ENCRYPT.patch Type: text/x-patch Size: 992 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-ssh-keygen.c-add-needed-WITH_OPENSSL-gaurds.patch Type: text/x-patch Size: 1243 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-ssh-keygen.c-isolate-ssl-code-wrap-in-WITH_OPENSSL.patch Type: text/x-patch Size: 3498 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0004-ssh-keygen.c-man-ed25519-default-without-openssl.patch Type: text/x-patch Size: 923 bytes Desc: not available URL: From reubenhwk at gmail.com Thu Apr 23 06:26:06 2015 From: reubenhwk at gmail.com (Reuben Hawkins) Date: Wed, 22 Apr 2015 13:26:06 -0700 Subject: shared private key In-Reply-To: <5537E08C.4040807@gmail.com> References: <5537E08C.4040807@gmail.com> Message-ID: On Wed, Apr 22, 2015 at 10:55 AM, ?ngel Gonz?lez wrote: > On 22/04/15 16:42, Reuben Hawkins wrote: >> >> Hi SSH-devs, >> >> This may be a bit off topic for this list, but.... >> >> Would it be ok to share a private key in an installer script so long >> as the corresponding public key is setup like this... >> >> command="cat ~/.ssh/id_rsa.pub" ssh-rsa AAAA... > > You would also need at least no-port-forwarding > > I'd add all available restricting options. > > >> I'm looking for a secure way to get a user to share their public key >> through SSH which can be invoked from an installer on another >> host...for example... >> >> # ssh-keyscan server.local> .ssh/known_hosts >> # ssh -i hardcoded_private_key server.local> .ssh/authorized_keys >> >> Of course in this installer the key fingerprints will be examined by >> the user before any keys are actually put in known hosts and >> authorized_keys. >> >> Is this secure? Is there a better way? > > I see no obvious flaw. Everything depends on the integrity of the server, > but you already knew that? > > > PS: Why ssh-keyscan? You can hardcode it directly in the known_hosts of .ssh > or /etc > ssh-keyscan because we don't know the server's host keys ahead of time. The user is going to install a server on some machine, another user is going to install a client. The clients must get the host keys in its known-host file and the server user's keys in its authorized keys file. ssh-keyscan gets the hostkeys from the server, and the hardcoded private key will get the server user's public key. Also, each server needs unique keys. I wouldn't want one of our customers to be able to trick another one of our customers into ssh'ing to the wrong server without a known_host identity changed message, so I can't hardcode a host key directly into the known_hosts files in either .ssh or /etc. Let me know if I'm missing something. :) Thanks in advance, Reuben From gert at greenie.muc.de Thu Apr 23 06:53:48 2015 From: gert at greenie.muc.de (Gert Doering) Date: Wed, 22 Apr 2015 22:53:48 +0200 Subject: shared private key In-Reply-To: References: <5537E08C.4040807@gmail.com> Message-ID: <20150422205348.GN382@greenie.muc.de> Hi, On Wed, Apr 22, 2015 at 01:26:06PM -0700, Reuben Hawkins wrote: > Let me know if I'm missing something. :) Signed keys from a common CA? gert -- USENET is *not* the non-clickable part of WWW! //www.muc.de/~gert/ Gert Doering - Munich, Germany gert at greenie.muc.de fax: +49-89-35655025 gert at net.informatik.tu-muenchen.de From reubenhwk at gmail.com Thu Apr 23 07:51:02 2015 From: reubenhwk at gmail.com (Reuben Hawkins) Date: Wed, 22 Apr 2015 14:51:02 -0700 Subject: shared private key In-Reply-To: <20150422205348.GN382@greenie.muc.de> References: <5537E08C.4040807@gmail.com> <20150422205348.GN382@greenie.muc.de> Message-ID: On Wed, Apr 22, 2015 at 1:53 PM, Gert Doering wrote: > Hi, > > On Wed, Apr 22, 2015 at 01:26:06PM -0700, Reuben Hawkins wrote: >> Let me know if I'm missing something. :) > > Signed keys from a common CA? I don't think the signed key helps in my particular case (I may be wrong, if so please correct me). I'm working on a management application and the next version's big feature is network security via SSH. My application is actually backwards from most other client/server models. It's backwards in that the "server" initiates connections to the "clients" (so the ssh client runs on the "server", sshd on the "clients") to make the clients do things (let's just say run updates as an example). I need to get the server user's public key into the client's authorized_keys file when the client software is installed. I can't think of a way to get the public key from the server other than the private key hardcoded into the installer and the corresponding hardcoded public key in the server's authorized_keys file like this... command="cat ~/.ssh/id_rsa.pub",other-safty-restrictions ssh-rsa AAAA.... With this anybody can get the server user's public key. My installer looks like this.... #!/bin/bash # install software ..... echo -n "who's your server? " read server # get host keys from server, verify key fingerprints, etc ssh-keyscan $server | update-known-hosts.sh # get admin user's public key from the server cat << EOF >> /tmp/known-private-key ssh-rsa AAAA.... single-use-key EOF ssh -i /tmp/known-private-key -o "BatchMode on" -T admin@$server | check-key > /home/client/.ssh/authorized_keys chmod 600 /home/client/.ssh/authorized_keys chown client:client /home/client/.ssh/authorized_keys exit 0 So it's the getting that public key out of admin at server's .ssh/id_[dsa|rsa|ecdsa|ed25519].pub that is the hurdle. Can a signed key from a common CA fit in this process somewhere? I do want to avoid forcing a requirement onto our customers to get keys signed by us, or anybody else. > > gert > -- > USENET is *not* the non-clickable part of WWW! > //www.muc.de/~gert/ > Gert Doering - Munich, Germany gert at greenie.muc.de > fax: +49-89-35655025 gert at net.informatik.tu-muenchen.de From djm at mindrot.org Thu Apr 23 11:38:25 2015 From: djm at mindrot.org (Damien Miller) Date: Thu, 23 Apr 2015 11:38:25 +1000 (AEST) Subject: non-openssl build fixes In-Reply-To: References: Message-ID: Thanks! Could I ask you to please create a bug at https://bugzilla.mindrot.org and attach the patches to it? -d On Wed, 22 Apr 2015, Reuben Hawkins wrote: > The attached patches fixes and cleans up the build when configured > with --without-openssl. > > Summary: > * Fix KEX_SERVER_ENCRYPT macro in myproposal.h > * Fix unresolved symbols in ssh-keygen.c > * Isolate openssl code and extend WITH_OPENSSL wrappers around it > * Make ed25519 default key type in ssh-keygen when configured --without-openssl > From reubenhwk at gmail.com Thu Apr 23 13:49:02 2015 From: reubenhwk at gmail.com (Reuben Hawkins) Date: Wed, 22 Apr 2015 20:49:02 -0700 Subject: non-openssl build fixes In-Reply-To: References: Message-ID: done: bug 2388. On Wed, Apr 22, 2015 at 6:38 PM, Damien Miller wrote: > Thanks! Could I ask you to please create a bug at > https://bugzilla.mindrot.org and attach the patches to it? > > -d > > On Wed, 22 Apr 2015, Reuben Hawkins wrote: > >> The attached patches fixes and cleans up the build when configured >> with --without-openssl. >> >> Summary: >> * Fix KEX_SERVER_ENCRYPT macro in myproposal.h >> * Fix unresolved symbols in ssh-keygen.c >> * Isolate openssl code and extend WITH_OPENSSL wrappers around it >> * Make ed25519 default key type in ssh-keygen when configured --without-openssl >> From gert at greenie.muc.de Thu Apr 23 16:56:23 2015 From: gert at greenie.muc.de (Gert Doering) Date: Thu, 23 Apr 2015 08:56:23 +0200 Subject: shared private key In-Reply-To: References: <5537E08C.4040807@gmail.com> <20150422205348.GN382@greenie.muc.de> Message-ID: <20150423065623.GO382@greenie.muc.de> Hi, On Wed, Apr 22, 2015 at 02:51:02PM -0700, Reuben Hawkins wrote: > Can a signed key from a common CA fit in this process somewhere? I do > want to avoid forcing a requirement onto our customers to get keys > signed by us, or anybody else. "common" = "common to the client and server", no external parties needed. Recent OpenSSH versions can handle signed keys, so if your management system can generate keys for both client and server, and sign them, all the systems know that they all belong to the same management domain - and you could trust all keys signed with a given signature (if I understood that part right, didn't try it yet). Might not fit your need, but worth consideration. gert -- USENET is *not* the non-clickable part of WWW! //www.muc.de/~gert/ Gert Doering - Munich, Germany gert at greenie.muc.de fax: +49-89-35655025 gert at net.informatik.tu-muenchen.de From phil at hands.com Thu Apr 23 18:22:29 2015 From: phil at hands.com (Philip Hands) Date: Thu, 23 Apr 2015 09:22:29 +0100 Subject: shared private key In-Reply-To: References: <5537E08C.4040807@gmail.com> <20150422205348.GN382@greenie.muc.de> Message-ID: <87k2x3ntiy.fsf@hands.com> Reuben Hawkins writes: > On Wed, Apr 22, 2015 at 1:53 PM, Gert Doering wrote: >> Hi, >> >> On Wed, Apr 22, 2015 at 01:26:06PM -0700, Reuben Hawkins wrote: >>> Let me know if I'm missing something. :) >> >> Signed keys from a common CA? > > I don't think the signed key helps in my particular case (I may be > wrong, if so please correct me). > > I'm working on a management application and the next version's big > feature is network security via SSH. My application is actually > backwards from most other client/server models. It's backwards in > that the "server" initiates connections to the "clients" (so the ssh > client runs on the "server", sshd on the "clients") to make the > clients do things (let's just say run updates as an example). I need > to get the server user's public key into the client's authorized_keys > file when the client software is installed. I can't think of a way to > get the public key from the server other than the private key > hardcoded into the installer and the corresponding hardcoded public > key in the server's authorized_keys file like this... > command="cat ~/.ssh/id_rsa.pub",other-safty-restrictions ssh-rsa AAAA.... > > With this anybody can get the server user's public key. I think you need to describe what you're after in terms of which group is meant to be generating keys, and what those keys are supposed to be trusted to do once everything's running. Is the key that you're interested in transfering being generated by the competent people in this arangement, or by the unskilled customers? If the key is being generated by the machine belonging to the unskilled customer, then I understand your problem, and the reason for the solution, but I'm not quite sure. It sounds like you have a key on an administration server that you want to get to the boxes being administrated. I presume that the people running the admin server can be expected to be a bit more capable? Is there any reason why you cannot simply ship the authorized_keys file with your software? Perhaps GPG signed? Or publish the GPG signed authorized_keys file on your web site? BTW For the case where the clients want to only offer access when they feel like it, rather than letting a cron job on the admin-server in whenever it feels like it, you could try not having keys on the server, and instead use agent forwarding such that the clients only trust a key they generated themselves, which they keep to themselves, as described in the example here: http://wiki.hands.com/howto/passphraseless-ssh/ HTH Cheers, Phil. -- |)| Philip Hands [+44 (0)20 8530 9560] HANDS.COM Ltd. |-| http://www.hands.com/ http://ftp.uk.debian.org/ |(| Hugo-Klemm-Strasse 34, 21075 Hamburg, GERMANY -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 818 bytes Desc: not available URL: From dsavints at gmail.com Thu Apr 23 19:22:44 2015 From: dsavints at gmail.com (Dmitry Savintsev) Date: Thu, 23 Apr 2015 11:22:44 +0200 Subject: double length prefix in ssh-keygen certificates (values of critical options) Message-ID: Hi, I have a question regarding the binary format of the certificates generated with ssh-keygen, in particular when the critical options of source-address or force-command are present and the correspondence to the certificate format specifications such as http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD . It appears that the string values of the source-address and force-command are prepended with *two* length offsets - 4-byte offset with the integer value of len(string)+4 followed by the 4-byte offset with the proper length, and then the string. Is it a correct behavior? I could not find anything in the spec that would prescribe such double-prefixing, or any description of why of all the strings it is done only for the values of critical options (not the labels etc.) The "Critical Options" section of the PROTOCOL.certkeys (referenced above) says only the following about the format for those options: string name string data so I would expect the "normal" string serialization for both name (label) and the data (actual value). There is also no list or multiple string values involved - both the source-address and force-command are singe "flat" strings (source-address can have multiple IPs but they are comma-separated inside of the same string). Could it be a bug in ssh-keygen? When I generate certificates that include such options - for example, with "ssh-keygen -s ... -O source-address=10.78.72.0/29 -O force-command=/tmp/foobar" and then decode the generated certificate (awk '{print $2}' filename-cert.pub | base64 -D | hexdump -C ) I get the following relevant snippet of the dump: 00000190 00 00 00 27 00 00 00 0e 73 6f 75 72 63 65 2d 61 |...'....source-a| 000001a0 64 64 72 65 73 73 *00 00 00 11 00 00 00 0d *31 30 |ddress........10| 000001b0 2e 37 38 2e 37 32 2e 30 2f 32 39 00 00 00 82 00 |.78.72.0/29.....| highlighted is the double-prefix in question: 00 00 00 11 00 00 00 0d The same happens with the force-command value. This apparent deviation (unless I misread the spec, of course!) creates problems in terms of interoperability with other tools. Go ssh library ( https://godoc.org/golang.org/x/crypto/ssh), for example, does not do the "double-wrapping", and as a result, you cannot read the certificates generated with Go using ssh-keygen -L -f . ssh-keygen tries to read the first 4 bytes of the string value as the second length offset and of course things quickly go south. Here's a hexdump of the certificate generated with Go around the critical options section: 00000180 00 00 00 00 00 00 32 00 00 00 00 00 00 00 64 00 |......2.......d.| 00000190 00 00 43 00 00 00 0d 66 6f 72 63 65 2d 63 6f 6d |..C....force-com| 000001a0 6d 61 6e 64 *00 00 00 0b* 2f 74 6d 70 2f 66 6f 6f |mand..../tmp/foo| 000001b0 62 61 72 00 00 00 0e 73 6f 75 72 63 65 2d 61 64 |bar....source-ad| 000001c0 64 72 65 73 73 00 00 00 0d 31 30 2e 37 38 2e 37 |dress....10.78.7| 000001d0 32 2e 30 2f 32 39 00 00 00 16 00 00 00 0e 70 65 |2.0/29........pe| - so before the value of force-command, there is a single length offset 00 00 00 0b, and before the IP address - a single length offset: 00 00 00 0d ssh-keygen -L on such a Go-generated certificate gives the following error: Critical Options: buffer_get_string_ret: bad string length 796159344 buffer_get_string: buffer error The "bad string length" is easily explained - the decimal 796159344 is 0x2f746d70 which comes from the bytes 2f 74 6d 70 - "*/tmp*" in the "/tmp/foobar" string value of the force-command critical option. If I hack the Go ssh library to add an extra prefix with length+4 value, then ssh-keygen -L is happy again. Let me know if you agree that it is a bug in ssh-keygen, I'll be happy to open a Bugzilla ticket. Thanks, Dmitry From dsavints at gmail.com Thu Apr 23 23:10:59 2015 From: dsavints at gmail.com (Dmitry Savintsev) Date: Thu, 23 Apr 2015 15:10:59 +0200 Subject: double length prefix in ssh-keygen certificates (values of critical options) In-Reply-To: References: Message-ID: I believe the double-prefixing in ssh-keygen.c in the add_string_option function: cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ssh-keygen.c?annotate=1.269 1453: static void 1454: add_string_option(struct sshbuf *c, const char *name, const char *value) 1455: { 1456: struct sshbuf *b; 1457: int r; 1458: 1459: debug3("%s: %s=%s", __func__, name, value); 1460: if ((b = sshbuf_new()) == NULL) 1461: fatal("%s: sshbuf_new failed", __func__); 1462: if ((r = *sshbuf_put_cstring(b, value))* != 0 || 1463: (r = sshbuf_put_cstring(c, name)) != 0 || 1464: (r = *sshbuf_put_stringb(c, b)*) != 0) 1465: fatal("%s: buffer error: %s", __func__, ssh_err(r)); First time the value is length-prefixed with the sshbuf_put_cstring call (line 1462), and then the result ("b") is sent to sshbuf_put_stringb (line 1464) which treats b (that already has the length prefix) as a string and prepends the second length field. The unwrapping of the double length prefix is done in the show_options function (from line 1795 of ssh-keygen.c). The first length prefix is "eaten up" by the sshbuf_froms(options, &option) call on line 1807 in: 1806: if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 || 1807: (r = *sshbuf_froms(options, &option)*) != 0) and the second one processed by sshbuf_get_cstring(option, &arg, NULL) a few lines later (notice that the option structure that was the destination on line 1807 becomes the source on line 1820): 1817: else if ((v00 || in_critical) && 1818: (strcmp(name, "force-command") == 0 || 1819: strcmp(name, "source-address") == 0)) { 1820: if ((r = *sshbuf_get_cstring(option, &arg, NULL)*) != 0) 1821: fatal("%s: buffer error: %s", 1822: __func__, ssh_err(r)); 1823: printf(" %s\n", arg); On Thu, Apr 23, 2015 at 11:22 AM, Dmitry Savintsev wrote: > Hi, > > I have a question regarding the binary format of the certificates > generated with ssh-keygen, in particular when the critical options of > source-address or force-command are present and the correspondence to the > certificate format specifications such as > http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD > . > > It appears that the string values of the source-address and force-command > are prepended with *two* length offsets - 4-byte offset with the integer > value of len(string)+4 followed by the 4-byte offset with the proper > length, and then the string. Is it a correct behavior? I could not find > anything in the spec that would prescribe such double-prefixing, or any > description of why of all the strings it is done only for the values of > critical options (not the labels etc.) The "Critical Options" section of > the PROTOCOL.certkeys (referenced above) says only the following about the > format for those options: > string name > string data > > so I would expect the "normal" string serialization for both name (label) > and the data (actual value). There is also no list or multiple string > values involved - both the source-address and force-command are singe > "flat" strings (source-address can have multiple IPs but they are > comma-separated inside of the same string). > > Could it be a bug in ssh-keygen? > > When I generate certificates that include such options - for example, with > "ssh-keygen -s ... -O source-address=10.78.72.0/29 -O > force-command=/tmp/foobar" and then decode the generated certificate (awk > '{print $2}' filename-cert.pub | base64 -D | hexdump -C ) > I get the following relevant snippet of the dump: > > 00000190 00 00 00 27 00 00 00 0e 73 6f 75 72 63 65 2d 61 > |...'....source-a| > 000001a0 64 64 72 65 73 73 *00 00 00 11 00 00 00 0d *31 30 > |ddress........10| > 000001b0 2e 37 38 2e 37 32 2e 30 2f 32 39 00 00 00 82 00 > |.78.72.0/29.....| > > highlighted is the double-prefix in question: 00 00 00 11 00 00 00 0d > > The same happens with the force-command value. > > This apparent deviation (unless I misread the spec, of course!) creates > problems in terms of interoperability with other tools. Go ssh library ( > https://godoc.org/golang.org/x/crypto/ssh), for example, does not do the > "double-wrapping", and as a result, you cannot read the certificates > generated with Go using ssh-keygen -L -f . ssh-keygen tries to > read the first 4 bytes of the string value as the second length offset and > of course things quickly go south. Here's a hexdump of the certificate > generated with Go around the critical options section: > 00000180 00 00 00 00 00 00 32 00 00 00 00 00 00 00 64 00 > |......2.......d.| > 00000190 00 00 43 00 00 00 0d 66 6f 72 63 65 2d 63 6f 6d > |..C....force-com| > 000001a0 6d 61 6e 64 *00 00 00 0b* 2f 74 6d 70 2f 66 6f 6f > |mand..../tmp/foo| > 000001b0 62 61 72 00 00 00 0e 73 6f 75 72 63 65 2d 61 64 > |bar....source-ad| > 000001c0 64 72 65 73 73 00 00 00 0d 31 30 2e 37 38 2e 37 > |dress....10.78.7| > 000001d0 32 2e 30 2f 32 39 00 00 00 16 00 00 00 0e 70 65 > |2.0/29........pe| > > - so before the value of force-command, there is a single length offset 00 > 00 00 0b, and before the IP address - a single length offset: 00 00 00 0d > > ssh-keygen -L on such a Go-generated certificate gives the following error: > Critical Options: > buffer_get_string_ret: bad string length 796159344 > buffer_get_string: buffer error > > The "bad string length" is easily explained - the decimal 796159344 is > 0x2f746d70 which comes from the bytes 2f 74 6d 70 - "*/tmp*" in the > "/tmp/foobar" string value of the force-command critical option. If I hack > the Go ssh library to add an extra prefix with length+4 value, then > ssh-keygen -L is happy again. > > Let me know if you agree that it is a bug in ssh-keygen, I'll be happy to > open a Bugzilla ticket. > > Thanks, > > Dmitry > > > > From reubenhwk at gmail.com Fri Apr 24 01:18:41 2015 From: reubenhwk at gmail.com (Reuben Hawkins) Date: Thu, 23 Apr 2015 08:18:41 -0700 Subject: shared private key In-Reply-To: <87k2x3ntiy.fsf@hands.com> References: <5537E08C.4040807@gmail.com> <20150422205348.GN382@greenie.muc.de> <87k2x3ntiy.fsf@hands.com> Message-ID: On Thu, Apr 23, 2015 at 1:22 AM, Philip Hands wrote: > Reuben Hawkins writes: > >> On Wed, Apr 22, 2015 at 1:53 PM, Gert Doering wrote: >>> Hi, >>> >>> On Wed, Apr 22, 2015 at 01:26:06PM -0700, Reuben Hawkins wrote: >>>> Let me know if I'm missing something. :) >>> >>> Signed keys from a common CA? >> >> I don't think the signed key helps in my particular case (I may be >> wrong, if so please correct me). >> >> I'm working on a management application and the next version's big >> feature is network security via SSH. My application is actually >> backwards from most other client/server models. It's backwards in >> that the "server" initiates connections to the "clients" (so the ssh >> client runs on the "server", sshd on the "clients") to make the >> clients do things (let's just say run updates as an example). I need >> to get the server user's public key into the client's authorized_keys >> file when the client software is installed. I can't think of a way to >> get the public key from the server other than the private key >> hardcoded into the installer and the corresponding hardcoded public >> key in the server's authorized_keys file like this... > >> command="cat ~/.ssh/id_rsa.pub",other-safty-restrictions ssh-rsa AAAA.... >> >> With this anybody can get the server user's public key. > > I think you need to describe what you're after in terms of which group > is meant to be generating keys, and what those keys are supposed to be > trusted to do once everything's running. Installers will generate keys when the software is installed. A user account will be created for the software (like admin-data, similar to www-data for Apache). Administration server is going to periodically regenerate keys for itself and for the clients according to NIST recommendations. They keys on the client will be trusted mainly to run backup jobs. The user accounts will all be fairly unprivileged, and the backup binary is setuid. > > Is the key that you're interested in transfering being generated by the > competent people in this arangement, or by the unskilled customers? The skill level of the customers is a fairly wide range. Some of them would know exactly how to do this and other had never heard of SSH. I'll be generating all the keys for them in the installer script. They'll have the option to regenerate keys for a host in the admin user interface, and the admin will periodically (maybe one a year) regenerate keys. > > If the key is being generated by the machine belonging to the unskilled > customer, then I understand your problem, and the reason for the > solution, but I'm not quite sure. > > It sounds like you have a key on an administration server that you want > to get to the boxes being administrated. I presume that the people > running the admin server can be expected to be a bit more capable? I generally assume the people running the admin server will be more capable than the ones installing the clients, but it also can sometimes be the same person. It also may be different people in different companies. So ssh-copy-id may not be an option because neither company will want to give password access to the other. To work around requiring password access, I'm attempting a solution where they can just swap public keys on demand and examine the key fingerprints and optionally reject the public key if it fingerprints dont look right. > > Is there any reason why you cannot simply ship the authorized_keys file > with your software? Perhaps GPG signed? Or publish the GPG signed > authorized_keys file on your web site? I think I can't do that. The authorized_keys file needs to only allow access to one specific administrator machine, so the client installer asks for the url/hostname/ip/whatever of the admin machine, then goes and gets the admin-data user's public key (from admin-data at admin.example.com:.ssh/id_[rsa|ecdsa|ed25519].pub). There's also going to be a second key hardcoded into the installer which will allow the clients to push the /etc/ssh/host_keys to the admin into a holding area. The admin will get a notice that there are pending keys needing approval. The approval script will show the key fingerprints, and the admin person will either accept the keys (which get added to the known hosts for the admin user), or reject the keys. something like this on the admin... command="receive-key" ssh-rsa AAAAA... The receive-key is a binary which parses the keys to ensure nothing fishy is being uploaded to the pending key directory. The filename is a hash of the key value (the AAAA... string) so uploading a key multiple times only writes to one file. The comment in the key is updated with info like $(date), the $SSH_CONNECTION, etc. So the security of it all depends on command= and a person looking at key fingerprints. Maybe this can be improved with signed keys, but I haven't managed to wrap my head around that yet. For the clients, and maybe the administrator machine, the keys are generated at install time, so there isn't much opportunity to sign the keys. I don't want to require our customers to send their keys to us to be signed. > > BTW For the case where the clients want to only offer access when they > feel like it, rather than letting a cron job on the admin-server in > whenever it feels like it, you could try not having keys on the server, > and instead use agent forwarding such that the clients only trust a key > they generated themselves, which they keep to themselves, as described > in the example here: > > http://wiki.hands.com/howto/passphraseless-ssh/ This is an excellent read! Thanks! :) > > HTH > > Cheers, Phil. > -- > |)| Philip Hands [+44 (0)20 8530 9560] HANDS.COM Ltd. > |-| http://www.hands.com/ http://ftp.uk.debian.org/ > |(| Hugo-Klemm-Strasse 34, 21075 Hamburg, GERMANY From openssh at tlinx.org Fri Apr 24 07:40:11 2015 From: openssh at tlinx.org (L. A. Walsh) Date: Thu, 23 Apr 2015 14:40:11 -0700 Subject: KEEPALIVE timeout? default taken from server, or other? length settable? Message-ID: <553966BB.8050803@tlinx.org> I see options for turning keepalive on or off, in both the server and client config files. Does one or the other take precendence? If it is "on", does it use the OS's default values? Or, if not, are the values settable? I am running a win-client to OpenSuse/linux server that has a default TCP_KEEPALIVE set to the linux default of 2 hours. I don't know if the Win client has its own KEEPALIVE value (or where I'd set it). Either way, is there a way to change the default value? Right now, from the docs (6.2p2-3.1.2.x86_64), it looks like if I turn off keepalive on Clnt+Serv, then the default on the server would be used (2 hours?) -- or would some default on Windows kill it sooner? (which is why I want to find out if there are KeepAlive vals on both ends -- and if so, how to change them globally and/or per openssh-config). Thanks! From dtucker at zip.com.au Fri Apr 24 09:55:19 2015 From: dtucker at zip.com.au (Darren Tucker) Date: Fri, 24 Apr 2015 09:55:19 +1000 Subject: KEEPALIVE timeout? default taken from server, or other? length settable? In-Reply-To: <553966BB.8050803@tlinx.org> References: <553966BB.8050803@tlinx.org> Message-ID: On Fri, Apr 24, 2015 at 7:40 AM, L. A. Walsh wrote: > > I see options for turning keepalive on or off, in both > the server and client config files. > There are 2 types of keepalives: the TCP level one (TCPKeepAlive) and application level keepalives (ServerAliveInterval+ServerAliveCountMax in the client, ClientAliveInterval+ClientAliveCountMax). Does one or the other take precendence? > The're independent. If they're enabled on a particular end then it'll send the keepalive and act on the presence (or not) of the response from the other end. > If it is "on", does it use the OS's default values? > TCPKeepAlive: yes. The others: no. Or, if not, are the values settable? > TCPKeepAlive: it's a system-wide setting. The others: yes. > I am running a win-client to OpenSuse/linux server that > has a default TCP_KEEPALIVE set to the linux default of 2 hours. > On Linux that's usually the net.ipv4.tcp_keepalive_time sysctl or maybe the equivalent under /proc or /sys. > I don't know if the Win client has its own KEEPALIVE value > (or where I'd set it). Either way, is there a way to change the default value? > > Right now, from the docs (6.2p2-3.1.2.x86_64), it looks > like if I turn off keepalive on Clnt+Serv, then the default on > the server would be used (2 hours?) -- or would some default > on Windows kill it sooner? > That's a question for the author of the client software. > (which is why I want to find out if there are KeepAlive vals > on both ends -- and if so, how to change them globally and/or > per openssh-config). > -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. From djm at mindrot.org Fri Apr 24 16:11:49 2015 From: djm at mindrot.org (Damien Miller) Date: Fri, 24 Apr 2015 16:11:49 +1000 (AEST) Subject: double length prefix in ssh-keygen certificates (values of critical options) In-Reply-To: References: Message-ID: On Thu, 23 Apr 2015, Dmitry Savintsev wrote: > Hi, > > I have a question regarding the binary format of the certificates generated > with ssh-keygen, in particular when the critical options of source-address > or force-command are present and the correspondence to the certificate > format specifications such as > http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD > . > > It appears that the string values of the source-address and force-command > are prepended with *two* length offsets - 4-byte offset with the integer > value of len(string)+4 followed by the 4-byte offset with the proper > length, and then the string. Is it a correct behavior? Yes, as per PROTOCOL.certkeys: > The critical options section of the certificate specifies zero or more > options on the certificates validity. The format of this field > is a sequence of zero or more tuples: > > string name > string data So that's the first header for the data. You then have to look at the table to determine the format of data's contents. E.g. > force-command string Specifies a command that is executed ... So, for name=force-command, the contents of the data buffer are a string. That's the second header. The intent is to support options/extensions with data types other than string, e.g. integers or arrays of string. > This apparent deviation (unless I misread the spec, of course!) creates > problems in terms of interoperability with other tools. Go ssh library ( > https://godoc.org/golang.org/x/crypto/ssh), for example, does not do the > "double-wrapping", and as a result, you cannot read the certificates > generated with Go using ssh-keygen -L -f . ssh-keygen tries to > read the first 4 bytes of the string value as the second length offset and > of course things quickly go south. Here's a hexdump of the certificate > generated with Go around the critical options section. Go's implementation is incorrect here. Maybe the wording of PROTOCOL.certkeys could be improved to avoid the confusion, but I'm surprised the Go SSH developers didn't check against what OpenSSH actually generates (or ask if in doubt). -d From dsavints at gmail.com Fri Apr 24 19:57:19 2015 From: dsavints at gmail.com (Dmitry Savintsev) Date: Fri, 24 Apr 2015 11:57:19 +0200 Subject: double length prefix in ssh-keygen certificates (values of critical options) In-Reply-To: References: Message-ID: Thanks Damien for your response and explanations - I opened https://bugzilla.mindrot.org/show_bug.cgi?id=2389 to improve the wording the PROTOCOL.certkeys spec. Currently reading that the format the critical options field is a sequence of tuples: > > string name > string data I would expect both fields to have the same encoding since they have the same type "string" (and also by analogy with multiple other string fields in the specification). Do you think it would be worth to give the second field of the tuple some other type like "object" or "composite" or string[] - especially since you say the intent is to support "data types other than string, e.g. integers or arrays of string"? http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD&content-type=text/x-cvsweb-markup uses the type string[] for the list of strings (as in: " string[] hostkeys") which makes it clear that the field has different semantics and encoding than a "plain" string one. I opened an issue for Go's crypto/ssh library: https://github.com/golang/go/issues/10569 Thanks, Dmitry On Fri, Apr 24, 2015 at 8:11 AM, Damien Miller wrote: > On Thu, 23 Apr 2015, Dmitry Savintsev wrote: > > > Hi, > > > > I have a question regarding the binary format of the certificates > generated > > with ssh-keygen, in particular when the critical options of > source-address > > or force-command are present and the correspondence to the certificate > > format specifications such as > > > http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD > > . > > > > It appears that the string values of the source-address and force-command > > are prepended with *two* length offsets - 4-byte offset with the integer > > value of len(string)+4 followed by the 4-byte offset with the proper > > length, and then the string. Is it a correct behavior? > > Yes, as per PROTOCOL.certkeys: > > > The critical options section of the certificate specifies zero or more > > options on the certificates validity. The format of this field > > is a sequence of zero or more tuples: > > > > string name > > string data > > So that's the first header for the data. You then have to look at the > table to determine the format of data's contents. E.g. > > > force-command string Specifies a command that is > executed > ... > > So, for name=force-command, the contents of the data buffer are a string. > That's the second header. > > The intent is to support options/extensions with data types other > than string, e.g. integers or arrays of string. > > > This apparent deviation (unless I misread the spec, of course!) creates > > problems in terms of interoperability with other tools. Go ssh library ( > > https://godoc.org/golang.org/x/crypto/ssh), for example, does not do the > > "double-wrapping", and as a result, you cannot read the certificates > > generated with Go using ssh-keygen -L -f . ssh-keygen tries to > > read the first 4 bytes of the string value as the second length offset > and > > of course things quickly go south. Here's a hexdump of the certificate > > generated with Go around the critical options section. > > Go's implementation is incorrect here. > > Maybe the wording of PROTOCOL.certkeys could be improved to avoid > the confusion, but I'm surprised the Go SSH developers didn't check > against what OpenSSH actually generates (or ask if in doubt). > > -d > From porten at froglogic.com Fri Apr 24 21:06:06 2015 From: porten at froglogic.com (Harri Porten) Date: Fri, 24 Apr 2015 13:06:06 +0200 (CEST) Subject: Test coverage results available online Message-ID: Dear OpenSHH developers, in case this helps with your testing efforts: At http://www.opencoverage.net/projects/openssh/index_html/sources.html you'll find an overview of the condition/decision code coverage as achieved through a run of the test suite. The state last used is from the git master branch commit 70860b6. You might find the total coverage 27.8% to be much lower than what you've seen before. Main reason is the use of the condition/decision metric which is more ambitious than plain branch or line coverage. It requires testing of more input combinations to achieve a higher level. On the positive side chances of missing out a bug decrease. Known and potential issues: - Some statements are flagged as dead (unreachable) code which might be fine according to the project's coding style. Like a 'break' after a 'goto'. - The code configuration or test execution setup might be non-optimal and have some features or tests disabled. Todos: - Improve the test execution name to be more meaningful than just 'ssh (33)'. - Filter out false negatives like above cases of dead code. If you have any questions about the results, see a problem, or have a suggestion just let me know. While the analysis of Open Source projects started as an internal dogfooding project for our company's tool Squish Coco we also hope to contribute something back to the quality of software we all rely on. Harri.