1 /*
2  * Copyright (c) 2001-2022, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef POLY_H
8 #define POLY_H
9 
10 /*
11  * All the includes that are needed for code using this module to
12  * compile correctly should be #included here.
13  */
14 #include <stdint.h>
15 #include "cc_error.h"
16 #include "mbedtls_cc_poly.h"
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /*! The POLY block size in 32-bit words */
23 #define CC_POLY_BLOCK_SIZE_IN_WORDS  4
24 #define CC_POLY_BLOCK_SIZE_IN_BYTES  (CC_POLY_BLOCK_SIZE_IN_WORDS*CC_32BIT_WORD_SIZE)
25 
26 #define POLY_PRIME_SIZE_IN_BITS   130
27 #define POLY_PRIME_SIZE_IN_WORDS  CALC_FULL_32BIT_WORDS(POLY_PRIME_SIZE_IN_BITS)
28 
29 /*! The POLY PKA registers size in 32-bit words */
30 #define CC_POLY_PKA_REG_SIZE_IN_PKA_WORDS  4
31 #define CC_POLY_PKA_REG_SIZE_IN_WORDS  (CC_POLY_PKA_REG_SIZE_IN_PKA_WORDS * (CALC_FULL_32BIT_WORDS(CC_PKA_WORD_SIZE_IN_BITS)))
32 #define CC_POLY_PKA_REG_SIZE_IN_BYTES  (CC_POLY_PKA_REG_SIZE_IN_WORDS*CC_32BIT_WORD_SIZE)
33 
34 /**
35  * PKA register contexts. Between multipart calls, the PKA engine needs to save
36  * and restore the register context. It's composed of the clamped key pair
37  * (r,s) 256 bit long and the value of the accumulator register which is mod P,
38  * where P is 2^130-5, which in full words is 160 bit long, 5 32-bit words.
39  */
40 typedef struct PolyPkaContext {
41     uint32_t key[8]; /*!< (r,s) concatenated with r already clamped */
42     uint32_t acc[5]; /*!< Value of the accumulator modulus P, i.e. [0,2^130-5)*/
43 } PolyPkaContext_t;
44 
45 /**
46  * State information required to support multipart APIs in AEAD for MAC
47  * computation. As Poly1305 operates on CC_POLY_BLOCK_SIZE_IN BYTES of data
48  * it needs to cache up to CC_POLY_BLOCK_SIZE_IN_BYTES-1 of the input. But
49  * for practical reasons (i.e. working on 4-byte aligned buffers) we store an
50  * entire block of 16 bytes that can be processed in one go without additional
51  * copies
52  */
53 typedef struct PolyState {
54     uint32_t msg_state[CC_POLY_BLOCK_SIZE_IN_WORDS]; /*!< Equals 16 bytes of
55                                                       *   data
56                                                       */
57     uint8_t msg_state_size;  /*!< Size of the message buffered in msg_state */
58     PolyPkaContext_t context; /*!< PKA registers context (clamped key, acc) */
59 } PolyState_t;
60 
61 /**
62  * @brief Generates the POLY mac according to RFC 7539 section 2.5.1
63  *
64  * @param[in]  key            Pointer to 256 bits of KEY.
65  * @param[in]  pAddData       Optional - pointer to additional data if any
66  * @param[in]  addDataSize    The size of the additional data
67  * @param[in]  pDataIn        Pointer to data buffer to calculate MAC on
68  * @param[in]  dataInSize     The size of the additional data
69  * @param[out] macRes         The calculated MAC
70  * @param[in]  isPolyAeadMode Boolean indicating if the Poly MAC operation is
71  *                            part of AEAD or just poly. In AEAD mode, the
72  *                            last block of AddData and DataIn accumulation
73  *                            will be padded with zeros up to 16 bytes as per
74  *                            the AEAD spec construction on RFC7539.
75  *
76  * @return  CC_OK On success, otherwise indicates failure
77  */
78 CCError_t PolyMacCalc(mbedtls_poly_key key,
79                       const uint8_t *pAddData,
80                       size_t addDataSize,
81                       const uint8_t *pDataIn,
82                       size_t dataInSize,
83                       mbedtls_poly_mac macRes,
84                       bool isPolyAeadMode);
85 
86 /**
87  * @brief Initialises a multipart authentication.
88  *
89  * @param[in,out] state    Pointer to the state associated to the operation.
90  * @param[in,out] key      Buffer containing the (r,s) keypair.
91  * @param[in]     key_size Size in bytes of the key. Must be 32 bytes.
92  *
93  * @return It returns CC_OK on success, or an error code otherwise
94  */
95 CCError_t PolyInit(PolyState_t *state, const uint8_t *key, size_t key_size);
96 
97 /**
98  * @brief Updates a pre-initialised multipart authentication with a new
99  *        chunk of data to be authenticated.
100  *
101  * @param[in,out] state      Pointer to the state associated to the operation.
102  * @param[in]     data       Buffer containing the data to be authenticated.
103  * @param[in]     data_size  Size in bytes of the data to be authenticated.
104  * @param[in] isPolyAeadMode Boolean indicating if the update is the last
105  *                           of an AEAD operation. In that case, it will pad
106  *                           the last partial block with zeros to make a
107  *                           full block as specified on RFC7539.
108  *
109  * @return It returns CC_OK on success, or an error code otherwise
110  */
111 CCError_t PolyUpdate(PolyState_t *state,
112                      const uint8_t *data,
113                      size_t data_size,
114                      bool isPolyAeadMode);
115 
116 /**
117  * @brief Finalises a pre-initialised multipart authentication outputting
118  *        the 16 bytes that make the Poly1305 tag.
119  *
120  * @param[in,out] state    Pointer to the state associated to the operation.
121  * @param[out]    tag      Buffer that will contain the 16 bytes of the tag.
122  * @param[in]     tag_size Size in bytes ot the tag buffer. It needs to be
123  *                         at least 16 bytes, i.e. CC_POLY_BLOCK_SIZE_IN_BYTES
124  *
125  * @return It returns CC_OK on success, or an error code otherwise
126  */
127 CCError_t PolyFinish(PolyState_t *state, uint8_t *tag, size_t tag_size);
128 
129 #ifdef __cplusplus
130 }
131 #endif
132 
133 #endif  /* POLY_H */
134