]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bearssl/src/ssl/ssl_rec_chapol.c
Add libbearssl
[FreeBSD/FreeBSD.git] / contrib / bearssl / src / ssl / ssl_rec_chapol.c
1 /*
2  * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining 
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be 
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #include "inner.h"
26
27 static void
28 gen_chapol_init(br_sslrec_chapol_context *cc,
29         br_chacha20_run ichacha, br_poly1305_run ipoly,
30         const void *key, const void *iv)
31 {
32         cc->seq = 0;
33         cc->ichacha = ichacha;
34         cc->ipoly = ipoly;
35         memcpy(cc->key, key, sizeof cc->key);
36         memcpy(cc->iv, iv, sizeof cc->iv);
37 }
38
39 static void
40 gen_chapol_process(br_sslrec_chapol_context *cc,
41         int record_type, unsigned version, void *data, size_t len,
42         void *tag, int encrypt)
43 {
44         unsigned char header[13];
45         unsigned char nonce[12];
46         uint64_t seq;
47         size_t u;
48
49         seq = cc->seq ++;
50         br_enc64be(header, seq);
51         header[8] = (unsigned char)record_type;
52         br_enc16be(header + 9, version);
53         br_enc16be(header + 11, len);
54         memcpy(nonce, cc->iv, 12);
55         for (u = 0; u < 8; u ++) {
56                 nonce[11 - u] ^= (unsigned char)seq;
57                 seq >>= 8;
58         }
59         cc->ipoly(cc->key, nonce, data, len, header, sizeof header,
60                 tag, cc->ichacha, encrypt);
61 }
62
63 static void
64 in_chapol_init(br_sslrec_chapol_context *cc,
65         br_chacha20_run ichacha, br_poly1305_run ipoly,
66         const void *key, const void *iv)
67 {
68         cc->vtable.in = &br_sslrec_in_chapol_vtable;
69         gen_chapol_init(cc, ichacha, ipoly, key, iv);
70 }
71
72 static int
73 chapol_check_length(const br_sslrec_chapol_context *cc, size_t rlen)
74 {
75         /*
76          * Overhead is just the authentication tag (16 bytes).
77          */
78         (void)cc;
79         return rlen >= 16 && rlen <= (16384 + 16);
80 }
81
82 static unsigned char *
83 chapol_decrypt(br_sslrec_chapol_context *cc,
84         int record_type, unsigned version, void *data, size_t *data_len)
85 {
86         unsigned char *buf;
87         size_t u, len;
88         unsigned char tag[16];
89         unsigned bad;
90
91         buf = data;
92         len = *data_len - 16;
93         gen_chapol_process(cc, record_type, version, buf, len, tag, 0);
94         bad = 0;
95         for (u = 0; u < 16; u ++) {
96                 bad |= tag[u] ^ buf[len + u];
97         }
98         if (bad) {
99                 return NULL;
100         }
101         *data_len = len;
102         return buf;
103 }
104
105 /* see bearssl_ssl.h */
106 const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable = {
107         {
108                 sizeof(br_sslrec_chapol_context),
109                 (int (*)(const br_sslrec_in_class *const *, size_t))
110                         &chapol_check_length,
111                 (unsigned char *(*)(const br_sslrec_in_class **,
112                         int, unsigned, void *, size_t *))
113                         &chapol_decrypt
114         },
115         (void (*)(const br_sslrec_in_chapol_class **,
116                 br_chacha20_run, br_poly1305_run,
117                 const void *, const void *))
118                 &in_chapol_init
119 };
120
121 static void
122 out_chapol_init(br_sslrec_chapol_context *cc,
123         br_chacha20_run ichacha, br_poly1305_run ipoly,
124         const void *key, const void *iv)
125 {
126         cc->vtable.out = &br_sslrec_out_chapol_vtable;
127         gen_chapol_init(cc, ichacha, ipoly, key, iv);
128 }
129
130 static void
131 chapol_max_plaintext(const br_sslrec_chapol_context *cc,
132         size_t *start, size_t *end)
133 {
134         size_t len;
135
136         (void)cc;
137         len = *end - *start - 16;
138         if (len > 16384) {
139                 len = 16384;
140         }
141         *end = *start + len;
142 }
143
144 static unsigned char *
145 chapol_encrypt(br_sslrec_chapol_context *cc,
146         int record_type, unsigned version, void *data, size_t *data_len)
147 {
148         unsigned char *buf;
149         size_t len;
150
151         buf = data;
152         len = *data_len;
153         gen_chapol_process(cc, record_type, version, buf, len, buf + len, 1);
154         buf -= 5;
155         buf[0] = (unsigned char)record_type;
156         br_enc16be(buf + 1, version);
157         br_enc16be(buf + 3, len + 16);
158         *data_len = len + 21;
159         return buf;
160 }
161
162 /* see bearssl_ssl.h */
163 const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable = {
164         {
165                 sizeof(br_sslrec_chapol_context),
166                 (void (*)(const br_sslrec_out_class *const *,
167                         size_t *, size_t *))
168                         &chapol_max_plaintext,
169                 (unsigned char *(*)(const br_sslrec_out_class **,
170                         int, unsigned, void *, size_t *))
171                         &chapol_encrypt
172         },
173         (void (*)(const br_sslrec_out_chapol_class **,
174                 br_chacha20_run, br_poly1305_run,
175                 const void *, const void *))
176                 &out_chapol_init
177 };