Subject: Re: [libssh2] Libgcrypt support

Re: [libssh2] Libgcrypt support

From: Simon Josefsson <simon_at_josefsson.org>
Date: Mon, 08 Jan 2007 14:24:39 +0100

Here are the first code changes to use libgcrypt. The idea here is to
first define generic libssh2_* APIs for the crypto calls, implement
that API using both libgcrypt and OpenSSL, and then change all callers
in libssh2 to use the internal API. (The idea is NOT to make these
libssh2_* interfaces be part of the public API of the libssh2
library.)

This is achieved by having libssh2_priv.h include the new files
"openssl.h" or "libgcrypt.h", respectively, which contains the glue
mappings. Eventually, files "openssl.c" and "libgcrypt.c", to hold
more complex functions, may be required, and the files could be
conditionally compiled using an automake directive. However, so far,
all the mappings are done via CPP #define's.

I have built libssh2 with both libgcrypt and OpenSSL with this patch
installed, and it seems to work fine (tested using curl, since there
are no self tests in libssh2 itself, hint, hint, nudge, nudge :)).

Comments? Any objections to installing this?

Thanks,
Simon

Index: src/Makefile.am
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/Makefile.am,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile.am
--- src/Makefile.am 20 Nov 2006 22:21:01 -0000 1.2
+++ src/Makefile.am 8 Jan 2007 13:19:51 -0000
@@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = foreign nostdinc
 
 libssh2_la_SOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c \
 misc.c packet.c publickey.c scp.c session.c sftp.c userauth.c \
-libssh2_priv.h
+libssh2_priv.h openssl.h libgcrypt.h
 
 EXTRA_DIST = libssh2_config.h.in
 
Index: src/channel.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/channel.c,v
retrieving revision 1.33
diff -u -p -r1.33 channel.c
--- src/channel.c 19 Nov 2006 13:26:19 -0000 1.33
+++ src/channel.c 8 Jan 2007 13:19:51 -0000
@@ -36,7 +36,6 @@
  */
 
 #include "libssh2_priv.h"
-#include <openssl/rand.h>
 #ifndef WIN32
 #include <unistd.h>
 #endif
@@ -637,7 +636,7 @@ LIBSSH2_API int libssh2_channel_x11_req_
                 int i;
                 unsigned char buffer[LIBSSH2_X11_RANDOM_COOKIE_LEN / 2];
 
- RAND_bytes(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
+ libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
                 for (i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
                         snprintf((char *)s + (i * 2), 2, "%02X", buffer[i]);
                 }
Index: src/hostkey.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/hostkey.c,v
retrieving revision 1.12
diff -u -p -r1.12 hostkey.c
--- src/hostkey.c 21 Dec 2006 14:19:42 -0000 1.12
+++ src/hostkey.c 8 Jan 2007 13:19:52 -0000
@@ -176,7 +176,7 @@ static int libssh2_hostkey_method_ssh_rs
 
         /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */
         sig += 15; sig_len -= 15;
- SHA1(m, m_len, hash);
+ libssh2_sha1(m, m_len, hash);
         ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
                          (unsigned char *)sig, sig_len, rsactx);
 
Index: src/kex.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/kex.c,v
retrieving revision 1.18
diff -u -p -r1.18 kex.c
--- src/kex.c 21 Dec 2006 14:24:55 -0000 1.18
+++ src/kex.c 8 Jan 2007 13:19:52 -0000
@@ -37,31 +37,29 @@
 
 #include "libssh2_priv.h"
 #include <openssl/bn.h>
-#include <openssl/sha.h>
-#include <openssl/rand.h>
 
 /* TODO: Switch this to an inline and handle alloc() failures */
 /* Helper macro called from libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange */
 #define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
 { \
- SHA_CTX hash; \
+ libssh2_sha1_ctx hash; \
         unsigned long len = 0; \
         if (!(value)) { \
                 value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
- } \
- while (len < reqlen) { \
- SHA1_Init(&hash); \
- SHA1_Update(&hash, k_value, k_value_len); \
- SHA1_Update(&hash, h_sig_comp, SHA_DIGEST_LENGTH); \
- if (len > 0) { \
- SHA1_Update(&hash, value, len); \
- } else { \
- SHA1_Update(&hash, (version), 1); \
- SHA1_Update(&hash, session->session_id, session->session_id_len); \
- } \
- SHA1_Final((value) + len, &hash); \
- len += SHA_DIGEST_LENGTH; \
- } \
+ } \
+ while (len < reqlen) { \
+ libssh2_sha1_init(&hash); \
+ libssh2_sha1_update(hash, k_value, k_value_len); \
+ libssh2_sha1_update(hash, h_sig_comp, SHA_DIGEST_LENGTH); \
+ if (len > 0) { \
+ libssh2_sha1_update(hash, value, len); \
+ } else { \
+ libssh2_sha1_update(hash, (version), 1); \
+ libssh2_sha1_update(hash, session->session_id, session->session_id_len); \
+ } \
+ libssh2_sha1_final(hash, (value) + len); \
+ len += SHA_DIGEST_LENGTH; \
+ } \
 }
 
 /* {{{ libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange
@@ -81,7 +79,7 @@ static int libssh2_kex_method_diffie_hel
         BIGNUM *k = BN_new(); /* The shared secret: f^x mod p */
         unsigned char *s, *f_value, *k_value = NULL, *h_sig;
         unsigned long f_value_len, k_value_len, h_sig_len;
- SHA_CTX exchange_hash;
+ libssh2_sha1_ctx exchange_hash;
 
         /* Generate x and e */
         BN_rand(x, group_order, 0, -1);
@@ -159,11 +157,11 @@ static int libssh2_kex_method_diffie_hel
 
 #ifndef OPENSSL_NO_MD5
 {
- MD5_CTX fingerprint_ctx;
+ libssh2_md5_ctx fingerprint_ctx;
 
- MD5_Init(&fingerprint_ctx);
- MD5_Update(&fingerprint_ctx, session->server_hostkey, session->server_hostkey_len);
- MD5_Final(session->server_hostkey_md5, &fingerprint_ctx);
+ libssh2_md5_init(&fingerprint_ctx);
+ libssh2_md5_update(fingerprint_ctx, session->server_hostkey, session->server_hostkey_len);
+ libssh2_md5_final(fingerprint_ctx, session->server_hostkey_md5);
 }
 #ifdef LIBSSH2_DEBUG_KEX
 {
@@ -180,11 +178,11 @@ static int libssh2_kex_method_diffie_hel
 
 #ifndef OPENSSL_NO_SHA
 {
- SHA_CTX fingerprint_ctx;
+ libssh2_sha1_ctx fingerprint_ctx;
 
- SHA1_Init(&fingerprint_ctx);
- SHA1_Update(&fingerprint_ctx, session->server_hostkey, session->server_hostkey_len);
- SHA1_Final(session->server_hostkey_sha1, &fingerprint_ctx);
+ libssh2_sha1_init(&fingerprint_ctx);
+ libssh2_sha1_update (fingerprint_ctx, session->server_hostkey, session->server_hostkey_len);
+ libssh2_sha1_final(fingerprint_ctx, session->server_hostkey_sha1);
 }
 #ifdef LIBSSH2_DEBUG_KEX
 {
@@ -233,36 +231,36 @@ static int libssh2_kex_method_diffie_hel
                 BN_bn2bin(k, k_value + 5);
         }
 
- SHA1_Init(&exchange_hash);
+ libssh2_sha1_init(&exchange_hash);
         if (session->local.banner) {
                 libssh2_htonu32(h_sig_comp,
                                 strlen((char *)session->local.banner) - 2);
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
- SHA1_Update(&exchange_hash, (char *)session->local.banner,
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, (char *)session->local.banner,
                             strlen((char *)session->local.banner) - 2);
         } else {
                 libssh2_htonu32(h_sig_comp, sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
- SHA1_Update(&exchange_hash, LIBSSH2_SSH_DEFAULT_BANNER,
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, LIBSSH2_SSH_DEFAULT_BANNER,
                             sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
         }
 
         libssh2_htonu32(h_sig_comp, strlen((char *)session->remote.banner));
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
- SHA1_Update(&exchange_hash, session->remote.banner,
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, session->remote.banner,
                     strlen((char *)session->remote.banner));
 
         libssh2_htonu32(h_sig_comp, session->local.kexinit_len);
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
- SHA1_Update(&exchange_hash, session->local.kexinit, session->local.kexinit_len);
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, session->local.kexinit, session->local.kexinit_len);
 
         libssh2_htonu32(h_sig_comp, session->remote.kexinit_len);
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
- SHA1_Update(&exchange_hash, session->remote.kexinit, session->remote.kexinit_len);
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, session->remote.kexinit, session->remote.kexinit_len);
 
         libssh2_htonu32(h_sig_comp, session->server_hostkey_len);
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
- SHA1_Update(&exchange_hash, session->server_hostkey, session->server_hostkey_len);
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, session->server_hostkey, session->server_hostkey_len);
 
         if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
                 /* diffie-hellman-group-exchange hashes additional fields */
