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