Coverage Report

Created: 2025-07-11 06:14

/src/hostap/src/crypto/aes-internal-dec.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * AES (Rijndael) cipher - decrypt
3
 *
4
 * Modifications to public domain implementation:
5
 * - cleanup
6
 * - use C pre-processor to make it easier to change S table access
7
 * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
8
 *   cost of reduced throughput (quite small difference on Pentium 4,
9
 *   10-25% when using -O1 or -O2 optimization)
10
 *
11
 * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
12
 *
13
 * This software may be distributed under the terms of the BSD license.
14
 * See README for more details.
15
 */
16
17
#include "includes.h"
18
19
#include "common.h"
20
#include "crypto.h"
21
#include "aes_i.h"
22
23
/**
24
 * Expand the cipher key into the decryption key schedule.
25
 *
26
 * @return  the number of rounds for the given cipher key size.
27
 */
28
static int rijndaelKeySetupDec(u32 rk[], const u8 cipherKey[], int keyBits)
29
0
{
30
0
  int Nr, i, j;
31
0
  u32 temp;
32
33
  /* expand the cipher key: */
34
0
  Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
35
0
  if (Nr < 0)
36
0
    return Nr;
37
  /* invert the order of the round keys: */
38
0
  for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
39
0
    temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
40
0
    temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
41
0
    temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
42
0
    temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
43
0
  }
44
  /* apply the inverse MixColumn transform to all round keys but the
45
   * first and the last: */
46
0
  for (i = 1; i < Nr; i++) {
47
0
    rk += 4;
48
0
    for (j = 0; j < 4; j++) {
49
0
      rk[j] = TD0_(TE4((rk[j] >> 24)       )) ^
50
0
        TD1_(TE4((rk[j] >> 16) & 0xff)) ^
51
0
        TD2_(TE4((rk[j] >>  8) & 0xff)) ^
52
0
        TD3_(TE4((rk[j]      ) & 0xff));
53
0
    }
54
0
  }
55
56
0
  return Nr;
57
0
}
58
59
void * aes_decrypt_init(const u8 *key, size_t len)
60
0
{
61
0
  u32 *rk;
62
0
  int res;
63
0
  rk = os_malloc(AES_PRIV_SIZE);
64
0
  if (rk == NULL)
65
0
    return NULL;
66
0
  res = rijndaelKeySetupDec(rk, key, len * 8);
67
0
  if (res < 0) {
68
0
    os_free(rk);
69
0
    return NULL;
70
0
  }
71
0
  rk[AES_PRIV_NR_POS] = res;
72
0
  return rk;
73
0
}
74
75
static void rijndaelDecrypt(const u32 rk[/*44*/], int Nr, const u8 ct[16],
76
          u8 pt[16])
77
0
{
78
0
  u32 s0, s1, s2, s3, t0, t1, t2, t3;
79
0
#ifndef FULL_UNROLL
80
0
  int r;
81
0
#endif /* ?FULL_UNROLL */
82
83
  /*
84
   * map byte array block to cipher state
85
   * and add initial round key:
86
   */
87
0
  s0 = GETU32(ct     ) ^ rk[0];
88
0
  s1 = GETU32(ct +  4) ^ rk[1];
89
0
  s2 = GETU32(ct +  8) ^ rk[2];
90
0
  s3 = GETU32(ct + 12) ^ rk[3];
91
92
0
#define ROUND(i,d,s) \
93
0
d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
94
0
d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
95
0
d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
96
0
d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
97
98
#ifdef FULL_UNROLL
99
100
  ROUND(1,t,s);
101
  ROUND(2,s,t);
102
  ROUND(3,t,s);
103
  ROUND(4,s,t);
104
  ROUND(5,t,s);
105
  ROUND(6,s,t);
106
  ROUND(7,t,s);
107
  ROUND(8,s,t);
108
  ROUND(9,t,s);
109
  if (Nr > 10) {
110
    ROUND(10,s,t);
111
    ROUND(11,t,s);
112
    if (Nr > 12) {
113
      ROUND(12,s,t);
114
      ROUND(13,t,s);
115
    }
116
  }
117
118
  rk += Nr << 2;
119
120
#else  /* !FULL_UNROLL */
121
122
  /* Nr - 1 full rounds: */
123
0
  r = Nr >> 1;
124
0
  for (;;) {
125
0
    ROUND(1,t,s);
126
0
    rk += 8;
127
0
    if (--r == 0)
128
0
      break;
129
0
    ROUND(0,s,t);
130
0
  }
131
132
0
#endif /* ?FULL_UNROLL */
133
134
0
#undef ROUND
135
136
  /*
137
   * apply last round and
138
   * map cipher state to byte array block:
139
   */
140
0
  s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
141
0
  PUTU32(pt     , s0);
142
0
  s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
143
0
  PUTU32(pt +  4, s1);
144
0
  s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
145
0
  PUTU32(pt +  8, s2);
146
0
  s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
147
0
  PUTU32(pt + 12, s3);
148
0
}
149
150
151
int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
152
0
{
153
0
  u32 *rk = ctx;
154
0
  rijndaelDecrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain);
155
0
  return 0;
156
0
}
157
158
159
void aes_decrypt_deinit(void *ctx)
160
0
{
161
0
  os_memset(ctx, 0, AES_PRIV_SIZE);
162
0
  os_free(ctx);
163
0
}