@@ -270,26 +268,26 @@ static int libssh2_kex_method_diffie_hel
                 libssh2_htonu32(h_sig_comp, LIBSSH2_DH_GEX_MINGROUP);
                 libssh2_htonu32(h_sig_comp + 4, LIBSSH2_DH_GEX_OPTGROUP);
                 libssh2_htonu32(h_sig_comp + 8, LIBSSH2_DH_GEX_MAXGROUP);
- SHA1_Update(&exchange_hash, h_sig_comp, 12);
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 12);
 #else
                 libssh2_htonu32(h_sig_comp, LIBSSH2_DH_GEX_OPTGROUP);
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
 #endif
         }
 
         if (midhash) {
- SHA1_Update(&exchange_hash, midhash, midhash_len);
+ libssh2_sha1_update(exchange_hash, midhash, midhash_len);
         }
 
- SHA1_Update(&exchange_hash, e_packet + 1, e_packet_len - 1);
+ libssh2_sha1_update(exchange_hash, e_packet + 1, e_packet_len - 1);
 
         libssh2_htonu32(h_sig_comp, f_value_len);
- SHA1_Update(&exchange_hash, h_sig_comp, 4);
- SHA1_Update(&exchange_hash, f_value, f_value_len);
+ libssh2_sha1_update(exchange_hash, h_sig_comp, 4);
+ libssh2_sha1_update(exchange_hash, f_value, f_value_len);
 
- SHA1_Update(&exchange_hash, k_value, k_value_len);
+ libssh2_sha1_update(exchange_hash, k_value, k_value_len);
 
- SHA1_Final(h_sig_comp, &exchange_hash);
+ libssh2_sha1_final(exchange_hash, h_sig_comp);
 
         if (session->hostkey->sig_verify(session, h_sig, h_sig_len, h_sig_comp, 20, &session->server_hostkey_abstract)) {
                 libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN, "Unable to verify hostkey signature", 0);
