]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libntp/a_md5encrypt.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[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
14 /*
15  * MD5authencrypt - generate message digest
16  *
17  * Returns length of MAC including key ID and digest.
18  */
19 int
20 MD5authencrypt(
21         int     type,           /* hash algorithm */
22         u_char  *key,           /* key pointer */
23         u_int32 *pkt,           /* packet pointer */
24         int     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, (u_int)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         u_char  *key,           /* key pointer */
63         u_int32 *pkt,           /* packet pointer */
64         int     length,         /* packet length */
65         int     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, (u_int)length);
89         EVP_DigestFinal(&ctx, digest, &len);
90         if ((u_int)size != len + 4) {
91                 msyslog(LOG_ERR,
92                     "MAC decrypt: MAC length error");
93                 return (0);
94         }
95         return !memcmp(digest, (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 }