2 * Copyright (c) 2016-2020 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>
30 #include <yaca_crypto.h>
31 #include <yaca_sign.h>
32 #include <yaca_error.h>
37 #ifdef OPENSSL_MOCKUP_TESTS
38 #include "../tests/openssl_mock_redefine.h"
42 /* Operation type saved in context to recognize what
43 * type of operation is performed and how to perform it.
50 struct yaca_sign_context_s {
51 struct yaca_context_s ctx;
54 enum sign_op_type op_type;
55 enum context_state_e state;
58 static bool CTX_DEFAULT_STATES[CTX_COUNT][CTX_COUNT] = {
59 /* from \ to INIT, MSG, FIN */
60 /* INIT */ { 0, 1, 1 },
61 /* MSG */ { 0, 1, 1 },
62 /* FIN */ { 0, 0, 0 },
65 static bool verify_state_change(struct yaca_sign_context_s *c, enum context_state_e to)
69 return CTX_DEFAULT_STATES[from][to];
72 static struct yaca_sign_context_s *get_sign_context(const yaca_context_h ctx)
74 if (ctx == YACA_CONTEXT_NULL)
78 case YACA_CONTEXT_SIGN:
79 return (struct yaca_sign_context_s *)ctx;
85 static int get_sign_output_length(const yaca_context_h ctx,
89 assert(output_len != NULL);
92 struct yaca_sign_context_s *c = get_sign_context(ctx);
94 assert(c->md_ctx != NULL);
97 return YACA_ERROR_INVALID_PARAMETER;
99 ret = EVP_DigestSign(c->md_ctx, NULL, output_len, NULL, input_len);
102 ret = YACA_ERROR_INTERNAL;
107 return YACA_ERROR_NONE;
110 static void destroy_sign_context(yaca_context_h ctx)
112 struct yaca_sign_context_s *c = get_sign_context(ctx);
115 EVP_MD_CTX_destroy(c->md_ctx);
119 int set_sign_property(yaca_context_h ctx,
120 yaca_property_e property,
125 yaca_padding_e padding;
129 struct yaca_sign_context_s *c = get_sign_context(ctx);
131 assert(c->md_ctx != NULL);
133 if (value == NULL || c->state == CTX_FINALIZED)
134 return YACA_ERROR_INVALID_PARAMETER;
136 pctx = EVP_MD_CTX_get_pkey_ctx(c->md_ctx);
138 ret = YACA_ERROR_INTERNAL;
143 /* this function only supports padding */
144 if (property != YACA_PROPERTY_PADDING || value_len != sizeof(yaca_padding_e))
145 return YACA_ERROR_INVALID_PARAMETER;
147 padding = *(yaca_padding_e *)(value);
150 case YACA_PADDING_X931:
151 case YACA_PADDING_PKCS1:
152 case YACA_PADDING_PKCS1_PSS:
155 return YACA_ERROR_INVALID_PARAMETER;
158 pad = rsa_padding2openssl(padding);
160 pkey = EVP_PKEY_CTX_get0_pkey(pctx);
162 ret = YACA_ERROR_INTERNAL;
167 /* padding only works for RSA */
168 if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA)
169 return YACA_ERROR_INVALID_PARAMETER;
171 ret = EVP_PKEY_CTX_set_rsa_padding(pctx, pad);
173 ret = ERROR_HANDLE();
177 return YACA_ERROR_NONE;
180 API int yaca_sign_initialize(yaca_context_h *ctx,
181 yaca_digest_algorithm_e algo,
182 const yaca_key_h prv_key)
184 struct yaca_sign_context_s *nc = NULL;
185 const EVP_MD *md = NULL;
187 const struct yaca_key_evp_s *evp_key = key_get_evp(prv_key);
189 if (ctx == NULL || evp_key == NULL)
190 return YACA_ERROR_INVALID_PARAMETER;
192 ret = digest_get_algorithm(algo, &md);
193 if (ret != YACA_ERROR_NONE)
196 switch (prv_key->type) {
197 case YACA_KEY_TYPE_RSA_PRIV:
198 if (EVP_MD_size(md) >= EVP_PKEY_get_size(evp_key->evp) ||
199 (algo == YACA_DIGEST_SHA384 && (EVP_PKEY_get_size(evp_key->evp) <= YACA_KEY_LENGTH_512BIT / 8)))
200 return YACA_ERROR_INVALID_PARAMETER;
202 case YACA_KEY_TYPE_DSA_PRIV:
203 case YACA_KEY_TYPE_EC_PRIV:
204 if (algo == YACA_DIGEST_MD5)
205 return YACA_ERROR_INVALID_PARAMETER;
208 return YACA_ERROR_INVALID_PARAMETER;
211 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
212 if (ret != YACA_ERROR_NONE)
215 nc->op_type = OP_SIGN;
216 nc->ctx.type = YACA_CONTEXT_SIGN;
217 nc->ctx.context_destroy = destroy_sign_context;
218 nc->ctx.get_output_length = get_sign_output_length;
219 nc->ctx.set_property = set_sign_property;
220 nc->ctx.get_property = NULL;
222 nc->md_ctx = EVP_MD_CTX_create();
223 if (nc->md_ctx == NULL) {
224 ret = YACA_ERROR_INTERNAL;
229 ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
231 ret = ERROR_HANDLE();
235 nc->state = CTX_INITIALIZED;
236 *ctx = (yaca_context_h)nc;
238 ret = YACA_ERROR_NONE;
241 yaca_context_destroy((yaca_context_h)nc);
246 API int yaca_sign_initialize_hmac(yaca_context_h *ctx,
247 yaca_digest_algorithm_e algo,
248 const yaca_key_h sym_key)
250 struct yaca_sign_context_s *nc = NULL;
251 EVP_PKEY *pkey = NULL;
254 const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key);
256 if (ctx == NULL || simple_key == NULL ||
257 (sym_key->type != YACA_KEY_TYPE_SYMMETRIC && sym_key->type != YACA_KEY_TYPE_DES))
258 return YACA_ERROR_INVALID_PARAMETER;
260 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
261 if (ret != YACA_ERROR_NONE)
264 nc->op_type = OP_SIGN;
265 nc->ctx.type = YACA_CONTEXT_SIGN;
266 nc->ctx.context_destroy = destroy_sign_context;
267 nc->ctx.get_output_length = get_sign_output_length;
268 nc->ctx.set_property = NULL;
269 nc->ctx.get_property = NULL;
271 pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
273 (unsigned char *)simple_key->d,
274 simple_key->bit_len / 8);
276 ret = YACA_ERROR_INTERNAL;
281 ret = digest_get_algorithm(algo, &md);
282 if (ret != YACA_ERROR_NONE)
285 nc->md_ctx = EVP_MD_CTX_create();
286 if (nc->md_ctx == NULL) {
287 ret = YACA_ERROR_INTERNAL;
292 ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, pkey);
294 ret = YACA_ERROR_INTERNAL;
299 nc->state = CTX_INITIALIZED;
300 *ctx = (yaca_context_h)nc;
302 ret = YACA_ERROR_NONE;
306 yaca_context_destroy((yaca_context_h)nc);
311 API int yaca_sign_initialize_cmac(yaca_context_h *ctx,
312 yaca_encrypt_algorithm_e algo,
313 const yaca_key_h sym_key)
315 struct yaca_sign_context_s *nc = NULL;
316 const EVP_CIPHER* cipher = NULL;
317 EVP_PKEY *pkey = NULL;
319 const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key);
321 if (ctx == NULL || simple_key == NULL ||
322 (sym_key->type != YACA_KEY_TYPE_SYMMETRIC && sym_key->type != YACA_KEY_TYPE_DES))
323 return YACA_ERROR_INVALID_PARAMETER;
325 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
326 if (ret != YACA_ERROR_NONE)
329 nc->op_type = OP_SIGN;
330 nc->ctx.type = YACA_CONTEXT_SIGN;
331 nc->ctx.context_destroy = destroy_sign_context;
332 nc->ctx.get_output_length = get_sign_output_length;
333 nc->ctx.set_property = NULL;
334 nc->ctx.get_property = NULL;
336 ret = encrypt_get_algorithm(algo, YACA_BCM_CBC, simple_key->bit_len, &cipher);
337 if (ret != YACA_ERROR_NONE)
340 /* create CMAC key */
341 pkey = EVP_PKEY_new_CMAC_key(NULL, (unsigned char *) simple_key->d, simple_key->bit_len / 8, cipher);
343 ret = YACA_ERROR_INTERNAL;
348 nc->md_ctx = EVP_MD_CTX_create();
349 if (nc->md_ctx == NULL) {
350 ret = YACA_ERROR_INTERNAL;
355 if (EVP_DigestSignInit(nc->md_ctx, NULL, NULL, NULL, pkey) != 1) {
356 ret = YACA_ERROR_INTERNAL;
361 nc->state = CTX_INITIALIZED;
362 *ctx = (yaca_context_h)nc;
364 ret = YACA_ERROR_NONE;
368 yaca_context_destroy((yaca_context_h)nc);
373 API int yaca_sign_update(yaca_context_h ctx,
377 struct yaca_sign_context_s *c = get_sign_context(ctx);
380 if (c == NULL || c->op_type != OP_SIGN ||
381 message == NULL || message_len == 0)
382 return YACA_ERROR_INVALID_PARAMETER;
384 if (!verify_state_change(c, CTX_MSG_UPDATED))
385 return YACA_ERROR_INVALID_PARAMETER;
387 ret = EVP_DigestSignUpdate(c->md_ctx, message, message_len);
389 ret = YACA_ERROR_INTERNAL;
394 c->state = CTX_MSG_UPDATED;
395 return YACA_ERROR_NONE;
398 API int yaca_sign_finalize(yaca_context_h ctx,
400 size_t *signature_len)
402 struct yaca_sign_context_s *c = get_sign_context(ctx);
405 if (c == NULL || c->op_type != OP_SIGN ||
406 signature == NULL || signature_len == NULL)
407 return YACA_ERROR_INVALID_PARAMETER;
409 if (!verify_state_change(c, CTX_FINALIZED))
410 return YACA_ERROR_INVALID_PARAMETER;
412 /* EVP_DigestSignFinal() is the only *Final that requires buffer
413 * length as the [in,out], don't break the symmetry in our API,
414 * don't require it from the user, get the apropriate length here.
416 ret = ctx->get_output_length(ctx, 0, signature_len);
417 if (ret != YACA_ERROR_NONE)
420 ret = EVP_DigestSignFinal(c->md_ctx, (unsigned char *)signature, signature_len);
422 ret = YACA_ERROR_INTERNAL;
427 c->state = CTX_FINALIZED;
428 return YACA_ERROR_NONE;
431 API int yaca_verify_initialize(yaca_context_h *ctx,
432 yaca_digest_algorithm_e algo,
433 const yaca_key_h pub_key)
435 struct yaca_sign_context_s *nc = NULL;
436 const EVP_MD *md = NULL;
438 const struct yaca_key_evp_s *evp_key = key_get_evp(pub_key);
440 if (ctx == NULL || evp_key == NULL)
441 return YACA_ERROR_INVALID_PARAMETER;
443 ret = digest_get_algorithm(algo, &md);
444 if (ret != YACA_ERROR_NONE)
447 switch (pub_key->type) {
448 case YACA_KEY_TYPE_RSA_PUB:
449 if (EVP_MD_size(md) >= EVP_PKEY_get_size(evp_key->evp) ||
450 (algo == YACA_DIGEST_SHA384 && (EVP_PKEY_get_size(evp_key->evp) <= YACA_KEY_LENGTH_512BIT / 8)))
451 return YACA_ERROR_INVALID_PARAMETER;
453 case YACA_KEY_TYPE_DSA_PUB:
454 case YACA_KEY_TYPE_EC_PUB:
455 if (algo == YACA_DIGEST_MD5)
456 return YACA_ERROR_INVALID_PARAMETER;
459 return YACA_ERROR_INVALID_PARAMETER;
462 ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
463 if (ret != YACA_ERROR_NONE)
466 nc->op_type = OP_VERIFY;
467 nc->ctx.type = YACA_CONTEXT_SIGN;
468 nc->ctx.context_destroy = destroy_sign_context;
469 nc->ctx.get_output_length = NULL;
470 nc->ctx.set_property = set_sign_property;
471 nc->ctx.get_property = NULL;
473 nc->md_ctx = EVP_MD_CTX_create();
474 if (nc->md_ctx == NULL) {
475 ret = YACA_ERROR_INTERNAL;
480 ret = EVP_DigestVerifyInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
482 ret = ERROR_HANDLE();
486 nc->state = CTX_INITIALIZED;
487 *ctx = (yaca_context_h)nc;
489 ret = YACA_ERROR_NONE;
492 yaca_context_destroy((yaca_context_h)nc);
497 API int yaca_verify_update(yaca_context_h ctx,
501 struct yaca_sign_context_s *c = get_sign_context(ctx);
504 if (c == NULL || message == NULL || message_len == 0 || c->op_type != OP_VERIFY)
505 return YACA_ERROR_INVALID_PARAMETER;
507 if (!verify_state_change(c, CTX_MSG_UPDATED))
508 return YACA_ERROR_INVALID_PARAMETER;
510 ret = EVP_DigestVerifyUpdate(c->md_ctx, message, message_len);
512 ret = YACA_ERROR_INTERNAL;
517 c->state = CTX_MSG_UPDATED;
518 return YACA_ERROR_NONE;
521 API int yaca_verify_finalize(yaca_context_h ctx,
522 const char *signature,
523 size_t signature_len)
525 struct yaca_sign_context_s *c = get_sign_context(ctx);
528 if (c == NULL || signature == NULL || signature_len == 0 || c->op_type != OP_VERIFY)
529 return YACA_ERROR_INVALID_PARAMETER;
531 if (!verify_state_change(c, CTX_FINALIZED))
532 return YACA_ERROR_INVALID_PARAMETER;
534 ret = EVP_DigestVerifyFinal(c->md_ctx,
535 (unsigned char *)signature,
539 c->state = CTX_FINALIZED;
540 return YACA_ERROR_NONE;
545 return YACA_ERROR_DATA_MISMATCH;
548 ret = YACA_ERROR_INTERNAL;