Handle invalid params properly for simple sign/verify/cmac/hmac
[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 *lcipher = NULL;
98         size_t out_len, lcipher_len, written;
99
100         if (plaintext == NULL || plaintext_len == 0 ||
101             ciphertext == NULL || ciphertext_len == NULL ||
102             sym_key == YACA_KEY_NULL)
103                 return YACA_ERROR_INVALID_PARAMETER;
104
105         ret = yaca_encrypt_initialize(&ctx, algo, bcm, sym_key, iv);
106         if (ret != YACA_ERROR_NONE)
107                 return ret;
108
109         ret = yaca_context_get_output_length(ctx, plaintext_len, &out_len);
110         if (ret != YACA_ERROR_NONE)
111                 goto exit;
112
113         ret = yaca_context_get_output_length(ctx, 0, &lcipher_len);
114         if (ret != YACA_ERROR_NONE)
115                 goto exit;
116
117         if (out_len > SIZE_MAX - lcipher_len) {
118                 ret = YACA_ERROR_INVALID_PARAMETER;
119                 goto exit;
120         }
121
122         lcipher_len += out_len;
123
124         assert(lcipher_len > 0);
125
126         ret = yaca_malloc(lcipher_len, (void**)&lcipher);
127         if (ret != YACA_ERROR_NONE)
128                 goto exit;
129
130         out_len = lcipher_len;
131         ret = yaca_encrypt_update(ctx, plaintext, plaintext_len, lcipher, &out_len);
132         if (ret != YACA_ERROR_NONE)
133                 goto exit;
134
135         assert(out_len <= lcipher_len);
136
137         written = out_len;
138         out_len = lcipher_len - written;
139         ret = yaca_encrypt_finalize(ctx, lcipher + written, &out_len);
140         if (ret != YACA_ERROR_NONE)
141                 goto exit;
142
143         written += out_len;
144         assert(written <= lcipher_len && written > 0);
145
146         ret = yaca_realloc(written, (void**)&lcipher);
147         if (ret != YACA_ERROR_NONE)
148                 goto exit;
149
150         *ciphertext = lcipher;
151         *ciphertext_len = written;
152         lcipher = NULL;
153         ret = YACA_ERROR_NONE;
154
155 exit:
156         yaca_free(lcipher);
157         yaca_context_destroy(ctx);
158
159         return ret;
160 }
161
162 API int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo,
163                             yaca_block_cipher_mode_e bcm,
164                             const yaca_key_h sym_key,
165                             const yaca_key_h iv,
166                             const char *ciphertext,
167                             size_t ciphertext_len,
168                             char **plaintext,
169                             size_t *plaintext_len)
170 {
171         yaca_context_h ctx;
172         int ret;
173         char *lplain = NULL;
174         size_t out_len, lplain_len, written;
175
176         if (ciphertext == NULL || ciphertext_len == 0 ||
177             plaintext == NULL || plaintext_len == NULL ||
178             sym_key == YACA_KEY_NULL)
179                 return YACA_ERROR_INVALID_PARAMETER;
180
181         ret = yaca_decrypt_initialize(&ctx, algo, bcm, sym_key, iv);
182         if (ret != YACA_ERROR_NONE)
183                 return ret;
184
185         ret = yaca_context_get_output_length(ctx, ciphertext_len, &out_len);
186         if (ret != YACA_ERROR_NONE)
187                 goto exit;
188
189         ret = yaca_context_get_output_length(ctx, 0, &lplain_len);
190         if (ret != YACA_ERROR_NONE)
191                 goto exit;
192
193         if (out_len > SIZE_MAX - lplain_len) {
194                 ret = YACA_ERROR_INVALID_PARAMETER;
195                 goto exit;
196         }
197
198         lplain_len += out_len;
199         assert(lplain_len > 0);
200
201         ret = yaca_malloc(lplain_len, (void**)&lplain);
202         if (ret != YACA_ERROR_NONE)
203                 goto exit;
204
205         out_len = lplain_len;
206         ret = yaca_decrypt_update(ctx, ciphertext, ciphertext_len, lplain, &out_len);
207         if (ret != YACA_ERROR_NONE)
208                 goto exit;
209
210         assert(out_len <= lplain_len);
211
212         written = out_len;
213         out_len = lplain_len - written;
214         ret = yaca_decrypt_finalize(ctx, lplain + written, &out_len);
215         if (ret != YACA_ERROR_NONE)
216                 goto exit;
217
218         written += out_len;
219         assert(written <= lplain_len && written > 0);
220
221         ret = yaca_realloc(written, (void**)&lplain);
222         if (ret != YACA_ERROR_NONE)
223                 goto exit;
224
225         *plaintext = lplain;
226         *plaintext_len = written;
227         lplain = NULL;
228         ret = YACA_ERROR_NONE;
229
230 exit:
231         yaca_free(lplain);
232         yaca_context_destroy(ctx);
233
234         return ret;
235 }
236
237 static int sign(const yaca_context_h ctx, const char *data, size_t data_len,
238                 char **signature, size_t *signature_len)
239 {
240         int ret;
241
242         assert(signature != NULL);
243         assert(signature_len != NULL);
244
245         if (data_len > 0) {
246                 ret = yaca_sign_update(ctx, data, data_len);
247                 if (ret != YACA_ERROR_NONE)
248                         return ret;
249         }
250
251         ret = yaca_context_get_output_length(ctx, 0, signature_len);
252         if (ret != YACA_ERROR_NONE)
253                 return ret;
254
255         assert(*signature_len > 0);
256
257         ret = yaca_malloc(*signature_len, (void**)signature);
258         if (ret != YACA_ERROR_NONE)
259                 return ret;
260
261         ret = yaca_sign_finalize(ctx, *signature, signature_len);
262         if (ret != YACA_ERROR_NONE) {
263                 yaca_free(*signature);
264                 *signature = NULL;
265         }
266
267         return ret;
268 }
269
270 API int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo,
271                                         const yaca_key_h key,
272                                         const char *data,
273                                         size_t data_len,
274                                         char **signature,
275                                         size_t *signature_len)
276 {
277         int ret;
278         yaca_context_h ctx = YACA_CONTEXT_NULL;
279
280         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
281             signature == NULL || signature_len == NULL)
282                 return YACA_ERROR_INVALID_PARAMETER;
283
284         ret = yaca_sign_initialize(&ctx, algo, key);
285         if (ret != YACA_ERROR_NONE)
286                 return ret;
287
288         ret = sign(ctx, data, data_len, signature, signature_len);
289
290         yaca_context_destroy(ctx);
291
292         return ret;
293 }
294
295 API int yaca_simple_verify_signature(yaca_digest_algorithm_e algo,
296                                      const yaca_key_h key,
297                                      const char *data,
298                                      size_t data_len,
299                                      const char *signature,
300                                      size_t signature_len)
301 {
302         int ret;
303         yaca_context_h ctx = YACA_CONTEXT_NULL;
304
305         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
306             signature == NULL || signature_len == 0)
307                 return YACA_ERROR_INVALID_PARAMETER;
308
309         ret = yaca_verify_initialize(&ctx, algo, key);
310         if (ret != YACA_ERROR_NONE)
311                 return ret;
312
313         if (data_len > 0) {
314                 ret = yaca_verify_update(ctx, data, data_len);
315                 if (ret != YACA_ERROR_NONE)
316                         goto exit;
317         }
318
319         ret = yaca_verify_finalize(ctx, signature, signature_len);
320
321 exit:
322         yaca_context_destroy(ctx);
323
324         return ret;
325 }
326
327 API int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo,
328                                    const yaca_key_h key,
329                                    const char *data,
330                                    size_t data_len,
331                                    char **mac,
332                                    size_t *mac_len)
333 {
334         int ret;
335         yaca_context_h ctx = YACA_CONTEXT_NULL;
336
337         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
338             mac == NULL || mac_len == NULL)
339                 return YACA_ERROR_INVALID_PARAMETER;
340
341         ret = yaca_sign_initialize_hmac(&ctx, algo, key);
342         if (ret != YACA_ERROR_NONE)
343                 return ret;
344
345         ret = sign(ctx, data, data_len, mac, mac_len);
346
347         yaca_context_destroy(ctx);
348
349         return ret;
350 }
351
352 API int yaca_simple_calculate_cmac(yaca_encrypt_algorithm_e algo,
353                                    const yaca_key_h key,
354                                    const char *data,
355                                    size_t data_len,
356                                    char **mac,
357                                    size_t *mac_len)
358 {
359         int ret;
360         yaca_context_h ctx = YACA_CONTEXT_NULL;
361
362         if ((data == NULL && data_len > 0) || (data != NULL && data_len == 0) ||
363             mac == NULL || mac_len == NULL)
364                 return YACA_ERROR_INVALID_PARAMETER;
365
366         ret = yaca_sign_initialize_cmac(&ctx, algo, key);
367         if (ret != YACA_ERROR_NONE)
368                 return ret;
369
370         ret = sign(ctx, data, data_len, mac, mac_len);
371
372         yaca_context_destroy(ctx);
373
374         return ret;
375 }