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