Path: blob/main/contrib/bearssl/src/ssl/ssl_rec_chapol.c
39483 views
/*1* Copyright (c) 2016 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#include "inner.h"2526static void27gen_chapol_init(br_sslrec_chapol_context *cc,28br_chacha20_run ichacha, br_poly1305_run ipoly,29const void *key, const void *iv)30{31cc->seq = 0;32cc->ichacha = ichacha;33cc->ipoly = ipoly;34memcpy(cc->key, key, sizeof cc->key);35memcpy(cc->iv, iv, sizeof cc->iv);36}3738static void39gen_chapol_process(br_sslrec_chapol_context *cc,40int record_type, unsigned version, void *data, size_t len,41void *tag, int encrypt)42{43unsigned char header[13];44unsigned char nonce[12];45uint64_t seq;46size_t u;4748seq = cc->seq ++;49br_enc64be(header, seq);50header[8] = (unsigned char)record_type;51br_enc16be(header + 9, version);52br_enc16be(header + 11, len);53memcpy(nonce, cc->iv, 12);54for (u = 0; u < 8; u ++) {55nonce[11 - u] ^= (unsigned char)seq;56seq >>= 8;57}58cc->ipoly(cc->key, nonce, data, len, header, sizeof header,59tag, cc->ichacha, encrypt);60}6162static void63in_chapol_init(br_sslrec_chapol_context *cc,64br_chacha20_run ichacha, br_poly1305_run ipoly,65const void *key, const void *iv)66{67cc->vtable.in = &br_sslrec_in_chapol_vtable;68gen_chapol_init(cc, ichacha, ipoly, key, iv);69}7071static int72chapol_check_length(const br_sslrec_chapol_context *cc, size_t rlen)73{74/*75* Overhead is just the authentication tag (16 bytes).76*/77(void)cc;78return rlen >= 16 && rlen <= (16384 + 16);79}8081static unsigned char *82chapol_decrypt(br_sslrec_chapol_context *cc,83int record_type, unsigned version, void *data, size_t *data_len)84{85unsigned char *buf;86size_t u, len;87unsigned char tag[16];88unsigned bad;8990buf = data;91len = *data_len - 16;92gen_chapol_process(cc, record_type, version, buf, len, tag, 0);93bad = 0;94for (u = 0; u < 16; u ++) {95bad |= tag[u] ^ buf[len + u];96}97if (bad) {98return NULL;99}100*data_len = len;101return buf;102}103104/* see bearssl_ssl.h */105const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable = {106{107sizeof(br_sslrec_chapol_context),108(int (*)(const br_sslrec_in_class *const *, size_t))109&chapol_check_length,110(unsigned char *(*)(const br_sslrec_in_class **,111int, unsigned, void *, size_t *))112&chapol_decrypt113},114(void (*)(const br_sslrec_in_chapol_class **,115br_chacha20_run, br_poly1305_run,116const void *, const void *))117&in_chapol_init118};119120static void121out_chapol_init(br_sslrec_chapol_context *cc,122br_chacha20_run ichacha, br_poly1305_run ipoly,123const void *key, const void *iv)124{125cc->vtable.out = &br_sslrec_out_chapol_vtable;126gen_chapol_init(cc, ichacha, ipoly, key, iv);127}128129static void130chapol_max_plaintext(const br_sslrec_chapol_context *cc,131size_t *start, size_t *end)132{133size_t len;134135(void)cc;136len = *end - *start - 16;137if (len > 16384) {138len = 16384;139}140*end = *start + len;141}142143static unsigned char *144chapol_encrypt(br_sslrec_chapol_context *cc,145int record_type, unsigned version, void *data, size_t *data_len)146{147unsigned char *buf;148size_t len;149150buf = data;151len = *data_len;152gen_chapol_process(cc, record_type, version, buf, len, buf + len, 1);153buf -= 5;154buf[0] = (unsigned char)record_type;155br_enc16be(buf + 1, version);156br_enc16be(buf + 3, len + 16);157*data_len = len + 21;158return buf;159}160161/* see bearssl_ssl.h */162const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable = {163{164sizeof(br_sslrec_chapol_context),165(void (*)(const br_sslrec_out_class *const *,166size_t *, size_t *))167&chapol_max_plaintext,168(unsigned char *(*)(const br_sslrec_out_class **,169int, unsigned, void *, size_t *))170&chapol_encrypt171},172(void (*)(const br_sslrec_out_chapol_class **,173br_chacha20_run, br_poly1305_run,174const void *, const void *))175&out_chapol_init176};177178179