Coverage Report

Created: 2024-11-21 07:03

/src/libgcrypt/mpi/mpih-const-time.c
Line
Count
Source (jump to first uncovered line)
1
/* mpih-const-time.c  -  Constant-time MPI helper functions
2
 *      Copyright (C) 2020  g10 Code GmbH
3
 *
4
 * This file is part of Libgcrypt.
5
 *
6
 * Libgcrypt is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as
8
 * published by the Free Software Foundation; either version 2.1 of
9
 * the License, or (at your option) any later version.
10
 *
11
 * Libgcrypt is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
#include <config.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include "mpi-internal.h"
24
#include "g10lib.h"
25
#include "const-time.h"
26
#include "longlong.h"
27
28
#define A_LIMB_1 ((mpi_limb_t)1)
29
30
31
/*
32
 * Return 1 if X > Y and otherwise return 0.
33
 */
34
static inline mpi_limb_t
35
mpih_ct_limb_greater_than (mpi_limb_t x, mpi_limb_t y)
36
4.01G
{
37
4.01G
  mpi_limb_t diff_hi, diff_lo;
38
4.01G
  sub_ddmmss (diff_hi, diff_lo, 0, y, 0, x);
39
4.01G
  (void)diff_lo;
40
4.01G
  return diff_hi >> (BITS_PER_MPI_LIMB - 1);
41
4.01G
}
42
43
44
/*
45
 * Return 1 if X < Y and otherwise return 0.
46
 */
47
static inline mpi_limb_t
48
mpih_ct_limb_less_than (mpi_limb_t x, mpi_limb_t y)
49
3.32G
{
50
3.32G
  return mpih_ct_limb_greater_than (y, x);
51
3.32G
}
52
53
54
/*
55
 *  W = U when OP_ENABLED=1
56
 *  otherwise, W keeps old value
57
 */
58
void
59
_gcry_mpih_set_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
60
                     unsigned long op_enable)
61
8.87M
{
62
  /* Note: dual mask with AND/OR used for EM leakage mitigation */
63
8.87M
  mpi_limb_t mask1 = ct_limb_gen_mask(op_enable);
64
8.87M
  mpi_limb_t mask2 = ct_limb_gen_inv_mask(op_enable);
65
8.87M
  mpi_size_t i;
66
67
66.5M
  for (i = 0; i < usize; i++)
68
57.6M
    {
69
57.6M
      wp[i] = (wp[i] & mask2) | (up[i] & mask1);
70
57.6M
    }
71
8.87M
}
72
73
74
/*
75
 *  W = U + V when OP_ENABLED=1
76
 *  otherwise, W = U
77
 */
78
mpi_limb_t
79
_gcry_mpih_add_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
80
                       mpi_size_t usize, unsigned long op_enable)
81
23.0M
{
82
  /* Note: dual mask with AND/OR used for EM leakage mitigation */
83
23.0M
  mpi_limb_t mask1 = ct_limb_gen_mask(op_enable);
84
23.0M
  mpi_limb_t mask2 = ct_limb_gen_inv_mask(op_enable);
85
23.0M
  mpi_size_t i;
86
23.0M
  mpi_limb_t cy;
87
88
23.0M
  cy = 0;
89
1.16G
  for (i = 0; i < usize; i++)
90
1.14G
    {
91
1.14G
      mpi_limb_t u = up[i];
92
1.14G
      mpi_limb_t x = u + vp[i];
93
1.14G
      mpi_limb_t cy1 = mpih_ct_limb_less_than(x, u);
94
1.14G
      mpi_limb_t cy2;
95
96
1.14G
      x = x + cy;
97
1.14G
      cy2 = mpih_ct_limb_less_than(x, cy);
98
1.14G
      cy = cy1 | cy2;
99
1.14G
      wp[i] = (u & mask2) | (x & mask1);
100
1.14G
    }
101
102
23.0M
  return cy & mask1;
103
23.0M
}
104
105
106
/*
107
 *  W = U - V when OP_ENABLED=1
108
 *  otherwise, W = U
109
 */
110
mpi_limb_t
111
_gcry_mpih_sub_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
112
                       mpi_size_t usize, unsigned long op_enable)
113
14.5M
{
114
  /* Note: dual mask with AND/OR used for EM leakage mitigation */
115
14.5M
  mpi_limb_t mask1 = ct_limb_gen_mask(op_enable);
116
14.5M
  mpi_limb_t mask2 = ct_limb_gen_inv_mask(op_enable);
117
14.5M
  mpi_size_t i;
118
14.5M
  mpi_limb_t cy;
119
120
14.5M
  cy = 0;
121
709M
  for (i = 0; i < usize; i++)
122
694M
    {
123
694M
      mpi_limb_t u = up[i];
124
694M
      mpi_limb_t x = u - vp[i];
125
694M
      mpi_limb_t cy1 = mpih_ct_limb_greater_than(x, u);
126
694M
      mpi_limb_t cy2;
127
128
694M
      cy2 = mpih_ct_limb_less_than(x, cy);
129
694M
      x = x - cy;
130
694M
      cy = cy1 | cy2;
131
694M
      wp[i] = (u & mask2) | (x & mask1);
132
694M
    }
133
134
14.5M
  return cy & mask1;
135
14.5M
}
136
137
138
/*
139
 *  Swap value of U and V when OP_ENABLED=1
140
 *  otherwise, no change
141
 */
