2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
26 #include <openssl/evp.h>
28 #include <yaca_crypto.h>
29 #include <yaca_digest.h>
30 #include <yaca_error.h>
34 struct yaca_digest_ctx_s {
35 struct yaca_context_s ctx;
40 static struct yaca_digest_ctx_s *get_digest_ctx(const yaca_context_h ctx)
42 if (ctx == YACA_CONTEXT_NULL)
47 return (struct yaca_digest_ctx_s *)ctx;
53 static int get_digest_output_length(const yaca_context_h ctx,
54 UNUSED size_t input_len,
57 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
60 return YACA_ERROR_INVALID_PARAMETER;
62 int md_size = EVP_MD_CTX_size(c->mdctx);
64 return YACA_ERROR_INTERNAL;
66 *output_len = md_size;
68 return YACA_ERROR_NONE;
71 static void destroy_digest_context(yaca_context_h ctx)
73 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
78 EVP_MD_CTX_destroy(c->mdctx);
82 int digest_get_algorithm(yaca_digest_algorithm_e algo, const EVP_MD **md)
84 int ret = YACA_ERROR_NONE;
87 return YACA_ERROR_INVALID_PARAMETER;
95 case YACA_DIGEST_SHA1:
98 case YACA_DIGEST_SHA224:
101 case YACA_DIGEST_SHA256:
104 case YACA_DIGEST_SHA384:
107 case YACA_DIGEST_SHA512:
111 ret = YACA_ERROR_INVALID_PARAMETER;
115 if (ret == YACA_ERROR_NONE && *md == NULL) {
116 ret = YACA_ERROR_INTERNAL;
123 API int yaca_digest_initialize(yaca_context_h *ctx, yaca_digest_algorithm_e algo)
126 struct yaca_digest_ctx_s *nc = NULL;
130 return YACA_ERROR_INVALID_PARAMETER;
132 ret = yaca_zalloc(sizeof(struct yaca_digest_ctx_s), (void**)&nc);
133 if (ret != YACA_ERROR_NONE)
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;
140 ret = digest_get_algorithm(algo, &md);
141 if (ret != YACA_ERROR_NONE)
144 nc->mdctx = EVP_MD_CTX_create();
145 if (nc->mdctx == NULL) {
146 ret = YACA_ERROR_INTERNAL;
151 ret = EVP_DigestInit(nc->mdctx, md);
153 ret = YACA_ERROR_INTERNAL;
158 *ctx = (yaca_context_h)nc;
160 ret = YACA_ERROR_NONE;
163 yaca_context_destroy((yaca_context_h)nc);
168 API int yaca_digest_update(yaca_context_h ctx, const char *data, size_t data_len)
170 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
173 if (c == NULL || data == NULL || data_len == 0)
174 return YACA_ERROR_INVALID_PARAMETER;
176 ret = EVP_DigestUpdate(c->mdctx, data, data_len);
178 ret = YACA_ERROR_INTERNAL;
183 return YACA_ERROR_NONE;
186 API int yaca_digest_finalize(yaca_context_h ctx, char *digest, size_t *digest_len)
188 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
192 if (c == NULL || digest == NULL || digest_len == NULL)
193 return YACA_ERROR_INVALID_PARAMETER;
195 if (*digest_len == 0 || *digest_len > UINT_MAX) /* DigestFinal accepts UINT */
196 return YACA_ERROR_INVALID_PARAMETER;
198 ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len);
200 ret = YACA_ERROR_INTERNAL;
207 return YACA_ERROR_NONE;