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
40void *
41alloc_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
72static inline void
73init_region(escrypt_region_t *region)
74{
75    region->base = region->aligned = NULL;
76    region->size                   = 0;
77}
78
79int
80free_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
96int
97escrypt_init_local(escrypt_local_t *local)
98{
99    init_region(local);
100
101    return 0;
102}
103
104int
105escrypt_free_local(escrypt_local_t *local)
106{
107    return free_region(local);
108}
109