/src/openssl30/crypto/evp/e_chacha20_poly1305.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  |  * | 
| 4 |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
| 5 |  |  * this file except in compliance with the License.  You can obtain a copy | 
| 6 |  |  * in the file LICENSE in the source distribution or at | 
| 7 |  |  * https://www.openssl.org/source/license.html | 
| 8 |  |  */ | 
| 9 |  |  | 
| 10 |  | #include <stdio.h> | 
| 11 |  | #include "internal/cryptlib.h" | 
| 12 |  | #include "internal/endian.h" | 
| 13 |  |  | 
| 14 |  | #ifndef OPENSSL_NO_CHACHA | 
| 15 |  |  | 
| 16 |  | # include <openssl/evp.h> | 
| 17 |  | # include <openssl/objects.h> | 
| 18 |  | # include "crypto/evp.h" | 
| 19 |  | # include "evp_local.h" | 
| 20 |  | # include "crypto/chacha.h" | 
| 21 |  |  | 
| 22 |  | typedef struct { | 
| 23 |  |     union { | 
| 24 |  |         OSSL_UNION_ALIGN;  /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */ | 
| 25 |  |         unsigned int d[CHACHA_KEY_SIZE / 4]; | 
| 26 |  |     } key; | 
| 27 |  |     unsigned int  counter[CHACHA_CTR_SIZE / 4]; | 
| 28 |  |     unsigned char buf[CHACHA_BLK_SIZE]; | 
| 29 |  |     unsigned int  partial_len; | 
| 30 |  | } EVP_CHACHA_KEY; | 
| 31 |  |  | 
| 32 | 19.0k | #define data(ctx)   ((EVP_CHACHA_KEY *)(ctx)->cipher_data) | 
| 33 |  |  | 
| 34 | 926 | #define CHACHA20_POLY1305_MAX_IVLEN     12 | 
| 35 |  |  | 
| 36 |  | static int chacha_init_key(EVP_CIPHER_CTX *ctx, | 
| 37 |  |                            const unsigned char user_key[CHACHA_KEY_SIZE], | 
| 38 |  |                            const unsigned char iv[CHACHA_CTR_SIZE], int enc) | 
| 39 | 10.0k | { | 
| 40 | 10.0k |     EVP_CHACHA_KEY *key = data(ctx); | 
| 41 | 10.0k |     unsigned int i; | 
| 42 |  |  | 
| 43 | 10.0k |     if (user_key) | 
| 44 | 8.52k |         for (i = 0; i < CHACHA_KEY_SIZE; i+=4) { | 
| 45 | 7.57k |             key->key.d[i/4] = CHACHA_U8TOU32(user_key+i); | 
| 46 | 7.57k |         } | 
| 47 |  |  | 
| 48 | 10.0k |     if (iv) | 
| 49 | 45.3k |         for (i = 0; i < CHACHA_CTR_SIZE; i+=4) { | 
| 50 | 36.3k |             key->counter[i/4] = CHACHA_U8TOU32(iv+i); | 
| 51 | 36.3k |         } | 
| 52 |  |  | 
| 53 | 10.0k |     key->partial_len = 0; | 
| 54 |  |  | 
| 55 | 10.0k |     return 1; | 
| 56 | 10.0k | } | 
| 57 |  |  | 
| 58 |  | static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, | 
| 59 |  |                          const unsigned char *inp, size_t len) | 
| 60 | 9.05k | { | 
| 61 | 9.05k |     EVP_CHACHA_KEY *key = data(ctx); | 
| 62 | 9.05k |     unsigned int n, rem, ctr32; | 
| 63 |  |  | 
| 64 | 9.05k |     if ((n = key->partial_len)) { | 
| 65 | 0 |         while (len && n < CHACHA_BLK_SIZE) { | 
| 66 | 0 |             *out++ = *inp++ ^ key->buf[n++]; | 
| 67 | 0 |             len--; | 
| 68 | 0 |         } | 
| 69 | 0 |         key->partial_len = n; | 
| 70 |  | 
 | 
| 71 | 0 |         if (len == 0) | 
| 72 | 0 |             return 1; | 
| 73 |  |  | 
| 74 | 0 |         if (n == CHACHA_BLK_SIZE) { | 
| 75 | 0 |             key->partial_len = 0; | 
| 76 | 0 |             key->counter[0]++; | 
| 77 | 0 |             if (key->counter[0] == 0) | 
| 78 | 0 |                 key->counter[1]++; | 
| 79 | 0 |         } | 
| 80 | 0 |     } | 
| 81 |  |  | 
| 82 | 9.05k |     rem = (unsigned int)(len % CHACHA_BLK_SIZE); | 
| 83 | 9.05k |     len -= rem; | 
| 84 | 9.05k |     ctr32 = key->counter[0]; | 
| 85 | 9.81k |     while (len >= CHACHA_BLK_SIZE) { | 
| 86 | 753 |         size_t blocks = len / CHACHA_BLK_SIZE; | 
| 87 |  |         /* | 
| 88 |  |          * 1<<28 is just a not-so-small yet not-so-large number... | 
| 89 |  |          * Below condition is practically never met, but it has to | 
| 90 |  |          * be checked for code correctness. | 
| 91 |  |          */ | 
| 92 | 753 |         if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U<<28)) | 
| 93 | 0 |             blocks = (1U<<28); | 
| 94 |  |  | 
| 95 |  |         /* | 
| 96 |  |          * As ChaCha20_ctr32 operates on 32-bit counter, caller | 
| 97 |  |          * has to handle overflow. 'if' below detects the | 
| 98 |  |          * overflow, which is then handled by limiting the | 
| 99 |  |          * amount of blocks to the exact overflow point... | 
| 100 |  |          */ | 
| 101 | 753 |         ctr32 += (unsigned int)blocks; | 
| 102 | 753 |         if (ctr32 < blocks) { | 
| 103 | 0 |             blocks -= ctr32; | 
| 104 | 0 |             ctr32 = 0; | 
| 105 | 0 |         } | 
| 106 | 753 |         blocks *= CHACHA_BLK_SIZE; | 
| 107 | 753 |         ChaCha20_ctr32(out, inp, blocks, key->key.d, key->counter); | 
| 108 | 753 |         len -= blocks; | 
| 109 | 753 |         inp += blocks; | 
| 110 | 753 |         out += blocks; | 
| 111 |  |  | 
| 112 | 753 |         key->counter[0] = ctr32; | 
| 113 | 753 |         if (ctr32 == 0) key->counter[1]++; | 
| 114 | 753 |     } | 
| 115 |  |  | 
| 116 | 9.05k |     if (rem) { | 
| 117 | 8.92k |         memset(key->buf, 0, sizeof(key->buf)); | 
| 118 | 8.92k |         ChaCha20_ctr32(key->buf, key->buf, CHACHA_BLK_SIZE, | 
| 119 | 8.92k |                        key->key.d, key->counter); | 
| 120 | 57.3k |         for (n = 0; n < rem; n++) | 
| 121 | 48.3k |             out[n] = inp[n] ^ key->buf[n]; | 
| 122 | 8.92k |         key->partial_len = rem; | 
| 123 | 8.92k |     } | 
| 124 |  |  | 
| 125 | 9.05k |     return 1; | 
| 126 | 9.05k | } | 
| 127 |  |  | 
| 128 |  | static const EVP_CIPHER chacha20 = { | 
| 129 |  |     NID_chacha20, | 
| 130 |  |     1,                      /* block_size */ | 
| 131 |  |     CHACHA_KEY_SIZE,        /* key_len */ | 
| 132 |  |     CHACHA_CTR_SIZE,        /* iv_len, 128-bit counter in the context */ | 
| 133 |  |     EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT, | 
| 134 |  |     EVP_ORIG_GLOBAL, | 
| 135 |  |     chacha_init_key, | 
| 136 |  |     chacha_cipher, | 
| 137 |  |     NULL, | 
| 138 |  |     sizeof(EVP_CHACHA_KEY), | 
| 139 |  |     NULL, | 
| 140 |  |     NULL, | 
| 141 |  |     NULL, | 
| 142 |  |     NULL | 
| 143 |  | }; | 
| 144 |  |  | 
| 145 |  | const EVP_CIPHER *EVP_chacha20(void) | 
| 146 | 31 | { | 
| 147 | 31 |     return &chacha20; | 
| 148 | 31 | } | 
| 149 |  |  | 
| 150 |  | # ifndef OPENSSL_NO_POLY1305 | 
| 151 |  | #  include "crypto/poly1305.h" | 
| 152 |  |  | 
| 153 |  | typedef struct { | 
| 154 |  |     EVP_CHACHA_KEY key; | 
| 155 |  |     unsigned int nonce[12/4]; | 
| 156 |  |     unsigned char tag[POLY1305_BLOCK_SIZE]; | 
| 157 |  |     unsigned char tls_aad[POLY1305_BLOCK_SIZE]; | 
| 158 |  |     struct { uint64_t aad, text; } len; | 
| 159 |  |     int aad, mac_inited, tag_len, nonce_len; | 
| 160 |  |     size_t tls_payload_length; | 
| 161 |  | } EVP_CHACHA_AEAD_CTX; | 
| 162 |  |  | 
| 163 | 10.9k | #  define NO_TLS_PAYLOAD_LENGTH ((size_t)-1) | 
| 164 | 32.6k | #  define aead_data(ctx)        ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data) | 
| 165 |  | #  define POLY1305_ctx(actx)    ((POLY1305 *)(actx + 1)) | 
| 166 |  |  | 
| 167 |  | static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx, | 
| 168 |  |                                       const unsigned char *inkey, | 
| 169 |  |                                       const unsigned char *iv, int enc) | 
| 170 | 10.9k | { | 
| 171 | 10.9k |     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); | 
| 172 |  |  | 
| 173 | 10.9k |     if (!inkey && !iv) | 
| 174 | 926 |         return 1; | 
| 175 |  |  | 
| 176 | 10.0k |     actx->len.aad = 0; | 
| 177 | 10.0k |     actx->len.text = 0; | 
| 178 | 10.0k |     actx->aad = 0; | 
| 179 | 10.0k |     actx->mac_inited = 0; | 
| 180 | 10.0k |     actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; | 
| 181 |  |  | 
| 182 | 10.0k |     if (iv != NULL) { | 
| 183 | 9.07k |         unsigned char temp[CHACHA_CTR_SIZE] = { 0 }; | 
| 184 |  |  | 
| 185 |  |         /* pad on the left */ | 
| 186 | 9.07k |         if (actx->nonce_len <= CHACHA_CTR_SIZE) | 
| 187 | 9.07k |             memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv, | 
| 188 | 9.07k |                    actx->nonce_len); | 
| 189 |  |  | 
| 190 | 9.07k |         chacha_init_key(ctx, inkey, temp, enc); | 
| 191 |  |  | 
| 192 | 9.07k |         actx->nonce[0] = actx->key.counter[1]; | 
| 193 | 9.07k |         actx->nonce[1] = actx->key.counter[2]; | 
| 194 | 9.07k |         actx->nonce[2] = actx->key.counter[3]; | 
| 195 | 9.07k |     } else { | 
| 196 | 926 |         chacha_init_key(ctx, inkey, NULL, enc); | 
| 197 | 926 |     } | 
| 198 |  |  | 
| 199 | 10.0k |     return 1; | 
| 200 | 10.9k | } | 
| 201 |  |  | 
| 202 |  | #  if !defined(OPENSSL_SMALL_FOOTPRINT) | 
| 203 |  |  | 
| 204 |  | #   if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \ | 
| 205 |  |                                  defined(_M_AMD64) || defined(_M_X64)) | 
| 206 |  | #    define XOR128_HELPERS | 
| 207 |  | void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len); | 
| 208 |  | void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len); | 
| 209 |  | static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 }; | 
| 210 |  | #   else | 
| 211 |  | static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 }; | 
| 212 |  | #   endif | 
| 213 |  |  | 
| 214 |  | static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | 
| 215 |  |                                         const unsigned char *in, size_t len) | 
| 216 |  | { | 
| 217 |  |     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); | 
| 218 |  |     size_t tail, tohash_len, buf_len, plen = actx->tls_payload_length; | 
| 219 |  |     unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32]; | 
| 220 |  |  | 
| 221 |  |     if (len != plen + POLY1305_BLOCK_SIZE) | 
| 222 |  |         return -1; | 
| 223 |  |  | 
| 224 |  |     buf = storage + ((0 - (size_t)storage) & 15);   /* align */ | 
| 225 |  |     ctr = buf + CHACHA_BLK_SIZE; | 
| 226 |  |     tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE; | 
| 227 |  |  | 
| 228 |  | #   ifdef XOR128_HELPERS | 
| 229 |  |     if (plen <= 3 * CHACHA_BLK_SIZE) { | 
| 230 |  |         actx->key.counter[0] = 0; | 
| 231 |  |         buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE); | 
| 232 |  |         ChaCha20_ctr32(buf, zero, buf_len, actx->key.key.d, | 
| 233 |  |                        actx->key.counter); | 
| 234 |  |         Poly1305_Init(POLY1305_ctx(actx), buf); | 
| 235 |  |         actx->key.partial_len = 0; | 
| 236 |  |         memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE); | 
| 237 |  |         tohash_len = POLY1305_BLOCK_SIZE; | 
| 238 |  |         actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; | 
| 239 |  |         actx->len.text = plen; | 
| 240 |  |  | 
| 241 |  |         if (plen) { | 
| 242 |  |             if (ctx->encrypt) | 
| 243 |  |                 ctr = xor128_encrypt_n_pad(out, in, ctr, plen); | 
| 244 |  |             else | 
| 245 |  |                 ctr = xor128_decrypt_n_pad(out, in, ctr, plen); | 
| 246 |  |  | 
| 247 |  |             in += plen; | 
| 248 |  |             out += plen; | 
| 249 |  |             tohash_len = (size_t)(ctr - tohash); | 
| 250 |  |         } | 
| 251 |  |     } | 
| 252 |  | #   else | 
| 253 |  |     if (plen <= CHACHA_BLK_SIZE) { | 
| 254 |  |         size_t i; | 
| 255 |  |  | 
| 256 |  |         actx->key.counter[0] = 0; | 
| 257 |  |         ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE), | 
| 258 |  |                        actx->key.key.d, actx->key.counter); | 
| 259 |  |         Poly1305_Init(POLY1305_ctx(actx), buf); | 
| 260 |  |         actx->key.partial_len = 0; | 
| 261 |  |         memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE); | 
| 262 |  |         tohash_len = POLY1305_BLOCK_SIZE; | 
| 263 |  |         actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; | 
| 264 |  |         actx->len.text = plen; | 
| 265 |  |  | 
| 266 |  |         if (ctx->encrypt) { | 
| 267 |  |             for (i = 0; i < plen; i++) { | 
| 268 |  |                 out[i] = ctr[i] ^= in[i]; | 
| 269 |  |             } | 
| 270 |  |         } else { | 
| 271 |  |             for (i = 0; i < plen; i++) { | 
| 272 |  |                 unsigned char c = in[i]; | 
| 273 |  |                 out[i] = ctr[i] ^ c; | 
| 274 |  |                 ctr[i] = c; | 
| 275 |  |             } | 
| 276 |  |         } | 
| 277 |  |  | 
| 278 |  |         in += i; | 
| 279 |  |         out += i; | 
| 280 |  |  | 
| 281 |  |         tail = (0 - i) & (POLY1305_BLOCK_SIZE - 1); | 
| 282 |  |         memset(ctr + i, 0, tail); | 
| 283 |  |         ctr += i + tail; | 
| 284 |  |         tohash_len += i + tail; | 
| 285 |  |     } | 
| 286 |  | #   endif | 
| 287 |  |     else { | 
| 288 |  |         actx->key.counter[0] = 0; | 
| 289 |  |         ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE), | 
| 290 |  |                        actx->key.key.d, actx->key.counter); | 
| 291 |  |         Poly1305_Init(POLY1305_ctx(actx), buf); | 
| 292 |  |         actx->key.counter[0] = 1; | 
| 293 |  |         actx->key.partial_len = 0; | 
| 294 |  |         Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad, POLY1305_BLOCK_SIZE); | 
| 295 |  |         tohash = ctr; | 
| 296 |  |         tohash_len = 0; | 
| 297 |  |         actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; | 
| 298 |  |         actx->len.text = plen; | 
| 299 |  |  | 
| 300 |  |         if (ctx->encrypt) { | 
| 301 |  |             ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter); | 
| 302 |  |             Poly1305_Update(POLY1305_ctx(actx), out, plen); | 
| 303 |  |         } else { | 
| 304 |  |             Poly1305_Update(POLY1305_ctx(actx), in, plen); | 
| 305 |  |             ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter); | 
| 306 |  |         } | 
| 307 |  |  | 
| 308 |  |         in += plen; | 
| 309 |  |         out += plen; | 
| 310 |  |         tail = (0 - plen) & (POLY1305_BLOCK_SIZE - 1); | 
| 311 |  |         Poly1305_Update(POLY1305_ctx(actx), zero, tail); | 
| 312 |  |     } | 
| 313 |  |  | 
| 314 |  |     { | 
| 315 |  |         DECLARE_IS_ENDIAN; | 
| 316 |  |  | 
| 317 |  |         if (IS_LITTLE_ENDIAN) { | 
| 318 |  |             memcpy(ctr, (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE); | 
| 319 |  |         } else { | 
| 320 |  |             ctr[0]  = (unsigned char)(actx->len.aad); | 
| 321 |  |             ctr[1]  = (unsigned char)(actx->len.aad>>8); | 
| 322 |  |             ctr[2]  = (unsigned char)(actx->len.aad>>16); | 
| 323 |  |             ctr[3]  = (unsigned char)(actx->len.aad>>24); | 
| 324 |  |             ctr[4]  = (unsigned char)(actx->len.aad>>32); | 
| 325 |  |             ctr[5]  = (unsigned char)(actx->len.aad>>40); | 
| 326 |  |             ctr[6]  = (unsigned char)(actx->len.aad>>48); | 
| 327 |  |             ctr[7]  = (unsigned char)(actx->len.aad>>56); | 
| 328 |  |  | 
| 329 |  |             ctr[8]  = (unsigned char)(actx->len.text); | 
| 330 |  |             ctr[9]  = (unsigned char)(actx->len.text>>8); | 
| 331 |  |             ctr[10] = (unsigned char)(actx->len.text>>16); | 
| 332 |  |             ctr[11] = (unsigned char)(actx->len.text>>24); | 
| 333 |  |             ctr[12] = (unsigned char)(actx->len.text>>32); | 
| 334 |  |             ctr[13] = (unsigned char)(actx->len.text>>40); | 
| 335 |  |             ctr[14] = (unsigned char)(actx->len.text>>48); | 
| 336 |  |             ctr[15] = (unsigned char)(actx->len.text>>56); | 
| 337 |  |         } | 
| 338 |  |         tohash_len += POLY1305_BLOCK_SIZE; | 
| 339 |  |     } | 
| 340 |  |  | 
| 341 |  |     Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len); | 
| 342 |  |     OPENSSL_cleanse(buf, buf_len); | 
| 343 |  |     Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag | 
| 344 |  |                                                     : tohash); | 
| 345 |  |  | 
| 346 |  |     actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; | 
| 347 |  |  | 
| 348 |  |     if (ctx->encrypt) { | 
| 349 |  |         memcpy(out, actx->tag, POLY1305_BLOCK_SIZE); | 
| 350 |  |     } else { | 
| 351 |  |         if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) { | 
| 352 |  |             memset(out - (len - POLY1305_BLOCK_SIZE), 0, | 
| 353 |  |                    len - POLY1305_BLOCK_SIZE); | 
| 354 |  |             return -1; | 
| 355 |  |         } | 
| 356 |  |     } | 
| 357 |  |  | 
| 358 |  |     return len; | 
| 359 |  | } | 
| 360 |  | #  else | 
| 361 |  | static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 }; | 
| 362 |  | #  endif | 
| 363 |  |  | 
| 364 |  | static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | 
| 365 |  |                                     const unsigned char *in, size_t len) | 
| 366 |  | { | 
| 367 |  |     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); | 
| 368 |  |     size_t rem, plen = actx->tls_payload_length; | 
| 369 |  |  | 
| 370 |  |     if (!actx->mac_inited) { | 
| 371 |  | #  if !defined(OPENSSL_SMALL_FOOTPRINT) | 
| 372 |  |         if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL) | 
| 373 |  |             return chacha20_poly1305_tls_cipher(ctx, out, in, len); | 
| 374 |  | #  endif | 
| 375 |  |         actx->key.counter[0] = 0; | 
| 376 |  |         ChaCha20_ctr32(actx->key.buf, zero, CHACHA_BLK_SIZE, | 
| 377 |  |                        actx->key.key.d, actx->key.counter); | 
| 378 |  |         Poly1305_Init(POLY1305_ctx(actx), actx->key.buf); | 
| 379 |  |         actx->key.counter[0] = 1; | 
| 380 |  |         actx->key.partial_len = 0; | 
| 381 |  |         actx->len.aad = actx->len.text = 0; | 
| 382 |  |         actx->mac_inited = 1; | 
| 383 |  |         if (plen != NO_TLS_PAYLOAD_LENGTH) { | 
| 384 |  |             Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad, | 
| 385 |  |                             EVP_AEAD_TLS1_AAD_LEN); | 
| 386 |  |             actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; | 
| 387 |  |             actx->aad = 1; | 
| 388 |  |         } | 
| 389 |  |     } | 
| 390 |  |  | 
| 391 |  |     if (in) {                                   /* aad or text */ | 
| 392 |  |         if (out == NULL) {                      /* aad */ | 
| 393 |  |             Poly1305_Update(POLY1305_ctx(actx), in, len); | 
| 394 |  |             actx->len.aad += len; | 
| 395 |  |             actx->aad = 1; | 
| 396 |  |             return len; | 
| 397 |  |         } else {                                /* plain- or ciphertext */ | 
| 398 |  |             if (actx->aad) {                    /* wrap up aad */ | 
| 399 |  |                 if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE)) | 
| 400 |  |                     Poly1305_Update(POLY1305_ctx(actx), zero, | 
| 401 |  |                                     POLY1305_BLOCK_SIZE - rem); | 
| 402 |  |                 actx->aad = 0; | 
| 403 |  |             } | 
| 404 |  |  | 
| 405 |  |             actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; | 
| 406 |  |             if (plen == NO_TLS_PAYLOAD_LENGTH) | 
| 407 |  |                 plen = len; | 
| 408 |  |             else if (len != plen + POLY1305_BLOCK_SIZE) | 
| 409 |  |                 return -1; | 
| 410 |  |  | 
| 411 |  |             if (ctx->encrypt) {                 /* plaintext */ | 
| 412 |  |                 chacha_cipher(ctx, out, in, plen); | 
| 413 |  |                 Poly1305_Update(POLY1305_ctx(actx), out, plen); | 
| 414 |  |                 in += plen; | 
| 415 |  |                 out += plen; | 
| 416 |  |                 actx->len.text += plen; | 
| 417 |  |             } else {                            /* ciphertext */ | 
| 418 |  |                 Poly1305_Update(POLY1305_ctx(actx), in, plen); | 
| 419 |  |                 chacha_cipher(ctx, out, in, plen); | 
| 420 |  |                 in += plen; | 
| 421 |  |                 out += plen; | 
| 422 |  |                 actx->len.text += plen; | 
| 423 |  |             } | 
| 424 |  |         } | 
| 425 |  |     } | 
| 426 |  |     if (in == NULL                              /* explicit final */ | 
| 427 |  |         || plen != len) {                       /* or tls mode */ | 
| 428 |  |         DECLARE_IS_ENDIAN; | 
| 429 |  |         unsigned char temp[POLY1305_BLOCK_SIZE]; | 
| 430 |  |  | 
| 431 |  |         if (actx->aad) {                        /* wrap up aad */ | 
| 432 |  |             if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE)) | 
| 433 |  |                 Poly1305_Update(POLY1305_ctx(actx), zero, | 
| 434 |  |                                 POLY1305_BLOCK_SIZE - rem); | 
| 435 |  |             actx->aad = 0; | 
| 436 |  |         } | 
| 437 |  |  | 
| 438 |  |         if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE)) | 
| 439 |  |             Poly1305_Update(POLY1305_ctx(actx), zero, | 
| 440 |  |                             POLY1305_BLOCK_SIZE - rem); | 
| 441 |  |  | 
| 442 |  |         if (IS_LITTLE_ENDIAN) { | 
| 443 |  |             Poly1305_Update(POLY1305_ctx(actx), | 
| 444 |  |                             (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE); | 
| 445 |  |         } else { | 
| 446 |  |             temp[0]  = (unsigned char)(actx->len.aad); | 
| 447 |  |             temp[1]  = (unsigned char)(actx->len.aad>>8); | 
| 448 |  |             temp[2]  = (unsigned char)(actx->len.aad>>16); | 
| 449 |  |             temp[3]  = (unsigned char)(actx->len.aad>>24); | 
| 450 |  |             temp[4]  = (unsigned char)(actx->len.aad>>32); | 
| 451 |  |             temp[5]  = (unsigned char)(actx->len.aad>>40); | 
| 452 |  |             temp[6]  = (unsigned char)(actx->len.aad>>48); | 
| 453 |  |             temp[7]  = (unsigned char)(actx->len.aad>>56); | 
| 454 |  |  | 
| 455 |  |             temp[8]  = (unsigned char)(actx->len.text); | 
| 456 |  |             temp[9]  = (unsigned char)(actx->len.text>>8); | 
| 457 |  |             temp[10] = (unsigned char)(actx->len.text>>16); | 
| 458 |  |             temp[11] = (unsigned char)(actx->len.text>>24); | 
| 459 |  |             temp[12] = (unsigned char)(actx->len.text>>32); | 
| 460 |  |             temp[13] = (unsigned char)(actx->len.text>>40); | 
| 461 |  |             temp[14] = (unsigned char)(actx->len.text>>48); | 
| 462 |  |             temp[15] = (unsigned char)(actx->len.text>>56); | 
| 463 |  |  | 
| 464 |  |             Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE); | 
| 465 |  |         } | 
| 466 |  |         Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag | 
| 467 |  |                                                         : temp); | 
| 468 |  |         actx->mac_inited = 0; | 
| 469 |  |  | 
| 470 |  |         if (in != NULL && len != plen) {        /* tls mode */ | 
| 471 |  |             if (ctx->encrypt) { | 
| 472 |  |                 memcpy(out, actx->tag, POLY1305_BLOCK_SIZE); | 
| 473 |  |             } else { | 
| 474 |  |                 if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) { | 
| 475 |  |                     memset(out - plen, 0, plen); | 
| 476 |  |                     return -1; | 
| 477 |  |                 } | 
| 478 |  |             } | 
| 479 |  |         } | 
| 480 |  |         else if (!ctx->encrypt) { | 
| 481 |  |             if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len)) | 
| 482 |  |                 return -1; | 
| 483 |  |         } | 
| 484 |  |     } | 
| 485 |  |     return len; | 
| 486 |  | } | 
| 487 |  |  | 
| 488 |  | static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx) | 
| 489 | 947 | { | 
| 490 | 947 |     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); | 
| 491 | 947 |     if (actx) | 
| 492 | 947 |         OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size()); | 
| 493 | 947 |     return 1; | 
| 494 | 947 | } | 
| 495 |  |  | 
| 496 |  | static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, | 
| 497 |  |                                   void *ptr) | 
| 498 | 20.8k | { | 
| 499 | 20.8k |     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); | 
| 500 |  |  | 
| 501 | 20.8k |     switch(type) { | 
| 502 | 947 |     case EVP_CTRL_INIT: | 
| 503 | 947 |         if (actx == NULL) | 
| 504 | 947 |             actx = ctx->cipher_data | 
| 505 | 947 |                  = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size()); | 
| 506 | 947 |         if (actx == NULL) { | 
| 507 | 0 |             ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | 
| 508 | 0 |             return 0; | 
| 509 | 0 |         } | 
| 510 | 947 |         actx->len.aad = 0; | 
| 511 | 947 |         actx->len.text = 0; | 
| 512 | 947 |         actx->aad = 0; | 
| 513 | 947 |         actx->mac_inited = 0; | 
| 514 | 947 |         actx->tag_len = 0; | 
| 515 | 947 |         actx->nonce_len = 12; | 
| 516 | 947 |         actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; | 
| 517 | 947 |         memset(actx->tls_aad, 0, POLY1305_BLOCK_SIZE); | 
| 518 | 947 |         return 1; | 
| 519 |  |  | 
| 520 | 0 |     case EVP_CTRL_COPY: | 
| 521 | 0 |         if (actx) { | 
| 522 | 0 |             EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr; | 
| 523 |  | 
 | 
| 524 | 0 |             dst->cipher_data = | 
| 525 | 0 |                    OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size()); | 
| 526 | 0 |             if (dst->cipher_data == NULL) { | 
| 527 | 0 |                 ERR_raise(ERR_LIB_EVP, EVP_R_COPY_ERROR); | 
| 528 | 0 |                 return 0; | 
| 529 | 0 |             } | 
| 530 | 0 |         } | 
| 531 | 0 |         return 1; | 
| 532 |  |  | 
| 533 | 9.85k |     case EVP_CTRL_GET_IVLEN: | 
| 534 | 9.85k |         *(int *)ptr = actx->nonce_len; | 
| 535 | 9.85k |         return 1; | 
| 536 |  |  | 
| 537 | 926 |     case EVP_CTRL_AEAD_SET_IVLEN: | 
| 538 | 926 |         if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN) | 
| 539 | 0 |             return 0; | 
| 540 | 926 |         actx->nonce_len = arg; | 
| 541 | 926 |         return 1; | 
| 542 |  |  | 
| 543 | 0 |     case EVP_CTRL_AEAD_SET_IV_FIXED: | 
| 544 | 0 |         if (arg != 12) | 
| 545 | 0 |             return 0; | 
| 546 | 0 |         actx->nonce[0] = actx->key.counter[1] | 
| 547 | 0 |                        = CHACHA_U8TOU32((unsigned char *)ptr); | 
| 548 | 0 |         actx->nonce[1] = actx->key.counter[2] | 
| 549 | 0 |                        = CHACHA_U8TOU32((unsigned char *)ptr+4); | 
| 550 | 0 |         actx->nonce[2] = actx->key.counter[3] | 
| 551 | 0 |                        = CHACHA_U8TOU32((unsigned char *)ptr+8); | 
| 552 | 0 |         return 1; | 
| 553 |  |  | 
| 554 | 7.77k |     case EVP_CTRL_AEAD_SET_TAG: | 
| 555 | 7.77k |         if (arg <= 0 || arg > POLY1305_BLOCK_SIZE) | 
| 556 | 0 |             return 0; | 
| 557 | 7.77k |         if (ptr != NULL) { | 
| 558 | 7.77k |             memcpy(actx->tag, ptr, arg); | 
| 559 | 7.77k |             actx->tag_len = arg; | 
| 560 | 7.77k |         } | 
| 561 | 7.77k |         return 1; | 
| 562 |  |  | 
| 563 | 1.28k |     case EVP_CTRL_AEAD_GET_TAG: | 
| 564 | 1.28k |         if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt) | 
| 565 | 0 |             return 0; | 
| 566 | 1.28k |         memcpy(ptr, actx->tag, arg); | 
| 567 | 1.28k |         return 1; | 
| 568 |  |  | 
| 569 | 18 |     case EVP_CTRL_AEAD_TLS1_AAD: | 
| 570 | 18 |         if (arg != EVP_AEAD_TLS1_AAD_LEN) | 
| 571 | 0 |             return 0; | 
| 572 | 18 |         { | 
| 573 | 18 |             unsigned int len; | 
| 574 | 18 |             unsigned char *aad = ptr; | 
| 575 |  |  | 
| 576 | 18 |             memcpy(actx->tls_aad, ptr, EVP_AEAD_TLS1_AAD_LEN); | 
| 577 | 18 |             len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 | | 
| 578 | 18 |                   aad[EVP_AEAD_TLS1_AAD_LEN - 1]; | 
| 579 | 18 |             aad = actx->tls_aad; | 
| 580 | 18 |             if (!ctx->encrypt) { | 
| 581 | 18 |                 if (len < POLY1305_BLOCK_SIZE) | 
| 582 | 3 |                     return 0; | 
| 583 | 15 |                 len -= POLY1305_BLOCK_SIZE;     /* discount attached tag */ | 
| 584 | 15 |                 aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8); | 
| 585 | 15 |                 aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len; | 
| 586 | 15 |             } | 
| 587 | 15 |             actx->tls_payload_length = len; | 
| 588 |  |  | 
| 589 |  |             /* | 
| 590 |  |              * merge record sequence number as per RFC7905 | 
| 591 |  |              */ | 
| 592 | 15 |             actx->key.counter[1] = actx->nonce[0]; | 
| 593 | 15 |             actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad); | 
| 594 | 15 |             actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4); | 
| 595 | 15 |             actx->mac_inited = 0; | 
| 596 |  |  | 
| 597 | 15 |             return POLY1305_BLOCK_SIZE;         /* tag length */ | 
| 598 | 18 |         } | 
| 599 |  |  | 
| 600 | 0 |     case EVP_CTRL_AEAD_SET_MAC_KEY: | 
| 601 |  |         /* no-op */ | 
| 602 | 0 |         return 1; | 
| 603 |  |  | 
| 604 | 0 |     default: | 
| 605 | 0 |         return -1; | 
| 606 | 20.8k |     } | 
| 607 | 20.8k | } | 
| 608 |  |  | 
| 609 |  | static EVP_CIPHER chacha20_poly1305 = { | 
| 610 |  |     NID_chacha20_poly1305, | 
| 611 |  |     1,                  /* block_size */ | 
| 612 |  |     CHACHA_KEY_SIZE,    /* key_len */ | 
| 613 |  |     12,                 /* iv_len, 96-bit nonce in the context */ | 
| 614 |  |     EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV | | 
| 615 |  |     EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | | 
| 616 |  |     EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER | | 
| 617 |  |     EVP_CIPH_CUSTOM_IV_LENGTH, | 
| 618 |  |     EVP_ORIG_GLOBAL, | 
| 619 |  |     chacha20_poly1305_init_key, | 
| 620 |  |     chacha20_poly1305_cipher, | 
| 621 |  |     chacha20_poly1305_cleanup, | 
| 622 |  |     0,          /* 0 moves context-specific structure allocation to ctrl */ | 
| 623 |  |     NULL,       /* set_asn1_parameters */ | 
| 624 |  |     NULL,       /* get_asn1_parameters */ | 
| 625 |  |     chacha20_poly1305_ctrl, | 
| 626 |  |     NULL        /* app_data */ | 
| 627 |  | }; | 
| 628 |  |  | 
| 629 |  | const EVP_CIPHER *EVP_chacha20_poly1305(void) | 
| 630 | 37 | { | 
| 631 | 37 |     return(&chacha20_poly1305); | 
| 632 | 37 | } | 
| 633 |  | # endif | 
| 634 |  | #endif |