File Coverage

inc/matrixssl-3-9-3-open/core/POSIX/osdep.c
Criterion Covered Total %
statement 59 150 39.3
branch 24 94 25.5
condition n/a
subroutine n/a
pod n/a
total 83 244 34.0


line stmt bran cond sub pod time code
1             /**
2             * @file osdep.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * POSIX layer.
6             * Mac OSX 10.5
7             * Linux
8             */
9             /*
10             * Copyright (c) 2013-2017 INSIDE Secure Corporation
11             * Copyright (c) PeerSec Networks, 2002-2011
12             * All Rights Reserved
13             *
14             * The latest version of this code is available at http://www.matrixssl.org
15             *
16             * This software is open source; you can redistribute it and/or modify
17             * it under the terms of the GNU General Public License as published by
18             * the Free Software Foundation; either version 2 of the License, or
19             * (at your option) any later version.
20             *
21             * This General Public License does NOT permit incorporating this software
22             * into proprietary programs. If you are unable to comply with the GPL, a
23             * commercial license for this software may be purchased from INSIDE at
24             * http://www.insidesecure.com/
25             *
26             * This program is distributed in WITHOUT ANY WARRANTY; without even the
27             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
28             * See the GNU General Public License for more details.
29             *
30             * You should have received a copy of the GNU General Public License
31             * along with this program; if not, write to the Free Software
32             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33             * http://www.gnu.org/copyleft/gpl.html
34             */
35             /******************************************************************************/
36              
37             #include "../coreApi.h"
38             #include "../osdep.h"
39              
40             #ifdef POSIX
41             /******************************************************************************/
42             /*
43             Universal system POSIX headers and then PScore/coreApi.h
44             OS-specific header includes should be added to PScore/osdep.h
45             */
46             # include /* abort() */
47             # include /* open(), O_RDONLY, ect... */
48             # include /* close() */
49             # include /* errno */
50             # include /* gettimeofday */
51              
52             /******************************************************************************/
53             /*
54             TIME FUNCTIONS
55             */
56             # ifndef USE_HIGHRES_TIME
57             /******************************************************************************/
58             /*
59             Module open and close
60             */
61             int osdepTimeOpen(void)
62             {
63             psTime_t lt;
64              
65             /*
66             Just a check that gettimeofday is functioning
67             */
68             if (gettimeofday(<, NULL) < 0)
69             {
70             return PS_FAILURE;
71             }
72             return PS_SUCCESS;
73             }
74              
75             void osdepTimeClose(void)
76             {
77             }
78              
79             /*
80             PScore Public API implementations
81              
82             This function always returns seconds/ticks AND OPTIONALLY populates
83             whatever psTime_t happens to be on the given platform.
84             */
85             int32 psGetTime(psTime_t *t, void *userPtr)
86             {
87             psTime_t lt;
88              
89             if (t == NULL)
90             {
91             if (gettimeofday(<, NULL) < 0)
92             {
93             return PS_FAILURE;
94             }
95             return lt.tv_sec;
96             }
97              
98             if (gettimeofday(t, NULL) < 0)
99             {
100             return PS_FAILURE;
101             }
102             return t->tv_sec;
103             }
104              
105             int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr)
106             {
107             if (now.tv_usec < then.tv_usec)
108             {
109             now.tv_sec--;
110             now.tv_usec += 1000000; /* borrow 1 second worth of usec */
111             }
112             return (int32) ((now.tv_sec - then.tv_sec) * 1000) +
113             ((now.tv_usec - then.tv_usec) / 1000);
114             }
115              
116             int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr)
117             {
118             /*
119             Time comparison. 1 if 'a' is less than or equal. 0 if 'a' is greater
120             */
121             if (a.tv_sec < b.tv_sec)
122             {
123             return 1;
124             }
125             if (a.tv_sec == b.tv_sec && a.tv_usec <= b.tv_usec)
126             {
127             return 1;
128             }
129             return 0;
130             }
131              
132             # else /* USE_HIGHRES_TIME */
133             /******************************************************************************/
134             # ifdef __APPLE__
135             /* MAC OS X */
136              
137             # include
138              
139             static mach_timebase_info_data_t hiresFreq;
140              
141             int osdepTimeOpen(void)
142             {
143             mach_timebase_info(&hiresFreq);
144             return PS_SUCCESS;
145             }
146              
147             void osdepTimeClose(void)
148             {
149             }
150              
151             int32 psGetTime(psTime_t *t, void *userPtr)
152             {
153             psTime_t lt;
154              
155             if (t == NULL)
156             {
157             t = <
158             }
159             *t = mach_absolute_time();
160             return (int32) ((*t * hiresFreq.numer) / (hiresFreq.denom * 1000000000L));
161             }
162              
163             int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr)
164             {
165             return (int32) (((now - then) * hiresFreq.numer) / (hiresFreq.denom * 1000000));
166             }
167              
168             int64_t psDiffUsecs(psTime_t then, psTime_t now)
169             {
170             return (int64_t) (((now - then) * hiresFreq.numer) / (hiresFreq.denom * 1000));
171             }
172              
173             int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr)
174             {
175             return a <= b ? 1 : 0;
176             }
177              
178             /******************************************************************************/
179             # else /* !APPLE, !tile */
180             /******************************************************************************/
181             /* LINUX */
182 17           int osdepTimeOpen(void)
183             {
184 17           return PS_SUCCESS;
185             }
186              
187 14           void osdepTimeClose(void)
188             {
189 14           }
190              
191 3352           int32 psGetTime(psTime_t *t, void *userPtr)
192             {
193             psTime_t lt;
194              
195 3352 50         if (t == NULL)
196             {
197 0           t = <
198             }
199 3352           clock_gettime(CLOCK_MONOTONIC, t);
200 3352           return t->tv_sec;
201             }
202              
203 2176           int32 psDiffMsecs(psTime_t then, psTime_t now, void *userPtr)
204             {
205 2176 100         if (now.tv_nsec < then.tv_nsec)
206             {
207 411           now.tv_sec--;
208 411           now.tv_nsec += 1000000000L; /* borrow 1 second worth of nsec */
209             }
210 2176           return (int32) ((now.tv_sec - then.tv_sec) * 1000) +
211 2176           ((now.tv_nsec - then.tv_nsec) / 1000000);
212             }
213              
214 0           int64_t psDiffUsecs(psTime_t then, psTime_t now)
215             {
216 0 0         if (now.tv_nsec < then.tv_nsec)
217             {
218 0           now.tv_sec--;
219 0           now.tv_nsec += 1000000000L; /* borrow 1 second worth of nsec */
220             }
221 0           return (int32) ((now.tv_sec - then.tv_sec) * 1000000) +
222 0           ((now.tv_nsec - then.tv_nsec) / 1000);
223             }
224              
225 0           int32 psCompareTime(psTime_t a, psTime_t b, void *userPtr)
226             {
227             /* Time comparison. 1 if 'a' is less than or equal. 0 if 'a' is greater */
228 0 0         if (a.tv_sec < b.tv_sec)
229             {
230 0           return 1;
231             }
232 0 0         if (a.tv_sec == b.tv_sec && a.tv_nsec <= b.tv_nsec)
    0          
233             {
234 0           return 1;
235             }
236 0           return 0;
237             }
238             # endif /* !APPLE */
239              
240             # endif /* USE_HIGHRES_TIME */
241              
242             /******************************************************************************/
243              
244             # ifdef USE_MULTITHREADING
245             /******************************************************************************/
246             /*
247             MUTEX FUNCTIONS
248             */
249             /******************************************************************************/
250              
251             int32_t osdepMutexOpen(void)
252             {
253             return PS_SUCCESS;
254             }
255              
256             void osdepMutexClose(void)
257             {
258             }
259              
260             int32_t psCreateMutex(psMutex_t *mutex, uint32_t flags)
261             {
262             pthread_mutexattr_t attr;
263             int rc;
264              
265             if (flags & ~PS_SHARED)
266             {
267             psErrorInt("psCreateMutex unsupported flag %u\n", flags);
268             return PS_PLATFORM_FAIL;
269             }
270             if ((rc = pthread_mutexattr_init(&attr)) < 0)
271             {
272             psErrorInt("pthread_mutexattr_init failed %d\n", rc);
273             return PS_PLATFORM_FAIL;
274             }
275             if ((flags & PS_SHARED) &&
276             (rc = pthread_mutexattr_setpshared(&attr,
277             PTHREAD_PROCESS_SHARED)) < 0)
278             {
279             pthread_mutexattr_destroy(&attr);
280             psErrorInt("pthread_mutexattr shared failed %d\n", rc);
281             return PS_PLATFORM_FAIL;
282             }
283             if ((rc = pthread_mutex_init(mutex, &attr)) != 0)
284             {
285             pthread_mutexattr_destroy(&attr);
286             psErrorInt("pthread_mutex_init failed %d\n", rc);
287             return PS_PLATFORM_FAIL;
288             }
289             if (pthread_mutexattr_destroy(&attr) != 0)
290             {
291             psTraceCore("pthread_mutexattr_destroy failed\n");
292             }
293             return PS_SUCCESS;
294             }
295              
296             void psLockMutex(psMutex_t *mutex)
297             {
298             if (pthread_mutex_lock(mutex) != 0)
299             {
300             psTraceCore("pthread_mutex_lock failed\n");
301             abort(); /* Catastrophic error: mutex does not work correctly. */
302             }
303             }
304              
305             void psUnlockMutex(psMutex_t *mutex)
306             {
307             if (pthread_mutex_unlock(mutex) != 0)
308             {
309             psTraceCore("pthread_mutex_unlock failed\n");
310             abort(); /* Catastrophic error: mutex does not work correctly. */
311             }
312             }
313              
314             void psDestroyMutex(psMutex_t *mutex)
315             {
316             pthread_mutex_destroy(mutex);
317             }
318             # endif /* USE_MULTITHREADING */
319             /******************************************************************************/
320              
321              
322             /******************************************************************************/
323             /*
324             ENTROPY FUNCTIONS
325             */
326             /******************************************************************************/
327             # define MAX_RAND_READS 1024
328              
329             static int32 urandfd = -1;
330             static int32 randfd = -1;
331             /*
332             Module open and close
333             */
334 17           int osdepEntropyOpen(void)
335             {
336             /*
337             Open /dev/random access non-blocking.
338             */
339 17 50         if ((urandfd = open("/dev/urandom", O_RDONLY)) < 0)
340             {
341 0           psErrorInt("open of urandom failed %d\n", urandfd);
342 0           return PS_PLATFORM_FAIL;
343             }
344             /*
345             For platforms that don't have /dev/random, just assign it to urandom
346             */
347 17 50         if ((randfd = open("/dev/random", O_RDONLY | O_NONBLOCK)) < 0)
348             {
349 0           randfd = urandfd;
350             }
351 17           return PS_SUCCESS;
352             }
353              
354 14           void osdepEntropyClose(void)
355             {
356 14 50         if (randfd != urandfd)
357             {
358 14           close(randfd);
359             }
360 14           close(urandfd);
361 14           }
362              
363             /*
364             PScore Public API implementations
365             */
366 15662           int32 psGetEntropy(unsigned char *bytes, uint32 size, void *userPtr)
367             {
368             /*
369             Read from /dev/random non-blocking first, then from urandom if it would
370             block. Also, handle file closure case and re-open.
371             */
372             int32 rc, sanity, retry, readBytes;
373 15662           unsigned char *where = bytes;
374              
375 15662           sanity = retry = rc = readBytes = 0;
376              
377 15664 50         while (size)
378             {
379 15664 100         if ((rc = read(randfd, where, size)) < 0 || sanity > MAX_RAND_READS)
    50          
380             {
381 15662 50         if (errno == EINTR)
382             {
383 0 0         if (sanity > MAX_RAND_READS)
384             {
385             psTraceCore("psGetEntropy failed randfd sanity\n");
386 0           return PS_PLATFORM_FAIL;
387             }
388 0           sanity++;
389 0           continue;
390             }
391 15662 50         else if (errno == EAGAIN)
392             {
393 15662           break;
394             }
395 0 0         else if (errno == EBADF && retry == 0)
    0          
396             {
397 0           close(randfd);
398 0 0         if ((randfd = open("/dev/random", O_RDONLY | O_NONBLOCK)) < 0)
399             {
400 0           break;
401             }
402 0           retry++;
403 0           continue;
404             }
405             else
406             {
407             break;
408             }
409             }
410 2           readBytes += rc;
411 2           where += rc;
412 2           size -= rc;
413             }
414              
415 15662           sanity = retry = 0;
416 31324 100         while (size)
417             {
418 15662 50         if ((rc = read(urandfd, where, size)) < 0 || sanity > MAX_RAND_READS)
    50          
419             {
420 0 0         if (errno == EINTR)
421             {
422 0 0         if (sanity > MAX_RAND_READS)
423             {
424             psTraceCore("psGetEntropy failed urandfd sanity\n");
425 0           return PS_PLATFORM_FAIL;
426             }
427 0           sanity++;
428 0           continue;
429             }
430 0 0         else if (errno == EBADF && retry == 0)
    0          
431             {
432 0           close(urandfd);
433 0 0         if ((urandfd =
434 0           open("/dev/urandom", O_RDONLY | O_NONBLOCK)) < 0)
435             {
436             psTraceCore("psGetEntropy failed urandom open\n");
437 0           return PS_PLATFORM_FAIL;
438             }
439 0           retry++;
440 0           continue;
441             }
442             else
443             {
444             psTraceIntCore("psGetEntropy fail errno %d\n", errno);
445 0           return PS_PLATFORM_FAIL;
446             }
447             }
448 15662           readBytes += rc;
449 15662           where += rc;
450 15662           size -= rc;
451             }
452 15662           return readBytes;
453             }
454             /******************************************************************************/
455              
456              
457             /******************************************************************************/
458             /*
459             RAW TRACE FUNCTIONS
460             */
461             /******************************************************************************/
462              
463 0           int osdepTraceOpen(void)
464             {
465 0           return PS_SUCCESS;
466             }
467              
468 0           void osdepTraceClose(void)
469             {
470 0           }
471              
472 0           FILE *_psGetTraceFile(void)
473             {
474             static FILE *tracefile = NULL;
475             #ifdef USE_MULTITHREADING
476             static pthread_mutex_t tracefile_mutex = PTHREAD_MUTEX_INITIALIZER;
477             #endif /* USE_MULTITHREADING */
478              
479 0 0         if (tracefile == NULL)
480             {
481             const char *str;
482              
483             #ifdef USE_MULTITHREADING
484             pthread_mutex_lock(&tracefile_mutex);
485             #endif /* USE_MULTITHREADING */
486            
487 0 0         if (tracefile == NULL)
488             {
489 0           str = getenv("PSCORE_DEBUG_FILE");
490 0 0         if (str != NULL)
491             {
492 0           tracefile = fopen(str, "w");
493 0 0         if (!tracefile)
494             {
495 0           fprintf(
496             stderr,
497             "%s: Unable to open file %s, %s.\n",
498             __func__,
499             str,
500             "producing log to standard output");
501 0           tracefile = stdout;
502             }
503             }
504             else
505             {
506 0           str = getenv("PSCORE_DEBUG_FILE_APPEND");
507             }
508              
509 0 0         if (tracefile == NULL && str != NULL)
    0          
510             {
511 0           tracefile = fopen(str, "a");
512 0 0         if (!tracefile)
513             {
514 0           fprintf(
515             stderr,
516             "%s: Unable to open file %s, %s.\n",
517             __func__,
518             str,
519             "producing log to standard output");
520 0           tracefile = stdout;
521             }
522             }
523              
524 0 0         if (tracefile == NULL)
525             {
526             /* Default: output to standard output. */
527 0           tracefile = stdout;
528             }
529             }
530              
531 0 0         if (tracefile)
532             {
533 0           setvbuf(tracefile, NULL, _IONBF, 0);
534             }
535              
536             #ifdef USE_MULTITHREADING
537             pthread_mutex_unlock(&tracefile_mutex);
538             #endif /* USE_MULTITHREADING */
539             }
540 0           return tracefile;
541             }
542              
543 0           void _psTrace(const char *msg)
544             {
545 0           FILE *tracefile = _psGetTraceFile();
546              
547 0 0         if (tracefile)
548             {
549 0           fprintf(tracefile, "%s", msg);
550             }
551 0           }
552              
553             /* message should contain one %s, unless value is NULL */
554 0           void _psTraceStr(const char *message, const char *value)
555             {
556 0           FILE *tracefile = _psGetTraceFile();
557 0 0         if (value)
558             {
559 0 0         if (tracefile)
560             {
561 0           fprintf(tracefile, message, value);
562             }
563             }
564             else
565             {
566 0 0         if (tracefile)
567             {
568 0           fprintf(tracefile, "%s", message);
569             }
570             }
571 0           }
572              
573             /* message should contain one %d */
574 0           void _psTraceInt(const char *message, int32 value)
575             {
576 0           FILE *tracefile = _psGetTraceFile();
577              
578 0 0         if (tracefile)
579             {
580 0           fprintf(tracefile, message, value);
581             }
582 0           }
583              
584             /* message should contain one %p */
585 0           void _psTracePtr(const char *message, const void *value)
586             {
587 0           FILE *tracefile = _psGetTraceFile();
588              
589 0 0         if (tracefile)
590             {
591 0           fprintf(tracefile, message, value);
592             }
593 0           }
594              
595             /******************************************************************************/
596              
597             # ifdef HALT_ON_PS_ERROR
598             /******************************************************************************/
599             /*
600             POSIX - abort() on psError when HALT_ON_PS_ERROR enabled
601             */
602             void osdepBreak(void)
603             {
604             abort();
605             }
606             # endif /* HALT_ON_PS_ERROR */
607              
608              
609             # ifdef MATRIX_USE_FILE_SYSTEM
610             /******************************************************************************/
611             /*
612             FILE APIs
613             */
614             /**
615             Allocate a buffer and read in a file.
616             @note Caller must free 'buf' parameter on success.
617             Callers do not need to free buf on function failure.
618              
619             Two variants: psGetFileBuf takes in a filename, psGetFileBufFp takes in
620             a pointer to an already opened FILE.
621             */
622 934           int32 psGetFileBufFp(psPool_t *pool, FILE *fp, unsigned char **buf,
623             int32 *bufLen)
624             {
625             struct stat f_stat;
626 934           size_t tmp = 0;
627              
628 934 50         if (fstat(fileno(fp), &f_stat) != 0)
629             {
630 0           fclose(fp);
631             psTraceStrCore("Unable to stat %s\n", (char *) fileName);
632 0           return PS_PLATFORM_FAIL;
633             }
634 934           *buf = psMalloc(pool, (size_t) (f_stat.st_size + 1));
635 934 50         if (*buf == NULL)
636             {
637 0           fclose(fp);
638 0           return PS_MEM_FAIL;
639             }
640 934           memset(*buf, 0x0, (size_t) f_stat.st_size + 1);
641              
642 6888 100         while (((tmp = fread(*buf + *bufLen, sizeof(char), 512, fp)) > 0) &&
    50          
643 5954           (*bufLen < f_stat.st_size))
644             {
645 5954           *bufLen += (int32) tmp;
646             }
647 934           fclose(fp);
648 934           return PS_SUCCESS;
649             }
650              
651 936           int32 psGetFileBuf(psPool_t *pool, const char *fileName, unsigned char **buf,
652             int32 *bufLen)
653             {
654             FILE *fp;
655              
656 936           *bufLen = 0;
657 936           *buf = NULL;
658              
659 936 50         if (fileName == NULL)
660             {
661 0           return PS_ARG_FAIL;
662             }
663 936 100         if ((fp = fopen(fileName, "r")) == NULL)
664             {
665             psTraceStrCore("Unable to open %s\n", (char *) fileName);
666 2           return PS_PLATFORM_FAIL;
667             }
668 934           return psGetFileBufFp(pool, fp, buf, bufLen);
669             }
670             # endif /* MATRIX_USE_FILE_SYSTEM */
671             #endif /* POSIX */
672             /******************************************************************************/