1 /* $NetBSD: crypto.c,v 1.1.1.1 2009/12/13 16:57:10 kardel Exp $ */ 2 3 #include "crypto.h" 4 5 struct key *key_ptr; 6 int key_cnt = 0; 7 8 /* Generates a md5 digest of the ntp packet (exluding the MAC) concatinated 9 * with the key specified in keyid and compares this digest to the digest in 10 * the packet's MAC. If they're equal this function returns 1 (packet is 11 * authentic) or else 0 (not authentic). 12 */ 13 int 14 auth_md5( 15 char *pkt_data, 16 int mac_size, 17 struct key *cmp_key 18 ) 19 { 20 register int a; 21 char digest[16]; 22 MD5_CTX ctx; 23 char *digest_data; 24 25 if (cmp_key->type != 'M') 26 return -1; 27 28 MD5Init(&ctx); 29 30 digest_data = emalloc(sizeof(char) * (LEN_PKT_NOMAC + cmp_key->key_len)); 31 32 for (a = 0; a < LEN_PKT_NOMAC; a++) 33 digest_data[a] = pkt_data[a]; 34 35 for (a = 0; a < cmp_key->key_len; a++) 36 digest_data[LEN_PKT_NOMAC + a] = cmp_key->key_seq[a]; 37 38 MD5Update(&ctx, (u_char *)digest_data, LEN_PKT_NOMAC + cmp_key->key_len); 39 MD5Final((u_char *)digest, &ctx); 40 41 free(digest_data); 42 43 for (a = 0; a < 16; a++) 44 if (digest[a] != pkt_data[LEN_PKT_MAC + a]) 45 return 0; 46 47 return 1; 48 } 49 50 /* Load keys from the specified keyfile into the key structures. 51 * Returns -1 if the reading failed, otherwise it returns the 52 * number of keys it read 53 */ 54 int 55 auth_init( 56 const char *keyfile, 57 struct key **keys 58 ) 59 { 60 FILE *keyf = fopen(keyfile, "r"); 61 struct key *prev = NULL; 62 register int a, line_limit; 63 int scan_cnt, line_cnt = 0; 64 char kbuf[96]; 65 66 if (keyf == NULL) { 67 if (ENABLED_OPT(NORMALVERBOSE)) 68 printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile); 69 70 return -1; 71 } 72 73 line_cnt = 0; 74 75 if (feof(keyf)) { 76 if (ENABLED_OPT(NORMALVERBOSE)) 77 printf("sntp auth_init: Key file %s is empty!\n", keyfile); 78 fclose(keyf); 79 80 return -1; 81 } 82 83 while (!feof(keyf)) { 84 struct key *act = emalloc(sizeof(struct key)); 85 line_limit = 0; 86 87 fgets(kbuf, sizeof(kbuf), keyf); 88 89 for (a = 0; a < strlen(kbuf) && a < sizeof(kbuf); a++) { 90 if (kbuf[a] == '#') { 91 line_limit = a; 92 break; 93 } 94 } 95 96 if (line_limit != 0) 97 kbuf[line_limit] = '\0'; 98 99 #ifdef DEBUG 100 printf("sntp auth_init: fgets: %s", kbuf); 101 #endif 102 103 104 if ((scan_cnt = sscanf(kbuf, "%i %c %16s", &act->key_id, &act->type, act->key_seq)) == 3) { 105 act->key_len = strlen(act->key_seq); 106 act->next = NULL; 107 108 if (NULL == prev) 109 *keys = act; 110 else 111 prev->next = act; 112 prev = act; 113 114 key_cnt++; 115 116 #ifdef DEBUG 117 printf("sntp auth_init: key_id %i type %c with key %s\n", act->key_id, act->type, act->key_seq); 118 #endif 119 } else { 120 #ifdef DEBUG 121 printf("sntp auth_init: scanf read %i items, doesn't look good, skipping line %i.\n", scan_cnt, line_cnt); 122 #endif 123 124 free(act); 125 } 126 127 line_cnt++; 128 } 129 130 fclose(keyf); 131 132 #ifdef DEBUG 133 STDLINE 134 printf("sntp auth_init: Read %i keys from file %s:\n", line_cnt, keyfile); 135 136 { 137 struct key *kptr = *keys; 138 139 for (a = 0; a < key_cnt; a++) { 140 printf("key_id %i type %c with key %s (key length: %i)\n", 141 kptr->key_id, kptr->type, kptr->key_seq, kptr->key_len); 142 kptr = kptr->next; 143 } 144 } 145 STDLINE 146 #endif 147 148 key_cnt = line_cnt; 149 key_ptr = *keys; 150 151 return line_cnt; 152 } 153 154 /* Looks for the key with keyid key_id and sets the d_key pointer to the 155 * address of the key. If no matching key is found the pointer is not touched. 156 */ 157 void 158 get_key( 159 int key_id, 160 struct key **d_key 161 ) 162 { 163 register int a; 164 struct key *itr_key = key_ptr; 165 166 if (key_cnt == 0) 167 return; 168 169 for (a = 0; a < key_cnt && itr_key != NULL; a++) { 170 if (itr_key->key_id == key_id) { 171 *d_key = itr_key; 172 return; 173 } 174 } 175 176 return; 177 } 178