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
22 #include <openssl/evp.h>
23 #include <openssl/err.h>
25 #include <yaca/crypto.h>
26 #include <yaca/error.h>
27 #include <yaca/types.h>
31 struct yaca_digest_ctx_s
33 struct yaca_ctx_s ctx;
38 static struct yaca_digest_ctx_s *get_digest_ctx(const yaca_ctx_h ctx)
40 if (ctx == YACA_CTX_NULL)
46 return (struct yaca_digest_ctx_s *)ctx;
52 static int get_digest_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len)
54 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
57 return YACA_ERROR_INVALID_ARGUMENT;
59 *output_len = EVP_MD_CTX_size(c->mdctx);
63 static void destroy_digest_context(yaca_ctx_h ctx)
65 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
70 EVP_MD_CTX_destroy(c->mdctx);
74 int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md)
79 return YACA_ERROR_INVALID_ARGUMENT;
88 case YACA_DIGEST_SHA1:
91 case YACA_DIGEST_SHA224:
94 case YACA_DIGEST_SHA256:
97 case YACA_DIGEST_SHA384:
100 case YACA_DIGEST_SHA512:
104 ret = YACA_ERROR_INVALID_ARGUMENT;
108 if (ret == 0 && *md == NULL) {
109 ret = YACA_ERROR_INTERNAL;
116 API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo)
119 struct yaca_digest_ctx_s *nc = NULL;
123 return YACA_ERROR_INVALID_ARGUMENT;
125 nc = yaca_zalloc(sizeof(struct yaca_digest_ctx_s));
127 return YACA_ERROR_OUT_OF_MEMORY;
129 nc->ctx.type = YACA_CTX_DIGEST;
130 nc->ctx.ctx_destroy = destroy_digest_context;
131 nc->ctx.get_output_length = get_digest_output_length;
133 ret = digest_get_algorithm(algo, &md);
137 nc->mdctx = EVP_MD_CTX_create();
138 if (nc->mdctx == NULL) {
139 ret = YACA_ERROR_INTERNAL;
144 ret = EVP_DigestInit(nc->mdctx, md);
146 ret = YACA_ERROR_INTERNAL;
151 *ctx = (yaca_ctx_h)nc;
156 EVP_MD_CTX_destroy(nc->mdctx);
162 API int yaca_digest_update(yaca_ctx_h ctx, const char *data, size_t data_len)
164 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
167 if (c == NULL || data == NULL || data_len == 0)
168 return YACA_ERROR_INVALID_ARGUMENT;
170 ret = EVP_DigestUpdate(c->mdctx, data, data_len);
172 ret = YACA_ERROR_INTERNAL;
180 API int yaca_digest_final(yaca_ctx_h ctx, char *digest, size_t *digest_len)
182 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
186 if (c == NULL || digest == NULL || digest_len == NULL)
187 return YACA_ERROR_INVALID_ARGUMENT;
189 if (*digest_len == 0 || *digest_len > UINT_MAX) // DigestFinal accepts uint
190 return YACA_ERROR_INVALID_ARGUMENT;
192 ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len);
194 ret = YACA_ERROR_INTERNAL;