1 /*-
2  * Copyright 2013 Alexander Peslyak
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted.
7  *
8  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
9  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
11  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
12  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18  * SUCH DAMAGE.
19  */
20 
21 #ifdef HAVE_SYS_MMAN_H
22 #include <sys/mman.h>
23 #endif
24 #include <errno.h>
25 #include <stdlib.h>
26 
27 #include "crypto_scrypt.h"
28 #include "runtime.h"
29 
30 #if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
31 # define MAP_ANON MAP_ANONYMOUS
32 #endif
33 #ifndef MAP_NOCORE
34 # define MAP_NOCORE 0
35 #endif
36 #ifndef MAP_POPULATE
37 # define MAP_POPULATE 0
38 #endif
39 
40 void *
alloc_region(escrypt_region_t * region,size_t size)41 alloc_region(escrypt_region_t *region, size_t size)
42 {
43     uint8_t *base, *aligned;
44 #if defined(MAP_ANON) && defined(HAVE_MMAP)
45     if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
46                                  MAP_ANON | MAP_PRIVATE | MAP_NOCORE | MAP_POPULATE,
47                                  -1, 0)) == MAP_FAILED) {
48         base = NULL; /* LCOV_EXCL_LINE */
49     }                /* LCOV_EXCL_LINE */
50     aligned  = base;
51 #elif defined(HAVE_POSIX_MEMALIGN)
52     if ((errno = posix_memalign((void **) &base, 64, size)) != 0) {
53         base = NULL;
54     }
55     aligned = base;
56 #else
57     base = aligned = NULL;
58     if (size + 63 < size) {
59         errno = ENOMEM;
60     } else if ((base = (uint8_t *) malloc(size + 63)) != NULL) {
61         aligned = base + 63;
62         aligned -= (uintptr_t) aligned & 63;
63     }
64 #endif
65     region->base    = base;
66     region->aligned = aligned;
67     region->size    = base ? size : 0;
68 
69     return aligned;
70 }
71 
72 static inline void
init_region(escrypt_region_t * region)73 init_region(escrypt_region_t *region)
74 {
75     region->base = region->aligned = NULL;
76     region->size                   = 0;
77 }
78 
79 int
free_region(escrypt_region_t * region)80 free_region(escrypt_region_t *region)
81 {
82     if (region->base) {
83 #if defined(MAP_ANON) && defined(HAVE_MMAP)
84         if (munmap(region->base, region->size)) {
85             return -1; /* LCOV_EXCL_LINE */
86         }
87 #else
88         free(region->base);
89 #endif
90     }
91     init_region(region);
92 
93     return 0;
94 }
95 
96 int
escrypt_init_local(escrypt_local_t * local)97 escrypt_init_local(escrypt_local_t *local)
98 {
99     init_region(local);
100 
101     return 0;
102 }
103 
104 int
escrypt_free_local(escrypt_local_t * local)105 escrypt_free_local(escrypt_local_t *local)
106 {
107     return free_region(local);
108 }
109