Coverage Report

Created: 2022-12-08 06:09

/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
26
0
#define A_LIMB_1 ((mpi_limb_t)1)
27
28
/* These variables are used to generate masks from conditional operation
29
 * flag parameters.  Use of volatile prevents compiler optimizations from
30
 * converting AND-masking to conditional branches.  */
31
static volatile mpi_limb_t vzero = 0;
32
static volatile mpi_limb_t vone = 1;
33
34
/*
35
 *  W = U when OP_ENABLED=1
36
 *  otherwise, W keeps old value
37
 */
38
void
39
_gcry_mpih_set_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
40
                     unsigned long op_enable)
41
0
{
42
0
  mpi_size_t i;
43
0
  mpi_limb_t mask1 = vzero - op_enable;
44
0
  mpi_limb_t mask2 = op_enable - vone;
45
46
0
  for (i = 0; i < usize; i++)
47
0
    {
48
0
      wp[i] = (wp[i] & mask2) | (up[i] & mask1);
49
0
    }
50
0
}
51
52
53
/*
54
 *  W = U + V when OP_ENABLED=1
55
 *  otherwise, W = U
56
 */
57
mpi_limb_t
58
_gcry_mpih_add_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
59
                       mpi_size_t usize, unsigned long op_enable)
60
0
{
61
0
  mpi_size_t i;
62
0
  mpi_limb_t cy;
63
0
  mpi_limb_t mask1 = vzero - op_enable;
64
0
  mpi_limb_t mask2 = op_enable - vone;
65
66
0
  cy = 0;
67
0
  for (i = 0; i < usize; i++)
68
0
    {
69
0
      mpi_limb_t u = up[i];
70
0
      mpi_limb_t x = u + vp[i];
71
0
      mpi_limb_t cy1 = x < u;
72
0
      mpi_limb_t cy2;
73
74
0
      x = x + cy;
75
0
      cy2 = x < cy;
76
0
      cy = cy1 | cy2;
77
0
      wp[i] = (u & mask2) | (x & mask1);
78
0
    }
79
80
0
  return cy & mask1;
81
0
}
82
83
84
/*
85
 *  W = U - V when OP_ENABLED=1
86
 *  otherwise, W = U
87
 */
88
mpi_limb_t
89
_gcry_mpih_sub_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
90
                       mpi_size_t usize, unsigned long op_enable)
91
0
{
92
0
  mpi_size_t i;
93
0
  mpi_limb_t cy;
94
0
  mpi_limb_t mask1 = vzero - op_enable;
95
0
  mpi_limb_t mask2 = op_enable - vone;
96
97
0
  cy = 0;
98
0
  for (i = 0; i < usize; i++)
99
0
    {
100
0
      mpi_limb_t u = up[i];
101
0
      mpi_limb_t x = u - vp[i];
102
0
      mpi_limb_t cy1 = x > u;
103
0
      mpi_limb_t cy2;
104
105
0
      cy2 = x < cy;
106
0
      x = x - cy;
107
0
      cy = cy1 | cy2;
108
0
      wp[i] = (u & mask2) | (x & mask1);
109
0
    }
110
111
0
  return cy & mask1;
112
0
}
113
114
115
/*
116
 *  Swap value of U and V when OP_ENABLED=1
117
 *  otherwise, no change
118
 */
119
void
120
_gcry_mpih_swap_cond (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t usize,
121
                      unsigned long op_enable)
122
0
{
123
0
  mpi_size_t i;
124
0
  mpi_limb_t mask1 = vzero - op_enable;
125
0
  mpi_limb_t mask2 = op_enable - vone;
126
127
0
  for (i = 0; i < usize; i++)
128
0
    {
129
0
      mpi_limb_t u = up[i];
130
0
      mpi_limb_t v = vp[i];
131
0
      up[i] = (u & mask2) | (v & mask1);
132
0
      vp[i] = (u & mask1) | (v & mask2);
133
0
    }
134
0
}
135
136
137
/*
138
 *  W = -U when OP_ENABLED=1
139
 *  otherwise, W = U
140
 */
141
void
142
_gcry_mpih_abs_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
143
                     unsigned long op_enable)
144
0
{
145
0
  mpi_size_t i;
146
0
  mpi_limb_t mask1 = vzero - op_enable;
147
0
  mpi_limb_t mask2 = op_enable - vone;
148
0
  mpi_limb_t cy = op_enable;
149
150
0
  for (i = 0; i < usize; i++)
151
0
    {
152
0
      mpi_limb_t u = up[i];
153
0
      mpi_limb_t x = ~u + cy;
154
155
0
      cy = (x < ~u);
156
0
      wp[i] = (u & mask2) | (x & mask1);
157
0
    }
158
0
}
159
160
161
/*
162
 * Allocating memory for W,
163
 * compute W = V % U, then return W
164
 */
165
mpi_ptr_t
166
_gcry_mpih_mod (mpi_ptr_t vp, mpi_size_t vsize,
167
                mpi_ptr_t up, mpi_size_t usize)
168
0
{
169
0
  int secure;
170
0
  mpi_ptr_t rp;
171
0
  mpi_size_t i;
172
173
0
  secure = _gcry_is_secure (vp);
174
0
  rp = mpi_alloc_limb_space (usize, secure);
175
0
  MPN_ZERO (rp, usize);
176
177
0
  for (i = 0; i < vsize * BITS_PER_MPI_LIMB; i++)
178
0
    {
179
0
      unsigned int j = vsize * BITS_PER_MPI_LIMB - 1 - i;
180
0
      unsigned int limbno = j / BITS_PER_MPI_LIMB;
181
0
      unsigned int bitno = j % BITS_PER_MPI_LIMB;
182
0
      mpi_limb_t limb = vp[limbno];
183
0
      unsigned int the_bit = ((limb & (A_LIMB_1 << bitno)) ? 1 : 0);
184
0
      mpi_limb_t underflow;
185
0
      mpi_limb_t overflow;
186
187
0
      overflow = _gcry_mpih_lshift (rp, rp, usize, 1);
188
0
      rp[0] |= the_bit;
189
190
0
      underflow = _gcry_mpih_sub_n (rp, rp, up, usize);
191
0
      mpih_add_n_cond (rp, rp, up, usize, overflow ^ underflow);
192
0
    }
193
194
0
  return rp;
195
0
}
196
197
int
198
_gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v)
199
0
{
200
0
  int is_all_zero = 1;
201
0
  mpi_size_t i;
202
203
0
  for (i = 1; i < usize; i++)
204
0
    is_all_zero &= (up[i] == 0);
205
206
0
  if (is_all_zero)
207
0
    {
208
0
      if (up[0] < v)
209
0
        return -1;
210
0
      else if (up[0] > v)
211
0
        return 1;
212
0
      else
213
0
        return 0;
214
0
    }
215
0
  return 1;
216
0
}