[PATCH] Updated: EVP_MAC interface for Poly1305

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

 



I've updated the patch to allow for the use of the EVP_MAC interface under OpenSSL 3.0. The test is now in configure and explicitly tests to see if the poly1305 algorithm can be loaded via EVP_MAC_fetch. I've also move the EVP calls to poly1305.c. To do this I had to extend the poly1305_auth interface to include another parameter. If the poly1305 MAC is available it will pass in the mac context. Otherwise it will pass a NULL. Throughput performance, in my test bed is, a bit more than double in comparison to baseline. Obviously results will vary but there is a significantly reduction in CPU utilization.

I was told that my mailer (thunderbird) was breaking patches so I've include the patch both inline and attached.
diff --git a/cipher-chachapoly-libcrypto.c b/cipher-chachapoly-libcrypto.c
index 719f9c843..7dbbe7ee1 100644
--- a/cipher-chachapoly-libcrypto.c
+++ b/cipher-chachapoly-libcrypto.c
@@ -35,8 +35,18 @@
 #include "ssherr.h"
 #include "cipher-chachapoly.h"

+
+/* using the EVP_MAC interface for poly1305 is significantly
+ * faster than the version bundled with OpenSSH. However,
+ * this interface is only available in OpenSSL 3.0+
+ * -cjr 10/21/2022 */
 struct chachapoly_ctx {
 	EVP_CIPHER_CTX *main_evp, *header_evp;
+#ifdef OPENSSL_HAVE_POLY_EVP
+	EVP_MAC_CTX    *poly_ctx;
+#else
+	char           *poly_ctx;
+#endif
 };

 struct chachapoly_ctx *
@@ -57,6 +67,15 @@ chachapoly_new(const u_char *key, u_int keylen)
 		goto fail;
 	if (EVP_CIPHER_CTX_iv_length(ctx->header_evp) != 16)
 		goto fail;
+#ifdef OPENSSL_HAVE_POLY_EVP
+	EVP_MAC *mac = NULL;
+	if ((mac = EVP_MAC_fetch(NULL, "POLY1305", NULL)) == NULL)
+		goto fail;
+	if ((ctx->poly_ctx = EVP_MAC_CTX_new(mac)) == NULL)
+		goto fail;
+#else
+	ctx->poly_ctx = NULL;
+#endif
 	return ctx;
  fail:
 	chachapoly_free(ctx);
@@ -70,6 +89,9 @@ chachapoly_free(struct chachapoly_ctx *cpctx)
 		return;
 	EVP_CIPHER_CTX_free(cpctx->main_evp);
 	EVP_CIPHER_CTX_free(cpctx->header_evp);
+#ifdef OPENSSL_HAVE_POLY_EVP
+	EVP_MAC_CTX_free(cpctx->poly_ctx);
+#endif
 	freezero(cpctx, sizeof(*cpctx));
 }

@@ -107,8 +129,7 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
 	/* If decrypting, check tag before anything else */
 	if (!do_encrypt) {
 		const u_char *tag = src + aadlen + len;
-
-		poly1305_auth(expected_tag, src, aadlen + len, poly_key);
+		poly1305_auth(ctx->poly_ctx, expected_tag, src, aadlen + len, poly_key);
 		if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
 			r = SSH_ERR_MAC_INVALID;
 			goto out;
@@ -134,8 +155,8 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,

 	/* If encrypting, calculate and append tag */
 	if (do_encrypt) {
-		poly1305_auth(dest + aadlen + len, dest, aadlen + len,
-		    poly_key);
+	  poly1305_auth(ctx->poly_ctx, dest + aadlen + len, dest, aadlen + len,
+			poly_key);
 	}
 	r = 0;
  out:
diff --git a/cipher-chachapoly.c b/cipher-chachapoly.c
index 716f8d426..136d2d502 100644
--- a/cipher-chachapoly.c
+++ b/cipher-chachapoly.c
@@ -89,7 +89,7 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
 	if (!do_encrypt) {
 		const u_char *tag = src + aadlen + len;

-		poly1305_auth(expected_tag, src, aadlen + len, poly_key);
+		poly1305_auth(NULL, expected_tag, src, aadlen + len, poly_key);
 		if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
 			r = SSH_ERR_MAC_INVALID;
 			goto out;
@@ -109,7 +109,7 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,

 	/* If encrypting, calculate and append tag */
 	if (do_encrypt) {
-		poly1305_auth(dest + aadlen + len, dest, aadlen + len,
+		poly1305_auth(NULL, dest + aadlen + len, dest, aadlen + len,
 		    poly_key);
 	}
 	r = 0;
diff --git a/configure.ac b/configure.ac
index 8a18f8381..5fe3ae74c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2932,6 +2933,30 @@ if test "x$openssl" = "xyes" ; then
 		EVP_chacha20 \
 	])

+	# OpenSSL 3.0 API
+	# Does OpenSSL support the EVP_MAC functions for Poly1305?
+	AC_MSG_CHECKING([whether OpenSSL supports Poly1305 MAC EVP])
+	AC_RUN_IFELSE(
+		[AC_LANG_PROGRAM([[
+	#include <stdlib.h>
+	#include <stdio.h>
+	#include <openssl/evp.h>
+		]], [[
+		EVP_MAC *mac = EVP_MAC_fetch(NULL, "poly1305", NULL);
+		if (mac == NULL)
+		   exit(1);
+		]])],
+		[
+			AC_MSG_RESULT([yes])
+			AC_DEFINE([OPENSSL_HAVE_POLY_EVP], [1],
+			    [Libcrypto supports Poly1305 MAC EVP])
+		],
+		[
+			AC_MSG_RESULT([no])
+		]
+	)
+
+
 	if test "x$openssl_engine" = "xyes" ; then
 		AC_MSG_CHECKING([for OpenSSL ENGINE support])
 		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
diff --git a/poly1305.c b/poly1305.c
index 6fd1fc8cd..53ebff884 100644
--- a/poly1305.c
+++ b/poly1305.c
@@ -13,6 +13,15 @@
 #endif

 #include "poly1305.h"
+#ifdef OPENSSL_HAVE_POLY_EVP
+void
+poly1305_auth(EVP_MAC_CTX *poly_ctx, unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
+	size_t poly_out_len;
+	EVP_MAC_init(poly_ctx, (const u_char *)key, POLY1305_KEYLEN, NULL);
+	EVP_MAC_update(poly_ctx, m, inlen);
+	EVP_MAC_final(poly_ctx, out, &poly_out_len, (size_t)POLY1305_TAGLEN);
+}
+#else

 #define mul32x32_64(a,b) ((uint64_t)(a) * (b))

@@ -31,7 +42,7 @@
 	} while (0)

 void
-poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) { +poly1305_auth(char *unused, unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
 	uint32_t t0,t1,t2,t3;
 	uint32_t h0,h1,h2,h3,h4;
 	uint32_t r0,r1,r2,r3,r4;
@@ -158,3 +169,4 @@ poly1305_donna_finish:
 	U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32);
 	U32TO8_LE(&out[12], f3);
 }
+#endif /* OPENSSL_HAVE_POLY_EVP */
diff --git a/poly1305.h b/poly1305.h
index f7db5f8d7..db2524b24 100644
--- a/poly1305.h
+++ b/poly1305.h
@@ -13,8 +13,15 @@
 #define POLY1305_KEYLEN		32
 #define POLY1305_TAGLEN		16

-void poly1305_auth(u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen,
+#ifdef OPENSSL_HAVE_POLY_EVP
+#include <openssl/evp.h>
+
+void poly1305_auth(EVP_MAC_CTX *poly_key, u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen,
+    const u_char key[POLY1305_KEYLEN])
+#else
+void poly1305_auth(char *unused, u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen,
     const u_char key[POLY1305_KEYLEN])
+#endif
     __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN)))
     __attribute__((__bounded__(__buffer__, 2, 3)))
     __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN)));
diff --git a/cipher-chachapoly-libcrypto.c b/cipher-chachapoly-libcrypto.c
index 719f9c843..7dbbe7ee1 100644
--- a/cipher-chachapoly-libcrypto.c
+++ b/cipher-chachapoly-libcrypto.c
@@ -35,8 +35,18 @@
 #include "ssherr.h"
 #include "cipher-chachapoly.h"
 
+
+/* using the EVP_MAC interface for poly1305 is significantly
+ * faster than the version bundled with OpenSSH. However,
+ * this interface is only available in OpenSSL 3.0+
+ * -cjr 10/21/2022 */
 struct chachapoly_ctx {
 	EVP_CIPHER_CTX *main_evp, *header_evp;
+#ifdef OPENSSL_HAVE_POLY_EVP
+	EVP_MAC_CTX    *poly_ctx;
+#else
+	char           *poly_ctx;
+#endif
 };
 
 struct chachapoly_ctx *
@@ -57,6 +67,15 @@ chachapoly_new(const u_char *key, u_int keylen)
 		goto fail;
 	if (EVP_CIPHER_CTX_iv_length(ctx->header_evp) != 16)
 		goto fail;
+#ifdef OPENSSL_HAVE_POLY_EVP
+	EVP_MAC *mac = NULL;
+	if ((mac = EVP_MAC_fetch(NULL, "POLY1305", NULL)) == NULL)
+		goto fail;
+	if ((ctx->poly_ctx = EVP_MAC_CTX_new(mac)) == NULL)
+		goto fail;
+#else
+	ctx->poly_ctx = NULL;
+#endif
 	return ctx;
  fail:
 	chachapoly_free(ctx);
@@ -70,6 +89,9 @@ chachapoly_free(struct chachapoly_ctx *cpctx)
 		return;
 	EVP_CIPHER_CTX_free(cpctx->main_evp);
 	EVP_CIPHER_CTX_free(cpctx->header_evp);
+#ifdef OPENSSL_HAVE_POLY_EVP
+	EVP_MAC_CTX_free(cpctx->poly_ctx);
+#endif
 	freezero(cpctx, sizeof(*cpctx));
 }
 
