Compare commits

...

127 Commits

Author SHA1 Message Date
David Benjamin c8ff30cbe7 Add an option to allow unknown ALPN protocols.
We received an external request to add an option to undo the check added
in 3e51757de2.

Change-Id: Ifdd4b07705f2fa3d781d775d5cd139ea72d36734
Reviewed-on: https://boringssl-review.googlesource.com/14644
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-04-05 00:33:57 +00:00
David Benjamin 0686c09eea Fix CRYPTO_dup_ex_data.
On malloc error, CRYPTO_set_ex_data may fail. (See upstream's
62f488d31733e5dc77b339f905b44f165550e47d.)

It also failed to copy the reserved slots when we revised the app-data
machinery, although this is unreachable as EC_KEY is the only thing
which uses this function and EC_KEY has no reserved slots. (We probably
can/should also take CRYPTO_dup_ex_data out of there, as it's a little
bit weird...)

Change-Id: I60bbc301f919d4c0ee7fff362f979f6ec18d73b7
Reviewed-on: https://boringssl-review.googlesource.com/14604
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-04-04 18:21:49 +00:00
Adam Langley b18cb6a5d0 Make the POWER hardware capability value a global in crypto.c.
(Thanks to Sam Panzer for the patch.)

At least some linkers will drop constructor functions if no symbols from
that translation unit are used elsewhere in the program. On POWER, since
the cached capability value isn't a global in crypto.o (like other
platforms), the constructor function is getting discarded.

The C++11 spec says (3.6.2, paragraph 4):

    It is implementation-defined whether the dynamic initialization of a
    non-local variable with static storage duration is done before the
    first statement of main. If the initialization is deferred to some
    point in time after the first statement of main, it shall occur
    before the first odr-use (3.2) of any function or variable defined
    in the same translation unit as the variable to be initialized.

Compilers appear to interpret that to mean they are allowed to drop
(i.e. indefinitely defer) constructors that occur in translation units
that are never used, so they can avoid initializing some part of a
library if it's dropped on the floor.

This change makes the hardware capability value for POWER a global in
crypto.c, which should prevent the constructor function from being
ignored.

Change-Id: I43ebe492d0ac1491f6f6c2097971a277f923dd3e
Reviewed-on: https://boringssl-review.googlesource.com/14664
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-04-04 18:19:19 +00:00
David Benjamin 42329a828b Clean up PKCS5_PBKDF2_HMAC.
This was a mess. HMAC_CTX_copy_ex would avoid having to cleanup and init
the HMAC_CTX repeatedly, but even that is unnecessary. hctx_tpl was just
to reuse the key. Instead, HMAC_CTX already can be reset with the same
key. (Alas, with a slightly odd API, but so it goes.) Do that, and use
goto err to cleanup the error-handling.

Thanks to upstream's b98530d6e09f4cb34c791b8840e936c1fc1467cf for
drawing attention to this. (Though we've diverged significantly from
upstream with all the heap-allocated bits, so I didn't use the change
itself.)

While I'm here, tidy up some variable names and cite the newer RFC.

Change-Id: Ic1259f46b7c5a14dc341b8cee385be5508ac4daf
Reviewed-on: https://boringssl-review.googlesource.com/14605
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-04-04 18:13:53 +00:00
Martin Kreichgauer 8b487b73aa util/generate_build_files.py: Filter test runner sources from BUILD files.
Change-Id: I6eb13647843b124b0cfeb7ea592736a80d723836
Reviewed-on: https://boringssl-review.googlesource.com/14624
Reviewed-by: Adam Langley <agl@google.com>
2017-04-03 23:12:33 +00:00
Alessandro Ghedini 67bb45f44b Support enabling early data on SSL
This moves the early data switch to CERT to make this
|SSL_set_SSL_CTX|-proof.

Change-Id: Icca96e76636d87578deb24b2d507cabee7e46a4a
Reviewed-on: https://boringssl-review.googlesource.com/14545
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-04-03 20:25:29 +00:00
Adam Langley faa539f877 Remove static output buffers for hash & HMAC functions.
These static output buffers are a legacy from a time before processes
had threads. This change drops support and callers who were depending on
this (of which there are hopefully none) will crash.

Change-Id: I7b8eb3440def507f92543e55465f821dfa02c7da
Reviewed-on: https://boringssl-review.googlesource.com/14528
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-04-02 17:53:17 +00:00
David Benjamin ebcb5beb19 Sync vendored copies of Go poly1305 and curve25519.
Taken from revision 3cb07270c9455e8ad27956a70891c962d121a228 of
go-crypto. Some of the changes look like they might fix some of the
crashes we've been having on ARM bots?

Change-Id: I127fd358db553eae4805e777011a89124f595ff0
Reviewed-on: https://boringssl-review.googlesource.com/14544
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-30 20:04:23 +00:00
Adam Langley 107d4388cb Gate assembly sources on !OPENSSL_NO_ASM.
Change-Id: I32b37306265e89afca568f20bfba2e04559c4f0b
Reviewed-on: https://boringssl-review.googlesource.com/14527
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-30 19:34:21 +00:00
David Benjamin cbfd3c044c Refresh fuzzer corpora.
Change-Id: I04babe31dcea8198a88c8affd5f9f9e24e449e4a
Reviewed-on: https://boringssl-review.googlesource.com/14526
Reviewed-by: Steven Valdez <svaldez@google.com>
2017-03-30 16:55:36 +00:00
David Benjamin 0c05c37f93 Update fuzzer exclusions.
We've got to get a bot for this...

Change-Id: I6af0c466c10ec52bf2e67f1e6fa2513411aeb3c0
Reviewed-on: https://boringssl-review.googlesource.com/14524
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2017-03-30 16:54:38 +00:00
David Benjamin 519118f984 Fix FUZZING.md typo.
Change-Id: Ie43ffabfdf5b10fbb0c8adcc2626a2913152e5e1
Reviewed-on: https://boringssl-review.googlesource.com/14525
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2017-03-30 16:54:18 +00:00
Doug Kwan a5f1b38de5 Use vec_vsx_ld to performance unaligned load instead of dereferencing a pointer
and relying on a compiler to generate code for unaligned access.  Both gcc
and llvm currently do that but llvm is going to change to generate code for
aligned access.  The change in llvm will break SHA-1 on POWER without this fix.

Change-Id: If9393968288cf94b684ad340e3ea295e03174aa9
Reviewed-on: https://boringssl-review.googlesource.com/14378
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:43:30 +00:00
David Benjamin 7e9949c30b Import additional test vectors from RFC 8032.
There are a few test vectors which were not imported from djb's. Mirror
those. Also as RFC 8032 uses a slightly different private key
representation, document this in curve25519.h.

BUG=187

Change-Id: I119381168ba1af9b332365fd8f974fba41759d57
Reviewed-on: https://boringssl-review.googlesource.com/14445
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:28:55 +00:00
David Benjamin 17eeb9820c Unwind the rest of EVP_PKEY_supports_digest.
This is a remnant of a previous iteration of the SSL client certificate
bridging logic in Chromium.

Change-Id: Ifa8e15cc970395f179e2f6db65c97a342af5498d
Reviewed-on: https://boringssl-review.googlesource.com/14444
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:28:25 +00:00
David Benjamin 6bb507bc9c Add missing tests for the Channel ID / 0-RTT interaction.
Clients or servers enabling both should not stop functioning.