@@ -758,7 +756,7 @@ static int libssh2_kexinit(LIBSSH2_SESSI
 
         *(s++) = SSH_MSG_KEXINIT;
 
- RAND_bytes(s, 16);
+ libssh2_random(s, 16);
         s += 16;
 
         /* Ennumerating through these lists twice is probably (certainly?) inefficient from a CPU standpoint, but it saves multiple malloc/realloc calls */
Index: src/libgcrypt.h
===================================================================
RCS file: src/libgcrypt.h
diff -N src/libgcrypt.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/libgcrypt.h 8 Jan 2007 13:19:52 -0000
@@ -0,0 +1,56 @@
+/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
+ * Author: Simon Josefsson
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * Neither the name of the copyright holder nor the names
+ * of any other contributors may be used to endorse or
+ * promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+#include <gcrypt.h>
+
+#define MD5_DIGEST_LENGTH 16
+#define SHA_DIGEST_LENGTH 20
+
+#define libssh2_random(buf, len) \
+ (gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1)
+
+#define libssh2_sha1_ctx gcry_md_hd_t
+#define libssh2_sha1_init(ctx) gcry_md_open (ctx, GCRY_MD_SHA1, 0);
+#define libssh2_sha1_update(ctx, data, len) gcry_md_write (ctx, data, len)
+#define libssh2_sha1_final(ctx, out) memcpy (out, gcry_md_read (ctx, 0), 20), gcry_md_close (ctx)
+#define libssh2_sha1(message, len, out) gcry_md_hash_buffer (GCRY_MD_SHA1, out, message, len)
+
+#define libssh2_md5_ctx gcry_md_hd_t
+#define libssh2_md5_init(ctx) gcry_md_open (ctx, GCRY_MD_MD5, 0);
+#define libssh2_md5_update(ctx, data, len) gcry_md_write (ctx, data, len)
+#define libssh2_md5_final(ctx, out) memcpy (out, gcry_md_read (ctx, 0), 20), gcry_md_close (ctx)
+#define libssh2_md5(message, len, out) gcry_md_hash_buffer (GCRY_MD_MD5, out, message, len)
Index: src/libssh2_priv.h
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/libssh2_priv.h,v
retrieving revision 1.3
diff -u -p -r1.3 libssh2_priv.h
--- src/libssh2_priv.h 7 Dec 2006 15:44:07 -0000 1.3
+++ src/libssh2_priv.h 8 Jan 2007 13:19:52 -0000
@@ -45,12 +45,11 @@
 #ifndef WIN32
 #include <sys/socket.h>
 #endif
-#include <openssl/evp.h>
-#ifndef OPENSSL_NO_SHA
-#include <openssl/sha.h>
-#endif
-#ifndef OPENSSL_NO_MD5
-#include <openssl/md5.h>
+
+#if LIBSSH2_LIBGCRYPT
+#include "libgcrypt.h"
+#else
+#include "openssl.h"
 #endif
 
 #define LIBSSH2_ALLOC(session, count) session->alloc((count), &(session)->abstract)
Index: src/openssl.h
===================================================================
RCS file: src/openssl.h
diff -N src/openssl.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/openssl.h 8 Jan 2007 13:19:52 -0000
@@ -0,0 +1,59 @@
+/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
+ * Author: Simon Josefsson
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * Neither the name of the copyright holder nor the names
+ * of any other contributors may be used to endorse or
+ * promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+#ifndef OPENSSL_NO_SHA
+#include <openssl/sha.h>
+#endif
+#ifndef OPENSSL_NO_MD5
+#include <openssl/md5.h>
+#endif
+#include <openssl/evp.h>
+
+#define libssh2_random(buf, len) \
+ RAND_bytes ((buf), (len))
+
+#define libssh2_sha1_ctx SHA_CTX
+#define libssh2_sha1_init(ctx) SHA1_Init(ctx)
+#define libssh2_sha1_update(ctx, data, len) SHA1_Update(&(ctx), data, len)
+#define libssh2_sha1_final(ctx, out) SHA1_Final(out, &(ctx))
+#define libssh2_sha1(message, len, out) SHA1(message, len, out)
+
+#define libssh2_md5_ctx SHA_CTX
+#define libssh2_md5_init(ctx) MD5_Init(ctx)
+#define libssh2_md5_update(ctx, data, len) MD5_Update(&(ctx), data, len)
+#define libssh2_md5_final(ctx, out) MD5_Final(out, &(ctx))
+#define libssh2_md5(message, len, out) MD5(message, len, out)
Index: src/packet.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/packet.c,v
retrieving revision 1.42
diff -u -p -r1.42 packet.c
--- src/packet.c 9 Dec 2006 09:09:16 -0000 1.42
+++ src/packet.c 8 Jan 2007 13:19:52 -0000
@@ -41,7 +41,6 @@
 #ifndef WIN32
 #include <unistd.h>
 #endif
-#include <openssl/rand.h>
 
 /* Needed for struct iovec on some platforms */
 #ifdef HAVE_SYS_UIO_H
@@ -1224,7 +1223,7 @@ int libssh2_packet_write(LIBSSH2_SESSION
                 /* Copy packet to encoding buffer */
                 memcpy(encbuf, buf, 5);
                 memcpy(encbuf + 5, data, data_len);
- RAND_bytes(encbuf + 5 + data_len, padding_length);
+ libssh2_random(encbuf + 5 + data_len, padding_length);
                 if (free_data) {
                         LIBSSH2_FREE(session, data);
                 }
Index: src/userauth.c
===================================================================
RCS file: /cvsroot/libssh2/libssh2/src/userauth.c,v
retrieving revision 1.18
diff -u -p -r1.18 userauth.c
--- src/userauth.c 13 Nov 2006 15:10:38 -0000 1.18
+++ src/userauth.c 8 Jan 2007 13:19:52 -0000
@@ -38,6 +38,7 @@
 #include "libssh2_priv.h"
 
 #include <ctype.h>
+#include <stdio.h>
 
 /* Needed for struct iovec on some platforms */
 #ifdef HAVE_SYS_UIO_H

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
libssh2-devel mailing list
libssh2-devel_at_lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libssh2-devel
Received on 2007-01-08