afaaec02fcd82950ca66577f96dd4f6da5b75b71
[platform/core/security/yaca.git] / src / sign.c
1 /*
2  *  Copyright (c) 2016 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 #include <openssl/cmac.h>
30
31 #include <yaca_crypto.h>
32 #include <yaca_sign.h>
33 #include <yaca_error.h>
34 #include <yaca_key.h>
35
36 #include "internal.h"
37
38 /* Operation type saved in context to recognize what
39  * type of operation is performed and how to perform it.
40  */
41 enum sign_op_type {
42         OP_SIGN = 0,
43         OP_VERIFY = 1
44 };
45
46 struct yaca_sign_ctx_s {
47         struct yaca_context_s ctx;
48
49         EVP_MD_CTX *mdctx;
50         enum sign_op_type op_type;
51 };
52
53 static struct yaca_sign_ctx_s *get_sign_ctx(const yaca_context_h ctx)
54 {
55         if (ctx == YACA_CONTEXT_NULL)
56                 return NULL;
57
58         switch (ctx->type) {
59         case YACA_CTX_SIGN:
60                 return (struct yaca_sign_ctx_s *)ctx;
61         default:
62                 return NULL;
63         }
64 }
65
66 static int get_sign_output_length(const yaca_context_h ctx,
67                                   size_t input_len,
68                                   size_t *output_len)
69 {
70         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
71
72         if (c == NULL)
73                 return YACA_ERROR_INVALID_PARAMETER;
74
75         assert(c->mdctx != NULL);
76
77         if (c->mdctx->pctx == NULL)
78                 return YACA_ERROR_INTERNAL;
79
80         EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx);
81         if (pkey == NULL) {
82                 ERROR_DUMP(YACA_ERROR_INTERNAL);
83                 return YACA_ERROR_INTERNAL;
84         }
85
86         int len = EVP_PKEY_size(pkey);
87         if (len <= 0) {
88                 ERROR_DUMP(YACA_ERROR_INTERNAL);
89                 return YACA_ERROR_INTERNAL;
90         }
91
92         *output_len = len;
93         return YACA_ERROR_NONE;
94 }
95
96 static void destroy_sign_context(yaca_context_h ctx)
97 {
98         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
99
100         if (c == NULL)
101                 return;
102
103         EVP_MD_CTX_destroy(c->mdctx);
104         c->mdctx = NULL;
105 }
106
107 int set_sign_param(yaca_context_h ctx,
108                    yaca_property_e param,
109                    const void *value,
110                    size_t value_len)
111 {
112         int ret;
113         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
114         yaca_padding_e padding;
115         int pad;
116         EVP_PKEY *pkey;
117
118         if (c == NULL || value == NULL)
119                 return YACA_ERROR_INVALID_PARAMETER;
120
121         assert(c->mdctx != NULL);
122
123         if (c->mdctx->pctx == NULL)
124                 return YACA_ERROR_INTERNAL;
125
126         /* this function only supports padding */
127         if (param != YACA_PROPERTY_PADDING || value_len != sizeof(yaca_padding_e))
128                 return YACA_ERROR_INVALID_PARAMETER;
129
130         padding = *(yaca_padding_e *)(value);
131
132         // TODO: investigate whether it's possible to set
133         // RSA_NO_PADDING or RSA_SSLV23_PADDING in some cases
134         switch (padding) {
135         case YACA_PADDING_X931:
136                 pad = RSA_X931_PADDING;
137                 break;
138         case YACA_PADDING_PKCS1:
139                 pad = RSA_PKCS1_PADDING;
140                 break;
141         case YACA_PADDING_PKCS1_PSS:
142                 pad = RSA_PKCS1_PSS_PADDING;
143                 break;
144         default:
145                 return YACA_ERROR_INVALID_PARAMETER;
146         }
147
148         pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx);
149         if (pkey == NULL) {
150                 ret = YACA_ERROR_INTERNAL;
151                 ERROR_DUMP(ret);
152                 return ret;
153         }
154
155         /* padding only works for RSA */
156         if (pkey->type != EVP_PKEY_RSA)
157                 return YACA_ERROR_INVALID_PARAMETER;
158
159         ret = EVP_PKEY_CTX_set_rsa_padding(c->mdctx->pctx, pad);
160         if (ret <= 0) {
161                 ret = YACA_ERROR_INTERNAL;
162                 ERROR_DUMP(ret);
163                 return ret;
164         }
165
166         return YACA_ERROR_NONE;
167 }
168
169 int get_sign_param(const yaca_context_h ctx,
170                    yaca_property_e param,
171                    void **value,
172                    size_t *value_len)
173 {
174         int ret;
175         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
176         EVP_PKEY *pkey;
177         int pad;
178         yaca_padding_e padding;
179
180         if (c == NULL || value == NULL || value_len == NULL)
181                 return YACA_ERROR_INVALID_PARAMETER;
182
183         assert(c->mdctx != NULL);
184
185         if (c->mdctx->pctx == NULL)
186                 return YACA_ERROR_INTERNAL;
187
188         /* this function only supports padding */
189         if (param != YACA_PROPERTY_PADDING)
190                 return YACA_ERROR_INVALID_PARAMETER;
191
192         pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx);
193         if (pkey == NULL) {
194                 ret = YACA_ERROR_INTERNAL;
195                 ERROR_DUMP(ret);
196                 return ret;
197         }
198
199         /* padding only works for RSA */
200         if (pkey->type != EVP_PKEY_RSA)
201                 return YACA_ERROR_INVALID_PARAMETER;
202
203         ret = EVP_PKEY_CTX_get_rsa_padding(c->mdctx->pctx, &pad);
204         if (ret <= 0) {
205                 ret = YACA_ERROR_INTERNAL;
206                 ERROR_DUMP(ret);
207                 return ret;
208         }
209
210         switch (pad) {
211         case RSA_X931_PADDING:
212                 padding = YACA_PADDING_X931;
213                 break;
214         case RSA_PKCS1_PADDING:
215                 padding = YACA_PADDING_PKCS1;
216                 break;
217         case RSA_PKCS1_PSS_PADDING:
218                 padding = YACA_PADDING_PKCS1_PSS;
219                 break;
220         default:
221                 ret = YACA_ERROR_INTERNAL;
222                 ERROR_DUMP(YACA_ERROR_INTERNAL);
223                 return ret;
224         }
225
226         ret = yaca_malloc(sizeof(yaca_padding_e), value);
227         if (ret != YACA_ERROR_NONE)
228                 return ret;
229
230         memcpy(*value, &padding, sizeof(yaca_padding_e));
231         *value_len = sizeof(yaca_padding_e);
232
233         return YACA_ERROR_NONE;
234 }
235
236 API int yaca_sign_initialize(yaca_context_h *ctx,
237                              yaca_digest_algorithm_e algo,
238                              const yaca_key_h key)
239 {
240         struct yaca_sign_ctx_s *nc = NULL;
241         const EVP_MD *md = NULL;
242         int ret;
243         const struct yaca_key_evp_s *evp_key = key_get_evp(key);
244
245         if (ctx == NULL || evp_key == NULL)
246                 return YACA_ERROR_INVALID_PARAMETER;
247
248         switch (key->type) {
249         case YACA_KEY_TYPE_RSA_PRIV:
250         case YACA_KEY_TYPE_DSA_PRIV:
251                 break;
252 //      case YACA_KEY_TYPE_EC_PRIV:
253 //              TODO NOT_IMPLEMENTED
254         default:
255                 return YACA_ERROR_INVALID_PARAMETER;
256         }
257
258         ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
259         if (ret != YACA_ERROR_NONE)
260                 return ret;
261
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;
268
269         ret = digest_get_algorithm(algo, &md);
270         if (ret != YACA_ERROR_NONE)
271                 goto exit;
272
273         nc->mdctx = EVP_MD_CTX_create();
274         if (nc->mdctx == NULL) {
275                 ret = YACA_ERROR_INTERNAL;
276                 ERROR_DUMP(ret);
277                 goto exit;
278         }
279
280         ret = EVP_DigestSignInit(nc->mdctx, NULL, md, NULL, evp_key->evp);
281         if (ret != 1) {
282                 ret = YACA_ERROR_INTERNAL;
283                 ERROR_DUMP(ret);
284                 goto exit;
285         }
286
287         *ctx = (yaca_context_h)nc;
288         nc = NULL;
289         ret = YACA_ERROR_NONE;
290
291 exit:
292         yaca_context_destroy((yaca_context_h)nc);
293
294         return ret;
295 }
296
297 API int yaca_sign_initialize_hmac(yaca_context_h *ctx,
298                                   yaca_digest_algorithm_e algo,
299                                   const yaca_key_h key)
300 {
301         struct yaca_sign_ctx_s *nc = NULL;
302         EVP_PKEY *pkey = NULL;
303         const EVP_MD *md;
304         int ret;
305         const struct yaca_key_simple_s *simple_key = key_get_simple(key);
306
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;
310
311         ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
312         if (ret != YACA_ERROR_NONE)
313                 return ret;
314
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;
319
320         pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
321                                     NULL,
322                                     (unsigned char *)simple_key->d,
323                                     simple_key->bits / 8);
324         if (pkey == NULL) {
325                 ret = YACA_ERROR_INTERNAL;
326                 ERROR_DUMP(ret);
327                 goto exit;
328         }
329
330         ret = digest_get_algorithm(algo, &md);
331         if (ret != YACA_ERROR_NONE)
332                 goto exit;
333
334         nc->mdctx = EVP_MD_CTX_create();
335         if (nc->mdctx == NULL) {
336                 ret = YACA_ERROR_INTERNAL;
337                 ERROR_DUMP(ret);
338                 goto exit;
339         }
340
341         ret = EVP_DigestSignInit(nc->mdctx, NULL, md, NULL, pkey);
342         if (ret != 1) {
343                 ret = YACA_ERROR_INTERNAL;
344                 ERROR_DUMP(ret);
345                 goto exit;
346         }
347
348         pkey = NULL;
349
350         *ctx = (yaca_context_h)nc;
351         nc = NULL;
352         ret = YACA_ERROR_NONE;
353
354 exit:
355         EVP_PKEY_free(pkey);
356         yaca_context_destroy((yaca_context_h)nc);
357
358         return ret;
359 }
360
361 API int yaca_sign_initialize_cmac(yaca_context_h *ctx,
362                                   yaca_encrypt_algorithm_e algo,
363                                   const yaca_key_h key)
364 {
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;
369         int ret;
370         const struct yaca_key_simple_s *simple_key = key_get_simple(key);
371
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;
375
376         ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
377         if (ret != YACA_ERROR_NONE)
378                 return ret;
379
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;
384
385         ret = encrypt_get_algorithm(algo, YACA_BCM_CBC, simple_key->bits, &cipher);
386         if (ret != YACA_ERROR_NONE)
387                 goto exit;
388
389         /* create and initialize low level CMAC context */
390         cmac_ctx = CMAC_CTX_new();
391         if (cmac_ctx == NULL) {
392                 ret = YACA_ERROR_INTERNAL;
393                 ERROR_DUMP(ret);
394                 goto exit;
395         }
396
397         if (CMAC_Init(cmac_ctx, simple_key->d, simple_key->bits / 8, cipher, NULL) != 1) {
398                 ret = YACA_ERROR_INTERNAL;
399                 ERROR_DUMP(ret);
400                 goto exit;
401         }
402
403         /* create key and assign CMAC context to it */
404         pkey = EVP_PKEY_new();
405         if (pkey == NULL) {
406                 ret = YACA_ERROR_INTERNAL;
407                 ERROR_DUMP(ret);
408                 goto exit;
409         }
410
411         if (EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmac_ctx) != 1) {
412                 ret = YACA_ERROR_INTERNAL;
413                 ERROR_DUMP(ret);
414                 goto exit;
415         }
416
417         cmac_ctx = NULL;
418
419         nc->mdctx = EVP_MD_CTX_create();
420         if (nc->mdctx == NULL) {
421                 ret = YACA_ERROR_INTERNAL;
422                 ERROR_DUMP(ret);
423                 goto exit;
424         }
425
426         if (EVP_DigestSignInit(nc->mdctx, NULL, NULL, NULL, pkey) != 1) {
427                 ret = YACA_ERROR_INTERNAL;
428                 ERROR_DUMP(ret);
429                 goto exit;
430         }
431
432         pkey = NULL;
433
434         *ctx = (yaca_context_h)nc;
435         nc = NULL;
436         ret = YACA_ERROR_NONE;
437
438 exit:
439         EVP_PKEY_free(pkey);
440         CMAC_CTX_free(cmac_ctx);
441         yaca_context_destroy((yaca_context_h)nc);
442
443         return ret;
444 }
445
446 API int yaca_sign_update(yaca_context_h ctx,
447                          const char *data,
448                          size_t data_len)
449 {
450         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
451         int ret;
452
453         if (c == NULL || c->op_type != OP_SIGN ||
454             data == NULL || data_len == 0)
455                 return YACA_ERROR_INVALID_PARAMETER;
456
457         ret = EVP_DigestSignUpdate(c->mdctx, data, data_len);
458         if (ret != 1) {
459                 ret = YACA_ERROR_INTERNAL;
460                 ERROR_DUMP(ret);
461                 return ret;
462         }
463
464         return YACA_ERROR_NONE;
465 }
466
467 API int yaca_sign_finalize(yaca_context_h ctx,
468                            char *signature,
469                            size_t *signature_len)
470 {
471         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
472         int ret;
473
474         if (c == NULL ||  c->op_type != OP_SIGN ||
475             signature == NULL || signature_len == NULL || *signature_len == 0)
476                 return YACA_ERROR_INVALID_PARAMETER;
477
478         ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)signature, signature_len);
479         if (ret != 1) {
480                 ret = YACA_ERROR_INTERNAL;
481                 ERROR_DUMP(ret);
482                 return ret;
483         }
484
485         return YACA_ERROR_NONE;
486 }
487
488 API int yaca_verify_initialize(yaca_context_h *ctx,
489                                yaca_digest_algorithm_e algo,
490                                const yaca_key_h key)
491 {
492         struct yaca_sign_ctx_s *nc = NULL;
493         const EVP_MD *md = NULL;
494         int ret;
495         const struct yaca_key_evp_s *evp_key = key_get_evp(key);
496
497         if (ctx == NULL || evp_key == NULL)
498                 return YACA_ERROR_INVALID_PARAMETER;
499
500         switch (key->type) {
501         case YACA_KEY_TYPE_RSA_PUB:
502         case YACA_KEY_TYPE_DSA_PUB:
503                 break;
504 //      case YACA_KEY_TYPE_EC_PUB:
505 //              TODO NOT_IMPLEMENTED
506         default:
507                 return YACA_ERROR_INVALID_PARAMETER;
508         }
509
510         ret = yaca_zalloc(sizeof(struct yaca_sign_ctx_s), (void**)&nc);
511         if (ret != YACA_ERROR_NONE)
512                 return ret;
513
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;
520
521         ret = digest_get_algorithm(algo, &md);
522         if (ret != YACA_ERROR_NONE)
523                 goto exit;
524
525         nc->mdctx = EVP_MD_CTX_create();
526         if (nc->mdctx == NULL) {
527                 ret = YACA_ERROR_INTERNAL;
528                 ERROR_DUMP(ret);
529                 goto exit;
530         }
531
532         ret = EVP_DigestVerifyInit(nc->mdctx, NULL, md, NULL, evp_key->evp);
533         if (ret != 1) {
534                 ret = YACA_ERROR_INTERNAL;
535                 ERROR_DUMP(ret);
536                 goto exit;
537         }
538
539         *ctx = (yaca_context_h)nc;
540         nc = NULL;
541         ret = YACA_ERROR_NONE;
542
543 exit:
544         yaca_context_destroy((yaca_context_h)nc);
545
546         return ret;
547 }
548
549 API int yaca_verify_update(yaca_context_h ctx,
550                            const char *data,
551                            size_t data_len)
552 {
553         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
554         int ret;
555
556         if (c == NULL || data == NULL || data_len == 0 || c->op_type != OP_VERIFY)
557                 return YACA_ERROR_INVALID_PARAMETER;
558
559         ret = EVP_DigestVerifyUpdate(c->mdctx, data, data_len);
560         if (ret != 1) {
561                 ret = YACA_ERROR_INTERNAL;
562                 ERROR_DUMP(ret);
563                 return ret;
564         }
565
566         return YACA_ERROR_NONE;
567 }
568
569 API int yaca_verify_finalize(yaca_context_h ctx,
570                              const char *signature,
571                              size_t signature_len)
572 {
573         struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
574         int ret;
575
576         if (c == NULL || signature == NULL || signature_len == 0 || c->op_type != OP_VERIFY)
577                 return YACA_ERROR_INVALID_PARAMETER;
578
579         ret = EVP_DigestVerifyFinal(c->mdctx,
580                                     (unsigned char *)signature,
581                                     signature_len);
582
583         if (ret == 1)
584                 return YACA_ERROR_NONE;
585
586         if (ret == YACA_ERROR_NONE) {
587                 ERROR_CLEAR();
588                 return YACA_ERROR_DATA_MISMATCH;
589         }
590
591         ret = YACA_ERROR_INTERNAL;
592         ERROR_DUMP(ret);
593         return ret;
594 }