a_md5encrypt.c revision 298699
1156772Sdeischen/*
2156772Sdeischen *	digest support for NTP, MD5 and with OpenSSL more
3156772Sdeischen */
4156772Sdeischen#ifdef HAVE_CONFIG_H
5156772Sdeischen#include <config.h>
6156772Sdeischen#endif
7156772Sdeischen
8156772Sdeischen#include "ntp_fp.h"
9156772Sdeischen#include "ntp_string.h"
10156772Sdeischen#include "ntp_stdlib.h"
11156772Sdeischen#include "ntp.h"
12156772Sdeischen#include "ntp_md5.h"	/* provides OpenSSL digest API */
13156772Sdeischen#include "isc/string.h"
14156772Sdeischen/*
15156772Sdeischen * MD5authencrypt - generate message digest
16156772Sdeischen *
17156772Sdeischen * Returns length of MAC including key ID and digest.
18156772Sdeischen */
19156772Sdeischensize_t
20156772SdeischenMD5authencrypt(
21156772Sdeischen	int		type,	/* hash algorithm */
22156772Sdeischen	const u_char *	key,	/* key pointer */
23156772Sdeischen	u_int32 *	pkt,	/* packet pointer */
24156772Sdeischen	size_t		length	/* packet length */
25156772Sdeischen	)
26156772Sdeischen{
27156772Sdeischen	u_char	digest[EVP_MAX_MD_SIZE];
28156772Sdeischen	u_int	len;
29156772Sdeischen	EVP_MD_CTX ctx;
30156772Sdeischen
31156772Sdeischen	/*
32156772Sdeischen	 * Compute digest of key concatenated with packet. Note: the
33156772Sdeischen	 * key type and digest type have been verified when the key
34156772Sdeischen	 * was creaded.
35156772Sdeischen	 */
36156772Sdeischen	INIT_SSL();
37172747Syar#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
38172729Syar	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
39156772Sdeischen		msyslog(LOG_ERR,
40156772Sdeischen		    "MAC encrypt: digest init failed");
41156772Sdeischen		return (0);
42172747Syar	}
43156772Sdeischen#else
44156772Sdeischen	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
45156772Sdeischen#endif
46156772Sdeischen	EVP_DigestUpdate(&ctx, key, cache_secretsize);
47156772Sdeischen	EVP_DigestUpdate(&ctx, (u_char *)pkt, length);
48156772Sdeischen	EVP_DigestFinal(&ctx, digest, &len);
49156772Sdeischen	memmove((u_char *)pkt + length + 4, digest, len);
50172729Syar	return (len + 4);
51172729Syar}
52172729Syar
53156772Sdeischen
54172729Syar/*
55172729Syar * MD5authdecrypt - verify MD5 message authenticator
56172729Syar *
57156772Sdeischen * Returns one if digest valid, zero if invalid.
58156772Sdeischen */
59156772Sdeischenint
60156772SdeischenMD5authdecrypt(
61168963Sdeischen	int		type,	/* hash algorithm */
62156772Sdeischen	const u_char *	key,	/* key pointer */
63156772Sdeischen	u_int32	*	pkt,	/* packet pointer */
64172729Syar	size_t		length,	/* packet length */
65172729Syar	size_t		size	/* MAC size */
66172729Syar	)
67172729Syar{
68156772Sdeischen	u_char	digest[EVP_MAX_MD_SIZE];
69172729Syar	u_int	len;
70172729Syar	EVP_MD_CTX ctx;
71172729Syar
72172729Syar	/*
73172729Syar	 * Compute digest of key concatenated with packet. Note: the
74172729Syar	 * key type and digest type have been verified when the key
75172729Syar	 * was created.
76172729Syar	 */
77172729Syar	INIT_SSL();
78172729Syar#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
79172729Syar	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
80172729Syar		msyslog(LOG_ERR,
81156772Sdeischen		    "MAC decrypt: digest init failed");
82172729Syar		return (0);
83156772Sdeischen	}
84156772Sdeischen#else
85172729Syar	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
86172729Syar#endif
87156772Sdeischen	EVP_DigestUpdate(&ctx, key, cache_secretsize);
88156772Sdeischen	EVP_DigestUpdate(&ctx, (u_char *)pkt, length);
89172729Syar	EVP_DigestFinal(&ctx, digest, &len);
90172729Syar	if (size != (size_t)len + 4) {
91156772Sdeischen		msyslog(LOG_ERR,
92156772Sdeischen		    "MAC decrypt: MAC length error");
93156772Sdeischen		return (0);
94172729Syar	}
95172729Syar	return !isc_tsmemcmp(digest, (const char *)pkt + length + 4, len);
96156772Sdeischen}
97172729Syar
98156772Sdeischen/*
99156772Sdeischen * Calculate the reference id from the address. If it is an IPv4
100156772Sdeischen * address, use it as is. If it is an IPv6 address, do a md5 on
101172729Syar * it and use the bottom 4 bytes.
102172729Syar * The result is in network byte order.
103156772Sdeischen */
104172729Syaru_int32
105172729Syaraddr2refid(sockaddr_u *addr)
106156772Sdeischen{
107156772Sdeischen	u_char		digest[20];
108156772Sdeischen	u_int32		addr_refid;
109156772Sdeischen	EVP_MD_CTX	ctx;
110172729Syar	u_int		len;
111172729Syar
112172729Syar	if (IS_IPV4(addr))
113172729Syar		return (NSRCADR(addr));
114156772Sdeischen
115156772Sdeischen	INIT_SSL();
116156772Sdeischen
117156772Sdeischen#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
118156772Sdeischen	EVP_MD_CTX_init(&ctx);
119156772Sdeischen#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
120156772Sdeischen	/* MD5 is not used as a crypto hash here. */
121156772Sdeischen	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
122156772Sdeischen#endif
123172729Syar	if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) {
124156772Sdeischen		msyslog(LOG_ERR,
125156772Sdeischen		    "MD5 init failed");
126172729Syar		exit(1);
127156772Sdeischen	}
128172729Syar#else
129172729Syar	EVP_DigestInit(&ctx, EVP_md5());
130172729Syar#endif
131156772Sdeischen
132156772Sdeischen	EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
133172729Syar	    sizeof(struct in6_addr));
134172729Syar	EVP_DigestFinal(&ctx, digest, &len);
135156772Sdeischen	memcpy(&addr_refid, digest, sizeof(addr_refid));
136156772Sdeischen	return (addr_refid);
137156772Sdeischen}
138156772Sdeischen