xref: /netbsd-src/external/bsd/ntp/dist/libntp/a_md5encrypt.c (revision 7788a0781fe6ff2cce37368b4578a7ade0850cb1)
1 /*	$NetBSD: a_md5encrypt.c,v 1.1.1.2 2012/01/31 21:23:56 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"	/* provides clone of OpenSSL MD5 API */
18 #endif
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 	EVP_MD_CTX ctx;
36 
37 	/*
38 	 * Compute digest of key concatenated with packet. Note: the
39 	 * key type and digest type have been verified when the key
40 	 * was creaded.
41 	 */
42 	INIT_SSL();
43 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
44 	EVP_DigestUpdate(&ctx, key, (u_int)cache_keylen);
45 	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)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 	u_char	*key,		/* key pointer */
61 	u_int32	*pkt,		/* packet pointer */
62 	int	length,	 	/* packet length */
63 	int	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 	EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
77 	EVP_DigestUpdate(&ctx, key, (u_int)cache_keylen);
78 	EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
79 	EVP_DigestFinal(&ctx, digest, &len);
80 	if ((u_int)size != len + 4) {
81 		msyslog(LOG_ERR,
82 		    "MAC decrypt: MAC length error");
83 		return (0);
84 	}
85 	return (!memcmp(digest, (char *)pkt + length + 4, len));
86 }
87 
88 /*
89  * Calculate the reference id from the address. If it is an IPv4
90  * address, use it as is. If it is an IPv6 address, do a md5 on
91  * it and use the bottom 4 bytes.
92  * The result is in network byte order.
93  */
94 u_int32
95 addr2refid(sockaddr_u *addr)
96 {
97 	u_char		digest[20];
98 	u_int32		addr_refid;
99 	EVP_MD_CTX	ctx;
100 	u_int		len;
101 
102 	if (IS_IPV4(addr))
103 		return (NSRCADR(addr));
104 
105 	INIT_SSL();
106 	EVP_DigestInit(&ctx, EVP_get_digestbynid(NID_md5));
107 	EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
108 	    sizeof(struct in6_addr));
109 	EVP_DigestFinal(&ctx, digest, &len);
110 	memcpy(&addr_refid, digest, 4);
111 	return (addr_refid);
112 }
113