• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the License); you may
5  *  not use this file except in compliance with the License.
6  *
7  *  http://www.apache.org/licenses/LICENSE-2.0
8  */
9 
10 
11 #include <string.h>
12 #include <gmssl/hmac.h>
13 #include <gmssl/error.h>
14 
15 
16 #define IPAD	0x36
17 #define OPAD	0x5C
18 
19 
hmac_init(HMAC_CTX * ctx,const DIGEST * digest,const uint8_t * key,size_t keylen)20 int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const uint8_t *key, size_t keylen)
21 {
22 	uint8_t i_key[DIGEST_MAX_BLOCK_SIZE] = {0};
23 	uint8_t o_key[DIGEST_MAX_BLOCK_SIZE] = {0};
24 	size_t blocksize;
25 	int i;
26 
27 	if (!ctx || !digest || !key || !keylen) {
28 		error_print();
29 		return -1;
30 	}
31 
32 	ctx->digest = digest;
33 
34 	blocksize = digest->block_size;
35 	if (keylen <= blocksize) {
36 		memcpy(i_key, key, keylen);
37 		memcpy(o_key, key, keylen);
38 	} else {
39 		digest_init(&ctx->digest_ctx, digest);
40 		digest_update(&ctx->digest_ctx, key, keylen);
41 		digest_finish(&ctx->digest_ctx, i_key, &keylen);
42 		memcpy(o_key, i_key, keylen);
43 	}
44 	for (i = 0; i < blocksize; i++) {
45 		i_key[i] ^= IPAD;
46 		o_key[i] ^= OPAD;
47 	}
48 
49 	digest_init(&ctx->i_ctx, digest);
50 	digest_update(&ctx->i_ctx, i_key, blocksize);
51 	digest_init(&ctx->o_ctx, digest);
52 	digest_update(&ctx->o_ctx, o_key, blocksize);
53 	memcpy(&ctx->digest_ctx, &ctx->i_ctx, sizeof(DIGEST_CTX));
54 
55 	memset(i_key, 0, sizeof(i_key));
56 	memset(o_key, 0, sizeof(o_key));
57 	return 1;
58 }
59 
hmac_update(HMAC_CTX * ctx,const uint8_t * data,size_t datalen)60 int hmac_update(HMAC_CTX *ctx, const uint8_t *data, size_t datalen)
61 {
62 	if (ctx == NULL) {
63 		error_print();
64 		return -1;
65 	}
66 	if (data == NULL || datalen == 0) {
67 		return 0;
68 	}
69 	if (digest_update(&ctx->digest_ctx, data, datalen) != 1) {
70 		error_print();
71 		return -1;
72 	}
73 	return 1;
74 }
75 
hmac_finish(HMAC_CTX * ctx,uint8_t * mac,size_t * maclen)76 int hmac_finish(HMAC_CTX *ctx, uint8_t *mac, size_t *maclen)
77 {
78 	if (ctx == NULL || maclen == NULL) {
79 		error_print();
80 		return -1;
81 	}
82 	if (digest_finish(&ctx->digest_ctx, mac, maclen) != 1) {
83 		error_print();
84 		return -1;
85 	}
86 	memcpy(&ctx->digest_ctx, &ctx->o_ctx, sizeof(DIGEST_CTX));
87 	if (digest_update(&ctx->digest_ctx, mac, *maclen) != 1
88 		|| digest_finish(&ctx->digest_ctx, mac, maclen) != 1) {
89 		error_print();
90 		return -1;
91 	}
92 	return 1;
93 }
94 
hmac_finish_and_verify(HMAC_CTX * ctx,const uint8_t * mac,size_t maclen)95 int hmac_finish_and_verify(HMAC_CTX *ctx, const uint8_t *mac, size_t maclen)
96 {
97 	uint8_t hmac[64];
98 	size_t hmaclen;
99 
100 	if (hmac_finish(ctx, hmac, &hmaclen) != 1) {
101 		error_print();
102 		return -1;
103 	}
104 	if (maclen != hmaclen
105 		|| memcmp(hmac, mac, maclen) != 0) {
106 		error_print();
107 		return -1;
108 	}
109 	return 1;
110 }
111 
hmac(const DIGEST * digest,const uint8_t * key,size_t keylen,const uint8_t * data,size_t datalen,uint8_t * mac,size_t * maclen)112 int hmac(const DIGEST *digest, const uint8_t *key, size_t keylen,
113 	const uint8_t *data, size_t datalen,
114 	uint8_t *mac, size_t *maclen)
115 {
116 	int ret = 0;
117 	HMAC_CTX ctx;
118 
119 	if (hmac_init(&ctx, digest, key, keylen) != 1
120 		|| hmac_update(&ctx, data, datalen) != 1
121 		|| hmac_finish(&ctx, mac, maclen) != 1) {
122 		goto end;
123 	}
124 	ret = 1;
125 
126 end:
127 	memset(&ctx, 0, sizeof(ctx));
128 	return ret;
129 }
130