]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Many files:
authorHarlan Stenn <stenn@ntp.org>
Sat, 17 Jun 2000 06:20:45 +0000 (06:20 -0000)
committerHarlan Stenn <stenn@ntp.org>
Sat, 17 Jun 2000 06:20:45 +0000 (06:20 -0000)
  * include/ntp.h: struct autokey's siglen is u_int32.  So is the
  siglen in struct cookie.  So is siglen and value length in struct
  value. Add fstamp to struct peer.  Resize the exten AUTOKEY field
  in struct pkt.
  * include/ntp_crypto.h: crypto_enable -> crypto_flags and a
  variety of other cleanups.
  * ntpd/ntp_config.c: crypto_enable -> crypto_flags, and some
  key/fudge cleanup.
  * ntpd/ntp_control.c: Much cleanup.
  * ntpd/ntp_crypto.c: Many changes that Harlan is too tired to
  properly document.
  * ntpd/ntp_peer.c: crypto_enable -> crypto_flags
  (peer_config): Hold off on crypto_public() until some resolver
  issue is fixed.
  * ntpd/ntp_proto.c (receive): Disable the reverse DNS lookup for now.
  (process_packet): Don't record_raw_stats() for now.
  crypto_enable was renamed to crypto_flags.
  (peer_xmit): In MODE_ACTIVE or MODE_PASSIVE, only call
  crypto_xmit() if the peer->cmmd is not CRYPTO_AUTO.  Reset
  peer->cmmd to 0 when we're thru.
  Don't reset peer->cmmd to 0 until the end of MODE_CLIENT.
  * ntpd/ntpd.c: Lose the call to crypto_init().  Instead, call
  crypto_setup() later on if we have crypto_flags.
  * util/ntp_genkeys.c: Lose GENLEN; use PRIMELEN/2 .
  From Dave Mills.
  * ntpd/ntp_crypto.c (crypto_rsa):
  (crypto_dh):
  Do some debug logging if readlink() fails with something other
  than EINVAL (file isn't a symlink).

bk: 394b18bd46O5vsY74avnqh0N6hmAuw

ChangeLog
include/ntp.h
include/ntp_crypto.h
ntpd/ntp_config.c
ntpd/ntp_control.c
ntpd/ntp_crypto.c
ntpd/ntp_peer.c
ntpd/ntp_proto.c
ntpd/ntpd.c
util/ntp_genkeys.c

index 9e9c35e374cf5632cd3a193f1e9bacd0c8bad432..094ea3d47036c138f2f6ba5222291d50045bd5a9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2000-06-17  Harlan Stenn  <stenn@whimsy.udel.edu>
+
+       * include/ntp.h: struct autokey's siglen is u_int32.  So is the
+       siglen in struct cookie.  So is siglen and value length in struct
+       value. Add fstamp to struct peer.  Resize the exten AUTOKEY field
+       in struct pkt.
+       * include/ntp_crypto.h: crypto_enable -> crypto_flags and a
+       variety of other cleanups.
+       * ntpd/ntp_config.c: crypto_enable -> crypto_flags, and some
+       key/fudge cleanup.
+       * ntpd/ntp_control.c: Much cleanup.
+       * ntpd/ntp_crypto.c: Many changes that Harlan is too tired to
+       properly document.
+       * ntpd/ntp_peer.c: crypto_enable -> crypto_flags
+       (peer_config): Hold off on crypto_public() until some resolver
+       issue is fixed.
+       * ntpd/ntp_proto.c (receive): Disable the reverse DNS lookup for now.
+       (process_packet): Don't record_raw_stats() for now.
+       crypto_enable was renamed to crypto_flags.
+       (peer_xmit): In MODE_ACTIVE or MODE_PASSIVE, only call
+       crypto_xmit() if the peer->cmmd is not CRYPTO_AUTO.  Reset
+       peer->cmmd to 0 when we're thru. 
+       Don't reset peer->cmmd to 0 until the end of MODE_CLIENT.
+       * ntpd/ntpd.c: Lose the call to crypto_init().  Instead, call
+       crypto_setup() later on if we have crypto_flags.
+       * util/ntp_genkeys.c: Lose GENLEN; use PRIMELEN/2 .
+       From Dave Mills.
+
+       * ntpd/ntp_crypto.c (crypto_rsa): 
+       (crypto_dh): 
+       Do some debug logging if readlink() fails with something other
+       than EINVAL (file isn't a symlink).
+
 2000-05-31  Harlan Stenn  <stenn@whimsy.udel.edu>
 
        * ntpd/ntp_timer.c: Protect <unistd.h>
index d8341e75d8f0c975f428db9c92100623364239dc..80ba45d48768a2f633c2d82581cebc19d5bfd280 100644 (file)
@@ -151,14 +151,16 @@ typedef char s_char;
 
 #ifdef AUTOKEY
 /*
+ * The following structures are used in the autokey protocol.
+ *
  * The autokey structure holds the data necessary to authenticate
  * the key IDs.
  */
 struct autokey {               /* network byte order */
        u_int32 tstamp;         /* timestamp */
        keyid_t key;            /* key ID */
-       int     seq;            /* key number */
-       u_int   siglen;         /* signature length */
+       int32   seq;            /* key number */
+       u_int32 siglen;         /* signature length */
        u_char  *sig;           /* signature */
 };
 
@@ -169,19 +171,20 @@ struct autokey {          /* network byte order */
 struct cookie {                        /* network byte order */
        u_int32 tstamp;         /* timestamp */
        keyid_t key;            /* key ID */
-       u_int   siglen;         /* signature length */
+       u_int32 siglen;         /* signature length */
        u_char  *sig;           /* signature */
 };
 
 /*
  * The value structure holds variable length data such as host
- * name and public value.
+ * name and public value and TAI.
  */
-struct value {                 /* network byte order */
+struct value {                 /* network byte order */
        u_int32 tstamp;         /* timestamp */
-       u_int   vallen;         /* value length */
+       u_int32 fstamp;         /* filestamp */
+       u_int32 vallen;         /* value length */
        u_char  *val;           /* value */
-       u_int   siglen;         /* signature length */
+       u_int32 siglen;         /* signature length */
        u_char  *sig;           /* signature */
 };
 #endif /* AUTOKEY */
@@ -282,6 +285,7 @@ struct peer {
 #endif /* AUTOKEY */
        keyid_t keyid;          /* current key ID */
        u_char  *keystr;        /* public key file name */
+       u_int   fstamp;         /* public key filestamp */
        keyid_t pkeyid;         /* previous key ID */
 #define clear_to_zero pkeyid
 #ifdef AUTOKEY
@@ -528,13 +532,13 @@ struct pkt {
 
        /*
         * The length of the packet less MAC must be a multiple of 64
-        * bits. The maximum length of an extension data field is 272
-        * octets. The next longest is 80 octets. There can only be
-        * two extension fields in a message, so the maximum lenth
-        * is 352 octets or 88 words, so we cheat and call it 100.
+        * with an RSA modulus and Diffie-Hellman prime of 64 octets,
+        * the maximum extension field size is 368 + 152 = 520 octets.
+        * or 130 words. We give an extra 10 words to allow the plants
+        * to grow if additional sunlight is available.
         */
 #ifdef AUTOKEY
-       u_int32 exten[100];     /* extension field */
+       u_int32 exten[140];     /* extension field */
 #else
        u_int32 exten[1];       /* misused */
 #endif /* AUTOKEY */
index 926df2058959f0e3099a7ede5ccd4bb5a544d2ad..a2ce6b1ded2d33ad1db6084b464f563d4bb2000e 100644 (file)
 /*
  * Extension field definitions
  */
-#define CRYPTO_NULL    0       /* no operation */
-#define CRYPTO_PUBL    1       /* public key */
-#define CRYPTO_ASSOC   2       /* association ID */
-#define CRYPTO_AUTO    3       /* autokey values */
-#define CRYPTO_PRIV    4       /* cookie value (client/server) */
-#define CRYPTO_DH      5       /* Diffie-Hellman value (symmetric) */
-#define CRYPTO_NAME    6       /* host name */
-#define CRYPTO_RESP    0x80    /* response */
-#define CRYPTO_ERROR   0x40    /* error */
+#define CRYPTO_VN      1       /* current protocol version number */
+
+#define CRYPTO_NULL    ((CRYPTO_VN << 8) | 0) /* no operation */
+#define CRYPTO_PUBL    ((CRYPTO_VN << 8) | 1) /* public key */
+#define CRYPTO_ASSOC   ((CRYPTO_VN << 8) | 2) /* association ID */
+#define CRYPTO_AUTO    ((CRYPTO_VN << 8) | 3) /* autokey values */
+#define CRYPTO_PRIV    ((CRYPTO_VN << 8) | 4) /* cookie value */
+#define CRYPTO_DHPAR   ((CRYPTO_VN << 8) | 5) /* DH parameters */
+#define CRYPTO_DH      ((CRYPTO_VN << 8) | 6) /* DH public value */
+#define CRYPTO_NAME    ((CRYPTO_VN << 8) | 7) /* host name */
+#define CRYPTO_TAI     ((CRYPTO_VN << 8) | 8) /* TAI offset */
+#define CRYPTO_RESP    0x8000  /* response */
+#define CRYPTO_ERROR   0x4000  /* error */
 
 /*
  * Cryptoflags
  */
-#define CRYPTO_FLAG_NONE  0x00 /* nothing happening */
-#define CRYPTO_FLAG_PUBL  0x01 /* read peer public key from file */
+#define CRYPTO_FLAG_ENAB  0x01 /* enable public key */
+#define CRYPTO_FLAG_PUBL  0x02 /* fetch peer public key from server */
 
 #ifdef PUBKEY
 
@@ -56,18 +60,19 @@ extern      void    make_keylist    P((struct peer *));
 extern void    key_expire      P((struct peer *));
 extern void    crypto_agree    P((void));
 #ifdef PUBKEY
-extern void    crypto_init     P((void));
 extern void    crypto_config   P((int, char *));
 extern void    crypto_setup    P((void));
-extern int     crypto_public   P((struct peer *, u_char *));
+extern int     crypto_public   P((struct peer *, u_char *, u_int));
 
 /*
  * Cryptographic values
  */
-extern int                     crypto_enable;
-extern int                     crypto_flags;
-extern char *                  private_key_file;
-extern char *                  public_key_file;
-extern char *                  dh_params_file;
+extern int     crypto_flags;
+extern char *  private_key_file;
+extern u_int   private_key_fstamp;
+extern char *  public_key_file;
+extern u_int   public_key_fstamp;
+extern char *  dh_params_file;
+extern u_int   dh_params_fstamp;
 #endif /* PUBKEY */
 #endif /* AUTOKEY */
index 9d2bba364c55c6670074ce52ea971a14d0364ae4..ff7b5f6f3e23407352b94c601bb20de14f179b29 100644 (file)
@@ -709,7 +709,7 @@ getconfig(
        unsigned long ul;
        keyid_t peerkey;
        u_char *peerkeystr;
-       keyid_t lpeerkey = 0;
+       u_long fudgeflag;
        int peerflags;
        int hmode;
        struct sockaddr_in peeraddr;
@@ -1308,7 +1308,7 @@ getconfig(
                        break;
 
                    case CONFIG_CRYPTO:
-                       crypto_enable = 1;
+                       crypto_flags |= CRYPTO_FLAG_ENAB;
                        for (i = 1; i < ntokens; i++) {
                            int temp;
 
@@ -1591,6 +1591,7 @@ getconfig(
                        }
 
                        memset((void *)&clock_stat, 0, sizeof clock_stat);
+                       fudgeflag = 0;
                        errflg = 0;
                        for (i = 2; i < ntokens-1; i++) {
                                switch (c = matchkey(tokens[i],
@@ -1646,17 +1647,14 @@ getconfig(
                                    case CONF_FDG_FLAG2:
                                    case CONF_FDG_FLAG3:
                                    case CONF_FDG_FLAG4:
-                                       if (!atouint(tokens[++i], &ul)
+                                       if (!atouint(tokens[++i], &fudgeflag)
                                            || ul > 1) {
                                                msyslog(LOG_ERR,
                                                        "fudge %s flag value in error",
                                                        ntoa(&peeraddr));
-                                               lpeerkey = (keyid_t)ul;
-                                               peerkey = lpeerkey;
                                                errflg = i;
                                                break;
                                        }
-                                       peerkey = lpeerkey;
                                        switch(c) {
                                            case CONF_FDG_FLAG1:
                                                c = CLK_FLAG1;
@@ -1675,7 +1673,7 @@ getconfig(
                                                clock_stat.haveflags|=CLK_HAVEFLAG4;
                                                break;
                                        }
-                                       if (peerkey == 0)
+                                       if (fudgeflag == 0)
                                            clock_stat.flags &= ~c;
                                        else
                                            clock_stat.flags |= c;
index a1f13de8517ec12444b99480f8a9e9a987b466bc..123108515d52713446fb3bb3449af3c9d27885bf 100644 (file)
@@ -1145,8 +1145,12 @@ ctl_putsys(
 {
        l_fp tmp;
 #ifdef HAVE_UNAME
-       char str[50];
+       char str[256];
 #endif
+#ifdef PUBKEY
+       char str1[256];
+#endif ?* PUBKEY */
+
        switch (varid) {
 
        case CS_LEAP:
@@ -1308,27 +1312,37 @@ ctl_putsys(
 
 #ifdef PUBKEY
        case CS_PRIVATE:
-               if (private_key_file != NULL)
-                       ctl_putstr(sys_var[CS_PRIVATE].text,
-                           private_key_file, strlen(private_key_file));
+               if (private_key_file == NULL)
+                       break;
+               strcpy(str1, private_key_file);
+               if (private_key_fstamp != 0)
+                       sprintf(str1, "%s.%u", str1, private_key_fstamp);
+               ctl_putstr(sys_var[CS_PRIVATE].text, str1, strlen(str1));
                break;
 
        case CS_PUBLIC:
-               if (public_key_file != NULL)
-                       ctl_putstr(sys_var[CS_PUBLIC].text,
-                           public_key_file, strlen(public_key_file));
+               if (public_key_file == NULL)
+                       break;
+               strcpy(str1, public_key_file);
+               if (public_key_fstamp != 0)
+                       sprintf(str1, "%s.%u", str1, public_key_fstamp);
+               ctl_putstr(sys_var[CS_PUBLIC].text, str1, strlen(str1));
                break;
 
        case CS_DHPARAMS:
-               if (dh_params_file != NULL)
-                       ctl_putstr(sys_var[CS_DHPARAMS].text,
-                           dh_params_file, strlen(dh_params_file));
+               if (dh_params_file == NULL)
+                       break;
+               strcpy(str1, dh_params_file);
+               if (dh_params_fstamp != 0)
+                       sprintf(str1, "%s.%u", str1, dh_params_fstamp);
+               ctl_putstr(sys_var[CS_DHPARAMS].text, str1, strlen(str1));
                break;
 
        case CS_HOSTNAM:
-               if (sys_hostname != NULL)
-                       ctl_putstr(sys_var[CS_HOSTNAM].text,
-                           sys_hostname, strlen(sys_hostname));
+               if (sys_hostname == NULL)
+                       break;
+               ctl_putstr(sys_var[CS_HOSTNAM].text, sys_hostname,
+                   strlen(sys_hostname));
                break;
 
        case CS_REVTIME:
index 039310e9bf25c11ee766db29530ded874271b199..82a10e90ce9889f8ee4aecf4c8c363c09ab12f76 100644 (file)
  *   +---------------+   +---------------+   +---------------+
  * 2 |   timestamp   |   |   timestamp   |   |   timestamp   |
  *   +---------------+   +---------------+   +---------------+
- * 3 |   final seq   |   |     cookie    |   |   value len   |
+ * 3 |   final seq   |   |     cookie    |   |   filestamp   |
+ *   +---------------+   +---------------+   +---------------+
+ * 4 |   final key   |   | signature len |   |   value len   |
  *   +---------------+   +---------------+   +---------------+
- * 4 |   final key   |   | signature len |   |               |
- *   +---------------+   +---------------+   =     value     =
  * 5 | signature len |   |               |   |               |
- *   +---------------+   =   signature   =   +---------------+
- * 6 |               |   |               |   | signature len |
+ *   +---------------+   =   signature   =   =     value     =
+ * 6 |               |   |               |   |               |
  *   =   signature   =   +---------------+   +---------------+
- * 7 |               |   CRYPTO_PRIV rsp     |               |
- *   +---------------+                       =   signature   =
+ * 7 |               |   CRYPTO_PRIV rsp     | signature len |
+ *   +---------------+                       +---------------+
  *   CRYPTO_AUTO rsp                         |               |
+ *                                           =   signature   =
+ *                                           |               |
  *                                           +---------------+
  *                                           CRYPTO_DH rsp
  *                                           CRYPTO_NAME rsp
+ *                                           CRYPTO_TAI rsp
  *                                           
  *   CRYPTO_PUBL  1  request/respond for public key
  *   CRYPTO_ASSOC 2  request/respond association ID
@@ -46,6 +49,7 @@
  *   CRYPTO_PRIV  4  request/respond cookie
  *   CRYPTO_DH    5  request public value/respond signature
  *   CRYPTO_NAME  6  request/respond host name
+ *   CRYPTO_TAI   6  request/respond TAI offset
  *
  *   Note: requests carry the association ID of the receiver; responses
  *   carry the association ID of the sender.
 #define MAX_KEYLEN     1024    /* maximum key length */
 
 /*
- * Cryptodata
+ * Autokey protocol status codes
+ */
+#define RV_OK          0x0     /* success */
+#define RV_TSP         0x1     /* timestamp replay */
+#define RV_PUB         0x2     /* no public key */
+#define RV_KEY         0x3     /* invalid RSA modulus */
+#define RV_SIG         0x4     /* invalid signature length */
+#define RV_DH          0x5     /* invalid DH prime or generator */
+#define RV_FIL         0x6     /* missing or corrupted key file */
+#define RV_DAT         0x7     /* missing or corrupted data */
+#define RV_DEC         0x8     /* PEM decoding error */
+
+/*
+ * Private cryptodata in networ byte order.
  */
-static R_DH_PARAMS dh_params;  /* Diffie-Hellman parameters */
-static u_int dh_keyLen;                /* Diffie-Hellman key length */
-static u_char *dh_public;      /* Diffie-Hellman public value */
-static u_char *dh_private;     /* Diffie-Hellman private value */
 static R_RSA_PRIVATE_KEY private_key; /* RSA private key */
 static R_RSA_PUBLIC_KEY public_key; /* RSA public key */
-static u_char *dh_sign = NULL; /* Diffie-Hellman public signature */
-static struct value host;      /* host name, timestamp and signature */
+static R_DH_PARAMS dh_params;  /* Diffie-Hellman parameters */
+static struct value host;      /* host name/public key */
+static struct value dhparam;   /* Diffie_Hellman parameters */
+static struct value dhpub;     /* Diffie_Hellman public value */
+static u_char *dh_private;     /* DH private value */
+static u_int dh_keyLen;                /* DH private value length */
 
-int    crypto_enable;          /* master switch */
+/*
+ * Global cryptodata in host byte order.
+ */
 int    crypto_flags;           /* flags that wave cryptically */
 char   *private_key_file = NULL; /* private key file */
+u_int  private_key_fstamp;     /* RSA private key filestamp */
 char   *public_key_file = NULL; /* public key file */
-char   *dh_params_file = NULL; /* D-H parameters file */
+u_int  public_key_fstamp;      /* RSA public key filestamp */
+char   *dh_params_file = NULL; /* DH parameters file */
+u_int  dh_params_fstamp;       /* DH parameters filestamp */
 char   *keysdir = "/usr/local/etc/"; /* crypto keys directory */
 
 /*
  * Cryptotypes
  */
-static int     crypto_read     P((u_char *, u_char *, u_int));
-static void    crypto_line     P((FILE *, u_char **, u_int *));
+static void    crypto_rsa      P((char *, u_int *, u_char *, u_int));
+static void    crypto_dh       P((char *, u_int *));
 #endif /* PUBKEY */
 
 
@@ -229,26 +251,23 @@ make_keylist(
        ap->siglen = 0;
 #if DEBUG
        if (debug)
-               printf("make_keys: %d %08x %08x ts %u\n", ntohl(ap->seq),
-                   ntohl(ap->key), cookie, ntohl(ap->tstamp));
+               printf("make_keys: %d %08x %08x ts %u\n",
+                   ntohl(ap->seq), ntohl(ap->key), cookie,
+                   ntohl(ap->tstamp));
 #endif
 #ifdef PUBKEY
-       if(!crypto_enable)
+       if(!crypto_flags)
                return;
-       if (private_key.bits < MIN_RSA_MODULUS_BITS ||
-           private_key.bits > MAX_RSA_MODULUS_BITS) {
-               rval = -1;
-       } else {
-               if (ap->sig == NULL)
-                       ap->sig = emalloc(MAX_SIGNATURE_LEN);
-               R_SignInit(&ctx, DA_MD5);
-               R_SignUpdate(&ctx, (u_char *)ap, 12);
-               rval = R_SignFinal(&ctx, ap->sig, &len, &private_key);
-               ap->siglen = htonl(len);
-       }
+       if (ap->sig == NULL)
+               ap->sig = emalloc(private_key.bits / 8);
+       R_SignInit(&ctx, DA_MD5);
+       R_SignUpdate(&ctx, (u_char *)ap, 12);
+       rval = R_SignFinal(&ctx, ap->sig, &len, &private_key);
        if (rval != 0)
                msyslog(LOG_ERR, "make_keylist: signature fails %x",
                    rval);
+       else
+               ap->siglen = htonl(len);
 #endif /* PUBKEY */
 }
 
@@ -270,6 +289,7 @@ crypto_recv(
        u_int32 *pkt;           /* packet pointer */
        struct autokey *ap;     /* autokey pointer */
        struct cookie *cp;      /* cookie pointer */
+       struct value *vp;       /* value pointer */
        int has_mac;            /* length of MAC field */
        int authlen;            /* offset of MAC field */
        int len;                /* extension field length */
@@ -280,7 +300,9 @@ crypto_recv(
 #ifdef PUBKEY
        R_SIGNATURE_CTX ctx;    /* signature context */
        u_char dh_key[MAX_DH_LEN]; /* Diffie-Hellman agreed key */
-       u_int modulus;
+       R_RSA_PUBLIC_KEY *kp;   /* temporary public key pointer */
+       u_int rsalen = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int) + 4;
+       u_int bits;
        int rval;
        int j;
 #endif /* PUBKEY */
@@ -316,29 +338,27 @@ crypto_recv(
 
                /*
                 * Install autokey values in broadcast client and
-                * symmetric modes. We believe the values only if the
-                * public key is valid and the signature has valid
-                * length and is verified. However, we mark as authentic
-                * only if the timestamp is nonzero.
+                * symmetric modes.
                 */
                case CRYPTO_AUTO | CRYPTO_RESP:
                        ap = (struct autokey *)&pkt[i + 2];
 #ifdef PUBKEY
-                       temp = public_key.bits / 8;
-                       if (!crypto_enable) {
+                       temp = ntohl(ap->siglen);
+                       kp = (R_RSA_PUBLIC_KEY *)peer->pubkey;
+                       if (!crypto_flags) {
                                rval = 0;
                        } else if (tstamp == 0 || tstamp <
                            peer->recauto.tstamp) {
-                               break;
-                       } else if (peer->pubkey == NULL || temp !=
-                           ntohl(ap->siglen)) {
-                               rval = -1;
+                               rval = RV_TSP;
+                       } else if (kp == NULL) {
+                               rval = RV_PUB;
+                       } else if (temp != kp->bits / 8) {
+                               rval = RV_SIG;
                        } else {
                                R_VerifyInit(&ctx, DA_MD5);
                                R_VerifyUpdate(&ctx, (u_char *)ap, 12);
                                rval = R_VerifyFinal(&ctx,
-                                   (u_char *)&ap->sig, temp,
-                                   (R_RSA_PUBLIC_KEY *)peer->pubkey);
+                                   (u_char *)&ap->sig, temp, kp);
                        }
 #ifdef DEBUG
                        if (debug)
@@ -348,7 +368,8 @@ crypto_recv(
                                    ntohl(ap->key), tstamp);
 #endif
                        if (rval != 0) {
-                               peer->flags &= ~FLAG_AUTOKEY;
+                               if (rval != RV_TSP)
+                                       peer->flags &= ~FLAG_AUTOKEY;
                                break;
                        }
                        peer->flags |= FLAG_AUTOKEY;
@@ -369,21 +390,22 @@ crypto_recv(
                case CRYPTO_PRIV | CRYPTO_RESP:
                        cp = (struct cookie *)&pkt[i + 2];
 #ifdef PUBKEY
-                       temp = public_key.bits / 8;
-                       if (!crypto_enable) {
+                       temp = ntohl(cp->siglen);
+                       kp = (R_RSA_PUBLIC_KEY *)peer->pubkey;
+                       if (!crypto_flags) {
                                rval = 0;
                        } else if (tstamp == 0 || tstamp <
                            peer->pcookie.tstamp) {
-                               break;
-                       } else if (peer->pubkey == NULL || temp !=
-                           ntohl(cp->siglen)) {
-                               rval = -1;
+                               rval = RV_TSP;
+                       } else if (kp == NULL) {
+                               rval = RV_PUB;
+                       } else if (temp != kp->bits / 8) {
+                               rval = RV_SIG;
                        } else {
                                R_VerifyInit(&ctx, DA_MD5);
                                R_VerifyUpdate(&ctx, (u_char *)cp, 8);
                                rval = R_VerifyFinal(&ctx,
-                                   (u_char *)&cp->sig, temp,
-                                   (R_RSA_PUBLIC_KEY *)peer->pubkey);
+                                   (u_char *)&cp->sig, temp, kp);
                        }
                        temp = ntohl(cp->key);
 #ifdef DEBUG
@@ -393,7 +415,8 @@ crypto_recv(
                                    rval, temp, tstamp);
 #endif
                        if (rval != 0) {
-                               peer->flags &= ~FLAG_AUTOKEY;
+                               if (rval != RV_TSP)
+                                       peer->flags &= ~FLAG_AUTOKEY;
                                break;
                        }
                        if (!(peer->flags & FLAG_MCAST2))
@@ -410,6 +433,51 @@ crypto_recv(
                        break;
 
 #ifdef PUBKEY
+               /*
+                * Verify Diffie-Hellman public value and compute key
+                * agreement in symmetric modes. We believe the
+                * value only if the public key is valid and the
+                * signature has valid length and is verified. 
+                */
+               case CRYPTO_DHPAR | CRYPTO_RESP:
+                       vp = (struct value *)&pkt[i + 2];
+                       temp = ntohl(vp->vallen);
+                       kp = (R_RSA_PUBLIC_KEY *)peer->pubkey;
+                       j = i + 5 + temp / 4;
+                       if (tstamp == 0 || tstamp <
+                           peer->pcookie.tstamp) {
+                               rval = RV_TSP;
+                       } else if (kp == NULL) {
+                               rval = RV_PUB;
+                       } else if (ntohl(pkt[j]) != kp->bits / 8) {
+                               rval = RV_SIG;
+                       } else if (temp != dh_params.primeLen ||
+                           dhpub.val == 0) {
+                               rval = RV_DH;
+                       } else {
+                               R_VerifyInit(&ctx, DA_MD5);
+                               R_VerifyUpdate(&ctx, (u_char *)vp,
+                                   temp + 12);
+                               rval = R_VerifyFinal(&ctx,
+                                   (u_char *)&pkt[j + 1],
+                                   ntohl(pkt[j]), kp);
+                       }
+
+                       /*
+                        * Stash the parameters in safe places.
+                        */
+                       j = 5;
+                       temp = htonl(pkt[j]);
+                       dh_params.primeLen = temp;
+                       dh_params.prime = emalloc(temp);
+                       memcpy(dh_params.prime, &pkt[j + 1], temp);
+                       j += temp / 4;
+                       temp = htonl(pkt[j]);
+                       dh_params.generatorLen = temp;
+                       dh_params.generator = emalloc(temp);
+                       memcpy(dh_params.generator, &pkt[j + 1], temp);
+                       break;
+
                /*
                 * Verify Diffie-Hellman public value and compute key
                 * agreement in symmetric modes. We believe the
@@ -421,25 +489,26 @@ crypto_recv(
                        /* fall through */
 
                case CRYPTO_DH | CRYPTO_RESP:
-                       temp = ntohl(pkt[i + 3]);
-                       j = i + 4 + temp / 4;
+                       vp = (struct value *)&pkt[i + 2];
+                       temp = ntohl(vp->vallen);
+                       kp = (R_RSA_PUBLIC_KEY *)peer->pubkey;
+                       j = i + 5 + temp / 4;
                        if (tstamp == 0 || tstamp <
                            peer->pcookie.tstamp) {
-                               break;
-                       } else if (peer->pubkey == NULL ||
-                           ntohl(pkt[j]) != public_key.bits / 8) {
-                               rval = -1;
-                       } else if (temp != dh_params.primeLen ||
-                           dh_public == NULL) {
-                               rval = -2;
+                               rval = RV_TSP;
+                       } else if (kp == NULL) {
+                               rval = RV_PUB;
+                       } else if (ntohl(pkt[j]) != kp->bits / 8) {
+                               rval = RV_SIG;
+                       } else if (temp != dh_params.primeLen) {
+                               rval = RV_DH;
                        } else {
                                R_VerifyInit(&ctx, DA_MD5);
-                               R_VerifyUpdate(&ctx, (u_char *)&pkt[i +
-                                   2], temp + 8);
+                               R_VerifyUpdate(&ctx, (u_char *)vp,
+                                   temp + 12);
                                rval = R_VerifyFinal(&ctx,
                                    (u_char *)&pkt[j + 1],
-                                   public_key.bits / 8,
-                                   (R_RSA_PUBLIC_KEY *)peer->pubkey);
+                                   ntohl(pkt[j]), kp);
                        }
 
                        /*
@@ -451,19 +520,22 @@ crypto_recv(
                                temp = 0;
                        } else {
                                rval = R_ComputeDHAgreedKey(dh_key,
-                                   (u_char *)&pkt[i + 4], dh_private,
+                                   (u_char *)&pkt[i + 5], dh_private,
                                    dh_keyLen, &dh_params);
                                temp = ntohl(*(u_int32 *)dh_key);
                        }
 #ifdef DEBUG
                        if (debug)
                                printf(
-                                   "crypto_recv: verify %x d-h %08x ts %u\n",
-                                   rval, temp, tstamp);
+                                   "crypto_recv: verify %x DH %08x ts %u fs %u\n",
+                                   rval, temp, tstamp,
+                                   ntohl(vp->fstamp));
 #endif
                        if (rval != 0) {
-                               peer->flags &= ~FLAG_AUTOKEY;
-                               peer->cmmd = 0;
+                               if (rval != RV_TSP) {
+                                       peer->flags &= ~FLAG_AUTOKEY;
+                                       peer->cmmd = 0;
+                               }
                                break;
                        }
                        peer->flash &= ~TEST10;
@@ -475,71 +547,51 @@ crypto_recv(
                        break;
 
                /*
-                * Receive remote host name and install public key from
-                * file.
+                * Receive and install public key and host name.
                 */
                case CRYPTO_NAME | CRYPTO_RESP:
-                       temp = ntohl(pkt[i + 3]);
-                       j = i + 4 + temp / 4;
+                       vp = (struct value *)&pkt[i + 2];
+                       temp = ntohl(vp->vallen);
+                       j = i + 5 + ntohl(vp->vallen) / 4;
+                       bits = ntohl(pkt[i + 5]);
                        if (tstamp == 0 || tstamp <
                            peer->pcookie.tstamp) {
-                               break;
-                       } else if (ntohl(pkt[j]) != public_key.bits / 8)
-                           {
-                               rval = -1;
-                       } else if (crypto_public(peer, (char *)&pkt[i +
-                           4])) {
+                               rval = RV_TSP;
+                       } else if (temp < rsalen ||
+                           bits < MIN_RSA_MODULUS_BITS ||
+                           bits > MAX_RSA_MODULUS_BITS) {
+                               rval = RV_KEY;
+                       } else if (ntohl(pkt[j]) != bits / 8) {
+                               rval = RV_SIG;
+                       } else {
                                R_VerifyInit(&ctx, DA_MD5);
-
-                               R_VerifyUpdate(&ctx, (char *)&pkt[i +
-                                   2], 8 + temp);
-
+                               R_VerifyUpdate(&ctx, (u_char *)vp,
+                                   temp + 12);
+                               kp = emalloc(sizeof(R_RSA_PUBLIC_KEY));
+                               kp->bits = bits;
+                               memcpy(&kp->modulus, &pkt[i + 6], rsalen - 4);
                                rval = R_VerifyFinal(&ctx,
                                    (u_char *)&pkt[j + 1],
-                                   public_key.bits / 8,
-                                   (R_RSA_PUBLIC_KEY *)peer->pubkey);
+                                   ntohl(pkt[j]), kp);
                                if (rval != 0) {
-                                       free(peer->pubkey);
-                                       peer->pubkey = NULL;
+                                       free(kp);
+                               } else {
+                                       j = i + 5 + rsalen / 4;
+                                       peer->pubkey = (u_char *)kp;
+                                       temp = strlen((char *)&pkt[j]);
+                                       peer->keystr = emalloc(temp);
+                                       strcpy(peer->keystr, (char *)&pkt[j]);
                                }
-                       } else {
-                               rval = -2;
                        }
 #ifdef DEBUG
                        if (debug)
 
                                printf(
-                                   "crypto_recv: verify %x host %s ts %u\n",
-                                   rval, (char *)&pkt[i + 4], tstamp); 
+                                   "crypto_recv: verify %x host %s ts %u fs %u\n",
+                                   rval, (char *)&pkt[j], tstamp,
+                                   ntohl(vp->fstamp));
 #endif
                        break;
-
-               /*
-                * Install peer public key. This is rather raucus, since
-                * the extension field is in network order and the first
-                * word is a u_int32; however, the corresponding word of
-                * the key is a u_int, which can be 32 or 64 bits
-                * depending on architecture. We don't do anything
-                * unless the length and modulus are valid. Picky,
-                * picky.
-                */
-               case CRYPTO_PUBL | CRYPTO_RESP:
-                       temp = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int);
-                       if (ntohl(pkt[i + 2]) != temp + 4)
-                               break;
-                       modulus = ntohl(pkt[i + 3]);
-                       if ( modulus < MIN_RSA_MODULUS_BITS ||
-                           modulus > MAX_RSA_MODULUS_BITS)
-                               break;
-                       if (peer->pubkey == NULL)
-                               peer->pubkey =
-                                   emalloc(sizeof(R_RSA_PUBLIC_KEY));
-                       ((R_RSA_PUBLIC_KEY *)peer->pubkey)->bits =
-                           modulus;
-                       memcpy(
-                           ((R_RSA_PUBLIC_KEY *)peer->pubkey)->modulus,
-                           (u_char *)&(pkt[i + 4]), temp);
-                       break;
 #endif /* PUBKEY */
 
                /*
@@ -578,12 +630,12 @@ crypto_xmit(
        struct peer *peer;      /* peer structure pointer */
        struct autokey *ap;     /* autokey pointer */
        struct cookie *cp;      /* cookie pointer */
+       struct value *vp;       /* value pointer */
        int len;                /* extension field length */
        u_int opcode;           /* extension field opcode */
        int i;
 #ifdef PUBKEY
        R_SIGNATURE_CTX ctx;    /* signature context */
-       struct value *vp;       /* value pointer */
        int rval;               /* return value */
        u_int temp;
        int j;
@@ -620,14 +672,13 @@ crypto_xmit(
                ap->tstamp = peer->sndauto.tstamp;
                ap->seq = peer->sndauto.seq;
                ap->key = peer->sndauto.key;
-               ap->siglen = 0;
+               ap->siglen = peer->sndauto.siglen;
                len += 16;
 #ifdef PUBKEY
-               if (!crypto_enable)
+               if (!crypto_flags)
                        break;
-               ap->siglen = peer->sndauto.siglen;
-               temp = ntohl(peer->sndauto.siglen);
-               if (temp > 0)
+               temp = ntohl(ap->siglen);
+               if (temp != 0)
                        memcpy(&ap->sig, peer->sndauto.sig, temp);
                len += temp;
 #endif /* PUBKEY */
@@ -643,87 +694,88 @@ crypto_xmit(
                cp->siglen = 0;
                len += 12;
 #ifdef PUBKEY
-               if (!crypto_enable)
+               if (!crypto_flags)
                        break;
-               cp->siglen = htonl(public_key.bits / 8);
-               if (private_key.bits < MIN_RSA_MODULUS_BITS ||
-                   private_key.bits > MAX_RSA_MODULUS_BITS) {
-                       rval = -1;
-               } else {
-                       R_SignInit(&ctx, DA_MD5);
-                       R_SignUpdate(&ctx, (u_char *)cp, 8);
-                       rval = R_SignFinal(&ctx, (u_char *)&cp->sig,
-                           &temp, &private_key);
-               }
+               R_SignInit(&ctx, DA_MD5);
+               R_SignUpdate(&ctx, (u_char *)cp, 8);
+               rval = R_SignFinal(&ctx, (u_char *)&cp->sig, &temp,
+                   &private_key);
                if (rval != 0) {
-                       cp->siglen = 0;
                        msyslog(LOG_ERR,
                            "crypto_xmit: cookie signature fails %x",
                            rval);
                        break;
                }
+               cp->siglen = htonl(temp);
                len += temp;
 #endif /* PUBKEY */
                break;
 
 #ifdef PUBKEY
        /*
-        * Send Diffie-Hellman public value, timestamp and signature.
+        * Send Diffie-Hellman parameters, timestamp and signature.
         */
-       case CRYPTO_DH:
-       case CRYPTO_DH | CRYPTO_RESP:
+       case CRYPTO_DHPAR | CRYPTO_RESP:
                vp = (struct value *)&xpkt[i + 2];
-               vp->tstamp = htonl(sys_revoketime.l_ui);
+               vp->tstamp = dhparam.tstamp;
+               vp->fstamp = dhparam.fstamp;
                vp->vallen = 0;
-               len += 8;
-               temp = dh_params.primeLen;
-               if (dh_sign == NULL)
+               len += 12;
+               temp = ntohl(dhparam.vallen);
+               if (dhparam.val == NULL)
                        break;
                vp->vallen = htonl(temp);
-               memcpy((u_char *)&vp->val, dh_public, temp);
+               memcpy(&vp->val, dhparam.val, temp);
                len += temp;
-               j = i + 4 + temp / 4;
+               j = i + 5 + temp / 4;
                temp = public_key.bits / 8;
                xpkt[j++] = htonl(temp);
-               memcpy((u_char *)&xpkt[j], dh_sign, temp);
+               memcpy(&xpkt[j], dhparam.sig, temp);
                len += temp + 4;
                break;
 
        /*
-        * Send host name, timestamp and signature.
+        * Send Diffie-Hellman public value, timestamp and signature.
         */
-       case CRYPTO_NAME | CRYPTO_RESP:
+       case CRYPTO_DH:
+       case CRYPTO_DH | CRYPTO_RESP:
                vp = (struct value *)&xpkt[i + 2];
-               vp->tstamp = htonl(sys_revoketime.l_ui);
-               vp->vallen = host.vallen;
-               len += 8;
-               temp = ntohl(host.vallen);
-               if (temp == 0)
+               vp->tstamp = dhpub.tstamp;
+               vp->fstamp = dhpub.fstamp;
+               vp->vallen = 0;
+               len += 12;
+               temp = ntohl(dhpub.vallen);
+               if (dhpub.val == NULL)
                        break;
-               memcpy((u_char *)&vp->val, host.val, temp);
+               vp->vallen = htonl(temp);
+               memcpy(&vp->val, dhpub.val, temp);
                len += temp;
-               j = i + 4 + temp / 4;
+               j = i + 5 + temp / 4;
                temp = public_key.bits / 8;
                xpkt[j++] = htonl(temp);
-               memcpy((u_char *)&xpkt[j], host.sig, temp);
+               memcpy(&xpkt[j], dhpub.sig, temp);
                len += temp + 4;
                break;
 
        /*
-        * Send public key. We send the public key only if it exists and
-        * is valid. This is used primarily for testing.
+        * Send public key, host name, timestamp and signature.
         */
-       case CRYPTO_PUBL | CRYPTO_RESP:
-               xpkt[i + 2] = 0;
-               len += 4;
-               if (public_key.bits < MIN_RSA_MODULUS_BITS ||
-                   public_key.bits > MAX_RSA_MODULUS_BITS)
+       case CRYPTO_NAME | CRYPTO_RESP:
+               vp = (struct value *)&xpkt[i + 2];
+               vp->tstamp = host.tstamp;
+               vp->fstamp = host.fstamp;
+               vp->vallen = 0;
+               len += 12;
+               temp = ntohl(host.vallen);
+               if (host.val == NULL)
                        break;
-               temp = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int);
-               xpkt[i + 2] = htonl(temp + 4);
-               xpkt[i + 3] = htonl(public_key.bits);
-               memcpy((u_char *)&xpkt[i + 4],
-                   (u_char *)&public_key.modulus, temp);
+               vp->vallen = htonl(temp);
+               memcpy(&vp->val, host.val, temp);
+               len += temp;
+               j = i + 5 + temp / 4;
+               temp = public_key.bits / 8;
+               xpkt[j++] = htonl(temp);
+               memcpy(&xpkt[j], host.sig, temp);
                len += temp + 4;
                break;
 #endif /* PUBKEY */
@@ -755,150 +807,236 @@ crypto_xmit(
        return (len);
 }
 
-
 #ifdef PUBKEY
 /*
- * crypto_agree - compute public and private Diffie-Hellman values from
- * given prime and generator, then sign with private key.
+ * crypto_setup - read RSA private key, RSA public key and Diffie-
+ * Hellman parameter files and initialize cryptographic data.
  */
 void
-crypto_agree(void)
+crypto_setup(void)
 {
        char filename[MAXFILENAME];
-       R_RANDOM_STRUCT randomstr;
-       R_SIGNATURE_CTX ctx;    /* signature context */
        u_int len, temp;
-       int rval;
-       int i;
-       char *sptr;
+       u_int32 *pp;
 
        /*
-        * Sign public key file name and timestamp.
+        * Initialize structures.
+        */
+       memset(&private_key, 0, sizeof(private_key));
+       memset(&public_key, 0, sizeof(public_key));
+       memset(&dh_params, 0, sizeof(dh_params));
+       memset(&host, 0, sizeof(host));
+       memset(&dhparam, 0, sizeof(dhparam));
+       memset(&dhpub, 0, sizeof(dhpub));
+
+       /*
+        * Load required RSA private key from file, default "ntpkey".
+        */
+       if (private_key_file == NULL)
+               private_key_file = "ntpkey";
+       crypto_rsa(private_key_file, &private_key_fstamp,
+           (u_char *)&private_key, sizeof(R_RSA_PRIVATE_KEY));
+       if (private_key.bits == 0) {
+               msyslog(LOG_ERR,
+                   "crypto_setup: required RSA private key missing or corrupted");
+               exit;
+       }
+
+       /*
+        * Load required RSA public key from file, default
+        * "ntpkey_host", where "host" is the canonical name of this
+        * machine.
         */
-       host.tstamp = htonl(sys_revoketime.l_ui);
        if (public_key_file == NULL) {
+               snprintf(filename, MAXFILENAME, "ntpkey_%s",
+                   sys_hostname);
+               public_key_file = emalloc(strlen(filename) + 1);
+               strcpy(public_key_file, filename);
+       }
+       crypto_rsa(public_key_file, &public_key_fstamp,
+           (u_char *)&public_key, sizeof(R_RSA_PUBLIC_KEY));
+       if (public_key.bits == 0) {
                msyslog(LOG_ERR,
-                   "crypto_agree: public key file unavailable");
-               return;
+                   "crypto_setup: required RSA public key missing or corrupted");
+               exit;
        }
-       if ((sptr = strstr(public_key_file, sys_hostname)) == NULL) {
+       if (strstr(public_key_file, sys_hostname) == NULL) {
                msyslog(LOG_ERR,
-                   "crypto_agree: public key file %s not generated by this host",
+                   "crypto_setup: RSA public key file %s not generated by this host",
                    public_key_file);
-               return;
+               exit;
        }
-       strcpy(filename, sptr);
+
+       /*
+        * Assemble public key and host name in network byte order.
+        * These data will later be signed and sent in response to
+        * a client request. Note that the modulus must be a u_int32 in
+        * network byte order independent of the host order or u_int
+        * size.
+        */
+       strcpy(filename, sys_hostname);
        for (len = strlen(filename) + 1; len % 4 != 0; len++)
-               filename[len] = 0;
-       host.vallen = htonl(len);
-       host.val = emalloc(len);
-       memcpy(host.val, filename, len);
-       host.siglen = dh_params.primeLen;
-       if (host.sig == NULL)
-               host.sig = emalloc(dh_params.primeLen);
+               filename[len - 1] = 0;
+       host.fstamp = htonl(public_key_fstamp);
+       temp = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int) + 4;
+       host.vallen = htonl(temp + len);
+       host.val = emalloc(temp + len);
+       pp = (u_int32 *)host.val;
+       *pp++ = htonl(public_key.bits);
+       memcpy(pp, &public_key.modulus, temp - 4);
+       memcpy(&host.val[temp], filename, len);
+       temp = private_key.bits / 8;
+       host.sig = emalloc(private_key.bits / 8);
+
+       /*
+        * Load optional Diffie-Hellman key agreement parameters from
+        * file, default "ntpkey_dh". If the file is missing or
+        * defective, the parameters can later be retrieved from a
+        * server.
+        */
+       if (dh_params_file == NULL)
+               dh_params_file = "ntpkey_dh";
+       crypto_dh(dh_params_file, &dh_params_fstamp);
+       dhpub.fstamp = htonl(dh_params_fstamp);
+       temp = dh_params.primeLen;
+       if (temp == 0)
+               return;
+       dhpub.vallen = htonl(temp);
+       dhpub.val = emalloc(temp);
+       dhpub.sig = emalloc(private_key.bits / 8);
+}
+
+
+/*
+ * crypto_agree - compute and sign host name and Diffie-Hellman values
+ */
+void
+crypto_agree(void)
+{
+       R_RANDOM_STRUCT randomstr;      /* wiggle bits */
+       R_SIGNATURE_CTX ctx;            /* signature context */
+       u_int len, temp;
+       int rval;
+       int i;
+
+       /*
+        * Sign host name and timestamps.
+        */
+       host.tstamp = htonl(sys_revoketime.l_ui);
        R_SignInit(&ctx, DA_MD5);
-       R_SignUpdate(&ctx, (u_char *)&host, 8);
-       R_SignUpdate(&ctx, host.val, len);
+       R_SignUpdate(&ctx, (u_char *)&host, 12);
+       R_SignUpdate(&ctx, host.val, ntohl(host.vallen));
        rval = R_SignFinal(&ctx, host.sig, &temp, &private_key);
        if (rval != 0) {
                msyslog(LOG_ERR,
                    "crypto_agree: host signature fails %x", rval);
-               return;
+               exit(1);
        }
+       host.siglen = ntohl(temp);
 
        /*
-        * Compute Diffie-Hellman public value. Note that the length of
-        * the private value is set arbitrarily to half the prime
-        * length.
+        * Sign Diffie-Hellman parameters and timestamps.
         */
        if (dh_params.primeLen == 0) {
                msyslog(LOG_ERR,
-                   "unavailable d-h parameters");
+                   "crypto_agree: unavailable DH parameters");
                return;
        }
+       dhparam.tstamp = htonl(sys_revoketime.l_ui);
+       R_SignInit(&ctx, DA_MD5);
+       R_SignUpdate(&ctx, (u_char *)&dhparam, 12);
+       R_SignUpdate(&ctx, dhparam.val, ntohl(dhparam.vallen));
+       rval = R_SignFinal(&ctx, dhparam.sig, &temp, &private_key);
+       if (rval != 0) {
+               msyslog(LOG_ERR,
+                   "crypto_agree: DH parameters signature fails %x",
+                   rval);
+               exit(1);
+       }
+       dhparam.siglen = ntohl(temp);
+
+       /*
+        * Compute Diffie-Hellman public value.
+        */
        R_RandomInit(&randomstr);
        R_GetRandomBytesNeeded(&len, &randomstr);
        for (i = 0; i < len; i++) {
-               temp = random();
+               temp = RANDOM;
                R_RandomUpdate(&randomstr, (u_char *)&temp, 1);
        }
-       if (dh_private == NULL)
-               dh_private = (u_char *)emalloc(dh_keyLen);
-       if (dh_public == NULL)
-               dh_public = (u_char *)emalloc(dh_params.primeLen);
-       rval = R_SetupDHAgreement(dh_public, dh_private, dh_keyLen,
+       rval = R_SetupDHAgreement(dhpub.val, dh_private, dh_keyLen,
            &dh_params, &randomstr);
        if (rval != 0) {
-               msyslog(LOG_ERR, "invalid d-h parameters");
-               return;
+               msyslog(LOG_ERR, "crypto_agree: invalid DH parameters");
+               exit(1);
        }
 
        /*
-        * Sign Diffie-Hellman public value.
+        * Sign Diffie-Hellman public value and timestamps.
         */
-       if (dh_sign == NULL)
-               dh_sign = emalloc(dh_params.primeLen);
+       dhpub.tstamp = htonl(sys_revoketime.l_ui);
        R_SignInit(&ctx, DA_MD5);
-       R_SignUpdate(&ctx, (char *)&host.tstamp, 4);
-       temp = htonl(dh_params.primeLen);
-       R_SignUpdate(&ctx, (char *)&temp, 4);
-       R_SignUpdate(&ctx, dh_public, dh_params.primeLen);
-       rval = R_SignFinal(&ctx, dh_sign, &temp, &private_key);
+       R_SignUpdate(&ctx, (u_char *)&dhpub, 12);
+       R_SignUpdate(&ctx, dhpub.val, ntohl(dhpub.vallen));
+       rval = R_SignFinal(&ctx, dhpub.sig, &temp, &private_key);
        if (rval != 0) {
                msyslog(LOG_ERR,
-                   "crypto_agree: d-h signature fails %x", rval);
-               return;
+                   "crypto_agree: DH public value signature fails %x",
+                   rval);
+               exit(1);
        }
+       dhpub.siglen = ntohl(temp);
 #ifdef DEBUG
        if (debug)
                printf(
-                   "cypto_agree: host %s d-h prime %d gen %d\n",
-                   host.val, dh_params.primeLen,
-                   dh_params.generatorLen);
+                   "cypto_agree: host %s ts %u pubval %d\n",
+                   sys_hostname, ntohl(host.tstamp),
+                   ntohl(dhpub.vallen));
 #endif
 }
 
 
 /*
- * crypto_read - read RSA key, decode and check for errors
+ * crypto_rsa - read RSA key, decode and check for errors.
  */
-static int
-crypto_read(
-       u_char *cp,             /* file name */
+static void
+crypto_rsa(
+       char *cp,               /* file name */
+       u_int *fstamp,          /* filestamp */
        u_char *key,            /* key pointer */
        u_int keylen            /* key length */
        )
 {
-       FILE *str;
-       u_char buf[MAX_KEYLEN];
-       u_char encoded_key[MAX_KEYLEN];
-       char filename[MAXFILENAME];
-       u_int modulus;
-       u_int buflen;
+       FILE *str;              /* file handle */
+       u_char buf[MAX_KEYLEN]; /* file line buffer */
+       u_char encoded_key[MAX_KEYLEN]; /* encoded key buffer */
+       char filename[MAXFILENAME]; /* name of parameter file */
+       char linkname[MAXFILENAME]; /* file link (for filestamp) */
+       u_int bits, len;
        char *rptr;
        int rval;
 
        /*
-        * Open the key file and discard comment lines.
+        * Open the key file and discard comment lines. If the first
+        * character of the file name is not '/', prepend the keys
+        * directory string. 
         */
-       if (strlen(cp) == 0 || strlen(cp) >= MAXFILENAME - 1) {
-               msyslog(LOG_ERR, "invalid key file name length %d",
-                   strlen(filename));
-               return (0);
-       } else if (*cp == '/') {
+       if (*cp == '/')
                strcpy(filename, cp);
-       } else {
-               snprintf(filename, MAXFILENAME - 1, "%s%s", keysdir,
-                   cp);
-       }
+       else
+               snprintf(filename, MAXFILENAME, "%s%s", keysdir, cp);
        str = fopen(filename, "r");
        if (str == NULL) {
-               msyslog(LOG_ERR, "key file %s not found", filename);
-               return (0);
+               msyslog(LOG_ERR, "RSA key file %s not found", filename);
+               return;
        }
+
+       /*
+        * Ignore initial comments and empty lines.
+        */
        while ((rptr = fgets(buf, MAX_KEYLEN - 1, str)) != NULL) {
-               buflen = strlen(buf);
-               if (buflen < 1)
+               len = strlen(buf);
+               if (len < 1)
                        continue;
                if (*buf == '#' || *buf == '\r' || *buf == '\0')
                        continue;
@@ -906,58 +1044,224 @@ crypto_read(
        }
 
        /*
-        * We are rather paranoid here, since an intruder can cause a
+        * We are rather paranoid here, since an intruder might cause a
         * coredump by infiltrating a naughty key. The line must contain
         * a single integer followed by a PEM encoded, null-terminated
         * string.
         */
-       if (rptr == NULL) {
-               msyslog(LOG_ERR, "invalid key file %s", filename);
-               return (0);
+       rval = RV_OK;
+       if (rptr == NULL)
+               rval = RV_DAT;
+       else if (sscanf(buf, "%d %s", &bits, encoded_key) != 2)
+               rval = RV_DAT;
+       else if (R_DecodePEMBlock(&buf[sizeof(u_int)], &len,
+                   encoded_key, strlen(encoded_key)))
+               rval = RV_DEC;
+       else if ((len += sizeof(u_int)) != keylen)
+               rval = RV_KEY;
+       else if (bits < MIN_RSA_MODULUS_BITS || bits >
+           MAX_RSA_MODULUS_BITS)
+               rval = RV_KEY;
+       if (rval != RV_OK) {
+               fclose(str);
+               msyslog(LOG_ERR,
+                   "crypto_dh: RSA key file %s error %x",
+                   cp, rval);
+               return;
        }
-       if (sscanf(buf, "%d %s", &modulus, encoded_key) != 2) {
-               msyslog(LOG_ERR, "invalid key format %s", filename);
-               return (0);
+       fclose(str);
+       *(u_int *)buf = bits;
+       memcpy(key, buf, keylen);
+
+       /*
+        * Extract filestamp if present.
+        */
+       len = readlink(filename, linkname, MAXFILENAME - 1);
+       if (len > 0) {
+               linkname[len] = '\0';
+               rptr = strrchr(linkname, '.');
+       } else {
+#ifdef DEBUG
+               if (len == -1 && errno != EINVAL)
+                       msyslog(LOG_INFO,
+                               "crypto_rsa: readlink(%s) returned %m",
+                               filename);
+#endif /* DEBUG */
+               rptr = strrchr(filename, '.');
        }
+       if (rptr != NULL)
+               sscanf(++rptr, "%u", fstamp);
+#ifdef DEBUG
+       if (debug)
+               printf(
+                   "crypto_rsa: RSA key file %s fs %u modulus %d\n",
+                   cp, *fstamp, bits);
+#endif
+       return;
+}
+
+
+/*
+ * crypto_dh - read DH parameters, decode and check for errors.
+ */
+static void
+crypto_dh(
+       char *cp,               /* file name */
+       u_int *fstamp           /* filestamp */
+       )
+{
+       FILE *str;              /* file handle */
+       u_char buf[MAX_KEYLEN]; /* file line buffer */
+       u_char encoded_key[MAX_KEYLEN]; /* encoded key buffer */
+       u_char prime[MAX_KEYLEN]; /* decoded prime */
+       u_char generator[MAX_KEYLEN]; /* decode generator */
+       u_int primelen;         /* prime length (octets) */
+       u_int generatorlen;     /* generator length (octets) */
+       char filename[MAXFILENAME]; /* name of parameter file */
+       char linkname[MAXFILENAME]; /* file link (for filestamp) */
+       u_int32 *pp;
+       u_int len;
+       char *rptr;
+       int rval;
 
        /*
-        * Initialize the key with the decoded PEM string, but leave
-        * room for the modulus length in the key structure.
+        * Open the key file and discard comment lines. If the first
+        * character of the file name is not '/', prepend the keys
+        * directory string. 
         */
-       rval = R_DecodePEMBlock(&key[sizeof(u_int)], &buflen,
-           encoded_key, strlen(encoded_key));
-       if (rval != 0) {
-               msyslog(LOG_ERR, "invalid key %s %x", filename, rval);
-               return (0);
+       *fstamp = 0;
+       if (*cp == '/')
+               strcpy(filename, cp);
+       else
+               snprintf(filename, MAXFILENAME, "%s%s", keysdir, cp);
+       str = fopen(filename, "r");
+       if (str == NULL) {
+               msyslog(LOG_ERR,
+                   "crypto_dh: DH parameter file %s not found",
+                   filename);
+               return;
        }
 
        /*
-        * Make sure the structure has the required length.
+        * Ignore initial comments and empty lines.
         */
-       buflen += sizeof(u_int);
-       if (buflen != keylen) {
-               msyslog(LOG_ERR, "invalid key length %s %d", filename,
-                   buflen);
-               return (0);
+       while ((rptr = fgets(buf, MAX_KEYLEN - 1, str)) != NULL) {
+               if (strlen(buf) < 1)
+                       continue;
+               if (*buf == '#' || *buf == '\r' || *buf == '\0')
+                       continue;
+               break;
        }
 
        /*
-        * Make sure the modulus length is within limits.
+        * We are rather paranoid here, since an intruder might cause a
+        * coredump by infiltrating a naughty key. The line must contain
+        * a single integer followed by a PEM encoded, null-terminated
+        * string.
         */
-       if (modulus < MIN_RSA_MODULUS_BITS || modulus >
-           MAX_RSA_MODULUS_BITS) {
-               msyslog(LOG_ERR, "invalid key modulus %s %d", filename,
-                   modulus);
-               return (0);
+       rval = RV_OK;
+       if (rptr == NULL)
+               rval = RV_DAT;
+       else if (sscanf(buf, "%u %s", &primelen, encoded_key) != 2)
+               rval = RV_DAT;
+       else if (primelen > MAX_DH_LEN)
+               rval = RV_KEY;
+       else if (R_DecodePEMBlock(prime, &len, encoded_key,
+           strlen(encoded_key)))
+               rval = RV_DEC;
+       else if (primelen != len || primelen >
+           DECODED_CONTENT_LEN(strlen(encoded_key)))
+               rval = RV_DAT;
+       if (rval != RV_OK) {
+               fclose(str);
+               msyslog(LOG_ERR,
+                   "crypto_dh: DH parameter file %s prime error %x",
+                   cp, rval);
+               return;
+       }
+
+       /*
+        * Load and check generator.
+        */
+       rval = RV_OK;
+       if (fscanf(str, "%u %s", &generatorlen, encoded_key) != 2)
+               rval = RV_DAT;
+       else if (generatorlen > MAX_DH_LEN)
+               rval = RV_KEY;
+       else if (R_DecodePEMBlock(generator, &len, encoded_key,
+           strlen(encoded_key)))
+               rval = RV_DEC;
+       else if (generatorlen != len || generatorlen >
+           DECODED_CONTENT_LEN(strlen(encoded_key)))
+               rval = RV_DAT;
+       if (rval != RV_OK) {
+               msyslog(LOG_ERR,
+                   "crypto_dh: DH parameter file %s generator error %x",
+                   cp, rval);
+               return;
        }
-       ((u_int *)key)[0] = modulus;
+       fclose(str);
+
+       /*
+        * Initialize Diffie-Hellman parameters extension field in
+        * network byte order. Note the private key length is set
+        * arbitrarily at half the prime length.
+        */
+       dhparam.fstamp = htonl(dh_params_fstamp);
+       len = 4 + primelen + 4 + generatorlen;
+       dhparam.vallen = htonl(len);
+       dhparam.val = emalloc(len);
+       pp = (u_int32 *)dhparam.val;
+       *pp++ = htonl(primelen);
+       dh_params.prime = (u_char *)pp;
+       memcpy(pp, &prime, primelen);
+       pp += primelen / 4;
+       *pp++ = htonl(generatorlen);
+       dh_params.generator = (u_char *)pp;
+       memcpy(pp, &generator, generatorlen);
+       dhparam.sig = emalloc(private_key.bits / 8);
+
+       /*
+        * Initialize parameters used by the agreement algorithm
+        */
+       dh_params.primeLen = primelen;
+       dh_params.generatorLen = generatorlen;
+       dh_keyLen = primelen / 2;
+       dh_private = emalloc(dh_keyLen);
+
+       /*
+        * Initialize Diffie-Hellman public value extension field.
+        */
+       dhpub.fstamp = htonl(dh_params_fstamp);
+       dhpub.vallen = htonl(dh_params.primeLen);
+       dhpub.val = emalloc(dh_params.primeLen);
+       dhpub.sig = emalloc(private_key.bits / 8);
+
+       /*
+        * Extract filestamp if present.
+        */
+       len = readlink(filename, linkname, MAXFILENAME - 1);
+       if (len > 0) {
+               linkname[len] = '\0';
+               rptr = strrchr(linkname, '.');
+       } else {
+#ifdef DEBUG
+               if (len == -1 && errno != EINVAL)
+                       msyslog(LOG_INFO,
+                               "crypto_dh: readlink(%s) returned %m",
+                               filename);
+#endif /* DEBUG */
+               rptr = strrchr(filename, '.');
+       }
+       if (rptr != NULL)
+               sscanf(++rptr, "%u", fstamp);
 #ifdef DEBUG
        if (debug)
                printf(
-                   "crypto_read: RSA key file %s length %d modulus %d\n",
-                   cp, keylen, modulus);
+                   "crypto_dh: DH parameter file %s fs %u prime %u gen %u\n",
+                   dh_params_file, dh_params_fstamp,
+                   dh_params.primeLen, dh_params.generatorLen);
 #endif
-       return (1);
 }
 
 
@@ -971,16 +1275,30 @@ crypto_read(
 int
 crypto_public(
        struct peer *peer,      /* peer structure pointer */
-       u_char *cp              /* canonical host name */
+       u_char *cp,             /* canonical host name */
+       u_int fstamp            /* filestamp */
        )
 {
        R_RSA_PUBLIC_KEY keybuf;
        u_int keylen = sizeof(R_RSA_PUBLIC_KEY);
        char filename[MAXFILENAME];
+       u_int temp;
 
-       snprintf(filename, MAXFILENAME - 1, "ntpkey_%s", cp);
-       if (!crypto_read(filename, (u_char *)&keybuf, keylen))
+       /*
+        * If the filestamp is nonzero, append it as the file name
+        * extension. If not and a link name has a filestamp, append
+        * that for looks.
+        */
+       if (fstamp == 0)
+               snprintf(filename, MAXFILENAME, "ntpkey_%s", cp);
+       else
+               snprintf(filename, MAXFILENAME, "ntpkey_%s.%u", cp,
+                   fstamp);
+       crypto_rsa(filename, &temp, (u_char *)&keybuf, keylen);
+       if (keybuf.bits == 0)
                return (0);
+       if (fstamp == 0 && temp != 0)
+               sprintf(filename, "%s.%u", filename, temp);
        if (peer->keystr != NULL)
                free(peer->keystr);
        peer->keystr = emalloc(strlen(filename) + 1);
@@ -993,120 +1311,8 @@ crypto_public(
 
 
 /*
- * crypto_line - read, decode and install Diffie-Hellman prime and
- * generator. Be very parannoyed here if every little thing is not
- * exactly right.
- */
-static void
-crypto_line(
-       FILE *str,              /* file handle */
-       u_char **key,           /* decoded string pointer */
-       u_int *len              /* length */
-       )
-{
-       u_char buf[MAX_KEYLEN];
-       u_char encoded_key[MAX_KEYLEN];
-       u_int temp, temp1, temp2;
-       char *rptr;
-
-       /*
-        * Read key and length. Bail out if the length word doesn't
-        * match the decoded string length and in other cases.
-        */
-       *key = NULL;
-       *len = 0;
-       while ((rptr = fgets(buf, MAX_KEYLEN - 1, str)) != NULL) {
-               if (strlen(buf) < 1)
-                       continue;
-               if (*buf == '#' || *buf == '\r' || *buf == '\0')
-                       continue;
-               break;
-       }
-       if (sscanf(buf, "%d %s", &temp, encoded_key) != 2)
-               return;
-       if (temp > MAX_DH_LEN)
-               return;
-       temp2 = DECODED_CONTENT_LEN(strlen(encoded_key));
-       if (R_DecodePEMBlock(buf, &temp1, encoded_key,
-           strlen(encoded_key)))
-               return;
-       if (temp != temp1 || temp > temp2)
-               return;
-       *key = (u_char *)emalloc(temp2);
-       memcpy(*key, buf, temp2);
-       *len = temp;
-       return;
-}
-
-
-/*
- * crypto_setup - read RSA private key, RSA public key and Diffie-
- * Hellman parameter files and initialize cryptographic data.
- */
-void
-crypto_setup(void)
-{
-       FILE *str;
-       char hostname[MAXFILENAME];
-       char filename[MAXFILENAME];
-
-       /*
-        * Load RSA private key from file.
-        */
-       if (private_key_file == NULL)
-               private_key_file = "ntpkey";
-       crypto_read(private_key_file, (u_char *)&private_key,
-           sizeof(R_RSA_PRIVATE_KEY));
-
-       /*
-        * Load RSA public key from file, default "ntpkey_host", where
-        * host is the DNS name of this machine.
-        */
-       if (public_key_file == NULL) {
-               gethostname(hostname, MAXFILENAME);
-               snprintf(filename, MAXFILENAME - 1, "ntpkey_%s",
-                   hostname);
-               public_key_file = emalloc(strlen(filename) + 1);
-               strcpy(public_key_file, filename);
-       }
-       crypto_read(public_key_file, (u_char *)&public_key,
-           sizeof(R_RSA_PUBLIC_KEY));
-
-       /*
-        * Load Diffie-Hellman key agreement parameters from file.
-        */
-       if (dh_params_file == NULL)
-               dh_params_file = "ntpkey_dh";
-       if (*dh_params_file == '/')
-               strcpy(filename, dh_params_file);
-       else
-               snprintf(filename, MAXFILENAME - 1, "%s%s", keysdir,
-                   dh_params_file);
-
-       str = fopen(filename, "r");
-       if (str == NULL) {
-               msyslog(LOG_ERR, "key file %s not found",
-                   filename);
-               return;
-       }
-
-       /*
-        * Read prime and generator. Note that the private value length
-        * is set arbitrarily at half the prime length.
-        */
-       crypto_line(str, &dh_params.prime, &dh_params.primeLen);
-       crypto_line(str, &dh_params.generator, &dh_params.generatorLen);
-       if (dh_params.primeLen == 0|| dh_params.generatorLen == 0) {
-               msyslog(LOG_ERR,
-                   "invalid Diffie-Hellman file format or value");
-               return;
-       }
-       dh_keyLen = dh_params.primeLen / 2;
-}
-
-
-/*
- * crypto_config - configure crypto data.
+ * crypto_config - configure crypto data from crypto configuration
+ * command.
  */
 void
 crypto_config(
@@ -1120,18 +1326,11 @@ crypto_config(
         * Initialize flags
         */
        case CRYPTO_CONF_FLAGS:
-               crypto_flags = atoi(cp);
-               break;
-       /*
-        * Override the default Diffie-Hellman parameter file name.
-        */
-       case CRYPTO_CONF_DH:
-               dh_params_file = emalloc(strlen(cp) + 1);
-               strcpy(dh_params_file, cp);
+               sscanf(cp, "%x", &crypto_flags);
                break;
 
        /*
-        * Override the default RSA private key file name.
+        * Set RSA private key file name.
         */
        case CRYPTO_CONF_PRIV:
                private_key_file = emalloc(strlen(cp) + 1);
@@ -1139,7 +1338,7 @@ crypto_config(
                break;
 
        /*
-        * Override the default RSA public key file name.
+        * Set RSA public key file name.
         */
        case CRYPTO_CONF_PUBL:
                public_key_file = emalloc(strlen(cp) + 1);
@@ -1147,7 +1346,15 @@ crypto_config(
                break;
 
        /*
-        * Override the default crypto keys directory.
+        * Set Diffie-Hellman parameter file name.
+        */
+       case CRYPTO_CONF_DH:
+               dh_params_file = emalloc(strlen(cp) + 1);
+               strcpy(dh_params_file, cp);
+               break;
+
+       /*
+        * Set crypto keys directory.
         */
        case CRYPTO_CONF_KEYS:
                keysdir = emalloc(strlen(cp) + 1);
@@ -1155,21 +1362,5 @@ crypto_config(
                break;
        }
 }
-
-
-/*
- * crypto_init () - initialize things.
- */
-void
-crypto_init(void)
-{
-       /*
-        * Zeroize sensitive crypto data.
-        */
-       memset((char *)&private_key, 0, sizeof(private_key));
-       memset((char *)&public_key, 0, sizeof(public_key));
-       memset((char *)&dh_params, 0, sizeof(dh_params));
-       memset((char *)&host, 0, sizeof(host));
-}
 #endif /* PUBKEY */
 #endif /* AUTOKEY */
index 3501be5256b4ca7d10fa7c4de7592e086c21592b..5a8696deca8b763f495c278e77934d38732cd609 100644 (file)
@@ -412,7 +412,7 @@ expire_all(void)
        if (sys_leap != LEAP_NOTINSYNC)
                get_systime(&sys_revoketime);
 #ifdef PUBKEY
-       if (crypto_enable)
+       if (crypto_flags)
                crypto_agree();
 #endif /* PUBKEY */
 #ifdef DEBUG
@@ -576,7 +576,9 @@ peer_config(
 #ifdef PUBKEY
        if (!(peer->flags & FLAG_SKEY) || peer->hmode == MODE_BROADCAST)
                return (peer);
-       crypto_public(peer, keystr);
+/* following line commented out until resolver is fixed
+       crypto_public(peer, keystr, 0);
+*/
 #endif /* PUBKEY */
        return (peer);
 }
index 26c0db46f28fa1e3901d021d2d703da7e710a2be..efe075c77dda20500d423457399937380e05772a 100644 (file)
@@ -541,8 +541,8 @@ receive(
                        break;
                }
                peer_config_manycast(peer2, peer);
-#ifdef PUBKEY
-               if (crypto_enable)
+#if defined(PUBKEY) && 0
+               if (crypto_flags)
                        ntp_res_name(peer->srcadr.sin_addr.s_addr,
                            peer->associd);
 #endif /* PUBKEY */
@@ -571,8 +571,8 @@ receive(
                peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
                    MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode),
                    NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid);
-#ifdef PUBKEY
-               if (crypto_enable)
+#if defined(PUBKEY) && 0
+               if (crypto_flags)
                        ntp_res_name(peer->srcadr.sin_addr.s_addr,
                            peer->associd);
 #endif /* PUBKEY */
@@ -596,8 +596,8 @@ receive(
                        break;
                peer->flags |= FLAG_MCAST1 | FLAG_MCAST2 | FLAG_BURST;
                peer->hmode = MODE_CLIENT;
-#ifdef PUBKEY
-               if (crypto_enable)
+#if defined(PUBKEY) && 0
+               if (crypto_flags)
                        ntp_res_name(peer->srcadr.sin_addr.s_addr,
                             peer->associd);
 #endif /* PUBKEY */
@@ -717,6 +717,8 @@ receive(
                } else {
                        int i;
 
+printf("xxx %08x %08x\n", tkeyid, peer->pkeyid);
+
                        for (i = 0; ; i++) {
                                if (tkeyid == peer->pkeyid ||
                                    tkeyid == peer->recauto.key) {
@@ -858,8 +860,10 @@ process_packet(
         * The header is valid. Capture the remaining header values and
         * mark as reachable.
         */
+/*
        record_raw_stats(&peer->srcadr, &peer->dstadr->sin,
            &p_org, &p_rec, &p_xmt, &peer->rec);
+*/
        peer->leap = PKT_LEAP(pkt->li_vn_mode);
        peer->pmode = pmode;            /* unspec */
        peer->stratum = PKT_TO_STRATUM(pkt->stratum);
@@ -1931,50 +1935,46 @@ peer_xmit(
                 *
                 * 5. When the agreed key has been stored and the key
                 *    list is regenerated, send the autokey values
-                *    gratis.
+                *    gratis unless it has already been sent.
                 */
                case MODE_ACTIVE:
                case MODE_PASSIVE:
 #ifdef PUBKEY
-                       if (crypto_enable && peer->cmmd != 0) {
+                       if (crypto_flags && peer->cmmd != 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, (peer->cmmd >> 16) |
                                    CRYPTO_RESP, peer->hcookie,
                                    peer->associd);
-                               peer->cmmd = 0;
-                       }
-                       if (crypto_enable && !(crypto_flags &
-                           CRYPTO_FLAG_PUBL) && peer->pubkey == 0) {
+                       if (crypto_flags && !(crypto_flags &
+                           CRYPTO_FLAG_PUBL) && peer->pubkey == 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_NAME, peer->hcookie,
                                    peer->assoc);
-                       } else if (peer->pcookie.tstamp == 0) {
+                       else if (peer->pcookie.tstamp == 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_DH, peer->hcookie,
                                    peer->assoc);
 #else
-                       if (peer->cmmd != 0) {
+                       if (peer->cmmd != 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, (peer->cmmd >> 16) |
                                    CRYPTO_RESP, peer->hcookie,
                                    peer->associd);
-                               peer->cmmd = 0;
-                       }
-                       if (peer->pcookie.tstamp == 0) {
+                       if (peer->pcookie.tstamp == 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_PRIV, peer->hcookie,
                                    peer->assoc);
 #endif /* PUBKEY */
-                       } else if (!(peer->flags & FLAG_AUTOKEY)) {
+                       else if (!(peer->flags & FLAG_AUTOKEY))
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_AUTO, peer->hcookie,
                                    peer->assoc);
-                       } else if (peer->keynumber == peer->sndauto.seq)
-                           {
+                       else if (peer->keynumber == peer->sndauto.seq &&
+                           (peer->cmmd >> 16) != CRYPTO_AUTO)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_AUTO | CRYPTO_RESP,
                                    peer->hcookie, peer->associd);
-                       }
+                       peer->cmmd = 0;
                        break;
 
                /*
@@ -1988,31 +1988,29 @@ peer_xmit(
                 * for the cookie at each key list regeneration anyway.
                 */
                case MODE_CLIENT:
-                       if (peer->cmmd != 0) {
+                       if (peer->cmmd != 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, (peer->cmmd >> 16) |
                                    CRYPTO_RESP, peer->hcookie,
                                    peer->associd);
-                               peer->cmmd = 0;
-                       }
 #ifdef PUBKEY
-                       if (crypto_enable && !(crypto_flags &
-                           CRYPTO_FLAG_PUBL) && peer->pubkey == 0) {
+                       if (crypto_flags && !(crypto_flags &
+                           CRYPTO_FLAG_PUBL) && peer->pubkey == 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_NAME, peer->hcookie,
                                    peer->assoc);
-                       else
+                       else
 #endif /* PUBKEY */
-                       if (peer->pcookie.tstamp == 0) {
+                       if (peer->pcookie.tstamp == 0)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_PRIV, peer->hcookie,
                                    peer->assoc);
-                       else if (!(peer->flags & FLAG_AUTOKEY) &&
-                           peer->flags & FLAG_MCAST2) {
+                       else if (!(peer->flags & FLAG_AUTOKEY) &&
+                           peer->flags & FLAG_MCAST2)
                                sendlen += crypto_xmit((u_int32 *)&xpkt,
                                    sendlen, CRYPTO_AUTO, peer->hcookie,
                                    peer->assoc);
-                       }
+                       peer->cmmd = 0;
                        break;
                }
 
index ada545366ff6a87433cd2d32f5bf801c43663fa7..58bc4b90f90ade1673103ca118fe51bc9ed90fc5 100644 (file)
@@ -728,9 +728,6 @@ service_main(
 #ifdef REFCLOCK
        init_refclock();
 #endif
-#ifdef PUBKEY
-       crypto_init();          /* Call *before* going to high-priority */
-#endif /* PUBKEY */
        set_process_priority();
        init_proto();           /* Call at high priority */
        init_io();
@@ -751,7 +748,7 @@ service_main(
        sys_hostname = emalloc(n);
        memcpy(sys_hostname, hostname, n);
 #ifdef PUBKEY
-       if (crypto_enable)
+       if (crypto_flags)
                crypto_setup();
 #endif /* PUBKEY */
 #endif /* AUTOKEY */
index d4b8e0cc8aec687bbfcc1dd5280a3a1b162a7599..709eaf049bca5e0798ed7a2820aacc716af292bd 100644 (file)
@@ -17,7 +17,6 @@
 #define MAXKEYLEN      1024    /* maximum encoded key length */
 #define MODULUSLEN     512     /* length of RSA modulus */
 #define PRIMELEN       512     /* length of D_H prime, generator */
-#define GENLEN         256     /* length of D-H key and subprime */
 
 /*
  * This program generates four files: ntp.keys containing the DES/MD5
@@ -221,7 +220,7 @@ main(
        len = DH_PRIME_LEN(PRIMELEN);
        dh_params.prime = (u_char *)malloc(len);
        dh_params.generator = (u_char *)malloc(len);
-       rval = R_GenerateDHParams(&dh_params, PRIMELEN, GENLEN,
+       rval = R_GenerateDHParams(&dh_params, PRIMELEN, PRIMELEN / 2,
            &randomstr);
        if (rval) {
                printf("R_GenerateDHParams error %x\n", rval);