1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/*
* digest support for NTP, MD5 and with OpenSSL more
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "ntp_fp.h"
#include "ntp_string.h"
#include "ntp_stdlib.h"
#include "ntp.h"
#include "ntp_md5.h" /* provides OpenSSL digest API */
/*
* MD5authencrypt - generate message digest
*
* Returns length of MAC including key ID and digest.
*/
int
MD5authencrypt(
int type, /* hash algorithm */
u_char *key, /* key pointer */
u_int32 *pkt, /* packet pointer */
int length /* packet length */
)
{
u_char digest[EVP_MAX_MD_SIZE];
u_int len;
EVP_MD_CTX ctx;
/*
* Compute digest of key concatenated with packet. Note: the
* key type and digest type have been verified when the key
* was creaded.
*/
INIT_SSL();
#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
msyslog(LOG_ERR,
"MAC encrypt: digest init failed");
return (0);
}
#else
EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
#endif
EVP_DigestUpdate(&ctx, key, cache_secretsize);
EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
EVP_DigestFinal(&ctx, digest, &len);
memmove((u_char *)pkt + length + 4, digest, len);
return (len + 4);
}
/*
* MD5authdecrypt - verify MD5 message authenticator
*
* Returns one if digest valid, zero if invalid.
*/
int
MD5authdecrypt(
int type, /* hash algorithm */
u_char *key, /* key pointer */
u_int32 *pkt, /* packet pointer */
int length, /* packet length */
int size /* MAC size */
)
{
u_char digest[EVP_MAX_MD_SIZE];
u_int len;
EVP_MD_CTX ctx;
/*
* Compute digest of key concatenated with packet. Note: the
* key type and digest type have been verified when the key
* was created.
*/
INIT_SSL();
#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
msyslog(LOG_ERR,
"MAC decrypt: digest init failed");
return (0);
}
#else
EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
#endif
EVP_DigestUpdate(&ctx, key, cache_secretsize);
EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
EVP_DigestFinal(&ctx, digest, &len);
if ((u_int)size != len + 4) {
msyslog(LOG_ERR,
"MAC decrypt: MAC length error");
return (0);
}
return !memcmp(digest, (char *)pkt + length + 4, len);
}
/*
* Calculate the reference id from the address. If it is an IPv4
* address, use it as is. If it is an IPv6 address, do a md5 on
* it and use the bottom 4 bytes.
* The result is in network byte order.
*/
u_int32
addr2refid(sockaddr_u *addr)
{
u_char digest[20];
u_int32 addr_refid;
EVP_MD_CTX ctx;
u_int len;
if (IS_IPV4(addr))
return (NSRCADR(addr));
INIT_SSL();
#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
EVP_MD_CTX_init(&ctx);
#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
/* MD5 is not used as a crypto hash here. */
EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
#endif
if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) {
msyslog(LOG_ERR,
"MD5 init failed");
exit(1);
}
#else
EVP_DigestInit(&ctx, EVP_md5());
#endif
EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
sizeof(struct in6_addr));
EVP_DigestFinal(&ctx, digest, &len);
memcpy(&addr_refid, digest, sizeof(addr_refid));
return (addr_refid);
}
|