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