diff options
Diffstat (limited to 'libbb/hash_hmac.c')
| -rw-r--r-- | libbb/hash_hmac.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/libbb/hash_hmac.c b/libbb/hash_hmac.c index 9e48e0f51..b3138029f 100644 --- a/libbb/hash_hmac.c +++ b/libbb/hash_hmac.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | // if we often need HMAC hmac with the same key. | 18 | // if we often need HMAC hmac with the same key. |
| 19 | // | 19 | // |
| 20 | // text is often given in disjoint pieces. | 20 | // text is often given in disjoint pieces. |
| 21 | #if !ENABLE_FEATURE_USE_CNG_API | ||
| 21 | void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin) | 22 | void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin) |
| 22 | { | 23 | { |
| 23 | #if HMAC_ONLY_SHA256 | 24 | #if HMAC_ONLY_SHA256 |
| @@ -89,12 +90,58 @@ void FAST_FUNC hmac_hash_v( | |||
| 89 | md5sha_hash(&ctx->hashed_key_xor_ipad, in, size); | 90 | md5sha_hash(&ctx->hashed_key_xor_ipad, in, size); |
| 90 | } | 91 | } |
| 91 | } | 92 | } |
| 93 | #else | ||
| 94 | void _hmac_begin(hmac_ctx_t *ctx, uint8_t *key, unsigned key_size, | ||
| 95 | BCRYPT_ALG_HANDLE alg_handle) { | ||
| 96 | DWORD hash_object_length = 0; | ||
| 97 | ULONG _unused; | ||
| 98 | NTSTATUS status; | ||
| 99 | |||
| 100 | status = BCryptGetProperty(alg_handle, BCRYPT_OBJECT_LENGTH, | ||
| 101 | (PUCHAR)&hash_object_length, sizeof(DWORD), &_unused, 0); | ||
| 102 | mingw_die_if_error(status, "BCryptGetProperty"); | ||
| 103 | status = BCryptGetProperty(alg_handle, BCRYPT_HASH_LENGTH, | ||
| 104 | (PUCHAR)&ctx->output_size, sizeof(DWORD), &_unused, 0); | ||
| 105 | mingw_die_if_error(status, "BCryptGetProperty"); | ||
| 106 | |||
| 107 | ctx->hash_obj = xmalloc(hash_object_length); | ||
| 108 | |||
| 109 | status = BCryptCreateHash(alg_handle, &ctx->handle, ctx->hash_obj, | ||
| 110 | hash_object_length, key, key_size, BCRYPT_HASH_REUSABLE_FLAG); | ||
| 111 | mingw_die_if_error(status, "BCryptCreateHash"); | ||
| 112 | } | ||
| 113 | |||
| 114 | unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out) | ||
| 115 | { | ||
| 116 | NTSTATUS status; | ||
| 117 | |||
| 118 | status = BCryptFinishHash(ctx->handle, out, ctx->output_size, 0); | ||
| 119 | mingw_die_if_error(status, "BCryptFinishHash"); | ||
| 120 | |||
| 121 | return ctx->output_size; | ||
| 122 | } | ||
| 123 | |||
| 124 | void FAST_FUNC hmac_hash_v(hmac_ctx_t *ctx, va_list va) | ||
| 125 | { | ||
| 126 | uint8_t *in; | ||
| 127 | |||
| 128 | while ((in = va_arg(va, uint8_t*)) != NULL) { | ||
| 129 | unsigned size = va_arg(va, unsigned); | ||
| 130 | BCryptHashData(ctx->handle, in, size, 0); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | void hmac_uninit(hmac_ctx_t *ctx) { | ||
| 135 | BCryptDestroyHash(ctx->handle); | ||
| 136 | free(ctx->hash_obj); | ||
| 137 | } | ||
| 138 | #endif | ||
| 92 | 139 | ||
| 93 | /* Using HMAC state, make a copy of it (IOW: without affecting this state!) | 140 | /* Using HMAC state, make a copy of it (IOW: without affecting this state!) |
| 94 | * hash in the list of (ptr,size) blocks, and finish the HMAC to out[] buffer. | 141 | * hash in the list of (ptr,size) blocks, and finish the HMAC to out[] buffer. |
| 95 | * This function is useful for TLS PRF. | 142 | * This function is useful for TLS PRF. |
| 96 | */ | 143 | */ |
| 97 | unsigned FAST_FUNC hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...) | 144 | unsigned hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...) |
| 98 | { | 145 | { |
| 99 | hmac_ctx_t tmpctx = *ctx; /* struct copy */ | 146 | hmac_ctx_t tmpctx = *ctx; /* struct copy */ |
| 100 | va_list va; | 147 | va_list va; |
