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 typedef struct { 16 const void * buf; 17 size_t len; 18 } robuffT; 19 20 typedef struct { 21 void * buf; 22 size_t len; 23 } rwbuffT; 24 25 #if defined(OPENSSL) && defined(ENABLE_CMAC) 26 static size_t 27 cmac_ctx_size( 28 CMAC_CTX * ctx) 29 { 30 size_t mlen = 0; 31 32 if (ctx) { 33 EVP_CIPHER_CTX * cctx; 34 if (NULL != (cctx = CMAC_CTX_get0_cipher_ctx (ctx))) 35 mlen = EVP_CIPHER_CTX_block_size(cctx); 36 } 37 return mlen; 38 } 39 #endif /*OPENSSL && ENABLE_CMAC*/ 40 41 static size_t 42 make_mac( 43 const rwbuffT * digest, 44 int ktype, 45 const robuffT * key, 46 const robuffT * msg) 47 { 48 /* 49 * Compute digest of key concatenated with packet. Note: the 50 * key type and digest type have been verified when the key 51 * was created. 52 */ 53 size_t retlen = 0; 54 55 #ifdef OPENSSL 56 57 INIT_SSL(); 58 59 /* Check if CMAC key type specific code required */ 60 # ifdef ENABLE_CMAC 61 if (ktype == NID_cmac) { 62 CMAC_CTX * ctx = NULL; 63 void const * keyptr = key->buf; 64 u_char keybuf[AES_128_KEY_SIZE]; 65 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)); 71 keyptr = keybuf; 72 } 73 74 if (NULL == (ctx = CMAC_CTX_new())) { 75 msyslog(LOG_ERR, "MAC encrypt: CMAC %s CTX new failed.", CMAC); 76 goto cmac_fail; 77 } 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); 80 goto cmac_fail; 81 } 82 if (cmac_ctx_size(ctx) > digest->len) { 83 msyslog(LOG_ERR, "MAC encrypt: CMAC %s buf too small.", CMAC); 84 goto cmac_fail; 85 } 86 if (!CMAC_Update(ctx, msg->buf, msg->len)) { 87 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Update failed.", CMAC); 88 goto cmac_fail; 89 } 90 if (!CMAC_Final(ctx, digest->buf, &retlen)) { 91 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Final failed.", CMAC); 92 retlen = 0; 93 } 94 cmac_fail: 95 if (ctx) 96 CMAC_CTX_free(ctx); 97 } 98 else 99 # endif /*ENABLE_CMAC*/ 100 { /* generic MAC handling */ 101 EVP_MD_CTX * ctx = EVP_MD_CTX_new(); 102 u_int uilen = 0; 103 104 if ( ! ctx) { 105 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest CTX new failed.", 106 OBJ_nid2sn(ktype)); 107 goto mac_fail; 108 } 109 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); 113 #endif 114 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would 115 * kill the flags! */ 116 if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(ktype), NULL)) { 117 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Init failed.", 118 OBJ_nid2sn(ktype)); 119 goto mac_fail; 120 } 121 if ((size_t)EVP_MD_CTX_size(ctx) > digest->len) { 122 msyslog(LOG_ERR, "MAC encrypt: MAC %s buf too small.", 123 OBJ_nid2sn(ktype)); 124 goto mac_fail; 125 } 126 if (!EVP_DigestUpdate(ctx, key->buf, (u_int)key->len)) { 127 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update key failed.", 128 OBJ_nid2sn(ktype)); 129 goto mac_fail; 130 } 131 if (!EVP_DigestUpdate(ctx, msg->buf, (u_int)msg->len)) { 132 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Update data failed.", 133 OBJ_nid2sn(ktype)); 134 goto mac_fail; 135 } 136 if (!EVP_DigestFinal(ctx, digest->buf, &uilen)) { 137 msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Final failed.", 138 OBJ_nid2sn(ktype)); 139 uilen = 0; 140 } 141 mac_fail: 142 retlen = (size_t)uilen; 143 144 if (ctx) 145 EVP_MD_CTX_free(ctx); 146 } 147 148 #else /* !OPENSSL follows */ 149 150 if (ktype == NID_md5) 151 { 152 EVP_MD_CTX * ctx = EVP_MD_CTX_new(); 153 u_int uilen = 0; 154 155 if (digest->len < 16) { 156 msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 buf too small."); 157 } 158 else if ( ! ctx) { 159 msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 Digest CTX new failed."); 160 } 161 else if (!EVP_DigestInit(ctx, EVP_get_digestbynid(ktype))) { 162 msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 Digest INIT failed."); 163 } 164 else { 165 EVP_DigestUpdate(ctx, key->buf, key->len); 166 EVP_DigestUpdate(ctx, msg->buf, msg->len); 167 EVP_DigestFinal(ctx, digest->buf, &uilen); 168 } 169 if (ctx) 170 EVP_MD_CTX_free(ctx); 171 retlen = (size_t)uilen; 172 } 173 else 174 { 175 msyslog(LOG_ERR, "MAC encrypt: invalid key type %d" , ktype); 176 } 177 178 #endif /* !OPENSSL */ 179 180 return retlen; 181 } 182 183 184 /* 185 * MD5authencrypt - generate message digest 186 * 187 * Returns length of MAC including key ID and digest. 188 */ 189 size_t 190 MD5authencrypt( 191 int type, /* hash algorithm */ 192 const u_char * key, /* key pointer */ 193 size_t klen, /* key length */ 194 u_int32 * pkt, /* packet pointer */ 195 size_t length /* packet length */ 196 ) 197 { 198 u_char digest[EVP_MAX_MD_SIZE]; 199 rwbuffT digb = { digest, sizeof(digest) }; 200 robuffT keyb = { key, klen }; 201 robuffT msgb = { pkt, length }; 202 size_t dlen = 0; 203 204 dlen = make_mac(&digb, type, &keyb, &msgb); 205 /* If the MAC is longer than the MAX then truncate it. */ 206 if (dlen > MAX_MDG_LEN) 207 dlen = MAX_MDG_LEN; 208 memcpy((u_char *)pkt + length + KEY_MAC_LEN, digest, dlen); 209 return (dlen + KEY_MAC_LEN); 210 } 211 212 213 /* 214 * MD5authdecrypt - verify MD5 message authenticator 215 * 216 * Returns one if digest valid, zero if invalid. 217 */ 218 int 219 MD5authdecrypt( 220 int type, /* hash algorithm */ 221 const u_char * key, /* key pointer */ 222 size_t klen, /* key length */ 223 u_int32 * pkt, /* packet pointer */ 224 size_t length, /* packet length */ 225 size_t size, /* MAC size */ 226 keyid_t keyno /* key id (for err log) */ 227 ) 228 { 229 u_char digest[EVP_MAX_MD_SIZE]; 230 rwbuffT digb = { digest, sizeof(digest) }; 231 robuffT keyb = { key, klen }; 232 robuffT msgb = { pkt, length }; 233 size_t dlen = 0; 234 235 dlen = make_mac(&digb, type, &keyb, &msgb); 236 237 /* If the MAC is longer than the MAX then truncate it. */ 238 if (dlen > MAX_MDG_LEN) 239 dlen = MAX_MDG_LEN; 240 if (size != (size_t)dlen + KEY_MAC_LEN) { 241 msyslog(LOG_ERR, 242 "MAC decrypt: MAC length error: len=%zu key=%d", 243 size, keyno); 244 return (0); 245 } 246 return !isc_tsmemcmp(digest, 247 (u_char *)pkt + length + KEY_MAC_LEN, dlen); 248 } 249 250 /* 251 * Calculate the reference id from the address. If it is an IPv4 252 * address, use it as is. If it is an IPv6 address, do a md5 on 253 * it and use the bottom 4 bytes. 254 * The result is in network byte order. 255 */ 256 u_int32 257 addr2refid(sockaddr_u *addr) 258 { 259 u_char digest[EVP_MAX_MD_SIZE]; 260 u_int32 addr_refid; 261 EVP_MD_CTX *ctx; 262 u_int len; 263 264 if (IS_IPV4(addr)) 265 return (NSRCADR(addr)); 266 267 INIT_SSL(); 268 269 ctx = EVP_MD_CTX_new(); 270 # ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 271 /* MD5 is not used as a crypto hash here. */ 272 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 273 # endif 274 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would kill the 275 * flags! */ 276 if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) { 277 msyslog(LOG_ERR, 278 "MD5 init failed"); 279 EVP_MD_CTX_free(ctx); /* pedantic... but safe */ 280 exit(1); 281 } 282 283 EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr), 284 sizeof(struct in6_addr)); 285 EVP_DigestFinal(ctx, digest, &len); 286 EVP_MD_CTX_free(ctx); 287 memcpy(&addr_refid, digest, sizeof(addr_refid)); 288 return (addr_refid); 289 } 290