summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/evp/e_chacha20poly1305.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/evp/e_chacha20poly1305.c')
-rw-r--r--src/lib/libcrypto/evp/e_chacha20poly1305.c231
1 files changed, 0 insertions, 231 deletions
diff --git a/src/lib/libcrypto/evp/e_chacha20poly1305.c b/src/lib/libcrypto/evp/e_chacha20poly1305.c
deleted file mode 100644
index c003b0ba7f..0000000000
--- a/src/lib/libcrypto/evp/e_chacha20poly1305.c
+++ /dev/null
@@ -1,231 +0,0 @@
1/* $OpenBSD: e_chacha20poly1305.c,v 1.9 2015/06/20 12:01:14 jsing Exp $ */
2/*
3 * Copyright (c) 2014, Google Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdint.h>
19#include <string.h>
20
21#include <openssl/opensslconf.h>
22
23#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
24
25#include <openssl/err.h>
26#include <openssl/evp.h>
27#include <openssl/chacha.h>
28#include <openssl/poly1305.h>
29
30#include "evp_locl.h"
31
32#define POLY1305_TAG_LEN 16
33#define CHACHA20_NONCE_LEN 8
34
35struct aead_chacha20_poly1305_ctx {
36 unsigned char key[32];
37 unsigned char tag_len;
38};
39
40static int
41aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key,
42 size_t key_len, size_t tag_len)
43{
44 struct aead_chacha20_poly1305_ctx *c20_ctx;
45
46 if (tag_len == 0)
47 tag_len = POLY1305_TAG_LEN;
48
49 if (tag_len > POLY1305_TAG_LEN) {
50 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_INIT, EVP_R_TOO_LARGE);
51 return 0;
52 }
53
54 /* Internal error - EVP_AEAD_CTX_init should catch this. */
55 if (key_len != sizeof(c20_ctx->key))
56 return 0;
57
58 c20_ctx = malloc(sizeof(struct aead_chacha20_poly1305_ctx));
59 if (c20_ctx == NULL)
60 return 0;
61
62 memcpy(&c20_ctx->key[0], key, key_len);
63 c20_ctx->tag_len = tag_len;
64 ctx->aead_state = c20_ctx;
65
66 return 1;
67}
68
69static void
70aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx)
71{
72 struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
73
74 OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
75 free(c20_ctx);
76}
77
78static void
79poly1305_update_with_length(poly1305_state *poly1305,
80 const unsigned char *data, size_t data_len)
81{
82 size_t j = data_len;
83 unsigned char length_bytes[8];
84 unsigned i;
85
86 for (i = 0; i < sizeof(length_bytes); i++) {
87 length_bytes[i] = j;
88 j >>= 8;
89 }
90
91 CRYPTO_poly1305_update(poly1305, data, data_len);
92 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
93}
94
95static int
96aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
97 size_t *out_len, size_t max_out_len, const unsigned char *nonce,
98 size_t nonce_len, const unsigned char *in, size_t in_len,
99 const unsigned char *ad, size_t ad_len)
100{
101 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
102 unsigned char poly1305_key[32];
103 poly1305_state poly1305;
104 const uint64_t in_len_64 = in_len;
105
106 /* The underlying ChaCha implementation may not overflow the block
107 * counter into the second counter word. Therefore we disallow
108 * individual operations that work on more than 2TB at a time.
109 * in_len_64 is needed because, on 32-bit platforms, size_t is only
110 * 32-bits and this produces a warning because it's always false.
111 * Casting to uint64_t inside the conditional is not sufficient to stop
112 * the warning. */
113 if (in_len_64 >= (1ULL << 32) * 64 - 64) {
114 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_TOO_LARGE);
115 return 0;
116 }
117
118 if (max_out_len < in_len + c20_ctx->tag_len) {
119 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL,
120 EVP_R_BUFFER_TOO_SMALL);
121 return 0;
122 }
123
124 if (nonce_len != CHACHA20_NONCE_LEN) {
125 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE);
126 return 0;
127 }
128
129 memset(poly1305_key, 0, sizeof(poly1305_key));
130 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
131 c20_ctx->key, nonce, 0);
132
133 CRYPTO_poly1305_init(&poly1305, poly1305_key);
134 poly1305_update_with_length(&poly1305, ad, ad_len);
135 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
136 poly1305_update_with_length(&poly1305, out, in_len);
137
138 if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
139 unsigned char tag[POLY1305_TAG_LEN];
140 CRYPTO_poly1305_finish(&poly1305, tag);
141 memcpy(out + in_len, tag, c20_ctx->tag_len);
142 *out_len = in_len + c20_ctx->tag_len;
143 return 1;
144 }
145
146 CRYPTO_poly1305_finish(&poly1305, out + in_len);
147 *out_len = in_len + POLY1305_TAG_LEN;
148 return 1;
149}
150
151static int
152aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
153 size_t *out_len, size_t max_out_len, const unsigned char *nonce,
154 size_t nonce_len, const unsigned char *in, size_t in_len,
155 const unsigned char *ad, size_t ad_len)
156{
157 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
158 unsigned char mac[POLY1305_TAG_LEN];
159 unsigned char poly1305_key[32];
160 poly1305_state poly1305;
161 const uint64_t in_len_64 = in_len;
162 size_t plaintext_len;
163
164 if (in_len < c20_ctx->tag_len) {
165 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
166 return 0;
167 }
168
169 /* The underlying ChaCha implementation may not overflow the block
170 * counter into the second counter word. Therefore we disallow
171 * individual operations that work on more than 2TB at a time.
172 * in_len_64 is needed because, on 32-bit platforms, size_t is only
173 * 32-bits and this produces a warning because it's always false.
174 * Casting to uint64_t inside the conditional is not sufficient to stop
175 * the warning. */
176 if (in_len_64 >= (1ULL << 32) * 64 - 64) {
177 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_TOO_LARGE);
178 return 0;
179 }
180
181 if (nonce_len != CHACHA20_NONCE_LEN) {
182 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE);
183 return 0;
184 }
185
186 plaintext_len = in_len - c20_ctx->tag_len;
187
188 if (max_out_len < plaintext_len) {
189 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN,
190 EVP_R_BUFFER_TOO_SMALL);
191 return 0;
192 }
193
194 memset(poly1305_key, 0, sizeof(poly1305_key));
195 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
196 c20_ctx->key, nonce, 0);
197
198 CRYPTO_poly1305_init(&poly1305, poly1305_key);
199 poly1305_update_with_length(&poly1305, ad, ad_len);
200 poly1305_update_with_length(&poly1305, in, plaintext_len);
201 CRYPTO_poly1305_finish(&poly1305, mac);
202
203 if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
204 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
205 return 0;
206 }
207
208 CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
209 *out_len = plaintext_len;
210 return 1;
211}
212
213static const EVP_AEAD aead_chacha20_poly1305 = {
214 .key_len = 32,
215 .nonce_len = CHACHA20_NONCE_LEN,
216 .overhead = POLY1305_TAG_LEN,
217 .max_tag_len = POLY1305_TAG_LEN,
218
219 .init = aead_chacha20_poly1305_init,
220 .cleanup = aead_chacha20_poly1305_cleanup,
221 .seal = aead_chacha20_poly1305_seal,
222 .open = aead_chacha20_poly1305_open,
223};
224
225const EVP_AEAD *
226EVP_aead_chacha20_poly1305()
227{
228 return &aead_chacha20_poly1305;
229}
230
231#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */