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_ctx_s {
47 struct yaca_context_s ctx;
50 enum sign_op_type op_type;
53 static struct yaca_sign_ctx_s *get_sign_ctx(const yaca_context_h ctx)
55 if (ctx == YACA_CONTEXT_NULL)
60 return (struct yaca_sign_ctx_s *)ctx;
66 static int get_sign_output_length(const yaca_context_h ctx,
67 UNUSED size_t input_len,
70 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
73 return YACA_ERROR_INVALID_PARAMETER;
75 assert(c->mdctx != NULL);
77 if (c->mdctx->pctx == NULL)
78 return YACA_ERROR_INTERNAL;
80 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx);
82 ERROR_DUMP(YACA_ERROR_INTERNAL);
83 return YACA_ERROR_INTERNAL;
86 int len = EVP_PKEY_size(pkey);
88 ERROR_DUMP(YACA_ERROR_INTERNAL);
89 return YACA_ERROR_INTERNAL;
93 return YACA_ERROR_NONE;
96 static void destroy_sign_context(yaca_context_h ctx)
98 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
103 EVP_MD_CTX_destroy(c->mdctx);
107 int set_sign_param(yaca_context_h ctx,
108 yaca_property_e param,
113 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
114 yaca_padding_e padding;
118 if (c == NULL || value == NULL)
119 return YACA_ERROR_INVALID_PARAMETER;
121 assert(c->mdctx != NULL);
123 if (c->mdctx->pctx == NULL)
124 return YACA_ERROR_INTERNAL;
126 /* this function only supports padding */
127 if (param != YACA_PROPERTY_PADDING || value_len != sizeof(yaca_padding_e))
128 return YACA_ERROR_INVALID_PARAMETER;
130 padding = *(yaca_padding_e *)(value);
132 // TODO: investigate whether it's possible to set
133 // RSA_NO_PADDING or RSA_SSLV23_PADDING in some cases
135 case YACA_PADDING_X931:
136 pad = RSA_X931_PADDING;
138 case YACA_PADDING_PKCS1:
139 pad = RSA_PKCS1_PADDING;
141 case YACA_PADDING_PKCS1_PSS:
142 pad = RSA_PKCS1_PSS_PADDING;
145 return YACA_ERROR_INVALID_PARAMETER;
148 pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx);
150 ret = YACA_ERROR_INTERNAL;
155 /* padding only works for RSA */
156 if (pkey->type != EVP_PKEY_RSA)
157 return YACA_ERROR_INVALID_PARAMETER;
159 ret = EVP_PKEY_CTX_set_rsa_padding(c->mdctx->pctx, pad);
161 ret = YACA_ERROR_INTERNAL;
166 return YACA_ERROR_NONE;
169 int get_sign_param(const yaca_context_h ctx,
170 yaca_property_e param,
175 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
178 yaca_padding_e padding;
180 if (c == NULL || value == NULL || value_len == NULL)
181 return YACA_ERROR_INVALID_PARAMETER;
183 assert(c->mdctx != NULL);
185 if (c->mdctx->pctx == NULL)
186 return YACA_ERROR_INTERNAL;
188 /* this function only supports padding */
189 if (param != YACA_PROPERTY_PADDING)
190 return YACA_ERROR_INVALID_PARAMETER;
192 pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx);
194 ret = YACA_ERROR_INTERNAL;
199 /* padding only works for RSA */
200 if (pkey->type != EVP_PKEY_RSA)
201 return YACA_ERROR_INVALID_PARAMETER;
203 ret = EVP_PKEY_CTX_get_rsa_padding(c->mdctx->pctx, &pad);
205 ret = YACA_ERROR_INTERNAL;
211 case RSA_X931_PADDING:
212 padding = YACA_PADDING_X931;
214 case RSA_PKCS1_PADDING:
215 padding = YACA_PADDING_PKCS1;
217 case RSA_PKCS1_PSS_PADDING:
218 padding = YACA_PADDING_PKCS1_PSS;
221 ret = YACA_ERROR_INTERNAL;
222 ERROR_DUMP(YACA_ERROR_INTERNAL);
226 ret = yaca_malloc(sizeof(yaca_padding_e), value);
227 if (ret != YACA_ERROR_NONE)
230 memcpy(*value, &padding, sizeof(yaca_padding_e));
231 *value_len = sizeof(yaca_padding_e);
233 return YACA_ERROR_NONE;
236 API int yaca_sign_initialize(yaca_context_h *ctx,
237 yaca_digest_algorithm_e algo,
238 const yaca_key_h key)
240 struct yaca_sign_ctx_s *nc = NULL;
241 const EVP_MD *md = NULL;
243 const struct yaca_key_evp_s *evp_key = key_get_evp(key);
245 if (ctx == NULL || evp_key == NULL)
246 return YACA_ERROR_INVALID_PARAMETER;
249 case YACA_KEY_TYPE_RSA_PRIV:
250 case YACA_KEY_TYPE_DSA_PRIV:
252 // case YACA_KEY_TYPE_EC_PRIV:
253 // TODO NOT_IMPLEMENTED
255 return YACA_ERROR_INVALID_PARAMETER;
258 ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
259 if (ret != YACA_ERROR_NONE)
262 nc->op_type = OP_SIGN;
263 nc->ctx.type = YACA_CTX_SIGN;
264 nc->ctx.ctx_destroy = destroy_sign_context;
265 nc->ctx.get_output_length = get_sign_output_length;
266 nc->ctx.set_param = set_sign_param;
267 nc->ctx.get_param = get_sign_param;
269 ret = digest_get_algorithm(algo, &md);
270 if (ret != YACA_ERROR_NONE)
273 nc->mdctx = EVP_MD_CTX_create();
274 if (nc->mdctx == NULL) {
275 ret = YACA_ERROR_INTERNAL;
280 ret = EVP_DigestSignInit(nc->mdctx, NULL, md, NULL, evp_key->evp);
282 ret = YACA_ERROR_INTERNAL;
287 *ctx = (yaca_context_h)nc;
289 ret = YACA_ERROR_NONE;
292 yaca_context_destroy((yaca_context_h)nc);
297 API int yaca_sign_initialize_hmac(yaca_context_h *ctx,
298 yaca_digest_algorithm_e algo,
299 const yaca_key_h key)
301 struct yaca_sign_ctx_s *nc = NULL;
302 EVP_PKEY *pkey = NULL;
305 const struct yaca_key_simple_s *simple_key = key_get_simple(key);
307 if (ctx == NULL || simple_key == NULL ||
308 (key->type != YACA_KEY_TYPE_SYMMETRIC && key->type != YACA_KEY_TYPE_DES))
309 return YACA_ERROR_INVALID_PARAMETER;
311 ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
312 if (ret != YACA_ERROR_NONE)
315 nc->op_type = OP_SIGN;
316 nc->ctx.type = YACA_CTX_SIGN;
317 nc->ctx.ctx_destroy = destroy_sign_context;
318 nc->ctx.get_output_length = get_sign_output_length;
320 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
322 (unsigned char *)simple_key->d,
323 simple_key->bits / 8);
325 ret = YACA_ERROR_INTERNAL;
330 ret = digest_get_algorithm(algo, &md);
331 if (ret != YACA_ERROR_NONE)
334 nc->mdctx = EVP_MD_CTX_create();
335 if (nc->mdctx == NULL) {
336 ret = YACA_ERROR_INTERNAL;
341 ret = EVP_DigestSignInit(nc->mdctx, NULL, md, NULL, pkey);
343 ret = YACA_ERROR_INTERNAL;
350 *ctx = (yaca_context_h)nc;
352 ret = YACA_ERROR_NONE;
356 yaca_context_destroy((yaca_context_h)nc);
361 API int yaca_sign_initialize_cmac(yaca_context_h *ctx,
362 yaca_encrypt_algorithm_e algo,
363 const yaca_key_h key)
365 struct yaca_sign_ctx_s *nc = NULL;
366 CMAC_CTX* cmac_ctx = NULL;
367 const EVP_CIPHER* cipher = NULL;
368 EVP_PKEY *pkey = NULL;
370 const struct yaca_key_simple_s *simple_key = key_get_simple(key);
372 if (ctx == NULL || simple_key == NULL ||
373 (key->type != YACA_KEY_TYPE_SYMMETRIC && key->type != YACA_KEY_TYPE_DES))
374 return YACA_ERROR_INVALID_PARAMETER;
376 ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
377 if (ret != YACA_ERROR_NONE)
380 nc->op_type = OP_SIGN;
381 nc->ctx.type = YACA_CTX_SIGN;
382 nc->ctx.ctx_destroy = destroy_sign_context;
383 nc->ctx.get_output_length = get_sign_output_length;
385 ret = encrypt_get_algorithm(algo, YACA_BCM_CBC, simple_key->bits, &cipher);
386 if (ret != YACA_ERROR_NONE)
389 /* create and initialize low level CMAC context */
390 cmac_ctx = CMAC_CTX_new();
391 if (cmac_ctx == NULL) {
392 ret = YACA_ERROR_INTERNAL;
397 if (CMAC_Init(cmac_ctx, simple_key->d, simple_key->bits / 8, cipher, NULL) != 1) {
398 ret = YACA_ERROR_INTERNAL;
403 /* create key and assign CMAC context to it */
404 pkey = EVP_PKEY_new();
406 ret = YACA_ERROR_INTERNAL;
411 if (EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmac_ctx) != 1) {
412 ret = YACA_ERROR_INTERNAL;
419 nc->mdctx = EVP_MD_CTX_create();
420 if (nc->mdctx == NULL) {
421 ret = YACA_ERROR_INTERNAL;
426 if (EVP_DigestSignInit(nc->mdctx, NULL, NULL, NULL, pkey) != 1) {
427 ret = YACA_ERROR_INTERNAL;
434 *ctx = (yaca_context_h)nc;
436 ret = YACA_ERROR_NONE;
440 CMAC_CTX_free(cmac_ctx);
441 yaca_context_destroy((yaca_context_h)nc);
446 API int yaca_sign_update(yaca_context_h ctx,
450 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
453 if (c == NULL || c->op_type != OP_SIGN ||
454 data == NULL || data_len == 0)
455 return YACA_ERROR_INVALID_PARAMETER;
457 ret = EVP_DigestSignUpdate(c->mdctx, data, data_len);
459 ret = YACA_ERROR_INTERNAL;
464 return YACA_ERROR_NONE;
467 API int yaca_sign_finalize(yaca_context_h ctx,
469 size_t *signature_len)
471 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
474 if (c == NULL || c->op_type != OP_SIGN ||
475 signature == NULL || signature_len == NULL || *signature_len == 0)
476 return YACA_ERROR_INVALID_PARAMETER;
478 ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)signature, signature_len);
480 ret = YACA_ERROR_INTERNAL;
485 return YACA_ERROR_NONE;
488 API int yaca_verify_initialize(yaca_context_h *ctx,
489 yaca_digest_algorithm_e algo,
490 const yaca_key_h key)
492 struct yaca_sign_ctx_s *nc = NULL;
493 const EVP_MD *md = NULL;
495 const struct yaca_key_evp_s *evp_key = key_get_evp(key);
497 if (ctx == NULL || evp_key == NULL)
498 return YACA_ERROR_INVALID_PARAMETER;
501 case YACA_KEY_TYPE_RSA_PUB:
502 case YACA_KEY_TYPE_DSA_PUB:
504 // case YACA_KEY_TYPE_EC_PUB:
505 // TODO NOT_IMPLEMENTED
507 return YACA_ERROR_INVALID_PARAMETER;
510 ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
511 if (ret != YACA_ERROR_NONE)
514 nc->op_type = OP_VERIFY;
515 nc->ctx.type = YACA_CTX_SIGN;
516 nc->ctx.ctx_destroy = destroy_sign_context;
517 nc->ctx.get_output_length = NULL;
518 nc->ctx.set_param = set_sign_param;
519 nc->ctx.get_param = get_sign_param;
521 ret = digest_get_algorithm(algo, &md);
522 if (ret != YACA_ERROR_NONE)
525 nc->mdctx = EVP_MD_CTX_create();
526 if (nc->mdctx == NULL) {
527 ret = YACA_ERROR_INTERNAL;
532 ret = EVP_DigestVerifyInit(nc->mdctx, NULL, md, NULL, evp_key->evp);
534 ret = YACA_ERROR_INTERNAL;
539 *ctx = (yaca_context_h)nc;
541 ret = YACA_ERROR_NONE;
544 yaca_context_destroy((yaca_context_h)nc);
549 API int yaca_verify_update(yaca_context_h ctx,
553 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
556 if (c == NULL || data == NULL || data_len == 0 || c->op_type != OP_VERIFY)
557 return YACA_ERROR_INVALID_PARAMETER;
559 ret = EVP_DigestVerifyUpdate(c->mdctx, data, data_len);
561 ret = YACA_ERROR_INTERNAL;
566 return YACA_ERROR_NONE;
569 API int yaca_verify_finalize(yaca_context_h ctx,
570 const char *signature,
571 size_t signature_len)
573 struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
576 if (c == NULL || signature == NULL || signature_len == 0 || c->op_type != OP_VERIFY)
577 return YACA_ERROR_INVALID_PARAMETER;
579 ret = EVP_DigestVerifyFinal(c->mdctx,
580 (unsigned char *)signature,
584 return YACA_ERROR_NONE;
586 if (ret == YACA_ERROR_NONE) {
588 return YACA_ERROR_DATA_MISMATCH;
591 ret = YACA_ERROR_INTERNAL;