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