1 /*
2  * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * \file integrity_checker_drv.h
19  * \brief Driver for Arm Integrity Checker.
20  */
21 
22 #ifndef __INTEGRITY_CHECKER_DRV_H__
23 #define __INTEGRITY_CHECKER_DRV_H__
24 
25 #include <stdint.h>
26 #include <stddef.h>
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #define INTEGRITY_CHECKER_CONFIG_REMAP_REGION_AM 4
33 
34 #define INTEGRITY_CHECKER_OUTPUT_SIZE_ZERO_COUNT  4
35 #define INTEGRITY_CHECKER_OUTPUT_SIZE_CRC32       4
36 #define INTEGRITY_CHECKER_OUTPUT_SIZE_SHA256     32
37 
38 #define INTEGRITY_CHECKER_REQUIRED_ALIGNMENT     8
39 
40 enum integrity_checker_error_t {
41     INTEGRITY_CHECKER_ERROR_NONE = 0x0u,
42     INTEGRITY_CHECKER_ERROR_OUTPUT_BUFFER_TOO_SMALL,
43     INTEGRITY_CHECKER_ERROR_VALUE_BUFFER_TOO_SMALL,
44     INTEGRITY_CHECKER_ERROR_UNSUPPORTED_MODE,
45     INTEGRITY_CHECKER_ERROR_COMPARISON_FAILED,
46     INTEGRITY_CHECKER_ERROR_OPERATION_FAILED,
47     INTEGRITY_CHECKER_ERROR_INVALID_ALIGNMENT,
48     INTEGRITY_CHECKER_ERROR_INVALID_LENGTH,
49 };
50 
51 enum integrity_checker_mode_t {
52     INTEGRITY_CHECKER_MODE_ZERO_COUNT = 0b00,
53     INTEGRITY_CHECKER_MODE_CRC32      = 0b01,
54     INTEGRITY_CHECKER_MODE_SHA256     = 0b10,
55 };
56 
57 typedef struct {
58     uintptr_t region_base; /*!< The base of the region that will be remapped */
59     size_t region_size;    /*!< The size of the region that will be remapped */
60     uintptr_t remap_base;  /*!< The base of the region that mapped to */
61     size_t remap_cpusel_offset; /*!< How much the remap will be incremented per cpu */
62 } integrity_checker_remap_region_t;
63 
64 /**
65  * \brief ARM Integrity Checker device configuration structure
66  */
67 struct integrity_checker_dev_cfg_t {
68     const uintptr_t base;                         /*!< Integrity Checker base address */
69     uint32_t remap_cpusel;
70     integrity_checker_remap_region_t remap_regions[INTEGRITY_CHECKER_CONFIG_REMAP_REGION_AM];
71 };
72 
73 /**
74  * \brief ARM Integrity Checker device structure
75  */
76 struct integrity_checker_dev_t {
77     const struct integrity_checker_dev_cfg_t *const cfg;       /*!< Integrity Checker configuration */
78 };
79 
80 /**
81  * \brief                    Compute an integrity value of a given buffer and
82  *                           output it.
83  *
84  * \param[in]  dev           The Integrity Checker device.
85  * \param[in]  mode          Which mode the Integrity Checker should use to
86  *                           calculate the integrity value. This may change the
87  *                           size of the output value.
88  * \param[in]  data          The buffer to calculate the integrity value from.
89  * \param[in]  size          The size of the data buffer.
90  * \param[out] value         The buffer to write the integrity value into.
91  * \param[in]  value_size    The size of the buffer to write the integrity value
92  *                           into.
93  * \param[out] value_len     The length of the outputted integrity value. This
94  *                           value can be NULL if the integrity value length
95  *                           isn't needed
96  *
97  * \return                   INTEGRITY_CHECKER_ERROR_NONE on success, otherwise
98  *                           a different integrity_checker_error_t.
99  */
100 enum integrity_checker_error_t integrity_checker_compute_value(struct integrity_checker_dev_t *dev,
101                                                                enum integrity_checker_mode_t mode,
102                                                                const uint32_t *data, size_t size,
103                                                                uint32_t *value, size_t value_size,
104                                                                size_t *value_len);
105 
106 /**
107  * \brief                    Check the integrity value of a given buffer against
108  *                           a given value.
109  *
110  * \param[in]  dev           The Integrity Checker device.
111  * \param[in]  mode          Which mode the Integrity Checker should use to
112  *                           calculate the integrity value. This may change the
113  *                           size that will be read from the value buffer.
114  * \param[in]  data          The buffer to calculate the integrity value from.
115  * \param[in]  size          The size of the data buffer.
116  * \param[in]  value         The buffer to read the integrity value from.
117  * \param[in]  value_size    The size of the buffer to read the integrity value
118  *                           from.
119  *
120  * \return                   INTEGRITY_CHECKER_ERROR_NONE on success,
121  *                           INTEGRITY_CHECKER_ERROR_COMPARISON_FAILED if the
122  *                           integrity value does not match the computed value,
123  *                           otherwise a different integrity_checker_error_t.
124  */
125 enum integrity_checker_error_t integrity_checker_check_value(struct integrity_checker_dev_t *dev,
126                                                              enum integrity_checker_mode_t mode,
127                                                              const uint32_t *data, size_t size,
128                                                              const uint32_t *value, size_t value_size);
129 
130 
131 #ifdef __cplusplus
132 }
133 #endif
134 
135 #endif /* __INTEGRITY_CHECKER_DRV_H__ */
136