• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DoInit(CmacCtx & ctx,ConstByteSpan key)34 Status DoInit(CmacCtx& ctx, ConstByteSpan key) {
35   const auto key_data = reinterpret_cast<const unsigned char*>(key.data());
36 
37   const mbedtls_cipher_info_t* info;
38   switch (key.size()) {
39     case kKey128SizeBytes:
40       info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
41       break;
42     case kKey192SizeBytes:
43       info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB);
44       break;
45     case kKey256SizeBytes:
46       info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB);
47       break;
48     default:
49       PW_CRASH("Unsupported key size for Cmac (%zu bit)", key.size() * kBits);
50   }
51 
52   if (mbedtls_cipher_setup(&ctx.cipher, info)) {
53     return Status::Internal();
54   }
55   if (mbedtls_cipher_cmac_starts(&ctx.cipher, key_data, key.size() * kBits)) {
56     return Status::Internal();
57   }
58 
59   return OkStatus();
60 }
61 
DoUpdate(CmacCtx & ctx,ConstByteSpan data)62 Status DoUpdate(CmacCtx& ctx, ConstByteSpan data) {
63   const auto data_in = reinterpret_cast<const unsigned char*>(data.data());
64   if (mbedtls_cipher_cmac_update(&ctx.cipher, data_in, data.size())) {
65     return Status::Internal();
66   }
67 
68   return OkStatus();
69 }
70 
DoFinal(CmacCtx & ctx,BlockSpan out_mac)71 Status DoFinal(CmacCtx& ctx, BlockSpan out_mac) {
72   const auto data_out = reinterpret_cast<unsigned char*>(out_mac.data());
73   if (mbedtls_cipher_cmac_finish(&ctx.cipher, data_out)) {
74     return Status::Internal();
75   }
76 
77   return OkStatus();
78 }
79 
DoEncryptBlock(ConstByteSpan key,ConstBlockSpan plaintext,BlockSpan out_ciphertext)80 Status DoEncryptBlock(ConstByteSpan key,
81                       ConstBlockSpan plaintext,
82                       BlockSpan out_ciphertext) {
83   const auto key_data = reinterpret_cast<const unsigned char*>(key.data());
84   const auto in = reinterpret_cast<const unsigned char*>(plaintext.data());
85   const auto out = reinterpret_cast<unsigned char*>(out_ciphertext.data());
86 
87   mbedtls_aes_context aes;
88   mbedtls_aes_init(&aes);
89 
90   if (mbedtls_aes_setkey_enc(&aes, key_data, key.size() * kBits)) {
91     mbedtls_aes_free(&aes);
92     return Status::Internal();
93   }
94   if (mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, in, out)) {
95     mbedtls_aes_free(&aes);
96     return Status::Internal();
97   }
98 
99   mbedtls_aes_free(&aes);
100   return OkStatus();
101 }
102 
103 }  // namespace pw::crypto::aes::backend
104