From 5f7c84f900b81e3bbff55378f8170ddf150daf9c Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Tue, 4 Oct 2005 22:11:19 +0000 Subject: added the gcrypt patch (without gcrypt as default library). still needs tests. git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@38 7dcaeef0-15fb-0310-b436-a5af3365683c --- libssh/auth.c | 2 + libssh/auth1.c | 3 +- libssh/base64.c | 6 +- libssh/buffer.c | 2 +- libssh/channels.c | 30 +++- libssh/client.c | 7 + libssh/connect.c | 64 +++---- libssh/crypt.c | 28 ++- libssh/dh.c | 169 ++++++++++++++---- libssh/gzip.c | 1 + libssh/kex.c | 13 +- libssh/keyfiles.c | 484 +++++++++++++++++++++++++++++++++++++++++++++++++++- libssh/keys.c | 313 ++++++++++++++++++++++++++++++--- libssh/messages.c | 1 + libssh/packet.c | 6 +- libssh/server.c | 2 +- libssh/session.c | 1 + libssh/sftp.c | 1 + libssh/sftpserver.c | 1 + libssh/string.c | 2 +- libssh/wrapper.c | 218 ++++++++++++++++++++--- 21 files changed, 1213 insertions(+), 141 deletions(-) (limited to 'libssh') diff --git a/libssh/auth.c b/libssh/auth.c index 938dff6b..12b90bf4 100644 --- a/libssh/auth.c +++ b/libssh/auth.c @@ -21,6 +21,8 @@ MA 02111-1307, USA. */ #include "libssh/priv.h" #include "libssh/ssh2.h" +#include +#include #include #include diff --git a/libssh/auth1.c b/libssh/auth1.c index 65fc9058..40cccda1 100644 --- a/libssh/auth1.c +++ b/libssh/auth1.c @@ -23,6 +23,7 @@ MA 02111-1307, USA. */ #include "libssh/ssh1.h" #include #include +#include /* static void burn(char *ptr){ @@ -187,7 +188,7 @@ int ssh_userauth1_password(SSH_SESSION *session,char *username,char *password){ */ password_s=string_new(128); ssh_get_random(password_s->string,128,0); - strcpy(password_s->string,password); + strcpy((char *)password_s->string,password); } packet_clear_out(session); diff --git a/libssh/base64.c b/libssh/base64.c index 1f0b415d..f16be600 100644 --- a/libssh/base64.c +++ b/libssh/base64.c @@ -193,10 +193,10 @@ static void _bin_to_base64(unsigned char *dest, unsigned char source[3], int len } } -char *bin_to_base64(unsigned char *source, int len){ +unsigned char *bin_to_base64(unsigned char *source, int len){ int flen=len + (3 - (len %3)); /* round to upper 3 multiple */ - char *buffer; - char *ptr; + unsigned char *buffer; + unsigned char *ptr; flen=(4 * flen)/3 + 1 ; ptr=buffer=malloc(flen); while(len>0){ diff --git a/libssh/buffer.c b/libssh/buffer.c index b511a8cd..9cdf8599 100644 --- a/libssh/buffer.c +++ b/libssh/buffer.c @@ -150,7 +150,7 @@ STRING *buffer_get_ssh_string(BUFFER *buffer){ hostlen=ntohl(stringlen); /* verify if there is enough space in buffer to get it */ if(buffer->pos+hostlen>buffer->used) - return 0; /* it is indeed */ + return NULL; /* it is indeed */ str=string_new(hostlen); if(buffer_get_data(buffer,str->string,hostlen)!=hostlen){ ssh_say(0,"buffer_get_ssh_string: oddish : second test failed when first was successful. len=%d",hostlen); diff --git a/libssh/channels.c b/libssh/channels.c index 31586314..8a0b1fa1 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -661,18 +661,20 @@ int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){ /* returns the number of bytes available, 0 if nothing is currently available, -1 if error */ int channel_poll(CHANNEL *channel, int is_stderr){ BUFFER *buffer; + int r=0,w=0,err=0; if(is_stderr) buffer=channel->stderr_buffer; else buffer=channel->stdout_buffer; while(buffer_get_rest_len(buffer)==0 && !channel->remote_eof){ - if(ssh_fd_poll(channel->session)){ - if(packet_read(channel->session)||packet_translate(channel->session)) - return -1; - packet_parse(channel->session); - } else - return 0; /* nothing is available has said fd_poll */ + r=ssh_fd_poll(channel->session,&w,&err); + if(r<=0) + return r; // error or no data available + /* if an exception happened, it will be trapped by packet_read() */ + if(packet_read(channel->session)||packet_translate(channel->session)) + return -1; + packet_parse(channel->session); } if(channel->remote_eof) return 1; @@ -700,4 +702,18 @@ int channel_read_nonblocking(CHANNEL *channel, char *dest, int len, int is_stder SSH_SESSION *channel_get_session(CHANNEL *channel){ return channel->session; } - +/* +int channel_select(CHANNEL *readchans, CHANNEL *writechans, CHANNEL *exceptchans, struct + timeval * timeout){ + fd_set rset; + fd_set wset; + fd_set eset; + int rmax=-1, wmax=-1, emax=-1; // nothing to do with the low quality editor :) + int i; + FD_ZERO(rset); + FD_ZERO(wset); + FD_ZERO(eset); + for(i=0;readchans[i];++i){ + if(!readchans[i]. + +*/ \ No newline at end of file diff --git a/libssh/client.c b/libssh/client.c index 42b10414..1ca8952d 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -26,6 +26,7 @@ MA 02111-1307, USA. */ #include #include "libssh/priv.h" #include "libssh/ssh2.h" +extern int connections; #define set_status(opt,status) do {\ if (opt->connect_status_function) \ @@ -277,6 +278,12 @@ void ssh_disconnect(SSH_SESSION *session){ } session->alive=0; ssh_cleanup(session); + if (!--connections) +#ifdef HAVE_LIBGCRYPT + gcry_control(GCRYCTL_TERM_SECMEM); +#elif defined HAVE_LIBCRYPTO + EVP_cleanup(); +#endif } const char *ssh_copyright(){ diff --git a/libssh/connect.c b/libssh/connect.c index ccb704ff..d1e8bf59 100644 --- a/libssh/connect.c +++ b/libssh/connect.c @@ -32,15 +32,16 @@ MA 02111-1307, USA. */ #include #include #include "libssh/priv.h" -#ifdef HAVE_SYS_POLL_H -#include -#endif #ifndef HAVE_GETHOSTBYNAME #ifndef HAVE_GETHOSTBYADDR #error "your system doesn't have gethostbyname nor gethostbyaddr" #endif #endif +#ifndef HAVE_SELECT +#error "Your system must have select()" +#endif + static void sock_set_nonblocking(int sock) { fcntl(sock,F_SETFL,O_NONBLOCK); } @@ -118,7 +119,7 @@ int ssh_connect_host(SSH_SESSION *session, const char *host, const char struct timeval to; fd_set set; int ret=0; - int len=sizeof(ret); + unsigned int len=sizeof(ret); to.tv_sec=timeout; to.tv_usec=usec; sock_set_nonblocking(s); @@ -157,46 +158,45 @@ int ssh_connect_host(SSH_SESSION *session, const char *host, const char return s; } -/* returns 1 if bytes are available on the stream, 0 instead */ -int ssh_fd_poll(SSH_SESSION *session){ -#ifdef HAVE_POLL - struct pollfd fdset; -#else +/* returns 1 if bytes are available to read on the stream, 0 instead */ +/* -1 on select() error. */ +int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){ struct timeval sometime; - fd_set descriptor; -#endif - if(session->data_to_read) - return(session->data_to_read); -#ifdef HAVE_POLL - fdset.fd=session->fd; - fdset.events=POLLHUP|POLLIN|POLLPRI; - fdset.revents=0; - if(poll(&fdset,1,0)==0) + fd_set rdes; // read set + fd_set wdes; // writing set + fd_set edes; // exception set + + FD_ZERO(&rdes); + FD_ZERO(&wdes); + FD_ZERO(&edes); + + if(!session->alive){ + *except=1; + *write=0; return 0; - if(fdset.revents & (POLLHUP|POLLIN|POLLPRI)) - return (session->data_to_read=1); - return 0; -#elif HAVE_SELECT + } + if(!session->data_to_read) + FD_SET(session->fd,&rdes); + if(!session->data_to_write) + FD_SET(session->fd,&wdes); + FD_SET(session->fd,&edes); /* Set to return immediately (no blocking) */ sometime.tv_sec = 0; sometime.tv_usec = 0; - /* Set up descriptor */ - FD_ZERO(&descriptor); - FD_SET(session->fd, &descriptor); - /* Make the call, and listen for errors */ - if (select(session->fd + 1, &descriptor, NULL, NULL, &sometime) < 0) { + if (select(session->fd + 1, &rdes,&wdes,&edes, &sometime) < 0) { ssh_set_error(NULL,SSH_FATAL, "select: %s", strerror(errno)); return -1; } - session->data_to_read=FD_ISSET(session->fd,&descriptor); + if(!session->data_to_read) + session->data_to_read=FD_ISSET(session->fd,&rdes); + if(!session->data_to_write) + session->data_to_write=FD_ISSET(session->fd,&wdes); + *except=FD_ISSET(session->fd,&edes); + *write=session->data_to_write; return session->data_to_read; -#else -#error This system does not have poll() or select(), so ssh_fd_poll() will not work correctly - return 0; -#endif } /* this function is a complete wrapper for the select syscall. it does more than wrapping ... */ diff --git a/libssh/crypt.c b/libssh/crypt.c index 5daab609..e118f6a7 100644 --- a/libssh/crypt.c +++ b/libssh/crypt.c @@ -22,11 +22,14 @@ MA 02111-1307, USA. */ #include #include +#include #include +#ifdef OPENSSL_CRYPTO #include #include #include +#endif #include #include "libssh/priv.h" @@ -45,25 +48,34 @@ int packet_decrypt(SSH_SESSION *session, void *data,u32 len){ struct crypto_struct *crypto=session->current_crypto->in_cipher; char *out=malloc(len); ssh_say(3,"Decrypting %d bytes data\n",len); +#ifdef HAVE_LIBGCRYPT + crypto->set_decrypt_key(crypto,session->current_crypto->decryptkey,session->current_crypto->decryptIV); + crypto->cbc_decrypt(crypto,data,out,len); +#elif defined HAVE_LIBCRYPTO crypto->set_decrypt_key(crypto,session->current_crypto->decryptkey); crypto->cbc_decrypt(crypto,data,out,len,session->current_crypto->decryptIV); +#endif memcpy(data,out,len); memset(out,0,len); free(out); return 0; } -char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){ +unsigned char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){ struct crypto_struct *crypto; - HMAC_CTX *ctx; + HMACCTX ctx; char *out; - int finallen; + unsigned int finallen; u32 seq=ntohl(session->send_seq); if(!session->current_crypto) return NULL; /* nothing to do here */ crypto= session->current_crypto->out_cipher; ssh_say(3,"seq num = %d, len = %d\n",session->send_seq,len); +#ifdef HAVE_LIBGCRYPT + crypto->set_encrypt_key(crypto,session->current_crypto->encryptkey,session->current_crypto->encryptIV); +#elif defined HAVE_LIBCRYPTO crypto->set_encrypt_key(crypto,session->current_crypto->encryptkey); +#endif out=malloc(len); if(session->version==2){ ctx=hmac_init(session->current_crypto->encryptMAC,20,HMAC_SHA1); @@ -77,7 +89,11 @@ char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){ ssh_print_hexa("packet hmac",session->current_crypto->hmacbuf,20); #endif } +#ifdef HAVE_LIBGCRYPT + crypto->cbc_encrypt(crypto,data,out,len); +#elif defined HAVE_LIBCRYPTO crypto->cbc_encrypt(crypto,data,out,len,session->current_crypto->encryptIV); +#endif memcpy(data,out,len); memset(out,0,len); free(out); @@ -87,10 +103,10 @@ char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){ return NULL; } -int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,char *mac){ - HMAC_CTX *ctx; +int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,unsigned char *mac){ + HMACCTX ctx; unsigned char hmacbuf[EVP_MAX_MD_SIZE]; - int len; + unsigned int len; u32 seq=htonl(session->recv_seq); ctx=hmac_init(session->current_crypto->decryptMAC,20,HMAC_SHA1); hmac_update(ctx,(unsigned char *)&seq,sizeof(u32)); diff --git a/libssh/dh.c b/libssh/dh.c index c96c70ac..89fda259 100644 --- a/libssh/dh.c +++ b/libssh/dh.c @@ -42,9 +42,11 @@ MA 02111-1307, USA. */ #include #include "libssh/priv.h" +#ifdef HAVE_LIBCRYPTO #include #include #include +#endif #include #include "libssh/crypto.h" static unsigned char p_value[] = { @@ -65,13 +67,23 @@ static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */ static bignum g; static bignum p; +int connections = 0; + /* maybe it might be enhanced .... */ /* XXX Do it. */ int ssh_get_random(void *where, int len, int strong){ if(strong){ +#ifdef HAVE_LIBGCRYPT + gcry_randomize(where,len,GCRY_VERY_STRONG_RANDOM); + return 1; + } else { + gcry_randomize(where,len,GCRY_STRONG_RANDOM); + return 1; +#elif defined HAVE_LIBCRYPTO return RAND_bytes(where,len); } else { return RAND_pseudo_bytes(where,len); +#endif } } @@ -79,19 +91,39 @@ int ssh_get_random(void *where, int len, int strong){ void ssh_crypto_init(){ static int init=0; if(!init){ +#ifdef HAVE_LIBGCRYPT + gcry_check_version(NULL); +#endif g=bignum_new(); bignum_set_word(g,g_int); +#ifdef HAVE_LIBGCRYPT + bignum_bin2bn(p_value,P_LEN,&p); +#elif defined HAVE_LIBCRYPTO p=bignum_new(); bignum_bin2bn(p_value,P_LEN,p); +#endif init++; } + if (!connections++){ +#ifdef HAVE_LIBGCRYPT + gcry_control(GCRYCTL_INIT_SECMEM,524288,0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED,0); +#elif defined HAVE_LIBCRYPTO + OpenSSL_add_all_algorithms(); +#endif + } } /* prints the bignum on stderr */ void ssh_print_bignum(char *which,bignum num){ +#ifdef HAVE_LIBGCRYPT + unsigned char *hex; + bignum_bn2hex(num,&hex); +#elif defined HAVE_LIBCRYPTO char *hex; - fprintf(stderr,"%s value: ",which); hex=bignum_bn2hex(num); +#endif + fprintf(stderr,"%s value: ",which); fprintf(stderr,"%s\n",hex); free(hex); } @@ -111,7 +143,11 @@ void ssh_print_hexa(char *descr,unsigned char *what, int len){ void dh_generate_x(SSH_SESSION *session){ session->next_crypto->x=bignum_new(); +#ifdef HAVE_LIBGCRYPT + bignum_rand(session->next_crypto->x,128); +#elif defined HAVE_LIBCRYPTO bignum_rand(session->next_crypto->x,128,0,-1); +#endif /* not harder than this */ #ifdef DEBUG_CRYPTO ssh_print_bignum("x",session->next_crypto->x); @@ -120,7 +156,11 @@ void dh_generate_x(SSH_SESSION *session){ /* used by server */ void dh_generate_y(SSH_SESSION *session){ session->next_crypto->y=bignum_new(); +#ifdef HAVE_LIBGCRYPT + bignum_rand(session->next_crypto->y,128); +#elif defined HAVE_LIBCRYPTO bignum_rand(session->next_crypto->y,128,0,-1); +#endif /* not harder than this */ #ifdef DEBUG_CRYPTO ssh_print_bignum("y",session->next_crypto->y); @@ -128,31 +168,46 @@ void dh_generate_y(SSH_SESSION *session){ } /* used by server */ void dh_generate_e(SSH_SESSION *session){ +#ifdef HAVE_LIBCRYPTO bignum_CTX ctx=bignum_ctx_new(); +#endif session->next_crypto->e=bignum_new(); +#ifdef HAVE_LIBGCRYPT + bignum_mod_exp(session->next_crypto->e,g,session->next_crypto->x,p); +#elif defined HAVE_LIBCRYPTO bignum_mod_exp(session->next_crypto->e,g,session->next_crypto->x,p,ctx); +#endif #ifdef DEBUG_CRYPTO ssh_print_bignum("e",session->next_crypto->e); #endif +#ifdef HAVE_LIBCRYPTO bignum_ctx_free(ctx); +#endif } void dh_generate_f(SSH_SESSION *session){ +#ifdef HAVE_LIBCRYPTO bignum_CTX ctx=bignum_ctx_new(); +#endif session->next_crypto->f=bignum_new(); +#ifdef HAVE_LIBGCRYPT + bignum_mod_exp(session->next_crypto->f,g,session->next_crypto->y,p); +#elif defined HAVE_LIBCRYPTO bignum_mod_exp(session->next_crypto->f,g,session->next_crypto->y,p,ctx); +#endif #ifdef DEBUG_CRYPTO ssh_print_bignum("f",session->next_crypto->f); #endif +#ifdef HAVE_LIBCRYPTO bignum_ctx_free(ctx); +#endif } STRING *make_bignum_string(bignum num){ STRING *ptr; int pad=0; - int len=bignum_num_bytes(num); - int bits=bignum_num_bits(num); - int finallen; + unsigned int len=bignum_num_bytes(num); + unsigned int bits=bignum_num_bits(num); /* remember if the fist bit is set, it is considered as a negative number. so 0's must be appended */ if(!(bits%8) && bignum_is_bit_set(num,bits-1)) pad++; @@ -161,14 +216,24 @@ STRING *make_bignum_string(bignum num){ ptr->size=htonl(len+pad); if(pad) ptr->string[0]=0; - finallen=bignum_bn2bin(num,ptr->string+pad); +#ifdef HAVE_LIBGCRYPT + bignum_bn2bin(num,len,ptr->string+pad); +#elif HAVE_LIBCRYPTO + bignum_bn2bin(num,ptr->string+pad); +#endif return ptr; } bignum make_string_bn(STRING *string){ - int len=ntohl(string->size); + bignum bn; + unsigned int len=string_len(string); ssh_say(3,"Importing a %d bits,%d bytes object ...\n",len*8,len); - return bignum_bin2bn(string->string,len,NULL); +#ifdef HAVE_LIBGCRYPT + bignum_bin2bn(string->string,len,&bn); +#elif defined HAVE_LIBCRYPTO + bn=bignum_bin2bn(string->string,len,NULL); +#endif + return bn; } STRING *dh_get_e(SSH_SESSION *session){ @@ -200,21 +265,33 @@ void dh_import_e(SSH_SESSION *session, STRING *e_string){ } void dh_build_k(SSH_SESSION *session){ +#ifdef HAVE_LIBCRYPTO bignum_CTX ctx=bignum_ctx_new(); +#endif session->next_crypto->k=bignum_new(); /* the server and clients don't use the same numbers */ +#ifdef HAVE_LIBGCRYPT + if(session->client){ + bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p); + } else { + bignum_mod_exp(session->next_crypto->k,session->next_crypto->e,session->next_crypto->y,p); + } +#elif defined HAVE_LIBCRYPTO if(session->client){ bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p,ctx); } else { bignum_mod_exp(session->next_crypto->k,session->next_crypto->e,session->next_crypto->y,p,ctx); } +#endif #ifdef DEBUG_CRYPTO ssh_print_bignum("shared secret key",session->next_crypto->k); #endif +#ifdef HAVE_LIBCRYPTO bignum_ctx_free(ctx); +#endif } /* -static void sha_add(STRING *str,SHACTX *ctx){ +static void sha_add(STRING *str,SHACTX ctx){ sha1_update(ctx,str,string_len(str)+4); #ifdef DEBUG_CRYPTO ssh_print_hexa("partial hashed sessionid",str,string_len(str)+4); @@ -222,7 +299,7 @@ static void sha_add(STRING *str,SHACTX *ctx){ } */ void make_sessionid(SSH_SESSION *session){ - SHACTX *ctx; + SHACTX ctx; STRING *num,*str; BUFFER *server_hash, *client_hash; BUFFER *buf=buffer_new(); @@ -294,7 +371,7 @@ void make_sessionid(SSH_SESSION *session){ buffer_free(buf); #ifdef DEBUG_CRYPTO printf("Session hash : "); - ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LENGTH); + ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LEN); #endif } @@ -314,18 +391,18 @@ void hashbufin_add_cookie(SSH_SESSION *session,unsigned char *cookie){ buffer_add_data(session->in_hashbuf,cookie,16); } -static void generate_one_key(STRING *k,char session_id[SHA_DIGEST_LENGTH],char output[SHA_DIGEST_LENGTH],char letter){ - SHACTX *ctx=sha1_init(); +static void generate_one_key(STRING *k,unsigned char session_id[SHA_DIGEST_LEN],unsigned char output[SHA_DIGEST_LEN],char letter){ + SHACTX ctx=sha1_init(); sha1_update(ctx,k,string_len(k)+4); - sha1_update(ctx,session_id,SHA_DIGEST_LENGTH); + sha1_update(ctx,session_id,SHA_DIGEST_LEN); sha1_update(ctx,&letter,1); - sha1_update(ctx,session_id,SHA_DIGEST_LENGTH); + sha1_update(ctx,session_id,SHA_DIGEST_LEN); sha1_final(output,ctx); } void generate_session_keys(SSH_SESSION *session){ STRING *k_string; - SHACTX *ctx; + SHACTX ctx; k_string=make_bignum_string(session->next_crypto->k); /* IV */ @@ -345,19 +422,19 @@ void generate_session_keys(SSH_SESSION *session){ } /* some ciphers need more than 20 bytes of input key */ /* XXX verify it's ok for server implementation */ - if(session->next_crypto->out_cipher->keylen > SHA_DIGEST_LENGTH*8){ + if(session->next_crypto->out_cipher->keysize > SHA_DIGEST_LEN*8){ ctx=sha1_init(); sha1_update(ctx,k_string,string_len(k_string)+4); - sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LENGTH); - sha1_update(ctx,session->next_crypto->encryptkey,SHA_DIGEST_LENGTH); + sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LEN); + sha1_update(ctx,session->next_crypto->encryptkey,SHA_DIGEST_LEN); sha1_final(session->next_crypto->encryptkey+SHA_DIGEST_LEN,ctx); } - if(session->next_crypto->in_cipher->keylen > SHA_DIGEST_LENGTH*8){ + if(session->next_crypto->in_cipher->keysize > SHA_DIGEST_LEN*8){ ctx=sha1_init(); sha1_update(ctx,k_string,string_len(k_string)+4); - sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LENGTH); - sha1_update(ctx,session->next_crypto->decryptkey,SHA_DIGEST_LENGTH); + sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LEN); + sha1_update(ctx,session->next_crypto->decryptkey,SHA_DIGEST_LEN); sha1_final(session->next_crypto->decryptkey+SHA_DIGEST_LEN,ctx); } if(session->client){ @@ -369,19 +446,19 @@ void generate_session_keys(SSH_SESSION *session){ } #ifdef DEBUG_CRYPTO - ssh_print_hexa("encrypt IV",session->next_crypto->encryptIV,SHA_DIGEST_LENGTH); - ssh_print_hexa("decrypt IV",session->next_crypto->decryptIV,SHA_DIGEST_LENGTH); + ssh_print_hexa("encrypt IV",session->next_crypto->encryptIV,SHA_DIGEST_LEN); + ssh_print_hexa("decrypt IV",session->next_crypto->decryptIV,SHA_DIGEST_LEN); ssh_print_hexa("encryption key",session->next_crypto->encryptkey,16); ssh_print_hexa("decryption key",session->next_crypto->decryptkey,16); - ssh_print_hexa("Encryption MAC",session->next_crypto->encryptMAC,SHA_DIGEST_LENGTH); + ssh_print_hexa("Encryption MAC",session->next_crypto->encryptMAC,SHA_DIGEST_LEN); ssh_print_hexa("Decryption MAC",session->next_crypto->decryptMAC,20); #endif free(k_string); } -int ssh_get_pubkey_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]){ +int ssh_get_pubkey_hash(SSH_SESSION *session,unsigned char hash[MD5_DIGEST_LEN]){ STRING *pubkey=session->current_crypto->server_pubkey; - MD5CTX *ctx; + MD5CTX ctx; int len=string_len(pubkey); ctx=md5_init(); @@ -390,7 +467,7 @@ int ssh_get_pubkey_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]){ return MD5_DIGEST_LEN; } -int pubkey_get_hash(SSH_SESSION *session, char hash[MD5_DIGEST_LEN]){ +int pubkey_get_hash(SSH_SESSION *session, unsigned char hash[MD5_DIGEST_LEN]){ return ssh_get_pubkey_hash(session,hash); } @@ -424,33 +501,59 @@ static int match(char *group,char *object){ } static int sig_verify(SSH_SESSION *session, PUBLIC_KEY *pubkey, SIGNATURE *signature, - char *digest){ + unsigned char *digest){ +#ifdef HAVE_LIBGCRYPT + gcry_error_t valid=0; + gcry_sexp_t gcryhash; +#elif defined HAVE_LIBCRYPTO int valid=0; - char hash[SHA_DIGEST_LENGTH]; - sha1(digest,SHA_DIGEST_LENGTH,hash); +#endif + unsigned char hash[SHA_DIGEST_LEN+1]; + sha1(digest,SHA_DIGEST_LEN,hash+1); + hash[0]=0; #ifdef DEBUG_CRYPTO - ssh_print_hexa("hash to be verified with dsa",hash,SHA_DIGEST_LENGTH); + ssh_print_hexa("hash to be verified with dsa",hash+1,SHA_DIGEST_LEN); #endif switch(pubkey->type){ case TYPE_DSS: - valid=DSA_do_verify(hash,SHA_DIGEST_LENGTH,signature->dsa_sign, +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN+1, hash); + valid=gcry_pk_verify(signature->dsa_sign,gcryhash,pubkey->dsa_pub); + gcry_sexp_release(gcryhash); + if(valid==0) + return 0; + if (gcry_err_code(valid)!=GPG_ERR_BAD_SIGNATURE){ + ssh_set_error(NULL,SSH_FATAL,"DSA error : %s", gcry_strerror(valid)); +#elif defined HAVE_LIBCRYPTO + valid=DSA_do_verify(hash+1,SHA_DIGEST_LEN,signature->dsa_sign, pubkey->dsa_pub); if(valid==1) return 0; if(valid==-1){ ssh_set_error(session,SSH_FATAL,"DSA error : %s",ERR_error_string(ERR_get_error(),NULL)); +#endif return -1; } ssh_set_error(session,SSH_FATAL,"Invalid DSA signature"); return -1; case TYPE_RSA: case TYPE_RSA1: - valid=RSA_verify(NID_sha1,hash,SHA_DIGEST_LENGTH, +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&gcryhash,NULL,"(data(flags pkcs1)(hash sha1 %b))",SHA_DIGEST_LEN,hash+1); + valid=gcry_pk_verify(signature->rsa_sign,gcryhash,pubkey->rsa_pub); + gcry_sexp_release(gcryhash); + if(valid==0) + return 0; + if(gcry_err_code(valid)!=GPG_ERR_BAD_SIGNATURE){ + ssh_set_error(NULL,SSH_FATAL,"RSA error : %s",gcry_strerror(valid)); +#elif defined HAVE_LIBCRYPTO + valid=RSA_verify(NID_sha1,hash+1,SHA_DIGEST_LEN, signature->rsa_sign->string,string_len(signature->rsa_sign),pubkey->rsa_pub); if(valid==1) return 0; if(valid==-1){ ssh_set_error(session,SSH_FATAL,"RSA error : %s",ERR_error_string(ERR_get_error(),NULL)); +#endif return -1; } ssh_set_error(session,SSH_FATAL,"Invalid RSA signature"); diff --git a/libssh/gzip.c b/libssh/gzip.c index 0b04f905..0af45f1f 100644 --- a/libssh/gzip.c +++ b/libssh/gzip.c @@ -29,6 +29,7 @@ MA 02111-1307, USA. */ #ifndef NO_GZIP #include #include +#include #define BLOCKSIZE 4092 static z_stream *initcompress(SSH_SESSION *session,int level){ diff --git a/libssh/kex.c b/libssh/kex.c index 7b7722e0..e069bf79 100644 --- a/libssh/kex.c +++ b/libssh/kex.c @@ -26,6 +26,11 @@ MA 02111-1307, USA. */ #include "libssh/ssh2.h" #include "libssh/ssh1.h" +#ifdef HAVE_LIBGCRYPT +#define BLOWFISH "blowfish-cbc," +#define AES "aes256-cbc,aes192-cbc,aes128-cbc," +#define DES "3des-cbc" +#elif defined HAVE_LIBCRYPTO #ifdef HAVE_OPENSSL_BLOWFISH_H #define BLOWFISH "blowfish-cbc," #else @@ -36,13 +41,15 @@ MA 02111-1307, USA. */ #else #define AES "" #endif - #define DES "3des-cbc" +#endif + #ifdef HAVE_LIBZ #define ZLIB "none,zlib" #else #define ZLIB "none" #endif + char *default_methods[]={ "diffie-hellman-group1-sha1","ssh-dss,ssh-rsa",AES BLOWFISH DES,AES BLOWFISH DES, "hmac-sha1","hmac-sha1","none","none","","",NULL }; @@ -286,7 +293,7 @@ static STRING *make_rsa1_string(STRING *e, STRING *n){ static void build_session_id1(SSH_SESSION *session, STRING *servern, STRING *hostn){ - MD5CTX *md5=md5_init(); + MD5CTX md5=md5_init(); #ifdef DEBUG_CRYPTO ssh_print_hexa("host modulus",hostn->string,string_len(hostn)); ssh_print_hexa("server modulus",servern->string,string_len(servern)); @@ -313,7 +320,7 @@ static int modulus_smaller(PUBLIC_KEY *k1, PUBLIC_KEY *k2){ #define ABS(A) ( (A)<0 ? -(A):(A) ) STRING *encrypt_session_key(SSH_SESSION *session, PUBLIC_KEY *svrkey, PUBLIC_KEY *hostkey,int slen, int hlen ){ - char buffer[32]; + unsigned char buffer[32]; int i; STRING *data1,*data2; /* first, generate a session key */ diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c index 93223538..e2992952 100644 --- a/libssh/keyfiles.c +++ b/libssh/keyfiles.c @@ -28,12 +28,431 @@ MA 02111-1307, USA. */ #include #include #include +#include "libssh/priv.h" +#ifdef HAVE_LIBCRYPTO #include #include #include #include -#include "libssh/priv.h" +#endif +#include #define MAXLINESIZE 80 +#ifdef HAVE_LIBGCRYPT +#define MAX_KEY_SIZE 32 +#define MAX_PASSPHRASE_SIZE 1024 +#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----" +#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----" +#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----" +#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----" +#define ASN1_INTEGER 2 +#define ASN1_SEQUENCE 48 +#define PKCS5_SALT_LEN 8 + +int load_iv(char *header, unsigned char *iv, int iv_len) +{ + int i; + int j; + int k; + + memset(iv, 0, iv_len); + for (i=0; i < iv_len; i++) + { + if ((header[2*i] >= '0') && (header[2*i] <= '9')) + j = header[2*i] - '0'; + else if ((header[2*i] >= 'A') && (header[2*i] <= 'F')) + j = header[2*i] - 'A' + 10; + else if ((header[2*i] >= 'a') && (header[2*i] <= 'f')) + j = header[2*i] - 'a' + 10; + else + return 0; + if ((header[2*i+1] >= '0') && (header[2*i+1] <= '9')) + k = header[2*i+1] - '0'; + else if ((header[2*i+1] >= 'A') && (header[2*i+1] <= 'F')) + k = header[2*i+1] - 'A' + 10; + else if ((header[2*i+1] >= 'a') && (header[2*i+1] <= 'f')) + k = header[2*i+1] - 'a' + 10; + else + return 0; + iv[i] = (j << 4) + k; + } + return 1; +} + +u32 char_to_u32(unsigned char *data, u32 size) +{ + u32 ret; + u32 i; + + for (i=0,ret=0;i 127) + { + len=tmp[0] & 127; + if (len>4) + return 0; /* Length doesn't fit in u32. Can this really happen? */ + if (!buffer_get_data(buffer,tmp,len)) + return 0; + len=char_to_u32(tmp,len); + } + else + len=char_to_u32(tmp,1); + return len; +} + +STRING *asn1_get_int(BUFFER *buffer) +{ + STRING *ret; + unsigned char type; + u32 size; + + if (!buffer_get_data(buffer,&type,1) || type != ASN1_INTEGER) + return NULL; + size=asn1_get_len(buffer); + if (!size) + return NULL; + ret=string_new(size); + if (!buffer_get_data(buffer,ret->string,size)) + return NULL; + return ret; +} + +int asn1_check_sequence(BUFFER *buffer) +{ + unsigned char tmp; + unsigned char *j; + int i; + u32 size; + + if (!buffer_get_data(buffer,&tmp,1) || tmp != ASN1_SEQUENCE) + return 0; + size=asn1_get_len(buffer); + if (size != buffer_get_len(buffer) - buffer->pos) + for (i = buffer_get_len(buffer) - buffer->pos - size, + j = buffer_get(buffer) + size + buffer->pos; i; i--, j++) + { + if (*j != 1) /* padding is allowed */ + return 0; /* but nothing else */ + } + return 1; +} + +int read_line(char *data, unsigned int len, FILE *fp) +{ + char tmp; + int i; + + for (i=0; fread(&tmp, 1, 1, fp) && tmp!='\n' && i=len) + return -1; + return 0; +} + +int passphrase_to_key(char *data, unsigned int datalen, unsigned char *salt, unsigned char *key,unsigned int keylen) +{ + MD5CTX md; + unsigned char digest[MD5_DIGEST_LEN]; + unsigned int i; + unsigned int j; + unsigned int md_not_empty; + + for (j=0,md_not_empty=0;j 13 && !strncmp("DES-EDE3-CBC", header, 12)) + { + *algo = GCRY_CIPHER_3DES; + iv_pos = 13; + *mode = GCRY_CIPHER_MODE_CBC; + *key_len = 24; + *iv_len = 8; + } + else if (header_len > 8 && !strncmp("DES-CBC", header, 7)) + { + *algo = GCRY_CIPHER_DES; + iv_pos = 8; + *mode = GCRY_CIPHER_MODE_CBC; + *key_len = 8; + *iv_len = 8; + } + else if (header_len > 12 && !strncmp("AES-128-CBC", header, 11)) + { + *algo = GCRY_CIPHER_AES128; + iv_pos = 12; + *mode = GCRY_CIPHER_MODE_CBC; + *key_len = 16; + *iv_len = 16; + } + else if (header_len > 12 && !strncmp("AES-192-CBC", header, 11)) + { + *algo = GCRY_CIPHER_AES192; + iv_pos = 12; + *mode = GCRY_CIPHER_MODE_CBC; + *key_len = 24; + *iv_len = 16; + } + else if (header_len > 12 && !strncmp("AES-256-CBC", header, 11)) + { + *algo = GCRY_CIPHER_AES256; + iv_pos = 12; + *mode = GCRY_CIPHER_MODE_CBC; + *key_len = 32; + *iv_len = 16; + } + else + return 0; + *iv = malloc(*iv_len); + load_iv(header + iv_pos, *iv, *iv_len); + return 1; +} + +BUFFER *privatekey_file_to_buffer(FILE *fp, int type, int cb(char *, int , int , char *), char *desc) +{ + char buf[MAXLINESIZE]; + char *header_begin; + unsigned int header_begin_size; + char *header_end; + unsigned int header_end_size; + BUFFER *buffer=buffer_new(); + BUFFER *ret; + int len; + int algo = 0; + int mode = 0; + unsigned int key_len = 0; + unsigned char *iv = NULL; + unsigned int iv_len = 0; + + switch(type) + { + case TYPE_DSS: + header_begin=DSA_HEADER_BEGIN; + header_end=DSA_HEADER_END; + break; + case TYPE_RSA: + header_begin=RSA_HEADER_BEGIN; + header_end=RSA_HEADER_END; + break; + default: + return NULL; + } + header_begin_size=strlen(header_begin); + header_end_size=strlen(header_end); + while (read_line(buf,MAXLINESIZE,fp) && strncmp(buf,header_begin,header_begin_size)) + ; + len = read_line(buf, MAXLINESIZE, fp); + if (len > 11 && !strncmp("Proc-Type: 4,ENCRYPTED", buf, 11)) + { + len = read_line(buf, MAXLINESIZE, fp); + if (len > 10 && !strncmp("DEK-Info: ", buf, 10)) + { + if (!privatekey_dek_header(buf + 10, len - 10, &algo, &mode, &key_len, + &iv, &iv_len) + || read_line(buf, MAXLINESIZE, fp)) + { + buffer_free(buffer); + free(iv); + return NULL; + } + } + else + { + buffer_free(buffer); + free(iv); + return NULL; + } + } + else + buffer_add_data(buffer,buf,len); + while ((len = read_line(buf,MAXLINESIZE,fp)) + && strncmp(buf,header_end,header_end_size)) + { + if (len == -1) + { + buffer_free(buffer); + free(iv); + return NULL; + } + buffer_add_data(buffer,buf,len); + } + if (strncmp(buf,header_end,header_end_size)) + { + buffer_free(buffer); + free(iv); + return NULL; + } + buffer_add_data(buffer,"\0",1); + ret=base64_to_bin(buffer_get(buffer)); + buffer_free(buffer); + if (algo) + { + if (!privatekey_decrypt(algo, mode, key_len, iv, iv_len, ret, cb, desc)) + { + free(iv); + return NULL; + } + } + free(iv); + return ret; +} + +int read_rsa_privatekey(FILE *fp, gcry_sexp_t *r, + int cb(char *, int , int , char *), char *desc) +{ + STRING *n; + STRING *e; + STRING *d; + STRING *p; + STRING *q; + STRING *unused1; + STRING *unused2; + STRING *u; + STRING *v; + BUFFER *buffer; + + if (!(buffer=privatekey_file_to_buffer(fp, TYPE_RSA, cb, desc))) + return 0; + if (!asn1_check_sequence(buffer)) + { + buffer_free(buffer); + return 0; + } + v=asn1_get_int(buffer); + if (ntohl(v->size)!=1 || v->string[0]!=0) + { + buffer_free(buffer); + return 0; + } + n=asn1_get_int(buffer); + e=asn1_get_int(buffer); + d=asn1_get_int(buffer); + q=asn1_get_int(buffer); + p=asn1_get_int(buffer); + unused1=asn1_get_int(buffer); + unused2=asn1_get_int(buffer); + u=asn1_get_int(buffer); + buffer_free(buffer); + if (!n || !e || !d || !p || !q || !unused1 || !unused2 || !u) + return 0; + gcry_sexp_build(r,NULL,"(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",ntohl(n->size),n->string,ntohl(e->size),e->string,ntohl(d->size),d->string,ntohl(p->size),p->string,ntohl(q->size),q->string,ntohl(u->size),u->string); + free(n); + free(e); + free(d); + free(p); + free(q); + free(unused1); + free(unused2); + free(u); + free(v); + return 1; +} + +int read_dsa_privatekey(FILE *fp, gcry_sexp_t *r, int cb(char *, int , int , char *), char *desc) +{ + STRING *p; + STRING *q; + STRING *g; + STRING *y; + STRING *x; + STRING *v; + BUFFER *buffer; + + if (!(buffer=privatekey_file_to_buffer(fp, TYPE_DSS, cb, desc))) + return 0; + if (!asn1_check_sequence(buffer)) + { + buffer_free(buffer); + return 0; + } + v=asn1_get_int(buffer); + if (ntohl(v->size)!=1 || v->string[0]!=0) + { + buffer_free(buffer); + return 0; + } + p=asn1_get_int(buffer); + q=asn1_get_int(buffer); + g=asn1_get_int(buffer); + y=asn1_get_int(buffer); + x=asn1_get_int(buffer); + buffer_free(buffer); + if (!p || !q || !g || !y || !x) + return 0; + gcry_sexp_build(r,NULL,"(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))",ntohl(p->size),p->string,ntohl(q->size),q->string,ntohl(g->size),g->string,ntohl(y->size),y->string,ntohl(x->size),x->string); + free(p); + free(q); + free(g); + free(y); + free(x); + free(v); + return 1; +} +#endif /* GCRYPT */ static int default_get_password(char *buf, int size,int rwflag, char *descr){ char *pass; @@ -41,7 +460,7 @@ static int default_get_password(char *buf, int size,int rwflag, char *descr){ int len; snprintf(buffer,256,"Please enter passphrase for %s",descr); pass=getpass(buffer); - snprintf(buf,size,"%s",buffer); + snprintf(buf,size,"%s",pass); len=strlen(buf); memset(pass,0,strlen(pass)); return len; @@ -57,8 +476,14 @@ static int get_password_specified(char *buf,int size, int rwflag, char *password PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,char *passphrase){ FILE *file=fopen(filename,"r"); PRIVATE_KEY *privkey; +#ifdef HAVE_LIBGCRYPT + gcry_sexp_t dsa=NULL; + gcry_sexp_t rsa=NULL; + int valid; +#elif defined HAVE_LIBCRYPTO DSA *dsa=NULL; RSA *rsa=NULL; +#endif if(!file){ ssh_set_error(session,SSH_REQUEST_DENIED,"Error opening %s : %s",filename,strerror(errno)); return NULL; @@ -66,6 +491,17 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type, if(type==TYPE_DSS){ if(!passphrase){ if(session && session->options->passphrase_function) +#ifdef HAVE_LIBGCRYPT + valid = read_dsa_privatekey(file,&dsa, session->options->passphrase_function,"DSA private key"); + else + valid = read_dsa_privatekey(file,&dsa,(void *)default_get_password, "DSA private key"); + } + else + valid = read_dsa_privatekey(file,&dsa,(void *)get_password_specified,passphrase); + fclose(file); + if(!valid){ + ssh_set_error(session,SSH_FATAL,"parsing private key %s",filename); +#elif defined HAVE_LIBCRYPTO dsa=PEM_read_DSAPrivateKey(file,NULL, session->options->passphrase_function,"DSA private key"); else dsa=PEM_read_DSAPrivateKey(file,NULL,(void *)default_get_password, "DSA private key"); @@ -76,12 +512,24 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type, if(!dsa){ ssh_set_error(session,SSH_FATAL,"parsing private key %s" ": %s",filename,ERR_error_string(ERR_get_error(),NULL)); +#endif return NULL; } } else if (type==TYPE_RSA){ if(!passphrase){ if(session && session->options->passphrase_function) +#ifdef HAVE_LIBGCRYPT + valid = read_rsa_privatekey(file,&rsa, session->options->passphrase_function,"RSA private key"); + else + valid = read_rsa_privatekey(file,&rsa,(void *)default_get_password, "RSA private key"); + } + else + valid = read_rsa_privatekey(file,&rsa,(void *)get_password_specified,passphrase); + fclose(file); + if(!valid){ + ssh_set_error(session,SSH_FATAL,"parsing private key %s",filename); +#elif defined HAVE_LIBCRYPTO rsa=PEM_read_RSAPrivateKey(file,NULL, session->options->passphrase_function,"RSA private key"); else rsa=PEM_read_RSAPrivateKey(file,NULL,(void *)default_get_password, "RSA private key"); @@ -92,6 +540,7 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type, if(!rsa){ ssh_set_error(session,SSH_FATAL,"parsing private key %s" ": %s",filename,ERR_error_string(ERR_get_error(),NULL)); +#endif return NULL; } } else { @@ -110,27 +559,49 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type, PRIVATE_KEY *_privatekey_from_file(void *session,char *filename,int type){ FILE *file=fopen(filename,"r"); PRIVATE_KEY *privkey; +#ifdef HAVE_LIBGCRYPT + gcry_sexp_t dsa=NULL; + gcry_sexp_t rsa=NULL; + int valid; +#elif defined HAVE_LIBCRYPTO DSA *dsa=NULL; RSA *rsa=NULL; +#endif if(!file){ ssh_set_error(session,SSH_REQUEST_DENIED,"Error opening %s : %s",filename,strerror(errno)); return NULL; } if(type==TYPE_DSS){ +#ifdef HAVE_LIBGCRYPT + valid=read_dsa_privatekey(file,&dsa,NULL,NULL); + fclose(file); + if(!valid){ + ssh_set_error(session,SSH_FATAL,"parsing private key %s" + ,filename); +#elif defined HAVE_LIBCRYPTO dsa=PEM_read_DSAPrivateKey(file,NULL,NULL,NULL); fclose(file); if(!dsa){ ssh_set_error(session,SSH_FATAL,"parsing private key %s" ": %s",filename,ERR_error_string(ERR_get_error(),NULL)); +#endif return NULL; } } else if (type==TYPE_RSA){ +#ifdef HAVE_LIBGCRYPT + valid=read_rsa_privatekey(file,&rsa,NULL,NULL); + fclose(file); + if(!valid){ + ssh_set_error(session,SSH_FATAL,"parsing private key %s" + ,filename); +#elif defined HAVE_LIBCRYPTO rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL); fclose(file); if(!rsa){ ssh_set_error(session,SSH_FATAL,"parsing private key %s" ": %s",filename,ERR_error_string(ERR_get_error(),NULL)); +#endif return NULL; } } else { @@ -145,10 +616,17 @@ PRIVATE_KEY *_privatekey_from_file(void *session,char *filename,int type){ } void private_key_free(PRIVATE_KEY *prv){ +#ifdef HAVE_LIBGCRYPT + if(prv->dsa_priv) + gcry_sexp_release(prv->dsa_priv); + if(prv->rsa_priv) + gcry_sexp_release(prv->rsa_priv); +#elif defined HAVE_LIBCRYPTO if(prv->dsa_priv) DSA_free(prv->dsa_priv); if(prv->rsa_priv) RSA_free(prv->rsa_priv); +#endif memset(prv,0,sizeof(PRIVATE_KEY)); free(prv); } @@ -359,7 +837,7 @@ int ssh_is_server_known(SSH_SESSION *session){ } int ssh_write_knownhost(SSH_SESSION *session){ - char *pubkey_64; + unsigned char *pubkey_64; STRING *pubkey=session->current_crypto->server_pubkey; char buffer[4096]; FILE *file; diff --git a/libssh/keys.c b/libssh/keys.c index a5def00e..67ee08fb 100644 --- a/libssh/keys.c +++ b/libssh/keys.c @@ -20,9 +20,13 @@ You should have received a copy of the GNU Lesser General Public License along with the SSH Library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include +#include +#ifdef HAVE_LIBCRYPTO #include #include +#endif #include "libssh/priv.h" @@ -63,11 +67,15 @@ PUBLIC_KEY *publickey_make_dss(BUFFER *buffer){ free(key); return NULL; } +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&key->dsa_pub,NULL,"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",string_len(p),p->string,string_len(q),q->string,string_len(g),g->string,string_len(pubkey),pubkey->string); +#elif defined HAVE_LIBCRYPTO key->dsa_pub=DSA_new(); key->dsa_pub->p=make_string_bn(p); key->dsa_pub->q=make_string_bn(q); key->dsa_pub->g=make_string_bn(g); key->dsa_pub->pub_key=make_string_bn(pubkey); +#endif free(p); free(q); free(g); @@ -95,12 +103,16 @@ PUBLIC_KEY *publickey_make_rsa(BUFFER *buffer, char *type){ free(key); return NULL; } +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&key->rsa_pub,NULL,"(public-key(rsa(n %b)(e %b)))",string_len(n),n->string,string_len(e),e->string); +#elif HAVE_LIBCRYPTO key->rsa_pub=RSA_new(); key->rsa_pub->e=make_string_bn(e); key->rsa_pub->n=make_string_bn(n); +#endif #ifdef DEBUG_CRYPTO - ssh_print_bignum("e",key->rsa_pub->e); - ssh_print_bignum("n",key->rsa_pub->n); + ssh_print_hexa("e",e->string,string_len(e)); + ssh_print_hexa("n",n->string,string_len(n)); #endif free(e); free(n); @@ -112,11 +124,19 @@ void publickey_free(PUBLIC_KEY *key){ return; switch(key->type){ case TYPE_DSS: +#ifdef HAVE_LIBGCRYPT + gcry_sexp_release(key->dsa_pub); +#elif HAVE_LIBCRYPTO DSA_free(key->dsa_pub); +#endif break; case TYPE_RSA: case TYPE_RSA1: +#ifdef HAVE_LIBGCRYPT + gcry_sexp_release(key->rsa_pub); +#elif defined HAVE_LIBCRYPTO RSA_free(key->rsa_pub); +#endif break; default: break; @@ -158,32 +178,112 @@ PUBLIC_KEY *publickey_from_string(STRING *pubkey_s){ PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv){ PUBLIC_KEY *key=malloc(sizeof(PUBLIC_KEY)); +#ifdef HAVE_LIBGCRYPT + gcry_sexp_t sexp; + const char *tmp; + size_t size; + STRING *p,*q,*g,*y,*e,*n; +#endif key->type=prv->type; switch(key->type){ case TYPE_DSS: +#ifdef HAVE_LIBGCRYPT + sexp=gcry_sexp_find_token(prv->dsa_priv,"p",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + p=string_new(size); + string_fill(p,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(prv->dsa_priv,"q",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + q=string_new(size); + string_fill(q,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(prv->dsa_priv,"g",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + g=string_new(size); + string_fill(g,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(prv->dsa_priv,"y",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + y=string_new(size); + string_fill(y,(char *)tmp,size); + gcry_sexp_release(sexp); + gcry_sexp_build(&key->dsa_pub,NULL,"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",string_len(p),p->string,string_len(q),q->string,string_len(g),g->string,string_len(y),y->string); + free(p); + free(q); + free(g); + free(y); +#elif defined HAVE_LIBCRYPTO key->dsa_pub=DSA_new(); key->dsa_pub->p=BN_dup(prv->dsa_priv->p); key->dsa_pub->q=BN_dup(prv->dsa_priv->q); key->dsa_pub->pub_key=BN_dup(prv->dsa_priv->pub_key); key->dsa_pub->g=BN_dup(prv->dsa_priv->g); +#endif break; case TYPE_RSA: case TYPE_RSA1: +#ifdef HAVE_LIBGCRYPT + sexp=gcry_sexp_find_token(prv->rsa_priv,"n",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + n=string_new(size); + string_fill(n,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(prv->rsa_priv,"e",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + e=string_new(size); + string_fill(e,(char *)tmp,size); + gcry_sexp_release(sexp); + gcry_sexp_build(&key->rsa_pub,NULL,"(public-key(rsa(n %b)(e %b)))",string_len(n),n->string,string_len(e),e->string); + free(e); + free(n); +#elif defined HAVE_LIBCRYPTO key->rsa_pub=RSA_new(); key->rsa_pub->e=BN_dup(prv->rsa_priv->e); key->rsa_pub->n=BN_dup(prv->rsa_priv->n); +#endif break; } key->type_c=ssh_type_to_char(prv->type); return key; } +#ifdef HAVE_LIBGCRYPT +static void dsa_public_to_string(gcry_sexp_t key, BUFFER *buffer){ +#elif defined HAVE_LIBCRYPTO static void dsa_public_to_string(DSA *key, BUFFER *buffer){ +#endif STRING *p,*q,*g,*n; +#ifdef HAVE_LIBGCRYPT + const char *tmp; + size_t size; + gcry_sexp_t sexp; + sexp=gcry_sexp_find_token(key,"p",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + p=string_new(size); + string_fill(p,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(key,"q",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + q=string_new(size); + string_fill(q,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(key,"g",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + g=string_new(size); + string_fill(g,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(key,"y",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + n=string_new(size); + string_fill(n,(char *)tmp,size); + gcry_sexp_release(sexp); +#elif defined HAVE_LIBCRYPTO p=make_bignum_string(key->p); q=make_bignum_string(key->q); g=make_bignum_string(key->g); n=make_bignum_string(key->pub_key); +#endif buffer_add_ssh_string(buffer,p); buffer_add_ssh_string(buffer,q); buffer_add_ssh_string(buffer,g); @@ -194,10 +294,30 @@ static void dsa_public_to_string(DSA *key, BUFFER *buffer){ free(n); } +#ifdef HAVE_LIBGCRYPT +static void rsa_public_to_string(gcry_sexp_t key, BUFFER *buffer){ +#elif defined HAVE_LIBCRYPTO static void rsa_public_to_string(RSA *key, BUFFER *buffer){ +#endif STRING *e, *n; +#ifdef HAVE_LIBGCRYPT + const char *tmp; + size_t size; + gcry_sexp_t sexp; + sexp=gcry_sexp_find_token(key,"n",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + n=string_new(size); + string_fill(n,(char *)tmp,size); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(key,"e",0); + tmp=gcry_sexp_nth_data(sexp,1,&size); + e=string_new(size); + string_fill(e,(char *)tmp,size); + gcry_sexp_release(sexp); +#elif defined HAVE_LIBCRYPTO e=make_bignum_string(key->e); n=make_bignum_string(key->n); +#endif buffer_add_ssh_string(buffer,e); buffer_add_ssh_string(buffer,n); free(e); @@ -231,7 +351,14 @@ STRING *publickey_to_string(PUBLIC_KEY *key){ STRING *signature_to_string(SIGNATURE *sign){ STRING *str; - STRING *rs,*r,*s; + STRING *rs; +#ifdef HAVE_LIBGCRYPT + const char *r,*s; + gcry_sexp_t sexp; + size_t size; +#elif defined HAVE_LIBCRYPTO + STRING *r,*s; +#endif unsigned char buffer[40]; BUFFER *tmpbuf=buffer_new(); STRING *tmp; @@ -240,21 +367,58 @@ STRING *signature_to_string(SIGNATURE *sign){ free(tmp); switch(sign->type){ case TYPE_DSS: + memset(buffer,0,40); +#ifdef HAVE_LIBGCRYPT + sexp=gcry_sexp_find_token(sign->dsa_sign,"r",0); + r=gcry_sexp_nth_data(sexp,1,&size); + if (*r == 0) /* libgcrypt put 0 when first bit is set */ + { + size--; + r++; + } + memcpy(buffer,r + size - 20,20); + gcry_sexp_release(sexp); + sexp=gcry_sexp_find_token(sign->dsa_sign,"s",0); + s=gcry_sexp_nth_data(sexp,1,&size); + if (*s == 0) + { + size--; + s++; + } + memcpy(buffer+ 20, s + size - 20, 20); + gcry_sexp_release(sexp); +#elif defined HAVE_LIBCRYPTO r=make_bignum_string(sign->dsa_sign->r); s=make_bignum_string(sign->dsa_sign->s); rs=string_new(40); - memset(buffer,0,40); memcpy(buffer,r->string+string_len(r)-20,20); memcpy(buffer+ 20, s->string + string_len(s) - 20, 20); - string_fill(rs,buffer,40); free(r); free(s); +#endif + rs=string_new(40); + string_fill(rs,buffer,40); buffer_add_ssh_string(tmpbuf,rs); free(rs); break; case TYPE_RSA: case TYPE_RSA1: +#ifdef HAVE_LIBGCRYPT + sexp=gcry_sexp_find_token(sign->rsa_sign,"s",0); + s=gcry_sexp_nth_data(sexp,1,&size); + if (*s == 0) + { + size--; + s++; + } + rs=string_new(size); + string_fill(rs,(char *)s,size); + buffer_add_ssh_string(tmpbuf,rs); + gcry_sexp_release(sexp); + free(rs); +#elif defined HAVE_LIBCRYPTO buffer_add_ssh_string(tmpbuf,sign->rsa_sign); +#endif break; } str=string_new(buffer_get_len(tmpbuf)); @@ -265,11 +429,16 @@ STRING *signature_to_string(SIGNATURE *sign){ /* TODO : split this function in two so it becomes smaller */ SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed_type){ +#ifdef HAVE_LIBGCRYPT + gcry_sexp_t sig; +#elif defined HAVE_LIBCRYPTO DSA_SIG *sig; + STRING *r,*s; +#endif SIGNATURE *sign=malloc(sizeof(SIGNATURE)); BUFFER *tmpbuf=buffer_new(); STRING *rs; - STRING *r,*s,*type_s,*e; + STRING *type_s,*e; int len,rsalen; char *type; buffer_add_data(tmpbuf,signature->string,string_len(signature)); @@ -314,21 +483,25 @@ SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed free(rs); return NULL; } - /* we make use of strings because we have all-made functions to convert them to bignums */ + /* we make use of strings (because we have all-made functions to convert them to bignums (ou pas ;)*/ +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&sig,NULL,"(sig-val(dsa(r %b)(s %b)))",20,rs->string,20,rs->string+20); +#elif defined HAVE_LIBCRYPTO r=string_new(20); s=string_new(20); string_fill(r,rs->string,20); string_fill(s,rs->string+20,20); - free(rs); sig=DSA_SIG_new(); sig->r=make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */ sig->s=make_string_bn(s); -#ifdef DEBUG_CRYPTO - ssh_print_bignum("r",sig->r); - ssh_print_bignum("s",sig->s); -#endif free(r); free(s); +#endif +#ifdef DEBUG_CRYPTO + ssh_print_hexa("r",rs->string,20); + ssh_print_hexa("s",rs->string+20,20); +#endif + free(rs); sign->type=TYPE_DSS; sign->dsa_sign=sig; return sign; @@ -336,11 +509,14 @@ SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed e=buffer_get_ssh_string(tmpbuf); buffer_free(tmpbuf); if(!e){ - free(e); - return NULL; + return NULL; } len=string_len(e); +#ifdef HAVE_LIBGCRYPT + rsalen=(gcry_pk_get_nbits(pubkey->rsa_pub)+7)/8; +#elif defined HAVE_LIBCRYPTO rsalen=RSA_size(pubkey->rsa_pub); +#endif if(len>rsalen){ free(e); free(sign); @@ -350,10 +526,18 @@ SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed if(lentype=TYPE_RSA; +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&sig,NULL,"(sig-val(rsa(s %b)))",string_len(e),e->string); + sign->rsa_sign=sig; +#elif defined HAVE_LIBCRYPTO sign->rsa_sign=e; +#endif #ifdef DEBUG_CRYPTO ssh_say(0,"Len : %d\n",len); ssh_print_hexa("rsa signature",e->string,len); +#endif +#ifdef HAVE_LIBGCRYPT + free(e); #endif return sign; default: @@ -366,11 +550,19 @@ void signature_free(SIGNATURE *sign){ return; switch(sign->type){ case TYPE_DSS: +#ifdef HAVE_LIBGCRYPT + gcry_sexp_release(sign->dsa_sign); +#elif defined HAVE_LIBCRYPTO DSA_SIG_free(sign->dsa_sign); +#endif break; case TYPE_RSA: case TYPE_RSA1: +#ifdef HAVE_LIBGCRYPT + gcry_sexp_release(sign->rsa_sign); +#elif defined HAVE_LIBCRYPTO free(sign->rsa_sign); +#endif break; default: ssh_say(1,"freeing a signature with no type !\n"); @@ -378,6 +570,7 @@ void signature_free(SIGNATURE *sign){ free(sign); } +#ifdef HAVE_LIBCRYPTO /* maybe the missing function from libcrypto */ /* i think now, maybe it's a bad idea to name it has it should have be named in libcrypto */ static STRING *RSA_do_sign(void *payload,int len,RSA *privkey){ @@ -395,42 +588,64 @@ static STRING *RSA_do_sign(void *payload,int len,RSA *privkey){ free(buffer); return sign; } +#endif /* this function signs the session id (known as H) as a string then the content of sigbuf */ STRING *ssh_do_sign(SSH_SESSION *session,BUFFER *sigbuf, PRIVATE_KEY *privatekey){ - SHACTX *ctx; + SHACTX ctx; STRING *session_str=string_new(SHA_DIGEST_LEN); - char hash[SHA_DIGEST_LEN]; + unsigned char hash[SHA_DIGEST_LEN+1]; +#ifdef HAVE_LIBGCRYPT + gcry_sexp_t gcryhash; +#endif SIGNATURE *sign; STRING *signature; CRYPTO *crypto=session->current_crypto?session->current_crypto:session->next_crypto; - string_fill(session_str,crypto->session_id,SHA_DIGEST_LENGTH); + string_fill(session_str,crypto->session_id,SHA_DIGEST_LEN); ctx=sha1_init(); sha1_update(ctx,session_str,string_len(session_str)+4); sha1_update(ctx,buffer_get(sigbuf),buffer_get_len(sigbuf)); - sha1_final(hash,ctx); + sha1_final(hash+1,ctx); + hash[0]=0; #ifdef DEBUG_CRYPTO - ssh_print_hexa("Hash being signed with dsa",hash,SHA_DIGEST_LENGTH); + ssh_print_hexa("Hash being signed with dsa",hash+1,SHA_DIGEST_LEN); #endif free(session_str); sign=malloc(sizeof(SIGNATURE)); switch(privatekey->type){ case TYPE_DSS: - sign->dsa_sign=DSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->dsa_priv); +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&gcryhash,NULL,"%b",SHA_DIGEST_LEN+1,hash); + gcry_pk_sign(&sign->dsa_sign,gcryhash,privatekey->dsa_priv); +#elif defined HAVE_LIBCRYPTO + sign->dsa_sign=DSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->dsa_priv); #ifdef DEBUG_CRYPTO ssh_print_bignum("r",sign->dsa_sign->r); ssh_print_bignum("s",sign->dsa_sign->s); +#endif #endif sign->rsa_sign=NULL; break; case TYPE_RSA: - sign->rsa_sign=RSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->rsa_priv); +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&gcryhash,NULL,"(data(flags pkcs1)(hash sha1 %b))",SHA_DIGEST_LEN,hash+1); + gcry_pk_sign(&sign->rsa_sign,gcryhash,privatekey->rsa_priv); +#elif defined HAVE_LIBCRYPTO + sign->rsa_sign=RSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->rsa_priv); +#endif sign->dsa_sign=NULL; break; } +#ifdef HAVE_LIBGCRYPT + gcry_sexp_release(gcryhash); +#endif sign->type=privatekey->type; if(!sign->dsa_sign && !sign->rsa_sign){ +#ifdef HAVE_LIBGCRYPT + ssh_set_error(session,SSH_FATAL,"Signing : libcrypt error"); +#elif HAVE_LIBCRYPTO ssh_set_error(session,SSH_FATAL,"Signing : openssl error"); +#endif signature_free(sign); return NULL; } @@ -441,45 +656,87 @@ STRING *ssh_do_sign(SSH_SESSION *session,BUFFER *sigbuf, PRIVATE_KEY *privatekey STRING *ssh_encrypt_rsa1(SSH_SESSION *session, STRING *data, PUBLIC_KEY *key){ int len=string_len(data); +#ifdef HAVE_LIBGCRYPT + STRING *ret; + gcry_sexp_t ret_sexp; + gcry_sexp_t data_sexp; + const char *tmp; + size_t size; + gcry_sexp_build(&data_sexp,NULL,"(data(flags pkcs1)(value %b))",len,data->string); + gcry_pk_encrypt(&ret_sexp,data_sexp,key->rsa_pub); + gcry_sexp_release(data_sexp); + data_sexp=gcry_sexp_find_token(ret_sexp,"a",0); + tmp=gcry_sexp_nth_data(data_sexp,1,&size); + if (*tmp == 0) + { + size--; + tmp++; + } + ret=string_new(size); + string_fill(ret,(char *)tmp,size); + gcry_sexp_release(ret_sexp); +#elif defined HAVE_LIBCRYPTO int flen=RSA_size(key->rsa_pub); STRING *ret=string_new(flen); RSA_public_encrypt(len,data->string,ret->string,key->rsa_pub, RSA_PKCS1_PADDING); +#endif return ret; } /* this function signs the session id */ STRING *ssh_sign_session_id(SSH_SESSION *session, PRIVATE_KEY *privatekey){ - SHACTX *ctx; - char hash[SHA_DIGEST_LEN]; + SHACTX ctx; + unsigned char hash[SHA_DIGEST_LEN+1]; SIGNATURE *sign; STRING *signature; CRYPTO *crypto=session->current_crypto?session->current_crypto:session->next_crypto; +#ifdef HAVE_LIBGCRYPT + gcry_sexp_t data_sexp; +#endif ctx=sha1_init(); - sha1_update(ctx,crypto->session_id,SHA_DIGEST_LENGTH); - sha1_final(hash,ctx); + sha1_update(ctx,crypto->session_id,SHA_DIGEST_LEN); + sha1_final(hash+1,ctx); + hash[0]=0; #ifdef DEBUG_CRYPTO - ssh_print_hexa("Hash being signed with dsa",hash,SHA_DIGEST_LENGTH); + ssh_print_hexa("Hash being signed with dsa",hash+1,SHA_DIGEST_LEN); #endif sign=malloc(sizeof(SIGNATURE)); switch(privatekey->type){ case TYPE_DSS: - sign->dsa_sign=DSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->dsa_priv); +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&data_sexp,NULL,"%b",SHA_DIGEST_LEN+1,hash); + gcry_pk_sign(&sign->dsa_sign,data_sexp,privatekey->dsa_priv); +#elif defined HAVE_LIBCRYPTO + sign->dsa_sign=DSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->dsa_priv); #ifdef DEBUG_CRYPTO ssh_print_bignum("r",sign->dsa_sign->r); ssh_print_bignum("s",sign->dsa_sign->s); +#endif #endif sign->rsa_sign=NULL; break; case TYPE_RSA: - sign->rsa_sign=RSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->rsa_priv); +#ifdef HAVE_LIBGCRYPT + gcry_sexp_build(&data_sexp,NULL,"(data(flags pkcs1)(hash sha1 %b))",SHA_DIGEST_LEN,hash+1); + gcry_pk_sign(&sign->rsa_sign,data_sexp,privatekey->rsa_priv); +#elif defined HAVE_LIBCRYPTO + sign->rsa_sign=RSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->rsa_priv); +#endif sign->dsa_sign=NULL; break; } +#ifdef HAVE_LIBGCRYPT + gcry_sexp_release(data_sexp); +#endif sign->type=privatekey->type; if(!sign->dsa_sign && !sign->rsa_sign){ +#ifdef HAVE_LIBGCRYPT + ssh_set_error(session,SSH_FATAL,"Signing : libgcrypt error"); +#elif defined HAVE_LIBCRYPTO ssh_set_error(session,SSH_FATAL,"Signing : openssl error"); +#endif signature_free(sign); return NULL; } diff --git a/libssh/messages.c b/libssh/messages.c index 6523f1c7..d8c16ed1 100644 --- a/libssh/messages.c +++ b/libssh/messages.c @@ -32,6 +32,7 @@ MA 02111-1307, USA. */ #include "libssh/ssh2.h" #include #include +#include static SSH_MESSAGE *message_new(SSH_SESSION *session){ SSH_MESSAGE *msg=session->ssh_message; diff --git a/libssh/packet.c b/libssh/packet.c index e717ba59..4085f60d 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -32,7 +32,7 @@ MA 02111-1307, USA. */ #include "libssh/crypto.h" /* XXX include selected mac size */ -static int macsize=SHA_DIGEST_LENGTH; +static int macsize=SHA_DIGEST_LEN; /* completeread will read blocking until len bytes have been read */ static int completeread(int fd, void *buffer, int len){ @@ -55,7 +55,7 @@ static int completeread(int fd, void *buffer, int len){ static int packet_read2(SSH_SESSION *session){ u32 len; void *packet=NULL; - char mac[30]; + unsigned char mac[30]; char buffer[16]; int be_read,i; int to_be_read; @@ -316,7 +316,7 @@ static int packet_send2(SSH_SESSION *session){ u32 finallen; u8 padding; u32 currentlen=buffer_get_len(session->out_buffer); - char *hmac; + unsigned char *hmac; int ret=0; unsigned int blocksize=(session->current_crypto?session->current_crypto->out_cipher->blocksize:8); ssh_say(3,"Writing on the wire a packet having %ld bytes before",currentlen); diff --git a/libssh/server.c b/libssh/server.c index 0f429852..4a915889 100644 --- a/libssh/server.c +++ b/libssh/server.c @@ -27,10 +27,10 @@ MA 02111-1307, USA. */ #include #include #include -#include #include #include #include +#include #include "libssh/libssh.h" #include "libssh/server.h" #include "libssh/ssh2.h" diff --git a/libssh/session.c b/libssh/session.c index 1a0f25ce..b084c29d 100644 --- a/libssh/session.c +++ b/libssh/session.c @@ -22,6 +22,7 @@ /* ssh_new() returns a newly allocated SSH_SESSION structure pointer */ #include +#include #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/server.h" diff --git a/libssh/sftp.c b/libssh/sftp.c index 3c7e7410..5a49fb7b 100644 --- a/libssh/sftp.c +++ b/libssh/sftp.c @@ -22,6 +22,7 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include #include diff --git a/libssh/sftpserver.c b/libssh/sftpserver.c index bfbbc400..7779512a 100644 --- a/libssh/sftpserver.c +++ b/libssh/sftpserver.c @@ -26,6 +26,7 @@ MA 02111-1307, USA. */ #include #include #include +#include SFTP_CLIENT_MESSAGE *sftp_get_client_message(SFTP_SESSION *sftp){ SFTP_PACKET *packet=sftp_packet_read(sftp); diff --git a/libssh/string.c b/libssh/string.c index 2f14c141..2e6c3bfd 100644 --- a/libssh/string.c +++ b/libssh/string.c @@ -26,7 +26,7 @@ MA 02111-1307, USA. */ #include #include "libssh/priv.h" -STRING *string_new(u32 size){ +STRING *string_new(unsigned int size){ STRING *str=malloc(size + 4); str->size=htonl(size); return str; diff --git a/libssh/wrapper.c b/libssh/wrapper.c index 9d418df0..92a25a90 100644 --- a/libssh/wrapper.c +++ b/libssh/wrapper.c @@ -27,8 +27,178 @@ MA 02111-1307, USA. */ #include "libssh/priv.h" #include "libssh/crypto.h" +#include +#include #include -#ifdef OPENSSL_CRYPTO +#ifdef HAVE_LIBGCRYPT +#include + +SHACTX sha1_init(){ + SHACTX ret; + gcry_md_open(&ret,GCRY_MD_SHA1,GCRY_MD_FLAG_SECURE); + return ret; +} +void sha1_update(SHACTX c, const void *data, unsigned long len){ + gcry_md_write(c,data,len); +} +void sha1_final(unsigned char *md,SHACTX c){ + gcry_md_final(c); + memcpy(md, gcry_md_read(c, 0), SHA_DIGEST_LEN); + gcry_md_close(c); +} +void sha1(unsigned char *digest,int len,unsigned char *hash){ + gcry_md_hash_buffer(GCRY_MD_SHA1,hash,digest,len); +} + +MD5CTX md5_init(){ + MD5CTX ret; + gcry_md_open(&ret,GCRY_MD_MD5,GCRY_MD_FLAG_SECURE); + return ret; +} +void md5_update(MD5CTX c, const void *data, unsigned long len){ + gcry_md_write(c,data,len); +} +void md5_final(unsigned char *md,MD5CTX c){ + gcry_md_final(c); + memcpy(md, gcry_md_read(c, 0), MD5_DIGEST_LEN); + gcry_md_close(c); +} + +HMACCTX hmac_init(const void *key, int len,int type){ + HMACCTX c; + switch(type){ + case HMAC_SHA1: + gcry_md_open(&c,GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); + break; + case HMAC_MD5: + gcry_md_open(&c,GCRY_MD_MD5, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); + break; + default: + c=NULL; + } + gcry_md_setkey(c,key,len); + return c; +} +void hmac_update(HMACCTX c, const void *data, unsigned long len){ + gcry_md_write(c,data,len); +} + +void hmac_final(HMACCTX c,unsigned char *hashmacbuf,unsigned int *len){ + *len = gcry_md_get_algo_dlen(gcry_md_get_algo(c)); + memcpy(hashmacbuf, gcry_md_read(c, 0), *len); + gcry_md_close(c); +} + +static void alloc_key(struct crypto_struct *cipher){ + cipher->key=malloc(cipher->keylen); +} + +/* the wrapper functions for blowfish */ +static void blowfish_set_key(struct crypto_struct *cipher, void *key, void *IV){ + if(!cipher->key){ + alloc_key(cipher); + gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_BLOWFISH,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + gcry_cipher_setkey(cipher->key[0],key,16); + gcry_cipher_setiv(cipher->key[0],IV,8); + } +} + +static void blowfish_encrypt(struct crypto_struct *cipher, void *in, void *out,unsigned long len){ + gcry_cipher_encrypt(cipher->key[0],out,len,in,len); +} + +static void blowfish_decrypt(struct crypto_struct *cipher, void *in, void *out, unsigned long len){ + gcry_cipher_decrypt(cipher->key[0],out,len,in,len); +} + +static void aes_set_key(struct crypto_struct *cipher, void *key, void *IV){ + if(!cipher->key){ + alloc_key(cipher); + switch(cipher->keysize){ + case 128: + gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_AES128,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + break; + case 192: + gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_AES192,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + break; + case 256: + gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_AES256,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + break; + } + gcry_cipher_setkey(cipher->key[0],key,cipher->keysize/8); + gcry_cipher_setiv(cipher->key[0], IV, 16); + } +} + +static void aes_encrypt(struct crypto_struct *cipher, void *in, void *out, unsigned long len){ + gcry_cipher_encrypt(cipher->key[0],out,len,in,len); +} + +static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out,unsigned long len){ + gcry_cipher_decrypt(cipher->key[0],out,len,in,len); +} + +static void des3_set_key(struct crypto_struct *cipher, void *key, void *IV){ + if(!cipher->key){ + alloc_key(cipher); + gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_3DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + gcry_cipher_setkey(cipher->key[0],key,24); + gcry_cipher_setiv(cipher->key[0],IV,8); + } +} + +static void des3_encrypt(struct crypto_struct *cipher, void *in, void *out, + unsigned long len){ + gcry_cipher_encrypt(cipher->key[0],out,len,in,len); +} + +static void des3_decrypt(struct crypto_struct *cipher, void *in, void *out, + unsigned long len){ + gcry_cipher_decrypt(cipher->key[0],out,len,in,len); +} + +static void des3_1_set_key(struct crypto_struct *cipher, void *key, void *IV){ + if(!cipher->key){ + alloc_key(cipher); + gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + gcry_cipher_setkey(cipher->key[0],key,8); + gcry_cipher_setiv(cipher->key[0],IV,8); + gcry_cipher_open(&cipher->key[1],GCRY_CIPHER_DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + gcry_cipher_setkey(cipher->key[1],key+8,8); + gcry_cipher_setiv(cipher->key[1],IV+8,8); + gcry_cipher_open(&cipher->key[2],GCRY_CIPHER_DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE); + gcry_cipher_setkey(cipher->key[2],key+16,8); + gcry_cipher_setiv(cipher->key[2],IV+16,8); + } +} + +static void des3_1_encrypt(struct crypto_struct *cipher, void *in, void *out, + unsigned long len){ + gcry_cipher_encrypt(cipher->key[0],out,len,in,len); + gcry_cipher_decrypt(cipher->key[1],in,len,out,len); + gcry_cipher_encrypt(cipher->key[2],out,len,in,len); +} + +static void des3_1_decrypt(struct crypto_struct *cipher, void *in, void *out, + unsigned long len){ + gcry_cipher_decrypt(cipher->key[2],out,len,in,len); + gcry_cipher_encrypt(cipher->key[1],in,len,out,len); + gcry_cipher_decrypt(cipher->key[0],out,len,in,len); +} + +/* the table of supported ciphers */ +static struct crypto_struct ssh_ciphertab[]={ + { "blowfish-cbc", 8 ,sizeof (gcry_cipher_hd_t),NULL,128,blowfish_set_key,blowfish_set_key,blowfish_encrypt, blowfish_decrypt}, + { "aes128-cbc",16,sizeof(gcry_cipher_hd_t),NULL,128,aes_set_key,aes_set_key,aes_encrypt,aes_decrypt}, + { "aes192-cbc",16,sizeof(gcry_cipher_hd_t),NULL,192,aes_set_key,aes_set_key,aes_encrypt,aes_decrypt}, + { "aes256-cbc",16,sizeof(gcry_cipher_hd_t),NULL,256,aes_set_key,aes_set_key,aes_encrypt,aes_decrypt}, + { "3des-cbc",8,sizeof(gcry_cipher_hd_t),NULL,192,des3_set_key, + des3_set_key,des3_encrypt, des3_decrypt}, + { "3des-cbc-ssh1",8,sizeof(gcry_cipher_hd_t)*3,NULL,192,des3_1_set_key, + des3_1_set_key,des3_1_encrypt, des3_1_decrypt}, + { NULL,0,0,NULL,0,NULL,NULL,NULL} +}; +#elif defined HAVE_LIBCRYPTO #include #include #include @@ -43,22 +213,24 @@ MA 02111-1307, USA. */ #define HAS_BLOWFISH #include #endif - +#ifdef HAVE_OPENSSL_DES_H +#define HAS_DES #include +#endif #if (OPENSSL_VERSION_NUMBER<0x009070000) #define OLD_CRYPTO #endif -SHACTX *sha1_init(){ - SHACTX *c=malloc(sizeof(SHACTX)); +SHACTX sha1_init(){ + SHACTX c=malloc(sizeof(*c)); SHA1_Init(c); return c; } -void sha1_update(SHACTX *c, const void *data, unsigned long len){ +void sha1_update(SHACTX c, const void *data, unsigned long len){ SHA1_Update(c,data,len); } -void sha1_final(unsigned char *md,SHACTX *c){ +void sha1_final(unsigned char *md,SHACTX c){ SHA1_Final(md,c); free(c); } @@ -66,21 +238,21 @@ void sha1(unsigned char *digest,int len,unsigned char *hash){ SHA1(digest,len,hash); } -MD5CTX *md5_init(){ - MD5CTX *c=malloc(sizeof(MD5CTX)); +MD5CTX md5_init(){ + MD5CTX c=malloc(sizeof(MD5CTX)); MD5_Init(c); return c; } -void md5_update(MD5CTX *c, const void *data, unsigned long len){ +void md5_update(MD5CTX c, const void *data, unsigned long len){ MD5_Update(c,data,len); } -void md5_final(unsigned char *md,MD5CTX *c){ +void md5_final(unsigned char *md,MD5CTX c){ MD5_Final(md,c); free(c); } -HMACCTX *hmac_init(const void *key, int len,int type){ - HMAC_CTX *ctx; +HMACCTX hmac_init(const void *key, int len,int type){ + HMACCTX ctx; ctx=malloc(sizeof(HMAC_CTX)); #ifndef OLD_CRYPTO HMAC_CTX_init(ctx); // openssl 0.9.7 requires it. @@ -98,10 +270,10 @@ HMACCTX *hmac_init(const void *key, int len,int type){ } return ctx; } -void hmac_update(HMACCTX *ctx,const void *data, unsigned long len){ +void hmac_update(HMACCTX ctx,const void *data, unsigned long len){ HMAC_Update(ctx,data,len); } -void hmac_final(HMACCTX *ctx,unsigned char *hashmacbuf,int *len){ +void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len){ HMAC_Final(ctx,hashmacbuf,len); #ifndef OLD_CRYPTO HMAC_CTX_cleanup(ctx); @@ -152,7 +324,7 @@ static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out, unsig AES_cbc_encrypt(in,out,len,cipher->key,IV,AES_DECRYPT); } #endif - +#ifdef HAS_DES static void des3_set_key(struct crypto_struct *cipher, void *key){ if(!cipher->key){ alloc_key(cipher); @@ -205,10 +377,8 @@ static void des3_1_decrypt(struct crypto_struct *cipher, void *in, void *out, ssh_print_hexa("decrypt IV after",IV,24); #endif } +#endif - - - /* the table of supported ciphers */ static struct crypto_struct ssh_ciphertab[]={ #ifdef HAS_BLOWFISH @@ -223,10 +393,12 @@ static struct crypto_struct ssh_ciphertab[]={ { "aes256-cbc",16,sizeof(AES_KEY),NULL,256,aes_set_encrypt_key, aes_set_decrypt_key,aes_encrypt,aes_decrypt}, #endif +#ifdef HAS_DES { "3des-cbc",8,sizeof(DES_key_schedule)*3,NULL,192,des3_set_key, des3_set_key,des3_encrypt, des3_decrypt}, { "3des-cbc-ssh1",8,sizeof(DES_key_schedule)*3,NULL,192,des3_set_key, des3_set_key,des3_1_encrypt, des3_1_decrypt}, +#endif { NULL,0,0,NULL,0,NULL,NULL,NULL} }; #endif /* OPENSSL_CRYPTO */ @@ -240,9 +412,17 @@ struct crypto_struct *cipher_new(int offset){ } void cipher_free(struct crypto_struct *cipher){ +#ifdef HAVE_LIBGCRYPT + int i; +#endif if(cipher->key){ - // destroy the key +#ifdef HAVE_LIBGCRYPT + for (i=0;ikeylen/sizeof (gcry_cipher_hd_t);i++) + gcry_cipher_close(cipher->key[i]); +#elif defined HAVE_LIBCRYPTO + /* destroy the key */ memset(cipher->key,0,cipher->keylen); +#endif free(cipher->key); } free(cipher); -- cgit v1.2.3