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