/src/BearSSL/src/mac/hmac.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining |
5 | | * a copy of this software and associated documentation files (the |
6 | | * "Software"), to deal in the Software without restriction, including |
7 | | * without limitation the rights to use, copy, modify, merge, publish, |
8 | | * distribute, sublicense, and/or sell copies of the Software, and to |
9 | | * permit persons to whom the Software is furnished to do so, subject to |
10 | | * the following conditions: |
11 | | * |
12 | | * The above copyright notice and this permission notice shall be |
13 | | * included in all copies or substantial portions of the Software. |
14 | | * |
15 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
16 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
17 | | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
18 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
19 | | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
20 | | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
21 | | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
22 | | * SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include "inner.h" |
26 | | |
27 | | static inline size_t |
28 | | block_size(const br_hash_class *dig) |
29 | 248k | { |
30 | 248k | unsigned ls; |
31 | | |
32 | 248k | ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF) |
33 | 248k | & BR_HASHDESC_LBLEN_MASK; |
34 | 248k | return (size_t)1 << ls; |
35 | 248k | } |
36 | | |
37 | | static void |
38 | | process_key(const br_hash_class **hc, void *ks, |
39 | | const void *key, size_t key_len, unsigned bb) |
40 | 13.6k | { |
41 | 13.6k | unsigned char tmp[256]; |
42 | 13.6k | size_t blen, u; |
43 | | |
44 | 13.6k | blen = block_size(*hc); |
45 | 13.6k | memcpy(tmp, key, key_len); |
46 | 377k | for (u = 0; u < key_len; u ++) { |
47 | 363k | tmp[u] ^= (unsigned char)bb; |
48 | 363k | } |
49 | 13.6k | memset(tmp + key_len, bb, blen - key_len); |
50 | 13.6k | (*hc)->init(hc); |
51 | 13.6k | (*hc)->update(hc, tmp, blen); |
52 | 13.6k | (*hc)->state(hc, ks); |
53 | 13.6k | } |
54 | | |
55 | | /* see bearssl.h */ |
56 | | void |
57 | | br_hmac_key_init(br_hmac_key_context *kc, |
58 | | const br_hash_class *dig, const void *key, size_t key_len) |
59 | 6.81k | { |
60 | 6.81k | br_hash_compat_context hc; |
61 | 6.81k | unsigned char kbuf[64]; |
62 | | |
63 | 6.81k | kc->dig_vtable = dig; |
64 | 6.81k | hc.vtable = dig; |
65 | 6.81k | if (key_len > block_size(dig)) { |
66 | 131 | dig->init(&hc.vtable); |
67 | 131 | dig->update(&hc.vtable, key, key_len); |
68 | 131 | dig->out(&hc.vtable, kbuf); |
69 | 131 | key = kbuf; |
70 | 131 | key_len = br_digest_size(dig); |
71 | 131 | } |
72 | 6.81k | process_key(&hc.vtable, kc->ksi, key, key_len, 0x36); |
73 | 6.81k | process_key(&hc.vtable, kc->kso, key, key_len, 0x5C); |
74 | 6.81k | } |
75 | | |
76 | | /* see bearssl.h */ |
77 | | void |
78 | | br_hmac_init(br_hmac_context *ctx, |
79 | | const br_hmac_key_context *kc, size_t out_len) |
80 | 114k | { |
81 | 114k | const br_hash_class *dig; |
82 | 114k | size_t blen, hlen; |
83 | | |
84 | 114k | dig = kc->dig_vtable; |
85 | 114k | blen = block_size(dig); |
86 | 114k | dig->init(&ctx->dig.vtable); |
87 | 114k | dig->set_state(&ctx->dig.vtable, kc->ksi, (uint64_t)blen); |
88 | 114k | memcpy(ctx->kso, kc->kso, sizeof kc->kso); |
89 | 114k | hlen = br_digest_size(dig); |
90 | 114k | if (out_len > 0 && out_len < hlen) { |
91 | 0 | hlen = out_len; |
92 | 0 | } |
93 | 114k | ctx->out_len = hlen; |
94 | 114k | } |
95 | | |
96 | | /* see bearssl.h */ |
97 | | void |
98 | | br_hmac_update(br_hmac_context *ctx, const void *data, size_t len) |
99 | 746k | { |
100 | 746k | ctx->dig.vtable->update(&ctx->dig.vtable, data, len); |
101 | 746k | } |
102 | | |
103 | | /* see bearssl.h */ |
104 | | size_t |
105 | | br_hmac_out(const br_hmac_context *ctx, void *out) |
106 | 114k | { |
107 | 114k | const br_hash_class *dig; |
108 | 114k | br_hash_compat_context hc; |
109 | 114k | unsigned char tmp[64]; |
110 | 114k | size_t blen, hlen; |
111 | | |
112 | 114k | dig = ctx->dig.vtable; |
113 | 114k | dig->out(&ctx->dig.vtable, tmp); |
114 | 114k | blen = block_size(dig); |
115 | 114k | dig->init(&hc.vtable); |
116 | 114k | dig->set_state(&hc.vtable, ctx->kso, (uint64_t)blen); |
117 | 114k | hlen = br_digest_size(dig); |
118 | 114k | dig->update(&hc.vtable, tmp, hlen); |
119 | 114k | dig->out(&hc.vtable, tmp); |
120 | 114k | memcpy(out, tmp, ctx->out_len); |
121 | 114k | return ctx->out_len; |
122 | 114k | } |