1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3
4 /**
5 ***************************************************************************
6 * @file lac_sym_auth_enc.c
7 *
8 * @ingroup LacAuthEnc
9 *
10 * @description
11 * Authenticated encryption specific functionality.
12 * For CCM related code NIST SP 800-38C is followed.
13 * For GCM related code NIST SP 800-38D is followed.
14 ***************************************************************************/
15
16 /*
17 *******************************************************************************
18 * Include public/global header files
19 *******************************************************************************
20 */
21
22 #include "cpa.h"
23 #include "cpa_cy_sym.h"
24
25 #include "icp_accel_devices.h"
26 #include "icp_adf_init.h"
27 #include "icp_adf_transport.h"
28 #include "icp_adf_debug.h"
29 /*
30 *******************************************************************************
31 * Include private header files
32 *******************************************************************************
33 */
34 #include "lac_log.h"
35 #include "lac_common.h"
36 #include "lac_session.h"
37 #include "lac_sym_auth_enc.h"
38
39 /* These defines describe position of the flag fields
40 * in B0 block for CCM algorithm*/
41 #define LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT 6
42 #define LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT 3
43
44 /* This macro builds flags field to be put in B0 block for CCM algorithm */
45 #define LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(Adata, t, q) \
46 ((((Adata) > 0 ? 1 : 0) << LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT) | \
47 ((((t)-2) >> 1) << LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT) | ((q)-1))
48
49 /**
50 * @ingroup LacAuthEnc
51 */
52 CpaStatus
LacSymAlgChain_CheckCCMData(Cpa8U * pAdditionalAuthData,Cpa8U * pIv,Cpa32U messageLenToCipherInBytes,Cpa32U ivLenInBytes)53 LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData,
54 Cpa8U *pIv,
55 Cpa32U messageLenToCipherInBytes,
56 Cpa32U ivLenInBytes)
57 {
58 Cpa8U q = 0;
59
60 LAC_CHECK_NULL_PARAM(pIv);
61 LAC_CHECK_NULL_PARAM(pAdditionalAuthData);
62
63 /* check if n is within permitted range */
64 if (ivLenInBytes < LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN ||
65 ivLenInBytes > LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX) {
66 LAC_INVALID_PARAM_LOG2("ivLenInBytes for CCM algorithm "
67 "must be between %d and %d inclusive",
68 LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN,
69 LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX);
70 return CPA_STATUS_INVALID_PARAM;
71 }
72
73 q = LAC_ALG_CHAIN_CCM_NQ_CONST - ivLenInBytes;
74
75 /* Check if q is big enough to hold actual length of message to cipher
76 * if q = 8 -> maxlen = 2^64 always good as
77 * messageLenToCipherInBytes is 32 bits
78 * if q = 7 -> maxlen = 2^56 always good
79 * if q = 6 -> maxlen = 2^48 always good
80 * if q = 5 -> maxlen = 2^40 always good
81 * if q = 4 -> maxlen = 2^32 always good.
82 */
83 if ((messageLenToCipherInBytes >= (1 << (q * LAC_NUM_BITS_IN_BYTE))) &&
84 (q < sizeof(Cpa32U))) {
85 LAC_INVALID_PARAM_LOG(
86 "messageLenToCipherInBytes too long for the given"
87 " ivLenInBytes for CCM algorithm\n");
88 return CPA_STATUS_INVALID_PARAM;
89 }
90
91 return CPA_STATUS_SUCCESS;
92 }
93
94
95 /**
96 * @ingroup LacAuthEnc
97 */
98 void
LacSymAlgChain_PrepareCCMData(lac_session_desc_t * pSessionDesc,Cpa8U * pAdditionalAuthData,Cpa8U * pIv,Cpa32U messageLenToCipherInBytes,Cpa32U ivLenInBytes)99 LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc,
100 Cpa8U *pAdditionalAuthData,
101 Cpa8U *pIv,
102 Cpa32U messageLenToCipherInBytes,
103 Cpa32U ivLenInBytes)
104 {
105 Cpa8U n =
106 ivLenInBytes; /* assumes ivLenInBytes has been param checked */
107 Cpa8U q = LAC_ALG_CHAIN_CCM_NQ_CONST - n;
108 Cpa8U lenOfEncodedLen = 0;
109 Cpa16U lenAEncoded = 0;
110 Cpa32U bitStrQ = 0;
111
112 /* populate Ctr0 block - stored in pIv */
113 pIv[0] = (q - 1);
114 /* bytes 1 to n are already set with nonce by the user */
115 /* set last q bytes with 0 */
116 memset(pIv + n + 1, 0, q);
117
118 /* Encode the length of associated data 'a'. As the API limits the
119 * length
120 * of an array pointed by pAdditionalAuthData to be 240 bytes max, the
121 * maximum length of 'a' might be 240 - 16 - 2 = 222. Hence the encoding
122 * below is simplified. */
123 if (pSessionDesc->aadLenInBytes > 0) {
124 lenOfEncodedLen = sizeof(Cpa16U);
125 lenAEncoded = QAT_UTILS_HOST_TO_NW_16(
126 (Cpa16U)pSessionDesc->aadLenInBytes);
127 }
128
129 /* populate B0 block */
130 /* first, set the flags field */
131 pAdditionalAuthData[0] =
132 LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(lenOfEncodedLen,
133 pSessionDesc->hashResultSize,
134 q);
135 /* bytes 1 to n are already set with nonce by the user*/
136 /* put Q in bytes 16-q...15 */
137 bitStrQ = QAT_UTILS_HOST_TO_NW_32(messageLenToCipherInBytes);
138
139 if (q > sizeof(bitStrQ)) {
140 memset(pAdditionalAuthData + n + 1, 0, q);
141 memcpy(pAdditionalAuthData + n + 1 + (q - sizeof(bitStrQ)),
142 (Cpa8U *)&bitStrQ,
143 sizeof(bitStrQ));
144 } else {
145 memcpy(pAdditionalAuthData + n + 1,
146 ((Cpa8U *)&bitStrQ) + (sizeof(bitStrQ) - q),
147 q);
148 }
149
150 /* populate B1-Bn blocks */
151 if (lenAEncoded > 0) {
152 *(Cpa16U
153 *)(&pAdditionalAuthData[1 + LAC_ALG_CHAIN_CCM_NQ_CONST]) =
154 lenAEncoded;
155 /* Next bytes are already set by the user with
156 * the associated data 'a' */
157
158 /* Check if padding is required */
159 if (((pSessionDesc->aadLenInBytes + lenOfEncodedLen) %
160 LAC_HASH_AES_CCM_BLOCK_SIZE) != 0) {
161 Cpa8U paddingLen = 0;
162 Cpa8U paddingIndex = 0;
163
164 paddingLen = LAC_HASH_AES_CCM_BLOCK_SIZE -
165 ((pSessionDesc->aadLenInBytes + lenOfEncodedLen) %
166 LAC_HASH_AES_CCM_BLOCK_SIZE);
167
168 paddingIndex = 1 + LAC_ALG_CHAIN_CCM_NQ_CONST;
169 paddingIndex +=
170 lenOfEncodedLen + pSessionDesc->aadLenInBytes;
171
172 memset(&pAdditionalAuthData[paddingIndex],
173 0,
174 paddingLen);
175 }
176 }
177 }
178
179 /**
180 * @ingroup LacAuthEnc
181 */
182 void
LacSymAlgChain_PrepareGCMData(lac_session_desc_t * pSessionDesc,Cpa8U * pAdditionalAuthData)183 LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc,
184 Cpa8U *pAdditionalAuthData)
185 {
186 Cpa8U paddingLen = 0;
187
188 if ((pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE) != 0) {
189 paddingLen = LAC_HASH_AES_GCM_BLOCK_SIZE -
190 (pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE);
191
192 memset(&pAdditionalAuthData[pSessionDesc->aadLenInBytes],
193 0,
194 paddingLen);
195 }
196 }
197