summaryrefslogtreecommitdiff
path: root/libntp/a_md5encrypt.c
blob: ffabc47c7d0978ee9bee010f471ea6244513b204 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 *	digest support for NTP, MD5 and with OpenSSL more
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "ntp_fp.h"
#include "ntp_string.h"
#include "ntp_stdlib.h"
#include "ntp.h"
#include "ntp_md5.h"	/* provides OpenSSL digest API */

/*
 * MD5authencrypt - generate message digest
 *
 * Returns length of MAC including key ID and digest.
 */
int
MD5authencrypt(
	int	type,		/* hash algorithm */
	u_char	*key,		/* key pointer */
	u_int32 *pkt,		/* packet pointer */
	int	length		/* packet length */
	)
{
	u_char	digest[EVP_MAX_MD_SIZE];
	u_int	len;
	EVP_MD_CTX ctx;

	/*
	 * Compute digest of key concatenated with packet. Note: the
	 * key type and digest type have been verified when the key
	 * was creaded.
	 */
	INIT_SSL();
#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
		msyslog(LOG_ERR,
		    "MAC encrypt: digest init failed");
		return (0);
	}
#else
	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
#endif
	EVP_DigestUpdate(&ctx, key, cache_secretsize);
	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
	EVP_DigestFinal(&ctx, digest, &len);
	memmove((u_char *)pkt + length + 4, digest, len);
	return (len + 4);
}


/*
 * MD5authdecrypt - verify MD5 message authenticator
 *
 * Returns one if digest valid, zero if invalid.
 */
int
MD5authdecrypt(
	int	type,		/* hash algorithm */
	u_char	*key,		/* key pointer */
	u_int32	*pkt,		/* packet pointer */
	int	length,	 	/* packet length */
	int	size		/* MAC size */
	)
{
	u_char	digest[EVP_MAX_MD_SIZE];
	u_int	len;
	EVP_MD_CTX ctx;

	/*
	 * Compute digest of key concatenated with packet. Note: the
	 * key type and digest type have been verified when the key
	 * was created.
	 */
	INIT_SSL();
#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
		msyslog(LOG_ERR,
		    "MAC decrypt: digest init failed");
		return (0);
	}
#else
	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
#endif
	EVP_DigestUpdate(&ctx, key, cache_secretsize);
	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
	EVP_DigestFinal(&ctx, digest, &len);
	if ((u_int)size != len + 4) {
		msyslog(LOG_ERR,
		    "MAC decrypt: MAC length error");
		return (0);
	}
	return !memcmp(digest, (char *)pkt + length + 4, len);
}

/*
 * Calculate the reference id from the address. If it is an IPv4
 * address, use it as is. If it is an IPv6 address, do a md5 on
 * it and use the bottom 4 bytes.
 * The result is in network byte order.
 */
u_int32
addr2refid(sockaddr_u *addr)
{
	u_char		digest[20];
	u_int32		addr_refid;
	EVP_MD_CTX	ctx;
	u_int		len;

	if (IS_IPV4(addr))
		return (NSRCADR(addr));

	INIT_SSL();

#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
	EVP_MD_CTX_init(&ctx);
#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
	/* MD5 is not used as a crypto hash here. */
	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
#endif
	if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) {
		msyslog(LOG_ERR,
		    "MD5 init failed");
		exit(1);
	}
#else
	EVP_DigestInit(&ctx, EVP_md5());
#endif

	EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
	    sizeof(struct in6_addr));
	EVP_DigestFinal(&ctx, digest, &len);
	memcpy(&addr_refid, digest, sizeof(addr_refid));
	return (addr_refid);
}