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 #ifdef OPENSSL 16 # include "openssl/cmac.h" 17 # define CMAC "AES128CMAC" 18 # define AES_128_KEY_SIZE 16 19 #endif 20 21 typedef struct { 22 const void * buf; 23 size_t len; 24 } robuffT; 25 26 typedef struct { 27 void * buf; 28 size_t len; 29 } rwbuffT; 30 31 #ifdef OPENSSL 32 static size_t 33 cmac_ctx_size( 34 CMAC_CTX * ctx) 35 { 36 size_t mlen = 0; 37 38 if (ctx) { 39 EVP_CIPHER_CTX * cctx; 40 if (NULL != (cctx = CMAC_CTX_get0_cipher_ctx (ctx))) 41 mlen = EVP_CIPHER_CTX_block_size(cctx); 42 } 43 return mlen; 44 } 45 #endif /*OPENSSL*/ 46 47 static size_t 48 make_mac( 49 const rwbuffT * digest, 50 int ktype, 51 const robuffT * key, 52 const robuffT * msg) 53 { 54 /* 55 * Compute digest of key concatenated with packet. Note: the 56 * key type and digest type have been verified when the key 57 * was created. 58 */ 59 size_t retlen = 0; 60 61 #ifdef OPENSSL 62 63 INIT_SSL(); 64 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]; 70 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)); 76 keyptr = keybuf; 77 } 78 79 if (NULL == (ctx = CMAC_CTX_new())) { 80 msyslog(LOG_ERR, "MAC encrypt: CMAC %s CTX new failed.", CMAC); 81 goto cmac_fail; 82 } 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); 85 goto cmac_fail; 86 } 87 if (cmac_ctx_size(ctx) > digest->len) { 88 msyslog(LOG_ERR, "MAC encrypt: CMAC %s buf too small.", CMAC); 89 goto cmac_fail; 90 } 91 if (!CMAC_Update(ctx, msg->buf, msg->len)) { 92 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Update failed.", CMAC); 93 goto cmac_fail; 94 } 95 if (!CMAC_Final(ctx, digest->buf, &retlen)) { 96 msyslog(LOG_ERR, "MAC encrypt: CMAC %s Final failed.", CMAC); 97 retlen = 0; 98 } 99 cmac_fail: 100 if (ctx) 101 CMAC_CTX_cleanup(ctx); 102 } 103 else { /* 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 uint 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 { 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); 169 } 170 if (ctx) 171 EVP_MD_CTX_free(ctx); 172 retlen = (size_t)uilen; 173 } 174 else 175 { 176 msyslog(LOG_ERR, "MAC encrypt: invalid key type %d" , ktype); 177 } 178 179 #endif /* !OPENSSL */ 180 181 return retlen; 182 } 183 184 185 /* 186 * MD5authencrypt - generate message digest 187 * 188 * Returns length of MAC including key ID and digest. 189 */ 190 size_t 191 MD5authencrypt( 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 */ 197 ) 198 { 199 u_char digest[EVP_MAX_MD_SIZE]; 200 rwbuffT digb = { digest, sizeof(digest) }; 201 robuffT keyb = { key, klen }; 202 robuffT msgb = { pkt, length }; 203 size_t dlen = 0; 204 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) 208 dlen = MAX_MDG_LEN; 209 memcpy((u_char *)pkt + length + KEY_MAC_LEN, digest, dlen); 210 return (dlen + KEY_MAC_LEN); 211 } 212 213 214 /* 215 * MD5authdecrypt - verify MD5 message authenticator 216 * 217 * Returns one if digest valid, zero if invalid. 218 */ 219 int 220 MD5authdecrypt( 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 */ 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"); 243 return (0); 244 } 245 return !isc_tsmemcmp(digest, 246 (u_char *)pkt + length + KEY_MAC_LEN, dlen); 247 } 248 249 /* 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. 254 */ 255 u_int32 256 addr2refid(sockaddr_u *addr) 257 { 258 u_char digest[EVP_MAX_MD_SIZE]; 259 u_int32 addr_refid; 260 EVP_MD_CTX *ctx; 261 u_int len; 262 263 if (IS_IPV4(addr)) 264 return (NSRCADR(addr)); 265 266 INIT_SSL(); 267 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); 272 # endif 273 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would kill the 274 * flags! */ 275 if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) { 276 msyslog(LOG_ERR, 277 "MD5 init failed"); 278 EVP_MD_CTX_free(ctx); /* pedantic... but safe */ 279 exit(1); 280 } 281 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)); 287 return (addr_refid); 288 } 289