Remove no-unused-parameter compilation flag. Fix some errors.
[platform/core/security/yaca.git] / src / digest.c
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19 /**
20  * @file digest.c
21  * @brief
22  */
23
24 #include <assert.h>
25
26 #include <openssl/evp.h>
27
28 #include <yaca_crypto.h>
29 #include <yaca_digest.h>
30 #include <yaca_error.h>
31
32 #include "internal.h"
33
34 struct yaca_digest_ctx_s {
35         struct yaca_context_s ctx;
36
37         EVP_MD_CTX *mdctx;
38 };
39
40 static struct yaca_digest_ctx_s *get_digest_ctx(const yaca_context_h ctx)
41 {
42         if (ctx == YACA_CONTEXT_NULL)
43                 return NULL;
44
45         switch (ctx->type) {
46         case YACA_CTX_DIGEST:
47                 return (struct yaca_digest_ctx_s *)ctx;
48         default:
49                 return NULL;
50         }
51 }
52
53 static int get_digest_output_length(const yaca_context_h ctx,
54                                     UNUSED size_t input_len,
55                                     size_t *output_len)
56 {
57         struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
58
59         if (c == NULL)
60                 return YACA_ERROR_INVALID_PARAMETER;
61
62         int md_size = EVP_MD_CTX_size(c->mdctx);
63         if (md_size <= 0)
64                 return YACA_ERROR_INTERNAL;
65
66         *output_len = md_size;
67
68         return YACA_ERROR_NONE;
69 }
70
71 static void destroy_digest_context(yaca_context_h ctx)
72 {
73         struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
74
75         if (c == NULL)
76                 return;
77
78         EVP_MD_CTX_destroy(c->mdctx);
79         c->mdctx = NULL;
80 }
81
82 int digest_get_algorithm(yaca_digest_algorithm_e algo, const EVP_MD **md)
83 {
84         int ret = YACA_ERROR_NONE;
85
86         if (!md)
87                 return YACA_ERROR_INVALID_PARAMETER;
88
89         *md = NULL;
90
91         switch (algo) {
92         case YACA_DIGEST_MD5:
93                 *md = EVP_md5();
94                 break;
95         case YACA_DIGEST_SHA1:
96                 *md = EVP_sha1();
97                 break;
98         case YACA_DIGEST_SHA224:
99                 *md = EVP_sha224();
100                 break;
101         case YACA_DIGEST_SHA256:
102                 *md = EVP_sha256();
103                 break;
104         case YACA_DIGEST_SHA384:
105                 *md = EVP_sha384();
106                 break;
107         case YACA_DIGEST_SHA512:
108                 *md = EVP_sha512();
109                 break;
110         default:
111                 ret = YACA_ERROR_INVALID_PARAMETER;
112                 break;
113         }
114
115         if (ret == YACA_ERROR_NONE && *md == NULL) {
116                 ret = YACA_ERROR_INTERNAL;
117                 ERROR_DUMP(ret);
118         }
119
120         return ret;
121 }
122
123 API int yaca_digest_initialize(yaca_context_h *ctx, yaca_digest_algorithm_e algo)
124 {
125         int ret;
126         struct yaca_digest_ctx_s *nc = NULL;
127         const EVP_MD *md;
128
129         if (ctx == NULL)
130                 return YACA_ERROR_INVALID_PARAMETER;
131
132         ret = yaca_zalloc(sizeof(struct yaca_digest_ctx_s), (void**)&nc);
133         if (ret != YACA_ERROR_NONE)
134                 return ret;
135
136         nc->ctx.type = YACA_CTX_DIGEST;
137         nc->ctx.ctx_destroy = destroy_digest_context;
138         nc->ctx.get_output_length = get_digest_output_length;
139
140         ret = digest_get_algorithm(algo, &md);
141         if (ret != YACA_ERROR_NONE)
142                 goto exit;
143
144         nc->mdctx = EVP_MD_CTX_create();
145         if (nc->mdctx == NULL) {
146                 ret = YACA_ERROR_INTERNAL;
147                 ERROR_DUMP(ret);
148                 goto exit;
149         }
150
151         ret = EVP_DigestInit(nc->mdctx, md);
152         if (ret != 1) {
153                 ret = YACA_ERROR_INTERNAL;
154                 ERROR_DUMP(ret);
155                 goto exit;
156         }
157
158         *ctx = (yaca_context_h)nc;
159         nc = NULL;
160         ret = YACA_ERROR_NONE;
161
162 exit:
163         yaca_context_destroy((yaca_context_h)nc);
164
165         return ret;
166 }
167
168 API int yaca_digest_update(yaca_context_h ctx, const char *data, size_t data_len)
169 {
170         struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
171         int ret;
172
173         if (c == NULL || data == NULL || data_len == 0)
174                 return YACA_ERROR_INVALID_PARAMETER;
175
176         ret = EVP_DigestUpdate(c->mdctx, data, data_len);
177         if (ret != 1) {
178                 ret = YACA_ERROR_INTERNAL;
179                 ERROR_DUMP(ret);
180                 return ret;
181         }
182
183         return YACA_ERROR_NONE;
184 }
185
186 API int yaca_digest_finalize(yaca_context_h ctx, char *digest, size_t *digest_len)
187 {
188         struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
189         int ret;
190         unsigned len = 0;
191
192         if (c == NULL || digest == NULL || digest_len == NULL)
193                 return YACA_ERROR_INVALID_PARAMETER;
194
195         if (*digest_len == 0 || *digest_len > UINT_MAX) /* DigestFinal accepts UINT */
196                 return YACA_ERROR_INVALID_PARAMETER;
197
198         ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len);
199         if (ret != 1) {
200                 ret = YACA_ERROR_INTERNAL;
201                 ERROR_DUMP(ret);
202                 return ret;
203         }
204
205         *digest_len = len;
206
207         return YACA_ERROR_NONE;
208 }