Replace spaces with tabs
[platform/core/security/yaca.git] / src / simple.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 simple.c
21  * @brief
22  */
23
24 #include <assert.h>
25 #include <stdint.h>
26
27 #include <yaca_crypto.h>
28 #include <yaca_error.h>
29 #include <yaca_encrypt.h>
30 #include <yaca_digest.h>
31 #include <yaca_key.h>
32 #include <yaca_sign.h>
33
34 #include "internal.h"
35
36 API int yaca_simple_calculate_digest(yaca_digest_algorithm_e algo,
37                                                                          const char *data,
38                                                                          size_t data_len,
39                                                                          char **digest,
40                                                                          size_t *digest_len)
41 {
42         yaca_context_h ctx;
43         int ret;
44         char *ldigest = NULL;
45         size_t ldigest_len;
46
47         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
48                 digest == NULL || digest_len == NULL)
49                 return YACA_ERROR_INVALID_PARAMETER;
50
51         ret = yaca_digest_initialize(&ctx, algo);
52         if (ret != YACA_ERROR_NONE)
53                 return ret;
54
55         if (data_len > 0) {
56                 ret = yaca_digest_update(ctx, data, data_len);
57                 if (ret != YACA_ERROR_NONE)
58                         goto exit;
59         }
60
61         ret = yaca_context_get_output_length(ctx, 0, &ldigest_len);
62         if (ret != YACA_ERROR_NONE)
63                 goto exit;
64
65         assert(ldigest_len > 0);
66
67         ret = yaca_malloc(ldigest_len, (void**)&ldigest);
68         if (ret != YACA_ERROR_NONE)
69                 goto exit;
70
71         ret = yaca_digest_finalize(ctx, ldigest, &ldigest_len);
72         if (ret != YACA_ERROR_NONE)
73                 goto exit;
74
75         *digest_len = ldigest_len;
76         *digest = ldigest;
77         ldigest = NULL;
78
79 exit:
80         yaca_free(ldigest);
81         yaca_context_destroy(ctx);
82
83         return ret;
84 }
85
86 API int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo,
87                                                         yaca_block_cipher_mode_e bcm,
88                                                         const yaca_key_h sym_key,
89                                                         const yaca_key_h iv,
90                                                         const char *plaintext,
91                                                         size_t plaintext_len,
92                                                         char **ciphertext,
93                                                         size_t *ciphertext_len)
94 {
95         yaca_context_h ctx;
96         int ret;
97         char *lciphertext = NULL;
98         size_t out_len = 0;
99         size_t lciphertext_len = 0;
100         size_t written = 0;
101
102         if ((plaintext == NULL && plaintext_len > 0) || (plaintext != NULL && plaintext_len == 0) ||
103                 ciphertext == NULL || ciphertext_len == NULL ||
104                 sym_key == YACA_KEY_NULL ||
105                 bcm == YACA_BCM_CCM || bcm == YACA_BCM_GCM)
106                 return YACA_ERROR_INVALID_PARAMETER;
107
108         ret = yaca_encrypt_initialize(&ctx, algo, bcm, sym_key, iv);
109         if (ret != YACA_ERROR_NONE)
110                 return ret;
111
112         if (plaintext_len > 0) {
113                 ret = yaca_context_get_output_length(ctx, plaintext_len, &out_len);
114                 if (ret != YACA_ERROR_NONE)
115                         goto exit;
116         }
117
118         ret = yaca_context_get_output_length(ctx, 0, &lciphertext_len);
119         if (ret != YACA_ERROR_NONE)
120                 goto exit;
121
122         if (out_len > SIZE_MAX - lciphertext_len) {
123                 ret = YACA_ERROR_INVALID_PARAMETER;
124                 goto exit;
125         }
126
127         lciphertext_len += out_len;
128         assert(lciphertext_len > 0);
129
130         ret = yaca_malloc(lciphertext_len, (void**)&lciphertext);
131         if (ret != YACA_ERROR_NONE)
132                 goto exit;
133
134         if (plaintext_len > 0) {
135                 ret = yaca_encrypt_update(ctx, plaintext, plaintext_len, lciphertext, &out_len);
136                 if (ret != YACA_ERROR_NONE)
137                         goto exit;
138         }
139
140         assert(out_len <= lciphertext_len);
141         written = out_len;
142
143         ret = yaca_encrypt_finalize(ctx, lciphertext + written, &out_len);
144         if (ret != YACA_ERROR_NONE)
145                 goto exit;
146
147         written += out_len;
148         assert(written <= lciphertext_len);
149
150         if (((bcm == YACA_BCM_CBC || bcm == YACA_BCM_ECB) && written == 0) ||
151                 (bcm != YACA_BCM_CBC && bcm != YACA_BCM_ECB && plaintext_len == 0 && written > 0)) {
152                 ret = YACA_ERROR_INTERNAL;
153                 goto exit;
154         }
155
156         if (written > 0) {
157                 ret = yaca_realloc(written, (void**)&lciphertext);
158                 if (ret != YACA_ERROR_NONE)
159                         goto exit;
160         } else {
161                 yaca_free(lciphertext);
162                 lciphertext = NULL;
163         }
164
165         *ciphertext = lciphertext;
166         *ciphertext_len = written;
167         lciphertext = NULL;
168         ret = YACA_ERROR_NONE;
169
170 exit:
171         yaca_free(lciphertext);
172         yaca_context_destroy(ctx);
173
174         return ret;
175 }
176
177 API int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo,
178                                                         yaca_block_cipher_mode_e bcm,
179                                                         const yaca_key_h sym_key,
180                                                         const yaca_key_h iv,
181                                                         const char *ciphertext,
182                                                         size_t ciphertext_len,
183                                                         char **plaintext,
184                                                         size_t *plaintext_len)
185 {
186         yaca_context_h ctx;
187         int ret;
188         char *lplaintext = NULL;
189         size_t out_len = 0;
190         size_t lplaintext_len = 0;
191         size_t written = 0;
192
193         if ((ciphertext == NULL && ciphertext_len > 0) || (ciphertext != NULL && ciphertext_len == 0) ||
194                 ((bcm == YACA_BCM_ECB || bcm == YACA_BCM_CBC) && ciphertext == NULL && ciphertext_len == 0) ||
195                 plaintext == NULL || plaintext_len == NULL ||
196                 sym_key == YACA_KEY_NULL ||
197                 bcm == YACA_BCM_CCM || bcm == YACA_BCM_GCM)
198                 return YACA_ERROR_INVALID_PARAMETER;
199
200         ret = yaca_decrypt_initialize(&ctx, algo, bcm, sym_key, iv);
201         if (ret != YACA_ERROR_NONE)
202                 return ret;
203
204         if (ciphertext_len > 0) {
205                 ret = yaca_context_get_output_length(ctx, ciphertext_len, &out_len);
206                 if (ret != YACA_ERROR_NONE)
207                         goto exit;
208         }
209
210         ret = yaca_context_get_output_length(ctx, 0, &lplaintext_len);
211         if (ret != YACA_ERROR_NONE)
212                 goto exit;
213
214         if (out_len > SIZE_MAX - lplaintext_len) {
215                 ret = YACA_ERROR_INVALID_PARAMETER;
216                 goto exit;
217         }
218
219         lplaintext_len += out_len;
220         assert(lplaintext_len > 0);
221
222         ret = yaca_malloc(lplaintext_len, (void**)&lplaintext);
223         if (ret != YACA_ERROR_NONE)
224                 goto exit;
225
226         if (ciphertext_len > 0) {
227                 ret = yaca_decrypt_update(ctx, ciphertext, ciphertext_len, lplaintext, &out_len);
228                 if (ret != YACA_ERROR_NONE)
229                         goto exit;
230         }
231
232         assert(out_len <= lplaintext_len);
233         written = out_len;
234
235         ret = yaca_decrypt_finalize(ctx, lplaintext + written, &out_len);
236         if (ret != YACA_ERROR_NONE)
237                 goto exit;
238
239         written += out_len;
240         assert(written <= lplaintext_len);
241
242         if (bcm != YACA_BCM_CBC && bcm != YACA_BCM_ECB && ciphertext_len == 0 && written > 0) {
243                 ret = YACA_ERROR_INTERNAL;
244                 goto exit;
245         }
246
247         if (written > 0) {
248                 ret = yaca_realloc(written, (void**)&lplaintext);
249                 if (ret != YACA_ERROR_NONE)
250                         goto exit;
251         } else {
252                 yaca_free(lplaintext);
253                 lplaintext = NULL;
254         }
255
256         *plaintext = lplaintext;
257         *plaintext_len = written;
258         lplaintext = NULL;
259         ret = YACA_ERROR_NONE;
260
261 exit:
262         yaca_free(lplaintext);
263         yaca_context_destroy(ctx);
264
265         return ret;
266 }
267
268 static int sign(const yaca_context_h ctx, const char *data, size_t data_len,
269                                 char **signature, size_t *signature_len)
270 {
271         int ret;
272
273         assert(signature != NULL);
274         assert(signature_len != NULL);
275
276         if (data_len > 0) {
277                 ret = yaca_sign_update(ctx, data, data_len);
278                 if (ret != YACA_ERROR_NONE)
279                         return ret;
280         }
281
282         ret = yaca_context_get_output_length(ctx, 0, signature_len);
283         if (ret != YACA_ERROR_NONE)
284                 return ret;
285
286         assert(*signature_len > 0);
287
288         ret = yaca_malloc(*signature_len, (void**)signature);
289         if (ret != YACA_ERROR_NONE)
290                 return ret;
291
292         ret = yaca_sign_finalize(ctx, *signature, signature_len);
293         if (ret != YACA_ERROR_NONE) {
294                 yaca_free(*signature);
295                 *signature = NULL;
296         }
297
298         return ret;
299 }
300
301 API int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo,
302                                                                                 const yaca_key_h prv_key,
303                                                                                 const char *data,
304                                                                                 size_t data_len,
305                                                                                 char **signature,
306                                                                                 size_t *signature_len)
307 {
308         int ret;
309         yaca_context_h ctx = YACA_CONTEXT_NULL;
310
311         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
312                 signature == NULL || signature_len == NULL)
313                 return YACA_ERROR_INVALID_PARAMETER;
314
315         ret = yaca_sign_initialize(&ctx, algo, prv_key);
316         if (ret != YACA_ERROR_NONE)
317                 return ret;
318
319         ret = sign(ctx, data, data_len, signature, signature_len);
320
321         yaca_context_destroy(ctx);
322
323         return ret;
324 }
325
326 API int yaca_simple_verify_signature(yaca_digest_algorithm_e algo,
327                                                                          const yaca_key_h pub_key,
328                                                                          const char *data,
329                                                                          size_t data_len,
330                                                                          const char *signature,
331                                                                          size_t signature_len)
332 {
333         int ret;
334         yaca_context_h ctx = YACA_CONTEXT_NULL;
335
336         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
337                 signature == NULL || signature_len == 0)
338                 return YACA_ERROR_INVALID_PARAMETER;
339
340         ret = yaca_verify_initialize(&ctx, algo, pub_key);
341         if (ret != YACA_ERROR_NONE)
342                 return ret;
343
344         if (data_len > 0) {
345                 ret = yaca_verify_update(ctx, data, data_len);
346                 if (ret != YACA_ERROR_NONE)
347                         goto exit;
348         }
349
350         ret = yaca_verify_finalize(ctx, signature, signature_len);
351
352 exit:
353         yaca_context_destroy(ctx);
354
355         return ret;
356 }
357
358 API int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo,
359                                                                    const yaca_key_h sym_key,
360                                                                    const char *data,
361                                                                    size_t data_len,
362                                                                    char **mac,
363                                                                    size_t *mac_len)
364 {
365         int ret;
366         yaca_context_h ctx = YACA_CONTEXT_NULL;
367
368         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
369                 mac == NULL || mac_len == NULL)
370                 return YACA_ERROR_INVALID_PARAMETER;
371
372         ret = yaca_sign_initialize_hmac(&ctx, algo, sym_key);
373         if (ret != YACA_ERROR_NONE)
374                 return ret;
375
376         ret = sign(ctx, data, data_len, mac, mac_len);
377
378         yaca_context_destroy(ctx);
379
380         return ret;
381 }
382
383 API int yaca_simple_calculate_cmac(yaca_encrypt_algorithm_e algo,
384                                                                    const yaca_key_h sym_key,
385                                                                    const char *data,
386                                                                    size_t data_len,
387                                                                    char **mac,
388                                                                    size_t *mac_len)
389 {
390         int ret;
391         yaca_context_h ctx = YACA_CONTEXT_NULL;
392
393         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
394                 mac == NULL || mac_len == NULL)
395                 return YACA_ERROR_INVALID_PARAMETER;
396
397         ret = yaca_sign_initialize_cmac(&ctx, algo, sym_key);
398         if (ret != YACA_ERROR_NONE)
399                 return ret;
400
401         ret = sign(ctx, data, data_len, mac, mac_len);
402
403         yaca_context_destroy(ctx);
404
405         return ret;
406 }