summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2014-05-15 15:13:56 +0000
committerjsing <>2014-05-15 15:13:56 +0000
commit58717fb038a81b7b57c09bf92e8a67e2c23377e2 (patch)
tree4faa38278c62b9bbe0e7ded53414d5ae7564efa1
parentfec12ac838b5428d9c1c0d074de2cfcfc2d60f6a (diff)
downloadopenbsd-58717fb038a81b7b57c09bf92e8a67e2c23377e2.tar.gz
openbsd-58717fb038a81b7b57c09bf92e8a67e2c23377e2.tar.bz2
openbsd-58717fb038a81b7b57c09bf92e8a67e2c23377e2.zip
KNF.
-rw-r--r--src/lib/libcrypto/evp/e_chacha20poly1305.c137
-rw-r--r--src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c137
2 files changed, 134 insertions, 140 deletions
diff --git a/src/lib/libcrypto/evp/e_chacha20poly1305.c b/src/lib/libcrypto/evp/e_chacha20poly1305.c
index 9df6b7c453..6e4a3f507a 100644
--- a/src/lib/libcrypto/evp/e_chacha20poly1305.c
+++ b/src/lib/libcrypto/evp/e_chacha20poly1305.c
@@ -6,7 +6,7 @@
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 10 *
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in 12 * notice, this list of conditions and the following disclaimer in
@@ -63,24 +63,24 @@
63#define POLY1305_TAG_LEN 16 63#define POLY1305_TAG_LEN 16
64#define CHACHA20_NONCE_LEN 8 64#define CHACHA20_NONCE_LEN 8
65 65
66struct aead_chacha20_poly1305_ctx 66struct aead_chacha20_poly1305_ctx {
67 {
68 unsigned char key[32]; 67 unsigned char key[32];
69 unsigned char tag_len; 68 unsigned char tag_len;
70 }; 69};
71 70
72static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key, size_t key_len, size_t tag_len) 71static int
73 { 72aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key,
73 size_t key_len, size_t tag_len)
74{
74 struct aead_chacha20_poly1305_ctx *c20_ctx; 75 struct aead_chacha20_poly1305_ctx *c20_ctx;
75 76
76 if (tag_len == 0) 77 if (tag_len == 0)
77 tag_len = POLY1305_TAG_LEN; 78 tag_len = POLY1305_TAG_LEN;
78 79
79 if (tag_len > POLY1305_TAG_LEN) 80 if (tag_len > POLY1305_TAG_LEN) {
80 {
81 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_INIT, EVP_R_TOO_LARGE); 81 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_INIT, EVP_R_TOO_LARGE);
82 return 0; 82 return 0;
83 } 83 }
84 84
85 if (key_len != sizeof(c20_ctx->key)) 85 if (key_len != sizeof(c20_ctx->key))
86 return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */ 86 return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */
@@ -94,38 +94,39 @@ static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *k
94 ctx->aead_state = c20_ctx; 94 ctx->aead_state = c20_ctx;
95 95
96 return 1; 96 return 1;
97 } 97}
98 98
99static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) 99static void
100 { 100aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx)
101{
101 struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 102 struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
102 OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key)); 103 OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
103 OPENSSL_free(c20_ctx); 104 OPENSSL_free(c20_ctx);
104 } 105}
105 106
106static void poly1305_update_with_length(poly1305_state *poly1305, 107static void
107 const unsigned char *data, size_t data_len) 108poly1305_update_with_length(poly1305_state *poly1305,
108 { 109 const unsigned char *data, size_t data_len)
110{
109 size_t j = data_len; 111 size_t j = data_len;
110 unsigned char length_bytes[8]; 112 unsigned char length_bytes[8];
111 unsigned i; 113 unsigned i;
112 114
113 for (i = 0; i < sizeof(length_bytes); i++) 115 for (i = 0; i < sizeof(length_bytes); i++) {
114 {
115 length_bytes[i] = j; 116 length_bytes[i] = j;
116 j >>= 8; 117 j >>= 8;
117 } 118 }
118 119
119 CRYPTO_poly1305_update(poly1305, data, data_len); 120 CRYPTO_poly1305_update(poly1305, data, data_len);
120 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); 121 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
121} 122}
122 123
123static ssize_t aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, 124static ssize_t
124 unsigned char *out, size_t max_out_len, 125aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
125 const unsigned char *nonce, size_t nonce_len, 126 size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
126 const unsigned char *in, size_t in_len, 127 const unsigned char *in, size_t in_len, const unsigned char *ad,
127 const unsigned char *ad, size_t ad_len) 128 size_t ad_len)
128 { 129{
129 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 130 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
130 unsigned char poly1305_key[32]; 131 unsigned char poly1305_key[32];
131 poly1305_state poly1305; 132 poly1305_state poly1305;
@@ -138,50 +139,48 @@ static ssize_t aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx,
138 * 32-bits and this produces a warning because it's always false. 139 * 32-bits and this produces a warning because it's always false.
139 * Casting to uint64_t inside the conditional is not sufficient to stop 140 * Casting to uint64_t inside the conditional is not sufficient to stop
140 * the warning. */ 141 * the warning. */
141 if (in_len_64 >= (1ull << 32)*64-64) 142 if (in_len_64 >= (1ull << 32)*64 - 64) {
142 {
143 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_TOO_LARGE); 143 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_TOO_LARGE);
144 return -1; 144 return -1;
145 } 145 }
146 146
147 if (max_out_len < in_len + c20_ctx->tag_len) 147 if (max_out_len < in_len + c20_ctx->tag_len) {
148 { 148 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL,
149 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_BUFFER_TOO_SMALL); 149 EVP_R_BUFFER_TOO_SMALL);
150 return -1; 150 return -1;
151 } 151 }
152 152
153 if (nonce_len != CHACHA20_NONCE_LEN) 153 if (nonce_len != CHACHA20_NONCE_LEN) {
154 {
155 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE); 154 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE);
156 return -1; 155 return -1;
157 } 156 }
158 157
159 memset(poly1305_key, 0, sizeof(poly1305_key)); 158 memset(poly1305_key, 0, sizeof(poly1305_key));
160 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), c20_ctx->key, nonce, 0); 159 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
160 c20_ctx->key, nonce, 0);
161 161
162 CRYPTO_poly1305_init(&poly1305, poly1305_key); 162 CRYPTO_poly1305_init(&poly1305, poly1305_key);
163 poly1305_update_with_length(&poly1305, ad, ad_len); 163 poly1305_update_with_length(&poly1305, ad, ad_len);
164 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); 164 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
165 poly1305_update_with_length(&poly1305, out, in_len); 165 poly1305_update_with_length(&poly1305, out, in_len);
166 166
167 if (c20_ctx->tag_len != POLY1305_TAG_LEN) 167 if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
168 {
169 unsigned char tag[POLY1305_TAG_LEN]; 168 unsigned char tag[POLY1305_TAG_LEN];
170 CRYPTO_poly1305_finish(&poly1305, tag); 169 CRYPTO_poly1305_finish(&poly1305, tag);
171 memcpy(out + in_len, tag, c20_ctx->tag_len); 170 memcpy(out + in_len, tag, c20_ctx->tag_len);
172 return in_len + c20_ctx->tag_len; 171 return in_len + c20_ctx->tag_len;
173 } 172 }
174 173
175 CRYPTO_poly1305_finish(&poly1305, out + in_len); 174 CRYPTO_poly1305_finish(&poly1305, out + in_len);
176 return in_len + POLY1305_TAG_LEN; 175 return in_len + POLY1305_TAG_LEN;
177 } 176}
178 177
179static ssize_t aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, 178static ssize_t
180 unsigned char *out, size_t max_out_len, 179aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
181 const unsigned char *nonce, size_t nonce_len, 180 size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
182 const unsigned char *in, size_t in_len, 181 const unsigned char *in, size_t in_len, const unsigned char *ad,
183 const unsigned char *ad, size_t ad_len) 182 size_t ad_len)
184 { 183{
185 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 184 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
186 unsigned char mac[POLY1305_TAG_LEN]; 185 unsigned char mac[POLY1305_TAG_LEN];
187 unsigned char poly1305_key[32]; 186 unsigned char poly1305_key[32];
@@ -189,11 +188,10 @@ static ssize_t aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx,
189 poly1305_state poly1305; 188 poly1305_state poly1305;
190 const uint64_t in_len_64 = in_len; 189 const uint64_t in_len_64 = in_len;
191 190
192 if (in_len < c20_ctx->tag_len) 191 if (in_len < c20_ctx->tag_len) {
193 {
194 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 192 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
195 return -1; 193 return -1;
196 } 194 }
197 195
198 /* The underlying ChaCha implementation may not overflow the block 196 /* The underlying ChaCha implementation may not overflow the block
199 * counter into the second counter word. Therefore we disallow 197 * counter into the second counter word. Therefore we disallow
@@ -202,46 +200,44 @@ static ssize_t aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx,
202 * 32-bits and this produces a warning because it's always false. 200 * 32-bits and this produces a warning because it's always false.
203 * Casting to uint64_t inside the conditional is not sufficient to stop 201 * Casting to uint64_t inside the conditional is not sufficient to stop
204 * the warning. */ 202 * the warning. */
205 if (in_len_64 >= (1ull << 32)*64-64) 203 if (in_len_64 >= (1ull << 32)*64 - 64) {
206 {
207 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_TOO_LARGE); 204 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_TOO_LARGE);
208 return -1; 205 return -1;
209 } 206 }
210 207
211 if (nonce_len != CHACHA20_NONCE_LEN) 208 if (nonce_len != CHACHA20_NONCE_LEN) {
212 {
213 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE); 209 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE);
214 return -1; 210 return -1;
215 } 211 }
216 212
217 out_len = in_len - c20_ctx->tag_len; 213 out_len = in_len - c20_ctx->tag_len;
218 214
219 if (max_out_len < out_len) 215 if (max_out_len < out_len) {
220 { 216 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN,
221 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BUFFER_TOO_SMALL); 217 EVP_R_BUFFER_TOO_SMALL);
222 return -1; 218 return -1;
223 } 219 }
224 220
225 memset(poly1305_key, 0, sizeof(poly1305_key)); 221 memset(poly1305_key, 0, sizeof(poly1305_key));
226 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), c20_ctx->key, nonce, 0); 222 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
223 c20_ctx->key, nonce, 0);
227 224
228 CRYPTO_poly1305_init(&poly1305, poly1305_key); 225 CRYPTO_poly1305_init(&poly1305, poly1305_key);
229 poly1305_update_with_length(&poly1305, ad, ad_len); 226 poly1305_update_with_length(&poly1305, ad, ad_len);
230 poly1305_update_with_length(&poly1305, in, out_len); 227 poly1305_update_with_length(&poly1305, in, out_len);
231 CRYPTO_poly1305_finish(&poly1305, mac); 228 CRYPTO_poly1305_finish(&poly1305, mac);
232 229
233 if (CRYPTO_memcmp(mac, in + out_len, c20_ctx->tag_len) != 0) 230 if (CRYPTO_memcmp(mac, in + out_len, c20_ctx->tag_len) != 0) {
234 {
235 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 231 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
236 return -1; 232 return -1;
237 } 233 }
238 234
239 CRYPTO_chacha_20(out, in, out_len, c20_ctx->key, nonce, 1); 235 CRYPTO_chacha_20(out, in, out_len, c20_ctx->key, nonce, 1);
236
240 return out_len; 237 return out_len;
241 } 238}
242 239
243static const EVP_AEAD aead_chacha20_poly1305 = 240static const EVP_AEAD aead_chacha20_poly1305 = {
244 {
245 32, /* key len */ 241 32, /* key len */
246 CHACHA20_NONCE_LEN, /* nonce len */ 242 CHACHA20_NONCE_LEN, /* nonce len */
247 POLY1305_TAG_LEN, /* overhead */ 243 POLY1305_TAG_LEN, /* overhead */
@@ -251,11 +247,12 @@ static const EVP_AEAD aead_chacha20_poly1305 =
251 aead_chacha20_poly1305_cleanup, 247 aead_chacha20_poly1305_cleanup,
252 aead_chacha20_poly1305_seal, 248 aead_chacha20_poly1305_seal,
253 aead_chacha20_poly1305_open, 249 aead_chacha20_poly1305_open,
254 }; 250};
255 251
256const EVP_AEAD *EVP_aead_chacha20_poly1305() 252const EVP_AEAD *
257 { 253EVP_aead_chacha20_poly1305()
254{
258 return &aead_chacha20_poly1305; 255 return &aead_chacha20_poly1305;
259 } 256}
260 257
261#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */ 258#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */
diff --git a/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c b/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c
index 9df6b7c453..6e4a3f507a 100644
--- a/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c
+++ b/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c
@@ -6,7 +6,7 @@
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 10 *
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in 12 * notice, this list of conditions and the following disclaimer in
@@ -63,24 +63,24 @@
63#define POLY1305_TAG_LEN 16 63#define POLY1305_TAG_LEN 16
64#define CHACHA20_NONCE_LEN 8 64#define CHACHA20_NONCE_LEN 8
65 65
66struct aead_chacha20_poly1305_ctx 66struct aead_chacha20_poly1305_ctx {
67 {
68 unsigned char key[32]; 67 unsigned char key[32];
69 unsigned char tag_len; 68 unsigned char tag_len;
70 }; 69};
71 70
72static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key, size_t key_len, size_t tag_len) 71static int
73 { 72aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key,
73 size_t key_len, size_t tag_len)
74{
74 struct aead_chacha20_poly1305_ctx *c20_ctx; 75 struct aead_chacha20_poly1305_ctx *c20_ctx;
75 76
76 if (tag_len == 0) 77 if (tag_len == 0)
77 tag_len = POLY1305_TAG_LEN; 78 tag_len = POLY1305_TAG_LEN;
78 79
79 if (tag_len > POLY1305_TAG_LEN) 80 if (tag_len > POLY1305_TAG_LEN) {
80 {
81 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_INIT, EVP_R_TOO_LARGE); 81 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_INIT, EVP_R_TOO_LARGE);
82 return 0; 82 return 0;
83 } 83 }
84 84
85 if (key_len != sizeof(c20_ctx->key)) 85 if (key_len != sizeof(c20_ctx->key))
86 return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */ 86 return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */
@@ -94,38 +94,39 @@ static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *k
94 ctx->aead_state = c20_ctx; 94 ctx->aead_state = c20_ctx;
95 95
96 return 1; 96 return 1;
97 } 97}
98 98
99static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) 99static void
100 { 100aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx)
101{
101 struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 102 struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
102 OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key)); 103 OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
103 OPENSSL_free(c20_ctx); 104 OPENSSL_free(c20_ctx);
104 } 105}
105 106
106static void poly1305_update_with_length(poly1305_state *poly1305, 107static void
107 const unsigned char *data, size_t data_len) 108poly1305_update_with_length(poly1305_state *poly1305,
108 { 109 const unsigned char *data, size_t data_len)
110{
109 size_t j = data_len; 111 size_t j = data_len;
110 unsigned char length_bytes[8]; 112 unsigned char length_bytes[8];
111 unsigned i; 113 unsigned i;
112 114
113 for (i = 0; i < sizeof(length_bytes); i++) 115 for (i = 0; i < sizeof(length_bytes); i++) {
114 {
115 length_bytes[i] = j; 116 length_bytes[i] = j;
116 j >>= 8; 117 j >>= 8;
117 } 118 }
118 119
119 CRYPTO_poly1305_update(poly1305, data, data_len); 120 CRYPTO_poly1305_update(poly1305, data, data_len);
120 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); 121 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
121} 122}
122 123
123static ssize_t aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, 124static ssize_t
124 unsigned char *out, size_t max_out_len, 125aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
125 const unsigned char *nonce, size_t nonce_len, 126 size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
126 const unsigned char *in, size_t in_len, 127 const unsigned char *in, size_t in_len, const unsigned char *ad,
127 const unsigned char *ad, size_t ad_len) 128 size_t ad_len)
128 { 129{
129 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 130 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
130 unsigned char poly1305_key[32]; 131 unsigned char poly1305_key[32];
131 poly1305_state poly1305; 132 poly1305_state poly1305;
@@ -138,50 +139,48 @@ static ssize_t aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx,
138 * 32-bits and this produces a warning because it's always false. 139 * 32-bits and this produces a warning because it's always false.
139 * Casting to uint64_t inside the conditional is not sufficient to stop 140 * Casting to uint64_t inside the conditional is not sufficient to stop
140 * the warning. */ 141 * the warning. */
141 if (in_len_64 >= (1ull << 32)*64-64) 142 if (in_len_64 >= (1ull << 32)*64 - 64) {
142 {
143 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_TOO_LARGE); 143 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_TOO_LARGE);
144 return -1; 144 return -1;
145 } 145 }
146 146
147 if (max_out_len < in_len + c20_ctx->tag_len) 147 if (max_out_len < in_len + c20_ctx->tag_len) {
148 { 148 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL,
149 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_BUFFER_TOO_SMALL); 149 EVP_R_BUFFER_TOO_SMALL);
150 return -1; 150 return -1;
151 } 151 }
152 152
153 if (nonce_len != CHACHA20_NONCE_LEN) 153 if (nonce_len != CHACHA20_NONCE_LEN) {
154 {
155 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE); 154 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE);
156 return -1; 155 return -1;
157 } 156 }
158 157
159 memset(poly1305_key, 0, sizeof(poly1305_key)); 158 memset(poly1305_key, 0, sizeof(poly1305_key));
160 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), c20_ctx->key, nonce, 0); 159 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
160 c20_ctx->key, nonce, 0);
161 161
162 CRYPTO_poly1305_init(&poly1305, poly1305_key); 162 CRYPTO_poly1305_init(&poly1305, poly1305_key);
163 poly1305_update_with_length(&poly1305, ad, ad_len); 163 poly1305_update_with_length(&poly1305, ad, ad_len);
164 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); 164 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
165 poly1305_update_with_length(&poly1305, out, in_len); 165 poly1305_update_with_length(&poly1305, out, in_len);
166 166
167 if (c20_ctx->tag_len != POLY1305_TAG_LEN) 167 if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
168 {
169 unsigned char tag[POLY1305_TAG_LEN]; 168 unsigned char tag[POLY1305_TAG_LEN];
170 CRYPTO_poly1305_finish(&poly1305, tag); 169 CRYPTO_poly1305_finish(&poly1305, tag);
171 memcpy(out + in_len, tag, c20_ctx->tag_len); 170 memcpy(out + in_len, tag, c20_ctx->tag_len);
172 return in_len + c20_ctx->tag_len; 171 return in_len + c20_ctx->tag_len;
173 } 172 }
174 173
175 CRYPTO_poly1305_finish(&poly1305, out + in_len); 174 CRYPTO_poly1305_finish(&poly1305, out + in_len);
176 return in_len + POLY1305_TAG_LEN; 175 return in_len + POLY1305_TAG_LEN;
177 } 176}
178 177
179static ssize_t aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, 178static ssize_t
180 unsigned char *out, size_t max_out_len, 179aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
181 const unsigned char *nonce, size_t nonce_len, 180 size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
182 const unsigned char *in, size_t in_len, 181 const unsigned char *in, size_t in_len, const unsigned char *ad,
183 const unsigned char *ad, size_t ad_len) 182 size_t ad_len)
184 { 183{
185 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 184 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
186 unsigned char mac[POLY1305_TAG_LEN]; 185 unsigned char mac[POLY1305_TAG_LEN];
187 unsigned char poly1305_key[32]; 186 unsigned char poly1305_key[32];
@@ -189,11 +188,10 @@ static ssize_t aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx,
189 poly1305_state poly1305; 188 poly1305_state poly1305;
190 const uint64_t in_len_64 = in_len; 189 const uint64_t in_len_64 = in_len;
191 190
192 if (in_len < c20_ctx->tag_len) 191 if (in_len < c20_ctx->tag_len) {
193 {
194 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 192 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
195 return -1; 193 return -1;
196 } 194 }
197 195
198 /* The underlying ChaCha implementation may not overflow the block 196 /* The underlying ChaCha implementation may not overflow the block
199 * counter into the second counter word. Therefore we disallow 197 * counter into the second counter word. Therefore we disallow
@@ -202,46 +200,44 @@ static ssize_t aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx,
202 * 32-bits and this produces a warning because it's always false. 200 * 32-bits and this produces a warning because it's always false.
203 * Casting to uint64_t inside the conditional is not sufficient to stop 201 * Casting to uint64_t inside the conditional is not sufficient to stop
204 * the warning. */ 202 * the warning. */
205 if (in_len_64 >= (1ull << 32)*64-64) 203 if (in_len_64 >= (1ull << 32)*64 - 64) {
206 {
207 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_TOO_LARGE); 204 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_TOO_LARGE);
208 return -1; 205 return -1;
209 } 206 }
210 207
211 if (nonce_len != CHACHA20_NONCE_LEN) 208 if (nonce_len != CHACHA20_NONCE_LEN) {
212 {
213 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE); 209 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE);
214 return -1; 210 return -1;
215 } 211 }
216 212
217 out_len = in_len - c20_ctx->tag_len; 213 out_len = in_len - c20_ctx->tag_len;
218 214
219 if (max_out_len < out_len) 215 if (max_out_len < out_len) {
220 { 216 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN,
221 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BUFFER_TOO_SMALL); 217 EVP_R_BUFFER_TOO_SMALL);
222 return -1; 218 return -1;
223 } 219 }
224 220
225 memset(poly1305_key, 0, sizeof(poly1305_key)); 221 memset(poly1305_key, 0, sizeof(poly1305_key));
226 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), c20_ctx->key, nonce, 0); 222 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
223 c20_ctx->key, nonce, 0);
227 224
228 CRYPTO_poly1305_init(&poly1305, poly1305_key); 225 CRYPTO_poly1305_init(&poly1305, poly1305_key);
229 poly1305_update_with_length(&poly1305, ad, ad_len); 226 poly1305_update_with_length(&poly1305, ad, ad_len);
230 poly1305_update_with_length(&poly1305, in, out_len); 227 poly1305_update_with_length(&poly1305, in, out_len);
231 CRYPTO_poly1305_finish(&poly1305, mac); 228 CRYPTO_poly1305_finish(&poly1305, mac);
232 229
233 if (CRYPTO_memcmp(mac, in + out_len, c20_ctx->tag_len) != 0) 230 if (CRYPTO_memcmp(mac, in + out_len, c20_ctx->tag_len) != 0) {
234 {
235 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 231 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
236 return -1; 232 return -1;
237 } 233 }
238 234
239 CRYPTO_chacha_20(out, in, out_len, c20_ctx->key, nonce, 1); 235 CRYPTO_chacha_20(out, in, out_len, c20_ctx->key, nonce, 1);
236
240 return out_len; 237 return out_len;
241 } 238}
242 239
243static const EVP_AEAD aead_chacha20_poly1305 = 240static const EVP_AEAD aead_chacha20_poly1305 = {
244 {
245 32, /* key len */ 241 32, /* key len */
246 CHACHA20_NONCE_LEN, /* nonce len */ 242 CHACHA20_NONCE_LEN, /* nonce len */
247 POLY1305_TAG_LEN, /* overhead */ 243 POLY1305_TAG_LEN, /* overhead */
@@ -251,11 +247,12 @@ static const EVP_AEAD aead_chacha20_poly1305 =
251 aead_chacha20_poly1305_cleanup, 247 aead_chacha20_poly1305_cleanup,
252 aead_chacha20_poly1305_seal, 248 aead_chacha20_poly1305_seal,
253 aead_chacha20_poly1305_open, 249 aead_chacha20_poly1305_open,
254 }; 250};
255 251
256const EVP_AEAD *EVP_aead_chacha20_poly1305() 252const EVP_AEAD *
257 { 253EVP_aead_chacha20_poly1305()
254{
258 return &aead_chacha20_poly1305; 255 return &aead_chacha20_poly1305;
259 } 256}
260 257
261#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */ 258#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */