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.c62
1 files changed, 33 insertions, 29 deletions
diff --git a/src/lib/libcrypto/evp/e_chacha20poly1305.c b/src/lib/libcrypto/evp/e_chacha20poly1305.c
index 7e32668b7f..7aeaf8775d 100644
--- a/src/lib/libcrypto/evp/e_chacha20poly1305.c
+++ b/src/lib/libcrypto/evp/e_chacha20poly1305.c
@@ -82,8 +82,9 @@ aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key,
82 return 0; 82 return 0;
83 } 83 }
84 84
85 /* Internal error - EVP_AEAD_CTX_init should catch this. */
85 if (key_len != sizeof(c20_ctx->key)) 86 if (key_len != sizeof(c20_ctx->key))
86 return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */ 87 return 0;
87 88
88 c20_ctx = malloc(sizeof(struct aead_chacha20_poly1305_ctx)); 89 c20_ctx = malloc(sizeof(struct aead_chacha20_poly1305_ctx));
89 if (c20_ctx == NULL) 90 if (c20_ctx == NULL)
@@ -100,6 +101,7 @@ static void
100aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) 101aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx)
101{ 102{
102 struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 103 struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
104
103 OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key)); 105 OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
104 free(c20_ctx); 106 free(c20_ctx);
105} 107}
@@ -121,11 +123,11 @@ poly1305_update_with_length(poly1305_state *poly1305,
121 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); 123 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
122} 124}
123 125
124static ssize_t 126static int
125aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, 127aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
126 size_t max_out_len, const unsigned char *nonce, size_t nonce_len, 128 size_t *out_len, size_t max_out_len, const unsigned char *nonce,
127 const unsigned char *in, size_t in_len, const unsigned char *ad, 129 size_t nonce_len, const unsigned char *in, size_t in_len,
128 size_t ad_len) 130 const unsigned char *ad, size_t ad_len)
129{ 131{
130 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 132 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
131 unsigned char poly1305_key[32]; 133 unsigned char poly1305_key[32];
@@ -139,20 +141,20 @@ aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
139 * 32-bits and this produces a warning because it's always false. 141 * 32-bits and this produces a warning because it's always false.
140 * Casting to uint64_t inside the conditional is not sufficient to stop 142 * Casting to uint64_t inside the conditional is not sufficient to stop
141 * the warning. */ 143 * the warning. */
142 if (in_len_64 >= (1ull << 32)*64 - 64) { 144 if (in_len_64 >= (1ULL << 32) * 64 - 64) {
143 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_TOO_LARGE); 145 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_TOO_LARGE);
144 return -1; 146 return 0;
145 } 147 }
146 148
147 if (max_out_len < in_len + c20_ctx->tag_len) { 149 if (max_out_len < in_len + c20_ctx->tag_len) {
148 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, 150 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL,
149 EVP_R_BUFFER_TOO_SMALL); 151 EVP_R_BUFFER_TOO_SMALL);
150 return -1; 152 return 0;
151 } 153 }
152 154
153 if (nonce_len != CHACHA20_NONCE_LEN) { 155 if (nonce_len != CHACHA20_NONCE_LEN) {
154 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE); 156 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE);
155 return -1; 157 return 0;
156 } 158 }
157 159
158 memset(poly1305_key, 0, sizeof(poly1305_key)); 160 memset(poly1305_key, 0, sizeof(poly1305_key));
@@ -168,29 +170,31 @@ aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
168 unsigned char tag[POLY1305_TAG_LEN]; 170 unsigned char tag[POLY1305_TAG_LEN];
169 CRYPTO_poly1305_finish(&poly1305, tag); 171 CRYPTO_poly1305_finish(&poly1305, tag);
170 memcpy(out + in_len, tag, c20_ctx->tag_len); 172 memcpy(out + in_len, tag, c20_ctx->tag_len);
171 return in_len + c20_ctx->tag_len; 173 *out_len = in_len + c20_ctx->tag_len;
174 return 1;
172 } 175 }
173 176
174 CRYPTO_poly1305_finish(&poly1305, out + in_len); 177 CRYPTO_poly1305_finish(&poly1305, out + in_len);
175 return in_len + POLY1305_TAG_LEN; 178 *out_len = in_len + POLY1305_TAG_LEN;
179 return 1;
176} 180}
177 181
178static ssize_t 182static int
179aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out, 183aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
180 size_t max_out_len, const unsigned char *nonce, size_t nonce_len, 184 size_t *out_len, size_t max_out_len, const unsigned char *nonce,
181 const unsigned char *in, size_t in_len, const unsigned char *ad, 185 size_t nonce_len, const unsigned char *in, size_t in_len,
182 size_t ad_len) 186 const unsigned char *ad, size_t ad_len)
183{ 187{
184 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 188 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
185 unsigned char mac[POLY1305_TAG_LEN]; 189 unsigned char mac[POLY1305_TAG_LEN];
186 unsigned char poly1305_key[32]; 190 unsigned char poly1305_key[32];
187 size_t out_len;
188 poly1305_state poly1305; 191 poly1305_state poly1305;
189 const uint64_t in_len_64 = in_len; 192 const uint64_t in_len_64 = in_len;
193 size_t plaintext_len;
190 194
191 if (in_len < c20_ctx->tag_len) { 195 if (in_len < c20_ctx->tag_len) {
192 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 196 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
193 return -1; 197 return 0;
194 } 198 }
195 199
196 /* The underlying ChaCha implementation may not overflow the block 200 /* The underlying ChaCha implementation may not overflow the block
@@ -200,22 +204,22 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
200 * 32-bits and this produces a warning because it's always false. 204 * 32-bits and this produces a warning because it's always false.
201 * Casting to uint64_t inside the conditional is not sufficient to stop 205 * Casting to uint64_t inside the conditional is not sufficient to stop
202 * the warning. */ 206 * the warning. */
203 if (in_len_64 >= (1ull << 32)*64 - 64) { 207 if (in_len_64 >= (1ULL << 32) * 64 - 64) {
204 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_TOO_LARGE); 208 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_TOO_LARGE);
205 return -1; 209 return 0;
206 } 210 }
207 211
208 if (nonce_len != CHACHA20_NONCE_LEN) { 212 if (nonce_len != CHACHA20_NONCE_LEN) {
209 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE); 213 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE);
210 return -1; 214 return 0;
211 } 215 }
212 216
213 out_len = in_len - c20_ctx->tag_len; 217 plaintext_len = in_len - c20_ctx->tag_len;
214 218
215 if (max_out_len < out_len) { 219 if (max_out_len < plaintext_len) {
216 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, 220 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN,
217 EVP_R_BUFFER_TOO_SMALL); 221 EVP_R_BUFFER_TOO_SMALL);
218 return -1; 222 return 0;
219 } 223 }
220 224
221 memset(poly1305_key, 0, sizeof(poly1305_key)); 225 memset(poly1305_key, 0, sizeof(poly1305_key));
@@ -224,17 +228,17 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
224 228
225 CRYPTO_poly1305_init(&poly1305, poly1305_key); 229 CRYPTO_poly1305_init(&poly1305, poly1305_key);
226 poly1305_update_with_length(&poly1305, ad, ad_len); 230 poly1305_update_with_length(&poly1305, ad, ad_len);
227 poly1305_update_with_length(&poly1305, in, out_len); 231 poly1305_update_with_length(&poly1305, in, plaintext_len);
228 CRYPTO_poly1305_finish(&poly1305, mac); 232 CRYPTO_poly1305_finish(&poly1305, mac);
229 233
230 if (CRYPTO_memcmp(mac, in + out_len, c20_ctx->tag_len) != 0) { 234 if (CRYPTO_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
231 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 235 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
232 return -1; 236 return 0;
233 } 237 }
234 238
235 CRYPTO_chacha_20(out, in, out_len, c20_ctx->key, nonce, 1); 239 CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
236 240 *out_len = plaintext_len;
237 return out_len; 241 return 1;
238} 242}
239 243
240static const EVP_AEAD aead_chacha20_poly1305 = { 244static const EVP_AEAD aead_chacha20_poly1305 = {