1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer * util.c
3825eb42bSJan Lentfer *
4825eb42bSJan Lentfer * some general memory functions
5825eb42bSJan Lentfer *
6825eb42bSJan Lentfer * a Net::DNS like library for C
7825eb42bSJan Lentfer *
8825eb42bSJan Lentfer * (c) NLnet Labs, 2004-2006
9825eb42bSJan Lentfer *
10825eb42bSJan Lentfer * See the file LICENSE for the license
11825eb42bSJan Lentfer */
12825eb42bSJan Lentfer
13825eb42bSJan Lentfer #include <ldns/config.h>
14825eb42bSJan Lentfer
15825eb42bSJan Lentfer #include <ldns/rdata.h>
16825eb42bSJan Lentfer #include <ldns/rr.h>
17825eb42bSJan Lentfer #include <ldns/util.h>
18825eb42bSJan Lentfer #include <strings.h>
19825eb42bSJan Lentfer #include <stdlib.h>
20825eb42bSJan Lentfer #include <stdio.h>
21825eb42bSJan Lentfer #include <sys/time.h>
22825eb42bSJan Lentfer #include <time.h>
235340022aSzrj #include <ctype.h>
24825eb42bSJan Lentfer
25825eb42bSJan Lentfer #ifdef HAVE_SSL
26825eb42bSJan Lentfer #include <openssl/rand.h>
27825eb42bSJan Lentfer #endif
28825eb42bSJan Lentfer
29825eb42bSJan Lentfer ldns_lookup_table *
ldns_lookup_by_name(ldns_lookup_table * table,const char * name)30825eb42bSJan Lentfer ldns_lookup_by_name(ldns_lookup_table *table, const char *name)
31825eb42bSJan Lentfer {
32825eb42bSJan Lentfer while (table->name != NULL) {
33825eb42bSJan Lentfer if (strcasecmp(name, table->name) == 0)
34825eb42bSJan Lentfer return table;
35825eb42bSJan Lentfer table++;
36825eb42bSJan Lentfer }
37825eb42bSJan Lentfer return NULL;
38825eb42bSJan Lentfer }
39825eb42bSJan Lentfer
40825eb42bSJan Lentfer ldns_lookup_table *
ldns_lookup_by_id(ldns_lookup_table * table,int id)41825eb42bSJan Lentfer ldns_lookup_by_id(ldns_lookup_table *table, int id)
42825eb42bSJan Lentfer {
43825eb42bSJan Lentfer while (table->name != NULL) {
44825eb42bSJan Lentfer if (table->id == id)
45825eb42bSJan Lentfer return table;
46825eb42bSJan Lentfer table++;
47825eb42bSJan Lentfer }
48825eb42bSJan Lentfer return NULL;
49825eb42bSJan Lentfer }
50825eb42bSJan Lentfer
51825eb42bSJan Lentfer int
ldns_get_bit(uint8_t bits[],size_t index)52825eb42bSJan Lentfer ldns_get_bit(uint8_t bits[], size_t index)
53825eb42bSJan Lentfer {
54825eb42bSJan Lentfer /*
55825eb42bSJan Lentfer * The bits are counted from left to right, so bit #0 is the
56825eb42bSJan Lentfer * left most bit.
57825eb42bSJan Lentfer */
58825eb42bSJan Lentfer return (int) (bits[index / 8] & (1 << (7 - index % 8)));
59825eb42bSJan Lentfer }
60825eb42bSJan Lentfer
61825eb42bSJan Lentfer int
ldns_get_bit_r(uint8_t bits[],size_t index)62825eb42bSJan Lentfer ldns_get_bit_r(uint8_t bits[], size_t index)
63825eb42bSJan Lentfer {
64825eb42bSJan Lentfer /*
65825eb42bSJan Lentfer * The bits are counted from right to left, so bit #0 is the
66825eb42bSJan Lentfer * right most bit.
67825eb42bSJan Lentfer */
68825eb42bSJan Lentfer return (int) bits[index / 8] & (1 << (index % 8));
69825eb42bSJan Lentfer }
70825eb42bSJan Lentfer
71825eb42bSJan Lentfer void
ldns_set_bit(uint8_t * byte,int bit_nr,bool value)72825eb42bSJan Lentfer ldns_set_bit(uint8_t *byte, int bit_nr, bool value)
73825eb42bSJan Lentfer {
74d1b2b5caSJohn Marino /*
75d1b2b5caSJohn Marino * The bits are counted from right to left, so bit #0 is the
76d1b2b5caSJohn Marino * right most bit.
77d1b2b5caSJohn Marino */
78825eb42bSJan Lentfer if (bit_nr >= 0 && bit_nr < 8) {
79825eb42bSJan Lentfer if (value) {
80825eb42bSJan Lentfer *byte = *byte | (0x01 << bit_nr);
81825eb42bSJan Lentfer } else {
82fd185f4dSJan Lentfer *byte = *byte & ~(0x01 << bit_nr);
83825eb42bSJan Lentfer }
84825eb42bSJan Lentfer }
85825eb42bSJan Lentfer }
86825eb42bSJan Lentfer
87825eb42bSJan Lentfer int
ldns_hexdigit_to_int(char ch)88825eb42bSJan Lentfer ldns_hexdigit_to_int(char ch)
89825eb42bSJan Lentfer {
90825eb42bSJan Lentfer switch (ch) {
91825eb42bSJan Lentfer case '0': return 0;
92825eb42bSJan Lentfer case '1': return 1;
93825eb42bSJan Lentfer case '2': return 2;
94825eb42bSJan Lentfer case '3': return 3;
95825eb42bSJan Lentfer case '4': return 4;
96825eb42bSJan Lentfer case '5': return 5;
97825eb42bSJan Lentfer case '6': return 6;
98825eb42bSJan Lentfer case '7': return 7;
99825eb42bSJan Lentfer case '8': return 8;
100825eb42bSJan Lentfer case '9': return 9;
101825eb42bSJan Lentfer case 'a': case 'A': return 10;
102825eb42bSJan Lentfer case 'b': case 'B': return 11;
103825eb42bSJan Lentfer case 'c': case 'C': return 12;
104825eb42bSJan Lentfer case 'd': case 'D': return 13;
105825eb42bSJan Lentfer case 'e': case 'E': return 14;
106825eb42bSJan Lentfer case 'f': case 'F': return 15;
107825eb42bSJan Lentfer default:
108825eb42bSJan Lentfer return -1;
109825eb42bSJan Lentfer }
110825eb42bSJan Lentfer }
111825eb42bSJan Lentfer
112825eb42bSJan Lentfer char
ldns_int_to_hexdigit(int i)113825eb42bSJan Lentfer ldns_int_to_hexdigit(int i)
114825eb42bSJan Lentfer {
115825eb42bSJan Lentfer switch (i) {
116825eb42bSJan Lentfer case 0: return '0';
117825eb42bSJan Lentfer case 1: return '1';
118825eb42bSJan Lentfer case 2: return '2';
119825eb42bSJan Lentfer case 3: return '3';
120825eb42bSJan Lentfer case 4: return '4';
121825eb42bSJan Lentfer case 5: return '5';
122825eb42bSJan Lentfer case 6: return '6';
123825eb42bSJan Lentfer case 7: return '7';
124825eb42bSJan Lentfer case 8: return '8';
125825eb42bSJan Lentfer case 9: return '9';
126825eb42bSJan Lentfer case 10: return 'a';
127825eb42bSJan Lentfer case 11: return 'b';
128825eb42bSJan Lentfer case 12: return 'c';
129825eb42bSJan Lentfer case 13: return 'd';
130825eb42bSJan Lentfer case 14: return 'e';
131825eb42bSJan Lentfer case 15: return 'f';
132825eb42bSJan Lentfer default:
133825eb42bSJan Lentfer abort();
134825eb42bSJan Lentfer }
135825eb42bSJan Lentfer }
136825eb42bSJan Lentfer
137825eb42bSJan Lentfer int
ldns_hexstring_to_data(uint8_t * data,const char * str)138825eb42bSJan Lentfer ldns_hexstring_to_data(uint8_t *data, const char *str)
139825eb42bSJan Lentfer {
140825eb42bSJan Lentfer size_t i;
141825eb42bSJan Lentfer
142825eb42bSJan Lentfer if (!str || !data) {
143825eb42bSJan Lentfer return -1;
144825eb42bSJan Lentfer }
145825eb42bSJan Lentfer
146825eb42bSJan Lentfer if (strlen(str) % 2 != 0) {
147825eb42bSJan Lentfer return -2;
148825eb42bSJan Lentfer }
149825eb42bSJan Lentfer
150825eb42bSJan Lentfer for (i = 0; i < strlen(str) / 2; i++) {
151825eb42bSJan Lentfer data[i] =
152825eb42bSJan Lentfer 16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) +
153825eb42bSJan Lentfer (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]);
154825eb42bSJan Lentfer }
155825eb42bSJan Lentfer
156825eb42bSJan Lentfer return (int) i;
157825eb42bSJan Lentfer }
158825eb42bSJan Lentfer
159825eb42bSJan Lentfer const char *
ldns_version(void)160825eb42bSJan Lentfer ldns_version(void)
161825eb42bSJan Lentfer {
162825eb42bSJan Lentfer return (char*)LDNS_VERSION;
163825eb42bSJan Lentfer }
164825eb42bSJan Lentfer
165825eb42bSJan Lentfer /* Number of days per month (except for February in leap years). */
166825eb42bSJan Lentfer static const int mdays[] = {
167825eb42bSJan Lentfer 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
168825eb42bSJan Lentfer };
169825eb42bSJan Lentfer
170b5dedccaSJan Lentfer #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y)))
171b5dedccaSJan Lentfer #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y)))
172b5dedccaSJan Lentfer
173825eb42bSJan Lentfer static int
is_leap_year(int year)174825eb42bSJan Lentfer is_leap_year(int year)
175825eb42bSJan Lentfer {
176b5dedccaSJan Lentfer return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0
177b5dedccaSJan Lentfer || LDNS_MOD(year, 400) == 0);
178825eb42bSJan Lentfer }
179825eb42bSJan Lentfer
180825eb42bSJan Lentfer static int
leap_days(int y1,int y2)181825eb42bSJan Lentfer leap_days(int y1, int y2)
182825eb42bSJan Lentfer {
183825eb42bSJan Lentfer --y1;
184825eb42bSJan Lentfer --y2;
185b5dedccaSJan Lentfer return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) -
186b5dedccaSJan Lentfer (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) +
187b5dedccaSJan Lentfer (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400));
188825eb42bSJan Lentfer }
189825eb42bSJan Lentfer
190825eb42bSJan Lentfer /*
191825eb42bSJan Lentfer * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
192825eb42bSJan Lentfer */
193825eb42bSJan Lentfer time_t
ldns_mktime_from_utc(const struct tm * tm)194d1b2b5caSJohn Marino ldns_mktime_from_utc(const struct tm *tm)
195825eb42bSJan Lentfer {
196825eb42bSJan Lentfer int year = 1900 + tm->tm_year;
197825eb42bSJan Lentfer time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year);
198825eb42bSJan Lentfer time_t hours;
199825eb42bSJan Lentfer time_t minutes;
200825eb42bSJan Lentfer time_t seconds;
201825eb42bSJan Lentfer int i;
202825eb42bSJan Lentfer
203825eb42bSJan Lentfer for (i = 0; i < tm->tm_mon; ++i) {
204825eb42bSJan Lentfer days += mdays[i];
205825eb42bSJan Lentfer }
206825eb42bSJan Lentfer if (tm->tm_mon > 1 && is_leap_year(year)) {
207825eb42bSJan Lentfer ++days;
208825eb42bSJan Lentfer }
209825eb42bSJan Lentfer days += tm->tm_mday - 1;
210825eb42bSJan Lentfer
211825eb42bSJan Lentfer hours = days * 24 + tm->tm_hour;
212825eb42bSJan Lentfer minutes = hours * 60 + tm->tm_min;
213825eb42bSJan Lentfer seconds = minutes * 60 + tm->tm_sec;
214825eb42bSJan Lentfer
215825eb42bSJan Lentfer return seconds;
216825eb42bSJan Lentfer }
217825eb42bSJan Lentfer
218d1b2b5caSJohn Marino time_t
mktime_from_utc(const struct tm * tm)219d1b2b5caSJohn Marino mktime_from_utc(const struct tm *tm)
220d1b2b5caSJohn Marino {
221d1b2b5caSJohn Marino return ldns_mktime_from_utc(tm);
222d1b2b5caSJohn Marino }
223d1b2b5caSJohn Marino
224b5dedccaSJan Lentfer #if SIZEOF_TIME_T <= 4
225b5dedccaSJan Lentfer
226b5dedccaSJan Lentfer static void
ldns_year_and_yday_from_days_since_epoch(int64_t days,struct tm * result)227b5dedccaSJan Lentfer ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result)
228b5dedccaSJan Lentfer {
229b5dedccaSJan Lentfer int year = 1970;
230b5dedccaSJan Lentfer int new_year;
231b5dedccaSJan Lentfer
232b5dedccaSJan Lentfer while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) {
233d1b2b5caSJohn Marino new_year = year + (int) LDNS_DIV(days, 365);
234b5dedccaSJan Lentfer days -= (new_year - year) * 365;
235b5dedccaSJan Lentfer days -= leap_days(year, new_year);
236b5dedccaSJan Lentfer year = new_year;
237b5dedccaSJan Lentfer }
238b5dedccaSJan Lentfer result->tm_year = year;
239b5dedccaSJan Lentfer result->tm_yday = (int) days;
240b5dedccaSJan Lentfer }
241b5dedccaSJan Lentfer
242b5dedccaSJan Lentfer /* Number of days per month in a leap year. */
243b5dedccaSJan Lentfer static const int leap_year_mdays[] = {
244b5dedccaSJan Lentfer 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
245b5dedccaSJan Lentfer };
246b5dedccaSJan Lentfer
247b5dedccaSJan Lentfer static void
ldns_mon_and_mday_from_year_and_yday(struct tm * result)248b5dedccaSJan Lentfer ldns_mon_and_mday_from_year_and_yday(struct tm *result)
249b5dedccaSJan Lentfer {
250b5dedccaSJan Lentfer int idays = result->tm_yday;
251b5dedccaSJan Lentfer const int *mon_lengths = is_leap_year(result->tm_year) ?
252b5dedccaSJan Lentfer leap_year_mdays : mdays;
253b5dedccaSJan Lentfer
254b5dedccaSJan Lentfer result->tm_mon = 0;
255b5dedccaSJan Lentfer while (idays >= mon_lengths[result->tm_mon]) {
256b5dedccaSJan Lentfer idays -= mon_lengths[result->tm_mon++];
257b5dedccaSJan Lentfer }
258b5dedccaSJan Lentfer result->tm_mday = idays + 1;
259b5dedccaSJan Lentfer }
260b5dedccaSJan Lentfer
261b5dedccaSJan Lentfer static void
ldns_wday_from_year_and_yday(struct tm * result)262b5dedccaSJan Lentfer ldns_wday_from_year_and_yday(struct tm *result)
263b5dedccaSJan Lentfer {
264b5dedccaSJan Lentfer result->tm_wday = 4 /* 1-1-1970 was a thursday */
265b5dedccaSJan Lentfer + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7)
266b5dedccaSJan Lentfer + leap_days(1970, result->tm_year)
267b5dedccaSJan Lentfer + result->tm_yday;
268b5dedccaSJan Lentfer result->tm_wday = LDNS_MOD(result->tm_wday, 7);
269b5dedccaSJan Lentfer if (result->tm_wday < 0) {
270b5dedccaSJan Lentfer result->tm_wday += 7;
271b5dedccaSJan Lentfer }
272b5dedccaSJan Lentfer }
273b5dedccaSJan Lentfer
274b5dedccaSJan Lentfer static struct tm *
ldns_gmtime64_r(int64_t clock,struct tm * result)275b5dedccaSJan Lentfer ldns_gmtime64_r(int64_t clock, struct tm *result)
276b5dedccaSJan Lentfer {
277b5dedccaSJan Lentfer result->tm_isdst = 0;
278b5dedccaSJan Lentfer result->tm_sec = (int) LDNS_MOD(clock, 60);
279b5dedccaSJan Lentfer clock = LDNS_DIV(clock, 60);
280b5dedccaSJan Lentfer result->tm_min = (int) LDNS_MOD(clock, 60);
281b5dedccaSJan Lentfer clock = LDNS_DIV(clock, 60);
282b5dedccaSJan Lentfer result->tm_hour = (int) LDNS_MOD(clock, 24);
283b5dedccaSJan Lentfer clock = LDNS_DIV(clock, 24);
284b5dedccaSJan Lentfer
285b5dedccaSJan Lentfer ldns_year_and_yday_from_days_since_epoch(clock, result);
286b5dedccaSJan Lentfer ldns_mon_and_mday_from_year_and_yday(result);
287b5dedccaSJan Lentfer ldns_wday_from_year_and_yday(result);
288b5dedccaSJan Lentfer result->tm_year -= 1900;
289b5dedccaSJan Lentfer
290b5dedccaSJan Lentfer return result;
291b5dedccaSJan Lentfer }
292b5dedccaSJan Lentfer
293b5dedccaSJan Lentfer #endif /* SIZEOF_TIME_T <= 4 */
294b5dedccaSJan Lentfer
295b5dedccaSJan Lentfer static int64_t
ldns_serial_arithmetics_time(int32_t time,time_t now)296*ee791febSAntonio Huete Jimenez ldns_serial_arithmetics_time(int32_t time, time_t now)
297b5dedccaSJan Lentfer {
298*ee791febSAntonio Huete Jimenez /* Casting due to https://github.com/NLnetLabs/ldns/issues/71 */
299*ee791febSAntonio Huete Jimenez int32_t offset = (int32_t) ((uint32_t) time - (uint32_t) now);
300b5dedccaSJan Lentfer return (int64_t) now + offset;
301b5dedccaSJan Lentfer }
302b5dedccaSJan Lentfer
303*ee791febSAntonio Huete Jimenez struct tm *
ldns_serial_arithmetics_gmtime_r(int32_t time,time_t now,struct tm * result)304*ee791febSAntonio Huete Jimenez ldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result)
305*ee791febSAntonio Huete Jimenez {
306*ee791febSAntonio Huete Jimenez #if SIZEOF_TIME_T <= 4
307*ee791febSAntonio Huete Jimenez int64_t secs_since_epoch = ldns_serial_arithmetics_time(time, now);
308*ee791febSAntonio Huete Jimenez return ldns_gmtime64_r(secs_since_epoch, result);
309*ee791febSAntonio Huete Jimenez #else
310*ee791febSAntonio Huete Jimenez time_t secs_since_epoch = ldns_serial_arithmetics_time(time, now);
311*ee791febSAntonio Huete Jimenez return gmtime_r(&secs_since_epoch, result);
312*ee791febSAntonio Huete Jimenez #endif
313*ee791febSAntonio Huete Jimenez }
314b5dedccaSJan Lentfer
315*ee791febSAntonio Huete Jimenez #ifdef ldns_serial_arithmitics_gmtime_r
316*ee791febSAntonio Huete Jimenez #undef ldns_serial_arithmitics_gmtime_r
317*ee791febSAntonio Huete Jimenez #endif
318*ee791febSAntonio Huete Jimenez /* alias function because of previously used wrong spelling */
319b5dedccaSJan Lentfer struct tm *
ldns_serial_arithmitics_gmtime_r(int32_t time,time_t now,struct tm * result)320b5dedccaSJan Lentfer ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result)
321b5dedccaSJan Lentfer {
322*ee791febSAntonio Huete Jimenez return ldns_serial_arithmetics_gmtime_r(time, now, result);
323b5dedccaSJan Lentfer }
324b5dedccaSJan Lentfer
325825eb42bSJan Lentfer /**
326825eb42bSJan Lentfer * Init the random source
327825eb42bSJan Lentfer * applications should call this if they need entropy data within ldns
328825eb42bSJan Lentfer * If openSSL is available, it is automatically seeded from /dev/urandom
329825eb42bSJan Lentfer * or /dev/random
330825eb42bSJan Lentfer *
331825eb42bSJan Lentfer * If you need more entropy, or have no openssl available, this function
332825eb42bSJan Lentfer * MUST be called at the start of the program
333825eb42bSJan Lentfer *
334825eb42bSJan Lentfer * If openssl *is* available, this function just adds more entropy
335825eb42bSJan Lentfer **/
336825eb42bSJan Lentfer int
ldns_init_random(FILE * fd,unsigned int size)337825eb42bSJan Lentfer ldns_init_random(FILE *fd, unsigned int size)
338825eb42bSJan Lentfer {
339825eb42bSJan Lentfer /* if fp is given, seed srandom with data from file
340825eb42bSJan Lentfer otherwise use /dev/urandom */
341825eb42bSJan Lentfer FILE *rand_f;
342825eb42bSJan Lentfer uint8_t *seed;
343825eb42bSJan Lentfer size_t read = 0;
344825eb42bSJan Lentfer unsigned int seed_i;
345825eb42bSJan Lentfer struct timeval tv;
346825eb42bSJan Lentfer
347825eb42bSJan Lentfer /* we'll need at least sizeof(unsigned int) bytes for the
348825eb42bSJan Lentfer standard prng seed */
349825eb42bSJan Lentfer if (size < (unsigned int) sizeof(seed_i)){
350825eb42bSJan Lentfer size = (unsigned int) sizeof(seed_i);
351825eb42bSJan Lentfer }
352825eb42bSJan Lentfer
353825eb42bSJan Lentfer seed = LDNS_XMALLOC(uint8_t, size);
354fd185f4dSJan Lentfer if(!seed) {
355fd185f4dSJan Lentfer return 1;
356fd185f4dSJan Lentfer }
357825eb42bSJan Lentfer
358825eb42bSJan Lentfer if (!fd) {
359825eb42bSJan Lentfer if ((rand_f = fopen("/dev/urandom", "r")) == NULL) {
360825eb42bSJan Lentfer /* no readable /dev/urandom, try /dev/random */
361825eb42bSJan Lentfer if ((rand_f = fopen("/dev/random", "r")) == NULL) {
362825eb42bSJan Lentfer /* no readable /dev/random either, and no entropy
363825eb42bSJan Lentfer source given. we'll have to improvise */
364825eb42bSJan Lentfer for (read = 0; read < size; read++) {
365ac996e71SJan Lentfer gettimeofday(&tv, NULL);
366825eb42bSJan Lentfer seed[read] = (uint8_t) (tv.tv_usec % 256);
367825eb42bSJan Lentfer }
368825eb42bSJan Lentfer } else {
369825eb42bSJan Lentfer read = fread(seed, 1, size, rand_f);
370825eb42bSJan Lentfer }
371825eb42bSJan Lentfer } else {
372825eb42bSJan Lentfer read = fread(seed, 1, size, rand_f);
373825eb42bSJan Lentfer }
374825eb42bSJan Lentfer } else {
375825eb42bSJan Lentfer rand_f = fd;
376825eb42bSJan Lentfer read = fread(seed, 1, size, rand_f);
377825eb42bSJan Lentfer }
378825eb42bSJan Lentfer
379825eb42bSJan Lentfer if (read < size) {
380825eb42bSJan Lentfer LDNS_FREE(seed);
381d1b2b5caSJohn Marino if (!fd) fclose(rand_f);
382825eb42bSJan Lentfer return 1;
383825eb42bSJan Lentfer } else {
384825eb42bSJan Lentfer #ifdef HAVE_SSL
385825eb42bSJan Lentfer /* Seed the OpenSSL prng (most systems have it seeded
386825eb42bSJan Lentfer automatically, in that case this call just adds entropy */
387825eb42bSJan Lentfer RAND_seed(seed, (int) size);
388825eb42bSJan Lentfer #else
389825eb42bSJan Lentfer /* Seed the standard prng, only uses the first
390*ee791febSAntonio Huete Jimenez * unsigned sizeof(unsigned int) bytes found in the entropy pool
391825eb42bSJan Lentfer */
392825eb42bSJan Lentfer memcpy(&seed_i, seed, sizeof(seed_i));
393825eb42bSJan Lentfer srandom(seed_i);
394825eb42bSJan Lentfer #endif
395825eb42bSJan Lentfer LDNS_FREE(seed);
396825eb42bSJan Lentfer }
397825eb42bSJan Lentfer
398825eb42bSJan Lentfer if (!fd) {
399ac996e71SJan Lentfer if (rand_f) fclose(rand_f);
400825eb42bSJan Lentfer }
401825eb42bSJan Lentfer
402825eb42bSJan Lentfer return 0;
403825eb42bSJan Lentfer }
404825eb42bSJan Lentfer
405ac996e71SJan Lentfer /**
406ac996e71SJan Lentfer * Get random number.
407ac996e71SJan Lentfer *
408ac996e71SJan Lentfer */
409ac996e71SJan Lentfer uint16_t
ldns_get_random(void)410ac996e71SJan Lentfer ldns_get_random(void)
411ac996e71SJan Lentfer {
412ac996e71SJan Lentfer uint16_t rid = 0;
413ac996e71SJan Lentfer #ifdef HAVE_SSL
414ac996e71SJan Lentfer if (RAND_bytes((unsigned char*)&rid, 2) != 1) {
415ac996e71SJan Lentfer rid = (uint16_t) random();
416ac996e71SJan Lentfer }
417ac996e71SJan Lentfer #else
418ac996e71SJan Lentfer rid = (uint16_t) random();
419ac996e71SJan Lentfer #endif
420ac996e71SJan Lentfer return rid;
421ac996e71SJan Lentfer }
422ac996e71SJan Lentfer
423825eb42bSJan Lentfer /*
424825eb42bSJan Lentfer * BubbleBabble code taken from OpenSSH
425825eb42bSJan Lentfer * Copyright (c) 2001 Carsten Raskgaard. All rights reserved.
426825eb42bSJan Lentfer */
427825eb42bSJan Lentfer char *
ldns_bubblebabble(uint8_t * data,size_t len)428825eb42bSJan Lentfer ldns_bubblebabble(uint8_t *data, size_t len)
429825eb42bSJan Lentfer {
430825eb42bSJan Lentfer char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
431825eb42bSJan Lentfer char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
432825eb42bSJan Lentfer 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
433825eb42bSJan Lentfer size_t i, j = 0, rounds, seed = 1;
434825eb42bSJan Lentfer char *retval;
435825eb42bSJan Lentfer
436825eb42bSJan Lentfer rounds = (len / 2) + 1;
437825eb42bSJan Lentfer retval = LDNS_XMALLOC(char, rounds * 6);
438ac996e71SJan Lentfer if(!retval) return NULL;
439825eb42bSJan Lentfer retval[j++] = 'x';
440825eb42bSJan Lentfer for (i = 0; i < rounds; i++) {
441825eb42bSJan Lentfer size_t idx0, idx1, idx2, idx3, idx4;
442825eb42bSJan Lentfer if ((i + 1 < rounds) || (len % 2 != 0)) {
443825eb42bSJan Lentfer idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) +
444825eb42bSJan Lentfer seed) % 6;
445825eb42bSJan Lentfer idx1 = (((size_t)(data[2 * i])) >> 2) & 15;
446825eb42bSJan Lentfer idx2 = ((((size_t)(data[2 * i])) & 3) +
447825eb42bSJan Lentfer (seed / 6)) % 6;
448825eb42bSJan Lentfer retval[j++] = vowels[idx0];
449825eb42bSJan Lentfer retval[j++] = consonants[idx1];
450825eb42bSJan Lentfer retval[j++] = vowels[idx2];
451825eb42bSJan Lentfer if ((i + 1) < rounds) {
452825eb42bSJan Lentfer idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15;
453825eb42bSJan Lentfer idx4 = (((size_t)(data[(2 * i) + 1]))) & 15;
454825eb42bSJan Lentfer retval[j++] = consonants[idx3];
455825eb42bSJan Lentfer retval[j++] = '-';
456825eb42bSJan Lentfer retval[j++] = consonants[idx4];
457825eb42bSJan Lentfer seed = ((seed * 5) +
458825eb42bSJan Lentfer ((((size_t)(data[2 * i])) * 7) +
459825eb42bSJan Lentfer ((size_t)(data[(2 * i) + 1])))) % 36;
460825eb42bSJan Lentfer }
461825eb42bSJan Lentfer } else {
462825eb42bSJan Lentfer idx0 = seed % 6;
463825eb42bSJan Lentfer idx1 = 16;
464825eb42bSJan Lentfer idx2 = seed / 6;
465825eb42bSJan Lentfer retval[j++] = vowels[idx0];
466825eb42bSJan Lentfer retval[j++] = consonants[idx1];
467825eb42bSJan Lentfer retval[j++] = vowels[idx2];
468825eb42bSJan Lentfer }
469825eb42bSJan Lentfer }
470825eb42bSJan Lentfer retval[j++] = 'x';
471825eb42bSJan Lentfer retval[j++] = '\0';
472825eb42bSJan Lentfer return retval;
473825eb42bSJan Lentfer }
4745340022aSzrj
4755340022aSzrj /*
4765340022aSzrj * For backwards compatibility, because we have always exported this symbol.
4775340022aSzrj */
4785340022aSzrj #ifdef HAVE_B64_NTOP
4795340022aSzrj int ldns_b64_ntop(const uint8_t* src, size_t srclength,
4805340022aSzrj char *target, size_t targsize);
4815340022aSzrj {
4825340022aSzrj return b64_ntop(src, srclength, target, targsize);
4835340022aSzrj }
4845340022aSzrj #endif
4855340022aSzrj
4865340022aSzrj /*
4875340022aSzrj * For backwards compatibility, because we have always exported this symbol.
4885340022aSzrj */
4895340022aSzrj #ifdef HAVE_B64_PTON
ldns_b64_pton(const char * src,uint8_t * target,size_t targsize)4905340022aSzrj int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize)
4915340022aSzrj {
4925340022aSzrj return b64_pton(src, target, targsize);
4935340022aSzrj }
4945340022aSzrj #endif
4955340022aSzrj
4965340022aSzrj
4975340022aSzrj static int
ldns_b32_ntop_base(const uint8_t * src,size_t src_sz,char * dst,size_t dst_sz,bool extended_hex,bool add_padding)4985340022aSzrj ldns_b32_ntop_base(const uint8_t* src, size_t src_sz,
4995340022aSzrj char* dst, size_t dst_sz,
5005340022aSzrj bool extended_hex, bool add_padding)
5015340022aSzrj {
5025340022aSzrj size_t ret_sz;
5035340022aSzrj const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv"
5045340022aSzrj : "abcdefghijklmnopqrstuvwxyz234567";
5055340022aSzrj
5065340022aSzrj size_t c = 0; /* c is used to carry partial base32 character over
5075340022aSzrj * byte boundaries for sizes with a remainder.
5085340022aSzrj * (i.e. src_sz % 5 != 0)
5095340022aSzrj */
5105340022aSzrj
5115340022aSzrj ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz)
5125340022aSzrj : ldns_b32_ntop_calculate_size_no_padding(src_sz);
5135340022aSzrj
5145340022aSzrj /* Do we have enough space? */
5155340022aSzrj if (dst_sz < ret_sz + 1)
5165340022aSzrj return -1;
5175340022aSzrj
5185340022aSzrj /* We know the size; terminate the string */
5195340022aSzrj dst[ret_sz] = '\0';
5205340022aSzrj
5215340022aSzrj /* First process all chunks of five */
5225340022aSzrj while (src_sz >= 5) {
5235340022aSzrj /* 00000... ........ ........ ........ ........ */
5245340022aSzrj dst[0] = b32[(src[0] ) >> 3];
5255340022aSzrj
5265340022aSzrj /* .....111 11...... ........ ........ ........ */
5275340022aSzrj dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6];
5285340022aSzrj
5295340022aSzrj /* ........ ..22222. ........ ........ ........ */
5305340022aSzrj dst[2] = b32[(src[1] & 0x3e) >> 1];
5315340022aSzrj
5325340022aSzrj /* ........ .......3 3333.... ........ ........ */
5335340022aSzrj dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4];
5345340022aSzrj
5355340022aSzrj /* ........ ........ ....4444 4....... ........ */
5365340022aSzrj dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7];
5375340022aSzrj
5385340022aSzrj /* ........ ........ ........ .55555.. ........ */
5395340022aSzrj dst[5] = b32[(src[3] & 0x7c) >> 2];
5405340022aSzrj
5415340022aSzrj /* ........ ........ ........ ......66 666..... */
5425340022aSzrj dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5];
5435340022aSzrj
5445340022aSzrj /* ........ ........ ........ ........ ...77777 */
5455340022aSzrj dst[7] = b32[(src[4] & 0x1f) ];
5465340022aSzrj
5475340022aSzrj src_sz -= 5;
5485340022aSzrj src += 5;
5495340022aSzrj dst += 8;
5505340022aSzrj }
5515340022aSzrj /* Process what remains */
5525340022aSzrj switch (src_sz) {
5535340022aSzrj case 4: /* ........ ........ ........ ......66 666..... */
5545340022aSzrj dst[6] = b32[(src[3] & 0x03) << 3];
5555340022aSzrj
5565340022aSzrj /* ........ ........ ........ .55555.. ........ */
5575340022aSzrj dst[5] = b32[(src[3] & 0x7c) >> 2];
5585340022aSzrj
5595340022aSzrj /* ........ ........ ....4444 4....... ........ */
5605340022aSzrj c = src[3] >> 7 ;
561819dec71SDaniel Fojt /* fallthrough */
5625340022aSzrj case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
5635340022aSzrj
5645340022aSzrj /* ........ .......3 3333.... ........ ........ */
5655340022aSzrj c = src[2] >> 4 ;
566819dec71SDaniel Fojt /* fallthrough */
5675340022aSzrj case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c];
5685340022aSzrj
5695340022aSzrj /* ........ ..22222. ........ ........ ........ */
5705340022aSzrj dst[2] = b32[(src[1] & 0x3e) >> 1];
5715340022aSzrj
5725340022aSzrj /* .....111 11...... ........ ........ ........ */
5735340022aSzrj c = src[1] >> 6 ;
574819dec71SDaniel Fojt /* fallthrough */
5755340022aSzrj case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c];
5765340022aSzrj
5775340022aSzrj /* 00000... ........ ........ ........ ........ */
5785340022aSzrj dst[0] = b32[ src[0] >> 3];
5795340022aSzrj }
5805340022aSzrj /* Add padding */
5815340022aSzrj if (add_padding) {
5825340022aSzrj switch (src_sz) {
5835340022aSzrj case 1: dst[2] = '=';
5845340022aSzrj dst[3] = '=';
585819dec71SDaniel Fojt /* fallthrough */
5865340022aSzrj case 2: dst[4] = '=';
587819dec71SDaniel Fojt /* fallthrough */
5885340022aSzrj case 3: dst[5] = '=';
5895340022aSzrj dst[6] = '=';
590819dec71SDaniel Fojt /* fallthrough */
5915340022aSzrj case 4: dst[7] = '=';
5925340022aSzrj }
5935340022aSzrj }
5945340022aSzrj return (int)ret_sz;
5955340022aSzrj }
5965340022aSzrj
5975340022aSzrj int
ldns_b32_ntop(const uint8_t * src,size_t src_sz,char * dst,size_t dst_sz)5985340022aSzrj ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
5995340022aSzrj {
6005340022aSzrj return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
6015340022aSzrj }
6025340022aSzrj
6035340022aSzrj int
ldns_b32_ntop_extended_hex(const uint8_t * src,size_t src_sz,char * dst,size_t dst_sz)6045340022aSzrj ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
6055340022aSzrj char* dst, size_t dst_sz)
6065340022aSzrj {
6075340022aSzrj return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
6085340022aSzrj }
6095340022aSzrj
6105340022aSzrj #ifndef HAVE_B32_NTOP
6115340022aSzrj
6125340022aSzrj int
b32_ntop(const uint8_t * src,size_t src_sz,char * dst,size_t dst_sz)6135340022aSzrj b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
6145340022aSzrj {
6155340022aSzrj return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
6165340022aSzrj }
6175340022aSzrj
6185340022aSzrj int
b32_ntop_extended_hex(const uint8_t * src,size_t src_sz,char * dst,size_t dst_sz)6195340022aSzrj b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
6205340022aSzrj char* dst, size_t dst_sz)
6215340022aSzrj {
6225340022aSzrj return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
6235340022aSzrj }
6245340022aSzrj
6255340022aSzrj #endif /* ! HAVE_B32_NTOP */
6265340022aSzrj
6275340022aSzrj static int
ldns_b32_pton_base(const char * src,size_t src_sz,uint8_t * dst,size_t dst_sz,bool extended_hex,bool check_padding)6285340022aSzrj ldns_b32_pton_base(const char* src, size_t src_sz,
6295340022aSzrj uint8_t* dst, size_t dst_sz,
6305340022aSzrj bool extended_hex, bool check_padding)
6315340022aSzrj {
6325340022aSzrj size_t i = 0;
6335340022aSzrj char ch = '\0';
6345340022aSzrj uint8_t buf[8];
6355340022aSzrj uint8_t* start = dst;
6365340022aSzrj
6375340022aSzrj while (src_sz) {
6385340022aSzrj /* Collect 8 characters in buf (if possible) */
6395340022aSzrj for (i = 0; i < 8; i++) {
6405340022aSzrj
6415340022aSzrj do {
6425340022aSzrj ch = *src++;
6435340022aSzrj --src_sz;
6445340022aSzrj
6455340022aSzrj } while (isspace((unsigned char)ch) && src_sz > 0);
6465340022aSzrj
6475340022aSzrj if (ch == '=' || ch == '\0')
6485340022aSzrj break;
6495340022aSzrj
6505340022aSzrj else if (extended_hex)
6515340022aSzrj
6525340022aSzrj if (ch >= '0' && ch <= '9')
6535340022aSzrj buf[i] = (uint8_t)ch - '0';
6545340022aSzrj else if (ch >= 'a' && ch <= 'v')
6555340022aSzrj buf[i] = (uint8_t)ch - 'a' + 10;
6565340022aSzrj else if (ch >= 'A' && ch <= 'V')
6575340022aSzrj buf[i] = (uint8_t)ch - 'A' + 10;
6585340022aSzrj else
6595340022aSzrj return -1;
6605340022aSzrj
6615340022aSzrj else if (ch >= 'a' && ch <= 'z')
6625340022aSzrj buf[i] = (uint8_t)ch - 'a';
6635340022aSzrj else if (ch >= 'A' && ch <= 'Z')
6645340022aSzrj buf[i] = (uint8_t)ch - 'A';
6655340022aSzrj else if (ch >= '2' && ch <= '7')
6665340022aSzrj buf[i] = (uint8_t)ch - '2' + 26;
6675340022aSzrj else
6685340022aSzrj return -1;
6695340022aSzrj }
6705340022aSzrj /* Less that 8 characters. We're done. */
6715340022aSzrj if (i < 8)
6725340022aSzrj break;
6735340022aSzrj
6745340022aSzrj /* Enough space available at the destination? */
6755340022aSzrj if (dst_sz < 5)
6765340022aSzrj return -1;
6775340022aSzrj
6785340022aSzrj /* 00000... ........ ........ ........ ........ */
6795340022aSzrj /* .....111 11...... ........ ........ ........ */
6805340022aSzrj dst[0] = buf[0] << 3 | buf[1] >> 2;
6815340022aSzrj
6825340022aSzrj /* .....111 11...... ........ ........ ........ */
6835340022aSzrj /* ........ ..22222. ........ ........ ........ */
6845340022aSzrj /* ........ .......3 3333.... ........ ........ */
6855340022aSzrj dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
6865340022aSzrj
6875340022aSzrj /* ........ .......3 3333.... ........ ........ */
6885340022aSzrj /* ........ ........ ....4444 4....... ........ */
6895340022aSzrj dst[2] = buf[3] << 4 | buf[4] >> 1;
6905340022aSzrj
6915340022aSzrj /* ........ ........ ....4444 4....... ........ */
6925340022aSzrj /* ........ ........ ........ .55555.. ........ */
6935340022aSzrj /* ........ ........ ........ ......66 666..... */
6945340022aSzrj dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
6955340022aSzrj
6965340022aSzrj /* ........ ........ ........ ......66 666..... */
6975340022aSzrj /* ........ ........ ........ ........ ...77777 */
6985340022aSzrj dst[4] = buf[6] << 5 | buf[7];
6995340022aSzrj
7005340022aSzrj dst += 5;
7015340022aSzrj dst_sz -= 5;
7025340022aSzrj }
7035340022aSzrj /* Not ending on a eight byte boundary? */
7045340022aSzrj if (i > 0 && i < 8) {
7055340022aSzrj
7065340022aSzrj /* Enough space available at the destination? */
7075340022aSzrj if (dst_sz < (i + 1) / 2)
7085340022aSzrj return -1;
7095340022aSzrj
7105340022aSzrj switch (i) {
7115340022aSzrj case 7: /* ........ ........ ........ ......66 666..... */
7125340022aSzrj /* ........ ........ ........ .55555.. ........ */
7135340022aSzrj /* ........ ........ ....4444 4....... ........ */
7145340022aSzrj dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
715819dec71SDaniel Fojt /* fallthrough */
7165340022aSzrj
7175340022aSzrj case 5: /* ........ ........ ....4444 4....... ........ */
7185340022aSzrj /* ........ .......3 3333.... ........ ........ */
7195340022aSzrj dst[2] = buf[3] << 4 | buf[4] >> 1;
720819dec71SDaniel Fojt /* fallthrough */
7215340022aSzrj
7225340022aSzrj case 4: /* ........ .......3 3333.... ........ ........ */
7235340022aSzrj /* ........ ..22222. ........ ........ ........ */
7245340022aSzrj /* .....111 11...... ........ ........ ........ */
7255340022aSzrj dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
726819dec71SDaniel Fojt /* fallthrough */
7275340022aSzrj
7285340022aSzrj case 2: /* .....111 11...... ........ ........ ........ */
7295340022aSzrj /* 00000... ........ ........ ........ ........ */
7305340022aSzrj dst[0] = buf[0] << 3 | buf[1] >> 2;
7315340022aSzrj
7325340022aSzrj break;
7335340022aSzrj
7345340022aSzrj default:
7355340022aSzrj return -1;
7365340022aSzrj }
7375340022aSzrj dst += (i + 1) / 2;
7385340022aSzrj
7395340022aSzrj if (check_padding) {
7405340022aSzrj /* Check remaining padding characters */
7415340022aSzrj if (ch != '=')
7425340022aSzrj return -1;
7435340022aSzrj
7445340022aSzrj /* One down, 8 - i - 1 more to come... */
7455340022aSzrj for (i = 8 - i - 1; i > 0; i--) {
7465340022aSzrj
7475340022aSzrj do {
7485340022aSzrj if (src_sz == 0)
7495340022aSzrj return -1;
7505340022aSzrj ch = *src++;
7515340022aSzrj src_sz--;
7525340022aSzrj
7535340022aSzrj } while (isspace((unsigned char)ch));
7545340022aSzrj
7555340022aSzrj if (ch != '=')
7565340022aSzrj return -1;
7575340022aSzrj }
7585340022aSzrj }
7595340022aSzrj }
7605340022aSzrj return dst - start;
7615340022aSzrj }
7625340022aSzrj
7635340022aSzrj int
ldns_b32_pton(const char * src,size_t src_sz,uint8_t * dst,size_t dst_sz)7645340022aSzrj ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
7655340022aSzrj {
7665340022aSzrj return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
7675340022aSzrj }
7685340022aSzrj
7695340022aSzrj int
ldns_b32_pton_extended_hex(const char * src,size_t src_sz,uint8_t * dst,size_t dst_sz)7705340022aSzrj ldns_b32_pton_extended_hex(const char* src, size_t src_sz,
7715340022aSzrj uint8_t* dst, size_t dst_sz)
7725340022aSzrj {
7735340022aSzrj return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
7745340022aSzrj }
7755340022aSzrj
7765340022aSzrj #ifndef HAVE_B32_PTON
7775340022aSzrj
7785340022aSzrj int
b32_pton(const char * src,size_t src_sz,uint8_t * dst,size_t dst_sz)7795340022aSzrj b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
7805340022aSzrj {
7815340022aSzrj return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
7825340022aSzrj }
7835340022aSzrj
7845340022aSzrj int
b32_pton_extended_hex(const char * src,size_t src_sz,uint8_t * dst,size_t dst_sz)7855340022aSzrj b32_pton_extended_hex(const char* src, size_t src_sz,
7865340022aSzrj uint8_t* dst, size_t dst_sz)
7875340022aSzrj {
7885340022aSzrj return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
7895340022aSzrj }
7905340022aSzrj
7915340022aSzrj #endif /* ! HAVE_B32_PTON */
7925340022aSzrj
793