2 * digest support for NTP, MD5 and with OpenSSL more
9 #include "ntp_string.h"
10 #include "ntp_stdlib.h"
12 #include "ntp_md5.h" /* provides OpenSSL digest API */
13 #include "isc/string.h"
16 # include "openssl/cmac.h"
17 # define CMAC "AES128CMAC"
18 # define AES_128_KEY_SIZE 16
39 EVP_CIPHER_CTX * cctx;
40 if (NULL != (cctx = CMAC_CTX_get0_cipher_ctx (ctx)))
41 mlen = EVP_CIPHER_CTX_block_size(cctx);
49 const rwbuffT * digest,
55 * Compute digest of key concatenated with packet. Note: the
56 * key type and digest type have been verified when the key
65 /* Check if CMAC key type specific code required */
66 if (ktype == NID_cmac) {
67 CMAC_CTX * ctx = NULL;
68 void const * keyptr = key->buf;
69 u_char keybuf[AES_128_KEY_SIZE];
71 /* adjust key size (zero padded buffer) if necessary */
72 if (AES_128_KEY_SIZE > key->len) {
73 memcpy(keybuf, keyptr, key->len);
74 memset((keybuf + key->len), 0,
75 (AES_128_KEY_SIZE - key->len));
79 if (NULL == (ctx = CMAC_CTX_new())) {
80 msyslog(LOG_ERR, "MAC encrypt: CMAC %s CTX new failed.", CMAC);
83 if (!CMAC_Init(ctx, keyptr, AES_128_KEY_SIZE, EVP_aes_128_cbc(), NULL)) {
84 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Init failed.", CMAC);
87 if (cmac_ctx_size(ctx) > digest->len) {
88 msyslog(LOG_ERR, "MAC encrypt: CMAC %s buf too small.", CMAC);
91 if (!CMAC_Update(ctx, msg->buf, msg->len)) {
92 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Update failed.", CMAC);
95 if (!CMAC_Final(ctx, digest->buf, &retlen)) {
96 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Final failed.", CMAC);
101 CMAC_CTX_cleanup(ctx);
103 else { /* generic MAC handling */
104 EVP_MD_CTX * ctx = EVP_MD_CTX_new();
108 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest CTX new failed.",
113 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
114 /* make sure MD5 is allowd */
115 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
117 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would
119 if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(ktype), NULL)) {
120 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Init failed.",
124 if ((size_t)EVP_MD_CTX_size(ctx) > digest->len) {
125 msyslog(LOG_ERR, "MAC encrypt: MAC %s buf too small.",
129 if (!EVP_DigestUpdate(ctx, key->buf, (u_int)key->len)) {
130 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update key failed.",
134 if (!EVP_DigestUpdate(ctx, msg->buf, (u_int)msg->len)) {
135 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update data failed.",
139 if (!EVP_DigestFinal(ctx, digest->buf, &uilen)) {
140 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Final failed.",
145 retlen = (size_t)uilen;
148 EVP_MD_CTX_free(ctx);
151 #else /* !OPENSSL follows */
153 if (ktype == NID_md5)
155 EVP_MD_CTX * ctx = EVP_MD_CTX_new();
158 if (digest->len < 16) {
159 msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 buf too small.");
162 msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 Digest CTX new failed.");
165 EVP_DigestInit(ctx, EVP_get_digestbynid(ktype));
166 EVP_DigestUpdate(ctx, key->buf, key->len);
167 EVP_DigestUpdate(ctx, msg->buf, msg->len);
168 EVP_DigestFinal(ctx, digest->buf, &uilen);
171 EVP_MD_CTX_free(ctx);
172 retlen = (size_t)uilen;
176 msyslog(LOG_ERR, "MAC encrypt: invalid key type %d" , ktype);
179 #endif /* !OPENSSL */
186 * MD5authencrypt - generate message digest
188 * Returns length of MAC including key ID and digest.
192 int type, /* hash algorithm */
193 const u_char * key, /* key pointer */
194 size_t klen, /* key length */
195 u_int32 * pkt, /* packet pointer */
196 size_t length /* packet length */
199 u_char digest[EVP_MAX_MD_SIZE];
200 rwbuffT digb = { digest, sizeof(digest) };
201 robuffT keyb = { key, klen };
202 robuffT msgb = { pkt, length };
205 dlen = make_mac(&digb, type, &keyb, &msgb);
206 /* If the MAC is longer than the MAX then truncate it. */
207 if (dlen > MAX_MDG_LEN)
209 memcpy((u_char *)pkt + length + KEY_MAC_LEN, digest, dlen);
210 return (dlen + KEY_MAC_LEN);
215 * MD5authdecrypt - verify MD5 message authenticator
217 * Returns one if digest valid, zero if invalid.
221 int type, /* hash algorithm */
222 const u_char * key, /* key pointer */
223 size_t klen, /* key length */
224 u_int32 * pkt, /* packet pointer */
225 size_t length, /* packet length */
226 size_t size /* MAC size */
229 u_char digest[EVP_MAX_MD_SIZE];
230 rwbuffT digb = { digest, sizeof(digest) };
231 robuffT keyb = { key, klen };
232 robuffT msgb = { pkt, length };
235 dlen = make_mac(&digb, type, &keyb, &msgb);
237 /* If the MAC is longer than the MAX then truncate it. */
238 if (dlen > MAX_MDG_LEN)
240 if (size != (size_t)dlen + KEY_MAC_LEN) {
242 "MAC decrypt: MAC length error");
245 return !isc_tsmemcmp(digest,
246 (u_char *)pkt + length + KEY_MAC_LEN, dlen);
250 * Calculate the reference id from the address. If it is an IPv4
251 * address, use it as is. If it is an IPv6 address, do a md5 on
252 * it and use the bottom 4 bytes.
253 * The result is in network byte order.
256 addr2refid(sockaddr_u *addr)
258 u_char digest[EVP_MAX_MD_SIZE];
264 return (NSRCADR(addr));
268 ctx = EVP_MD_CTX_new();
269 # ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
270 /* MD5 is not used as a crypto hash here. */
271 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
273 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would kill the
275 if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) {
278 EVP_MD_CTX_free(ctx); /* pedantic... but safe */
282 EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr),
283 sizeof(struct in6_addr));
284 EVP_DigestFinal(ctx, digest, &len);
285 EVP_MD_CTX_free(ctx);
286 memcpy(&addr_refid, digest, sizeof(addr_refid));