xref: /netbsd-src/external/bsd/ntp/dist/libntp/a_md5encrypt.c (revision daf6c4152fcddc27c445489775ed1f66ab4ea9a9)
1 /*	$NetBSD: a_md5encrypt.c,v 1.1.1.1 2009/12/13 16:54:59 kardel 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 #ifdef OPENSSL
15 #include "openssl/evp.h"
16 #else
17 #include "ntp_md5.h"
18 #endif /* OPENSSSL */
19 
20 /*
21  * MD5authencrypt - generate message digest
22  *
23  * Returns length of MAC including key ID and digest.
24  */
25 int
26 MD5authencrypt(
27 	int	type,		/* hash algorithm */
28 	u_char	*key,		/* key pointer */
29 	u_int32 *pkt,		/* packet pointer */
30 	int	length		/* packet length */
31 	)
32 {
33 	u_char	digest[EVP_MAX_MD_SIZE];
34 	u_int	len;
35 #ifdef OPENSSL
36 	EVP_MD_CTX ctx;
37 #else
38 	MD5_CTX	md5;
39 #endif /* OPENSSL */
40 
41 	/*
42 	 * Compute digest of key concatenated with packet. Note: the
43 	 * key type and digest type have been verified when the key
44 	 * was creaded.
45 	 */
46 #ifdef OPENSSL
47 	INIT_SSL();
48 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
49 	EVP_DigestUpdate(&ctx, key, (u_int)cache_keylen);
50 	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
51 	EVP_DigestFinal(&ctx, digest, &len);
52 #else /* OPENSSL */
53 	MD5Init(&md5);
54 	MD5Update(&md5, key, (u_int)cache_keylen);
55 	MD5Update(&md5, (u_char *)pkt, (u_int)length);
56 	MD5Final(digest, &md5);
57 	len = 16;
58 #endif /* OPENSSL */
59 	memmove((u_char *)pkt + length + 4, digest, len);
60 	return (len + 4);
61 }
62 
63 
64 /*
65  * MD5authdecrypt - verify MD5 message authenticator
66  *
67  * Returns one if digest valid, zero if invalid.
68  */
69 int
70 MD5authdecrypt(
71 	int	type,		/* hash algorithm */
72 	u_char	*key,		/* key pointer */
73 	u_int32	*pkt,		/* packet pointer */
74 	int	length,	 	/* packet length */
75 	int	size		/* MAC size */
76 	)
77 {
78 	u_char	digest[EVP_MAX_MD_SIZE];
79 	u_int	len;
80 #ifdef OPENSSL
81 	EVP_MD_CTX ctx;
82 #else
83 	MD5_CTX	md5;
84 #endif /* OPENSSL */
85 
86 	/*
87 	 * Compute digest of key concatenated with packet. Note: the
88 	 * key type and digest type have been verified when the key
89 	 * was created.
90 	 */
91 #ifdef OPENSSL
92 	INIT_SSL();
93 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
94 	EVP_DigestUpdate(&ctx, key, (u_int)cache_keylen);
95 	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
96 	EVP_DigestFinal(&ctx, digest, &len);
97 #else /* OPENSSL */
98 	MD5Init(&md5);
99 	MD5Update(&md5, key, (u_int)cache_keylen);
100 	MD5Update(&md5, (u_char *)pkt, (u_int)length);
101 	MD5Final(digest, &md5);
102 	len = 16;
103 #endif /* OPENSSL */
104 	if ((u_int)size != len + 4) {
105 		msyslog(LOG_ERR,
106 		    "MAC decrypt: MAC length error");
107 		return (0);
108 	}
109 	return (!memcmp(digest, (char *)pkt + length + 4, len));
110 }
111 
112 /*
113  * Calculate the reference id from the address. If it is an IPv4
114  * address, use it as is. If it is an IPv6 address, do a md5 on
115  * it and use the bottom 4 bytes.
116  */
117 u_int32
118 addr2refid(sockaddr_u *addr)
119 {
120 	u_char		digest[20];
121 	u_int32		addr_refid;
122 #ifdef OPENSSL
123 	EVP_MD_CTX	ctx;
124 	u_int		len;
125 #else
126 	MD5_CTX	md5;
127 #endif /* OPENSSL */
128 
129 	if (IS_IPV4(addr))
130 		return (NSRCADR(addr));
131 
132 #ifdef OPENSSL
133 	INIT_SSL();
134 	EVP_DigestInit(&ctx, EVP_get_digestbynid(NID_md5));
135 	EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
136 	    sizeof(struct in6_addr));
137 	EVP_DigestFinal(&ctx, digest, &len);
138 #else
139 	MD5Init(&md5);
140 	MD5Update(&md5, (u_char *)PSOCK_ADDR6(addr),
141 	    sizeof(struct in6_addr));
142 	MD5Final(digest, &md5);
143 #endif /* OPENSSL */
144 	memcpy(&addr_refid, digest, 4);
145 	return (addr_refid);
146 }
147