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