Change-Id: I5cca09f8adfc8ff56b8943123847bbdaf8885cf4
Reviewed-on: https://boringssl-review.googlesource.com/14485
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-30 16:25:44 +00:00
David Benjamin e94ec3f85b Use a union in tls_cbc.c.
This is slightly tidier than casting through function pointers. (Also
more defined? But we cast T* => void* within a function pointer all over
the place, so that's probably a lost cause.)

Change-Id: I8f435906f3066d1377eababf940e3db34c626acd
Reviewed-on: https://boringssl-review.googlesource.com/14313
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:25:11 +00:00
David Benjamin 79bc7a3212 Remove unsigned-based constant-time functions.
We only need the size_t ones now.

BUG=22

Change-Id: Ie6935656bbc4bd2b602b8fad78effc401c493416
Reviewed-on: https://boringssl-review.googlesource.com/14312
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:24:19 +00:00
David Benjamin 643b77e644 Convert tls_cbc.c to size_t.
Not that this is remotely necessary since the code bounds to 1MB, the
caller bounds to INT_MAX (due to EVP_CIPHER) and the grandcaller bounds
to 16k (due to TLS).

BUG=22

Change-Id: Ia75990a30bac26ca617532630340ff94a88e4e20
Reviewed-on: https://boringssl-review.googlesource.com/14311
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:23:38 +00:00
David Benjamin 053a8f728e Bound EVP_tls_cbc_digest_record at runtime.
This is redundant because these "AEAD"s are not meant to be used outside
of TLS, but since we've moved them into their own layer, they should
check internally.

Change-Id: Ieb3541b2e494902527c2bb56a816cef620cb237b
Reviewed-on: https://boringssl-review.googlesource.com/14310
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:20:55 +00:00
David Benjamin 8d979e5430 Push variable declarations in EVP_tls_cbc_digest_record.
This makes it a bit easier to see what is what.

Change-Id: I0f73f6ffa84bd30de3efcbf2bd34e1d3a889d1ee
Reviewed-on: https://boringssl-review.googlesource.com/14309
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:20:36 +00:00
David Benjamin b0ad3d74db Convert more RSA padding check functions to size_t.
BUG=22

Change-Id: I9f392eef44e83efb4b13931acb2a3c642cbf1f29
Reviewed-on: https://boringssl-review.googlesource.com/14308
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:19:45 +00:00
David Benjamin 43ea204db7 Convert RSA_padding_check_PKCS1_type_1 to size_t.
BUG=22

Change-Id: I5bfa543c261623d125e7a25cea905e3b90b0c014
Reviewed-on: https://boringssl-review.googlesource.com/14307
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 16:03:20 +00:00
David Benjamin d1c0de6fe0 Add size_t variants of constant-time functions.
These will be used in follow-up commits. The _s names are taken from
upstream, to ease importing code. I've also promoted the CONSTTIME_*
macros from the test. None of them are really necessary except
~0u cannot substitute for CONSTTIME_TRUE_S on 64-bit platforms, so
having the macros seems safer.

Once everything is converted, I expect the unsigned versions can be
removed, so I've made the _8 and _int functions act on size_t rather
than unsigned. The users of these functions basically only believe that
array indices and bytes exist.

BUG=22

Change-Id: I987bfb0c708dc726a6f2afcb05b6619bbd600564
Reviewed-on: https://boringssl-review.googlesource.com/14306
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-30 15:38:43 +00:00
Steven Valdez f368c73826 Fix fuzzer excludes.
Change-Id: I013cf58528463ccca9e087c1c5d544beec3db24a
Reviewed-on: https://boringssl-review.googlesource.com/14466
Reviewed-by: David Benjamin <davidben@google.com>
2017-03-30 02:39:56 +00:00
David Benjamin fef78b0356 Use an actual SCT for fuzzing.
SSL_CTX_set_signed_cert_timestamp_list fails now if its input is not
well-formed.

Change-Id: I84a4034f66868da11f98bf33e5b7f5c9fc958933
Reviewed-on: https://boringssl-review.googlesource.com/14484
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-29 23:00:36 +00:00
Steven Valdez a507617e4d Adding server fuzzer for early data.
Since any ALPN mismatch and other cause for early data rejection will
cause the server to revert to the non-early data path, this is safe to
flip on for all the fuzzers.

BUG=76

Change-Id: I573740ef8f455915820943d82247fb6bfc37ae41
Reviewed-on: https://boringssl-review.googlesource.com/14465
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-29 22:51:46 +00:00
Adam Langley 764ab9802e Support and test P-224 certificates.
Previously we only needed to be able to serve P-224 certificates, but
now we anticipate a need to be able to connect and validate them also.
Since this requires advertising support for P-224 in the handshake, we
need to support P-224 ECDHE too.

P-224 support is disabled by default and so clients need to both set the
enabled curves explicitly and set a maximum version of TLS 1.2.

Change-Id: Idc69580f47334e0912eb431a0db0e78ee2eb5bbe
Reviewed-on: https://boringssl-review.googlesource.com/14225
Reviewed-by: Adam Langley <alangley@gmail.com>
Commit-Queue: Adam Langley <alangley@gmail.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-29 17:50:36 +00:00
Steven Valdez a0ba400c33 Add cipher asserts for read/write app data.
Allow the fuzzers to treat this situation, if they ever discover it,
as a bug.

Change-Id: Ie6f1562e9b185d49463cf1a6db28d28780169b11
Reviewed-on: https://boringssl-review.googlesource.com/14424
Reviewed-by: David Benjamin <davidben@google.com>
2017-03-28 21:02:56 +00:00
David Benjamin ccbb165d98 Tidy up ssl3_choose_cipher.
Change-Id: Ied6b73fde61eb133c9871b42a56aa5a64131b67b
Reviewed-on: https://boringssl-review.googlesource.com/14328
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-27 20:13:13 +00:00
David Benjamin 8c26d750e1 Test the behavior of running SSL_do_handshake twice in a row.
BUG=185

Change-Id: I4ce6735ca78cd687538a8c0fdbd78ee97b93585c
Reviewed-on: https://boringssl-review.googlesource.com/14382
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-27 18:30:44 +00:00
David Benjamin 7a60ca095d Synchronize bsaes-armv7.pl with upstream.
This pulls in upstream's 0822d41b6d54132df96c02cc6f6fa9b179378351 and a
portion of a285992763f3961f69a8d86bf7dfff020a08cef9. The former, in
particular, fixes a crash on iOS.

Change-Id: I3c083975d8d11e58b5a2919fcabbf83628f36340
Reviewed-on: https://boringssl-review.googlesource.com/14383
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-27 16:38:33 +00:00
David Benjamin 0f5d7d3f04 Just allocate what's needed for SSL write buffers.
When we refactored all the buffering logic, we retained upstream
OpenSSL's allocation patterns. In particular, we always allocated fixed
size write buffer, even though, unlike when reading, we trivially know a
tighter bound (namely however much we happen to be writing right now).

Since the cutoff for when Windows' malloc starts having a hard time is
just below the TLS maximum record size, do the more natural thing of
allocating what we need to hold outgoing ciphertext.

(This only does anything to the write half. Read half is a bit more
involved.)

BUG=chromium:524258

Change-Id: I0165f9ce822b9cc413f3c77e269e6154160537a7
Reviewed-on: https://boringssl-review.googlesource.com/14405
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-27 16:37:53 +00:00
David Benjamin 95321e15f2 Fix diff_asm.go.
We now have another non-OpenSSL perlasm file.

Change-Id: Id5ab606089f22a4cb4c7d29f2cf7d140b66861f7
Reviewed-on: https://boringssl-review.googlesource.com/14404
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-27 14:29:55 +00:00
David Benjamin bbfe603519 Clean up end_of_early_data processing.
Remove another remnant of the SSL3_PROTOCOL_METHOD hook.

Change-Id: If6bf055e2ee318420e4c5c40b8eb5356eadda68c
Reviewed-on: https://boringssl-review.googlesource.com/14381
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
2017-03-26 20:39:44 +00:00
David Benjamin fc2d78dd1e Document server 0-RTT behavior.
BUG=76

Change-Id: I68bc1dce13af9155b385a7b589480aacf02ec0db
Reviewed-on: https://boringssl-review.googlesource.com/14380
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
2017-03-26 20:39:31 +00:00
Steven Valdez 681eb6ac2d Adding support for receiving early data on the server.
BUG=76

Change-Id: Ie894ea5d327f88e66b234767de437dbe5c67c41d
Reviewed-on: https://boringssl-review.googlesource.com/12960
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 19:30:27 +00:00
David Benjamin 32c8927159 Add a test for missing end_of_early_data.
BUG=76

Change-Id: I43672ee82a50f8fe706a5d607ef774a6e96db252
Reviewed-on: https://boringssl-review.googlesource.com/14379
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 19:09:17 +00:00
David Benjamin 81a191dc4d Convert constant_time_test to GTest.
This ends up under half the size of the original file.

BUG=129

Change-Id: Idec69d9517bd57cee6b3b83bc0cce05396565b70
Reviewed-on: https://boringssl-review.googlesource.com/14305
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 19:04:07 +00:00
David Benjamin 94cf5d030f Remove some unnecessary NULL checks.
OPENSSL_free will handle NULL.

Change-Id: I18593a015cd4a081c2eeebf0cd738a024d02a97d
Reviewed-on: https://boringssl-review.googlesource.com/14373
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 18:58:17 +00:00
David Benjamin e000440982 Detach pkcs7.c from the OID table.
It still depends on crypto/x509, but we will need a CRYPTO_BUFFER
version of PKCS7_get_certificates for Chromium. Start with this.

BUG=54

Change-Id: I62dcb9ba768091ce37dc9fe819f4f14ac025219c
Reviewed-on: https://boringssl-review.googlesource.com/14372
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 18:58:15 +00:00
Alessandro Ghedini ca307ab6a3 tool: show if early data was accepted
Change-Id: I5e1302d75f863fb2e531d431a4e3ecfd90e0dca1
Reviewed-on: https://boringssl-review.googlesource.com/14376
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 18:31:07 +00:00
David Benjamin 065d733c4b Test ticket age skew when resuming a resumed session.
This tests that the ticket age is measured from ticket issuance and not
the initial authentication. Specifically, that ssl_session_renew_timeout
also rebases the time.

Change-Id: Iba51efb49c691a44e6428d1cd35f0803ca3d396a
Reviewed-on: https://boringssl-review.googlesource.com/14375
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 18:24:37 +00:00
Steven Valdez 2a0707210a Prevent Channel ID and Custom Extensions on 0-RTT.
Channel ID is incompatible with 0-RTT, so we gracefully decline 0-RTT
as a server and forbid their combination as a client. We'll keep this
logic around until Channel ID is removed.

Channel ID will be replaced by tokbind which currently uses custom
extensions. Those will need additional logic to work with 0-RTT.
This is not implemented yet so, for now, fail if both are ever
configured together at all. A later change will allow the two to
combine.

BUG=183

Change-Id: I46c5ba883ccd47930349691fb08074a1fab13d5f
Reviewed-on: https://boringssl-review.googlesource.com/14370
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 18:13:57 +00:00
Steven Valdez 246eeee61a Make RI on TLS 1.3 alert with ILLEGAL_PARAMETER.
Change-Id: I0e2e4166ad2c57e3192af058f23374f014a2fcf4
Reviewed-on: https://boringssl-review.googlesource.com/14377
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 18:10:37 +00:00
David Benjamin 794cc59e25 Send half-RTT tickets when negotiating 0-RTT.
Once 0-RTT data is added to the current 0-RTT logic, the server will
trigger a write when processing incoming data via SSL_read. This means
SSL_read will block on transport write, which is something we've not
tried to avoid far (assuming no renegotiation).

The specification allows for tickets to be sent at half-RTT by
predicting the client Finished. By doing this we both get the tickets on
the wire sooner and avoid confusing I/O patterns. Moreover, we
anticipate we will need this mode for one of the QUIC stateless reject
patterns.

This is tested by always processing NewSessionTickets in the
ExpectHalfRTTData path on 0-RTT connections. As not other
implementations using BoGo may not do this, this is configurable via the
shim config.

BUG=76

Change-Id: Ia0f56ae63f15078ff1cacceba972d2b99001947f
Reviewed-on: https://boringssl-review.googlesource.com/14371
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 18:10:07 +00:00
David Benjamin 02084ea398 Decouple PKCS8_encrypt and PKCS8_decrypt's core from crypto/asn1.
These will be used by Chromium's crypto::ECPrivateKey to work with
EncryptedPrivateKeyInfo structures.

Note this comes with a behavior change: PKCS8_encrypt and PKCS8_decrypt
will no longer preserve PKCS#8 PrivateKeyInfo attributes. However, those
functions are only called by Chromium which does not care. They are also
called by the PEM code, but not in a way which exposes attributes.

The PKCS#12 PFX code is made to use PKCS8_parse_encrypted_private_key
because it's cleaner (no more tossing X509_SIG around) and to ease
decoupling that in the future.

crypto/pkcs8's dependency on the legacy ASN.1 stack is now limited to
pkcs8_x509.c.

BUG=54

Change-Id: I173e605d175e982c6b0250dd22187b73aca15b1a
Reviewed-on: https://boringssl-review.googlesource.com/14215
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 04:00:26 +00:00
David Benjamin 3cb12467cc Remove session_tickets_sent.
This is a remnant of before we made the handshake write
flight by flight.

Change-Id: I94c0105bb071ffca9ff5aa4c4bf43311c750b49a
Reviewed-on: https://boringssl-review.googlesource.com/14369
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 01:22:27 +00:00
David Benjamin 7ce10d5da7 Partially split out crypto/pkcs8's legacy ASN.1 dependencies.
PKCS8_encrypt and PKCS8_decrypt still need to be split. The code for
processing PKCS#12 files is, for now, placed entirely in pkcs8_x509.c.
If we need to split it up, it should be straightforward to do so.
(Introduce a CRYPTO_BUFFER version of PKCS12_get_key_and_certs and go
from there.)

BUG=54

Change-Id: I9c87e916ec29ee14dbbd81c4d3fc10ac8a461f1a
Reviewed-on: https://boringssl-review.googlesource.com/14214
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-26 00:17:25 +00:00
David Benjamin 4784b99bf3 Use set_{accept,connect}_state + do_handshake in bssl_shim.
This will make it easier to test 0-RTT later on.

BUG=76

Change-Id: I4d60b77c14bc9143ca9785d0a6b8169653a1b120
Reviewed-on: https://boringssl-review.googlesource.com/14367
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 23:34:27 +00:00
David Benjamin 7d2dbc3791 Add a comment around the set_{min,max}_version logic.
It's not immediately obvious what's going on here.

Change-Id: Ibbba80a6ff9ace4d88e89a42efc270b77b4fad12
Reviewed-on: https://boringssl-review.googlesource.com/14368
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 23:28:45 +00:00
David Benjamin e3843d41b9 Run all state machine coverage tests on implicit handshake.
The tests all work fine under it except for tests where the shim shuts
down. (In those the shim calls SSL_shutdown as the first function, so it
wouldn't do anything useful.)

Change-Id: Ia2e811bb3c553a690df38d1fd7d3107ae7c9aa12
Reviewed-on: https://boringssl-review.googlesource.com/14366
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 23:18:12 +00:00
David Benjamin f466cdb5e0 size_t the RSA padding add functions.
The padding check functions will need to tweak their calling conventions
and the constant-time helpers, so leaving those alone for now. These
were the easy ones.

BUG=22

Change-Id: Ia00e41e26a134de17d56be3def5820cb042794e1
Reviewed-on: https://boringssl-review.googlesource.com/14265
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 21:59:49 +00:00
David Benjamin bbf4246546 Add a test that ALPN is rejected on renegotiation.
We've never allowed this as no good can come of it. Add a test for this.

Change-Id: I4b92372f58c1fe2054e33007adbe496d153a9251
Reviewed-on: https://boringssl-review.googlesource.com/14266
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 21:51:42 +00:00
David Benjamin 8cd7bbf514 Push password encoding back into pkcs12_key_gen.
With PKCS8_encrypt_pbe and PKCS8_decrypt_pbe gone in
3e8b782c0c, we can restore the old
arrangement where the password encoding was handled in pkcs12_key_gen.
This simplifies the interface for the follow-up crypto/asn1 split.

Note this change is *not* a no-op for PKCS#12 files which use PBES2.
Before, we would perform the PKCS#12 password encoding for all parts of
PKCS#12 processing. The new behavior is we only perform it for the parts
that go through the PKCS#12 KDF. For such a file, it would only be the
MAC.

I believe the specification supports our new behavior. Although RFC 7292
B.1 says something which implies that the transformation is about
converting passwords to byte strings and would thus be universal,
appendix B itself is prefaced with:

   Note that this method for password privacy mode is not recommended
   and is deprecated for new usage.  The procedures and algorithms
   defined in PKCS #5 v2.1 [13] [22] should be used instead.
   Specifically, PBES2 should be used as encryption scheme, with PBKDF2
   as the key derivation function.

"This method" refers to the key derivation and not the password
formatting, but it does give support to the theory that password
formatting is tied to PKCS#12 key derivation.

(Of course, if one believes PKCS#12's assertion that their inane
encoding (NUL-terminated UTF-16!) is because PKCS#5 failed to talk about
passwords as Unicode strings, one would think that PBES2 (also in
PKCS#5) would have the same issue and thus need PKCS#12 to valiantly
save the day with an encoding...)

This matches OpenSSL's behavior and that of recent versions of NSS. See
https://bugzilla.mozilla.org/show_bug.cgi?id=1268141. I was unable to
figure out what variants, if any, macOS accepts.

BUG=54

Change-Id: I9a1bb4d5e168e6e76b82241e4634b1103e620b9b
Reviewed-on: https://boringssl-review.googlesource.com/14213
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 21:25:30 +00:00
David Benjamin 3cb047e56c Decouple PKCS#12 hash lookup from the OID table.
This isn't strictly necessary for Chromium yet, but we already have a
decoupled version of hash algorithm parsing available. For now, don't
export it but eventually we may wish to use it for OCSP.

BUG=54

Change-Id: If460d38d48bd47a2b4a853779f210c0cf7ee236b
Reviewed-on: https://boringssl-review.googlesource.com/14211
Reviewed-by: Steven Valdez <svaldez@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 21:22:50 +00:00
Steven Valdez 2d85062c4f Add Data-less Zero-RTT support.
This adds support on the server and client to accept data-less early
data. The server will still fail to parse early data with any
contents, so this should remain disabled.

BUG=76

Change-Id: Id85d192d8e0360b8de4b6971511b5e8a0e8012f7
Reviewed-on: https://boringssl-review.googlesource.com/12921
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 21:00:18 +00:00
David Benjamin f35e8384a8 Fix parsing of PBKDF2 parameters.
The OPTIONAL prf field is an AlgorithmIdentifier, not an OID.  I messed
this up in the recent rewrite.

Fix the parsing and add a test, produced by commenting out the logic in
OpenSSL to omit the field for hmacWithSHA1. (We don't currently support
any other PBKDF2, or I'd just add a test for that.)

Change-Id: I7d258bb01b93cd203a6fc1b8cccbddfdbc4dbbad
Reviewed-on: https://boringssl-review.googlesource.com/14330
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 16:29:06 +00:00
David Benjamin 7179e53ea6 Remove TODO.
This isn't something we need to fix, just an explanatory comment.

Change-Id: I284e6580d176f981c6b161e9951f367fef1b1be6
Reviewed-on: https://boringssl-review.googlesource.com/14264
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 16:29:04 +00:00
David Benjamin 1d4fa785bc Decouple PBE lookup from the OID table.
BUG=54

Change-Id: Ia792dadcbda4efb22b45ae69a6e425ae2b341f61
Reviewed-on: https://boringssl-review.googlesource.com/14210
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-25 16:28:44 +00:00
David Benjamin cfb9d147bb Update pkcs8 error data.
We forgot to run the script at some point.

Change-Id: I0bd142fdd13d64c1ed81d9b1515449220d1c936b
Reviewed-on: https://boringssl-review.googlesource.com/14329
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-23 15:07:28 +00:00
David Benjamin c90ed1901d Tidy up error-handling around computing the hash in PSS.
EVP_DigestUpdate can tolerate zero length inputs. Also properly clean up
ctx in all codepaths.

Change-Id: I90889c6236f6bf74625ba9f967de36949a9a6f83
Reviewed-on: https://boringssl-review.googlesource.com/14327
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-23 15:07:08 +00:00
David Benjamin 96e744c176 Decouple PKCS#5 cipher lookup from OID table.
We still need to expose a suitable API for Chromium to consume, but the
core implementation itself should now be ready.

The supported cipher list is based on what EVP_get_cipherbynid currently
supports, excluding the entries which don't have OIDs.

BUG=54

Change-Id: I3befca0a34b330ec1f663a029a8fbf049a4406bd
Reviewed-on: https://boringssl-review.googlesource.com/14212
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-22 18:30:24 +00:00
David Benjamin 9292632c8d Add some PSS test vectors with non-zero salt length.
Change-Id: I8c8341fef2c141aa2460f634b596856f40cbbaba
Reviewed-on: https://boringssl-review.googlesource.com/14326
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-22 17:53:10 +00:00
David Benjamin 5e2d0c929c Add some more RSA-PSS verification tests.
Playing around with the code, we seem to have sufficient positive test
vectors for the logic around the high bits, but not negative test
vectors. Add some. Also add a negative test vector for the trailing
byte.

(For future reference, use openssl rsautl -raw for raw RSA operations
and openssl pkeyutil for EVP_PKEY_sign.)

Change-Id: I36eddf048e51e037fd924902cd13dcb3c62bfd02
Reviewed-on: https://boringssl-review.googlesource.com/14325
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-22 17:47:40 +00:00
Alessandro Ghedini 57e81e666a Name |select_certificate_cb| return values
The |select_certificate_cb| return values are somewhat confusing due
to the fact that they don't match the |cert_cb| ones, despite the
similarities between the two callbacks (they both have "certificate" in
the name! well, sort of).

This also documents the error return value (-1) which was previously
undocumented, and it expands the |SSL_CTX_set_select_certificate_cb|
documentation regarding retrial (by shamelessly copying from
|SSL_CTX_set_ticket_aead_method|).

Also updates other scattered documentation that was missed by previous
changes.

Change-Id: Ib962b31d08e6475e09954cbc3c939988b0ba13f7
Reviewed-on: https://boringssl-review.googlesource.com/14245
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-22 01:27:00 +00:00
Matthew Braithwaite cedc6f1824 Remove DHE ciphersuites from TLS.
They can be restored by compiling with -DBORINGSSL_ENABLE_DHE_TLS.

This is similar to 9c8c4188 for RC4 ciphers.

Change-Id: I7cd3421b108a024f1ee11f13a6df881c2d0de3c3
Reviewed-on: https://boringssl-review.googlesource.com/14284
Commit-Queue: Matt Braithwaite <mab@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 23:55:10 +00:00
David Benjamin d851842228 Reduce crypto/pkcs8 dependency on OID table.
To remove the OID table from Chromium, we'll need to decouple a lot of
this code. In preparation for that, detach the easy cases from the OID
table. What remains is PBES, cipher, and digest OIDs which will be doing
in follow-up changes.

BUG=54

Change-Id: Ie205d23d042e21114ca1faf68917fdc870969d09
Reviewed-on: https://boringssl-review.googlesource.com/14209
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 21:10:00 +00:00
David Benjamin aea20c15c9 Fix potential memory leak in ASN1_TIME_to_generalizedtime()
If ret is allocated, it may be leaked on error.

(Imported from upstream's cdfb7809b6a365a0a7874afd8f8778c5c572f267 and
ffcdb0e6efb6fb7033b2cd29e8cca2e2fe355c14.)

Change-Id: I50ed9ad072cf80461d9527d0834b596a8c32e3d3
Reviewed-on: https://boringssl-review.googlesource.com/14315
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 18:10:51 +00:00
David Benjamin 5c12778948 Convert bio_test to GTest.
BUG=129

Change-Id: Iaf07075afaa2ea447e19a8c53ec0d29560d625b3
Reviewed-on: https://boringssl-review.googlesource.com/14207
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 17:39:57 +00:00
David Benjamin 2d05568a7b Fix out-of-memory condition in conf.
conf has the ability to expand variables in config files. Repeatedly doing
this can lead to an exponential increase in the amount of memory required.
This places a limit on the length of a value that can result from an
expansion.

Credit to OSS-Fuzz for finding this problem.

(Imported from upstream's 6a6213556a80ab0a9eb926a1d6023b8bf44f2afd. This
also import's upstream's ee1ccd0a41ad068957fe65ba7521e593b51bbad4 which
we had previously missed.)

Change-Id: I9be06a7e8a062b5adcd00c974a7b245226123563
Reviewed-on: https://boringssl-review.googlesource.com/14316
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 16:19:22 +00:00
David Benjamin fd67f61bb4 Fix bounds check in RSA_verify_PKCS1_PSS_mgf1 when sLen is -2.
(Imported from upstream's 04cf39207f94abf89b3964c7710f22f829a1a78f.)

The other half of the change was fixed earlier, but this logic was still
off. This code is kind of a mess and needs a rewrite, but import the
change to get it correct and sufficiently tested first.

(If we could take the sLen = -2 case away altogether, that would be
great...)

Change-Id: I5786e980f26648822633fc216315e8f77ed4d45b
Reviewed-on: https://boringssl-review.googlesource.com/14321
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 16:17:19 +00:00
David Benjamin 5916207dd3 Improve RSA-PSS test coverage around length bounds.
One test case is commented out, to be fixed in a follow-up.

Change-Id: I543c7f54e63837c6e8088fdcbb03226e0144b2e5
Reviewed-on: https://boringssl-review.googlesource.com/14320
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 16:15:32 +00:00
David Benjamin 8c6467976c Remove BIGNUM and CBIGNUM crypto/asn1 types.
These too appear to be unused now that the core parsers use CBS. They
also were buggy as they silently ignored sign bits. This removes all
ASN1_PRIMITIVE_FUNCS definitions.  (The code to use them still exists as
we're not ready to diverge on tasn_*. Current thinking is we'll
eventually just ditch the code rather than do so.)

Change-Id: I8d20e2989460dd593d62368cfbd083d5de1ee2a1
Reviewed-on: https://boringssl-review.googlesource.com/14324
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 16:07:05 +00:00
David Benjamin eb3028847e Remove crypto/asn1 LONG and ZLONG.
These have no consumers remaining. Upstream recently had a long series
of bugfixes for these types (2cbd4d98673d99cd7cb10715656b6d3727342e77,
e5afec1831248c767be7c5844a88535dabecc01a,
9abe889702bdc73f9490f611f54bf9c865702554,
2e5adeb2904dd68780fb154dbeb6e3efafb418bb). Rather than worry about this,
just remove the code.

Change-Id: I90f896aad096fc4979877e2006131e76c9ff023b
Reviewed-on: https://boringssl-review.googlesource.com/14323
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 16:06:23 +00:00
David Benjamin 2ddc461a3f Add additional RSA-PSS and RSA-OAEP tests.
Import test data from:
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip

This is a set of RSA-PSS and RSA-OAEP test vectors including some edge cases
with unusual key sizes.

(Imported from upstream's 946a515a2b370dbadb1f8c39e3586a8f1e3cff1a.)

Change-Id: I1d8aa85a8578e47b26c74bb4e4c246975619d574
Reviewed-on: https://boringssl-review.googlesource.com/14318
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 14:55:36 +00:00
David Benjamin 6a53b99f34 Fix generate-coverage.sh.
It was not updated to exclude GTest. (Sometime later we really should
just write a productionized version of this that runs automatically and
portably. Preferably not in bash.)

Change-Id: I99c9d2370fa0a35641a9905e071b96b7fbd7a993
Reviewed-on: https://boringssl-review.googlesource.com/14319
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 14:54:47 +00:00
David Benjamin 076c6a3389 Fix a memory leak in X509_STORE_add_cert/crl error handling.
(Imported from upstream's c8ee68aa28889a1b7824ee399262536202f27cc0.)

Change-Id: If794793f766bf70fb35b60274e74d581fcb2b9de
Reviewed-on: https://boringssl-review.googlesource.com/14317
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 14:51:17 +00:00
David Benjamin aefc6b27e1 Fix a crash in print_notice.
(Imported from upstream's e6c53b0ced916633c8038736fde5613bf5b3e0dc.)

Change-Id: I165ce6ab9a162cb14a93ac8cab2e1f44a60fe961
Reviewed-on: https://boringssl-review.googlesource.com/14322
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 14:50:26 +00:00
David Benjamin b228541129 Convert asn1_test to GTest.
BUG=129

Change-Id: I0af881c6f50a558a220853084e53189b8919e41e
Reviewed-on: https://boringssl-review.googlesource.com/14206
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-21 14:31:01 +00:00
David Benjamin 73812e06b0 Fix SSLv3 version check in BoGo.
Static RSA key exchange in SSLv3 does not have a length prefix. We were
checking the ClientHello version rather than the final version.

Change-Id: I2d0e9d3b5a368a7caf8b1ca69f1631400a847f52
Reviewed-on: https://boringssl-review.googlesource.com/14314
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: Matt Braithwaite <mab@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-20 22:12:16 +00:00
Alessandro Ghedini edb729959f Fix typo in the |ssl_ticket_aead_success| documentation
Change-Id: I6d07a8e146a925a14dbf5d11b4e8a57ef6eee39c
Reviewed-on: https://boringssl-review.googlesource.com/14244
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-20 19:10:10 +00:00
Alessandro Ghedini 3c8652d0c6 tool: fix typo in -root-certs description
Without the space the help output is:

    Implies thatverification is required.

Change-Id: If7ff91ef70f2d968da5f8c76de562996c83dff2f
Reviewed-on: https://boringssl-review.googlesource.com/14246
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-20 17:39:42 +00:00
Victor Vasiliev 438229a8d7 Correct a typo in ASN.1 type name.
Change-Id: I5879d78ce22163c66bf8e4c05f3a7d1b6dbbd9d9
Reviewed-on: https://boringssl-review.googlesource.com/14304
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-16 21:57:58 +00:00
David Benjamin 48e1d180a4 Restore SSL_CTX_set_ecdh_auto compatibility hook.
This was inadvertently dropped in
59015c365b. Python otherwise configures
P-256 if it assumes our OpenSSL predate's 1.0.2's multi-curve support.
This disables X25519, our preferred curve.

Change-Id: Ibf758583ea53e68c56667f16ee7096656bac719b
Reviewed-on: https://boringssl-review.googlesource.com/14208
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-14 14:54:45 +00:00
Adam Langley 2070f8ad91 Apply bugs to second, TLS 1.3 ClientHello.
Based on elements of the Bugs structure, runner will tweak a ClientHello
message after parsing. However, unless the same tweaks are made to a
second ClientHello in a TLS 1.3 connection, it might appear that they
don't match.

Change-Id: I4467c8ece12dc75c7c7b0fad9e622e6783c55f21
Reviewed-on: https://boringssl-review.googlesource.com/14224
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-11 16:33:50 +00:00
David Benjamin 707af294a8 Support asynchronous ticket decryption with TLS 1.3.
This shuffles a bit of the code around session resumption in TLS 1.3 to
make the async point cleaner to inject. It also fills in cipher and
tlsext_hostname more uniformly.

Filling in the cipher on resumption is a no-op as SSL_SESSION_dup
already copies it, but avoids confusion should we ever implement TLS
1.3's laxer cipher matching on the server. Not filling in
tlsext_hostname on resumption was an oversight; the relevant check isn't
whether we are resuming but whether we have a fresh SSL_SESSION to fill
things into.

Change-Id: Ic02eb079ff228ce4a4d3e0de7445e18cd367e8b2
Reviewed-on: https://boringssl-review.googlesource.com/14205
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-11 00:05:29 +00:00
Adam Langley 4c341d0299 Support asynchronous ticket decryption with TLS 1.0–1.2.
This change adds support for setting an |SSL_TICKET_AEAD_METHOD| which
allows a caller to control ticket encryption and decryption to a greater
extent than previously possible and also permits asynchronous ticket
decryption.

This change only includes partial support: TLS 1.3 work remains to be
done.

Change-Id: Ia2e10ebb3257e1a119630c463b6bf389cf20ef18
Reviewed-on: https://boringssl-review.googlesource.com/14144
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-11 00:04:18 +00:00
David Benjamin be49706c42 Rename initial_ctx to session_ctx.
This makes its purpose clearer. That the session cache is based on the
initial SSL_CTX is confusing (it's a remnant of OpenSSL's backwards
session resumption ordering), but we're probably stuck with it.
Relatedly, document SSL_set_SSL_CTX better.

Change-Id: I2832efc63f6c959c5424271b365825afc7eec5e4
Reviewed-on: https://boringssl-review.googlesource.com/14204
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-10 22:50:46 +00:00
David Benjamin 93103177a5 Remove 'file:' feature in v3_pci.c's CONF hooks.
This makes it easier to build a subset of BoringSSL which doesn't depend
on the filesystem (though perhaps it's worth a build define for that
now). This hook is also generally surprising. CONF hooks are bad enough
when they don't open arbitrary files.

Change-Id: Ibf791162dd3d4cec8117eb49ff0cd716a1c54abd
Reviewed-on: https://boringssl-review.googlesource.com/14166
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-10 17:12:55 +00:00
David Benjamin 91222b8d38 Fix configuring the empty cipher list.
Although it returns failure, the cipher list should still be updated.
Conscrypt relies on this behavior to support a Java API edge case.

Change-Id: If58efafc6a4a81e85a0e2ee2c38873a7a4938123
Reviewed-on: https://boringssl-review.googlesource.com/14165
Reviewed-by: Kenny Root <kroot@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-10 01:20:25 +00:00
Matthew Braithwaite 6ad20dc912 Move error-on-empty-cipherlist into ssl_create_cipher_list().
It's more consistent to have the helper function do the check that
its every caller already performs.  This removes the error code
SSL_R_LIBRARY_HAS_NO_CIPHERS in favor of SSL_R_NO_CIPHER_MATCH.

Change-Id: I522239770dcb881d33d54616af386142ae41b29f
Reviewed-on: https://boringssl-review.googlesource.com/13964
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-09 17:31:45 +00:00
Steven Valdez 130d529b71 Adding version to AEAD.
This in preparation of 0-RTT which needs the AEAD version as part of
early data, before the full version negotiation.

BUG=76

Change-Id: Ief68bc69d794da6e55bb9208977b35f3b947273b
Reviewed-on: https://boringssl-review.googlesource.com/14104
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-08 19:12:39 +00:00
Adam Langley d04ca95356 Add |SSL[_CTX]_set_chain_and_key|.
This allows a caller to configure a serving chain without dealing with
crypto/x509.

Change-Id: Ib42bb2ab9227d32071cf13ab07f92d029643a9a6
Reviewed-on: https://boringssl-review.googlesource.com/14126
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-08 19:11:57 +00:00
Adam Langley c77ea04c81 Enable RSA AVX2 code.
This was disabled because we couldn't test it. We now have SDE for
testing which, even if it's not running on a builder yet, confirms that
this passes tests for all current and past Intel chips.

Change-Id: Iad74cc9944ee85557bb45c981751f84f335fb6c8
Reviewed-on: https://boringssl-review.googlesource.com/14010
Commit-Queue: Adam Langley <alangley@gmail.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-03-08 17:28:12 +00:00
David Benjamin 35ac5b7500 Export server-side ticket_age skew.
We'll measure this value to guide what tolerance to use in the 0-RTT
anti-replay mechanism. This also fixes a bug where we were previously
minting ticket_age_add-less tickets on the server. Add a check to reject
all those tickets.

BUG=113

Change-Id: I68e690c0794234234e0d0500b4b9a7f79aea641e
Reviewed-on: https://boringssl-review.googlesource.com/14068
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-08 14:59:01 +00:00
Adam Langley fe36672bf5 Allow users of the |CRYPTO_BUFFER|-based methods to verify certs after the handshake.
Previously, the |CRYPTO_BUFFER|-based methods always rejected
certificate chains because none of the current callbacks is suitable to
use. In the medium-term, we want an async callback for this but, for
now, we would like to get Chromium working. Chromium already installs a
no-op callback (except for the logic that was moved into BoringSSL in
a58baaf9e6) and so this hack will suffice
for Chromium.

Change-Id: Ie44b7b32b9e42f503c47b072e958507754136d72
Reviewed-on: https://boringssl-review.googlesource.com/14125
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-08 01:09:42 +00:00
Adam Langley 0cade989e7 Make the no-op verify function push an error.
(Otherwise it's a pretty opaque failure.)

Change-Id: I164b237eebe2641f2148bb705966da74b399a618
Reviewed-on: https://boringssl-review.googlesource.com/14124
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-08 01:03:05 +00:00
Brian Smith b6473199a3 Avoid the error case in |bn_mul_mont|.
On 32-bit x86, |bn_mul_mont| returns 0 when the modulus has less than
four limbs. Instead of calling |bn_mul_mont| and then falling back to
the |BN_mul|+|BN_from_montgomery_word| path for small moduli, just
avoid calling |bn_mul_mont| at all for small moduli.

This allows us to more clearly understand exactly when the fallback
code path, which is a timing side channel, is taken. This change makes
it easier to start minimizing this side channel.

The limit is set at 128 bits, which is four limbs on 32-bit and two
limbs on 64-bit platforms. Do this consistently on all platforms even
though it seems to be needed only for 32-bit x86, to minimize platform
variance: every platform uses the same cut-off in terms of input size.
128 bits is small enough to allow even questionably small curves, like
secp128r1, to use the |bn_mul_mont| path, and is way too small for RSA
and FFDH, so this change shouldn't have any security impact other than
the positive impact of simplifying the control flow.

Change-Id: I9b68ae33dc2c86b54ed4294839c7eca6a1dc11c0
Reviewed-on: https://boringssl-review.googlesource.com/14084
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-07 23:30:13 +00:00
David Benjamin 54689ed91e Move ssl_verify_alarm_type into ssl_x509.c.
It's only called from within that file.

Change-Id: I281c9eb1ea25d9cfbec492ba8a4d007f45ae2635
Reviewed-on: https://boringssl-review.googlesource.com/14027
Reviewed-by: Adam Langley <agl@google.com>
2017-03-07 23:14:16 +00:00
David Benjamin ab1d28e305 Trim x509.h includes.
There are still a few x509.h includes outside ssl_x509.c and ssl_file.c
due to referencing X509_V_* values, but otherwise these includes are no
longer needed.

Change-Id: Ide458e01358dc2ddb6838277d074ad249e599040
Reviewed-on: https://boringssl-review.googlesource.com/14026
Reviewed-by: Adam Langley <agl@google.com>
2017-03-07 23:13:49 +00:00
David Benjamin 8ebeabf0e2 Add SSL_CTX_get_ciphers.
This is an API from OpenSSL 1.1.0 which is a little risky to add ahead
of bumping OPENSSL_VERSION_NUMBER, but anything which currently builds
against BoringSSL already had an #ifdef due to the
ssl_cipher_preference_list_st business anyway.

Bump BORINGSSL_API_VERSION to make it easier to patch envoy for this.

BUG=6

Change-Id: If8307e30eb069bbd7dc4b8447b6e48e83899d584
Reviewed-on: https://boringssl-review.googlesource.com/14067
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-03 17:16:18 +00:00
David Benjamin f29c429324 Remove support for old-style SSL_PRIVATE_KEY_METHOD types.
Everything has been updated to return the ECDSA curve.

Change-Id: Iee8fafb576c0ff92d9a47304d59cc607b5faa112
Reviewed-on: https://boringssl-review.googlesource.com/14066
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-03 15:52:08 +00:00
David Benjamin f465461062 Add SSL_get0_peer_certificates.
This adds a CRYPTO_BUFFER getter for the peer certificate chain.  Other
things we need for Chromium:

- Verification callback. Ultimately, we want an asynchronous one, but a
  synchronous one will do for now.

- Configure client cert chain without X509

I've also removed the historical note about SSL_SESSION serialization.
That was years ago and we've since invalidated all serialized client
sessions.

BUG=671420

Change-Id: I2b3bb010f9182e751fc791cdfd7db44a4ec348e6
Reviewed-on: https://boringssl-review.googlesource.com/14065
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-03 02:17:31 +00:00
Steven Valdez 924a352d1b Remove experimental TLS 1.3 short record header extension.
Due to middlebox and ecosystem intolerance, short record headers are going to
be unsustainable to deploy.

BUG=119

Change-Id: I20fee79dd85bff229eafc6aeb72e4f33cac96d82
Reviewed-on: https://boringssl-review.googlesource.com/14044
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-02 22:39:17 +00:00
Steven Valdez 9ea9f9ce51 Updating fuzzer corpus
Change-Id: Iaf31cc5978322fb45aca43b39178ac998dabb11a
Reviewed-on: https://boringssl-review.googlesource.com/14064
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-02 22:26:38 +00:00
Adam Langley d6c22ee938 Add |SSL_get0_server_requested_CAs|.
This function is a |CRYPTO_BUFFER|-based method for getting the X.509
names from a CertificateRequest.

Change-Id: Ife26f726d3c1a055b332656678c2bc560b5a66ec
Reviewed-on: https://boringssl-review.googlesource.com/14013
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-02 21:04:53 +00:00
David Benjamin 919d8cf94e Sync util/bot with Chromium.
Change-Id: Iad15c9b824ca48e6c8a0e5f74fb2d296b3c1170e
Reviewed-on: https://boringssl-review.googlesource.com/14032
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-02 18:45:14 +00:00
Adam Langley 84cd49385c Don't pass |overhead_len| when testing “open” speed.
It's not needed and some compilers warn about it.

Change-Id: I45ace0db3e9773300387df9e319af4dd5a50d3dc
Reviewed-on: https://boringssl-review.googlesource.com/14011
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-02 18:38:16 +00:00
David Benjamin a58baaf9e6 Forbid the server certificate from changing on renego.
This allows us to move the code from Chrome into BoringSSL itself.

BUG=126

Change-Id: I04b4f63008a6de0a58dd6c685c78e9edd06deda6
Reviewed-on: https://boringssl-review.googlesource.com/14028
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-01 23:26:50 +00:00
David Benjamin ad8f5e1de9 Don't use long for timestamps.
This is the first part to fixing the SSL stack to be 2038-clean.
Internal structures and functions are switched to use OPENSSL_timeval
which, unlike timeval and long, are suitable for timestamps on all
platforms.

It is generally accepted that the year is now sometime after 1970, so
use uint64_t for the timestamps to avoid worrying about serializing
negative numbers in SSL_SESSION.

A follow-up change will fix SSL_CTX_set_current_time_cb to use
OPENSSL_timeval. This will require some coordinating with WebRTC.
DTLSv1_get_timeout is left alone for compatibility and because it stores
time remaining rather than an absolute time.

BUG=155

Change-Id: I1a5054813300874b6f29e348f9cd8ca80f6b9729
Reviewed-on: https://boringssl-review.googlesource.com/13944
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-01 21:58:38 +00:00
David Benjamin 7dd4e429a5 Convert x25519_test to GTest.
This also adds a few missing assertions (X25519 returns true in normal
cases and, even when it returns zero, it still writes to out.)

BUG=129

Change-Id: I63f7e9025f88b2ec309382b66fc915acca6513a9
Reviewed-on: https://boringssl-review.googlesource.com/14030
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-01 21:46:11 +00:00
David Benjamin 11c82895d7 Remove support for blocking DTLS timeout handling.
The DTLS stack has two very different APIs for handling timeouts. In
non-blocking mode, timeouts are driven externally by the caller with
DTLSv1_get_timeout. In blocking mode, timeouts are driven by the BIO by
calling a BIO_ctrl with BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT.

The latter is never used by consumers, so remove support for it.
BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT implicitly depends on struct timeval
being used for timestamps, which we would like to remove. Without this,
the only public API which relies on this is the testing-only
SSL_CTX_set_current_time_cb which is BoringSSL-only and we can change at
our leisure.

BUG=155

Change-Id: Ic68fa70afab2fa9e6286b84d010eac8ddc9d2ef4
Reviewed-on: https://boringssl-review.googlesource.com/13945
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-01 19:59:28 +00:00
David Benjamin 7e42999122 Convert evp_extra_test into GTest.
BUG=129

Change-Id: Ie64a445a42fb3a6d16818b1fabba8481e6e9ad94
Reviewed-on: https://boringssl-review.googlesource.com/14029
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-01 18:32:29 +00:00
Adam Langley 39425b0f36 Add |TLS_with_buffers_method|.
This allows a caller to get an |SSL_METHOD| that is free of crypto/x509.

Change-Id: I088e78310fd3ff5db453844784e7890659a633bf
Reviewed-on: https://boringssl-review.googlesource.com/14009
Reviewed-by: Adam Langley <agl@google.com>
2017-03-01 00:24:40 +00:00
Adam Langley d5c565a98d Name ssl_x509.c functions consistently.
All the other |X509_METHOD| functions have their type in the name. The
|CERT|-based functions happened not to because they were first, but
that's not a good reason.

Change-Id: I5bcd8a5fb1d1db6966686700e293d8b1361c0095
Reviewed-on: https://boringssl-review.googlesource.com/14007
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 23:33:05 +00:00
Adam Langley 94a62e61aa Hang ssl_auto_chain_if_needed off |X509_METHOD|.
Change-Id: I6609b0e62ea13d14578ccbd945803a27e01ed488
Reviewed-on: https://boringssl-review.googlesource.com/13972
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 23:07:02 +00:00
Adam Langley 2a3b3439c8 Move X509-related verification code into ssl_x509.c.
Change-Id: I9f94033036550ae85c98cd4e09584972b4441b5d
Reviewed-on: https://boringssl-review.googlesource.com/13971
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 22:57:34 +00:00
Adam Langley 415c010d4a Make all X509-related functions check the X509_METHOD.
We don't have a way to create an X509-less |SSL| yet but, when we do,
it'll be bad to call any X509-related functions on it. This change adds
an assert to every X509-related call to catch this.

Change-Id: Iec1bdf13baa587ee3487a7cfdc8a105bee20f5ca
Reviewed-on: https://boringssl-review.googlesource.com/13970
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 22:51:52 +00:00
Adam Langley 0bdef09263 Check CA names during the handshake.
Rather than store CA names and only find out that they're unparsable
when we're asked for a |STACK_OF(X509_NAME)|, check that we can parse
them all during the handshake. This avoids changing the semantics with
the previous change that kept CA names as |CRYPTO_BUFFER|s.

Change-Id: I0fc7a4e6ab01685347e7a5be0d0579f45b8a4818
Reviewed-on: https://boringssl-review.googlesource.com/13969
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 22:33:05 +00:00
Adam Langley 34b4c829fd Hold CA names as |CRYPTO_BUFFER|s.
This change converts the CA names that are parsed from a server's
CertificateRequest, as well as the CA names that are configured for
sending to clients in the same, to use |CRYPTO_BUFFER|.

The |X509_NAME|-based interfaces are turned into compatibility wrappers.

Change-Id: I95304ecc988ee39320499739a0866c7f8ff5ed98
Reviewed-on: https://boringssl-review.googlesource.com/13585
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 22:24:31 +00:00
Adam Langley 2ff7933f22 Add test for |SSL_get_client_CA_list|.
Change-Id: Ibea6a9d52b000876740097f98c6891db4772371b
Reviewed-on: https://boringssl-review.googlesource.com/14008
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 22:17:39 +00:00
David Benjamin 0d3c96337a Build with -fsanitize-address-use-after-scope if -DASAN=1
This would have caught
https://boringssl-review.googlesource.com/c/12400/ and similar classes
of errors with using CBB. A follow-up change will update the builders
to use -DASAN=1 for ASan.

Change-Id: I37817cb1d6bfd5c82ff0b0afaecc8bbbf506bb92
Reviewed-on: https://boringssl-review.googlesource.com/14025
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-02-28 20:07:09 +00:00
David Benjamin 591f251bf3 Remove direct calls to BN_mod_exp.
Within the library, we never need to exponentiate modulo an even number.
In fact, all the remaining BN_mod_exp calls are modulo an odd prime.
This extends 617804adc5 to the rest of the
library.

Change-Id: I4273439faa6a516c99673b28f8ae38ddfff7e42d
Reviewed-on: https://boringssl-review.googlesource.com/14024
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-02-28 18:00:02 +00:00
Adam Langley ba9557d0ef Benchmark open & seal separately for AES-GCM-SIV.
AES-GCM-SIV (potentially) runs at different speeds for opening and
sealing. (Since sealing is fundamentally two-pass, while opening need
not be.)

This change benchmarks AES-GCM-SIV for each direction.

Change-Id: Ic221c46eea7319ced8ef1f1dec0427b98f6a58ef
Reviewed-on: https://boringssl-review.googlesource.com/14004
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-28 17:41:35 +00:00
David Benjamin 218f51bcef Fix Android bots.
Change-Id: I62a14a52237cbcb1706df6ab63014370d9228be1
Reviewed-on: https://boringssl-review.googlesource.com/13946
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-02-27 23:18:25 +00:00
Adam Langley 898be92b67 Support P-224 certificates as a server.
Change-Id: I3bc1e46fb94104c4ae31c1c98fa0d5a931e5f954
Reviewed-on: https://boringssl-review.googlesource.com/13974
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-02-27 21:27:39 +00:00
413 changed files with 9200 additions and 8160 deletions
+2 -2
View File
@@ -221,8 +221,8 @@ if (ASAN)
message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
set(OPENSSL_NO_ASM "1")
endif()
+1 -1
View File
@@ -80,5 +80,5 @@ If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora
```
cd fuzz
./refresh_fuzzer_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
./refresh_ssl_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
```
+1
View File
@@ -227,6 +227,7 @@ parameter.
`SSL_CTRL_OPTIONS` | `SSL_CTX_get_options` or `SSL_CTX_set_options`
`SSL_CTRL_SESS_NUMBER` | `SSL_CTX_sess_number`
`SSL_CTRL_SET_CURVES` | `SSL_CTX_set1_curves`
`SSL_CTRL_SET_ECDH_AUTO` | `SSL_CTX_set_ecdh_auto`
`SSL_CTRL_SET_MAX_CERT_LIST` | `SSL_CTX_set_max_cert_list`
`SSL_CTRL_SET_MAX_SEND_FRAGMENT` | `SSL_CTX_set_max_send_fragment`
`SSL_CTRL_SET_MSG_CALLBACK` | `SSL_set_msg_callback`
+8 -11
View File
@@ -176,17 +176,6 @@ if(NOT MSVC AND NOT ANDROID)
target_link_libraries(crypto pthread)
endif()
add_executable(
constant_time_test
constant_time_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(constant_time_test crypto)
add_dependencies(all_tests constant_time_test)
add_executable(
thread_test
@@ -211,11 +200,16 @@ add_dependencies(all_tests refcount_test)
add_executable(
crypto_test
asn1/asn1_test.cc
bio/bio_test.cc
chacha/chacha_test.cc
constant_time_test.cc
curve25519/x25519_test.cc
dh/dh_test.cc
dsa/dsa_test.cc
ec/ec_test.cc
err/err_test.cc
evp/evp_extra_test.cc
rsa/rsa_test.cc
$<TARGET_OBJECTS:gtest_main>
@@ -223,4 +217,7 @@ add_executable(
)
target_link_libraries(crypto_test crypto gtest)
if (WIN32)
target_link_libraries(crypto_test ws2_32)
endif()
add_dependencies(all_tests crypto_test)
+10 -2
View File
@@ -1,4 +1,11 @@
#!/usr/bin/env perl
#! /usr/bin/env perl
# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -731,6 +738,7 @@ $code.=<<___;
.thumb
#else
.code 32
# undef __thumb2__
#endif
.type _bsaes_decrypt8,%function
@@ -1357,7 +1365,7 @@ bsaes_cbc_encrypt:
vmov @XMM[4],@XMM[15] @ just in case ensure that IV
vmov @XMM[5],@XMM[0] @ and input are preserved
bl AES_decrypt
vld1.8 {@XMM[0]}, [$fp,:64] @ load result
vld1.8 {@XMM[0]}, [$fp] @ load result
veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV
vmov @XMM[15], @XMM[5] @ @XMM[5] holds input
vst1.8 {@XMM[0]}, [$rounds] @ write output
-13
View File
@@ -36,17 +36,4 @@ add_library(
tasn_typ.c
tasn_utl.c
time_support.c
x_bignum.c
x_long.c
)
add_executable(
asn1_test
asn1_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(asn1_test crypto)
add_dependencies(all_tests asn1_test)
+17 -9
View File
@@ -114,7 +114,7 @@ int ASN1_TIME_check(ASN1_TIME *t)
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret;
ASN1_GENERALIZEDTIME *ret = NULL;
char *str;
int newlen;
@@ -123,22 +123,21 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
if (!out || !*out) {
if (!(ret = ASN1_GENERALIZEDTIME_new()))
return NULL;
if (out)
*out = ret;
} else
goto err;
} else {
ret = *out;
}
/* If already GeneralizedTime just copy across */
if (t->type == V_ASN1_GENERALIZEDTIME) {
if (!ASN1_STRING_set(ret, t->data, t->length))
return NULL;
return ret;
goto err;
goto done;
}
/* grow the string */
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
return NULL;
goto err;
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
newlen = t->length + 2 + 1;
str = (char *)ret->data;
@@ -150,9 +149,18 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
BUF_strlcat(str, (char *)t->data, newlen);
return ret;
done:
if (out != NULL && *out == NULL)
*out = ret;
return ret;
err:
if (out == NULL || *out != ret)
ASN1_GENERALIZEDTIME_free(ret);
return NULL;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
+12 -29
View File
@@ -14,10 +14,13 @@
#include <stdio.h>
#include <gtest/gtest.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../test/test_util.h"
// kTag128 is an ASN.1 structure with a universal tag with number 128.
static const uint8_t kTag128[] = {
@@ -38,42 +41,22 @@ static const uint8_t kTagOverflow[] = {
0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
};
static bool TestLargeTags() {
TEST(ASN1Test, LargeTags) {
const uint8_t *p = kTag258;
bssl::UniquePtr<ASN1_TYPE> obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
if (obj) {
fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type);
return false;
}
EXPECT_FALSE(obj) << "Parsed value with illegal tag" << obj->type;
ERR_clear_error();
p = kTagOverflow;
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow)));
if (obj) {
fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type);
return false;
}
EXPECT_FALSE(obj) << "Parsed value with tag overflow" << obj->type;
ERR_clear_error();
p = kTag128;
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128)));
if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 ||
obj->value.asn1_string->data[0] != 0) {
fprintf(stderr, "Failed to parse value with tag 128.\n");
ERR_print_errors_fp(stderr);
return false;
}
return true;
}
int main() {
CRYPTO_library_init();
if (!TestLargeTags()) {
return 1;
}
printf("PASS\n");
return 0;
ASSERT_TRUE(obj);
EXPECT_EQ(128, obj->type);
const uint8_t kZero = 0;
EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
obj->value.asn1_string->length));
}
-153
View File
@@ -1,153 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
/*
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
* since all BIGNUMs used are non negative and anything that looks negative
* is normally due to an encoding error.
*/
#define BN_SENSITIVE 1
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
NULL, 0,
bn_new,
bn_free,
0,
bn_c2i,
bn_i2c,
NULL /* prim_print */ ,
};
ASN1_ITEM_start(BIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
ASN1_ITEM_end(BIGNUM)
ASN1_ITEM_start(CBIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
ASN1_ITEM_end(CBIGNUM)
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*pval = (ASN1_VALUE *)BN_new();
if (*pval)
return 1;
else
return 0;
}
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if (!*pval)
return;
if (it->size & BN_SENSITIVE)
BN_clear_free((BIGNUM *)*pval);
else
BN_free((BIGNUM *)*pval);
*pval = NULL;
}
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
BIGNUM *bn;
int pad;
if (!*pval)
return -1;
bn = (BIGNUM *)*pval;
/* If MSB set in an octet we need a padding byte */
if (BN_num_bits(bn) & 0x7)
pad = 0;
else
pad = 1;
if (cont) {
if (pad)
*cont++ = 0;
BN_bn2bin(bn, cont);
}
return pad + BN_num_bytes(bn);
}
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
BIGNUM *bn;
if (!*pval) {
if (!bn_new(pval, it)) {
return 0;
}
}
bn = (BIGNUM *)*pval;
if (!BN_bin2bn(cont, len, bn)) {
bn_free(pval, it);
return 0;
}
return 1;
}
-200
View File
@@ -1,200 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
/*
* Custom primitive type for long handling. This converts between an
* ASN1_INTEGER and a long directly.
*/
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx);
static const ASN1_PRIMITIVE_FUNCS long_pf = {
NULL, 0,
long_new,
long_free,
long_free, /* Clear should set to initial value */
long_c2i,
long_i2c,
long_print
};
ASN1_ITEM_start(LONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
ASN1_ITEM_end(LONG)
ASN1_ITEM_start(ZLONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
ASN1_ITEM_end(ZLONG)
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
return 1;
}
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
}
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
long ltmp;
unsigned long utmp;
int clen, pad, i;
/* this exists to bypass broken gcc optimization */
char *cp = (char *)pval;
/* use memcpy, because we may not be long aligned */
OPENSSL_memcpy(&ltmp, cp, sizeof(long));
if (ltmp == it->size)
return -1;
/*
* Convert the long to positive: we subtract one if negative so we can
* cleanly handle the padding if only the MSB of the leading octet is
* set.
*/
if (ltmp < 0)
utmp = -ltmp - 1;
else
utmp = ltmp;
clen = BN_num_bits_word(utmp);
/* If MSB of leading octet set we need to pad */
if (!(clen & 0x7))
pad = 1;
else
pad = 0;
/* Convert number of bits to number of octets */
clen = (clen + 7) >> 3;
if (cont) {
if (pad)
*cont++ = (ltmp < 0) ? 0xff : 0;
for (i = clen - 1; i >= 0; i--) {
cont[i] = (unsigned char)(utmp & 0xff);
if (ltmp < 0)
cont[i] ^= 0xff;
utmp >>= 8;
}
}
return clen + pad;
}
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
int neg, i;
long ltmp;
unsigned long utmp = 0;
char *cp = (char *)pval;
if (len > (int)sizeof(long)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
/* Is it negative? */
if (len && (cont[0] & 0x80))
neg = 1;
else
neg = 0;
utmp = 0;
for (i = 0; i < len; i++) {
utmp <<= 8;
if (neg)
utmp |= cont[i] ^ 0xff;
else
utmp |= cont[i];
}
ltmp = (long)utmp;
if (neg) {
ltmp++;
ltmp = -ltmp;
}
if (ltmp == it->size) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
OPENSSL_memcpy(cp, &ltmp, sizeof(long));
return 1;
}
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
return BIO_printf(out, "%ld\n", *(long *)pval);
}
-14
View File
@@ -16,17 +16,3 @@ add_library(
socket.c
socket_helper.c
)
add_executable(
bio_test
bio_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(bio_test crypto)
if (WIN32)
target_link_libraries(bio_test ws2_32)
endif()
add_dependencies(all_tests bio_test)
+207 -318
View File
@@ -16,7 +16,18 @@
#define _POSIX_C_SOURCE 201410L
#endif
#include <openssl/base.h>
#include <algorithm>
#include <string>
#include <gtest/gtest.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
#include "../test/test_util.h"
#if !defined(OPENSSL_WINDOWS)
#include <arpa/inet.h>
@@ -33,27 +44,15 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <algorithm>
#include "../internal.h"
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
return close(sock);
}
static void PrintSocketError(const char *func) {
perror(func);
}
static int closesocket(int sock) { return close(sock); }
static std::string LastSocketError() { return strerror(errno); }
#else
static void PrintSocketError(const char *func) {
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
static std::string LastSocketError() {
char buf[DECIMAL_SIZE(int) + 1];
BIO_snprintf(buf, sizeof(buf), "%d", WSAGetLastError());
return buf;
}
#endif
@@ -68,356 +67,246 @@ class ScopedSocket {
const int sock_;
};
static bool TestSocketConnect() {
TEST(BIOTest, SocketConnect) {
static const char kTestMessage[] = "test";
// Set up a listening socket on localhost.
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listening_sock == -1) {
PrintSocketError("socket");
return false;
}
ASSERT_NE(-1, listening_sock) << LastSocketError();
ScopedSocket listening_sock_closer(listening_sock);
struct sockaddr_in sin;
OPENSSL_memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
PrintSocketError("inet_pton");
return false;
}
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
PrintSocketError("bind");
return false;
}
if (listen(listening_sock, 1)) {
PrintSocketError("listen");
return false;
}
ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr))
<< LastSocketError();
ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)))
<< LastSocketError();
ASSERT_EQ(0, listen(listening_sock, 1)) << LastSocketError();
socklen_t sockaddr_len = sizeof(sin);
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
sockaddr_len != sizeof(sin)) {
PrintSocketError("getsockname");
return false;
}
ASSERT_EQ(0,
getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len))
<< LastSocketError();
// The Android NDK, contrary to POSIX, makes |socklen_t| signed.
ASSERT_EQ(sizeof(sin), static_cast<size_t>(sockaddr_len));
// Connect to it with a connect BIO.
char hostname[80];
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
ntohs(sin.sin_port));
bssl::UniquePtr<BIO> bio(BIO_new_connect(hostname));
if (!bio) {
fprintf(stderr, "BIO_new_connect failed.\n");
return false;
}
ASSERT_TRUE(bio);
if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
sizeof(kTestMessage)) {
fprintf(stderr, "BIO_write failed.\n");
ERR_print_errors_fp(stderr);
return false;
}
// Write a test message to the BIO.
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)));
// Accept the socket.
int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
if (sock == -1) {
PrintSocketError("accept");
return false;
}
ASSERT_NE(-1, sock) << LastSocketError();
ScopedSocket sock_closer(sock);
char buf[5];
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
PrintSocketError("read");
return false;
}
if (OPENSSL_memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
return false;
}
return true;
// Check the same message is read back out.
char buf[sizeof(kTestMessage)];
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
recv(sock, buf, sizeof(buf), 0))
<< LastSocketError();
EXPECT_EQ(Bytes(kTestMessage, sizeof(kTestMessage)), Bytes(buf, sizeof(buf)));
}
static bool TestPrintf() {
TEST(BIOTest, Printf) {
// Test a short output, a very long one, and various sizes around
// 256 (the size of the buffer) to ensure edge cases are correct.
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
static const size_t kLengths[] = {5, 250, 251, 252, 253, 254, 1023};
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
if (!bio) {
fprintf(stderr, "BIO_new failed\n");
return false;
}
ASSERT_TRUE(bio);
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kLengths); i++) {
char string[1024];
if (kLengths[i] >= sizeof(string)) {
fprintf(stderr, "Bad test string length\n");
return false;
}
OPENSSL_memset(string, 'a', sizeof(string));
string[kLengths[i]] = '\0';
for (size_t length : kLengths) {
SCOPED_TRACE(length);
std::string in(length, 'a');
int ret = BIO_printf(bio.get(), "test %s", in.c_str());
ASSERT_GE(ret, 0);
EXPECT_EQ(5 + length, static_cast<size_t>(ret));
int ret = BIO_printf(bio.get(), "test %s", string);
if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
fprintf(stderr, "BIO_printf failed: %d\n", ret);
return false;
}
const uint8_t *contents;
size_t len;
if (!BIO_mem_contents(bio.get(), &contents, &len)) {
fprintf(stderr, "BIO_mem_contents failed\n");
return false;
}
if (len != 5 + kLengths[i] ||
strncmp((const char *)contents, "test ", 5) != 0 ||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
return false;
}
ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
EXPECT_EQ("test " + in,
std::string(reinterpret_cast<const char *>(contents), len));
if (!BIO_reset(bio.get())) {
fprintf(stderr, "BIO_reset failed\n");
return false;
}
ASSERT_TRUE(BIO_reset(bio.get()));
}
return true;
}
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
size_t expected_len, size_t max_len) {
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(data, data_len));
static const size_t kLargeASN1PayloadLen = 8000;
struct ASN1TestParam {
bool should_succeed;
std::vector<uint8_t> input;
// suffix_len is the number of zeros to append to |input|.
size_t suffix_len;
// expected_len, if |should_succeed| is true, is the expected length of the
// ASN.1 element.
size_t expected_len;
size_t max_len;
} kASN1TestParams[] = {
{true, {0x30, 2, 1, 2, 0, 0}, 0, 4, 100},
{false /* truncated */, {0x30, 3, 1, 2}, 0, 0, 100},
{false /* should be short len */, {0x30, 0x81, 1, 1}, 0, 0, 100},
{false /* zero padded */, {0x30, 0x82, 0, 1, 1}, 0, 0, 100},
// Test a large payload.
{true,
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
kLargeASN1PayloadLen,
4 + kLargeASN1PayloadLen,
kLargeASN1PayloadLen * 2},
{false /* max_len too short */,
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
kLargeASN1PayloadLen,
4 + kLargeASN1PayloadLen,
3 + kLargeASN1PayloadLen},
// Test an indefinite-length input.
{true,
{0x30, 0x80},
kLargeASN1PayloadLen + 2,
2 + kLargeASN1PayloadLen + 2,
kLargeASN1PayloadLen * 2},
{false /* max_len too short */,
{0x30, 0x80},
kLargeASN1PayloadLen + 2,
2 + kLargeASN1PayloadLen + 2,
2 + kLargeASN1PayloadLen + 1},
};
class BIOASN1Test : public testing::TestWithParam<ASN1TestParam> {};
TEST_P(BIOASN1Test, ReadASN1) {
const ASN1TestParam& param = GetParam();
std::vector<uint8_t> input = param.input;
input.resize(input.size() + param.suffix_len, 0);
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(input.data(), input.size()));
ASSERT_TRUE(bio);
uint8_t *out;
size_t out_len;
int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
int ok = BIO_read_asn1(bio.get(), &out, &out_len, param.max_len);
if (!ok) {
out = nullptr;
}
bssl::UniquePtr<uint8_t> out_storage(out);
if (should_succeed != (ok == 1)) {
return false;
ASSERT_EQ(param.should_succeed, (ok == 1));
if (param.should_succeed) {
EXPECT_EQ(Bytes(input.data(), param.expected_len), Bytes(out, out_len));
}
if (should_succeed && (out_len != expected_len ||
OPENSSL_memcmp(data, out, expected_len) != 0)) {
return false;
}
return true;
}
static bool TestASN1() {
static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */
static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */
static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */
INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
!ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
!ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
!ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
return false;
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
class BIOPairTest : public testing::TestWithParam<bool> {};
TEST_P(BIOPairTest, TestPair) {
BIO *bio1, *bio2;
ASSERT_TRUE(BIO_new_bio_pair(&bio1, 10, &bio2, 10));
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
if (GetParam()) {
std::swap(bio1, bio2);
}
static const size_t kLargePayloadLen = 8000;
static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
kLargePayloadLen & 0xff};
bssl::UniquePtr<uint8_t> large(reinterpret_cast<uint8_t *>(
OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
if (!large) {
return false;
}
OPENSSL_memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
OPENSSL_memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
// Check initial states.
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen * 2)) {
fprintf(stderr, "Large payload test failed.\n");
return false;
}
// Data written in one end may be read out the other.
uint8_t buf[20];
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen - 1)) {
fprintf(stderr, "max_len test failed.\n");
return false;
}
// Attempting to write more than 10 bytes will write partially.
EXPECT_EQ(10, BIO_write(bio1, "1234567890___", 13));
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(-1, BIO_write(bio1, "z", 1));
EXPECT_TRUE(BIO_should_write(bio1));
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("1234567890"), Bytes(buf, 10));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
static const uint8_t kIndefPrefix[] = {0x30, 0x80};
OPENSSL_memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen*2)) {
fprintf(stderr, "indefinite length test failed.\n");
return false;
}
// Unsuccessful reads update the read request.
EXPECT_EQ(-1, BIO_read(bio2, buf, 5));
EXPECT_TRUE(BIO_should_read(bio2));
EXPECT_EQ(5u, BIO_ctrl_get_read_request(bio1));
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen-1)) {
fprintf(stderr, "indefinite length, max_len test failed.\n");
return false;
}
// The read request is clamped to the size of the buffer.
EXPECT_EQ(-1, BIO_read(bio2, buf, 20));
EXPECT_TRUE(BIO_should_read(bio2));
EXPECT_EQ(10u, BIO_ctrl_get_read_request(bio1));
return true;
// Data may be written and read in chunks.
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(5, BIO_write(bio1, "67890___", 8));
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
EXPECT_EQ(Bytes("123"), Bytes(buf, 3));
EXPECT_EQ(3u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(7, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("4567890"), Bytes(buf, 7));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
// Successful reads reset the read request.
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
// Test writes and reads starting in the middle of the ring buffer and
// wrapping to front.
EXPECT_EQ(8, BIO_write(bio1, "abcdefgh", 8));
EXPECT_EQ(2u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
EXPECT_EQ(Bytes("abc"), Bytes(buf, 3));
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(5, BIO_write(bio1, "ijklm___", 8));
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("defghijklm"), Bytes(buf, 10));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
// Data may flow from both ends in parallel.
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_EQ(5, BIO_write(bio2, "67890", 5));
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
EXPECT_EQ(Bytes("67890"), Bytes(buf, 5));
// Closing the write end causes an EOF on the read half, after draining.
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_TRUE(BIO_shutdown_wr(bio1));
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
EXPECT_EQ(0, BIO_read(bio2, buf, sizeof(buf)));
// A closed write end may not be written to.
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(-1, BIO_write(bio1, "_____", 5));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_BIO, ERR_GET_LIB(err));
EXPECT_EQ(BIO_R_BROKEN_PIPE, ERR_GET_REASON(err));
// The other end is still functional.
EXPECT_EQ(5, BIO_write(bio2, "12345", 5));
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
}
static bool TestPair() {
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
for (int i = 0; i < 2; i++) {
BIO *bio1, *bio2;
if (!BIO_new_bio_pair(&bio1, 10, &bio2, 10)) {
return false;
}
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
if (i == 1) {
std::swap(bio1, bio2);
}
// Check initial states.
if (BIO_ctrl_get_write_guarantee(bio1) != 10 ||
BIO_ctrl_get_read_request(bio1) != 0) {
return false;
}
// Data written in one end may be read out the other.
char buf[20];
if (BIO_write(bio1, "12345", 5) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Attempting to write more than 10 bytes will write partially.
if (BIO_write(bio1, "1234567890___", 13) != 10 ||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_write(bio1, "z", 1) != -1 ||
!BIO_should_write(bio1) ||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
OPENSSL_memcmp(buf, "1234567890", 10) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Unsuccessful reads update the read request.
if (BIO_read(bio2, buf, 5) != -1 ||
!BIO_should_read(bio2) ||
BIO_ctrl_get_read_request(bio1) != 5) {
return false;
}
// The read request is clamped to the size of the buffer.
if (BIO_read(bio2, buf, 20) != -1 ||
!BIO_should_read(bio2) ||
BIO_ctrl_get_read_request(bio1) != 10) {
return false;
}
// Data may be written and read in chunks.
if (BIO_write(bio1, "12345", 5) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
BIO_write(bio1, "67890___", 8) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_read(bio2, buf, 3) != 3 ||
OPENSSL_memcmp(buf, "123", 3) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 3 ||
BIO_read(bio2, buf, sizeof(buf)) != 7 ||
OPENSSL_memcmp(buf, "4567890", 7) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Successful reads reset the read request.
if (BIO_ctrl_get_read_request(bio1) != 0) {
return false;
}
// Test writes and reads starting in the middle of the ring buffer and
// wrapping to front.
if (BIO_write(bio1, "abcdefgh", 8) != 8 ||
BIO_ctrl_get_write_guarantee(bio1) != 2 ||
BIO_read(bio2, buf, 3) != 3 ||
OPENSSL_memcmp(buf, "abc", 3) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
BIO_write(bio1, "ijklm___", 8) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
OPENSSL_memcmp(buf, "defghijklm", 10) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Data may flow from both ends in parallel.
if (BIO_write(bio1, "12345", 5) != 5 ||
BIO_write(bio2, "67890", 5) != 5 ||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "67890", 5) != 0) {
return false;
}
// Closing the write end causes an EOF on the read half, after draining.
if (BIO_write(bio1, "12345", 5) != 5 ||
!BIO_shutdown_wr(bio1) ||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
BIO_read(bio2, buf, sizeof(buf)) != 0) {
return false;
}
// A closed write end may not be written to.
if (BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_write(bio1, "_____", 5) != -1) {
return false;
}
uint32_t err = ERR_get_error();
if (ERR_GET_LIB(err) != ERR_LIB_BIO ||
ERR_GET_REASON(err) != BIO_R_BROKEN_PIPE) {
return false;
}
// The other end is still functional.
if (BIO_write(bio2, "12345", 5) != 5 ||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0) {
return false;
}
}
return true;
}
int main() {
CRYPTO_library_init();
#if defined(OPENSSL_WINDOWS)
// Initialize Winsock.
WORD wsa_version = MAKEWORD(2, 2);
WSADATA wsa_data;
int wsa_err = WSAStartup(wsa_version, &wsa_data);
if (wsa_err != 0) {
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
return 1;
}
if (wsa_data.wVersion != wsa_version) {
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
return 1;
}
#endif
if (!TestSocketConnect() ||
!TestPrintf() ||
!TestASN1() ||
!TestPair()) {
return 1;
}
printf("PASS\n");
return 0;
}
INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true));
+2 -2
View File
@@ -84,8 +84,8 @@ die "can't locate x86_64-xlate.pl";
# output, so this isn't useful anyway.
#
# TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1.
$avx = 0;
$addx = 0;
$avx = 2;
$addx = 1;
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
*STDOUT = *OUT;
+36 -15
View File
@@ -125,6 +125,11 @@
#define OPENSSL_BN_ASM_MONT
#endif
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx);
BN_MONT_CTX *BN_MONT_CTX_new(void) {
BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
@@ -361,27 +366,43 @@ err:
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx) {
BIGNUM *tmp;
int ret = 0;
#if defined(OPENSSL_BN_ASM_MONT)
#if !defined(OPENSSL_BN_ASM_MONT)
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
#else
int num = mont->N.top;
if (num > 1 && a->top == num && b->top == num) {
if (bn_wexpand(r, num) == NULL) {
return 0;
}
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
r->neg = a->neg ^ b->neg;
r->top = num;
bn_correct_top(r);
return 1;
}
/* |bn_mul_mont| requires at least 128 bits of limbs, at least for x86. */
if (num < (128 / BN_BITS2) ||
a->top != num ||
b->top != num) {
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
}
if (bn_wexpand(r, num) == NULL) {
return 0;
}
if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
/* The check above ensures this won't happen. */
assert(0);
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
return 0;
}
r->neg = a->neg ^ b->neg;
r->top = num;
bn_correct_top(r);
return 1;
#endif
}
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
const BIGNUM *b,
const BN_MONT_CTX *mont,
BN_CTX *ctx) {
int ret = 0;
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
BIGNUM *tmp = BN_CTX_get(ctx);
if (tmp == NULL) {
goto err;
}
+4 -4
View File
@@ -148,7 +148,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
}
q->neg = 0;
if (!BN_add_word(q, 1) ||
!BN_mod_exp(ret, A, q, p, ctx)) {
!BN_mod_exp_mont(ret, A, q, p, ctx, NULL)) {
goto end;
}
err = 0;
@@ -193,7 +193,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
goto end;
}
q->neg = 0;
if (!BN_mod_exp(b, t, q, p, ctx)) {
if (!BN_mod_exp_mont(b, t, q, p, ctx, NULL)) {
goto end;
}
@@ -281,7 +281,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
/* Now that we have some non-square, we can find an element
* of order 2^e by computing its q'th power. */
if (!BN_mod_exp(y, y, q, p, ctx)) {
if (!BN_mod_exp_mont(y, y, q, p, ctx, NULL)) {
goto end;
}
if (BN_is_one(y)) {
@@ -327,7 +327,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
goto end;
}
} else {
if (!BN_mod_exp(x, A, t, p, ctx)) {
if (!BN_mod_exp_mont(x, A, t, p, ctx, NULL)) {
goto end;
}
if (BN_is_zero(x)) {
+1 -1
View File
@@ -38,7 +38,7 @@ static int is_string_type(unsigned tag) {
case CBS_ASN1_UTF8STRING:
case CBS_ASN1_NUMERICSTRING:
case CBS_ASN1_PRINTABLESTRING:
case CBS_ASN1_T16STRING:
case CBS_ASN1_T61STRING:
case CBS_ASN1_VIDEOTEXSTRING:
case CBS_ASN1_IA5STRING:
case CBS_ASN1_GRAPHICSTRING:
+6 -6
View File
@@ -262,24 +262,24 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
/* Remove CBC padding. Code from here on is timing-sensitive with respect to
* |padding_ok| and |data_plus_mac_len| for CBC ciphers. */
unsigned padding_ok, data_plus_mac_len;
size_t padding_ok, data_plus_mac_len;
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
if (!EVP_tls_cbc_remove_padding(
&padding_ok, &data_plus_mac_len, out, total,
EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
(unsigned)HMAC_size(&tls_ctx->hmac_ctx))) {
HMAC_size(&tls_ctx->hmac_ctx))) {
/* Publicly invalid. This can be rejected in non-constant time. */
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
} else {
padding_ok = ~0u;
padding_ok = CONSTTIME_TRUE_S;
data_plus_mac_len = total;
/* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
* already been checked against the MAC size at the top of the function. */
assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
}
unsigned data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
size_t data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
/* At this point, if the padding is valid, the first |data_plus_mac_len| bytes
* after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is
@@ -332,8 +332,8 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
* safe to simply perform the padding check first, but it would not be under a
* different choice of MAC location on padding failure. See
* EVP_tls_cbc_remove_padding. */
unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len),
0);
size_t good =
constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len), 0);
good &= padding_ok;
if (!good) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+5 -6
View File
@@ -110,9 +110,9 @@ struct evp_aead_st {
* If the function returns one, it runs in time independent of the contents of
* |in|. It is also guaranteed that |*out_len| >= |mac_size|, satisfying
* |EVP_tls_cbc_copy_mac|'s precondition. */
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
const uint8_t *in, unsigned in_len,
unsigned block_size, unsigned mac_size);
int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
const uint8_t *in, size_t in_len,
size_t block_size, size_t mac_size);
/* EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first
* |in_len| bytes of |in| to |out| in constant time (independent of the concrete
@@ -122,9 +122,8 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
* On entry:
* orig_len >= in_len >= md_size
* md_size <= EVP_MAX_MD_SIZE */
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
const uint8_t *in, unsigned in_len,
unsigned orig_len);
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
size_t in_len, size_t orig_len);
/* EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function
* which EVP_tls_cbc_digest_record supports. */
+104 -102
View File
@@ -73,20 +73,19 @@
* supported by TLS.) */
#define MAX_HASH_BLOCK_SIZE 128
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
const uint8_t *in, unsigned in_len,
unsigned block_size, unsigned mac_size) {
unsigned padding_length, good, to_check, i;
const unsigned overhead = 1 /* padding length byte */ + mac_size;
int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
const uint8_t *in, size_t in_len,
size_t block_size, size_t mac_size) {
const size_t overhead = 1 /* padding length byte */ + mac_size;
/* These lengths are all public so we can test them in non-constant time. */
if (overhead > in_len) {
return 0;
}
padding_length = in[in_len - 1];
size_t padding_length = in[in_len - 1];
good = constant_time_ge(in_len, overhead + padding_length);
size_t good = constant_time_ge_s(in_len, overhead + padding_length);
/* The padding consists of a length byte at the end of the record and
* then that many bytes of padding, all with the same value as the
* length byte. Thus, with the length byte included, there are i+1
@@ -96,12 +95,12 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
* decrypted information. Therefore we always have to check the maximum
* amount of padding possible. (Again, the length of the record is
* public information so we can use it.) */
to_check = 256; /* maximum amount of padding, inc length byte. */
size_t to_check = 256; /* maximum amount of padding, inc length byte. */
if (to_check > in_len) {
to_check = in_len;
}
for (i = 0; i < to_check; i++) {
for (size_t i = 0; i < to_check; i++) {
uint8_t mask = constant_time_ge_8(padding_length, i);
uint8_t b = in[in_len - 1 - i];
/* The final |padding_length+1| bytes should all have the value
@@ -111,7 +110,7 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
/* If any of the final |padding_length+1| bytes had the wrong value,
* one or more of the lower eight bits of |good| will be cleared. */
good = constant_time_eq(0xff, good & 0xff);
good = constant_time_eq_s(0xff, good & 0xff);
/* Always treat |padding_length| as zero on error. If, assuming block size of
* 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16
@@ -123,16 +122,15 @@ int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
return 1;
}
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
const uint8_t *in, unsigned in_len,
unsigned orig_len) {
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
size_t in_len, size_t orig_len) {
uint8_t rotated_mac1[EVP_MAX_MD_SIZE], rotated_mac2[EVP_MAX_MD_SIZE];
uint8_t *rotated_mac = rotated_mac1;
uint8_t *rotated_mac_tmp = rotated_mac2;
/* mac_end is the index of |in| just after the end of the MAC. */
unsigned mac_end = in_len;
unsigned mac_start = mac_end - md_size;
size_t mac_end = in_len;
size_t mac_start = mac_end - md_size;
assert(orig_len >= in_len);
assert(in_len >= md_size);
@@ -140,20 +138,20 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
/* scan_start contains the number of bytes that we can ignore because
* the MAC's position can only vary by 255 bytes. */
unsigned scan_start = 0;
size_t scan_start = 0;
/* This information is public so it's safe to branch based on it. */
if (orig_len > md_size + 255 + 1) {
scan_start = orig_len - (md_size + 255 + 1);
}
unsigned rotate_offset = 0;
size_t rotate_offset = 0;
uint8_t mac_started = 0;
OPENSSL_memset(rotated_mac, 0, md_size);
for (unsigned i = scan_start, j = 0; i < orig_len; i++, j++) {
for (size_t i = scan_start, j = 0; i < orig_len; i++, j++) {
if (j >= md_size) {
j -= md_size;
}
unsigned is_mac_start = constant_time_eq(i, mac_start);
size_t is_mac_start = constant_time_eq_s(i, mac_start);
mac_started |= is_mac_start;
uint8_t mac_ended = constant_time_ge_8(i, mac_end);
rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
@@ -163,12 +161,11 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
/* Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
* position. */
for (unsigned offset = 1; offset < md_size;
offset <<= 1, rotate_offset >>= 1) {
for (size_t offset = 1; offset < md_size; offset <<= 1, rotate_offset >>= 1) {
/* Rotate by |offset| iff the corresponding bit is set in
* |rotate_offset|, placing the result in |rotated_mac_tmp|. */
const uint8_t skip_rotate = (rotate_offset & 1) - 1;
for (unsigned i = 0, j = offset; i < md_size; i++, j++) {
for (size_t i = 0, j = offset; i < md_size; i++, j++) {
if (j >= md_size) {
j -= md_size;
}
@@ -211,40 +208,49 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
*((p)++) = (uint8_t)((n)); \
} while (0)
typedef union {
SHA_CTX sha1;
SHA256_CTX sha256;
SHA512_CTX sha512;
} HASH_CTX;
static void tls1_sha1_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA1_Transform(&ctx->sha1, block);
}
static void tls1_sha256_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA256_Transform(&ctx->sha256, block);
}
static void tls1_sha512_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA512_Transform(&ctx->sha512, block);
}
/* These functions serialize the state of a hash and thus perform the standard
* "final" operation without adding the padding and length that such a function
* typically does. */
static void tls1_sha1_final_raw(void *ctx, uint8_t *md_out) {
SHA_CTX *sha1 = ctx;
static void tls1_sha1_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA_CTX *sha1 = &ctx->sha1;
u32toBE(sha1->h[0], md_out);
u32toBE(sha1->h[1], md_out);
u32toBE(sha1->h[2], md_out);
u32toBE(sha1->h[3], md_out);
u32toBE(sha1->h[4], md_out);
}
#define LARGEST_DIGEST_CTX SHA_CTX
static void tls1_sha256_final_raw(void *ctx, uint8_t *md_out) {
SHA256_CTX *sha256 = ctx;
unsigned i;
for (i = 0; i < 8; i++) {
static void tls1_sha256_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA256_CTX *sha256 = &ctx->sha256;
for (unsigned i = 0; i < 8; i++) {
u32toBE(sha256->h[i], md_out);
}
}
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA256_CTX
static void tls1_sha512_final_raw(void *ctx, uint8_t *md_out) {
SHA512_CTX *sha512 = ctx;
unsigned i;
for (i = 0; i < 8; i++) {
static void tls1_sha512_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA512_CTX *sha512 = &ctx->sha512;
for (unsigned i = 0; i < 8; i++) {
u64toBE(sha512->h[i], md_out);
}
}
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA512_CTX
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) {
switch (EVP_MD_type(md)) {
@@ -264,54 +270,42 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
size_t data_plus_mac_plus_padding_size,
const uint8_t *mac_secret,
unsigned mac_secret_length) {
union {
double align;
uint8_t c[sizeof(LARGEST_DIGEST_CTX)];
} md_state;
void (*md_final_raw)(void *ctx, uint8_t *md_out);
void (*md_transform)(void *ctx, const uint8_t *block);
HASH_CTX md_state;
void (*md_final_raw)(HASH_CTX *ctx, uint8_t *md_out);
void (*md_transform)(HASH_CTX *ctx, const uint8_t *block);
unsigned md_size, md_block_size = 64;
unsigned len, max_mac_bytes, num_blocks, num_starting_blocks, k,
mac_end_offset, c, index_a, index_b;
unsigned int bits; /* at most 18 bits */
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
/* hmac_pad is the masked HMAC key. */
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
uint8_t mac_out[EVP_MAX_MD_SIZE];
unsigned i, j, md_out_size_u;
EVP_MD_CTX md_ctx;
/* mdLengthSize is the number of bytes in the length field that terminates
* the hash. */
/* md_length_size is the number of bytes in the length field that terminates
* the hash. */
unsigned md_length_size = 8;
/* This is a, hopefully redundant, check that allows us to forget about
* many possible overflows later in this function. */
assert(data_plus_mac_plus_padding_size < 1024 * 1024);
/* Bound the acceptable input so we can forget about many possible overflows
* later in this function. This is redundant with the record size limits in
* TLS. */
if (data_plus_mac_plus_padding_size >= 1024 * 1024) {
assert(0);
return 0;
}
switch (EVP_MD_type(md)) {
case NID_sha1:
SHA1_Init((SHA_CTX *)md_state.c);
SHA1_Init(&md_state.sha1);
md_final_raw = tls1_sha1_final_raw;
md_transform =
(void (*)(void *ctx, const uint8_t *block))SHA1_Transform;
md_size = 20;
md_transform = tls1_sha1_transform;
md_size = SHA_DIGEST_LENGTH;
break;
case NID_sha256:
SHA256_Init((SHA256_CTX *)md_state.c);
SHA256_Init(&md_state.sha256);
md_final_raw = tls1_sha256_final_raw;
md_transform =
(void (*)(void *ctx, const uint8_t *block))SHA256_Transform;
md_size = 32;
md_transform = tls1_sha256_transform;
md_size = SHA256_DIGEST_LENGTH;
break;
case NID_sha384:
SHA384_Init((SHA512_CTX *)md_state.c);
SHA384_Init(&md_state.sha512);
md_final_raw = tls1_sha512_final_raw;
md_transform =
(void (*)(void *ctx, const uint8_t *block))SHA512_Transform;
md_size = 384 / 8;
md_transform = tls1_sha512_transform;
md_size = SHA384_DIGEST_LENGTH;
md_block_size = 128;
md_length_size = 16;
break;
@@ -328,7 +322,7 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
assert(md_size <= EVP_MAX_MD_SIZE);
static const unsigned kHeaderLength = 13;
static const size_t kHeaderLength = 13;
/* kVarianceBlocks is the number of blocks of the hash that we have to
* calculate in constant time because they could be altered by the
@@ -337,16 +331,16 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
* TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
* required to be minimal. Therefore we say that the final six blocks
* can vary based on the padding. */
static const unsigned kVarianceBlocks = 6;
static const size_t kVarianceBlocks = 6;
/* From now on we're dealing with the MAC, which conceptually has 13
* bytes of `header' before the start of the data. */
len = data_plus_mac_plus_padding_size + kHeaderLength;
size_t len = data_plus_mac_plus_padding_size + kHeaderLength;
/* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
* |header|, assuming that there's no padding. */
max_mac_bytes = len - md_size - 1;
* |header|, assuming that there's no padding. */
size_t max_mac_bytes = len - md_size - 1;
/* num_blocks is the maximum number of hash blocks. */
num_blocks =
size_t num_blocks =
(max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
/* In order to calculate the MAC in constant time we have to handle
* the final blocks specially because the padding value could cause the
@@ -354,43 +348,47 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
* can't leak where. However, |num_starting_blocks| worth of data can
* be hashed right away because no padding value can affect whether
* they are plaintext. */
num_starting_blocks = 0;
size_t num_starting_blocks = 0;
/* k is the starting byte offset into the conceptual header||data where
* we start processing. */
k = 0;
size_t k = 0;
/* mac_end_offset is the index just past the end of the data to be
* MACed. */
mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
size_t mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
/* c is the index of the 0x80 byte in the final hash block that
* contains application data. */
c = mac_end_offset % md_block_size;
size_t c = mac_end_offset % md_block_size;
/* index_a is the hash block number that contains the 0x80 terminating
* value. */
index_a = mac_end_offset / md_block_size;
size_t index_a = mac_end_offset / md_block_size;
/* index_b is the hash block number that contains the 64-bit hash
* length, in bits. */
index_b = (mac_end_offset + md_length_size) / md_block_size;
/* bits is the hash-length in bits. It includes the additional hash
* block for the masked HMAC key. */
size_t index_b = (mac_end_offset + md_length_size) / md_block_size;
if (num_blocks > kVarianceBlocks) {
num_starting_blocks = num_blocks - kVarianceBlocks;
k = md_block_size * num_starting_blocks;
}
bits = 8 * mac_end_offset;
/* bits is the hash-length in bits. It includes the additional hash
* block for the masked HMAC key. */
size_t bits = 8 * mac_end_offset; /* at most 18 bits to represent */
/* Compute the initial HMAC block. */
bits += 8 * md_block_size;
/* hmac_pad is the masked HMAC key. */
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
OPENSSL_memset(hmac_pad, 0, md_block_size);
assert(mac_secret_length <= sizeof(hmac_pad));
OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length);
for (i = 0; i < md_block_size; i++) {
for (size_t i = 0; i < md_block_size; i++) {
hmac_pad[i] ^= 0x36;
}
md_transform(md_state.c, hmac_pad);
md_transform(&md_state, hmac_pad);
/* The length check means |bits| fits in four bytes. */
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
OPENSSL_memset(length_bytes, 0, md_length_size - 4);
length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
@@ -399,27 +397,29 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
if (k > 0) {
/* k is a multiple of md_block_size. */
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
OPENSSL_memcpy(first_block, header, 13);
OPENSSL_memcpy(first_block + 13, data, md_block_size - 13);
md_transform(md_state.c, first_block);
for (i = 1; i < k / md_block_size; i++) {
md_transform(md_state.c, data + md_block_size * i - 13);
md_transform(&md_state, first_block);
for (size_t i = 1; i < k / md_block_size; i++) {
md_transform(&md_state, data + md_block_size * i - 13);
}
}
uint8_t mac_out[EVP_MAX_MD_SIZE];
OPENSSL_memset(mac_out, 0, sizeof(mac_out));
/* We now process the final hash blocks. For each block, we construct
* it in constant time. If the |i==index_a| then we'll include the 0x80
* bytes and zero pad etc. For each block we selectively copy it, in
* constant time, to |mac_out|. */
for (i = num_starting_blocks; i <= num_starting_blocks + kVarianceBlocks;
i++) {
for (size_t i = num_starting_blocks;
i <= num_starting_blocks + kVarianceBlocks; i++) {
uint8_t block[MAX_HASH_BLOCK_SIZE];
uint8_t is_block_a = constant_time_eq_8(i, index_a);
uint8_t is_block_b = constant_time_eq_8(i, index_b);
for (j = 0; j < md_block_size; j++) {
uint8_t b = 0, is_past_c, is_past_cp1;
for (size_t j = 0; j < md_block_size; j++) {
uint8_t b = 0;
if (k < kHeaderLength) {
b = header[k];
} else if (k < data_plus_mac_plus_padding_size + kHeaderLength) {
@@ -427,8 +427,8 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
}
k++;
is_past_c = is_block_a & constant_time_ge_8(j, c);
is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
uint8_t is_past_c = is_block_a & constant_time_ge_8(j, c);
uint8_t is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
/* If this is the block containing the end of the
* application data, and we are at the offset for the
* 0x80 value, then overwrite b with 0x80. */
@@ -453,14 +453,15 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
block[j] = b;
}
md_transform(md_state.c, block);
md_final_raw(md_state.c, block);
md_transform(&md_state, block);
md_final_raw(&md_state, block);
/* If this is index_b, copy the hash value to |mac_out|. */
for (j = 0; j < md_size; j++) {
for (size_t j = 0; j < md_size; j++) {
mac_out[j] |= block[j] & is_block_b;
}
}
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) {
EVP_MD_CTX_cleanup(&md_ctx);
@@ -468,12 +469,13 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
}
/* Complete the HMAC in the standard manner. */
for (i = 0; i < md_block_size; i++) {
for (size_t i = 0; i < md_block_size; i++) {
hmac_pad[i] ^= 0x6a;
}
EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
EVP_DigestUpdate(&md_ctx, mac_out, md_size);
unsigned md_out_size_u;
EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
*md_out_size = md_out_size_u;
EVP_MD_CTX_cleanup(&md_ctx);
+13 -1
View File
@@ -69,6 +69,10 @@
#include "../internal.h"
/* The maximum length we can grow a value to after variable expansion. 64k
* should be more than enough for all reasonable uses. */
#define MAX_CONF_VALUE_LENGTH 65536
static uint32_t conf_value_hash(const CONF_VALUE *v) {
return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name);
}
@@ -316,7 +320,15 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from) {
OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_HAS_NO_VALUE);
goto err;
}
BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from)));
size_t newsize = strlen(p) + buf->length - (e - from);
if (newsize > MAX_CONF_VALUE_LENGTH) {
OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
goto err;
}
if (!BUF_MEM_grow_clean(buf, newsize)) {
OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
while (*p) {
buf->data[to++] = *(p++);
}
+63 -234
View File
@@ -49,259 +49,88 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits>
static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
static const unsigned int CONSTTIME_FALSE = 0;
static const uint8_t CONSTTIME_TRUE_8 = 0xff;
static const uint8_t CONSTTIME_FALSE_8 = 0;
#include <gtest/gtest.h>
static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
const char* op_name, unsigned int a, unsigned int b,
int is_true) {
unsigned c = op(a, b);
if (is_true && c != CONSTTIME_TRUE) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %du (TRUE), got %du\n",
op_name, a, b, CONSTTIME_TRUE, c);
return 1;
} else if (!is_true && c != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %du (FALSE), got %du\n",
op_name, a, b, CONSTTIME_FALSE, c);
return 1;
}
return 0;
static uint8_t FromBool8(bool b) {
return b ? CONSTTIME_TRUE_8 : CONSTTIME_FALSE_8;
}
static int test_binary_op_8(uint8_t (*op)(unsigned int a, unsigned int b),
const char* op_name, unsigned int a, unsigned int b,
int is_true) {
uint8_t c = op(a, b);
if (is_true && c != CONSTTIME_TRUE_8) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %u (TRUE), got %u\n",
op_name, a, b, CONSTTIME_TRUE_8, c);
return 1;
} else if (!is_true && c != CONSTTIME_FALSE_8) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %u (FALSE), got %u\n",
op_name, a, b, CONSTTIME_FALSE_8, c);
return 1;
}
return 0;
static size_t FromBoolS(bool b) {
return b ? CONSTTIME_TRUE_S : CONSTTIME_FALSE_S;
}
static int test_is_zero(unsigned int a) {
unsigned int c = constant_time_is_zero(a);
if (a == 0 && c != CONSTTIME_TRUE) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %du (TRUE), "
"got %du\n",
a, CONSTTIME_TRUE, c);
return 1;
} else if (a != 0 && c != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %du (FALSE), "
"got %du\n",
a, CONSTTIME_FALSE, c);
return 1;
}
return 0;
}
static const uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
static int test_is_zero_8(unsigned int a) {
uint8_t c = constant_time_is_zero_8(a);
if (a == 0 && c != CONSTTIME_TRUE_8) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %u (TRUE), "
"got %u\n",
a, CONSTTIME_TRUE_8, c);
return 1;
} else if (a != 0 && c != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %u (FALSE), "
"got %u\n",
a, CONSTTIME_FALSE_8, c);
return 1;
}
return 0;
}
static int test_select(unsigned int a, unsigned int b) {
unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
if (selected != a) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %du,"
"%du): expected %du(first value), got %du\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select(CONSTTIME_FALSE, a, b);
if (selected != b) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %du,"
"%du): expected %du(second value), got %du\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}
static int test_select_8(uint8_t a, uint8_t b) {
uint8_t selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
if (selected != a) {
fprintf(stderr,
"Test failed for constant_time_select(%u, %u,"
"%u): expected %u(first value), got %u\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
if (selected != b) {
fprintf(stderr,
"Test failed for constant_time_select(%u, %u,"
"%u): expected %u(second value), got %u\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}
static int test_select_int(int a, int b) {
int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
if (selected != a) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %d,"
"%d): expected %d(first value), got %d\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
if (selected != b) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %d,"
"%d): expected %d(second value), got %d\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}
static int test_eq_int(int a, int b) {
unsigned int equal = constant_time_eq_int(a, b);
if (a == b && equal != CONSTTIME_TRUE) {
fprintf(stderr,
"Test failed for constant_time_eq_int(%d, %d): expected %du(TRUE), "
"got %du\n",
a, b, CONSTTIME_TRUE, equal);
return 1;
} else if (a != b && equal != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for constant_time_eq_int(%d, %d): expected "
"%du(FALSE), got %du\n",
a, b, CONSTTIME_FALSE, equal);
return 1;
}
return 0;
}
static int test_eq_int_8(int a, int b) {
uint8_t equal = constant_time_eq_int_8(a, b);
if (a == b && equal != CONSTTIME_TRUE_8) {
fprintf(stderr,
"Test failed for constant_time_eq_int_8(%d, %d): expected "
"%u(TRUE), got %u\n",
a, b, CONSTTIME_TRUE_8, equal);
return 1;
} else if (a != b && equal != CONSTTIME_FALSE_8) {
fprintf(stderr,
"Test failed for constant_time_eq_int_8(%d, %d): expected "
"%u(FALSE), got %u\n",
a, b, CONSTTIME_FALSE_8, equal);
return 1;
}
return 0;
}
static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
UINT_MAX / 2, UINT_MAX / 2 + 1,
UINT_MAX - 1, UINT_MAX};
static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
static size_t test_values_s[] = {
0,
1,
1024,
12345,
32000,
#if defined(OPENSSL_64_BIT)
0xffffffff / 2 - 1,
0xffffffff / 2,
0xffffffff / 2 + 1,
0xffffffff - 1,
0xffffffff,
#endif
std::numeric_limits<size_t>::max() / 2 - 1,
std::numeric_limits<size_t>::max() / 2,
std::numeric_limits<size_t>::max() / 2 + 1,
std::numeric_limits<size_t>::max() - 1,
std::numeric_limits<size_t>::max(),
};
static int signed_test_values[] = {
0, 1, -1, 1024, -1024, 12345, -12345,
32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
int main(int argc, char* argv[]) {
unsigned int a, b, i, j;
int c, d;
uint8_t e, f;
int num_failed = 0, num_all = 0;
fprintf(stdout, "Testing constant time operations...\n");
TEST(ConstantTimeTest, Test) {
for (size_t a : test_values_s) {
SCOPED_TRACE(a);
for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) {
a = test_values[i];
num_failed += test_is_zero(a);
num_failed += test_is_zero_8(a);
num_all += 2;
for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) {
b = test_values[j];
num_failed +=
test_binary_op(&constant_time_lt, "constant_time_lt", a, b, a < b);
num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
a, b, a < b);
num_failed +=
test_binary_op(&constant_time_lt, "constant_time_lt_8", b, a, b < a);
num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
b, a, b < a);
num_failed +=
test_binary_op(&constant_time_ge, "constant_time_ge", a, b, a >= b);
num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
a, b, a >= b);
num_failed +=
test_binary_op(&constant_time_ge, "constant_time_ge", b, a, b >= a);
num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
b, a, b >= a);
num_failed +=
test_binary_op(&constant_time_eq, "constant_time_eq", a, b, a == b);
num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
a, b, a == b);
num_failed +=
test_binary_op(&constant_time_eq, "constant_time_eq", b, a, b == a);
num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
b, a, b == a);
num_failed += test_select(a, b);
num_all += 13;
EXPECT_EQ(FromBoolS(a == 0), constant_time_is_zero_s(a));
EXPECT_EQ(FromBool8(a == 0), constant_time_is_zero_8(a));
for (size_t b : test_values_s) {
SCOPED_TRACE(b);
EXPECT_EQ(FromBoolS(a < b), constant_time_lt_s(a, b));
EXPECT_EQ(FromBool8(a < b), constant_time_lt_8(a, b));
EXPECT_EQ(FromBoolS(a >= b), constant_time_ge_s(a, b));
EXPECT_EQ(FromBool8(a >= b), constant_time_ge_8(a, b));
EXPECT_EQ(FromBoolS(a == b), constant_time_eq_s(a, b));
EXPECT_EQ(FromBool8(a == b), constant_time_eq_8(a, b));
EXPECT_EQ(a, constant_time_select_s(CONSTTIME_TRUE_S, a, b));
EXPECT_EQ(b, constant_time_select_s(CONSTTIME_FALSE_S, a, b));
}
}
for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) {
c = signed_test_values[i];
for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) {
d = signed_test_values[j];
num_failed += test_select_int(c, d);
num_failed += test_eq_int(c, d);
num_failed += test_eq_int_8(c, d);
num_all += 3;
for (int a : signed_test_values) {
SCOPED_TRACE(a);
for (int b : signed_test_values) {
SCOPED_TRACE(b);
EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE_S, a, b));
EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE_S, a, b));
EXPECT_EQ(FromBoolS(a == b), constant_time_eq_int(a, b));
EXPECT_EQ(FromBool8(a == b), constant_time_eq_int_8(a, b));
}
}
for (i = 0; i < sizeof(test_values_8); ++i) {
e = test_values_8[i];
for (j = 0; j < sizeof(test_values_8); ++j) {
f = test_values_8[j];
num_failed += test_select_8(e, f);
num_all += 1;
for (uint8_t a : test_values_8) {
SCOPED_TRACE(static_cast<int>(a));
for (uint8_t b : test_values_8) {
SCOPED_TRACE(static_cast<int>(b));
EXPECT_EQ(a, constant_time_select_8(CONSTTIME_TRUE_8, a, b));
EXPECT_EQ(b, constant_time_select_8(CONSTTIME_FALSE_8, a, b));
}
}
if (!num_failed) {
fprintf(stdout, "ok (ran %d tests)\n", num_all);
fprintf(stdout, "PASS\n");
return EXIT_SUCCESS;
} else {
fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
return EXIT_FAILURE;
}
}
+2 -4
View File
@@ -27,14 +27,12 @@
#define PPC_FEATURE2_HAS_VCRYPTO 0x02000000
#endif
static unsigned long g_ppc64le_hwcap2 = 0;
void OPENSSL_cpuid_setup(void) {
g_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
OPENSSL_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
}
int CRYPTO_is_PPC64LE_vcrypto_capable(void) {
return (g_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
return (OPENSSL_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
}
#endif /* OPENSSL_PPC64LE */
+6
View File
@@ -49,6 +49,7 @@
* far, the init constructor function only sets the capability variables. */
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
/* This value must be explicitly initialised to zero in order to work around a
* bug in libtool or the linker on OS X.
*
@@ -57,6 +58,11 @@
* initialising it to zero, it becomes a "data symbol", which isn't so
* affected. */
uint32_t OPENSSL_ia32cap_P[4] = {0};
#elif defined(OPENSSL_PPC64LE)
unsigned long OPENSSL_ppc64le_hwcap2 = 0;
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
#include <openssl/arm_arch.h>
-9
View File
@@ -38,15 +38,6 @@ add_executable(
target_link_libraries(ed25519_test crypto)
add_dependencies(all_tests ed25519_test)
add_executable(
x25519_test
x25519_test.cc
)
target_link_libraries(x25519_test crypto)
add_dependencies(all_tests x25519_test)
add_executable(
spake25519_test
+13
View File
@@ -2575,3 +2575,16 @@ PRIV: 4f4b20d899366f2f23ee628f229b236cf80f43ba183177c97ee34829546f1742c94576641f
PUB: c94576641f4a893cdfcee7b39fc21929b86b349976d7b0a46d39a588bcfe4357
MESSAGE: db8ef02e3033e6b96a56cab05082fb4695f4a1c916250dd75173f430a10c9468817709d37623346ae8245b42bda0da6b60462ccfdfc75a9ab994e66c9ab9fecdd8599610910affe4f10215cb280bf8f9f2700a444796dae93e06c6bea7d8b4fe1301baa79ccec769368feb2442c7de84f095e6b3bff63d388cbafb2b9809dc38e9b12ebd039c0a57f4d522e91ec8d1f2b8d23a4a0ae059af85393bb0a15f749110f6774a1fd731a6ec213e4ff435daab546d31ed9ec3b6d8cc2edacebf4facc5566556eea92e5b3f2542239b25e28012dd4ef40072eebf83ed2a255181f3a442189d68c6c609f4dfdf3db7d67d087a2fcd6d2dc50bbfed8bfbbfcb74d3c41f02a87865b13b8efcf5c3581257be0aa913f60c370527bde11a475c136a17c5eefeb03f5bff28693ed841e8ed1f7c29102f5599dd444009bcea6a92d5574152458e0caf8a36aa72b5dc4908a6461c9b741453005c8fbcc68113ae184208ee14b835480c6efafed18a76000b38e5858290f4d51f52f096cbe490e1eb5cacb226ec495a55a7fa457843d57fab67f8be7e209334785bdd665d7b63e4daf57b6e78928b603c8c0f9bc85464733b61273ef9e2b8a0cd7c3bf8ee0a6872e34d5a27a625e35eaf7ff5440b8b141af704df70c9c18623bd11209513192505105cd7bcfa5f0d919da706948fbe1f761f315846aa3b4813dd9ba3d81b9204e5409c0382b6eb
SIG: 0f80ff5d17488fe26f93c543b04ed959b5f0643fc61c7f2c3bc60132ba9c6210c8b250ea5e84d07b01de68bc174414eeeb31fdc2ba6823e231e312a91ededd02
# Additional test vectors from RFC 8032
PRIV: f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
PUB: 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
MESSAGE: 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0
SIG: 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03
PRIV: 833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
PUB: ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
MESSAGE: ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
SIG: dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704
+21 -42
View File
@@ -16,13 +16,16 @@
#include <stdio.h>
#include <string.h>
#include <gtest/gtest.h>
#include <openssl/curve25519.h>
#include "../internal.h"
#include "../test/test_util.h"
static bool TestX25519() {
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
TEST(X25519Test, TestVector) {
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2
static const uint8_t kScalar1[32] = {
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
@@ -35,17 +38,14 @@ static bool TestX25519() {
};
uint8_t out[32];
X25519(out, kScalar1, kPoint1);
EXPECT_TRUE(X25519(out, kScalar1, kPoint1));
static const uint8_t kExpected1[32] = {
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
};
if (OPENSSL_memcmp(kExpected1, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test one failed.\n");
return false;
}
EXPECT_EQ(Bytes(kExpected1), Bytes(out));
static const uint8_t kScalar2[32] = {
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26,
@@ -58,22 +58,17 @@ static bool TestX25519() {
0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
};
X25519(out, kScalar2, kPoint2);
EXPECT_TRUE(X25519(out, kScalar2, kPoint2));
static const uint8_t kExpected2[32] = {
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
};
if (OPENSSL_memcmp(kExpected2, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test two failed.\n");
return false;
}
return true;
EXPECT_EQ(Bytes(kExpected2), Bytes(out));
}
static bool TestX25519SmallOrder() {
TEST(X25519Test, SmallOrder) {
static const uint8_t kSmallOrderPoint[32] = {
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
@@ -83,21 +78,21 @@ static bool TestX25519SmallOrder() {
uint8_t out[32], private_key[32];
OPENSSL_memset(private_key, 0x11, sizeof(private_key));
if (X25519(out, private_key, kSmallOrderPoint)) {
fprintf(stderr, "X25519 returned success with a small-order input.\n");
return false;
}
OPENSSL_memset(out, 0xff, sizeof(out));
EXPECT_FALSE(X25519(out, private_key, kSmallOrderPoint))
<< "X25519 returned success with a small-order input.";
return true;
// For callers which don't check, |out| should still be filled with zeros.
static const uint8_t kZeros[32] = {0};
EXPECT_EQ(Bytes(kZeros), Bytes(out));
}
static bool TestX25519Iterated() {
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
TEST(X25519Test, Iterated) {
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2.
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
unsigned i;
for (i = 0; i < 1000; i++) {
X25519(out, scalar, point);
for (unsigned i = 0; i < 1000; i++) {
EXPECT_TRUE(X25519(out, scalar, point));
OPENSSL_memcpy(point, scalar, sizeof(point));
OPENSSL_memcpy(scalar, out, sizeof(scalar));
}
@@ -108,21 +103,5 @@ static bool TestX25519Iterated() {
0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
};
if (OPENSSL_memcmp(kExpected, scalar, sizeof(kExpected)) != 0) {
fprintf(stderr, "Iterated X25519 test failed\n");
return false;
}
return true;
}
int main(int argc, char **argv) {
if (!TestX25519() ||
!TestX25519Iterated() ||
!TestX25519SmallOrder()) {
return 1;
}
printf("PASS\n");
return 0;
EXPECT_EQ(Bytes(kExpected), Bytes(scalar));
}
+2 -2
View File
@@ -93,7 +93,7 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
/* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114
* groups which are not safe primes but pick a generator on a prime-order
* subgroup of size |dh->q|. */
if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) {
if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx, NULL)) {
goto err;
}
if (!BN_is_one(tmp)) {
@@ -145,7 +145,7 @@ int DH_check(const DH *dh, int *ret) {
*ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
} else {
/* Check g^q == 1 mod p */
if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) {
if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx, NULL)) {
goto err;
}
if (!BN_is_one(t1)) {
-7
View File
@@ -225,13 +225,6 @@ static int TestDigest(const TestVector *test) {
if (!CompareDigest(test, digest.get(), EVP_MD_size(test->md.func()))) {
return false;
}
// Test the deprecated static buffer variant, until it's removed.
out = test->md.one_shot_func((const uint8_t *)test->input,
strlen(test->input), NULL);
if (!CompareDigest(test, out, EVP_MD_size(test->md.func()))) {
return false;
}
}
return true;
+44 -5
View File
@@ -60,6 +60,7 @@
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/bytestring.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/nid.h>
@@ -328,20 +329,58 @@ static const struct {
{ {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, EVP_sha224 },
};
static const EVP_MD *cbs_to_md(const CBS *cbs) {
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
if (CBS_len(cbs) == kMDOIDs[i].oid_len &&
OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) ==
0) {
return kMDOIDs[i].md_func();
}
}
return NULL;
}
const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj) {
/* Handle objects with no corresponding OID. */
if (obj->nid != NID_undef) {
return EVP_get_digestbynid(obj->nid);
}
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
if (obj->length == kMDOIDs[i].oid_len &&
memcmp(obj->data, kMDOIDs[i].oid, obj->length) == 0) {
return kMDOIDs[i].md_func();
CBS cbs;
CBS_init(&cbs, obj->data, obj->length);
return cbs_to_md(&cbs);
}
const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) {
CBS algorithm, oid;
if (!CBS_get_asn1(cbs, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) {
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
return NULL;
}
const EVP_MD *ret = cbs_to_md(&oid);
if (ret == NULL) {
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH);
return NULL;
}
/* The parameters, if present, must be NULL. Historically, whether the NULL
* was included or omitted was not well-specified. When parsing an
* AlgorithmIdentifier, we allow both. (Note this code is not used when
* verifying RSASSA-PKCS1-v1_5 signatures.) */
if (CBS_len(&algorithm) > 0) {
CBS param;
if (!CBS_get_asn1(&algorithm, &param, CBS_ASN1_NULL) ||
CBS_len(&param) != 0 ||
CBS_len(&algorithm) != 0) {
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
return NULL;
}
}
return NULL;
return ret;
}
const EVP_MD *EVP_get_digestbyname(const char *name) {
+2
View File
@@ -104,6 +104,8 @@ struct evp_md_pctx_ops {
EVP_PKEY_CTX* (*dup) (EVP_PKEY_CTX *pctx);
};
const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
#if defined(__cplusplus)
} /* extern C */
+1
View File
@@ -3,4 +3,5 @@ CONF,101,MISSING_CLOSE_SQUARE_BRACKET
CONF,102,MISSING_EQUAL_SIGN
CONF,103,NO_CLOSE_BRACE
CONF,104,UNABLE_TO_CREATE_NEW_SECTION
CONF,106,VARIABLE_EXPANSION_TOO_LONG
CONF,105,VARIABLE_HAS_NO_VALUE
+2
View File
@@ -1 +1,3 @@
DIGEST,101,DECODE_ERROR
DIGEST,100,INPUT_NOT_INITIALIZED
DIGEST,102,UNKNOWN_HASH
+6
View File
@@ -1,3 +1,4 @@
PKCS8,129,BAD_ITERATION_COUNT
PKCS8,100,BAD_PKCS12_DATA
PKCS8,101,BAD_PKCS12_VERSION
PKCS8,102,CIPHER_HAS_NO_OBJECT_IDENTIFIER
@@ -22,4 +23,9 @@ PKCS8,120,UNKNOWN_CIPHER
PKCS8,121,UNKNOWN_CIPHER_ALGORITHM
PKCS8,122,UNKNOWN_DIGEST
PKCS8,123,UNKNOWN_HASH
PKCS8,127,UNSUPPORTED_CIPHER
PKCS8,125,UNSUPPORTED_KEYLENGTH
PKCS8,128,UNSUPPORTED_KEY_DERIVATION_FUNCTION
PKCS8,130,UNSUPPORTED_PRF
PKCS8,124,UNSUPPORTED_PRIVATE_KEY_ALGORITHM
PKCS8,126,UNSUPPORTED_SALT_TYPE
+7 -1
View File
@@ -1,3 +1,4 @@
SSL,277,ALPN_MISMATCH_ON_EARLY_DATA
SSL,100,APP_DATA_IN_HANDSHAKE
SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT
SSL,102,BAD_ALERT
@@ -22,14 +23,17 @@ SSL,261,BLOCK_CIPHER_PAD_IS_WRONG
SSL,120,BN_LIB
SSL,255,BUFFERED_MESSAGES_ON_CIPHER_CHANGE
SSL,121,BUFFER_TOO_SMALL
SSL,275,CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD
SSL,272,CANNOT_PARSE_LEAF_CERT
SSL,122,CA_DN_LENGTH_MISMATCH
SSL,123,CA_DN_TOO_LONG
SSL,124,CCS_RECEIVED_EARLY
SSL,274,CERTIFICATE_AND_PRIVATE_KEY_MISMATCH
SSL,125,CERTIFICATE_VERIFY_FAILED
SSL,126,CERT_CB_ERROR
SSL,127,CERT_LENGTH_MISMATCH
SSL,128,CHANNEL_ID_NOT_P256
SSL,279,CHANNEL_ID_ON_EARLY_DATA
SSL,129,CHANNEL_ID_SIGNATURE_INVALID
SSL,130,CIPHER_OR_HASH_UNAVAILABLE
SSL,131,CLIENTHELLO_PARSE_FAILED
@@ -71,7 +75,6 @@ SSL,269,INVALID_SCT_LIST
SSL,160,INVALID_SSL_SESSION
SSL,161,INVALID_TICKET_KEYS_LENGTH
SSL,162,LENGTH_MISMATCH
SSL,163,LIBRARY_HAS_NO_CIPHERS
SSL,164,MISSING_EXTENSION
SSL,258,MISSING_KEY_SHARE
SSL,165,MISSING_RSA_CERTIFICATE
@@ -125,6 +128,7 @@ SSL,204,RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION
SSL,205,RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION
SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING
SSL,207,SERVERHELLO_TLSEXT
SSL,273,SERVER_CERT_CHANGED
SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED
SSL,209,SESSION_MAY_NOT_BE_CREATED
SSL,250,SHUTDOWN_WHILE_IN_INIT
@@ -147,6 +151,7 @@ SSL,1043,SSLV3_ALERT_UNSUPPORTED_CERTIFICATE
SSL,214,SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION
SSL,215,SSL_HANDSHAKE_FAILURE
SSL,216,SSL_SESSION_ID_CONTEXT_TOO_LONG
SSL,276,TICKET_ENCRYPTION_FAILED
SSL,1049,TLSV1_ALERT_ACCESS_DENIED
SSL,1050,TLSV1_ALERT_DECODE_ERROR
SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED
@@ -201,5 +206,6 @@ SSL,244,WRONG_MESSAGE_TYPE
SSL,245,WRONG_SIGNATURE_TYPE
SSL,246,WRONG_SSL_VERSION
SSL,247,WRONG_VERSION_NUMBER
SSL,278,WRONG_VERSION_ON_EARLY_DATA
SSL,248,X509_LIB
SSL,249,X509_VERIFICATION_SETUP_PROBLEMS
+1 -10
View File
@@ -20,14 +20,6 @@ add_library(
)
add_executable(
evp_extra_test
evp_extra_test.cc
$<TARGET_OBJECTS:test_support>
)
add_executable(
evp_test
@@ -44,7 +36,6 @@ add_executable(
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(evp_extra_test crypto)
target_link_libraries(evp_test crypto)
target_link_libraries(pbkdf_test crypto)
add_dependencies(all_tests evp_extra_test evp_test pbkdf_test)
add_dependencies(all_tests evp_test pbkdf_test)
-7
View File
@@ -120,13 +120,6 @@ int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
return 0;
}
int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
if (pkey->ameth && pkey->ameth->pkey_supports_digest) {
return pkey->ameth->pkey_supports_digest(pkey, md);
}
return 1;
}
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
if (a->type != b->type) {
return -1;
+101 -280
View File
@@ -20,6 +20,8 @@
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
@@ -28,6 +30,7 @@
#include <openssl/rsa.h>
#include "../internal.h"
#include "../test/test_util.h"
// kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
@@ -370,352 +373,170 @@ static bssl::UniquePtr<EVP_PKEY> LoadExampleRSAKey() {
return pkey;
}
static bool TestEVP_DigestSignInit(void) {
TEST(EVPExtraTest, DigestSignInit) {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
ASSERT_TRUE(pkey);
bssl::ScopedEVP_MD_CTX md_ctx;
if (!pkey ||
!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
!EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) {
return false;
}
ASSERT_TRUE(
EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
// Determine the size of the signature.
size_t sig_len = 0;
if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) {
return false;
}
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len));
// Sanity check for testing.
if (sig_len != (size_t)EVP_PKEY_size(pkey.get())) {
fprintf(stderr, "sig_len mismatch\n");
return false;
}
EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(pkey.get())), sig_len);
std::vector<uint8_t> sig;
sig.resize(sig_len);
if (!EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len)) {
return false;
}
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len));
sig.resize(sig_len);
// Ensure that the signature round-trips.
md_ctx.Reset();
if (!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
pkey.get()) ||
!EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
!EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len)) {
return false;
}
return true;
ASSERT_TRUE(
EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len));
}
static bool TestEVP_DigestVerifyInit(void) {
TEST(EVPExtraTest, DigestVerifyInit) {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
bssl::ScopedEVP_MD_CTX md_ctx;
if (!pkey ||
!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
pkey.get()) ||
!EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
!EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature))) {
return false;
}
return true;
ASSERT_TRUE(pkey);
ASSERT_TRUE(
EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
ASSERT_TRUE(
EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature)));
}
static bool TestVerifyRecover() {
TEST(EVPExtraTest, VerifyRecover) {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
if (!pkey) {
return false;
}
ASSERT_TRUE(pkey);
bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey.get()));
if (!rsa) {
return false;
}
ASSERT_TRUE(rsa);
const uint8_t kDummyHash[32] = {0};
uint8_t sig[2048/8];
unsigned sig_len = sizeof(sig);
if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig, &sig_len,
rsa.get())) {
fprintf(stderr, "RSA_sign failed.\n");
ERR_print_errors_fp(stderr);
return false;
}
ASSERT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig,
&sig_len, rsa.get()));
size_t out_len;
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
if (!EVP_PKEY_verify_recover_init(ctx.get()) ||
!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) ||
!EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()) ||
!EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len)) {
fprintf(stderr, "verify_recover failed will nullptr buffer.\n");
ERR_print_errors_fp(stderr);
return false;
}
ASSERT_TRUE(EVP_PKEY_verify_recover_init(ctx.get()));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING));
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()));
ASSERT_TRUE(
EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len));
std::vector<uint8_t> recovered;
recovered.resize(out_len);
if (!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
sig_len)) {
fprintf(stderr, "verify_recover failed.\n");
ERR_print_errors_fp(stderr);
return false;
}
if (out_len != sizeof(kDummyHash)) {
fprintf(stderr, "verify_recover length is %u, expected %u.\n",
static_cast<unsigned>(out_len),
static_cast<unsigned>(sizeof(kDummyHash)));
return false;
}
if (OPENSSL_memcmp(recovered.data(), kDummyHash, sizeof(kDummyHash)) != 0) {
fprintf(stderr, "verify_recover got wrong value.\n");
ERR_print_errors_fp(stderr);
return false;
}
ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
sig, sig_len));
EXPECT_EQ(Bytes(kDummyHash), Bytes(recovered.data(), out_len));
out_len = recovered.size();
if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr) ||
!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
sig_len)) {
fprintf(stderr, "verify_recover failed with NULL MD.\n");
ERR_print_errors_fp(stderr);
return false;
}
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr));
ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
sig, sig_len));
/* The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
* bytes. */
static const size_t kExpectedASN1Size = 51;
if (out_len != kExpectedASN1Size) {
fprintf(stderr, "verify_recover length without MD is %u, expected %u.\n",
static_cast<unsigned>(out_len),
static_cast<unsigned>(kExpectedASN1Size));
return false;
}
return true;
// The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
// bytes.
EXPECT_EQ(51u, out_len);
}
static bool TestValidPrivateKey(const uint8_t *input, size_t input_len,
static void TestValidPrivateKey(const uint8_t *input, size_t input_len,
int expected_id) {
const uint8_t *p = input;
bssl::UniquePtr<EVP_PKEY> pkey(d2i_AutoPrivateKey(NULL, &p, input_len));
if (!pkey || p != input + input_len) {
fprintf(stderr, "d2i_AutoPrivateKey failed\n");
return false;
}
if (EVP_PKEY_id(pkey.get()) != expected_id) {
fprintf(stderr, "Did not decode expected type\n");
return false;
}
return true;
ASSERT_TRUE(pkey);
EXPECT_EQ(input + input_len, p);
EXPECT_EQ(expected_id, EVP_PKEY_id(pkey.get()));
}
static bool Testd2i_AutoPrivateKey() {
if (!TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
EVP_PKEY_RSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
EVP_PKEY_RSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
EVP_PKEY_EC)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
EVP_PKEY_EC)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyPKCS8) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
sizeof(kExampleECKeySpecifiedCurvePKCS8),
EVP_PKEY_EC)) {
fprintf(stderr,
"d2i_AutoPrivateKey(kExampleECKeySpecifiedCurvePKCS8) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
EVP_PKEY_DSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n");
return false;
}
TEST(EVPExtraTest, d2i_AutoPrivateKey) {
TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
EVP_PKEY_RSA);
TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
EVP_PKEY_RSA);
TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER), EVP_PKEY_EC);
TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
EVP_PKEY_EC);
TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
sizeof(kExampleECKeySpecifiedCurvePKCS8), EVP_PKEY_EC);
TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
EVP_PKEY_DSA);
const uint8_t *p = kInvalidPrivateKey;
bssl::UniquePtr<EVP_PKEY> pkey(d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
if (pkey) {
fprintf(stderr, "Parsed invalid private key\n");
return false;
}
bssl::UniquePtr<EVP_PKEY> pkey(
d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
EXPECT_FALSE(pkey) << "Parsed invalid private key";
ERR_clear_error();
return true;
}
// TestEVP_PKCS82PKEY tests loading a bad key in PKCS8 format.
static bool TestEVP_PKCS82PKEY(void) {
// Tests loading a bad key in PKCS8 format.
TEST(EVPExtraTest, BadECKey) {
const uint8_t *derp = kExampleBadECKeyDER;
bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> p8inf(
d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER)));
if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) {
fprintf(stderr, "Failed to parse key\n");
return false;
}
ASSERT_TRUE(p8inf);
EXPECT_EQ(kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER), derp);
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKCS82PKEY(p8inf.get()));
if (pkey) {
fprintf(stderr, "Imported invalid EC key\n");
return false;
}
ASSERT_FALSE(pkey) << "Imported invalid EC key";
ERR_clear_error();
return true;
}
// TestEVPMarshalEmptyPublicKey tests |EVP_marshal_public_key| on an empty key.
static bool TestEVPMarshalEmptyPublicKey(void) {
// Tests |EVP_marshal_public_key| on an empty key.
TEST(EVPExtraTest, MarshalEmptyPublicKey) {
bssl::UniquePtr<EVP_PKEY> empty(EVP_PKEY_new());
if (!empty) {
return false;
}
ASSERT_TRUE(empty);
bssl::ScopedCBB cbb;
if (EVP_marshal_public_key(cbb.get(), empty.get())) {
fprintf(stderr, "Marshalled empty public key.\n");
return false;
}
if (ERR_GET_REASON(ERR_peek_last_error()) != EVP_R_UNSUPPORTED_ALGORITHM) {
fprintf(stderr, "Marshalling an empty public key gave wrong error.\n");
return false;
}
ERR_clear_error();
return true;
EXPECT_FALSE(EVP_marshal_public_key(cbb.get(), empty.get()))
<< "Marshalled empty public key.";
EXPECT_EQ(EVP_R_UNSUPPORTED_ALGORITHM, ERR_GET_REASON(ERR_peek_last_error()));
}
// Testd2i_PrivateKey tests |d2i_PrivateKey|.
static bool Testd2i_PrivateKey(void) {
const uint8_t *derp = kExampleRSAKeyDER;
bssl::UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
sizeof(kExampleRSAKeyDER)));
if (!pkey || derp != kExampleRSAKeyDER + sizeof(kExampleRSAKeyDER)) {
fprintf(stderr, "Failed to import raw RSA key.\n");
return false;
static bssl::UniquePtr<EVP_PKEY> ParsePrivateKey(int type, const uint8_t *in,
size_t len) {
const uint8_t *ptr = in;
bssl::UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(type, nullptr, &ptr, len));
if (!pkey) {
return nullptr;
}
derp = kExampleDSAKeyDER;
pkey.reset(d2i_PrivateKey(EVP_PKEY_DSA, nullptr, &derp,
sizeof(kExampleDSAKeyDER)));
if (!pkey || derp != kExampleDSAKeyDER + sizeof(kExampleDSAKeyDER)) {
fprintf(stderr, "Failed to import raw DSA key.\n");
return false;
}
EXPECT_EQ(in + len, ptr);
return pkey;
}
derp = kExampleRSAKeyPKCS8;
pkey.reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
sizeof(kExampleRSAKeyPKCS8)));
if (!pkey || derp != kExampleRSAKeyPKCS8 + sizeof(kExampleRSAKeyPKCS8)) {
fprintf(stderr, "Failed to import PKCS#8 RSA key.\n");
return false;
}
TEST(EVPExtraTest, d2i_PrivateKey) {
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyDER,
sizeof(kExampleRSAKeyDER)));
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_DSA, kExampleDSAKeyDER,
sizeof(kExampleDSAKeyDER)));
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyPKCS8,
sizeof(kExampleRSAKeyPKCS8)));
EXPECT_TRUE(
ParsePrivateKey(EVP_PKEY_EC, kExampleECKeyDER, sizeof(kExampleECKeyDER)));
derp = kExampleECKeyDER;
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
sizeof(kExampleECKeyDER)));
if (!pkey || derp != kExampleECKeyDER + sizeof(kExampleECKeyDER)) {
fprintf(stderr, "Failed to import raw EC key.\n");
return false;
}
derp = kExampleBadECKeyDER;
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
sizeof(kExampleBadECKeyDER)));
if (pkey) {
fprintf(stderr, "Imported invalid EC key.\n");
return false;
}
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleBadECKeyDER,
sizeof(kExampleBadECKeyDER)));
ERR_clear_error();
// Copy the input into a |malloc|'d vector to flag memory errors.
std::vector<uint8_t> copy(kExampleBadECKeyDER2, kExampleBadECKeyDER2 +
sizeof(kExampleBadECKeyDER2));
derp = copy.data();
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, copy.size()));
if (pkey) {
fprintf(stderr, "Imported invalid EC key #2.\n");
return false;
}
std::vector<uint8_t> copy(
kExampleBadECKeyDER2,
kExampleBadECKeyDER2 + sizeof(kExampleBadECKeyDER2));
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, copy.data(), copy.size()));
ERR_clear_error();
derp = kExampleRSAKeyPKCS8;
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
sizeof(kExampleRSAKeyPKCS8)));
if (pkey) {
fprintf(stderr, "Imported RSA key as EC key.\n");
return false;
}
// Test that an RSA key may not be imported as an EC key.
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleRSAKeyPKCS8,
sizeof(kExampleRSAKeyPKCS8)));
ERR_clear_error();
return true;
}
int main() {
CRYPTO_library_init();
if (!TestEVP_DigestSignInit()) {
fprintf(stderr, "EVP_DigestSignInit failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestEVP_DigestVerifyInit()) {
fprintf(stderr, "EVP_DigestVerifyInit failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestVerifyRecover()) {
fprintf(stderr, "EVP_PKEY_verify_recover failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!Testd2i_AutoPrivateKey()) {
fprintf(stderr, "Testd2i_AutoPrivateKey failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestEVP_PKCS82PKEY()) {
fprintf(stderr, "TestEVP_PKCS82PKEY failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestEVPMarshalEmptyPublicKey()) {
fprintf(stderr, "TestEVPMarshalEmptyPublicKey failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!Testd2i_PrivateKey()) {
fprintf(stderr, "Testd2i_PrivateKey failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
printf("PASS\n");
return 0;
}
+8 -6
View File
@@ -224,9 +224,8 @@ static bool TestEVP(FileTest *t, void *arg) {
}
EVP_PKEY *key = (*key_map)[key_name].get();
std::vector<uint8_t> input, output;
if (!t->GetBytes(&input, "Input") ||
!t->GetBytes(&output, "Output")) {
std::vector<uint8_t> input;
if (!t->GetBytes(&input, "Input")) {
return false;
}
@@ -263,7 +262,9 @@ static bool TestEVP(FileTest *t, void *arg) {
}
if (t->GetType() == "Verify") {
if (!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
std::vector<uint8_t> output;
if (!t->GetBytes(&output, "Output") ||
!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
input.size())) {
// ECDSA sometimes doesn't push an error code. Push one on the error queue
// so it's distinguishable from other errors.
@@ -274,7 +275,7 @@ static bool TestEVP(FileTest *t, void *arg) {
}
size_t len;
std::vector<uint8_t> actual;
std::vector<uint8_t> actual, output;
if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
return false;
}
@@ -283,7 +284,8 @@ static bool TestEVP(FileTest *t, void *arg) {
return false;
}
actual.resize(len);
if (!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
if (!t->GetBytes(&output, "Output") ||
!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
return false;
}
return true;
File diff suppressed because it is too large Load Diff
-6
View File
@@ -100,12 +100,6 @@ struct evp_pkey_asn1_method_st {
* custom implementations which do not expose key material and parameters.*/
int (*pkey_opaque)(const EVP_PKEY *pk);
/* pkey_supports_digest returns one if |pkey| supports digests of
* type |md|. This is intended for use with EVP_PKEYs backing custom
* implementations which can't sign all digests. If null, it is
* assumed that all digests are supported. */
int (*pkey_supports_digest)(const EVP_PKEY *pkey, const EVP_MD *md);
int (*pkey_size)(const EVP_PKEY *pk);
int (*pkey_bits)(const EVP_PKEY *pk);
+2 -2
View File
@@ -151,7 +151,8 @@ static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* Calculate the public key. */
ctx = BN_CTX_new();
if (ctx == NULL ||
!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
!BN_mod_exp_mont(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx,
NULL)) {
goto err;
}
@@ -255,7 +256,6 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
dsa_priv_encode,
NULL /* pkey_opaque */,
NULL /* pkey_supports_digest */,
int_dsa_size,
dsa_bits,
-1
View File
@@ -244,7 +244,6 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
eckey_priv_encode,
eckey_opaque,
0 /* pkey_supports_digest */,
int_ec_size,
ec_bits,
+6 -13
View File
@@ -386,22 +386,15 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out,
}
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
size_t plaintext_len;
int message_len;
size_t padded_len;
if (!setup_tbuf(rctx, ctx) ||
!RSA_decrypt(rsa, &plaintext_len, rctx->tbuf, key_len, in, inlen,
RSA_NO_PADDING)) {
!RSA_decrypt(rsa, &padded_len, rctx->tbuf, key_len, in, inlen,
RSA_NO_PADDING) ||
!RSA_padding_check_PKCS1_OAEP_mgf1(
out, outlen, key_len, rctx->tbuf, padded_len, rctx->oaep_label,
rctx->oaep_labellen, rctx->md, rctx->mgf1md)) {
return 0;
}
message_len = RSA_padding_check_PKCS1_OAEP_mgf1(
out, key_len, rctx->tbuf, plaintext_len, rctx->oaep_label,
rctx->oaep_labellen, rctx->md, rctx->mgf1md);
if (message_len < 0) {
return 0;
}
*outlen = message_len;
return 1;
}
-5
View File
@@ -162,10 +162,6 @@ static int rsa_opaque(const EVP_PKEY *pkey) {
return RSA_is_opaque(pkey->pkey.rsa);
}
static int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
return RSA_supports_digest(pkey->pkey.rsa, md);
}
static int int_rsa_size(const EVP_PKEY *pkey) {
return RSA_size(pkey->pkey.rsa);
}
@@ -189,7 +185,6 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
rsa_priv_encode,
rsa_opaque,
rsa_supports_digest,
int_rsa_size,
rsa_bits,
+54 -61
View File
@@ -65,83 +65,76 @@
int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
const uint8_t *salt, size_t salt_len, unsigned iterations,
const EVP_MD *digest, size_t key_len, uint8_t *out_key) {
uint8_t digest_tmp[EVP_MAX_MD_SIZE], *p, itmp[4];
size_t cplen, mdlen, tkeylen, k;
unsigned j;
/* See RFC 8018, section 5.2. */
int ret = 0;
size_t md_len = EVP_MD_size(digest);
uint32_t i = 1;
HMAC_CTX hctx_tpl, hctx;
HMAC_CTX hctx;
HMAC_CTX_init(&hctx);
mdlen = EVP_MD_size(digest);
HMAC_CTX_init(&hctx_tpl);
p = out_key;
tkeylen = key_len;
if (!HMAC_Init_ex(&hctx_tpl, password, password_len, digest, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
if (!HMAC_Init_ex(&hctx, password, password_len, digest, NULL)) {
goto err;
}
while (tkeylen) {
if (tkeylen > mdlen) {
cplen = mdlen;
} else {
cplen = tkeylen;
while (key_len > 0) {
size_t todo = md_len;
if (todo > key_len) {
todo = key_len;
}
/* We are unlikely to ever use more than 256 blocks (5120 bits!)
* but just in case... */
itmp[0] = (uint8_t)((i >> 24) & 0xff);
itmp[1] = (uint8_t)((i >> 16) & 0xff);
itmp[2] = (uint8_t)((i >> 8) & 0xff);
itmp[3] = (uint8_t)(i & 0xff);
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, salt, salt_len) ||
!HMAC_Update(&hctx, itmp, 4) ||
uint8_t i_buf[4];
i_buf[0] = (uint8_t)((i >> 24) & 0xff);
i_buf[1] = (uint8_t)((i >> 16) & 0xff);
i_buf[2] = (uint8_t)((i >> 8) & 0xff);
i_buf[3] = (uint8_t)(i & 0xff);
/* Compute U_1. */
uint8_t digest_tmp[EVP_MAX_MD_SIZE];
if (!HMAC_Init_ex(&hctx, NULL, 0, NULL, NULL) ||
!HMAC_Update(&hctx, salt, salt_len) ||
!HMAC_Update(&hctx, i_buf, 4) ||
!HMAC_Final(&hctx, digest_tmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
goto err;
}
HMAC_CTX_cleanup(&hctx);
OPENSSL_memcpy(p, digest_tmp, cplen);
for (j = 1; j < iterations; j++) {
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, digest_tmp, mdlen) ||
OPENSSL_memcpy(out_key, digest_tmp, todo);
for (unsigned j = 1; j < iterations; j++) {
/* Compute the remaining U_* values and XOR. */
if (!HMAC_Init_ex(&hctx, NULL, 0, NULL, NULL) ||
!HMAC_Update(&hctx, digest_tmp, md_len) ||
!HMAC_Final(&hctx, digest_tmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
goto err;
}
HMAC_CTX_cleanup(&hctx);
for (k = 0; k < cplen; k++) {
p[k] ^= digest_tmp[k];
for (size_t k = 0; k < todo; k++) {
out_key[k] ^= digest_tmp[k];
}
}
tkeylen -= cplen;
key_len -= todo;
out_key += todo;
i++;
p += cplen;
}
HMAC_CTX_cleanup(&hctx_tpl);
// RFC 2898 describes iterations (c) as being a "positive integer", so a
// value of 0 is an error.
//
// Unfortunatley not all consumers of PKCS5_PBKDF2_HMAC() check their return
// value, expecting it to succeed and unconditonally using |out_key|.
// As a precaution for such callsites in external code, the old behavior
// of iterations < 1 being treated as iterations == 1 is preserved, but
// additionally an error result is returned.
//
// TODO(eroman): Figure out how to remove this compatibility hack, or change
// the default to something more sensible like 2048.
/* RFC 8018 describes iterations (c) as being a "positive integer", so a
* value of 0 is an error.
*
* Unfortunately not all consumers of PKCS5_PBKDF2_HMAC() check their return
* value, expecting it to succeed and unconditionally using |out_key|. As a
* precaution for such callsites in external code, the old behavior of
* iterations < 1 being treated as iterations == 1 is preserved, but
* additionally an error result is returned.
*
* TODO(eroman): Figure out how to remove this compatibility hack, or change
* the default to something more sensible like 2048. */
if (iterations == 0) {
return 0;
goto err;
}
return 1;
ret = 1;
err:
HMAC_CTX_cleanup(&hctx);
return ret;
}
int PKCS5_PBKDF2_HMAC_SHA1(const char *password, size_t password_len,
+11 -1
View File
@@ -239,6 +239,13 @@ int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to,
return 1;
}
for (size_t i = 0; i < ex_data_class->num_reserved; i++) {
void *ptr = CRYPTO_get_ex_data(from, i);
if (!CRYPTO_set_ex_data(to, i, ptr)) {
return 0;
}
}
STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
if (!get_func_pointers(&func_pointers, ex_data_class)) {
return 0;
@@ -252,7 +259,10 @@ int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to,
func_pointer->dup_func(to, from, &ptr, i + ex_data_class->num_reserved,
func_pointer->argl, func_pointer->argp);
}
CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr);
if (!CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr)) {
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
return 0;
}
}
sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
-9
View File
@@ -69,15 +69,6 @@ uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
const uint8_t *data, size_t data_len, uint8_t *out,
unsigned int *out_len) {
HMAC_CTX ctx;
static uint8_t static_out_buffer[EVP_MAX_MD_SIZE];
/* OpenSSL has traditionally supported using a static buffer if |out| is
* NULL. We maintain that but don't document it. This behaviour should be
* considered to be deprecated. */
if (out == NULL) {
out = static_out_buffer;
}
HMAC_CTX_init(&ctx);
if (!HMAC_Init_ex(&ctx, key, key_len, evp_md, NULL) ||
!HMAC_Update(&ctx, data, data_len) ||
+51 -43
View File
@@ -183,17 +183,22 @@ static inline int buffers_alias(const uint8_t *a, size_t a_len,
*
* can be written as
*
* unsigned int lt = constant_time_lt(a, b);
* c = constant_time_select(lt, a, b); */
* size_t lt = constant_time_lt_s(a, b);
* c = constant_time_select_s(lt, a, b); */
/* constant_time_msb returns the given value with the MSB copied to all the
#define CONSTTIME_TRUE_S ~((size_t)0)
#define CONSTTIME_FALSE_S ((size_t)0)
#define CONSTTIME_TRUE_8 ((uint8_t)0xff)
#define CONSTTIME_FALSE_8 ((uint8_t)0)
/* constant_time_msb_s returns the given value with the MSB copied to all the
* other bits. */
static inline unsigned int constant_time_msb(unsigned int a) {
return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
static inline size_t constant_time_msb_s(size_t a) {
return 0u - (a >> (sizeof(a) * 8 - 1));
}
/* constant_time_lt returns 0xff..f if a < b and 0 otherwise. */
static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) {
/* constant_time_lt_s returns 0xff..f if a < b and 0 otherwise. */
static inline size_t constant_time_lt_s(size_t a, size_t b) {
/* Consider the two cases of the problem:
* msb(a) == msb(b): a < b iff the MSB of a - b is set.
* msb(a) != msb(b): a < b iff the MSB of b is set.
@@ -225,26 +230,28 @@ static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) {
* (check-sat)
* (get-model)
*/
return constant_time_msb(a^((a^b)|((a-b)^a)));
return constant_time_msb_s(a^((a^b)|((a-b)^a)));
}
/* constant_time_lt_8 acts like |constant_time_lt| but returns an 8-bit mask. */
static inline uint8_t constant_time_lt_8(unsigned int a, unsigned int b) {
return (uint8_t)(constant_time_lt(a, b));
/* constant_time_lt_8 acts like |constant_time_lt_s| but returns an 8-bit
* mask. */
static inline uint8_t constant_time_lt_8(size_t a, size_t b) {
return (uint8_t)(constant_time_lt_s(a, b));
}
/* constant_time_gt returns 0xff..f if a >= b and 0 otherwise. */
static inline unsigned int constant_time_ge(unsigned int a, unsigned int b) {
return ~constant_time_lt(a, b);
/* constant_time_ge_s returns 0xff..f if a >= b and 0 otherwise. */
static inline size_t constant_time_ge_s(size_t a, size_t b) {
return ~constant_time_lt_s(a, b);
}
/* constant_time_ge_8 acts like |constant_time_ge| but returns an 8-bit mask. */
static inline uint8_t constant_time_ge_8(unsigned int a, unsigned int b) {
return (uint8_t)(constant_time_ge(a, b));
/* constant_time_ge_8 acts like |constant_time_ge_s| but returns an 8-bit
* mask. */
static inline uint8_t constant_time_ge_8(size_t a, size_t b) {
return (uint8_t)(constant_time_ge_s(a, b));
}
/* constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. */
static inline unsigned int constant_time_is_zero(unsigned int a) {
static inline size_t constant_time_is_zero_s(size_t a) {
/* Here is an SMT-LIB verification of this formula:
*
* (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32)
@@ -257,41 +264,42 @@ static inline unsigned int constant_time_is_zero(unsigned int a) {
* (check-sat)
* (get-model)
*/
return constant_time_msb(~a & (a - 1));
return constant_time_msb_s(~a & (a - 1));
}
/* constant_time_is_zero_8 acts like constant_time_is_zero but returns an 8-bit
/* constant_time_is_zero_8 acts like |constant_time_is_zero_s| but returns an
* 8-bit mask. */
static inline uint8_t constant_time_is_zero_8(size_t a) {
return (uint8_t)(constant_time_is_zero_s(a));
}
/* constant_time_eq_s returns 0xff..f if a == b and 0 otherwise. */
static inline size_t constant_time_eq_s(size_t a, size_t b) {
return constant_time_is_zero_s(a ^ b);
}
/* constant_time_eq_8 acts like |constant_time_eq_s| but returns an 8-bit
* mask. */
static inline uint8_t constant_time_is_zero_8(unsigned int a) {
return (uint8_t)(constant_time_is_zero(a));
static inline uint8_t constant_time_eq_8(size_t a, size_t b) {
return (uint8_t)(constant_time_eq_s(a, b));
}
/* constant_time_eq returns 0xff..f if a == b and 0 otherwise. */
static inline unsigned int constant_time_eq(unsigned int a, unsigned int b) {
return constant_time_is_zero(a ^ b);
}
/* constant_time_eq_8 acts like |constant_time_eq| but returns an 8-bit mask. */
static inline uint8_t constant_time_eq_8(unsigned int a, unsigned int b) {
return (uint8_t)(constant_time_eq(a, b));
}
/* constant_time_eq_int acts like |constant_time_eq| but works on int values. */
static inline unsigned int constant_time_eq_int(int a, int b) {
return constant_time_eq((unsigned)(a), (unsigned)(b));
/* constant_time_eq_int acts like |constant_time_eq_s| but works on int
* values. */
static inline size_t constant_time_eq_int(int a, int b) {
return constant_time_eq_s((size_t)(a), (size_t)(b));
}
/* constant_time_eq_int_8 acts like |constant_time_eq_int| but returns an 8-bit
* mask. */
static inline uint8_t constant_time_eq_int_8(int a, int b) {
return constant_time_eq_8((unsigned)(a), (unsigned)(b));
return constant_time_eq_8((size_t)(a), (size_t)(b));
}
/* constant_time_select returns (mask & a) | (~mask & b). When |mask| is all 1s
* or all 0s (as returned by the methods above), the select methods return
/* constant_time_select_s returns (mask & a) | (~mask & b). When |mask| is all
* 1s or all 0s (as returned by the methods above), the select methods return
* either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). */
static inline unsigned int constant_time_select(unsigned int mask,
unsigned int a, unsigned int b) {
static inline size_t constant_time_select_s(size_t mask, size_t a, size_t b) {
return (mask & a) | (~mask & b);
}
@@ -299,13 +307,13 @@ static inline unsigned int constant_time_select(unsigned int mask,
* 8-bit values. */
static inline uint8_t constant_time_select_8(uint8_t mask, uint8_t a,
uint8_t b) {
return (uint8_t)(constant_time_select(mask, a, b));
return (uint8_t)(constant_time_select_s(mask, a, b));
}
/* constant_time_select_int acts like |constant_time_select| but operates on
* ints. */
static inline int constant_time_select_int(unsigned int mask, int a, int b) {
return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
static inline int constant_time_select_int(size_t mask, int a, int b) {
return (int)(constant_time_select_s(mask, (size_t)(a), (size_t)(b)));
}
-7
View File
@@ -65,13 +65,6 @@
uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out) {
MD5_CTX ctx;
static uint8_t digest[MD5_DIGEST_LENGTH];
/* TODO(fork): remove this static buffer. */
if (out == NULL) {
out = digest;
}
MD5_Init(&ctx);
MD5_Update(&ctx, data, len);
MD5_Final(out, &ctx);
+2 -2
View File
@@ -36,11 +36,11 @@ static void byte_reverse(polyval_block *b) {
static void reverse_and_mulX_ghash(polyval_block *b) {
uint64_t hi = b->u[0];
uint64_t lo = b->u[1];
const unsigned carry = constant_time_eq(hi & 1, 1);
const size_t carry = constant_time_eq_s(hi & 1, 1);
hi >>= 1;
hi |= lo << 63;
lo >>= 1;
lo ^= ((uint64_t) constant_time_select(carry, 0xe1, 0)) << 56;
lo ^= ((uint64_t) constant_time_select_s(carry, 0xe1, 0)) << 56;
b->u[0] = CRYPTO_bswap8(lo);
b->u[1] = CRYPTO_bswap8(hi);
+1 -1
View File
@@ -1134,7 +1134,7 @@ ___
OPTION DOTNAME
___
}
print STDOUT "#if defined(__x86_64__)\n" if ($gas);
print STDOUT "#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)\n" if ($gas);
while(defined(my $line=<>)) {
+1 -1
View File
@@ -6,7 +6,7 @@ add_library(
OBJECT
pkcs8.c
p8_pkey.c
pkcs8_x509.c
p5_pbev2.c
)
+26 -8
View File
@@ -63,35 +63,53 @@ extern "C" {
#endif
#define PBE_UCS2_CONVERT_PASSWORD 0x1
/* pkcs8_pbe_decrypt decrypts |in| using the PBE scheme described by
* |algorithm|, which should be a serialized AlgorithmIdentifier structure. On
* success, it sets |*out| to a newly-allocated buffer containing the decrypted
* result and returns one. Otherwise, it returns zero. */
int pkcs8_pbe_decrypt(uint8_t **out, size_t *out_len, CBS *algorithm,
const char *pass, size_t pass_len, const uint8_t *in,
size_t in_len);
#define PKCS12_KEY_ID 1
#define PKCS12_IV_ID 2
#define PKCS12_MAC_ID 3
/* pkcs12_key_gen runs the PKCS#12 key derivation function as specified in
* RFC 7292, appendix B. On success, it writes the resulting |out_len| bytes of
* key material to |out| and returns one. Otherwise, it returns zero. |id|
* should be one of the |PKCS12_*_ID| values. */
int pkcs12_key_gen(const char *pass, size_t pass_len, const uint8_t *salt,
size_t salt_len, uint8_t id, unsigned iterations,
size_t out_len, uint8_t *out, const EVP_MD *md);
struct pbe_suite {
int pbe_nid;
uint8_t oid[10];
uint8_t oid_len;
const EVP_CIPHER *(*cipher_func)(void);
const EVP_MD *(*md_func)(void);
/* decrypt_init initialize |ctx| for decrypting. The password is specified by
* |pass_raw| and |pass_raw_len|. |param| contains the serialized parameters
* field of the AlgorithmIdentifier.
* |pass| and |pass_len|. |param| contains the serialized parameters field of
* the AlgorithmIdentifier.
*
* It returns one on success and zero on error. */
int (*decrypt_init)(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
const uint8_t *pass_raw, size_t pass_raw_len, CBS *param);
int flags;
const char *pass, size_t pass_len, CBS *param);
};
#define PKCS5_DEFAULT_ITERATIONS 2048
#define PKCS5_SALT_LEN 8
int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
const uint8_t *pass_raw, size_t pass_raw_len,
CBS *param);
const char *pass, size_t pass_len, CBS *param);
/* PKCS5_pbe2_encrypt_init configures |ctx| for encrypting with PKCS #5 PBES2,
* as defined in RFC 2998, with the specified parameters. It writes the
* corresponding AlgorithmIdentifier to |out|. */
int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher, unsigned iterations,
const uint8_t *pass_raw, size_t pass_raw_len,
const char *pass, size_t pass_len,
const uint8_t *salt, size_t salt_len);
+107 -26
View File
@@ -62,16 +62,86 @@
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/nid.h>
#include <openssl/rand.h>
#include "internal.h"
#include "../internal.h"
/* 1.2.840.113549.1.5.12 */
static const uint8_t kPBKDF2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x05, 0x0c};
/* 1.2.840.113549.1.5.13 */
static const uint8_t kPBES2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x05, 0x0d};
/* 1.2.840.113549.2.7 */
static const uint8_t kHMACWithSHA1[] = {0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x02, 0x07};
static const struct {
uint8_t oid[9];
uint8_t oid_len;
int nid;
const EVP_CIPHER *(*cipher_func)(void);
} kCipherOIDs[] = {
/* 1.2.840.113549.3.2 */
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02},
8,
NID_rc2_cbc,
&EVP_rc2_cbc},
/* 1.2.840.113549.3.7 */
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07},
8,
NID_des_ede3_cbc,
&EVP_des_ede3_cbc},
/* 2.16.840.1.101.3.4.1.2 */
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02},
9,
NID_aes_128_cbc,
&EVP_aes_128_cbc},
/* 2.16.840.1.101.3.4.1.22 */
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16},
9,
NID_aes_192_cbc,
&EVP_aes_192_cbc},
/* 2.16.840.1.101.3.4.1.42 */
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a},
9,
NID_aes_256_cbc,
&EVP_aes_256_cbc},
};
static const EVP_CIPHER *cbs_to_cipher(const CBS *cbs) {
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
if (CBS_mem_equal(cbs, kCipherOIDs[i].oid, kCipherOIDs[i].oid_len)) {
return kCipherOIDs[i].cipher_func();
}
}
return NULL;
}
static int add_cipher_oid(CBB *out, int nid) {
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
if (kCipherOIDs[i].nid == nid) {
CBB child;
return CBB_add_asn1(out, &child, CBS_ASN1_OBJECT) &&
CBB_add_bytes(&child, kCipherOIDs[i].oid,
kCipherOIDs[i].oid_len) &&
CBB_flush(out);
}
}
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
return 0;
}
static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
unsigned iterations, const uint8_t *pass_raw,
size_t pass_raw_len, const uint8_t *salt,
unsigned iterations, const char *pass,
size_t pass_len, const uint8_t *salt,
size_t salt_len, const uint8_t *iv,
size_t iv_len, int enc) {
if (iv_len != EVP_CIPHER_iv_length(cipher)) {
@@ -80,8 +150,7 @@ static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
}
uint8_t key[EVP_MAX_KEY_LENGTH];
int ret = PKCS5_PBKDF2_HMAC_SHA1((const char *)pass_raw, pass_raw_len, salt,
salt_len, iterations,
int ret = PKCS5_PBKDF2_HMAC_SHA1(pass, pass_len, salt, salt_len, iterations,
EVP_CIPHER_key_length(cipher), key) &&
EVP_CipherInit_ex(ctx, cipher, NULL /* engine */, key, iv, enc);
OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
@@ -90,7 +159,7 @@ static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher, unsigned iterations,
const uint8_t *pass_raw, size_t pass_raw_len,
const char *pass, size_t pass_len,
const uint8_t *salt, size_t salt_len) {
int cipher_nid = EVP_CIPHER_nid(cipher);
if (cipher_nid == NID_undef) {
@@ -105,12 +174,15 @@ int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
}
/* See RFC 2898, appendix A. */
CBB algorithm, param, kdf, kdf_param, salt_cbb, cipher_cbb, iv_cbb;
CBB algorithm, oid, param, kdf, kdf_oid, kdf_param, salt_cbb, cipher_cbb,
iv_cbb;
if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) ||
!OBJ_nid2cbb(&algorithm, NID_pbes2) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, kPBES2, sizeof(kPBES2)) ||
!CBB_add_asn1(&algorithm, &param, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&param, &kdf, CBS_ASN1_SEQUENCE) ||
!OBJ_nid2cbb(&kdf, NID_id_pbkdf2) ||
!CBB_add_asn1(&kdf, &kdf_oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&kdf_oid, kPBKDF2, sizeof(kPBKDF2)) ||
!CBB_add_asn1(&kdf, &kdf_param, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&kdf_param, &salt_cbb, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&salt_cbb, salt, salt_len) ||
@@ -120,7 +192,7 @@ int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
!CBB_add_asn1_uint64(&kdf_param, EVP_CIPHER_key_length(cipher))) ||
/* Omit the PRF. We use the default hmacWithSHA1. */
!CBB_add_asn1(&param, &cipher_cbb, CBS_ASN1_SEQUENCE) ||
!OBJ_nid2cbb(&cipher_cbb, cipher_nid) ||
!add_cipher_oid(&cipher_cbb, cipher_nid) ||
/* RFC 2898 says RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and
* IV, but OpenSSL always uses an OCTET STRING IV, so we do the same. */
!CBB_add_asn1(&cipher_cbb, &iv_cbb, CBS_ASN1_OCTETSTRING) ||
@@ -129,14 +201,13 @@ int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
return 0;
}
return pkcs5_pbe2_cipher_init(ctx, cipher, iterations, pass_raw, pass_raw_len,
salt, salt_len, iv,
EVP_CIPHER_iv_length(cipher), 1 /* encrypt */);
return pkcs5_pbe2_cipher_init(ctx, cipher, iterations, pass, pass_len, salt,
salt_len, iv, EVP_CIPHER_iv_length(cipher),
1 /* encrypt */);
}
int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
const uint8_t *pass_raw, size_t pass_raw_len,
CBS *param) {
const char *pass, size_t pass_len, CBS *param) {
CBS pbe_param, kdf, kdf_obj, enc_scheme, enc_obj;
if (!CBS_get_asn1(param, &pbe_param, CBS_ASN1_SEQUENCE) ||
CBS_len(param) != 0 ||
@@ -149,20 +220,20 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
return 0;
}
/* Check that the key derivation function is PBKDF2. */
if (OBJ_cbs2nid(&kdf_obj) != NID_id_pbkdf2) {
/* Only PBKDF2 is supported. */
if (!CBS_mem_equal(&kdf_obj, kPBKDF2, sizeof(kPBKDF2))) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
return 0;
}
/* See if we recognise the encryption algorithm. */
const EVP_CIPHER *cipher = EVP_get_cipherbynid(OBJ_cbs2nid(&enc_obj));
const EVP_CIPHER *cipher = cbs_to_cipher(&enc_obj);
if (cipher == NULL) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
return 0;
}
/* Parse the KDF parameters. */
/* Parse the KDF parameters. See RFC 8018, appendix A.2. */
CBS pbkdf2_params, salt;
uint64_t iterations;
if (!CBS_get_asn1(&kdf, &pbkdf2_params, CBS_ASN1_SEQUENCE) ||
@@ -194,8 +265,9 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
}
if (CBS_len(&pbkdf2_params) != 0) {
CBS prf;
if (!CBS_get_asn1(&pbkdf2_params, &prf, CBS_ASN1_OBJECT) ||
CBS alg_id, prf;
if (!CBS_get_asn1(&pbkdf2_params, &alg_id, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&alg_id, &prf, CBS_ASN1_OBJECT) ||
CBS_len(&pbkdf2_params) != 0) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
return 0;
@@ -203,16 +275,25 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
/* We only support hmacWithSHA1. It is the DEFAULT, so DER requires it be
* omitted, but we match OpenSSL in tolerating it being present. */
if (OBJ_cbs2nid(&prf) != NID_hmacWithSHA1) {
if (!CBS_mem_equal(&prf, kHMACWithSHA1, sizeof(kHMACWithSHA1))) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF);
return 0;
}
/* hmacWithSHA1 has a NULL parameter. */
CBS null;
if (!CBS_get_asn1(&alg_id, &null, CBS_ASN1_NULL) ||
CBS_len(&null) != 0 ||
CBS_len(&alg_id) != 0) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
return 0;
}
}
/* Parse the encryption scheme parameters. Note OpenSSL does not match the
* specification. Per RFC 2898, this should depend on the encryption scheme.
* In particular, RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and IV.
* We align with OpenSSL. */
* In particular, RC2-CBC uses a SEQUENCE with version and IV. We align with
* OpenSSL. */
CBS iv;
if (!CBS_get_asn1(&enc_scheme, &iv, CBS_ASN1_OCTETSTRING) ||
CBS_len(&enc_scheme) != 0) {
@@ -220,7 +301,7 @@ int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
return 0;
}
return pkcs5_pbe2_cipher_init(ctx, cipher, (unsigned)iterations, pass_raw,
pass_raw_len, CBS_data(&salt), CBS_len(&salt),
return pkcs5_pbe2_cipher_init(ctx, cipher, (unsigned)iterations, pass,
pass_len, CBS_data(&salt), CBS_len(&salt),
CBS_data(&iv), CBS_len(&iv), 0 /* decrypt */);
}
-85
View File
@@ -1,85 +0,0 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <stdio.h>
#include <openssl/asn1t.h>
#include <openssl/mem.h>
#include <openssl/x509.h>
/* Minor tweak to operation: zero private key data */
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) {
/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
if (operation == ASN1_OP_FREE_PRE) {
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING &&
key->pkey->value.octet_string) {
OPENSSL_cleanse(key->pkey->value.octet_string->data,
key->pkey->value.octet_string->length);
}
}
return 1;
}
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+220
View File
@@ -679,6 +679,225 @@ static const uint8_t kWindows[] = {
0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
};
/* kPBES2 is a PKCS#12 file using PBES2 created with:
* openssl pkcs12 -export -inkey key.pem -in cert.pem -keypbe AES-128-CBC \
* -certpbe AES-128-CBC */
static const uint8_t kPBES2[] = {
0x30, 0x82, 0x0a, 0x03, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0xc9, 0x06,
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
0x09, 0xba, 0x04, 0x82, 0x09, 0xb6, 0x30, 0x82, 0x09, 0xb2, 0x30, 0x82,
0x04, 0x34, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
0x06, 0xa0, 0x82, 0x04, 0x25, 0x30, 0x82, 0x04, 0x21, 0x02, 0x01, 0x00,
0x30, 0x82, 0x04, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x07, 0x01, 0x30, 0x49, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x05, 0x0d, 0x30, 0x3c, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x0e, 0x04, 0x08, 0xdb,
0x48, 0xe6, 0x98, 0x09, 0x8f, 0x6e, 0x2d, 0x02, 0x02, 0x08, 0x00, 0x30,
0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02,
0x04, 0x10, 0xee, 0xb3, 0x10, 0xe5, 0x21, 0x85, 0x03, 0x3e, 0x69, 0xad,
0xdf, 0x78, 0xa7, 0xd8, 0xac, 0xf1, 0x80, 0x82, 0x03, 0xc0, 0xcb, 0x58,
0x11, 0x28, 0x1d, 0xbc, 0x3c, 0x8c, 0xe7, 0x7b, 0x15, 0x67, 0x30, 0xf3,
0x2b, 0x94, 0x10, 0x8c, 0xbe, 0xfd, 0xaa, 0x11, 0xd7, 0x99, 0xee, 0x21,
0xb6, 0x1b, 0x4f, 0x53, 0xcb, 0x44, 0xff, 0x4f, 0xbf, 0xf6, 0x43, 0x3d,
0x12, 0xe6, 0x09, 0xe8, 0x05, 0xdd, 0x2f, 0xc5, 0x39, 0xde, 0x0c, 0x88,
0xe8, 0x4e, 0x89, 0x8f, 0x5f, 0xdf, 0x23, 0x50, 0xe6, 0xb7, 0xba, 0x1a,
0xdd, 0x1c, 0x63, 0x51, 0x0e, 0x71, 0xb7, 0xf7, 0x39, 0x3c, 0xd4, 0xe7,
0x52, 0x50, 0xc5, 0xd7, 0xbf, 0x65, 0x94, 0x72, 0x97, 0x2a, 0xb9, 0x68,
0xc2, 0xbd, 0x0c, 0x97, 0x02, 0x74, 0x23, 0x7f, 0x11, 0x6b, 0xea, 0xb4,
0xe4, 0x2f, 0xf0, 0x8b, 0x91, 0x5c, 0xdb, 0xae, 0x10, 0xbf, 0x89, 0xbc,
0x62, 0xef, 0x99, 0xbf, 0x07, 0x59, 0x58, 0x12, 0xef, 0xaf, 0xe6, 0xcd,
0x30, 0x27, 0xe4, 0xab, 0x44, 0xf7, 0xf9, 0x14, 0xb2, 0x5d, 0xfa, 0x97,
0xe6, 0x9a, 0xed, 0x85, 0x60, 0x86, 0xd9, 0xb0, 0xd7, 0xa4, 0xe4, 0x00,
0xa8, 0xee, 0xbb, 0xfc, 0x0d, 0xe8, 0x58, 0x7a, 0xca, 0x02, 0x1d, 0x02,
0xab, 0xbd, 0x16, 0x50, 0x4f, 0xfc, 0x60, 0xde, 0x48, 0xb1, 0x7f, 0xea,
0xba, 0x45, 0x7b, 0x29, 0xfe, 0x8e, 0xed, 0x48, 0xd2, 0x31, 0x64, 0xda,
0x89, 0x84, 0x6f, 0xd1, 0xd2, 0xb1, 0x7b, 0x97, 0x19, 0x38, 0x16, 0xd9,
0x3f, 0xd6, 0xdb, 0x6f, 0xab, 0x56, 0x34, 0xca, 0x34, 0x9c, 0x57, 0x41,
0x6e, 0x87, 0x85, 0x2a, 0xa8, 0xfb, 0xe9, 0xf6, 0x3d, 0xb6, 0x83, 0x7b,
0x02, 0xc9, 0xbe, 0xf1, 0xbb, 0x8e, 0xe5, 0x68, 0xae, 0xaa, 0xe1, 0x25,
0x8d, 0x1f, 0x1f, 0x52, 0x45, 0x3e, 0xef, 0x33, 0xd8, 0x58, 0xd9, 0x48,
0xd4, 0xb5, 0xe1, 0x53, 0x21, 0xb5, 0xbd, 0xd4, 0x63, 0x1f, 0xbf, 0xe4,
0x30, 0x5e, 0xc3, 0x63, 0xce, 0xdc, 0x12, 0x8c, 0xc7, 0x0c, 0xea, 0x3b,
0xf3, 0x0b, 0x38, 0x8d, 0xcc, 0x9b, 0xe7, 0xa0, 0x14, 0x5e, 0x48, 0x9c,
0x74, 0x86, 0x8e, 0x2b, 0x77, 0x80, 0xbb, 0x85, 0xa6, 0xd4, 0x25, 0x6e,
0x75, 0x07, 0x59, 0xd6, 0x88, 0x00, 0x35, 0x03, 0x5a, 0xb0, 0x86, 0x7e,
0x01, 0xa7, 0x77, 0x74, 0x13, 0xfa, 0x9f, 0x2d, 0xe3, 0x90, 0xda, 0x68,
0x23, 0x36, 0x0b, 0x62, 0x21, 0x76, 0xda, 0x6c, 0x05, 0x35, 0x80, 0xfc,
0xee, 0x5f, 0x3c, 0xac, 0x60, 0x2a, 0x9c, 0x6e, 0x4c, 0xaa, 0xa3, 0xd1,
0xdf, 0x2c, 0x7e, 0x0e, 0xc0, 0xa0, 0x84, 0xe4, 0xb2, 0x33, 0x1f, 0x8c,
0xcb, 0x74, 0x31, 0x18, 0x5b, 0x0b, 0x18, 0x41, 0xc6, 0x87, 0x13, 0xa2,
0xad, 0x1d, 0x43, 0x5e, 0x67, 0xd0, 0x31, 0xf5, 0x61, 0x7c, 0x3d, 0x16,
0x55, 0x01, 0x94, 0x45, 0xa4, 0x50, 0x0f, 0xb1, 0x1b, 0x81, 0x51, 0xa7,
0x92, 0xae, 0xa3, 0x6d, 0x4e, 0x55, 0x46, 0x37, 0x98, 0xe1, 0xe4, 0x5c,
0x29, 0x79, 0xc9, 0x76, 0x0a, 0xb5, 0x9d, 0x1b, 0x8a, 0xf6, 0xab, 0xeb,
0x69, 0x6e, 0x17, 0x88, 0xeb, 0x82, 0xfa, 0x78, 0x2f, 0x8c, 0x30, 0xfd,
0xf1, 0x74, 0xcd, 0x53, 0x78, 0x27, 0x43, 0x82, 0x05, 0x37, 0x07, 0xb3,
0x4c, 0x89, 0x9d, 0x00, 0x1d, 0x73, 0xad, 0x0f, 0xcd, 0x63, 0xbe, 0x9b,
0xa9, 0x50, 0xa5, 0x43, 0x74, 0x86, 0x87, 0xbc, 0xd9, 0x97, 0x66, 0x84,
0x35, 0x3e, 0x67, 0xce, 0x92, 0x2c, 0x78, 0xc7, 0x88, 0x19, 0x6a, 0x1c,
0xa8, 0x93, 0x0b, 0x79, 0x21, 0xe5, 0x39, 0x1b, 0x00, 0x68, 0x2a, 0x0b,
0xac, 0x6a, 0x2f, 0xc1, 0x9c, 0x90, 0x18, 0x86, 0x63, 0x53, 0x72, 0x34,
0xd9, 0xa8, 0x92, 0xce, 0x64, 0x3a, 0xeb, 0xba, 0xd8, 0x31, 0xf3, 0xfb,
0x2a, 0xac, 0xc6, 0xe7, 0xd1, 0x0b, 0x7c, 0xfc, 0xbb, 0x69, 0x57, 0xc8,
0x97, 0x3d, 0xdb, 0x81, 0x77, 0x2a, 0x9f, 0x07, 0x2c, 0x79, 0x69, 0xbc,
0x51, 0x0e, 0x68, 0x11, 0x00, 0x10, 0xed, 0x9f, 0xb8, 0x8d, 0xa0, 0x25,
0x20, 0xd3, 0x3d, 0x08, 0x20, 0x46, 0xfa, 0x89, 0xef, 0x69, 0x4c, 0x60,
0x33, 0x80, 0xb9, 0x53, 0xb4, 0x7b, 0xab, 0x38, 0xf1, 0xcd, 0xb8, 0x75,
0xc4, 0x85, 0x0a, 0xda, 0xab, 0x19, 0x40, 0xd3, 0x88, 0xd5, 0xf7, 0x5f,
0x8e, 0xcd, 0x8e, 0xa4, 0x1c, 0x9c, 0x22, 0x6d, 0xce, 0x66, 0x29, 0xfa,
0x62, 0x6f, 0x01, 0xdc, 0x46, 0x45, 0x38, 0x64, 0xf7, 0xc4, 0x94, 0xfd,
0x48, 0x44, 0x70, 0x4d, 0xef, 0xf0, 0x4b, 0x95, 0xf8, 0x68, 0x8d, 0xb7,
0x35, 0x7d, 0xc6, 0xf5, 0x97, 0xce, 0x5d, 0xad, 0xe8, 0x5c, 0xeb, 0x4f,
0x9b, 0x5b, 0x03, 0xce, 0x33, 0x60, 0xf5, 0xce, 0xcc, 0xfe, 0xfb, 0x77,
0x40, 0xc4, 0xf4, 0x9d, 0xf3, 0x2c, 0xdb, 0x83, 0xc2, 0x1a, 0xf2, 0xb6,
0xbe, 0xfc, 0x2c, 0x7f, 0x29, 0x20, 0x35, 0x50, 0x00, 0x60, 0x03, 0xd2,
0xb3, 0x03, 0x18, 0x64, 0xb9, 0x64, 0x98, 0x33, 0xdb, 0x47, 0x43, 0xe2,
0xa1, 0x85, 0x79, 0x9b, 0xb1, 0x0b, 0x0e, 0xbb, 0x14, 0x5f, 0xb9, 0x16,
0xb6, 0xc3, 0xf6, 0x5c, 0x01, 0xe3, 0xaa, 0x3f, 0x03, 0xad, 0x18, 0xeb,
0x0e, 0x3d, 0xa3, 0x1f, 0xcc, 0x4d, 0x48, 0x44, 0x7e, 0xda, 0xb9, 0x9d,
0x17, 0xe8, 0x92, 0x46, 0xea, 0xf5, 0x3e, 0x05, 0x4e, 0xa7, 0xb5, 0x94,
0x6d, 0x95, 0x42, 0xa7, 0x71, 0xfb, 0xc2, 0x45, 0xd6, 0xd2, 0x86, 0xd0,
0x79, 0x99, 0x1f, 0x96, 0x78, 0x22, 0xeb, 0x05, 0x26, 0xf2, 0xa1, 0x67,
0x67, 0x2b, 0xae, 0x1d, 0x28, 0x42, 0xd6, 0xbe, 0x08, 0xf6, 0xb7, 0x54,
0xc8, 0x82, 0xbf, 0x92, 0x0f, 0x2c, 0xba, 0x47, 0xe2, 0x01, 0x73, 0x2c,
0xd7, 0x34, 0x84, 0x2f, 0xb6, 0x41, 0x84, 0xeb, 0x7a, 0xb2, 0xf9, 0xdd,
0x31, 0xbe, 0x07, 0xb4, 0x88, 0x05, 0xd8, 0xe1, 0x79, 0x55, 0xe6, 0x4b,
0x8c, 0xdc, 0xd1, 0x76, 0x58, 0x72, 0x42, 0x28, 0xb3, 0x9f, 0xd0, 0x05,
0x37, 0x6b, 0x65, 0x74, 0xce, 0x0d, 0x01, 0xa9, 0x49, 0xc5, 0x90, 0xab,
0x90, 0x16, 0x2c, 0x9c, 0xba, 0xcb, 0x94, 0xc7, 0xfa, 0xe0, 0x39, 0x82,
0xa2, 0x88, 0xd6, 0x0c, 0xc4, 0x4d, 0xfe, 0xb4, 0xbc, 0x87, 0xe5, 0x63,
0x3b, 0x6b, 0xf0, 0xd1, 0x09, 0x39, 0x8f, 0x51, 0x4f, 0x32, 0xae, 0xed,
0x0c, 0xff, 0x79, 0x52, 0x19, 0xa9, 0x4e, 0x45, 0x11, 0xc3, 0x5f, 0xd6,
0x2b, 0x66, 0xe3, 0x9c, 0xbe, 0xbc, 0xda, 0x65, 0x25, 0xcd, 0xf5, 0x73,
0x45, 0x09, 0xf5, 0x5d, 0x6b, 0x83, 0x45, 0x28, 0x98, 0x2c, 0x58, 0x44,
0xca, 0x37, 0xeb, 0xc3, 0xc2, 0x10, 0x77, 0x14, 0x79, 0x9b, 0xd8, 0xb2,
0xbf, 0x45, 0xd5, 0x63, 0xe4, 0x37, 0x42, 0x7b, 0x2d, 0xe2, 0x49, 0xb3,
0x18, 0x8e, 0x86, 0x73, 0xf1, 0x59, 0x8a, 0xf2, 0x3c, 0x49, 0x12, 0x7b,
0xb1, 0x40, 0x8c, 0x8c, 0xac, 0x05, 0x50, 0xbd, 0x9b, 0x3b, 0x84, 0x81,
0x68, 0x26, 0x88, 0x1b, 0xbf, 0xa0, 0x28, 0xc2, 0x06, 0xa9, 0xe4, 0xd9,
0x1f, 0x5d, 0xca, 0x96, 0x4f, 0xfe, 0xd8, 0x64, 0xee, 0x73, 0x30, 0x82,
0x05, 0x76, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
0x01, 0xa0, 0x82, 0x05, 0x67, 0x04, 0x82, 0x05, 0x63, 0x30, 0x82, 0x05,
0x5f, 0x30, 0x82, 0x05, 0x5b, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x05, 0x23, 0x30, 0x82,
0x05, 0x1f, 0x30, 0x49, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x05, 0x0d, 0x30, 0x3c, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48,
0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x0e, 0x04, 0x08, 0xe3, 0x3e,
0xd3, 0x8d, 0xd6, 0xb5, 0x8a, 0x05, 0x02, 0x02, 0x08, 0x00, 0x30, 0x1d,
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02, 0x04,
0x10, 0x61, 0xa0, 0x2f, 0x8d, 0x0c, 0xa1, 0x03, 0xc9, 0xdf, 0x2e, 0x81,
0x65, 0xe0, 0x63, 0x70, 0x55, 0x04, 0x82, 0x04, 0xd0, 0x24, 0x1e, 0xf9,
0x1d, 0xc4, 0xe9, 0xbf, 0x49, 0x3c, 0x1e, 0x55, 0x4a, 0xd4, 0xb0, 0x0c,
0xdd, 0x5b, 0x92, 0xb2, 0xed, 0x18, 0xac, 0x66, 0x90, 0x1b, 0x29, 0x3d,
0x10, 0xad, 0x02, 0xe7, 0x17, 0x83, 0x44, 0x67, 0xba, 0x11, 0x6f, 0x05,
0xf5, 0xf7, 0x37, 0xcb, 0x5a, 0xe9, 0x0e, 0xc3, 0x4b, 0x1b, 0x62, 0xee,
0xb2, 0xb7, 0x14, 0x85, 0x07, 0x2d, 0x95, 0x83, 0xa9, 0xdc, 0x3d, 0x4b,
0x33, 0xad, 0x68, 0xbf, 0x54, 0xf8, 0xef, 0x25, 0x05, 0x40, 0xcd, 0x61,
0xbe, 0x12, 0xeb, 0x78, 0x75, 0x36, 0x08, 0x8c, 0x5a, 0x57, 0xa1, 0x98,
0xd5, 0x42, 0x01, 0x1b, 0x4c, 0x25, 0xc2, 0x18, 0x9f, 0x91, 0xfe, 0x78,
0x88, 0x99, 0x47, 0x5a, 0x20, 0x2c, 0x37, 0x31, 0x05, 0x98, 0xef, 0x91,
0x6e, 0xeb, 0x2e, 0x86, 0x90, 0x61, 0xb1, 0x57, 0x1a, 0x05, 0x82, 0x14,
0x0c, 0xa8, 0x94, 0xae, 0x56, 0x7b, 0xd6, 0x2f, 0x8b, 0x2e, 0x91, 0xa6,
0x12, 0x68, 0x1f, 0x06, 0x09, 0x2f, 0xa6, 0xed, 0x33, 0x99, 0x72, 0x56,
0xe5, 0xf7, 0xea, 0xcc, 0xcf, 0x27, 0xa5, 0xad, 0x49, 0x5a, 0xbc, 0x7b,
0xe3, 0x62, 0x63, 0x8f, 0x00, 0x2b, 0x96, 0xc5, 0x3f, 0xaf, 0x24, 0xba,
0xf6, 0x8d, 0xe2, 0xef, 0x18, 0x50, 0xd6, 0xd8, 0x4f, 0xb2, 0x5d, 0xb7,
0x96, 0x6f, 0x02, 0xf7, 0x7d, 0xf2, 0xa2, 0x7b, 0x9b, 0x13, 0x98, 0xde,
0xdd, 0x6e, 0xb5, 0x48, 0x52, 0x8e, 0x44, 0xad, 0xe0, 0xcf, 0x40, 0x9f,
0xfd, 0x88, 0x33, 0x66, 0xce, 0x6a, 0x49, 0x5f, 0xe7, 0x4b, 0x36, 0x93,
0x7f, 0x49, 0x62, 0xc9, 0x5a, 0xae, 0xa1, 0xca, 0xf7, 0x5a, 0xbe, 0x85,
0x77, 0x9a, 0x8f, 0xce, 0x4d, 0x84, 0x81, 0xd0, 0xa2, 0xee, 0x60, 0x92,
0x86, 0x16, 0x2a, 0xd5, 0x08, 0xb6, 0x58, 0x63, 0x07, 0x7c, 0x41, 0xac,
0x97, 0x4f, 0xf0, 0xcf, 0xd8, 0xd2, 0xb1, 0xd7, 0x1d, 0xe5, 0xb8, 0x7c,
0x04, 0x2b, 0xd9, 0xee, 0xf7, 0x22, 0x88, 0xa1, 0x53, 0xdb, 0x5e, 0x5b,
0x47, 0x49, 0xeb, 0xcf, 0x04, 0x78, 0x69, 0xd1, 0xfc, 0x8a, 0xa9, 0x61,
0x92, 0xbf, 0x5c, 0x7f, 0xde, 0x49, 0x42, 0xfc, 0x0d, 0xc2, 0xa2, 0x8f,
0xba, 0xdf, 0x12, 0xa4, 0x62, 0xfb, 0x8d, 0xd3, 0xc5, 0xf9, 0x85, 0x4c,
0x17, 0x70, 0xb7, 0xf7, 0x99, 0x29, 0x52, 0x92, 0x36, 0xc5, 0x4b, 0x31,
0x23, 0x5c, 0x09, 0x27, 0x3c, 0xa0, 0x76, 0x5d, 0x92, 0x99, 0x63, 0x88,
0xca, 0xad, 0xed, 0xd7, 0x85, 0x98, 0x2f, 0xbe, 0xaa, 0xa5, 0xf3, 0x0a,
0x76, 0x13, 0x01, 0x90, 0x8a, 0xe7, 0x5a, 0x2d, 0x2b, 0x1a, 0x80, 0x33,
0x86, 0xab, 0xd8, 0xa7, 0xae, 0x0b, 0x7d, 0xcd, 0x64, 0x8d, 0xa6, 0xb6,
0xfb, 0x83, 0x9f, 0x91, 0x23, 0xcb, 0xda, 0x63, 0xd0, 0xde, 0xf4, 0xdd,
0xaa, 0x23, 0x49, 0x6c, 0x44, 0xfa, 0x6f, 0x12, 0x13, 0x90, 0x37, 0xde,
0xa3, 0x72, 0x45, 0x1a, 0xa7, 0xab, 0x01, 0x6d, 0xd6, 0x34, 0xe7, 0x51,
0x0e, 0x33, 0xbc, 0x09, 0xbf, 0xb6, 0x16, 0xf8, 0xd3, 0x11, 0x11, 0xd1,
0x5f, 0xaa, 0x32, 0xb6, 0x5b, 0xe7, 0xbc, 0xdd, 0xaa, 0xe4, 0xed, 0x42,
0x3d, 0x2e, 0xf7, 0xa1, 0x06, 0x39, 0xd4, 0x00, 0xc6, 0xc8, 0xed, 0xb5,
0x96, 0xc1, 0xbf, 0x4c, 0xf1, 0xf6, 0xc6, 0x59, 0xf4, 0x99, 0x9c, 0x10,
0x22, 0xa1, 0x3a, 0xcd, 0x94, 0xac, 0x0b, 0xc8, 0x7e, 0x29, 0xbc, 0xf0,
0xae, 0x27, 0x7a, 0xb8, 0x5c, 0xa0, 0x13, 0x36, 0xb5, 0x19, 0x4b, 0x2c,
0xc1, 0xce, 0x49, 0x57, 0x1d, 0x36, 0xf0, 0xc2, 0x4c, 0xdf, 0x6d, 0xc9,
0x64, 0x68, 0xcb, 0xea, 0x22, 0x32, 0xd7, 0x11, 0x2c, 0x77, 0xbe, 0x01,
0xa3, 0x82, 0x2d, 0xa1, 0x4b, 0x13, 0x93, 0x87, 0x3d, 0x01, 0x74, 0xc6,
0xc6, 0xf9, 0xae, 0x2e, 0xa1, 0x44, 0x5d, 0x47, 0x6c, 0x6f, 0xc6, 0xce,
0xef, 0x32, 0xf8, 0x8d, 0x53, 0x4d, 0xa5, 0xf0, 0xa0, 0x51, 0x7e, 0xd8,
0x35, 0x55, 0x2a, 0x04, 0xb9, 0x42, 0xa7, 0x51, 0xba, 0xad, 0xce, 0x88,
0x7b, 0x93, 0x25, 0x9d, 0x03, 0x08, 0xfa, 0x75, 0x38, 0x63, 0x78, 0x13,
0x11, 0x9d, 0xf6, 0xcc, 0x18, 0xe3, 0x99, 0xa9, 0x5d, 0x90, 0x6b, 0xbf,
0x9c, 0x69, 0x99, 0x63, 0x27, 0x35, 0x8a, 0x26, 0x07, 0x67, 0xd1, 0xae,
0x57, 0xec, 0xc0, 0x45, 0x6e, 0x2a, 0x42, 0x46, 0x8f, 0xe4, 0x84, 0xc7,
0x67, 0x06, 0x0c, 0xa7, 0x7e, 0x5c, 0x20, 0x80, 0xdc, 0xc1, 0xe4, 0x7a,
0x74, 0x76, 0x8f, 0x41, 0x78, 0xce, 0x6a, 0xf9, 0xcb, 0x7f, 0xe9, 0x17,
0x70, 0x45, 0x01, 0x9a, 0xc3, 0x9c, 0xa2, 0x68, 0xa0, 0x79, 0xfd, 0x44,
0x4c, 0xc8, 0xa0, 0xaf, 0xa5, 0xba, 0x0f, 0x03, 0x30, 0x43, 0x4a, 0x1d,
0x3e, 0xd4, 0x8e, 0x1f, 0x6d, 0x09, 0xf9, 0x63, 0xde, 0xd2, 0x9e, 0x77,
0xe7, 0xde, 0x61, 0x52, 0x76, 0x0f, 0x6d, 0x37, 0xf7, 0xc2, 0x69, 0x96,
0x9d, 0xc5, 0xd9, 0x15, 0x10, 0xf2, 0x22, 0x1f, 0x3b, 0x83, 0xb3, 0xb4,
0x2c, 0x25, 0x36, 0xc3, 0x3a, 0x24, 0x17, 0xed, 0xad, 0x11, 0x1f, 0x46,
0x31, 0x0c, 0x6a, 0x3c, 0xd2, 0x1a, 0xe7, 0x41, 0xb3, 0x75, 0xd8, 0x80,
0xb3, 0xf8, 0x2b, 0xab, 0xb5, 0x81, 0xc6, 0x5e, 0x40, 0x9a, 0x77, 0xaa,
0x79, 0x31, 0x1f, 0x79, 0xfe, 0x0f, 0x0f, 0xb0, 0x36, 0xb7, 0xdc, 0xca,
0xf6, 0xbf, 0x80, 0xeb, 0x78, 0xc6, 0x73, 0x6a, 0xb3, 0x71, 0x69, 0x9c,
0x1d, 0xdd, 0x90, 0xd9, 0x73, 0x07, 0x43, 0x37, 0x19, 0x7f, 0x22, 0xa4,
0x9a, 0x4d, 0x98, 0x66, 0x10, 0x5b, 0x08, 0x62, 0xb3, 0xd8, 0x2f, 0x56,
0x68, 0x22, 0xdf, 0xd1, 0xa2, 0x5a, 0x45, 0xf9, 0xb4, 0xb9, 0xf2, 0x48,
0x4e, 0x38, 0x1a, 0x23, 0x36, 0x6d, 0x42, 0x56, 0xbb, 0x32, 0xe3, 0x00,
0x84, 0xa9, 0xe2, 0xba, 0xb6, 0x86, 0xc9, 0xa6, 0x64, 0x8a, 0xd6, 0xa6,
0xc4, 0xd7, 0x3e, 0x8b, 0x34, 0x1b, 0x6b, 0x65, 0xfe, 0xb1, 0xc9, 0x93,
0xe1, 0xeb, 0x8a, 0x3b, 0xf1, 0x0f, 0xdb, 0x84, 0xe2, 0x2d, 0xf8, 0x69,
0x04, 0xee, 0xaf, 0x58, 0x2f, 0xc7, 0x96, 0x70, 0x4d, 0xd9, 0x4c, 0x1d,
0x52, 0x38, 0xc6, 0x26, 0x27, 0x41, 0x38, 0x0b, 0xa5, 0x1c, 0x16, 0xd0,
0x1d, 0x32, 0x99, 0xb9, 0x1f, 0x35, 0xaf, 0x02, 0xb0, 0x13, 0x0f, 0x95,
0xd3, 0x9b, 0xd6, 0x09, 0xcc, 0x29, 0x46, 0xe8, 0xf1, 0x54, 0x4d, 0xb8,
0x96, 0xa6, 0x0d, 0x59, 0x61, 0x1f, 0xee, 0xaf, 0xbc, 0x23, 0x58, 0xff,
0xcf, 0x96, 0x91, 0x1f, 0x00, 0x80, 0x4e, 0x9a, 0xa2, 0xe0, 0x00, 0xf7,
0x3e, 0xb1, 0x91, 0x6c, 0x29, 0x58, 0x5e, 0xe7, 0xc7, 0x23, 0xfa, 0x88,
0xf7, 0xfb, 0x0b, 0x0e, 0x4a, 0x04, 0x46, 0xe0, 0x67, 0x10, 0x09, 0xea,
0xc0, 0xa9, 0xbe, 0x83, 0x11, 0x33, 0x8e, 0xfb, 0xd6, 0xd5, 0x67, 0xef,
0xb4, 0x13, 0x4d, 0x17, 0xa1, 0x44, 0xb7, 0x98, 0x77, 0xd0, 0x63, 0xe7,
0x9c, 0xa7, 0x96, 0x29, 0xe5, 0xfe, 0x72, 0x4c, 0xa9, 0x85, 0x9b, 0xc9,
0xf3, 0xf6, 0x05, 0x0a, 0x28, 0x68, 0x99, 0x31, 0xe8, 0x64, 0x30, 0x9c,
0x2a, 0x90, 0x48, 0x84, 0x00, 0x1a, 0x66, 0x0e, 0x3e, 0xf7, 0xaa, 0xc9,
0x6c, 0x5b, 0x57, 0x7b, 0xa9, 0x17, 0x91, 0x1e, 0x6b, 0xe8, 0x12, 0xa1,
0xd4, 0xde, 0x1e, 0x38, 0x14, 0x7b, 0xe0, 0x9a, 0x15, 0xae, 0x5a, 0x26,
0x93, 0x7a, 0xd6, 0x8d, 0x26, 0x61, 0x28, 0xf2, 0x40, 0x71, 0xc7, 0x8a,
0x2d, 0x69, 0x72, 0x04, 0x5b, 0xb9, 0xc1, 0x7b, 0x17, 0xde, 0x2c, 0xfc,
0xa9, 0xf2, 0xf8, 0x34, 0x33, 0x09, 0x87, 0x91, 0xdf, 0xeb, 0xf7, 0x57,
0x5b, 0x32, 0xe2, 0xd4, 0xe4, 0x47, 0x78, 0xe8, 0x9b, 0x1a, 0xab, 0x44,
0x55, 0x28, 0x98, 0x20, 0xa7, 0x16, 0x8b, 0x4e, 0x42, 0xf1, 0x91, 0xbe,
0x00, 0x87, 0x3a, 0x91, 0x63, 0x9a, 0xc2, 0x8d, 0x13, 0x34, 0x8b, 0x33,
0x02, 0x88, 0x1e, 0xb1, 0xa8, 0x07, 0x6d, 0xb1, 0xf5, 0xb3, 0x7a, 0x3d,
0x17, 0x3f, 0xbd, 0xa1, 0xdb, 0x04, 0x0f, 0x29, 0x7b, 0x0e, 0x98, 0x18,
0x63, 0x0b, 0x60, 0xcd, 0xa5, 0x0d, 0x5f, 0x1e, 0x53, 0xcd, 0xfa, 0xc0,
0xc7, 0x99, 0x53, 0x5f, 0xb7, 0xe5, 0x4a, 0x30, 0xde, 0x14, 0xc9, 0x49,
0x46, 0x31, 0xb6, 0x92, 0xf3, 0x4b, 0xc1, 0xb0, 0xdd, 0xec, 0x48, 0xff,
0x2d, 0x52, 0x53, 0x64, 0x27, 0x4c, 0x78, 0x96, 0x80, 0x90, 0xa3, 0xd7,
0xfd, 0x7a, 0x23, 0x36, 0xa0, 0x76, 0x9e, 0x96, 0xfc, 0xcd, 0xec, 0x58,
0xf8, 0x76, 0x4b, 0x2f, 0x8d, 0xb9, 0xd6, 0x89, 0xa1, 0x57, 0xe1, 0xc6,
0xed, 0x9a, 0x1e, 0xde, 0xc7, 0x68, 0x93, 0x2b, 0x2e, 0x84, 0x1a, 0xf9,
0x8c, 0x58, 0xb8, 0xf0, 0x29, 0xfe, 0x7b, 0x03, 0x84, 0xe8, 0x52, 0x1c,
0x01, 0xbb, 0xcc, 0x5d, 0x88, 0xcd, 0x37, 0x8b, 0xe2, 0x2d, 0x30, 0xd1,
0xbe, 0xf7, 0xc1, 0x95, 0xb7, 0x01, 0x43, 0xab, 0x30, 0x3f, 0x96, 0x47,
0x6d, 0x52, 0x29, 0x87, 0x10, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14,
0x14, 0x74, 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3,
0x7e, 0x33, 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x30, 0x31, 0x30, 0x21,
0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
0x14, 0x2f, 0x5c, 0xc6, 0xaf, 0xa7, 0xcc, 0xb5, 0x77, 0x40, 0xca, 0x71,
0xc3, 0x8c, 0xc6, 0x69, 0xdc, 0xc6, 0x7f, 0x54, 0xef, 0x04, 0x08, 0xf8,
0x9c, 0x8b, 0x12, 0x27, 0xe8, 0xec, 0x65, 0x02, 0x02, 0x08, 0x00};
static const char kPassword[] = "foo";
static bool Test(const char *name, const uint8_t *der, size_t der_len) {
@@ -759,6 +978,7 @@ int main(int argc, char **argv) {
if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
!Test("NSS", kNSS, sizeof(kNSS)) ||
!Test("Windows", kWindows, sizeof(kWindows)) ||
!Test("PBES2", kPBES2, sizeof(kPBES2)) ||
!TestCompat(kWindows, sizeof(kWindows))) {
return 1;
}
+127 -830
View File
File diff suppressed because it is too large Load Diff
+27
View File
@@ -143,6 +143,31 @@ static const uint8_t kEmptyPasswordOpenSSL[] = {
0xed,
};
// kExplicitHMACWithSHA1 is a PBES2-encrypted private key with an explicit
// hmacWithSHA1 AlgorithmIdentifier in the PBKDF2 parameters.
static const uint8_t kExplicitHMACWithSHA1[] = {
0x30, 0x81, 0xec, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x05, 0x0d, 0x30, 0x4a, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x1c, 0x04, 0x08, 0x90,
0xcd, 0x1e, 0x47, 0x1d, 0xff, 0x4c, 0xa8, 0x02, 0x02, 0x08, 0x00, 0x30,
0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07, 0x05,
0x00, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
0x01, 0x02, 0x04, 0x10, 0x34, 0xe7, 0x5b, 0x9b, 0xf9, 0x17, 0xcf, 0x15,
0x59, 0x7c, 0xfd, 0xc1, 0xac, 0xed, 0x6f, 0xdd, 0x04, 0x81, 0x90, 0xe3,
0xd7, 0xfc, 0xbe, 0xe6, 0xe8, 0x92, 0xc1, 0xa2, 0x57, 0x42, 0x4b, 0xf1,
0x35, 0x6c, 0x4f, 0x58, 0x61, 0x14, 0x30, 0x4e, 0xa3, 0x8d, 0x4f, 0xde,
0x2d, 0x0b, 0xa2, 0x62, 0x4b, 0xee, 0x9f, 0xc4, 0xeb, 0x89, 0x33, 0x76,
0x3f, 0x0c, 0x20, 0xad, 0x75, 0x29, 0x42, 0xbc, 0xbd, 0x83, 0x46, 0x1d,
0x5c, 0xae, 0xec, 0x10, 0x05, 0xbb, 0xd3, 0x98, 0xc9, 0x5a, 0x5e, 0x0a,
0x95, 0x12, 0x1e, 0x65, 0x93, 0xdd, 0xdd, 0x51, 0xd5, 0x56, 0xc2, 0xa9,
0xf9, 0x43, 0x0f, 0x68, 0x8a, 0x14, 0x40, 0xe5, 0x62, 0x9e, 0x0d, 0xd7,
0x67, 0x62, 0xf4, 0x49, 0xb1, 0x62, 0x22, 0x42, 0xb1, 0xe1, 0xb2, 0x1d,
0x37, 0x3e, 0x95, 0x52, 0xe9, 0x61, 0x89, 0xc7, 0x62, 0xcc, 0xb1, 0x44,
0x40, 0xef, 0x89, 0xc8, 0xc4, 0x0e, 0xae, 0xa8, 0xf9, 0x17, 0x42, 0x2b,
0x8c, 0x0b, 0x26, 0xf6, 0x07, 0x00, 0xab, 0x25, 0x2b, 0x64, 0xcf, 0xc3,
0x68, 0xf9, 0x5e, 0x01, 0x66, 0x59, 0x5f, 0x3f, 0x05, 0x57, 0xcd,
};
static bool TestDecrypt(const uint8_t *der, size_t der_len,
const char *password) {
const uint8_t *data = der;
@@ -222,6 +247,8 @@ int main(int argc, char **argv) {
!TestDecrypt(kNullPassword, sizeof(kNullPassword), NULL) ||
!TestDecrypt(kNullPasswordNSS, sizeof(kNullPasswordNSS), NULL) ||
!TestDecrypt(kEmptyPasswordOpenSSL, sizeof(kEmptyPasswordOpenSSL), "") ||
!TestDecrypt(kExplicitHMACWithSHA1, sizeof(kExplicitHMACWithSHA1),
"foo") ||
!TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr,
"password", nullptr, 0, 10) ||
// Vary the salt
+790
View File
@@ -0,0 +1,790 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/pkcs8.h>
#include <limits.h>
#include <openssl/asn1t.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/buf.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/digest.h>
#include <openssl/hmac.h>
#include <openssl/mem.h>
#include <openssl/x509.h>
#include "internal.h"
#include "../bytestring/internal.h"
#include "../digest/internal.h"
#include "../internal.h"
/* Minor tweak to operation: zero private key data */
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) {
/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
if (operation == ASN1_OP_FREE_PRE) {
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING &&
key->pkey->value.octet_string) {
OPENSSL_cleanse(key->pkey->value.octet_string->data,
key->pkey->value.octet_string->length);
}
}
return 1;
}
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
uint8_t *der = NULL;
int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der);
if (der_len < 0) {
return NULL;
}
CBS cbs;
CBS_init(&cbs, der, (size_t)der_len);
EVP_PKEY *ret = EVP_parse_private_key(&cbs);
if (ret == NULL || CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
EVP_PKEY_free(ret);
OPENSSL_free(der);
return NULL;
}
OPENSSL_free(der);
return ret;
}
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
CBB cbb;
uint8_t *der = NULL;
size_t der_len;
if (!CBB_init(&cbb, 0) ||
!EVP_marshal_private_key(&cbb, pkey) ||
!CBB_finish(&cbb, &der, &der_len) ||
der_len > LONG_MAX) {
CBB_cleanup(&cbb);
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR);
goto err;
}
const uint8_t *p = der;
PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len);
if (p8 == NULL || p != der + der_len) {
PKCS8_PRIV_KEY_INFO_free(p8);
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
goto err;
}
OPENSSL_free(der);
return p8;
err:
OPENSSL_free(der);
return NULL;
}
PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
int pass_len_in) {
size_t pass_len;
if (pass_len_in == -1 && pass != NULL) {
pass_len = strlen(pass);
} else {
pass_len = (size_t)pass_len_in;
}
PKCS8_PRIV_KEY_INFO *ret = NULL;
EVP_PKEY *pkey = NULL;
uint8_t *in = NULL;
/* Convert the legacy ASN.1 object to a byte string. */
int in_len = i2d_X509_SIG(pkcs8, &in);
if (in_len < 0) {
goto err;
}
CBS cbs;
CBS_init(&cbs, in, in_len);
pkey = PKCS8_parse_encrypted_private_key(&cbs, pass, pass_len);
if (pkey == NULL || CBS_len(&cbs) != 0) {
goto err;
}
ret = EVP_PKEY2PKCS8(pkey);
err:
OPENSSL_free(in);
EVP_PKEY_free(pkey);
return ret;
}
X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
int pass_len_in, const uint8_t *salt, size_t salt_len,
int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
size_t pass_len;
if (pass_len_in == -1 && pass != NULL) {
pass_len = strlen(pass);
} else {
pass_len = (size_t)pass_len_in;
}
/* Parse out the private key. */
EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
if (pkey == NULL) {
return NULL;
}
X509_SIG *ret = NULL;
uint8_t *der = NULL;
size_t der_len;
CBB cbb;
if (!CBB_init(&cbb, 128) ||
!PKCS8_marshal_encrypted_private_key(&cbb, pbe_nid, cipher, pass,
pass_len, salt, salt_len, iterations,
pkey) ||
!CBB_finish(&cbb, &der, &der_len)) {
CBB_cleanup(&cbb);
goto err;
}
/* Convert back to legacy ASN.1 objects. */
const uint8_t *ptr = der;
ret = d2i_X509_SIG(NULL, &ptr, der_len);
if (ret == NULL || ptr != der + der_len) {
OPENSSL_PUT_ERROR(PKCS8, ERR_R_INTERNAL_ERROR);
X509_SIG_free(ret);
ret = NULL;
}
err:
OPENSSL_free(der);
EVP_PKEY_free(pkey);
return ret;
}
struct pkcs12_context {
EVP_PKEY **out_key;
STACK_OF(X509) *out_certs;
const char *password;
size_t password_len;
};
/* PKCS12_handle_sequence parses a BER-encoded SEQUENCE of elements in a PKCS#12
* structure. */
static int PKCS12_handle_sequence(
CBS *sequence, struct pkcs12_context *ctx,
int (*handle_element)(CBS *cbs, struct pkcs12_context *ctx)) {
uint8_t *der_bytes = NULL;
size_t der_len;
CBS in;
int ret = 0;
/* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|,
* the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the
* conversion cannot see through those wrappings. So each time we step
* through one we need to convert to DER again. */
if (!CBS_asn1_ber_to_der(sequence, &der_bytes, &der_len)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
return 0;
}
if (der_bytes != NULL) {
CBS_init(&in, der_bytes, der_len);
} else {
CBS_init(&in, CBS_data(sequence), CBS_len(sequence));
}
CBS child;
if (!CBS_get_asn1(&in, &child, CBS_ASN1_SEQUENCE) ||
CBS_len(&in) != 0) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
while (CBS_len(&child) > 0) {
CBS element;
if (!CBS_get_asn1(&child, &element, CBS_ASN1_SEQUENCE)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (!handle_element(&element, ctx)) {
goto err;
}
}
ret = 1;
err:
OPENSSL_free(der_bytes);
return ret;
}
/* 1.2.840.113549.1.12.10.1.2 */
static const uint8_t kPKCS8ShroudedKeyBag[] = {
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02};
/* 1.2.840.113549.1.12.10.1.3 */
static const uint8_t kCertBag[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x0c, 0x0a, 0x01, 0x03};
/* 1.2.840.113549.1.9.22.1 */
static const uint8_t kX509Certificate[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x09, 0x16, 0x01};
/* PKCS12_handle_safe_bag parses a single SafeBag element in a PKCS#12
* structure. */
static int PKCS12_handle_safe_bag(CBS *safe_bag, struct pkcs12_context *ctx) {
CBS bag_id, wrapped_value;
if (!CBS_get_asn1(safe_bag, &bag_id, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(safe_bag, &wrapped_value,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)
/* Ignore the bagAttributes field. */) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
return 0;
}
if (CBS_mem_equal(&bag_id, kPKCS8ShroudedKeyBag,
sizeof(kPKCS8ShroudedKeyBag))) {
/* See RFC 7292, section 4.2.2. */
if (*ctx->out_key) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
return 0;
}
EVP_PKEY *pkey = PKCS8_parse_encrypted_private_key(
&wrapped_value, ctx->password, ctx->password_len);
if (pkey == NULL) {
return 0;
}
if (CBS_len(&wrapped_value) != 0) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
EVP_PKEY_free(pkey);
return 0;
}
*ctx->out_key = pkey;
return 1;
}
if (CBS_mem_equal(&bag_id, kCertBag, sizeof(kCertBag))) {
/* See RFC 7292, section 4.2.3. */
CBS cert_bag, cert_type, wrapped_cert, cert;
if (!CBS_get_asn1(&wrapped_value, &cert_bag, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(&cert_bag, &wrapped_cert,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
!CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
return 0;
}
/* Skip unknown certificate types. */
if (!CBS_mem_equal(&cert_type, kX509Certificate,
sizeof(kX509Certificate))) {
return 1;
}
if (CBS_len(&cert) > LONG_MAX) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
return 0;
}
const uint8_t *inp = CBS_data(&cert);
X509 *x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert));
if (!x509) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
return 0;
}
if (inp != CBS_data(&cert) + CBS_len(&cert)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
X509_free(x509);
return 0;
}
if (0 == sk_X509_push(ctx->out_certs, x509)) {
X509_free(x509);
return 0;
}
return 1;
}
/* Unknown element type - ignore it. */
return 1;
}
/* 1.2.840.113549.1.7.1 */
static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x07, 0x01};
/* 1.2.840.113549.1.7.6 */
static const uint8_t kPKCS7EncryptedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x07, 0x06};
/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
* PKCS#12 structure. */
static int PKCS12_handle_content_info(CBS *content_info,
struct pkcs12_context *ctx) {
CBS content_type, wrapped_contents, contents;
int ret = 0;
uint8_t *storage = NULL;
if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(content_info, &wrapped_contents,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
CBS_len(content_info) != 0) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (CBS_mem_equal(&content_type, kPKCS7EncryptedData,
sizeof(kPKCS7EncryptedData))) {
/* See https://tools.ietf.org/html/rfc2315#section-13.
*
* PKCS#7 encrypted data inside a PKCS#12 structure is generally an
* encrypted certificate bag and it's generally encrypted with 40-bit
* RC2-CBC. */
CBS version_bytes, eci, contents_type, ai, encrypted_contents;
uint8_t *out;
size_t out_len;
if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
/* EncryptedContentInfo, see
* https://tools.ietf.org/html/rfc2315#section-10.1 */
!CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
/* AlgorithmIdentifier, see
* https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
!CBS_get_asn1(&eci, &ai, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_implicit_string(
&eci, &encrypted_contents, &storage,
CBS_ASN1_CONTEXT_SPECIFIC | 0, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (!CBS_mem_equal(&contents_type, kPKCS7Data, sizeof(kPKCS7Data))) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (!pkcs8_pbe_decrypt(&out, &out_len, &ai, ctx->password,
ctx->password_len, CBS_data(&encrypted_contents),
CBS_len(&encrypted_contents))) {
goto err;
}
CBS safe_contents;
CBS_init(&safe_contents, out, out_len);
ret = PKCS12_handle_sequence(&safe_contents, ctx, PKCS12_handle_safe_bag);
OPENSSL_free(out);
} else if (CBS_mem_equal(&content_type, kPKCS7Data, sizeof(kPKCS7Data))) {
CBS octet_string_contents;
if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
ret = PKCS12_handle_sequence(&octet_string_contents, ctx,
PKCS12_handle_safe_bag);
} else {
/* Unknown element type - ignore it. */
ret = 1;
}
err:
OPENSSL_free(storage);
return ret;
}
int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
CBS *ber_in, const char *password) {
uint8_t *der_bytes = NULL;
size_t der_len;
CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes;
uint64_t version;
int ret = 0;
struct pkcs12_context ctx;
const size_t original_out_certs_len = sk_X509_num(out_certs);
/* The input may be in BER format. */
if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
return 0;
}
if (der_bytes != NULL) {
CBS_init(&in, der_bytes, der_len);
} else {
CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in));
}
*out_key = NULL;
OPENSSL_memset(&ctx, 0, sizeof(ctx));
/* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
* four. */
if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
CBS_len(&in) != 0 ||
!CBS_get_asn1_uint64(&pfx, &version)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (version < 3) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_VERSION);
goto err;
}
if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (CBS_len(&pfx) == 0) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MISSING_MAC);
goto err;
}
if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
/* authsafe is a PKCS#7 ContentInfo. See
* https://tools.ietf.org/html/rfc2315#section-7. */
if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(&authsafe, &wrapped_authsafes,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
/* The content type can either be data or signedData. The latter indicates
* that it's signed by a public key, which isn't supported. */
if (!CBS_mem_equal(&content_type, kPKCS7Data, sizeof(kPKCS7Data))) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED);
goto err;
}
if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
ctx.out_key = out_key;
ctx.out_certs = out_certs;
ctx.password = password;
ctx.password_len = password != NULL ? strlen(password) : 0;
/* Verify the MAC. */
{
CBS mac, salt, expected_mac;
if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
const EVP_MD *md = EVP_parse_digest_algorithm(&mac);
if (md == NULL) {
goto err;
}
if (!CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) ||
!CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
/* The iteration count is optional and the default is one. */
uint64_t iterations = 1;
if (CBS_len(&mac_data) > 0) {
if (!CBS_get_asn1_uint64(&mac_data, &iterations) ||
iterations > UINT_MAX) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
}
uint8_t hmac_key[EVP_MAX_MD_SIZE];
if (!pkcs12_key_gen(ctx.password, ctx.password_len, CBS_data(&salt),
CBS_len(&salt), PKCS12_MAC_ID, iterations,
EVP_MD_size(md), hmac_key, md)) {
goto err;
}
uint8_t hmac[EVP_MAX_MD_SIZE];
unsigned hmac_len;
if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes),
CBS_len(&authsafes), hmac, &hmac_len)) {
goto err;
}
if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INCORRECT_PASSWORD);
goto err;
}
}
/* authsafes contains a series of PKCS#7 ContentInfos. */
if (!PKCS12_handle_sequence(&authsafes, &ctx, PKCS12_handle_content_info)) {
goto err;
}
ret = 1;
err:
OPENSSL_free(der_bytes);
if (!ret) {
EVP_PKEY_free(*out_key);
*out_key = NULL;
while (sk_X509_num(out_certs) > original_out_certs_len) {
X509 *x509 = sk_X509_pop(out_certs);
X509_free(x509);
}
}
return ret;
}
void PKCS12_PBE_add(void) {}
struct pkcs12_st {
uint8_t *ber_bytes;
size_t ber_len;
};
PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes,
size_t ber_len) {
PKCS12 *p12;
p12 = OPENSSL_malloc(sizeof(PKCS12));
if (!p12) {
return NULL;
}
p12->ber_bytes = OPENSSL_malloc(ber_len);
if (!p12->ber_bytes) {
OPENSSL_free(p12);
return NULL;
}
OPENSSL_memcpy(p12->ber_bytes, *ber_bytes, ber_len);
p12->ber_len = ber_len;
*ber_bytes += ber_len;
if (out_p12) {
PKCS12_free(*out_p12);
*out_p12 = p12;
}
return p12;
}
PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
size_t used = 0;
BUF_MEM *buf;
const uint8_t *dummy;
static const size_t kMaxSize = 256 * 1024;
PKCS12 *ret = NULL;
buf = BUF_MEM_new();
if (buf == NULL) {
return NULL;
}
if (BUF_MEM_grow(buf, 8192) == 0) {
goto out;
}
for (;;) {
int n = BIO_read(bio, &buf->data[used], buf->length - used);
if (n < 0) {
if (used == 0) {
goto out;
}
/* Workaround a bug in node.js. It uses a memory BIO for this in the wrong
* mode. */
n = 0;
}
if (n == 0) {
break;
}
used += n;
if (used < buf->length) {
continue;
}
if (buf->length > kMaxSize ||
BUF_MEM_grow(buf, buf->length * 2) == 0) {
goto out;
}
}
dummy = (uint8_t*) buf->data;
ret = d2i_PKCS12(out_p12, &dummy, used);
out:
BUF_MEM_free(buf);
return ret;
}
PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) {
BIO *bio;
PKCS12 *ret;
bio = BIO_new_fp(fp, 0 /* don't take ownership */);
if (!bio) {
return NULL;
}
ret = d2i_PKCS12_bio(bio, out_p12);
BIO_free(bio);
return ret;
}
int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
CBS ber_bytes;
STACK_OF(X509) *ca_certs = NULL;
char ca_certs_alloced = 0;
if (out_ca_certs != NULL && *out_ca_certs != NULL) {
ca_certs = *out_ca_certs;
}
if (!ca_certs) {
ca_certs = sk_X509_new_null();
if (ca_certs == NULL) {
OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
return 0;
}
ca_certs_alloced = 1;
}
CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len);
if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) {
if (ca_certs_alloced) {
sk_X509_free(ca_certs);
}
return 0;
}
*out_cert = NULL;
if (sk_X509_num(ca_certs) > 0) {
*out_cert = sk_X509_shift(ca_certs);
}
if (out_ca_certs) {
*out_ca_certs = ca_certs;
} else {
sk_X509_pop_free(ca_certs, X509_free);
}
return 1;
}
int PKCS12_verify_mac(const PKCS12 *p12, const char *password,
int password_len) {
if (password == NULL) {
if (password_len != 0) {
return 0;
}
} else if (password_len != -1 &&
(password[password_len] != 0 ||
OPENSSL_memchr(password, 0, password_len) != NULL)) {
return 0;
}
EVP_PKEY *pkey = NULL;
X509 *cert = NULL;
if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) {
ERR_clear_error();
return 0;
}
EVP_PKEY_free(pkey);
X509_free(cert);
return 1;
}
void PKCS12_free(PKCS12 *p12) {
if (p12 == NULL) {
return;
}
OPENSSL_free(p12->ber_bytes);
OPENSSL_free(p12);
}
+4 -4
View File
@@ -24,11 +24,11 @@
#include "../internal.h"
/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occured.
/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occurred.
*
* TODO(davidben): This is intentionally not thread-safe. If the fuzzer mode is
* ever used in a multi-threaded program, replace this with a thread-local. (A
* mutex would not be deterministic.) */
* This is intentionally not thread-safe. If the fuzzer mode is ever used in a
* multi-threaded program, replace this with a thread-local. (A mutex would not
* be deterministic.) */
static uint64_t g_num_calls = 0;
void RAND_reset_for_fuzzing(void) { g_num_calls = 0; }
+17 -18
View File
@@ -95,24 +95,23 @@ int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx,
BN_CTX *ctx);
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len);
int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len);
int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len);
int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len);
int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len,
const uint8_t *param, unsigned plen,
const EVP_MD *md, const EVP_MD *mgf1md);
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len,
const uint8_t *param, unsigned plen,
const EVP_MD *md, const EVP_MD *mgf1md);
int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
unsigned from_len);
int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
const uint8_t *from, size_t from_len);
int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *from,
size_t from_len);
int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
const uint8_t *from, size_t from_len);
int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *from,
size_t from_len);
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *from,
size_t from_len, const uint8_t *param,
size_t param_len, const EVP_MD *md,
const EVP_MD *mgf1md);
int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
size_t from_len);
/* RSA_private_transform calls either the method-specific |private_transform|
* function (if given) or the generic one. See the comment for
+158 -176
View File
@@ -71,10 +71,9 @@
/* TODO(fork): don't the check functions have to be constant time? */
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
unsigned j;
int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
const uint8_t *from, size_t from_len) {
/* See RFC 8017, section 9.2. */
if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
@@ -85,118 +84,114 @@ int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
return 0;
}
uint8_t *p = to;
*(p++) = 0;
*(p++) = 1; /* Private Key BT (Block Type) */
/* pad out with 0xff data */
j = to_len - 3 - from_len;
OPENSSL_memset(p, 0xff, j);
p += j;
*(p++) = 0;
OPENSSL_memcpy(p, from, from_len);
to[0] = 0;
to[1] = 1;
OPENSSL_memset(to + 2, 0xff, to_len - 3 - from_len);
to[to_len - from_len - 1] = 0;
OPENSSL_memcpy(to + to_len - from_len, from, from_len);
return 1;
}
int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
unsigned i, j;
const uint8_t *p;
int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *from,
size_t from_len) {
/* See RFC 8017, section 9.2. This is part of signature verification and thus
* does not need to run in constant-time. */
if (from_len < 2) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL);
return -1;
return 0;
}
p = from;
if ((*(p++) != 0) || (*(p++) != 1)) {
/* Check the header. */
if (from[0] != 0 || from[1] != 1) {
OPENSSL_PUT_ERROR(RSA, RSA_R_BLOCK_TYPE_IS_NOT_01);
return -1;
return 0;
}
/* scan over padding data */
j = from_len - 2; /* one for leading 00, one for type. */
for (i = 0; i < j; i++) {
/* should decrypt to 0xff */
if (*p != 0xff) {
if (*p == 0) {
p++;
break;
} else {
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT);
return -1;
}
/* Scan over padded data, looking for the 00. */
size_t pad;
for (pad = 2 /* header */; pad < from_len; pad++) {
if (from[pad] == 0x00) {
break;
}
if (from[pad] != 0xff) {
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT);
return 0;
}
p++;
}
if (i == j) {
if (pad == from_len) {
OPENSSL_PUT_ERROR(RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING);
return -1;
return 0;
}
if (i < 8) {
if (pad < 2 /* header */ + 8) {
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_PAD_BYTE_COUNT);
return -1;
return 0;
}
i++; /* Skip over the '\0' */
j -= i;
if (j > to_len) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
return -1;
}
OPENSSL_memcpy(to, p, j);
return j;
/* Skip over the 00. */
pad++;
if (from_len - pad > max_out) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
return 0;
}
OPENSSL_memcpy(out, from + pad, from_len - pad);
*out_len = from_len - pad;
return 1;
}
int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
unsigned i, j;
if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
static int rand_nonzero(uint8_t *out, size_t len) {
if (!RAND_bytes(out, len)) {
return 0;
}
if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
uint8_t *p = to;
*(p++) = 0;
*(p++) = 2; /* Public Key BT (Block Type) */
/* pad out with non-zero random data */
j = to_len - 3 - from_len;
if (!RAND_bytes(p, j)) {
return 0;
}
for (i = 0; i < j; i++) {
while (*p == 0) {
if (!RAND_bytes(p, 1)) {
for (size_t i = 0; i < len; i++) {
while (out[i] == 0) {
if (!RAND_bytes(out + i, 1)) {
return 0;
}
}
p++;
}
*(p++) = 0;
OPENSSL_memcpy(p, from, from_len);
return 1;
}
int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
const uint8_t *from, size_t from_len) {
/* See RFC 8017, section 7.2.1. */
if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
to[0] = 0;
to[1] = 2;
size_t padding_len = to_len - 3 - from_len;
if (!rand_nonzero(to + 2, padding_len)) {
return 0;
}
to[2 + padding_len] = 0;
OPENSSL_memcpy(to + to_len - from_len, from, from_len);
return 1;
}
int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *from,
size_t from_len) {
if (from_len == 0) {
OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
return -1;
return 0;
}
/* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
@@ -205,29 +200,29 @@ int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
/* |from| is zero-padded to the size of the RSA modulus, a public value, so
* this can be rejected in non-constant time. */
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return -1;
return 0;
}
unsigned first_byte_is_zero = constant_time_eq(from[0], 0);
unsigned second_byte_is_two = constant_time_eq(from[1], 2);
size_t first_byte_is_zero = constant_time_eq_s(from[0], 0);
size_t second_byte_is_two = constant_time_eq_s(from[1], 2);
unsigned i, zero_index = 0, looking_for_index = ~0u;
for (i = 2; i < from_len; i++) {
unsigned equals0 = constant_time_is_zero(from[i]);
zero_index = constant_time_select(looking_for_index & equals0, (unsigned)i,
zero_index);
looking_for_index = constant_time_select(equals0, 0, looking_for_index);
size_t zero_index = 0, looking_for_index = CONSTTIME_TRUE_S;
for (size_t i = 2; i < from_len; i++) {
size_t equals0 = constant_time_is_zero_s(from[i]);
zero_index =
constant_time_select_s(looking_for_index & equals0, i, zero_index);
looking_for_index = constant_time_select_s(equals0, 0, looking_for_index);
}
/* The input must begin with 00 02. */
unsigned valid_index = first_byte_is_zero;
size_t valid_index = first_byte_is_zero;
valid_index &= second_byte_is_two;
/* We must have found the end of PS. */
valid_index &= ~looking_for_index;
/* PS must be at least 8 bytes long, and it starts two bytes into |from|. */
valid_index &= constant_time_ge(zero_index, 2 + 8);
valid_index &= constant_time_ge_s(zero_index, 2 + 8);
/* Skip the zero byte. */
zero_index++;
@@ -235,31 +230,28 @@ int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
/* NOTE: Although this logic attempts to be constant time, the API contracts
* of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it
* impossible to completely avoid Bleichenbacher's attack. Consumers should
* use |RSA_unpad_key_pkcs1|. */
* use |RSA_PADDING_NONE| and perform the padding check in constant-time
* combined with a swap to a random session key or other mitigation. */
if (!valid_index) {
OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
return -1;
return 0;
}
const unsigned msg_len = from_len - zero_index;
if (msg_len > to_len) {
const size_t msg_len = from_len - zero_index;
if (msg_len > max_out) {
/* This shouldn't happen because this function is always called with
* |to_len| as the key size and |from_len| is bounded by the key size. */
* |max_out| as the key size and |from_len| is bounded by the key size. */
OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
return -1;
return 0;
}
if (msg_len > INT_MAX) {
OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
return -1;
}
OPENSSL_memcpy(to, &from[zero_index], msg_len);
return (int)msg_len;
OPENSSL_memcpy(out, &from[zero_index], msg_len);
*out_len = msg_len;
return 1;
}
int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
unsigned from_len) {
int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
size_t from_len) {
if (from_len > to_len) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
@@ -317,15 +309,10 @@ err:
return ret;
}
int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len,
const uint8_t *param, unsigned param_len,
int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, size_t to_len,
const uint8_t *from, size_t from_len,
const uint8_t *param, size_t param_len,
const EVP_MD *md, const EVP_MD *mgf1md) {
unsigned i, emlen, mdlen;
uint8_t *db, *seed;
uint8_t *dbmask = NULL, seedmask[EVP_MAX_MD_SIZE];
int ret = 0;
if (md == NULL) {
md = EVP_sha1();
}
@@ -333,14 +320,14 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
mgf1md = md;
}
mdlen = EVP_MD_size(md);
size_t mdlen = EVP_MD_size(md);
if (to_len < 2 * mdlen + 2) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
emlen = to_len - 1;
size_t emlen = to_len - 1;
if (from_len > emlen - 2 * mdlen - 1) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
@@ -352,8 +339,8 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
}
to[0] = 0;
seed = to + 1;
db = to + mdlen + 1;
uint8_t *seed = to + 1;
uint8_t *db = to + mdlen + 1;
if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) {
return 0;
@@ -365,23 +352,25 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
return 0;
}
dbmask = OPENSSL_malloc(emlen - mdlen);
uint8_t *dbmask = OPENSSL_malloc(emlen - mdlen);
if (dbmask == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
return 0;
}
int ret = 0;
if (!PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md)) {
goto out;
}
for (i = 0; i < emlen - mdlen; i++) {
for (size_t i = 0; i < emlen - mdlen; i++) {
db[i] ^= dbmask[i];
}
uint8_t seedmask[EVP_MAX_MD_SIZE];
if (!PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md)) {
goto out;
}
for (i = 0; i < mdlen; i++) {
for (size_t i = 0; i < mdlen; i++) {
seed[i] ^= seedmask[i];
}
ret = 1;
@@ -391,13 +380,12 @@ out:
return ret;
}
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len,
const uint8_t *param, unsigned param_len,
const EVP_MD *md, const EVP_MD *mgf1md) {
unsigned i, dblen, mlen = -1, mdlen, bad, looking_for_one_byte, one_index = 0;
const uint8_t *maskeddb, *maskedseed;
uint8_t *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *from,
size_t from_len, const uint8_t *param,
size_t param_len, const EVP_MD *md,
const EVP_MD *mgf1md) {
uint8_t *db = NULL;
if (md == NULL) {
md = EVP_sha1();
@@ -406,7 +394,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
mgf1md = md;
}
mdlen = EVP_MD_size(md);
size_t mdlen = EVP_MD_size(md);
/* The encoded message is one byte smaller than the modulus to ensure that it
* doesn't end up greater than the modulus. Thus there's an extra "+1" here
@@ -417,45 +405,47 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
goto decoding_err;
}
dblen = from_len - mdlen - 1;
size_t dblen = from_len - mdlen - 1;
db = OPENSSL_malloc(dblen);
if (db == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
maskedseed = from + 1;
maskeddb = from + 1 + mdlen;
const uint8_t *maskedseed = from + 1;
const uint8_t *maskeddb = from + 1 + mdlen;
uint8_t seed[EVP_MAX_MD_SIZE];
if (!PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
goto err;
}
for (i = 0; i < mdlen; i++) {
for (size_t i = 0; i < mdlen; i++) {
seed[i] ^= maskedseed[i];
}
if (!PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
goto err;
}
for (i = 0; i < dblen; i++) {
for (size_t i = 0; i < dblen; i++) {
db[i] ^= maskeddb[i];
}
uint8_t phash[EVP_MAX_MD_SIZE];
if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
goto err;
}
bad = ~constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));
bad |= ~constant_time_is_zero(from[0]);
size_t bad = ~constant_time_is_zero_s(CRYPTO_memcmp(db, phash, mdlen));
bad |= ~constant_time_is_zero_s(from[0]);
looking_for_one_byte = ~0u;
for (i = mdlen; i < dblen; i++) {
unsigned equals1 = constant_time_eq(db[i], 1);
unsigned equals0 = constant_time_eq(db[i], 0);
one_index = constant_time_select(looking_for_one_byte & equals1, i,
one_index);
size_t looking_for_one_byte = CONSTTIME_TRUE_S, one_index = 0;
for (size_t i = mdlen; i < dblen; i++) {
size_t equals1 = constant_time_eq_s(db[i], 1);
size_t equals0 = constant_time_eq_s(db[i], 0);
one_index =
constant_time_select_s(looking_for_one_byte & equals1, i, one_index);
looking_for_one_byte =
constant_time_select(equals1, 0, looking_for_one_byte);
constant_time_select_s(equals1, 0, looking_for_one_byte);
bad |= looking_for_one_byte & ~equals0;
}
@@ -466,16 +456,16 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
}
one_index++;
mlen = dblen - one_index;
if (to_len < mlen) {
size_t mlen = dblen - one_index;
if (max_out < mlen) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
mlen = -1;
} else {
OPENSSL_memcpy(to, db + one_index, mlen);
goto err;
}
OPENSSL_memcpy(out, db + one_index, mlen);
*out_len = mlen;
OPENSSL_free(db);
return mlen;
return 1;
decoding_err:
/* to avoid chosen ciphertext attacks, the error message should not reveal
@@ -483,10 +473,10 @@ decoding_err:
OPENSSL_PUT_ERROR(RSA, RSA_R_OAEP_DECODING_ERROR);
err:
OPENSSL_free(db);
return -1;
return 0;
}
static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0};
static const uint8_t kPSSZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};
int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
@@ -530,7 +520,7 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
EM++;
emLen--;
}
if (emLen < ((int)hLen + sLen + 2)) {
if (emLen < (int)hLen + 2 || emLen < ((int)hLen + sLen + 2)) {
/* sLen can be small negative */
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
goto err;
@@ -567,16 +557,10 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
goto err;
}
if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
!EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
!EVP_DigestUpdate(&ctx, mHash, hLen)) {
goto err;
}
if (maskedDBLen - i) {
if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i)) {
goto err;
}
}
if (!EVP_DigestFinal_ex(&ctx, H_, NULL)) {
!EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) ||
!EVP_DigestUpdate(&ctx, mHash, hLen) ||
!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i) ||
!EVP_DigestFinal_ex(&ctx, H_, NULL)) {
goto err;
}
if (OPENSSL_memcmp(H_, H, hLen)) {
@@ -601,7 +585,6 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
size_t maskedDBLen, MSBits, emLen;
size_t hLen;
unsigned char *H, *salt = NULL, *p;
EVP_MD_CTX ctx;
if (mgf1Hash == NULL) {
mgf1Hash = Hash;
@@ -660,19 +643,18 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
}
maskedDBLen = emLen - hLen - 1;
H = EM + maskedDBLen;
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
!EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
!EVP_DigestUpdate(&ctx, mHash, hLen)) {
goto err;
}
if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen)) {
goto err;
}
if (!EVP_DigestFinal_ex(&ctx, H, NULL)) {
goto err;
}
int digest_ok = EVP_DigestInit_ex(&ctx, Hash, NULL) &&
EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) &&
EVP_DigestUpdate(&ctx, mHash, hLen) &&
EVP_DigestUpdate(&ctx, salt, sLen) &&
EVP_DigestFinal_ex(&ctx, H, NULL);
EVP_MD_CTX_cleanup(&ctx);
if (!digest_ok) {
goto err;
}
/* Generate dbMask in place then perform XOR on it */
if (!PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) {
-7
View File
@@ -321,13 +321,6 @@ int RSA_is_opaque(const RSA *rsa) {
return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE);
}
int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
if (rsa->meth && rsa->meth->supports_digest) {
return rsa->meth->supports_digest(rsa, md);
}
return 1;
}
int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
int index;
+13 -16
View File
@@ -363,7 +363,6 @@ err:
int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding) {
const unsigned rsa_size = RSA_size(rsa);
int r = -1;
uint8_t *buf = NULL;
int ret = 0;
@@ -394,26 +393,25 @@ int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
switch (padding) {
case RSA_PKCS1_PADDING:
r = RSA_padding_check_PKCS1_type_2(out, rsa_size, buf, rsa_size);
ret =
RSA_padding_check_PKCS1_type_2(out, out_len, rsa_size, buf, rsa_size);
break;
case RSA_PKCS1_OAEP_PADDING:
/* Use the default parameters: SHA-1 for both hashes and no label. */
r = RSA_padding_check_PKCS1_OAEP_mgf1(out, rsa_size, buf, rsa_size,
NULL, 0, NULL, NULL);
ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, out_len, rsa_size, buf,
rsa_size, NULL, 0, NULL, NULL);
break;
case RSA_NO_PADDING:
r = rsa_size;
*out_len = rsa_size;
ret = 1;
break;
default:
OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (r < 0) {
if (!ret) {
OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
} else {
*out_len = r;
ret = 1;
}
err:
@@ -436,7 +434,6 @@ int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const unsigned rsa_size = RSA_size(rsa);
BIGNUM *f, *result;
int r = -1;
if (max_out < rsa_size) {
OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
@@ -500,21 +497,21 @@ int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
switch (padding) {
case RSA_PKCS1_PADDING:
r = RSA_padding_check_PKCS1_type_1(out, rsa_size, buf, rsa_size);
ret =
RSA_padding_check_PKCS1_type_1(out, out_len, rsa_size, buf, rsa_size);
break;
case RSA_NO_PADDING:
r = rsa_size;
ret = 1;
*out_len = rsa_size;
break;
default:
OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (r < 0) {
if (!ret) {
OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
} else {
*out_len = r;
ret = 1;
goto err;
}
err:
+3 -1
View File
@@ -105,7 +105,9 @@ static const vec_uint32_t K_60_79_x_4 = {K_60_79, K_60_79, K_60_79, K_60_79};
* Byte shifting code below may not be correct for big-endian systems. */
static vec_uint32_t sched_00_15(vec_uint32_t *pre_added, const void *data,
vec_uint32_t k) {
const vec_uint32_t v = *((const vec_uint32_t *)data);
const vector unsigned char unaligned_data =
vec_vsx_ld(0, (const unsigned char*) data);
const vec_uint32_t v = (vec_uint32_t) unaligned_data;
const vec_uint32_t w = vec_perm(v, v, k_swap_endianness);
vec_st(w + k, 0, pre_added);
return w;
-6
View File
@@ -82,12 +82,6 @@ int SHA1_Init(SHA_CTX *sha) {
uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out) {
SHA_CTX ctx;
static uint8_t buf[SHA_DIGEST_LENGTH];
/* TODO(fork): remove this static buffer. */
if (out == NULL) {
out = buf;
}
if (!SHA1_Init(&ctx)) {
return NULL;
}
-12
View File
@@ -99,12 +99,6 @@ int SHA256_Init(SHA256_CTX *sha) {
uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
SHA256_CTX ctx;
static uint8_t buf[SHA224_DIGEST_LENGTH];
/* TODO(fork): remove this static buffer. */
if (out == NULL) {
out = buf;
}
SHA224_Init(&ctx);
SHA224_Update(&ctx, data, len);
SHA224_Final(out, &ctx);
@@ -114,12 +108,6 @@ uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out) {
SHA256_CTX ctx;
static uint8_t buf[SHA256_DIGEST_LENGTH];
/* TODO(fork): remove this static buffer. */
if (out == NULL) {
out = buf;
}
SHA256_Init(&ctx);
SHA256_Update(&ctx, data, len);
SHA256_Final(out, &ctx);
-13
View File
@@ -123,13 +123,6 @@ int SHA512_Init(SHA512_CTX *sha) {
uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
SHA512_CTX ctx;
static uint8_t buf[SHA384_DIGEST_LENGTH];
/* TODO(fork): remove this static buffer. */
if (out == NULL) {
out = buf;
}
SHA384_Init(&ctx);
SHA384_Update(&ctx, data, len);
SHA384_Final(out, &ctx);
@@ -139,12 +132,6 @@ uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out) {
SHA512_CTX ctx;
static uint8_t buf[SHA512_DIGEST_LENGTH];
/* TODO(fork): remove this static buffer. */
if (out == NULL) {
out = buf;
}
SHA512_Init(&ctx);
SHA512_Update(&ctx, data, len);
SHA512_Final(out, &ctx);
+23
View File
@@ -19,6 +19,13 @@
#include <openssl/err.h>
#include <openssl/crypto.h>
#if defined(OPENSSL_WINDOWS)
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
namespace {
class ErrorTestEventListener : public testing::EmptyTestEventListener {
@@ -41,6 +48,22 @@ class ErrorTestEventListener : public testing::EmptyTestEventListener {
int main(int argc, char **argv) {
CRYPTO_library_init();
#if defined(OPENSSL_WINDOWS)
// Initialize Winsock.
WORD wsa_version = MAKEWORD(2, 2);
WSADATA wsa_data;
int wsa_err = WSAStartup(wsa_version, &wsa_data);
if (wsa_err != 0) {
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
return 1;
}
if (wsa_data.wVersion != wsa_version) {
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
return 1;
}
#endif
testing::InitGoogleTest(&argc, argv);
testing::UnitTest::GetInstance()->listeners().Append(
new ErrorTestEventListener);
+2
View File
@@ -34,6 +34,8 @@ void hexdump(FILE *fp, const char *msg, const void *in, size_t len);
struct Bytes {
Bytes(const uint8_t *data_arg, size_t len_arg)
: data(data_arg), len(len_arg) {}
Bytes(const char *data_arg, size_t len_arg)
: data(reinterpret_cast<const uint8_t *>(data_arg)), len(len_arg) {}
Bytes(const char *str)
: data(reinterpret_cast<const uint8_t *>(str)), len(strlen(str)) {}
+19 -15
View File
@@ -27,6 +27,14 @@
#include "../bytestring/internal.h"
/* 1.2.840.113549.1.7.1 */
static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x07, 0x01};
/* 1.2.840.113549.1.7.2 */
static const uint8_t kPKCS7SignedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x07, 0x02};
/* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7
* SignedData blob from |cbs| and sets |*out| to point to the rest of the
* input. If the input is in BER format, then |*der_bytes| will be set to a
@@ -57,7 +65,8 @@ static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) {
goto err;
}
if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
if (!CBS_mem_equal(&content_type, kPKCS7SignedData,
sizeof(kPKCS7SignedData))) {
OPENSSL_PUT_ERROR(X509, X509_R_NOT_PKCS7_SIGNED_DATA);
goto err;
}
@@ -81,11 +90,8 @@ static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) {
return 1;
err:
if (*der_bytes) {
OPENSSL_free(*der_bytes);
*der_bytes = NULL;
}
OPENSSL_free(*der_bytes);
*der_bytes = NULL;
return 0;
}
@@ -135,9 +141,7 @@ int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
ret = 1;
err:
if (der_bytes) {
OPENSSL_free(der_bytes);
}
OPENSSL_free(der_bytes);
if (!ret) {
while (sk_X509_num(out_certs) != initial_certs_len) {
@@ -205,9 +209,7 @@ int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) {
ret = 1;
err:
if (der_bytes) {
OPENSSL_free(der_bytes);
}
OPENSSL_free(der_bytes);
if (!ret) {
while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
@@ -270,12 +272,13 @@ int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) {
* pkcs7_bundle returns one on success or zero on error. */
static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg),
const void *arg) {
CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set,
CBB outer_seq, oid, wrapped_seq, seq, version_bytes, digest_algos_set,
content_info;
/* See https://tools.ietf.org/html/rfc2315#section-7 */
if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
!OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
!CBB_add_asn1(&outer_seq, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, kPKCS7SignedData, sizeof(kPKCS7SignedData)) ||
!CBB_add_asn1(&outer_seq, &wrapped_seq,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
/* See https://tools.ietf.org/html/rfc2315#section-9.1 */
@@ -284,7 +287,8 @@ static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg),
!CBB_add_u8(&version_bytes, 1) ||
!CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
!CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
!OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
!CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
!cb(&seq, arg)) {
return 0;
}
+12 -4
View File
@@ -356,8 +356,12 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
OPENSSL_free(obj);
OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
ret = 0;
} else
sk_X509_OBJECT_push(ctx->objs, obj);
} else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
X509_OBJECT_free_contents(obj);
OPENSSL_free(obj);
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
ret = 0;
}
CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
@@ -388,8 +392,12 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
OPENSSL_free(obj);
OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
ret = 0;
} else
sk_X509_OBJECT_push(ctx->objs, obj);
} else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
X509_OBJECT_free_contents(obj);
OPENSSL_free(obj);
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
ret = 0;
}
CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
+9 -3
View File
@@ -468,9 +468,15 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent)
num = sk_ASN1_INTEGER_value(ref->noticenos, i);
if (i)
BIO_puts(out, ", ");
tmp = i2s_ASN1_INTEGER(NULL, num);
BIO_puts(out, tmp);
OPENSSL_free(tmp);
if (num == NULL)
BIO_puts(out, "(null)");
else {
tmp = i2s_ASN1_INTEGER(NULL, num);
if (tmp == NULL)
return;
BIO_puts(out, tmp);
OPENSSL_free(tmp);
}
}
BIO_puts(out, "\n");
}
-33
View File
@@ -35,7 +35,6 @@
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <openssl/conf.h>
@@ -153,38 +152,6 @@ static int process_pci_value(CONF_VALUE *val,
goto err;
}
OPENSSL_free(tmp_data2);
} else if (strncmp(val->value, "file:", 5) == 0) {
unsigned char buf[2048];
int n;
BIO *b = BIO_new_file(val->value + 5, "r");
if (!b) {
OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
X509V3_conf_err(val);
goto err;
}
while ((n = BIO_read(b, buf, sizeof(buf))) > 0
|| (n == 0 && BIO_should_retry(b))) {
if (!n)
continue;
tmp_data = OPENSSL_realloc((*policy)->data,
(*policy)->length + n + 1);
if (!tmp_data)
break;
(*policy)->data = tmp_data;
OPENSSL_memcpy(&(*policy)->data[(*policy)->length], buf, n);
(*policy)->length += n;
(*policy)->data[(*policy)->length] = '\0';
}
BIO_free_all(b);
if (n < 0) {
OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
X509V3_conf_err(val);
goto err;
}
} else if (strncmp(val->value, "text:", 5) == 0) {
val_len = strlen(val->value + 5);
tmp_data = OPENSSL_realloc((*policy)->data,
+3
View File
@@ -46,4 +46,7 @@ add_executable(
)
target_link_libraries(decrepit_test crypto decrepit gtest)
if (WIN32)
target_link_libraries(decrepit_test ws2_32)
endif()
add_dependencies(all_tests decrepit_test)
+3 -3
View File
@@ -95,9 +95,9 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, const EVP_MD *Hash,
return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
}
int RSA_padding_add_PKCS1_OAEP(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len,
const uint8_t *param, unsigned param_len) {
int RSA_padding_add_PKCS1_OAEP(uint8_t *to, size_t to_len,
const uint8_t *from, size_t from_len,
const uint8_t *param, size_t param_len) {
return RSA_padding_add_PKCS1_OAEP_mgf1(to, to_len, from, from_len, param,
param_len, NULL, NULL);
}
-2
View File
@@ -247,8 +247,6 @@ struct GlobalState {
assert(pkey != nullptr);
SSL_CTX_set1_tls_channel_id(ctx, pkey);
EVP_PKEY_free(pkey);
SSL_CTX_set_short_header_enabled(ctx, 1);
}
~GlobalState() {

Some files were not shown because too many files have changed in this diff Show More