|
| 1 | +/*! |
| 2 | + \ingroup PUF |
| 3 | +
|
| 4 | + For a complete bare-metal example (tested on NUCLEO-H563ZI), see |
| 5 | + https://github.com/wolfSSL/wolfssl-examples/tree/master/puf |
| 6 | +*/ |
| 7 | + |
| 8 | +/*! |
| 9 | + \ingroup PUF |
| 10 | +
|
| 11 | + \brief Initialize a wc_PufCtx structure, zeroing all fields. |
| 12 | + Must be called before any other PUF operations. |
| 13 | +
|
| 14 | + \return 0 on success |
| 15 | + \return BAD_FUNC_ARG if ctx is NULL |
| 16 | +
|
| 17 | + \param ctx pointer to wc_PufCtx structure to initialize |
| 18 | +
|
| 19 | + _Example_ |
| 20 | + \code |
| 21 | + wc_PufCtx ctx; |
| 22 | + ret = wc_PufInit(&ctx); |
| 23 | + \endcode |
| 24 | +
|
| 25 | + \sa wc_PufReadSram |
| 26 | + \sa wc_PufEnroll |
| 27 | + \sa wc_PufZeroize |
| 28 | +*/ |
| 29 | +int wc_PufInit(wc_PufCtx* ctx); |
| 30 | + |
| 31 | +/*! |
| 32 | + \ingroup PUF |
| 33 | +
|
| 34 | + \brief Read raw SRAM data into the PUF context. The sramAddr should |
| 35 | + point to a NOLOAD linker section to preserve the power-on state. |
| 36 | +
|
| 37 | + \return 0 on success |
| 38 | + \return BAD_FUNC_ARG if ctx or sramAddr is NULL |
| 39 | + \return PUF_READ_E if sramSz < WC_PUF_RAW_BYTES |
| 40 | +
|
| 41 | + \param ctx pointer to wc_PufCtx structure |
| 42 | + \param sramAddr pointer to raw SRAM memory region |
| 43 | + \param sramSz size of SRAM buffer (must be >= WC_PUF_RAW_BYTES) |
| 44 | +
|
| 45 | + _Example_ |
| 46 | + \code |
| 47 | + __attribute__((section(".puf_sram"))) |
| 48 | + static volatile uint8_t puf_sram[256]; |
| 49 | + wc_PufReadSram(&ctx, (const byte*)puf_sram, sizeof(puf_sram)); |
| 50 | + \endcode |
| 51 | +
|
| 52 | + \sa wc_PufInit |
| 53 | + \sa wc_PufEnroll |
| 54 | + \sa wc_PufReconstruct |
| 55 | +*/ |
| 56 | +int wc_PufReadSram(wc_PufCtx* ctx, const byte* sramAddr, word32 sramSz); |
| 57 | + |
| 58 | +/*! |
| 59 | + \ingroup PUF |
| 60 | +
|
| 61 | + \brief Perform PUF enrollment. Encodes raw SRAM using BCH(127,64,t=10) |
| 62 | + and generates public helper data. After enrollment the context is ready |
| 63 | + for key derivation and identity retrieval. |
| 64 | +
|
| 65 | + \return 0 on success |
| 66 | + \return BAD_FUNC_ARG if ctx is NULL |
| 67 | + \return PUF_ENROLL_E if enrollment fails |
| 68 | +
|
| 69 | + \param ctx pointer to wc_PufCtx (must have SRAM data loaded) |
| 70 | +
|
| 71 | + _Example_ |
| 72 | + \code |
| 73 | + wc_PufEnroll(&ctx); |
| 74 | + XMEMCPY(helperData, ctx.helperData, WC_PUF_HELPER_BYTES); |
| 75 | + \endcode |
| 76 | +
|
| 77 | + \sa wc_PufReadSram |
| 78 | + \sa wc_PufReconstruct |
| 79 | + \sa wc_PufDeriveKey |
| 80 | +*/ |
| 81 | +int wc_PufEnroll(wc_PufCtx* ctx); |
| 82 | + |
| 83 | +/*! |
| 84 | + \ingroup PUF |
| 85 | +
|
| 86 | + \brief Reconstruct stable PUF bits from noisy SRAM using stored helper |
| 87 | + data. BCH error correction (t=10) corrects up to 10 bit flips per |
| 88 | + 127-bit codeword. |
| 89 | +
|
| 90 | + \return 0 on success |
| 91 | + \return BAD_FUNC_ARG if ctx or helperData is NULL |
| 92 | + \return PUF_RECONSTRUCT_E on failure (too many bit errors or helperSz |
| 93 | + too small) |
| 94 | +
|
| 95 | + \param ctx pointer to wc_PufCtx (must have SRAM data loaded) |
| 96 | + \param helperData pointer to helper data from previous enrollment |
| 97 | + \param helperSz size of helper data (>= WC_PUF_HELPER_BYTES) |
| 98 | +
|
| 99 | + _Example_ |
| 100 | + \code |
| 101 | + wc_PufReconstruct(&ctx, helperData, sizeof(helperData)); |
| 102 | + \endcode |
| 103 | +
|
| 104 | + \sa wc_PufEnroll |
| 105 | + \sa wc_PufDeriveKey |
| 106 | + \sa wc_PufGetIdentity |
| 107 | +*/ |
| 108 | +int wc_PufReconstruct(wc_PufCtx* ctx, const byte* helperData, word32 helperSz); |
| 109 | + |
| 110 | +/*! |
| 111 | + \ingroup PUF |
| 112 | +
|
| 113 | + \brief Derive a cryptographic key from PUF stable bits using HKDF. |
| 114 | + Uses SHA-256 by default, or SHA3-256 when WC_PUF_SHA3 is defined. |
| 115 | + The info parameter provides domain separation for multiple keys. |
| 116 | + Requires HAVE_HKDF. |
| 117 | +
|
| 118 | + \return 0 on success |
| 119 | + \return BAD_FUNC_ARG if ctx or key is NULL, or keySz is 0 |
| 120 | + \return PUF_DERIVE_KEY_E if PUF not ready or HKDF fails |
| 121 | +
|
| 122 | + \param ctx pointer to wc_PufCtx (must be enrolled or reconstructed) |
| 123 | + \param info optional context info for domain separation (may be NULL) |
| 124 | + \param infoSz size of info in bytes |
| 125 | + \param key output buffer for derived key |
| 126 | + \param keySz desired key size in bytes |
| 127 | +
|
| 128 | + _Example_ |
| 129 | + \code |
| 130 | + byte key[32]; |
| 131 | + const byte info[] = "my-app-key"; |
| 132 | + wc_PufDeriveKey(&ctx, info, sizeof(info), key, sizeof(key)); |
| 133 | + \endcode |
| 134 | +
|
| 135 | + \sa wc_PufEnroll |
| 136 | + \sa wc_PufReconstruct |
| 137 | + \sa wc_PufGetIdentity |
| 138 | +*/ |
| 139 | +int wc_PufDeriveKey(wc_PufCtx* ctx, const byte* info, word32 infoSz, |
| 140 | + byte* key, word32 keySz); |
| 141 | + |
| 142 | +/*! |
| 143 | + \ingroup PUF |
| 144 | +
|
| 145 | + \brief Retrieve the device identity hash (SHA-256 or SHA3-256 of stable |
| 146 | + bits). Deterministic for a given device. |
| 147 | +
|
| 148 | + \return 0 on success |
| 149 | + \return BAD_FUNC_ARG if ctx or id is NULL |
| 150 | + \return PUF_IDENTITY_E if PUF not ready or idSz < WC_PUF_ID_SZ |
| 151 | +
|
| 152 | + \param ctx pointer to wc_PufCtx (must be enrolled or reconstructed) |
| 153 | + \param id output buffer for identity hash |
| 154 | + \param idSz size of id buffer (>= WC_PUF_ID_SZ, 32 bytes) |
| 155 | +
|
| 156 | + _Example_ |
| 157 | + \code |
| 158 | + byte identity[WC_PUF_ID_SZ]; |
| 159 | + wc_PufGetIdentity(&ctx, identity, sizeof(identity)); |
| 160 | + \endcode |
| 161 | +
|
| 162 | + \sa wc_PufEnroll |
| 163 | + \sa wc_PufReconstruct |
| 164 | + \sa wc_PufDeriveKey |
| 165 | +*/ |
| 166 | +int wc_PufGetIdentity(wc_PufCtx* ctx, byte* id, word32 idSz); |
| 167 | + |
| 168 | +/*! |
| 169 | + \ingroup PUF |
| 170 | +
|
| 171 | + \brief Securely zeroize all sensitive data in the PUF context using |
| 172 | + ForceZero. Call when PUF is no longer needed. |
| 173 | +
|
| 174 | + \return 0 on success |
| 175 | + \return BAD_FUNC_ARG if ctx is NULL |
| 176 | +
|
| 177 | + \param ctx pointer to wc_PufCtx to zeroize |
| 178 | +
|
| 179 | + _Example_ |
| 180 | + \code |
| 181 | + wc_PufZeroize(&ctx); |
| 182 | + \endcode |
| 183 | +
|
| 184 | + \sa wc_PufInit |
| 185 | +*/ |
| 186 | +int wc_PufZeroize(wc_PufCtx* ctx); |
| 187 | + |
| 188 | +/*! |
| 189 | + \ingroup PUF |
| 190 | +
|
| 191 | + \brief Inject synthetic SRAM test data for testing without hardware. |
| 192 | + Only available when WOLFSSL_PUF_TEST is defined. |
| 193 | +
|
| 194 | + \return 0 on success |
| 195 | + \return BAD_FUNC_ARG if ctx or data is NULL |
| 196 | + \return PUF_READ_E if sz < WC_PUF_RAW_BYTES |
| 197 | +
|
| 198 | + \param ctx pointer to wc_PufCtx |
| 199 | + \param data pointer to synthetic SRAM data |
| 200 | + \param sz size of data (>= WC_PUF_RAW_BYTES, 256 bytes) |
| 201 | +
|
| 202 | + _Example_ |
| 203 | + \code |
| 204 | + byte testSram[WC_PUF_RAW_BYTES]; |
| 205 | + wc_PufSetTestData(&ctx, testSram, sizeof(testSram)); |
| 206 | + \endcode |
| 207 | +
|
| 208 | + \sa wc_PufInit |
| 209 | + \sa wc_PufReadSram |
| 210 | +*/ |
| 211 | +int wc_PufSetTestData(wc_PufCtx* ctx, const byte* data, word32 sz); |
0 commit comments