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_cleanup(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 { 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); 166 } 167 if (ctx) 168 EVP_MD_CTX_free(ctx); 169 retlen = (size_t)uilen; 170 } 171 else 172 { 173 msyslog(LOG_ERR, "MAC encrypt: invalid key type %d" , ktype); 174 } 175 176 #endif /* !OPENSSL */ 177 178 return retlen; 179 } 180 181 182 /* 183 * MD5authencrypt - generate message digest 184 * 185 * Returns length of MAC including key ID and digest. 186 */ 187 size_t 188 MD5authencrypt( 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 */ 194 ) 195 { 196 u_char digest[EVP_MAX_MD_SIZE]; 197 rwbuffT digb = { digest, sizeof(digest) }; 198 robuffT keyb = { key, klen }; 199 robuffT msgb = { pkt, length }; 200 size_t dlen = 0; 201 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) 205 dlen = MAX_MDG_LEN; 206 memcpy((u_char *)pkt + length + KEY_MAC_LEN, digest, dlen); 207 return (dlen + KEY_MAC_LEN); 208 } 209 210 211 /* 212 * MD5authdecrypt - verify MD5 message authenticator 213 * 214 * Returns one if digest valid, zero if invalid. 215 */ 216 int 217 MD5authdecrypt( 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 */ 224 ) 225 { 226 u_char digest[EVP_MAX_MD_SIZE]; 227 rwbuffT digb = { digest, sizeof(digest) }; 228 robuffT keyb = { key, klen }; 229 robuffT msgb = { pkt, length }; 230 size_t dlen = 0; 231 232 dlen = make_mac(&digb, type, &keyb, &msgb); 233 234 /* If the MAC is longer than the MAX then truncate it. */ 235 if (dlen > MAX_MDG_LEN) 236 dlen = MAX_MDG_LEN; 237 if (size != (size_t)dlen + KEY_MAC_LEN) { 238 msyslog(LOG_ERR, 239 "MAC decrypt: MAC length error"); 240 return (0); 241 } 242 return !isc_tsmemcmp(digest, 243 (u_char *)pkt + length + KEY_MAC_LEN, dlen); 244 } 245 246 /* 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. 251 */ 252 u_int32 253 addr2refid(sockaddr_u *addr) 254 { 255 u_char digest[EVP_MAX_MD_SIZE]; 256 u_int32 addr_refid; 257 EVP_MD_CTX *ctx; 258 u_int len; 259 260 if (IS_IPV4(addr)) 261 return (NSRCADR(addr)); 262 263 INIT_SSL(); 264 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); 269 # endif 270 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would kill the 271 * flags! */ 272 if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) { 273 msyslog(LOG_ERR, 274 "MD5 init failed"); 275 EVP_MD_CTX_free(ctx); /* pedantic... but safe */ 276 exit(1); 277 } 278 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)); 284 return (addr_refid); 285 } 286