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