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