]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/ntp/libntp/a_md5encrypt.c
Fix multiple vulnerabilities of ntp. [SA-17:03]
[FreeBSD/releng/10.3.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         ctx = EVP_MD_CTX_new();
38         if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) {
39                 msyslog(LOG_ERR,
40                     "MAC encrypt: digest init failed");
41                 EVP_MD_CTX_free(ctx);
42                 return (0);
43         }
44         EVP_DigestUpdate(ctx, key, cache_secretsize);
45         EVP_DigestUpdate(ctx, (u_char *)pkt, length);
46         EVP_DigestFinal(ctx, digest, &len);
47         EVP_MD_CTX_free(ctx);
48         /* If the MAC is longer than the MAX then truncate it. */
49         if (len > MAX_MAC_LEN - 4)
50             len = MAX_MAC_LEN - 4;
51         memmove((u_char *)pkt + length + 4, digest, len);
52         return (len + 4);
53 }
54
55
56 /*
57  * MD5authdecrypt - verify MD5 message authenticator
58  *
59  * Returns one if digest valid, zero if invalid.
60  */
61 int
62 MD5authdecrypt(
63         int             type,   /* hash algorithm */
64         const u_char *  key,    /* key pointer */
65         u_int32 *       pkt,    /* packet pointer */
66         size_t          length, /* packet length */
67         size_t          size    /* MAC size */
68         )
69 {
70         u_char  digest[EVP_MAX_MD_SIZE];
71         u_int   len;
72         EVP_MD_CTX *ctx;
73
74         /*
75          * Compute digest of key concatenated with packet. Note: the
76          * key type and digest type have been verified when the key
77          * was created.
78          */
79         INIT_SSL();
80         ctx = EVP_MD_CTX_new();
81         if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) {
82                 msyslog(LOG_ERR,
83                     "MAC decrypt: digest init failed");
84                 EVP_MD_CTX_free(ctx);
85                 return (0);
86         }
87         EVP_DigestUpdate(ctx, key, cache_secretsize);
88         EVP_DigestUpdate(ctx, (u_char *)pkt, length);
89         EVP_DigestFinal(ctx, digest, &len);
90         EVP_MD_CTX_free(ctx);
91         /* If the MAC is longer than the MAX then truncate it. */
92         if (len > MAX_MAC_LEN - 4)
93             len = MAX_MAC_LEN - 4;
94         if (size != (size_t)len + 4) {
95                 msyslog(LOG_ERR,
96                     "MAC decrypt: MAC length error");
97                 return (0);
98         }
99         return !isc_tsmemcmp(digest, (u_char *)pkt + length + 4, len);
100 }
101
102 /*
103  * Calculate the reference id from the address. If it is an IPv4
104  * address, use it as is. If it is an IPv6 address, do a md5 on
105  * it and use the bottom 4 bytes.
106  * The result is in network byte order.
107  */
108 u_int32
109 addr2refid(sockaddr_u *addr)
110 {
111         u_char          digest[20];
112         u_int32         addr_refid;
113         EVP_MD_CTX      *ctx;
114         u_int           len;
115
116         if (IS_IPV4(addr))
117                 return (NSRCADR(addr));
118
119         INIT_SSL();
120
121         ctx = EVP_MD_CTX_new();
122         EVP_MD_CTX_init(ctx);
123 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
124         /* MD5 is not used as a crypto hash here. */
125         EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
126 #endif
127         if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) {
128                 msyslog(LOG_ERR,
129                     "MD5 init failed");
130                 EVP_MD_CTX_free(ctx);   /* pedantic... but safe */
131                 exit(1);
132         }
133
134         EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr),
135             sizeof(struct in6_addr));
136         EVP_DigestFinal(ctx, digest, &len);
137         EVP_MD_CTX_free(ctx);
138         memcpy(&addr_refid, digest, sizeof(addr_refid));
139         return (addr_refid);
140 }