@@ -107,8 +129,7 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
 	/* If decrypting, check tag before anything else */
 	if (!do_encrypt) {
 		const u_char *tag = src + aadlen + len;
-
-		poly1305_auth(expected_tag, src, aadlen + len, poly_key);
+		poly1305_auth(ctx->poly_ctx, expected_tag, src, aadlen + len, poly_key);
 		if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
 			r = SSH_ERR_MAC_INVALID;
 			goto out;
@@ -134,8 +155,8 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
 
 	/* If encrypting, calculate and append tag */
 	if (do_encrypt) {
-		poly1305_auth(dest + aadlen + len, dest, aadlen + len,
-		    poly_key);
+	  poly1305_auth(ctx->poly_ctx, dest + aadlen + len, dest, aadlen + len,
+			poly_key);
 	}
 	r = 0;
  out:
diff --git a/cipher-chachapoly.c b/cipher-chachapoly.c
index 716f8d426..136d2d502 100644
--- a/cipher-chachapoly.c
+++ b/cipher-chachapoly.c
@@ -89,7 +89,7 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
 	if (!do_encrypt) {
 		const u_char *tag = src + aadlen + len;
 
-		poly1305_auth(expected_tag, src, aadlen + len, poly_key);
+		poly1305_auth(NULL, expected_tag, src, aadlen + len, poly_key);
 		if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
 			r = SSH_ERR_MAC_INVALID;
 			goto out;
@@ -109,7 +109,7 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
 
 	/* If encrypting, calculate and append tag */
 	if (do_encrypt) {
-		poly1305_auth(dest + aadlen + len, dest, aadlen + len,
+		poly1305_auth(NULL, dest + aadlen + len, dest, aadlen + len,
 		    poly_key);
 	}
 	r = 0;
diff --git a/configure.ac b/configure.ac
index 8a18f8381..5fe3ae74c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2932,6 +2933,30 @@ if test "x$openssl" = "xyes" ; then
 		EVP_chacha20 \
 	])
 
+	# OpenSSL 3.0 API
+	# Does OpenSSL support the EVP_MAC functions for Poly1305?
+	AC_MSG_CHECKING([whether OpenSSL supports Poly1305 MAC EVP])
+	AC_RUN_IFELSE(
+		[AC_LANG_PROGRAM([[
+	#include <stdlib.h>
+	#include <stdio.h>
+	#include <openssl/evp.h>
+		]], [[
+		EVP_MAC *mac = EVP_MAC_fetch(NULL, "poly1305", NULL);
+		if (mac == NULL)
+		   exit(1);
+		]])],
+		[
+			AC_MSG_RESULT([yes])
+			AC_DEFINE([OPENSSL_HAVE_POLY_EVP], [1],
+			    [Libcrypto supports Poly1305 MAC EVP])
+		],
+		[
+			AC_MSG_RESULT([no])
+		]
+	)
+
+
 	if test "x$openssl_engine" = "xyes" ; then
 		AC_MSG_CHECKING([for OpenSSL ENGINE support])
 		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
diff --git a/poly1305.c b/poly1305.c
index 6fd1fc8cd..53ebff884 100644
--- a/poly1305.c
+++ b/poly1305.c
@@ -13,6 +13,15 @@
 #endif
 
 #include "poly1305.h"
+#ifdef OPENSSL_HAVE_POLY_EVP
+void
+poly1305_auth(EVP_MAC_CTX *poly_ctx, unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
+	size_t poly_out_len;
+	EVP_MAC_init(poly_ctx, (const u_char *)key, POLY1305_KEYLEN, NULL);
+	EVP_MAC_update(poly_ctx, m, inlen);
+	EVP_MAC_final(poly_ctx, out, &poly_out_len, (size_t)POLY1305_TAGLEN);
+}
+#else
 
 #define mul32x32_64(a,b) ((uint64_t)(a) * (b))
 
@@ -31,7 +42,7 @@
 	} while (0)
 
 void
-poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
+poly1305_auth(char *unused, unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
 	uint32_t t0,t1,t2,t3;
 	uint32_t h0,h1,h2,h3,h4;
 	uint32_t r0,r1,r2,r3,r4;
@@ -158,3 +169,4 @@ poly1305_donna_finish:
 	U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32);
 	U32TO8_LE(&out[12], f3);
 }
+#endif /* OPENSSL_HAVE_POLY_EVP */
diff --git a/poly1305.h b/poly1305.h
index f7db5f8d7..db2524b24 100644
--- a/poly1305.h
+++ b/poly1305.h
@@ -13,8 +13,15 @@
 #define POLY1305_KEYLEN		32
 #define POLY1305_TAGLEN		16
 
-void poly1305_auth(u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen,
+#ifdef OPENSSL_HAVE_POLY_EVP
+#include <openssl/evp.h>
+
+void poly1305_auth(EVP_MAC_CTX *poly_key, u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen,
+    const u_char key[POLY1305_KEYLEN])
+#else
+void poly1305_auth(char *unused, u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen,
     const u_char key[POLY1305_KEYLEN])
+#endif
     __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN)))
     __attribute__((__bounded__(__buffer__, 2, 3)))
     __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN)));
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux