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 #include "libssl_compat.h" 15 /* 16 * MD5authencrypt - generate message digest 17 * 18 * Returns length of MAC including key ID and digest. 19 */ 20 size_t 21 MD5authencrypt( 22 int type, /* hash algorithm */ 23 const u_char * key, /* key pointer */ 24 u_int32 * pkt, /* packet pointer */ 25 size_t length /* packet length */ 26 ) 27 { 28 u_char digest[EVP_MAX_MD_SIZE]; 29 u_int len; 30 EVP_MD_CTX *ctx; 31 32 /* 33 * Compute digest of key concatenated with packet. Note: the 34 * key type and digest type have been verified when the key 35 * was creaded. 36 */ 37 INIT_SSL(); 38 ctx = EVP_MD_CTX_new(); 39 if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { 40 msyslog(LOG_ERR, 41 "MAC encrypt: digest init failed"); 42 EVP_MD_CTX_free(ctx); 43 return (0); 44 } 45 EVP_DigestUpdate(ctx, key, cache_secretsize); 46 EVP_DigestUpdate(ctx, (u_char *)pkt, length); 47 EVP_DigestFinal(ctx, digest, &len); 48 EVP_MD_CTX_free(ctx); 49 /* If the MAC is longer than the MAX then truncate it. */ 50 if (len > MAX_MAC_LEN - 4) 51 len = MAX_MAC_LEN - 4; 52 memmove((u_char *)pkt + length + 4, digest, len); 53 return (len + 4); 54 } 55 56 57 /* 58 * MD5authdecrypt - verify MD5 message authenticator 59 * 60 * Returns one if digest valid, zero if invalid. 61 */ 62 int 63 MD5authdecrypt( 64 int type, /* hash algorithm */ 65 const u_char * key, /* key pointer */ 66 u_int32 * pkt, /* packet pointer */ 67 size_t length, /* packet length */ 68 size_t size /* MAC size */ 69 ) 70 { 71 u_char digest[EVP_MAX_MD_SIZE]; 72 u_int len; 73 EVP_MD_CTX *ctx; 74 75 /* 76 * Compute digest of key concatenated with packet. Note: the 77 * key type and digest type have been verified when the key 78 * was created. 79 */ 80 INIT_SSL(); 81 ctx = EVP_MD_CTX_new(); 82 if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { 83 msyslog(LOG_ERR, 84 "MAC decrypt: digest init failed"); 85 EVP_MD_CTX_free(ctx); 86 return (0); 87 } 88 EVP_DigestUpdate(ctx, key, cache_secretsize); 89 EVP_DigestUpdate(ctx, (u_char *)pkt, length); 90 EVP_DigestFinal(ctx, digest, &len); 91 EVP_MD_CTX_free(ctx); 92 /* If the MAC is longer than the MAX then truncate it. */ 93 if (len > MAX_MAC_LEN - 4) 94 len = MAX_MAC_LEN - 4; 95 if (size != (size_t)len + 4) { 96 msyslog(LOG_ERR, 97 "MAC decrypt: MAC length error"); 98 return (0); 99 } 100 return !isc_tsmemcmp(digest, (u_char *)pkt + length + 4, len); 101 } 102 103 /* 104 * Calculate the reference id from the address. If it is an IPv4 105 * address, use it as is. If it is an IPv6 address, do a md5 on 106 * it and use the bottom 4 bytes. 107 * The result is in network byte order. 108 */ 109 u_int32 110 addr2refid(sockaddr_u *addr) 111 { 112 u_char digest[20]; 113 u_int32 addr_refid; 114 EVP_MD_CTX *ctx; 115 u_int len; 116 117 if (IS_IPV4(addr)) 118 return (NSRCADR(addr)); 119 120 INIT_SSL(); 121 122 ctx = EVP_MD_CTX_new(); 123 EVP_MD_CTX_init(ctx); 124 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 125 /* MD5 is not used as a crypto hash here. */ 126 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 127 #endif 128 if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) { 129 msyslog(LOG_ERR, 130 "MD5 init failed"); 131 EVP_MD_CTX_free(ctx); /* pedantic... but safe */ 132 exit(1); 133 } 134 135 EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr), 136 sizeof(struct in6_addr)); 137 EVP_DigestFinal(ctx, digest, &len); 138 EVP_MD_CTX_free(ctx); 139 memcpy(&addr_refid, digest, sizeof(addr_refid)); 140 return (addr_refid); 141 } 142