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