Coverage Report

Created: 2024-02-25 06:16

/src/nettle-with-mini-gmp/sm4.c
Line
Count
Source (jump to first uncovered line)
1
/* sm4.c
2
3
   Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
4
5
   This file is part of GNU Nettle.
6
7
   GNU Nettle is free software: you can redistribute it and/or
8
   modify it under the terms of either:
9
10
     * the GNU Lesser General Public License as published by the Free
11
       Software Foundation; either version 3 of the License, or (at your
12
       option) any later version.
13
14
   or
15
16
     * the GNU General Public License as published by the Free
17
       Software Foundation; either version 2 of the License, or (at your
18
       option) any later version.
19
20
   or both in parallel, as here.
21
22
   GNU Nettle is distributed in the hope that it will be useful,
23
   but WITHOUT ANY WARRANTY; without even the implied warranty of
24
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25
   General Public License for more details.
26
27
   You should have received copies of the GNU General Public License and
28
   the GNU Lesser General Public License along with this program.  If
29
   not, see http://www.gnu.org/licenses/.
30
*/
31
32
#if HAVE_CONFIG_H
33
# include "config.h"
34
#endif
35
36
#include <assert.h>
37
#include <string.h>
38
39
#include "sm4.h"
40
41
#include "macros.h"
42
43
44
static const uint32_t fk[4] =
45
{
46
  0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
47
};
48
49
static const uint32_t ck[32] =
50
{
51
  0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
52
  0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
53
  0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
54
  0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
55
  0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
56
  0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
57
  0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
58
  0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
59
};
60
61
static const uint8_t sbox[256] =
62
{
63
  0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
64
  0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
65
  0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
66
  0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
67
  0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
68
  0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
69
  0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
70
  0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
71
  0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
72
  0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
73
  0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
74
  0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
75
  0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
76
  0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
77
  0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
78
  0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
79
  0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
80
  0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
81
  0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
82
  0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
83
  0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
84
  0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
85
  0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
86
  0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
87
  0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
88
  0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
89
  0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
90
  0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
91
  0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
92
  0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
93
  0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
94
  0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
95
};
96
97
static uint32_t
98
sm4_t_non_lin_sub(uint32_t x)
99
73.5k
{
100
73.5k
  uint32_t out;
101
102
73.5k
  out  = (uint32_t)sbox[x & 0xff];
103
73.5k
  out |= (uint32_t)sbox[(x >> 8) & 0xff] << 8;
104
73.5k
  out |= (uint32_t)sbox[(x >> 16) & 0xff] << 16;
105
73.5k
  out |= (uint32_t)sbox[(x >> 24) & 0xff] << 24;
106
107
73.5k
  return out;
108
73.5k
}
109
110
static uint32_t
111
sm4_key_lin_sub(uint32_t x)
112
13.5k
{
113
13.5k
  return x ^ ROTL32(13, x) ^ ROTL32(23, x);
114
13.5k
}
115
116
static uint32_t
117
sm4_enc_lin_sub(uint32_t x)
118
59.9k
{
119
59.9k
  return x ^ ROTL32(2, x) ^ ROTL32(10, x) ^ ROTL32(18, x) ^ ROTL32(24, x);
120
59.9k
}
121
122
static uint32_t
123
sm4_key_sub(uint32_t x)
124
13.5k
{
125
13.5k
  return sm4_key_lin_sub(sm4_t_non_lin_sub(x));
126
13.5k
}
127
128
static uint32_t
129
sm4_enc_sub(uint32_t x)
130
59.9k
{
131
59.9k
  return sm4_enc_lin_sub(sm4_t_non_lin_sub(x));
132
59.9k
}
133
134
static uint32_t
135
sm4_round(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t rk)
136
59.9k
{
137
59.9k
  return x0 ^ sm4_enc_sub(x1 ^ x2 ^ x3 ^ rk);
138
59.9k
}
139
140
static void
141
sm4_set_key(struct sm4_ctx *ctx, const uint8_t *key, int encrypt)
142
423
{
143
423
  uint32_t rk0, rk1, rk2, rk3;
144
423
  unsigned i;
145
146
423
  rk0 = READ_UINT32(key +  0) ^ fk[0];
147
423
  rk1 = READ_UINT32(key +  4) ^ fk[1];
148
423
  rk2 = READ_UINT32(key +  8) ^ fk[2];
149
423
  rk3 = READ_UINT32(key + 12) ^ fk[3];
150
151
3.80k
  for (i = 0; i < 32; i += 4)
152
3.38k
    {
153
3.38k
      rk0 ^= sm4_key_sub(rk1 ^ rk2 ^ rk3 ^ ck[i + 0]);
154
3.38k
      rk1 ^= sm4_key_sub(rk2 ^ rk3 ^ rk0 ^ ck[i + 1]);
155
3.38k
      rk2 ^= sm4_key_sub(rk3 ^ rk0 ^ rk1 ^ ck[i + 2]);
156
3.38k
      rk3 ^= sm4_key_sub(rk0 ^ rk1 ^ rk2 ^ ck[i + 3]);
157
158
3.38k
      if (encrypt)
159
3.38k
        {
160
3.38k
          ctx->rkey[i + 0] = rk0;
161
3.38k
          ctx->rkey[i + 1] = rk1;
162
3.38k
          ctx->rkey[i + 2] = rk2;
163
3.38k
          ctx->rkey[i + 3] = rk3;
164
3.38k
        }
165
0
      else
166
0
        {
167
0
          ctx->rkey[31 - 0 - i] = rk0;
168
0
          ctx->rkey[31 - 1 - i] = rk1;
169
0
          ctx->rkey[31 - 2 - i] = rk2;
170
0
          ctx->rkey[31 - 3 - i] = rk3;
171
0
        }
172
3.38k
    }
173
423
}
174
175
void
176
sm4_set_encrypt_key(struct sm4_ctx *ctx, const uint8_t *key)
177
423
{
178
423
  sm4_set_key(ctx, key, 1);
179
423
}
180
181
void
182
sm4_set_decrypt_key(struct sm4_ctx *ctx, const uint8_t *key)
183
0
{
184
0
  sm4_set_key(ctx, key, 0);
185
0
}
186
187
void
188
sm4_crypt(const struct sm4_ctx *context,
189
    size_t length,
190
    uint8_t *dst,
191
    const uint8_t *src)
