unable to use RSA SecureID on Unbuntu 14.04 LTS 64 bit

David Woodhouse dwmw2 at infradead.org
Thu Jul 31 17:21:24 PDT 2014


On Thu, 2014-07-31 at 10:28 -0700, Kevin Cernekee wrote:
> Don't know if anyone has tried to build libstoken under MinGW.

I had a quick look at this but Fedora doesn't have a mingw32-libtomcrypt
package. Here's an almost completely untested patch to make it use
nettle as an alternative. And then I get:

[dwoodhou at i7 stoken]$ make -k
make  all-am
make[1]: Entering directory `/ssd/git/stoken'
  CC       src/libstoken_la-library.lo
src/library.c: In function '__stoken_parse_and_decode_token':
src/library.c:71:3: error: implicit declaration of function 'strcasestr' [-Werror=implicit-function-declaration]
   p = strcasestr(str, "ctfData=3D");
   ^
src/library.c:71:3: warning: nested extern declaration of 'strcasestr' [-Wnested-externs]
src/library.c:71:5: warning: assignment makes pointer from integer without a cast [enabled by default]
   p = strcasestr(str, "ctfData=3D");
     ^
src/library.c:78:5: warning: assignment makes pointer from integer without a cast [enabled by default]
   p = strcasestr(str, "ctfData=");
     ^
src/library.c:85:5: warning: assignment makes pointer from integer without a cast [enabled by default]
   p = strcasestr(str, "<?xml ");
     ^
cc1: some warnings being treated as errors
make[1]: *** [src/libstoken_la-library.lo] Error 1
  CC       src/libstoken_la-securid.lo
src/securid.c: In function 'securid_compute_tokencode':
src/securid.c:984:2: error: implicit declaration of function 'gmtime_r' [-Werror=implicit-function-declaration]
  gmtime_r(&now, &gmt);
  ^
src/securid.c:984:2: warning: nested extern declaration of 'gmtime_r' [-Wnested-externs]
cc1: some warnings being treated as errors
make[1]: *** [src/libstoken_la-securid.lo] Error 1
  CC       src/libstoken_la-sdtid.lo
src/sdtid.c: In function 'format_date':
src/sdtid.c:660:2: error: implicit declaration of function 'gmtime_r' [-Werror=implicit-function-declaration]
  gmtime_r(&t, &tm);
  ^
src/sdtid.c:660:2: warning: nested extern declaration of 'gmtime_r' [-Wnested-externs]
cc1: some warnings being treated as errors
make[1]: *** [src/libstoken_la-sdtid.lo] Error 1
  CC       src/cli.o
src/cli.c:29:21: fatal error: termios.h: No such file or directory
 #include <termios.h>
                     ^
compilation terminated.
make[1]: *** [src/cli.o] Error 1
  CC       src/common.o
src/common.c:29:22: fatal error: sys/mman.h: No such file or directory
 #include <sys/mman.h>
                      ^
compilation terminated.
make[1]: *** [src/common.o] Error 1
make[1]: Target `all-am' not remade because of errors.
make[1]: Leaving directory `/ssd/git/stoken'
make: *** [all] Error 2
[dwoodhou at i7 stoken]$ 


diff --git a/Makefile.am b/Makefile.am
index 565af85..8e94842 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,16 @@
+if CRYPTO_NETTLE
+CRYPTO_LIBS = $(NETTLE_LIBS)
+CRYPTO_CFLAGS = $(NETTLE_CFLAGS)
+endif
+if CRYPTO_TOMCRYPT
+CRYPTO_LIBS = $(TOMCRYPT_LIBS)
+CRYPTO_CFLAGS = $(TOMCRYPT_CFLAGS)
+endif
+
 AUTOMAKE_OPTIONS	= foreign subdir-objects
 
 AM_CPPFLAGS		= -DDATA_DIR=\"$(datadir)\"
-AM_CFLAGS		= $(TOMCRYPT_CFLAGS) $(LIBXML2_CFLAGS) $(WFLAGS)
+AM_CFLAGS		= $(CRYPTO_CFLAGS) $(LIBXML2_CFLAGS) $(WFLAGS)
 
 dist_man_MANS		= stoken.1
 
@@ -10,7 +19,7 @@ libstoken_la_SOURCES	= src/library.c src/securid.c src/sdtid.c
 libstoken_la_CFLAGS	= $(AM_CFLAGS)
 libstoken_la_LDFLAGS	= -version-number @APIMAJOR@:@APIMINOR@
 libstoken_la_LDFLAGS	+= -Wl,--version-script, at srcdir@/libstoken.map
-libstoken_la_LIBADD	= $(TOMCRYPT_LIBS) $(LIBXML2_LIBS)
+libstoken_la_LIBADD	= $(CRYPTO_LIBS) $(LIBXML2_LIBS)
 libstoken_la_DEPENDENCIES = libstoken.map
 include_HEADERS		= src/stoken.h
 noinst_HEADERS		= src/common.h src/securid.h src/stoken-internal.h \
diff --git a/configure.ac b/configure.ac
index 0e10d07..24128bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,41 +113,60 @@ AM_CONDITIONAL([ENABLE_GUI], [test $enable_gui = yes])
 
 PKG_CHECK_MODULES([LIBXML2], [libxml-2.0])
 
-# libtomcrypt
-# Some distributions add a libtomcrypt.pc file, but it isn't in the upstream
-# libtomcrypt distribution so we can't count on it.
-
-tomcrypt_pkg=no
-
-if test "x$PKG_CONFIG" != x; then
-	PKG_CHECK_EXISTS([libtomcrypt], [tomcrypt_pkg=yes], [])
+AC_ARG_WITH([crypto],
+	[AS_HELP_STRING([--with-crypto=PACKAGE],
+	[Use PACKAGE (nettle/tomcrypt) for crypto [default=tomcrypt]])])
+if test "x$with_crypto" = "x"; then
+	with_crypto=tomcrypt
 fi
 
-if test $tomcrypt_pkg = no; then
-	AC_SUBST(TOMCRYPT_LIBS, [-ltomcrypt])
-	AC_SUBST(LIBTOMCRYPT_PC, [])
-	EXTRA_PC_LIBS="$EXTRA_PC_LIBS -ltomcrypt"
-else
-	AC_SUBST(LIBTOMCRYPT_PC, [libtomcrypt])
-	PKG_CHECK_MODULES([TOMCRYPT], libtomcrypt)
-fi
+case "$with_crypto" in
+     nettle)
+	PKG_CHECK_MODULES(NETTLE, nettle)
+	AC_SUBST(CRYPTO_PC, [nettle])
+	AC_DEFINE(CRYPTO_NETTLE, [1], [Use nettle for crypto])
+	;;
+     tomcrypt)
+	tomcrypt_pkg=no
+
+	# Try libtomcrypt
+	if test "x$PKG_CONFIG" != x; then
+		PKG_CHECK_EXISTS([libtomcrypt], [tomcrypt_pkg=yes], [])
+	fi
 
-saved_LIBS="$LIBS"
-saved_CFLAGS="$CFLAGS"
-LIBS="$LIBS $TOMCRYPT_LIBS"
-CFLAGS="$CFLAGS $TOMCRYPT_CFLAGS"
+	if test $tomcrypt_pkg = no; then
+		AC_SUBST(TOMCRYPT_LIBS, [-ltomcrypt])
+		AC_SUBST(LIBTOMCRYPT_PC, [])
+		EXTRA_PC_LIBS="$EXTRA_PC_LIBS -ltomcrypt"
+	else
+		AC_SUBST(CRYPTO_PC, [libtomcrypt])
+		PKG_CHECK_MODULES([TOMCRYPT], libtomcrypt)
+	fi
 
-AC_MSG_CHECKING([if libtomcrypt is usable])
-AC_TRY_LINK([#include <tomcrypt.h>],
-	[rijndael_ecb_encrypt(NULL,NULL,NULL);],
-	[AC_MSG_RESULT([yes])],
-	[AC_MSG_FAILURE([unable to link libtomcrypt test program])])
+	saved_LIBS="$LIBS"
+	saved_CFLAGS="$CFLAGS"
+	LIBS="$LIBS $TOMCRYPT_LIBS"
+	CFLAGS="$CFLAGS $TOMCRYPT_CFLAGS"
 
-LIBS="$saved_LIBS"
-CFLAGS="$saved_CFLAGS"
+	AC_MSG_CHECKING([if libtomcrypt is usable])
+	AC_TRY_LINK([#include <tomcrypt.h>],
+		[rijndael_ecb_encrypt(NULL,NULL,NULL);],
+		[AC_MSG_RESULT([yes])],
+		[AC_MSG_FAILURE([unable to link libtomcrypt test program])])
 
+	LIBS="$saved_LIBS"
+	CFLAGS="$saved_CFLAGS"
+	AC_DEFINE(CRYPTO_TOMCRYPT, [1], [Use libtomcrypt for crypto])
+	;;
+     *)
+        AC_MSG_FAILURE([Unrecognised crypto library "$with_crypto"])
+	;;
+esac
 AC_SUBST(EXTRA_PC_LIBS, [$EXTRA_PC_LIBS])
 
+AM_CONDITIONAL([CRYPTO_NETTLE], [test "$with_crypto" = "nettle"])
+AM_CONDITIONAL([CRYPTO_TOMCRYPT], [test "$with_crypto" = "tomcrypt"])
+
 # JNI
 
 AC_ARG_WITH([java],
diff --git a/src/sdtid.c b/src/sdtid.c
index 89990f7..ba00b60 100644
--- a/src/sdtid.c
+++ b/src/sdtid.c
@@ -27,10 +27,13 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
+#ifdef CRYPTO_TOMCRYPT
 #include <tomcrypt.h>
+#endif
 
 #include "securid.h"
 #include "sdtid.h"
@@ -338,8 +341,7 @@ static int lookup_b64(struct sdtid *s, const char *name, uint8_t *out,
 	if (*p && !strcmp(name, "Seed"))
 		p++;
 
-	len = base64_decode(p, strlen(p), out, &actual) == CRYPT_OK ?
-	      actual : -1;
+	len = base64_decode(p, strlen(p), out, &actual) ? -1 : actual;
 
 	free(data);
 	return len == buf_len ? 0 : -1;
diff --git a/src/securid.c b/src/securid.c
index 602880a..5f0148a 100644
--- a/src/securid.c
+++ b/src/securid.c
@@ -27,7 +27,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <tomcrypt.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
@@ -81,6 +80,36 @@ static uint8_t hex2byte(const char *in)
 	return (hex2nibble(in[0]) << 4) | hex2nibble(in[1]);
 }
 
+static int read_dev_random(const char *dev, void *out, int len)
+{
+	/*
+	 * Use /dev/random for long lived key material but not for
+	 * test purposes.  This can block for a long time if entropy
+	 * is limited.
+	 */
+	int fd;
+	char *p = out;
+
+	fd = open(dev, O_RDONLY);
+	if (fd < 0)
+		return ERR_GENERAL;
+
+	while (len) {
+		ssize_t ret = read(fd, p, len);
+		if (ret < 0) {
+			close(fd);
+			return ERR_GENERAL;
+		}
+		p += ret;
+		len -= ret;
+	}
+	close(fd);
+	return ERR_NONE;
+}
+
+#ifdef CRYPTO_TOMCRYPT
+#include <tomcrypt.h>
+
 void aes128_ecb_encrypt(const uint8_t *key, const uint8_t *in, uint8_t *out)
 {
 	symmetric_key skey;
@@ -153,36 +182,175 @@ static void aes256_cbc_encrypt(const uint8_t *key, const uint8_t *in, int in_len
 
 int securid_rand(void *out, int len, int paranoid)
 {
-	if (paranoid) {
-		/*
-		 * Use /dev/random for long lived key material but not for
-		 * test purposes.  This can block for a long time if entropy
-		 * is limited.
-		 */
-		int fd;
-		char *p = out;
+	if (paranoid)
+		return read_dev_random("/dev/random", out, len);
 
-		fd = open("/dev/random", O_RDONLY);
-		if (fd < 0)
-			return ERR_GENERAL;
+	if (rng_get_bytes(out, len, NULL) != len)
+		return ERR_GENERAL;
 
-		while (len) {
-			ssize_t ret = read(fd, p, len);
-			if (ret < 0) {
-				close(fd);
-				return ERR_GENERAL;
-			}
-			p += ret;
-			len -= ret;
-		}
-		close(fd);
-	} else {
-		if (rng_get_bytes(out, len, NULL) != len)
-			return ERR_GENERAL;
-	}
 	return ERR_NONE;
 }
 
+static void sha256_hash(const uint8_t *in, int in_len, uint8_t *out)
+{
+	hash_state md;
+	sha256_init(&md);
+	sha256_process(&md, in, in_len);
+	sha256_done(&md, out);
+}
+
+static void sha256_hmac(const uint8_t *key, int key_len,
+			const uint8_t *msg, int msg_len, uint8_t *out)
+{
+	hash_state md;
+	uint8_t tmp_key[SHA256_HASH_SIZE], o_key_pad[SHA256_BLOCK_SIZE],
+		i_key_pad[SHA256_BLOCK_SIZE], inner_hash[SHA256_BLOCK_SIZE];
+	int i;
+
+	if (key_len > SHA256_BLOCK_SIZE) {
+		sha256_hash(key, key_len, tmp_key);
+		key = tmp_key;
+		key_len = SHA256_HASH_SIZE;
+	}
+
+	memset(o_key_pad, 0x5c, SHA256_BLOCK_SIZE);
+	memset(i_key_pad, 0x36, SHA256_BLOCK_SIZE);
+	for (i = 0; i < key_len; i++) {
+		o_key_pad[i] ^= key[i];
+		i_key_pad[i] ^= key[i];
+	}
+
+	sha256_init(&md);
+	sha256_process(&md, i_key_pad, SHA256_BLOCK_SIZE);
+	sha256_process(&md, msg, msg_len);
+	sha256_done(&md, inner_hash);
+
+	sha256_init(&md);
+	sha256_process(&md, o_key_pad, SHA256_BLOCK_SIZE);
+	sha256_process(&md, inner_hash, SHA256_HASH_SIZE);
+	sha256_done(&md, out);
+}
+#elif defined (CRYPTO_NETTLE)
+#include <nettle/base64.h>
+#include <nettle/sha2.h>
+#include <nettle/hmac.h>
+#include <nettle/aes.h>
+#include <nettle/cbc.h>
+
+/* Ick. */
+#undef AES_KEY_SIZE
+#define AES_KEY_SIZE 16
+
+void aes128_ecb_encrypt(const uint8_t *key, const uint8_t *in, uint8_t *out)
+{
+	struct aes_ctx ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+	aes_set_encrypt_key(&ctx, AES_MIN_KEY_SIZE, key);
+	aes_encrypt(&ctx, AES_BLOCK_SIZE, out, in);
+}
+
+void aes128_ecb_decrypt(const uint8_t *key, const uint8_t *in, uint8_t *out)
+{
+	struct aes_ctx ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+	aes_set_decrypt_key(&ctx, AES_MIN_KEY_SIZE, key);
+	aes_decrypt(&ctx, AES_BLOCK_SIZE, out, in);
+}
+
+
+
+static void aes256_cbc_encrypt(const uint8_t *key, const uint8_t *in, int in_len,
+			       const uint8_t *iv, uint8_t *out)
+{
+	struct CBC_CTX(struct aes_ctx, AES_BLOCK_SIZE) cbc;
+
+	memset(&cbc.ctx, 0, sizeof(cbc.ctx));
+	aes_set_encrypt_key(&cbc.ctx, AES_MAX_KEY_SIZE, key);
+	CBC_SET_IV(&cbc, iv);
+
+	CBC_ENCRYPT(&cbc, aes_encrypt, in_len, out, in);
+}
+
+static void aes256_cbc_decrypt(const uint8_t *key, const uint8_t *in, int in_len,
+			       const uint8_t *iv, uint8_t *out)
+{
+	struct CBC_CTX(struct aes_ctx, AES_BLOCK_SIZE) cbc;
+
+	memset(&cbc.ctx, 0, sizeof(cbc.ctx));
+	aes_set_decrypt_key(&cbc.ctx, AES_MAX_KEY_SIZE, key);
+	CBC_SET_IV(&cbc, iv);
+
+	CBC_DECRYPT(&cbc, aes_decrypt, in_len, out, in);
+}
+
+int securid_rand(void *out, int len, int paranoid)
+{
+
+	return read_dev_random(paranoid ? "/dev/random" : "/dev/urandom",
+			       out, len);
+}
+
+static void sha256_hash(const uint8_t *in, int in_len, uint8_t *out)
+{
+	struct sha256_ctx ctx;
+
+	sha256_init(&ctx);
+	sha256_update(&ctx, in_len, in);
+	sha256_digest(&ctx, SHA256_DIGEST_SIZE, out);
+}
+
+static void sha256_hmac(const uint8_t *key, int key_len,
+			const uint8_t *msg, int msg_len, uint8_t *out)
+{
+	struct hmac_sha256_ctx hmac;
+
+	hmac_sha256_set_key(&hmac, key_len, key);
+	hmac_sha256_update(&hmac, msg_len, msg);
+	hmac_sha256_digest(&hmac, SHA256_DIGEST_SIZE, out);
+}
+
+int __stoken_base64_encode(const uint8_t *in, unsigned long in_len,
+			   uint8_t *out, unsigned long *out_len)
+{
+	struct base64_encode_ctx ctx;
+
+	base64_encode_init(&ctx);
+
+	/* This should never happen and the callers don't check */
+	if (*out_len < BASE64_ENCODE_LENGTH(in_len))
+		abort();
+	*out_len = base64_encode_update(&ctx, out, in_len, in);
+	out += *out_len;
+	*out_len += base64_encode_final(&ctx, out);
+
+	return 0;
+}
+
+int __stoken_base64_decode(const uint8_t *in, unsigned long in_len,
+			   uint8_t *out, unsigned long *out_len)
+{
+	struct base64_decode_ctx ctx;
+	unsigned int s;
+
+	base64_decode_init(&ctx);
+
+	/* This should never happen and the callers don't check */
+	if (*out_len < BASE64_DECODE_LENGTH(in_len))
+		abort();
+	if (!base64_decode_update(&ctx, &s, out, in_len, in))
+		return -EILSEQ;
+	if (!base64_decode_final(&ctx))
+		return -EILSEQ;
+
+	*out_len = s;
+
+	return 0;
+}
+
+#endif /* Nettle */
+
 static void encrypt_then_xor(const uint8_t *key, uint8_t *work, uint8_t *enc)
 {
 	int i;
@@ -236,46 +404,6 @@ static uint16_t securid_shortmac(const uint8_t *in, int in_len)
 	return (hash[0] << 7) | (hash[1] >> 1);
 }
 
-static void sha256_hash(const uint8_t *in, int in_len, uint8_t *out)
-{
-	hash_state md;
-	sha256_init(&md);
-	sha256_process(&md, in, in_len);
-	sha256_done(&md, out);
-}
-
-static void sha256_hmac(const uint8_t *key, int key_len,
-			const uint8_t *msg, int msg_len, uint8_t *out)
-{
-	hash_state md;
-	uint8_t tmp_key[SHA256_HASH_SIZE], o_key_pad[SHA256_BLOCK_SIZE],
-		i_key_pad[SHA256_BLOCK_SIZE], inner_hash[SHA256_BLOCK_SIZE];
-	int i;
-
-	if (key_len > SHA256_BLOCK_SIZE) {
-		sha256_hash(key, key_len, tmp_key);
-		key = tmp_key;
-		key_len = SHA256_HASH_SIZE;
-	}
-
-	memset(o_key_pad, 0x5c, SHA256_BLOCK_SIZE);
-	memset(i_key_pad, 0x36, SHA256_BLOCK_SIZE);
-	for (i = 0; i < key_len; i++) {
-		o_key_pad[i] ^= key[i];
-		i_key_pad[i] ^= key[i];
-	}
-
-	sha256_init(&md);
-	sha256_process(&md, i_key_pad, SHA256_BLOCK_SIZE);
-	sha256_process(&md, msg, msg_len);
-	sha256_done(&md, inner_hash);
-
-	sha256_init(&md);
-	sha256_process(&md, o_key_pad, SHA256_BLOCK_SIZE);
-	sha256_process(&md, inner_hash, SHA256_HASH_SIZE);
-	sha256_done(&md, out);
-}
-
 static void sha256_pbkdf2(const uint8_t *pass, int pass_len,
 			  const uint8_t *salt, int salt_len,
 			  int n_rounds, uint8_t *key_out)
@@ -609,7 +737,7 @@ static int v3_decode_token(const char *in, struct securid_token *t)
 		return ERR_NO_MEMORY;
 
 	if (base64_decode(decoded, strlen(decoded),
-			  (void *)t->v3, &actual) != CRYPT_OK ||
+			  (void *)t->v3, &actual) ||
 	    actual != sizeof(struct v3_token) ||
 	    t->v3->version != 0x03) {
 		free(t->v3);
diff --git a/src/stoken-internal.h b/src/stoken-internal.h
index 2b94217..7792102 100644
--- a/src/stoken-internal.h
+++ b/src/stoken-internal.h
@@ -22,6 +22,7 @@
 #define __STOKEN_INTERNAL_H__
 
 #include "stoken.h"
+#include <stdint.h>
 
 #define BUFLEN			2048
 #define RC_NAME			".stokenrc"
@@ -62,6 +63,15 @@ int __stoken_write_rcfile(const char *override, const struct stoken_cfg *cfg,
 	warn_fn_t warn_fn);
 void __stoken_zap_rcfile_data(struct stoken_cfg *cfg);
 
+#ifdef CRYPTO_NETTLE
+int __stoken_base64_decode(const uint8_t *in, unsigned long in_len,
+			   uint8_t *out, unsigned long *out_len);
+int __stoken_base64_encode(const uint8_t *in, unsigned long in_len,
+			   uint8_t *out, unsigned long *out_len);
+#define base64_decode __stoken_base64_decode
+#define base64_encode __stoken_base64_encode
+#endif
+
 #ifdef __ANDROID__
 /* Sigh.  This exists but it isn't in the Bionic headers. */
 int mkstemps(char *path, int slen);
diff --git a/stoken.pc.in b/stoken.pc.in
index d605bbc..73a812c 100644
--- a/stoken.pc.in
+++ b/stoken.pc.in
@@ -6,6 +6,6 @@ includedir=@includedir@
 Name: stoken
 Description: Software token
 Version: @VERSION@
-Requires.private: @LIBTOMCRYPT_PC@
+Requires.private: @CRYPTO_PC@
 Libs: -L${libdir} -lstoken @EXTRA_PC_LIBS@
 Cflags: -I${includedir}


-- 
dwmw2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5745 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20140801/e503c88a/attachment.bin>


More information about the openconnect-devel mailing list