The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/opencrypto/xform_chacha20_poly1305.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2020 Netflix Inc.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <opencrypto/xform_auth.h>
   29 #include <opencrypto/xform_enc.h>
   30 
   31 #include <sodium/crypto_core_hchacha20.h>
   32 #include <sodium/crypto_onetimeauth_poly1305.h>
   33 #include <sodium/crypto_stream_chacha20.h>
   34 
   35 struct chacha20_poly1305_ctx {
   36         struct crypto_onetimeauth_poly1305_state auth;
   37         const void *key;
   38         uint32_t ic;
   39         bool ietf;
   40         char nonce[CHACHA20_POLY1305_IV_LEN];
   41 };
   42 
   43 struct xchacha20_poly1305_ctx {
   44         struct chacha20_poly1305_ctx base_ctx;  /* must be first */
   45         const void *key;
   46         char derived_key[CHACHA20_POLY1305_KEY];
   47 };
   48 
   49 static int
   50 chacha20_poly1305_setkey(void *vctx, const uint8_t *key, int len)
   51 {
   52         struct chacha20_poly1305_ctx *ctx = vctx;
   53 
   54         if (len != CHACHA20_POLY1305_KEY)
   55                 return (EINVAL);
   56 
   57         ctx->key = key;
   58         return (0);
   59 }
   60 
   61 static void
   62 chacha20_poly1305_reinit(void *vctx, const uint8_t *iv, size_t ivlen)
   63 {
   64         struct chacha20_poly1305_ctx *ctx = vctx;
   65         char block[CHACHA20_NATIVE_BLOCK_LEN];
   66 
   67         KASSERT(ivlen == 8 || ivlen == sizeof(ctx->nonce),
   68             ("%s: invalid nonce length", __func__));
   69 
   70         memcpy(ctx->nonce, iv, ivlen);
   71         ctx->ietf = (ivlen == CHACHA20_POLY1305_IV_LEN);
   72 
   73         /* Block 0 is used for the poly1305 key. */
   74         if (ctx->ietf)
   75                 crypto_stream_chacha20_ietf(block, sizeof(block), iv, ctx->key);
   76         else
   77                 crypto_stream_chacha20(block, sizeof(block), iv, ctx->key);
   78         crypto_onetimeauth_poly1305_init(&ctx->auth, block);
   79         explicit_bzero(block, sizeof(block));
   80 
   81         /* Start with block 1 for ciphertext. */
   82         ctx->ic = 1;
   83 }
   84 
   85 static void
   86 chacha20_poly1305_crypt(void *vctx, const uint8_t *in, uint8_t *out)
   87 {
   88         struct chacha20_poly1305_ctx *ctx = vctx;
   89         int error __diagused;
   90 
   91         if (ctx->ietf)
   92                 error = crypto_stream_chacha20_ietf_xor_ic(out, in,
   93                     CHACHA20_NATIVE_BLOCK_LEN, ctx->nonce, ctx->ic, ctx->key);
   94         else
   95                 error = crypto_stream_chacha20_xor_ic(out, in,
   96                     CHACHA20_NATIVE_BLOCK_LEN, ctx->nonce, ctx->ic, ctx->key);
   97         KASSERT(error == 0, ("%s failed: %d", __func__, error));
   98         ctx->ic++;
   99 }
  100 
  101 static void
  102 chacha20_poly1305_crypt_multi(void *vctx, const uint8_t *in, uint8_t *out, size_t len)
  103 {
  104         struct chacha20_poly1305_ctx *ctx = vctx;
  105         int error __diagused;
  106 
  107         KASSERT(len % CHACHA20_NATIVE_BLOCK_LEN == 0, ("%s: invalid length",
  108             __func__));
  109         if (ctx->ietf)
  110                 error = crypto_stream_chacha20_ietf_xor_ic(out, in, len,
  111                     ctx->nonce, ctx->ic, ctx->key);
  112         else
  113                 error = crypto_stream_chacha20_xor_ic(out, in, len, ctx->nonce,
  114                     ctx->ic, ctx->key);
  115         KASSERT(error == 0, ("%s failed: %d", __func__, error));
  116         ctx->ic += len / CHACHA20_NATIVE_BLOCK_LEN;
  117 }
  118 
  119 static void
  120 chacha20_poly1305_crypt_last(void *vctx, const uint8_t *in, uint8_t *out,
  121     size_t len)
  122 {
  123         struct chacha20_poly1305_ctx *ctx = vctx;
  124 
  125         int error __diagused;
  126 
  127         if (ctx->ietf)
  128                 error = crypto_stream_chacha20_ietf_xor_ic(out, in, len,
  129                     ctx->nonce, ctx->ic, ctx->key);
  130         else
  131                 error = crypto_stream_chacha20_xor_ic(out, in, len, ctx->nonce,
  132                     ctx->ic, ctx->key);
  133         KASSERT(error == 0, ("%s failed: %d", __func__, error));
  134 }
  135 
  136 static int
  137 chacha20_poly1305_update(void *vctx, const void *data, u_int len)
  138 {
  139         struct chacha20_poly1305_ctx *ctx = vctx;
  140 
  141         crypto_onetimeauth_poly1305_update(&ctx->auth, data, len);
  142         return (0);
  143 }
  144 
  145 static void
  146 chacha20_poly1305_final(uint8_t *digest, void *vctx)
  147 {
  148         struct chacha20_poly1305_ctx *ctx = vctx;
  149 
  150         crypto_onetimeauth_poly1305_final(&ctx->auth, digest);
  151 }
  152 
  153 const struct enc_xform enc_xform_chacha20_poly1305 = {
  154         .type = CRYPTO_CHACHA20_POLY1305,
  155         .name = "ChaCha20-Poly1305",
  156         .ctxsize = sizeof(struct chacha20_poly1305_ctx),
  157         .blocksize = 1,
  158         .native_blocksize = CHACHA20_NATIVE_BLOCK_LEN,
  159         .ivsize = CHACHA20_POLY1305_IV_LEN,
  160         .minkey = CHACHA20_POLY1305_KEY,
  161         .maxkey = CHACHA20_POLY1305_KEY,
  162         .macsize = POLY1305_HASH_LEN,
  163         .setkey = chacha20_poly1305_setkey,
  164         .reinit = chacha20_poly1305_reinit,
  165         .encrypt = chacha20_poly1305_crypt,
  166         .decrypt = chacha20_poly1305_crypt,
  167         .encrypt_multi = chacha20_poly1305_crypt_multi,
  168         .decrypt_multi = chacha20_poly1305_crypt_multi,
  169         .encrypt_last = chacha20_poly1305_crypt_last,
  170         .decrypt_last = chacha20_poly1305_crypt_last,
  171         .update = chacha20_poly1305_update,
  172         .final = chacha20_poly1305_final,
  173 };
  174 
  175 static int
  176 xchacha20_poly1305_setkey(void *vctx, const uint8_t *key, int len)
  177 {
  178         struct xchacha20_poly1305_ctx *ctx = vctx;
  179 
  180         if (len != XCHACHA20_POLY1305_KEY)
  181                 return (EINVAL);
  182 
  183         ctx->key = key;
  184         ctx->base_ctx.key = ctx->derived_key;
  185         return (0);
  186 }
  187 
  188 static void
  189 xchacha20_poly1305_reinit(void *vctx, const uint8_t *iv, size_t ivlen)
  190 {
  191         struct xchacha20_poly1305_ctx *ctx = vctx;
  192         char nonce[CHACHA20_POLY1305_IV_LEN];
  193 
  194         KASSERT(ivlen == XCHACHA20_POLY1305_IV_LEN,
  195             ("%s: invalid nonce length", __func__));
  196 
  197         /*
  198          * Use HChaCha20 to derive the internal key used for
  199          * ChaCha20-Poly1305.
  200          */
  201         crypto_core_hchacha20(ctx->derived_key, iv, ctx->key, NULL);
  202 
  203         memset(nonce, 0, 4);
  204         memcpy(nonce + 4, iv + crypto_core_hchacha20_INPUTBYTES,
  205             sizeof(nonce) - 4);
  206         chacha20_poly1305_reinit(&ctx->base_ctx, nonce, sizeof(nonce));
  207         explicit_bzero(nonce, sizeof(nonce));
  208 }
  209 
  210 const struct enc_xform enc_xform_xchacha20_poly1305 = {
  211         .type = CRYPTO_XCHACHA20_POLY1305,
  212         .name = "XChaCha20-Poly1305",
  213         .ctxsize = sizeof(struct xchacha20_poly1305_ctx),
  214         .blocksize = 1,
  215         .native_blocksize = CHACHA20_NATIVE_BLOCK_LEN,
  216         .ivsize = XCHACHA20_POLY1305_IV_LEN,
  217         .minkey = XCHACHA20_POLY1305_KEY,
  218         .maxkey = XCHACHA20_POLY1305_KEY,
  219         .macsize = POLY1305_HASH_LEN,
  220         .setkey = xchacha20_poly1305_setkey,
  221         .reinit = xchacha20_poly1305_reinit,
  222         .encrypt = chacha20_poly1305_crypt,
  223         .decrypt = chacha20_poly1305_crypt,
  224         .encrypt_multi = chacha20_poly1305_crypt_multi,
  225         .decrypt_multi = chacha20_poly1305_crypt_multi,
  226         .encrypt_last = chacha20_poly1305_crypt_last,
  227         .decrypt_last = chacha20_poly1305_crypt_last,
  228         .update = chacha20_poly1305_update,
  229         .final = chacha20_poly1305_final,
  230 };

Cache object: 5a4a43000c5475f9017f39ac238f319d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.