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"
25 #if defined(OPENSSL) && defined(ENABLE_CMAC)
33 EVP_CIPHER_CTX * cctx;
34 if (NULL != (cctx = CMAC_CTX_get0_cipher_ctx (ctx)))
35 mlen = EVP_CIPHER_CTX_block_size(cctx);
39 #endif /*OPENSSL && ENABLE_CMAC*/
43 const rwbuffT * digest,
49 * Compute digest of key concatenated with packet. Note: the
50 * key type and digest type have been verified when the key
59 /* Check if CMAC key type specific code required */
61 if (ktype == NID_cmac) {
62 CMAC_CTX * ctx = NULL;
63 void const * keyptr = key->buf;
64 u_char keybuf[AES_128_KEY_SIZE];
66 /* adjust key size (zero padded buffer) if necessary */
67 if (AES_128_KEY_SIZE > key->len) {
68 memcpy(keybuf, keyptr, key->len);
69 memset((keybuf + key->len), 0,
70 (AES_128_KEY_SIZE - key->len));
74 if (NULL == (ctx = CMAC_CTX_new())) {
75 msyslog(LOG_ERR, "MAC encrypt: CMAC %s CTX new failed.", CMAC);
78 if (!CMAC_Init(ctx, keyptr, AES_128_KEY_SIZE, EVP_aes_128_cbc(), NULL)) {
79 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Init failed.", CMAC);
82 if (cmac_ctx_size(ctx) > digest->len) {
83 msyslog(LOG_ERR, "MAC encrypt: CMAC %s buf too small.", CMAC);
86 if (!CMAC_Update(ctx, msg->buf, msg->len)) {
87 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Update failed.", CMAC);
90 if (!CMAC_Final(ctx, digest->buf, &retlen)) {
91 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Final failed.", CMAC);
96 CMAC_CTX_cleanup(ctx);
99 # endif /*ENABLE_CMAC*/
100 { /* generic MAC handling */
101 EVP_MD_CTX * ctx = EVP_MD_CTX_new();
105 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest CTX new failed.",
110 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
111 /* make sure MD5 is allowd */
112 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
114 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would
116 if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(ktype), NULL)) {
117 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Init failed.",
121 if ((size_t)EVP_MD_CTX_size(ctx) > digest->len) {
122 msyslog(LOG_ERR, "MAC encrypt: MAC %s buf too small.",
126 if (!EVP_DigestUpdate(ctx, key->buf, (u_int)key->len)) {
127 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update key failed.",
131 if (!EVP_DigestUpdate(ctx, msg->buf, (u_int)msg->len)) {
132 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update data failed.",
136 if (!EVP_DigestFinal(ctx, digest->buf, &uilen)) {
137 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Final failed.",
142 retlen = (size_t)uilen;
145 EVP_MD_CTX_free(ctx);
148 #else /* !OPENSSL follows */
150 if (ktype == NID_md5)
152 EVP_MD_CTX * ctx = EVP_MD_CTX_new();
155 if (digest->len < 16) {
156 msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 buf too small.");
159 msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 Digest CTX new failed.");
162 EVP_DigestInit(ctx, EVP_get_digestbynid(ktype));
163 EVP_DigestUpdate(ctx, key->buf, key->len);
164 EVP_DigestUpdate(ctx, msg->buf, msg->len);
165 EVP_DigestFinal(ctx, digest->buf, &uilen);
168 EVP_MD_CTX_free(ctx);
169 retlen = (size_t)uilen;
173 msyslog(LOG_ERR, "MAC encrypt: invalid key type %d" , ktype);
176 #endif /* !OPENSSL */
183 * MD5authencrypt - generate message digest
185 * Returns length of MAC including key ID and digest.
189 int type, /* hash algorithm */
190 const u_char * key, /* key pointer */
191 size_t klen, /* key length */
192 u_int32 * pkt, /* packet pointer */
193 size_t length /* packet length */
196 u_char digest[EVP_MAX_MD_SIZE];
197 rwbuffT digb = { digest, sizeof(digest) };
198 robuffT keyb = { key, klen };
199 robuffT msgb = { pkt, length };
202 dlen = make_mac(&digb, type, &keyb, &msgb);
203 /* If the MAC is longer than the MAX then truncate it. */
204 if (dlen > MAX_MDG_LEN)
206 memcpy((u_char *)pkt + length + KEY_MAC_LEN, digest, dlen);
207 return (dlen + KEY_MAC_LEN);
212 * MD5authdecrypt - verify MD5 message authenticator
214 * Returns one if digest valid, zero if invalid.
218 int type, /* hash algorithm */
219 const u_char * key, /* key pointer */
220 size_t klen, /* key length */
221 u_int32 * pkt, /* packet pointer */
222 size_t length, /* packet length */
223 size_t size /* MAC size */
226 u_char digest[EVP_MAX_MD_SIZE];
227 rwbuffT digb = { digest, sizeof(digest) };
228 robuffT keyb = { key, klen };
229 robuffT msgb = { pkt, length };
232 dlen = make_mac(&digb, type, &keyb, &msgb);
234 /* If the MAC is longer than the MAX then truncate it. */
235 if (dlen > MAX_MDG_LEN)
237 if (size != (size_t)dlen + KEY_MAC_LEN) {
239 "MAC decrypt: MAC length error");
242 return !isc_tsmemcmp(digest,
243 (u_char *)pkt + length + KEY_MAC_LEN, dlen);
247 * Calculate the reference id from the address. If it is an IPv4
248 * address, use it as is. If it is an IPv6 address, do a md5 on
249 * it and use the bottom 4 bytes.
250 * The result is in network byte order.
253 addr2refid(sockaddr_u *addr)
255 u_char digest[EVP_MAX_MD_SIZE];
261 return (NSRCADR(addr));
265 ctx = EVP_MD_CTX_new();
266 # ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
267 /* MD5 is not used as a crypto hash here. */
268 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
270 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would kill the
272 if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) {
275 EVP_MD_CTX_free(ctx); /* pedantic... but safe */
279 EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr),
280 sizeof(struct in6_addr));
281 EVP_DigestFinal(ctx, digest, &len);
282 EVP_MD_CTX_free(ctx);
283 memcpy(&addr_refid, digest, sizeof(addr_refid));