/src/relic/src/bn/relic_bn_mem.c
Line | Count | Source |
1 | | /* |
2 | | * RELIC is an Efficient LIbrary for Cryptography |
3 | | * Copyright (c) 2009 RELIC Authors |
4 | | * |
5 | | * This file is part of RELIC. RELIC is legal property of its developers, |
6 | | * whose names are not listed here. Please refer to the COPYRIGHT file |
7 | | * for contact information. |
8 | | * |
9 | | * RELIC is free software; you can redistribute it and/or modify it under the |
10 | | * terms of the version 2.1 (or later) of the GNU Lesser General Public License |
11 | | * as published by the Free Software Foundation; or version 2.0 of the Apache |
12 | | * License as published by the Apache Software Foundation. See the LICENSE files |
13 | | * for more details. |
14 | | * |
15 | | * RELIC is distributed in the hope that it will be useful, but WITHOUT ANY |
16 | | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
17 | | * A PARTICULAR PURPOSE. See the LICENSE files for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public or the |
20 | | * Apache License along with RELIC. If not, see <https://www.gnu.org/licenses/> |
21 | | * or <https://www.apache.org/licenses/>. |
22 | | */ |
23 | | |
24 | | /** |
25 | | * @file |
26 | | * |
27 | | * Implementation of the multiple precision integer memory management routines. |
28 | | * |
29 | | * @ingroup bn |
30 | | */ |
31 | | |
32 | | #include <errno.h> |
33 | | |
34 | | #if ALLOC != AUTO |
35 | | #include <malloc.h> |
36 | | #endif |
37 | | |
38 | | #include "relic_core.h" |
39 | | |
40 | | /*============================================================================*/ |
41 | | /* Public definitions */ |
42 | | /*============================================================================*/ |
43 | | |
44 | 39.2M | void bn_make(bn_t a, size_t digits) { |
45 | 39.2M | if (digits < 0) { |
46 | 0 | RLC_THROW(ERR_NO_VALID); |
47 | 0 | } |
48 | | /* Allocate at least one digit. */ |
49 | 39.2M | digits = RLC_MAX(digits, 1); |
50 | | |
51 | 39.2M | #if ALLOC == DYNAMIC |
52 | 39.2M | if (digits % RLC_BN_SIZE != 0) { |
53 | | /* Pad the number of digits to a multiple of the block. */ |
54 | 33.6M | digits += (RLC_BN_SIZE - digits % RLC_BN_SIZE); |
55 | 33.6M | } |
56 | | |
57 | 39.2M | if (a != NULL) { |
58 | 39.2M | a->dp = NULL; |
59 | 39.2M | #if ALIGN == 1 |
60 | 39.2M | a->dp = (dig_t *)malloc(digits * sizeof(dig_t)); |
61 | | #elif OPSYS == WINDOWS |
62 | | a->dp = _aligned_malloc(digits * sizeof(dig_t), ALIGN); |
63 | | #else |
64 | | int r = posix_memalign((void **)&a->dp, ALIGN, digits * sizeof(dig_t)); |
65 | | if (r == ENOMEM) { |
66 | | RLC_THROW(ERR_NO_MEMORY); |
67 | | } |
68 | | if (r == EINVAL) { |
69 | | RLC_THROW(ERR_NO_VALID); |
70 | | } |
71 | | #endif /* ALIGN */ |
72 | 39.2M | } |
73 | | |
74 | 39.2M | if (a->dp == NULL) { |
75 | 0 | free((void *)a); |
76 | 0 | RLC_THROW(ERR_NO_MEMORY); |
77 | 0 | } |
78 | | #else |
79 | | /* Verify if the number of digits is sane. */ |
80 | | if (digits > RLC_BN_SIZE) { |
81 | | RLC_THROW(ERR_NO_PRECI); |
82 | | return; |
83 | | } else { |
84 | | digits = RLC_BN_SIZE; |
85 | | } |
86 | | #endif |
87 | 39.2M | if (a != NULL) { |
88 | 39.2M | a->used = 1; |
89 | 39.2M | a->dp[0] = 0; |
90 | 39.2M | a->alloc = digits; |
91 | 39.2M | a->sign = RLC_POS; |
92 | 39.2M | } |
93 | 39.2M | } |
94 | | |
95 | 39.2M | void bn_clean(bn_t a) { |
96 | 39.2M | #if ALLOC == DYNAMIC |
97 | 39.2M | if (a != NULL) { |
98 | 39.2M | if (a->dp != NULL) { |
99 | | #if OPSYS == WINDOWS && ALIGN > 1 |
100 | | _aligned_free(a->dp); |
101 | | #else |
102 | 39.2M | free(a->dp); |
103 | 39.2M | #endif |
104 | 39.2M | a->dp = NULL; |
105 | 39.2M | } |
106 | 39.2M | a->alloc = 0; |
107 | 39.2M | } |
108 | 39.2M | #endif |
109 | 39.2M | if (a != NULL) { |
110 | 39.2M | a->used = 0; |
111 | 39.2M | a->sign = RLC_POS; |
112 | 39.2M | } |
113 | 39.2M | } |
114 | | |
115 | 87.5M | void bn_grow(bn_t a, size_t digits) { |
116 | 87.5M | #if ALLOC == DYNAMIC |
117 | 87.5M | dig_t *t = NULL; |
118 | | |
119 | 87.5M | if (a->alloc < digits) { |
120 | 2.10M | size_t pad = (RLC_BN_SIZE * 2) - (digits % RLC_BN_SIZE); |
121 | | /* Check overflow. */ |
122 | 2.10M | if (digits > SIZE_MAX - pad) { |
123 | 0 | RLC_THROW(ERR_NO_MEMORY); |
124 | 0 | return; |
125 | 0 | } |
126 | | /* At least add RLC_BN_SIZE more digits. */ |
127 | 2.10M | digits += pad; |
128 | 2.10M | t = (dig_t *)realloc(a->dp, (RLC_DIG / 8) * digits); |
129 | 2.10M | if (t == NULL) { |
130 | 63 | RLC_THROW(ERR_NO_MEMORY); |
131 | 63 | return; |
132 | 63 | } |
133 | 2.10M | a->dp = t; |
134 | | /* Set the newly allocated digits to zero. */ |
135 | 2.10M | a->alloc = digits; |
136 | 2.10M | } |
137 | | #elif ALLOC == AUTO |
138 | | if (digits > RLC_BN_SIZE) { |
139 | | RLC_THROW(ERR_NO_PRECI); |
140 | | return; |
141 | | } |
142 | | (void)a; |
143 | | #endif |
144 | 87.5M | } |
145 | | |
146 | 111M | void bn_trim(bn_t a) { |
147 | 111M | if (a->used <= a->alloc) { |
148 | 127M | while (a->used > 0 && a->dp[a->used - 1] == 0) { |
149 | 16.1M | --(a->used); |
150 | 16.1M | } |
151 | | /* Zero can't be negative. */ |
152 | 111M | if (a->used == 0) { |
153 | 861k | a->used = 1; |
154 | 861k | a->dp[0] = 0; |
155 | 861k | a->sign = RLC_POS; |
156 | 861k | } |
157 | 111M | } |
158 | 111M | } |