a_md5encrypt.c revision 316068
1179055Sjfv/* 2171384Sjfv * digest support for NTP, MD5 and with OpenSSL more 3179055Sjfv */ 4171384Sjfv#ifdef HAVE_CONFIG_H 5171384Sjfv#include <config.h> 6171384Sjfv#endif 7171384Sjfv 8171384Sjfv#include "ntp_fp.h" 9171384Sjfv#include "ntp_string.h" 10171384Sjfv#include "ntp_stdlib.h" 11171384Sjfv#include "ntp.h" 12171384Sjfv#include "ntp_md5.h" /* provides OpenSSL digest API */ 13171384Sjfv#include "isc/string.h" 14171384Sjfv/* 15171384Sjfv * MD5authencrypt - generate message digest 16171384Sjfv * 17171384Sjfv * Returns length of MAC including key ID and digest. 18171384Sjfv */ 19171384Sjfvsize_t 20171384SjfvMD5authencrypt( 21171384Sjfv int type, /* hash algorithm */ 22171384Sjfv const u_char * key, /* key pointer */ 23171384Sjfv u_int32 * pkt, /* packet pointer */ 24171384Sjfv size_t length /* packet length */ 25171384Sjfv ) 26171384Sjfv{ 27171384Sjfv u_char digest[EVP_MAX_MD_SIZE]; 28171384Sjfv u_int len; 29171384Sjfv EVP_MD_CTX *ctx; 30171384Sjfv 31171384Sjfv /* 32179055Sjfv * Compute digest of key concatenated with packet. Note: the 33179055Sjfv * key type and digest type have been verified when the key 34171384Sjfv * was creaded. 35171384Sjfv */ 36171384Sjfv INIT_SSL(); 37171384Sjfv ctx = EVP_MD_CTX_new(); 38171384Sjfv if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { 39171384Sjfv msyslog(LOG_ERR, 40171384Sjfv "MAC encrypt: digest init failed"); 41171384Sjfv EVP_MD_CTX_free(ctx); 42172043Sjfv return (0); 43171384Sjfv } 44171384Sjfv EVP_DigestUpdate(ctx, key, cache_secretsize); 45171384Sjfv EVP_DigestUpdate(ctx, (u_char *)pkt, length); 46171384Sjfv EVP_DigestFinal(ctx, digest, &len); 47171384Sjfv EVP_MD_CTX_free(ctx); 48171384Sjfv /* If the MAC is longer than the MAX then truncate it. */ 49171384Sjfv if (len > MAX_MAC_LEN - 4) 50171384Sjfv len = MAX_MAC_LEN - 4; 51171384Sjfv memmove((u_char *)pkt + length + 4, digest, len); 52171384Sjfv return (len + 4); 53179055Sjfv} 54171384Sjfv 55171384Sjfv 56171384Sjfv/* 57171384Sjfv * MD5authdecrypt - verify MD5 message authenticator 58179055Sjfv * 59171384Sjfv * Returns one if digest valid, zero if invalid. 60179055Sjfv */ 61171384Sjfvint 62179055SjfvMD5authdecrypt( 63179055Sjfv int type, /* hash algorithm */ 64179055Sjfv const u_char * key, /* key pointer */ 65179055Sjfv u_int32 * pkt, /* packet pointer */ 66179055Sjfv size_t length, /* packet length */ 67179055Sjfv size_t size /* MAC size */ 68179055Sjfv ) 69179055Sjfv{ 70171384Sjfv u_char digest[EVP_MAX_MD_SIZE]; 71171384Sjfv u_int len; 72179055Sjfv EVP_MD_CTX *ctx; 73171384Sjfv 74179055Sjfv /* 75179055Sjfv * Compute digest of key concatenated with packet. Note: the 76179055Sjfv * key type and digest type have been verified when the key 77171384Sjfv * was created. 78171384Sjfv */ 79171384Sjfv INIT_SSL(); 80171384Sjfv ctx = EVP_MD_CTX_new(); 81171384Sjfv if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { 82171384Sjfv msyslog(LOG_ERR, 83171384Sjfv "MAC decrypt: digest init failed"); 84171384Sjfv EVP_MD_CTX_free(ctx); 85171384Sjfv return (0); 86171384Sjfv } 87171384Sjfv EVP_DigestUpdate(ctx, key, cache_secretsize); 88179055Sjfv EVP_DigestUpdate(ctx, (u_char *)pkt, length); 89179055Sjfv EVP_DigestFinal(ctx, digest, &len); 90181003Sjfv EVP_MD_CTX_free(ctx); 91179055Sjfv /* If the MAC is longer than the MAX then truncate it. */ 92181003Sjfv if (len > MAX_MAC_LEN - 4) 93171384Sjfv len = MAX_MAC_LEN - 4; 94171384Sjfv if (size != (size_t)len + 4) { 95179055Sjfv msyslog(LOG_ERR, 96179055Sjfv "MAC decrypt: MAC length error"); 97171384Sjfv return (0); 98179055Sjfv } 99171384Sjfv return !isc_tsmemcmp(digest, (u_char *)pkt + length + 4, len); 100171384Sjfv} 101171384Sjfv 102171384Sjfv/* 103179055Sjfv * Calculate the reference id from the address. If it is an IPv4 104171384Sjfv * address, use it as is. If it is an IPv6 address, do a md5 on 105171384Sjfv * it and use the bottom 4 bytes. 106171384Sjfv * The result is in network byte order. 107171384Sjfv */ 108179055Sjfvu_int32 109179055Sjfvaddr2refid(sockaddr_u *addr) 110172043Sjfv{ 111172043Sjfv u_char digest[20]; 112181003Sjfv u_int32 addr_refid; 113171384Sjfv EVP_MD_CTX *ctx; 114171384Sjfv 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