⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntp_crypto.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
 * hostval	host name (not signed) * pubkey	public key * cinfo	certificate info/value list * tai_leap	leapseconds file * * Filestamps are proventicated data, so this routine is run only when * the host has been synchronized to a proventicated source. Thus, the * timestamp is proventicated, too, and can be used to deflect * clogging attacks and even cook breakfast. * * Returns void (no errors) */voidcrypto_update(void){	EVP_MD_CTX ctx;		/* message digest context */	struct cert_info *cp, *cpn; /* certificate info/value */	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */	tstamp_t tstamp;	/* NTP timestamp */	u_int	len;	if ((tstamp = crypto_time()) == 0)		return;	hostval.tstamp = htonl(tstamp);	/*	 * Sign public key and timestamps. The filestamp is derived from	 * the host key file extension from wherever the file was	 * generated. 	 */	if (pubkey.vallen != 0) {		pubkey.tstamp = hostval.tstamp;		pubkey.siglen = 0;		if (pubkey.sig == NULL)			pubkey.sig = emalloc(sign_siglen);		EVP_SignInit(&ctx, sign_digest);		EVP_SignUpdate(&ctx, (u_char *)&pubkey, 12);		EVP_SignUpdate(&ctx, pubkey.ptr, ntohl(pubkey.vallen));		if (EVP_SignFinal(&ctx, pubkey.sig, &len, sign_pkey))			pubkey.siglen = htonl(len);	}	/*	 * Sign certificates and timestamps. The filestamp is derived	 * from the certificate file extension from wherever the file	 * was generated. Note we do not throw expired certificates	 * away; they may have signed younger ones.	 */	for (cp = cinfo; cp != NULL; cp = cpn) {		cpn = cp->link;		cp->cert.tstamp = hostval.tstamp;		cp->cert.siglen = 0;		if (cp->cert.sig == NULL)			cp->cert.sig = emalloc(sign_siglen);		EVP_SignInit(&ctx, sign_digest);		EVP_SignUpdate(&ctx, (u_char *)&cp->cert, 12);		EVP_SignUpdate(&ctx, cp->cert.ptr,		    ntohl(cp->cert.vallen));		if (EVP_SignFinal(&ctx, cp->cert.sig, &len, sign_pkey))			cp->cert.siglen = htonl(len);	}	/*	 * Sign leapseconds table and timestamps. The filestamp is	 * derived from the leapsecond file extension from wherever the	 * file was generated.	 */	if (tai_leap.vallen != 0) {		tai_leap.tstamp = hostval.tstamp;		tai_leap.siglen = 0;		if (tai_leap.sig == NULL)			tai_leap.sig = emalloc(sign_siglen);		EVP_SignInit(&ctx, sign_digest);		EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);		EVP_SignUpdate(&ctx, tai_leap.ptr,		    ntohl(tai_leap.vallen));		if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))			tai_leap.siglen = htonl(len);	}	sprintf(statstr, "update ts %u", ntohl(hostval.tstamp)); 	record_crypto_stats(NULL, statstr);#ifdef DEBUG	if (debug)		printf("crypto_update: %s\n", statstr);#endif}/* * value_free - free value structure components. * * Returns void (no errors) */voidvalue_free(	struct value *vp	/* value structure */	){	if (vp->ptr != NULL)		free(vp->ptr);	if (vp->sig != NULL)		free(vp->sig);	memset(vp, 0, sizeof(struct value));}/* * crypto_time - returns current NTP time in seconds. */tstamp_tcrypto_time(){	l_fp	tstamp;		/* NTP time */	L_CLR(&tstamp);	L_CLR(&tstamp);	if (sys_leap != LEAP_NOTINSYNC)		get_systime(&tstamp);	return (tstamp.l_ui);}/* * asn2ntp - convert ASN1_TIME time structure to NTP time in seconds. */u_longasn2ntp	(	ASN1_TIME *asn1time	/* pointer to ASN1_TIME structure */	){	char	*v;		/* pointer to ASN1_TIME string */	struct	tm tm;		/* used to convert to NTP time */	/*	 * Extract time string YYMMDDHHMMSSZ from ASN1 time structure.	 * Note that the YY, MM, DD fields start with one, the HH, MM,	 * SS fiels start with zero and the Z character should be 'Z'	 * for UTC. Also note that years less than 50 map to years	 * greater than 100. Dontcha love ASN.1? Better than MIL-188.	 */	if (asn1time->length > 13)		return ((u_long)(~0));	/* We can't use -1 here. It's invalid */	v = (char *)asn1time->data;	tm.tm_year = (v[0] - '0') * 10 + v[1] - '0';	if (tm.tm_year < 50)		tm.tm_year += 100;	tm.tm_mon = (v[2] - '0') * 10 + v[3] - '0' - 1;	tm.tm_mday = (v[4] - '0') * 10 + v[5] - '0';	tm.tm_hour = (v[6] - '0') * 10 + v[7] - '0';	tm.tm_min = (v[8] - '0') * 10 + v[9] - '0';	tm.tm_sec = (v[10] - '0') * 10 + v[11] - '0';	tm.tm_wday = 0;	tm.tm_yday = 0;	tm.tm_isdst = 0;	return (timegm(&tm) + JAN_1970);}/* * bigdig() - compute a BIGNUM MD5 hash of a BIGNUM number. */static intbighash(	BIGNUM	*bn,		/* BIGNUM * from */	BIGNUM	*bk		/* BIGNUM * to */	){	EVP_MD_CTX ctx;		/* message digest context */	u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */	u_char	*ptr;		/* a BIGNUM as binary string */	u_int	len;	len = BN_num_bytes(bn);	ptr = emalloc(len);	BN_bn2bin(bn, ptr);	EVP_DigestInit(&ctx, EVP_md5());	EVP_DigestUpdate(&ctx, ptr, len);	EVP_DigestFinal(&ctx, dgst, &len);	BN_bin2bn(dgst, len, bk);	return (1);}/* *********************************************************************** *								       * * The following routines implement the Schnorr (IFF) identity scheme  * *								       * *********************************************************************** * * The Schnorr (IFF) identity scheme is intended for use when * the ntp-genkeys program does not generate the certificates used in * the protocol and the group key cannot be conveyed in the certificate * itself. For this purpose, new generations of IFF values must be * securely transmitted to all members of the group before use. The * scheme is self contained and independent of new generations of host * keys, sign keys and certificates. * * The IFF identity scheme is based on DSA cryptography and algorithms * described in Stinson p. 285. The IFF values hide in a DSA cuckoo * structure, but only the primes and generator are used. The p is a * 512-bit prime, q a 160-bit prime that divides p - 1 and is a qth root * of 1 mod p; that is, g^q = 1 mod p. The TA rolls primvate random * group key b disguised as a DSA structure member, then computes public * key g^(q - b). These values are shared only among group members and * never revealed in messages. Alice challenges Bob to confirm identity * using the protocol described below. * * How it works * * The scheme goes like this. Both Alice and Bob have the public primes * p, q and generator g. The TA gives private key b to Bob and public * key v = g^(q - a) mod p to Alice. * * Alice rolls new random challenge r and sends to Bob in the IFF * request message. Bob rolls new random k, then computes y = k + b r * mod q and x = g^k mod p and sends (y, hash(x)) to Alice in the * response message. Besides making the response shorter, the hash makes * it effectivey impossible for an intruder to solve for b by observing * a number of these messages. *  * Alice receives the response and computes g^y v^r mod p. After a bit * of algebra, this simplifies to g^k. If the hash of this result * matches hash(x), Alice knows that Bob has the group key b. The signed * response binds this knowledge to Bob's private key and the public key * previously received in his certificate. * * crypto_alice - construct Alice's challenge in IFF scheme * * Returns * XEVNT_OK	success * XEVNT_PUB	bad or missing public key * XEVNT_ID	bad or missing group key */static intcrypto_alice(	struct peer *peer,	/* peer pointer */	struct value *vp	/* value pointer */	){	DSA	*dsa;		/* IFF parameters */	BN_CTX	*bctx;		/* BIGNUM context */	EVP_MD_CTX ctx;		/* signature context */	tstamp_t tstamp;	u_int	len;	/*	 * The identity parameters must have correct format and content.	 */	if (peer->ident_pkey == NULL)		return (XEVNT_ID);	if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {		msyslog(LOG_INFO, "crypto_alice: defective key");		return (XEVNT_PUB);	}	/*	 * Roll new random r (0 < r < q). The OpenSSL library has a bug	 * omitting BN_rand_range, so we have to do it the hard way.	 */	bctx = BN_CTX_new();	len = BN_num_bytes(dsa->q);	if (peer->iffval != NULL)		BN_free(peer->iffval);	peer->iffval = BN_new();	BN_rand(peer->iffval, len * 8, -1, 1);	/* r */	BN_mod(peer->iffval, peer->iffval, dsa->q, bctx);	BN_CTX_free(bctx);	/*	 * Sign and send to Bob. The filestamp is from the local file.	 */	tstamp = crypto_time();	memset(vp, 0, sizeof(struct value));	vp->tstamp = htonl(tstamp);	vp->fstamp = htonl(peer->fstamp);	vp->vallen = htonl(len);	vp->ptr = emalloc(len);	BN_bn2bin(peer->iffval, vp->ptr);	vp->siglen = 0;	if (tstamp == 0)		return (XEVNT_OK);	if (tstamp < cinfo->first || tstamp > cinfo->last)		return (XEVNT_PER);	vp->sig = emalloc(sign_siglen);	EVP_SignInit(&ctx, sign_digest);	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);	EVP_SignUpdate(&ctx, vp->ptr, len);	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))		vp->siglen = htonl(len);	return (XEVNT_OK);}/* * crypto_bob - construct Bob's response to Alice's challenge * * Returns * XEVNT_OK	success * XEVNT_ID	bad or missing group key * XEVNT_ERR	protocol error * XEVNT_PER	host expired certificate */static intcrypto_bob(	struct exten *ep,	/* extension pointer */	struct value *vp	/* value pointer */	){	DSA	*dsa;		/* IFF parameters */	DSA_SIG	*sdsa;		/* DSA signature context fake */	BN_CTX	*bctx;		/* BIGNUM context */	EVP_MD_CTX ctx;		/* signature context */	tstamp_t tstamp;	/* NTP timestamp */	BIGNUM	*bn, *bk, *r;	u_char	*ptr;	u_int	len;	/*	 * If the IFF parameters are not valid, something awful	 * happened or we are being tormented.	 */	if (iffpar_pkey == NULL) {		msyslog(LOG_INFO, "crypto_bob: scheme unavailable");		return (XEVNT_ID);	}	dsa = iffpar_pkey->pkey.dsa;	/*	 * Extract r from the challenge.	 */	len = ntohl(ep->vallen);	if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {		msyslog(LOG_ERR, "crypto_bob %s\n",		    ERR_error_string(ERR_get_error(), NULL));		return (XEVNT_ERR);	}	/*	 * Bob rolls random k (0 < k < q), computes y = k + b r mod q	 * and x = g^k mod p, then sends (y, hash(x)) to Alice.	 */	bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();	sdsa = DSA_SIG_new();	BN_rand(bk, len * 8, -1, 1);		/* k */	BN_mod_mul(bn, dsa->priv_key, r, dsa->q, bctx); /* b r mod q */	BN_add(bn, bn, bk);	BN_mod(bn, bn, dsa->q, bctx);		/* k + b r mod q */	sdsa->r = BN_dup(bn);	BN_mod_exp(bk, dsa->g, bk, dsa->p, bctx); /* g^k mod p */	bighash(bk, bk);	sdsa->s = BN_dup(bk);	BN_CTX_free(bctx);	BN_free(r); BN_free(bn); BN_free(bk);	/*	 * Encode the values in ASN.1 and sign.	 */	tstamp = crypto_time();	memset(vp, 0, sizeof(struct value));	vp->tstamp = htonl(tstamp);	vp->fstamp = htonl(if_fstamp);	len = i2d_DSA_SIG(sdsa, NULL);	if (len <= 0) {		msyslog(LOG_ERR, "crypto_bob %s\n",		    ERR_error_string(ERR_get_error(), NULL));		DSA_SIG_free(sdsa);		return (XEVNT_ERR);	}	vp->vallen = htonl(len);	ptr = emalloc(len);	vp->ptr = ptr;	i2d_DSA_SIG(sdsa, &ptr);	DSA_SIG_free(sdsa);	vp->siglen = 0;	if (tstamp == 0)		return (XEVNT_OK);	if (tstamp < cinfo->first || tstamp > cinfo->last)		return (XEVNT_PER);	vp->sig = emalloc(sign_siglen);	EVP_SignInit(&ctx, sign_digest);	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);	EVP_SignUpdate(&ctx, vp->ptr, len);	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))		vp->siglen = htonl(len);	return (XEVNT_OK);}/* * crypto_iff - verify Bob's response to Alice's challenge * * Returns * XEVNT_OK	success * XEVNT_PUB	bad or missing public key * XEVNT_ID	bad or missing group key * XEVNT_FSP	bad filestamp */intcrypto_iff(	struct exten *ep,	/* extension pointer */	struct peer *peer	/* peer structure pointer */	){	DSA	*dsa;		/* IFF parameters */	BN_CTX	*bctx;		/* BIGNUM context */	DSA_SIG	*sdsa;		/* DSA parameters */	BIGNUM	*bn, *bk;	u_int	len;	const u_char	*ptr;	int	temp;	/*	 * If the IFF parameters are not valid or no challenge was sent,	 * something awful happened or we are being tormented.	 */	if (peer->ident_pkey == NULL) {		msyslog(LOG_INFO, "crypto_iff: scheme unavailable");		return (XEVNT_ID);	}	if (ntohl(ep->fstamp) != peer->fstamp) {		msyslog(LOG_INFO, "crypto_iff: invalid filestamp %u",		    ntohl(ep->fstamp));		return (XEVNT_FSP);	}	if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {		msyslog(LOG_INFO, "crypto_iff: defective key");		return (XEVNT_PUB);	}	if (peer->iffval == NULL) {		msyslog(LOG_INFO, "crypto_iff: missing challenge");		return (XEVNT_ID);	}	/*	 * Extract the k + b r and g^k values from the response.	 */	bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();	len = ntohl(ep->vallen);	ptr = (const u_char *)ep->pkt;	if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {		msyslog(LOG_ERR, "crypto_iff %s\n",		    ERR_error_string(ERR_get_error(), NULL));		return (XEVNT_ERR);	}	/*	 * Compute g^(k + b r) g^(q - b)r mod p.	 */	BN_mod_exp(bn, dsa->pub_key, peer->iffval, dsa->p, bctx);	BN_mod_exp(bk, dsa->g, sdsa->r, dsa->p, bctx);	BN_mod_mul(bn, bn, bk, dsa->p, bctx);	/*	 * Verify the hash of the result matches hash(x).	 */	bighash(bn, bn);	temp = B

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -