1 /*
2  * ngtcp2
3  *
4  * Copyright (c) 2020 ngtcp2 contributors
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif /* HAVE_CONFIG_H */
28 
29 #include <assert.h>
30 
31 #include <ngtcp2/ngtcp2_crypto.h>
32 #include <ngtcp2/ngtcp2_crypto_gnutls.h>
33 
34 #include <gnutls/gnutls.h>
35 #include <gnutls/crypto.h>
36 #include <string.h>
37 
38 #include "shared.h"
39 
ngtcp2_crypto_aead_aes_128_gcm(ngtcp2_crypto_aead * aead)40 ngtcp2_crypto_aead *ngtcp2_crypto_aead_aes_128_gcm(ngtcp2_crypto_aead *aead) {
41   return ngtcp2_crypto_aead_init(aead, (void *)GNUTLS_CIPHER_AES_128_GCM);
42 }
43 
ngtcp2_crypto_md_sha256(ngtcp2_crypto_md * md)44 ngtcp2_crypto_md *ngtcp2_crypto_md_sha256(ngtcp2_crypto_md *md) {
45   md->native_handle = (void *)GNUTLS_DIG_SHA256;
46   return md;
47 }
48 
ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx * ctx)49 ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx) {
50   ngtcp2_crypto_aead_init(&ctx->aead, (void *)GNUTLS_CIPHER_AES_128_GCM);
51   ctx->md.native_handle = (void *)GNUTLS_DIG_SHA256;
52   ctx->hp.native_handle = (void *)GNUTLS_CIPHER_AES_128_CBC;
53   ctx->max_encryption = 0;
54   ctx->max_decryption_failure = 0;
55   return ctx;
56 }
57 
ngtcp2_crypto_aead_init(ngtcp2_crypto_aead * aead,void * aead_native_handle)58 ngtcp2_crypto_aead *ngtcp2_crypto_aead_init(ngtcp2_crypto_aead *aead,
59                                             void *aead_native_handle) {
60   aead->native_handle = aead_native_handle;
61   aead->max_overhead = gnutls_cipher_get_tag_size(
62       (gnutls_cipher_algorithm_t)(intptr_t)aead_native_handle);
63   return aead;
64 }
65 
ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead * aead)66 ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) {
67   return ngtcp2_crypto_aead_init(aead, (void *)GNUTLS_CIPHER_AES_128_GCM);
68 }
69 
70 static gnutls_cipher_algorithm_t
crypto_get_hp(gnutls_cipher_algorithm_t cipher)71 crypto_get_hp(gnutls_cipher_algorithm_t cipher) {
72   switch (cipher) {
73   case GNUTLS_CIPHER_AES_128_GCM:
74   case GNUTLS_CIPHER_AES_128_CCM:
75     return GNUTLS_CIPHER_AES_128_CBC;
76   case GNUTLS_CIPHER_AES_256_GCM:
77   case GNUTLS_CIPHER_AES_256_CCM:
78     return GNUTLS_CIPHER_AES_256_CBC;
79   case GNUTLS_CIPHER_CHACHA20_POLY1305:
80     return GNUTLS_CIPHER_CHACHA20_32;
81   default:
82     return GNUTLS_CIPHER_UNKNOWN;
83   }
84 }
85 
86 static uint64_t
crypto_get_aead_max_encryption(gnutls_cipher_algorithm_t cipher)87 crypto_get_aead_max_encryption(gnutls_cipher_algorithm_t cipher) {
88   switch (cipher) {
89   case GNUTLS_CIPHER_AES_128_GCM:
90   case GNUTLS_CIPHER_AES_256_GCM:
91     return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM;
92   case GNUTLS_CIPHER_CHACHA20_POLY1305:
93     return NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305;
94   case GNUTLS_CIPHER_AES_128_CCM:
95   case GNUTLS_CIPHER_AES_256_CCM:
96     return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_CCM;
97   default:
98     return 0;
99   }
100 }
101 
102 static uint64_t
crypto_get_aead_max_decryption_failure(gnutls_cipher_algorithm_t cipher)103 crypto_get_aead_max_decryption_failure(gnutls_cipher_algorithm_t cipher) {
104   switch (cipher) {
105   case GNUTLS_CIPHER_AES_128_GCM:
106   case GNUTLS_CIPHER_AES_256_GCM:
107     return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM;
108   case GNUTLS_CIPHER_CHACHA20_POLY1305:
109     return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305;
110   case GNUTLS_CIPHER_AES_128_CCM:
111   case GNUTLS_CIPHER_AES_256_CCM:
112     return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM;
113   default:
114     return 0;
115   }
116 }
117 
ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx * ctx,void * tls_native_handle)118 ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx,
119                                          void *tls_native_handle) {
120   gnutls_session_t session = tls_native_handle;
121   gnutls_cipher_algorithm_t cipher;
122   gnutls_digest_algorithm_t hash;
123   gnutls_cipher_algorithm_t hp_cipher;
124 
125   cipher = gnutls_cipher_get(session);
126   if (cipher != GNUTLS_CIPHER_UNKNOWN && cipher != GNUTLS_CIPHER_NULL) {
127     ngtcp2_crypto_aead_init(&ctx->aead, (void *)cipher);
128   }
129 
130   hash = gnutls_prf_hash_get(session);
131   if (hash != GNUTLS_DIG_UNKNOWN && hash != GNUTLS_DIG_NULL) {
132     ctx->md.native_handle = (void *)hash;
133   }
134 
135   hp_cipher = crypto_get_hp(cipher);
136   if (hp_cipher != GNUTLS_CIPHER_UNKNOWN) {
137     ctx->hp.native_handle = (void *)hp_cipher;
138   }
139 
140   ctx->max_encryption = crypto_get_aead_max_encryption(cipher);
141   ctx->max_decryption_failure = crypto_get_aead_max_decryption_failure(cipher);
142 
143   return ctx;
144 }
145 
ngtcp2_crypto_ctx_tls_early(ngtcp2_crypto_ctx * ctx,void * tls_native_handle)146 ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls_early(ngtcp2_crypto_ctx *ctx,
147                                                void *tls_native_handle) {
148   gnutls_session_t session = tls_native_handle;
149   gnutls_cipher_algorithm_t cipher;
150   gnutls_digest_algorithm_t hash;
151   gnutls_cipher_algorithm_t hp_cipher;
152 
153   cipher = gnutls_early_cipher_get(session);
154   if (cipher != GNUTLS_CIPHER_UNKNOWN && cipher != GNUTLS_CIPHER_NULL) {
155     ngtcp2_crypto_aead_init(&ctx->aead, (void *)cipher);
156   }
157 
158   hash = gnutls_early_prf_hash_get(session);
159   if (hash != GNUTLS_DIG_UNKNOWN && hash != GNUTLS_DIG_NULL) {
160     ctx->md.native_handle = (void *)hash;
161   }
162 
163   hp_cipher = crypto_get_hp(cipher);
164   if (hp_cipher != GNUTLS_CIPHER_UNKNOWN) {
165     ctx->hp.native_handle = (void *)hp_cipher;
166   }
167 
168   ctx->max_encryption = crypto_get_aead_max_encryption(cipher);
169   ctx->max_decryption_failure = crypto_get_aead_max_decryption_failure(cipher);
170 
171   return ctx;
172 }
173 
ngtcp2_crypto_md_hashlen(const ngtcp2_crypto_md * md)174 size_t ngtcp2_crypto_md_hashlen(const ngtcp2_crypto_md *md) {
175   return gnutls_hash_get_len(
176       (gnutls_digest_algorithm_t)(intptr_t)md->native_handle);
177 }
178 
ngtcp2_crypto_aead_keylen(const ngtcp2_crypto_aead * aead)179 size_t ngtcp2_crypto_aead_keylen(const ngtcp2_crypto_aead *aead) {
180   return gnutls_cipher_get_key_size(
181       (gnutls_cipher_algorithm_t)(intptr_t)aead->native_handle);
182 }
183 
ngtcp2_crypto_aead_noncelen(const ngtcp2_crypto_aead * aead)184 size_t ngtcp2_crypto_aead_noncelen(const ngtcp2_crypto_aead *aead) {
185   return gnutls_cipher_get_iv_size(
186       (gnutls_cipher_algorithm_t)(intptr_t)aead->native_handle);
187 }
188 
ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx * aead_ctx,const ngtcp2_crypto_aead * aead,const uint8_t * key,size_t noncelen)189 int ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
190                                         const ngtcp2_crypto_aead *aead,
191                                         const uint8_t *key, size_t noncelen) {
192   gnutls_cipher_algorithm_t cipher =
193       (gnutls_cipher_algorithm_t)(intptr_t)aead->native_handle;
194   gnutls_aead_cipher_hd_t hd;
195   gnutls_datum_t _key;
196 
197   (void)noncelen;
198 
199   _key.data = (void *)key;
200   _key.size = (unsigned int)ngtcp2_crypto_aead_keylen(aead);
201 
202   if (gnutls_aead_cipher_init(&hd, cipher, &_key) != 0) {
203     return -1;
204   }
205 
206   aead_ctx->native_handle = hd;
207 
208   return 0;
209 }
210 
ngtcp2_crypto_aead_ctx_decrypt_init(ngtcp2_crypto_aead_ctx * aead_ctx,const ngtcp2_crypto_aead * aead,const uint8_t * key,size_t noncelen)211 int ngtcp2_crypto_aead_ctx_decrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
212                                         const ngtcp2_crypto_aead *aead,
213                                         const uint8_t *key, size_t noncelen) {
214   gnutls_cipher_algorithm_t cipher =
215       (gnutls_cipher_algorithm_t)(intptr_t)aead->native_handle;
216   gnutls_aead_cipher_hd_t hd;
217   gnutls_datum_t _key;
218 
219   (void)noncelen;
220 
221   _key.data = (void *)key;
222   _key.size = (unsigned int)ngtcp2_crypto_aead_keylen(aead);
223 
224   if (gnutls_aead_cipher_init(&hd, cipher, &_key) != 0) {
225     return -1;
226   }
227 
228   aead_ctx->native_handle = hd;
229 
230   return 0;
231 }
232 
ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx * aead_ctx)233 void ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx) {
234   if (aead_ctx->native_handle) {
235     gnutls_aead_cipher_deinit(aead_ctx->native_handle);
236   }
237 }
238 
ngtcp2_crypto_cipher_ctx_encrypt_init(ngtcp2_crypto_cipher_ctx * cipher_ctx,const ngtcp2_crypto_cipher * cipher,const uint8_t * key)239 int ngtcp2_crypto_cipher_ctx_encrypt_init(ngtcp2_crypto_cipher_ctx *cipher_ctx,
240                                           const ngtcp2_crypto_cipher *cipher,
241                                           const uint8_t *key) {
242   gnutls_cipher_algorithm_t _cipher =
243       (gnutls_cipher_algorithm_t)(intptr_t)cipher->native_handle;
244   gnutls_cipher_hd_t hd;
245   gnutls_datum_t _key;
246 
247   _key.data = (void *)key;
248   _key.size = (unsigned int)gnutls_cipher_get_key_size(_cipher);
249 
250   if (gnutls_cipher_init(&hd, _cipher, &_key, NULL) != 0) {
251     return -1;
252   }
253 
254   cipher_ctx->native_handle = hd;
255 
256   return 0;
257 }
258 
ngtcp2_crypto_cipher_ctx_free(ngtcp2_crypto_cipher_ctx * cipher_ctx)259 void ngtcp2_crypto_cipher_ctx_free(ngtcp2_crypto_cipher_ctx *cipher_ctx) {
260   if (cipher_ctx->native_handle) {
261     gnutls_cipher_deinit(cipher_ctx->native_handle);
262   }
263 }
264 
ngtcp2_crypto_hkdf_extract(uint8_t * dest,const ngtcp2_crypto_md * md,const uint8_t * secret,size_t secretlen,const uint8_t * salt,size_t saltlen)265 int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md,
266                                const uint8_t *secret, size_t secretlen,
267                                const uint8_t *salt, size_t saltlen) {
268   gnutls_mac_algorithm_t prf =
269       (gnutls_mac_algorithm_t)(intptr_t)md->native_handle;
270   gnutls_datum_t _secret = {(void *)secret, (unsigned int)secretlen};
271   gnutls_datum_t _salt = {(void *)salt, (unsigned int)saltlen};
272 
273   if (gnutls_hkdf_extract(prf, &_secret, &_salt, dest) != 0) {
274     return -1;
275   }
276 
277   return 0;
278 }
279 
ngtcp2_crypto_hkdf_expand(uint8_t * dest,size_t destlen,const ngtcp2_crypto_md * md,const uint8_t * secret,size_t secretlen,const uint8_t * info,size_t infolen)280 int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen,
281                               const ngtcp2_crypto_md *md, const uint8_t *secret,
282                               size_t secretlen, const uint8_t *info,
283                               size_t infolen) {
284   gnutls_mac_algorithm_t prf =
285       (gnutls_mac_algorithm_t)(intptr_t)md->native_handle;
286   gnutls_datum_t _secret = {(void *)secret, (unsigned int)secretlen};
287   gnutls_datum_t _info = {(void *)info, (unsigned int)infolen};
288 
289   if (gnutls_hkdf_expand(prf, &_secret, &_info, dest, destlen) != 0) {
290     return -1;
291   }
292 
293   return 0;
294 }
295 
ngtcp2_crypto_hkdf(uint8_t * dest,size_t destlen,const ngtcp2_crypto_md * md,const uint8_t * secret,size_t secretlen,const uint8_t * salt,size_t saltlen,const uint8_t * info,size_t infolen)296 int ngtcp2_crypto_hkdf(uint8_t *dest, size_t destlen,
297                        const ngtcp2_crypto_md *md, const uint8_t *secret,
298                        size_t secretlen, const uint8_t *salt, size_t saltlen,
299                        const uint8_t *info, size_t infolen) {
300   gnutls_mac_algorithm_t prf =
301       (gnutls_mac_algorithm_t)(intptr_t)md->native_handle;
302   size_t keylen = ngtcp2_crypto_md_hashlen(md);
303   uint8_t key[64];
304   gnutls_datum_t _secret = {(void *)secret, (unsigned int)secretlen};
305   gnutls_datum_t _key = {(void *)key, (unsigned int)keylen};
306   gnutls_datum_t _salt = {(void *)salt, (unsigned int)saltlen};
307   gnutls_datum_t _info = {(void *)info, (unsigned int)infolen};
308 
309   assert(keylen <= sizeof(key));
310 
311   if (gnutls_hkdf_extract(prf, &_secret, &_salt, key) != 0) {
312     return -1;
313   }
314 
315   if (gnutls_hkdf_expand(prf, &_key, &_info, dest, destlen) != 0) {
316     return -1;
317   }
318 
319   return 0;
320 }
321 
ngtcp2_crypto_encrypt(uint8_t * dest,const ngtcp2_crypto_aead * aead,const ngtcp2_crypto_aead_ctx * aead_ctx,const uint8_t * plaintext,size_t plaintextlen,const uint8_t * nonce,size_t noncelen,const uint8_t * aad,size_t aadlen)322 int ngtcp2_crypto_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
323                           const ngtcp2_crypto_aead_ctx *aead_ctx,
324                           const uint8_t *plaintext, size_t plaintextlen,
325                           const uint8_t *nonce, size_t noncelen,
326                           const uint8_t *aad, size_t aadlen) {
327   gnutls_cipher_algorithm_t cipher =
328       (gnutls_cipher_algorithm_t)(intptr_t)aead->native_handle;
329   gnutls_aead_cipher_hd_t hd = aead_ctx->native_handle;
330   size_t taglen = gnutls_cipher_get_tag_size(cipher);
331   size_t ciphertextlen = plaintextlen + taglen;
332 
333   if (gnutls_aead_cipher_encrypt(hd, nonce, noncelen, aad, aadlen, taglen,
334                                  plaintext, plaintextlen, dest,
335                                  &ciphertextlen) != 0) {
336     return -1;
337   }
338 
339   return 0;
340 }
341 
ngtcp2_crypto_decrypt(uint8_t * dest,const ngtcp2_crypto_aead * aead,const ngtcp2_crypto_aead_ctx * aead_ctx,const uint8_t * ciphertext,size_t ciphertextlen,const uint8_t * nonce,size_t noncelen,const uint8_t * aad,size_t aadlen)342 int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
343                           const ngtcp2_crypto_aead_ctx *aead_ctx,
344                           const uint8_t *ciphertext, size_t ciphertextlen,
345                           const uint8_t *nonce, size_t noncelen,
346                           const uint8_t *aad, size_t aadlen) {
347   gnutls_cipher_algorithm_t cipher =
348       (gnutls_cipher_algorithm_t)(intptr_t)aead->native_handle;
349   gnutls_aead_cipher_hd_t hd = aead_ctx->native_handle;
350   size_t taglen = gnutls_cipher_get_tag_size(cipher);
351   size_t plaintextlen;
352 
353   if (taglen > ciphertextlen) {
354     return -1;
355   }
356 
357   plaintextlen = ciphertextlen - taglen;
358 
359   if (gnutls_aead_cipher_decrypt(hd, nonce, noncelen, aad, aadlen, taglen,
360                                  ciphertext, ciphertextlen, dest,
361                                  &plaintextlen) != 0) {
362     return -1;
363   }
364 
365   return 0;
366 }
367 
ngtcp2_crypto_hp_mask(uint8_t * dest,const ngtcp2_crypto_cipher * hp,const ngtcp2_crypto_cipher_ctx * hp_ctx,const uint8_t * sample)368 int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
369                           const ngtcp2_crypto_cipher_ctx *hp_ctx,
370                           const uint8_t *sample) {
371   gnutls_cipher_algorithm_t cipher =
372       (gnutls_cipher_algorithm_t)(intptr_t)hp->native_handle;
373   gnutls_cipher_hd_t hd = hp_ctx->native_handle;
374 
375   switch (cipher) {
376   case GNUTLS_CIPHER_AES_128_CBC:
377   case GNUTLS_CIPHER_AES_256_CBC: {
378     uint8_t iv[16];
379     uint8_t buf[16];
380 
381     /* Emulate one block AES-ECB by invalidating the effect of IV */
382     memset(iv, 0, sizeof(iv));
383 
384     gnutls_cipher_set_iv(hd, iv, sizeof(iv));
385 
386     if (gnutls_cipher_encrypt2(hd, sample, 16, buf, sizeof(buf)) != 0) {
387       return -1;
388     }
389 
390     memcpy(dest, buf, 5);
391   } break;
392 
393   case GNUTLS_CIPHER_CHACHA20_32: {
394     static const uint8_t PLAINTEXT[] = "\x00\x00\x00\x00\x00";
395     uint8_t buf[5 + 16];
396     size_t buflen = sizeof(buf);
397 
398     gnutls_cipher_set_iv(hd, (void *)sample, 16);
399 
400     if (gnutls_cipher_encrypt2(hd, PLAINTEXT, sizeof(PLAINTEXT) - 1, buf,
401                                buflen) != 0) {
402       return -1;
403     }
404 
405     memcpy(dest, buf, 5);
406   } break;
407   default:
408     assert(0);
409   }
410 
411   return 0;
412 }
413 
ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gnutls_record_encryption_level_t gtls_level)414 ngtcp2_crypto_level ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(
415     gnutls_record_encryption_level_t gtls_level) {
416   switch (gtls_level) {
417   case GNUTLS_ENCRYPTION_LEVEL_INITIAL:
418     return NGTCP2_CRYPTO_LEVEL_INITIAL;
419   case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE:
420     return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
421   case GNUTLS_ENCRYPTION_LEVEL_APPLICATION:
422     return NGTCP2_CRYPTO_LEVEL_APPLICATION;
423   case GNUTLS_ENCRYPTION_LEVEL_EARLY:
424     return NGTCP2_CRYPTO_LEVEL_EARLY;
425   default:
426     assert(0);
427     abort();
428   }
429 }
430 
431 gnutls_record_encryption_level_t
ngtcp2_crypto_gnutls_from_ngtcp2_level(ngtcp2_crypto_level crypto_level)432 ngtcp2_crypto_gnutls_from_ngtcp2_level(ngtcp2_crypto_level crypto_level) {
433   switch (crypto_level) {
434   case NGTCP2_CRYPTO_LEVEL_INITIAL:
435     return GNUTLS_ENCRYPTION_LEVEL_INITIAL;
436   case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
437     return GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE;
438   case NGTCP2_CRYPTO_LEVEL_APPLICATION:
439     return GNUTLS_ENCRYPTION_LEVEL_APPLICATION;
440   case NGTCP2_CRYPTO_LEVEL_EARLY:
441     return GNUTLS_ENCRYPTION_LEVEL_EARLY;
442   default:
443     assert(0);
444     abort();
445   }
446 }
447 
ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn * conn,ngtcp2_crypto_level crypto_level,const uint8_t * data,size_t datalen)448 int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn,
449                                          ngtcp2_crypto_level crypto_level,
450                                          const uint8_t *data, size_t datalen) {
451   gnutls_session_t session = ngtcp2_conn_get_tls_native_handle(conn);
452   int rv;
453 
454   if (datalen > 0) {
455     if (gnutls_handshake_write(
456             session, ngtcp2_crypto_gnutls_from_ngtcp2_level(crypto_level), data,
457             datalen) != 0) {
458       return -1;
459     }
460   }
461 
462   if (!ngtcp2_conn_get_handshake_completed(conn)) {
463     rv = gnutls_handshake(session);
464     if (rv < 0) {
465       if (!gnutls_error_is_fatal(rv)) {
466         return 0;
467       }
468       gnutls_alert_send_appropriate(session, rv);
469       return -1;
470     }
471 
472     ngtcp2_conn_handshake_completed(conn);
473   }
474 
475   return 0;
476 }
477 
ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn * conn,void * tls)478 int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls) {
479   (void)conn;
480   (void)tls;
481   /* Nothing to do; GnuTLS applications are supposed to register the
482      quic_transport_parameters extension with
483      gnutls_session_ext_register. */
484   return 0;
485 }
486 
ngtcp2_crypto_set_local_transport_params(void * tls,const uint8_t * buf,size_t len)487 int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf,
488                                              size_t len) {
489   (void)tls;
490   (void)buf;
491   (void)len;
492   /* Nothing to do; GnuTLS applications are supposed to register the
493      quic_transport_parameters extension with
494      gnutls_session_ext_register. */
495   return 0;
496 }
497 
ngtcp2_crypto_get_path_challenge_data_cb(ngtcp2_conn * conn,uint8_t * data,void * user_data)498 int ngtcp2_crypto_get_path_challenge_data_cb(ngtcp2_conn *conn, uint8_t *data,
499                                              void *user_data) {
500   (void)conn;
501   (void)user_data;
502 
503   if (gnutls_rnd(GNUTLS_RND_RANDOM, data, NGTCP2_PATH_CHALLENGE_DATALEN) != 0) {
504     return NGTCP2_ERR_CALLBACK_FAILURE;
505   }
506 
507   return 0;
508 }
509 
ngtcp2_crypto_random(uint8_t * data,size_t datalen)510 int ngtcp2_crypto_random(uint8_t *data, size_t datalen) {
511   if (gnutls_rnd(GNUTLS_RND_RANDOM, data, datalen) != 0) {
512     return -1;
513   }
514 
515   return 0;
516 }
517