diff options
Diffstat (limited to 'src/lib/libcrypto/evp/e_chacha20poly1305.c')
-rw-r--r-- | src/lib/libcrypto/evp/e_chacha20poly1305.c | 62 |
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 | |||
100 | aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) | 101 | aead_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 | ||
124 | static ssize_t | 126 | static int |
125 | aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, | 127 | aead_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 | ||
178 | static ssize_t | 182 | static int |
179 | aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out, | 183 | aead_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 | ||
240 | static const EVP_AEAD aead_chacha20_poly1305 = { | 244 | static const EVP_AEAD aead_chacha20_poly1305 = { |