1 /*
2  * Copyright (c) 2018, Henry Corrigan-Gibbs
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 #include <mprio.h>
10 #include <stdlib.h>
11 
12 #include "config.h"
13 #include "mparray.h"
14 #include "share.h"
15 #include "util.h"
16 
17 MPArray
MPArray_new(int len)18 MPArray_new(int len)
19 {
20   SECStatus rv = SECSuccess;
21   MPArray arr = malloc(sizeof *arr);
22   if (!arr)
23     return NULL;
24 
25   arr->data = NULL;
26   arr->len = len;
27 
28   P_CHECKA(arr->data = calloc(len, sizeof(mp_int)));
29 
30   // Initialize these to NULL so that we can figure
31   // out which allocations failed (if any)
32   for (int i = 0; i < len; i++) {
33     MP_DIGITS(&arr->data[i]) = NULL;
34   }
35 
36   for (int i = 0; i < len; i++) {
37     MP_CHECKC(mp_init(&arr->data[i]));
38   }
39 
40 cleanup:
41   if (rv != SECSuccess) {
42     MPArray_clear(arr);
43     return NULL;
44   }
45 
46   return arr;
47 }
48 
49 MPArray
MPArray_new_bool(int len,const bool * data_in)50 MPArray_new_bool(int len, const bool* data_in)
51 {
52   MPArray arr = MPArray_new(len);
53   if (arr == NULL)
54     return NULL;
55 
56   for (int i = 0; i < len; i++) {
57     mp_set(&arr->data[i], data_in[i]);
58   }
59 
60   return arr;
61 }
62 
63 SECStatus
MPArray_resize(MPArray arr,int newlen)64 MPArray_resize(MPArray arr, int newlen)
65 {
66   SECStatus rv = SECSuccess;
67   const int oldlen = arr->len;
68 
69   if (oldlen == newlen)
70     return rv;
71 
72   // TODO: Use realloc for this?
73   mp_int* newdata = calloc(newlen, sizeof(mp_int));
74   if (newdata == NULL)
75     return SECFailure;
76 
77   for (int i = 0; i < newlen; i++) {
78     MP_DIGITS(&newdata[i]) = NULL;
79   }
80 
81   // Initialize new array
82   for (int i = 0; i < newlen; i++) {
83     MP_CHECKC(mp_init(&newdata[i]));
84   }
85 
86   // Copy old data into new array
87   for (int i = 0; i < newlen && i < oldlen; i++) {
88     MP_CHECKC(mp_copy(&arr->data[i], &newdata[i]));
89   }
90 
91   // Free old data
92   for (int i = 0; i < oldlen; i++) {
93     mp_clear(&arr->data[i]);
94   }
95   free(arr->data);
96   arr->data = newdata;
97   arr->len = newlen;
98 
99 cleanup:
100   if (rv != SECSuccess) {
101     for (int i = 0; i < newlen; i++) {
102       mp_clear(&newdata[i]);
103     }
104     free(newdata);
105   }
106 
107   return rv;
108 }
109 
110 MPArray
MPArray_dup(const_MPArray src)111 MPArray_dup(const_MPArray src)
112 {
113   MPArray dst = MPArray_new(src->len);
114   if (!dst)
115     return NULL;
116 
117   SECStatus rv = MPArray_copy(dst, src);
118   if (rv == SECSuccess) {
119     return dst;
120   } else {
121     MPArray_clear(dst);
122     return NULL;
123   }
124 }
125 
126 SECStatus
MPArray_copy(MPArray dst,const_MPArray src)127 MPArray_copy(MPArray dst, const_MPArray src)
128 {
129   if (dst->len != src->len)
130     return SECFailure;
131 
132   for (int i = 0; i < src->len; i++) {
133     if (mp_copy(&src->data[i], &dst->data[i]) != MP_OKAY) {
134       return SECFailure;
135     }
136   }
137 
138   return SECSuccess;
139 }
140 
141 SECStatus
MPArray_set_share(MPArray arrA,MPArray arrB,const_MPArray src,const_PrioConfig cfg)142 MPArray_set_share(MPArray arrA, MPArray arrB, const_MPArray src,
143                   const_PrioConfig cfg)
144 {
145   SECStatus rv = SECSuccess;
146   if (arrA->len != src->len || arrB->len != src->len)
147     return SECFailure;
148 
149   const int len = src->len;
150 
151   for (int i = 0; i < len; i++) {
152     P_CHECK(share_int(cfg, &src->data[i], &arrA->data[i], &arrB->data[i]));
153   }
154 
155   return rv;
156 }
157 
158 void
MPArray_clear(MPArray arr)159 MPArray_clear(MPArray arr)
160 {
161   if (arr == NULL)
162     return;
163 
164   if (arr->data != NULL) {
165     for (int i = 0; i < arr->len; i++) {
166       mp_clear(&arr->data[i]);
167     }
168     free(arr->data);
169   }
170   free(arr);
171 }
172 
173 SECStatus
MPArray_addmod(MPArray dst,const_MPArray to_add,const mp_int * mod)174 MPArray_addmod(MPArray dst, const_MPArray to_add, const mp_int* mod)
175 {
176   if (dst->len != to_add->len)
177     return SECFailure;
178 
179   for (int i = 0; i < dst->len; i++) {
180     MP_CHECK(mp_addmod(&dst->data[i], &to_add->data[i], mod, &dst->data[i]));
181   }
182 
183   return SECSuccess;
184 }
185 
186 bool
MPArray_areEqual(const_MPArray arr1,const_MPArray arr2)187 MPArray_areEqual(const_MPArray arr1, const_MPArray arr2)
188 {
189   if (arr1->len != arr2->len)
190     return false;
191 
192   for (int i = 0; i < arr1->len; i++) {
193     if (mp_cmp(&arr1->data[i], &arr2->data[i]))
194       return false;
195   }
196 
197   return true;
198 }
199