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