FreeBSD/contrib/ntp/ntpd/ntp_crypto.c
/*
 * make_keylist - generate key list
 *
 * Returns
 * XEVNT_OK	success
 * XEVNT_ERR	protocol error
 *
 * This routine constructs a pseudo-random sequence by repeatedly
 * hashing the session key starting from a given source address,
 * destination address, private value and the next key ID of the
 * preceeding session key. The last entry on the list is saved along
 * with its sequence number and public signature.
 */
generate key list
Returns
XEVNT_OK     success
XEVNT_ERR    protocol error

This routine constructs a pseudo-random sequence by repeatedly
hashing the session key starting from a given source address,
destination address, private value and the next key ID of the
preceeding session key. The last entry on the list is saved along
with its sequence number and public signature.
generate key list Returns XEVNT_OK success XEVNT_ERR protocol error This routine constructs a pseudo - random sequence by repeatedly hashing the session key starting from a given source address destination address private value and the next key ID of the preceeding session key . The last entry on the list is saved along with its sequence number and public signature .
int
make_keylist(
	struct peer *peer,	
	struct interface *dstadr 
	)
{
	EVP_MD_CTX *ctx;	
	tstamp_t tstamp;	
	struct autokey *ap;	
	struct value *vp;	
	keyid_t	keyid = 0;	
	keyid_t	cookie;		
	long	lifetime;
	u_int	len, mpoll;
	int	i;
	if (!dstadr)
		return XEVNT_ERR;
	tstamp = crypto_time();
	if (peer->keylist == NULL)
		peer->keylist = eallocarray(NTP_MAXSESSION,
					    sizeof(keyid_t));
	while (1) {
		keyid = ntp_random() & 0xffffffff;
		if (keyid <= NTP_MAXKEY)
			continue;
		if (authhavekey(keyid))
			continue;
		break;
	}
	mpoll = 1 << min(peer->ppoll, peer->hpoll);
	lifetime = min(1U << sys_automax, NTP_MAXSESSION * mpoll);
	if (peer->hmode == MODE_BROADCAST)
		cookie = 0;
	else
		cookie = peer->pcookie;
	for (i = 0; i < NTP_MAXSESSION; i++) {
		peer->keylist[i] = keyid;
		peer->keynumber = i;
		keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
		    cookie, lifetime + mpoll);
		lifetime -= mpoll;
		if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
		    lifetime < 0 || tstamp == 0)
			break;
	}
	vp = &peer->sndval;
	if (vp->ptr == NULL)
		vp->ptr = emalloc(sizeof(struct autokey));
	ap = (struct autokey *)vp->ptr;
	ap->seq = htonl(peer->keynumber);
	ap->key = htonl(keyid);
	vp->tstamp = htonl(tstamp);
	vp->fstamp = hostval.tstamp;
	vp->vallen = htonl(sizeof(struct autokey));
	vp->siglen = 0;
	if (tstamp != 0) {
		if (vp->sig == NULL)
			vp->sig = emalloc(sign_siglen);
		ctx = EVP_MD_CTX_new();
		EVP_SignInit(ctx, sign_digest);
		EVP_SignUpdate(ctx, (u_char *)vp, 12);
		EVP_SignUpdate(ctx, vp->ptr, sizeof(struct autokey));
		if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
			INSIST(len <= sign_siglen);
			vp->siglen = htonl(len);
			peer->flags |= FLAG_ASSOC;
		}
		EVP_MD_CTX_free(ctx);
	}
	DPRINTF(1, ("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
		    peer->keynumber, keyid, cookie, ntohl(vp->tstamp),
		    ntohl(vp->fstamp), peer->hpoll));
	return (XEVNT_OK);
}
int make_keylist ( struct peer * peer , struct interface * dstadr ) { EVP_MD_CTX * ctx ; tstamp_t tstamp ; struct autokey * ap ; struct value * vp ; keyid_t keyid = 0 ; keyid_t cookie ; long lifetime ; u_int len , mpoll ; int i ; if ( ! dstadr ) return XEVNT_ERR ; tstamp = crypto_time ( ) ; if ( peer -> keylist == NULL ) peer -> keylist = eallocarray ( NTP_MAXSESSION , sizeof ( keyid_t ) ) ; while ( 1 ) { keyid = ntp_random ( ) & 0xffffffff ; if ( keyid <= NTP_MAXKEY ) continue ; if ( authhavekey ( keyid ) ) continue ; break ; } mpoll = 1 << min ( peer -> ppoll , peer -> hpoll ) ; lifetime = min ( 1U << sys_automax , NTP_MAXSESSION * mpoll ) ; if ( peer -> hmode == MODE_BROADCAST ) cookie = 0 ; else cookie = peer -> pcookie ; for ( i = 0 ; i < NTP_MAXSESSION ; i ++ ) { peer -> keylist [ i ] = keyid ; peer -> keynumber = i ; keyid = session_key ( & dstadr -> sin , & peer -> srcadr , keyid , cookie , lifetime + mpoll ) ; lifetime -= mpoll ; if ( auth_havekey ( keyid ) || keyid <= NTP_MAXKEY || lifetime < 0 || tstamp == 0 ) break ; } vp = & peer -> sndval ; if ( vp -> ptr == NULL ) vp -> ptr = emalloc ( sizeof ( struct autokey ) ) ; ap = ( struct autokey * ) vp -> ptr ; ap -> seq = htonl ( peer -> keynumber ) ; ap -> key = htonl ( keyid ) ; vp -> tstamp = htonl ( tstamp ) ; vp -> fstamp = hostval . tstamp ; vp -> vallen = htonl ( sizeof ( struct autokey ) ) ; vp -> siglen = 0 ; if ( tstamp != 0 ) { if ( vp -> sig == NULL ) vp -> sig = emalloc ( sign_siglen ) ; ctx = EVP_MD_CTX_new ( ) ; EVP_SignInit ( ctx , sign_digest ) ; EVP_SignUpdate ( ctx , ( u_char * ) vp , 12 ) ; EVP_SignUpdate ( ctx , vp -> ptr , sizeof ( struct autokey ) ) ; if ( EVP_SignFinal ( ctx , vp -> sig , & len , sign_pkey ) ) { INSIST ( len <= sign_siglen ) ; vp -> siglen = htonl ( len ) ; peer -> flags |= FLAG_ASSOC ; } EVP_MD_CTX_free ( ctx ) ; } DPRINTF ( 1 , ( " \n " , peer -> keynumber , keyid , cookie , ntohl ( vp -> tstamp ) , ntohl ( vp -> fstamp ) , peer -> hpoll ) ) ; return ( XEVNT_OK ) ; }
make_keylist - generate key list
 Returns
 XEVNT_OK     success
 XEVNT_ERR    protocol error
make_keylist - generate key list Returns XEVNT_OK success XEVNT_ERR protocol error
/* peer structure pointer */ /* interface */ /* signature context */ /* NTP timestamp */ /* autokey pointer */ /* value pointer */ /* next key ID */ /* private value */ /*
	 * Allocate the key list if necessary.
	 */ /*
	 * Generate an initial key ID which is unique and greater than
	 * NTP_MAXKEY.
	 */ /*
	 * Generate up to NTP_MAXSESSION session keys. Stop if the
	 * next one would not be unique or not a session key ID or if
	 * it would expire before the next poll. The private value
	 * included in the hash is zero if broadcast mode, the peer
	 * cookie if client mode or the host cookie if symmetric modes.
	 */ /*
	 * Save the last session key ID, sequence number and timestamp,
	 * then sign these values for later retrieval by the clients. Be
	 * careful not to use invalid key media. Use the public values
	 * timestamp as filestamp. 
	 */