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#ifdef OTCRYPTO_STATUS_DEBUG
30
31#define OTCRYPTO_RECOV_ERR \
32 ((status_t){.value = (int32_t)(0x80000000 | MODULE_ID | \
33 ((__LINE__ & 0x7ff) << 5) | kAborted)})
34#define OTCRYPTO_FATAL_ERR \
35 ((status_t){.value = \
36 (int32_t)(0x80000000 | MODULE_ID | \
37 ((__LINE__ & 0x7ff) << 5) | kFailedPrecondition)})
38#define OTCRYPTO_BAD_ARGS \
39 ((status_t){.value = \
40 (int32_t)(0x80000000 | MODULE_ID | \
41 ((__LINE__ & 0x7ff) << 5) | kInvalidArgument)})
42#define OTCRYPTO_ASYNC_INCOMPLETE \
43 ((status_t){.value = (int32_t)(0x80000000 | MODULE_ID | \
44 ((__LINE__ & 0x7ff) << 5) | kUnavailable)})
45#define OTCRYPTO_NOT_IMPLEMENTED \
46 ((status_t){.value = (int32_t)(0x80000000 | MODULE_ID | \
47 ((__LINE__ & 0x7ff) << 5) | kUnimplemented)})
48#else
49
50#define OTCRYPTO_RECOV_ERR \
51 ((status_t){.value = kOtcryptoStatusValueInternalError})
52#define OTCRYPTO_FATAL_ERR ((status_t){.value = kOtcryptoStatusValueFatalError})
53#define OTCRYPTO_BAD_ARGS ((status_t){.value = kOtcryptoStatusValueBadArgs})
54#define OTCRYPTO_ASYNC_INCOMPLETE \
55 ((status_t){.value = kOtcryptoStatusValueAsyncIncomplete})
56#define OTCRYPTO_NOT_IMPLEMENTED \
57 ((status_t){.value = kOtcryptoStatusValueNotImplemented})
58
59#endif
60
61#if !defined(OT_DISABLE_HARDENING) && defined(OT_PLATFORM_RV32)
62/**
63 * Hardened version of the `TRY` macro from `status.h`.
64 *
65 * Returns an error if either expr_ represents an error, or if the OK code does
66 * not match the expected hardened value.
67 *
68 * To optimize code size this macro uses 16b branch on zero instructions with
69 * respective arithmetic for comparisons. In both the case where the status is
70 * OK or not, an additional check is performed to stop potential fault attacks
71 * by doubling the branch. More specifically, in both the case where the status
72 * is OK or not an additional check is performed to stop potential fault
73 * attacks.
74 *
75 * This macro specifically uses the fact that error statuses are negative
76 * values.
77 *
78 * @param expr_ An expression that evaluates to a `status_t`.
79 * @return The enclosed OK value.
80 */
81#define HARDENED_TRY(expr_) \
82 do { \
83 uint32_t status_ = OT_UNSIGNED(expr_.value); \
84 asm volatile("addi %[status_], %[status_], -%[kHardenedBoolTrue]" \
85 : [status_] "+r"(status_) \
86 : [kHardenedBoolTrue] "i"(kHardenedBoolTrue) \
87 :); \
88 if (status_) { \
89 asm volatile("addi %[status_], %[status_], %[kHardenedBoolTrue]" \
90 : [status_] "+r"(status_) \
91 : [kHardenedBoolTrue] "i"(kHardenedBoolTrue) \
92 :); \
93 if ((int32_t)(status_) < 0) { \
94 return (status_t){.value = (int32_t)(status_ | 0x80000000)}; \
95 } \
96 asm volatile("unimp"); \
97 } \
98 if (launder32(status_)) { \
99 asm volatile("unimp"); \
100 } \
101 } while (false)
102#else // !OT_PLATFORM_RV32 || OT_DISABLE_HARDENING
103/**
104 * Alternate version of HARDENED_TRY that is logically equivalent.
105 *
106 * This can be used to measure the code size and performance impact of
107 * control-flow countermeasures.
108 *
109 * @param expr_ An expression that evaluates to a `status_t`.
110 * @return The enclosed OK value.
111 */
112#define HARDENED_TRY(expr_) \
113 do { \
114 status_t status_ = expr_; \
115 if (status_.value != kHardenedBoolTrue) { \
116 return (status_t){ \
117 .value = (int32_t)(OT_UNSIGNED(status_.value) | 0x80000000)}; \
118 } \
119 status_.value; \
120 } while (false)
121
122#endif // OT_DISABLE_HARDENING
123
124#ifdef __cplusplus
125}
126#endif
127
128#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_STATUS_H_