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