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 */
25int
26MD5authencrypt(
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 */
57int
58MD5authdecrypt(
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 */
94u_int32
95addr2refid(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