• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _module-pw_crypto:
2
3=========
4pw_crypto
5=========
6.. pigweed-module::
7   :name: pw_crypto
8
9A set of safe (read: easy to use, hard to misuse) crypto APIs.
10
11The following crypto services are provided by this module.
12
131. Hashing a message with `SHA256`_.
142. Verifying a digital signature signed with `ECDSA`_ over the NIST P256 curve.
153. Many more to come ...
16
17------
18SHA256
19------
201. Obtaining a oneshot digest.
21
22.. code-block:: cpp
23
24   #include "pw_crypto/sha256.h"
25
26   std::byte digest[32];
27   if (!pw::crypto::sha256::Hash(message, digest).ok()) {
28     // Handle errors.
29   }
30
31   // The content can also come from a pw::stream::Reader.
32   if (!pw::crypto::sha256::Hash(reader, digest).ok()) {
33     // Handle errors.
34   }
35
362. Hashing a long, potentially non-contiguous message.
37
38.. code-block:: cpp
39
40   #include "pw_crypto/sha256.h"
41
42   std::byte digest[32];
43
44   if (!pw::crypto::sha256::Sha256()
45       .Update(chunk1).Update(chunk2).Update(chunk...)
46       .Final().ok()) {
47     // Handle errors.
48   }
49
50-----
51ECDSA
52-----
531. Verifying a digital signature signed with ECDSA over the NIST P256 curve.
54
55.. code-block:: cpp
56
57   #include "pw_crypto/sha256.h"
58
59   std::byte digest[32];
60   if (!pw::crypto::sha256::Hash(message, digest).ok()) {
61     // handle errors.
62   }
63
64   if (!pw::crypto::ecdsa::VerifyP256Signature(public_key, digest,
65                                               signature).ok()) {
66     // handle errors.
67   }
68
692. Verifying a digital signature signed with ECDSA over the NIST P256 curve,
70   with a long and/or non-contiguous message.
71
72.. code-block:: cpp
73
74   #include "pw_crypto/sha256.h"
75
76   std::byte digest[32];
77
78   if (!pw::crypto::sha256::Sha256()
79       .Update(chunk1).Update(chunk2).Update(chunkN)
80       .Final(digest).ok()) {
81       // Handle errors.
82   }
83
84   if (!pw::crypto::ecdsa::VerifyP256Signature(public_key, digest,
85                                               signature).ok()) {
86       // Handle errors.
87   }
88
89---
90AES
91---
92
931. Computing the AES-CMAC of a potentially long and/or non-contiguous message.
94   This is similar to a hash or digest except that the operation takes a secret
95   key as an input, so the MAC can be used to verify integrity and
96   authentication.
97
98.. code-block:: cpp
99
100   #include "pw_crypto/aes.h"
101
102   std::byte mac[16];
103
104   if (!pw::crypto::aes_cmac::Cmac(key).Update(chunk1).Update(chunk2)
105         .Update(chunk...).Final().ok()) {
106     // Handle errors.
107   }
108
1092. Encrypting a single AES 128-bit block.
110
111.. warning::
112  This is a low-level operation. Users should know exactly what they are doing
113  and must ensure that this operation does not violate any safety bounds that
114  more refined operations usually ensure.
115
116.. code-block:: cpp
117
118   #include "pw_crypto/aes.h"
119
120   std::byte encrypted[16];
121
122   if (!pw::crypto::unsafe::aes::EncryptBlock(key, message, encrypted).ok()) {
123       // Handle errors.
124   }
125
126-------------
127Configuration
128-------------
129The crypto services offered by pw_crypto can be backed by different backend
130crypto libraries.
131
132Mbed TLS
133========
134The `Mbed TLS project <https://www.trustedfirmware.org/projects/mbed-tls/>`_
135is a mature and full-featured crypto library that implements cryptographic
136primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols.
137
138The project also has good support for interfacing to cryptographic accelerators.
139
140The small code footprint makes the project suitable and popular for embedded
141systems.
142
143To select the Mbed TLS backend, the MbedTLS library needs to be installed and
144configured. If using GN, do,
145
146.. code-block:: sh
147
148   # Install and configure MbedTLS
149   pw package install mbedtls
150   gn gen out --args='
151       dir_pw_third_party_mbedtls=getenv("PW_PACKAGE_ROOT")+"/mbedtls"
152       pw_crypto_SHA256_BACKEND="//pw_crypto:sha256_mbedtls_v3"
153       pw_crypto_ECDSA_BACKEND="//pw_crypto:ecdsa_mbedtls_v3"
154       pw_crypto_AES_BACKEND="//pw_crypto:aes_mbedtls_v3"
155   '
156
157   ninja -C out
158
159If using Bazel, add the Mbed TLS repository to your WORKSPACE and select
160appropriate backends by adding them to your project's `platform
161<https://bazel.build/extending/platforms>`_:
162
163.. code-block:: python
164
165   platform(
166     name = "my_platform",
167     flags = [
168        "@pigweed//pw_crypto:sha256_backend=@pigweed//pw_crypto:sha256_mbedtls_backend",
169        "@pigweed//pw_crypto:ecdsa_backend=@pigweed//pw_crypto:ecdsa_mbedtls_backend",
170        "@pigweed//pw_crypto:aes_backend=@pigweed//pw_crypto:aes_mbedtls_backend",
171        # ... other flags
172      ],
173   )
174
175For optimal code size and/or performance, the Mbed TLS library can be configured
176per product. Mbed TLS configuration is achieved by turning on and off MBEDTLS_*
177options in a config.h file. See //third_party/mbedtls for how this is done.
178
179``pw::crypto::sha256`` does not need any special configuration as it uses the
180mbedtls_sha256_* APIs directly. However you can optionally turn on
181``MBEDTLS_SHA256_SMALLER`` to further reduce the code size to from 3KiB to
182~1.8KiB at a ~30% slowdown cost (Cortex-M4).
183
184.. code-block:: c
185
186   #define MBEDTLS_SHA256_SMALLER
187
188``pw::crypto::ecdsa`` requires the following minimum configurations which yields
189a code size of ~12KiB.
190
191.. code-block:: c
192
193   #define MBEDTLS_BIGNUM_C
194   #define MBEDTLS_ECP_C
195   #define MBEDTLS_ECDSA_C
196   // The ASN1 options are needed only because mbedtls considers and verifies
197   // them (in check_config.h) as dependencies of MBEDTLS_ECDSA_C.
198   #define MBEDTLS_ASN1_WRITE_C
199   #define MBEDTLS_ASN1_PARSE_C
200   #define MBEDTLS_ECP_NO_INTERNAL_RNG
201   #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
202
203.. _module-pw_crypto-boringssl:
204
205BoringSSL
206=========
207The BoringSSL project (`source
208<https://cs.opensource.google/boringssl/boringssl>`_, `GitHub mirror
209<https://github.com/google/boringssl>`_) is a fork of OpenSSL maintained by
210Google. It is not especially designed to be embedded-friendly, but it is used as
211the SSL library in Chrome, Android, and other apps. It is likely better to use
212another backend such as Mbed-TLS for embedded targets unless your project needs
213BoringSSL specifically.
214
215To use the BoringSSL backend with a GN project, it needs to be installed and
216configured. To do that:
217
218.. code-block:: sh
219
220   # Install and configure BoringSSL
221   pw package install boringssl
222   gn gen out --args='
223       dir_pw_third_party_boringssl=getenv("PW_PACKAGE_ROOT")+"/boringssl"
224       pw_crypto_AES_BACKEND="//pw_crypto:aes_boringssl"
225   '
226
227   ninja -C out
228
229If using Bazel, add the BoringSSL repository to your WORKSPACE or MODULE.bazel
230and select appropriate backends by adding them to your project's `platform
231<https://bazel.build/extending/platforms>`_:
232
233.. code-block:: python
234
235   platform(
236     name = "my_platform",
237     constraint_values = [
238       "@pigweed//pw_aes:aes_boringssl_backend",
239       # ... other constraint_values
240     ],
241   )
242
243------------
244Size Reports
245------------
246Below are size reports for each crypto service. These vary across
247configurations.
248
249.. TODO: b/388905812 - Re-enable the size report.
250.. .. include:: size_report
251.. include:: ../size_report_notice
252
253-------------
254API reference
255-------------
256.. doxygenfunction:: pw::crypto::ecdsa::VerifyP256Signature(ConstByteSpan public_key, ConstByteSpan digest, ConstByteSpan signature)
257.. doxygenfunction:: pw::crypto::sha256::Hash(ConstByteSpan message, ByteSpan out_digest)
258.. doxygenfunction:: pw::crypto::sha256::Hash(stream::Reader& reader, ByteSpan out_digest)
259.. doxygenvariable:: pw::crypto::sha256::kDigestSizeBytes
260.. doxygenfunction:: pw::crypto::sha256::Sha256::Final(ByteSpan out_digest)
261.. doxygenfunction:: pw::crypto::sha256::Sha256::Update(ConstByteSpan data)
262.. doxygenenum::     pw::crypto::sha256::Sha256State
263