1 /**
2  * \file mbedtls_md.c
3  *
4  * \brief Generic message digest wrapper for mbed TLS
5  *
6  * \author Adriaan de Jong <dejong@fox-it.com>
7  *
8  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
9  *  Copyright (C) 2018-2022, Intel Corporation.
10  *  SPDX-License-Identifier: Apache-2.0
11  *
12  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
13  *  not use this file except in compliance with the License.
14  *  You may obtain a copy of the License at
15  *
16  *  http://www.apache.org/licenses/LICENSE-2.0
17  *
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
20  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  *
24  *  This file is part of mbed TLS (https://tls.mbed.org)
25  */
26 
27 #include "md.h"
28 #include "md_internal.h"
29 
30 /*
31  * Reminder: update profiles in x509_crt.c when adding a new hash!
32  */
33 
mbedtls_md_info_from_type(mbedtls_md_type_t md_type)34 const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type)
35 {
36     const mbedtls_md_info_t *md_info;
37 
38     switch (md_type)
39     {
40         case MBEDTLS_MD_SHA256:
41             md_info = &mbedtls_sha256_info;
42             break;
43         default:
44             md_info = NULL;
45             break;
46     }
47 
48     return md_info;
49 }
50 
mbedtls_md_init(mbedtls_md_context_t * ctx)51 void mbedtls_md_init(mbedtls_md_context_t *ctx)
52 {
53     (void) memset(ctx, 0U, sizeof(mbedtls_md_context_t));
54 }
55 
mbedtls_md_free(mbedtls_md_context_t * ctx)56 void mbedtls_md_free(mbedtls_md_context_t *ctx)
57 {
58     if (ctx != NULL) {
59         (void) mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md_context_t));
60     }
61 
62     return;
63 }
64 
mbedtls_md_setup(mbedtls_md_context_t * ctx,const mbedtls_md_info_t * md_info)65 int32_t mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info)
66 {
67     int32_t ret = 0;
68 
69     if ((md_info == NULL) || (ctx == NULL)) {
70         ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
71     } else {
72         ctx->md_info = md_info;
73     }
74 
75     return ret;
76 }
77 
mbedtls_md_hmac_starts(mbedtls_md_context_t * ctx,const uint8_t * key,size_t keylen)78 int32_t mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const uint8_t *key, size_t keylen)
79 {
80     int32_t ret = 0;
81     uint8_t sum[MBEDTLS_MD_MAX_SIZE];
82     uint8_t *ipad, *opad;
83     const uint8_t *temp_key = key;
84     size_t i;
85 
86     if ((ctx == NULL) || (ctx->md_info == NULL) || (temp_key == NULL)) {
87         ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
88     }
89 
90     if (ret == 0) {
91         if (keylen > ctx->md_info->block_size) {
92             ret = ctx->md_info->starts_func((void *) ctx->md_ctx);
93             if (ret == 0) {
94                 ret = ctx->md_info->update_func((void *) ctx->md_ctx, temp_key, keylen);
95                 if (ret == 0) {
96                     ret = ctx->md_info->finish_func((void *) ctx->md_ctx, sum);
97                 }
98             }
99 
100             if (ret == 0) {
101                 keylen = (size_t) ctx->md_info->size;
102                 temp_key = sum;
103             }
104         }
105 
106         if (ret == 0) {
107             ipad = (uint8_t *) ctx->hmac_ctx;
108             opad = (uint8_t *) ctx->hmac_ctx + ctx->md_info->block_size;
109 
110             (void) memset(ipad, 0x36U, ctx->md_info->block_size);
111             (void) memset(opad, 0x5CU, ctx->md_info->block_size);
112 
113             for (i = 0U; i < keylen; i++) {
114                 *(ipad + i) = (uint8_t) (*(ipad + i) ^ (*(temp_key + i)));
115                 *(opad + i) = (uint8_t) (*(opad + i) ^ (*(temp_key + i)));
116             }
117 
118             ret = ctx->md_info->starts_func((void *) ctx->md_ctx);
119             if (ret == 0) {
120                 ret = ctx->md_info->update_func((void *) ctx->md_ctx, ipad,
121                                                    ctx->md_info->block_size);
122             }
123         }
124         (void) mbedtls_platform_zeroize(sum, sizeof(sum));
125     }
126 
127     return ret;
128 }
129 
mbedtls_md_hmac_update(mbedtls_md_context_t * ctx,const uint8_t * input,size_t ilen)130 int32_t mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const uint8_t *input, size_t ilen)
131 {
132     int32_t ret;
133 
134     if ((ctx == NULL) || (ctx->md_info == NULL)) {
135         ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
136     } else {
137         ret = ctx->md_info->update_func((void *) ctx->md_ctx, input, ilen);
138     }
139 
140     return ret;
141 }
142 
mbedtls_md_hmac_finish(mbedtls_md_context_t * ctx,uint8_t * output)143 int32_t mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, uint8_t *output)
144 {
145     int32_t ret = 0;
146     uint8_t tmp[MBEDTLS_MD_MAX_SIZE];
147     uint8_t *opad;
148 
149     if ((ctx == NULL) || (ctx->md_info == NULL)) {
150         ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
151     }
152 
153     if (ret == 0) {
154         opad = (uint8_t *) ctx->hmac_ctx + ctx->md_info->block_size;
155 
156         ret = ctx->md_info->finish_func((void *) ctx->md_ctx, tmp);
157         if (ret == 0) {
158             ret = ctx->md_info->starts_func((void *) ctx->md_ctx);
159         }
160     }
161 
162     if (ret == 0) {
163         ret = ctx->md_info->update_func((void *) ctx->md_ctx, opad,
164                                          ctx->md_info->block_size);
165         if (ret == 0) {
166             ret = ctx->md_info->update_func((void *) ctx->md_ctx, tmp,
167                                              ctx->md_info->size);
168         }
169 
170         if (ret == 0) {
171             ret = ctx->md_info->finish_func((void *) ctx->md_ctx,
172                                              (uint8_t *) output);
173         }
174     }
175 
176     return ret;
177 }
178 
mbedtls_md_hmac(const mbedtls_md_info_t * md_info,const uint8_t * key,size_t keylen,const uint8_t * input,size_t ilen,uint8_t * output)179 int32_t mbedtls_md_hmac(const mbedtls_md_info_t *md_info,
180                      const uint8_t *key, size_t keylen,
181                      const uint8_t *input, size_t ilen,
182                      uint8_t *output)
183 {
184     mbedtls_md_context_t ctx;
185     int32_t ret = 0;
186 
187     if (md_info == NULL) {
188         ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
189     }
190 
191     if (ret == 0) {
192         mbedtls_md_init(&ctx);
193 
194         ret = mbedtls_md_setup(&ctx, md_info);
195         if (ret == 0) {
196             ret = mbedtls_md_hmac_starts(&ctx, key, keylen);
197         }
198 
199         if (ret == 0) {
200             ret = mbedtls_md_hmac_update(&ctx, input, ilen);
201         }
202 
203         if (ret == 0) {
204             ret = mbedtls_md_hmac_finish(&ctx, output);
205         }
206 
207         mbedtls_md_free(&ctx);
208     }
209 
210     return ret;
211 }
212 
mbedtls_md_get_size(const mbedtls_md_info_t * md_info)213 uint8_t mbedtls_md_get_size(const mbedtls_md_info_t *md_info)
214 {
215     uint8_t ret = 0U;
216 
217     if (md_info != NULL) {
218         ret = (uint8_t) md_info->size;
219     }
220 
221     return ret;
222 }
223