1.. _module-pw_crypto: 2 3========= 4pw_crypto 5========= 6A set of safe (read: easy to use, hard to misuse) crypto APIs. 7 8The following crypto services are provided by this module. 9 101. Hashing a message with `SHA256`_. 112. Verifying a digital signature signed with `ECDSA`_ over the NIST P256 curve. 123. Many more to come ... 13 14------ 15SHA256 16------ 17 181. Obtaining a oneshot digest. 19 20.. code-block:: cpp 21 22 #include "pw_crypto/sha256.h" 23 24 std::byte digest[32]; 25 if (!pw::crypto::sha256::Hash(message, digest).ok()) { 26 // Handle errors. 27 } 28 29 // The content can also come from a pw::stream::Reader. 30 if (!pw::crypto::sha256::Hash(reader, digest).ok()) { 31 // Handle errors. 32 } 33 342. Hashing a long, potentially non-contiguous message. 35 36.. code-block:: cpp 37 38 #include "pw_crypto/sha256.h" 39 40 std::byte digest[32]; 41 42 if (!pw::crypto::sha256::Sha256() 43 .Update(chunk1).Update(chunk2).Update(chunk...) 44 .Final().ok()) { 45 // Handle errors. 46 } 47 48----- 49ECDSA 50----- 51 521. Verifying a digital signature signed with ECDSA over the NIST P256 curve. 53 54.. code-block:: cpp 55 56 #include "pw_crypto/sha256.h" 57 58 std::byte digest[32]; 59 if (!pw::crypto::sha256::Hash(message, digest).ok()) { 60 // handle errors. 61 } 62 63 if (!pw::crypto::ecdsa::VerifyP256Signature(public_key, digest, 64 signature).ok()) { 65 // handle errors. 66 } 67 682. Verifying a digital signature signed with ECDSA over the NIST P256 curve, 69 with a long and/or non-contiguous message. 70 71.. code-block:: cpp 72 73 #include "pw_crypto/sha256.h" 74 75 std::byte digest[32]; 76 77 if (!pw::crypto::sha256::Sha256() 78 .Update(chunk1).Update(chunk2).Update(chunkN) 79 .Final(digest).ok()) { 80 // Handle errors. 81 } 82 83 if (!pw::crypto::ecdsa::VerifyP256Signature(public_key, digest, 84 signature).ok()) { 85 // Handle errors. 86 } 87 88------------- 89Configuration 90------------- 91 92The crypto services offered by pw_crypto can be backed by different backend 93crypto libraries. 94 95Mbed TLS 96======== 97 98The `Mbed TLS project <https://www.trustedfirmware.org/projects/mbed-tls/>`_ 99is a mature and full-featured crypto library that implements cryptographic 100primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. 101 102The project also has good support for interfacing to cryptographic accelerators. 103 104The small code footprint makes the project suitable and popular for embedded 105systems. 106 107To select the Mbed TLS backend, the MbedTLS library needs to be installed and 108configured. If using GN, do, 109 110.. code-block:: sh 111 112 # Install and configure MbedTLS 113 pw package install mbedtls 114 gn gen out --args=' 115 dir_pw_third_party_mbedtls=getenv("PW_PACKAGE_ROOT")+"/mbedtls" 116 pw_crypto_SHA256_BACKEND="//pw_crypto:sha256_mbedtls_v3" 117 pw_crypto_ECDSA_BACKEND="//pw_crypto:ecdsa_mbedtls_v3" 118 ' 119 120 ninja -C out 121 122If using Bazel, add the Mbed TLS repository to your WORKSPACE and select 123appropriate backends by adding them to your project's `platform 124<https://bazel.build/extending/platforms>`_: 125 126.. code-block:: python 127 128 platform( 129 name = "my_platform", 130 constraint_values = [ 131 "@pigweed//pw_crypto:sha256_mbedtls_backend", 132 "@pigweed//pw_crypto:ecdsa_mbedtls_backend", 133 # ... other constraint_values 134 ], 135 ) 136 137For optimal code size and/or performance, the Mbed TLS library can be configured 138per product. Mbed TLS configuration is achieved by turning on and off MBEDTLS_* 139options in a config.h file. See //third_party/mbedtls for how this is done. 140 141``pw::crypto::sha256`` does not need any special configuration as it uses the 142mbedtls_sha256_* APIs directly. However you can optionally turn on 143``MBEDTLS_SHA256_SMALLER`` to further reduce the code size to from 3KiB to 144~1.8KiB at a ~30% slowdown cost (Cortex-M4). 145 146.. code-block:: c 147 148 #define MBEDTLS_SHA256_SMALLER 149 150``pw::crypto::ecdsa`` requires the following minimum configurations which yields 151a code size of ~12KiB. 152 153.. code-block:: c 154 155 #define MBEDTLS_BIGNUM_C 156 #define MBEDTLS_ECP_C 157 #define MBEDTLS_ECDSA_C 158 // The ASN1 options are needed only because mbedtls considers and verifies 159 // them (in check_config.h) as dependencies of MBEDTLS_ECDSA_C. 160 #define MBEDTLS_ASN1_WRITE_C 161 #define MBEDTLS_ASN1_PARSE_C 162 #define MBEDTLS_ECP_NO_INTERNAL_RNG 163 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED 164 165Micro ECC 166========= 167 168.. Warning:: 169 Micro ECC's upstream hasn't received any updates since April 2023. 170 Please investigate to make sure that it meets your product's security 171 requirements before use. 172 173To select Micro ECC, the library needs to be installed and configured. 174 175.. code-block:: sh 176 177 # Install and configure Micro ECC 178 pw package install micro-ecc 179 gn gen out --args=' 180 dir_pw_third_party_micro_ecc=getenv("PW_PACKAGE_ROOT")+"/micro-ecc" 181 pw_crypto_ECDSA_BACKEND="//pw_crypto:ecdsa_uecc" 182 ' 183 184The default micro-ecc backend uses big endian as is standard practice. It also 185has a little-endian configuration which can be used to slightly reduce call 186stack frame use and/or when non pw_crypto clients use the same micro-ecc 187with a little-endian configuration. The little-endian version of micro-ecc 188can be selected with ``pw_crypto_ECDSA_BACKEND="//pw_crypto:ecdsa_uecc_little_endian"`` 189 190Note Micro-ECC does not implement any hashing functions, so you will need to use other backends for SHA256 functionality if needed. 191 192------------ 193Size Reports 194------------ 195 196Below are size reports for each crypto service. These vary across 197configurations. 198 199.. include:: size_report 200 201------------- 202API reference 203------------- 204.. doxygenfunction:: pw::crypto::ecdsa::VerifyP256Signature(ConstByteSpan public_key, ConstByteSpan digest, ConstByteSpan signature) 205.. doxygenfunction:: pw::crypto::sha256::Hash(ConstByteSpan message, ByteSpan out_digest) 206.. doxygenfunction:: pw::crypto::sha256::Hash(stream::Reader& reader, ByteSpan out_digest) 207.. doxygenvariable:: pw::crypto::sha256::kDigestSizeBytes 208.. doxygenfunction:: pw::crypto::sha256::Sha256::Final(ByteSpan out_digest) 209.. doxygenfunction:: pw::crypto::sha256::Sha256::Update(ConstByteSpan data) 210.. doxygenenum:: pw::crypto::sha256::Sha256State 211