quic: quicly v0.1.2 update
[vpp.git] / src / plugins / tlspicotls / pico_vpp_crypto.c
1 /*
2  * Copyright (c) 2021 Intel and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vnet/crypto/crypto.h>
17 #include <vnet/tls/tls.h>
18 #include <picotls/openssl.h>
19 #include <picotls.h>
20
21 #include <tlspicotls/pico_vpp_crypto.h>
22 #include <tlspicotls/tls_picotls.h>
23
24 typedef void (*ptls_vpp_do_transform_fn) (ptls_cipher_context_t *, void *,
25                                           const void *, size_t);
26
27 vnet_crypto_main_t *cm = &crypto_main;
28 extern picotls_main_t picotls_main;
29
30 struct cipher_context_t
31 {
32   ptls_cipher_context_t super;
33   vnet_crypto_op_t op;
34   u32 key_index;
35 };
36
37 struct vpp_aead_context_t
38 {
39   ptls_aead_context_t super;
40   vnet_crypto_op_t op;
41   vnet_crypto_op_chunk_t chunks[2];
42   vnet_crypto_alg_t alg;
43   u32 key_index;
44   u32 chunk_index;
45   uint8_t iv[PTLS_MAX_IV_SIZE];
46   uint8_t static_iv[PTLS_MAX_IV_SIZE];
47 };
48
49 static void
50 ptls_vpp_crypto_cipher_do_init (ptls_cipher_context_t * _ctx, const void *iv)
51 {
52   struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx;
53
54   vnet_crypto_op_id_t id;
55   if (!strcmp (ctx->super.algo->name, "AES128-CTR"))
56     {
57       id = VNET_CRYPTO_OP_AES_128_CTR_ENC;
58     }
59   else if (!strcmp (ctx->super.algo->name, "AES256-CTR"))
60     {
61       id = VNET_CRYPTO_OP_AES_256_CTR_ENC;
62     }
63   else
64     {
65       TLS_DBG (1, "%s, Invalid crypto cipher : ", __FUNCTION__,
66                _ctx->algo->name);
67       assert (0);
68     }
69
70   vnet_crypto_op_init (&ctx->op, id);
71   ctx->op.iv = (u8 *) iv;
72   ctx->op.key_index = ctx->key_index;
73 }
74
75 static void
76 ptls_vpp_crypto_cipher_dispose (ptls_cipher_context_t * _ctx)
77 {
78   /* Do nothing */
79 }
80
81 static void
82 ptls_vpp_crypto_cipher_encrypt (ptls_cipher_context_t * _ctx, void *output,
83                                 const void *input, size_t _len)
84 {
85   vlib_main_t *vm = vlib_get_main ();
86   struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx;
87
88   ctx->op.src = (u8 *) input;
89   ctx->op.dst = output;
90   ctx->op.len = _len;
91
92   vnet_crypto_process_ops (vm, &ctx->op, 1);
93 }
94
95 static int
96 ptls_vpp_crypto_cipher_setup_crypto (ptls_cipher_context_t * _ctx, int is_enc,
97                                      const void *key,
98                                      const EVP_CIPHER * cipher,
99                                      ptls_vpp_do_transform_fn do_transform)
100 {
101   struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx;
102
103   ctx->super.do_dispose = ptls_vpp_crypto_cipher_dispose;
104   ctx->super.do_init = ptls_vpp_crypto_cipher_do_init;
105   ctx->super.do_transform = do_transform;
106
107   vlib_main_t *vm = vlib_get_main ();
108   vnet_crypto_alg_t algo;
109   if (!strcmp (ctx->super.algo->name, "AES128-CTR"))
110     {
111       algo = VNET_CRYPTO_ALG_AES_128_CTR;
112     }
113   else if (!strcmp (ctx->super.algo->name, "AES256-CTR"))
114     {
115       algo = VNET_CRYPTO_ALG_AES_256_CTR;
116     }
117   else
118     {
119       TLS_DBG (1, "%s, Invalid crypto cipher : ", __FUNCTION__,
120                _ctx->algo->name);
121       assert (0);
122     }
123
124   clib_rwlock_writer_lock (&picotls_main.crypto_keys_rw_lock);
125   ctx->key_index = vnet_crypto_key_add (vm, algo,
126                                         (u8 *) key, _ctx->algo->key_size);
127   clib_rwlock_writer_unlock (&picotls_main.crypto_keys_rw_lock);
128
129   return 0;
130 }
131
132 size_t
133 ptls_vpp_crypto_aead_decrypt (ptls_aead_context_t *_ctx, void *_output,
134                               const void *input, size_t inlen, uint64_t seq,
135                               const void *aad, size_t aadlen)
136 {
137   vlib_main_t *vm = vlib_get_main ();
138   struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx;
139   int tag_size = ctx->super.algo->tag_size;
140
141   ctx->op.dst = _output;
142   ctx->op.src = (void *) input;
143   ctx->op.len = inlen - tag_size;;
144   ctx->op.iv = ctx->static_iv;
145   ctx->op.aad = (void *) aad;
146   ctx->op.aad_len = aadlen;
147   ctx->op.tag = (void *) input + inlen - tag_size;
148   ctx->op.tag_len = tag_size;
149
150   vnet_crypto_process_ops (vm, &(ctx->op), 1);
151   assert (ctx->op.status == VNET_CRYPTO_OP_STATUS_COMPLETED);
152
153   return inlen - tag_size;
154 }
155
156 static void
157 ptls_vpp_crypto_aead_encrypt_init (ptls_aead_context_t *_ctx, uint64_t seq,
158                                    const void *aad, size_t aadlen)
159 {
160   struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx;
161   ctx->op.iv = ctx->iv;
162   ptls_aead__build_iv (ctx->super.algo, ctx->op.iv, ctx->static_iv, seq);
163   ctx->op.iv = ctx->static_iv;
164   ctx->op.aad = (void *) aad;
165   ctx->op.aad_len = aadlen;
166   ctx->op.n_chunks = 2;
167   ctx->op.chunk_index = 0;
168
169   ctx->op.flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
170 }
171
172 static size_t
173 ptls_vpp_crypto_aead_encrypt_update (ptls_aead_context_t * _ctx, void *output,
174                                      const void *input, size_t inlen)
175 {
176   struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx;
177   ctx->chunks[ctx->chunk_index].dst = output;
178   ctx->chunks[ctx->chunk_index].src = (void *) input;
179   ctx->chunks[ctx->chunk_index].len = inlen;
180
181   ctx->chunk_index = ctx->chunk_index == 0 ? 1 : 0;
182
183   return inlen;
184 }
185
186 static size_t
187 ptls_vpp_crypto_aead_encrypt_final (ptls_aead_context_t * _ctx, void *_output)
188 {
189   struct vlib_main_t *vm = vlib_get_main ();
190   struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx;
191
192   ctx->op.tag = _output;
193   ctx->op.tag_len = ctx->super.algo->tag_size;
194
195   vnet_crypto_process_chained_ops (vm, &(ctx->op), ctx->chunks, 1);
196   assert (ctx->op.status == VNET_CRYPTO_OP_STATUS_COMPLETED);
197
198   return ctx->super.algo->tag_size;
199 }
200
201 static void
202 ptls_vpp_crypto_aead_dispose_crypto (ptls_aead_context_t * _ctx)
203 {
204   /* Do nothing */
205 }
206
207 static int
208 ptls_vpp_crypto_aead_setup_crypto (ptls_aead_context_t *_ctx, int is_enc,
209                                    const void *key, const void *iv,
210                                    vnet_crypto_alg_t alg)
211 {
212   struct vlib_main_t *vm = vlib_get_main ();
213   struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx;
214   u16 key_len = ctx->super.algo->key_size;
215
216   memset (&(ctx->op), 0, sizeof (vnet_crypto_op_t));
217
218   if (alg == VNET_CRYPTO_ALG_AES_128_GCM)
219     {
220       if (is_enc)
221         vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_128_GCM_ENC);
222       else
223         vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_128_GCM_DEC);
224     }
225   else if (alg == VNET_CRYPTO_ALG_AES_256_GCM)
226     {
227       if (is_enc)
228         {
229           vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_256_GCM_ENC);
230         }
231       else
232         vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_256_GCM_DEC);
233     }
234   else
235     {
236       TLS_DBG (1, "%s, invalied aead cipher %s", __FUNCTION__,
237                _ctx->algo->name);
238       return -1;
239     }
240
241   ctx->alg = alg;
242
243   clib_rwlock_writer_lock (&picotls_main.crypto_keys_rw_lock);
244   ctx->op.key_index =
245     vnet_crypto_key_add (vm, ctx->alg, (void *) key, key_len);
246   clib_rwlock_writer_unlock (&picotls_main.crypto_keys_rw_lock);
247   ctx->chunk_index = 0;
248   clib_memcpy (ctx->static_iv, iv, ctx->super.algo->iv_size);
249
250   ctx->super.do_decrypt = ptls_vpp_crypto_aead_decrypt;
251   ctx->super.do_encrypt_init = ptls_vpp_crypto_aead_encrypt_init;
252   ctx->super.do_encrypt_update = ptls_vpp_crypto_aead_encrypt_update;
253   ctx->super.do_encrypt_final = ptls_vpp_crypto_aead_encrypt_final;
254   ctx->super.dispose_crypto = ptls_vpp_crypto_aead_dispose_crypto;
255
256   return 0;
257 }
258
259 static int
260 ptls_vpp_crypto_aes128ctr_setup_crypto (ptls_cipher_context_t * ctx,
261                                         int is_enc, const void *key)
262 {
263   return ptls_vpp_crypto_cipher_setup_crypto (ctx, 1, key, EVP_aes_128_ctr (),
264                                               ptls_vpp_crypto_cipher_encrypt);
265 }
266
267 static int
268 ptls_vpp_crypto_aes256ctr_setup_crypto (ptls_cipher_context_t * ctx,
269                                         int is_enc, const void *key)
270 {
271   return ptls_vpp_crypto_cipher_setup_crypto (ctx, 1, key, EVP_aes_256_ctr (),
272                                               ptls_vpp_crypto_cipher_encrypt);
273 }
274
275 static int
276 ptls_vpp_crypto_aead_aes128gcm_setup_crypto (ptls_aead_context_t *ctx,
277                                              int is_enc, const void *key,
278                                              const void *iv)
279 {
280   return ptls_vpp_crypto_aead_setup_crypto (ctx, is_enc, key, iv,
281                                             VNET_CRYPTO_ALG_AES_128_GCM);
282 }
283
284 static int
285 ptls_vpp_crypto_aead_aes256gcm_setup_crypto (ptls_aead_context_t *ctx,
286                                              int is_enc, const void *key,
287                                              const void *iv)
288 {
289   return ptls_vpp_crypto_aead_setup_crypto (ctx, is_enc, key, iv,
290                                             VNET_CRYPTO_ALG_AES_256_GCM);
291 }
292
293 ptls_cipher_algorithm_t ptls_vpp_crypto_aes128ctr = { "AES128-CTR",
294   PTLS_AES128_KEY_SIZE,
295   1, PTLS_AES_IV_SIZE,
296   sizeof (struct vpp_aead_context_t),
297   ptls_vpp_crypto_aes128ctr_setup_crypto
298 };
299
300 ptls_cipher_algorithm_t ptls_vpp_crypto_aes256ctr = { "AES256-CTR",
301   PTLS_AES256_KEY_SIZE,
302   1 /* block size */ ,
303   PTLS_AES_IV_SIZE,
304   sizeof (struct vpp_aead_context_t),
305   ptls_vpp_crypto_aes256ctr_setup_crypto
306 };
307
308 ptls_aead_algorithm_t ptls_vpp_crypto_aes128gcm = { "AES128-GCM",
309   &ptls_vpp_crypto_aes128ctr,
310   NULL,
311   PTLS_AES128_KEY_SIZE,
312   PTLS_AESGCM_IV_SIZE,
313   PTLS_AESGCM_TAG_SIZE,
314   sizeof (struct vpp_aead_context_t),
315   ptls_vpp_crypto_aead_aes128gcm_setup_crypto
316 };
317
318 ptls_aead_algorithm_t ptls_vpp_crypto_aes256gcm = { "AES256-GCM",
319   &ptls_vpp_crypto_aes256ctr,
320   NULL,
321   PTLS_AES256_KEY_SIZE,
322   PTLS_AESGCM_IV_SIZE,
323   PTLS_AESGCM_TAG_SIZE,
324   sizeof (struct vpp_aead_context_t),
325   ptls_vpp_crypto_aead_aes256gcm_setup_crypto
326 };
327
328 ptls_cipher_suite_t ptls_vpp_crypto_aes128gcmsha256 =
329   { PTLS_CIPHER_SUITE_AES_128_GCM_SHA256,
330   &ptls_vpp_crypto_aes128gcm,
331   &ptls_openssl_sha256
332 };
333
334 ptls_cipher_suite_t ptls_vpp_crypto_aes256gcmsha384 =
335   { PTLS_CIPHER_SUITE_AES_256_GCM_SHA384,
336   &ptls_vpp_crypto_aes256gcm,
337   &ptls_openssl_sha384
338 };
339
340 ptls_cipher_suite_t *ptls_vpp_crypto_cipher_suites[] =
341   { &ptls_vpp_crypto_aes256gcmsha384,
342   &ptls_vpp_crypto_aes128gcmsha256,
343   NULL
344 };
345
346 /*
347  * fd.io coding-style-patch-verification: ON
348  *
349  * Local Variables:
350  * eval: (c-set-style "gnu")
351  * End:
352  */