192
6.70k
{
193
6.70k
  const uint32_t *rk = context->rkey;
194
195
6.70k
  assert( !(length % SM4_BLOCK_SIZE) );
196
197
8.57k
  for ( ; length; length -= SM4_BLOCK_SIZE)
198
1.87k
    {
199
1.87k
      uint32_t x0, x1, x2, x3;
200
1.87k
      unsigned i;
201
202
1.87k
      x0 = READ_UINT32(src + 0 * 4);
203
1.87k
      x1 = READ_UINT32(src + 1 * 4);
204
1.87k
      x2 = READ_UINT32(src + 2 * 4);
205
1.87k
      x3 = READ_UINT32(src + 3 * 4);
206
207
16.8k
      for (i = 0; i < 32; i += 4)
208
14.9k
        {
209
14.9k
          x0 = sm4_round(x0, x1, x2, x3, rk[i + 0]);
210
14.9k
          x1 = sm4_round(x1, x2, x3, x0, rk[i + 1]);
211
14.9k
          x2 = sm4_round(x2, x3, x0, x1, rk[i + 2]);
212
14.9k
          x3 = sm4_round(x3, x0, x1, x2, rk[i + 3]);
213
14.9k
        }
214
215
1.87k
      WRITE_UINT32(dst + 0 * 4, x3);
216
1.87k
      WRITE_UINT32(dst + 1 * 4, x2);
217
1.87k
      WRITE_UINT32(dst + 2 * 4, x1);
218
1.87k
      WRITE_UINT32(dst + 3 * 4, x0);
219
220
1.87k
      src += SM4_BLOCK_SIZE;
221
1.87k
      dst += SM4_BLOCK_SIZE;
222
1.87k
    }
223
6.70k
}