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;
53 static struct yaca_sign_context_s *get_sign_context(const yaca_context_h ctx)
55 if (ctx == YACA_CONTEXT_NULL)
59 case YACA_CONTEXT_SIGN:
60 return (struct yaca_sign_context_s *)ctx;
66 static int get_sign_output_length(const yaca_context_h ctx,
70 assert(output_len != NULL);
72 struct yaca_sign_context_s *c = get_sign_context(ctx);
74 if (c == NULL || input_len != 0)
75 return YACA_ERROR_INVALID_PARAMETER;
77 assert(c->md_ctx != NULL);
79 if (c->md_ctx->pctx == NULL)
80 return YACA_ERROR_INTERNAL;
82 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->md_ctx->pctx);
84 ERROR_DUMP(YACA_ERROR_INTERNAL);
85 return YACA_ERROR_INTERNAL;
88 int len = EVP_PKEY_size(pkey);
90 ERROR_DUMP(YACA_ERROR_INTERNAL);
91 return YACA_ERROR_INTERNAL;
95 return YACA_ERROR_NONE;
98 static void destroy_sign_context(yaca_context_h ctx)
100 struct yaca_sign_context_s *c = get_sign_context(ctx);
105 EVP_MD_CTX_destroy(c->md_ctx);
109 int set_sign_property(yaca_context_h ctx,
110 yaca_property_e property,
115 struct yaca_sign_context_s *c = get_sign_context(ctx);
116 yaca_padding_e padding;
120 if (c == NULL || value == NULL)
121 return YACA_ERROR_INVALID_PARAMETER;
123 assert(c->md_ctx != NULL);
125 if (c->md_ctx->pctx == NULL)
126 return YACA_ERROR_INTERNAL;
128 /* this function only supports padding */
129 if (property != YACA_PROPERTY_PADDING || value_len != sizeof(yaca_padding_e))
130 return YACA_ERROR_INVALID_PARAMETER;
132 padding = *(yaca_padding_e *)(value);
134 // TODO: investigate whether it's possible to set
135 // RSA_NO_PADDING or RSA_SSLV23_PADDING in some cases
137 case YACA_PADDING_X931:
138 pad = RSA_X931_PADDING;
140 case YACA_PADDING_PKCS1:
141 pad = RSA_PKCS1_PADDING;
143 case YACA_PADDING_PKCS1_PSS:
144 pad = RSA_PKCS1_PSS_PADDING;
147 return YACA_ERROR_INVALID_PARAMETER;
150 pkey = EVP_PKEY_CTX_get0_pkey(c->md_ctx->pctx);
152 ret = YACA_ERROR_INTERNAL;
157 /* padding only works for RSA */
158 if (pkey->type != EVP_PKEY_RSA)
159 return YACA_ERROR_INVALID_PARAMETER;
161 ret = EVP_PKEY_CTX_set_rsa_padding(c->md_ctx->pctx, pad);
163 ret = YACA_ERROR_INTERNAL;
168 return YACA_ERROR_NONE;
171 int get_sign_property(const yaca_context_h ctx,
172 yaca_property_e property,
177 struct yaca_sign_context_s *c = get_sign_context(ctx);
180 yaca_padding_e padding;
182 if (c == NULL || value == NULL)
183 return YACA_ERROR_INVALID_PARAMETER;
185 assert(c->md_ctx != NULL);
187 if (c->md_ctx->pctx == NULL)
188 return YACA_ERROR_INTERNAL;
190 /* this function only supports padding */
191 if (property != YACA_PROPERTY_PADDING)
192 return YACA_ERROR_INVALID_PARAMETER;
194 pkey = EVP_PKEY_CTX_get0_pkey(c->md_ctx->pctx);
196 ret = YACA_ERROR_INTERNAL;
201 /* padding only works for RSA */
202 if (pkey->type != EVP_PKEY_RSA)
203 return YACA_ERROR_INVALID_PARAMETER;
205 ret = EVP_PKEY_CTX_get_rsa_padding(c->md_ctx->pctx, &pad);
207 ret = YACA_ERROR_INTERNAL;
213 case RSA_X931_PADDING:
214 padding = YACA_PADDING_X931;
216 case RSA_PKCS1_PADDING:
217 padding = YACA_PADDING_PKCS1;
219 case RSA_PKCS1_PSS_PADDING:
220 padding = YACA_PADDING_PKCS1_PSS;
223 ret = YACA_ERROR_INTERNAL;
224 ERROR_DUMP(YACA_ERROR_INTERNAL);
228 ret = yaca_malloc(sizeof(yaca_padding_e), value);
229 if (ret != YACA_ERROR_NONE)
232 memcpy(*value, &padding, sizeof(yaca_padding_e));
233 if (value_len != NULL)
234 *value_len = sizeof(yaca_padding_e);
236 return YACA_ERROR_NONE;
239 API int yaca_sign_initialize(yaca_context_h *ctx,
240 yaca_digest_algorithm_e algo,
241 const yaca_key_h key)
243 struct yaca_sign_context_s *nc = NULL;
244 const EVP_MD *md = NULL;
246 const struct yaca_key_evp_s *evp_key = key_get_evp(key);
248 if (ctx == NULL || evp_key == NULL)
249 return YACA_ERROR_INVALID_PARAMETER;
252 case YACA_KEY_TYPE_RSA_PRIV:
253 case YACA_KEY_TYPE_DSA_PRIV:
255 // case YACA_KEY_TYPE_EC_PRIV:
256 // TODO NOT_IMPLEMENTED
258 return YACA_ERROR_INVALID_PARAMETER;
261 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
262 if (ret != YACA_ERROR_NONE)
265 nc->op_type = OP_SIGN;
266 nc->ctx.type = YACA_CONTEXT_SIGN;
267 nc->ctx.context_destroy = destroy_sign_context;
268 nc->ctx.get_output_length = get_sign_output_length;
269 nc->ctx.set_property = set_sign_property;
270 nc->ctx.get_property = get_sign_property;
272 ret = digest_get_algorithm(algo, &md);
273 if (ret != YACA_ERROR_NONE)
276 nc->md_ctx = EVP_MD_CTX_create();
277 if (nc->md_ctx == NULL) {
278 ret = YACA_ERROR_INTERNAL;
283 ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
285 ret = YACA_ERROR_INTERNAL;
290 *ctx = (yaca_context_h)nc;
292 ret = YACA_ERROR_NONE;
295 yaca_context_destroy((yaca_context_h)nc);
300 API int yaca_sign_initialize_hmac(yaca_context_h *ctx,
301 yaca_digest_algorithm_e algo,
302 const yaca_key_h key)
304 struct yaca_sign_context_s *nc = NULL;
305 EVP_PKEY *pkey = NULL;
308 const struct yaca_key_simple_s *simple_key = key_get_simple(key);
310 if (ctx == NULL || simple_key == NULL ||
311 (key->type != YACA_KEY_TYPE_SYMMETRIC && key->type != YACA_KEY_TYPE_DES))
312 return YACA_ERROR_INVALID_PARAMETER;
314 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
315 if (ret != YACA_ERROR_NONE)
318 nc->op_type = OP_SIGN;
319 nc->ctx.type = YACA_CONTEXT_SIGN;
320 nc->ctx.context_destroy = destroy_sign_context;
321 nc->ctx.get_output_length = get_sign_output_length;
323 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
325 (unsigned char *)simple_key->d,
326 simple_key->bit_len / 8);
328 ret = YACA_ERROR_INTERNAL;
333 ret = digest_get_algorithm(algo, &md);
334 if (ret != YACA_ERROR_NONE)
337 nc->md_ctx = EVP_MD_CTX_create();
338 if (nc->md_ctx == NULL) {
339 ret = YACA_ERROR_INTERNAL;
344 ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, pkey);
346 ret = YACA_ERROR_INTERNAL;
353 *ctx = (yaca_context_h)nc;
355 ret = YACA_ERROR_NONE;
359 yaca_context_destroy((yaca_context_h)nc);
364 API int yaca_sign_initialize_cmac(yaca_context_h *ctx,
365 yaca_encrypt_algorithm_e algo,
366 const yaca_key_h key)
368 struct yaca_sign_context_s *nc = NULL;
369 CMAC_CTX* cmac_ctx = NULL;
370 const EVP_CIPHER* cipher = NULL;
371 EVP_PKEY *pkey = NULL;
373 const struct yaca_key_simple_s *simple_key = key_get_simple(key);
375 if (ctx == NULL || simple_key == NULL ||
376 (key->type != YACA_KEY_TYPE_SYMMETRIC && key->type != YACA_KEY_TYPE_DES))
377 return YACA_ERROR_INVALID_PARAMETER;
379 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
380 if (ret != YACA_ERROR_NONE)
383 nc->op_type = OP_SIGN;
384 nc->ctx.type = YACA_CONTEXT_SIGN;
385 nc->ctx.context_destroy = destroy_sign_context;
386 nc->ctx.get_output_length = get_sign_output_length;
388 ret = encrypt_get_algorithm(algo, YACA_BCM_CBC, simple_key->bit_len, &cipher);
389 if (ret != YACA_ERROR_NONE)
392 /* create and initialize low level CMAC context */
393 cmac_ctx = CMAC_CTX_new();
394 if (cmac_ctx == NULL) {
395 ret = YACA_ERROR_INTERNAL;
400 if (CMAC_Init(cmac_ctx, simple_key->d, simple_key->bit_len / 8, cipher, NULL) != 1) {
401 ret = YACA_ERROR_INTERNAL;
406 /* create key and assign CMAC context to it */
407 pkey = EVP_PKEY_new();
409 ret = YACA_ERROR_INTERNAL;
414 if (EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmac_ctx) != 1) {
415 ret = YACA_ERROR_INTERNAL;
422 nc->md_ctx = EVP_MD_CTX_create();
423 if (nc->md_ctx == NULL) {
424 ret = YACA_ERROR_INTERNAL;
429 if (EVP_DigestSignInit(nc->md_ctx, NULL, NULL, NULL, pkey) != 1) {
430 ret = YACA_ERROR_INTERNAL;
437 *ctx = (yaca_context_h)nc;
439 ret = YACA_ERROR_NONE;
443 CMAC_CTX_free(cmac_ctx);
444 yaca_context_destroy((yaca_context_h)nc);
449 API int yaca_sign_update(yaca_context_h ctx,
453 struct yaca_sign_context_s *c = get_sign_context(ctx);
456 if (c == NULL || c->op_type != OP_SIGN ||
457 data == NULL || data_len == 0)
458 return YACA_ERROR_INVALID_PARAMETER;
460 ret = EVP_DigestSignUpdate(c->md_ctx, data, data_len);
462 ret = YACA_ERROR_INTERNAL;
467 return YACA_ERROR_NONE;
470 API int yaca_sign_finalize(yaca_context_h ctx,
472 size_t *signature_len)
474 struct yaca_sign_context_s *c = get_sign_context(ctx);
477 if (c == NULL || c->op_type != OP_SIGN ||
478 signature == NULL || signature_len == NULL || *signature_len == 0)
479 return YACA_ERROR_INVALID_PARAMETER;
481 ret = EVP_DigestSignFinal(c->md_ctx, (unsigned char *)signature, signature_len);
483 ret = YACA_ERROR_INTERNAL;
488 return YACA_ERROR_NONE;
491 API int yaca_verify_initialize(yaca_context_h *ctx,
492 yaca_digest_algorithm_e algo,
493 const yaca_key_h key)
495 struct yaca_sign_context_s *nc = NULL;
496 const EVP_MD *md = NULL;
498 const struct yaca_key_evp_s *evp_key = key_get_evp(key);
500 if (ctx == NULL || evp_key == NULL)
501 return YACA_ERROR_INVALID_PARAMETER;
504 case YACA_KEY_TYPE_RSA_PUB:
505 case YACA_KEY_TYPE_DSA_PUB:
507 // case YACA_KEY_TYPE_EC_PUB:
508 // TODO NOT_IMPLEMENTED
510 return YACA_ERROR_INVALID_PARAMETER;
513 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
514 if (ret != YACA_ERROR_NONE)
517 nc->op_type = OP_VERIFY;
518 nc->ctx.type = YACA_CONTEXT_SIGN;
519 nc->ctx.context_destroy = destroy_sign_context;
520 nc->ctx.get_output_length = NULL;
521 nc->ctx.set_property = set_sign_property;
522 nc->ctx.get_property = get_sign_property;
524 ret = digest_get_algorithm(algo, &md);
525 if (ret != YACA_ERROR_NONE)
528 nc->md_ctx = EVP_MD_CTX_create();
529 if (nc->md_ctx == NULL) {
530 ret = YACA_ERROR_INTERNAL;
535 ret = EVP_DigestVerifyInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
537 ret = YACA_ERROR_INTERNAL;
542 *ctx = (yaca_context_h)nc;
544 ret = YACA_ERROR_NONE;
547 yaca_context_destroy((yaca_context_h)nc);
552 API int yaca_verify_update(yaca_context_h ctx,
556 struct yaca_sign_context_s *c = get_sign_context(ctx);
559 if (c == NULL || data == NULL || data_len == 0 || c->op_type != OP_VERIFY)
560 return YACA_ERROR_INVALID_PARAMETER;
562 ret = EVP_DigestVerifyUpdate(c->md_ctx, data, data_len);
564 ret = YACA_ERROR_INTERNAL;
569 return YACA_ERROR_NONE;
572 API int yaca_verify_finalize(yaca_context_h ctx,
573 const char *signature,
574 size_t signature_len)
576 struct yaca_sign_context_s *c = get_sign_context(ctx);
579 if (c == NULL || signature == NULL || signature_len == 0 || c->op_type != OP_VERIFY)
580 return YACA_ERROR_INVALID_PARAMETER;
582 ret = EVP_DigestVerifyFinal(c->md_ctx,
583 (unsigned char *)signature,
587 return YACA_ERROR_NONE;
591 return YACA_ERROR_DATA_MISMATCH;
594 ret = YACA_ERROR_INTERNAL;