lib/gssapi/krb5: implement GSS_C_CHANNEL_BOUND_FLAG for gss_init_sec_context()
[heimdal.git] / lib / hcrypto / hmac.c
blobb646d5612217392d23f9ecea99546a789308f749
1 /*
2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include <config.h>
35 #include <roken.h>
37 #include <hmac.h>
39 void
40 HMAC_CTX_init(HMAC_CTX *ctx)
42 memset(ctx, 0, sizeof(*ctx));
45 void
46 HMAC_CTX_cleanup(HMAC_CTX *ctx)
48 if (ctx->buf) {
49 memset_s(ctx->buf, ctx->key_length, 0, ctx->key_length);
50 free(ctx->buf);
51 ctx->buf = NULL;
53 if (ctx->opad) {
54 memset_s(ctx->opad, EVP_MD_block_size(ctx->md), 0, EVP_MD_block_size(ctx->md));
55 free(ctx->opad);
56 ctx->opad = NULL;
58 if (ctx->ipad) {
59 memset_s(ctx->ipad, EVP_MD_block_size(ctx->md), 0, EVP_MD_block_size(ctx->md));
60 free(ctx->ipad);
61 ctx->ipad = NULL;
63 if (ctx->ctx) {
64 EVP_MD_CTX_destroy(ctx->ctx);
65 ctx->ctx = NULL;
69 HMAC_CTX *
70 HMAC_CTX_new(void)
72 return calloc(1, sizeof(HMAC_CTX));
75 void
76 HMAC_CTX_free(HMAC_CTX *ctx)
78 HMAC_CTX_cleanup(ctx);
79 free(ctx);
82 size_t
83 HMAC_size(const HMAC_CTX *ctx)
85 return EVP_MD_size(ctx->md);
88 int
89 HMAC_Init_ex(HMAC_CTX *ctx,
90 const void *key,
91 size_t keylen,
92 const EVP_MD *md,
93 ENGINE *engine)
95 unsigned char *p;
96 size_t i, blockSize;
98 blockSize = EVP_MD_block_size(md);
100 if (ctx->md != md) {
101 if (ctx->md != NULL)
102 HMAC_CTX_cleanup(ctx);
104 ctx->md = md;
105 ctx->key_length = EVP_MD_size(ctx->md);
106 ctx->opad = NULL;
107 ctx->ipad = NULL;
108 ctx->ctx = NULL;
109 ctx->buf = malloc(ctx->key_length);
110 if (ctx->buf)
111 ctx->opad = malloc(blockSize);
112 if (ctx->opad)
113 ctx->ipad = malloc(blockSize);
114 if (ctx->ipad)
115 ctx->ctx = EVP_MD_CTX_create();
117 /* We do this check here to quiet scan-build */
118 if (!ctx->buf || !ctx->opad || !ctx->ipad || !ctx->ctx)
119 return 0;
120 #if 0
121 ctx->engine = engine;
122 #endif
124 if (keylen > blockSize) {
125 if (EVP_Digest(key, keylen, ctx->buf, NULL, ctx->md, engine) == 0)
126 return 0;
127 key = ctx->buf;
128 keylen = EVP_MD_size(ctx->md);
131 memset(ctx->ipad, 0x36, blockSize);
132 memset(ctx->opad, 0x5c, blockSize);
134 for (i = 0, p = ctx->ipad; i < keylen; i++)
135 p[i] ^= ((const unsigned char *)key)[i];
136 for (i = 0, p = ctx->opad; i < keylen; i++)
137 p[i] ^= ((const unsigned char *)key)[i];
139 if (EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine) == 0)
140 return 0;
141 EVP_DigestUpdate(ctx->ctx, ctx->ipad, EVP_MD_block_size(ctx->md));
142 return 1;
145 void
146 HMAC_Update(HMAC_CTX *ctx, const void *data, size_t len)
148 EVP_DigestUpdate(ctx->ctx, data, len);
151 void
152 HMAC_Final(HMAC_CTX *ctx, void *md, unsigned int *len)
154 EVP_DigestFinal_ex(ctx->ctx, ctx->buf, NULL);
156 EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine);
157 EVP_DigestUpdate(ctx->ctx, ctx->opad, EVP_MD_block_size(ctx->md));
158 EVP_DigestUpdate(ctx->ctx, ctx->buf, ctx->key_length);
159 EVP_DigestFinal_ex(ctx->ctx, md, len);
162 void *
163 HMAC(const EVP_MD *md,
164 const void *key, size_t key_size,
165 const void *data, size_t data_size,
166 void *hash, unsigned int *hash_len)
168 HMAC_CTX ctx;
170 HMAC_CTX_init(&ctx);
171 if (HMAC_Init_ex(&ctx, key, key_size, md, NULL) == 0) {
172 HMAC_CTX_cleanup(&ctx);
173 return NULL;
175 HMAC_Update(&ctx, data, data_size);
176 HMAC_Final(&ctx, hash, hash_len);
177 HMAC_CTX_cleanup(&ctx);
178 return hash;