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)
54 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
57 return YACA_ERROR_INVALID_ARGUMENT;
59 return EVP_MD_CTX_size(c->mdctx);
62 static void destroy_digest_context(yaca_ctx_h ctx)
64 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
69 EVP_MD_CTX_destroy(c->mdctx);
72 int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md)
77 return YACA_ERROR_INVALID_ARGUMENT;
86 case YACA_DIGEST_SHA1:
89 case YACA_DIGEST_SHA224:
92 case YACA_DIGEST_SHA256:
95 case YACA_DIGEST_SHA384:
98 case YACA_DIGEST_SHA512:
101 case YACA_DIGEST_CMAC:
102 ret = YACA_ERROR_NOT_IMPLEMENTED;
105 ret = YACA_ERROR_INVALID_ARGUMENT;
109 if (ret == 0 && *md == NULL)
110 ret = YACA_ERROR_OPENSSL_FAILURE;
115 API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo)
118 struct yaca_digest_ctx_s *nc = NULL;
122 return YACA_ERROR_INVALID_ARGUMENT;
124 nc = yaca_zalloc(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, &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, md);
144 ret = YACA_ERROR_OPENSSL_FAILURE;
148 *ctx = (yaca_ctx_h)nc;
153 EVP_MD_CTX_destroy(nc->mdctx);
159 API int yaca_digest_update(yaca_ctx_h ctx, const char *data, size_t data_len)
161 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
164 if (c == NULL || data == NULL || data_len == 0)
165 return YACA_ERROR_INVALID_ARGUMENT;
167 ret = EVP_DigestUpdate(c->mdctx, data, data_len);
169 return YACA_ERROR_OPENSSL_FAILURE;
174 API int yaca_digest_final(yaca_ctx_h ctx, char *digest, size_t *digest_len)
176 struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
180 if (c == NULL || digest == NULL || digest_len == NULL)
181 return YACA_ERROR_INVALID_ARGUMENT;
183 if (*digest_len == 0 || *digest_len > UINT_MAX) // DigestFinal accepts uint
184 return YACA_ERROR_INVALID_ARGUMENT;
186 ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len);
188 return YACA_ERROR_OPENSSL_FAILURE;