Coverage Report

Created: 2026-11-12 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libstrongswan/crypto/aead.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2013 Tobias Brunner
3
 * Copyright (C) 2010 Martin Willi
4
 *
5
 * Copyright (C) secunet Security Networks AG
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
#include "aead.h"
19
20
#include <utils/debug.h>
21
#include <crypto/iv/iv_gen_rand.h>
22
23
typedef struct private_aead_t private_aead_t;
24
25
/**
26
 * Private data of an aead_t object.
27
 */
28
struct private_aead_t {
29
30
  /**
31
   * Public aead_t interface.
32
   */
33
  aead_t public;
34
35
  /**
36
   * traditional crypter
37
   */
38
  crypter_t *crypter;
39
40
  /**
41
   * traditional signer
42
   */
43
  signer_t *signer;
44
45
  /**
46
   * IV generator
47
   */
48
  iv_gen_t *iv_gen;
49
};
50
51
METHOD(aead_t, encrypt, bool,
52
  private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
53
  chunk_t *encrypted)
54
0
{
55
0
  chunk_t encr, sig;
56
57
0
  if (!this->signer->get_signature(this->signer, assoc, NULL) ||
58
0
    !this->signer->get_signature(this->signer, iv, NULL))
59
0
  {
60
0
    return FALSE;
61
0
  }
62
63
0
  if (encrypted)
64
0
  {
65
0
    if (!this->crypter->encrypt(this->crypter, plain, iv, &encr))
66
0
    {
67
0
      return FALSE;
68
0
    }
69
0
    if (!this->signer->allocate_signature(this->signer, encr, &sig))
70
0
    {
71
0
      free(encr.ptr);
72
0
      return FALSE;
73
0
    }
74
0
    *encrypted = chunk_cat("cmm", iv, encr, sig);
75
0
  }
76
0
  else
77
0
  {
78
0
    if (!this->crypter->encrypt(this->crypter, plain, iv, NULL) ||
79
0
      !this->signer->get_signature(this->signer,
80
0
                     plain, plain.ptr + plain.len))
81
0
    {
82
0
      return FALSE;
83
0
    }
84
0
  }
85
0
  return TRUE;
86
0
}
87
88
METHOD(aead_t, decrypt, bool,
89
  private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
90
  chunk_t *plain)
91
0
{
92
0
  chunk_t sig;
93
0
  size_t bs;
94
95
0
  bs = this->crypter->get_block_size(this->crypter);
96
0
  sig.len = this->signer->get_block_size(this->signer);
97
0
  if (sig.len > encrypted.len || (encrypted.len - sig.len) % bs)
98
0
  {
99
0
    DBG1(DBG_LIB, "invalid encrypted data length %d with block size %d",
100
0
      encrypted.len - sig.len, bs);
101
0
    return FALSE;
102
0
  }
103
0
  chunk_split(encrypted, "mm", encrypted.len - sig.len,
104
0
        &encrypted, sig.len, &sig);
105
106
0
  if (!this->signer->get_signature(this->signer, assoc, NULL) ||
107
0
    !this->signer->get_signature(this->signer, iv, NULL))
108
0
  {
109
0
    return FALSE;
110
0
  }
111
0
  if (!this->signer->verify_signature(this->signer, encrypted, sig))
112
0
  {
113
0
    DBG1(DBG_LIB, "MAC verification failed");
114
0
    return FALSE;
115
0
  }
116
0
  return this->crypter->decrypt(this->crypter, encrypted, iv, plain);
117
0
}
118
119
METHOD(aead_t, get_block_size, size_t,
120
  private_aead_t *this)
121
0
{
122
0
  return this->crypter->get_block_size(this->crypter);
123
0
}
124
125
METHOD(aead_t, get_icv_size, size_t,
126
  private_aead_t *this)
127
0
{
128
0
  return this->signer->get_block_size(this->signer);
129
0
}
130
131
METHOD(aead_t, get_iv_size, size_t,
132
  private_aead_t *this)
133
0
{
134
0
  return this->crypter->get_iv_size(this->crypter);
135
0
}
136
137
METHOD(aead_t, get_iv_gen, iv_gen_t*,
138
  private_aead_t *this)
139
0
{
140
0
  return this->iv_gen;
141
0
}
142
143
METHOD(aead_t, get_key_size, size_t,
144
  private_aead_t *this)
145
0
{
146
0
  return this->crypter->get_key_size(this->crypter) +
147
0
      this->signer->get_key_size(this->signer);
148
0
}
149
150
METHOD(aead_t, set_key, bool,
151
  private_aead_t *this, chunk_t key)
152
0
{
153
0
  chunk_t sig, enc;
154
155
0
  chunk_split(key, "mm", this->signer->get_key_size(this->signer), &sig,
156
0
        this->crypter->get_key_size(this->crypter), &enc);
157
158
0
  return this->signer->set_key(this->signer, sig) &&
159
0
       this->crypter->set_key(this->crypter, enc);
160
0
}
161
162
METHOD(aead_t, destroy, void,
163
  private_aead_t *this)
164
0
{
165
0
  this->iv_gen->destroy(this->iv_gen);
166
0
  this->crypter->destroy(this->crypter);
167
0
  this->signer->destroy(this->signer);
168
0
  free(this);
169
0
}
170
171
/**
172
 * See header
173
 */
174
aead_t *aead_create(crypter_t *crypter, signer_t *signer, iv_gen_t *iv_gen)
175
0
{
176
0
  private_aead_t *this;
177
178
0
  INIT(this,
179
0
    .public = {
180
0
      .encrypt = _encrypt,
181
0
      .decrypt = _decrypt,
182
0
      .get_block_size = _get_block_size,
183
0
      .get_icv_size = _get_icv_size,
184
0
      .get_iv_size = _get_iv_size,
185
0
      .get_iv_gen = _get_iv_gen,
186
0
      .get_key_size = _get_key_size,
187
0
      .set_key = _set_key,
188
0
      .destroy = _destroy,
189
0
    },
190
0
    .crypter = crypter,
191
0
    .signer = signer,
192
0
    .iv_gen = iv_gen,
193
0
  );
194
195
0
  return &this->public;
196
0
}