Replace spaces with tabs
[platform/core/security/yaca.git] / src / seal.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 seal.c
21  * @brief
22  */
23
24 #include <assert.h>
25 #include <stdint.h>
26 #include <string.h>
27
28 #include <openssl/evp.h>
29
30 #include <yaca_crypto.h>
31 #include <yaca_seal.h>
32 #include <yaca_error.h>
33 #include <yaca_key.h>
34
35 #include "internal.h"
36
37 static int seal_generate_sym_key(yaca_encrypt_algorithm_e algo,
38                                                                  size_t sym_key_bit_len,
39                                                                  yaca_key_h *sym_key)
40 {
41         assert(sym_key != NULL);
42
43         if (algo == YACA_ENCRYPT_3DES_3TDEA ||
44                 algo == YACA_ENCRYPT_UNSAFE_3DES_2TDEA ||
45                 algo == YACA_ENCRYPT_UNSAFE_DES)
46                 return yaca_key_generate(YACA_KEY_TYPE_DES, sym_key_bit_len, sym_key);
47         else
48                 return yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, sym_key_bit_len, sym_key);
49 }
50
51 static int seal_generate_iv(const EVP_CIPHER *cipher, yaca_key_h *iv)
52 {
53         int ret;
54         int iv_len;
55
56         assert(iv != NULL);
57         assert(cipher != NULL);
58
59         ret = EVP_CIPHER_iv_length(cipher);
60         if (ret < 0) {
61                 ret = YACA_ERROR_INTERNAL;
62                 ERROR_DUMP(ret);
63                 return ret;
64         }
65
66         iv_len = ret;
67         if (iv_len == 0) {
68                 *iv = YACA_KEY_NULL;
69                 return YACA_ERROR_NONE;
70         }
71
72         return yaca_key_generate(YACA_KEY_TYPE_IV, iv_len * 8, iv);
73 }
74
75 /* used for asymmetric encryption and decryption */
76 static int seal_encrypt_decrypt_key(const yaca_key_h asym_key,
77                                                                         const yaca_key_h in_key,
78                                                                         yaca_key_h *out_key)
79 {
80         int ret;
81         const struct yaca_key_evp_s *lasym_key;
82         const struct yaca_key_simple_s *lin_key;
83         struct yaca_key_simple_s *lout_key;
84         size_t output_len;
85
86         lin_key = key_get_simple(in_key);
87         if (lin_key == NULL)
88                 return YACA_ERROR_INVALID_PARAMETER;
89
90         if (asym_key->type != YACA_KEY_TYPE_RSA_PRIV && asym_key->type != YACA_KEY_TYPE_RSA_PUB)
91                 return YACA_ERROR_INVALID_PARAMETER;
92
93         lasym_key = key_get_evp(asym_key);
94         if (lasym_key == NULL)
95                 return YACA_ERROR_INVALID_PARAMETER;
96
97         ret = EVP_PKEY_size(lasym_key->evp);
98         if (ret <= 0) {
99                 ret = YACA_ERROR_INTERNAL;
100                 ERROR_DUMP(ret);
101                 return ret;
102         }
103
104         output_len = ret;
105
106         ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + output_len, (void**)&lout_key);
107         if (ret != YACA_ERROR_NONE)
108                 return ret;
109
110         lout_key->key.type = YACA_KEY_TYPE_SYMMETRIC;
111         lout_key->bit_len = output_len * 8;
112
113         if (asym_key->type == YACA_KEY_TYPE_RSA_PRIV)
114                 ret = EVP_PKEY_decrypt_old((unsigned char*)lout_key->d,
115                                                                    (unsigned char*)lin_key->d,
116                                                                    lin_key->bit_len / 8,
117                                                                    lasym_key->evp);
118         else
119                 ret = EVP_PKEY_encrypt_old((unsigned char*)lout_key->d,
120                                                                    (unsigned char*)lin_key->d,
121                                                                    lin_key->bit_len / 8,
122                                                                    lasym_key->evp);
123
124         if (ret <= 0) {
125                 ret = ERROR_HANDLE();
126                 goto exit;
127         }
128
129         output_len = ret;
130
131         /* Update the key length just in case */
132         lout_key->bit_len = output_len * 8;
133
134         *out_key = (yaca_key_h)lout_key;
135         lout_key = NULL;
136
137         ret = YACA_ERROR_NONE;
138
139 exit:
140         yaca_key_destroy((yaca_key_h)lout_key);
141
142         return ret;
143 }
144
145 API int yaca_seal_initialize(yaca_context_h *ctx,
146                                                          const yaca_key_h pub_key,
147                                                          yaca_encrypt_algorithm_e algo,
148                                                          yaca_block_cipher_mode_e bcm,
149                                                          size_t sym_key_bit_len,
150                                                          yaca_key_h *sym_key,
151                                                          yaca_key_h *iv)
152 {
153         int ret;
154         const EVP_CIPHER *cipher;
155         yaca_key_h lsym_key = YACA_KEY_NULL;
156         yaca_key_h liv = YACA_KEY_NULL;
157         yaca_key_h lenc_sym_key = YACA_KEY_NULL;
158
159         if (pub_key == YACA_KEY_NULL || pub_key->type != YACA_KEY_TYPE_RSA_PUB ||
160                 sym_key == NULL || bcm == YACA_BCM_WRAP || sym_key_bit_len % 8 != 0)
161                 return YACA_ERROR_INVALID_PARAMETER;
162
163         ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher);
164         if (ret != YACA_ERROR_NONE)
165                 goto exit;
166
167         ret = seal_generate_sym_key(algo, sym_key_bit_len, &lsym_key);
168         if (ret != YACA_ERROR_NONE)
169                 goto exit;
170
171         ret = seal_generate_iv(cipher, &liv);
172         if (ret != YACA_ERROR_NONE)
173                 goto exit;
174
175         if (liv != YACA_KEY_NULL && iv == NULL) {
176                 ret = YACA_ERROR_INVALID_PARAMETER;
177                 goto exit;
178         }
179
180         /* using public key will make it encrypt the symmetric key */
181         ret = seal_encrypt_decrypt_key(pub_key, lsym_key, &lenc_sym_key);
182         if (ret != YACA_ERROR_NONE)
183                 goto exit;
184
185         ret = encrypt_initialize(ctx, cipher, lsym_key, liv, OP_SEAL);
186         if (ret != YACA_ERROR_NONE)
187                 goto exit;
188
189         *sym_key = lenc_sym_key;
190         lenc_sym_key = YACA_KEY_NULL;
191         *iv = liv;
192         liv = YACA_KEY_NULL;
193         ret = YACA_ERROR_NONE;
194
195 exit:
196         yaca_key_destroy(liv);
197         yaca_key_destroy(lsym_key);
198         yaca_key_destroy(lenc_sym_key);
199
200         return ret;
201 }
202
203 API int yaca_seal_update(yaca_context_h ctx,
204                                                  const char *plaintext,
205                                                  size_t plaintext_len,
206                                                  char *ciphertext,
207                                                  size_t *ciphertext_len)
208 {
209         return encrypt_update(ctx, (const unsigned char*)plaintext,  plaintext_len,
210                                                   (unsigned char*)ciphertext, ciphertext_len, OP_SEAL);
211 }
212
213 API int yaca_seal_finalize(yaca_context_h ctx,
214                                                    char *ciphertext,
215                                                    size_t *ciphertext_len)
216 {
217         return encrypt_finalize(ctx, (unsigned char*)ciphertext, ciphertext_len, OP_SEAL);
218 }
219
220 API int yaca_open_initialize(yaca_context_h *ctx,
221                                                          const yaca_key_h prv_key,
222                                                          yaca_encrypt_algorithm_e algo,
223                                                          yaca_block_cipher_mode_e bcm,
224                                                          size_t sym_key_bit_len,
225                                                          const yaca_key_h sym_key,
226                                                          const yaca_key_h iv)
227 {
228         int ret;
229         const EVP_CIPHER *cipher;
230         yaca_key_h lsym_key = YACA_KEY_NULL;
231
232         if (prv_key == YACA_KEY_NULL || prv_key->type != YACA_KEY_TYPE_RSA_PRIV ||
233                 sym_key == YACA_KEY_NULL || bcm == YACA_BCM_WRAP || sym_key_bit_len % 8 != 0)
234                 return YACA_ERROR_INVALID_PARAMETER;
235
236         ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher);
237         if (ret != YACA_ERROR_NONE)
238                 goto exit;
239
240         /* using private key will make it decrypt the symmetric key */
241         ret = seal_encrypt_decrypt_key(prv_key, sym_key, &lsym_key);
242         if (ret != YACA_ERROR_NONE)
243                 goto exit;
244
245         ret = encrypt_initialize(ctx, cipher, lsym_key, iv, OP_OPEN);
246         if (ret != YACA_ERROR_NONE)
247                 goto exit;
248
249         ret = YACA_ERROR_NONE;
250
251 exit:
252         yaca_key_destroy(lsym_key);
253         return ret;
254 }
255
256 API int yaca_open_update(yaca_context_h ctx,
257                                                  const char *ciphertext,
258                                                  size_t ciphertext_len,
259                                                  char *plaintext,
260                                                  size_t *plaintext_len)
261 {
262         return encrypt_update(ctx, (const unsigned char*)ciphertext, ciphertext_len,
263                                                   (unsigned char*)plaintext, plaintext_len, OP_OPEN);
264 }
265
266 API int yaca_open_finalize(yaca_context_h ctx,
267                                                    char *plaintext,
268                                                    size_t *plaintext_len)
269 {
270         return encrypt_finalize(ctx, (unsigned char*)plaintext, plaintext_len, OP_OPEN);
271 }