[Git][NTPsec/ntpsec][master] 2 commits: Add CMAC timing to attic/digest-timing.c

Hal Murray gitlab at mg.gitlab.com
Fri Mar 2 08:46:49 UTC 2018


Hal Murray pushed to branch master at NTPsec / ntpsec


Commits:
86f85050 by Hal Murray at 2018-03-02T08:46:14Z
Add CMAC timing to attic/digest-timing.c

- - - - -
b01f1d65 by Hal Murray at 2018-03-02T08:46:14Z
Truncate digests longer than 20 bytes.

- - - - -


6 changed files:

- attic/digest-timing.c
- docs/authentic.txt
- docs/includes/ntp.keys-body.txt
- include/ntp_types.h
- libntp/authreadkeys.c
- libntp/macencrypt.c


Changes:

=====================================
attic/digest-timing.c
=====================================
--- a/attic/digest-timing.c
+++ b/attic/digest-timing.c
@@ -6,6 +6,10 @@
  * It doesn't include the copy or compare or finding the right key.
  *
  * Beware of overflows in the timing computations.
+ *
+ * Disable AES-NI (Intel hardware: NI == New Instruction) with:
+ *    OPENSSL_ia32cap="~0x200000200000000"
+ * Check /proc/cpuinfo flags for "aes" to see if you have it.
  */
 
 #include <stdint.h>
@@ -14,6 +18,7 @@
 #include <time.h>
 
 #include <openssl/err.h>
+#include <openssl/cmac.h>
 #include <openssl/evp.h>
 #include <openssl/md5.h>
 #include <openssl/rand.h>
@@ -39,18 +44,20 @@ int NUM = 1000000;
 /* Nothing magic about these key lengths.
  * ntpkeygen just happens to label things this way.
  */
+#define AES_KEY_LENGTH 16
 #define MD5_KEY_LENGTH 16
 #define SHA1_KEY_LENGTH 20
 #define MAX_KEY_LENGTH 64
 
 EVP_MD_CTX *ctx;
+CMAC_CTX *cmac;
 
