xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/hmac.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1*d3273b5bSchristos /*	$NetBSD: hmac.c,v 1.2 2017/01/28 21:31:47 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
36b9d004c6Schristos #include <config.h>
37b9d004c6Schristos #include <krb5/roken.h>
38b9d004c6Schristos 
39ca1c9b0cSelric #include <hmac.h>
40ca1c9b0cSelric 
41ca1c9b0cSelric void
HMAC_CTX_init(HMAC_CTX * ctx)42ca1c9b0cSelric HMAC_CTX_init(HMAC_CTX *ctx)
43ca1c9b0cSelric {
44ca1c9b0cSelric     memset(ctx, 0, sizeof(*ctx));
45ca1c9b0cSelric }
46ca1c9b0cSelric 
47ca1c9b0cSelric void
HMAC_CTX_cleanup(HMAC_CTX * ctx)48ca1c9b0cSelric HMAC_CTX_cleanup(HMAC_CTX *ctx)
49ca1c9b0cSelric {
50ca1c9b0cSelric     if (ctx->buf) {
51ca1c9b0cSelric 	memset(ctx->buf, 0, ctx->key_length);
52ca1c9b0cSelric 	free(ctx->buf);
53ca1c9b0cSelric 	ctx->buf = NULL;
54ca1c9b0cSelric     }
55ca1c9b0cSelric     if (ctx->opad) {
56ca1c9b0cSelric 	memset(ctx->opad, 0, EVP_MD_block_size(ctx->md));
57ca1c9b0cSelric 	free(ctx->opad);
58ca1c9b0cSelric 	ctx->opad = NULL;
59ca1c9b0cSelric     }
60ca1c9b0cSelric     if (ctx->ipad) {
61ca1c9b0cSelric 	memset(ctx->ipad, 0, EVP_MD_block_size(ctx->md));
62ca1c9b0cSelric 	free(ctx->ipad);
63ca1c9b0cSelric 	ctx->ipad = NULL;
64ca1c9b0cSelric     }
65ca1c9b0cSelric     if (ctx->ctx) {
66ca1c9b0cSelric 	EVP_MD_CTX_destroy(ctx->ctx);
67ca1c9b0cSelric 	ctx->ctx = NULL;
68ca1c9b0cSelric     }
69ca1c9b0cSelric }
70ca1c9b0cSelric 
71ca1c9b0cSelric size_t
HMAC_size(const HMAC_CTX * ctx)72ca1c9b0cSelric HMAC_size(const HMAC_CTX *ctx)
73ca1c9b0cSelric {
74ca1c9b0cSelric     return EVP_MD_size(ctx->md);
75ca1c9b0cSelric }
76ca1c9b0cSelric 
77ca1c9b0cSelric void
HMAC_Init_ex(HMAC_CTX * ctx,const void * key,size_t keylen,const EVP_MD * md,ENGINE * engine)78ca1c9b0cSelric HMAC_Init_ex(HMAC_CTX *ctx,
79ca1c9b0cSelric 	     const void *key,
80ca1c9b0cSelric 	     size_t keylen,
81ca1c9b0cSelric 	     const EVP_MD *md,
82ca1c9b0cSelric 	     ENGINE *engine)
83ca1c9b0cSelric {
84ca1c9b0cSelric     unsigned char *p;
85ca1c9b0cSelric     size_t i;
86ca1c9b0cSelric 
87ca1c9b0cSelric     if (ctx->md != md) {
88ca1c9b0cSelric 	ctx->md = md;
89ca1c9b0cSelric 	if (ctx->buf) {
90ca1c9b0cSelric 	    memset(ctx->buf, 0, ctx->key_length);
91ca1c9b0cSelric 	    free (ctx->buf);
92ca1c9b0cSelric 	}
93ca1c9b0cSelric 	ctx->key_length = EVP_MD_size(ctx->md);
94ca1c9b0cSelric 	ctx->buf = malloc(ctx->key_length);
95ca1c9b0cSelric     }
96ca1c9b0cSelric #if 0
97ca1c9b0cSelric     ctx->engine = engine;
98ca1c9b0cSelric #endif
99ca1c9b0cSelric 
100ca1c9b0cSelric     if (keylen > EVP_MD_block_size(ctx->md)) {
101ca1c9b0cSelric 	EVP_Digest(key, keylen, ctx->buf, NULL, ctx->md, engine);
102ca1c9b0cSelric 	key = ctx->buf;
103ca1c9b0cSelric 	keylen = EVP_MD_size(ctx->md);
104ca1c9b0cSelric     }
105ca1c9b0cSelric 
106ca1c9b0cSelric     if (ctx->opad) {
107ca1c9b0cSelric 	memset(ctx->opad, 0, ctx->key_length);
108ca1c9b0cSelric 	free(ctx->opad);
109ca1c9b0cSelric     }
110ca1c9b0cSelric     if (ctx->ipad) {
111ca1c9b0cSelric 	memset(ctx->ipad, 0, ctx->key_length);
112ca1c9b0cSelric 	free(ctx->ipad);
113ca1c9b0cSelric     }
114ca1c9b0cSelric 
115ca1c9b0cSelric     ctx->opad = malloc(EVP_MD_block_size(ctx->md));
116ca1c9b0cSelric     ctx->ipad = malloc(EVP_MD_block_size(ctx->md));
117ca1c9b0cSelric     memset(ctx->ipad, 0x36, EVP_MD_block_size(ctx->md));
118ca1c9b0cSelric     memset(ctx->opad, 0x5c, EVP_MD_block_size(ctx->md));
119ca1c9b0cSelric 
120ca1c9b0cSelric     for (i = 0, p = ctx->ipad; i < keylen; i++)
121ca1c9b0cSelric 	p[i] ^= ((const unsigned char *)key)[i];
122ca1c9b0cSelric     for (i = 0, p = ctx->opad; i < keylen; i++)
123ca1c9b0cSelric 	p[i] ^= ((const unsigned char *)key)[i];
124ca1c9b0cSelric 
125ca1c9b0cSelric     if (ctx->ctx == NULL)
126ca1c9b0cSelric 	ctx->ctx = EVP_MD_CTX_create();
127ca1c9b0cSelric 
128ca1c9b0cSelric     EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine);
129ca1c9b0cSelric     EVP_DigestUpdate(ctx->ctx, ctx->ipad, EVP_MD_block_size(ctx->md));
130ca1c9b0cSelric }
131ca1c9b0cSelric 
132ca1c9b0cSelric void
HMAC_Update(HMAC_CTX * ctx,const void * data,size_t len)133ca1c9b0cSelric HMAC_Update(HMAC_CTX *ctx, const void *data, size_t len)
134ca1c9b0cSelric {
135ca1c9b0cSelric     EVP_DigestUpdate(ctx->ctx, data, len);
136ca1c9b0cSelric }
137ca1c9b0cSelric 
138ca1c9b0cSelric void
HMAC_Final(HMAC_CTX * ctx,void * md,unsigned int * len)139ca1c9b0cSelric HMAC_Final(HMAC_CTX *ctx, void *md, unsigned int *len)
140ca1c9b0cSelric {
141ca1c9b0cSelric     EVP_DigestFinal_ex(ctx->ctx, ctx->buf, NULL);
142ca1c9b0cSelric 
143ca1c9b0cSelric     EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine);
144ca1c9b0cSelric     EVP_DigestUpdate(ctx->ctx, ctx->opad, EVP_MD_block_size(ctx->md));
145ca1c9b0cSelric     EVP_DigestUpdate(ctx->ctx, ctx->buf, ctx->key_length);
146ca1c9b0cSelric     EVP_DigestFinal_ex(ctx->ctx, md, len);
147ca1c9b0cSelric }
148ca1c9b0cSelric 
149ca1c9b0cSelric void *
HMAC(const EVP_MD * md,const void * key,size_t key_size,const void * data,size_t data_size,void * hash,unsigned int * hash_len)150ca1c9b0cSelric HMAC(const EVP_MD *md,
151ca1c9b0cSelric      const void *key, size_t key_size,
152ca1c9b0cSelric      const void *data, size_t data_size,
153ca1c9b0cSelric      void *hash, unsigned int *hash_len)
154ca1c9b0cSelric {
155ca1c9b0cSelric     HMAC_CTX ctx;
156ca1c9b0cSelric 
157ca1c9b0cSelric     HMAC_CTX_init(&ctx);
158ca1c9b0cSelric     HMAC_Init_ex(&ctx, key, key_size, md, NULL);
159ca1c9b0cSelric     HMAC_Update(&ctx, data, data_size);
160ca1c9b0cSelric     HMAC_Final(&ctx, hash, hash_len);
161ca1c9b0cSelric     HMAC_CTX_cleanup(&ctx);
162ca1c9b0cSelric     return hash;
163ca1c9b0cSelric }
164