xref: /freebsd/contrib/ntp/libntp/a_md5encrypt.c (revision 4f0a4502a1f33fef287ac558c98e5ef99a32216f)
1 /*
2  *	digest support for NTP, MD5 and with OpenSSL more
3  */
4 #ifdef HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7 
8 #include "ntp_fp.h"
9 #include "ntp_string.h"
10 #include "ntp_stdlib.h"
11 #include "ntp.h"
12 #include "ntp_md5.h"	/* provides OpenSSL digest API */
13 
14 /*
15  * MD5authencrypt - generate message digest
16  *
17  * Returns length of MAC including key ID and digest.
18  */
19 size_t
20 MD5authencrypt(
21 	int		type,	/* hash algorithm */
22 	const u_char *	key,	/* key pointer */
23 	u_int32 *	pkt,	/* packet pointer */
24 	size_t		length	/* packet length */
25 	)
26 {
27 	u_char	digest[EVP_MAX_MD_SIZE];
28 	u_int	len;
29 	EVP_MD_CTX ctx;
30 
31 	/*
32 	 * Compute digest of key concatenated with packet. Note: the
33 	 * key type and digest type have been verified when the key
34 	 * was creaded.
35 	 */
36 	INIT_SSL();
37 #if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
38 	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
39 		msyslog(LOG_ERR,
40 		    "MAC encrypt: digest init failed");
41 		return (0);
42 	}
43 #else
44 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
45 #endif
46 	EVP_DigestUpdate(&ctx, key, cache_secretsize);
47 	EVP_DigestUpdate(&ctx, (u_char *)pkt, length);
48 	EVP_DigestFinal(&ctx, digest, &len);
49 	memmove((u_char *)pkt + length + 4, digest, len);
50 	return (len + 4);
51 }
52 
53 
54 /*
55  * MD5authdecrypt - verify MD5 message authenticator
56  *
57  * Returns one if digest valid, zero if invalid.
58  */
59 int
60 MD5authdecrypt(
61 	int		type,	/* hash algorithm */
62 	const u_char *	key,	/* key pointer */
63 	u_int32	*	pkt,	/* packet pointer */
64 	size_t		length,	/* packet length */
65 	size_t		size	/* MAC size */
66 	)
67 {
68 	u_char	digest[EVP_MAX_MD_SIZE];
69 	u_int	len;
70 	EVP_MD_CTX ctx;
71 
72 	/*
73 	 * Compute digest of key concatenated with packet. Note: the
74 	 * key type and digest type have been verified when the key
75 	 * was created.
76 	 */
77 	INIT_SSL();
78 #if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
79 	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
80 		msyslog(LOG_ERR,
81 		    "MAC decrypt: digest init failed");
82 		return (0);
83 	}
84 #else
85 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
86 #endif
87 	EVP_DigestUpdate(&ctx, key, cache_secretsize);
88 	EVP_DigestUpdate(&ctx, (u_char *)pkt, length);
89 	EVP_DigestFinal(&ctx, digest, &len);
90 	if (size != (size_t)len + 4) {
91 		msyslog(LOG_ERR,
92 		    "MAC decrypt: MAC length error");
93 		return (0);
94 	}
95 	return !memcmp(digest, (const char *)pkt + length + 4, len);
96 }
97 
98 /*
99  * Calculate the reference id from the address. If it is an IPv4
100  * address, use it as is. If it is an IPv6 address, do a md5 on
101  * it and use the bottom 4 bytes.
102  * The result is in network byte order.
103  */
104 u_int32
105 addr2refid(sockaddr_u *addr)
106 {
107 	u_char		digest[20];
108 	u_int32		addr_refid;
109 	EVP_MD_CTX	ctx;
110 	u_int		len;
111 
112 	if (IS_IPV4(addr))
113 		return (NSRCADR(addr));
114 
115 	INIT_SSL();
116 
117 #if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
118 	EVP_MD_CTX_init(&ctx);
119 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
120 	/* MD5 is not used as a crypto hash here. */
121 	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
122 #endif
123 	if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) {
124 		msyslog(LOG_ERR,
125 		    "MD5 init failed");
126 		exit(1);
127 	}
128 #else
129 	EVP_DigestInit(&ctx, EVP_md5());
130 #endif
131 
132 	EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
133 	    sizeof(struct in6_addr));
134 	EVP_DigestFinal(&ctx, digest, &len);
135 	memcpy(&addr_refid, digest, sizeof(addr_refid));
136 	return (addr_refid);
137 }
138