1 /*  libGringotts - generic data encoding (crypto+compression) library
2  *  (c) 2002, Germano Rizzo <mano@pluto.linux.it>
3  *
4  *  libgrg_utils.c - utility functions for libgringotts
5  *  Author: Germano Rizzo
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #include "config.h"
23 #include "libgringotts.h"
24 #include "libgrg_crypt.h"
25 #include "libgrg_structs.h"
26 
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <time.h>
32 #include <math.h>
33 #include <ctype.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <sys/mman.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/file.h>
40 
41 #include <mhash.h>
42 
43 // Basically, the following 2 functions are the adaptation of string.h
44 // functions for byte sequences. Strings are byte sequence that are
45 // \0-terminated; in this case, this is dangerous, because a \0 can
46 // occour _inside_ the very sequence. Of course, there's no way to tell
47 // how long the sequence is, other than "remembering" it, and passing it
48 // to the functions.
49 
50 /**
51  * grg_memdup
52  * @src: the source
53  * @len: its length
54  *
55  * Duplicates a byte sequence into a new one
56  *
57  * Returns: a newly allocated (to free() afterwards) byte sequence
58  */
59 unsigned char *
grg_memdup(const unsigned char * src,long len)60 grg_memdup (const unsigned char *src, long len)
61 {
62 	unsigned char *ret;
63 
64 	if (!src || !len)
65 		return NULL;
66 
67 	ret = (unsigned char *) malloc (len);
68 
69 	if (ret)
70 		memcpy (ret, src, len);
71 
72 	return ret;
73 }
74 
75 /**
76  * grg_memconcat:
77  * @count: the number of byte sequences to concatenate
78  * @src1: the first byte sequence to concatenate
79  * @len1: the length of the first sequence
80  * @...: the other sequences/lengths
81  *
82  * Concatenates some byte sequences
83  *
84  * Returns: a newly allocated (to free() afterwards) byte sequence
85  */
86 unsigned char *
grg_memconcat(const int count,...)87 grg_memconcat (const int count, ...)
88 {
89 	va_list ap;
90 	unsigned char *ret, *tmp, *strings[count];
91 	int dim[count], i, dimtot = 0;
92 
93 	if (count < 1)
94 		return NULL;
95 
96 	va_start (ap, count);
97 
98 	for (i = 0; i < count; i++)
99 	{
100 		strings[i] = va_arg (ap, unsigned char *);
101 		dim[i] = va_arg (ap, int);
102 		dimtot += dim[i];
103 	}
104 
105 	if (!dimtot)
106 		return NULL;
107 
108 	ret = (unsigned char *) malloc (dimtot);
109 	if (!ret)
110 		return NULL;
111 
112 	tmp = ret;
113 	for (i = 0; i < count; i++)
114 	{
115 		memcpy (tmp, strings[i], dim[i]);
116 		tmp += dim[i];
117 	}
118 
119 	va_end (ap);
120 
121 	return ret;
122 }
123 
124 /**
125  * grg_get_version:
126  * Returns the version string
127  *
128  * Returns: a newly-allocated string, to be free()'d afterwards
129  */
130 unsigned char *
grg_get_version(void)131 grg_get_version (void)
132 {
133 	return (unsigned char *) strdup (LIBGRG_VERSION);
134 }
135 
136 /**
137  * grg_get_int_version:
138  * Returns the version as a (comparable) integer
139  *
140  * Returns: a positional integer, of the form xxyyzz, for libgringotts version x.y.z
141  */
142 unsigned int
grg_get_int_version(void)143 grg_get_int_version (void)
144 {
145 	char *rem;
146 	unsigned int vers = strtol (LIBGRG_VERSION, &rem, 10) * 10000;
147 	vers += strtol (rem, &rem, 10) * 100;
148 	vers += strtol (rem, NULL, 10);
149 
150 	return vers;
151 }
152 
153 /**
154  * grg_XOR_mem:
155  * @src: the byte sequence to XOR
156  * @src_len: its length
157  * @mask: the byte sequence to XOR the first with. It will be repeated if shorter.
158  * @mask_length: its length
159  *
160  * XORs a byte sequence with another, eventually repeating the latter to match the first.
161  */
162 void
grg_XOR_mem(unsigned char * src,int src_len,unsigned char * mask,int mask_len)163 grg_XOR_mem (unsigned char *src, int src_len, unsigned char *mask,
164 	     int mask_len)
165 {
166 	int i;
167 	for (i = 0; i < src_len; i++)
168 		src[i] ^= mask[i % mask_len];
169 }
170 
171 /**
172  * grg_long2char:
173  * @seed: the long to convert
174  *
175  * Converts a long into four bytes
176  *
177  * Returns: a newly allocated 4-bytes sequence, to free after use
178  */
179 unsigned char *
grg_long2char(const long seed)180 grg_long2char (const long seed)
181 {
182 	unsigned char *ret;
183 	long tmp = seed;
184 	int i;
185 
186 	ret = (unsigned char *) malloc (4);
187 
188 	if (ret)
189 		for (i = 3; i >= 0; i--, tmp >>= 8)
190 			ret[i] = tmp & 0x0ff;
191 
192 	return ret;
193 }
194 
195 /**
196  * grg_char2long:
197  * @seed: the 4-char sequence to convert
198  *
199  * Reverts grg_long2char(), converting back into a long
200  *
201  * Returns: a long
202  */
203 long
grg_char2long(const unsigned char * seed)204 grg_char2long (const unsigned char *seed)
205 {
206 	long ret = 0;
207 	int i;
208 
209 	for (i = 3; i >= 0; i--)
210 		ret |= seed[i] << ((3 - i) * 8);
211 
212 	return ret;
213 }
214 
215 void
grg_rnd_seq_direct(const GRG_CTX gctx,unsigned char * toOverwrite,const unsigned int size)216 grg_rnd_seq_direct (const GRG_CTX gctx, unsigned char *toOverwrite,
217 	const unsigned int size)
218 {
219 	int csize = size;
220 
221 	if (!gctx || !size || !toOverwrite)
222 		return;
223 
224 	if (csize < 0)
225 		csize = strlen (toOverwrite);
226 
227 #ifdef HAVE__DEV_RANDOM
228 	read (gctx->rnd, toOverwrite, csize);
229 #else
230 	int step = sizeof (long int), i;
231 	long int val;
232 
233 	for (i = 0; i < csize; i += step)
234 	{
235 		val = random ();
236 		memcpy (toOverwrite + i, &val, step);
237 	}
238 
239 	for (i -= step; i < csize; i++)
240 		toOverwrite[i] = (random () / 256) % 256;
241 #endif
242 }
243 
244 /**
245  * grg_rnd_seq:
246  * @size: the size of the sequence to generate
247  *
248  * Generates a random sequence of bytes.
249  *
250  * Returns: a newly-allocated byte sequence
251  */
252 unsigned char *
grg_rnd_seq(const GRG_CTX gctx,const unsigned int size)253 grg_rnd_seq (const GRG_CTX gctx, const unsigned int size)
254 {
255 	unsigned char *ret;
256 
257 	if (!gctx || size < 1)
258 		return NULL;
259 
260 	ret = (unsigned char *) malloc (size);
261 
262 	if (!ret)
263 		return NULL;
264 
265 	grg_rnd_seq_direct (gctx, ret, size);
266 
267 	return ret;
268 }
269 
270 /**
271  * grg_rnd_chr:
272  *
273  * Returns a random byte.
274  *
275  * Returns: a random byte.
276  */
277 unsigned char
grg_rnd_chr(const GRG_CTX gctx)278 grg_rnd_chr (const GRG_CTX gctx)
279 {
280 	unsigned char rnd;
281 	if (!gctx)
282 		return 0;
283 #ifdef HAVE__DEV_RANDOM
284 	read (gctx->rnd, &rnd, 1);
285 #else
286 	rnd = (random () / 256) % 256;
287 #endif
288 	return rnd;
289 }
290 
291 /**
292  * grg_free:
293  * @pntr: pointer to the memory to free
294  * @dim: length of the sequence; if -1 it must be NULL-terminated
295  *
296  * Frees a sequence of bytes, overwriting it with random data
297  */
298 void
grg_free(const GRG_CTX gctx,void * alloc_data,const long dim)299 grg_free (const GRG_CTX gctx, void *alloc_data, const long dim)
300 {
301 	char *pntr = (char *) alloc_data;
302 
303 	if (!pntr)
304 		return;
305 
306 	if (gctx)
307 		grg_rnd_seq_direct (gctx, pntr, (dim >= 0) ? dim : strlen (pntr));
308 
309 	free (pntr);
310 }
311 
312 /**
313  * grg_unsafe_free:
314  * @alloc_data: pointer to the memory to free
315  *
316  * Frees a memory segment; wrapper for free(), to behave correctly when NULL
317  * is passed as argument
318  */
319 void
grg_unsafe_free(void * alloc_data)320 grg_unsafe_free (void *alloc_data)
321 {
322 	if (!alloc_data)
323 		return;
324 
325 	free (alloc_data);
326 }
327 
328 /**
329  * grg_ascii_pwd_quality:
330  * @pwd: a non-multibyte string with the password
331  * @pwd_len: the maximum length, to grant a termination. If
332  * negative, the string _must_ be null-terminated
333  *
334  * Calculates an indicative value proportional to the password
335  * "quality". Returns a value from 0 to 1, where 0 is the worst
336  * password (4 char, all numeric), 1 the approximation of 256
337  * bits of real data in the password, or better. The scale is
338  * logarythmic, so it will grow faster for shorter passwords than
339  * for larger ones, since improvements in a scarcely-secure password
340  * are more valuable than improvements in better ones.<br>
341  * Anyway, this should be used only for ASCII-like passwords, null
342  * terminated. If you want to eval more "generic" sequences of
343  * bytes, use grg_file_pwd_quality. If you use multibyte encodings,
344  * you must convert them to your locale encoding before evaluation.
345  *
346  * Returns: a double between 0 and 1, inclusive
347  */
348 double
grg_ascii_pwd_quality(const unsigned char * pwd,const long pwd_len)349 grg_ascii_pwd_quality (const unsigned char *pwd, const long pwd_len)
350 {
351 	int A = FALSE, a = FALSE, n = FALSE, p = FALSE;
352 	long i = 0;
353 	long tmp = (pwd_len < 0) ? LONG_MAX - 1 : pwd_len;
354 	int basin = 0;
355 	double ret;
356 
357 	if (!pwd)
358 		return 0.0;
359 
360 	while ((i < tmp) && (pwd[i] != '\0'))
361 	{
362 
363 		if (islower (pwd[i]))
364 		{
365 			a = TRUE;
366 			i++;
367 			continue;
368 		}
369 
370 		if (isdigit (pwd[i]))
371 		{
372 			n = TRUE;
373 			i++;
374 			continue;
375 		}
376 
377 		if (isupper (pwd[i]))
378 		{
379 			A = TRUE;
380 			i++;
381 			continue;
382 		}
383 
384 		p = TRUE;
385 		i++;
386 	}
387 
388 	if (i < 4)
389 		return 0.0;
390 
391 	if (a)
392 		basin += 26;
393 	if (A)
394 		basin += 26;
395 	if (n)
396 		basin += 10;
397 	if (p)
398 		basin += 32;
399 
400 #undef LOG2
401 #define LOG2(val) \
402 		(log(val)/0.693147)	/* log, basis 2 */
403 #define QVAL(length, num_char) \
404 		(length*LOG2(num_char))	/* number of `real' bits in pwd */
405 #define QMAX	5.545177	//log(256)
406 #define QMIN	2.586840	//log(4*LOG2(10))
407 #define QDIF	2.958337	//QMAX-QMIN
408 
409 	ret = (log (QVAL (i, basin)) - QMIN) / QDIF;
410 
411 #undef LOG2
412 #undef QVAL
413 #undef QMAX
414 #undef QMIN
415 #undef QDIF
416 
417 	if (ret < 0)
418 		return 0.0;
419 	if (ret > 1)
420 		return 1.0;
421 	return ret;
422 }
423 
424 /**
425  * grg_file_pwd_quality:
426  * @pwd_path: the path to the file to use as password
427  *
428  * Calculates an indicative value proportional to the password
429  * "quality", in the case you want to use a file content as a
430  * password. Returns a value from 0 to 1, where 0 is the worst
431  * case (empty file), 1 the approximation of 256 bits of real
432  * data, or better. The scale is linear.
433  *
434  * Returns: a double between 0 and 1, inclusive
435  */
436 double
grg_file_pwd_quality(const unsigned char * pwd_path)437 grg_file_pwd_quality (const unsigned char *pwd_path)
438 {
439 	double ret;
440 	int pdf;
441 
442 	pdf = open (pwd_path, O_RDONLY);
443 
444 	if (pdf < 3)
445 	{
446 		close (pdf);
447 		return 0.0;
448 	}
449 
450 	ret = ((double) (lseek (pdf, 0, SEEK_END))) / 32.0;
451 
452 	close (pdf);
453 
454 	if (ret < 0)
455 		return 0.0;
456 	if (ret > 1)
457 		return 1.0;
458 	return ret;
459 }
460 
461 
462 #define CHAR64(c) \
463 	((c < 0 || c > 127) ? -1 : index_64[c])
464 
465 static const char basis_64[] =
466 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
467 
468 static const char index_64[128] = {
469 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
470 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
471 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
472 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
473 	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
474 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
475 	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
476 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
477 };
478 
479 unsigned char *
grg_encode64(const unsigned char * in,const int inlen,unsigned int * outlen)480 grg_encode64 (const unsigned char *in, const int inlen,
481 	      unsigned int *outlen)
482 {
483 	unsigned char *out, *ret;
484 	unsigned char oval;
485 	unsigned int olen, origlen;
486 
487 	if (!in)
488 		return NULL;
489 
490 	origlen = (inlen >= 0) ? inlen : strlen (in);
491 	olen = (origlen + 2) / 3 * 4 + 1;
492 	out = (unsigned char *) malloc (olen);
493 	if (!out)
494 		return NULL;
495 
496 	ret = out;
497 	if (outlen)
498 		*outlen = olen;
499 
500 	while (origlen >= 3)
501 	{
502 		*out++ = basis_64[in[0] >> 2];
503 		*out++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)];
504 		*out++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
505 		*out++ = basis_64[in[2] & 0x3f];
506 		in += 3;
507 		origlen -= 3;
508 	}
509 	if (origlen > 0)
510 	{
511 		*out++ = basis_64[in[0] >> 2];
512 		oval = (in[0] << 4) & 0x30;
513 		if (origlen > 1)
514 			oval |= in[1] >> 4;
515 		*out++ = basis_64[oval];
516 		*out++ = (origlen < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c];
517 		*out++ = '=';
518 	}
519 
520 	ret[olen - 1] = '\0';
521 
522 	return ret;
523 }
524 
525 unsigned char *
grg_decode64(const unsigned char * in,const int inlen,unsigned int * outlen)526 grg_decode64 (const unsigned char *in, const int inlen,
527 	      unsigned int *outlen)
528 {
529 	unsigned olen, lup, tmpinlen;
530 	int c1, c2, c3, c4;
531 	char *out, *ret;
532 
533 	if (!in)
534 		return NULL;
535 
536 	tmpinlen = (inlen >= 0) ? inlen : strlen (in);
537 
538 	olen = tmpinlen / 4 * 3;
539 	if (in[tmpinlen - 1] == '=')
540 	{
541 		olen--;
542 		if (in[tmpinlen - 2] == '=')
543 			olen--;
544 	}
545 
546 	out = (char *) malloc (olen+1);
547 	if (!out)
548 		return NULL;
549 
550 	ret = out;
551 
552 	if (in[0] == '+' && in[1] == ' ')
553 		in += 2;
554 
555 	if (*in == '\0')
556 		return NULL;
557 
558 	for (lup = 0; lup < tmpinlen / 4; lup++)
559 	{
560 		c1 = in[0];
561 		if (CHAR64 (c1) == -1)
562 			return NULL;
563 		c2 = in[1];
564 		if (CHAR64 (c2) == -1)
565 			return NULL;
566 		c3 = in[2];
567 		if (c3 != '=' && CHAR64 (c3) == -1)
568 			return NULL;
569 		c4 = in[3];
570 		if (c4 != '=' && CHAR64 (c4) == -1)
571 			return NULL;
572 		in += 4;
573 		*out++ = (CHAR64 (c1) << 2) | (CHAR64 (c2) >> 4);
574 		if (c3 != '=')
575 		{
576 			*out++ = ((CHAR64 (c2) << 4) & 0xf0) | (CHAR64 (c3) >>
577 								2);
578 			if (c4 != '=')
579 				*out++ = ((CHAR64 (c3) << 6) & 0xc0) |
580 					CHAR64 (c4);
581 		}
582 	}
583 
584 	if (outlen)
585 		*outlen = olen;
586 
587 	ret[olen] = '\0';
588 
589 	return ret;
590 }
591 
592 int
grg_file_shred(const char * path,const int npasses)593 grg_file_shred (const char *path, const int npasses)
594 {
595 
596 #define SHRED_BLOCK_SIZE	65536
597 
598 	int fd, dim, tmpnpasses, i/* , j */;
599 	struct stat buf;
600 	char *mem;
601 	GRG_CTX gctx;
602 
603 	fd = open (path, O_RDWR);
604 
605 	if (fd < 3)
606 	{
607 		close (fd);
608 		return GRG_SHRED_CANT_OPEN_FILE;
609 	}
610 
611 	tmpnpasses = (npasses > 0) ? npasses : 1;
612 
613 	fstat (fd, &buf);
614 
615 	if (buf.st_nlink > 1)
616 	{
617 		close (fd);
618 		return GRG_SHRED_YET_LINKED;
619 	}
620 
621 	dim = buf.st_size;
622 
623 	mem = mmap (NULL, dim, PROT_WRITE, MAP_SHARED, fd, 0);
624 
625 	if (mem == MAP_FAILED)
626 	{
627 		close (fd);
628 		return GRG_SHRED_CANT_MMAP;
629 	}
630 
631 	gctx = grg_context_initialize_defaults ("GRG");
632 	if (!gctx)
633 	{
634 		close (fd);
635 		return GRG_MEM_ALLOCATION_ERR;
636 	}
637 
638 	for (i = 0; i < tmpnpasses; i++)
639 	{
640 /*		int rem = dim % SHRED_BLOCK_SIZE;
641 
642 		for (j = SHRED_BLOCK_SIZE; j < dim; j += SHRED_BLOCK_SIZE)
643 			grg_rnd_seq_direct (gctx, mem + j - SHRED_BLOCK_SIZE, SHRED_BLOCK_SIZE);
644 		grg_rnd_seq_direct (gctx, mem + dim - rem, rem);
645 */
646 		grg_rnd_seq_direct (gctx, mem, dim);
647 		fsync (fd);
648 	}
649 
650 	munmap (mem, dim);
651 	close (fd);
652 	unlink (path);
653 	grg_context_free (gctx);
654 
655 	sync ();
656 
657 	return 0;
658 }
659