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