xref: /freebsd/contrib/ntp/libntp/a_md5encrypt.c (revision d93a896ef95946b0bf1219866fcb324b78543444)
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 #include "isc/string.h"
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 	ctx = EVP_MD_CTX_new();
38 	if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) {
39 		msyslog(LOG_ERR,
40 		    "MAC encrypt: digest init failed");
41 		EVP_MD_CTX_free(ctx);
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 	EVP_MD_CTX_free(ctx);
48 	/* If the MAC is longer than the MAX then truncate it. */
49 	if (len > MAX_MAC_LEN - 4)
50 	    len = MAX_MAC_LEN - 4;
51 	memmove((u_char *)pkt + length + 4, digest, len);
52 	return (len + 4);
53 }
54 
55 
56 /*
57  * MD5authdecrypt - verify MD5 message authenticator
58  *
59  * Returns one if digest valid, zero if invalid.
60  */
61 int
62 MD5authdecrypt(
63 	int		type,	/* hash algorithm */
64 	const u_char *	key,	/* key pointer */
65 	u_int32	*	pkt,	/* packet pointer */
66 	size_t		length,	/* packet length */
67 	size_t		size	/* MAC size */
68 	)
69 {
70 	u_char	digest[EVP_MAX_MD_SIZE];
71 	u_int	len;
72 	EVP_MD_CTX *ctx;
73 
74 	/*
75 	 * Compute digest of key concatenated with packet. Note: the
76 	 * key type and digest type have been verified when the key
77 	 * was created.
78 	 */
79 	INIT_SSL();
80 	ctx = EVP_MD_CTX_new();
81 	if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) {
82 		msyslog(LOG_ERR,
83 		    "MAC decrypt: digest init failed");
84 		EVP_MD_CTX_free(ctx);
85 		return (0);
86 	}
87 	EVP_DigestUpdate(ctx, key, cache_secretsize);
88 	EVP_DigestUpdate(ctx, (u_char *)pkt, length);
89 	EVP_DigestFinal(ctx, digest, &len);
90 	EVP_MD_CTX_free(ctx);
91 	/* If the MAC is longer than the MAX then truncate it. */
92 	if (len > MAX_MAC_LEN - 4)
93 	    len = MAX_MAC_LEN - 4;
94 	if (size != (size_t)len + 4) {
95 		msyslog(LOG_ERR,
96 		    "MAC decrypt: MAC length error");
97 		return (0);
98 	}
99 	return !isc_tsmemcmp(digest, (u_char *)pkt + length + 4, len);
100 }
101 
102 /*
103  * Calculate the reference id from the address. If it is an IPv4
104  * address, use it as is. If it is an IPv6 address, do a md5 on
105  * it and use the bottom 4 bytes.
106  * The result is in network byte order.
107  */
108 u_int32
109 addr2refid(sockaddr_u *addr)
110 {
111 	u_char		digest[20];
112 	u_int32		addr_refid;
113 	EVP_MD_CTX	*ctx;
114 	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