diff options
author | jsing <> | 2014-05-26 13:01:58 +0000 |
---|---|---|
committer | jsing <> | 2014-05-26 13:01:58 +0000 |
commit | 1e04f96479c885fa94175f42f348872cbdd3c9d4 (patch) | |
tree | 2d8c2f3b74e112db8f84b41231b2cde79d0be571 /src/lib/libcrypto/evp/e_chacha20poly1305.c | |
parent | 3ebf48c494177b3b775febf8302322375c80fe3b (diff) | |
download | openbsd-1e04f96479c885fa94175f42f348872cbdd3c9d4.tar.gz openbsd-1e04f96479c885fa94175f42f348872cbdd3c9d4.tar.bz2 openbsd-1e04f96479c885fa94175f42f348872cbdd3c9d4.zip |
Implement an improved version of the EVP AEAD API. The
EVP_AEAD_CTX_{open,seal} functions previously returned an ssize_t that was
overloaded to indicate success/failure, along with the number of bytes
written as output. This change adds an explicit *out_len argument which
is used to return the number of output bytes and the return value is now
an int that is purely used to identify success or failure.
This change effectively rides the last libcrypto crank (although I do not
expect there to be many users of the EVP AEAD API currently).
Thanks to Adam Langley for providing the improved code that this diff is
based on.
ok miod@
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 = { |