+ {
+ clib_sha256_block (&ipad_state, ikey, 1);
+ clib_sha256_block (&opad_state, okey, 1);
+ }
+
+ kd->ipad_h = ipad_state.h;
+ kd->opad_h = opad_state.h;
+}
+
+static_always_inline void
+clib_sha2_hmac_init (clib_sha2_hmac_ctx_t *ctx, clib_sha2_type_t type,
+ clib_sha2_hmac_key_data_t *kd)
+{
+ u8 block_size = clib_sha2_variants[type].block_size;
+ u8 digest_size = clib_sha2_variants[type].digest_size;
+
+ *ctx = (clib_sha2_hmac_ctx_t) {
+ .type = type,
+ .block_size = block_size,
+ .digest_size = digest_size,
+ .ipad_state = {
+ .h = kd->ipad_h,
+ .total_bytes = block_size,
+ },
+ .opad_state = {
+ .h = kd->opad_h,
+ .total_bytes = block_size,
+ },
+ };
+}
+
+static_always_inline void
+clib_sha2_hmac_update (clib_sha2_hmac_ctx_t *ctx, const u8 *msg, uword len)
+{
+ clib_sha2_update_internal (&ctx->ipad_state, ctx->block_size, msg, len);
+}
+
+static_always_inline void
+clib_sha2_hmac_final (clib_sha2_hmac_ctx_t *ctx, u8 *digest)
+{
+ u8 i_digest[SHA2_MAX_DIGEST_SIZE];
+
+ clib_sha2_final_internal (&ctx->ipad_state, ctx->block_size,
+ ctx->digest_size, i_digest);
+ clib_sha2_update_internal (&ctx->opad_state, ctx->block_size, i_digest,
+ ctx->digest_size);
+ clib_sha2_final_internal (&ctx->opad_state, ctx->block_size,
+ ctx->digest_size, digest);
+}
+
+static_always_inline void
+clib_sha2_hmac (clib_sha2_type_t type, const u8 *key, uword key_len,
+ const u8 *msg, uword len, u8 *digest)
+{
+ clib_sha2_hmac_ctx_t _ctx, *ctx = &_ctx;
+ clib_sha2_hmac_key_data_t kd;