- djm@cvs.openbsd.org 2014/01/12 08:13:13
     [bufaux.c buffer.h kex.c kex.h kexc25519.c kexc25519c.c kexc25519s.c]
     [kexdhc.c kexdhs.c kexecdhc.c kexecdhs.c kexgexc.c kexgexs.c]
     avoid use of OpenSSL BIGNUM type and functions for KEX with
     Curve25519 by adding a buffer_put_bignum2_from_string() that stores
     a string using the bignum encoding rules. Will make it easier to
     build a reduced-feature OpenSSH without OpenSSL in the future;
     ok markus@
diff --git a/bufaux.c b/bufaux.c
index 3e70b8d..9401fe1 100644
--- a/bufaux.c
+++ b/bufaux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bufaux.c,v 1.53 2013/11/08 11:15:19 dtucker Exp $ */
+/* $OpenBSD: bufaux.c,v 1.54 2014/01/12 08:13:13 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -315,3 +315,76 @@
 
 	buffer_append(buffer, &ch, 1);
 }
+
+/* Pseudo bignum functions */
+
+void *
+buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr)
+{
+	u_int len;
+	u_char *bin, *p, *ret;
+
+	if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) {
+		error("%s: invalid bignum", __func__);
+		return NULL;
+	}
+
+	if (len > 0 && (bin[0] & 0x80)) {
+		error("%s: negative numbers not supported", __func__);
+		free(bin);
+		return NULL;
+	}
+	if (len > 8 * 1024) {
+		error("%s: cannot handle BN of size %d", __func__, len);
+		free(bin);
+		return NULL;
+	}
+	/* Skip zero prefix on numbers with the MSB set */
+	if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) {
+		p++;
+		len--;
+	}
+	ret = xmalloc(len);
+	memcpy(ret, p, len);
+	memset(p, '\0', len);
+	free(bin);
+	return ret;
+}
+
+void *
+buffer_get_bignum2_as_string(Buffer *buffer, u_int *l)
+{
+	void *ret = buffer_get_bignum2_as_string_ret(buffer, l);
+
+	if (ret == NULL)
+		fatal("%s: buffer error", __func__);
+	return ret;
+}
+
+/*
+ * Stores a string using the bignum encoding rules (\0 pad if MSB set).
+ */
+void
+buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
+{
+	u_char *buf, *p;
+	int pad = 0;
+
+	if (l > 8 * 1024)
+		fatal("%s: length %u too long", __func__, l);
+	p = buf = xmalloc(l + 1);
+	/*
+	 * If most significant bit is set then prepend a zero byte to
+	 * avoid interpretation as a negative number.
+	 */
+	if (l > 0 && (s[0] & 0x80) != 0) {
+		*p++ = '\0';
+		pad = 1;
+	}
+	memcpy(p, s, l);
+	buffer_put_string(buffer, buf, l + pad);
+	memset(buf, '\0', l + pad);
+	free(buf);
+}
+
+