[API-NEXT,v5,14/23] linux-generic: crypto: make HMAC work across segmented packets

Message ID 20170601090339.9313-15-dmitry.ereminsolenikov@linaro.org
State Accepted
Commit fec16fd81d4084340f0f9a6893c9772000608031
Headers show
Series
  • Major cryptography code rework
Related show

Commit Message

Dmitry Eremin-Solenikov June 1, 2017, 9:03 a.m.
Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

---
 platform/linux-generic/odp_crypto.c | 78 +++++++++++++++++++++----------------
 1 file changed, 45 insertions(+), 33 deletions(-)

-- 
2.11.0

Patch

diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index 2ba077f9dcd9..7ea90fb92b48 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -112,29 +112,53 @@  null_crypto_routine(odp_crypto_op_param_t *param ODP_UNUSED,
 }
 
 static
+void packet_hmac(odp_crypto_op_param_t *param,
+		 odp_crypto_generic_session_t *session,
+		 uint8_t *hash)
+{
+	odp_packet_t pkt = param->out_pkt;
+	uint32_t offset = param->auth_range.offset;
+	uint32_t len   = param->auth_range.length;
+	HMAC_CTX ctx;
+
+	ODP_ASSERT(offset + len <= odp_packet_len(pkt));
+
+	/* Hash it */
+	HMAC_CTX_init(&ctx);
+	HMAC_Init_ex(&ctx,
+		     session->auth.key,
+		     session->auth.key_length,
+		     session->auth.evp_md,
+		     NULL);
+
+	while (len > 0) {
+		uint32_t seglen = 0; /* GCC */
+		void *mapaddr = odp_packet_offset(pkt, offset, &seglen, NULL);
+		uint32_t maclen = len > seglen ? seglen : len;
+
+		HMAC_Update(&ctx, mapaddr, maclen);
+		offset  += maclen;
+		len     -= maclen;
+	}
+
+	HMAC_Final(&ctx, hash, NULL);
+	HMAC_CTX_cleanup(&ctx);
+}
+
+static
 odp_crypto_alg_err_t auth_gen(odp_crypto_op_param_t *param,
 			      odp_crypto_generic_session_t *session)
 {
-	uint8_t *data  = odp_packet_data(param->out_pkt);
-	uint8_t *icv   = data;
-	uint32_t len   = param->auth_range.length;
 	uint8_t  hash[EVP_MAX_MD_SIZE];
 
-	/* Adjust pointer for beginning of area to auth */
-	data += param->auth_range.offset;
-	icv  += param->hash_result_offset;
-
 	/* Hash it */
-	HMAC(session->auth.evp_md,
-	     session->auth.key,
-	     session->auth.key_length,
-	     data,
-	     len,
-	     hash,
-	     NULL);
+	packet_hmac(param, session, hash);
 
 	/* Copy to the output location */
-	memcpy(icv, hash, session->auth.bytes);
+	odp_packet_copy_from_mem(param->out_pkt,
+				 param->hash_result_offset,
+				 session->auth.bytes,
+				 hash);
 
 	return ODP_CRYPTO_ALG_ERR_NONE;
 }
@@ -143,31 +167,19 @@  static
 odp_crypto_alg_err_t auth_check(odp_crypto_op_param_t *param,
 				odp_crypto_generic_session_t *session)
 {
-	uint8_t *data  = odp_packet_data(param->out_pkt);
-	uint8_t *icv   = data;
-	uint32_t len   = param->auth_range.length;
 	uint32_t bytes = session->auth.bytes;
 	uint8_t  hash_in[EVP_MAX_MD_SIZE];
 	uint8_t  hash_out[EVP_MAX_MD_SIZE];
 
-	/* Adjust pointer for beginning of area to auth */
-	data += param->auth_range.offset;
-	icv  += param->hash_result_offset;
-
 	/* Copy current value out and clear it before authentication */
-	memset(hash_in, 0, sizeof(hash_in));
-	memcpy(hash_in, icv, bytes);
-	memset(icv, 0, bytes);
-	memset(hash_out, 0, sizeof(hash_out));
+	odp_packet_copy_to_mem(param->out_pkt, param->hash_result_offset,
+			       bytes, hash_in);
+
+	_odp_packet_set_data(param->out_pkt, param->hash_result_offset,
+			     0, bytes);
 
 	/* Hash it */
-	HMAC(session->auth.evp_md,
-	     session->auth.key,
-	     session->auth.key_length,
-	     data,
-	     len,
-	     hash_out,
-	     NULL);
+	packet_hmac(param, session, hash_out);
 
 	/* Verify match */
 	if (0 != memcmp(hash_in, hash_out, bytes))