[331] | 1 | /*
|
---|
| 2 | * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the OpenSSL license (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 |
|
---|
| 13 | #ifndef OPENSSL_NO_CHACHA
|
---|
| 14 |
|
---|
| 15 | # include <openssl/evp.h>
|
---|
| 16 | # include <openssl/objects.h>
|
---|
| 17 | # include "evp_locl.h"
|
---|
| 18 | # include "internal/evp_int.h"
|
---|
| 19 | # include "internal/chacha.h"
|
---|
| 20 |
|
---|
| 21 | typedef struct {
|
---|
| 22 | union {
|
---|
| 23 | double align; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
|
---|
| 24 | unsigned int d[CHACHA_KEY_SIZE / 4];
|
---|
| 25 | } key;
|
---|
| 26 | unsigned int counter[CHACHA_CTR_SIZE / 4];
|
---|
| 27 | unsigned char buf[CHACHA_BLK_SIZE];
|
---|
| 28 | unsigned int partial_len;
|
---|
| 29 | } EVP_CHACHA_KEY;
|
---|
| 30 |
|
---|
| 31 | #define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
|
---|
| 32 |
|
---|
| 33 | static int chacha_init_key(EVP_CIPHER_CTX *ctx,
|
---|
| 34 | const unsigned char user_key[CHACHA_KEY_SIZE],
|
---|
| 35 | const unsigned char iv[CHACHA_CTR_SIZE], int enc)
|
---|
| 36 | {
|
---|
| 37 | EVP_CHACHA_KEY *key = data(ctx);
|
---|
| 38 | unsigned int i;
|
---|
| 39 |
|
---|
| 40 | if (user_key)
|
---|
| 41 | for (i = 0; i < CHACHA_KEY_SIZE; i+=4) {
|
---|
| 42 | key->key.d[i/4] = CHACHA_U8TOU32(user_key+i);
|
---|
| 43 | }
|
---|
| 44 |
|
---|
| 45 | if (iv)
|
---|
| 46 | for (i = 0; i < CHACHA_CTR_SIZE; i+=4) {
|
---|
| 47 | key->counter[i/4] = CHACHA_U8TOU32(iv+i);
|
---|
| 48 | }
|
---|
| 49 |
|
---|
| 50 | key->partial_len = 0;
|
---|
| 51 |
|
---|
| 52 | return 1;
|
---|
| 53 | }
|
---|
| 54 |
|
---|
| 55 | static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out,
|
---|
| 56 | const unsigned char *inp, size_t len)
|
---|
| 57 | {
|
---|
| 58 | EVP_CHACHA_KEY *key = data(ctx);
|
---|
| 59 | unsigned int n, rem, ctr32;
|
---|
| 60 |
|
---|
| 61 | if ((n = key->partial_len)) {
|
---|
| 62 | while (len && n < CHACHA_BLK_SIZE) {
|
---|
| 63 | *out++ = *inp++ ^ key->buf[n++];
|
---|
| 64 | len--;
|
---|
| 65 | }
|
---|
| 66 | key->partial_len = n;
|
---|
| 67 |
|
---|
| 68 | if (len == 0)
|
---|
| 69 | return 1;
|
---|
| 70 |
|
---|
| 71 | if (n == CHACHA_BLK_SIZE) {
|
---|
| 72 | key->partial_len = 0;
|
---|
| 73 | key->counter[0]++;
|
---|
| 74 | if (key->counter[0] == 0)
|
---|
| 75 | key->counter[1]++;
|
---|
| 76 | }
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | rem = (unsigned int)(len % CHACHA_BLK_SIZE);
|
---|
| 80 | len -= rem;
|
---|
| 81 | ctr32 = key->counter[0];
|
---|
| 82 | while (len >= CHACHA_BLK_SIZE) {
|
---|
| 83 | size_t blocks = len / CHACHA_BLK_SIZE;
|
---|
| 84 | /*
|
---|
| 85 | * 1<<28 is just a not-so-small yet not-so-large number...
|
---|
| 86 | * Below condition is practically never met, but it has to
|
---|
| 87 | * be checked for code correctness.
|
---|
| 88 | */
|
---|
| 89 | if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U<<28))
|
---|
| 90 | blocks = (1U<<28);
|
---|
| 91 |
|
---|
| 92 | /*
|
---|
| 93 | * As ChaCha20_ctr32 operates on 32-bit counter, caller
|
---|
| 94 | * has to handle overflow. 'if' below detects the
|
---|
| 95 | * overflow, which is then handled by limiting the
|
---|
| 96 | * amount of blocks to the exact overflow point...
|
---|
| 97 | */
|
---|
| 98 | ctr32 += (unsigned int)blocks;
|
---|
| 99 | if (ctr32 < blocks) {
|
---|
| 100 | blocks -= ctr32;
|
---|
| 101 | ctr32 = 0;
|
---|
| 102 | }
|
---|
| 103 | blocks *= CHACHA_BLK_SIZE;
|
---|
| 104 | ChaCha20_ctr32(out, inp, blocks, key->key.d, key->counter);
|
---|
| 105 | len -= blocks;
|
---|
| 106 | inp += blocks;
|
---|
| 107 | out += blocks;
|
---|
| 108 |
|
---|
| 109 | key->counter[0] = ctr32;
|
---|
| 110 | if (ctr32 == 0) key->counter[1]++;
|
---|
| 111 | }
|
---|
| 112 |
|
---|
| 113 | if (rem) {
|
---|
| 114 | memset(key->buf, 0, sizeof(key->buf));
|
---|
| 115 | ChaCha20_ctr32(key->buf, key->buf, CHACHA_BLK_SIZE,
|
---|
| 116 | key->key.d, key->counter);
|
---|
| 117 | for (n = 0; n < rem; n++)
|
---|
| 118 | out[n] = inp[n] ^ key->buf[n];
|
---|
| 119 | key->partial_len = rem;
|
---|
| 120 | }
|
---|
| 121 |
|
---|
| 122 | return 1;
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | static const EVP_CIPHER chacha20 = {
|
---|
| 126 | NID_chacha20,
|
---|
| 127 | 1, /* block_size */
|
---|
| 128 | CHACHA_KEY_SIZE, /* key_len */
|
---|
| 129 | CHACHA_CTR_SIZE, /* iv_len, 128-bit counter in the context */
|
---|
| 130 | EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT,
|
---|
| 131 | chacha_init_key,
|
---|
| 132 | chacha_cipher,
|
---|
| 133 | NULL,
|
---|
| 134 | sizeof(EVP_CHACHA_KEY),
|
---|
| 135 | NULL,
|
---|
| 136 | NULL,
|
---|
| 137 | NULL,
|
---|
| 138 | NULL
|
---|
| 139 | };
|
---|
| 140 |
|
---|
| 141 | const EVP_CIPHER *EVP_chacha20(void)
|
---|
| 142 | {
|
---|
| 143 | return (&chacha20);
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | # ifndef OPENSSL_NO_POLY1305
|
---|
| 147 | # include "internal/poly1305.h"
|
---|
| 148 |
|
---|
| 149 | typedef struct {
|
---|
| 150 | EVP_CHACHA_KEY key;
|
---|
| 151 | unsigned int nonce[12/4];
|
---|
| 152 | unsigned char tag[POLY1305_BLOCK_SIZE];
|
---|
| 153 | struct { uint64_t aad, text; } len;
|
---|
| 154 | int aad, mac_inited, tag_len, nonce_len;
|
---|
| 155 | size_t tls_payload_length;
|
---|
| 156 | } EVP_CHACHA_AEAD_CTX;
|
---|
| 157 |
|
---|
| 158 | # define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
|
---|
| 159 | # define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
|
---|
| 160 | # define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
|
---|
| 161 |
|
---|
| 162 | static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
|
---|
| 163 | const unsigned char *inkey,
|
---|
| 164 | const unsigned char *iv, int enc)
|
---|
| 165 | {
|
---|
| 166 | EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
|
---|
| 167 |
|
---|
| 168 | if (!inkey && !iv)
|
---|
| 169 | return 1;
|
---|
| 170 |
|
---|
| 171 | actx->len.aad = 0;
|
---|
| 172 | actx->len.text = 0;
|
---|
| 173 | actx->aad = 0;
|
---|
| 174 | actx->mac_inited = 0;
|
---|
| 175 | actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
|
---|
| 176 |
|
---|
| 177 | if (iv != NULL) {
|
---|
| 178 | unsigned char temp[CHACHA_CTR_SIZE] = { 0 };
|
---|
| 179 |
|
---|
| 180 | /* pad on the left */
|
---|
| 181 | if (actx->nonce_len <= CHACHA_CTR_SIZE)
|
---|
| 182 | memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv, actx->nonce_len);
|
---|
| 183 |
|
---|
| 184 | chacha_init_key(ctx, inkey, temp, enc);
|
---|
| 185 |
|
---|
| 186 | actx->nonce[0] = actx->key.counter[1];
|
---|
| 187 | actx->nonce[1] = actx->key.counter[2];
|
---|
| 188 | actx->nonce[2] = actx->key.counter[3];
|
---|
| 189 | } else {
|
---|
| 190 | chacha_init_key(ctx, inkey, NULL, enc);
|
---|
| 191 | }
|
---|
| 192 |
|
---|
| 193 | return 1;
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
---|
| 197 | const unsigned char *in, size_t len)
|
---|
| 198 | {
|
---|
| 199 | EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
|
---|
| 200 | size_t rem, plen = actx->tls_payload_length;
|
---|
| 201 | static const unsigned char zero[POLY1305_BLOCK_SIZE] = { 0 };
|
---|
| 202 |
|
---|
| 203 | if (!actx->mac_inited) {
|
---|
| 204 | actx->key.counter[0] = 0;
|
---|
| 205 | memset(actx->key.buf, 0, sizeof(actx->key.buf));
|
---|
| 206 | ChaCha20_ctr32(actx->key.buf, actx->key.buf, CHACHA_BLK_SIZE,
|
---|
| 207 | actx->key.key.d, actx->key.counter);
|
---|
| 208 | Poly1305_Init(POLY1305_ctx(actx), actx->key.buf);
|
---|
| 209 | actx->key.counter[0] = 1;
|
---|
| 210 | actx->key.partial_len = 0;
|
---|
| 211 | actx->len.aad = actx->len.text = 0;
|
---|
| 212 | actx->mac_inited = 1;
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 | if (in) { /* aad or text */
|
---|
| 216 | if (out == NULL) { /* aad */
|
---|
| 217 | Poly1305_Update(POLY1305_ctx(actx), in, len);
|
---|
| 218 | actx->len.aad += len;
|
---|
| 219 | actx->aad = 1;
|
---|
| 220 | return len;
|
---|
| 221 | } else { /* plain- or ciphertext */
|
---|
| 222 | if (actx->aad) { /* wrap up aad */
|
---|
| 223 | if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
|
---|
| 224 | Poly1305_Update(POLY1305_ctx(actx), zero,
|
---|
| 225 | POLY1305_BLOCK_SIZE - rem);
|
---|
| 226 | actx->aad = 0;
|
---|
| 227 | }
|
---|
| 228 |
|
---|
| 229 | actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
|
---|
| 230 | if (plen == NO_TLS_PAYLOAD_LENGTH)
|
---|
| 231 | plen = len;
|
---|
| 232 | else if (len != plen + POLY1305_BLOCK_SIZE)
|
---|
| 233 | return -1;
|
---|
| 234 |
|
---|
| 235 | if (ctx->encrypt) { /* plaintext */
|
---|
| 236 | chacha_cipher(ctx, out, in, plen);
|
---|
| 237 | Poly1305_Update(POLY1305_ctx(actx), out, plen);
|
---|
| 238 | in += plen;
|
---|
| 239 | out += plen;
|
---|
| 240 | actx->len.text += plen;
|
---|
| 241 | } else { /* ciphertext */
|
---|
| 242 | Poly1305_Update(POLY1305_ctx(actx), in, plen);
|
---|
| 243 | chacha_cipher(ctx, out, in, plen);
|
---|
| 244 | in += plen;
|
---|
| 245 | out += plen;
|
---|
| 246 | actx->len.text += plen;
|
---|
| 247 | }
|
---|
| 248 | }
|
---|
| 249 | }
|
---|
| 250 | if (in == NULL /* explicit final */
|
---|
| 251 | || plen != len) { /* or tls mode */
|
---|
| 252 | const union {
|
---|
| 253 | long one;
|
---|
| 254 | char little;
|
---|
| 255 | } is_endian = { 1 };
|
---|
| 256 | unsigned char temp[POLY1305_BLOCK_SIZE];
|
---|
| 257 |
|
---|
| 258 | if (actx->aad) { /* wrap up aad */
|
---|
| 259 | if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
|
---|
| 260 | Poly1305_Update(POLY1305_ctx(actx), zero,
|
---|
| 261 | POLY1305_BLOCK_SIZE - rem);
|
---|
| 262 | actx->aad = 0;
|
---|
| 263 | }
|
---|
| 264 |
|
---|
| 265 | if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
|
---|
| 266 | Poly1305_Update(POLY1305_ctx(actx), zero,
|
---|
| 267 | POLY1305_BLOCK_SIZE - rem);
|
---|
| 268 |
|
---|
| 269 | if (is_endian.little) {
|
---|
| 270 | Poly1305_Update(POLY1305_ctx(actx),
|
---|
| 271 | (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
|
---|
| 272 | } else {
|
---|
| 273 | temp[0] = (unsigned char)(actx->len.aad);
|
---|
| 274 | temp[1] = (unsigned char)(actx->len.aad>>8);
|
---|
| 275 | temp[2] = (unsigned char)(actx->len.aad>>16);
|
---|
| 276 | temp[3] = (unsigned char)(actx->len.aad>>24);
|
---|
| 277 | temp[4] = (unsigned char)(actx->len.aad>>32);
|
---|
| 278 | temp[5] = (unsigned char)(actx->len.aad>>40);
|
---|
| 279 | temp[6] = (unsigned char)(actx->len.aad>>48);
|
---|
| 280 | temp[7] = (unsigned char)(actx->len.aad>>56);
|
---|
| 281 |
|
---|
| 282 | temp[8] = (unsigned char)(actx->len.text);
|
---|
| 283 | temp[9] = (unsigned char)(actx->len.text>>8);
|
---|
| 284 | temp[10] = (unsigned char)(actx->len.text>>16);
|
---|
| 285 | temp[11] = (unsigned char)(actx->len.text>>24);
|
---|
| 286 | temp[12] = (unsigned char)(actx->len.text>>32);
|
---|
| 287 | temp[13] = (unsigned char)(actx->len.text>>40);
|
---|
| 288 | temp[14] = (unsigned char)(actx->len.text>>48);
|
---|
| 289 | temp[15] = (unsigned char)(actx->len.text>>56);
|
---|
| 290 |
|
---|
| 291 | Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
|
---|
| 292 | }
|
---|
| 293 | Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
|
---|
| 294 | : temp);
|
---|
| 295 | actx->mac_inited = 0;
|
---|
| 296 |
|
---|
| 297 | if (in != NULL && len != plen) { /* tls mode */
|
---|
| 298 | if (ctx->encrypt) {
|
---|
| 299 | memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
|
---|
| 300 | } else {
|
---|
| 301 | if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
|
---|
| 302 | memset(out - plen, 0, plen);
|
---|
| 303 | return -1;
|
---|
| 304 | }
|
---|
| 305 | }
|
---|
| 306 | }
|
---|
| 307 | else if (!ctx->encrypt) {
|
---|
| 308 | if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
|
---|
| 309 | return -1;
|
---|
| 310 | }
|
---|
| 311 | }
|
---|
| 312 | return len;
|
---|
| 313 | }
|
---|
| 314 |
|
---|
| 315 | static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
|
---|
| 316 | {
|
---|
| 317 | EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
|
---|
| 318 | if (actx)
|
---|
| 319 | OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size());
|
---|
| 320 | return 1;
|
---|
| 321 | }
|
---|
| 322 |
|
---|
| 323 | static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
---|
| 324 | void *ptr)
|
---|
| 325 | {
|
---|
| 326 | EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
|
---|
| 327 |
|
---|
| 328 | switch(type) {
|
---|
| 329 | case EVP_CTRL_INIT:
|
---|
| 330 | if (actx == NULL)
|
---|
| 331 | actx = ctx->cipher_data
|
---|
| 332 | = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size());
|
---|
| 333 | if (actx == NULL) {
|
---|
| 334 | EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_INITIALIZATION_ERROR);
|
---|
| 335 | return 0;
|
---|
| 336 | }
|
---|
| 337 | actx->len.aad = 0;
|
---|
| 338 | actx->len.text = 0;
|
---|
| 339 | actx->aad = 0;
|
---|
| 340 | actx->mac_inited = 0;
|
---|
| 341 | actx->tag_len = 0;
|
---|
| 342 | actx->nonce_len = 12;
|
---|
| 343 | actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
|
---|
| 344 | return 1;
|
---|
| 345 |
|
---|
| 346 | case EVP_CTRL_COPY:
|
---|
| 347 | if (actx) {
|
---|
| 348 | EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr;
|
---|
| 349 |
|
---|
| 350 | dst->cipher_data =
|
---|
| 351 | OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size());
|
---|
| 352 | if (dst->cipher_data == NULL) {
|
---|
| 353 | EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_COPY_ERROR);
|
---|
| 354 | return 0;
|
---|
| 355 | }
|
---|
| 356 | }
|
---|
| 357 | return 1;
|
---|
| 358 |
|
---|
| 359 | case EVP_CTRL_AEAD_SET_IVLEN:
|
---|
| 360 | if (arg <= 0 || arg > CHACHA_CTR_SIZE)
|
---|
| 361 | return 0;
|
---|
| 362 | actx->nonce_len = arg;
|
---|
| 363 | return 1;
|
---|
| 364 |
|
---|
| 365 | case EVP_CTRL_AEAD_SET_IV_FIXED:
|
---|
| 366 | if (arg != 12)
|
---|
| 367 | return 0;
|
---|
| 368 | actx->nonce[0] = actx->key.counter[1]
|
---|
| 369 | = CHACHA_U8TOU32((unsigned char *)ptr);
|
---|
| 370 | actx->nonce[1] = actx->key.counter[2]
|
---|
| 371 | = CHACHA_U8TOU32((unsigned char *)ptr+4);
|
---|
| 372 | actx->nonce[2] = actx->key.counter[3]
|
---|
| 373 | = CHACHA_U8TOU32((unsigned char *)ptr+8);
|
---|
| 374 | return 1;
|
---|
| 375 |
|
---|
| 376 | case EVP_CTRL_AEAD_SET_TAG:
|
---|
| 377 | if (arg <= 0 || arg > POLY1305_BLOCK_SIZE)
|
---|
| 378 | return 0;
|
---|
| 379 | if (ptr != NULL) {
|
---|
| 380 | memcpy(actx->tag, ptr, arg);
|
---|
| 381 | actx->tag_len = arg;
|
---|
| 382 | }
|
---|
| 383 | return 1;
|
---|
| 384 |
|
---|
| 385 | case EVP_CTRL_AEAD_GET_TAG:
|
---|
| 386 | if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt)
|
---|
| 387 | return 0;
|
---|
| 388 | memcpy(ptr, actx->tag, arg);
|
---|
| 389 | return 1;
|
---|
| 390 |
|
---|
| 391 | case EVP_CTRL_AEAD_TLS1_AAD:
|
---|
| 392 | if (arg != EVP_AEAD_TLS1_AAD_LEN)
|
---|
| 393 | return 0;
|
---|
| 394 | {
|
---|
| 395 | unsigned int len;
|
---|
| 396 | unsigned char *aad = ptr, temp[POLY1305_BLOCK_SIZE];
|
---|
| 397 |
|
---|
| 398 | len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 |
|
---|
| 399 | aad[EVP_AEAD_TLS1_AAD_LEN - 1];
|
---|
| 400 | if (!ctx->encrypt) {
|
---|
| 401 | if (len < POLY1305_BLOCK_SIZE)
|
---|
| 402 | return 0;
|
---|
| 403 | len -= POLY1305_BLOCK_SIZE; /* discount attached tag */
|
---|
| 404 | memcpy(temp, aad, EVP_AEAD_TLS1_AAD_LEN - 2);
|
---|
| 405 | aad = temp;
|
---|
| 406 | temp[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
|
---|
| 407 | temp[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
|
---|
| 408 | }
|
---|
| 409 | actx->tls_payload_length = len;
|
---|
| 410 |
|
---|
| 411 | /*
|
---|
| 412 | * merge record sequence number as per RFC7905
|
---|
| 413 | */
|
---|
| 414 | actx->key.counter[1] = actx->nonce[0];
|
---|
| 415 | actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad);
|
---|
| 416 | actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
|
---|
| 417 | actx->mac_inited = 0;
|
---|
| 418 | chacha20_poly1305_cipher(ctx, NULL, aad, EVP_AEAD_TLS1_AAD_LEN);
|
---|
| 419 | return POLY1305_BLOCK_SIZE; /* tag length */
|
---|
| 420 | }
|
---|
| 421 |
|
---|
| 422 | case EVP_CTRL_AEAD_SET_MAC_KEY:
|
---|
| 423 | /* no-op */
|
---|
| 424 | return 1;
|
---|
| 425 |
|
---|
| 426 | default:
|
---|
| 427 | return -1;
|
---|
| 428 | }
|
---|
| 429 | }
|
---|
| 430 |
|
---|
| 431 | static EVP_CIPHER chacha20_poly1305 = {
|
---|
| 432 | NID_chacha20_poly1305,
|
---|
| 433 | 1, /* block_size */
|
---|
| 434 | CHACHA_KEY_SIZE, /* key_len */
|
---|
| 435 | 12, /* iv_len, 96-bit nonce in the context */
|
---|
| 436 | EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
|
---|
| 437 | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
|
---|
| 438 | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER,
|
---|
| 439 | chacha20_poly1305_init_key,
|
---|
| 440 | chacha20_poly1305_cipher,
|
---|
| 441 | chacha20_poly1305_cleanup,
|
---|
| 442 | 0, /* 0 moves context-specific structure allocation to ctrl */
|
---|
| 443 | NULL, /* set_asn1_parameters */
|
---|
| 444 | NULL, /* get_asn1_parameters */
|
---|
| 445 | chacha20_poly1305_ctrl,
|
---|
| 446 | NULL /* app_data */
|
---|
| 447 | };
|
---|
| 448 |
|
---|
| 449 | const EVP_CIPHER *EVP_chacha20_poly1305(void)
|
---|
| 450 | {
|
---|
| 451 | return(&chacha20_poly1305);
|
---|
| 452 | }
|
---|
| 453 | # endif
|
---|
| 454 | #endif
|
---|