-void ssl_init(void);
-void ssl_init(void)
+static void ssl_init(void)
 {
   ERR_load_crypto_strings();
   OpenSSL_add_all_digests();
   ctx = EVP_MD_CTX_new();
+  cmac = CMAC_CTX_new();
 }
 
 static unsigned int SSL_Digest(
@@ -89,7 +96,23 @@ static unsigned int SSL_DigestSlow(
   return len;
 }
 
-static void DoOne(
+static size_t SSL_CMAC(
+  const EVP_CIPHER *cipher, /* cipher algorithm */
+  uint8_t *key,             /* key pointer */
+  int     keylength,        /* key size */
+  uint8_t *pkt,             /* packet pointer */
+  int     pktlength         /* packet length */
+) {
+  unsigned char answer[EVP_MAX_MD_SIZE];
+  size_t len;
+  CMAC_resume(cmac);
+  CMAC_Init(cmac, key, keylength, cipher, NULL);
+  CMAC_Update(cmac, pkt, pktlength);
+  CMAC_Final(cmac, answer, &len);
+  return len;
+}
+
+static void DoDigest(
   const char *name,       /* type of digest */
   uint8_t *key,           /* key pointer */
   int     keylength,      /* key size */
@@ -128,6 +151,34 @@ static void DoOne(
   printf("\n");
 }
 
+static void DoCMAC(
+  const char *name,       /* name of cipher */
+  const EVP_CIPHER *cipher,
+  uint8_t *key,           /* key pointer */
+  int     keylength,      /* key length */
+  uint8_t *pkt,           /* packet pointer */
+  int     pktlength       /* packet length */
+)
+{
+  struct timespec start, stop;
+  int i;
+  double fast;
+  unsigned long digestlength = 0;
+
+  if (NULL == cipher) return;
+
+  clock_gettime(CLOCK_MONOTONIC, &start);
+  for (i = 0; i < NUM; i++) {
+    digestlength = SSL_CMAC(cipher, key, keylength, pkt, pktlength);
+  }
+  clock_gettime(CLOCK_MONOTONIC, &stop);
+  fast = (stop.tv_sec-start.tv_sec)*1E9 + (stop.tv_nsec-start.tv_nsec);
+  printf("%10s  %2d %2d %2lu %6.0f  %6.3f",
+    name, keylength, pktlength, digestlength, fast/NUM,  fast/1E9);
+
+  printf("\n");
+}
+
 
 
 int main(int argc, char *argv[])
@@ -146,25 +197,37 @@ int main(int argc, char *argv[])
   printf("# KL=key length, PL=packet length, DL=digest length\n");
   printf("# Digest    KL PL DL  ns/op sec/run     slow   %% diff\n");
 
-  DoOne("MD5",    key, MD5_KEY_LENGTH, packet, PACKET_LENGTH);
-  DoOne("MD5",    key, MD5_KEY_LENGTH-1, packet, PACKET_LENGTH);
-  DoOne("MD5",    key, SHA1_KEY_LENGTH, packet, PACKET_LENGTH);
-  DoOne("SHA1",   key, MD5_KEY_LENGTH, packet, PACKET_LENGTH);
-  DoOne("SHA1",   key, SHA1_KEY_LENGTH, packet, PACKET_LENGTH);
-  DoOne("SHA1",   key, SHA1_KEY_LENGTH-1, packet, PACKET_LENGTH);
-  DoOne("SHA224", key, 16, packet, PACKET_LENGTH);
-  DoOne("SHA224", key, 20, packet, PACKET_LENGTH);
-  DoOne("SHA256", key, 16, packet, PACKET_LENGTH);
-  DoOne("SHA256", key, 20, packet, PACKET_LENGTH);
-  DoOne("SHA384", key, 16, packet, PACKET_LENGTH);
-  DoOne("SHA384", key, 20, packet, PACKET_LENGTH);
-  DoOne("SHA512", key, 16, packet, PACKET_LENGTH);
-  DoOne("SHA512", key, 20, packet, PACKET_LENGTH);
-  DoOne("SHA512", key, 24, packet, PACKET_LENGTH);
-  DoOne("SHA512", key, 32, packet, PACKET_LENGTH);
-  DoOne("RIPEMD160", key, 16, packet, PACKET_LENGTH);
-  DoOne("RIPEMD160", key, 20, packet, PACKET_LENGTH);
-  DoOne("RIPEMD160", key, 32, packet, PACKET_LENGTH);
+  DoDigest("MD5",    key, MD5_KEY_LENGTH, packet, PACKET_LENGTH);
+  DoDigest("MD5",    key, MD5_KEY_LENGTH-1, packet, PACKET_LENGTH);
+  DoDigest("MD5",    key, SHA1_KEY_LENGTH, packet, PACKET_LENGTH);
+  DoDigest("SHA1",   key, MD5_KEY_LENGTH, packet, PACKET_LENGTH);
+  DoDigest("SHA1",   key, SHA1_KEY_LENGTH, packet, PACKET_LENGTH);
+  DoDigest("SHA1",   key, SHA1_KEY_LENGTH-1, packet, PACKET_LENGTH);
+  DoDigest("SHA224", key, 16, packet, PACKET_LENGTH);
+  DoDigest("SHA224", key, 20, packet, PACKET_LENGTH);
+  DoDigest("SHA256", key, 16, packet, PACKET_LENGTH);
+  DoDigest("SHA256", key, 20, packet, PACKET_LENGTH);
+  DoDigest("SHA384", key, 16, packet, PACKET_LENGTH);
+  DoDigest("SHA384", key, 20, packet, PACKET_LENGTH);
+  DoDigest("SHA512", key, 16, packet, PACKET_LENGTH);
+  DoDigest("SHA512", key, 20, packet, PACKET_LENGTH);
+  DoDigest("SHA512", key, 24, packet, PACKET_LENGTH);
+  DoDigest("SHA512", key, 32, packet, PACKET_LENGTH);
+  DoDigest("RIPEMD160", key, 16, packet, PACKET_LENGTH);
+  DoDigest("RIPEMD160", key, 20, packet, PACKET_LENGTH);
+  DoDigest("RIPEMD160", key, 32, packet, PACKET_LENGTH);
+
+  printf("\n");
+  printf("# KL=key length, PL=packet length, CL=CMAC length\n");
+  printf("# CMAC      KL PL CL  ns/op sec/run\n");
+
+  DoCMAC("DES",     EVP_des_cbc(),          key,  8, packet, PACKET_LENGTH);
+  DoCMAC("AES-128", EVP_aes_128_cbc(),      key, 16, packet, PACKET_LENGTH);
+  DoCMAC("AES-192", EVP_aes_192_cbc(),      key, 24, packet, PACKET_LENGTH);
+  DoCMAC("AES-256", EVP_aes_256_cbc(),      key, 32, packet, PACKET_LENGTH);
+  DoCMAC("CAM-128", EVP_camellia_128_cbc(), key, 16, packet, PACKET_LENGTH);
+  DoCMAC("CAM-192", EVP_camellia_192_cbc(), key, 24, packet, PACKET_LENGTH);
+  DoCMAC("CAM-256", EVP_camellia_256_cbc(), key, 32, packet, PACKET_LENGTH);
 
   return 0;
   


=====================================
docs/authentic.txt
=====================================
--- a/docs/authentic.txt
+++ b/docs/authentic.txt
@@ -111,7 +111,8 @@ program.
 == Algorithms ==
 
 The NTP standards include symmetric (private-key) authentication using
-any message digest algorithm supported by the OpenSSL package
+any message digest algorithm supported by the OpenSSL package.
+Digests longer than 20 bytes will be truncated.
 This algorithm computes a message digest or one-way hash
 which can be used to verify the client has the same message digest as
 the server.


=====================================
docs/includes/ntp.keys-body.txt
=====================================
--- a/docs/includes/ntp.keys-body.txt
+++ b/docs/includes/ntp.keys-body.txt
@@ -24,6 +24,8 @@ where `keyno` is a positive integer (between 1 and 65534),
 The file does not need to be sorted by `keyno`.
 
 `type` can be any digest type supported by your OpenSSL package.
+Digests longer than 20 bytes will be trucnated.
+
 You can probably get a list from `man 1 dgst` or `openssl help`.
 (As of Jan 2018, they lie.  Be sure to try it.  {ntpdman} will
 print an error on startup if a selected type isn't supported.)


=====================================
include/ntp_types.h
=====================================
--- a/include/ntp_types.h
+++ b/include/ntp_types.h
@@ -68,6 +68,9 @@ typedef uint16_t	associd_t; /* association ID */
 typedef uint32_t keyid_t;	/* cryptographic key ID */
 #define NTP_MAXKEY 0xffff	/* max authentication key number */
 
+/* Max digest length in non-extension MACs, add 4 for keyID */
+#define MAX_BARE_DIGEST_LENGTH 20
+
 /*
  * Ordinary double has only 53 bits  of precision in IEEE754.  But l_fp
  * needs 64 bits of precision, arguably 65 bits after 2026. Thus, to have


=====================================
libntp/authreadkeys.c
=====================================
--- a/libntp/authreadkeys.c
+++ b/libntp/authreadkeys.c
@@ -60,6 +60,28 @@ nexttok(
 }
 
 
+static void
+check_digest_length(
+	keyid_t keyno,
+	int keytype,
+	char *name) {
+    unsigned char digest[EVP_MAX_MD_SIZE];
+    unsigned int length = 0;
+    EVP_MD_CTX *ctx;
+    const EVP_MD *md;
+
+    md = EVP_get_digestbynid(keytype);
+    ctx = EVP_MD_CTX_create();
+    EVP_DigestInit_ex(ctx, md, NULL);
+    EVP_DigestFinal_ex(ctx, digest, &length);
+    EVP_MD_CTX_destroy(ctx);
+
+    if (MAX_BARE_DIGEST_LENGTH < length) {
+	msyslog(LOG_ERR, "AUTH: authreadkeys: digest for key %u, %s will be truncated.", keyno, name);
+    }
+}
+
+
 /*
  * authreadkeys - (re)read keys from a file.
  */
@@ -177,13 +199,21 @@ msyslog(LOG_ERR, "AUTH: authreadkeys: reading %s", file);
 		}
 		len = strlen(token);
 		if (len <= 20) {	/* Bug 2537 */
+			check_digest_length(keyno, keytype, upcased);
 			mac_setkey(keyno, keytype, (uint8_t *)token, len);
 			keys++;
 		} else {
 			char	hex[] = "0123456789abcdef";
 			size_t	jlim;
 
-			jlim = min(len, 2 * sizeof(keystr));
+			jlim = len;
+			if ((2*sizeof(keystr)) < jlim) {
+			  jlim =  2 * sizeof(keystr);
+			  msyslog(LOG_ERR,
+			    "AUTH: authreadkeys: key %u trucated to %u bytes",
+			    keyno, (unsigned int)jlim);
+
+			}
 			for (j = 0; j < jlim; j++) {
 				char *ptr = strchr(hex, tolower((unsigned char)token[j]));
 				if (ptr == NULL)
@@ -200,6 +230,7 @@ msyslog(LOG_ERR, "AUTH: authreadkeys: reading %s", file);
 				keyno);
 			    continue;
 			}
+			check_digest_length(keyno, keytype, upcased);
 			mac_setkey(keyno, keytype, keystr, jlim / 2);
 			keys++;
 		}


=====================================
libntp/macencrypt.c
=====================================
--- a/libntp/macencrypt.c
+++ b/libntp/macencrypt.c
@@ -9,6 +9,7 @@
 #include <stdint.h>
 
 #include <openssl/evp.h>	/* provides OpenSSL digest API */
+#include <openssl/md5.h>
 
 #include "ntp_fp.h"
 #include "ntp_stdlib.h"
@@ -77,6 +78,8 @@ mac_authencrypt(
 	EVP_DigestUpdate(ctx, key, key_size);
 	EVP_DigestUpdate(ctx, (uint8_t *)pkt, (unsigned int)length);
 	EVP_DigestFinal_ex(ctx, digest, &len);
+	if (MAX_BARE_DIGEST_LENGTH < len)
+		len = MAX_BARE_DIGEST_LENGTH;
 	memmove((uint8_t *)pkt + length + 4, digest, len);
 	return (int)(len + 4);
 }
@@ -115,6 +118,8 @@ mac_authdecrypt(
 	EVP_DigestUpdate(ctx, key, key_size);
 	EVP_DigestUpdate(ctx, (uint8_t *)pkt, (unsigned int)length);
 	EVP_DigestFinal_ex(ctx, digest, &len);
+	if (MAX_BARE_DIGEST_LENGTH < len)
+		len = MAX_BARE_DIGEST_LENGTH;
 	if ((unsigned int)size != len + 4) {
 		msyslog(LOG_ERR,
 		    "MAC: decrypt: MAC length error");
@@ -133,7 +138,7 @@ mac_authdecrypt(
 uint32_t
 addr2refid(sockaddr_u *addr)
 {
-	uint8_t		digest[20];
+	uint8_t		digest[MD5_DIGEST_LENGTH];
 	uint32_t	addr_refid;
 	EVP_MD_CTX	*ctx;
 	unsigned int	len;



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/7c3e7805922797d671d594d17ba262d8e61b8cb4...b01f1d658b11c4e8c24b307a7a79e8307364fbc2

---
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/7c3e7805922797d671d594d17ba262d8e61b8cb4...b01f1d658b11c4e8c24b307a7a79e8307364fbc2
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20180302/a6fc8639/attachment.html>


More information about the vc mailing list