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