├── README.md ├── poly1305.h ├── chacha.h ├── chachapoly.h ├── chachapoly-test.c ├── chachapoly.c ├── chacha.c └── poly1305.c /README.md: -------------------------------------------------------------------------------- 1 | # ChaChaPoly 2 | 3 | This is an RFC 7539 compliant ChaCha20-Poly1305 AEAD implementation. The underlying ChaCha20 implementation used is the original implementation from D. J. Bernstein with changes to the nonce/counter split as required by RFC7539. The Poly1305 implementation is poly1305-donna. 4 | 5 | The AEAD code has been designed to be as simple, easy to understand and small as possible. That means no particular architecture specific optimizations are included. The ChaCha20 and Poly1305 implementations were also chosen with this in mind. 6 | 7 | An additional AEAD construction is included that reuses 32 byte of keystream that are otherwise thrown away for encryption or decryption of small messages. Use this at your own risk! 8 | 9 | # License 10 | 11 | The chachapoly code is MIT licensed. The underlying chacha20 implementation by D.J. Bernstein is public domain. The poly1305 implementation used, donna-poly1305, is public domain or MIT licensed (at your own choice). In conclusion, you should consider the combined work MIT licensed. 12 | -------------------------------------------------------------------------------- /poly1305.h: -------------------------------------------------------------------------------- 1 | #ifndef POLY1305_H 2 | #define POLY1305_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define POLY1305_KEYLEN 32 9 | #define POLY1305_TAGLEN 16 10 | #define POLY1305_BLOCK_SIZE 16 11 | 12 | /* use memcpy() to copy blocks of memory (typically faster) */ 13 | #define USE_MEMCPY 1 14 | /* use unaligned little-endian load/store (can be faster) */ 15 | #define USE_UNALIGNED 0 16 | 17 | struct poly1305_context { 18 | uint32_t r[5]; 19 | uint32_t h[5]; 20 | uint32_t pad[4]; 21 | size_t leftover; 22 | unsigned char buffer[POLY1305_BLOCK_SIZE]; 23 | unsigned char final; 24 | }; 25 | 26 | void poly1305_init(struct poly1305_context *ctx, const unsigned char key[32]); 27 | void poly1305_update(struct poly1305_context *ctx, const unsigned char *m, size_t bytes); 28 | void poly1305_finish(struct poly1305_context *ctx, unsigned char mac[16]); 29 | void poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]); 30 | 31 | #endif /* POLY1305_H */ 32 | 33 | -------------------------------------------------------------------------------- /chacha.h: -------------------------------------------------------------------------------- 1 | /* 2 | chacha-merged.c version 20080118 3 | D. J. Bernstein 4 | Public domain. 5 | */ 6 | 7 | #ifndef CHACHA_H 8 | #define CHACHA_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define CHACHA_MINKEYLEN 16 16 | #define CHACHA_NONCELEN 8 17 | #define CHACHA_CTRLEN 8 18 | #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) 19 | #define CHACHA_BLOCKLEN 64 20 | 21 | /* use memcpy() to copy blocks of memory (typically faster) */ 22 | #define USE_MEMCPY 1 23 | /* use unaligned little-endian load/store (can be faster) */ 24 | #define USE_UNALIGNED 0 25 | 26 | struct chacha_ctx { 27 | uint32_t input[16]; 28 | }; 29 | 30 | void chacha_keysetup(struct chacha_ctx *x, const unsigned char *k, 31 | uint32_t kbits); 32 | void chacha_ivsetup(struct chacha_ctx *x, const unsigned char *iv, 33 | const unsigned char *ctr); 34 | void chacha_encrypt_bytes(struct chacha_ctx *x, const unsigned char *m, 35 | unsigned char *c, uint32_t bytes); 36 | 37 | #endif /* CHACHA_H */ 38 | 39 | -------------------------------------------------------------------------------- /chachapoly.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Grigori Goronzy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef CHACHAPOLY_H 26 | #define CHACHAPOLY_H 27 | 28 | #include "chacha.h" 29 | #include "poly1305.h" 30 | 31 | #define CHACHAPOLY_OK 0 32 | #define CHACHAPOLY_INVALID_MAC -1 33 | 34 | struct chachapoly_ctx { 35 | struct chacha_ctx cha_ctx; 36 | }; 37 | 38 | /** 39 | * Initialize ChaCha20-Poly1305 AEAD. 40 | * For RFC 7539 conformant AEAD, 256 bit keys must be used. 41 | * 42 | * \param ctx context data 43 | * \param key 16 or 32 bytes of key material 44 | * \param key_len key length, 256 or 512 bits 45 | * \return success if 0 46 | */ 47 | int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len); 48 | 49 | /** 50 | * Encrypt or decrypt with ChaCha20-Poly1305. The AEAD construction conforms 51 | * to RFC 7539. 52 | * 53 | * \param ctx context data 54 | * \param nonce nonce (12 bytes) 55 | * \param ad associated data 56 | * \param ad_len associated data length in bytes 57 | * \param input plaintext/ciphertext input 58 | * \param input_len input length in bytes; 59 | * \param output plaintext/ciphertext output 60 | * \param tag tag output 61 | * \param tag_len tag length in bytes (0-16); 62 | if 0, authentification is skipped 63 | * \param encrypt decrypt if 0, else encrypt 64 | * \return CHACHAPOLY_OK if no error, CHACHAPOLY_INVALID_MAC if auth 65 | * failed when decrypting 66 | */ 67 | int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce, 68 | const void *ad, int ad_len, void *input, int input_len, 69 | void *output, void *tag, int tag_len, int encrypt); 70 | 71 | /** 72 | * Encrypt or decrypt with Chacha20-Poly1305 for short messages. 73 | * The AEAD construction is different from chachapoly_crypt, but more 74 | * efficient for small messages. Up to 32 bytes can be encrypted. The size 75 | * of associated data is not restricted. The interface is similar to 76 | * chachapoly_crypt. 77 | */ 78 | int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce, 79 | const void *ad, int ad_len, void *input, int input_len, 80 | void *output, void *tag, int tag_len, int encrypt); 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /chachapoly-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Grigori Goronzy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include "chachapoly.h" 27 | 28 | /* AEAD test vector from RFC 7539 */ 29 | int chachapoly_test_rfc7539(void) 30 | { 31 | unsigned char tag[16]; 32 | unsigned char ct[114]; 33 | int i, ret; 34 | struct chachapoly_ctx ctx; 35 | 36 | unsigned char key[32] = { 37 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 38 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f 39 | }; 40 | unsigned char ad[12] = { 41 | 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 42 | }; 43 | unsigned char pt[114]; 44 | memcpy(pt, "Ladies and Gentlemen of the class of '99: If I could offer you " 45 | "only one tip for the future, sunscreen would be it.", 114); 46 | unsigned char nonce[12] = { 47 | 0x07, 0x00, 0x00, 0x00, 48 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 49 | }; 50 | unsigned char tag_verify[16] = { 51 | 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 52 | }; 53 | unsigned char ct_verify[114] = { 54 | 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 55 | 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 56 | 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 57 | 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 58 | 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 59 | 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 60 | 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 61 | 0x61, 0x16 62 | }; 63 | 64 | chachapoly_init(&ctx, key, 256); 65 | chachapoly_crypt(&ctx, nonce, ad, 12, pt, 114, ct, tag, 16, 1); 66 | 67 | for (i = 0; i < 114; i++) { 68 | if (ct[i] != ct_verify[i]) { 69 | return -2; 70 | } 71 | } 72 | 73 | for (i = 0; i < 16; i++) { 74 | if (tag[i] != tag_verify[i]) { 75 | return -3; 76 | } 77 | } 78 | 79 | ret = chachapoly_crypt(&ctx, nonce, ad, 12, ct, 114, pt, tag, 16, 0); 80 | 81 | return ret; 82 | } 83 | 84 | /* AEAD auth-only case */ 85 | int chachapoly_test_auth_only(void) 86 | { 87 | unsigned char tag[16]; 88 | int i, ret; 89 | struct chachapoly_ctx ctx; 90 | 91 | unsigned char key[32] = { 92 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 93 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f 94 | }; 95 | unsigned char pt[114]; 96 | memcpy(pt, "Ladies and Gentlemen of the class of '99: If I could offer you " 97 | "only one tip for the future, sunscreen would be it.", 114); 98 | unsigned char nonce[12] = { 99 | 0x07, 0x00, 0x00, 0x00, 100 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 101 | }; 102 | unsigned char tag_verify[16] = { 103 | 0x03, 0xDC, 0xD0, 0x84, 0x04, 0x67, 0x80, 0xE6, 0x39, 0x50, 0x67, 0x0D, 0x3B, 0xBC, 0xC8, 0x95 104 | }; 105 | 106 | chachapoly_init(&ctx, key, 256); 107 | chachapoly_crypt(&ctx, nonce, pt, 114, NULL, 0, NULL, tag, 16, 1); 108 | 109 | for (i = 0; i < 16; i++) { 110 | if (tag[i] != tag_verify[i]) { 111 | return -3; 112 | } 113 | } 114 | 115 | ret = chachapoly_crypt(&ctx, nonce, pt, 114, NULL, 0, NULL, tag, 16, 0); 116 | 117 | return ret; 118 | } 119 | 120 | int main(int argc, char **argv) 121 | { 122 | int res = chachapoly_test_rfc7539(); 123 | printf("%s = %d\n", "rfc7539", res); 124 | res = chachapoly_test_auth_only(); 125 | printf("%s = %d\n", "auth_only", res); 126 | } 127 | 128 | -------------------------------------------------------------------------------- /chachapoly.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 Grigori Goronzy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "chachapoly.h" 31 | 32 | /** 33 | * Constant-time memory compare. This should help to protect against 34 | * side-channel attacks. 35 | * 36 | * \param av input 1 37 | * \param bv input 2 38 | * \param n bytes to compare 39 | * \return 0 if inputs are equal 40 | */ 41 | static int memcmp_eq(const void *av, const void *bv, int n) 42 | { 43 | const unsigned char *a = (const unsigned char*) av; 44 | const unsigned char *b = (const unsigned char*) bv; 45 | unsigned char res = 0; 46 | int i; 47 | 48 | for (i = 0; i < n; i++) { 49 | res |= *a ^ *b; 50 | a++; 51 | b++; 52 | } 53 | 54 | return res; 55 | } 56 | 57 | /** 58 | * Poly1305 tag generation. This concatenates a string according to the rules 59 | * outlined in RFC 7539 and calculates the tag. 60 | * 61 | * \param poly_key 32 byte secret one-time key for poly1305 62 | * \param ad associated data 63 | * \param ad_len associated data length in bytes 64 | * \param ct ciphertext 65 | * \param ct_len ciphertext length in bytes 66 | * \param tag pointer to 16 bytes for tag storage 67 | */ 68 | static void poly1305_get_tag(unsigned char *poly_key, const void *ad, 69 | int ad_len, const void *ct, int ct_len, unsigned char *tag) 70 | { 71 | struct poly1305_context poly; 72 | unsigned left_over; 73 | uint64_t len; 74 | unsigned char pad[16]; 75 | 76 | poly1305_init(&poly, poly_key); 77 | memset(&pad, 0, sizeof(pad)); 78 | 79 | /* associated data and padding */ 80 | poly1305_update(&poly, ad, ad_len); 81 | left_over = ad_len % 16; 82 | if (left_over) 83 | poly1305_update(&poly, pad, 16 - left_over); 84 | 85 | /* payload and padding */ 86 | poly1305_update(&poly, ct, ct_len); 87 | left_over = ct_len % 16; 88 | if (left_over) 89 | poly1305_update(&poly, pad, 16 - left_over); 90 | 91 | /* lengths */ 92 | len = ad_len; 93 | poly1305_update(&poly, (unsigned char *)&len, 8); 94 | len = ct_len; 95 | poly1305_update(&poly, (unsigned char *)&len, 8); 96 | 97 | poly1305_finish(&poly, tag); 98 | } 99 | 100 | int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len) 101 | { 102 | assert (key_len == 128 || key_len == 256); 103 | 104 | memset(ctx, 0, sizeof(*ctx)); 105 | chacha_keysetup(&ctx->cha_ctx, key, key_len); 106 | return CHACHAPOLY_OK; 107 | } 108 | 109 | int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce, 110 | const void *ad, int ad_len, void *input, int input_len, 111 | void *output, void *tag, int tag_len, int encrypt) 112 | { 113 | unsigned char poly_key[CHACHA_BLOCKLEN]; 114 | unsigned char calc_tag[POLY1305_TAGLEN]; 115 | const unsigned char one[4] = { 1, 0, 0, 0 }; 116 | 117 | /* initialize keystream and generate poly1305 key */ 118 | memset(poly_key, 0, sizeof(poly_key)); 119 | chacha_ivsetup(&ctx->cha_ctx, nonce, NULL); 120 | chacha_encrypt_bytes(&ctx->cha_ctx, poly_key, poly_key, sizeof(poly_key)); 121 | 122 | /* check tag if decrypting */ 123 | if (encrypt == 0 && tag_len) { 124 | poly1305_get_tag(poly_key, ad, ad_len, input, input_len, calc_tag); 125 | if (memcmp_eq(calc_tag, tag, tag_len) != 0) { 126 | return CHACHAPOLY_INVALID_MAC; 127 | } 128 | } 129 | 130 | /* crypt data */ 131 | chacha_ivsetup(&ctx->cha_ctx, nonce, one); 132 | chacha_encrypt_bytes(&ctx->cha_ctx, (unsigned char *)input, 133 | (unsigned char *)output, input_len); 134 | 135 | /* add tag if encrypting */ 136 | if (encrypt && tag_len) { 137 | poly1305_get_tag(poly_key, ad, ad_len, output, input_len, calc_tag); 138 | memcpy(tag, calc_tag, tag_len); 139 | } 140 | 141 | return CHACHAPOLY_OK; 142 | } 143 | 144 | int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce, 145 | const void *ad, int ad_len, void *input, int input_len, 146 | void *output, void *tag, int tag_len, int encrypt) 147 | { 148 | unsigned char keystream[CHACHA_BLOCKLEN]; 149 | unsigned char calc_tag[POLY1305_TAGLEN]; 150 | int i; 151 | 152 | assert(input_len <= 32); 153 | 154 | /* initialize keystream and generate poly1305 key */ 155 | memset(keystream, 0, sizeof(keystream)); 156 | chacha_ivsetup(&ctx->cha_ctx, nonce, NULL); 157 | chacha_encrypt_bytes(&ctx->cha_ctx, keystream, keystream, 158 | sizeof(keystream)); 159 | 160 | /* check tag if decrypting */ 161 | if (encrypt == 0 && tag_len) { 162 | poly1305_get_tag(keystream, ad, ad_len, input, input_len, calc_tag); 163 | if (memcmp_eq(calc_tag, tag, tag_len) != 0) { 164 | return CHACHAPOLY_INVALID_MAC; 165 | } 166 | } 167 | 168 | /* crypt data */ 169 | for (i = 0; i < input_len; i++) { 170 | ((unsigned char *)output)[i] = 171 | ((unsigned char *)input)[i] ^ keystream[32 + i]; 172 | } 173 | 174 | /* add tag if encrypting */ 175 | if (encrypt && tag_len) { 176 | poly1305_get_tag(keystream, ad, ad_len, output, input_len, calc_tag); 177 | memcpy(tag, calc_tag, tag_len); 178 | } 179 | 180 | return CHACHAPOLY_OK; 181 | } 182 | -------------------------------------------------------------------------------- /chacha.c: -------------------------------------------------------------------------------- 1 | /* 2 | chacha-merged.c version 20080118 3 | D. J. Bernstein 4 | Public domain. 5 | */ 6 | 7 | #include "chacha.h" 8 | 9 | #define U8C(v) (v##U) 10 | #define U32C(v) (v##U) 11 | 12 | #define U8V(v) ((unsigned char)(v) & U8C(0xFF)) 13 | #define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF)) 14 | 15 | #define ROTL32(v, n) \ 16 | (U32V((v) << (n)) | ((v) >> (32 - (n)))) 17 | 18 | #if (USE_UNALIGNED == 1) 19 | #define U8TO32_LITTLE(p) \ 20 | (*((uint32_t *)(p))) 21 | #define U32TO8_LITTLE(p, v) \ 22 | do { \ 23 | *((uint32_t *)(p)) = v; \ 24 | } while (0) 25 | #else 26 | #define U8TO32_LITTLE(p) \ 27 | (((uint32_t)((p)[0]) ) | \ 28 | ((uint32_t)((p)[1]) << 8) | \ 29 | ((uint32_t)((p)[2]) << 16) | \ 30 | ((uint32_t)((p)[3]) << 24)) 31 | #define U32TO8_LITTLE(p, v) \ 32 | do { \ 33 | (p)[0] = U8V((v) ); \ 34 | (p)[1] = U8V((v) >> 8); \ 35 | (p)[2] = U8V((v) >> 16); \ 36 | (p)[3] = U8V((v) >> 24); \ 37 | } while (0) 38 | #endif 39 | 40 | #define ROTATE(v,c) (ROTL32(v,c)) 41 | #define XOR(v,w) ((v) ^ (w)) 42 | #define PLUS(v,w) (U32V((v) + (w))) 43 | #define PLUSONE(v) (PLUS((v),1)) 44 | 45 | #define QUARTERROUND(a,b,c,d) \ 46 | a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ 47 | c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ 48 | a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ 49 | c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); 50 | 51 | static const char sigma[16] = "expand 32-byte k"; 52 | static const char tau[16] = "expand 16-byte k"; 53 | 54 | void 55 | chacha_keysetup(struct chacha_ctx *x,const unsigned char *k,uint32_t kbits) 56 | { 57 | const char *constants; 58 | 59 | x->input[4] = U8TO32_LITTLE(k + 0); 60 | x->input[5] = U8TO32_LITTLE(k + 4); 61 | x->input[6] = U8TO32_LITTLE(k + 8); 62 | x->input[7] = U8TO32_LITTLE(k + 12); 63 | if (kbits == 256) { /* recommended */ 64 | k += 16; 65 | constants = sigma; 66 | } else { /* kbits == 128 */ 67 | constants = tau; 68 | } 69 | x->input[8] = U8TO32_LITTLE(k + 0); 70 | x->input[9] = U8TO32_LITTLE(k + 4); 71 | x->input[10] = U8TO32_LITTLE(k + 8); 72 | x->input[11] = U8TO32_LITTLE(k + 12); 73 | x->input[0] = U8TO32_LITTLE(constants + 0); 74 | x->input[1] = U8TO32_LITTLE(constants + 4); 75 | x->input[2] = U8TO32_LITTLE(constants + 8); 76 | x->input[3] = U8TO32_LITTLE(constants + 12); 77 | } 78 | 79 | void 80 | chacha_ivsetup(struct chacha_ctx *x, const unsigned char *iv, const unsigned char *counter) 81 | { 82 | x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); 83 | //x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); 84 | x->input[13] = U8TO32_LITTLE(iv + 0); 85 | x->input[14] = U8TO32_LITTLE(iv + 4); 86 | x->input[15] = U8TO32_LITTLE(iv + 8); 87 | } 88 | 89 | void 90 | chacha_encrypt_bytes(struct chacha_ctx *x,const unsigned char *m,unsigned char *c,uint32_t bytes) 91 | { 92 | uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; 93 | uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; 94 | unsigned char *ctarget = NULL; 95 | unsigned char tmp[64]; 96 | u_int i; 97 | 98 | if (!bytes) return; 99 | 100 | j0 = x->input[0]; 101 | j1 = x->input[1]; 102 | j2 = x->input[2]; 103 | j3 = x->input[3]; 104 | j4 = x->input[4]; 105 | j5 = x->input[5]; 106 | j6 = x->input[6]; 107 | j7 = x->input[7]; 108 | j8 = x->input[8]; 109 | j9 = x->input[9]; 110 | j10 = x->input[10]; 111 | j11 = x->input[11]; 112 | j12 = x->input[12]; 113 | j13 = x->input[13]; 114 | j14 = x->input[14]; 115 | j15 = x->input[15]; 116 | 117 | for (;;) { 118 | if (bytes < 64) { 119 | #if (USE_MEMCPY == 1) 120 | memcpy(tmp, m, bytes); 121 | #else 122 | for (i = 0;i < bytes;++i) tmp[i] = m[i]; 123 | #endif 124 | m = tmp; 125 | ctarget = c; 126 | c = tmp; 127 | } 128 | x0 = j0; 129 | x1 = j1; 130 | x2 = j2; 131 | x3 = j3; 132 | x4 = j4; 133 | x5 = j5; 134 | x6 = j6; 135 | x7 = j7; 136 | x8 = j8; 137 | x9 = j9; 138 | x10 = j10; 139 | x11 = j11; 140 | x12 = j12; 141 | x13 = j13; 142 | x14 = j14; 143 | x15 = j15; 144 | for (i = 20;i > 0;i -= 2) { 145 | QUARTERROUND( x0, x4, x8,x12) 146 | QUARTERROUND( x1, x5, x9,x13) 147 | QUARTERROUND( x2, x6,x10,x14) 148 | QUARTERROUND( x3, x7,x11,x15) 149 | QUARTERROUND( x0, x5,x10,x15) 150 | QUARTERROUND( x1, x6,x11,x12) 151 | QUARTERROUND( x2, x7, x8,x13) 152 | QUARTERROUND( x3, x4, x9,x14) 153 | } 154 | x0 = PLUS(x0,j0); 155 | x1 = PLUS(x1,j1); 156 | x2 = PLUS(x2,j2); 157 | x3 = PLUS(x3,j3); 158 | x4 = PLUS(x4,j4); 159 | x5 = PLUS(x5,j5); 160 | x6 = PLUS(x6,j6); 161 | x7 = PLUS(x7,j7); 162 | x8 = PLUS(x8,j8); 163 | x9 = PLUS(x9,j9); 164 | x10 = PLUS(x10,j10); 165 | x11 = PLUS(x11,j11); 166 | x12 = PLUS(x12,j12); 167 | x13 = PLUS(x13,j13); 168 | x14 = PLUS(x14,j14); 169 | x15 = PLUS(x15,j15); 170 | 171 | x0 = XOR(x0,U8TO32_LITTLE(m + 0)); 172 | x1 = XOR(x1,U8TO32_LITTLE(m + 4)); 173 | x2 = XOR(x2,U8TO32_LITTLE(m + 8)); 174 | x3 = XOR(x3,U8TO32_LITTLE(m + 12)); 175 | x4 = XOR(x4,U8TO32_LITTLE(m + 16)); 176 | x5 = XOR(x5,U8TO32_LITTLE(m + 20)); 177 | x6 = XOR(x6,U8TO32_LITTLE(m + 24)); 178 | x7 = XOR(x7,U8TO32_LITTLE(m + 28)); 179 | x8 = XOR(x8,U8TO32_LITTLE(m + 32)); 180 | x9 = XOR(x9,U8TO32_LITTLE(m + 36)); 181 | x10 = XOR(x10,U8TO32_LITTLE(m + 40)); 182 | x11 = XOR(x11,U8TO32_LITTLE(m + 44)); 183 | x12 = XOR(x12,U8TO32_LITTLE(m + 48)); 184 | x13 = XOR(x13,U8TO32_LITTLE(m + 52)); 185 | x14 = XOR(x14,U8TO32_LITTLE(m + 56)); 186 | x15 = XOR(x15,U8TO32_LITTLE(m + 60)); 187 | 188 | j12 = PLUSONE(j12); 189 | if (!j12) { 190 | j13 = PLUSONE(j13); 191 | /* stopping at 2^70 bytes per nonce is user's responsibility */ 192 | } 193 | 194 | U32TO8_LITTLE(c + 0,x0); 195 | U32TO8_LITTLE(c + 4,x1); 196 | U32TO8_LITTLE(c + 8,x2); 197 | U32TO8_LITTLE(c + 12,x3); 198 | U32TO8_LITTLE(c + 16,x4); 199 | U32TO8_LITTLE(c + 20,x5); 200 | U32TO8_LITTLE(c + 24,x6); 201 | U32TO8_LITTLE(c + 28,x7); 202 | U32TO8_LITTLE(c + 32,x8); 203 | U32TO8_LITTLE(c + 36,x9); 204 | U32TO8_LITTLE(c + 40,x10); 205 | U32TO8_LITTLE(c + 44,x11); 206 | U32TO8_LITTLE(c + 48,x12); 207 | U32TO8_LITTLE(c + 52,x13); 208 | U32TO8_LITTLE(c + 56,x14); 209 | U32TO8_LITTLE(c + 60,x15); 210 | 211 | if (bytes <= 64) { 212 | if (bytes < 64) { 213 | #if (USE_MEMCPY == 1) 214 | memcpy(ctarget, c, bytes); 215 | #else 216 | for (i = 0;i < bytes;++i) ctarget[i] = c[i]; 217 | #endif 218 | } 219 | x->input[12] = j12; 220 | x->input[13] = j13; 221 | return; 222 | } 223 | bytes -= 64; 224 | c += 64; 225 | m += 64; 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /poly1305.c: -------------------------------------------------------------------------------- 1 | /* 2 | poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition 3 | public domain 4 | */ 5 | 6 | #include "poly1305.h" 7 | 8 | #if (USE_UNALIGNED == 1) 9 | #define U8TO32(p) \ 10 | (*((uint32_t *)(p))) 11 | #define U32TO8(p, v) \ 12 | do { \ 13 | *((uint32_t *)(p)) = v; \ 14 | } while (0) 15 | #else 16 | /* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */ 17 | static uint32_t 18 | U8TO32(const unsigned char *p) 19 | { 20 | return 21 | (((uint32_t)(p[0] & 0xff) ) | 22 | ((uint32_t)(p[1] & 0xff) << 8) | 23 | ((uint32_t)(p[2] & 0xff) << 16) | 24 | ((uint32_t)(p[3] & 0xff) << 24)); 25 | } 26 | 27 | /* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */ 28 | static void 29 | U32TO8(unsigned char *p, uint32_t v) 30 | { 31 | p[0] = (v ) & 0xff; 32 | p[1] = (v >> 8) & 0xff; 33 | p[2] = (v >> 16) & 0xff; 34 | p[3] = (v >> 24) & 0xff; 35 | } 36 | #endif 37 | 38 | void 39 | poly1305_init(struct poly1305_context *st, const unsigned char key[32]) 40 | { 41 | /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ 42 | st->r[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff; 43 | st->r[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03; 44 | st->r[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff; 45 | st->r[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff; 46 | st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff; 47 | 48 | /* h = 0 */ 49 | st->h[0] = 0; 50 | st->h[1] = 0; 51 | st->h[2] = 0; 52 | st->h[3] = 0; 53 | st->h[4] = 0; 54 | 55 | /* save pad for later */ 56 | st->pad[0] = U8TO32(&key[16]); 57 | st->pad[1] = U8TO32(&key[20]); 58 | st->pad[2] = U8TO32(&key[24]); 59 | st->pad[3] = U8TO32(&key[28]); 60 | 61 | st->leftover = 0; 62 | st->final = 0; 63 | } 64 | 65 | static void 66 | poly1305_blocks(struct poly1305_context *st, const unsigned char *m, size_t bytes) 67 | { 68 | const uint32_t hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */ 69 | uint32_t r0,r1,r2,r3,r4; 70 | uint32_t s1,s2,s3,s4; 71 | uint32_t h0,h1,h2,h3,h4; 72 | uint64_t d0,d1,d2,d3,d4; 73 | uint32_t c; 74 | 75 | r0 = st->r[0]; 76 | r1 = st->r[1]; 77 | r2 = st->r[2]; 78 | r3 = st->r[3]; 79 | r4 = st->r[4]; 80 | 81 | s1 = r1 * 5; 82 | s2 = r2 * 5; 83 | s3 = r3 * 5; 84 | s4 = r4 * 5; 85 | 86 | h0 = st->h[0]; 87 | h1 = st->h[1]; 88 | h2 = st->h[2]; 89 | h3 = st->h[3]; 90 | h4 = st->h[4]; 91 | 92 | while (bytes >= POLY1305_BLOCK_SIZE) { 93 | /* h += m[i] */ 94 | h0 += (U8TO32(m+ 0) ) & 0x3ffffff; 95 | h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; 96 | h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; 97 | h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; 98 | h4 += (U8TO32(m+12) >> 8) | hibit; 99 | 100 | /* h *= r */ 101 | d0 = ((uint64_t)h0 * r0) + ((uint64_t)h1 * s4) + ((uint64_t)h2 * s3) + ((uint64_t)h3 * s2) + ((uint64_t)h4 * s1); 102 | d1 = ((uint64_t)h0 * r1) + ((uint64_t)h1 * r0) + ((uint64_t)h2 * s4) + ((uint64_t)h3 * s3) + ((uint64_t)h4 * s2); 103 | d2 = ((uint64_t)h0 * r2) + ((uint64_t)h1 * r1) + ((uint64_t)h2 * r0) + ((uint64_t)h3 * s4) + ((uint64_t)h4 * s3); 104 | d3 = ((uint64_t)h0 * r3) + ((uint64_t)h1 * r2) + ((uint64_t)h2 * r1) + ((uint64_t)h3 * r0) + ((uint64_t)h4 * s4); 105 | d4 = ((uint64_t)h0 * r4) + ((uint64_t)h1 * r3) + ((uint64_t)h2 * r2) + ((uint64_t)h3 * r1) + ((uint64_t)h4 * r0); 106 | 107 | /* (partial) h %= p */ 108 | c = (uint32_t)(d0 >> 26); h0 = (uint32_t)d0 & 0x3ffffff; 109 | d1 += c; c = (uint32_t)(d1 >> 26); h1 = (uint32_t)d1 & 0x3ffffff; 110 | d2 += c; c = (uint32_t)(d2 >> 26); h2 = (uint32_t)d2 & 0x3ffffff; 111 | d3 += c; c = (uint32_t)(d3 >> 26); h3 = (uint32_t)d3 & 0x3ffffff; 112 | d4 += c; c = (uint32_t)(d4 >> 26); h4 = (uint32_t)d4 & 0x3ffffff; 113 | h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; 114 | h1 += c; 115 | 116 | m += POLY1305_BLOCK_SIZE; 117 | bytes -= POLY1305_BLOCK_SIZE; 118 | } 119 | 120 | st->h[0] = h0; 121 | st->h[1] = h1; 122 | st->h[2] = h2; 123 | st->h[3] = h3; 124 | st->h[4] = h4; 125 | } 126 | 127 | void 128 | poly1305_finish(struct poly1305_context *st, unsigned char mac[16]) 129 | { 130 | uint32_t h0,h1,h2,h3,h4,c; 131 | uint32_t g0,g1,g2,g3,g4; 132 | uint64_t f; 133 | uint32_t mask; 134 | 135 | /* process the remaining block */ 136 | if (st->leftover) { 137 | size_t i = st->leftover; 138 | st->buffer[i++] = 1; 139 | for (; i < POLY1305_BLOCK_SIZE; i++) 140 | st->buffer[i] = 0; 141 | st->final = 1; 142 | poly1305_blocks(st, st->buffer, POLY1305_BLOCK_SIZE); 143 | } 144 | 145 | /* fully carry h */ 146 | h0 = st->h[0]; 147 | h1 = st->h[1]; 148 | h2 = st->h[2]; 149 | h3 = st->h[3]; 150 | h4 = st->h[4]; 151 | 152 | c = h1 >> 26; h1 = h1 & 0x3ffffff; 153 | h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; 154 | h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; 155 | h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; 156 | h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; 157 | h1 += c; 158 | 159 | /* compute h + -p */ 160 | g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; 161 | g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; 162 | g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; 163 | g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; 164 | g4 = h4 + c - (1 << 26); 165 | 166 | /* select h if h < p, or h + -p if h >= p */ 167 | mask = (g4 >> ((sizeof(uint32_t) * 8) - 1)) - 1; 168 | g0 &= mask; 169 | g1 &= mask; 170 | g2 &= mask; 171 | g3 &= mask; 172 | g4 &= mask; 173 | mask = ~mask; 174 | h0 = (h0 & mask) | g0; 175 | h1 = (h1 & mask) | g1; 176 | h2 = (h2 & mask) | g2; 177 | h3 = (h3 & mask) | g3; 178 | h4 = (h4 & mask) | g4; 179 | 180 | /* h = h % (2^128) */ 181 | h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; 182 | h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; 183 | h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; 184 | h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; 185 | 186 | /* mac = (h + pad) % (2^128) */ 187 | f = (uint64_t)h0 + st->pad[0] ; h0 = (uint32_t)f; 188 | f = (uint64_t)h1 + st->pad[1] + (f >> 32); h1 = (uint32_t)f; 189 | f = (uint64_t)h2 + st->pad[2] + (f >> 32); h2 = (uint32_t)f; 190 | f = (uint64_t)h3 + st->pad[3] + (f >> 32); h3 = (uint32_t)f; 191 | 192 | U32TO8(mac + 0, h0); 193 | U32TO8(mac + 4, h1); 194 | U32TO8(mac + 8, h2); 195 | U32TO8(mac + 12, h3); 196 | 197 | /* zero out the state */ 198 | st->h[0] = 0; 199 | st->h[1] = 0; 200 | st->h[2] = 0; 201 | st->h[3] = 0; 202 | st->h[4] = 0; 203 | st->r[0] = 0; 204 | st->r[1] = 0; 205 | st->r[2] = 0; 206 | st->r[3] = 0; 207 | st->r[4] = 0; 208 | st->pad[0] = 0; 209 | st->pad[1] = 0; 210 | st->pad[2] = 0; 211 | st->pad[3] = 0; 212 | } 213 | 214 | 215 | void 216 | poly1305_update(struct poly1305_context *st, const unsigned char *m, size_t bytes) 217 | { 218 | size_t i; 219 | 220 | /* handle leftover */ 221 | if (st->leftover) { 222 | size_t want = (POLY1305_BLOCK_SIZE - st->leftover); 223 | if (want > bytes) 224 | want = bytes; 225 | for (i = 0; i < want; i++) 226 | st->buffer[st->leftover + i] = m[i]; 227 | bytes -= want; 228 | m += want; 229 | st->leftover += want; 230 | if (st->leftover < POLY1305_BLOCK_SIZE) 231 | return; 232 | poly1305_blocks(st, st->buffer, POLY1305_BLOCK_SIZE); 233 | st->leftover = 0; 234 | } 235 | 236 | /* process full blocks */ 237 | if (bytes >= POLY1305_BLOCK_SIZE) { 238 | size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1)); 239 | poly1305_blocks(st, m, want); 240 | m += want; 241 | bytes -= want; 242 | } 243 | 244 | /* store leftover */ 245 | if (bytes) { 246 | #if (USE_MEMCPY == 1) 247 | memcpy(st->buffer + st->leftover, m, bytes); 248 | #else 249 | for (i = 0; i < bytes; i++) 250 | st->buffer[st->leftover + i] = m[i]; 251 | #endif 252 | st->leftover += bytes; 253 | } 254 | } 255 | 256 | void 257 | poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]) 258 | { 259 | struct poly1305_context ctx; 260 | poly1305_init(&ctx, key); 261 | poly1305_update(&ctx, m, bytes); 262 | poly1305_finish(&ctx, mac); 263 | } 264 | --------------------------------------------------------------------------------