aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/s2n/pq-crypto/bike_r2/openssl_utils.c
blob: c80d3365cb881ea9466d4e90da02b6cc54e23929 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0"
 *
 * Written by Nir Drucker and Shay Gueron,
 * AWS Cryptographic Algorithms Group.
 * (ndrucker@amazon.com, gueron@amazon.com)
 */

#include "openssl_utils.h"
#include "utilities.h"
#include <assert.h>
#include <openssl/bn.h>
#include <string.h>

#ifdef USE_OPENSSL_GF2M

#  define MAX_OPENSSL_INV_TRIALS 1000

_INLINE_ void
BN_CTX_cleanup(BN_CTX *ctx)
{
  if(ctx)
  {
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
  }
}

DEFINE_POINTER_CLEANUP_FUNC(BN_CTX *, BN_CTX_cleanup);

// Loading (big) numbers into OpenSSL should use Big Endian representation.
// Therefore, the bytes ordering of the number should be reversed.
_INLINE_ void
reverse_endian(OUT uint8_t *res, IN const uint8_t *in, IN const uint32_t n)
{
  uint32_t i;

  for(i = 0; i < (n / 2); i++)
  {
    uint64_t tmp            = in[i];
    res[i]         = in[n - 1 - i];
    res[n - 1 - i] = tmp;
  }

  // If the number of blocks is odd, swap also the middle block.
  if(n % 2)
  {
    res[i] = in[i];
  }
}

_INLINE_ ret_t
ossl_bn2bin(OUT uint8_t *out, IN const BIGNUM *in, IN const uint32_t size)
{
  assert(size <= N_SIZE);
  uint8_t be_tmp[N_SIZE] = {0};

  memset(out, 0, size);

  if(BN_bn2bin(in, be_tmp) == -1)
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }
  reverse_endian(out, be_tmp, BN_num_bytes(in));

  return SUCCESS;
}

_INLINE_ ret_t
ossl_bin2bn(IN BIGNUM *out, OUT const uint8_t *in, IN const uint32_t size)
{
  assert(size <= N_SIZE);
  uint8_t be_tmp[N_SIZE] = {0};

  reverse_endian(be_tmp, in, size);

  if(BN_bin2bn(be_tmp, size, out) == 0)
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  return SUCCESS;
}

ret_t
ossl_add(OUT uint8_t      res_bin[R_SIZE],
         IN const uint8_t a_bin[R_SIZE],
         IN const uint8_t b_bin[R_SIZE])
{
  DEFER_CLEANUP(BN_CTX *bn_ctx = BN_CTX_new(), BN_CTX_cleanup_pointer);
  BIGNUM *r = NULL;
  BIGNUM *a = NULL;
  BIGNUM *b = NULL;

  if(NULL == bn_ctx)
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  BN_CTX_start(bn_ctx);

  r = BN_CTX_get(bn_ctx);
  a = BN_CTX_get(bn_ctx);
  b = BN_CTX_get(bn_ctx);

  if((NULL == r) || (NULL == a) || (NULL == b))
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  POSIX_GUARD(ossl_bin2bn(a, a_bin, R_SIZE));
  POSIX_GUARD(ossl_bin2bn(b, b_bin, R_SIZE));

  if(BN_GF2m_add(r, a, b) == 0)
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  POSIX_GUARD(ossl_bn2bin(res_bin, r, R_SIZE));

  return SUCCESS;
}

// Perform a cyclic product by using OpenSSL.
_INLINE_ ret_t
ossl_cyclic_product(OUT BIGNUM *r,
                    IN const BIGNUM *a,
                    IN const BIGNUM *b,
                    BN_CTX *         bn_ctx)
{
  BIGNUM *m = BN_CTX_get(bn_ctx);
  if(NULL == m)
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  // m = x^PARAM_R - 1
  if((BN_set_bit(m, R_BITS) == 0) || (BN_set_bit(m, 0) == 0))
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  // r = a*b mod m
  if(BN_GF2m_mod_mul(r, a, b, m, bn_ctx) == 0)
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  return SUCCESS;
}

// Perform a cyclic product by using OpenSSL.
ret_t
cyclic_product(OUT uint8_t      res_bin[R_SIZE],
               IN const uint8_t a_bin[R_SIZE],
               IN const uint8_t b_bin[R_SIZE])
{
  DEFER_CLEANUP(BN_CTX *bn_ctx = BN_CTX_new(), BN_CTX_cleanup_pointer);
  BIGNUM *r = NULL;
  BIGNUM *a = NULL;
  BIGNUM *b = NULL;

  if(NULL == bn_ctx)
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  BN_CTX_start(bn_ctx);

  r = BN_CTX_get(bn_ctx);
  a = BN_CTX_get(bn_ctx);
  b = BN_CTX_get(bn_ctx);

  if((NULL == r) || (NULL == a) || (NULL == b))
  {
    BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL);
  }

  POSIX_GUARD(ossl_bin2bn(a, a_bin, R_SIZE));
  POSIX_GUARD(ossl_bin2bn(b, b_bin, R_SIZE));
  POSIX_GUARD(ossl_cyclic_product(r, a, b, bn_ctx));
  POSIX_GUARD(ossl_bn2bin(res_bin, r, R_SIZE));

  return SUCCESS;
}

#endif // USE_OPENSSL_GF2M