xref: /freebsd/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c (revision 25f09d4a9c358c5452435d299e00c1a1bdafff87)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2025 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  * @ingroup LacAuthEnc
96  */
97 void
LacSymAlgChain_PrepareCCMData(lac_session_desc_t * pSessionDesc,Cpa8U * pAdditionalAuthData,Cpa8U * pIv,Cpa32U messageLenToCipherInBytes,Cpa32U ivLenInBytes)98 LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc,
99 			      Cpa8U *pAdditionalAuthData,
100 			      Cpa8U *pIv,
101 			      Cpa32U messageLenToCipherInBytes,
102 			      Cpa32U ivLenInBytes)
103 {
104 	Cpa8U n =
105 	    ivLenInBytes; /* assumes ivLenInBytes has been param checked */
106 	Cpa8U q = LAC_ALG_CHAIN_CCM_NQ_CONST - n;
107 	Cpa8U lenOfEncodedLen = 0;
108 	Cpa16U lenAEncoded = 0;
109 	Cpa32U bitStrQ = 0;
110 
111 	/* populate Ctr0 block - stored in pIv */
112 	pIv[0] = (q - 1);
113 	/* bytes 1 to n are already set with nonce by the user */
114 	/* set last q bytes with 0 */
115 	memset(pIv + n + 1, 0, q);
116 
117 	/* Encode the length of associated data 'a'. As the API limits the
118 	 * length
119 	 * of an array pointed by pAdditionalAuthData to be 240 bytes max, the
120 	 * maximum length of 'a' might be 240 - 16 - 2 = 222. Hence the encoding
121 	 * below is simplified. */
122 	if (pSessionDesc->aadLenInBytes > 0) {
123 		lenOfEncodedLen = sizeof(Cpa16U);
124 		lenAEncoded = QAT_UTILS_HOST_TO_NW_16(
125 		    (Cpa16U)pSessionDesc->aadLenInBytes);
126 	}
127 
128 	/* populate B0 block */
129 	/* first, set the flags field */
130 	pAdditionalAuthData[0] =
131 	    LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(lenOfEncodedLen,
132 					     pSessionDesc->hashResultSize,
133 					     q);
134 	/* bytes 1 to n are already set with nonce by the user*/
135 	/* put Q in bytes 16-q...15 */
136 	bitStrQ = QAT_UTILS_HOST_TO_NW_32(messageLenToCipherInBytes);
137 
138 	if (q > sizeof(bitStrQ)) {
139 		memset(pAdditionalAuthData + n + 1, 0, q);
140 		memcpy(pAdditionalAuthData + n + 1 + (q - sizeof(bitStrQ)),
141 		       (Cpa8U *)&bitStrQ,
142 		       sizeof(bitStrQ));
143 	} else {
144 		memcpy(pAdditionalAuthData + n + 1,
145 		       ((Cpa8U *)&bitStrQ) + (sizeof(bitStrQ) - q),
146 		       q);
147 	}
148 
149 	/* populate B1-Bn blocks */
150 	if (lenAEncoded > 0) {
151 		*(Cpa16U
152 		      *)(&pAdditionalAuthData[1 + LAC_ALG_CHAIN_CCM_NQ_CONST]) =
153 		    lenAEncoded;
154 		/* Next bytes are already set by the user with
155 		 * the associated data 'a' */
156 
157 		/* Check if padding is required */
158 		if (((pSessionDesc->aadLenInBytes + lenOfEncodedLen) %
159 		     LAC_HASH_AES_CCM_BLOCK_SIZE) != 0) {
160 			Cpa8U paddingLen = 0;
161 			Cpa8U paddingIndex = 0;
162 
163 			paddingLen = LAC_HASH_AES_CCM_BLOCK_SIZE -
164 			    ((pSessionDesc->aadLenInBytes + lenOfEncodedLen) %
165 			     LAC_HASH_AES_CCM_BLOCK_SIZE);
166 
167 			paddingIndex = 1 + LAC_ALG_CHAIN_CCM_NQ_CONST;
168 			paddingIndex +=
169 			    lenOfEncodedLen + pSessionDesc->aadLenInBytes;
170 
171 			memset(&pAdditionalAuthData[paddingIndex],
172 			       0,
173 			       paddingLen);
174 		}
175 	}
176 }
177 
178 /**
179  * @ingroup LacAuthEnc
180  */
181 void
LacSymAlgChain_PrepareGCMData(lac_session_desc_t * pSessionDesc,Cpa8U * pAdditionalAuthData)182 LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc,
183 			      Cpa8U *pAdditionalAuthData)
184 {
185 	Cpa8U paddingLen = 0;
186 
187 	if ((pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE) != 0) {
188 		paddingLen = LAC_HASH_AES_GCM_BLOCK_SIZE -
189 		    (pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE);
190 
191 		memset(&pAdditionalAuthData[pSessionDesc->aadLenInBytes],
192 		       0,
193 		       paddingLen);
194 	}
195 }
196