xref: /netbsd-src/external/bsd/ntp/dist/libntp/a_md5encrypt.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: a_md5encrypt.c,v 1.1.1.3 2013/12/27 23:30:48 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 
16 /*
17  * MD5authencrypt - generate message digest
18  *
19  * Returns length of MAC including key ID and digest.
20  */
21 int
22 MD5authencrypt(
23 	int	type,		/* hash algorithm */
24 	u_char	*key,		/* key pointer */
25 	u_int32 *pkt,		/* packet pointer */
26 	int	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 defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
40 	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
41 		msyslog(LOG_ERR,
42 		    "MAC encrypt: digest init failed");
43 		return (0);
44 	}
45 #else
46 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
47 #endif
48 	EVP_DigestUpdate(&ctx, key, cache_secretsize);
49 	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
50 	EVP_DigestFinal(&ctx, digest, &len);
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 	u_char	*key,		/* key pointer */
65 	u_int32	*pkt,		/* packet pointer */
66 	int	length,	 	/* packet length */
67 	int	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 #if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
81 	if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
82 		msyslog(LOG_ERR,
83 		    "MAC decrypt: digest init failed");
84 		return (0);
85 	}
86 #else
87 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
88 #endif
89 	EVP_DigestUpdate(&ctx, key, cache_secretsize);
90 	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
91 	EVP_DigestFinal(&ctx, digest, &len);
92 	if ((u_int)size != len + 4) {
93 		msyslog(LOG_ERR,
94 		    "MAC decrypt: MAC length error");
95 		return (0);
96 	}
97 	return !memcmp(digest, (char *)pkt + length + 4, len);
98 }
99 
100 /*
101  * Calculate the reference id from the address. If it is an IPv4
102  * address, use it as is. If it is an IPv6 address, do a md5 on
103  * it and use the bottom 4 bytes.
104  * The result is in network byte order.
105  */
106 u_int32
107 addr2refid(sockaddr_u *addr)
108 {
109 	u_char		digest[20];
110 	u_int32		addr_refid;
111 	EVP_MD_CTX	ctx;
112 	u_int		len;
113 
114 	if (IS_IPV4(addr))
115 		return (NSRCADR(addr));
116 
117 	INIT_SSL();
118 
119 #if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
120 	EVP_MD_CTX_init(&ctx);
121 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
122 	/* MD5 is not used as a crypto hash here. */
123 	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
124 #endif
125 	if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) {
126 		msyslog(LOG_ERR,
127 		    "MD5 init failed");
128 		exit(1);
129 	}
130 #else
131 	EVP_DigestInit(&ctx, EVP_md5());
132 #endif
133 
134 	EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
135 	    sizeof(struct in6_addr));
136 	EVP_DigestFinal(&ctx, digest, &len);
137 	memcpy(&addr_refid, digest, sizeof(addr_refid));
138 	return (addr_refid);
139 }
140