Software APIs
status.h
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_STATUS_H_
6#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_STATUS_H_
7
9#include "sw/device/lib/base/status.h"
11
12#ifdef __cplusplus
13extern "C" {
14#endif
15
16/**
17 * Values in `status_t` that are guaranteed to correspond to each
18 * `otcrypto_status_t` value.
19 *
20 * If `OTCRYPTO_STATUS_DEBUG` is set, full line-number and module information
21 * is included to ease debugging. Otherwise, we use the cryptolib error codes
22 * directly.
23 *
24 * Note: These values bypass `status_create` to avoid having a function call in
25 * error cases, where we may be under attack and complexity should be
26 * minimized.
27 */
28#define OTCRYPTO_OK ((status_t){.value = kHardenedBoolTrue})
29
30#define LAUNDERED_OTCRYPTO_OK \
31 ((status_t){.value = (int)launder32(kHardenedBoolTrue)})
32
33#ifdef OTCRYPTO_STATUS_DEBUG
34
35#define OTCRYPTO_RECOV_ERR \
36 ((status_t){.value = (int32_t)(0x80000000 | \
37 status_encode_module_id(MODULE_ID) << 16 | \
38 ((__LINE__ & 0x7ff) << 5) | kAborted)})
39#define OTCRYPTO_FATAL_ERR \
40 ((status_t){.value = \
41 (int32_t)(0x80000000 | \
42 status_encode_module_id(MODULE_ID) << 16 | \
43 ((__LINE__ & 0x7ff) << 5) | kFailedPrecondition)})
44#define OTCRYPTO_BAD_ARGS \
45 ((status_t){.value = \
46 (int32_t)(0x80000000 | \
47 status_encode_module_id(MODULE_ID) << 16 | \
48 ((__LINE__ & 0x7ff) << 5) | kInvalidArgument)})
49#define OTCRYPTO_ASYNC_INCOMPLETE \
50 ((status_t){.value = (int32_t)(0x80000000 | \
51 status_encode_module_id(MODULE_ID) << 16 | \
52 ((__LINE__ & 0x7ff) << 5) | kUnavailable)})
53#define OTCRYPTO_NOT_IMPLEMENTED \
54 ((status_t){.value = (int32_t)(0x80000000 | \
55 status_encode_module_id(MODULE_ID) << 16 | \
56 ((__LINE__ & 0x7ff) << 5) | kUnimplemented)})
57#else
58
59#define OTCRYPTO_RECOV_ERR \
60 ((status_t){.value = kOtcryptoStatusValueInternalError})
61#define OTCRYPTO_FATAL_ERR ((status_t){.value = kOtcryptoStatusValueFatalError})
62#define OTCRYPTO_BAD_ARGS ((status_t){.value = kOtcryptoStatusValueBadArgs})
63#define OTCRYPTO_ASYNC_INCOMPLETE \
64 ((status_t){.value = kOtcryptoStatusValueAsyncIncomplete})
65#define OTCRYPTO_NOT_IMPLEMENTED \
66 ((status_t){.value = kOtcryptoStatusValueNotImplemented})
67
68#endif
69
70#if !defined(OT_DISABLE_HARDENING) && defined(OT_PLATFORM_RV32)
71/**
72 * Hardened version of the `TRY` macro from `status.h`.
73 *
74 * Returns an error if either expr_ represents an error, or if the OK code does
75 * not match the expected hardened value.
76 *
77 * To optimize code size this macro uses 16b branch on zero instructions with
78 * respective arithmetic for comparisons. In both the case where the status is
79 * OK or not, an additional check is performed to stop potential fault attacks
80 * by doubling the branch. More specifically, in both the case where the status
81 * is OK or not an additional check is performed to stop potential fault
82 * attacks.
83 *
84 * This macro specifically uses the fact that error statuses are negative
85 * values.
86 *
87 * @param expr_ An expression that evaluates to a `status_t`.
88 * @return The enclosed OK value.
89 */
90#define HARDENED_TRY(expr_) \
91 do { \
92 uint32_t status_ = OT_UNSIGNED(expr_.value); \
93 asm volatile("addi %[status_], %[status_], -%[kHardenedBoolTrue]" \
94 : [status_] "+r"(status_) \
95 : [kHardenedBoolTrue] "i"(kHardenedBoolTrue) \
96 :); \
97 if (status_) { \
98 asm volatile("addi %[status_], %[status_], %[kHardenedBoolTrue]" \
99 : [status_] "+r"(status_) \
100 : [kHardenedBoolTrue] "i"(kHardenedBoolTrue) \
101 :); \
102 if ((int32_t)(status_) < 0) { \
103 return (status_t){.value = (int32_t)(status_ | 0x80000000)}; \
104 } \
105 asm volatile("unimp"); \
106 } \
107 if (launder32(status_)) { \
108 asm volatile("unimp"); \
109 } \
110 } while (false)
111// COVERAGE (FI CM) We do not cover the redundant checks of the HARDENED_TRY as
112// they serve as redundant encoding against fault attacks.
113#else // !OT_PLATFORM_RV32 || OT_DISABLE_HARDENING
114/**
115 * Alternate version of HARDENED_TRY that is logically equivalent.
116 *
117 * This can be used to measure the code size and performance impact of
118 * control-flow countermeasures.
119 *
120 * @param expr_ An expression that evaluates to a `status_t`.
121 * @return The enclosed OK value.
122 */
123#define HARDENED_TRY(expr_) \
124 do { \
125 status_t status_ = expr_; \
126 if (status_.value != kHardenedBoolTrue) { \
127 return (status_t){ \
128 .value = (int32_t)(OT_UNSIGNED(status_.value) | 0x80000000)}; \
129 } \
130 status_.value; \
131 } while (false)
132
133#endif // OT_DISABLE_HARDENING
134
135#ifdef __cplusplus
136}
137#endif
138
139#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_STATUS_H_