Advertisement
Guest User

Untitled

a guest
Dec 11th, 2013
1,776
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.67 KB | None | 0 0
  1. /*
  2.  * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software for any
  5.  * purpose with or without fee is hereby granted, provided that the above
  6.  * copyright notice and this permission notice appear in all copies.
  7.  *
  8.  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9.  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10.  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11.  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13.  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15.  */
  16.  
  17. /* $OpenBSD: cipher-chachapoly.c,v 1.2 2013/11/21 02:50:00 djm Exp $ */
  18.  
  19. #include <sys/types.h>
  20. #include <stdarg.h> /* needed for log.h */
  21. #include <string.h>
  22. #include <stdio.h>  /* needed for misc.h */
  23.  
  24. #include "log.h"
  25. #include "misc.h"
  26. #include "cipher-chachapoly.h"
  27.  
  28. void chachapoly_init(struct chachapoly_ctx *ctx,
  29.     const u_char *key, u_int keylen)
  30. {
  31.     if (keylen != (32 + 32)) /* 2 x 256 bit keys */
  32.         fatal("%s: invalid keylen %u", __func__, keylen);
  33.     chacha_keysetup(&ctx->main_ctx, key, 256);
  34.     chacha_keysetup(&ctx->header_ctx, key + 32, 256);
  35. }
  36.  
  37. /*
  38.  * chachapoly_crypt() operates as following:
  39.  * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
  40.  * Theses bytes are treated as additional authenticated data.
  41.  * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
  42.  * Use POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the
  43.  * authentication tag.
  44.  * This tag is written on encryption and verified on decryption.
  45.  * Both 'aadlen' and 'authlen' can be set to 0.
  46.  */
  47. int
  48. chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
  49.     const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt)
  50. {
  51.     u_char seqbuf[8];
  52.     u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB. little-endian */
  53.     u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
  54.     int r = -1;
  55.  
  56.     /*
  57.      * Run ChaCha20 once to generate the Poly1305 key. The IV is the
  58.      * packet sequence number.
  59.      */
  60.     bzero(poly_key, sizeof(poly_key));
  61.     put_u64(seqbuf, seqnr);
  62.     chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
  63.     chacha_encrypt_bytes(&ctx->main_ctx,
  64.         poly_key, poly_key, sizeof(poly_key));
  65.     /* Set Chacha's block counter to 1 */
  66.     chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
  67.  
  68.     /* If decrypting, check tag before anything else */
  69.     if (!do_encrypt) {
  70.         const u_char *tag = src + aadlen + len;
  71.  
  72.         poly1305_auth(expected_tag, src, aadlen + len, poly_key);
  73.         if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0)
  74.             goto out;
  75.     }
  76.     /* Crypt additional data */
  77.         if (aadlen) {
  78.         chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
  79.         chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen);
  80.     }
  81.     chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen,
  82.         dest + aadlen, len);
  83.  
  84.     /* If encrypting, calculate and append tag */
  85.     if (do_encrypt) {
  86.         poly1305_auth(dest + aadlen + len, dest, aadlen + len,
  87.             poly_key);
  88.     }
  89.     r = 0;
  90.  
  91.  out:
  92.     bzero(expected_tag, sizeof(expected_tag));
  93.     bzero(seqbuf, sizeof(seqbuf));
  94.     bzero(poly_key, sizeof(poly_key));
  95.     return r;
  96. }
  97.  
  98. int
  99. chachapoly_get_length(struct chachapoly_ctx *ctx,
  100.     u_int *plenp, u_int seqnr, const u_char *cp, u_int len)
  101. {
  102.     u_char buf[4], seqbuf[8];
  103.  
  104.     if (len < 4)
  105.         return -1; /* Insufficient length */
  106.     put_u64(seqbuf, seqnr);
  107.     chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
  108.     chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4);
  109.     *plenp = get_u32(buf);
  110.     return 0;
  111. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement