9931ab56b76f0b2af01e8ba55a2b83dcfb356de0
[vpp.git] / src / plugins / quic / quic_crypto.c
1 /*
2  * Copyright (c) 2021 Cisco 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 <quic/quic.h>
17 #include <quic/quic_crypto.h>
18 #include <vnet/session/session.h>
19
20 #include <quicly.h>
21 #include <picotls/openssl.h>
22 #include <pthread.h>
23
24 #define QUICLY_EPOCH_1RTT 3
25
26 extern quic_main_t quic_main;
27 extern quic_ctx_t *quic_get_conn_ctx (quicly_conn_t * conn);
28 vnet_crypto_main_t *cm = &crypto_main;
29
30 typedef struct crypto_key_
31 {
32   vnet_crypto_alg_t algo;
33   u8 key[32];
34   u16 key_len;
35 } crypto_key_t;
36
37 struct cipher_context_t
38 {
39   ptls_cipher_context_t super;
40   vnet_crypto_op_t op;
41   vnet_crypto_op_id_t id;
42   crypto_key_t key;
43 };
44
45 struct aead_crypto_context_t
46 {
47   ptls_aead_context_t super;
48   EVP_CIPHER_CTX *evp_ctx;
49   uint8_t static_iv[PTLS_MAX_IV_SIZE];
50   vnet_crypto_op_t op;
51   crypto_key_t key;
52
53   vnet_crypto_op_id_t id;
54   uint8_t iv[PTLS_MAX_IV_SIZE];
55 };
56
57 static int
58 quic_crypto_setup_cipher (quicly_crypto_engine_t *engine, quicly_conn_t *conn,
59                           size_t epoch, int is_enc,
60                           ptls_cipher_context_t **header_protect_ctx,
61                           ptls_aead_context_t **packet_protect_ctx,
62                           ptls_aead_algorithm_t *aead,
63                           ptls_hash_algorithm_t *hash, const void *secret)
64 {
65   uint8_t hpkey[PTLS_MAX_SECRET_SIZE];
66   int ret;
67
68   *packet_protect_ctx = NULL;
69   /* generate new header protection key */
70   if (header_protect_ctx != NULL)
71     {
72       *header_protect_ctx = NULL;
73       ret =
74         ptls_hkdf_expand_label (hash, hpkey, aead->ctr_cipher->key_size,
75                                 ptls_iovec_init (secret, hash->digest_size),
76                                 "quic hp", ptls_iovec_init (NULL, 0), NULL);
77       if (ret)
78         goto Exit;
79       *header_protect_ctx = ptls_cipher_new (aead->ctr_cipher, is_enc, hpkey);
80       if (NULL == *header_protect_ctx)
81         {
82           ret = PTLS_ERROR_NO_MEMORY;
83           goto Exit;
84         }
85     }
86
87   /* generate new AEAD context */
88   *packet_protect_ctx =
89     ptls_aead_new (aead, hash, is_enc, secret, QUICLY_AEAD_BASE_LABEL);
90   if (NULL == *packet_protect_ctx)
91     {
92       ret = PTLS_ERROR_NO_MEMORY;
93       goto Exit;
94     }
95
96   if (epoch == QUICLY_EPOCH_1RTT && !is_enc)
97     {
98       quic_ctx_t *qctx = quic_get_conn_ctx (conn);
99       if (qctx->ingress_keys.aead_ctx != NULL)
100         qctx->key_phase_ingress++;
101
102       qctx->ingress_keys.aead_ctx = *packet_protect_ctx;
103       if (header_protect_ctx != NULL)
104         qctx->ingress_keys.hp_ctx = *header_protect_ctx;
105     }
106
107   ret = 0;
108
109 Exit:
110   if (ret)
111     {
112       if (*packet_protect_ctx != NULL)
113         {
114           ptls_aead_free (*packet_protect_ctx);
115           *packet_protect_ctx = NULL;
116         }
117       if (header_protect_ctx && *header_protect_ctx != NULL)
118         {
119           ptls_cipher_free (*header_protect_ctx);
120           *header_protect_ctx = NULL;
121         }
122     }
123   ptls_clear_memory (hpkey, sizeof (hpkey));
124   return ret;
125 }
126
127 static u32
128 quic_crypto_set_key (crypto_key_t *key)
129 {
130   u8 thread_index = vlib_get_thread_index ();
131   u32 key_id = quic_main.per_thread_crypto_key_indices[thread_index];
132   vnet_crypto_key_t *vnet_key = vnet_crypto_get_key (key_id);
133   vlib_main_t *vm = vlib_get_main ();
134   vnet_crypto_engine_t *engine;
135
136   vec_foreach (engine, cm->engines)
137     if (engine->key_op_handler)
138       engine->key_op_handler (vm, VNET_CRYPTO_KEY_OP_DEL, key_id);
139
140   vnet_key->alg = key->algo;
141   clib_memcpy (vnet_key->data, key->key, key->key_len);
142
143   vec_foreach (engine, cm->engines)
144     if (engine->key_op_handler)
145       engine->key_op_handler (vm, VNET_CRYPTO_KEY_OP_ADD, key_id);
146
147   return key_id;
148 }
149
150 static size_t
151 quic_crypto_aead_decrypt (quic_ctx_t *qctx, ptls_aead_context_t *_ctx,
152                           void *_output, const void *input, size_t inlen,
153                           uint64_t decrypted_pn, const void *aad,
154                           size_t aadlen)
155 {
156   vlib_main_t *vm = vlib_get_main ();
157
158   struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *) _ctx;
159
160   vnet_crypto_op_init (&ctx->op, ctx->id);
161   ctx->op.aad = (u8 *) aad;
162   ctx->op.aad_len = aadlen;
163   ctx->op.iv = ctx->iv;
164   ptls_aead__build_iv (ctx->super.algo, ctx->op.iv, ctx->static_iv,
165                        decrypted_pn);
166   ctx->op.src = (u8 *) input;
167   ctx->op.dst = _output;
168   ctx->op.key_index = quic_crypto_set_key (&ctx->key);
169   ctx->op.len = inlen - ctx->super.algo->tag_size;
170   ctx->op.tag_len = ctx->super.algo->tag_size;
171   ctx->op.tag = ctx->op.src + ctx->op.len;
172
173   vnet_crypto_process_ops (vm, &(ctx->op), 1);
174
175   return ctx->op.len;
176 }
177
178 void
179 quic_crypto_decrypt_packet (quic_ctx_t * qctx, quic_rx_packet_ctx_t * pctx)
180 {
181   ptls_cipher_context_t *header_protection = NULL;
182   ptls_aead_context_t *aead = NULL;
183   int pn;
184
185   /* Long Header packets are not decrypted by vpp */
186   if (QUICLY_PACKET_IS_LONG_HEADER (pctx->packet.octets.base[0]))
187     return;
188
189   uint64_t next_expected_packet_number =
190     quicly_get_next_expected_packet_number (qctx->conn);
191   if (next_expected_packet_number == UINT64_MAX)
192     return;
193
194   aead = qctx->ingress_keys.aead_ctx;
195   header_protection = qctx->ingress_keys.hp_ctx;
196
197   if (!aead || !header_protection)
198     return;
199
200   size_t encrypted_len = pctx->packet.octets.len - pctx->packet.encrypted_off;
201   uint8_t hpmask[5] = { 0 };
202   uint32_t pnbits = 0;
203   size_t pnlen, ptlen, i;
204
205   /* decipher the header protection, as well as obtaining pnbits, pnlen */
206   if (encrypted_len < header_protection->algo->iv_size + QUICLY_MAX_PN_SIZE)
207     return;
208   ptls_cipher_init (header_protection,
209                     pctx->packet.octets.base + pctx->packet.encrypted_off +
210                     QUICLY_MAX_PN_SIZE);
211   ptls_cipher_encrypt (header_protection, hpmask, hpmask, sizeof (hpmask));
212   pctx->packet.octets.base[0] ^=
213     hpmask[0] & (QUICLY_PACKET_IS_LONG_HEADER (pctx->packet.octets.base[0]) ?
214                  0xf : 0x1f);
215   pnlen = (pctx->packet.octets.base[0] & 0x3) + 1;
216   for (i = 0; i != pnlen; ++i)
217     {
218       pctx->packet.octets.base[pctx->packet.encrypted_off + i] ^=
219         hpmask[i + 1];
220       pnbits =
221         (pnbits << 8) | pctx->packet.octets.base[pctx->packet.encrypted_off +
222                                                  i];
223     }
224
225   size_t aead_off = pctx->packet.encrypted_off + pnlen;
226
227   pn =
228     quicly_determine_packet_number (pnbits, pnlen * 8,
229                                     next_expected_packet_number);
230
231   int key_phase_bit =
232     (pctx->packet.octets.base[0] & QUICLY_KEY_PHASE_BIT) != 0;
233
234   if (key_phase_bit != (qctx->key_phase_ingress & 1))
235     {
236       pctx->packet.octets.base[0] ^=
237         hpmask[0] &
238         (QUICLY_PACKET_IS_LONG_HEADER (pctx->packet.octets.base[0]) ? 0xf :
239          0x1f);
240       for (i = 0; i != pnlen; ++i)
241         {
242           pctx->packet.octets.base[pctx->packet.encrypted_off + i] ^=
243             hpmask[i + 1];
244         }
245       return;
246     }
247
248   if ((ptlen = quic_crypto_aead_decrypt (
249          qctx, aead, pctx->packet.octets.base + aead_off,
250          pctx->packet.octets.base + aead_off,
251          pctx->packet.octets.len - aead_off, pn, pctx->packet.octets.base,
252          aead_off)) == SIZE_MAX)
253     {
254       fprintf (stderr,
255                "%s: aead decryption failure (pn: %d)\n", __FUNCTION__, pn);
256       return;
257     }
258
259   pctx->packet.encrypted_off = aead_off;
260   pctx->packet.octets.len = ptlen + aead_off;
261
262   pctx->packet.decrypted.pn = pn;
263   pctx->packet.decrypted.key_phase = qctx->key_phase_ingress;
264 }
265
266 void
267 quic_crypto_encrypt_packet (struct st_quicly_crypto_engine_t *engine,
268                             quicly_conn_t *conn,
269                             ptls_cipher_context_t *header_protect_ctx,
270                             ptls_aead_context_t *packet_protect_ctx,
271                             ptls_iovec_t datagram, size_t first_byte_at,
272                             size_t payload_from, uint64_t packet_number,
273                             int coalesced)
274 {
275   vlib_main_t *vm = vlib_get_main ();
276
277   struct cipher_context_t *hp_ctx =
278     (struct cipher_context_t *) header_protect_ctx;
279   struct aead_crypto_context_t *aead_ctx =
280     (struct aead_crypto_context_t *) packet_protect_ctx;
281
282   void *input = datagram.base + payload_from;
283   void *output = input;
284   size_t inlen =
285     datagram.len - payload_from - packet_protect_ctx->algo->tag_size;
286   const void *aad = datagram.base + first_byte_at;
287   size_t aadlen = payload_from - first_byte_at;
288
289   /* Build AEAD encrypt crypto operation */
290   vnet_crypto_op_init (&aead_ctx->op, aead_ctx->id);
291   aead_ctx->op.aad = (u8 *) aad;
292   aead_ctx->op.aad_len = aadlen;
293   aead_ctx->op.iv = aead_ctx->iv;
294   ptls_aead__build_iv (aead_ctx->super.algo, aead_ctx->op.iv,
295                        aead_ctx->static_iv, packet_number);
296   aead_ctx->op.key_index = quic_crypto_set_key (&aead_ctx->key);
297   aead_ctx->op.src = (u8 *) input;
298   aead_ctx->op.dst = output;
299   aead_ctx->op.len = inlen;
300   aead_ctx->op.tag_len = aead_ctx->super.algo->tag_size;
301   aead_ctx->op.tag = aead_ctx->op.src + inlen;
302   vnet_crypto_process_ops (vm, &(aead_ctx->op), 1);
303   assert (aead_ctx->op.status == VNET_CRYPTO_OP_STATUS_COMPLETED);
304
305   /* Build Header protection crypto operation */
306   ptls_aead_supplementary_encryption_t supp = {
307     .ctx = header_protect_ctx,
308     .input =
309       datagram.base + payload_from - QUICLY_SEND_PN_SIZE + QUICLY_MAX_PN_SIZE
310   };
311
312   /* Build Header protection crypto operation */
313   vnet_crypto_op_init (&hp_ctx->op, hp_ctx->id);
314   memset (supp.output, 0, sizeof (supp.output));
315   hp_ctx->op.iv = (u8 *) supp.input;
316   hp_ctx->op.key_index = quic_crypto_set_key (&hp_ctx->key);
317   ;
318   hp_ctx->op.src = (u8 *) supp.output;
319   hp_ctx->op.dst = (u8 *) supp.output;
320   hp_ctx->op.len = sizeof (supp.output);
321   vnet_crypto_process_ops (vm, &(hp_ctx->op), 1);
322   assert (hp_ctx->op.status == VNET_CRYPTO_OP_STATUS_COMPLETED);
323
324   datagram.base[first_byte_at] ^=
325     supp.output[0] &
326     (QUICLY_PACKET_IS_LONG_HEADER (datagram.base[first_byte_at]) ? 0xf : 0x1f);
327   for (size_t i = 0; i != QUICLY_SEND_PN_SIZE; ++i)
328     datagram.base[payload_from + i - QUICLY_SEND_PN_SIZE] ^=
329       supp.output[i + 1];
330 }
331
332 static int
333 quic_crypto_cipher_setup_crypto (ptls_cipher_context_t *_ctx, int is_enc,
334                                  const void *key, const EVP_CIPHER *cipher)
335 {
336   struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx;
337
338   vnet_crypto_alg_t algo;
339   if (!strcmp (ctx->super.algo->name, "AES128-CTR"))
340     {
341       algo = VNET_CRYPTO_ALG_AES_128_CTR;
342       ctx->id = is_enc ? VNET_CRYPTO_OP_AES_128_CTR_ENC :
343                          VNET_CRYPTO_OP_AES_128_CTR_DEC;
344       ptls_openssl_aes128ctr.setup_crypto (_ctx, is_enc, key);
345     }
346   else if (!strcmp (ctx->super.algo->name, "AES256-CTR"))
347     {
348       algo = VNET_CRYPTO_ALG_AES_256_CTR;
349       ctx->id = is_enc ? VNET_CRYPTO_OP_AES_256_CTR_ENC :
350                          VNET_CRYPTO_OP_AES_256_CTR_DEC;
351       ptls_openssl_aes256ctr.setup_crypto (_ctx, is_enc, key);
352     }
353   else
354     {
355       QUIC_DBG (1, "%s, Invalid crypto cipher : ", __FUNCTION__,
356                 _ctx->algo->name);
357       assert (0);
358     }
359
360   if (quic_main.vnet_crypto_enabled)
361     {
362       //       ctx->key_index =
363       //        quic_crypto_go_setup_key (algo, key, _ctx->algo->key_size);
364       ctx->key.algo = algo;
365       ctx->key.key_len = _ctx->algo->key_size;
366       assert (ctx->key.key_len <= 32);
367       clib_memcpy (&ctx->key.key, key, ctx->key.key_len);
368     }
369
370   return 0;
371 }
372
373 static int
374 quic_crypto_aes128ctr_setup_crypto (ptls_cipher_context_t * ctx, int is_enc,
375                                     const void *key)
376 {
377   return quic_crypto_cipher_setup_crypto (ctx, 1, key, EVP_aes_128_ctr ());
378 }
379
380 static int
381 quic_crypto_aes256ctr_setup_crypto (ptls_cipher_context_t * ctx, int is_enc,
382                                     const void *key)
383 {
384   return quic_crypto_cipher_setup_crypto (ctx, 1, key, EVP_aes_256_ctr ());
385 }
386
387 static int
388 quic_crypto_aead_setup_crypto (ptls_aead_context_t *_ctx, int is_enc,
389                                const void *key, const void *iv,
390                                const EVP_CIPHER *cipher)
391 {
392   struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *) _ctx;
393
394   vnet_crypto_alg_t algo;
395   if (!strcmp (ctx->super.algo->name, "AES128-GCM"))
396     {
397       algo = VNET_CRYPTO_ALG_AES_128_GCM;
398       ctx->id = is_enc ? VNET_CRYPTO_OP_AES_128_GCM_ENC :
399                          VNET_CRYPTO_OP_AES_128_GCM_DEC;
400       ptls_openssl_aes128gcm.setup_crypto (_ctx, is_enc, key, iv);
401     }
402   else if (!strcmp (ctx->super.algo->name, "AES256-GCM"))
403     {
404       algo = VNET_CRYPTO_ALG_AES_256_GCM;
405       ctx->id = is_enc ? VNET_CRYPTO_OP_AES_256_GCM_ENC :
406                          VNET_CRYPTO_OP_AES_256_GCM_DEC;
407       ptls_openssl_aes256gcm.setup_crypto (_ctx, is_enc, key, iv);
408     }
409   else
410     {
411       QUIC_DBG (1, "%s, invalied aead cipher %s", __FUNCTION__,
412                 _ctx->algo->name);
413       assert (0);
414     }
415
416   if (quic_main.vnet_crypto_enabled)
417     {
418       clib_memcpy (ctx->static_iv, iv, ctx->super.algo->iv_size);
419       //       ctx->key_index =
420       //        quic_crypto_go_setup_key (algo, key, _ctx->algo->key_size);
421       ctx->key.algo = algo;
422       ctx->key.key_len = _ctx->algo->key_size;
423       assert (ctx->key.key_len <= 32);
424       clib_memcpy (&ctx->key.key, key, ctx->key.key_len);
425     }
426
427   return 0;
428 }
429
430 static int
431 quic_crypto_aead_aes128gcm_setup_crypto (ptls_aead_context_t *ctx, int is_enc,
432                                          const void *key, const void *iv)
433 {
434   return quic_crypto_aead_setup_crypto (ctx, is_enc, key, iv,
435                                         EVP_aes_128_gcm ());
436 }
437
438 static int
439 quic_crypto_aead_aes256gcm_setup_crypto (ptls_aead_context_t *ctx, int is_enc,
440                                          const void *key, const void *iv)
441 {
442   return quic_crypto_aead_setup_crypto (ctx, is_enc, key, iv,
443                                         EVP_aes_256_gcm ());
444 }
445
446 int
447 quic_encrypt_ticket_cb (ptls_encrypt_ticket_t *_self, ptls_t *tls,
448                         int is_encrypt, ptls_buffer_t *dst, ptls_iovec_t src)
449 {
450   quic_session_cache_t *self = (void *) _self;
451   int ret;
452
453   if (is_encrypt)
454     {
455
456       /* replace the cached entry along with a newly generated session id */
457       clib_mem_free (self->data.base);
458       if ((self->data.base = clib_mem_alloc (src.len)) == NULL)
459         return PTLS_ERROR_NO_MEMORY;
460
461       ptls_get_context (tls)->random_bytes (self->id, sizeof (self->id));
462       clib_memcpy (self->data.base, src.base, src.len);
463       self->data.len = src.len;
464
465       /* store the session id in buffer */
466       if ((ret = ptls_buffer_reserve (dst, sizeof (self->id))) != 0)
467         return ret;
468       clib_memcpy (dst->base + dst->off, self->id, sizeof (self->id));
469       dst->off += sizeof (self->id);
470     }
471   else
472     {
473       /* check if session id is the one stored in cache */
474       if (src.len != sizeof (self->id))
475         return PTLS_ERROR_SESSION_NOT_FOUND;
476       if (clib_memcmp (self->id, src.base, sizeof (self->id)) != 0)
477         return PTLS_ERROR_SESSION_NOT_FOUND;
478
479       /* return the cached value */
480       if ((ret = ptls_buffer_reserve (dst, self->data.len)) != 0)
481         return ret;
482       clib_memcpy (dst->base + dst->off, self->data.base, self->data.len);
483       dst->off += self->data.len;
484     }
485
486   return 0;
487 }
488
489 ptls_cipher_algorithm_t quic_crypto_aes128ctr = {
490   "AES128-CTR",
491   PTLS_AES128_KEY_SIZE,
492   1,
493   PTLS_AES_IV_SIZE,
494   sizeof (struct cipher_context_t),
495   quic_crypto_aes128ctr_setup_crypto
496 };
497
498 ptls_cipher_algorithm_t quic_crypto_aes256ctr = {
499   "AES256-CTR",
500   PTLS_AES256_KEY_SIZE,
501   1 /* block size */,
502   PTLS_AES_IV_SIZE,
503   sizeof (struct cipher_context_t),
504   quic_crypto_aes256ctr_setup_crypto
505 };
506
507 ptls_aead_algorithm_t quic_crypto_aes128gcm = {
508   "AES128-GCM",
509   PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
510   PTLS_AESGCM_INTEGRITY_LIMIT,
511   &quic_crypto_aes128ctr,
512   &ptls_openssl_aes128ecb,
513   PTLS_AES128_KEY_SIZE,
514   PTLS_AESGCM_IV_SIZE,
515   PTLS_AESGCM_TAG_SIZE,
516   sizeof (struct aead_crypto_context_t),
517   quic_crypto_aead_aes128gcm_setup_crypto
518 };
519
520 ptls_aead_algorithm_t quic_crypto_aes256gcm = {
521   "AES256-GCM",
522   PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
523   PTLS_AESGCM_INTEGRITY_LIMIT,
524   &quic_crypto_aes256ctr,
525   &ptls_openssl_aes256ecb,
526   PTLS_AES256_KEY_SIZE,
527   PTLS_AESGCM_IV_SIZE,
528   PTLS_AESGCM_TAG_SIZE,
529   sizeof (struct aead_crypto_context_t),
530   quic_crypto_aead_aes256gcm_setup_crypto
531 };
532
533 ptls_cipher_suite_t quic_crypto_aes128gcmsha256 = {
534   PTLS_CIPHER_SUITE_AES_128_GCM_SHA256,
535   &quic_crypto_aes128gcm, &ptls_openssl_sha256
536 };
537
538 ptls_cipher_suite_t quic_crypto_aes256gcmsha384 = {
539   PTLS_CIPHER_SUITE_AES_256_GCM_SHA384,
540   &quic_crypto_aes256gcm, &ptls_openssl_sha384
541 };
542
543 ptls_cipher_suite_t *quic_crypto_cipher_suites[] = {
544   &quic_crypto_aes256gcmsha384, &quic_crypto_aes128gcmsha256, NULL
545 };
546
547 quicly_crypto_engine_t quic_crypto_engine = { quic_crypto_setup_cipher,
548                                               quic_crypto_encrypt_packet };
549
550 /*
551  * fd.io coding-style-patch-verification: ON
552  *
553  * Local Variables:
554  * eval: (c-set-style "gnu")
555  * End:
556  */