Migrate to openssl3
[platform/core/security/yaca.git] / src / sign.c
1 /*
2  *  Copyright (c) 2016-2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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
17  */
18
19 /**
20  * @file sign.c
21  * @brief
22  */
23
24 #include <assert.h>
25 #include <string.h>
26
27 #include <openssl/evp.h>
28 #include <openssl/rsa.h>
29
30 #include <yaca_crypto.h>
31 #include <yaca_sign.h>
32 #include <yaca_error.h>
33 #include <yaca_key.h>
34
35 #include "internal.h"
36
37 #ifdef OPENSSL_MOCKUP_TESTS
38 #include "../tests/openssl_mock_redefine.h"
39 #endif
40
41
42 /* Operation type saved in context to recognize what
43  * type of operation is performed and how to perform it.
44  */
45 enum sign_op_type {
46         OP_SIGN = 0,
47         OP_VERIFY = 1
48 };
49
50 struct yaca_sign_context_s {
51         struct yaca_context_s ctx;
52
53         EVP_MD_CTX *md_ctx;
54         enum sign_op_type op_type;
55         enum context_state_e state;
56 };
57
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 },
63 };
64
65 static bool verify_state_change(struct yaca_sign_context_s *c, enum context_state_e to)
66 {
67         int from = c->state;
68
69         return CTX_DEFAULT_STATES[from][to];
70 }
71
72 static struct yaca_sign_context_s *get_sign_context(const yaca_context_h ctx)
73 {
74         if (ctx == YACA_CONTEXT_NULL)
75                 return NULL;
76
77         switch (ctx->type) {
78         case YACA_CONTEXT_SIGN:
79                 return (struct yaca_sign_context_s *)ctx;
80         default:
81                 return NULL;
82         }
83 }
84
85 static int get_sign_output_length(const yaca_context_h ctx,
86                                                                   size_t input_len,
87                                                                   size_t *output_len)
88 {
89         assert(output_len != NULL);
90
91         int ret;
92         struct yaca_sign_context_s *c = get_sign_context(ctx);
93         assert(c != NULL);
94         assert(c->md_ctx != NULL);
95
96         if (input_len != 0)
97                 return YACA_ERROR_INVALID_PARAMETER;
98
99         ret = EVP_DigestSign(c->md_ctx, NULL, output_len, NULL, input_len);
100         if (ret != 1) {
101                 *output_len = 0;
102                 ret = YACA_ERROR_INTERNAL;
103                 ERROR_DUMP(ret);
104                 return ret;
105         }
106
107         return YACA_ERROR_NONE;
108 }
109
110 static void destroy_sign_context(yaca_context_h ctx)
111 {
112         struct yaca_sign_context_s *c = get_sign_context(ctx);
113         assert(c != NULL);
114
115         EVP_MD_CTX_destroy(c->md_ctx);
116         c->md_ctx = NULL;
117 }
118
119 int set_sign_property(yaca_context_h ctx,
120                                           yaca_property_e property,
121                                           const void *value,
122                                           size_t value_len)
123 {
124         int ret;
125         yaca_padding_e padding;
126         int pad;
127         EVP_PKEY *pkey;
128         EVP_PKEY_CTX *pctx;
129         struct yaca_sign_context_s *c = get_sign_context(ctx);
130         assert(c != NULL);
131         assert(c->md_ctx != NULL);
132
133         if (value == NULL || c->state == CTX_FINALIZED)
134                 return YACA_ERROR_INVALID_PARAMETER;
135
136         pctx = EVP_MD_CTX_get_pkey_ctx(c->md_ctx);
137         if (pctx == NULL) {
138                 ret = YACA_ERROR_INTERNAL;
139                 ERROR_DUMP(ret);
140                 return ret;
141         }
142
143         /* this function only supports padding */
144         if (property != YACA_PROPERTY_PADDING || value_len != sizeof(yaca_padding_e))
145                 return YACA_ERROR_INVALID_PARAMETER;
146
147         padding = *(yaca_padding_e *)(value);
148
149         switch (padding) {
150         case YACA_PADDING_X931:
151         case YACA_PADDING_PKCS1:
152         case YACA_PADDING_PKCS1_PSS:
153                 break;
154         default:
155                 return YACA_ERROR_INVALID_PARAMETER;
156         }
157
158         pad = rsa_padding2openssl(padding);
159
160         pkey = EVP_PKEY_CTX_get0_pkey(pctx);
161         if (pkey == NULL) {
162                 ret = YACA_ERROR_INTERNAL;
163                 ERROR_DUMP(ret);
164                 return ret;
165         }
166
167         /* padding only works for RSA */
168         if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA)
169                 return YACA_ERROR_INVALID_PARAMETER;
170
171         ret = EVP_PKEY_CTX_set_rsa_padding(pctx, pad);
172         if (ret <= 0) {
173                 ret = ERROR_HANDLE();
174                 return ret;
175         }
176
177         return YACA_ERROR_NONE;
178 }
179
180 API int yaca_sign_initialize(yaca_context_h *ctx,
181                                                          yaca_digest_algorithm_e algo,
182                                                          const yaca_key_h prv_key)
183 {
184         struct yaca_sign_context_s *nc = NULL;
185         const EVP_MD *md = NULL;
186         int ret;
187         const struct yaca_key_evp_s *evp_key = key_get_evp(prv_key);
188
189         if (ctx == NULL || evp_key == NULL)
190                 return YACA_ERROR_INVALID_PARAMETER;
191
192         ret = digest_get_algorithm(algo, &md);
193         if (ret != YACA_ERROR_NONE)
194                 return ret;
195
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;
201                 break;
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;
206                 break;
207         default:
208                 return YACA_ERROR_INVALID_PARAMETER;
209         }
210
211         ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
212         if (ret != YACA_ERROR_NONE)
213                 return ret;
214
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;
221
222         nc->md_ctx = EVP_MD_CTX_create();
223         if (nc->md_ctx == NULL) {
224                 ret = YACA_ERROR_INTERNAL;
225                 ERROR_DUMP(ret);
226                 goto exit;
227         }
228
229         ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
230         if (ret != 1) {
231                 ret = ERROR_HANDLE();
232                 goto exit;
233         }
234
235         nc->state = CTX_INITIALIZED;
236         *ctx = (yaca_context_h)nc;
237         nc = NULL;
238         ret = YACA_ERROR_NONE;
239
240 exit:
241         yaca_context_destroy((yaca_context_h)nc);
242
243         return ret;
244 }
245
246 API int yaca_sign_initialize_hmac(yaca_context_h *ctx,
247                                                                   yaca_digest_algorithm_e algo,
248                                                                   const yaca_key_h sym_key)
249 {
250         struct yaca_sign_context_s *nc = NULL;
251         EVP_PKEY *pkey = NULL;
252         const EVP_MD *md;
253         int ret;
254         const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key);
255
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;
259
260         ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
261         if (ret != YACA_ERROR_NONE)
262                 return ret;
263
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;
270
271         pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
272                                                                 NULL,
273                                                                 (unsigned char *)simple_key->d,
274                                                                 simple_key->bit_len / 8);
275         if (pkey == NULL) {
276                 ret = YACA_ERROR_INTERNAL;
277                 ERROR_DUMP(ret);
278                 goto exit;
279         }
280
281         ret = digest_get_algorithm(algo, &md);
282         if (ret != YACA_ERROR_NONE)
283                 goto exit;
284
285         nc->md_ctx = EVP_MD_CTX_create();
286         if (nc->md_ctx == NULL) {
287                 ret = YACA_ERROR_INTERNAL;
288                 ERROR_DUMP(ret);
289                 goto exit;
290         }
291
292         ret = EVP_DigestSignInit(nc->md_ctx, NULL, md, NULL, pkey);
293         if (ret != 1) {
294                 ret = YACA_ERROR_INTERNAL;
295                 ERROR_DUMP(ret);
296                 goto exit;
297         }
298
299         nc->state = CTX_INITIALIZED;
300         *ctx = (yaca_context_h)nc;
301         nc = NULL;
302         ret = YACA_ERROR_NONE;
303
304 exit:
305         EVP_PKEY_free(pkey);
306         yaca_context_destroy((yaca_context_h)nc);
307
308         return ret;
309 }
310
311 API int yaca_sign_initialize_cmac(yaca_context_h *ctx,
312                                                                   yaca_encrypt_algorithm_e algo,
313                                                                   const yaca_key_h sym_key)
314 {
315         struct yaca_sign_context_s *nc = NULL;
316         const EVP_CIPHER* cipher = NULL;
317         EVP_PKEY *pkey = NULL;
318         int ret;
319         const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key);
320
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;
324
325         ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
326         if (ret != YACA_ERROR_NONE)
327                 return ret;
328
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;
335
336         ret = encrypt_get_algorithm(algo, YACA_BCM_CBC, simple_key->bit_len, &cipher);
337         if (ret != YACA_ERROR_NONE)
338                 goto exit;
339
340         /* create CMAC key */
341         pkey = EVP_PKEY_new_CMAC_key(NULL, (unsigned char *) simple_key->d, simple_key->bit_len / 8, cipher);
342         if (pkey == NULL) {
343                 ret = YACA_ERROR_INTERNAL;
344                 ERROR_DUMP(ret);
345                 goto exit;
346         }
347
348         nc->md_ctx = EVP_MD_CTX_create();
349         if (nc->md_ctx == NULL) {
350                 ret = YACA_ERROR_INTERNAL;
351                 ERROR_DUMP(ret);
352                 goto exit;
353         }
354
355         if (EVP_DigestSignInit(nc->md_ctx, NULL, NULL, NULL, pkey) != 1) {
356                 ret = YACA_ERROR_INTERNAL;
357                 ERROR_DUMP(ret);
358                 goto exit;
359         }
360
361         nc->state = CTX_INITIALIZED;
362         *ctx = (yaca_context_h)nc;
363         nc = NULL;
364         ret = YACA_ERROR_NONE;
365
366 exit:
367         EVP_PKEY_free(pkey);
368         yaca_context_destroy((yaca_context_h)nc);
369
370         return ret;
371 }
372
373 API int yaca_sign_update(yaca_context_h ctx,
374                                                  const char *message,
375                                                  size_t message_len)
376 {
377         struct yaca_sign_context_s *c = get_sign_context(ctx);
378         int ret;
379
380         if (c == NULL || c->op_type != OP_SIGN ||
381                 message == NULL || message_len == 0)
382                 return YACA_ERROR_INVALID_PARAMETER;
383
384         if (!verify_state_change(c, CTX_MSG_UPDATED))
385                 return YACA_ERROR_INVALID_PARAMETER;
386
387         ret = EVP_DigestSignUpdate(c->md_ctx, message, message_len);
388         if (ret != 1) {
389                 ret = YACA_ERROR_INTERNAL;
390                 ERROR_DUMP(ret);
391                 return ret;
392         }
393
394         c->state = CTX_MSG_UPDATED;
395         return YACA_ERROR_NONE;
396 }
397
398 API int yaca_sign_finalize(yaca_context_h ctx,
399                                                    char *signature,
400                                                    size_t *signature_len)
401 {
402         struct yaca_sign_context_s *c = get_sign_context(ctx);
403         int ret;
404
405         if (c == NULL ||  c->op_type != OP_SIGN ||
406                 signature == NULL || signature_len == NULL)
407                 return YACA_ERROR_INVALID_PARAMETER;
408
409         if (!verify_state_change(c, CTX_FINALIZED))
410                 return YACA_ERROR_INVALID_PARAMETER;
411
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.
415          */
416         ret = ctx->get_output_length(ctx, 0, signature_len);
417         if (ret != YACA_ERROR_NONE)
418                 return ret;
419
420         ret = EVP_DigestSignFinal(c->md_ctx, (unsigned char *)signature, signature_len);
421         if (ret != 1) {
422                 ret = YACA_ERROR_INTERNAL;
423                 ERROR_DUMP(ret);
424                 return ret;
425         }
426
427         c->state = CTX_FINALIZED;
428         return YACA_ERROR_NONE;
429 }
430
431 API int yaca_verify_initialize(yaca_context_h *ctx,
432                                                            yaca_digest_algorithm_e algo,
433                                                            const yaca_key_h pub_key)
434 {
435         struct yaca_sign_context_s *nc = NULL;
436         const EVP_MD *md = NULL;
437         int ret;
438         const struct yaca_key_evp_s *evp_key = key_get_evp(pub_key);
439
440         if (ctx == NULL || evp_key == NULL)
441                 return YACA_ERROR_INVALID_PARAMETER;
442
443         ret = digest_get_algorithm(algo, &md);
444         if (ret != YACA_ERROR_NONE)
445                 return ret;
446
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;
452                 break;
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;
457                 break;
458         default:
459                 return YACA_ERROR_INVALID_PARAMETER;
460         }
461
462         ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc);
463         if (ret != YACA_ERROR_NONE)
464                 return ret;
465
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;
472
473         nc->md_ctx = EVP_MD_CTX_create();
474         if (nc->md_ctx == NULL) {
475                 ret = YACA_ERROR_INTERNAL;
476                 ERROR_DUMP(ret);
477                 goto exit;
478         }
479
480         ret = EVP_DigestVerifyInit(nc->md_ctx, NULL, md, NULL, evp_key->evp);
481         if (ret != 1) {
482                 ret = ERROR_HANDLE();
483                 goto exit;
484         }
485
486         nc->state = CTX_INITIALIZED;
487         *ctx = (yaca_context_h)nc;
488         nc = NULL;
489         ret = YACA_ERROR_NONE;
490
491 exit:
492         yaca_context_destroy((yaca_context_h)nc);
493
494         return ret;
495 }
496
497 API int yaca_verify_update(yaca_context_h ctx,
498                                                    const char *message,
499                                                    size_t message_len)
500 {
501         struct yaca_sign_context_s *c = get_sign_context(ctx);
502         int ret;
503
504         if (c == NULL || message == NULL || message_len == 0 || c->op_type != OP_VERIFY)
505                 return YACA_ERROR_INVALID_PARAMETER;
506
507         if (!verify_state_change(c, CTX_MSG_UPDATED))
508                 return YACA_ERROR_INVALID_PARAMETER;
509
510         ret = EVP_DigestVerifyUpdate(c->md_ctx, message, message_len);
511         if (ret != 1) {
512                 ret = YACA_ERROR_INTERNAL;
513                 ERROR_DUMP(ret);
514                 return ret;
515         }
516
517         c->state = CTX_MSG_UPDATED;
518         return YACA_ERROR_NONE;
519 }
520
521 API int yaca_verify_finalize(yaca_context_h ctx,
522                                                          const char *signature,
523                                                          size_t signature_len)
524 {
525         struct yaca_sign_context_s *c = get_sign_context(ctx);
526         int ret;
527
528         if (c == NULL || signature == NULL || signature_len == 0 || c->op_type != OP_VERIFY)
529                 return YACA_ERROR_INVALID_PARAMETER;
530
531         if (!verify_state_change(c, CTX_FINALIZED))
532                 return YACA_ERROR_INVALID_PARAMETER;
533
534         ret = EVP_DigestVerifyFinal(c->md_ctx,
535                                                                 (unsigned char *)signature,
536                                                                 signature_len);
537
538         if (ret == 1) {
539                 c->state = CTX_FINALIZED;
540                 return YACA_ERROR_NONE;
541         }
542
543         if (ret == 0) {
544                 ERROR_CLEAR();
545                 return YACA_ERROR_DATA_MISMATCH;
546         }
547
548         ret = YACA_ERROR_INTERNAL;
549         ERROR_DUMP(ret);
550         return ret;
551 }