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 14 struct key *key_ptr; 15 size_t key_cnt = 0; 16 17 typedef struct key Key_T; 18 19 static u_int 20 compute_mac( 21 u_char digest[EVP_MAX_MD_SIZE], 22 char const * macname, 23 void const * pkt_data, 24 u_int pkt_size, 25 void const * key_data, 26 u_int key_size 27 ) 28 { 29 u_int len = 0; 30 #if defined(OPENSSL) && defined(ENABLE_CMAC) 31 size_t slen = 0; 32 #endif 33 int key_type; 34 35 INIT_SSL(); 36 key_type = keytype_from_text(macname, NULL); 37 38 #if defined(OPENSSL) && defined(ENABLE_CMAC) 39 /* Check if CMAC key type specific code required */ 40 if (key_type == NID_cmac) { 41 CMAC_CTX * ctx = NULL; 42 u_char keybuf[AES_128_KEY_SIZE]; 43 44 /* adjust key size (zero padded buffer) if necessary */ 45 if (AES_128_KEY_SIZE > key_size) { 46 memcpy(keybuf, key_data, key_size); 47 memset((keybuf + key_size), 0, 48 (AES_128_KEY_SIZE - key_size)); 49 key_data = keybuf; 50 } 51 52 if (!(ctx = CMAC_CTX_new())) { 53 msyslog(LOG_ERR, "make_mac: CMAC %s CTX new failed.", CMAC); 54 } 55 else if (!CMAC_Init(ctx, key_data, AES_128_KEY_SIZE, 56 EVP_aes_128_cbc(), NULL)) { 57 msyslog(LOG_ERR, "make_mac: CMAC %s Init failed.", CMAC); 58 } 59 else if (!CMAC_Update(ctx, pkt_data, (size_t)pkt_size)) { 60 msyslog(LOG_ERR, "make_mac: CMAC %s Update failed.", CMAC); 61 } 62 else if (!CMAC_Final(ctx, digest, &slen)) { 63 msyslog(LOG_ERR, "make_mac: CMAC %s Final failed.", CMAC); 64 slen = 0; 65 } 66 len = (u_int)slen; 67 68 if (ctx) 69 CMAC_CTX_free(ctx); 70 /* Test our AES-128-CMAC implementation */ 71 72 } else /* MD5 MAC handling */ 73 #endif 74 { 75 EVP_MD_CTX * ctx; 76 77 if (!(ctx = EVP_MD_CTX_new())) { 78 msyslog(LOG_ERR, "make_mac: MAC %s Digest CTX new failed.", 79 macname); 80 goto mac_fail; 81 } 82 #ifdef OPENSSL /* OpenSSL 1 supports return codes 0 fail, 1 okay */ 83 # ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 84 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 85 # endif 86 /* [Bug 3457] DON'T use plain EVP_DigestInit! It would 87 * kill the flags! */ 88 if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(key_type), NULL)) { 89 msyslog(LOG_ERR, "make_mac: MAC %s Digest Init failed.", 90 macname); 91 goto mac_fail; 92 } 93 if (!EVP_DigestUpdate(ctx, key_data, key_size)) { 94 msyslog(LOG_ERR, "make_mac: MAC %s Digest Update key failed.", 95 macname); 96 goto mac_fail; 97 } 98 if (!EVP_DigestUpdate(ctx, pkt_data, pkt_size)) { 99 msyslog(LOG_ERR, "make_mac: MAC %s Digest Update data failed.", 100 macname); 101 goto mac_fail; 102 } 103 if (!EVP_DigestFinal(ctx, digest, &len)) { 104 msyslog(LOG_ERR, "make_mac: MAC %s Digest Final failed.", 105 macname); 106 len = 0; 107 } 108 #else /* !OPENSSL */ 109 (void)key_type; /* unused, so try to prevent compiler from croaks */ 110 if (!EVP_DigestInit(ctx, EVP_get_digestbynid(key_type))) { 111 msyslog(LOG_ERR, "make_mac: MAC MD5 Digest Init failed."); 112 goto mac_fail; 113 } 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