a_md5encrypt.c revision 316068
1179055Sjfv/*
2171384Sjfv *	digest support for NTP, MD5 and with OpenSSL more
3179055Sjfv */
4171384Sjfv#ifdef HAVE_CONFIG_H
5171384Sjfv#include <config.h>
6171384Sjfv#endif
7171384Sjfv
8171384Sjfv#include "ntp_fp.h"
9171384Sjfv#include "ntp_string.h"
10171384Sjfv#include "ntp_stdlib.h"
11171384Sjfv#include "ntp.h"
12171384Sjfv#include "ntp_md5.h"	/* provides OpenSSL digest API */
13171384Sjfv#include "isc/string.h"
14171384Sjfv/*
15171384Sjfv * MD5authencrypt - generate message digest
16171384Sjfv *
17171384Sjfv * Returns length of MAC including key ID and digest.
18171384Sjfv */
19171384Sjfvsize_t
20171384SjfvMD5authencrypt(
21171384Sjfv	int		type,	/* hash algorithm */
22171384Sjfv	const u_char *	key,	/* key pointer */
23171384Sjfv	u_int32 *	pkt,	/* packet pointer */
24171384Sjfv	size_t		length	/* packet length */
25171384Sjfv	)
26171384Sjfv{
27171384Sjfv	u_char	digest[EVP_MAX_MD_SIZE];
28171384Sjfv	u_int	len;
29171384Sjfv	EVP_MD_CTX *ctx;
30171384Sjfv
31171384Sjfv	/*
32179055Sjfv	 * Compute digest of key concatenated with packet. Note: the
33179055Sjfv	 * key type and digest type have been verified when the key
34171384Sjfv	 * was creaded.
35171384Sjfv	 */
36171384Sjfv	INIT_SSL();
37171384Sjfv	ctx = EVP_MD_CTX_new();
38171384Sjfv	if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) {
39171384Sjfv		msyslog(LOG_ERR,
40171384Sjfv		    "MAC encrypt: digest init failed");
41171384Sjfv		EVP_MD_CTX_free(ctx);
42172043Sjfv		return (0);
43171384Sjfv	}
44171384Sjfv	EVP_DigestUpdate(ctx, key, cache_secretsize);
45171384Sjfv	EVP_DigestUpdate(ctx, (u_char *)pkt, length);
46171384Sjfv	EVP_DigestFinal(ctx, digest, &len);
47171384Sjfv	EVP_MD_CTX_free(ctx);
48171384Sjfv	/* If the MAC is longer than the MAX then truncate it. */
49171384Sjfv	if (len > MAX_MAC_LEN - 4)
50171384Sjfv	    len = MAX_MAC_LEN - 4;
51171384Sjfv	memmove((u_char *)pkt + length + 4, digest, len);
52171384Sjfv	return (len + 4);
53179055Sjfv}
54171384Sjfv
55171384Sjfv
56171384Sjfv/*
57171384Sjfv * MD5authdecrypt - verify MD5 message authenticator
58179055Sjfv *
59171384Sjfv * Returns one if digest valid, zero if invalid.
60179055Sjfv */
61171384Sjfvint
62179055SjfvMD5authdecrypt(
63179055Sjfv	int		type,	/* hash algorithm */
64179055Sjfv	const u_char *	key,	/* key pointer */
65179055Sjfv	u_int32	*	pkt,	/* packet pointer */
66179055Sjfv	size_t		length,	/* packet length */
67179055Sjfv	size_t		size	/* MAC size */
68179055Sjfv	)
69179055Sjfv{
70171384Sjfv	u_char	digest[EVP_MAX_MD_SIZE];
71171384Sjfv	u_int	len;
72179055Sjfv	EVP_MD_CTX *ctx;
73171384Sjfv
74179055Sjfv	/*
75179055Sjfv	 * Compute digest of key concatenated with packet. Note: the
76179055Sjfv	 * key type and digest type have been verified when the key
77171384Sjfv	 * was created.
78171384Sjfv	 */
79171384Sjfv	INIT_SSL();
80171384Sjfv	ctx = EVP_MD_CTX_new();
81171384Sjfv	if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) {
82171384Sjfv		msyslog(LOG_ERR,
83171384Sjfv		    "MAC decrypt: digest init failed");
84171384Sjfv		EVP_MD_CTX_free(ctx);
85171384Sjfv		return (0);
86171384Sjfv	}
87171384Sjfv	EVP_DigestUpdate(ctx, key, cache_secretsize);
88179055Sjfv	EVP_DigestUpdate(ctx, (u_char *)pkt, length);
89179055Sjfv	EVP_DigestFinal(ctx, digest, &len);
90181003Sjfv	EVP_MD_CTX_free(ctx);
91179055Sjfv	/* If the MAC is longer than the MAX then truncate it. */
92181003Sjfv	if (len > MAX_MAC_LEN - 4)
93171384Sjfv	    len = MAX_MAC_LEN - 4;
94171384Sjfv	if (size != (size_t)len + 4) {
95179055Sjfv		msyslog(LOG_ERR,
96179055Sjfv		    "MAC decrypt: MAC length error");
97171384Sjfv		return (0);
98179055Sjfv	}
99171384Sjfv	return !isc_tsmemcmp(digest, (u_char *)pkt + length + 4, len);
100171384Sjfv}
101171384Sjfv
102171384Sjfv/*
103179055Sjfv * Calculate the reference id from the address. If it is an IPv4
104171384Sjfv * address, use it as is. If it is an IPv6 address, do a md5 on
105171384Sjfv * it and use the bottom 4 bytes.
106171384Sjfv * The result is in network byte order.
107171384Sjfv */
108179055Sjfvu_int32
109179055Sjfvaddr2refid(sockaddr_u *addr)
110172043Sjfv{
111172043Sjfv	u_char		digest[20];
112181003Sjfv	u_int32		addr_refid;
113171384Sjfv	EVP_MD_CTX	*ctx;
114171384Sjfv	u_int		len;
115
116	if (IS_IPV4(addr))
117		return (NSRCADR(addr));
118
119	INIT_SSL();
120
121	ctx = EVP_MD_CTX_new();
122	EVP_MD_CTX_init(ctx);
123#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
124	/* MD5 is not used as a crypto hash here. */
125	EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
126#endif
127	if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) {
128		msyslog(LOG_ERR,
129		    "MD5 init failed");
130		EVP_MD_CTX_free(ctx);	/* pedantic... but safe */
131		exit(1);
132	}
133
134	EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr),
135	    sizeof(struct in6_addr));
136	EVP_DigestFinal(ctx, digest, &len);
137	EVP_MD_CTX_free(ctx);
138	memcpy(&addr_refid, digest, sizeof(addr_refid));
139	return (addr_refid);
140}
141