1 /* $NetBSD: a_md5encrypt.c,v 1.6 2016/06/29 18:42:17 christos Exp $ */ 2 3 /* 4 * digest support for NTP, MD5 and with OpenSSL more 5 */ 6 #ifdef HAVE_CONFIG_H 7 #include <config.h> 8 #endif 9 10 #include "ntp_fp.h" 11 #include "ntp_string.h" 12 #include "ntp_stdlib.h" 13 #include "ntp.h" 14 #include "ntp_md5.h" /* provides OpenSSL digest API */ 15 #include "isc/string.h" 16 /* 17 * MD5authencrypt - generate message digest 18 * 19 * Returns length of MAC including key ID and digest. 20 */ 21 size_t 22 MD5authencrypt( 23 int type, /* hash algorithm */ 24 const u_char * key, /* key pointer */ 25 u_int32 * pkt, /* packet pointer */ 26 size_t length /* packet length */ 27 ) 28 { 29 u_char digest[EVP_MAX_MD_SIZE]; 30 u_int len; 31 EVP_MD_CTX ctx; 32 33 /* 34 * Compute digest of key concatenated with packet. Note: the 35 * key type and digest type have been verified when the key 36 * was creaded. 37 */ 38 INIT_SSL(); 39 if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) { 40 msyslog(LOG_ERR, 41 "MAC encrypt: digest init failed"); 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 memmove((u_char *)pkt + length + 4, digest, len); 48 return (len + 4); 49 } 50 51 52 /* 53 * MD5authdecrypt - verify MD5 message authenticator 54 * 55 * Returns one if digest valid, zero if invalid. 56 */ 57 int 58 MD5authdecrypt( 59 int type, /* hash algorithm */ 60 const u_char * key, /* key pointer */ 61 u_int32 * pkt, /* packet pointer */ 62 size_t length, /* packet length */ 63 size_t size /* MAC size */ 64 ) 65 { 66 u_char digest[EVP_MAX_MD_SIZE]; 67 u_int len; 68 EVP_MD_CTX ctx; 69 70 /* 71 * Compute digest of key concatenated with packet. Note: the 72 * key type and digest type have been verified when the key 73 * was created. 74 */ 75 INIT_SSL(); 76 if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) { 77 msyslog(LOG_ERR, 78 "MAC decrypt: digest init failed"); 79 return (0); 80 } 81 EVP_DigestUpdate(&ctx, key, cache_secretsize); 82 EVP_DigestUpdate(&ctx, (u_char *)pkt, length); 83 EVP_DigestFinal(&ctx, digest, &len); 84 if (size != (size_t)len + 4) { 85 msyslog(LOG_ERR, 86 "MAC decrypt: MAC length error"); 87 return (0); 88 } 89 return !isc_tsmemcmp(digest, (const char *)pkt + length + 4, len); 90 } 91 92 /* 93 * Calculate the reference id from the address. If it is an IPv4 94 * address, use it as is. If it is an IPv6 address, do a md5 on 95 * it and use the bottom 4 bytes. 96 * The result is in network byte order. 97 */ 98 u_int32 99 addr2refid(sockaddr_u *addr) 100 { 101 u_char digest[20]; 102 u_int32 addr_refid; 103 EVP_MD_CTX ctx; 104 u_int len; 105 106 if (IS_IPV4(addr)) 107 return (NSRCADR(addr)); 108 109 INIT_SSL(); 110 111 #if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL 112 EVP_MD_CTX_init(&ctx); 113 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 114 /* MD5 is not used as a crypto hash here. */ 115 EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 116 #endif 117 #endif 118 if (!EVP_DigestInit(&ctx, EVP_md5())) { 119 msyslog(LOG_ERR, 120 "MD5 init failed"); 121 exit(1); 122 } 123 124 EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr), 125 sizeof(struct in6_addr)); 126 EVP_DigestFinal(&ctx, digest, &len); 127 memcpy(&addr_refid, digest, sizeof(addr_refid)); 128 return (addr_refid); 129 } 130