a_md5encrypt.c revision 298699
1156772Sdeischen/* 2156772Sdeischen * digest support for NTP, MD5 and with OpenSSL more 3156772Sdeischen */ 4156772Sdeischen#ifdef HAVE_CONFIG_H 5156772Sdeischen#include <config.h> 6156772Sdeischen#endif 7156772Sdeischen 8156772Sdeischen#include "ntp_fp.h" 9156772Sdeischen#include "ntp_string.h" 10156772Sdeischen#include "ntp_stdlib.h" 11156772Sdeischen#include "ntp.h" 12156772Sdeischen#include "ntp_md5.h" /* provides OpenSSL digest API */ 13156772Sdeischen#include "isc/string.h" 14156772Sdeischen/* 15156772Sdeischen * MD5authencrypt - generate message digest 16156772Sdeischen * 17156772Sdeischen * Returns length of MAC including key ID and digest. 18156772Sdeischen */ 19156772Sdeischensize_t 20156772SdeischenMD5authencrypt( 21156772Sdeischen int type, /* hash algorithm */ 22156772Sdeischen const u_char * key, /* key pointer */ 23156772Sdeischen u_int32 * pkt, /* packet pointer */ 24156772Sdeischen size_t length /* packet length */ 25156772Sdeischen ) 26156772Sdeischen{ 27156772Sdeischen u_char digest[EVP_MAX_MD_SIZE]; 28156772Sdeischen u_int len; 29156772Sdeischen EVP_MD_CTX ctx; 30156772Sdeischen 31156772Sdeischen /* 32156772Sdeischen * Compute digest of key concatenated with packet. Note: the 33156772Sdeischen * key type and digest type have been verified when the key 34156772Sdeischen * was creaded. 35156772Sdeischen */ 36156772Sdeischen INIT_SSL(); 37172747Syar#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL 38172729Syar if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) { 39156772Sdeischen msyslog(LOG_ERR, 40156772Sdeischen "MAC encrypt: digest init failed"); 41156772Sdeischen return (0); 42172747Syar } 43156772Sdeischen#else 44156772Sdeischen EVP_DigestInit(&ctx, EVP_get_digestbynid(type)); 45156772Sdeischen#endif 46156772Sdeischen EVP_DigestUpdate(&ctx, key, cache_secretsize); 47156772Sdeischen EVP_DigestUpdate(&ctx, (u_char *)pkt, length); 48156772Sdeischen EVP_DigestFinal(&ctx, digest, &len); 49156772Sdeischen memmove((u_char *)pkt + length + 4, digest, len); 50172729Syar return (len + 4); 51172729Syar} 52172729Syar 53156772Sdeischen 54172729Syar/* 55172729Syar * MD5authdecrypt - verify MD5 message authenticator 56172729Syar * 57156772Sdeischen * Returns one if digest valid, zero if invalid. 58156772Sdeischen */ 59156772Sdeischenint 60156772SdeischenMD5authdecrypt( 61168963Sdeischen int type, /* hash algorithm */ 62156772Sdeischen const u_char * key, /* key pointer */ 63156772Sdeischen u_int32 * pkt, /* packet pointer */ 64172729Syar size_t length, /* packet length */ 65172729Syar size_t size /* MAC size */ 66172729Syar ) 67172729Syar{ 68156772Sdeischen u_char digest[EVP_MAX_MD_SIZE]; 69172729Syar u_int len; 70172729Syar EVP_MD_CTX ctx; 71172729Syar 72172729Syar /* 73172729Syar * Compute digest of key concatenated with packet. Note: the 74172729Syar * key type and digest type have been verified when the key 75172729Syar * was created. 76172729Syar */ 77172729Syar INIT_SSL(); 78172729Syar#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL 79172729Syar if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) { 80172729Syar msyslog(LOG_ERR, 81156772Sdeischen "MAC decrypt: digest init failed"); 82172729Syar return (0); 83156772Sdeischen } 84156772Sdeischen#else 85172729Syar EVP_DigestInit(&ctx, EVP_get_digestbynid(type)); 86172729Syar#endif 87156772Sdeischen EVP_DigestUpdate(&ctx, key, cache_secretsize); 88156772Sdeischen EVP_DigestUpdate(&ctx, (u_char *)pkt, length); 89172729Syar EVP_DigestFinal(&ctx, digest, &len); 90172729Syar if (size != (size_t)len + 4) { 91156772Sdeischen msyslog(LOG_ERR, 92156772Sdeischen "MAC decrypt: MAC length error"); 93156772Sdeischen return (0); 94172729Syar } 95172729Syar return !isc_tsmemcmp(digest, (const char *)pkt + length + 4, len); 96156772Sdeischen} 97172729Syar 98156772Sdeischen/* 99156772Sdeischen * Calculate the reference id from the address. If it is an IPv4 100156772Sdeischen * address, use it as is. If it is an IPv6 address, do a md5 on 101172729Syar * it and use the bottom 4 bytes. 102172729Syar * The result is in network byte order. 103156772Sdeischen */ 104172729Syaru_int32 105172729Syaraddr2refid(sockaddr_u *addr) 106156772Sdeischen{ 107156772Sdeischen u_char digest[20]; 108156772Sdeischen u_int32 addr_refid; 109156772Sdeischen EVP_MD_CTX ctx; 110172729Syar u_int len; 111172729Syar 112172729Syar if (IS_IPV4(addr)) 113172729Syar return (NSRCADR(addr)); 114156772Sdeischen 115156772Sdeischen INIT_SSL(); 116156772Sdeischen 117156772Sdeischen#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL 118156772Sdeischen EVP_MD_CTX_init(&ctx); 119156772Sdeischen#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 120156772Sdeischen /* MD5 is not used as a crypto hash here. */ 121156772Sdeischen EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 122156772Sdeischen#endif 123172729Syar if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) { 124156772Sdeischen msyslog(LOG_ERR, 125156772Sdeischen "MD5 init failed"); 126172729Syar exit(1); 127156772Sdeischen } 128172729Syar#else 129172729Syar EVP_DigestInit(&ctx, EVP_md5()); 130172729Syar#endif 131156772Sdeischen 132156772Sdeischen EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr), 133172729Syar sizeof(struct in6_addr)); 134172729Syar EVP_DigestFinal(&ctx, digest, &len); 135156772Sdeischen memcpy(&addr_refid, digest, sizeof(addr_refid)); 136156772Sdeischen return (addr_refid); 137156772Sdeischen} 138156772Sdeischen