Coverage Report

Created: 2025-04-24 06:18

/src/hostap/src/crypto/aes-siv.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * AES SIV (RFC 5297)
3
 * Copyright (c) 2013 Cozybit, Inc.
4
 *
5
 * This software may be distributed under the terms of the BSD license.
6
 * See README for more details.
7
 */
8
9
#include "includes.h"
10
11
#include "common.h"
12
#include "aes.h"
13
#include "aes_wrap.h"
14
#include "aes_siv.h"
15
16
17
static const u8 zero[AES_BLOCK_SIZE];
18
19
20
static void dbl(u8 *pad)
21
0
{
22
0
  int i, carry;
23
24
0
  carry = pad[0] & 0x80;
25
0
  for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
26
0
    pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
27
0
  pad[AES_BLOCK_SIZE - 1] <<= 1;
28
0
  if (carry)
29
0
    pad[AES_BLOCK_SIZE - 1] ^= 0x87;
30
0
}
31
32
33
static void xor(u8 *a, const u8 *b)
34
0
{
35
0
  int i;
36
37
0
  for (i = 0; i < AES_BLOCK_SIZE; i++)
38
0
    *a++ ^= *b++;
39
0
}
40
41
42
static void xorend(u8 *a, int alen, const u8 *b, int blen)
43
0
{
44
0
  int i;
45
46
0
  if (alen < blen)
47
0
    return;
48
49
0
  for (i = 0; i < blen; i++)
50
0
    a[alen - blen + i] ^= b[i];
51
0
}
52
53
54
static void pad_block(u8 *pad, const u8 *addr, size_t len)
55
0
{
56
0
  os_memset(pad, 0, AES_BLOCK_SIZE);
57
0
  os_memcpy(pad, addr, len);
58
59
0
  if (len < AES_BLOCK_SIZE)
60
0
    pad[len] = 0x80;
61
0
}
62
63
64
static int aes_s2v(const u8 *key, size_t key_len,
65
       size_t num_elem, const u8 *addr[], size_t *len, u8 *mac)
66
0
{
67
0
  u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
68
0
  u8 *buf = NULL;
69
0
  int ret;
70
0
  size_t i;
71
0
  const u8 *data[1];
72
0
  size_t data_len[1];
73
74
0
  if (!num_elem) {
75
0
    os_memcpy(tmp, zero, sizeof(zero));
76
0
    tmp[AES_BLOCK_SIZE - 1] = 1;
77
0
    data[0] = tmp;
78
0
    data_len[0] = sizeof(tmp);
79
0
    return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
80
0
  }
81
82
0
  data[0] = zero;
83
0
  data_len[0] = sizeof(zero);
84
0
  ret = omac1_aes_vector(key, key_len, 1, data, data_len, tmp);
85
0
  if (ret)
86
0
    return ret;
87
88
0
  for (i = 0; i < num_elem - 1; i++) {
89
0
    ret = omac1_aes_vector(key, key_len, 1, &addr[i], &len[i],
90
0
               tmp2);
91
0
    if (ret)
92
0
      return ret;
93
94
0
    dbl(tmp);
95
0
    xor(tmp, tmp2);
96
0
  }
97
0
  if (len[i] >= AES_BLOCK_SIZE) {
98
0
    buf = os_memdup(addr[i], len[i]);
99
0
    if (!buf)
100
0
      return -ENOMEM;
101
102
0
    xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
103
0
    data[0] = buf;
104
0
    ret = omac1_aes_vector(key, key_len, 1, data, &len[i], mac);
105
0
    bin_clear_free(buf, len[i]);
106
0
    return ret;
107
0
  }
108
109
0
  dbl(tmp);
110
0
  pad_block(tmp2, addr[i], len[i]);
111
0
  xor(tmp, tmp2);
112
113
0
  data[0] = tmp;
114
0
  data_len[0] = sizeof(tmp);
115
0
  return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
116
0
}
117
118
119
int aes_siv_encrypt(const u8 *key, size_t key_len,
120
        const u8 *pw, size_t pwlen,
121
        size_t num_elem, const u8 *addr[], const size_t *len,
122
        u8 *out)
123
0
{
124
0
  const u8 *_addr[6];
125
0
  size_t _len[6];
126
0
  const u8 *k1, *k2;
127
0
  u8 v[AES_BLOCK_SIZE];
128
0
  size_t i;
129
0
  u8 *iv, *crypt_pw;
130
131
0
  if (num_elem > ARRAY_SIZE(_addr) - 1 ||
132
0
      (key_len != 32 && key_len != 48 && key_len != 64))
133
0
    return -1;
134
135
0
  key_len /= 2;
136
0
  k1 = key;
137
0
  k2 = key + key_len;
138
139
0
  for (i = 0; i < num_elem; i++) {
140
0
    _addr[i] = addr[i];
141
0
    _len[i] = len[i];
142
0
  }
143
0
  _addr[num_elem] = pw;
144
0
  _len[num_elem] = pwlen;
145
146
0
  if (aes_s2v(k1, key_len, num_elem + 1, _addr, _len, v))
147
0
    return -1;
148
149
0
  iv = out;
150
0
  crypt_pw = out + AES_BLOCK_SIZE;
151
152
0
  os_memcpy(iv, v, AES_BLOCK_SIZE);
153
0
  os_memcpy(crypt_pw, pw, pwlen);
154
155
  /* zero out 63rd and 31st bits of ctr (from right) */
156
0
  v[8] &= 0x7f;
157
0
  v[12] &= 0x7f;
158
0
  return aes_ctr_encrypt(k2, key_len, v, crypt_pw, pwlen);
159
0
}
160
161
162
int aes_siv_decrypt(const u8 *key, size_t key_len,
163
        const u8 *iv_crypt, size_t iv_c_len,
164
        size_t num_elem, const u8 *addr[], const size_t *len,
165
        u8 *out)
166
0
{
167
0
  const u8 *_addr[6];
168
0
  size_t _len[6];
169
0
  const u8 *k1, *k2;
170
0
  size_t crypt_len;
171
0
  size_t i;
172
0
  int ret;
173
0
  u8 iv[AES_BLOCK_SIZE];
174
0
  u8 check[AES_BLOCK_SIZE];
175
176
0
  if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1 ||
177
0
      (key_len != 32 && key_len != 48 && key_len != 64))
178
0
    return -1;
179
0
  crypt_len = iv_c_len - AES_BLOCK_SIZE;
180
0
  key_len /= 2;
181
0
  k1 = key;
182
0
  k2 = key + key_len;
183
184
0
  for (i = 0; i < num_elem; i++) {
185
0
    _addr[i] = addr[i];
186
0
    _len[i] = len[i];
187
0
  }
188
0
  _addr[num_elem] = out;
189
0
  _len[num_elem] = crypt_len;
190
191
0
  os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
192
0
  os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
193
194
0
  iv[8] &= 0x7f;
195
0
  iv[12] &= 0x7f;
196
197
0
  ret = aes_ctr_encrypt(k2, key_len, iv, out, crypt_len);
198
0
  if (ret)
199
0
    return ret;
200
201
0
  ret = aes_s2v(k1, key_len, num_elem + 1, _addr, _len, check);
202
0
  if (ret)
203
0
    return ret;
204
0
  if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
205
0
    return 0;
206
207
0
  return -1;
208
0
}