1 /* 2 * Copyright (c) 2015 Mike Belopuhov 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 #include <sys/param.h> 18 #include <sys/systm.h> 19 20 #include <crypto/chacha_private.h> 21 #include <crypto/poly1305.h> 22 #include <crypto/chachapoly.h> 23 24 int 25 chacha20_setkey(void *sched, u_int8_t *key, int len) 26 { 27 struct chacha20_ctx *ctx = (struct chacha20_ctx *)sched; 28 29 if (len != CHACHA20_KEYSIZE + CHACHA20_SALT) 30 return (-1); 31 32 /* initial counter is 1 */ 33 ctx->nonce[0] = 1; 34 memcpy(ctx->nonce + CHACHA20_CTR, key + CHACHA20_KEYSIZE, 35 CHACHA20_SALT); 36 chacha_keysetup((chacha_ctx *)&ctx->block, key, CHACHA20_KEYSIZE * 8); 37 return (0); 38 } 39 40 void 41 chacha20_reinit(caddr_t key, u_int8_t *iv) 42 { 43 struct chacha20_ctx *ctx = (struct chacha20_ctx *)key; 44 45 chacha_ivsetup((chacha_ctx *)ctx->block, iv, ctx->nonce); 46 } 47 48 void 49 chacha20_crypt(caddr_t key, u_int8_t *data) 50 { 51 struct chacha20_ctx *ctx = (struct chacha20_ctx *)key; 52 53 chacha_encrypt_bytes((chacha_ctx *)ctx->block, data, data, 54 CHACHA20_BLOCK_LEN); 55 } 56 57 void 58 Chacha20_Poly1305_Init(void *xctx) 59 { 60 CHACHA20_POLY1305_CTX *ctx = xctx; 61 62 memset(ctx, 0, sizeof(*ctx)); 63 } 64 65 void 66 Chacha20_Poly1305_Setkey(void *xctx, const uint8_t *key, uint16_t klen) 67 { 68 CHACHA20_POLY1305_CTX *ctx = xctx; 69 70 /* salt is provided with the key material */ 71 memcpy(ctx->nonce + CHACHA20_CTR, key + CHACHA20_KEYSIZE, 72 CHACHA20_SALT); 73 chacha_keysetup((chacha_ctx *)&ctx->chacha, key, CHACHA20_KEYSIZE * 8); 74 } 75 76 void 77 Chacha20_Poly1305_Reinit(void *xctx, const uint8_t *iv, uint16_t ivlen) 78 { 79 CHACHA20_POLY1305_CTX *ctx = xctx; 80 81 /* initial counter is 0 */ 82 chacha_ivsetup((chacha_ctx *)&ctx->chacha, iv, ctx->nonce); 83 chacha_encrypt_bytes((chacha_ctx *)&ctx->chacha, ctx->key, ctx->key, 84 POLY1305_KEYLEN); 85 poly1305_init((poly1305_state *)&ctx->poly, ctx->key); 86 } 87 88 int 89 Chacha20_Poly1305_Update(void *xctx, const uint8_t *data, uint16_t len) 90 { 91 static const char zeroes[POLY1305_BLOCK_LEN]; 92 CHACHA20_POLY1305_CTX *ctx = xctx; 93 size_t rem; 94 95 poly1305_update((poly1305_state *)&ctx->poly, data, len); 96 97 /* number of bytes in the last 16 byte block */ 98 rem = (len + POLY1305_BLOCK_LEN) & (POLY1305_BLOCK_LEN - 1); 99 if (rem > 0) 100 poly1305_update((poly1305_state *)&ctx->poly, zeroes, 101 POLY1305_BLOCK_LEN - rem); 102 return (0); 103 } 104 105 void 106 Chacha20_Poly1305_Final(uint8_t tag[POLY1305_TAGLEN], void *xctx) 107 { 108 CHACHA20_POLY1305_CTX *ctx = xctx; 109 110 poly1305_finish((poly1305_state *)&ctx->poly, tag); 111 explicit_bzero(ctx, sizeof(*ctx)); 112 } 113