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;
39 static struct yaca_digest_ctx_s *get_digest_ctx(const yaca_ctx_h ctx)
41 if (ctx == YACA_CTX_NULL)
47 return (struct yaca_digest_ctx_s *)ctx;
53 static int get_digest_output_length(const yaca_ctx_h ctx, size_t input_len)
55 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
58 return YACA_ERROR_INVALID_ARGUMENT;
60 return EVP_MD_size(c->md);
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);
73 int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md)
78 return YACA_ERROR_INVALID_ARGUMENT;
87 case YACA_DIGEST_SHA1:
90 case YACA_DIGEST_SHA224:
93 case YACA_DIGEST_SHA256:
96 case YACA_DIGEST_SHA384:
99 case YACA_DIGEST_SHA512:
102 case YACA_DIGEST_CMAC:
103 ret = YACA_ERROR_NOT_IMPLEMENTED;
106 ret = YACA_ERROR_INVALID_ARGUMENT;
110 if (ret == 0 && *md == NULL)
111 ret = YACA_ERROR_OPENSSL_FAILURE;
116 API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo)
119 struct yaca_digest_ctx_s *nc = NULL;
122 return YACA_ERROR_INVALID_ARGUMENT;
124 nc = yaca_malloc(sizeof(struct yaca_digest_ctx_s));
126 return YACA_ERROR_OUT_OF_MEMORY;
128 nc->ctx.type = YACA_CTX_DIGEST;
129 nc->ctx.ctx_destroy = destroy_digest_context;
130 nc->ctx.get_output_length = get_digest_output_length;
132 ret = digest_get_algorithm(algo, &nc->md);
136 nc->mdctx = EVP_MD_CTX_create();
137 if (nc->mdctx == NULL) {
138 ret = YACA_ERROR_OPENSSL_FAILURE;
142 ret = EVP_DigestInit(nc->mdctx, nc->md);
144 ret = YACA_ERROR_OPENSSL_FAILURE;
148 *ctx = (yaca_ctx_h)nc;
154 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 return YACA_ERROR_OPENSSL_FAILURE;
177 API int yaca_digest_final(yaca_ctx_h ctx, char *digest, size_t *digest_len)
179 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
183 if (c == NULL || digest == NULL || digest_len == NULL)
184 return YACA_ERROR_INVALID_ARGUMENT;
186 if (*digest_len == 0 || *digest_len > UINT_MAX) // DigestFinal accepts uint
187 return YACA_ERROR_INVALID_ARGUMENT;
189 ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len);
191 return YACA_ERROR_OPENSSL_FAILURE;