Coverage Report

Created: 2025-06-13 06:31

/proc/self/cwd/pw_crypto/aes_mbedtls.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2024 The Pigweed Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4
// use this file except in compliance with the License. You may obtain a copy of
5
// the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
// License for the specific language governing permissions and limitations under
13
// the License.
14
15
#include "pw_crypto/aes_mbedtls.h"
16
17
#include <mbedtls/aes.h>
18
#include <mbedtls/cmac.h>
19
20
#include "pw_assert/check.h"
21
#include "pw_crypto/aes.h"
22
#include "pw_status/status.h"
23
24
namespace {
25
/// Number of bits in a byte.
26
constexpr size_t kBits = 8;
27
}  // namespace
28
29
namespace pw::crypto::aes::backend {
30
namespace {
31
using CmacCtx = NativeCmacContext;
32
}  // namespace
33
34
0
Status DoInit(CmacCtx& ctx, ConstByteSpan key) {
35
0
  const auto key_data = reinterpret_cast<const unsigned char*>(key.data());
36
37
0
  const mbedtls_cipher_info_t* info;
38
0
  switch (key.size()) {
39
0
    case kKey128SizeBytes:
40
0
      info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
41
0
      break;
42
0
    case kKey192SizeBytes:
43
0
      info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB);
44
0
      break;
45
0
    case kKey256SizeBytes:
46
0
      info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB);
47
0
      break;
48
0
    default:
49
0
      PW_CRASH("Unsupported key size for Cmac (%zu bit)", key.size() * kBits);
50
0
  }
51
52
0
  if (mbedtls_cipher_setup(&ctx.cipher, info)) {
53
0
    return Status::Internal();
54
0
  }
55
0
  if (mbedtls_cipher_cmac_starts(&ctx.cipher, key_data, key.size() * kBits)) {
56
0
    return Status::Internal();
57
0
  }
58
59
0
  return OkStatus();
60
0
}
61
62
0
Status DoUpdate(CmacCtx& ctx, ConstByteSpan data) {
63
0
  const auto data_in = reinterpret_cast<const unsigned char*>(data.data());
64
0
  if (mbedtls_cipher_cmac_update(&ctx.cipher, data_in, data.size())) {
65
0
    return Status::Internal();
66
0
  }
67
68
0
  return OkStatus();
69
0
}
70
71
0
Status DoFinal(CmacCtx& ctx, BlockSpan out_mac) {
72
0
  const auto data_out = reinterpret_cast<unsigned char*>(out_mac.data());
73
0
  if (mbedtls_cipher_cmac_finish(&ctx.cipher, data_out)) {
74
0
    return Status::Internal();
75
0
  }
76
77
0
  return OkStatus();
78
0
}
79
80
Status DoEncryptBlock(ConstByteSpan key,
81
                      ConstBlockSpan plaintext,
82
0
                      BlockSpan out_ciphertext) {
83
0
  const auto key_data = reinterpret_cast<const unsigned char*>(key.data());
84
0
  const auto in = reinterpret_cast<const unsigned char*>(plaintext.data());
85
0
  const auto out = reinterpret_cast<unsigned char*>(out_ciphertext.data());
86
87
0
  mbedtls_aes_context aes;
88
0
  mbedtls_aes_init(&aes);
89
90
0
  if (mbedtls_aes_setkey_enc(&aes, key_data, key.size() * kBits)) {
91
0
    mbedtls_aes_free(&aes);
92
0
    return Status::Internal();
93
0
  }
94
0
  if (mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, in, out)) {
95
0
    mbedtls_aes_free(&aes);
96
0
    return Status::Internal();
97
0
  }
98
99
0
  mbedtls_aes_free(&aes);
100
0
  return OkStatus();
101
0
}
102
103
}  // namespace pw::crypto::aes::backend