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
27 #include <openssl/evp.h>
28 #include <openssl/rsa.h>
29 #include <openssl/cmac.h>
31 #include <yaca_crypto.h>
32 #include <yaca_sign.h>
33 #include <yaca_error.h>
38 /* Operation type saved in context to recognize what
39 * type of operation is performed and how to perform it.
46 struct yaca_sign_context_s {
47 struct yaca_context_s ctx;
50 enum sign_op_type op_type;
51 enum context_state_e state;
54 static bool CTX_DEFAULT_STATES[CTX_COUNT][CTX_COUNT] = {
55 /* from \ to INIT, MSG, FIN */
56 /* INIT */ { 0, 1, 1 },
57 /* MSG */ { 0, 1, 1 },
58 /* FIN */ { 0, 0, 0 },
61 static bool verify_state_change(struct yaca_sign_context_s *c, enum context_state_e to)
65 return CTX_DEFAULT_STATES[from][to];
68 static struct yaca_sign_context_s *get_sign_context(const yaca_context_h ctx)
70 if (ctx == YACA_CONTEXT_NULL)
74 case YACA_CONTEXT_SIGN:
75 return (struct yaca_sign_context_s *)ctx;
81 static int get_sign_output_length(const yaca_context_h ctx,
85 assert(output_len != NULL);
87 struct yaca_sign_context_s *c = get_sign_context(ctx);
90 if (c == NULL || input_len != 0)
91 return YACA_ERROR_INVALID_PARAMETER;
93 assert(c->md_ctx != NULL);
95 pctx = EVP_MD_CTX_pkey_ctx(c->md_ctx);
97 return YACA_ERROR_INTERNAL;
99 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
101 ERROR_DUMP(YACA_ERROR_INTERNAL);
102 return YACA_ERROR_INTERNAL;
105 int len = EVP_PKEY_size(pkey);
107 ERROR_DUMP(YACA_ERROR_INTERNAL);
108 return YACA_ERROR_INTERNAL;
112 return YACA_ERROR_NONE;
115 static void destroy_sign_context(yaca_context_h ctx)
117 struct yaca_sign_context_s *c = get_sign_context(ctx);
122 EVP_MD_CTX_destroy(c->md_ctx);
126 int set_sign_property(yaca_context_h ctx,
127 yaca_property_e property,
132 struct yaca_sign_context_s *c = get_sign_context(ctx);
133 yaca_padding_e padding;
138 if (c == NULL || value == NULL || c->state == CTX_FINALIZED)
139 return YACA_ERROR_INVALID_PARAMETER;
141 assert(c->md_ctx != NULL);
143 pctx = EVP_MD_CTX_pkey_ctx(c->md_ctx);
145 return YACA_ERROR_INTERNAL;
147 /* this function only supports padding */
148 if (property != YACA_PROPERTY_PADDING || value_len != sizeof(yaca_padding_e))
149 return YACA_ERROR_INVALID_PARAMETER;
151 padding = *(yaca_padding_e *)(value);
154 case YACA_PADDING_X931:
155 case YACA_PADDING_PKCS1:
156 case YACA_PADDING_PKCS1_PSS:
159 return YACA_ERROR_INVALID_PARAMETER;
162 pad = rsa_padding2openssl(padding);
165 pkey = EVP_PKEY_CTX_get0_pkey(pctx);
167 ret = YACA_ERROR_INTERNAL;
172 /* padding only works for RSA */
173 if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA)
174 return YACA_ERROR_INVALID_PARAMETER;
176 ret = EVP_PKEY_CTX_set_rsa_padding(pctx, pad);
178 ret = ERROR_HANDLE();
182 return YACA_ERROR_NONE;
185 API int yaca_sign_initialize(yaca_context_h *ctx,
186 yaca_digest_algorithm_e algo,
187 const yaca_key_h prv_key)
189 struct yaca_sign_context_s *nc = NULL;
190 const EVP_MD *md = NULL;
192 const struct yaca_key_evp_s *evp_key = key_get_evp(prv_key);
194 if (ctx == NULL || evp_key == NULL)
195 return YACA_ERROR_INVALID_PARAMETER;
197 ret = digest_get_algorithm(algo, &md);
198 if (ret != YACA_ERROR_NONE)
201 switch (prv_key->type) {
202 case YACA_KEY_TYPE_RSA_PRIV:
203 if (EVP_MD_size(md) >= EVP_PKEY_size(evp_key->evp) ||
204 (algo == YACA_DIGEST_SHA384 && (EVP_PKEY_size(evp_key->evp) <= YACA_KEY_LENGTH_512BIT / 8)))
205 return YACA_ERROR_INVALID_PARAMETER;
207 case YACA_KEY_TYPE_DSA_PRIV:
208 case YACA_KEY_TYPE_EC_PRIV:
211 return YACA_ERROR_INVALID_PARAMETER;
214 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
215 if (ret != YACA_ERROR_NONE)
218 nc->op_type = OP_SIGN;
219 nc->ctx.type = YACA_CONTEXT_SIGN;
220 nc->ctx.context_destroy = destroy_sign_context;
221 nc->ctx.get_output_length = get_sign_output_length;
222 nc->ctx.set_property = set_sign_property;
223 nc->ctx.get_property = NULL;
225 nc->md_ctx = EVP_MD_CTX_create();
226 if (nc->md_ctx == NULL) {
227 ret = YACA_ERROR_INTERNAL;
232 ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
234 ret = ERROR_HANDLE();
238 nc->state = CTX_INITIALIZED;
239 *ctx = (yaca_context_h)nc;
241 ret = YACA_ERROR_NONE;
244 yaca_context_destroy((yaca_context_h)nc);
249 API int yaca_sign_initialize_hmac(yaca_context_h *ctx,
250 yaca_digest_algorithm_e algo,
251 const yaca_key_h sym_key)
253 struct yaca_sign_context_s *nc = NULL;
254 EVP_PKEY *pkey = NULL;
257 const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key);
259 if (ctx == NULL || simple_key == NULL ||
260 (sym_key->type != YACA_KEY_TYPE_SYMMETRIC && sym_key->type != YACA_KEY_TYPE_DES))
261 return YACA_ERROR_INVALID_PARAMETER;
263 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
264 if (ret != YACA_ERROR_NONE)
267 nc->op_type = OP_SIGN;
268 nc->ctx.type = YACA_CONTEXT_SIGN;
269 nc->ctx.context_destroy = destroy_sign_context;
270 nc->ctx.get_output_length = get_sign_output_length;
271 nc->ctx.set_property = NULL;
272 nc->ctx.get_property = NULL;
274 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
276 (unsigned char *)simple_key->d,
277 simple_key->bit_len / 8);
279 ret = YACA_ERROR_INTERNAL;
284 ret = digest_get_algorithm(algo, &md);
285 if (ret != YACA_ERROR_NONE)
288 nc->md_ctx = EVP_MD_CTX_create();
289 if (nc->md_ctx == NULL) {
290 ret = YACA_ERROR_INTERNAL;
295 ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, pkey);
297 ret = YACA_ERROR_INTERNAL;
302 nc->state = CTX_INITIALIZED;
303 *ctx = (yaca_context_h)nc;
305 ret = YACA_ERROR_NONE;
309 yaca_context_destroy((yaca_context_h)nc);
314 API int yaca_sign_initialize_cmac(yaca_context_h *ctx,
315 yaca_encrypt_algorithm_e algo,
316 const yaca_key_h sym_key)
318 struct yaca_sign_context_s *nc = NULL;
319 CMAC_CTX* cmac_ctx = NULL;
320 const EVP_CIPHER* cipher = NULL;
321 EVP_PKEY *pkey = NULL;
323 const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key);
325 if (ctx == NULL || simple_key == NULL ||
326 (sym_key->type != YACA_KEY_TYPE_SYMMETRIC && sym_key->type != YACA_KEY_TYPE_DES))
327 return YACA_ERROR_INVALID_PARAMETER;
329 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
330 if (ret != YACA_ERROR_NONE)
333 nc->op_type = OP_SIGN;
334 nc->ctx.type = YACA_CONTEXT_SIGN;
335 nc->ctx.context_destroy = destroy_sign_context;
336 nc->ctx.get_output_length = get_sign_output_length;
337 nc->ctx.set_property = NULL;
338 nc->ctx.get_property = NULL;
340 ret = encrypt_get_algorithm(algo, YACA_BCM_CBC, simple_key->bit_len, &cipher);
341 if (ret != YACA_ERROR_NONE)
344 /* create and initialize low level CMAC context */
345 cmac_ctx = CMAC_CTX_new();
346 if (cmac_ctx == NULL) {
347 ret = YACA_ERROR_INTERNAL;
352 if (CMAC_Init(cmac_ctx, simple_key->d, simple_key->bit_len / 8, cipher, NULL) != 1) {
353 ret = YACA_ERROR_INTERNAL;
358 /* create key and assign CMAC context to it */
359 pkey = EVP_PKEY_new();
361 ret = YACA_ERROR_INTERNAL;
366 if (EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmac_ctx) != 1) {
367 ret = YACA_ERROR_INTERNAL;
374 nc->md_ctx = EVP_MD_CTX_create();
375 if (nc->md_ctx == NULL) {
376 ret = YACA_ERROR_INTERNAL;
381 if (EVP_DigestSignInit(nc->md_ctx, NULL, NULL, NULL, pkey) != 1) {
382 ret = YACA_ERROR_INTERNAL;
387 nc->state = CTX_INITIALIZED;
388 *ctx = (yaca_context_h)nc;
390 ret = YACA_ERROR_NONE;
394 CMAC_CTX_free(cmac_ctx);
395 yaca_context_destroy((yaca_context_h)nc);
400 API int yaca_sign_update(yaca_context_h ctx,
404 struct yaca_sign_context_s *c = get_sign_context(ctx);
407 if (c == NULL || c->op_type != OP_SIGN ||
408 message == NULL || message_len == 0)
409 return YACA_ERROR_INVALID_PARAMETER;
411 if (!verify_state_change(c, CTX_MSG_UPDATED))
412 return YACA_ERROR_INVALID_PARAMETER;
414 ret = EVP_DigestSignUpdate(c->md_ctx, message, message_len);
416 ret = YACA_ERROR_INTERNAL;
421 c->state = CTX_MSG_UPDATED;
422 return YACA_ERROR_NONE;
425 API int yaca_sign_finalize(yaca_context_h ctx,
427 size_t *signature_len)
429 struct yaca_sign_context_s *c = get_sign_context(ctx);
432 if (c == NULL || c->op_type != OP_SIGN ||
433 signature == NULL || signature_len == NULL || *signature_len == 0)
434 return YACA_ERROR_INVALID_PARAMETER;
436 if (!verify_state_change(c, CTX_FINALIZED))
437 return YACA_ERROR_INVALID_PARAMETER;
439 ret = EVP_DigestSignFinal(c->md_ctx, (unsigned char *)signature, signature_len);
441 ret = YACA_ERROR_INTERNAL;
446 c->state = CTX_FINALIZED;
447 return YACA_ERROR_NONE;
450 API int yaca_verify_initialize(yaca_context_h *ctx,
451 yaca_digest_algorithm_e algo,
452 const yaca_key_h pub_key)
454 struct yaca_sign_context_s *nc = NULL;
455 const EVP_MD *md = NULL;
457 const struct yaca_key_evp_s *evp_key = key_get_evp(pub_key);
459 if (ctx == NULL || evp_key == NULL)
460 return YACA_ERROR_INVALID_PARAMETER;
462 ret = digest_get_algorithm(algo, &md);
463 if (ret != YACA_ERROR_NONE)
466 switch (pub_key->type) {
467 case YACA_KEY_TYPE_RSA_PUB:
468 if (EVP_MD_size(md) >= EVP_PKEY_size(evp_key->evp) ||
469 (algo == YACA_DIGEST_SHA384 && (EVP_PKEY_size(evp_key->evp) <= YACA_KEY_LENGTH_512BIT / 8)))
470 return YACA_ERROR_INVALID_PARAMETER;
472 case YACA_KEY_TYPE_DSA_PUB:
473 case YACA_KEY_TYPE_EC_PUB:
476 return YACA_ERROR_INVALID_PARAMETER;
479 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
480 if (ret != YACA_ERROR_NONE)
483 nc->op_type = OP_VERIFY;
484 nc->ctx.type = YACA_CONTEXT_SIGN;
485 nc->ctx.context_destroy = destroy_sign_context;
486 nc->ctx.get_output_length = NULL;
487 nc->ctx.set_property = set_sign_property;
488 nc->ctx.get_property = NULL;
490 nc->md_ctx = EVP_MD_CTX_create();
491 if (nc->md_ctx == NULL) {
492 ret = YACA_ERROR_INTERNAL;
497 ret = EVP_DigestVerifyInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
499 ret = ERROR_HANDLE();
503 nc->state = CTX_INITIALIZED;
504 *ctx = (yaca_context_h)nc;
506 ret = YACA_ERROR_NONE;
509 yaca_context_destroy((yaca_context_h)nc);
514 API int yaca_verify_update(yaca_context_h ctx,
518 struct yaca_sign_context_s *c = get_sign_context(ctx);
521 if (c == NULL || message == NULL || message_len == 0 || c->op_type != OP_VERIFY)
522 return YACA_ERROR_INVALID_PARAMETER;
524 if (!verify_state_change(c, CTX_MSG_UPDATED))
525 return YACA_ERROR_INVALID_PARAMETER;
527 ret = EVP_DigestVerifyUpdate(c->md_ctx, message, message_len);
529 ret = YACA_ERROR_INTERNAL;
534 c->state = CTX_MSG_UPDATED;
535 return YACA_ERROR_NONE;
538 API int yaca_verify_finalize(yaca_context_h ctx,
539 const char *signature,
540 size_t signature_len)
542 struct yaca_sign_context_s *c = get_sign_context(ctx);
545 if (c == NULL || signature == NULL || signature_len == 0 || c->op_type != OP_VERIFY)
546 return YACA_ERROR_INVALID_PARAMETER;
548 if (!verify_state_change(c, CTX_FINALIZED))
549 return YACA_ERROR_INVALID_PARAMETER;
551 ret = EVP_DigestVerifyFinal(c->md_ctx,
552 (unsigned char *)signature,
556 c->state = CTX_FINALIZED;
557 return YACA_ERROR_NONE;
562 return YACA_ERROR_DATA_MISMATCH;
565 ret = YACA_ERROR_INTERNAL;