1 /* 2 * HMS: we need to test: 3 * - OpenSSL versions, if we are building with them 4 * - our versions 5 * 6 * We may need to test with(out) OPENSSL separately. 7 */ 8 9 #include <config.h> 10 #include "crypto.h" 11 #include <ctype.h> 12 #include "isc/string.h" 13 #include "ntp_md5.h" 14 15 #ifndef EVP_MAX_MD_SIZE 16 # define EVP_MAX_MD_SIZE 32 17 #endif 18 19 struct key *key_ptr; 20 size_t key_cnt = 0; 21 22 typedef struct key Key_T; 23 24 static u_int 25 compute_mac( 26 u_char digest[EVP_MAX_MD_SIZE], 27 char const * macname, 28 void const * pkt_data, 29 u_int pkt_size, 30 void const * key_data, 31 u_int key_size 32 ) 33 { 34 u_int len = 0; 35 #if defined(OPENSSL) && defined(ENABLE_CMAC) 36 size_t slen = 0; 37 #endif 38 int key_type; 39 40 INIT_SSL(); 41 key_type = keytype_from_text(macname, NULL); 42 43 #if defined(OPENSSL) && defined(ENABLE_CMAC) 44 /* Check if CMAC key type specific code required */ 45 if (key_type == NID_cmac) { 46 CMAC_CTX * ctx = NULL; 47 u_char keybuf[AES_128_KEY_SIZE]; 48 49 /* adjust key size (zero padded buffer) if necessary */ 50 if (AES_128_KEY_SIZE > key_size) { 51 memcpy(keybuf, key_data, key_size); 52 memset((keybuf + key_size), 0, 53 (AES_128_KEY_SIZE - key_size)); 54 key_data = keybuf; 55 } 56 57 if (!(ctx = CMAC_CTX_new())) { 58 msyslog(LOG_ERR, "make_mac: CMAC %s CTX new failed.", CMAC); 59 } 60 else if (!CMAC_Init(ctx, key_data, AES_128_KEY_SIZE, 61 EVP_aes_128_cbc(), NULL)) { 62 msyslog(LOG_ERR, "make_mac: CMAC %s Init failed.", CMAC); 63 } 64 else if (!CMAC_Update(ctx, pkt_data, (size_t)pkt_size)) { 65 msyslog(LOG_ERR, "make_mac: CMAC %s Update failed.", CMAC); 66 } 67 else if (!CMAC_Final(ctx, digest, &slen)) { 68 msyslog(LOG_ERR, "make_mac: CMAC %s Final failed.", CMAC); 69 slen = 0; 70 } 71 len = (u_int)slen; 72 73 CMAC_CTX_cleanup(ctx); 74 /* Test our AES-128-CMAC implementation */ 75 76 } else /* MD5 MAC handling */ 77 #endif 78 { 79 EVP_MD_CTX * ctx; 80 81 if (!(ctx = EVP_MD_CTX_new())) { 82 msyslog(LOG_ERR, "make_mac: MAC %s Digest CTX new failed.", 83 macname); 84 goto mac_fail; 85 } 86 #ifdef OPENSSL /* OpenSSL 1 supports return codes 0 fail, 1 okay */ 87 # ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 88 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 89 # endif 90 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would 91 * kill the flags! */ 92 if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(key_type), NULL)) { 93 msyslog(LOG_ERR, "make_mac: MAC %s Digest Init failed.", 94 macname); 95 goto mac_fail; 96 } 97 if (!EVP_DigestUpdate(ctx, key_data, key_size)) { 98 msyslog(LOG_ERR, "make_mac: MAC %s Digest Update key failed.", 99 macname); 100 goto mac_fail; 101 } 102 if (!EVP_DigestUpdate(ctx, pkt_data, pkt_size)) { 103 msyslog(LOG_ERR, "make_mac: MAC %s Digest Update data failed.", 104 macname); 105 goto mac_fail; 106 } 107 if (!EVP_DigestFinal(ctx, digest, &len)) { 108 msyslog(LOG_ERR, "make_mac: MAC %s Digest Final failed.", 109 macname); 110 len = 0; 111 } 112 #else /* !OPENSSL */ 113 EVP_DigestInit(ctx, EVP_get_digestbynid(key_type)); 114 EVP_DigestUpdate(ctx, key_data, key_size); 115 EVP_DigestUpdate(ctx, pkt_data, pkt_size); 116 EVP_DigestFinal(ctx, digest, &len); 117 #endif 118 mac_fail: 119 EVP_MD_CTX_free(ctx); 120 } 121 122 return len; 123 } 124 125 int 126 make_mac( 127 const void * pkt_data, 128 int pkt_size, 129 int mac_size, 130 Key_T const * cmp_key, 131 void * digest 132 ) 133 { 134 u_int len; 135 u_char dbuf[EVP_MAX_MD_SIZE]; 136 137 if (cmp_key->key_len > 64 || mac_size <= 0) 138 return 0; 139 if (pkt_size % 4 != 0) 140 return 0; 141 142 len = compute_mac(dbuf, cmp_key->typen, 143 pkt_data, (u_int)pkt_size, 144 cmp_key->key_seq, (u_int)cmp_key->key_len); 145 146 147 if (len) { 148 if (len > (u_int)mac_size) 149 len = (u_int)mac_size; 150 memcpy(digest, dbuf, len); 151 } 152 return (int)len; 153 } 154 155 156 /* Generates a md5 digest of the key specified in keyid concatenated with the 157 * ntp packet (exluding the MAC) and compares this digest to the digest in 158 * the packet's MAC. If they're equal this function returns 1 (packet is 159 * authentic) or else 0 (not authentic). 160 */ 161 int 162 auth_md5( 163 void const * pkt_data, 164 int pkt_size, 165 int mac_size, 166 Key_T const * cmp_key 167 ) 168 { 169 u_int len = 0; 170 u_char const * pkt_ptr = pkt_data; 171 u_char dbuf[EVP_MAX_MD_SIZE]; 172 173 if (mac_size <= 0 || (size_t)mac_size > sizeof(dbuf)) 174 return FALSE; 175 176 len = compute_mac(dbuf, cmp_key->typen, 177 pkt_ptr, (u_int)pkt_size, 178 cmp_key->key_seq, (u_int)cmp_key->key_len); 179 180 pkt_ptr += pkt_size + 4; 181 if (len > (u_int)mac_size) 182 len = (u_int)mac_size; 183 184 /* isc_tsmemcmp will be better when its easy to link with. sntp 185 * is a 1-shot program, so snooping for timing attacks is 186 * Harder. 187 */ 188 return ((u_int)mac_size == len) && !memcmp(dbuf, pkt_ptr, len); 189 } 190 191 static int 192 hex_val( 193 unsigned char x 194 ) 195 { 196 int val; 197 198 if ('0' <= x && x <= '9') 199 val = x - '0'; 200 else if ('a' <= x && x <= 'f') 201 val = x - 'a' + 0xa; 202 else if ('A' <= x && x <= 'F') 203 val = x - 'A' + 0xA; 204 else 205 val = -1; 206 207 return val; 208 } 209 210 /* Load keys from the specified keyfile into the key structures. 211 * Returns -1 if the reading failed, otherwise it returns the 212 * number of keys it read 213 */ 214 int 215 auth_init( 216 const char *keyfile, 217 struct key **keys 218 ) 219 { 220 FILE *keyf = fopen(keyfile, "r"); 221 struct key *prev = NULL; 222 int scan_cnt, line_cnt = 1; 223 char kbuf[200]; 224 char keystring[129]; 225 226 /* HMS: Is it OK to do this later, after we know we have a key file? */ 227 INIT_SSL(); 228 229 if (keyf == NULL) { 230 if (debug) 231 printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 232 return -1; 233 } 234 if (feof(keyf)) { 235 if (debug) 236 printf("sntp auth_init: Key file %s is empty!\n", keyfile); 237 fclose(keyf); 238 return -1; 239 } 240 key_cnt = 0; 241 while (!feof(keyf)) { 242 char * octothorpe; 243 struct key *act; 244 int goodline = 0; 245 246 if (NULL == fgets(kbuf, sizeof(kbuf), keyf)) 247 continue; 248 249 kbuf[sizeof(kbuf) - 1] = '\0'; 250 octothorpe = strchr(kbuf, '#'); 251 if (octothorpe) 252 *octothorpe = '\0'; 253 act = emalloc(sizeof(*act)); 254 /* keep width 15 = sizeof struct key.typen - 1 synced */ 255 scan_cnt = sscanf(kbuf, "%d %15s %128s", 256 &act->key_id, act->typen, keystring); 257 if (scan_cnt == 3) { 258 int len = strlen(keystring); 259 goodline = 1; /* assume best for now */ 260 if (len <= 20) { 261 act->key_len = len; 262 memcpy(act->key_seq, keystring, len + 1); 263 } else if ((len & 1) != 0) { 264 goodline = 0; /* it's bad */ 265 } else { 266 int j; 267 act->key_len = len >> 1; 268 for (j = 0; j < len; j+=2) { 269 int val; 270 val = (hex_val(keystring[j]) << 4) | 271 hex_val(keystring[j+1]); 272 if (val < 0) { 273 goodline = 0; /* it's bad */ 274 break; 275 } 276 act->key_seq[j>>1] = (char)val; 277 } 278 } 279 act->typei = keytype_from_text(act->typen, NULL); 280 if (0 == act->typei) { 281 printf("%s: line %d: key %d, %s not supported - ignoring\n", 282 keyfile, line_cnt, 283 act->key_id, act->typen); 284 goodline = 0; /* it's bad */ 285 } 286 } 287 if (goodline) { 288 act->next = NULL; 289 if (NULL == prev) 290 *keys = act; 291 else 292 prev->next = act; 293 prev = act; 294 key_cnt++; 295 } else { 296 if (debug) { 297 printf("auth_init: scanf %d items, skipping line %d.", 298 scan_cnt, line_cnt); 299 } 300 free(act); 301 } 302 line_cnt++; 303 } 304 fclose(keyf); 305 306 key_ptr = *keys; 307 return key_cnt; 308 } 309 310 /* Looks for the key with keyid key_id and sets the d_key pointer to the 311 * address of the key. If no matching key is found the pointer is not touched. 312 */ 313 void 314 get_key( 315 int key_id, 316 struct key **d_key 317 ) 318 { 319 struct key *itr_key; 320 321 if (key_cnt == 0) 322 return; 323 for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) { 324 if (itr_key->key_id == key_id) { 325 *d_key = itr_key; 326 break; 327 } 328 } 329 return; 330 } 331