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