142
void
143
_gcry_mpih_swap_cond (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t usize,
144
                      unsigned long op_enable)
145
7.29M
{
146
  /* Note: dual mask with AND/OR used for EM leakage mitigation */
147
7.29M
  mpi_limb_t mask1 = ct_limb_gen_mask(op_enable);
148
7.29M
  mpi_limb_t mask2 = ct_limb_gen_inv_mask(op_enable);
149
7.29M
  mpi_size_t i;
150
151
354M
  for (i = 0; i < usize; i++)
152
347M
    {
153
347M
      mpi_limb_t u = up[i];
154
347M
      mpi_limb_t v = vp[i];
155
347M
      up[i] = (u & mask2) | (v & mask1);
156
347M
      vp[i] = (u & mask1) | (v & mask2);
157
347M
    }
158
7.29M
}
159
160
161
/*
162
 *  W = -U when OP_ENABLED=1
163
 *  otherwise, W = U
164
 */
165
void
166
_gcry_mpih_abs_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
167
                     unsigned long op_enable)
168
7.29M
{
169
  /* Note: dual mask with AND/OR used for EM leakage mitigation */
170
7.29M
  mpi_limb_t mask1 = ct_limb_gen_mask(op_enable);
171
7.29M
  mpi_limb_t mask2 = ct_limb_gen_inv_mask(op_enable);
172
7.29M
  mpi_limb_t cy = op_enable;
173
7.29M
  mpi_size_t i;
174
175
354M
  for (i = 0; i < usize; i++)
176
347M
    {
177
347M
      mpi_limb_t u = up[i];
178
347M
      mpi_limb_t x = ~u + cy;
179
180
347M
      cy = mpih_ct_limb_less_than(x, ~u);
181
347M
      wp[i] = (u & mask2) | (x & mask1);
182
347M
    }
183
7.29M
}
184
185
186
/*
187
 * Allocating memory for W,
188
 * compute W = V % U, then return W
189
 */
190
mpi_ptr_t
191
_gcry_mpih_mod (mpi_ptr_t vp, mpi_size_t vsize,
192
                mpi_ptr_t up, mpi_size_t usize)
193
768
{
194
768
  int secure;
195
768
  mpi_ptr_t rp;
196
768
  mpi_size_t i;
197
198
768
  secure = _gcry_is_secure (vp);
199
768
  rp = mpi_alloc_limb_space (usize, secure);
200
768
  MPN_ZERO (rp, usize);
201
202
1.15M
  for (i = 0; i < vsize * BITS_PER_MPI_LIMB; i++)
203
1.15M
    {
204
1.15M
      unsigned int j = vsize * BITS_PER_MPI_LIMB - 1 - i;
205
1.15M
      unsigned int limbno = j / BITS_PER_MPI_LIMB;
206
1.15M
      unsigned int bitno = j % BITS_PER_MPI_LIMB;
207
1.15M
      mpi_limb_t limb = vp[limbno];
208
1.15M
      unsigned int the_bit = (limb >> bitno) & 1;
209
1.15M
      mpi_limb_t underflow;
210
1.15M
      mpi_limb_t overflow;
211
212
1.15M
      overflow = _gcry_mpih_lshift (rp, rp, usize, 1);
213
1.15M
      rp[0] |= the_bit;
214
215
1.15M
      underflow = _gcry_mpih_sub_n (rp, rp, up, usize);
216
1.15M
      mpih_add_n_cond (rp, rp, up, usize, overflow ^ underflow);
217
1.15M
    }
218
219
768
  return rp;
220
768
}
221
222
int
223
_gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v)
224
6.41k
{
225
6.41k
  int is_all_zero = 1;
226
6.41k
  mpi_size_t i;
227
228
56.9k
  for (i = 1; i < usize; i++)
229
50.5k
    is_all_zero &= mpih_limb_is_zero (up[i]);
230
231
6.41k
  if (is_all_zero)
232
6.41k
    {
233
6.41k
      if (up[0] < v)
234
0
        return -1;
235
6.41k
      else if (up[0] > v)
236
194
        return 1;
237
6.22k
      else
238
6.22k
        return 0;
239
6.41k
    }
240
0
  return 1;
241
6.41k
}