Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Baulig <martin.baulig@xamarin.com>2016-10-20 04:03:55 +0300
committerMartin Baulig <martin.baulig@xamarin.com>2016-10-20 19:43:51 +0300
commiteec2ca7e76c04ca41ef5bfc875ee3b0374cb7a94 (patch)
tree1ae353ad512bac182c8fa1e572beccf8a7fd1f55
parent2bc26c2772ad0a5d6b0ad4ba2ec77c8183d8932d (diff)
Update to chromium-stable commit 3cab5572b1fcf5a8f6018529dc30dc8d21b2a4bd.
Squashed commit of the following: commit 3cab5572b1fcf5a8f6018529dc30dc8d21b2a4bd Author: Adam Langley <agl@google.com> Date: Thu Jun 16 10:43:39 2016 -0700 Don't align NEWPOLY_POLY. The alignas in NEWPOLY_POLY told the compiler that it could assume a certain alignment. However, values were allocated with malloc with no specific alignment. We could try and allocate aligned memory but the alignment doesn't have a performance impact (on x86-64) so this is the simpler change. (Also, Windows doesn't have |posix_memalign|. The cloest thing is _alligned_alloc but then one has to use a special free function.) Change-Id: I53955a88862160c02aa5436d991b1b797c3c17db Reviewed-on: https://boringssl-review.googlesource.com/8315 Reviewed-by: David Benjamin <davidben@google.com> commit 13603a8399cd50bdc476cf46ac8c81244aadbad9 Author: Brian Smith <brian@briansmith.org> Date: Wed Jun 15 14:03:32 2016 -1000 Move "no inverse" test earlier in |BN_mod_inverse_no_branch|. There's no use doing the remaining work if we're going to fail due to there being no inverse. Change-Id: Ic6d7c92cbbc2f7c40c51e6be2de3802980d32543 Reviewed-on: https://boringssl-review.googlesource.com/8310 Reviewed-by: David Benjamin <davidben@google.com> commit 7975056ac1ca5917dff1943415864f12dc913657 Author: Steven Valdez <svaldez@google.com> Date: Thu Jun 16 06:38:04 2016 -0400 Fixing iv_length for TLS 1.3. In TLS 1.3, the iv_length is equal to the explicit AEAD nonce length, and is required to be at least 8 bytes. Change-Id: Ib258f227d0a02c5abfc7b65adb4e4a689feffe33 Reviewed-on: https://boringssl-review.googlesource.com/8304 Reviewed-by: David Benjamin <davidben@google.com> commit 3675dddab9993e9c521c76c6b10176b8da7c0141 Author: Matt Braithwaite <mab@google.com> Date: Wed May 25 10:43:39 2016 -0700 newhope_test: corrupt things harder. This ensures that the test is not flaky after lots of iterations. Along the way, change newhope_test.cc to C++. Change-Id: I4ef139444b8c8a98db53d075105eb6806f6c5fc7 Reviewed-on: https://boringssl-review.googlesource.com/8110 Reviewed-by: Adam Langley <agl@google.com> commit da7f0c65efb72556f8fc92e460e6c90cd1b1add7 Author: David Benjamin <davidben@google.com> Date: Wed Jun 15 18:41:51 2016 -0400 Unwind X509_LU_RETRY and fix a lot of type confusion. (This change will be sent upstream. Since the legacy X.509 stack is just kept around for compatibility, if they decide to fix it in a different way, we may wish to revert this and apply their fix.) Dating back to SSLeay, X509_LOOKUP_METHOD had this X509_LU_RETRY machinery. But it's not documented and it appears to have never worked. Problems with the existing logic: - X509_LU_* is not sure whether it is a type enum (to be passed into X509_LOOKUP_by_*) or a return enum (to be retained by those same functions). - X509_LOOKUP_by_* is not sure whether it returns 0/1 or an X509_LU_* value. Looking at the functions themselves, one might think it's the latter, but for X509_LOOKUP_by_subject returning both 0 and X509_LU_FAIL. But looking at the call sites, some expect 0/1 (such as X509_STORE_get1_certs) while others expect an X509_LU_* enum (such as X509_STORE_CTX_get1_issuer). It is very fortunate that FAIL happens to be 0 and X509 happens to be 1. These functions primarily call to X509_LOOKUP_METHOD hooks. Looking through OpenSSL itself and code checked into Google, I found no evidence that any hooks have been implemented except for get_by_subject in by_dir.c. We take that one as definitive and observe it believes it returns 0/1. Notably, it returns 1 on success even if asked for a type other than X509_LU_X509. (X509_LU_X509 = 1. Others are different.) I found another piece of third-party software which corroborates this worldview. - X509_STORE_get_by_subject's handling of X509_LU_RETRY (it's the j < 0 check) is broken. It saves j into vs->current_method where it probably meant to save i. (This bug has existed since SSLeay.) It also returns j (supposedly X509_LU_RETRY) while all callers of X509_STORE_get_by_subject expect it to return 0/1 by checking with ! instead of <= 0. (Note that all other codepaths return 0 and 1 so this function did not actually believe it returned X509_LU_* most of the time.) This, in turn, gives us a free of uninitialized pointers in X509_STORE_get1_certs and other functions which expect that *ret is filled in if X509_STORE_get_by_subject returns success. GCC 4.9 with optimizations from the Android NDK noticed this, which trigged this saga. (It's only reachable if any X509_LOOKUP_METHOD returned X509_LU_RETRY.) - Although the code which expects X509_STORE_get_by_subject return 0/1 does not date to SSLeay, the X509_STORE_get_by_subject call in X509_STORE_CTX_get1_issuer *does* (though, at the time, it was inline in X509_verify_cert. That code believes X509_STORE_get_by_subject returns an X509_LU_* enum, but it doesn't work either! It believes *ret is filled in on X509_LU_RETRY, thus freeing another uninitialized pointer (GCC noticed this too). Since this "retry" code has clearly never worked, from SSLeay onwards, unwind it completely rather than attempt to fix it. No X509_LOOKUP_METHOD can possibly have depended on it. Matching all non-broken codepaths X509_LOOKUP_by_* now returns 0/1 and X509_STORE_get_by_subject returns 0/1. X509_LU_* is purely a type enum with X509_LU_{REJECT,FAIL} being legacy constants to keep old code compiling. (Upstream is recommended to remove those values altogether for 1.1.0.) On the off chance any get_by_* X509_LOOKUP_METHOD implementations did not return 0/1 (I have found no evidence anywhere of this, and I believe it wouldn't have worked anyway), the X509_LOOKUP_by_* wrapper functions will coerce the return values back to 0/1 before passing up to the callers which want 0/1. This both avoids the error-prone -1/0/1 calling convention and, more importantly, avoids problems with third-party callers which expect a X509_LU_* return code. 0/1 collide with FAIL/X509 while -1 will collide with RETRY and might confuse things. Change-Id: I98ecf6fa7342866b9124dc6f0b422cb9ce4a1ae7 Reviewed-on: https://boringssl-review.googlesource.com/8303 Reviewed-by: Adam Langley <agl@google.com> commit 054e597670b158012a585f0f3d3bbf106211a7e9 Author: David Benjamin <davidben@google.com> Date: Thu Jun 16 12:08:26 2016 -0400 Include intrin.h under cover of warning pragmas. intrin.h on MSVC seems to have the same problem as other MSVC headers. https://build.chromium.org/p/client.boringssl/builders/win64_small/builds/455/steps/ninja/logs/stdio Change-Id: I98e959132c2f6188727d6c432f9c85aa0a78e91e Reviewed-on: https://boringssl-review.googlesource.com/8305 Reviewed-by: Adam Langley <agl@google.com> commit 2b360714abf9395d85ac9b50850fcd2fc4bda442 Author: Nico Weber <thakis@chromium.org> Date: Thu Jun 16 10:12:05 2016 +0200 win: Add an explicit intrin.h include to work around a clang-cl bug. I did the same change in NaCl in https://codereview.chromium.org/2070533002/. I thought NaCl is the only place where this was needed, but at least it's due to SecureZeroMemory() again. So it's two files now, but at least there's only one function we know of that needs this, and it's only called in three files total in all projects used by Chromium. BUG=chromium:592745 Change-Id: I07ed197869e26ec70c1f4b75d91fd64abae5015e Reviewed-on: https://boringssl-review.googlesource.com/8320 Reviewed-by: David Benjamin <davidben@google.com> commit 80ef4333591db8eb79c654cb030142edeab181ce Author: David Benjamin <davidben@google.com> Date: Wed Jun 15 17:46:31 2016 -0400 No-op change to kick the bots. Change-Id: Ifed0b7e23bb4df191628486b0c07c888056c22a8 commit f8fcdf399c2da11e248c0b14265ed4088001c5f2 Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 15:56:13 2016 -0400 Add tests for both Channel ID and NPN together. Both messages go between CCS and Finished. We weren't testing their relative order and one of the state machine edges. Also test resume + NPN since that too is a different handshake shape. Change-Id: Iaeaf6c2c9bfd133103e2fb079d0e5a86995becfd Reviewed-on: https://boringssl-review.googlesource.com/8196 Reviewed-by: Adam Langley <agl@google.com> commit 65dac9c8a30d6427aee988a06dcb603d09863000 Author: David Benjamin <davidben@google.com> Date: Wed Jun 15 17:24:20 2016 -0400 Fix the name of OPENSSL_add_all_algorithms_conf. I named the compatibility function wrong. Change-Id: Idc289c317c5826c338c1daf58a2d3b26b09a7e49 Reviewed-on: https://boringssl-review.googlesource.com/8301 Reviewed-by: Adam Langley <agl@google.com> commit 41e08045f7e5150f74f5020d3f470335191d2e46 Author: David Benjamin <davidben@google.com> Date: Tue Jun 14 15:53:40 2016 -0400 Fix typo. Change-Id: I7699d59e61df16f2091c3e12607c08333dcc9813 Reviewed-on: https://boringssl-review.googlesource.com/8280 Reviewed-by: Adam Langley <agl@google.com> commit f715c423224a292d79ba0e3df373c828fbae29f7 Author: David Benjamin <davidben@google.com> Date: Sat Jun 11 19:01:56 2016 -0400 Make SSL_set_bio's ownership easier to reason about. SSL_set_bio has some rather complex ownership story because whether rbio/wbio are both owning depends on whether they are equal. Moreover, whether SSL_set_bio(ssl, rbio, wbio) frees ssl->rbio depends on whether rbio is the existing rbio or not. The current logic doesn't even get it right; see tests. Simplify this. First, rbio and wbio are always owning. All the weird ownership cases which we're stuck with for compatibility will live in SSL_set_bio. It will internally BIO_up_ref if necessary and appropriately no-op the left or right side as needed. It will then call more well-behaved ssl_set_rbio or ssl_set_wbio functions as necessary. Change-Id: I6b4b34e23ed01561a8c0aead8bb905363ee413bb Reviewed-on: https://boringssl-review.googlesource.com/8240 Reviewed-by: Adam Langley <agl@google.com> commit 5c0fb889a1348ecaa5691f6139f9d60a610f2129 Author: David Benjamin <davidben@google.com> Date: Tue Jun 14 14:03:51 2016 -0400 Add tests for SSL_set_fd and friends. Their implementations expose a lot of really weird SSL_set_bio behavior. Note that one test must be disabled as it doesn't even work. The subsequent commit will re-enable it. Change-Id: I4b7acadd710b3be056951886fc3e073a5aa816de Reviewed-on: https://boringssl-review.googlesource.com/8272 Reviewed-by: Adam Langley <agl@google.com> commit dfdd49c9612afb928b0275d7fad34da1803062d4 Author: Matt Braithwaite <mab@google.com> Date: Mon Jun 13 17:06:48 2016 -0700 generate_build_files: more flexible Bazel deps Include all internal headers in |test_support_sources|, since that's easier than enumerating the ones specifically required for each test. This incidentally removes test headers from |crypto_internal_headers| and |ssl_internal_headers|. Require the crypto and ssl libraries to be passed as arguments to create_tests(), rather than hardcoding the names :crypto and :ssl Change-Id: Idcc522298c5baca2a84635ad3a7fdcf6e4968a5a Reviewed-on: https://boringssl-review.googlesource.com/8260 Reviewed-by: David Benjamin <davidben@google.com> commit 7af3140a824a4a1763609a0107a918bde02bef04 Author: David Benjamin <davidben@google.com> Date: Sat Jun 11 19:37:21 2016 -0400 Remove ASN.1 BIOs. These are more remnants of CMS. Nothing uses them directly. Removing them means more code we don't have to think about when importing upstream patches. Also take out a bunch of dead prototypes nearby. Change-Id: Ife094d9d2078570006d1355fa4e3323f435be608 Reviewed-on: https://boringssl-review.googlesource.com/8244 Reviewed-by: David Benjamin <davidben@google.com> commit ae0bf3b7c15d20304279ca53550b4c75876651c1 Author: David Benjamin <davidben@google.com> Date: Sat Jun 11 19:13:58 2016 -0400 Remove ASN1_parse and ASN1_parse_dump. These are more pretty-printers for generic ASN.1 structures. They're never called externally and otherwise are only used in the X509V3_EXT_PARSE_UNKNOWN mode for the X509 pretty-print functions. That makes unknown extensions pretty-print as ASN.1 structures. This is a rather useless feature, so have that fall through to X509V3_EXT_DUMP_UNKNOWN which does a hexdump instead. (The immediate trigger is I don't know what |op| is in upstream's 8c918b7b9c93ba38790ffd1a83e23c3684e66f57 and don't think it is worth the time to puzzle that out and verify it. Better ditch this code completely.) Change-Id: I0217906367d83056030aea64ef344d4fedf74763 Reviewed-on: https://boringssl-review.googlesource.com/8243 Reviewed-by: David Benjamin <davidben@google.com> commit e77b16ef71a7669f166f0bdd153c512598694403 Author: David Benjamin <davidben@google.com> Date: Sat Jun 11 19:22:10 2016 -0400 Remove ASN.1 print hooks. These functions are never instantiated. (They're a remnant of the PKCS#7 and CMS bits.) Next time upstream touches this code, we don't have to puzzle through the diff and import it. Change-Id: I67c2102ae13e8e0527d858e1c63637dd442a4ffb Reviewed-on: https://boringssl-review.googlesource.com/8242 Reviewed-by: David Benjamin <davidben@google.com> commit 6278e24a62c613d8c23b70eec1142af7934b1900 Author: Matt Braithwaite <mab@google.com> Date: Tue Jun 14 08:18:22 2016 -0700 shim: fix var unused when asserts compiled out This is not very satisfactory. Change-Id: I7e7a86f921e66f8f830c72eac084e9fea5ffd4d9 Reviewed-on: https://boringssl-review.googlesource.com/8270 Reviewed-by: David Benjamin <davidben@google.com> commit 54217e4d85b7d7d3ba1cd3024c54615b7fa87f3c Author: Matt Braithwaite <mab@google.com> Date: Mon Jun 13 13:03:47 2016 -0700 newhope: test corrupt key exchange messages. By corrupting the X25519 and Newhope parts separately, the test shows that both are in use. Possibly excessive? Change-Id: Ieb10f46f8ba876faacdafe70c5561c50a5863153 Reviewed-on: https://boringssl-review.googlesource.com/8250 Reviewed-by: Adam Langley <agl@google.com> commit d0c677cd8e2fca7fce5d77090f3616ba1d59e0c9 Author: David Benjamin <davidben@google.com> Date: Sat Jun 11 19:12:10 2016 -0400 Avoid illegal pointers in asn1_string_canon. (Imported from upstream's 3892b95750b6aa5ed4328a287068f7cdfb9e55bc.) More reasonable would have been to drop |to| altogether and act on from[len-1], but I suppose this works. Change-Id: I280b4991042b4d330ba034f6a631f8421ddb2643 Reviewed-on: https://boringssl-review.googlesource.com/8241 Reviewed-by: Adam Langley <agl@google.com> commit 37e01b393cd4c4d2f8b2b48fe9b2a94907a495a9 Author: David Benjamin <davidben@google.com> Date: Mon Jun 13 13:42:04 2016 -0400 Spell C++11 as C++11, not C++0x. We already require GCC 4.8+, so -std=c++11 should work fine. Change-Id: I07d46d7dcccb695b5df97a702f0d5007fdff3385 Reviewed-on: https://boringssl-review.googlesource.com/8245 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit f6a74c61f7455885a514e577d69670f924b6cf6f Author: David Benjamin <davidben@google.com> Date: Fri Jun 10 13:12:20 2016 -0400 Document compiler and assembler requirements. The minimum version is purely based on what we've patched out of the perlasm files. I'm assuming they're accurate. Change-Id: I5ae176cf793512125fa78f203a1314396e8a14d7 Reviewed-on: https://boringssl-review.googlesource.com/8238 Reviewed-by: Adam Langley <agl@google.com> commit 171b5403ee767fa0f3aecd377867db6533c3eb8f Author: David Benjamin <davidben@google.com> Date: Thu Jun 9 19:01:11 2016 -0400 Fix ssl3_do_write error handling. The functions it calls all pass through <= 0 as error codes, not < 0. Change-Id: I9d0d6b1df0065efc63f2d3a5e7f3497b2c28453a Reviewed-on: https://boringssl-review.googlesource.com/8237 Reviewed-by: Adam Langley <agl@google.com> commit 166958944506f28a87a8577cd51394ee9a53a228 Author: Matt Braithwaite <mab@google.com> Date: Thu Jun 9 09:34:11 2016 -0700 Bazel: allow arbitrary path prefix before 'src' Change-Id: Ifd8e6466620a92f0d4b79c179bb21e634a930f52 Reviewed-on: https://boringssl-review.googlesource.com/8220 Reviewed-by: David Benjamin <davidben@google.com> commit a353cdb67191a6eacd3409cc642816574084b871 Author: David Benjamin <davidben@google.com> Date: Thu Jun 9 16:48:33 2016 -0400 Wrap MSVC-only warning pragmas in a macro. There's a __pragma expression which allows this. Android builds us Windows with MinGW for some reason, so we actually do have to tolerate non-MSVC-compatible Windows compilers. (Clang for Windows is much more sensible than MinGW and intentionally mimicks MSVC.) MinGW doesn't understand MSVC's pragmas and warns a lot. #pragma warning is safe to suppress, so wrap those to shush them. This also lets us do away with a few ifdefs. Change-Id: I1f5a8bec4940d4b2d947c4c1cc9341bc15ec4972 Reviewed-on: https://boringssl-review.googlesource.com/8236 Reviewed-by: Adam Langley <agl@google.com> commit 2e8ba2d25d18d37ac36f5aea07b546c7221d4d1c Author: David Benjamin <davidben@google.com> Date: Thu Jun 9 16:22:26 2016 -0400 Use one C99-style for loop. Switch one for loop to the new spelling as a canary. All our compilers seem to support it fine, except GCC needs to be told to build with -std=c99. (And, upon doing so, it'll require _XOPEN_SOURCE=700 for pthread_rwlock_t.) We'll let this sit for a bit until it's gotten into downstreams without issue and then open the floodgates. BUG=47 Change-Id: I1c69d4b2df8206e0b55f30aa59b5874d82fca893 Reviewed-on: https://boringssl-review.googlesource.com/8235 Reviewed-by: Adam Langley <agl@google.com> commit 95d7a498cceb6a1eff93b175cad10d97c1e9fb82 Author: David Benjamin <davidben@google.com> Date: Thu Jun 9 16:38:00 2016 -0400 Fix the alias checks in dtls_record.c. I forgot to save this file. Change-Id: I8540839fac2a7f426aebd7f2cb85baba337efd37 Reviewed-on: https://boringssl-review.googlesource.com/8234 Reviewed-by: Adam Langley <agl@google.com> commit bf1905a9106a1f1398c0c1509191f2767ad0709b Author: David Benjamin <davidben@google.com> Date: Thu Jun 9 13:32:25 2016 -0400 Revert "Import chacha-x86.pl fix." This reverts commit 762e1d039c1d85e4651700eed82801878a9a86bc. We no longer need to support out < in. Better to keep the assembly aligned with upstream. Change-Id: I345bf822953bd0e1e79ad5ab4d337dcb22e7676b Reviewed-on: https://boringssl-review.googlesource.com/8232 Reviewed-by: Adam Langley <agl@google.com> commit 2446db0f52b8697f3e131db3315de8a66fd9e0fe Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 18:31:42 2016 -0400 Require in == out for in-place encryption. While most of OpenSSL's assembly allows out < in too, some of it doesn't. Upstream seems to not consider this a problem (or, at least, they're failing to make a decision on whether it is a problem, so we should assume they'll stay their course). Accordingly, require aliased buffers to exactly align so we don't have to keep chasing this down. Change-Id: I00eb3df3e195b249116c68f7272442918d7077eb Reviewed-on: https://boringssl-review.googlesource.com/8231 Reviewed-by: Adam Langley <agl@google.com> commit 1a01e1fc88968c4db023f38967f9e81a8c42a15d Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 18:31:24 2016 -0400 Remove in-place TLS record assembly for now. Decrypting is very easy to do in-place, but encrypting in-place is a hassle. The rules actually were wrong due to record-splitting. The aliasing prefix and the alignment prefix actually differ by 1. Take it out for now in preparation for tightening the aliasing rules. If we decide to do in-place encrypt later, probably it'd be more useful to return header + in-place ciphertext + trailer. (That, in turn, needs a scatter/gather thing on the AEAD thanks to TLS 1.3's padding and record type construction.) We may also wish to rethink how record-splitting works here. Change-Id: I0187d39c541e76ef933b7c2c193323164fd8a156 Reviewed-on: https://boringssl-review.googlesource.com/8230 Reviewed-by: Adam Langley <agl@google.com> commit 67cb49d045f04973ddba0f92fe8a8ad483c7da89 Author: David Benjamin <davidben@google.com> Date: Thu Jun 9 18:57:56 2016 +0000 Fix BN_mod_word bug. On systems where we do not have BN_ULLONG (notably Win64), BN_mod_word() can return incorrect results if the supplied modulus is too big. (Imported from upstream's e82fd1b4574c8908b2c3bb68e1237f057a981820 and e4c4b2766bb97b34ea3479252276ab7c66311809.) Change-Id: Icee8a7c5c67a8ee14c276097f43a7c491e68c2f9 Reviewed-on: https://boringssl-review.googlesource.com/8233 Reviewed-by: Adam Langley <agl@google.com> commit 8f1e113a73e406db710479ea4d8478890c0514ea Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 12:49:36 2016 -0400 Ensure verify error is set when X509_verify_cert() fails. Set ctx->error = X509_V_ERR_OUT_OF_MEM when verification cannot continue due to malloc failure. Similarly for issuer lookup failures and caller errors (bad parameters or invalid state). Also, when X509_verify_cert() returns <= 0 make sure that the verification status does not remain X509_V_OK, as a last resort set it it to X509_V_ERR_UNSPECIFIED, just in case some code path returns an error without setting an appropriate value of ctx->error. Add new and some missing error codes to X509 error -> SSL alert switch. (Imported from upstream's 5553a12735e11bc9aa28727afe721e7236788aab.) Change-Id: I3231a6b2e72a3914cb9316b8e90ebaee009a1c5f Reviewed-on: https://boringssl-review.googlesource.com/8170 Reviewed-by: David Benjamin <davidben@google.com> commit 82d0ffbac1a892e23b63d055b67b7d93e489af3e Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 19:19:58 2016 -0400 Use the new setter for CurrentTimeCallback in bssl_shim. Change-Id: I0aaf9d926a81c3a10e70ae3ae6605d4643419f89 Reviewed-on: https://boringssl-review.googlesource.com/8210 Reviewed-by: Taylor Brandstetter <deadbeef@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 9edb2c60559b2d1d35972de62f0d8d604c1d1e6d Author: Taylor Brandstetter <deadbeef@webrtc.org> Date: Wed Jun 8 15:26:59 2016 -0700 Adding function to set the "current time" callback used for DTLS. This callback is used by BoringSSL tests in order to simulate the time, so that the tests have repeatable results. This API will allow consumers of BoringSSL to write the same sort of tests. Change-Id: I79d72bce5510bbd83c307915cd2cc937579ce948 Reviewed-on: https://boringssl-review.googlesource.com/8200 Reviewed-by: David Benjamin <davidben@google.com> commit 2e045a980caba02868f6a1e5e29f7fff358873b1 Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 13:09:56 2016 -0400 Add a deterministic PRNG for runner. It's useful, when combined with patching crypto/rand/deterministic.c in, for debugging things. Also if we want to record fuzzer transcripts again, this probably should be on. Change-Id: I109cf27ebab64f01a13466f0d960def3257d8750 Reviewed-on: https://boringssl-review.googlesource.com/8192 Reviewed-by: David Benjamin <davidben@google.com> commit 1e3376a790d044facd929205fcdf4eb30783e07f Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 14:17:18 2016 -0400 Add missing copyright header. x25519-x86_64.c, like the rest of crypto/curve25519, is descended from SUPERCOP. Add the usual copyright header along with the SUPERCOP attribution. BUG=64 Change-Id: I43f3de0731f33ab2aa48492c4b742e9f23c87fe1 Reviewed-on: https://boringssl-review.googlesource.com/8195 Reviewed-by: Adam Langley <agl@google.com> commit 1c0e1e4a33249b8a64fdf1a6f6e31b8acc9c45e9 Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 14:05:29 2016 -0400 Avoid overflow in newhope.go. Depending on bittedness of the runner, uint16 * uint16 can overflow an int. There's other computations that can overflow a uint32 as well, so I just made everything uint64 to avoid thinking about it too much. Change-Id: Ia3c976987f39f78285c865a2d7688600d73c2514 Reviewed-on: https://boringssl-review.googlesource.com/8193 Reviewed-by: Adam Langley <agl@google.com> commit 45d45c119475fe1601b2a19faf170cade262fffb Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 15:20:49 2016 -0400 Trim the DTLS write code slightly. Change-Id: I0fb4152ed656a60fae3aa7922652df766d4978d7 Reviewed-on: https://boringssl-review.googlesource.com/8178 Reviewed-by: David Benjamin <davidben@google.com> commit 936aada25a410cf87e0a8a4b700ea37cdb7dcbdf Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 19:09:22 2016 -0400 Move a bunch of public APIs from s3_lib.c to ssl_lib.c. The separation is purely historical (what happened to use an SSL_ctrl hook), so put them all in one place. Make a vague attempt to match the order of the header file, though we're still very far from matching. Change-Id: Iba003ff4a06684a6be342e438d34bc92cab1cd14 Reviewed-on: https://boringssl-review.googlesource.com/8189 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 01784b44b9096255a3ab7e33e7b24c4814c366f7 Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 18:00:52 2016 -0400 Rename -timeout to -idle-timeout. -timeout collides with go test's flags. Change-Id: Icfc954915a61f1bb4d0acc8f02ec8a482ea10158 Reviewed-on: https://boringssl-review.googlesource.com/8188 Reviewed-by: David Benjamin <davidben@google.com> commit 3dcec458f18eb0d8e463de254e71c252970d4cbc Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 17:13:28 2016 -0400 Rename SERVER_DONE to SERVER_HELLO_DONE. Match the actual name of the type. Change-Id: I0ad27196ee2876ce0690d13068fa95f68b05b0da Reviewed-on: https://boringssl-review.googlesource.com/8187 Reviewed-by: David Benjamin <davidben@google.com> commit cfec7c60b9eb2c403d923081ebc5158cc97e65e7 Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 17:05:07 2016 -0400 Rename s3_{clnt,srvr}.c Give them much more reasonable names. Change-Id: Id14d983ab3231da21a4f987e662c2e01af7a2cd6 Reviewed-on: https://boringssl-review.googlesource.com/8185 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 9f1dc8254effa6c430618020b08e04ab3ce8157c Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 17:03:46 2016 -0400 A bit of cleanup post state machine merging. Reorder states and functions by where they appear in the handshake. Remove unnecessary hooks on SSL_PROTOCOL_METHOD. Change-Id: I78dae9cf70792170abed6f38510ce870707e82ff Reviewed-on: https://boringssl-review.googlesource.com/8184 Reviewed-by: David Benjamin <davidben@google.com> commit df50eecfbce6c0f4614044e84869c3f43b78fc5b Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 16:49:42 2016 -0400 Fold DTLS server state machine into TLS state machine. Change-Id: I56d3d625dbe2e338f305bc1332fb0131a20e1c16 Reviewed-on: https://boringssl-review.googlesource.com/8183 Reviewed-by: David Benjamin <davidben@google.com> commit aa7734b81b5f4914829a25a4a798f22770de4bab Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 16:40:46 2016 -0400 Fold the DTLS client handshake into the TLS one. Change-Id: Ib8b1c646cf1652ee1481fe73589830be8263fc20 Reviewed-on: https://boringssl-review.googlesource.com/8182 Reviewed-by: David Benjamin <davidben@google.com> commit 0d21dcd9bb2cf06341369cfad94054af3e2aacd1 Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 16:17:06 2016 -0400 Remove unnecessary sectioning in ssl.h. There's only one thing under "SNI Extension". Change-Id: I8d8c54c286cb5775a20c4e2623896eb9be2f0009 Reviewed-on: https://boringssl-review.googlesource.com/8181 Reviewed-by: David Benjamin <davidben@google.com> commit 24fe4489d32e073e5fde1441e2073e52c06548bb Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 16:07:42 2016 -0400 Consolidate dtls1_start_timer calls. Rather than reset the timer on every message, start it up immediately after flushing one of our flights. Change-Id: I97f8b4f572ceff62c546c94933b2700975c50a02 Reviewed-on: https://boringssl-review.googlesource.com/8180 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 2a08c8d85d9c99d1548da67627e5320646eae44f Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 15:06:39 2016 -0400 Remove ssl3_do_write's 0 case. It's unreachable and wouldn't work anyway. We'd never bubble up to the caller to retry. As a consequence, the TLS side doesn't actually need to pay attention to init_off. (For now anyway. We'll probably need state of this sort once the write half is all reworked. All the craziness with wpend_buf ought to be limited to the SSL_write bits.) Change-Id: I951534f6bbeb547ce0492d5647aaf76be42108a3 Reviewed-on: https://boringssl-review.googlesource.com/8179 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit af62d61df37b50a902efb17f4ed147f6853c8bbe Author: David Benjamin <davidben@google.com> Date: Wed Jun 1 20:49:50 2016 -0400 Remove dtls1_read_bytes. It can be folded into dtls1_read_app_data. This code, since it still takes an output pointer, does not yet process records atomically. (Though, being DTLS, it probably should...) Change-Id: I57d60785c9c1dd13b5b2ed158a08a8f5a518db4f Reviewed-on: https://boringssl-review.googlesource.com/8177 Reviewed-by: David Benjamin <davidben@google.com> commit c660417bd7a7a438eddb0bc087931671b6a849e7 Author: David Benjamin <davidben@google.com> Date: Thu Jun 2 16:38:35 2016 -0400 Don't use dtls1_read_bytes to read messages. This was probably the worst offender of them all as read_bytes is the wrong abstraction to begin with. Note this is a slight change in how processing a record works. Rather than reading one fragment at a time, we process all fragments in a record and return. The intent here is so that all records are processed atomically since the connection eventually will not be able to retain a buffer holding the record. This loses a ton of (though not quite all yet) those a2b macros. Change-Id: Ibe4bbcc33c496328de08d272457d2282c411b38b Reviewed-on: https://boringssl-review.googlesource.com/8176 Reviewed-by: David Benjamin <davidben@google.com> commit 585320c9e9fc3396ffbc0d66d3c474cfdfa24607 Author: David Benjamin <davidben@google.com> Date: Tue May 10 20:46:16 2016 -0400 Don't call read_bytes in read_change_cipher_spec. Change-Id: If7d50e43c8ea28c5eed38209f31d481fb57bf225 Reviewed-on: https://boringssl-review.googlesource.com/8175 Reviewed-by: David Benjamin <davidben@google.com> commit 4aa4081e7f21916ad17e916f558a1c5dc8531830 Author: David Benjamin <davidben@google.com> Date: Wed Jun 1 19:40:23 2016 -0400 Don't use ssl3_read_bytes in ssl3_read_close_notify. read_close_notify is a very straight-forward hook and doesn't need much. Change-Id: I7407d842321ea1bcb47838424a0d8f7550ad71ca Reviewed-on: https://boringssl-review.googlesource.com/8174 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit a7810c12e99ed8cf2e3b2a049e124b4a3b1b274b Author: David Benjamin <davidben@google.com> Date: Mon Jun 6 18:54:51 2016 -0400 Make tls_open_record always in-place. The business with ssl_record_prefix_len is rather a hassle. Instead, have tls_open_record always decrypt in-place and give back a CBS to where the body is. This way the caller doesn't need to do an extra check all to avoid creating an invalid pointer and underflow in subtraction. Change-Id: I4e12b25a760870d8f8a503673ab00a2d774fc9ee Reviewed-on: https://boringssl-review.googlesource.com/8173 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 728f354a2ba5653d10ebededc5acaa5ab5c4becd Author: David Benjamin <davidben@google.com> Date: Thu Jun 2 15:42:01 2016 -0400 Push alert handling down into the record functions. Alert handling is more-or-less identical across all contexts. Push it down from read_bytes into the low-level record functions. This also deduplicates the code shared between TLS and DTLS. Now the only type mismatch managed by read_bytes is if we get handshake data in read_app_data. Change-Id: Ia8331897b304566e66d901899cfbf31d2870194e Reviewed-on: https://boringssl-review.googlesource.com/8124 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit ac2920200baec989553b145c26ed29b6807698c7 Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 14:15:46 2016 -0400 Fix typo. Change-Id: I70499c686b955152840987ffe65d2d3436bf6f6d Reviewed-on: https://boringssl-review.googlesource.com/8194 Reviewed-by: David Benjamin <davidben@google.com> commit 4e9cc71a27234d8506c5b5987122188e34ece951 Author: David Benjamin <davidben@google.com> Date: Wed Jun 1 20:16:03 2016 -0400 Add helper functions for info_callback and msg_callback. This is getting a little repetitive. Change-Id: Ib0fa8ab10149557c2d728b88648381b9368221d9 Reviewed-on: https://boringssl-review.googlesource.com/8126 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 15aa895a0b6bb6d8f409cff8f1d6f47a069cd4b9 Author: David Benjamin <davidben@google.com> Date: Tue May 10 20:51:34 2016 -0400 Tidy up the DTLS code's blocking-mode retransmits. Move this logic out of dtls1_read_bytes and into dtls1_get_record. Only trigger it when reading from the buffer fails. The other one shouldn't be necessary. This exists to handle the blocking BIO case when the BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT signal triggers, so we only need to do it when timeouts actually trigger. There also doesn't seem to be a need for most of the machinery. The BIO_set_flags call seems to be working around a deficiency in the underlying BIO. There also shouldn't be a need to check the handshake state as there wouldn't be a timer to restart otherwise. Change-Id: Ic901ccfb5b82aeb409d16a9d32c04741410ad6d7 Reviewed-on: https://boringssl-review.googlesource.com/8122 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 585d7a4987126192d90d5e6d33fc400da00a863b Author: David Benjamin <davidben@google.com> Date: Thu Jun 2 14:58:00 2016 -0400 Test both synchronous and asynchronous DTLS retransmit. The two modes are quite different. One of them requires the BIO honor an extra BIO_ctrl. Also add an explanation at the top of addDTLSRetransmitTests for how these tests work. The description is scattered across many different places. BUG=63 Change-Id: Iff4cdd1fbf4f4439ae0c293f565eb6780c7c84f9 Reviewed-on: https://boringssl-review.googlesource.com/8121 Reviewed-by: David Benjamin <davidben@google.com> commit ed9c8fcb23877e647416768e741d50f36e1c170d Author: David Benjamin <davidben@google.com> Date: Wed Jun 8 09:40:32 2016 -0400 Honor exit codes in run_android_tests.go. adb kindly doesn't forward exit codes until N (https://code.google.com/p/android/issues/detail?id=3254), so we need to work around it. Otherwise all our test failures have been silently ignored (oops!). Change-Id: I03440db7dd77e6b9af5445b309b67dc719cea054 Reviewed-on: https://boringssl-review.googlesource.com/8190 Reviewed-by: David Benjamin <davidben@google.com> commit 0a45822afee4eb4a047c7b41ad1783f31a838820 Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 14:34:21 2016 -0400 Fix some missing inits (Imported from upstream's f792c663048f19347a1bb72125e535e4fb2ecf39.) Change-Id: If9bbb10de3ea858076bd9587d21ec331e837dd53 Reviewed-on: https://boringssl-review.googlesource.com/8171 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 26b7c35d8c78065a57c93a01d95b31eb85de51b9 Author: David Benjamin <davidben@google.com> Date: Tue Jun 7 14:38:01 2016 -0400 Fix DSA, preserve BN_FLG_CONSTTIME Operations in the DSA signing algorithm should run in constant time in order to avoid side channel attacks. A flaw in the OpenSSL DSA implementation means that a non-constant time codepath is followed for certain operations. This has been demonstrated through a cache-timing attack to be sufficient for an attacker to recover the private DSA key. CVE-2016-2178 (Imported from upstream's 621eaf49a289bfac26d4cbcdb7396e796784c534 and b7d0f2834e139a20560d64c73e2565e93715ce2b.) We should eventually not depend on BN_FLG_CONSTTIME since it's a mess (seeing as the original fix was wrong until we reported b7d0f2834e to them), but, for now, go with the simplest fix. Change-Id: I9ea15c1d1cc3a7e21ef5b591e1879ec97a179718 Reviewed-on: https://boringssl-review.googlesource.com/8172 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 0d275bdb32e22e5e75e30981976dbbc28c8805bc Author: David Benjamin <davidben@google.com> Date: Wed Jun 1 20:19:34 2016 -0400 Don't call ERR_clear_system_error in so many places. We've got it in entry points. That should be sufficient. (Do we even need it there?) Change-Id: I39b245a08fcde7b57e61b0bfc595c6ff4ce2a07a Reviewed-on: https://boringssl-review.googlesource.com/8127 Reviewed-by: David Benjamin <davidben@google.com> commit 4bea8509dacd4d637c5c77964d315172bf35d825 Author: David Benjamin <davidben@google.com> Date: Thu May 12 09:34:55 2016 -0400 Lift an impossible check to an assert. This cannot happen. Change-Id: Ib1b473aa91d6479eeff43f7eaf94906d0b2c2a8f Reviewed-on: https://boringssl-review.googlesource.com/8123 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit e90d004e007272df4dcc65a35138fe639635e5ab Author: David Benjamin <davidben@google.com> Date: Wed Jun 1 20:05:59 2016 -0400 Remove impossible condition. ssl->cert is never NULL. It gets created in SSL_new unconditionally. Change-Id: I5c54c9c73e281e61a554820d61421226d763d33a Reviewed-on: https://boringssl-review.googlesource.com/8125 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 83042a829260f53b0f0f49e06d33bc3a73401bf0 Author: David Benjamin <davidben@google.com> Date: Mon Jun 6 11:29:58 2016 -0400 Add a no-op OpenSSL_add_all_algorithms_conf. More spring-cleaning of unnecessary incompatibilities. Since OpenSSL_add_all_algorithms_conf doesn't specify a configuration file, it's perfectly sound to have such a function. Dear BoringSSL, please add all algorithms. Uh, sure. They were already all there, but I have added them! PS: Could you also load all your configuration files while you're at it. ...I don't have any. Fine. I have loaded all configuration files which I recognize. *mutters under breath* why does everyone ask all these strange questions... Change-Id: I57f956933d9e519445bf22f89853bd5f56904172 Reviewed-on: https://boringssl-review.googlesource.com/8160 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit adf27430efa4062ad4585d9cf788c9ab7a164e44 Author: Adam Langley <agl@google.com> Date: Sun Jun 5 11:01:20 2016 -0700 Be consistent about 𝑥_tests.txt Some files were named 𝑥_test.txt and some 𝑥_tests.txt. This change unifies around the latter. Change-Id: Id6f29bad8b998f3c3466655097ef593f7f18f82f Reviewed-on: https://boringssl-review.googlesource.com/8150 Reviewed-by: David Benjamin <davidben@google.com> commit bbc7859817e9e6d1fee989d7ded5d5836d7efded Author: David Benjamin <davidben@google.com> Date: Fri Jun 3 16:56:32 2016 -0400 Match OpenSSL's values for BIO_CTRL_*. The fake numbers collide with other numbers defined below. Also PUSH and POP are actually used. DUP legitimately isn't though. Change-Id: Iaa15a065d846b89b9b7958b78068393cfee2bd6f Reviewed-on: https://boringssl-review.googlesource.com/8143 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit f4978b78a0219c1846ad3d58a53250b827b4140a Author: David Benjamin <davidben@google.com> Date: Fri Jun 3 16:53:15 2016 -0400 Add some getters for the old lock callbacks. Some OpenSSL consumers use them, so provide no-op versions to make porting code easier. Change-Id: I4348568c1cb08d2b2c0a9ec9a17e2c0449260965 Reviewed-on: https://boringssl-review.googlesource.com/8142 Reviewed-by: David Benjamin <davidben@google.com> commit e7b3ce58ad100adbe738eae6b38e0fa72542663e Author: David Benjamin <davidben@google.com> Date: Fri Jun 3 16:45:30 2016 -0400 Add BIO_set_conn_int_port. Make building against software that expects OpenSSL easier. Change-Id: I1af090ae8208218d6e226ee0baf51053699d85cc Reviewed-on: https://boringssl-review.googlesource.com/8141 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit dbec90b62328e483323394f93e89fe657f4568c2 Author: David Benjamin <davidben@google.com> Date: Fri Jun 3 17:51:36 2016 -0400 Sort out signedness issues. Windows is, not unreasonably, complaining that taking abs() of an unsigned is ridiculous. But these values actually are signed and fit very easily in an int anyway. Change-Id: I34fecaaa3616732112e3eea105a7c84bd9cd0bae Reviewed-on: https://boringssl-review.googlesource.com/8144 Reviewed-by: Adam Langley <agl@google.com> commit d206dfa91fce51c8e454f2dd1e17da6afac76fb9 Author: David Benjamin <davidben@google.com> Date: Fri Jun 3 18:00:34 2016 -0400 Add missing newline in newhope.h. doc.go is still a little unhappy. Change-Id: I5a8f3da91dabb45d29d0e08f13b7dabdcd521c38 Reviewed-on: https://boringssl-review.googlesource.com/8145 Reviewed-by: David Benjamin <davidben@google.com> commit aa80ff50bf1467ed522a127ffb724864ac5d6d05 Author: Adam Langley <agl@google.com> Date: Fri Jun 3 14:45:18 2016 -0700 crypto/newhope: add OPENSSL_EXPORT to functions used by tests. Change-Id: Ie6701d6ea809f5c590f0773cb4b733a208553879 commit a34bd8e38cf3e6908b7a0c72ad9b78e119709ada Author: Adam Langley <agl@google.com> Date: Fri Jun 3 14:37:03 2016 -0700 crypto/newhope: fix comment typo. Change-Id: Ic7dc57680e8cc8306fb1541249fb356eece30999 commit 77fe71101bde819ea5e93eb2e3a8e1335548e210 Author: Adam Langley <agl@google.com> Date: Fri Jun 3 14:32:59 2016 -0700 crypto/newhope: print values as unsigneds. Otherwise builds fail with: crypto/newhope/newhope_statistical_test.cc:136:27: error: format specifies type 'long' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Werror,-Wformat] Change-Id: I85d5816c1d7ee71eef362bffe983b2781ce310a4 commit 6b7436b0d29ac3018e23cfc0dd734dfd8024a80f Author: Matt Braithwaite <mab@google.com> Date: Thu Jun 2 17:23:29 2016 -0700 newhope: restore statistical tests. One of these tests the distribution of noise polynomials; the other tests that that agreed-upon keys (prior to whitening) have roughly equal numbers of 0s and 1s. Along the way, expose a few more API bits. Change-Id: I6b04708d41590de45d82ea95bae1033cfccd5d67 Reviewed-on: https://boringssl-review.googlesource.com/8130 Reviewed-by: Adam Langley <agl@google.com> commit 0fc7df55c04e439e765c32a4dd93e43387fe40be Author: David Benjamin <davidben@google.com> Date: Thu Jun 2 18:36:33 2016 -0400 Add SSL_CIPHER_is_DHE. Change-Id: I158d1fa1a6b70a278054862326562988c97911b5 Reviewed-on: https://boringssl-review.googlesource.com/8140 Reviewed-by: David Benjamin <davidben@google.com> commit 66af3b0ebc1ed1b4e6dba6c8d399096e21e68299 Author: Steven Valdez <svaldez@google.com> Date: Wed Jun 1 14:07:09 2016 -0400 Adding TLS 1.3 Record Layer. In TLS 1.3, the actual record type is hidden within the encrypted data and the record layer defaults to using a TLS 1.0 {3, 1} record version for compatibility. Additionally the record layer no longer checks the minor version of the record layer to maintain compatibility with the TLS 1.3 spec. Change-Id: If2c08e48baab170c1658e0715c33929d36c9be3a Reviewed-on: https://boringssl-review.googlesource.com/8091 Reviewed-by: David Benjamin <davidben@google.com> commit 1a88df13e51af83de8c1631327e942f3ca03fbe6 Author: David Benjamin <davidben@google.com> Date: Thu Jun 2 17:14:33 2016 -0400 Update style guide note on files which match OpenSSL. They match the new style not the old EAY style now. They're also not likely to be reformatted. It's just the legacy ASN.1 stuff now and we're intentionally not doing much with those. (The old text was written back before the SSL stack had been reformatted.) Change-Id: I4852761b013e8c2688ebc7eaf4970afbdc69e858 Reviewed-on: https://boringssl-review.googlesource.com/8129 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 3084e7b87ded165d3dab194f9b4666d02437cbb7 Author: Steven Valdez <svaldez@google.com> Date: Thu Jun 2 12:07:20 2016 -0400 Adding ECDHE-PSK GCM Ciphersuites. Change-Id: Iecf534ca0ebdcf34dbf4f922f5000c096a266862 Reviewed-on: https://boringssl-review.googlesource.com/8101 Reviewed-by: David Benjamin <davidben@google.com> commit 8ca0b4127da11d766067ea6ec4122017ba0edb0e Author: Piotr Sikora <piotrsikora@google.com> Date: Thu Jun 2 11:59:21 2016 -0700 Fix X25519 on OS X when using build systems other than CMake. Assembly code for X25519 wasn't included on OS X when built with build systems other than CMake, which lead to a SIGTRAP due to a missing x25519_x86_64. Reported by Gurgen Hrachyan. Change-Id: Ib6026f31cce0405ec3e75d8a52bf0940e57c62c8 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/8111 Reviewed-by: David Benjamin <davidben@google.com> commit 27e863e711408cb20daf1125be4519d465e48d4e Author: Matt Braithwaite <mab@google.com> Date: Wed Jun 1 16:28:48 2016 -0700 newhope: improve test vectors. This commit adds coverage of the "offer" (first) step, as well as testing all outputs of the "accept" (second) step, not just the shared key. Change-Id: Id11fe24029abc302442484a6c01fa496a1578b3a Reviewed-on: https://boringssl-review.googlesource.com/8100 Reviewed-by: Adam Langley <agl@google.com> commit 686bb19ba114b3b8c87264d9a5a7a4af32587756 Author: David Benjamin <davidben@google.com> Date: Tue May 10 15:15:41 2016 -0400 Add a unit test for one-sided shutdown. OpenSSL was actually super-buggy here (though known bugs on our end have been fixed), but pyOpenSSL was confused and incorrectly documented that callers call SSL_read after SSL_shutdown to do bidi shutdown, so we should probably support this. Add a test that it works. Change-Id: I2b6d012161330aeb4cf894bae3a0b6a55d53c70d Reviewed-on: https://boringssl-review.googlesource.com/8093 Reviewed-by: Adam Langley <agl@google.com> commit bbd43b5e90c073a3c8b719d538a273fe683b9944 Author: Steven Valdez <svaldez@google.com> Date: Wed Jun 1 11:46:58 2016 -0400 Renaming SSL3_MT_NEWSESSION_TICKET to SSL3_MT_NEW_SESSION_TICKET. This keeps the naming convention in line with the actual spec. Change-Id: I34673f78dbc29c1659b4da0e49677ebe9b79636b Reviewed-on: https://boringssl-review.googlesource.com/8090 Reviewed-by: David Benjamin <davidben@google.com> commit db207264ad69af640f6d1d60e6489ff2896e72b9 Author: Matt Braithwaite <mab@google.com> Date: Fri May 27 16:49:29 2016 -0700 newhope: refactor and add test vectors. The test vectors are taken from the reference implementation, modified to output the results of its random-number generator, and the results of key generation prior to SHA3. This allows the interoperability of the two implementations to be tested somewhat. To accomplish the testing, this commit creates a new, lower-level API that leaves the generation of random numbers and all wire encoding and decoding up to the caller. Change-Id: Ifae3517696dde4be4a0b7c1998bdefb789bac599 Reviewed-on: https://boringssl-review.googlesource.com/8070 Reviewed-by: Adam Langley <agl@google.com> commit 3995a38f3b8f8c944338e94bb63d04bc323b60b4 Author: David Benjamin <davidben@google.com> Date: Tue May 31 16:15:04 2016 -0400 Print out whether EMS was supported. Change-Id: I3c5aa418fe767bce883fcdd0a926f922f9f8bbd3 Reviewed-on: https://boringssl-review.googlesource.com/8082 Reviewed-by: Adam Langley <agl@google.com> commit 156edfe5361ad635c091265eb8035f2c310371d3 Author: David Benjamin <davidben@google.com> Date: Tue May 24 15:41:11 2016 +0000 Switch Windows CRYPTO_MUTEX implementation to SRWLOCK. Now that we no longer support Windows XP, this is available. Unfortunately, the public header version of CRYPTO_MUTEX means we still can't easily merge CRYPTO_MUTEX and CRYPTO_STATIC_MUTEX. BUG=37 Change-Id: If309de3f06e0854c505083b72fd64d1dbb3f4563 Reviewed-on: https://boringssl-review.googlesource.com/8081 Reviewed-by: Adam Langley <agl@google.com> commit 29270dea85741f69bd080bea6b28a83476c2bc91 Author: David Benjamin <davidben@google.com> Date: Tue May 24 15:28:36 2016 +0000 Split unlock functions into read/write variants. Windows SRWLOCK requires you call different functions here. Split them up in preparation for switching Windows from CRITICAL_SECTION. BUG=37 Change-Id: I7b5c6a98eab9ae5bb0734b805cfa1ff334918f35 Reviewed-on: https://boringssl-review.googlesource.com/8080 Reviewed-by: Adam Langley <agl@google.com> commit 053931e74e42bebd129d9b35d9aceb986e873a8f Author: Matt Braithwaite <mab@google.com> Date: Wed May 25 12:06:05 2016 -0700 CECPQ1: change from named curve to ciphersuite. This is easier to deploy, and more obvious. This commit reverts a few pieces of e25775bc, but keeps most of it. Change-Id: If8d657a4221c665349c06041bb12fffca1527a2c Reviewed-on: https://boringssl-review.googlesource.com/8061 Reviewed-by: Adam Langley <agl@google.com> commit d09175ffe335d9be6846b4ac5e9e622d96213a00 Author: Adam Langley <alangley@gmail.com> Date: Fri May 20 10:51:48 2016 -0700 Replace base64 decoding. This code has caused a long history of problems. This change rewrites it completely with something that is, hopefully, much simplier and robust and adds more testing. Change-Id: Ibeef51f9386afd95d5b73316e451eb3a2d7ec4e0 Reviewed-on: https://boringssl-review.googlesource.com/8033 Reviewed-by: Adam Langley <agl@google.com> commit 1cb405d96b11db5767446766d76516534067bbd1 Author: Adam Langley <alangley@gmail.com> Date: Wed May 25 16:05:11 2016 -0700 Revert "Forbid calling SSL_read, SSL_peek, and SSL_do_handshake post-shutdown." This reverts commit c7eae5a3267dfc9557314a24cc8da77d287ae885. pyOpenSSL expects to be able to call |SSL_read| after a shutdown and get EOF. Change-Id: Icc5faa09d644ec29aac99b181dac0db197f283e3 Reviewed-on: https://boringssl-review.googlesource.com/8060 Reviewed-by: Adam Langley <agl@google.com> commit 494650cfcff2330652922ebd078066c2eff202cb Author: Steven Valdez <svaldez@google.com> Date: Tue May 24 12:43:04 2016 -0400 Adding TLS 1.3 AEAD construction. The TLS 1.3 spec has an explicit nonce construction for AEADs that requires xoring the IV and sequence number. Change-Id: I77145e12f7946ffb35ebeeb9b2947aa51058cbe9 Reviewed-on: https://boringssl-review.googlesource.com/8042 Reviewed-by: Adam Langley <agl@google.com> commit 4f94b1c19f8520273fa7751687b6daab82e02bc3 Author: Steven Valdez <svaldez@google.com> Date: Tue May 24 12:31:07 2016 -0400 Adding TLS 1.3 constants. Constants representing TLS 1.3 are added to allow for future work to be flagged on TLS1_3_VERSION. To prevent BoringSSL from negotiating the non-existent TLS 1.3 version, it is explicitly disabled using SSL_OP_NO_TLSv1_3. Change-Id: Ie5258a916f4c19ef21646c4073d5b4a7974d6f3f Reviewed-on: https://boringssl-review.googlesource.com/8041 Reviewed-by: Adam Langley <agl@google.com> commit 1eca1d3816df495e83e0d22edfbb2d380dda6984 Author: Steven Valdez <svaldez@google.com> Date: Mon May 23 16:29:25 2016 -0400 Renaming Channel ID Encrypted Extensions. This renames the Channel ID EncryptedExtensions message to allow for compatibility with TLS 1.3 EncryptedExtensions. Change-Id: I5b67d00d548518045554becb1b7213fba86731f2 Reviewed-on: https://boringssl-review.googlesource.com/8040 Reviewed-by: Adam Langley <agl@google.com> commit 2f87112b963fe9dee6a75b23a8dae45000001063 Author: David Benjamin <davidben@google.com> Date: Fri May 20 14:27:17 2016 -0400 Never expose ssl->bbio in the public API. OpenSSL's bbio logic is kind of crazy. It would be good to eventually do the buffering in a better way (notably, bbio is fragile, if not outright broken, for DTLS). In the meantime, this fixes a number of bugs where the existence of bbio was leaked in the public API and broke things. - SSL_get_wbio returned the bbio during the handshake. It must always return the BIO the consumer configured. In doing so, internal accesses of SSL_get_wbio should be switched to ssl->wbio since those want to see bbio. For consistency, do the same with rbio. - The logic in SSL_set_rfd, etc. (which I doubt is quite right since SSL_set_bio's lifetime is unclear) would get confused once wbio got wrapped. Those want to compare to SSL_get_wbio. - If SSL_set_bio was called mid-handshake, bbio would get disconnected and lose state. It forgets to reattach the bbio afterwards. Unfortunately, Conscrypt does this a lot. It just never ended up calling it at a point where the bbio would cause problems. - Make more explicit the invariant that any bbio's which exist are always attached. Simplify a few things as part of that. Change-Id: Ia02d6bdfb9aeb1e3021a8f82dcbd0629f5c7fb8d Reviewed-on: https://boringssl-review.googlesource.com/8023 Reviewed-by: Kenny Root <kroot@google.com> Reviewed-by: Adam Langley <agl@google.com> commit 7e7a82d962d84b5dea95bb5dfe82616b3551e3bc Author: David Benjamin <davidben@google.com> Date: Fri May 20 20:12:42 2016 -0400 Rename GetConfigPtr to GetTestConfig. GetConfigPtr was a silly name. GetTestConfig matches the type and GetTestState. Change-Id: I9998437a7be35dbdaab6e460954acf1b95375de0 Reviewed-on: https://boringssl-review.googlesource.com/8024 Reviewed-by: Adam Langley <agl@google.com> commit 7fcfd3b37a73ca3efde348b8bb41f37052cdd959 Author: Adam Langley <alangley@gmail.com> Date: Fri May 20 11:02:50 2016 -0700 Add ISC license to Go files that were missing a license. Change-Id: I1fe3bed7d5c577748c9f4c3ccd5c1b90fec3d7d7 Reviewed-on: https://boringssl-review.googlesource.com/8032 Reviewed-by: David Benjamin <davidben@google.com> commit ce902a9bcd59c8a3ef33900d39eeb431365c34bc Author: Steven Valdez <svaldez@google.com> Date: Tue May 17 11:47:53 2016 -0400 Generalizing curves to groups in preparation for TLS 1.3. The 'elliptic_curves' extension is being renamed to 'supported_groups' in the TLS 1.3 draft, and most of the curve-specific methods are generalized to groups/group IDs. Change-Id: Icd1a1cf7365c8a4a64ae601993dc4273802610fb Reviewed-on: https://boringssl-review.googlesource.com/7955 Reviewed-by: David Benjamin <davidben@google.com> commit f1012b5c31c8dce14a0adf1566c14a87e1889ba8 Author: Steven Valdez <svaldez@google.com> Date: Fri May 20 11:40:31 2016 -0400 Fix HKDF leak. Change-Id: Ia83935420d38ededa699aa7f8011a2e358f6c4d3 Reviewed-on: https://boringssl-review.googlesource.com/8022 Reviewed-by: David Benjamin <davidben@google.com> commit 2b1ca80e0908dac5f69aa12a2ec180c62004d6fa Author: David Benjamin <davidben@google.com> Date: Fri May 20 11:28:59 2016 -0400 Link back to the main page in documentation. Also give the main page a title. Change-Id: I6db588a9454d90a5974de5446d58d709f84d1906 Reviewed-on: https://boringssl-review.googlesource.com/8020 Reviewed-by: Adam Langley <agl@google.com> commit 1aa03f07450da091b440b1f14937aa44bab4e428 Author: Adam Langley <agl@google.com> Date: Fri May 20 08:22:33 2016 -0700 Add |EVP_dss1| as an alias for |EVP_sha1| in decrepit. Change-Id: I51fa744c367d1f0c7044050f99c4992778e649bd Reviewed-on: https://boringssl-review.googlesource.com/8030 Reviewed-by: David Benjamin <davidben@google.com> commit 7cb920b6acbbddf281d9eb77ef785ec63fde3843 Author: Adam Langley <agl@google.com> Date: Fri May 20 08:28:56 2016 -0700 Include crypto.h from pem.h. open_iscsi assumes that it can get |OPENSSL_malloc| after including only pem.h and err.h. Since pem.h already includes quite a lot, this change adds crypto.h to that set so that open_iscsi is happy. Change-Id: I6dc06c27088ce3ca46c1ab53bb29650033cba267 Reviewed-on: https://boringssl-review.googlesource.com/8031 Reviewed-by: David Benjamin <davidben@google.com> commit 3686584d16dc5141dfab8510b116527c463d4b56 Author: Steven Valdez <svaldez@google.com> Date: Thu May 19 12:26:42 2016 -0400 Separating HKDF into HKDFExtract and HKDFExpand. The key schedule in TLS 1.3 requires a separate Extract and Expand phase for the cryptographic computations. Change-Id: Ifdac1237bda5212de5d4f7e8db54e202151d45ec Reviewed-on: https://boringssl-review.googlesource.com/7983 Reviewed-by: David Benjamin <davidben@google.com> commit e25775bcacb120f7f501a61d78a622ba429ba5d9 Author: Matt Braithwaite <mab@google.com> Date: Mon May 16 16:31:05 2016 -0700 Elliptic curve + post-quantum key exchange CECPQ1 is a new key exchange that concatenates the results of an X25519 key agreement and a NEWHOPE key agreement. Change-Id: Ib919bdc2e1f30f28bf80c4c18f6558017ea386bb Reviewed-on: https://boringssl-review.googlesource.com/7962 Reviewed-by: David Benjamin <davidben@google.com> commit 61d4cdc03dd7e6920d74070a8d10a6db58c044db Author: David Benjamin <davidben@google.com> Date: Thu May 19 17:55:36 2016 -0400 No-op change to kick the bots. Let's see if the Android bots work! Change-Id: Ic4a52edcb441c26bc87d776984466e04cff93ae3 commit f0322b2abce91458f62db44dc6b777fc5e0323d9 Author: nmittler <nathanmittler@google.com> Date: Thu May 19 08:49:59 2016 -0700 Use non-deprecated methods on windows. Use of strdup, close, lseek, read, and write prevent linking statically againt libcmt.lib. Change-Id: I04f7876ec0f03f29f000bbcc6b2ccdec844452d2 Reviewed-on: https://boringssl-review.googlesource.com/8010 Reviewed-by: David Benjamin <davidben@google.com> commit e09e579603bf7d05b5160bb9bd53eacea6cff47d Author: Matt Braithwaite <mab@google.com> Date: Thu May 19 10:30:52 2016 -0700 Rename NEWHOPE functions to offer/accept/finish. This is consistent with the new convention in ssl_ecdh.c. Along the way, change newhope_test.c to not iterate 1000 times over each test. Change-Id: I7a500f45b838eba8f6df96957891aa8e880ba089 Reviewed-on: https://boringssl-review.googlesource.com/8012 Reviewed-by: David Benjamin <davidben@google.com> commit 1147be052c4e8b8a9b9ed1057e786eba5d58ba56 Author: David Benjamin <davidben@google.com> Date: Thu May 19 13:23:11 2016 -0400 Inherit the parent environment when shelling out to Go. The recipes need to run with a funny GOROOT and we were clearing the environment. BUG=26 Change-Id: If233a16e060533ad3fa6f215ce596456c2d7afa5 Reviewed-on: https://boringssl-review.googlesource.com/7988 Reviewed-by: Adam Langley <agl@google.com> commit 3ccf4d6d652fb26b9fb2f0db519d68050d7867d7 Author: David Benjamin <davidben@google.com> Date: Thu May 19 00:33:41 2016 -0400 Pull Chromium's android_tools as an android-only dependency. This will be used by the bots to get adb and the NDK. BUG=26 Change-Id: Iae07a380c49b4990f0aa7d73c4f0b399924b9784 Reviewed-on: https://boringssl-review.googlesource.com/7986 Reviewed-by: Adam Langley <agl@google.com> commit 75021b747f2d1547553ee4f9c14e4be350c198c6 Author: David Benjamin <davidben@google.com> Date: Thu Apr 28 14:51:36 2016 -0400 Update Android build instructions. We now have a copy of android-cmake. Also remove the mention of running cmake twice. It seems to work fine once? The API level also got specified twice somehow. BUG=26 Change-Id: I1331b079a4d8531cd53f7de3605ac318c14b3e26 Reviewed-on: https://boringssl-review.googlesource.com/7985 Reviewed-by: Adam Langley <agl@google.com> commit f07ba17942eaffe52763ff75487acab5d2f2d5c1 Author: David Benjamin <davidben@google.com> Date: Thu Apr 28 14:38:20 2016 -0400 Check in a copy of android-cmake. BUG=26 Change-Id: I2f95740afdbc3bdb0676626679a30f1e1cc307d6 Reviewed-on: https://boringssl-review.googlesource.com/7984 Reviewed-by: Adam Langley <agl@google.com> commit 00b1069a6b22d8ea0dc6c682b5edb39297e62398 Author: David Benjamin <davidben@google.com> Date: Thu May 19 00:13:22 2016 -0400 Add an option to pick a different adb binary. This will let the recipes use the copy pulled from Chromium's android_tools. BUG=26 Change-Id: Ica6519223b9fb6daef30f3e14c72ef6422de0f6c Reviewed-on: https://boringssl-review.googlesource.com/7982 Reviewed-by: Adam Langley <agl@google.com> commit 5693e42ae4f8e9beb712fd0c551cc4109639e85f Author: Tamas Berghammer <tberghammer@google.com> Date: Thu May 19 14:28:14 2016 +0100 Fix discovery rule for perl and go for Android We don't use find_package/find_program on android to find go/perl because the android toolchain reconfigure the $PATH. The pervious way of solving this was to let ninja look for go/perl on the $PATH but this approach prevented us from specifying explicit go/perl executables what is needed for hermetic build using prebuilts. This CL changes the Android specific discovery rule to only set GO_EXECUTABLE and PERL_EXECUTABLE if they are not specified on the command line or inside the toolchain file. Change-Id: Ib6ef69707749073f2b79244ebb301502b2a5a34a Reviewed-on: https://boringssl-review.googlesource.com/8000 Reviewed-by: David Benjamin <davidben@google.com> commit ea77107e9ad507708b592b64a1fb406115d9abcf Author: David Benjamin <davidben@google.com> Date: Wed May 18 17:40:04 2016 -0400 Remove references to non-existent BIO functions. We don't have any of these. Change-Id: I8d12284fbbab0ff35ac32d35a5f2eba326ab79f8 Reviewed-on: https://boringssl-review.googlesource.com/7981 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit c82b70155d9139e56190c004b257c4882ee7ea15 Author: Matt Braithwaite <mab@google.com> Date: Tue May 17 13:06:03 2016 -0700 Go version of New Hope post-quantum key exchange. (Code mostly due to agl.) Change-Id: Iec77396141954e5f8e845cc261eadab77f551f08 Reviewed-on: https://boringssl-review.googlesource.com/7990 Reviewed-by: Adam Langley <agl@google.com> commit 54092ffeaa80ed032a50b914f14e3aa41de763df Author: David Benjamin <davidben@google.com> Date: Tue May 10 18:09:40 2016 -0400 Remove dead checks. Those checks contradict an assert up in read_app_data. This is part of shrinking read_bytes further into get_record and its callers until it goes away. Here, this kind of policy should be controlled by the callers. Change-Id: If8f9a45b8b95093beab1b3d4abcd31da55c65322 Reviewed-on: https://boringssl-review.googlesource.com/7954 Reviewed-by: Adam Langley <agl@google.com> commit fce37b0debf158b5d09f8d6a2fc09c6f680d2f32 Author: David Benjamin <davidben@google.com> Date: Sun May 15 13:51:35 2016 -0400 Add a TODO for why init_buf isn't released post-handshake. There is no good reason why this needs to be this way. Later work should make this all use a much more appropriate design. In the meantime, leave a note here so this does not look accidental. Change-Id: I7599dea7a474f54e26d9ab175b0e3cada99a974d Reviewed-on: https://boringssl-review.googlesource.com/7951 Reviewed-by: Adam Langley <agl@google.com> commit 1d64afda449ff63b8bd99172ed58549c8099ca81 Author: David Benjamin <davidben@google.com> Date: Sun May 15 13:46:07 2016 -0400 Stop reseting init_num everywhere in the handshake loop. This was needed because ssl3_get_message would get confused if init_num were not set back to zero when reading the next message. However, ssl3_get_message now treats init_num only as an output, not an input. (The message sending logic and the individual handshake states still use it, so we can't get rid of it altogether yet.) I've kept the init_num reset at the start and end of the handshake loop alone for now since that's more about initialization and cleanup. Though I believe they too do not do anything. Change-Id: I64bbdd82122498de32364e7edb3b00b166059ecd Reviewed-on: https://boringssl-review.googlesource.com/7950 Reviewed-by: Adam Langley <agl@google.com> commit 1e6d6df943a681eb8454cf40b9cd554519156e16 Author: David Benjamin <davidben@google.com> Date: Fri May 13 18:28:17 2016 -0400 Remove state parameters to ssl3_get_message. They're completely unused now. The handshake message reassembly logic should not depend on the state machine. This should partially free it up (ugly as it is) to be shared with a future TLS 1.3 implementation while, in parallel, it and the layers below, get reworked. This also cuts down on the number of states significantly. Partially because I expect we'd want to get ssl_hash_message_t out of there too. Having it in common code is fine, but it needs to be in the (supposed to be) protocol-agnostic handshake state machine, not the protocol-specific handshake message layer. Change-Id: I12f9dc57bf433ceead0591106ab165d352ef6ee4 Reviewed-on: https://boringssl-review.googlesource.com/7949 Reviewed-by: Adam Langley <agl@google.com> commit a6338be3fa1a08f53d6d5f80aa4f26629fd047ab Author: David Benjamin <davidben@google.com> Date: Fri May 13 18:12:19 2016 -0400 Simplify ssl3_get_message. Rather than this confusing coordination with the handshake state machine and init_num changing meaning partway through, use the length field already in BUF_MEM. Like the new record layer parsing, is no need to keep track of whether we are reading the header or the body. Simply keep extending the handshake message until it's far enough along. ssl3_get_message still needs tons of work, but this allows us to disentangle it from the handshake state. Change-Id: Ic2b3e7cfe6152a7e28a04980317d3c7c396d9b08 Reviewed-on: https://boringssl-review.googlesource.com/7948 Reviewed-by: Adam Langley <agl@google.com> commit 1f9329aaf55f9beb7c95550f5f1fffc395a5f859 Author: David Benjamin <davidben@google.com> Date: Fri May 13 17:00:49 2016 -0400 Add BUF_MEM_reserve. BUF_MEM is actually a rather silly API for the SSL stack. There's separate length and max fields, but init_buf effectively treats length as max and max as nothing. We possibly don't want to be using it long-term anyway (if nothing else, the char*/uint8_t* thing is irritating), but in the meantime, it'll be easier to separately fix up get_message's book-keeping and state tracking from where the handshake gets its messages from. Change-Id: I9e56ea008173991edc8312ec707505ead410a9ee Reviewed-on: https://boringssl-review.googlesource.com/7947 Reviewed-by: Adam Langley <agl@google.com> commit 4d559617cd9c0fe5c047bad610be9f6ebbbb19c9 Author: David Benjamin <davidben@google.com> Date: Wed May 18 14:31:51 2016 -0400 Unflake Unclean-Shutdown-Alert on Windows. On Windows, if we write to our socket and then close it, the peer sometimes doesn't get all the data. This was working for our shimShutsDown tests because we send close_notify in parallel with the peer and sendAlert(alertCloseNotify) did not internally return an error. For convenience, sendAlert returns a local error for non-close_notify alerts. Suppress that error to avoid the race condition. This makes it behave like the other shimShutsDown tests. Change-Id: Iad256e3ea5223285793991e2eba9c7d61f2e3ddf Reviewed-on: https://boringssl-review.googlesource.com/7980 Reviewed-by: Adam Langley <agl@google.com> commit f4ce8e532476a26ba18459cbd3622f50258969fe Author: Matt Braithwaite <mab@google.com> Date: Mon May 16 14:27:14 2016 -0700 Refactor ECDH key exchange to make it asymmetrical Previously, SSL_ECDH_METHOD consisted of two methods: one to produce a public key to be sent to the peer, and another to produce the shared key upon receipt of the peer's message. This API does not work for NEWHOPE, because the client-to-server message cannot be produced until the server's message has been received by the client. Solve this by introducing a new method which consumes data from the server key exchange message and produces data for the client key exchange message. Change-Id: I1ed5a2bf198ca2d2ddb6d577888c1fa2008ef99a Reviewed-on: https://boringssl-review.googlesource.com/7961 Reviewed-by: David Benjamin <davidben@google.com> commit 68a533c0ef70596032e724fa6762f816e20c17dd Author: David Benjamin <davidben@google.com> Date: Tue May 17 17:36:47 2016 -0400 Fix line-number counting in doc.go. There's an off-by-one when skipping blank lines. The initial logic also has an off-by-one but since it starts lineNo 0-based and then switches to 1-based, it cancels out. The decl error line number also was not of where the decl began. Change-Id: I58fd157dad3276cb9de52ac48ff8c7c73e40f337 Reviewed-on: https://boringssl-review.googlesource.com/7959 Reviewed-by: Adam Langley <agl@google.com> commit 7f6706ce64bff23d29cdf8e1fb48e8c56f464050 Author: David Benjamin <davidben@google.com> Date: Tue May 17 17:49:49 2016 -0400 MSVC doesn't like C bitfields. Change-Id: I88a415e3dd7ac9ea2fa83ca3e4d835efefa7fcc6 Reviewed-on: https://boringssl-review.googlesource.com/7970 Reviewed-by: David Benjamin <davidben@google.com> commit 47f5a1feca50e3e524ff91528e629f8d16e19309 Author: David Benjamin <davidben@google.com> Date: Tue May 17 17:31:53 2016 -0400 Allow documentation comments to begin with A/An. This aligns with Go style. Change-Id: I773c6a2e8ddd8d40a8480efae86736c4b338d203 Reviewed-on: https://boringssl-review.googlesource.com/7958 Reviewed-by: Adam Langley <agl@google.com> commit c7eae5a3267dfc9557314a24cc8da77d287ae885 Author: David Benjamin <davidben@google.com> Date: Tue May 10 18:00:03 2016 -0400 Forbid calling SSL_read, SSL_peek, and SSL_do_handshake post-shutdown. This explicitly forbids an API pattern which formerly kind of worked, but was extremely buggy (see preceding commits). Depending on how one interprets close_notify and our API, one might wish to call SSL_shutdown only once (morally shutdown(SHUT_WR)) and then SSL_read until EOF. However, this exposes additional confusing states where we might try to send an alert post-SHUT_WR, etc. Early commits made us more robust here (whether one is allowed to touch the SSL* after an operattion failed because it read an alert is... unclear), so we could support it if we wanted to, but this doesn't seem worth the additional statespace. See if we can get away with not allowing it. Change-Id: Ie7a7e5520b464360b1e6316c34ec9854b571782f Reviewed-on: https://boringssl-review.googlesource.com/7433 Reviewed-by: David Benjamin <davidben@google.com> commit ea65e100c7b5dc5cb44bd68fae64e67d19bde8f2 Author: David Benjamin <davidben@google.com> Date: Tue May 10 17:57:32 2016 -0400 Condition the read_close_notify check on type, not shutdown state. The logic to drop records really should be in the caller. Unless ssl3_read_bytes is broken apart, condition on the type field which is more robust. If we manage to call, say, SSL_read after SSL_shutdown completes at 0 (instead of 1), this logic can incorrectly cause unknown record types to be dropped. Change-Id: Iab90e5d9190fcccbf6ff55e17079a2704ed99901 Reviewed-on: https://boringssl-review.googlesource.com/7953 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit fa214e4a18785a4281375b56c00732b470e9cd5b Author: David Benjamin <davidben@google.com> Date: Tue May 10 17:03:10 2016 -0400 Tidy up shutdown state. The existing logic gets confused in a number of cases around close_notify vs. fatal alert. SSL_shutdown, while still pushing to the error queue, will fail to notice alerts. We also get confused if we try to send a fatal alert when we've already sent something else. Change-Id: I9b1d217fbf1ee8a9c59efbebba60165b7de9689e Reviewed-on: https://boringssl-review.googlesource.com/7952 Reviewed-by: David Benjamin <davidben@google.com> commit 8f73135485f376f0a08c8d54c0c0e12a5fb9a7d7 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 01:15:15 2016 -0500 Consolidate SSL_RECEIVED_SHUTDOWN checks. SSL_RECEIVED_SHUTDOWN checks in the record layer happen in two different places. Some operations (but not all) check it, and so does read_bytes. Move it to get_record. This check should be at a low-level since it is otherwise duplicated in every operation. It is also a signal which originates from around the peer's record layer, so it makes sense to check it near the same code. (This one's in get_record which is technically lower-level than read_bytes, but we're trying to get rid of read_bytes. They're very coupled functions.) Also, if we've seen a fatal alert, replay an error, not an EOF. Change-Id: Idec35c5068ddabe5b1a9145016d8f945da2421cf Reviewed-on: https://boringssl-review.googlesource.com/7436 Reviewed-by: David Benjamin <davidben@google.com> commit f448c609035d5afb83d5de4c2b3f619f793cd832 Author: Adam Langley <agl@google.com> Date: Tue May 17 12:33:27 2016 -0700 Update INCORPORATING.md to clarify one point. In practice it seems that it's not clear that consumers of BoringSSL generally check in the generated files. Change-Id: Iaa03aa62139bbcf3e7e7f68662073854954b835f Reviewed-on: https://boringssl-review.googlesource.com/7956 Reviewed-by: David Benjamin <davidben@google.com> commit 4fac8d0eae6eaddb45f2eef7fbe978894b96b8dd Author: Adam Langley <agl@google.com> Date: Mon May 16 13:44:40 2016 -0700 Add CRYPTO_has_asm. This function will return whether BoringSSL was built with OPENSSL_NO_ASM. This will allow us to write a test in our internal codebase which asserts that normal builds should always have assembly code included. Change-Id: Ib226bf63199022f0039d590edd50c0cc823927b9 Reviewed-on: https://boringssl-review.googlesource.com/7960 Reviewed-by: David Benjamin <davidben@google.com> commit c032dfa27ec8a9f286e3ae7e545932aac13b87d6 Author: David Benjamin <davidben@google.com> Date: Thu May 12 14:54:57 2016 -0400 Client auth is only legal in certificate-based ciphers. OpenSSL used to only forbid it on the server in plain PSK and allow it on the client. Enforce it properly on both sides. My read of the rule in RFC 5246 ("A non-anonymous server can optionally request a certificate") and in RFC 4279 ("The Certificate and CertificateRequest payloads are omitted from the response.") is that client auth happens iff we're certificate-based. The line in RFC 4279 is under the plain PSK section, but that doesn't make a whole lot of sense and there is only one diagram. PSK already authenticates both sides. I think the most plausible interpretation is that this is for certificate-based ciphers. Change-Id: If195232c83f21e011e25318178bb45186de707e6 Reviewed-on: https://boringssl-review.googlesource.com/7942 Reviewed-by: David Benjamin <davidben@google.com> commit 060cfb091194edf7341d91009764c64096a87157 Author: David Benjamin <davidben@google.com> Date: Thu May 12 00:43:05 2016 -0400 Simplify handshake message size limits. A handshake message can go up to 2^24 bytes = 16MB which is a little large for the peer to force us to buffer. Accordingly, we bound the size of a handshake message. Rather than have a global limit, the existing logic uses a different limit at each state in the handshake state machine and, for certificates, allows configuring the maximum certificate size. This is nice in that we engage larger limits iff the relevant state is reachable from the handshake. Servers without client auth get a tighter limit "for free". However, this doesn't work for DTLS due to out-of-order messages and we use a simpler scheme for DTLS. This scheme also is tricky on optional messages and makes the handshake <-> message layer communication complex. Apart from an ignored 20,000 byte limit on ServerHello, the largest non-certificate limit is the common 16k limit on ClientHello. So this complexity wasn't buying us anything. Unify everything on the DTLS scheme except, so as not to regress bounds on client-auth-less servers, also correctly check for whether client auth is configured. The value of 16k was chosen based on this value. (The 20,000 byte ServerHello limit makes no sense. We can easily bound the ServerHello because servers may not send extensions we don't implement. But it gets overshadowed by the certificate anyway.) Change-Id: I00309b16d809a3c2a1543f99fd29c4163e3add81 Reviewed-on: https://boringssl-review.googlesource.com/7941 Reviewed-by: David Benjamin <davidben@google.com> commit 4e7a1ff055b987c9f900a2279380290cb8d9e939 Author: Brian Smith <brian@briansmith.org> Date: Thu Apr 21 17:10:09 2016 -1000 Remove unuseful comments in |BN_mod_exp|. The performance measurements seem to be very out-of-date. Also, the idea for optimizing the case of an even modulus is interesting, but it isn't useful because we never use an even modulus. Change-Id: I012eb37638cda3c63db0e390c8c728f65b949e54 Reviewed-on: https://boringssl-review.googlesource.com/7733 Reviewed-by: David Benjamin <davidben@google.com> commit 448fa427795c5e8a447b18a05600ad19961acf94 Author: Brian Smith <brian@briansmith.org> Date: Thu Apr 21 17:08:29 2016 -1000 Deprecate |BN_mod_exp2_mont| and simplify its implementation. This function is only really useful for DSA signature verification, which is something that isn't performance-sensitive. Replace its optimized implementation with a naïve implementation that's much simpler. Note that it would be simpler to use |BN_mod_mul| in the new implementation; |BN_mod_mul_montgomery| is used instead only to be consistent with other work being done to replace uses of non-Montgomery modular reduction with Montgomery modular reduction. Change-Id: If587d463b73dd997acfc5b7ada955398c99cc342 Reviewed-on: https://boringssl-review.googlesource.com/7732 Reviewed-by: David Benjamin <davidben@google.com> commit ada97998f270ad45d46a986723852db0af54736f Author: David Benjamin <davidben@google.com> Date: Fri May 13 13:14:28 2016 -0400 Fix stack macro const-ness. sk_FOO_num may be called on const stacks. Given that was wrong, I suspect no one ever uses a const STACK_OF(T)... Other macros were correctly const, but were casting the constness a way (only to have it come back again). Also remove the extra newline after a group. It seems depending on which version of clang-format was being used, we'd either lose or keep the extra newline. The current file doesn't have them, so settle on that. Change-Id: I19de6bc85b0a043d39c05ee3490321e9f0adec60 Reviewed-on: https://boringssl-review.googlesource.com/7946 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit c6cc6e76a6919769977046df6a72a5bd8a171cef Author: David Benjamin <davidben@google.com> Date: Tue May 10 17:19:00 2016 -0400 Make kSRTPProfiles static. It's only used in one file. Change-Id: I5d60cbc02799b22317f5f7593faf25eb8eea0a24 Reviewed-on: https://boringssl-review.googlesource.com/7943 Reviewed-by: David Benjamin <davidben@google.com> commit ef2dc61edd4f5bedcefd88703c4eb5786f01a0a1 Author: David Benjamin <davidben@google.com> Date: Tue May 10 16:08:57 2016 -0400 Remove invalid comment for alert_dispatch. The array is of size two for the level and description, not because we allow two alerts outstanding; we don't. Change-Id: I25e42c059ce977a947397a3dc83e9684bc8f0595 Reviewed-on: https://boringssl-review.googlesource.com/7940 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 8de8b3d23ced19c9e1fadfd31a9ada172909ca2a Author: David Benjamin <davidben@google.com> Date: Thu May 12 23:07:47 2016 -0400 Revise run_android_tests.go for use in recipes. Allow running only one of the test suites. The recipe expects these happen in two separate steps (it wants only one JSON results file per "step"). Also add an option to extract the results file. BUG=26 Change-Id: I0cda19bd9643b66f40a30bc8410a357da33baacc Reviewed-on: https://boringssl-review.googlesource.com/7945 Reviewed-by: Adam Langley <agl@google.com> commit 641f42b1a2c54f5eb2512a6d970b7b783eac7688 Author: David Benjamin <davidben@google.com> Date: Thu May 12 23:05:57 2016 -0400 Make i2d_X509_AUX work if *pp = NULL. When *pp is NULL, don't write garbage, return an unexpected pointer or leak memory on error. (Imported from upstream's 36c37944909496a123e2656ad1f651769a7cc72f.) This calling convention... Change-Id: Ic733092cfb942a3e1d3ceda6797222901ad55bef Reviewed-on: https://boringssl-review.googlesource.com/7944 Reviewed-by: Adam Langley <agl@google.com> commit 80d1b35520127a83cde953249c4533360c27a5df Author: David Benjamin <davidben@google.com> Date: Wed May 4 19:19:06 2016 -0400 Add a test for SCTs sent on resume. The specification, sadly, did not say that servers MUST NOT send it, only that they are "not expected to" do anything with the client extension. Accordingly, we decided to tolerate this. Add a test for this so that we check this behavior. This test also ensures that the original session's value for it carries over. Change-Id: I38c738f218a09367c9d8d1b0c4d68ab5cbec730e Reviewed-on: https://boringssl-review.googlesource.com/7860 Reviewed-by: Adam Langley <agl@google.com> commit e31d103a0ae334d0dc1de348e8177ae984d169f0 Author: Brian Smith <brian@briansmith.org> Date: Thu Apr 21 17:08:13 2016 -1000 Deprecate |BN_mod_exp_mont_word| and simplify its implementation. |BN_mod_exp_mont_word| is only useful when the base is a single word in length and timing side channel protection of the exponent is not needed. That's never the case in real life. Keep the function in the API, but removes its single-word-base optimized implementation with a call to |BN_mod_exp_mont|. Change-Id: Ic25f6d4f187210b681c6ee6b87038b64a5744958 Reviewed-on: https://boringssl-review.googlesource.com/7731 Reviewed-by: David Benjamin <davidben@google.com> commit 376a0fed24cad21752357add314f3c43e39c3bcc Author: Taylor Brandstetter <deadbeef@google.com> Date: Tue May 10 19:30:28 2016 -0700 Adding a method to change the initial DTLS retransmission timer value. This allows an application to override the default of 1 second, which is what's instructed in RFC 6347 but is not an absolute requirement. Change-Id: I0bbb16e31990fbcab44a29325b6ec7757d5789e5 Reviewed-on: https://boringssl-review.googlesource.com/7930 Reviewed-by: David Benjamin <davidben@google.com> commit 0e01eb534c25ccd5ce59917cd5ef37c059a94ebb Author: Brian Smith <brian@briansmith.org> Date: Thu Apr 21 16:30:37 2016 -1000 Call |BN_mod_exp_mont_consttime| in crypto/dh. |BN_mod_exp_mont| will forward to |BN_mod_exp_mont_consttime|, so this is a no-op semantically. However, this allows the linker to drop the implementation of |BN_mod_exp_mont| even when the DH code is in use. Change-Id: I0cb8b260224ed661ede74923bd134acb164459c1 Reviewed-on: https://boringssl-review.googlesource.com/7730 Reviewed-by: David Benjamin <davidben@google.com> commit d229433d7537dae5723a168c64ed8c70719d3f24 Author: David Benjamin <davidben@google.com> Date: Mon May 9 13:27:01 2016 -0400 Free any existing SRTP connection profile. When setting a new SRTP connection profile using SSL_CTX_set_tlsext_use_srtp() or SSL_set_tlsext_use_srtp() we should free any existing profile first to avoid a memory leak. (Imported from upstream's fbdf0299dc98bc611d854c0a62c6ab1810d856fc.) Change-Id: I738e711f1c23ed4a8ac97486d94c08cc0db7aea7 Reviewed-on: https://boringssl-review.googlesource.com/7910 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 347331541536b616bf5147d6f8093a1541b77da7 Author: David Benjamin <davidben@google.com> Date: Sat May 7 17:40:02 2016 -0400 Reimplement PKCS #3 DH parameter parsing with crypto/bytestring. Also add a test. This is the last of the openssl/asn1.h includes from the directories that are to be kept in the core libcrypto library. (What remains is to finish sorting out the crypto/obj stuff. We'll also want to retain a decoupled version of the PKCS#12 stuff.) Functions that need to be audited for reuse: i2d_DHparams BUG=54 Change-Id: Ibef030a98d3a93ae26e8e56869f14858ec75601b Reviewed-on: https://boringssl-review.googlesource.com/7900 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit e72df93461c6d9d2b5698f10e16d3ab82f5adde3 Author: David Benjamin <davidben@google.com> Date: Fri May 6 02:12:26 2016 -0400 Add a README.md for ssl/test. The SSL tests are fairly different from most test suites. Add some high-level documentation so people know where to start. Change-Id: Ie5ea108883dca82675571a3025b3fbc4b9d66da9 Reviewed-on: https://boringssl-review.googlesource.com/7890 Reviewed-by: Adam Langley <agl@google.com> commit e9a36421266fccc28506b1b0d2f8b0bd9b7f04f7 Author: David Benjamin <davidben@google.com> Date: Thu May 5 21:53:00 2016 -0400 Don't reset ssl->shutdown in the state machine. This is particularly questionable with ClientHello encompassing several states. ssl->shutdown is already initialized to zero and further reset in SSL_set_{connect,accept}_state. At any other state, if it manages to not be a no-op, it will erase a close_notify we have sent or received, neither of which is okay. (I don't think this is possible, but I'm not positive.) This dates to the initial commit in OpenSSL, so git is not enlightening. The state machine logic historically reset many fields it had no reason to reset, so this is likely more of that. Change-Id: Ie872316701720cb8ef2cfcb67b7f07a9fea3620f Reviewed-on: https://boringssl-review.googlesource.com/7874 Reviewed-by: Adam Langley <agl@google.com> commit b095f0f0ca4ef08de8c5b48045e20206d55173bf Author: David Benjamin <davidben@google.com> Date: Thu May 5 21:50:24 2016 -0400 Remove the push argument to ssl_init_wbio_buffer. Having bbio be tri-state (not allocated, allocated but not active, and allocated and active) is confusing. The extra state is only used in the client handshake, where ClientHello is special-cased to not go through the buffer while everything else is. This dates to OpenSSL's initial commit and doesn't seem to do much. I do not believe it can affect renego as the buffer only affects writes; although OpenSSL accepted interleave on read (though this logic predates it slightly), it never sent application data while it believed a handshake was active. The handshake would always be driven to completion first. My guess is this was to save a copy since the ClientHello is a one-message flight so it wouldn't need to be buffered? This is probably not worth the extra variation in the state. (Especially with the DTLS state machine going through ClientHello twice and pushing the BIO in between the two. Though I suspect that was a mistake in itself. If the optimization guess is correct, there was no need to do that.) Change-Id: I6726f866e16ee7213cab0c3e6abb133981444d47 Reviewed-on: https://boringssl-review.googlesource.com/7873 Reviewed-by: Adam Langley <agl@google.com> commit 2730955e7449989bb982092d3301f89340dbc189 Author: David Benjamin <davidben@google.com> Date: Thu May 5 21:17:53 2016 -0400 Check BIO_flush return value. That we're ignoring the return value is clearly wrong when dtls1_retransmit_message has other code that doesn't ignore it, by way of dtls1_do_handshake_write. Change-Id: Ie3f8c0defdf1f5e709d67af4ca6fa4f0d83c76c9 Reviewed-on: https://boringssl-review.googlesource.com/7872 Reviewed-by: Adam Langley <agl@google.com> commit 30152fdfc116d9ef328661b59a306d6b591243af Author: David Benjamin <davidben@google.com> Date: Thu May 5 20:45:48 2016 -0400 Always buffer DTLS retransmits. The DTLS bbio logic is rather problematic, but this shouldn't make things worse. In the in-handshake case, the new code merges the per-message (unchecked) BIO_flush calls into one call at the end but otherwise the BIO is treated as is. Otherwise any behavior around non-block writes should be preserved. In the post-handshake case, we now install the buffer when we didn't previously. On write error, the buffer will have garbage in it, but it will be discarded, so that will preserve any existing retry behavior. (Arguably the existing retry behavior is a bug, but that's another matter.) Add a test for all this, otherwise it is sure to regress. Testing for record-packing is a little fuzzy, but we can assert ChangeCipherSpec always shares a record with something. BUG=57 Change-Id: I8603f20811d502c71ded2943b0e72a8bdc4e46f2 Reviewed-on: https://boringssl-review.googlesource.com/7871 Reviewed-by: Adam Langley <agl@google.com> commit 9d908ba519f2cfe5e21561bdee3e224b94d14a89 Author: David Benjamin <davidben@google.com> Date: Thu May 5 18:54:33 2016 -0400 Add BORINGSSL_API_VERSION. The BORINGSSL_YYYYMM #defines have served well to coordinate short-term skews in BoringSSL's public API, but some consumers (notably wpa_supplicant in Android) wish to build against multiple versions for an extended period of time. Consumers should not do this unless there is no alternative, but to accommodate this, start a BORINGSSL_API_VERSION counter. In future, instead of BORINGSSL_YYYYMM #defines, we'll simply increment the number. This is specifically called an "API version" rather than a plain "version" as this number does not denote any particular point in development or stability. It purely counts how many times we found it convenient to let the preprocessor observe a public API change up to now. Change-Id: I39f9740ae8e793cef4c2b5fb5707b9763b3e55ce Reviewed-on: https://boringssl-review.googlesource.com/7870 Reviewed-by: Adam Langley <agl@google.com> commit 598e55a795fa206571f94a7cb2e5834728b85c98 Author: Brian Smith <brian@briansmith.org> Date: Sat Mar 26 20:17:37 2016 -1000 Do RSA blinding unless |e| is NULL and specifically requested not to. Change-Id: I189db990df2a3cbf68f820a8f9f16142ccd7070f Reviewed-on: https://boringssl-review.googlesource.com/7595 Reviewed-by: David Benjamin <davidben@google.com> commit 86080c336fc9a71d600abc67ba3185390e005061 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 12:23:16 2016 -1000 Verify RSA private key operation regardless of whether CRT is used. Previously, the verification was only done when using the CRT method, as the CRT method has been shown to be extremely sensitive to fault attacks. However, there's no reason to avoid doing the verification when the non-CRT method is used (performance-sensitive applications should always be using the CRT-capable keys). Previously, when we detected a fault (attack) through this verification, libcrypto would fall back to the non-CRT method and assume that the non-CRT method would give a correct result, despite having just detecting corruption that is likely from an attack. Instead, just give up, like NSS does. Previously, the code tried to handle the case where the input was not reduced mod rsa->n. This is (was) not possible, so avoid trying to handle that. This simplifies the equality check and lets us use |CRYPTO_memcmp|. Change-Id: I78d1e55520a1c8c280cae2b7256e12ff6290507d Reviewed-on: https://boringssl-review.googlesource.com/7582 Reviewed-by: David Benjamin <davidben@google.com> commit 8107e92a1aa71cee717450c25dace2a32233a917 Author: Adam Langley <agl@google.com> Date: Wed May 4 10:32:37 2016 -0700 Add a comment with an SMT verification of the Barrett reductions. Change-Id: I32dc13b16733fc09e53e3891ca68f51df6c1624c Reviewed-on: https://boringssl-review.googlesource.com/7850 Reviewed-by: David Benjamin <davidben@google.com> commit f0bba6166356a4dac6c1cef7a693c96cb1e3f567 Author: David Benjamin <davidben@google.com> Date: Tue May 3 11:35:23 2016 -0400 Fix ASN1_INTEGER handling. Only treat an ASN1_ANY type as an integer if it has the V_ASN1_INTEGER tag: V_ASN1_NEG_INTEGER is an internal only value which is never used for on the wire encoding. (Imported from upstream's d4b25980020821d4685752ecb9105c0902109ab5.) This is redundant with our fb2c6f8c8565e1e2d85c24408050c96521acbcdc which I think is a much better fix (having two notions of "type" depending on whether we're in an ASN1_TYPE or an ASN1_STRING is fragile), so I think we should keep our restriction too. Still, this is also worth doing. Change-Id: I6ea54aae7b517a59c6e563d8c993d0ee22e25bee Reviewed-on: https://boringssl-review.googlesource.com/7848 Reviewed-by: Adam Langley <agl@google.com> commit de2cf273d76e94ee47cb4ed7e9826f68175ec217 Author: David Benjamin <davidben@google.com> Date: Tue May 3 09:19:36 2016 -0400 Avoid theoretical overflows in EVP_EncodeUpdate. See also upstream's 172c6e1e14defe7d49d62f5fc9ea6a79b225424f, but note our values have different types. In particular, because we put in_len in a size_t and C implicitly requires that all valid buffers' lengths fit in a ptrdiff_t (signed), the overflow was impossible, assuming EVP_ENCODE_CTX::length is untouched externally. More importantly, this function is stuck taking an int output and has no return value, so the only plausible contract is the caller is responsible for ensuring the length fits anyway. Indeed, callers all call EVP_EncodeUpdate in bounded chunks, so upstream's analysis is off. Anyway, in theory that logic could locally overflow, so tweak it slightly. Tidy up some of the variable names while I'm here. Change-Id: Ifa78707cc26c11e0d67019918a028531b3d6738c Reviewed-on: https://boringssl-review.googlesource.com/7847 Reviewed-by: Adam Langley <agl@google.com> commit e31e0123ea331f640852dac55c072b4cec3e3ff8 Author: David Benjamin <davidben@google.com> Date: Tue May 3 07:55:29 2016 -0400 Add size limit to X509_NAME structure. This adds an explicit limit to the size of an X509_NAME structure. Some part of OpenSSL (e.g. TLS) already effectively limit the size due to restrictions on certificate size. See also upstream's 65cb92f4da37a3895437f0c9940ee0bcf9f28c8a, although this is different from upstream's. Upstream's version bounds both the X509_NAME *and* any data after it in the immediately containing structure. While adding a bound on all of crypto/asn1 is almost certainly a good idea (will look into that for a follow-up), it seems bizarre and unnecessary to have X509_NAME affect its parent. Change-Id: Ica2136bcd1455d7c501ccc6ef2a19bc5ed042501 Reviewed-on: https://boringssl-review.googlesource.com/7846 Reviewed-by: Adam Langley <agl@google.com> commit 204dea8daeee9935b2b08da2c2dfe7b890ed36a7 Author: David Benjamin <davidben@google.com> Date: Tue May 3 07:42:19 2016 -0400 Fix encrypt overflow An overflow can occur in the EVP_EncryptUpdate function. If an attacker is able to supply very large amounts of input data after a previous call to EVP_EncryptUpdate with a partial block then a length check can overflow resulting in a heap corruption. Following an analysis of all OpenSSL internal usage of the EVP_EncryptUpdate function all usage is one of two forms. The first form is like this: EVP_EncryptInit() EVP_EncryptUpdate() i.e. where the EVP_EncryptUpdate() call is known to be the first called function after an EVP_EncryptInit(), and therefore that specific call must be safe. The second form is where the length passed to EVP_EncryptUpdate() can be seen from the code to be some small value and therefore there is no possibility of an overflow. [BoringSSL: We also have code that calls EVP_CIPHER functions by way of the TLS/SSL3 "AEADs". However, there we know the inputs are bounded by 2^16.] Since all instances are one of these two forms, I believe that there can be no overflows in internal code due to this problem. It should be noted that EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths. Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). Therefore I have checked all instances of these calls too, and came to the same conclusion, i.e. there are no instances in internal usage where an overflow could occur. This could still represent a security issue for end user code that calls this function directly. CVE-2016-2106 Issue reported by Guido Vranken. (Imported from upstream's 3ab937bc440371fbbe74318ce494ba95021f850a.) Change-Id: Iabde896555c39899c7f0f6baf7a163a7b3c2f3d6 Reviewed-on: https://boringssl-review.googlesource.com/7845 Reviewed-by: Adam Langley <agl@google.com> commit a43fd90c5ddd85604f308d1664e8f2cedca28b92 Author: David Benjamin <davidben@google.com> Date: Tue May 3 07:40:09 2016 -0400 Sync with upstream on i2d_X509_AUX. Upstream decided to reset *pp on error and to later fix up the other i2d functions to behave similarly. See upstream's c5e603ee182b40ede7713c6e229c15a8f3fdb58a. Change-Id: I01f82b578464060d0f2be5460fe4c1b969124c8e Reviewed-on: https://boringssl-review.googlesource.com/7844 Reviewed-by: Adam Langley <agl@google.com> commit eb3257211e3bd7dbdbe636144b6838dd20c37ef3 Author: David Benjamin <davidben@google.com> Date: Tue May 3 07:38:54 2016 -0400 Don't free ret->data if malloc fails. Issue reported by Guido Vranken. (Imported from upstream's 64eaf6c928f4066d62aa86f805796ef05bd0b1cc.) Change-Id: I99793abb4e1b5da5b70468b207ec03013fff674a Reviewed-on: https://boringssl-review.googlesource.com/7843 Reviewed-by: Adam Langley <agl@google.com> commit 52a3bf2835200a7beabe349a85cb2355e42ab599 Author: David Benjamin <davidben@google.com> Date: Tue May 3 07:50:44 2016 -0400 Add checks to X509_NAME_oneline() Sanity check field lengths and sums to avoid potential overflows and reject excessively large X509_NAME structures. Issue reported by Guido Vranken. (Imported from upstream's 9b08619cb45e75541809b1154c90e1a00450e537.) Change-Id: Ib2e1e7cd086f9c3f0d689d61947f8ec3e9220049 Reviewed-on: https://boringssl-review.googlesource.com/7842 Reviewed-by: Adam Langley <agl@google.com> commit ddc69230f30ed53bf81e2e6755cb74f02f537b1a Author: David Benjamin <davidben@google.com> Date: Tue May 3 07:35:56 2016 -0400 Sanity check buffer length. Reject zero length buffers passed to X509_NAME_oneline(). Issue reported by Guido Vranken. (Imported from upstream's 66e731ab09f2c652d0e179df3df10d069b407604.) Tweaked slightly to use <= 0 instead of == 0 since the length is signed. Change-Id: I5ee54d77170845e4699fda7df5e94538c8e55ed9 Reviewed-on: https://boringssl-review.googlesource.com/7841 Reviewed-by: Adam Langley <agl@google.com> commit d230a0c8904c4a67ee24ead8951345042bb73979 Author: David Benjamin <davidben@google.com> Date: Tue May 3 07:33:29 2016 -0400 Reject inappropriate private key encryption ciphers. The traditional private key encryption algorithm doesn't function properly if the IV length of the cipher is zero. These ciphers (e.g. ECB mode) are not suitable for private key encryption anyway. (Imported from upstream's 4436299296cc10c6d6611b066b4b73dc0bdae1a6.) Change-Id: I218c9c1d11274ef11b7c0cfce380521efa415215 Reviewed-on: https://boringssl-review.googlesource.com/7840 Reviewed-by: Adam Langley <agl@google.com> commit b83c680d03b302a88fefcddbdce1b753c4c54ca6 Author: Adam Langley <agl@google.com> Date: Tue May 3 09:16:21 2016 -0700 Add |CRYPTO_is_confidential_build|. In the past we have needed the ability to deploy security fixes to our frontend systems without leaking them in source code or in published binaries. This change adds a function that provides some infrastructure for supporting this in BoringSSL while meeting our internal build needs. We do not currently have any specific patch that requires this—this is purely preparation. Change-Id: I5c64839e86db4e5ea7419a38106d8f88b8e5987e Reviewed-on: https://boringssl-review.googlesource.com/7849 Reviewed-by: David Benjamin <davidben@google.com> commit 8368050fa9371840d76ea53ed38c3e5a1cb5e3bc Author: David Benjamin <davidben@google.com> Date: Mon May 2 13:15:52 2016 -0400 Clean up ssl_get_compatible_server_ciphers. The logic is a little hairy, partly because we used to support multiple certificate slots. Change-Id: Iee8503e61f5e0e91b7bcb15f526e9ef7cc7ad860 Reviewed-on: https://boringssl-review.googlesource.com/7823 Reviewed-by: David Benjamin <davidben@google.com> commit 7acd6bc07a25e85d784106fcdfda52809c09699f Author: David Benjamin <davidben@google.com> Date: Mon May 2 12:57:01 2016 -0400 Start assuming MSVC 2015. BUG=43 Change-Id: I46ad1ca62b8921a03fae51f5d7bbe1c68fc0b170 Reviewed-on: https://boringssl-review.googlesource.com/7821 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 8861daa5a9f3ed85500aebcde10278f604e673ac Author: David Benjamin <davidben@google.com> Date: Mon May 2 15:22:34 2016 -0400 Fix vs_toolchain.py, possibly. Sync a few changes with the upstream one, notably get_toolchain_if_necessary.py needs GYP_MSVS_VERSION set. Also pull the variables that change up to the top. This diverges a bit more from the upstream one, but we're already heavily diverged. If we ever need to support two concurrent toolchains, I'll bring us closer to parity. Change-Id: I6db7fbaccd5dddd92ad2deee15bd6dd3e28841f7 Reviewed-on: https://boringssl-review.googlesource.com/7830 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit bbe6af0e2ab5b80de6f9cb8ebe8571a5c4b48dbb Author: David Benjamin <davidben@google.com> Date: Fri Apr 29 14:15:39 2016 -0400 Bump requirements to MSVC 2015. Track the Chromium requirements. This makes our bots build with 2015 instead of 2013. BUG=43 Change-Id: Id5329900a5d1d5fae4b5b22299ed47bc1b947dd8 Reviewed-on: https://boringssl-review.googlesource.com/7820 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 9e7efdb008f98c0e311af37ee7193de4e54dcf75 Author: David Benjamin <davidben@google.com> Date: Mon May 2 13:03:34 2016 -0400 Update the various pinned revisions in util/bot. See util/bot/UPDATING for where they come from. Change-Id: Ib2eae6efc737dd8c4e5fb001fd4b478102e0ad6a Reviewed-on: https://boringssl-review.googlesource.com/7822 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit d18cb77864dcc4b5c7cb08c2331008c01165f34f Author: David Benjamin <davidben@google.com> Date: Fri Apr 29 16:22:40 2016 -0400 Fix d2i_X509_AUX. The logic to reset *pp doesn't actually work if pp is NULL. (It also doesn't work if *pp is NULL, but that didn't work before either.) Don't bother resetting it. This is consistent with the template-based i2d functions which do not appear to leave *pp alone on error. Will send this upstream. Change-Id: I9fb5753e5d36fc1d490535720b8aa6116de69a70 Reviewed-on: https://boringssl-review.googlesource.com/7812 Reviewed-by: Adam Langley <agl@google.com> commit 176dbf04b725b1ee53415fb84720935491c6b989 Author: David Benjamin <davidben@google.com> Date: Thu Apr 28 20:30:03 2016 -0400 Check for malloc failure in r2i_certpol. See upstream's 34b9acbd3f81b46967f692c0af49020c8c405746. Change-Id: I88d5b3cfbbe87e883323a9e6e1bf85227ed9576e Reviewed-on: https://boringssl-review.googlesource.com/7811 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 3bb5a77205b1ea66fd7ad3d103ff15cb752fe0bd Author: David Benjamin <davidben@google.com> Date: Thu Apr 28 20:28:11 2016 -0400 Fix memory leak on error in BN_mpi2bn. See also upstream's 91fb42ddbef7a88640d1a0f853c941c20df07de7, though that has a bug if |out| was non-NULL on entry. (I'll send them a patch.) Change-Id: I807f23007b89063c23e02dac11c4ffb41f847fdf Reviewed-on: https://boringssl-review.googlesource.com/7810 Reviewed-by: David Benjamin <davidben@google.com> commit 6f621bd8f7a4fa348bc2dec62c3b5870d6708fa7 Author: Nick Harper <nharper@chromium.org> Date: Thu Apr 28 12:13:42 2016 -0700 Merge documentation from chromium's net/der into cbs.c Change-Id: Icfd959a168e3fce423b10dd0dcb1312ec03f0623 Reviewed-on: https://boringssl-review.googlesource.com/7800 Reviewed-by: David Benjamin <davidben@google.com> commit 992c20aedc0e5206bfa2b6bc032fbff570c6deb3 Author: David Benjamin <davidben@google.com> Date: Thu Apr 28 12:56:35 2016 -0400 Another OPENSSL_NO_THREADS build fix. GCC gets unhappy if we don't initialize the padding. Change-Id: I084ffee1717d9025dcb10d8f32de0da2339c7f01 Reviewed-on: https://boringssl-review.googlesource.com/7797 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 0a63b96535dff86fc226e3a13e34252e702a45d0 Author: David Benjamin <davidben@google.com> Date: Thu Apr 28 12:17:55 2016 -0400 Make CRYPTO_is_NEON_capable aware of the buggy CPU. If we're to allow the buggy CPU workaround to fire when __ARM_NEON__ is set, CRYPTO_is_NEON_capable also needs to be aware of it. Also add an API to export this value out of BoringSSL, so we can get some metrics on how prevalent this chip is. BUG=chromium:606629 Change-Id: I97d65a47a6130689098b32ce45a8c57c468aa405 Reviewed-on: https://boringssl-review.googlesource.com/7796 Reviewed-by: Adam Langley <agl@google.com> commit b3be1cf97da6c0c796f0ab9aebe7232b030d32b0 Author: David Benjamin <davidben@google.com> Date: Wed Apr 27 19:15:06 2016 -0400 Add a 'configs_exclude' option to the generated GN 'create_tests' template. Chromium uses GN's default configs feature which makes all targets default to a set of configs. It then expects third_party code to take one of them (chromium_code) out and put in a different one (no_chromium_code). Because of that, we need a way to tell the template to emit -= lines. Add a separate option for that. (It may be worth making us clean against the chromium_code config rather than the no_chromium_code one, but I'll explore that separately in case making the C code clean ends up being a rabbithole.) BUG=chromium:607294 Change-Id: I2aa179665ab17439cc123fc86a7af9690cd4bcd6 Reviewed-on: https://boringssl-review.googlesource.com/7795 Reviewed-by: Adam Langley <agl@google.com> commit 2b4820bd523c7ee7406537bfad1bde9bb29673bb Author: David Benjamin <davidben@google.com> Date: Wed Apr 27 18:27:11 2016 -0400 Don't set a default armcap state in dynamic armcap modes. The getauxval (and friends) code would be filling that in anyway. The default only serves to enable NEON even if the OS is old enough to be missing getauxval (and everything else). Notably, this unbreaks the has_buggy_neon code when __ARM_NEON__ is set, as is the case in Chrome for Android, as of M50. Before, the default OPENSSL_armcap_P value was getting in the way. Arguably, this doesn't make a whole lot of sense. We're saying we'll let the CPU run compiler-generated NEON code, but not our hand-crafted stuff. But, so far, we only have evidence of the hand-written NEON tickling the bug and not the compiler-generated stuff, so avoid the unintentional regression. (Naively, I would expect the hand-crafted NEON is better at making full use of the pipeline and is thus more likely to tickle the CPU bug.) This is not the fix for M50, as in the associated Chromium bug, but it will fix master and M51. M50 will instead want to revert https://codereview.chromium.org/1730823002. BUG=chromium:606629 Change-Id: I394f97fea2f09891dd8fa30e0ec6fc6b1adfab7a Reviewed-on: https://boringssl-review.googlesource.com/7794 Reviewed-by: Adam Langley <agl@google.com> commit 9478f321753fcb9b1f495abab4e57aa8f6bfce15 Author: Matt Braithwaite <mab@google.com> Date: Wed Apr 27 11:53:18 2016 -0700 newhope: use less stack to compute client key Change-Id: Idf500545317242c8855e67b897975e54969fea10 Reviewed-on: https://boringssl-review.googlesource.com/7782 Reviewed-by: Adam Langley <agl@google.com> commit 862c0aa8806b226286205a3ce2482840721173d6 Author: David Benjamin <davidben@google.com> Date: Wed Apr 27 14:59:12 2016 -0400 Revert md_len removal from SHA256_CTX and SHA512_CTX. This reverts commits: - 91586371422dae70481c39752e55f01f50e9a93a - a90aa643024459c1698dbec84f4c79a3238b3db8 - c0d8b83b4462a0eb1889f32dbd7f46e83f4dbc81 It turns out code outside of BoringSSL also mismatches Init and Update/Final functions. Since this is largely cosmetic, it's probably not worth the cost to do this. Change-Id: I14e7b299172939f69ced2114be45ccba1dbbb704 Reviewed-on: https://boringssl-review.googlesource.com/7793 Reviewed-by: Adam Langley <agl@google.com> commit 88e27bcbe08210666b1e05c3daa12ff9faed2564 Author: David Benjamin <davidben@google.com> Date: Wed Apr 27 14:51:17 2016 -0400 Don't mismatch Init and Update/Final hash functions. Fixes the ASan bot. Change-Id: I29b9b98680b634c5e486a734afa38f9d4e458518 Reviewed-on: https://boringssl-review.googlesource.com/7792 Reviewed-by: Adam Langley <agl@google.com> commit 91586371422dae70481c39752e55f01f50e9a93a Author: David Benjamin <davidben@google.com> Date: Tue Apr 19 23:56:41 2016 -0400 Make SHA256_Final actually only return one. As with SHA512_Final, use the different APIs rather than store md_len. Change-Id: Ie1150de6fefa96f283d47aa03de0f18de38c93eb Reviewed-on: https://boringssl-review.googlesource.com/7722 Reviewed-by: Adam Langley <agl@google.com> commit a90aa643024459c1698dbec84f4c79a3238b3db8 Author: David Benjamin <davidben@google.com> Date: Tue Apr 19 23:51:11 2016 -0400 Pull HASH_MAKE_STRING out of md32_common.h. This is in preparation for taking md_len out of SHA256_CTX by allowing us to do something similar to SHA512_CTX. md32_common.h now emits a static "finish" function which Final composes with the extraction step. Change-Id: I314fb31e2482af642fd280500cc0e4716aef1ac6 Reviewed-on: https://boringssl-review.googlesource.com/7721 Reviewed-by: Adam Langley <agl@google.com> commit e3118b8dc4c05abc8ed822a181e81a2a070ebe61 Author: David Benjamin <davidben@google.com> Date: Wed Apr 27 14:44:22 2016 -0400 Fix Windows build. Change-Id: Ie35b8d0e2da0f7d2588c4a436fc4b2b2596aaf18 Reviewed-on: https://boringssl-review.googlesource.com/7791 Reviewed-by: David Benjamin <davidben@google.com> commit c0d8b83b4462a0eb1889f32dbd7f46e83f4dbc81 Author: David Benjamin <davidben@google.com> Date: Tue Apr 19 17:39:28 2016 -0400 Make SHA512_Final actually only return one. Rather than store md_len, factor out the common parts of SHA384_Final and SHA512_Final and then extract the right state. Also add a missing SHA384_Transform and be consistent about "1" vs "one" in comments. This also removes the NULL output special-case which no other hash function had. Change-Id: If60008bae7d7d5b123046a46d8fd64139156a7c5 Reviewed-on: https://boringssl-review.googlesource.com/7720 Reviewed-by: Adam Langley <agl@google.com> commit 3baee2a495df5aa212b13c5948da829332b75b24 Author: David Benjamin <davidben@google.com> Date: Fri Apr 1 18:37:07 2016 -0400 Banish SSL_add_dir_cert_subjects_to_stack and OPENSSL_DIR_CTX to decrepit. There was only one function that required BoringSSL to know how to read directories. Unfortunately, it does have some callers and it's not immediately obvious whether the code is unreachable. Rather than worry about that, just toss it all into decrepit. In doing so, do away with the Windows and PNaCl codepaths. Only implement OPENSSL_DIR_CTX on Linux. Change-Id: Ie64d20254f2f632fadc3f248bbf5a8293ab2b451 Reviewed-on: https://boringssl-review.googlesource.com/7661 Reviewed-by: Adam Langley <agl@google.com> commit 724dcbf5e209f118b9e6af82997d144b9c692b19 Author: Adam Langley <agl@google.com> Date: Wed Apr 27 11:08:13 2016 -0700 Correct markdown misinterpretation. The term “#define”, when the line breaking happens to put at the beginning of a line, confuses markdown. This change escapes the '#'. Change-Id: I8300324f9e8c7561f32aba6fa29c0132a188a58b commit a08142380981b366fb4f5eb61f9888f49342d388 Author: Adam Langley <agl@google.com> Date: Wed Apr 27 10:24:11 2016 -0700 Add document about incorporating BoringSSL into a project. Change-Id: Ia825300bae236e3133dd9a19313b7f5450f0c8e2 Reviewed-on: https://boringssl-review.googlesource.com/7781 Reviewed-by: David Benjamin <davidben@google.com> commit a9959f2f5083ed72a80800d7c8f8287122473be6 Author: David Benjamin <davidben@google.com> Date: Tue Apr 26 20:12:52 2016 -0400 Work around Android mingw issues. The copy of mingw-w64 used by Android isn't new enough and is missing half of the INIT_ONCE definitions. (But not the other half, strangely.) Work around this for now. Change-Id: I5c7e89db481f932e03477e50cfb3cbacaeb630e6 Reviewed-on: https://boringssl-review.googlesource.com/7790 Reviewed-by: Adam Langley <agl@google.com> commit 7909aa7c23f04dc5dd471824ea04443d96189618 Author: Adam Langley <agl@google.com> Date: Tue Apr 26 16:31:38 2016 -0700 Pass array by reference in newhope speed test. This is another thing that MSVC can't cope with: ..\tool\speed.cc(537) : error C2536: 'SpeedNewHope::<⋯>::SpeedNewHope::<⋯>::clientmsg' : cannot specify explicit initializer for arrays Change-Id: I6b4cb430895f7794e9cef1b1c12b57ba5d537c64 commit e75f0530a009efac5519053ff6c342ad0da50eea Author: Adam Langley <agl@google.com> Date: Tue Apr 26 16:25:31 2016 -0700 More fixes for MSVC. Change-Id: I2cde4d99974a28126452bb66c6e176b92b7f0bc9 commit bc57d55c9fe88d3c4f41dd204ec25a8dcf606a5e Author: Adam Langley <agl@google.com> Date: Tue Apr 26 16:10:53 2016 -0700 Corrupt the newhope secret key directly. Rather than use an internal function in a test (which would need an OPENSSL_EXPORT to work in a shared-library build), this change corrupts the secret key directly. Change-Id: Iee501910b23a0affaa0639dcc773d6ea2d0c5a82 Reviewed-on: https://boringssl-review.googlesource.com/7780 Reviewed-by: Matt Braithwaite <mab@google.com> Reviewed-by: Adam Langley <agl@google.com> commit 945cf9a131d52069dfec6488f901cef475732584 Author: Matt Braithwaite <mab@google.com> Date: Tue Apr 26 16:03:47 2016 -0700 newhope: MSVC can't size array using static size_t Change-Id: I5060b1a3e800db21d2205f11951b4ad8a5986133 Reviewed-on: https://boringssl-review.googlesource.com/7770 Reviewed-by: Adam Langley <agl@google.com> commit 045a0ffe358b81609e5b93e1f02e948b581304a3 Author: Matt Braithwaite <mab@google.com> Date: Mon Apr 18 11:30:19 2016 -0700 Import `newhope' (post-quantum key exchange). This derives from the reference implementation: Source: https://github.com/tpoeppelmann/newhope/tree/master/ref at bc06c1ac Paper: https://eprint.iacr.org/2015/1092 However, it does not interoperate, due to the replacement of SHAKE-128 with AES-CTR (for polynomial generation) and the replacement of SHA-3 with SHA-256 (for key whitening). Change-Id: I6a55507aea85331245e2fbd41bae5cc049fdca3c Reviewed-on: https://boringssl-review.googlesource.com/7690 Reviewed-by: Adam Langley <agl@google.com> commit c25d2e63795f7af7db5b1ca120f3f158a357f014 Author: David Benjamin <davidben@google.com> Date: Tue Apr 26 18:04:36 2016 -0400 Resolve -Wextern-c-compat warnings with OPENSSL_NO_THREADS. C and C++ disagree on the sizes of empty structs, which can be rather bad for structs embedded in public headers. Stick a char in them to avoid issues. (It doesn't really matter for CRYPTO_STATIC_MUTEX, but it's easier to add a char in there too.) Thanks to Andrew Chi for reporting this issue. Change-Id: Ic54fff710b688decaa94848e9c7e1e73f0c58fd3 Reviewed-on: https://boringssl-review.googlesource.com/7760 Reviewed-by: David Benjamin <davidben@google.com> commit ede2e2c5cec6a4ac40a247f7588fd8ccf625d182 Author: Steven Valdez <svaldez@google.com> Date: Tue Apr 26 12:51:18 2016 -0400 Fix buffer overrun in ASN1_parse() and signed/unsigned warning. (Imported from upstream's 2442382e11c022aaab4fdc6975bd15d5a75c4db2 and 0ca67644ddedfd656d43a6639d89a6236ff64652) Change-Id: I601ef07e39f936e8f3e30412fd90cd339d712dc4 Reviewed-on: https://boringssl-review.googlesource.com/7742 Reviewed-by: David Benjamin <davidben@google.com> commit b32a9151da35c12136299a3bf4e21c8c77d13866 Author: Steven Valdez <svaldez@google.com> Date: Tue Apr 26 12:57:22 2016 -0400 Ensure we check i2d_X509 return val The i2d_X509() function can return a negative value on error. Therefore we should make sure we check it. Issue reported by Yuan Jochen Kang. (Imported from upstream's 8f43c80bfac15544820739bf035df946eeb603e8) Change-Id: If247d5bf1d792eb7c6dc179b606ed21ea0ccdbb8 Reviewed-on: https://boringssl-review.googlesource.com/7743 Reviewed-by: David Benjamin <davidben@google.com> commit 14b07a02a6b16f24e6bd6cbb11f9904e9ee50442 Author: Steven Valdez <svaldez@google.com> Date: Tue Apr 26 12:43:39 2016 -0400 Harden ASN.1 BIO handling of large amounts of data. If the ASN.1 BIO is presented with a large length field read it in chunks of increasing size checking for EOF on each read. This prevents small files allocating excessive amounts of data. CVE-2016-2109 Thanks to Brian Carpenter for reporting this issue. (Imported from upstream's f32774087f7b3db1f789688368d16d917757421e) Change-Id: Id1b0d4436c4879d0ba7d3b7482b937cafffa28f7 Reviewed-on: https://boringssl-review.googlesource.com/7741 Reviewed-by: David Benjamin <davidben@google.com> commit f040d3c7e1a2da2cd1902ef90fd4b6daed061296 Author: David Benjamin <davidben@google.com> Date: Tue Apr 26 11:52:29 2016 -0400 Fix build. Forgot to mark something static. Change-Id: I497075d0ad27e2062f84528fb568b333e72a7d3b Reviewed-on: https://boringssl-review.googlesource.com/7753 Reviewed-by: David Benjamin <davidben@google.com> commit dc9194f78b120fddb6a63daa2ce53d48381b545a Author: David Benjamin <davidben@google.com> Date: Sun Apr 24 12:17:46 2016 -0400 Fix a bug in obj_dat.pl and add basic crypto/obj tests. It's not possible to encode an OID with only one component, so some of the NIDs do not have encodings. The logic to actually encode OIDs checks for this (before calling der_it), but not the logic to compute the sorted OID list. Without this, OBJ_obj2nid, when given an empty OID, returns something arbitrary based on the binary search implementation instead of NID_undef. Change-Id: Ib68bae349f66eff3d193616eb26491b6668d4b0a Reviewed-on: https://boringssl-review.googlesource.com/7752 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit f13444a5ad92974005df38c4344c922af2449ca3 Author: David Benjamin <davidben@google.com> Date: Mon Apr 25 13:22:22 2016 -0400 Use different bit tricks to extend the LSB. C gets grumpy when you shift into a sign bit. Replace it with a different bit trick. BUG=chromium:603502 Change-Id: Ia4cc2e2d68675528b7c0155882ff4d6230df482b Reviewed-on: https://boringssl-review.googlesource.com/7740 Reviewed-by: Adam Langley <agl@google.com> commit 1fc7564ba7dd985f311d5fccd1de4b01ee368b43 Author: David Benjamin <davidben@google.com> Date: Fri Apr 22 00:43:20 2016 -0400 Add standalone PKCS#8 and SPKI fuzzers. We already had coverage for our new EVP_PKEY parsers, but it's good to have some that cover them directly. The initial corpus was generated manually with der-ascii and should cover most of the insanity around EC key serialization. BUG=15 Change-Id: I7aaf56876680bfd5a89f5e365c5052eee03ba862 Reviewed-on: https://boringssl-review.googlesource.com/7728 Reviewed-by: Adam Langley <agl@google.com> commit af18cdd733a05a088518e5adb01704c1980fff3b Author: David Benjamin <davidben@google.com> Date: Sat Apr 23 01:40:03 2016 -0400 Add a copyright header to run_android_tests.go. Change-Id: Ifd60964e4074fa7900e9ebfbb669864bae0821dd Reviewed-on: https://boringssl-review.googlesource.com/7729 Reviewed-by: Adam Langley <agl@google.com> commit 6e96d2be3d86f81abc230309821691c0cf48343c Author: David Benjamin <davidben@google.com> Date: Mon Apr 25 15:07:53 2016 -0400 Remove stale wpa_supplicant hacks. aosp-master has been updated past the point that this is necessary. Sadly, all the other hacks still are. I'll try to get things rolling so we can ditch the others in time. Change-Id: If7b3aad271141fb26108a53972d2d3273f956e8d Reviewed-on: https://boringssl-review.googlesource.com/7751 Reviewed-by: Adam Langley <agl@google.com> commit 1be6a7e4428181e750bf00955df52a8155578ef0 Author: David Benjamin <davidben@google.com> Date: Mon Apr 25 14:41:19 2016 -0400 Add another temporary hack for wpa_supplicant. Due to Android's complex branching scheme, we have to keep building against a snapshotted version of wpa_supplicant. wpa_supplicant, in preparation for OpenSSL 1.1.0, added compatibility versions of some accessors that we, in working towards opaquification, have imported. This causes a conflict (C does not like having static and non-static functions share a name). Add a hack in the headers to suppress the conflicting accessors when BORINGSSL_SUPPRESS_ACCESSORS is defined. Android releases which include an updated BoringSSL will also locally carry this #define in wpa_supplicant build files. Once we can be sure releases of BoringSSL will only see a new enough wpa_supplicant (one which includes a to-be-submitted patch), we can ditch this. Change-Id: I3e27fde86bac1e59077498ee5cbd916cd880821e Reviewed-on: https://boringssl-review.googlesource.com/7750 Reviewed-by: Adam Langley <agl@google.com> commit b70cd92c82b4626b8ea69e22e8044fc486fe17bd Author: Adam Langley <agl@google.com> Date: Mon Apr 25 10:48:19 2016 -0700 Add licenses to fuzz tests. These source files previously didn't have the ISC license on them. Change-Id: Ic0a2047d23b28d9d7f0a85b2fedb67574bdcab25 Reviewed-on: https://boringssl-review.googlesource.com/7735 Reviewed-by: David Benjamin <davidben@google.com> commit 3d907ed964c721a395c82c5733e7d6dd7fcdd1fb Author: Adam Langley <agl@google.com> Date: Fri Apr 22 14:06:50 2016 -0700 Remove RC4_options from rc4-586.pl. The x86-64 version of this assembly doesn't include this function. It's in decrepit/rc4 as a compatibility backfill but that means that 32-bit builds end up with two definitions of this symbol. Change-Id: Ib6da6b91aded8efc679ebbae6d60c96a78f3dc4e Reviewed-on: https://boringssl-review.googlesource.com/7734 Reviewed-by: David Benjamin <davidben@google.com> commit 38d01c6b95df135875c2b2d50448c068e5b090e8 Author: David Benjamin <davidben@google.com> Date: Thu Apr 21 18:47:57 2016 -0400 Improve generate_build_files.py gn support. Split gn and gyp generators apart. Since we're pre-generating files, there's no need to make BoringSSL's build depend on the gypi_to_gn.py script. Also emit the tests and a list of fuzzers so we don't need to manually update BUILD.gn each time. The new gn generator is based on the bazel one since they're fairly similar. BUG=chromium:429246 Change-Id: I5a819a964d6ac6e56e9251bb3fd3de1db08214a4 Reviewed-on: https://boringssl-review.googlesource.com/7726 Reviewed-by: Adam Langley <agl@google.com> commit 818aff01fb41b1e46aed9b9ec3bcfc76ae6cf0dd Author: David Benjamin <davidben@google.com> Date: Thu Apr 21 16:58:49 2016 -0400 Add SSL_SESSION_get_master_key. Opaquifying SSL_SESSION is less important than the other structs, but this will cause less turbulence in wpa_supplicant if we add this API too. Semantics and name taken from OpenSSL 1.1.0 to match. BUG=6 Change-Id: Ic39f58d74640fa19a60aafb434dd2c4cb43cdea9 Reviewed-on: https://boringssl-review.googlesource.com/7725 Reviewed-by: Adam Langley <agl@google.com> commit 7fadfc6135aecb4ae44543bf94950593979c3547 Author: David Benjamin <davidben@google.com> Date: Thu Apr 21 16:28:19 2016 -0400 Move TLS-specific "AEAD" functions to the bottom of aead.h. Probably better to keep it out of the way for someone just trying to figure out how to use the library. Notably, we don't really want people to think they need to use the directioned init function. Change-Id: Icacc2061071581abf46e38eb1d7a52e7b1f8361b Reviewed-on: https://boringssl-review.googlesource.com/7724 Reviewed-by: Adam Langley <agl@google.com> commit 325664eec4f33b8adecdeb6f151d10d2c57689c9 Author: David Benjamin <davidben@google.com> Date: Thu Apr 21 16:07:49 2016 -0400 Add hkdf.h to doc.config. It has all of one function in there. Change-Id: I86f0fbb76d267389c62b63ac01df685acb70535e Reviewed-on: https://boringssl-review.googlesource.com/7723 Reviewed-by: Adam Langley <agl@google.com> commit f01fb5dc0e9d2227a20fe33f7bf76c2160ecf9c9 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 14:34:03 2016 -1000 Avoid minor waste in |ec_GFp_nistp256_point_get_affine_coordinates|. Avoid calculating the affine Y coordinate when the caller didn't ask for it, as occurs, for example, in ECDH. For symmetry and clarity, avoid calculating the affine X coordinate in the hypothetical case where the caller only asked for the Y coordinate. Change-Id: I69f5993fa0dfac8b010c38e695b136cefc277fed Reviewed-on: https://boringssl-review.googlesource.com/7590 Reviewed-by: David Benjamin <davidben@google.com> commit 3f3358ac150465fafffaf1c51c2928dd2b2018a9 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 14:29:52 2016 -1000 Save one call to |ecp_nistz256_from_mont| in |ecp_nistz256_get_affine|. Change-Id: I38faa5c4e9101c100614ebadf421bde0a05af360 Reviewed-on: https://boringssl-review.googlesource.com/7589 Reviewed-by: David Benjamin <davidben@google.com> commit a7aa2bb8f86f9891bba9d05544e2b9796b2da864 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 14:22:40 2016 -1000 Avoid a multiplication in |ecp_nistz256_get_affine| when |x| is NULL. This is purely hypothetical, as in real life nobody cares about the |y| component without also caring about the |x| component, but it clarifies the code and makes a future change clearer. Change-Id: Icaa4de83c87b82a8e68cd2942779a06e5db300c3 Reviewed-on: https://boringssl-review.googlesource.com/7588 Reviewed-by: David Benjamin <davidben@google.com> commit d860b7b1cdefa22b2d42074aa5c8ce2a8ec1da5c Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 14:19:42 2016 -1000 Set output coordinates' |neg| field in |ecp_nistz256_get_affine|. The result would not be correct if, on input, |x->neg != 0| or |y->neg != 0|. Change-Id: I645566a78c2e18e42492fbfca1df17baa05240f7 Reviewed-on: https://boringssl-review.googlesource.com/7587 Reviewed-by: David Benjamin <davidben@google.com> commit 97770d17d8dad60295cf0090f498472907ffd738 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 11 14:04:14 2016 -1000 Use only Montgomery math in |ec_GFp_mont_point_get_affine_coordinates|. Use only Montgomery math in |ec_GFp_mont_point_get_affine_coordinates|. In particular, avoid |BN_mod_sqr| and |BN_mod_mul|. Change-Id: I05c8f831d2865d1b105cda3871e9ae67083f8399 Reviewed-on: https://boringssl-review.googlesource.com/7586 Reviewed-by: David Benjamin <davidben@google.com> commit f3835839b1f3f7a922748153ca5aa17132220407 Author: David Benjamin <davidben@google.com> Date: Tue Apr 19 17:48:11 2016 -0400 Use nanosleep instead of usleep. usleep is guarded by feature macro insanity. Use nanosleep which looks to be less unfriendly. Change-Id: I75cb2284f26cdedabb19871610761ec7440b6ad3 Reviewed-on: https://boringssl-review.googlesource.com/7710 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 9dadc3b6e1c2d5e2e8a3b1188c905d5541a75df7 Author: David Benjamin <davidben@google.com> Date: Wed Mar 30 19:04:28 2016 -0400 Replace CRYPTO_once_t on Windows with INIT_ONCE. Now that we no longer support Windows XP, this function is available. In doing so, remove the odd run_once_arg_t union and pass in a pointer to a function pointer which is cleaner and still avoids C's silly rule where function pointers can't be placed in a void*. BUG=37 Change-Id: I44888bb3779dacdb660706debd33888ca389ebd5 Reviewed-on: https://boringssl-review.googlesource.com/7613 Reviewed-by: David Benjamin <davidben@google.com> commit 3ed24f0502ea3f38fa79306dfe263527f0491230 Author: David Benjamin <davidben@google.com> Date: Wed Mar 30 19:03:45 2016 -0400 Test CRYPTO_once_t collisions. The existing tests never actually tested this case. Change-Id: Idb9cf0cbbe32fdf5cd353656a95fbedbaac09376 Reviewed-on: https://boringssl-review.googlesource.com/7612 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 582d2847eda65671883649347f60f6916838a3d1 Author: David Benjamin <davidben@google.com> Date: Sat Apr 16 17:10:01 2016 -0400 Reimplement PKCS#12 key derivation. This is avoids pulling in BIGNUM for doing a straight-forward addition on a block-sized value, and avoids a ton of mallocs. It's also -Wconversion-clean, unlike the old one. In doing so, this replaces the HMAC_MAX_MD_CBLOCK with EVP_MAX_MD_BLOCK_SIZE. By having the maximum block size available, most of the temporary values in the key derivation don't need to be malloc'd. BUG=22 Change-Id: I940a62bba4ea32bf82b1190098f3bf185d4cc7fe Reviewed-on: https://boringssl-review.googlesource.com/7688 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 0e21f41fe884bedf708d3d4d6ab2ce9f53712bb8 Author: David Benjamin <davidben@google.com> Date: Sat Apr 16 15:20:07 2016 -0400 Switch all 'num' parameters in crypto/modes to unsigned. Also switch the EVP_CIPHER copy to cut down on how frequently we need to cast back and forth. BUG=22 Change-Id: I9af1e586ca27793a4ee6193bbb348cf2b28a126e Reviewed-on: https://boringssl-review.googlesource.com/7689 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 1a0a8b6760a9bc21c1c14a07c88fe63d637464ea Author: David Benjamin <davidben@google.com> Date: Sat Apr 16 15:23:54 2016 -0400 Make EVP_MD_CTX size functions return size_t. The EVP_MD versions do, so the types should bubble up. BUG=22 Change-Id: Ibccbc9ff35bbfd3d164fc28bcdd53ed97c0ab338 Reviewed-on: https://boringssl-review.googlesource.com/7687 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 86361a391062e02012c92d1eefa20df3deb897f3 Author: Brian Smith <brian@briansmith.org> Date: Sat Mar 26 19:42:31 2016 -1000 Require the public exponent to be available in RSA blinding. Require the public exponent to be available unless |RSA_FLAG_NO_BLINDING| is set on the key. Also, document this. If the public exponent |e| is not available, then we could compute it from |p|, |q|, and |d|. However, there's no reasonable situation in which we'd have |p| or |q| but not |e|; either we have all the CRT parameters, or we have (e, d, n), or we have only (d, n). The calculation to compute |e| exposes the private key to risk of side channel attacks. Also, it was particularly wasteful to compute |e| for each |BN_BLINDING| created, instead of just once before the first |BN_BLINDING| was created. |BN_BLINDING| now no longer needs to contain a duplicate copy of |e|, so it is now more space-efficient. Note that the condition |b->e != NULL| in |bn_blinding_update| was always true since commit cbf56a5683ddda831ff91c46ea48d1fba545db66. Change-Id: Ic2fd6980e0d359dcd53772a7c31bdd0267e316b4 Reviewed-on: https://boringssl-review.googlesource.com/7594 Reviewed-by: David Benjamin <davidben@google.com> commit d035730ac7ebb82fbf1895fea50c29048bb6edb2 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 10:11:04 2016 -1000 Make return value of |BN_MONT_CTX_set_locked| int. This reduces the chance of double-frees. BUG=10 Change-Id: I11a240e2ea5572effeddc05acb94db08c54a2e0b Reviewed-on: https://boringssl-review.googlesource.com/7583 Reviewed-by: David Benjamin <davidben@google.com> commit 51b0d5b1e86590c6e828b11ede90db04916e9ff1 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 13:15:39 2016 -1000 Do not use the CRT when |rsa->e == NULL|. When |rsa->e == NULL| we cannot verify the result, so using the CRT would leave the key too vulnerable to fault attacks. Change-Id: I154622cf6205ba4d5fb219143db6072a787c2d1f Reviewed-on: https://boringssl-review.googlesource.com/7581 Reviewed-by: David Benjamin <davidben@google.com> commit 69f0532c8530ef3b26a63f6fbf819bb006c13222 Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 15 12:44:36 2016 -1000 Use |memcmp| instead of |CRYPTO_memcmp| in |RSA_verify|. |CRYPTO_memcmp| isn't necessary because there is no secret data being acted on here. Change-Id: Ib678d5d4fc16958aca409a93df139bdff8cb73fb Reviewed-on: https://boringssl-review.googlesource.com/7465 Reviewed-by: David Benjamin <davidben@google.com> commit 2a92031bb4dceef47b8ee49a9184d7e572fb841b Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 4 13:42:47 2016 -1000 Clarify |RSA_verify_raw| error handling & cleanup. Use the common pattern of returning early instead of |goto err;| when there's no cleanup to do yet. Also, move the error checking of |BN_CTX_get| failure closer to the the calls to |BN_CTX_get|. Avoid calling |OPENSSL_cleanse| on public data. Clarify when/why |buf| is not freed. Change-Id: I9df833db7eb7041c5af9349c461297372b988f98 Reviewed-on: https://boringssl-review.googlesource.com/7464 Reviewed-by: David Benjamin <davidben@google.com> commit 9902262af6fa38acd9bf4e55f2a6d3389faba7e8 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 4 09:20:07 2016 -1000 Remove redundant check of |sig_len| in |RSA_verify|. The same check is already done in |RSA_verify_raw|, so |RSA_verify| doesn't need to do it. Also, move the |RSA_verify_raw| check earlier. Change-Id: I15f7db0aad386c0f764bba53e77dfc46574f7635 Reviewed-on: https://boringssl-review.googlesource.com/7463 Reviewed-by: David Benjamin <davidben@google.com> commit c0b196d4ebc75c9f9cb61411b8fe291e70059d58 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 4 08:54:07 2016 -1000 Drop support for engines-provided signature verification. We do not need to support engine-provided verification methods. Change-Id: Iaad8369d403082b728c831167cc386fdcabfb067 Reviewed-on: https://boringssl-review.googlesource.com/7311 Reviewed-by: David Benjamin <davidben@google.com> commit 9b611e28e42761527c700506194a33b1dd1b90db Author: David Benjamin <davidben@google.com> Date: Thu Mar 3 08:48:30 2016 -0500 Simplify server_name extension parsing. Although the server_name extension was intended to be extensible to new name types, OpenSSL 1.0.x had a bug which meant different name types will cause an error. Further, RFC 4366 originally defined syntax inextensibly. RFC 6066 corrected this mistake, but adding new name types is no longer feasible. Act as if the extensibility does not exist to simplify parsing. This also aligns with OpenSSL 1.1.x's behavior. See upstream's 062178678f5374b09f00d70796f6e692e8775aca and https://www.ietf.org/mail-archive/web/tls/current/msg19425.html Change-Id: I5af26516e8f777ddc1dab5581ff552daf2ea59b5 Reviewed-on: https://boringssl-review.googlesource.com/7294 Reviewed-by: David Benjamin <davidben@google.com> commit 4c5ddb80477738d8063d3b65038b5879b20f8e84 Author: David Benjamin <davidben@google.com> Date: Fri Mar 11 22:56:19 2016 -0500 Set rwstate consistently. We reset it to SSL_NOTHING at the start of ever SSL_get_error-using operation. Then we only set it to a non-NOTHING value in the rest of the stack on error paths. Currently, ssl->rwstate is set all over the place. Sometimes the pattern is: ssl->rwstate = SSL_WRITING; if (BIO_write(...) <= 0) { goto err; } ssl->rwstate = SSL_NOTHING; Sometimes we only set it to the non-NOTHING value on error. if (BIO_write(...) <= 0) { ssl->rwstate = SSL_WRITING; } ssl->rwstate = SSL_NOTHING; Sometimes we just set it to SSL_NOTHING far from any callback in random places. The third case is arbitrary and clearly should be removed. But, in the second case, we sometimes forget to undo it afterwards. This is largely harmless since an error in the error queue overrides rwstate, but we don't always put something in the error queue (falling back to SSL_ERROR_SYSCALL for "I'm not sure why it failed. Perhaps it was one of your callbacks? Check your errno equivalent."), but in that case a stray rwstate value will cause it to be wrong. We could fix the cases where we fail to set SSL_NOTHING on success cases, but this doesn't account for there being multiple SSL_get_error operations. The consumer may have an SSL_read and an SSL_write running concurrently. Instead, it seems the best option is to lift the SSL_NOTHING reset to the operations and set SSL_WRITING and friends as in the second case. (Someday hopefully we can fix this to just be an enum that is internally returned. It can convert to something stateful at the API layer.) Change-Id: I54665ec066a64eb0e48a06e2fcd0d2681a42df7f Reviewed-on: https://boringssl-review.googlesource.com/7453 Reviewed-by: David Benjamin <davidben@google.com> commit c6972eb1f090adc26046859ce3424221de8e210e Author: David Benjamin <davidben@google.com> Date: Fri Mar 11 22:43:53 2016 -0500 Remove the no_renegotiation special case. The concern is if the peer denies our renegotiation attempt, but we will never initiate renegotiation. We only support server-initiated renegotiation when we are acting as the client. (Strictly speaking, only the client ever initiates renegotiation. The server sends a HelloRequest to ask the client to initiate it. But we forbid application data interleave as soon as we see the HelloRequest, so we treat it as part of the handshake.) Change-Id: I1a625130de32a7227e4471f2f889255aba962ce4 Reviewed-on: https://boringssl-review.googlesource.com/7452 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 0d3a8c6ac0f83bd38221bfbb4d83c3c315b5c4ce Author: David Benjamin <davidben@google.com> Date: Fri Mar 11 22:25:18 2016 -0500 Don't allow alert records with multiple alerts. This is just kind of a silly thing to do. NSS doesn't allow them either. Fatal alerts would kill the connection regardless and warning alerts are useless. We previously stopped accepting fragmented alerts but still allowed them doubled up. This is in preparation for pulling the shared alert processing code between TLS and DTLS out of read_bytes into some common place. Change-Id: Idbef04e39ad135f9601f5686d41f54531981e0cf Reviewed-on: https://boringssl-review.googlesource.com/7451 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 56703d91bf18f66867ed7f3fc8ed06fbf13fb18a Author: David Benjamin <davidben@google.com> Date: Mon Apr 18 15:39:33 2016 -0400 Make err_data_generator.go silent by default. I don't think I ever look at that output. This way our builds are nice and silent. Change-Id: Idb215e3702f530a8b8661622c726093530885c91 Reviewed-on: https://boringssl-review.googlesource.com/7700 Reviewed-by: Adam Langley <agl@google.com> commit 26993ad55eda0763990fdd11db929043761b56e1 Author: David Benjamin <davidben@google.com> Date: Fri Apr 15 16:12:19 2016 -0400 Only use recv/send for socket BIOs on Windows. In OpenSSL, socket BIOs only used recv/send on Windows and read/write on POSIX. Align our socket BIOs with that behavior. This should be a no-op, but avoids frustrating consumers overly sensitive to the syscalls used now that SSL_set_fd has switched to socket BIOs to align with OpenSSL. b/28138582. Change-Id: Id4870ef8e668e587d6ef51c5b5f21e03af66a288 Reviewed-on: https://boringssl-review.googlesource.com/7686 Reviewed-by: Adam Langley <agl@google.com> commit 919610b4c43ab394977eba70ceec66aaa0070472 Author: David Benjamin <davidben@google.com> Date: Fri Apr 15 15:34:30 2016 -0400 Fix memory leak on invalid ecPublicKey parameters. One of the codepaths didn't free the group. Found by libFuzzer. BUG=chromium:603893 Change-Id: Icb81f2f89a8c1a52e29069321498986b193a0e56 Reviewed-on: https://boringssl-review.googlesource.com/7685 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: Adam Langley <agl@google.com> commit 4365c3f522f2fc57fa0c87bde5f25ea98dd9a59c Author: Daniel Bathgate <dbathgate@google.com> Date: Thu Apr 14 17:18:02 2016 -0400 Send an error rather than assert when decrypt_len != rsa_size. With SSL_PRIVATE_KEY_METHOD, decryption can happen outside of BoringSSL. Rather than crash the process, it would be nicer if BoringSSL handled the error gracefully. Change-Id: I3f24d066f7a329d41420b208a7e13c82ec966710 Reviewed-on: https://boringssl-review.googlesource.com/7683 Reviewed-by: David Benjamin <davidben@google.com> commit 0fe4d8bef5918f84a7f260c34c26dd13c0d70ade Author: David Benjamin <davidben@google.com> Date: Wed Apr 13 17:28:35 2016 -0400 chacha/asm/chacha-armv8.pl: fix intermittent build failures. (Imported from b9077d85b0042d3d5d877d5cf7f06a8a8c035673.) Change-Id: I6df3b3d0913b001712a78671c69b9468e059047f Reviewed-on: https://boringssl-review.googlesource.com/7682 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 9980ce1dcd1a90990e7e922979ef4445032aa383 Author: Steven Valdez <svaldez@google.com> Date: Thu Apr 14 16:35:26 2016 -0400 Add BORINGSSL_PREFIX for prefixing symbols This currently doesn't prefix assembly symbols since they don't pull in openssl/base.h BUG=5 Change-Id: Ie0fdc79ae73099f84ecbf3f17604a1e615569b3b Reviewed-on: https://boringssl-review.googlesource.com/7681 Reviewed-by: David Benjamin <davidben@google.com> commit a82e8dd9d28705eef77e47762f06626c9134dd6a Author: David Benjamin <davidben@google.com> Date: Thu Apr 14 09:48:39 2016 -0400 Tweak X25519 documentation. Both the header-level and section-level documentation define curve25519 which is a little odd. Change-Id: I81aa2b74e8028d3cfd5635e1d3cfda402ba1ae38 Reviewed-on: https://boringssl-review.googlesource.com/7680 Reviewed-by: Adam Langley <agl@google.com> commit aaccbfec04a09d6711e0ead04e5bef612b8fa65e Author: Adam Langley <agl@google.com> Date: Wed Apr 13 08:19:03 2016 -0700 Export RSA_padding_add_PKCS1_OAEP[_mgf1] This is needed by trousers. As with the PSS function, the version that assumes SHA-1 is put into decrepit. Change-Id: I153e8ea0150e48061b978384b600a7b990d21d03 Reviewed-on: https://boringssl-review.googlesource.com/7670 Reviewed-by: David Benjamin <davidben@google.com> commit 188487faadcda73e80ce84a3e113d2c9de9bbb3b Author: Max Moroz <mmoroz@google.com> Date: Mon Apr 11 15:36:49 2016 +0200 Remove .options files for libFuzzers and update FUZZING.md documentation. Due to https://codereview.chromium.org/1867833002/ replacing .options files. Change-Id: I17f0d5b8b1784fdcf163791e72f6b58b29657e95 Reviewed-on: https://boringssl-review.googlesource.com/7640 Reviewed-by: David Benjamin <davidben@google.com> commit e4c678adda26367e1195cf1aca2af66cb7c3d650 Author: David Benjamin <davidben@google.com> Date: Mon Apr 11 18:04:18 2016 -0400 Revert "Banish SSL_add_dir_cert_subjects_to_stack and OPENSSL_DIR_CTX to decrepit." This reverts commit 112c4dd1ff895bf5af0d64488234b0fc40b616bc. Accidentally used the wrong push line. commit 112c4dd1ff895bf5af0d64488234b0fc40b616bc Author: David Benjamin <davidben@google.com> Date: Fri Apr 1 18:37:07 2016 -0400 Banish SSL_add_dir_cert_subjects_to_stack and OPENSSL_DIR_CTX to decrepit. There was only one function that required BoringSSL to know how to read directories. Unfortunately, it does have some callers and it's not immediately obvious whether the code is unreachable. Rather than worry about that, just toss it all into decrepit. In doing so, do away with the Windows and PNaCl codepaths. Only implement OPENSSL_DIR_CTX on Linux. Change-Id: I3eb55b098e3aa042b422bb7da115c0812685553e commit 2a187a43169ec4855f549972e01b7b34d704be41 Author: David Benjamin <davidben@google.com> Date: Mon Apr 11 17:26:50 2016 -0400 No-op change to test bugdroid. Making sure the BUG= line works correctly. BUG=41 Change-Id: Icedf5f1ec8211696c74d9e9f9d322483c43444fc commit 14420e91e0d6b5e2b5d2c39b2315151ae5837fb1 Author: David Benjamin <davidben@google.com> Date: Mon Apr 11 13:25:37 2016 -0400 Remove EVP_aead_chacha20_poly1305_rfc7539 alias. This slipped through, but all the callers are now using EVP_aead_chacha20_poly1305, so we can remove this version. Change-Id: I76eb3a4481aae4d18487ca96ebe3776e60d6abe8 Reviewed-on: https://boringssl-review.googlesource.com/7650 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit a13ad73cee6e7c490e91daba6971e45ea42ac8dd Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Apr 8 17:23:10 2016 -0700 Use UINT64_C instead of unsigned long long integer constant. Change-Id: Id181957956ccaacc6c29b641a1f1144886d442c0 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7630 Reviewed-by: David Benjamin <davidben@google.com> commit dcb3383463fa2c70bbafefff53004f6896dbc504 Author: Gabriel Redner <gredner@google.com> Date: Wed Apr 6 15:47:28 2016 -0400 Modify 'bssl client' to print the cert subject and issuer This is the one piece of functionality I miss from the openssl tool - the ability to see some basic information about the server cert. Sample output: ========== $ bssl client -connect www.google.com Connecting to [2607:f8b0:4006:80d::1010]:443 Connected. Version: TLSv1.2 Resumed session: no Cipher: ECDHE-RSA-AES128-GCM-SHA256 ECDHE curve: P-256 Secure renegotiation: yes Next protocol negotiated: ALPN protocol: Cert subject: /C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com Cert issuer: /C=US/O=Google Inc/CN=Google Internet Authority G2 ========== Change-Id: I758682784752a616628138e420f52586d5a1bb31 Reviewed-on: https://boringssl-review.googlesource.com/7620 Reviewed-by: David Benjamin <davidben@google.com> commit d44a9431112d37430b3a686bbf4fb6211be69848 Author: David Benjamin <davidben@google.com> Date: Thu Mar 31 18:15:27 2016 -0400 Fix docs typo. Change-Id: Idb786ee2ca6354dcf2f665e9229aef4a43e05dd4 Reviewed-on: https://boringssl-review.googlesource.com/7614 Reviewed-by: David Benjamin <davidben@google.com> commit 046b27815ec4804695f8eed093d4fe5b4589aabc Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 18:07:16 2016 -0400 Decouple crypto/evp from the OID table. BUG=chromium:499653 Change-Id: I4e8d4af3129dbf61d4a8846ec9db685e83999d5e Reviewed-on: https://boringssl-review.googlesource.com/7565 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 0d76c402b81507e13ac628ee04990b1c5ce892e8 Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 18:07:15 2016 -0400 Decouple crypto/ec from the OID table. Instead, embed the (very short) encoding of the OID into built_in_curve. BUG=chromium:499653 Change-Id: I0db36f83c71fbd3321831f54fa5022f8304b30cd Reviewed-on: https://boringssl-review.googlesource.com/7564 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 981936791eb76c52daedb18310fced187252ed30 Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 18:07:11 2016 -0400 Remove some easy obj.h dependencies. A lot of consumers of obj.h only want the NID values. Others didn't need it at all. This also removes some OBJ_nid2sn and OBJ_nid2ln calls in EVP error paths which isn't worth pulling a large table in for. BUG=chromium:499653 Change-Id: Id6dff578f993012e35b740a13b8e4f9c2edc0744 Reviewed-on: https://boringssl-review.googlesource.com/7563 Reviewed-by: David Benjamin <davidben@google.com> commit 5d38f78e2987be876e3023808b4eed57c84ce23c Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 18:07:08 2016 -0400 Rename obj_mac.h to nid.h and make it a multiply-includable header. obj_mac.h is missing #include guards, so one cannot use NIDs without pulling in the OBJ_* functions which depend on the giant OID table. Give it #include guards, tidy up the style slightly, and also rename it to nid.h which is a much more reasonable name. obj_mac.h is kept as a forwarding header as, despite it being a little screwy, some code #includes it anyway. BUG=chromium:499653 Change-Id: Iec0b3f186c02e208ff1f7437bf27ee3a5ad004b7 Reviewed-on: https://boringssl-review.googlesource.com/7562 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 66ec5c90667a32030d64af6d3da426924fbc732a Author: David Benjamin <davidben@google.com> Date: Wed Mar 30 14:26:46 2016 -0400 Also re-serialize X509 objects in fuzz/cert.cc. This is a fairly common operation on an X509. Change-Id: I1820f20b555f75c98ab7e3283b5530bc1c200e2a Reviewed-on: https://boringssl-review.googlesource.com/7611 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 20568e7a4f028782fb76df5407ca9ceaf16de59e Author: David Benjamin <davidben@google.com> Date: Wed Mar 30 14:23:31 2016 -0400 Remove inaccurate comments in fuzz/{client,server}.cc. They now fuzz a lot more than just the initial flow. Change-Id: Ib0b7eb66969442e539a937d7d87f5ba031fcbef3 Reviewed-on: https://boringssl-review.googlesource.com/7610 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 9e5eb63d011cbc6730b4fbc05c4dd3ae6021e97f Author: David Benjamin <davidben@google.com> Date: Sat Mar 26 00:58:38 2016 -0400 Document that CRYPTO_library_init may be called concurrently. This was fixed in 93a5b442964d9770b5faa0fb381a8c4f43e65abe, but it wasn't documented. Now that there are no pre-init functions to call like CRYPTO_set_neon_capable, one instance of BoringSSL may be safely shared between multiple consumers. As part of that, multiple consumers need to be able to call CRYPTO_library_init possibly redundantlyand possibly on different threads without synchronization. (Though there is still that static initializer nuisance. It would be nice to replace this with internal CRYPTO_once_t's and then CRYPTO_library_init need only be called to prime armcap for a sandbox. But one thing at a time.) Change-Id: I48430182d3649c8cf19082e34da24dee48e6119e Reviewed-on: https://boringssl-review.googlesource.com/7571 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit d879e299366895d7d80d83cfbbe05bc6a09e2a27 Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 22 17:30:42 2016 -1000 Further optimize Montgomery math in RSA blinding. Change-Id: I830c6115ce2515a7b9d1dcb153c4cd8928fb978f Reviewed-on: https://boringssl-review.googlesource.com/7591 Reviewed-by: David Benjamin <davidben@google.com> commit bfefc27c2bb4af62e09569e36b018d60da98a680 Author: David Benjamin <davidben@google.com> Date: Tue Mar 29 19:00:33 2016 -0400 Avoid doing arithmetic on void pointers. Whatever compiler settings AOSP is using warns that this is a GNU extension. Change-Id: Ife395d2b206b607b14c713cbb5a94d479816dad0 Reviewed-on: https://boringssl-review.googlesource.com/7604 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 4b7b048417d8ff92c993da9dbb3d9df20455fc1d Author: David Benjamin <davidben@google.com> Date: Wed Mar 30 00:42:17 2016 -0400 Spell __attribute__((format(printf, ...))) with more underscores. They may be spelled with or without underscores. Alas, a lot of C code (adb, cURL) seems to find it a popular pasttime to #define printf *before* including external headers. This is completely nonsense and invalid, but working around it is easy and is what we (and OpenSSL) were doing before 061332f21643a910941c32cbfc40e577c380e342. I'll be sending a patch to cURL tomorrow to make them at least do their macro trickery after external #includes for sanity. adb's sysdeps.h is a lot longer and consistently #included first so I'll probably leave that be for lack of time. Change-Id: I03a0a253f2c902eb45f45faace1e5c5df4335ebf Reviewed-on: https://boringssl-review.googlesource.com/7605 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit aa0bea7bc1927b737f46c41ceb1f1508c9a3ff11 Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 13:27:30 2016 -0400 Add additional poly1305 tests. Thanks to Hanno Boeck for reporting them in https://rt.openssl.org/Ticket/Display.html?id=4483 Change-Id: Ic902c0ceea32c76cad924a1ffc462d39ae6ca3de Reviewed-on: https://boringssl-review.googlesource.com/7603 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 3c4a5cbb71453c5d61314a3f76a5ca6f123dbf94 Author: David Benjamin <davidben@google.com> Date: Tue Mar 29 17:43:31 2016 -0400 Revert "Enable upstream's Poly1305 code." This reverts commit 6f0c4db90e47437ed87a2d385c7797e692a2cf65 except for the imported assembly files, which are left as-is but unused. Until upstream fixes https://rt.openssl.org/Ticket/Display.html?id=4483, we shouldn't ship this code. Once that bug has been fixed, we'll restore it. Change-Id: I74aea18ce31a4b79657d04f8589c18d6b17f1578 Reviewed-on: https://boringssl-review.googlesource.com/7602 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit f08c1c68957024ced93d35d757daeb373de8f073 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 13:24:46 2016 -1000 Drop support for custom |mod_exp| hooks in |RSA_METHOD|. The documentation in |RSA_METHOD| says that the |ctx| parameter to |mod_exp| can be NULL, however the default implementation doesn't handle that case. That wouldn't matter since internally it is always called with a non-NULL |ctx| and it is static, but an external application could get a pointer to |mod_exp| by extracting it from the default |RSA_METHOD|. That's unlikely, but making that impossible reduces the chances that future refactorings will cause unexpected trouble. Change-Id: Ie0e35e9f107551a16b49c1eb91d0d3386604e594 Reviewed-on: https://boringssl-review.googlesource.com/7580 Reviewed-by: David Benjamin <davidben@google.com> commit 3426d1011946b26ff1bb2fd98a081ba4753c9cc8 Author: Brian Smith <brian@briansmith.org> Date: Thu Mar 17 16:10:04 2016 -1000 Convert RSA blinding to use Montgomery multiplication. |BN_mod_mul_montgomery| has better constant-time behavior (usually) than |BN_mod_mul| and |BN_mod_sqr| and on platforms where we have assembly language optimizations (when |OPENSSL_BN_ASM_MONT| is set in crypto/bn/montgomery.c) it is faster. While doing so, reorder and rename the |BN_MONT_CTX| parameters of the blinding functions to match the order normally used in Montgomery math functions. As a bonus, remove a redundant copy of the RSA public modulus from the |BN_BLINDING| structure, which reduces memory usage. Change-Id: I70597e40246429c7964947a1dc46d0d81c7530ef Reviewed-on: https://boringssl-review.googlesource.com/7524 Reviewed-by: David Benjamin <davidben@google.com> commit feaa57d13daa0b5bf3c068ce18d24870d50bfae9 Author: David Benjamin <davidben@google.com> Date: Tue Mar 29 14:17:27 2016 -0400 Only call thread-local destructors on DLL_THREAD_DETACH. In VS2015's debug runtime, the C runtime has been unloaded by the time DLL_PROCESS_DETACH is called and things crash. Instead, don't run destructors at that point. This means we do *not* free memory associated with any remaining thread-locals on application shutdown, only shutdown of individual threads. This is actually desirable since it's consistent with pthreads. If an individual thread calls pthread_exit, destructors are run. If the entire process exits, they are not. (It's also consistent with thread_none.c which never bothers to free anything.) BUG=chromium:595795 Change-Id: I3e64d46ea03158fefff583c1e3e12dfa0c0e172d Reviewed-on: https://boringssl-review.googlesource.com/7601 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 1e4ae00ac2beb893aa59b9a98eb70908332904ba Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 18:56:10 2016 -0400 Add a comment about final empty extension intolerance. We reordered extensions some time ago to ensure a non-empty extension was last, but the comment was since lost (or I forgot to put one in in the first place). Add one now so we don't regress. Change-Id: I2f6e2c3777912eb2c522a54bbbee579ee37ee58a Reviewed-on: https://boringssl-review.googlesource.com/7570 Reviewed-by: David Benjamin <davidben@google.com> commit 44477c03b96d2ca8f25111ef25e71e6405ee4f22 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 18:12:13 2016 -1000 Fix |BN_CTX_get| error checking in |BN_from_montgomery|. In the case |BN_CTX_get| failed, the function returned without calling |BN_CTX_end|. Fix that. Change-Id: Ia24cba3256e2cec106b539324e9679d690048780 Reviewed-on: https://boringssl-review.googlesource.com/7592 Reviewed-by: David Benjamin <davidben@google.com> commit 9d354693ff3365f2fb0a7848dc19c6a06db0cb4f Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 23:09:26 2016 -1000 Small tweak to P-256-x86-64 inversion. Change-Id: I2a55db93e6140a0adc741b4ee5ee090d524605e0 Reviewed-on: https://boringssl-review.googlesource.com/7593 Reviewed-by: David Benjamin <davidben@google.com> commit 040ff622dcf2e7cea2bc1f8d16f6e7a22500f758 Author: David Benjamin <davidben@google.com> Date: Mon Mar 28 13:54:48 2016 -0400 Remove duplicate BN_from_montgomery_word implementation. It looks like we started reformatting that function and adding curly braces, etc., but forget to finish it. This is corroborated by the diff. Although git thinks I removed the EAY-style one and tweaked the #if-0'd one, I actually clang-formatted the EAY-style one anew and deleted the #if-0'd one after tweaking the style to match. Only difference is the alignment stuff is uintptr_t rather than intptr_t since the old logic was using unsigned arithmetic. Change-Id: Ia244e4082a6b6aed3ef587d392d171382c32db33 Reviewed-on: https://boringssl-review.googlesource.com/7574 Reviewed-by: David Benjamin <davidben@google.com> commit 95cc3bea3b4817698ab0f62a29c906e7c85b8796 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 11 13:19:14 2016 -1000 Remove dead code from |ec_GFp_mont_point_get_affine_coordinates|. This code is only used in ec_montgomery.c, so |field_encode| and |field_decode| are never NULL. Change-Id: I42a3ad5744d4ed6f0be1707494411e7efcf930ff Reviewed-on: https://boringssl-review.googlesource.com/7585 Reviewed-by: David Benjamin <davidben@google.com> commit a00f8454341f9d089da96e8cd3960d926e8c6599 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 11 13:12:11 2016 -1000 Move & rename |ec_GFp_simple_point_get_affine_coordinates|. It is only used in ec_montgomery.c, so move it there. Change-Id: Ib189d5579d6363bdc1da89b775ad3df824129758 Reviewed-on: https://boringssl-review.googlesource.com/7584 Reviewed-by: David Benjamin <davidben@google.com> commit b7c5e84847f6b92aee8d5825cd46d316db318a00 Author: David Benjamin <davidben@google.com> Date: Mon Mar 28 09:59:10 2016 -0400 Fix some malloc test failures. These only affect the tests. Change-Id: If22d047dc98023501c771787b485276ece92d4a2 Reviewed-on: https://boringssl-review.googlesource.com/7573 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit e29ea166a6ec44bbfce81d1c93f064b9aca0f443 Author: David Benjamin <davidben@google.com> Date: Wed Mar 23 16:10:44 2016 -0400 Use ssl3_is_version_enabled to skip offering sessions. We do an ad-hoc upper-bound check, but if the version is too low, we also shouldn't offer the session. This isn't fatal to the connection and doesn't have issues (we'll check the version later regardless), but offering a session we're never going to accept is pointless. The check should match what we do in ServerHello. Credit to Matt Caswell for noticing the equivalent issue in an OpenSSL pull request. Change-Id: I17a4efd37afa63b34fca53f4c9b7ac3ae2fa3336 Reviewed-on: https://boringssl-review.googlesource.com/7543 Reviewed-by: David Benjamin <davidben@google.com> commit 762e1d039c1d85e4651700eed82801878a9a86bc Author: David Benjamin <davidben@google.com> Date: Thu Mar 24 20:40:22 2016 -0400 Import chacha-x86.pl fix. Patch from https://mta.openssl.org/pipermail/openssl-dev/2016-March/005625.html. Upstream has yet to make a decision on aliasing requirements for their assembly. If they choose to go with the stricter aliasing requirement rather than land this patch, we'll probably want to tweak EVP_AEAD's API guarantees accordingly and then undiverge. In the meantime, import this to avoid a regression on x86 from when we had compiler-vectorized code on GCC platforms. Per our assembly coverage tools and pending multi-CPU-variant tests, we have good coverage here. Unlike Poly1305 (which is currently waiting on yet another upstream bugfix), where there is risk of missed carries everywhere, it is much more difficult to accidentally make a ChaCha20 implementation that fails based on the data passed into it. This restores a sizeable speed improvement on x86. Before: Did 1131000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000205us (1130768.2 ops/sec): 18.1 MB/s Did 161000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1006136us (160018.1 ops/sec): 216.0 MB/s Did 28000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1023264us (27363.4 ops/sec): 224.2 MB/s Did 1166000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000447us (1165479.0 ops/sec): 18.6 MB/s Did 160000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1004818us (159232.8 ops/sec): 215.0 MB/s Did 30000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1016977us (29499.2 ops/sec): 241.7 MB/s After: Did 2208000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000031us (2207931.6 ops/sec): 35.3 MB/s Did 402000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1001717us (401310.9 ops/sec): 541.8 MB/s Did 97000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1005394us (96479.6 ops/sec): 790.4 MB/s Did 2444000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000089us (2443782.5 ops/sec): 39.1 MB/s Did 459000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1000563us (458741.7 ops/sec): 619.3 MB/s Did 97000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1007942us (96235.7 ops/sec): 788.4 MB/s Change-Id: I976da606dae062a776e0cc01229ec03a074035d1 Reviewed-on: https://boringssl-review.googlesource.com/7561 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 17d729e61b9193c16f45c344d96b8c3537a5aada Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 18:07:18 2016 -0400 Remove unnecessary include. Change-Id: I24d0179ca5019e82ca1494c8773f373f8c09ce82 Reviewed-on: https://boringssl-review.googlesource.com/7566 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 2aca226412fd3b5f1bd0bb3daddfe6c89f0d05f0 Author: David Benjamin <davidben@google.com> Date: Sun Mar 27 10:34:01 2016 -0400 Fix typo in comment. Change-Id: I0effe99d244c4ccdbb0e34db6e01a59c9463cb15 Reviewed-on: https://boringssl-review.googlesource.com/7572 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit baca950e8e1de1399849d54a827b89fc24c1da14 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 01:29:44 2016 -0500 Remove in_handshake. The removes the last of OpenSSL's variables that count occurrences of a function on the stack. Change-Id: I1722c6d47bedb47b1613c4a5da01375b5c4cc220 Reviewed-on: https://boringssl-review.googlesource.com/7450 Reviewed-by: David Benjamin <davidben@google.com> commit c79845c2a8c52c31ccf6ba2fa2a48f1814568fff Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 01:28:00 2016 -0500 Move implicit handshake driving out of read_bytes. This removes the final use of in_handshake. Note that there is still a rentrant call of read_bytes -> handshake_func when we see a HelloRequest. That will need to be signaled up to ssl_read_impl separately out of read_app_data. Change-Id: I823de243f75e6b73eb40c6cf44157b4fc21eb8fb Reviewed-on: https://boringssl-review.googlesource.com/7439 Reviewed-by: David Benjamin <davidben@google.com> commit b2a73188584b6555656c539137052420257c054f Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 01:25:26 2016 -0500 Switch some 0s to NULLs. Change-Id: Id89c982f8f524720f189b528c987c9e58ca06ddf Reviewed-on: https://boringssl-review.googlesource.com/7438 Reviewed-by: David Benjamin <davidben@google.com> commit d7ac1438140d3bb05376d57b0b5d73e53fa11cdc Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 00:41:25 2016 -0500 Lift the handshake driving in write_bytes up to SSL_write. This removes one use of in_handshake and consolidates some DTLS and TLS code. Change-Id: Ibbdd38360a983dabfb7b18c7bd59cb5e316b2adb Reviewed-on: https://boringssl-review.googlesource.com/7435 Reviewed-by: David Benjamin <davidben@google.com> commit 282511d7eb7ef506c68d21be483f888cac913bb9 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 00:23:55 2016 -0500 Consolidate shutdown state. fatal_alert isn't read at all right now, and warn_alert is only checked for close_notify. We only need three states: - Not shutdown. - Got a fatal alert (don't care which). - Got a warning close_notify. Leave ssl->shutdown alone for now as it's tied up with SSL_set_shutdown and friends. To distinguish the remaining two, we only need a boolean. Change-Id: I5877723af82b76965c75cefd67ec1f981242281b Reviewed-on: https://boringssl-review.googlesource.com/7434 Reviewed-by: David Benjamin <davidben@google.com> commit a2d4c0c426caf2b212dea39d7bc05868d780eb34 Author: David Benjamin <davidben@google.com> Date: Sun Mar 20 17:53:34 2016 -0400 Work around Android devices without AT_HWCAP2. Some ARMv8 Android devices don't have AT_HWCAP2. This means, when running in 32-bit mode (ARM capability APIs on Linux are different between AArch32 and AArch64), we can't discover the various nice instructions. On a Nexus 6P, this gives a, uh, minor performance win when running in 32-bit mode. Before: Did 1085000 AES-128-GCM (16 bytes) seal operations in 1000003us (1084996.7 ops/sec): 17.4 MB/s Did 60000 AES-128-GCM (1350 bytes) seal operations in 1013416us (59205.7 ops/sec): 79.9 MB/s Did 11000 AES-128-GCM (8192 bytes) seal operations in 1019778us (10786.7 ops/sec): 88.4 MB/s Did 1009000 AES-256-GCM (16 bytes) seal operations in 1000650us (1008344.6 ops/sec): 16.1 MB/s Did 49000 AES-256-GCM (1350 bytes) seal operations in 1015698us (48242.7 ops/sec): 65.1 MB/s Did 9394 AES-256-GCM (8192 bytes) seal operations in 1071104us (8770.4 ops/sec): 71.8 MB/s Did 1557000 SHA-1 (16 bytes) operations in 1000317us (1556506.6 ops/sec): 24.9 MB/s Did 762000 SHA-1 (256 bytes) operations in 1000527us (761598.6 ops/sec): 195.0 MB/s Did 45000 SHA-1 (8192 bytes) operations in 1013773us (44388.6 ops/sec): 363.6 MB/s Did 1459000 SHA-256 (16 bytes) operations in 1000271us (1458604.7 ops/sec): 23.3 MB/s Did 538000 SHA-256 (256 bytes) operations in 1000990us (537467.9 ops/sec): 137.6 MB/s Did 26000 SHA-256 (8192 bytes) operations in 1008403us (25783.3 ops/sec): 211.2 MB/s After: Did 1890000 AES-128-GCM (16 bytes) seal operations in 1000068us (1889871.5 ops/sec): 30.2 MB/s Did 509000 AES-128-GCM (1350 bytes) seal operations in 1000112us (508943.0 ops/sec): 687.1 MB/s Did 110000 AES-128-GCM (8192 bytes) seal operations in 1007966us (109130.7 ops/sec): 894.0 MB/s Did 1960000 AES-256-GCM (16 bytes) seal operations in 1000303us (1959406.3 ops/sec): 31.4 MB/s Did 460000 AES-256-GCM (1350 bytes) seal operations in 1001873us (459140.0 ops/sec): 619.8 MB/s Did 97000 AES-256-GCM (8192 bytes) seal operations in 1005337us (96485.1 ops/sec): 790.4 MB/s Did 1927000 SHA-1 (16 bytes) operations in 1000429us (1926173.7 ops/sec): 30.8 MB/s Did 1151000 SHA-1 (256 bytes) operations in 1000425us (1150511.0 ops/sec): 294.5 MB/s Did 87000 SHA-1 (8192 bytes) operations in 1003089us (86732.1 ops/sec): 710.5 MB/s Did 2357390 SHA-256 (16 bytes) operations in 1000116us (2357116.6 ops/sec): 37.7 MB/s Did 1410000 SHA-256 (256 bytes) operations in 1000176us (1409751.9 ops/sec): 360.9 MB/s Did 101000 SHA-256 (8192 bytes) operations in 1007007us (100297.2 ops/sec): 821.6 MB/s BUG=chromium:596156 Change-Id: Iacc1f8d8a07e991d4615f2e12c5c54923fb31aa2 Reviewed-on: https://boringssl-review.googlesource.com/7507 Reviewed-by: David Benjamin <davidben@google.com> commit 054e151b16be6ada891ee8fd71915088dda30886 Author: David Benjamin <davidben@google.com> Date: Tue Mar 1 17:35:47 2016 -0500 Rewrite ARM feature detection. This removes the thread-unsafe SIGILL-based detection and the multi-consumer-hostile CRYPTO_set_NEON_capable API. (Changing OPENSSL_armcap_P after initialization is likely to cause problems.) The right way to detect ARM features on Linux is getauxval. On aarch64, we should be able to rely on this, so use it straight. Split this out into its own file. The #ifdefs in the old cpu-arm.c meant it shared all but no code with its arm counterpart anyway. Unfortunately, various versions of Android have different missing APIs, so, on arm, we need a series of workarounds. Previously, we used a SIGILL fallback based on OpenSSL's logic, but this is inherently not thread-safe. (SIGILL also does not tell us if the OS knows how to save and restore NEON state.) Instead, base the behavior on Android NDK's cpu-features library, what Chromium currently uses with CRYPTO_set_NEON_capable: - Android before API level 20 does not provide getauxval. Where missing, we can read from /proc/self/auxv. - On some versions of Android, /proc/self/auxv is also not readable, so use /proc/cpuinfo's Features line. - Linux only advertises optional features in /proc/cpuinfo. ARMv8 makes NEON mandatory, so /proc/cpuinfo can't be used without additional effort. Finally, we must blacklist a particular chip because the NEON unit is broken (https://crbug.com/341598). Unfortunately, this means CRYPTO_library_init now depends on /proc being available, which will require some care with Chromium's sandbox. The simplest solution is to just call CRYPTO_library_init before entering the sandbox. It's worth noting that Chromium's current EnsureOpenSSLInit function already depends on /proc/cpuinfo to detect the broken CPU, by way of base::CPU. android_getCpuFeatures also interally depends on it. We were already relying on both of those being stateful and primed prior to entering the sandbox. BUG=chromium:589200 Change-Id: Ic5d1c341aab5a614eb129d8aa5ada2809edd6af8 Reviewed-on: https://boringssl-review.googlesource.com/7506 Reviewed-by: David Benjamin <davidben@google.com> commit dc6c1b83819cb3788c60dd669241adc6752a4604 Author: Brian Smith <brian@briansmith.org> Date: Sun Jan 17 22:21:42 2016 -1000 Fix build when using Visual Studio 2015 Update 1. Many of the compatibility issues are described at https://msdn.microsoft.com/en-us/library/mt612856.aspx. The macros that suppressed warnings on a per-function basis no longer work in Update 1, so replace them with #pragmas. Update 1 warns when |size_t| arguments to |printf| are casted, so stop doing that casting. Unfortunately, this requires an ugly hack to continue working in MSVC 2013 as MSVC 2013 doesn't support "%zu". Finally, Update 1 has new warnings, some of which need to be suppressed. --- Updated by davidben to give up on suppressing warnings in crypto/x509 and crypto/x509v3 as those directories aren't changed much from upstream. In each of these cases, upstream opted just blindly initialize the variable, so do the same. Also switch C4265 to level 4, per Microsoft's recommendation and work around a bug in limits.h that happens to get fixed by Google include order style. (limits.h is sensitive to whether corecrt.h, pulled in by stddef.h and some other headers, is included before it. The reason it affected just one file is we often put the file's header first, which means base.h is pulling in stddef.h. Relying on this is ugly, but it's no worse than what everything else is doing and this doesn't seem worth making something as tame as limits.h so messy to use.) Change-Id: I02d1f935356899f424d3525d03eca401bfa3e6cd Reviewed-on: https://boringssl-review.googlesource.com/7480 Reviewed-by: David Benjamin <davidben@google.com> commit db50299b247bb7eab4df8c8fdd82fc727e8f67c8 Author: David Benjamin <davidben@google.com> Date: Fri Mar 25 16:18:19 2016 -0400 Add tests for RSA objects with only n and d. Conscrypt, thanks to Java's RSAPrivateKeySpec API, must be able to use RSA keys with only modulus and exponent. This is kind of silly and breaks the blinding code so they, both in OpenSSL and BoringSSL, had to explicitly turn blinding off. Add a test for this as we're otherwise sure to break it on accident. We may wish to avoid the silly rsa->flags modification, I'm not sure. For now, keep the requirement in so other consumers do not accidentally rely on this. (Also add a few missing ERR_clear_error calls. Functions which are expected to fail should be followed by an ERR_clear_error so later unexpected failures don't get confused.) BUG=boringssl:12 Change-Id: I674349821f1f59292b8edd085f21dc37e8bcaa75 Reviewed-on: https://boringssl-review.googlesource.com/7560 Reviewed-by: David Benjamin <davidben@google.com> commit cbf56a5683ddda831ff91c46ea48d1fba545db66 Author: Brian Smith <brian@briansmith.org> Date: Mon Mar 21 11:25:39 2016 -1000 Clarify lifecycle of |BN_BLINDING|. In |bn_blinding_update| the condition |b->e != NULL| would never be true (probably), but the test made reasoning about the correctness of the code confusing. That confusion was amplified by the circuitous and unusual way in which |BN_BLINDING|s are constructed. Clarify all this by simplifying the construction of |BN_BLINDING|s, making it more like the construction of other structures. Also, make counter unsigned as it is no longer ever negative. Change-Id: I6161dcfeae19a80c780ccc6762314079fca1088b Reviewed-on: https://boringssl-review.googlesource.com/7530 Reviewed-by: David Benjamin <davidben@google.com> commit 24493a4ff4909616b6d95ad1e968ff485af0d4c4 Author: Brian Smith <brian@briansmith.org> Date: Fri Mar 25 09:12:48 2016 -1000 Always cache Montgomery contexts in RSA. Simplify the code by always caching Montgomery contexts in the RSA structure, regardless of the |RSA_FLAG_CACHE_PUBLIC| and |RSA_FLAG_CACHE_PRIVATE| flags. Deprecate those flags. Now that we do this no more than once per key per RSA exponent, the private key exponents better because the initialization of the Montgomery contexts isn't perfectly side-channel protected. Change-Id: I4fbcfec0f2f628930bfeb811285b0ae3d103ac5e Reviewed-on: https://boringssl-review.googlesource.com/7521 Reviewed-by: David Benjamin <davidben@google.com> commit 4339552fbb2257156ce5c5bf49da2614d7c5a9a9 Author: David Benjamin <davidben@google.com> Date: Thu Mar 17 16:10:58 2016 -0400 Flip the arguments to ExpectBytesEqual in poly1305_test. The function wants the expected value first. Change-Id: I6d3e21ebfa55d6dd99a34fe8380913641b4f5ff6 Reviewed-on: https://boringssl-review.googlesource.com/7501 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 270f0a77617ef2a00eb3e3a50a00f2fe58827e38 Author: David Benjamin <davidben@google.com> Date: Thu Mar 17 14:41:36 2016 -0400 Print an error if no tests match in runner. Otherwise it's confusing if you mistype the test name. Change-Id: Idf32081958f85f3b5aeb8993a07f6975c27644f8 Reviewed-on: https://boringssl-review.googlesource.com/7500 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 4c34026d12eb92406d07ef15f9a151f3913098e9 Author: David Benjamin <davidben@google.com> Date: Thu Mar 17 16:27:41 2016 -0400 Fix poly1305-x86.pl. Imported from patch attached to https://rt.openssl.org/Ticket/Display.html?id=4439. But with the extra vs $extra typo fixed. The root problem appears to be that lazy_reduction tries to use paddd instead of paddq when they believe the sum will not overflow a u32. In the final call to lazy_reduction, this is not true. svaldez and I attempted to work through the bounds, but the bounds derived from the cited paper imply paddd is always fine. Empirically in a debugger, the bounds are exceeded in the test case. I requested more comments from upstream on the bug. When upstream lands their final fix (hopefully with comments), I will update this code. In the meantime, let's stop carrying known-broken stuff. (vlazy_reduction is probably something similar, but since we don't enable that code, we haven't bothered analyzing it.) Also add the smaller of the two test cases that catch the bug. (The other uses an update pattern which isn't quite what poly1305_test does.) Change-Id: I446ed47c21f10b41a0745de96ab119a3f6fd7801 Reviewed-on: https://boringssl-review.googlesource.com/7544 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit fdb88ba2e9ae9e4ebc8c2053ae53160e048efa57 Author: Piotr Sikora <piotrsikora@google.com> Date: Wed Mar 23 18:34:10 2016 -0700 Fix build with -Wwrite-strings. Change-Id: If76154c8d255600e925a408acdc674fc7dad0359 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7526 Reviewed-by: David Benjamin <davidben@google.com> commit 897be6afe34d1c5839e5bba8f2c67d56485d6a5d Author: Matt Mueller <mattm@google.com> Date: Wed Mar 23 12:06:12 2016 -0700 Add CBS_ASN1_UTF8STRING define. Change-Id: I34384feb46c15c4f443f506d724ad500a4cf0f36 Reviewed-on: https://boringssl-review.googlesource.com/7525 Reviewed-by: David Benjamin <davidben@google.com> commit 0a0f83d308f30f71af115960af7dda064ad734a4 Author: Steven Valdez <svaldez@google.com> Date: Tue Mar 22 17:32:45 2016 -0400 Fixing assembly coverage We failed to correctly parse files that executed from the very start of the file due to a missing '- line XXX'. We now use the 'Ir' indicator to recognize the beginning of a file. Change-Id: I529fae9458ac634bf7bf8af61ef18f080e808535 Reviewed-on: https://boringssl-review.googlesource.com/7542 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit afd6d9d61aa27cdba0506f9525e32823e543ba6e Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 15 13:32:46 2016 -1000 Use |size_t| and |int| consistently in p{224,256}-64.c. Use |size_t| for array indexes. Use |int| for boolean flags. Declare the variables that had their types changed closer to where they are used. Previously, some `for` loops depended on `i` being signed, so their structure had to be changed to work with the unsigned type. Change-Id: I247e4f04468419466733b6818d81d28666da0ad3 Reviewed-on: https://boringssl-review.googlesource.com/7468 Reviewed-by: David Benjamin <davidben@google.com> commit 9539ebbf7042f8eaf8c6ddac25ad01aa4017634e Author: David Benjamin <davidben@google.com> Date: Mon Mar 21 18:24:53 2016 -0400 Update FUZZING documentation about max_len. Maintain the max_len values in foo.options files which ClusterFuzz can process. Also recompute the recommended client and server lengths as they've since gotten much more extensive. Change-Id: Ie87a80d8a4a0c41e215f0537c8ccf82b38c4de09 Reviewed-on: https://boringssl-review.googlesource.com/7509 Reviewed-by: Mike Aizatsky <aizatsky@chromium.org> Reviewed-by: David Benjamin <davidben@google.com> commit 78f8aabe44da43d03ecf82d8d81f4251cd4bfe4a Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 16:33:58 2016 -0500 ssl->ctx cannot be NULL. Most code already dereferences it directly. Change-Id: I227fa91ecbf25a19077f7cfba21b0abd2bc2bd1d Reviewed-on: https://boringssl-review.googlesource.com/7422 Reviewed-by: David Benjamin <davidben@google.com> commit c087c332f89b86b7fc6768e461c97a5ef24b1670 Author: Steven Valdez <svaldez@google.com> Date: Tue Mar 22 11:14:22 2016 -0400 Fix potential double free in EVP_DigestInit_ex There is a potential double free in EVP_DigestInit_ex. This is believed to be reached only as a result of programmer error - but we should fix it anyway. (Imported from upstream's e78dc7e279ed98e1ab9845a70d14dafdfdc88f58) Change-Id: I1da7be7db7afcbe9f30f168df000d64ed73d7edd Reviewed-on: https://boringssl-review.googlesource.com/7541 Reviewed-by: David Benjamin <davidben@google.com> commit be1224882962b63b716ef717377db75f0a805de5 Author: David Benjamin <davidben@google.com> Date: Mon Mar 21 18:32:16 2016 -0400 Fix aarch64 build. We recently gained -Werror=missing-prototypes. (See also, we really need to get those Android bots...) Change-Id: I3962d3050bccf5f5a057d029b5cbff1695ca1a03 Reviewed-on: https://boringssl-review.googlesource.com/7540 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 95b97693403d5c8f09b2870ad9a6d7d198246da4 Author: Brian Smith <brian@briansmith.org> Date: Sun Mar 20 00:33:11 2016 -1000 Fix error handling in |bn_blinding_update|. The fields of the |bn_blinding_st| are not updated atomically. Consequently, one field (|A| or |Ai|) might get updated while the other field (|Ai| or |A|) doesn't get updated, if an error occurs in the middle of updating. Deal with this by reseting the counter so that |A| and |Ai| will both get recreated the next time the blinding is used. Fix a separate but related issue by resetting the counter to zero after calling |bn_blinding_create_param| only if |bn_blinding_create_param| succeeded. Previously, regardless of whether an error occured in |bn_blinding_create_param|, |b->counter| would get reset to zero. The consequence of this was that potentially-bad blinding values would get used 32 times instead of (32 - |b->counter|) times. Change-Id: I236cdb6120870ef06cba129ed86619f593cbcf3d Reviewed-on: https://boringssl-review.googlesource.com/7520 Reviewed-by: David Benjamin <davidben@google.com> commit e11988f5116831969af56d1ffeaa8b82ad19ef2e Author: David Benjamin <davidben@google.com> Date: Mon Mar 21 15:55:19 2016 -0400 Tweak FUZZING.md and minimise_corpuses.sh. Change-Id: If312ce3783bcc39ebd2047470251334aa0897d3d Reviewed-on: https://boringssl-review.googlesource.com/7508 Reviewed-by: David Benjamin <davidben@google.com> commit fdc955cf14c79fb5399652f3a166e7fc4dec0767 Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 15 13:10:11 2016 -1000 Fix parameter type of p256-64.c's |select_point|. Make it match how it is done in p224-64.c. Note in particular that |size| may be 17, so presumably |pre_comp[16]| is accessed, which one would not expect when it was declared |precomp[16][3]|. Change-Id: I54c1555f9e20ccaacbd4cd75a7154b483b4197b7 Reviewed-on: https://boringssl-review.googlesource.com/7467 Reviewed-by: David Benjamin <davidben@google.com> commit df1201e6eefc920fd70d693db4bfb5f76f177b95 Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 15 15:35:53 2016 -1000 Remove unnecessary |BN_CTX_start|/|BN_CTX_end| in |BN_mod_exp_mont_consttime|. Since the function doesn't call |BN_CTX_get|, it doesn't need to call |BN_CTX_start|/|BN_CTX_end|. Change-Id: I6cb954d3fee2959bdbc81b9b97abc52bb6f7704c Reviewed-on: https://boringssl-review.googlesource.com/7469 Reviewed-by: David Benjamin <davidben@google.com> commit 7cf6085b00e194877b88b72d710d1aea6cb03e20 Author: Brian Smith <brian@briansmith.org> Date: Sat Mar 19 22:39:37 2016 -1000 Check for |BN_CTX_new| failure in |mod_exp|. As far as I can tell, this is the last place within libcrypto where this type of check is missing. Change-Id: I3d09676abab8c9f6c4e87214019a382ec2ba90ee Reviewed-on: https://boringssl-review.googlesource.com/7519 Reviewed-by: David Benjamin <davidben@google.com> commit 35673b945dcbf240093f1f0b286e889d31c4d8f9 Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Mar 18 18:25:28 2016 -0700 Build with -Wmissing-prototypes -Wmissing-declarations. Change-Id: Ieba81f114483095f3657e87f669c7562ff75b58c Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7516 Reviewed-by: David Benjamin <davidben@google.com> commit f932894c7f379a74327afca6bd283d842f2ebee2 Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Mar 18 18:24:50 2016 -0700 Move function declarations to internal header. Partially fixes build with -Wmissing-declarations. Change-Id: Ia563063fb077cda79244c21f02fd1c0f550353c2 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7515 Reviewed-by: David Benjamin <davidben@google.com> commit f188f9dce8878bd4ac7f1d792b34a15c1496ff3e Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Mar 18 18:23:50 2016 -0700 Fix typo in function name. Partially fixes build with -Wmissing-prototypes. Change-Id: I828bcfb49b23c5a9ea403038bc3fb76750556ef8 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7514 Reviewed-by: David Benjamin <davidben@google.com> commit cd4cf9a12eceaeb22460c3d45d53fd067508fc39 Author: David Benjamin <davidben@google.com> Date: Sun Mar 20 12:45:54 2016 -0400 Fix Windows build Change-Id: I66ecb9f89ec13e432e888e3825d01a015b117568 Reviewed-on: https://boringssl-review.googlesource.com/7505 Reviewed-by: David Benjamin <davidben@google.com> commit 8b0fe8c0ac629ed7b87755f2aebb4d07b78c24df Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Mar 18 18:22:54 2016 -0700 Add missing prototypes. Partially fixes build with -Wmissing-prototypes. Change-Id: If04d8fe7cbf068883485e95bd5ea6cdab6743e46 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7513 Reviewed-by: David Benjamin <davidben@google.com> commit c6d3029edaeeb6bab86fcba6ab31bdce77e2ec9c Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Mar 18 17:28:36 2016 -0700 Add missing internal includes. Partially fixes build with -Wmissing-prototypes -Wmissing-declarations. Change-Id: I51209c30f532899f57cfdd9a50cff0a8ee3da5b5 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7512 Reviewed-by: David Benjamin <davidben@google.com> commit 9bb8ba6ba1a865bd7e55ccf494d082b1bc027734 Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Mar 18 18:19:04 2016 -0700 Make local functions static. Partially fixes build with -Wmissing-prototypes -Wmissing-declarations. Change-Id: I6048f5b7ef31560399b25ed9880156bc7d8abac2 Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7511 Reviewed-by: David Benjamin <davidben@google.com> commit 537cfc37b82f91f1006596317ba544e4be1a5c8e Author: Piotr Sikora <piotrsikora@google.com> Date: Fri Mar 18 15:53:29 2016 -0700 Use UINT64_C instead of unsigned long long integer constant. Change-Id: I44aa9be26ad9aea6771cb46a886a721b4bc28fde Signed-off-by: Piotr Sikora <piotrsikora@google.com> Reviewed-on: https://boringssl-review.googlesource.com/7510 Reviewed-by: David Benjamin <davidben@google.com> commit 594e7d2b7703a6c231264edf6b03460b018d2200 Author: David Benjamin <davidben@google.com> Date: Thu Mar 17 17:49:56 2016 -0400 Add a test that declining ALPN works. Inspired by https://mta.openssl.org/pipermail/openssl-dev/2016-March/006150.html Change-Id: I973b3baf054ed1051002f7bb9941cb1deeb36d78 Reviewed-on: https://boringssl-review.googlesource.com/7504 Reviewed-by: David Benjamin <davidben@google.com> commit f277add6c2de55286f0d13edebf41929e4970d5a Author: David Benjamin <davidben@google.com> Date: Wed Mar 9 14:38:24 2016 -0500 Run ripemd_test as part of all_tests.go. Change-Id: I9c5e66c34d0f1b735c69d033daee5d312e3c2fe7 Reviewed-on: https://boringssl-review.googlesource.com/7410 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 110fcc960757d7aeb7760359800b8f5646dc70ca Author: David Benjamin <davidben@google.com> Date: Wed Mar 16 15:43:15 2016 -0400 poly1305/asm/poly1305-x86_64.pl: make it work with linux-x32. (Imported from upstream's 2460c7f13389d766dd65fa4e14b69b6fbe3e4e3b.) This is a no-op for us, but avoid a diff with upstream. Change-Id: I6e875704a38dcd9339371393a4dd523647aeef44 Reviewed-on: https://boringssl-review.googlesource.com/7491 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit eebfd896fe178b4ca78bbd8064944a5b31a27667 Author: David Benjamin <davidben@google.com> Date: Mon Mar 14 19:23:58 2016 -0400 Don't shift serial number into sign bit (Imported from upstream's 01c32b5e448f6d42a23ff16bdc6bb0605287fa6f.) Change-Id: Ib52278dbbac1ed1ad5c80f0ad69e34584d411cec Reviewed-on: https://boringssl-review.googlesource.com/7461 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 8d5717b019b5540a72dceefd747d02a72d539dda Author: David Benjamin <davidben@google.com> Date: Mon Mar 14 19:18:14 2016 -0400 perlasm/x86_64-xlate.pl: handle binary constants early. Not all assemblers of "gas" flavour handle binary constants, e.g. seasoned MacOS Xcode doesn't, so give them a hand. (Imported from upstream's ba26fa14556ba49466d51e4d9e6be32afee9c465.) Change-Id: I35096dc8035e06d2fbef2363b869128da206ff9d Reviewed-on: https://boringssl-review.googlesource.com/7459 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 51545ceac659fe30e245c6e992e7fd45b00e8f16 Author: David Benjamin <davidben@google.com> Date: Wed Mar 16 19:53:34 2016 -0400 Remove a number of unnecessary stdio.h includes. Change-Id: I6267c9bfb66940d0b6fe5368514210a058ebd3cc Reviewed-on: https://boringssl-review.googlesource.com/7494 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit b371f1b9ddd8ed519b4ab74b8860aea317e943fa Author: David Benjamin <davidben@google.com> Date: Tue Mar 15 18:06:13 2016 -0400 Include time.h in time_support.h. For time_t and struct tm. BUG=595118 Change-Id: I6c7f05998887ed2bd3fb56c83ac543894ef27fe6 Reviewed-on: https://boringssl-review.googlesource.com/7462 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: Nico Weber <thakis@chromium.org> Reviewed-by: David Benjamin <davidben@google.com> commit 9aa1562843fbe63bc520c513222d0100a2085780 Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 15 13:00:49 2016 -1000 Remove unnecessary type casts in crypto/rsa. Change-Id: I0b5c661674fbcaf6b4d5b0ce7944459cd45606b1 Reviewed-on: https://boringssl-review.googlesource.com/7466 Reviewed-by: David Benjamin <davidben@google.com> commit 6f7374b0edf3960eeb292b4af2a4003db395e22d Author: David Benjamin <davidben@google.com> Date: Fri Mar 11 16:08:39 2016 -0500 Restore EC_GROUP_new_by_curve_name and EC_GROUP_set_generator. Having a different API for this case than upstream is more trouble than is worth it. This is sad since the new API avoids incomplete EC_GROUPs at least, but I don't believe supporting this pair of functions will be significantly more complex than supporting EC_GROUP_new_arbitrary even when we have static EC_GROUPs. For now, keep both sets of APIs around, but we'll be able to remove the scar tissue once Conscrypt's complex dependencies are resolved. Make the restored EC_GROUP_set_generator somewhat simpler than before by removing the ability to call it multiple times and with some parameters set to NULL. Keep the test. Change-Id: I64e3f6a742678411904cb15c0ad15d56cdae4a73 Reviewed-on: https://boringssl-review.googlesource.com/7432 Reviewed-by: David Benjamin <davidben@google.com> commit 5c05648b8d048c33105c96a41c48c855c44291f5 Author: Emily Stark <estark@google.com> Date: Tue Mar 15 11:40:10 2016 -0700 Tiny documentation fix for EC_POINT_set_affine_coordinates_GFp Change-Id: Icfd9986272f6e1adba54aa7521c28901fa02dfb7 Reviewed-on: https://boringssl-review.googlesource.com/7470 Reviewed-by: David Benjamin <davidben@google.com> commit a2f2bc3a4062d755644adf0f6dca79903638a283 Author: David Benjamin <davidben@google.com> Date: Mon Mar 14 17:13:54 2016 -0400 Align with upstream's error strings, take two. I messed up a few of these. ASN1_R_UNSUPPORTED_ALGORITHM doesn't exist. X509_R_UNSUPPORTED_ALGORITHM does exist as part of X509_PUBKEY_set, but the SPKI parser doesn't emit this. (I don't mind the legacy code having really weird errors, but since EVP is now limited to things we like, let's try to keep that clean.) To avoid churn in Conscrypt, we'll keep defining X509_R_UNSUPPORTED_ALGORITHM, but not actually do anything with it anymore. Conscrypt was already aware of EVP_R_UNSUPPORTED_ALGORITHM, so this should be fine. (I don't expect EVP_R_UNSUPPORTED_ALGORITHM to go away. The SPKI parsers we like live in EVP now.) A few other ASN1_R_* values didn't quite match upstream, so make those match again. Finally, I got some of the rsa_pss.c values wrong. Each of those corresponds to an (overly specific) RSA_R_* value in upstream. However, those were gone in BoringSSL since even the initial commit. We placed the RSA <-> EVP glue in crypto/evp (so crypto/rsa wouldn't depend on crypto/evp) while upstream placed them in crypto/rsa. Since no one seemed to notice the loss of RSA_R_INVALID_SALT_LENGTH, let's undo all the cross-module errors inserted in crypto/rsa. Instead, since that kind of specificity is not useful, funnel it all into X509_R_INVALID_PSS_PARAMETERS (formerly EVP_R_INVALID_PSS_PARAMETERS, formerly RSA_R_INVALID_PSS_PARAMETERS). Reset the error codes for all affected modules. (That our error code story means error codes are not stable across this kind of refactoring is kind of a problem. Hopefully this will be the last of it.) Change-Id: Ibfb3a0ac340bfc777bc7de6980ef3ddf0a8c84bc Reviewed-on: https://boringssl-review.googlesource.com/7458 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit a5177cb319f5ed5cb28f72bd564b4d6d6d355975 Author: David Benjamin <davidben@google.com> Date: Fri Mar 11 19:38:17 2016 -0500 Use a less tedious pattern for X509_NAME. Also fix a long/unsigned-long cast. (ssl_get_message returns long. It really shouldn't, but ssl_get_message needs much more work than just a long -> size_t change, so leave it as long for now.) Change-Id: Ice8741f62a138c0f35ca735eedb541440f57e114 Reviewed-on: https://boringssl-review.googlesource.com/7457 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 6b6e0b20893e2be0e68af605a60ffa2cbb0ffa64 Author: David Benjamin <davidben@google.com> Date: Fri Mar 11 19:30:29 2016 -0500 Fix a memory leak in ssl3_get_certificate_request. Found by libFuzzer. Change-Id: Ifa343a184cc65f71fb6591d290b2d47d24a2be80 Reviewed-on: https://boringssl-review.googlesource.com/7456 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 15c1488b6177b269a311814b63e670df534549e3 Author: David Benjamin <davidben@google.com> Date: Mon Mar 14 14:25:46 2016 -0400 Clear the error queue on entry to core SSL operations. OpenSSL historically made some poor API decisions. Rather than returning a status enum in SSL_read, etc., these functions must be paired with SSL_get_error which determines the cause of the last error's failure. This requires SSL_read communicate with SSL_get_error with some stateful flag, rwstate. Further, probably as workarounds for bugs elsewhere, SSL_get_error does not trust rwstate. Among other quirks, if the error queue is non-empty, SSL_get_error overrides rwstate and returns a value based on that. This requires that SSL_read, etc., be called with an empty error queue. (Or we hit one of the spurious ERR_clear_error calls in the handshake state machine, likely added as further self-workarounds.) Since requiring callers consistently clear the error queue everywhere is unreasonable (crbug.com/567501), clear ERR_clear_error *once* at the entry point. Until/unless[*] we make SSL_get_error sane, this is the most reasonable way to get to the point that clearing the error queue on error is optional. With those in place, the calls in the handshake state machine are no longer needed. (I suspect all the ERR_clear_system_error calls can also go, but I'll investigate and think about that separately.) [*] I'm not even sure it's possible anymore, thanks to the possibility of BIO_write pushing to the error queue. BUG=567501,593963 Change-Id: I564ace199e5a4a74b2554ad3335e99cd17120741 Reviewed-on: https://boringssl-review.googlesource.com/7455 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit cfa9de85a3f1b5c09fe0087fb94b3b5f7210ba69 Author: David Benjamin <davidben@google.com> Date: Mon Mar 14 14:19:41 2016 -0400 Revert "Revert "Reduce maximum RSA public exponent size to 33 bits."" This reverts commit ba70118d8ea7bb0232554bbd70606703bde5bde3. Reverting this did not resolve the regression and the cause is now known. BUG=593963 Change-Id: Ic5e24b74e8f16b01d9fdd80f267a07ef026c82cf Reviewed-on: https://boringssl-review.googlesource.com/7454 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit fb8e67889792e2a5914bcfdc590c250141645a74 Author: David Benjamin <davidben@google.com> Date: Fri Mar 11 14:39:46 2016 -0500 Match upstream's error codes for the old sigalg code. People seem to condition on these a lot. Since this code has now been moved twice, just make them all cross-module errors rather than leave a trail of renamed error codes in our wake. Change-Id: Iea18ab3d320f03cf29a64a27acca119768c4115c Reviewed-on: https://boringssl-review.googlesource.com/7431 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 3f1904bee1f1a119e48b4827579955cc11733e39 Author: Brian Smith <brian@briansmith.org> Date: Thu Mar 10 17:16:02 2016 -1000 Set |bn->neg| to zero in |bn_set_words|. If the values of any of the coordinates in the output point |r| were negative during nistz256 multiplication, then the calls to |bn_set_word| would result in the wrong coordinates being returned (the negatives of the correct coordinates would be returned instead). Fix that. Change-Id: I6048e62f76dca18f625650d11ef5a051c9e672a4 Reviewed-on: https://boringssl-review.googlesource.com/7442 Reviewed-by: David Benjamin <davidben@google.com> commit 6603b76f7616fe781ec6dcf3d66c82f29d776697 Author: Brian Smith <brian@briansmith.org> Date: Thu Mar 10 16:50:25 2016 -1000 Remove reduction in |ec_GFp_simple_set_Jprojective_coordinates_GFp|. The (internal) constant-time callers of this function already do a constant-time reduction before calling. And, nobody should be calling this function with out-of-range coordinates anyway. So, just require valid coordinates as input. Further, this function is rarely called, so don't bother with the optimization to avoid encoding Montgomery encoding of 1 for the Z coordinate. Change-Id: I637ffaf4d39135ca17214915b9a8582ea052eea8 Reviewed-on: https://boringssl-review.googlesource.com/7441 Reviewed-by: David Benjamin <davidben@google.com> commit 8542daa22d2cade301dfada99748d872a1f577af Author: Brian Smith <brian@briansmith.org> Date: Thu Mar 10 16:46:15 2016 -1000 Require compressed x EC coordinate to be a field element. Don't try to fix a bad |x| coordinate by reducing it. Instead, just fail. This also makes the code clearer; in particular, it was confusing why |x_| was used for some calculations when it seems like |x| was just as good or better. Change-Id: I9a6911f0d2bd72852a26b46f3828eb5ba3ef924f Reviewed-on: https://boringssl-review.googlesource.com/7440 Reviewed-by: David Benjamin <davidben@google.com> commit df28c3acf120361f260c8a91b902e089ff213bb8 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 16:11:51 2016 -0500 Tidy up the client Certificate message skipping slightly. Align all unexpected messages on SSL_R_UNEXPECTED_MESSAGE. Make the SSL 3.0 case the exceptional case. In doing so, make sure the SSL 3.0 SSL_VERIFY_FAIL_IF_NO_PEER_CERT case has its own test as that's a different handshake shape. Change-Id: I1a539165093fbdf33e2c1b25142f058aa1a71d83 Reviewed-on: https://boringssl-review.googlesource.com/7421 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 11d50f94d8742010520ecfc315534e9a39f71375 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 15:55:45 2016 -0500 Include colons in expectedError matches. If we're doing substring matching, we should at least include the delimiter. Change-Id: I98bee568140d0304bbb6a2788333dbfca044114c Reviewed-on: https://boringssl-review.googlesource.com/7420 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 454aa4c25e0cc0a0e95781d715038a16be3c190d Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 08:43:27 2016 -0500 Rewrite ssl3_send_client_certificate. The old logic was quite messy and grew a number of no-ops over the years. It was also unreasonably fond of the variable name |i|. The current logic wasn't even correct. It's overly fond of sending no certificate, even when it pushes errors on the error queue for a fatal error. Change-Id: Ie5b2b38dd309f535af1d17fa261da7dc23185866 Reviewed-on: https://boringssl-review.googlesource.com/7418 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 0b7ca7dc0098f329d6348a45e372bd884f92bc97 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 15:44:22 2016 -0500 Add tests for doing client auth with no certificates. In TLS, you never skip the Certificate message. It may be empty, but its presence is determined by CertificateRequest. (This is sensible.) In SSL 3.0, the client omits the Certificate message. This means you need to probe and may receive either Certificate or ClientKeyExchange (thankfully, ClientKeyExchange is not optional, or we'd have to probe at ChangeCipherSpec). We didn't have test coverage for this, despite some of this logic being a little subtle asynchronously. Fix this. Change-Id: I149490ae5506f02fa0136cb41f8fea381637bf45 Reviewed-on: https://boringssl-review.googlesource.com/7419 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit f41bb59703b5fed45209a608daac1d523072e4de Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 20:10:38 2016 -0500 Remove unused functions. We never heap-allocate a GCM128_CONTEXT. Change-Id: I7e89419ce4d81c1598a4b3a214c44dbbcd709651 Reviewed-on: https://boringssl-review.googlesource.com/7430 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit acb6dccf12f17545c219605d70e12c995018bdcd Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 09:15:01 2016 -0500 Add tests for the old client cert callback. Also add no-certificate cases to the state machine coverage tests. Change-Id: I88a80df6f3ea69aabc978dd356abcb9e309e156f Reviewed-on: https://boringssl-review.googlesource.com/7417 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit a857159dd61204bfe93bd8e2f00448434e8b0b99 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 01:41:55 2016 -0500 Clean up some silly variable names. Change-Id: I5b38e2938811520f52ece6055245248c80308b4d Reviewed-on: https://boringssl-review.googlesource.com/7416 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 08791e6756c3fbee0ef1bdc104a74ab212501bb6 Author: David Benjamin <davidben@google.com> Date: Thu Mar 10 12:41:19 2016 -0500 Appease sanitizers in x25519_ge_scalarmult. Although exactly one iteration of cmov_cached will always initialize selected, it ends up messing with uninitialized memory. Initialize |selected| before the loop. BUG=593540 Change-Id: I5921843f68c6dd1dc7f752538825bc43ba75df4a Reviewed-on: https://boringssl-review.googlesource.com/7415 Reviewed-by: Arnar Birgisson <arnarb@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 97c80512afc7ff8d0afcc806ef6dd936cca752a2 Author: Adam Langley <agl@google.com> Date: Thu Mar 10 09:23:03 2016 -0800 Add |DH_generate_parameters| to decrepit. This makes building OpenLDAP easier. Change-Id: Id64699f95477fb8fb98957027c97070ebf41f4b1 Reviewed-on: https://boringssl-review.googlesource.com/7407 Reviewed-by: David Benjamin <davidben@google.com> commit b8b28a64ff45fd88fd51b7af78452da5b10288f3 Author: Adam Langley <agl@google.com> Date: Thu Mar 10 09:20:47 2016 -0800 Add CRYPTO_[malloc|free|realloc] as aliases for the OPENSSL_𝑥 names. This makes building OpenLDAP easier. Change-Id: Ic1c5bcb2ec35c61c048e780ebc56db033d8382d8 Reviewed-on: https://boringssl-review.googlesource.com/7406 Reviewed-by: David Benjamin <davidben@google.com> commit 8f307d3805db102a5f2afffed821acff6b30c98e Author: David Benjamin <davidben@google.com> Date: Wed Mar 9 18:40:04 2016 -0500 Update cmake-linux64.tar.gz and cmake-mac.tar.gz. Built from: 92c83ad8a4fd6224cf6319a60b399854f55b38ebe9d297c942408b792b1a9efa cmake-3.5.0.tar.gz Update instructions in the UPDATING file. Change-Id: I49d3f5ef353347c446a04797719227e9793e3e0d Reviewed-on: https://boringssl-review.googlesource.com/7414 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 8169df23ddff0169560583052492715590b5c9df Author: David Benjamin <davidben@google.com> Date: Wed Mar 9 18:05:12 2016 -0500 Update Windows tools for the bots. See 0d5e080ab948da74be68e5f9f6c002fedc99a3ec for the previous version. Include instructions on where to get the tools used. 807f96230c889b10f2957a47585426af4cdb116a8a77f1caecca83b7d7ab862b cmake-3.5.0-win32-x86.zip e6bb5c3e4d936bb1067560a58a21260693a0fbe34e55afb0111fe14f7eebc92c strawberry-perl-5.22.1.2-32bit-portable.zip Change-Id: I504cf779abce26087d09c0c974fb481886c9c459 Reviewed-on: https://boringssl-review.googlesource.com/7413 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 659b24d96108bbb45e6c41caef08ce5bfaa05f20 Author: David Benjamin <davidben@google.com> Date: Wed Mar 9 17:46:47 2016 -0500 Update versions of tools in util/bot. Update the easy ones here. Also include instructions on how to do this. The .sha1 files will be updated separately with instructions. Change-Id: I2a3aba43b8ffbdf930b8a2602dc1460077f6d0e7 Reviewed-on: https://boringssl-review.googlesource.com/7412 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 23afa689379b1b5a6a7a98327b847d323141930a Author: David Benjamin <davidben@google.com> Date: Wed Mar 9 15:11:12 2016 -0500 Fix the shared library build. libdecrepit wants some symbols visible. Also a build file typo. Change-Id: I670d2324ab9048f84e7f80afdefc98cbab80335d Reviewed-on: https://boringssl-review.googlesource.com/7411 Reviewed-by: Adam Langley <agl@google.com> commit f284a7dab6fe4fcc3b96a520f93cd79ec4cff2fd Author: Adam Langley <agl@google.com> Date: Wed Mar 9 12:09:00 2016 -0800 Fix Windows build. Windows doesn't like returning void values from void functions. Change-Id: I9fbcb26098a5434ff4e8980f3ed0cd7b2567d658 commit f202d96875d5d66eb8e64a8ed9fd7b0232c7797a Author: Adam Langley <agl@google.com> Date: Wed Mar 9 12:04:55 2016 -0800 Fix bug in obj_decrepit.c Interestingly, Windows caught this with: ..\decrepit\obj\obj_decrepit.c(33) : warning C4090: 'function' : different 'const' qualifiers However, the value of |name| isn't const, only the thing that it points to. So this seems like a bug in MSVC, but I'm ok with it this time. Change-Id: I076f98339cb0b669a4f592fba89aafc0a580efc4 Reviewed-on: https://boringssl-review.googlesource.com/7404 Reviewed-by: David Benjamin <davidben@google.com> commit ef18746ad4421273d051aa32953fe422d7713563 Author: Brian Smith <brian@briansmith.org> Date: Fri Feb 5 14:41:39 2016 -1000 Remove unused code for multiple-point ECC multiplication. The points are only converted to affine form when there are at least three points being multiplied (in addition to the generator), but there never is more than one point, so this is all dead code. Also, I doubt that the comments "...point at infinity (which normally shouldn't happen)" in the deleted code are accurate. And, the projective->affine conversions that were removed from p224-64.c and p256-64.c didn't seem to properly account for the possibility that any of those points were at infinity. Change-Id: I611d42d36dcb7515eabf3abf1857e52ff3b45c92 Reviewed-on: https://boringssl-review.googlesource.com/7100 Reviewed-by: David Benjamin <davidben@google.com> commit a7a226add9a3fb9efc2540d12635683150820f83 Author: Adam Langley <agl@google.com> Date: Tue Mar 8 15:00:18 2016 -0800 Add |OBJ_NAME_do_all_sorted|. This another of those functions that tries to turn C into Python. In this case, implement it in terms of the similar functions in EVP so that at least we only have one list of things. This makes life with nmap easier. Change-Id: I6d01c43f062748d4ba7d7020587c286322e610bb Reviewed-on: https://boringssl-review.googlesource.com/7403 Reviewed-by: David Benjamin <davidben@google.com> commit ff452c1d0e5bf389a112e35dba09a61b424a7d00 Author: Adam Langley <agl@google.com> Date: Tue Mar 8 14:17:02 2016 -0800 Add RIPEMD160 support in decrepit. This version is taken from OpenSSL 1.0.2 with tweaks to support the changes that we have made to md32_common.h. None of the assembly implementations have been imported. This makes supporting nmap easier. Change-Id: Iae9241abdbc9021cc6bc35a65b40c3d739011ccc Reviewed-on: https://boringssl-review.googlesource.com/7402 Reviewed-by: David Benjamin <davidben@google.com> commit d279a21d8c7c39e603dd3d7922afa219fbbc713b Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 8 17:09:40 2016 -1000 Avoid potential uninitialized memory read in crypto/ec/p256-x86_64.c. If the function returns early due to an error, then the coordinates of the result will have their |top| value set to a value beyond what has actually been been written. Fix that, and make it easier to avoid such issues in the future by refactoring the code. As a bonus, avoid a false positive MSVC 64-bit opt build "potentially uninitialized value used" warning. Change-Id: I8c48deb63163a27f739c8797962414f8ca2588cd Reviewed-on: https://boringssl-review.googlesource.com/6579 Reviewed-by: David Benjamin <davidben@google.com> commit 081e3f34a2b324edce50b7a5df9b2e283781af7b Author: Brian Smith <brian@briansmith.org> Date: Wed Nov 25 14:19:21 2015 -1000 Remove |EC_POINT::Z_is_one|. Having |Z_is_one| be out of sync with |Z| could potentially be a very bad thing, and in the past there have been multiple bugs of this sort, including one currently in p256-x86_64.c (type confusion: Montgomery- encoded vs unencoded). Avoid the issue entirely by getting rid of |Z_is_one|. Change-Id: Icb5aa0342df41d6bc443f15f952734295d0ee4ba Reviewed-on: https://boringssl-review.googlesource.com/6576 Reviewed-by: David Benjamin <davidben@google.com> commit bfb38b1a3c5e37d43188bbd02365a87bebc8d122 Author: Adam Langley <agl@google.com> Date: Tue Mar 8 14:15:35 2016 -0800 Add |RC4_options| to decrepit. I've no idea who thought that this function was a good idea in the first place, but including it in decrepit makes supporting nmap easier. Change-Id: I7433cda6a6ddf1cc545126edf779625e9fc70ada Reviewed-on: https://boringssl-review.googlesource.com/7401 Reviewed-by: David Benjamin <davidben@google.com> commit a34a5aacffa98941fed0abe19dc1bb29e9c1c4ef Author: Adam Langley <agl@google.com> Date: Tue Mar 8 14:11:48 2016 -0800 Add one-shot |MD4| function. This could live in decrepit, but it's tiny and having it makes the interface more uniform that what we have for MD5 so I put it in the main code. This is to more easily support nmap. Change-Id: Ia098cc7ef6e00a90d2f3f56ee7deba8329c9a82e Reviewed-on: https://boringssl-review.googlesource.com/7400 Reviewed-by: David Benjamin <davidben@google.com> commit ba70118d8ea7bb0232554bbd70606703bde5bde3 Author: David Benjamin <davidben@google.com> Date: Tue Mar 8 18:03:31 2016 -0500 Revert "Reduce maximum RSA public exponent size to 33 bits." This reverts commit b944882f26d64881161622b6c708568ff67483dd. Recent Chrome canaries show a visible jump in ERR_SSL_PROTOCOL_ERROR which coincided with a DEPS roll that included this change. Speculatively revert it to see if they go back down afterwards. Change-Id: I067798db144c348d666985986dfb9720d1153b7a Reviewed-on: https://boringssl-review.googlesource.com/7391 Reviewed-by: David Benjamin <davidben@google.com> commit 617804adc5cd6760a3febcd9d4408fbfc6ebcd0c Author: Brian Smith <brian@briansmith.org> Date: Mon Feb 8 20:36:51 2016 -1000 Always use |BN_mod_exp_mont|/|BN_mod_exp_mont_consttime| in RSA. This removes a hard dependency on |BN_mod_exp|, which will allow the linker to drop it in programs that don't use other features that require it. Also, remove the |mont| member of |bn_blinding_st| in favor of having callers pass it when necssaary. The |mont| member was a weak reference, and weak references tend to be error-prone. Finally, reduce the scope of some parts of the blinding code to |static|. Change-Id: I16d8ccc2d6d950c1bb40377988daf1a377a21fe6 Reviewed-on: https://boringssl-review.googlesource.com/7111 Reviewed-by: David Benjamin <davidben@google.com> commit 3ed5977cbb14d82bc2c2e9b3cd717ba1235cdefd Author: David Benjamin <davidben@google.com> Date: Tue Mar 8 12:50:21 2016 -0500 Add an idle timeout to runner.go. If a Read or Write blocks for too long, time out the operation. Otherwise, some kinds of test failures result in hangs, which prevent the test harness from progressing. (Notably, OpenSSL currently has a lot of those failure modes and upstream expressed interest in being able to run the tests to completion.) Go's APIs want you to send an absolute timeout, to avoid problems when a Read is split into lots of little Reads. But we actively want the timer to reset in that case, so this needs a trivial adapter. The default timeout is set at 15 seconds for now. If this becomes a problem, we can extend it or build a more robust deadlock detector given an out-of-band channel (shim tells runner when it's waiting on data, abort if we're also waiting on data at the same time). But I don't think we'll need that complexity. 15 seconds appears fine for both valgrind and running tests on a Nexus 4. BUG=460189 Change-Id: I6463fd36058427d883b526044da1bbefba851785 Reviewed-on: https://boringssl-review.googlesource.com/7380 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 3d38c03a8e2011e1d2801c389fc481c8ba9841d6 Author: David Benjamin <davidben@google.com> Date: Tue Mar 8 16:04:50 2016 -0500 Fix a few more missing CBB_cleanups. See also 1b0c438e1a0e570de18ecc7aabda3be8dea4cfa0. Change-Id: Ifcfe15caa4d0db8ef725f8dacd0e8c5c94b00a09 Reviewed-on: https://boringssl-review.googlesource.com/7390 Reviewed-by: Emily Stark (Dunn) <estark@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit f945952d5779bf7e2b38297cad29d1efb61f5911 Author: David Benjamin <davidben@google.com> Date: Mon Mar 7 15:30:26 2016 -0500 Add a script to run tests on Android. The bots will likely use different infrastructure (I expect I'll need to write an isolate file and such). In the meantime, make it easier to run tests manually. BUG=487432 Change-Id: I0e10b23e5f3eb1c5cd60fb88f21ba4a8385b979e Reviewed-on: https://boringssl-review.googlesource.com/7334 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit dfd6fe4f9545a8fd55b65c99e5a04eb06f9f3600 Author: David Benjamin <davidben@google.com> Date: Mon Mar 7 21:41:13 2016 -0500 Add a PULL_REQUEST_TEMPLATE. Now that we have a GitHub mirror, set up a PULL_REQUEST_TEMPLATE so people know not to file pull requests against us. Text borrowed from Go's version of this file. Change-Id: I7da127fbf36eb3a7cb68e3a91cc9dfbb7fc92155 Reviewed-on: https://boringssl-review.googlesource.com/7370 Reviewed-by: Adam Langley <agl@google.com> commit cdd7048358b524567734eb5fc283cc9f42005686 Author: Adam Langley <agl@google.com> Date: Mon Mar 7 17:53:10 2016 -0800 Fix windows build. Windows doesn't like struct literals: ..\decrepit\dsa\dsa_decrepit.c(85) : warning C4204: nonstandard extension used : non-constant aggregate initializer Change-Id: I12541f2883ecbb10c85cddfae8d2adbbb1365ae3 Reviewed-on: https://boringssl-review.googlesource.com/7364 Reviewed-by: Adam Langley <agl@google.com> commit 6e96eaebe016804a96aa99c8a06a2654103f8de6 Author: Adam Langley <agl@google.com> Date: Mon Mar 7 17:07:54 2016 -0800 Add |X509_EXT_conf_nid| to decrepit. This function is a deprecated version of |X509_EXT_nconf_nid| that takes a hash of |CONF_VALUE|s directly rather than a |CONF|. Change-Id: I5fd1025b31d73b988d9298b2624453017dd34ff4 Reviewed-on: https://boringssl-review.googlesource.com/7363 Reviewed-by: David Benjamin <davidben@google.com> commit 8ba4b2d5bf812eae838796266b1d01aa363a8dcf Author: Adam Langley <agl@google.com> Date: Mon Mar 7 16:35:18 2016 -0800 Add |RSA_[padding_add|verify]_PKCS1_PSS to decrepit. These functions are just like the _mgf1 versions but omit one of the parameters. It's easier to add them than to patch the callers in some cases. Change-Id: Idee5b81374bf15f2ea89b7e0c06400c2badbb275 Reviewed-on: https://boringssl-review.googlesource.com/7362 Reviewed-by: David Benjamin <davidben@google.com> commit 4435e96b08c3cacdde5bb12a2f1aa82aa87a9516 Author: Adam Langley <agl@google.com> Date: Mon Mar 7 16:16:13 2016 -0800 Include buffer.h from bio.h. We shouldn't really have to do this, but there's a lot of code that doesn't always include what it uses. In this case, since bio.h references |BUF_MEM| in function signatures, it seems a little less distasteful. Change-Id: Ifb50f8bce40639f977b4447404597168a68c8388 Reviewed-on: https://boringssl-review.googlesource.com/7361 Reviewed-by: David Benjamin <davidben@google.com> commit 99a24ba0f14c1eb87b6ebc4c4de4dde5335534be Author: Adam Langley <agl@google.com> Date: Mon Mar 7 16:11:01 2016 -0800 Add DSA_generate_parameters to decrepit. This function was deprecated by OpenSSL in 0.9.8 but code that uses it still exists. This change adds an implementation of this function to decreipt/ to support these programs. Change-Id: Ie99cd00ff8b0ab2675f2b1c821c3d664b9811f16 Reviewed-on: https://boringssl-review.googlesource.com/7360 Reviewed-by: David Benjamin <davidben@google.com> commit 22ce9b2d08a52e399bf2ab86851952d727be034d Author: David Benjamin <davidben@google.com> Date: Sun Mar 6 19:26:52 2016 -0500 SSL_set_fd should create socket BIOs, not fd BIOs. In OpenSSL, they create socket BIOs. The distinction isn't important on UNIX. On Windows, file descriptors are provided by the C runtime, while sockets must use separate recv and send APIs. Document how these APIs are intended to work. Also add a TODO to resolve the SOCKET vs int thing. This code assumes that Windows HANDLEs only use the bottom 32 bits of precision. (Which is currently true and probably will continue to be true for the foreseeable future[*], but it'd be nice to do this right.) Thanks to Gisle Vanem and Daniel Stenberg for reporting the bug. [*] Both so Windows can continue to run 32-bit programs and because of all the random UNIX software, like OpenSSL and ourselves, out there which happily assumes sockets are ints. Change-Id: I67408c218572228cb1a7d269892513cda4261c82 Reviewed-on: https://boringssl-review.googlesource.com/7333 Reviewed-by: David Benjamin <davidben@google.com> commit 66b2fe8e0273d1f6cca5db95d4ac3979621dc4ce Author: Tom Thorogood <me+google@tomthorogood.co.uk> Date: Sun Mar 6 20:08:38 2016 +1030 Add |SSL_CTX_set_private_key_method| to parallel |SSL_set_private_key_method| This change adds a |SSL_CTX_set_private_key_method| method that sets key_method on a SSL_CTX's cert. It allows the private key method to be set once and inherited. A copy of key_method (from SSL_CTX's cert to SSL's cert) is added in |ssl_cert_dup|. Change-Id: Icb62e9055e689cfe2d5caa3a638797120634b63f Reviewed-on: https://boringssl-review.googlesource.com/7340 Reviewed-by: David Benjamin <davidben@google.com> commit 62e0219679f5a120445a95def01c7679f5eb1790 Author: Emily Stark <estark@google.com> Date: Sun Mar 6 23:41:16 2016 -0800 Handle empty keys in EVP_marshal_public_key() Instead of crashing when an empty key is passed to EVP_marshal_public_key(), return with an EVP_R_UNSUPPORTED_ALGORITHM_ERROR. This brings e.g. X509_PUBKEY_set() closer to how it behaved before 68772b31 (previously, it returned an error on an empty public key rather than dereferencing pkey->ameth). Change-Id: Ieac368725adb7f22329c035d9d0685b44b885888 Reviewed-on: https://boringssl-review.googlesource.com/7351 Reviewed-by: David Benjamin <davidben@google.com> commit ad004af661759cdc4bf486e81f70a350a3a0a5a9 Author: David Benjamin <davidben@google.com> Date: Sat Mar 5 14:35:35 2016 -0500 Rename NID_x25519 to NID_X25519. I went with NID_x25519 to match NID_sha1 and friends in being lowercase. However, upstream seems to have since chosen NID_X25519. Match their name. Change-Id: Icc7b183a2e2dfbe42c88e08e538fcbd242478ac3 Reviewed-on: https://boringssl-review.googlesource.com/7331 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 154c2f2b37b1acff8f033787072fe7f7bed82fa5 Author: David Benjamin <davidben@google.com> Date: Sat Mar 5 11:57:44 2016 -0500 Add some missing return false lines to test_config.cc. Change-Id: I9540c931b6cdd4d65fa9ebfc52e1770d2174abd2 Reviewed-on: https://boringssl-review.googlesource.com/7330 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit 1b0c438e1a0e570de18ecc7aabda3be8dea4cfa0 Author: Emily Stark <estark@google.com> Date: Sun Mar 6 23:11:31 2016 -0800 Fix i2d_RSAPrivateKey, i2d_RSAPublicKey memory leaks Change-Id: Id2678c20270f2f45efe56efd65caf23e0bb8c09e Reviewed-on: https://boringssl-review.googlesource.com/7350 Reviewed-by: David Benjamin <davidben@google.com> commit 05c7bb4565b1f099e3aceea3623c073003cf5ccd Author: David Benjamin <davidben@google.com> Date: Fri Mar 4 17:07:23 2016 -0500 Avoid shifting negative numbers in curve25519. C is still kind of unsure about the whole two's complement thing and leaves left-shifting of negative numbers undefined. Sadly, some sanitizers believe in teaching the controversy and complain when code relies on the theory of two's complement. Shushing these sanitizers in this case is easier than fighting with build configuration, so replace the shifts with masks. (This is equivalent as the left-shift was of a value right-shifted by the same amount. Instead, we store the unshifted value in carry0, etc., and mask off the bottom bits.) A few other places get casts to unsigned types which, by some miracle, C compilers are forbidden from miscompiling. This is imported from upstream's b95779846dc876cf959ccf96c49d4c0a48ea3082 and 5b7af0dd6c9315ca76fba16813b66f5792c7fe6e. Change-Id: I6bf8156ba692165940c0c4ea1edd5b3e88ca263e Reviewed-on: https://boringssl-review.googlesource.com/7320 Reviewed-by: Adam Langley <agl@google.com> commit 58218b63bc033782162168e1462c9c8890606885 Author: David Benjamin <davidben@google.com> Date: Fri Mar 4 12:44:35 2016 -0500 Regenerate server_corpus and client_corpus. Now that client.cc and server.cc run through application data, regenerate the corpus. Change-Id: I8278ebfe47fd2ba74f67db6f9b545aabf9fd1f84 Reviewed-on: https://boringssl-review.googlesource.com/7301 Reviewed-by: Adam Langley <agl@google.com> commit d86c8a400be34bd77d14448008e3985714654283 Author: David Benjamin <davidben@google.com> Date: Wed Mar 2 14:53:11 2016 -0500 Enable renegotiation in the client fuzzer and read app data. As long as the HTTP/1.1 client auth hack forces use to support renego, having it on seems much more useful than having it off for fuzzing purposes. Also read app data to exercise that code and, on the client, trigger renegotiations as needed. Change-Id: I1941ded6ec9bd764abd199d1518420a1075ed1b2 Reviewed-on: https://boringssl-review.googlesource.com/7291 Reviewed-by: Adam Langley <agl@google.com> commit 1d34e3c644cdafea4187002a8409895bbda31289 Author: David Benjamin <davidben@google.com> Date: Fri Mar 4 12:30:51 2016 -0500 Add an option to pick a different build directory in minimise_corpuses.sh. Also pass set -e instead of chaining things with &&. (One line was missing the &&.) Change-Id: Ia04e7f40f46688c9664101efefef1d1ea069de71 Reviewed-on: https://boringssl-review.googlesource.com/7300 Reviewed-by: Adam Langley <agl@google.com> commit d7166d07ade008390ac5d526ecc25e1ebd140ab1 Author: David Benjamin <davidben@google.com> Date: Thu Mar 3 20:03:55 2016 -0500 Add a standalone ChaCha test. The coverage tool revealed that we weren't testing all codepaths of the ChaCha assembly. Add a standalone test as it's much easier to iterate over all lengths when there isn't the entire AEAD in the way. I wasn't able to find a really long test vector, so I generated a random one with the Go implementation we have in runner. This test gives us full coverage on the ChaCha20_ssse3 variant. (We'll see how it fares on the other codepaths when the multi-variant test harnesses get in. I certainly hope there isn't a more novel way to call ChaCha20 than this...) Change-Id: I087e421c7351f46ea65dacdc7127e4fbf5f4c0aa Reviewed-on: https://boringssl-review.googlesource.com/7299 Reviewed-by: Adam Langley <agl@google.com> commit 433366587d6156c9660cc87a843e9dcef1a58917 Author: David Benjamin <davidben@google.com> Date: Thu Mar 3 15:32:29 2016 -0500 Move AES128 above AES256 by default. This is in preparation for adding AES_256_GCM in Chromium below AES_128_GCM. For now, AES_128_GCM is preferable over AES_256_GCM for performance reasons. While I'm here, swap the order of 3DES and RC4. Chromium has already disabled RC4, but the default order should probably reflect that until we can delete it altogether. BUG=591516 Change-Id: I1b4df0c0b7897930be726fb8321cee59b5d93a6d Reviewed-on: https://boringssl-review.googlesource.com/7296 Reviewed-by: Adam Langley <agl@google.com> commit bd30f480c5bf62444d350abd9a81958b0bb81ae8 Author: David Benjamin <davidben@google.com> Date: Thu Mar 3 15:36:33 2016 -0500 poly1305/asm/poly1305-*.pl: flip horizontal add and reduction. Only the 32-bit AVX2 code path needs this, but upstream choose to harmonize all vector code paths. RT#4346 (Imported from 1ea8ae5090f557fea2e5b4d5758b10566825d74b.) Tested the new code manually on arm and aarch64, NEON and non-NEON. Steven reports that all variants pass on x86 and x86-64 too. I've left the 32-bit x86 AVX2 code disabled since valgrind can't measure the code coverage, but this avoids diff with upstream. We can enable it if we ever end up caring. Change-Id: Id9becc2adfbe44b84764f8e9c1fb5e8349c4d5a8 Reviewed-on: https://boringssl-review.googlesource.com/7295 Reviewed-by: Adam Langley <agl@google.com> commit ab14a4a44042cc1623d287a4e8e3b88df752c344 Author: Steven Valdez <svaldez@google.com> Date: Mon Feb 29 16:58:26 2016 -0500 Adding scripts to generate line coverage. Uses LCOV for C(++) line coverage and Valgrind's Callgrind tool to generate assembly-level line coverage for the generated assembly code. BUG=590332 Change-Id: Ic70300a272c38f4fa6dd615747db568aa0853584 Reviewed-on: https://boringssl-review.googlesource.com/7251 Reviewed-by: David Benjamin <davidben@google.com> commit 80c0fd6746b601f274cd8815d1a9f4536ecc9423 Author: Adam Langley <agl@google.com> Date: Thu Mar 3 09:49:09 2016 -0800 Update fuzzing corpuses. This results from running the fuzzers for a little while with both the 8bit-counters change and after taking the transcripts from the runner tests as seeds for the `client` and `server` fuzzers. Change-Id: I545a89d8dccd7ef69dd97546ed61610eea4a27a3 Reviewed-on: https://boringssl-review.googlesource.com/7276 Reviewed-by: David Benjamin <davidben@google.com> commit fde5afcd887f682eccf3dc7fd6b6f7a31ecb5143 Author: David Benjamin <davidben@google.com> Date: Thu Mar 3 08:47:53 2016 -0500 Remove dead comment. EC point format negotiation is dead and gone. Change-Id: If13ed7c5f31b64df2bbe90c018b2683b6371a980 Reviewed-on: https://boringssl-review.googlesource.com/7293 Reviewed-by: Adam Langley <agl@google.com> commit ddcc186ef15a7739d370768327007d3259b77328 Author: Adam Langley <agl@google.com> Date: Thu Mar 3 09:50:25 2016 -0800 Document how to minimise corpuses. Change-Id: Ie487163787d78d867e34709fb34b4c6a836f668d Reviewed-on: https://boringssl-review.googlesource.com/7275 Reviewed-by: David Benjamin <davidben@google.com> commit de29f36cf4b538ac2027c36fc9d0ccf75a745320 Author: Adam Langley <agl@google.com> Date: Thu Mar 3 09:50:10 2016 -0800 Add `8bit-counters` option for fuzzing. This enables coverage counters[1] when fuzzing. [1] http://clang.llvm.org/docs/SanitizerCoverage.html#coverage-counters Change-Id: I33fca02d0406b75ac1f7598f41fe4c2ce43538d1 Reviewed-on: https://boringssl-review.googlesource.com/7274 Reviewed-by: David Benjamin <davidben@google.com> commit cf81b540ce938f43308eb37ab2ab6ee726c8f122 Author: Brian Smith <brian@briansmith.org> Date: Tue Dec 29 12:02:59 2015 -1000 Remove call to |fprintf| in |CRYPTO_once|. The |fprintf| dependency is quite heavyweight for small targets. Also, using |fprintf| on a closed file dsecriptor is undefined behavior, and there's no way that this code can know whether |stderr| has already been closed. So, just don't do it. Change-Id: I1277733afe0649ae1324d11cac84826a1056e308 Reviewed-on: https://boringssl-review.googlesource.com/6812 Reviewed-by: David Benjamin <davidben@chromium.org> Reviewed-by: David Benjamin <davidben@google.com> commit 9867b7dca287c8e74a5c48f20eec1cc6bc14d670 Author: David Benjamin <davidben@google.com> Date: Tue Mar 1 23:25:48 2016 -0500 Add an option to record transcripts from runner tests. This can be used to get some initial corpus for fuzzing. Change-Id: Ifcd365995b54d202c4a2674f49e7b28515f36025 Reviewed-on: https://boringssl-review.googlesource.com/7289 Reviewed-by: Adam Langley <agl@google.com> commit f2b8363578b289aee1fb1a2a6e6190b70801c600 Author: David Benjamin <davidben@google.com> Date: Tue Mar 1 22:57:46 2016 -0500 Fix the tests for the fuzzer mode. It's useful to make sure our fuzzer mode works. Not all tests pass, but most do. (Notably the negative tests for everything we've disabled don't work.) We can also use then use runner to record fuzzer-mode transcripts with the ciphers correctly nulled. Change-Id: Ie41230d654970ce6cf612c0a9d3adf01005522c6 Reviewed-on: https://boringssl-review.googlesource.com/7288 Reviewed-by: Adam Langley <agl@google.com> commit bc5b2a2e22b63f0f6f57cf067c3cdd23af785225 Author: David Benjamin <davidben@google.com> Date: Tue Mar 1 22:57:32 2016 -0500 Add a deterministic PRNG for fuzzing. If running the stack through a fuzzer, we would like execution to be completely deterministic. This is gated on a BORINGSSL_UNSAFE_FUZZER_MODE #ifdef. For now, this just uses the zero ChaCha20 key and a global counter. As needed, we can extend this to a thread-local counter and a separate ChaCha20 stream and counter per input length. Change-Id: Ic6c9d8a25e70d68e5dc6804e2c234faf48e51395 Reviewed-on: https://boringssl-review.googlesource.com/7286 Reviewed-by: Adam Langley <agl@google.com> commit 8b9e7802acde5e7d811ede05360b03fb4720e104 Author: David Benjamin <davidben@google.com> Date: Wed Mar 2 18:23:21 2016 -0500 Fix up all_tests.go parallelism support. A len(tests) should have been len(testCases), the code never added to the sync.WaitGroup, and feeding tests to the tests channel blocks on the tests completing, so with one worker the results didn't stream. (And if the results channel wasn't large enough, we'd deadlock.) Change-Id: Iee37507b9706b14cffddd9c1b55fc311ee9b666d Reviewed-on: https://boringssl-review.googlesource.com/7292 Reviewed-by: Adam Langley <agl@google.com> commit bf82aede675e343087ca9d31b53547d01c269be0 Author: David Benjamin <davidben@google.com> Date: Tue Mar 1 22:57:40 2016 -0500 Disable all TLS crypto in fuzzer mode. Both sides' signature and Finished checks still occur, but the results are ignored. Also, all ciphers behave like the NULL cipher. Conveniently, this isn't that much code since all ciphers and their size computations funnel into SSL_AEAD_CTX. This does carry some risk that we'll mess up this code. Up until now, we've tried to avoid test-only changes to the SSL stack. There is little risk that anyone will ship a BORINGSSL_UNSAFE_FUZZER_MODE build for anything since it doesn't interop anyway. There is some risk that we'll end up messing up the disableable checks. However, both skipped checks have negative tests in runner (see tests that set InvalidSKXSignature and BadFinished). For good measure, I've added a server variant of the existing BadFinished test to this CL, although they hit the same code. Change-Id: I37f6b4d62b43bc08fab7411965589b423d86f4b8 Reviewed-on: https://boringssl-review.googlesource.com/7287 Reviewed-by: Adam Langley <agl@google.com> commit 2477adcf6236c3040a291ad1bfd53f525e1af96d Author: Brian Smith <brian@briansmith.org> Date: Tue Mar 1 20:16:26 2016 -1000 Clarify use of |$end0| in stitched x86-64 AES-GCM code. There was some uncertainty about what the code is doing with |$end0| and whether it was necessary for |$len| to be a multiple of 16 or 96. Hopefully these added comments make it clear that the code is correct except for the caveat regarding low memory addresses. Change-Id: Iea546a59dc7aeb400f50ac5d2d7b9cb88ace9027 Reviewed-on: https://boringssl-review.googlesource.com/7194 Reviewed-by: Adam Langley <agl@google.com> commit 32223940f28dc55e2d875961bcd2b51b1685358f Author: Steven Valdez <svaldez@google.com> Date: Wed Mar 2 11:53:07 2016 -0500 Making all_tests.go parallelizable Use -num-workers to run multiple workers in parallel when running tests. Change-Id: Iee5554ee78ec8d77700a0df5a297bd2515d34dca Reviewed-on: https://boringssl-review.googlesource.com/7285 Reviewed-by: David Benjamin <davidben@google.com> commit 9bea349660c8230fe33f62a5c03e647854125afc Author: David Benjamin <davidben@google.com> Date: Wed Mar 2 10:59:16 2016 -0500 Account for Windows line endings in runner. Otherwise the split on "--- DONE ---\n" gets confused. Change-Id: I74561a99e52b98e85f67efd85523213ad443d325 Reviewed-on: https://boringssl-review.googlesource.com/7283 Reviewed-by: Adam Langley <agl@google.com> commit 29ec5d1fdab3286946a217878b0326af19f533f2 Author: Adam Langley <alangley@gmail.com> Date: Tue Mar 1 16:12:28 2016 -0800 Add dummy |SSL_get_server_tmp_key|. Node.js calls it but handles it failing. Since we have abstracted this in the state machine, we mightn't even be using a cipher suite where the server's key can be expressed as an EVP_PKEY. Change-Id: Ic3f013dc9bcd7170a9eb2c7535378d478b985849 Reviewed-on: https://boringssl-review.googlesource.com/7272 Reviewed-by: David Benjamin <davidben@google.com> commit d323f4b1e185b43f8d5e5a3b191d4bf0d5b65609 Author: Adam Langley <agl@google.com> Date: Tue Mar 1 15:58:14 2016 -0800 Bring back |verify_store|. This was dropped in d27441a9cb55b02149d7f1236de94f3a40dd1692 due to lack of use, but node.js now needs it. Change-Id: I1e207d4b46fc746cfae309a0ea7bbbc04ea785e8 Reviewed-on: https://boringssl-review.googlesource.com/7270 Reviewed-by: David Benjamin <davidben@google.com> commit 2b07fa4b22198ac02e0cee8f37f3337c3dba91bc Author: David Benjamin <davidben@google.com> Date: Wed Mar 2 00:23:57 2016 -0500 Fix a memory leak in an error path. Found by libFuzzer combined with some experimental unsafe-fuzzer-mode patches (to be uploaded once I've cleaned them up a bit) to disable all those pesky cryptographic checks in the protocol. Change-Id: I9153164fa56a0c2262c4740a3236c2b49a596b1b Reviewed-on: https://boringssl-review.googlesource.com/7282 Reviewed-by: Adam Langley <agl@google.com> commit ff3a1498dae79e7fa1cf8d93f735f6fdae49e286 Author: David Benjamin <davidben@google.com> Date: Wed Mar 2 10:12:06 2016 -0500 Ensure runner notices post-main stderr output. If LeakSanitizer fires something on a test that's expected to fail, runner will swallow it. Have stderr output always end in a "--- DONE ---" marker and treat all output following that as a test failure. Change-Id: Ia8fd9dfcaf48dd23972ab8f906d240bcb6badfe2 Reviewed-on: https://boringssl-review.googlesource.com/7281 Reviewed-by: Adam Langley <agl@google.com> commit 3cd8196f14d8fd762f06ce2e20a23cd912eb06f2 Author: David Benjamin <davidben@google.com> Date: Wed Mar 2 09:40:08 2016 -0500 Mark all curve25519 tables const. See also upstream's dc22d6b37e8058a4334e6f98932c2623cd3d8d0d. (Though I'm not sure why they didn't need to fix cmov.) Change-Id: I2a194a8aea1734d4c1e7f6a0536a636379381627 Reviewed-on: https://boringssl-review.googlesource.com/7280 Reviewed-by: Adam Langley <agl@google.com> commit 7a17ba2e3ab1cc30812193660138cb9f09b27c7e Author: Adam Langley <alangley@gmail.com> Date: Tue Mar 1 16:00:36 2016 -0800 Add |FIPS_mode|, which returns zero. (node.js calls it.) Change-Id: I7401f4cb4dfc61d500331821784ae717ad9f7adf Reviewed-on: https://boringssl-review.googlesource.com/7271 Reviewed-by: David Benjamin <davidben@google.com> commit 708db16463a21b922aed6d393ef74c3c5a366668 Author: Adam Langley <agl@google.com> Date: Tue Mar 1 11:48:00 2016 -0800 Pass |alice_msg| by reference in the SPAKE2 speed test. This is an attempt to make MSVC happy. Currently it's saying: ..\tool\speed.cc(508) : error C2536: 'SpeedSPAKE2::<lambda_…>::SpeedSPAKE2::<lambda_…>::alice_msg' : cannot specify explicit initializer for arrays Change-Id: Ifba1df26b5d734f142668a41834645c1549f9f52 Reviewed-on: https://boringssl-review.googlesource.com/7248 Reviewed-by: David Benjamin <davidben@google.com> commit f27459e41259bd66179febbd3b89cc183791172c Author: Arnar Birgisson <arnarb@google.com> Date: Tue Feb 9 18:09:00 2016 -0800 Add SPAKE2 over Ed25519. SPAKE2 is a password-authenticated key exchange. This implementation is over the twisted Edwards curve Ed25519, and uses SHA-512 as the hash primitive. See https://tools.ietf.org/html/draft-irtf-cfrg-spake2-03 Change-Id: I2cd3c3ebdc3d55ac3aea3a9eb0d06275509597ac Reviewed-on: https://boringssl-review.googlesource.com/7114 Reviewed-by: Adam Langley <agl@google.com> commit e4f3f4df6e521e9f98f6b2e340b98b59cba2c237 Author: Adam Langley <agl@google.com> Date: Tue Mar 1 09:07:14 2016 -0800 Add test that A+A = 2×A on elliptic curves. Change-Id: I914efab9a15c903f79a1b83388b577b14c534269 Reviewed-on: https://boringssl-review.googlesource.com/7247 Reviewed-by: David Benjamin <davidben@google.com> commit 060bd590cec36c11008a513a0f1f239e0c84c774 Author: Adam Langley <agl@google.com> Date: Tue Mar 1 08:23:53 2016 -0800 ec/asm/p256-x86_64-asm.pl: get corner case logic right. (Imported from upstream's 64333004a41a9f4aa587b8e5401420fb70d00687.) RT#4284. This case should be impossible to hit because |EC_POINT_add| doesn't use this function and trying to add equal inputs should never occur during a multiplication. Support for this exists because the pattern has been copied from the first 64-bit P-224 and P-256 work that Emilia, Bodo and I did. There it seemed like a reasonable defense-in-depth in case the code changed in the future. Change-Id: I7ff138669c5468b7d7a5153429bec728cb67e338 Reviewed-on: https://boringssl-review.googlesource.com/7246 Reviewed-by: David Benjamin <davidben@google.com> commit 7aea80f5761e839543b4c9b3952eec123d611f3c Author: Steven Valdez <svaldez@google.com> Date: Tue Mar 1 10:09:04 2016 -0500 Adding missing BN_CTX_start/BN_CTX_end in ec_key Change-Id: Icfa6a0bc36b808e2e6ea8b36a0fc49b3c4943b07 Reviewed-on: https://boringssl-review.googlesource.com/7254 Reviewed-by: David Benjamin <davidben@google.com> commit df2a5562f3cbbf4438cf215cca1d4c3f77fad292 Author: Adam Langley <agl@google.com> Date: Tue Mar 1 08:17:29 2016 -0800 bn/asm/x86_64-mont5.pl: unify gather procedure in hardly used path and reorganize/harmonize post-conditions. (Imported from upstream's 515f3be47a0b58eec808cf365bc5e8ef6917266b) Additional hardening following on from CVE-2016-0702. Change-Id: I19a6739b401887a42eb335fe5838379dc8d04100 Reviewed-on: https://boringssl-review.googlesource.com/7245 Reviewed-by: Adam Langley <agl@google.com> commit b360eaf0018a0ed82b3713adc993ffff8270631e Author: Adam Langley <agl@google.com> Date: Tue Mar 1 08:16:30 2016 -0800 crypto/bn/x86_64-mont5.pl: constant-time gather procedure. (Imported from upstream's 25d14c6c29b53907bf614b9964d43cd98401a7fc.) At the same time remove miniscule bias in final subtraction. Performance penalty varies from platform to platform, and even with key length. For rsa2048 sign it was observed to be 4% for Sandy Bridge and 7% on Broadwell. (This is part of the fix for CVE-2016-0702.) Change-Id: I43a13d592c4a589d04c17c33c0ca40c2d7375522 Reviewed-on: https://boringssl-review.googlesource.com/7244 Reviewed-by: Adam Langley <agl@google.com> commit 1168fc72fc7f3d5b2954ff0cd41365f2a973ba1b Author: Adam Langley <agl@google.com> Date: Tue Mar 1 07:58:38 2016 -0800 bn/asm/rsaz-avx2.pl: constant-time gather procedure. (Imported from upstream's 08ea966c01a39e38ef89e8920d53085e4807a43a) Performance penalty is 2%. (This is part of the fix for CVE-2016-0702.) Change-Id: Id3b6262c5d3201dd64b93bdd34601a51794a9275 Reviewed-on: https://boringssl-review.googlesource.com/7243 Reviewed-by: Adam Langley <agl@google.com> commit 842a06c2b9f7797d19f7f3ba862abe0f208d2391 Author: Adam Langley <agl@google.com> Date: Tue Mar 1 07:57:08 2016 -0800 bn/asm/rsax-x86_64.pl: constant-time gather procedure. (Imported from upstream's ef98503eeef5c108018081ace902d28e609f7772.) Performance penalty is 2% on Linux and 5% on Windows. (This is part of the fix for CVE-2016-0702.) Change-Id: If82f95131c93168282a46ac5a35e2b007cc2bd67 Reviewed-on: https://boringssl-review.googlesource.com/7242 Reviewed-by: Adam Langley <agl@google.com> commit 82bdaa89f07c944265fa899aff9dbefdfd5d0f92 Author: Adam Langley <agl@google.com> Date: Tue Mar 1 07:54:10 2016 -0800 Make copy_from_prebuf constant time. (Imported from upstream's 708dc2f1291e104fe4eef810bb8ffc1fae5b19c1.) Performance penalty varies from platform to platform, and even key length. For rsa2048 sign it was observed to reach almost 10%. This is part of the fix for CVE-2016-0702. Change-Id: Ie0860bf3e531196f03102db1bc48eeaf30ab1d58 Reviewed-on: https://boringssl-review.googlesource.com/7241 Reviewed-by: Adam Langley <agl@google.com> commit aeb69a02b833994766f0af1f4d84929f7496d7f6 Author: Steven Valdez <svaldez@google.com> Date: Fri Feb 26 10:48:59 2016 -0500 Pass pure constants verbatim in perlasm/x86_64-xlate.pl (Imported from upstream's 10c639a8a56c90bec9e332c7ca76ef552b3952ac) Change-Id: Ia8203eeae9d274249595a6e352ec2f77a97ca5d5 Reviewed-on: https://boringssl-review.googlesource.com/7227 Reviewed-by: David Benjamin <davidben@google.com> commit 2c198fae28c13f7cdeadd33dc7f68036310edbe5 Author: David Benjamin <davidben@google.com> Date: Wed Feb 17 14:52:08 2016 -0500 Enforce that d2i_PrivateKey returns a key of the specified type. If d2i_PrivateKey hit the PKCS#8 codepath, it didn't enforce that the key was of the specified type. Note that this requires tweaking d2i_AutoPrivateKey slightly. A PKCS #8 PrivateKeyInfo may have 3 or 4 elements (optional attributes), so we were relying on this bug for d2i_AutoPrivateKey to work. Change-Id: If50b7a742f535d208e944ba37c3a585689d1da43 Reviewed-on: https://boringssl-review.googlesource.com/7253 Reviewed-by: Adam Langley <agl@google.com> commit 886119b9f73b4fe0159c2ab793cccb3fa96ace99 Author: David Benjamin <davidben@google.com> Date: Mon Feb 29 17:21:02 2016 -0500 Disable ChaCha20 assembly for OPENSSL_X86. They fail the newly-added in-place tests. Since we don't have bots for them yet, verified manually that the arm and aarch64 code is fine. Change-Id: Ic6f4060f63e713e09707af05e6b7736b7b65c5df Reviewed-on: https://boringssl-review.googlesource.com/7252 Reviewed-by: Adam Langley <agl@google.com> commit f132d4e8f84602182e521fbe688a264dbc3d19f8 Author: Adam Langley <agl@google.com> Date: Thu Feb 25 17:07:19 2016 -0800 Test AEAD interface with aliased buffers. Cases where the input and output buffers overlap are always a little odd. This change adds a test to ensures that the (generic) AEADs function in these situations. Change-Id: I6f1987a5e10ddef6b2b8f037a6d50737a120bc99 Reviewed-on: https://boringssl-review.googlesource.com/7195 Reviewed-by: David Benjamin <davidben@google.com> commit 42c8c63fcbb53642674da648924e61d4aa65b67c Author: David Benjamin <davidben@google.com> Date: Mon Feb 29 16:59:19 2016 -0500 Fix build. Forgot to delete a line. Change-Id: Ia1fb2904398816d495045dc237337f0be5b09272 Reviewed-on: https://boringssl-review.googlesource.com/7250 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com> commit d7305d50e4dbc16edc2f22133b7daae2cd1724f2 Author: Steven Valdez <svaldez@google.com> Date: Mon Feb 29 10:38:26 2016 -0500 Add missing initialization in bn/exponentiation (Imported from upstream's 04f2a0b50d219aafcef2fa718d91462b587aa23d) Change-Id: Ie840edeb1fc9d5a4273f137467e3ef16528c9668 Reviewed-on: https://boringssl-review.googlesource.com/7234 Reviewed-by: David Benjamin <davidben@google.com> commit 318c076b69d1487cae300abbec7025583f198a2e Author: Steven Valdez <svaldez@google.com> Date: Mon Feb 29 10:14:11 2016 -0500 modes/ctr.c: Ensure ecount_buf alignment in CRYPTO_ctr128_encrypt. This isn't a problem when called from EVP, since the buffer is aligned in the EVP_CIPHER_CTX. The increment counter code is also fixed to deal with overflow. (Imported from upstream's 6533a0b8d1ed12aa5f7dfd7a429eec67c5486bb5) Change-Id: I8d7191c3d3873db254a551085d2358d90bc8397a Reviewed-on: https://boringssl-review.googlesource.com/7233 Reviewed-by: David Benjamin <davidben@google.com> commit df1dc9840946c91426a55c242fe3dc50ed781152 Author: David Benjamin <davidben@google.com> Date: Mon Feb 29 16:27:37 2016 -0500 Add a few more large tag tests to asn1_test. While we're here, may as well test others. Change-Id: I711528641a3f7dd035c696c3c1d6b035437c91cc Reviewed-on: https://boringssl-review.googlesource.com/7239 Reviewed-by: Adam Langley <agl@google.com> commit fb2c6f8c8565e1e2d85c24408050c96521acbcdc Author: David Benjamin <davidben@google.com> Date: Mon Feb 29 15:42:59 2016 -0500 ASN1_get_object should not accept large universal tags. The high bits of the type get used for the V_ASN1_NEG bit, so when used with ASN1_ANY/ASN1_TYPE, universal tags become ambiguous. This allows one to create a negative zero, which should be impossible. Impose an upper bound on universal tags accepted by crypto/asn1 and add a test. BUG=590615 Change-Id: I363e01ebfde621c8865101f5bcbd5f323fb59e79 Reviewed-on: https://boringssl-review.googlesource.com/7238 Reviewed-by: Adam Langley <agl@google.com> commit 7e8ed440135c166d0a29e28548b485b66d1645b8 Author: Adam Langley <agl@google.com> Date: Mon Feb 29 08:08:11 2016 -0800 Fix possible memory leak on BUF_MEM_grow_clean failure (Imported from upstream's e9cf5f03666bb82f0184e4f013702d0b164afdca and 29305f4edc886db349f2beedb345f9dd93311c09) Change-Id: I0fa019e9d337676a84a7a6c103d2c4e14e18aede Reviewed-on: https://boringssl-review.googlesource.com/7240 Reviewed-by: David Benjamin <davidben@google.com> commit a14934ff2de02c6a12cc34272a26816940e93a60 Author: Steven Valdez <svaldez@google.com> Date: Mon Feb 29 10:05:08 2016 -0500 Handle shutdown during init/handshake earlier Sending close_notify during init causes some problems for some applications so we instead revert to the previous behavior returning an error instead of silently passing. (Imported from upstream's 64193c8218540499984cd63cda41f3cd491f3f59) Change-Id: I5efed1ce152197d291e6c7ece6e5dbb8f3ad867d Reviewed-on: https://boringssl-review.googlesource.com/7232 Reviewed-by: David Benjamin <davidben@google.com> commit c4eec0c16b02c97a62a95b6a08656c3a9ddb6baa Author: Adam Langley <agl@google.com> Date: Mon Feb 29 08:01:05 2016 -0800 Fix encoding bug in i2c_ASN1_INTEGER (Imported from upstream's 3661bb4e7934668bd99ca777ea8b30eedfafa871.) Fix bug where i2c_ASN1_INTEGER mishandles zero if it is marked as negative. Thanks to Huzaifa Sidhpurwala <huzaifas@redhat.com> and Hanno Böck <hanno@hboeck.de> for reporting this issue. BUG=590615 Change-Id: I8959e8ae01510a5924862a3f353be23130eee554 Reviewed-on: https://boringssl-review.googlesource.com/7199 Reviewed-by: David Benjamin <davidben@google.com> commit b944882f26d64881161622b6c708568ff67483dd Author: Brian Smith <brian@briansmith.org> Date: Wed Jan 13 10:50:00 2016 -1000 Reduce maximum RSA public exponent size to 33 bits. Reduce the maximum RSA exponent size to 33 bits, regardless of modulus size, for public key operations. Change-Id: I88502b1033d8854696841531031298e8ad96a467 Reviewed-on: https://boringssl-review.googlesource.com/6901 Reviewed-by: Adam Langley <agl@google.com> commit f4e447c16d24aa2f6a9336aa6dbba015380beb29 Author: David Benjamin <davidben@chromium.org> Date: Sun Feb 7 12:31:53 2016 -0500 Move ASN1_bn_print to a static function in evp/print.c. It's not used anywhere else, in the library or consumers (Google ones or ones I could find on Debian codesearch). This is a sufficiently specialized function that the risk of a third-party library newly depending on it is low. This removes the last include of asn1.h or x509.h in crypto/evp. (This is almost entirely cosmetic because it wasn't keeping the static linker from doing the right thing anyway. But if we were want to separate the legacy ASN.1 stack into its own decrepit-like target, we'll need to be pickier about separation.) Change-Id: I9be97c9321572e3a2ed093e1d50036b7654cff41 Reviewed-on: https://boringssl-review.googlesource.com/7080 Reviewed-by: Adam Langley <agl@google.com> commit 63d9246812e4ee0055ca8be425d61b12b89a5876 Author: David Benjamin <davidben@chromium.org> Date: Mon Feb 1 15:48:51 2016 -0500 Reset crypto/evp error codes. A number of values have fallen off now that code's been shuffled around. Change-Id: I5eac1d3fa4a9335c6aa72b9876d37bb9a9a029ac Reviewed-on: https://boringssl-review.googlesource.com/7029 Reviewed-by: Adam Langley <agl@google.com> commit 921d906bb640e105b852c849edb8f0a115cc1a6c Author: David Benjamin <davidben@chromium.org> Date: Sat Jan 30 19:33:52 2016 -0500 Reimplement d2i_PrivateKey. Functions which lose object reuse and need auditing: - d2i_PrivateKey This removes evp_asn1.c's dependency on the old stack. (Aside from obj/.) It also takes old_priv_decode out of EVP_ASN1_METHOD in favor of calling out to the new-style function. EVP_ASN1_METHOD no longer has any old-style type-specific serialization hooks, only the PKCS#8 and SPKI ones. BUG=499653 Change-Id: Ic142dc05a5505b50e4717c260d3893b20e680194 Reviewed-on: https://boringssl-review.googlesource.com/7027 Reviewed-by: Adam Langley <agl@google.com> commit 6d3387d9c1cc184c7d9ca29d726ab478cdfc1023 Author: David Benjamin <davidben@chromium.org> Date: Thu Dec 31 15:11:31 2015 -0500 Reimplement d2i_AutoPrivateKey with the new ASN.1 stack. This is kind of a ridiculous function. It would be nice to lose it, but SSL_use_PrivateKey_file actually calls into it (by way of d2i_PrivateKey_bio). BUG=499653 Change-Id: I83634f6982b15f4b877e29f6793b7e00a1c10450 Reviewed-on: https://boringssl-review.googlesource.com/7026 Reviewed-by: Adam Langley <agl@google.com> commit 8ebc0f55a01539a9eef39e162c25d09303f4013b Author: David Benjamin <davidben@chromium.org> Date: Sun Jan 3 03:02:50 2016 -0800 Decouple the EVP and PEM code. EVP_PKEY_asn1_find can already be private. EVP_PKEY_asn1_find_str is used only so the PEM code can get at legacy encoders. Since this is all legacy non-PKCS8 stuff, we can just explicitly list out the three cases in the two places that need it. If this changes, we can later add a table in crypto/pem mapping string to EVP_PKEY type. With this, EVP_PKEY_ASN1_METHOD is no longer exposed in the public API and nothing outside of EVP_PKEY reaches into it. Unexport all of that. Change-Id: Iab661014247dbdbc31e5e9887364176ec5ad2a6d Reviewed-on: https://boringssl-review.googlesource.com/6871 Reviewed-by: Adam Langley <agl@google.com> commit 3f4f7ee08fe0e36c87519befcaff073dc5a90e95 Author: David Benjamin <davidben@chromium.org> Date: Sun Jan 3 02:52:40 2016 -0800 PEM_write_bio_PrivateKey is always PKCS#8. Every key type which has a legacy PEM encoding also has a PKCS#8 encoding. The fallback codepath is never reached. This removes the only consumer of pem_str, so that may be removed from EVP_PKEY_ASN1_METHOD. Change-Id: Ic680bfc162e1dc76db8b8016f6c10f669b24f5aa Reviewed-on: https://boringssl-review.googlesource.com/6870 Reviewed-by: Adam Langley <agl@google.com> commit 8c07ad3e3be810663d2fe5f94de8cfb256285851 Author: David Benjamin <davidben@chromium.org> Date: Fri Aug 7 12:34:57 2015 -0400 Pull EVP_PKEY print hooks out of the main method table. This allows the static linker to drop it in consumers which don't need this stuff (i.e. all sane ones), once crypto/x509 falls off. This cuts down on a number of dependencies from the core crypto bits on crypto/asn1 and crypto/x509. BUG=499653 Change-Id: I76a10a04dcc444c1ded31683df9f87725a95a4e6 Reviewed-on: https://boringssl-review.googlesource.com/5660 Reviewed-by: Adam Langley <agl@google.com> commit 17727c6843e3b3d4ec93132a454732dd5176ff85 Author: David Benjamin <davidben@chromium.org> Date: Sat Jan 30 14:58:52 2016 -0500 Move all signature algorithm code to crypto/x509. All the signature algorithm logic depends on X509_ALGOR. This also removes the X509_ALGOR-based EVP functions which are no longer used externally. I think those APIs were a mistake on my part. The use in Chromium was unnecessary (and has since been removed anyway). The new X.509 stack will want to process the signatureAlgorithm itself to be able to enforce policies on it. This also moves the RSA_PSS_PARAMS bits to crypto/x509 from crypto/rsa. That struct is also tied to crypto/x509. Any new RSA-PSS code would have to use something else anyway. BUG=499653 Change-Id: I6c4b4573b2800a2e0f863d35df94d048864b7c41 Reviewed-on: https://boringssl-review.googlesource.com/7025 Reviewed-by: Adam Langley <agl@google.com> commit 93a69b4f8f33d70a3350512ec744b5b948fe2f6b Author: David Benjamin <davidben@chromium.org> Date: Sat Jan 30 12:57:05 2016 -0500 Move X.509 signature algorithm tests to the crypto/x509 layer. This is in preparation for moving the logic itself to crypto/x509, so the lower-level functions will not be as readily available. Change-Id: I6507b895317df831ab11d0588c5b09bbb2aa2c24 Reviewed-on: https://boringssl-review.googlesource.com/7023 Reviewed-by: Adam Langley <agl@google.com> commit da295d35f2ccd179635229d719345dd056a56cfb Author: David Benjamin <davidben@chromium.org> Date: Sat Jan 30 14:09:08 2016 -0500 Drop the DSA signature printing hook. It's only used by crypto/x509, and we don't even support DSA in crypto/x509 anymore since the EVP_PKEY_CTX hooks aren't wired up. Change-Id: I1b8538353eb51df353cf9171b1cbb0bb47a879a3 Reviewed-on: https://boringssl-review.googlesource.com/7024 Reviewed-by: Adam Langley <agl@google.com> commit 136df6bd999aa72d4a3817f719bcb87f86014490 Author: Aaron Green <aarongreen@google.com> Date: Fri Feb 12 08:15:35 2016 -0800 Fix implementation-specific behavior in gcm_test.c gcm_test.c includes a test case that does a 'malloc(0)'. This test case currently fails if malloc(0) returns NULL. According to the standard, malloc's behavior with a size of 0is implementation specific and may either be NULL or another pointer suitable to be passed to free(). This change modifies gcm_test.c to handle a return value of NULL. It has been tested with a custom allocator on an experimental branch. Change-Id: I35514ec9735cedffc621f7dfae42b4c6664a1766 Reviewed-on: https://boringssl-review.googlesource.com/7122 Reviewed-by: Adam Langley <agl@google.com> commit 95a79eec40703fcd9f108ff7dac0ec4d34856ecb Author: Emily Stark <estark@google.com> Date: Thu Feb 25 21:12:28 2016 -0800 Add a stub for SSL_get_shared_ciphers(). This stub returns an empty string rather than NULL (since some callers might assume that NULL means there are no shared ciphers). Change-Id: I9537fa0a80c76559b293d8518599b68fd9977dd8 Reviewed-on: https://boringssl-review.googlesource.com/7196 Reviewed-by: David Benjamin <davidben@google.com> commit 6f0c4db90e47437ed87a2d385c7797e692a2cf65 Author: David Benjamin <davidben@google.com> Date: Tue Feb 23 17:43:36 2016 -0500 Enable upstream's Poly1305 code. The C implementation is still our existing C implementation, but slightly tweaked to fit with upstream's init/block/emits convention. I've tested this by looking at code coverage in kcachegrind and valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes (NB: valgrind 3.11.0 is needed for AVX2. And even that only does 64-bit AVX2, so we can't get coverage for the 32-bit code yet. But I had to disable that anyway.) This was paired with a hacked up version of poly1305_test that would repeat tests with different ia32cap and armcap values. This isn't checked in, but we badly need a story for testing all the different variants. I'm not happy with upstream's code in either the C/asm boundary or how it dispatches between different versions, but just debugging the code has been a significant time investment. I'd hoped to extract the SIMD parts and do the rest in C, but I think we need to focus on testing first (and use that to guide what modifications would help). For now, this version seems to work at least. The x86 (not x86_64) AVX2 code needs to be disabled because it's broken. It also seems pretty unnecessary. https://rt.openssl.org/Ticket/Display.html?id=4346 Otherwise it seems to work and buys us a decent performance improvement. Notably, my Nexus 6P is finally faster at ChaCha20-Poly1305 than my Nexus 4! bssl speed numbers follow: x86 --- Old: Did 1554000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000536us (1553167.5 ops/sec): 24.9 MB/s Did 136000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1003947us (135465.3 ops/sec): 182.9 MB/s Did 30000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1022990us (29325.8 ops/sec): 240.2 MB/s Did 1888000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000206us (1887611.2 ops/sec): 30.2 MB/s Did 173000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1003036us (172476.4 ops/sec): 232.8 MB/s Did 30000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1027759us (29189.7 ops/sec): 239.1 MB/s New: Did 2030000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000507us (2028971.3 ops/sec): 32.5 MB/s Did 404000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1000287us (403884.1 ops/sec): 545.2 MB/s Did 83000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1001258us (82895.7 ops/sec): 679.1 MB/s Did 2018000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000006us (2017987.9 ops/sec): 32.3 MB/s Did 360000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1001962us (359295.1 ops/sec): 485.0 MB/s Did 85000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1002479us (84789.8 ops/sec): 694.6 MB/s x86_64, no AVX2 --- Old: Did 2023000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000258us (2022478.2 ops/sec): 32.4 MB/s Did 466000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1002619us (464782.7 ops/sec): 627.5 MB/s Did 90000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1001133us (89898.1 ops/sec): 736.4 MB/s Did 2238000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000175us (2237608.4 ops/sec): 35.8 MB/s Did 483000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1001348us (482349.8 ops/sec): 651.2 MB/s Did 90000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1003141us (89718.2 ops/sec): 735.0 MB/s New: Did 2558000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000275us (2557296.7 ops/sec): 40.9 MB/s Did 510000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1001810us (509078.6 ops/sec): 687.3 MB/s Did 115000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1006457us (114262.2 ops/sec): 936.0 MB/s Did 2818000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000187us (2817473.1 ops/sec): 45.1 MB/s Did 418000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1001140us (417524.0 ops/sec): 563.7 MB/s Did 91000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1002539us (90769.5 ops/sec): 743.6 MB/s x86_64, AVX2 --- Old: Did 2516000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000115us (2515710.7 ops/sec): 40.3 MB/s Did 774000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1000300us (773767.9 ops/sec): 1044.6 MB/s Did 171000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1004373us (170255.5 ops/sec): 1394.7 MB/s Did 2580000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000144us (2579628.5 ops/sec): 41.3 MB/s Did 769000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1000472us (768637.2 ops/sec): 1037.7 MB/s Did 169000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1000320us (168945.9 ops/sec): 1384.0 MB/s New: Did 3240000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000114us (3239630.7 ops/sec): 51.8 MB/s Did 932000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1000059us (931945.0 ops/sec): 1258.1 MB/s Did 217000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1003282us (216290.1 ops/sec): 1771.8 MB/s Did 3187000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000100us (3186681.3 ops/sec): 51.0 MB/s Did 926000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1000071us (925934.3 ops/sec): 1250.0 MB/s Did 215000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1000479us (214897.1 ops/sec): 1760.4 MB/s arm, Nexus 4 --- Old: Did 430248 ChaCha20-Poly1305 (16 bytes) seal operations in 1000153us (430182.2 ops/sec): 6.9 MB/s Did 115250 ChaCha20-Poly1305 (1350 bytes) seal operations in 1000549us (115186.8 ops/sec): 155.5 MB/s Did 27000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1030124us (26210.4 ops/sec): 214.7 MB/s Did 451750 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000549us (451502.1 ops/sec): 7.2 MB/s Did 118000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1001557us (117816.6 ops/sec): 159.1 MB/s Did 27000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1024263us (26360.4 ops/sec): 215.9 MB/s New: Did 553644 ChaCha20-Poly1305 (16 bytes) seal operations in 1000183us (553542.7 ops/sec): 8.9 MB/s Did 126000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1000396us (125950.1 ops/sec): 170.0 MB/s Did 27000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1000336us (26990.9 ops/sec): 221.1 MB/s Did 559000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1001465us (558182.3 ops/sec): 8.9 MB/s Did 124000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1000824us (123897.9 ops/sec): 167.3 MB/s Did 28000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1034854us (27057.0 ops/sec): 221.7 MB/s aarch64, Nexus 6P --- Old: Did 358000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000358us (357871.9 ops/sec): 5.7 MB/s Did 45000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1022386us (44014.7 ops/sec): 59.4 MB/s Did 8657 ChaCha20-Poly1305 (8192 bytes) seal operations in 1063722us (8138.4 ops/sec): 66.7 MB/s Did 350000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000074us (349974.1 ops/sec): 5.6 MB/s Did 44000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1007907us (43654.8 ops/sec): 58.9 MB/s Did 8525 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1042644us (8176.3 ops/sec): 67.0 MB/s New: Did 713000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000190us (712864.6 ops/sec): 11.4 MB/s Did 180000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1004249us (179238.4 ops/sec): 242.0 MB/s Did 41000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1005811us (40763.1 ops/sec): 333.9 MB/s Did 775000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000719us (774443.2 ops/sec): 12.4 MB/s Did 182000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1003529us (181360.0 ops/sec): 244.8 MB/s Did 41000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1010576us (40570.9 ops/sec): 332.4 MB/s Change-Id: Iaa4ab86ac1174b79833077963cc3616cfb08e686 Reviewed-on: https://boringssl-review.googlesource.com/7226 Reviewed-by: Adam Langley <agl@google.com> commit a211aee545cb665b5099803e106656e4c3b788bf Author: David Benjamin <davidben@google.com> Date: Wed Feb 24 17:18:44 2016 -0500 Add SSL_CIPHER_has_SHA256_HMAC. Change-Id: I05a8f5d1778aba1813fe4d34b4baa21849158218 Reviewed-on: https://boringssl-review.googlesource.com/7215 Reviewed-by: Adam Langley <agl@google.com> commit e593fed3786e9e5dcfe5a1e43181dc91c8e3ff27 Author: David Benjamin <davidben@google.com> Date: Thu Feb 25 11:39:59 2016 -0500 Rename opensslfeatures.h to opensslconf.h. Some software #includes opensslconf.h which typically contains settings that we put in opensslfeatures.h (a header name not in OpenSSL). Rename it to opensslconf.h. Change-Id: Icd21dde172e5e489ce90dd5c16ae4d2696909fb6 Reviewed-on: https://boringssl-review.googlesource.com/7216 Reviewed-by: Adam Langley <agl@google.com> commit a473e554b412abf8415cc83487d146909ecb1e45 Author: David Benjamin <davidben@google.com> Date: Thu Feb 25 12:04:37 2016 -0500 Add BIO_do_connect. Some consumers of connect BIOs connect them explicitly, and we already have the BIO_ctrl hooked up. Change-Id: Ie6b14f8ceb272b560e2b534e0b6c32fae050475b Reviewed-on: https://boringssl-review.googlesource.com/7217 Reviewed-by: Adam Langley <agl@google.com> commit b4e3e694e80bf59bbdc202c9a626e6ecb272c9b1 Author: Brian Smith <brian@briansmith.org> Date: Wed Feb 24 09:58:18 2016 -1000 Use correct counter after invoking stitched AES-NI GCM code. Commit a3d9528e9e212e0dcda30dcb561092c3b3a69010 has a bug that could cause counters to be reused if |$avx=2| were set in the AES-NI AES-GCM assembly code, if the EVP interface were used with certain coding patterns, as demonstrated by the test cases added in a5ee83f67e83d4065d1aa40137e8dd8b1c83b3e5. This changes the encryption code in the same way the decryption code was changed in a3d9528e9e212e0dcda30dcb561092c3b3a69010. This doesn't have any effect currently since the AES-NI AES-GCM code has |$avx=0| now, so |aesni_gcm_encrypt| doesn't change the counter. Change-Id: Iba69cb4d2043d1ea57c6538b398246af28cba006 Reviewed-on: https://boringssl-review.googlesource.com/7193 Reviewed-by: Adam Langley <agl@google.com> commit 6234a7f3a706d2f863e949b4d360ff07faba9dbd Author: David Benjamin <davidben@google.com> Date: Tue Feb 23 18:39:10 2016 -0500 Switch poly1305-armv4.pl to named constants. See https://rt.openssl.org/Ticket/Display.html?id=4341. Change-Id: Ied39744dcf557e4267c7a84d6f95d78a691084e1 Reviewed-on: https://boringssl-review.googlesource.com/7225 Reviewed-by: Adam Langley <agl@google.com> commit f28caea521aab668abf83629dc8116a518f53459 Author: David Benjamin <davidben@google.com> Date: Tue Feb 23 16:25:40 2016 -0500 Check in pristine copies of upstream's poly1305 assembly. Taken from 6b2ebe4332e22b4eb7dd6fadf418e3da7b926ca4. These don't do anything right now but are checked in unmodified to make diffs easier to see. Change-Id: I4f5bdb7b16f4ac27e7ef175f475540c481b8d593 Reviewed-on: https://boringssl-review.googlesource.com/7224 Reviewed-by: Adam Langley <agl@google.com> commit 8ccc3c383a3dc9f3fee1974c08f4f93b3e38404e Author: David Benjamin <davidben@google.com> Date: Thu Feb 25 11:37:12 2016 -0500 Test poly1305 more aggressively. OpenSSL upstream's SIMD assembly is rather complex. This pattern of update calls should be sufficient to stress all the codepaths. Change-Id: I50dea8351e4203b6b2cd9b23456eb4a592d31b5e Reviewed-on: https://boringssl-review.googlesource.com/7223 Reviewed-by: Adam Langley <agl@google.com> commit 3f81b607fee408fe8142442c6e654b0762d8f844 Author: Steven Valdez <svaldez@google.com> Date: Thu Feb 25 13:43:49 2016 -0500 Fix missing ok=0 with cert verification. Also avoid using "i" in X509_cert_verify as a loop counter, trust outcome and as an error ordinal. (Imported from upstream's a3baa171053547488475709c7197592c66e427cf) Change-Id: I4b0b542ffacf7fa861c93c8124b334c0aacc3c17 Reviewed-on: https://boringssl-review.googlesource.com/7222 Reviewed-by: David Benjamin <davidben@google.com> commit 06c5fb4512ecd9aeb74e7d438c257b9f606f67af Author: David Benjamin <davidben@google.com> Date: Thu Feb 25 20:23:24 2016 +0000 Revert "Fix missing ok=0 with cert verification." This reverts commit b0576889fa4c86a8e9cb7e978e7160904fa2c5b4. This broke x509_test. Change-Id: Idbb60df9ca0a8ce727931f8e35e99bbd0f08c3c1 Reviewed-on: https://boringssl-review.googlesource.com/7221 Reviewed-by: David Benjamin <davidben@google.com> commit fd26b7a015b4a5f372eff88c4cd981d34217cc45 Author: Steven Valdez <svaldez@google.com> Date: Thu Feb 25 13:49:45 2016 -0500 If no comparison function is set, sk_sort is a NOP (Imported from upstream's 402fb1896b2aab5cf887127bbce964554b9c8113) Change-Id: I80c1f952085c8fc9062d3395f211a525151c404d Reviewed-on: https://boringssl-review.googlesource.com/7219 Reviewed-by: David Benjamin <davidben@google.com> commit b0576889fa4c86a8e9cb7e978e7160904fa2c5b4 Author: Steven Valdez <svaldez@google.com> Date: Thu Feb 25 13:43:49 2016 -0500 Fix missing ok=0 with cert verification. Also avoid using "i" in X509_cert_verify as a loop counter, trust outcome and as an error ordinal. (Imported from upstream's a3baa171053547488475709c7197592c66e427cf) Change-Id: I492afdbaa5017bcf00a0412033cf99fca3fe9401 Reviewed-on: https://boringssl-review.googlesource.com/7218 Reviewed-by: David Benjamin <davidben@google.com> commit e42da0e4b4a587f30ee5fbb65ce7bb5791a7a5be Author: David Benjamin <davidben@google.com> Date: Thu Feb 25 13:53:25 2016 -0500 Fix bssl rand -hex. It emits NULs instead of c. Change-Id: Id7f103eac049129dbf9a3e852454b22134ce3270 Reviewed-on: https://boringssl-review.googlesource.com/7220 Reviewed-by: Adam Langley <agl@google.com> commit cd8d1761df85b460562237e50af3ee60a1b9856f Author: Brian Smith <brian@briansmith.org> Date: Sun Feb 14 10:12:05 2016 -1000 Move |bn_div_words| to crypto/bn/div.c and make it static. It is only used by |bn_div_rem_words|. Change-Id: I57627091d8db5890d7fea34d8560897717008646 Reviewed-on: https://boringssl-review.googlesource.com/7128 Reviewed-by: David Benjamin <davidben@google.com> commit d1425f69df16310bdca46a3d66144dcb4e3ad4fc Author: Brian Smith <brian@briansmith.org> Date: Thu Feb 11 12:10:16 2016 -1000 Simplify division-with-remainder calculations in crypto/bn/div.c. Create a |bn_div_rem_words| that is used for double-word/single-word divisions and division-with-remainder. Remove all implementations of |bn_div_words| except for the implementation needed for 64-bit MSVC. This allows more code to be shared across platforms and also removes an instance of the dangerous pattern wherein the |div_asm| macro modified a variable that wasn't passed as a parameter. Also, document the limitations of the compiler-generated code for the non-asm code paths more fully. Compilers indeed have not improved in this respect. Change-Id: I5a36a2edd7465de406d47d72dcd6bf3e63e5c232 Reviewed-on: https://boringssl-review.googlesource.com/7127 Reviewed-by: David Benjamin <davidben@google.com> commit 76c6381c21ef07b13371120dc0b938da64f51ca7 Author: Brian Smith <brian@briansmith.org> Date: Sat Feb 13 16:46:11 2016 -1000 Return 0 on error in |EC_POINT_is_on_curve| instead of -1. Callers of this function are not checking for the -1 result. Change the semantics to match their expectations and to match the common semantics of most other parts of BoringSSL. Change-Id: I4ec537d7619e20e8ddfee80c72125e4c02cfaac1 Reviewed-on: https://boringssl-review.googlesource.com/7125 Reviewed-by: David Benjamin <davidben@google.com> commit 0bc2349375212f79cc4a5996f86389d6250fde4f Author: Brian Smith <brian@briansmith.org> Date: Fri Feb 12 10:06:36 2016 -1000 Remove unused |ccm128_context| in crypto/modes/internal.h. Note that this structure has a weak pointer to the key, which was a problem corrected in the AES-GCM code in 0f8bfdeb3383749eecfefb17a36416e6b35fa10c. Also, it uses |void *| instead of |const AES_KEY *| to refer to that key. Change-Id: I70e632e3370ab27eb800bc1c0c64d2bd36b7cafb Reviewed-on: https://boringssl-review.googlesource.com/7123 Reviewed-by: David Benjamin <davidben@google.com> commit d8eea14443ab890b0a6d00a40d2dbf6d3bf79484 Author: Steven Valdez <svaldez@google.com> Date: Wed Feb 24 14:00:22 2016 -0500 BIO_new_mem_buf should take const void * BIO_FLAGS_MEM_RDONLY keeps the invariant. (Imported from upstream's a38a159bfcbc94214dda00e0e6b1fc6454a23b78) Change-Id: I4cb35615d76b77929915e370dbb7fec1455da069 Reviewed-on: https://boringssl-review.googlesource.com/7214 Reviewed-by: David Benjamin <davidben@google.com> commit a5ee83f67e83d4065d1aa40137e8dd8b1c83b3e5 Author: Adam Langley <agl@google.com> Date: Wed Feb 24 10:04:31 2016 -0800 Test different chunk sizes in cipher_test. This change causes cipher_test to test the EVP cipher interfaces with various chunk sizes and adds a couple of large tests of GCM. This is sufficient to uncover the issue that would have been caused by a3d9528e, had the AVX code been enabled. Change-Id: I58d4924c0bcd11a0999c24a0fb77fc5eee71130f Reviewed-on: https://boringssl-review.googlesource.com/7192 Reviewed-by: David Benjamin <davidben@google.com> commit 5ec72de203ff52ff73648b0a3018e79dca830208 Author: Steven Valdez <svaldez@google.com> Date: Wed Feb 24 12:16:32 2016 -0500 Add missing EC NULL Check (imported from upstream's 2b80d00e3ac652377ace84c51b53f51a1b7e1ba2) Change-Id: Iee5a8d85d276033b6ac8bc9ac87e157916a1a29a Reviewed-on: https://boringssl-review.googlesource.com/7212 Reviewed-by: David Benjamin <davidben@google.com> commit b9824e241746d70d985d1004078b5bad0ad9a75b Author: Steven Valdez <svaldez@chromium.org> Date: Wed Feb 24 10:47:52 2016 -0500 Handle SSL_shutdown while in init more appropriately Calling SSL_shutdown while in init previously gave a "1" response, meaning everything was successfully closed down (even though it wasn't). Better is to send our close_notify, but fail when trying to receive one. The problem with doing a shutdown while in the middle of a handshake is that once our close_notify is sent we shouldn't really do anything else (including process handshake/CCS messages) until we've received a close_notify back from the peer. However the peer might send a CCS before acting on our close_notify - so we won't be able to read it because we're not acting on CCS messages! (Imported from upstream's f73c737c7ac908c5d6407c419769123392a3b0a9) Change-Id: Iaad5c5e38983456d3697c955522a89919628024b Reviewed-on: https://boringssl-review.googlesource.com/7207 Reviewed-by: David Benjamin <davidben@google.com> commit e52d22d5f9dc439658746d25cb69702749ec3f67 Author: Steven Valdez <svaldez@chromium.org> Date: Wed Feb 24 10:44:54 2016 -0500 Empty SNI names are not valid (Imported from upstream's 4d6fe78f65be650c84e14777c90e7a088f7a44ce) Change-Id: Id28e0d49da2490e454dcb8603ccb93a506dfafaf Reviewed-on: https://boringssl-review.googlesource.com/7206 Reviewed-by: David Benjamin <davidben@google.com> commit e412bbd9a15d812666291e38e194b71da6a2a062 Author: Steven Valdez <svaldez@chromium.org> Date: Tue Feb 23 15:37:41 2016 -0500 Fix wildcard match on punycode/IDNA DNS names - bugfix: should not treat '--' as invalid domain substring. - '-' should not be the first letter of a domain (Imported from upstream's 15debc128ac13420a4eec9b4a66d72f1dfd69126) Change-Id: Ifd8ff7cef1aab69da5cade8ff8c76c3a723f3838 Reviewed-on: https://boringssl-review.googlesource.com/7205 Reviewed-by: David Benjamin <davidben@google.com> commit 85003903fc58d8825e02162fd33a9b9c28fdec35 Author: David Benjamin <davidben@google.com> Date: Tue Feb 23 18:04:15 2016 -0500 Remove CRYPTO_set_NEON_functional. This depends on https://codereview.chromium.org/1730823002/. The bit was only ever targetted to one (rather old) CPU. Disable NEON on it uniformly, so we don't have to worry about whether any new NEON code breaks it. BUG=589200 Change-Id: Icc7d17d634735aca5425fe0a765ec2fba3329326 Reviewed-on: https://boringssl-review.googlesource.com/7211 Reviewed-by: Adam Langley <agl@google.com> commit 030d08513e7127a0fe8608fed9d75308e1df98b6 Author: David Benjamin <davidben@google.com> Date: Tue Feb 23 16:43:54 2016 -0500 ymm registers are not suffixed with w. This imports a fix to x86gas.pl from upstream's a98c648e40ea5158c8ba29b5a70ccc239d426a20. It's needed to get poly1305-x86.pl working. Confirmed that this is a no-op for our current assembly files. Change-Id: I28de1dbf421b29a06147d1aea3ff3659372a78b3 Reviewed-on: https://boringssl-review.googlesource.com/7210 Reviewed-by: Adam Langley <agl@google.com> commit a3d9528e9e212e0dcda30dcb561092c3b3a69010 Author: Brian Smith <brian@briansmith.org> Date: Wed Feb 17 18:59:19 2016 -1000 Unify AEAD and EVP code paths for AES-GCM. This change makes the AEAD and EVP code paths use the same code for AES-GCM. When AVX instructions are enabled in the assembly this will allow them to use the stitched AES-GCM implementation. Note that the stitched implementations are no-ops for small inputs (smaller than 288 bytes for encryption; smaller than 96 bytes for decryption). This means that only a handful of test cases with longish inputs actually test the stitched code. Change-Id: Iece8003d90448dcac9e0bde1f42ff102ebe1a1c9 Reviewed-on: https://boringssl-review.googlesource.com/7173 Reviewed-by: Adam Langley <agl@google.com> commit 3dbecdf6f422fe6112533bef95be41caedb80583 Author: David Benjamin <davidben@google.com> Date: Tue Feb 23 17:44:12 2016 -0500 Append to CMAKE_ASM_FLAGS rather than replace it. Otherwise we clobber things like -m32. Change-Id: I9457e4b50dc3063643c31d19c7935276b8a312a1 Reviewed-on: https://boringssl-review.googlesource.com/7209 Reviewed-by: Adam Langley <agl@google.com> commit 65f83b64d92a17b999d7db711628ee0a9a74e9d6 Author: David Benjamin <davidben@google.com> Date: Thu Feb 18 13:44:25 2016 -0500 Set --noexecstack for assembly files in the standalone build. See also upstream's 2966c2ec31e81187da3fbbe1499a6aa3acfd355f. Change-Id: Iad0a0f11accb4fa2bd93667239dd7462f9fdbd7f Reviewed-on: https://boringssl-review.googlesource.com/7180 Reviewed-by: Adam Langley <agl@google.com> commit 35be6880788d90bc2a93de5295391b001a8a6a46 Author: David Benjamin <davidben@google.com> Date: Fri Feb 19 18:47:22 2016 -0500 Enable upstream's ChaCha20 assembly for x86 and ARM (32- and 64-bit). This removes chacha_vec_arm.S and chacha_vec.c in favor of unifying on upstream's code. Upstream's is faster and this cuts down on the number of distinct codepaths. Our old scheme also didn't give vectorized code on Windows or aarch64. BoringSSL-specific modifications made to the assembly: - As usual, the shelling out to $CC is replaced with hardcoding $avx. I've tested up to the AVX2 codepath, so enable it all. - I've removed the AMD XOP code as I have not tested it. - As usual, the ARM file need the arm_arch.h include tweaked. Speed numbers follow. We can hope for further wins on these benchmarks after importing the Poly1305 assembly. x86 --- Old: Did 1422000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000433us (1421384.5 ops/sec): 22.7 MB/s Did 123000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1003803us (122534.0 ops/sec): 165.4 MB/s Did 22000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1000282us (21993.8 ops/sec): 180.2 MB/s Did 1428000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000214us (1427694.5 ops/sec): 22.8 MB/s Did 124000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1006332us (123219.8 ops/sec): 166.3 MB/s Did 22000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1020771us (21552.3 ops/sec): 176.6 MB/s New: Did 1520000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000567us (1519138.6 ops/sec): 24.3 MB/s Did 152000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1004216us (151361.9 ops/sec): 204.3 MB/s Did 31000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1009085us (30720.9 ops/sec): 251.7 MB/s Did 1797000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000141us (1796746.7 ops/sec): 28.7 MB/s Did 171000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1003204us (170453.9 ops/sec): 230.1 MB/s Did 31000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1005349us (30835.1 ops/sec): 252.6 MB/s x86_64, no AVX2 --- Old: Did 1782000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000204us (1781636.5 ops/sec): 28.5 MB/s Did 317000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1001579us (316500.2 ops/sec): 427.3 MB/s Did 62000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1012146us (61256.0 ops/sec): 501.8 MB/s Did 1778000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000220us (1777608.9 ops/sec): 28.4 MB/s Did 315000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1002886us (314093.5 ops/sec): 424.0 MB/s Did 71000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1014606us (69977.9 ops/sec): 573.3 MB/s New: Did 1866000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000019us (1865964.5 ops/sec): 29.9 MB/s Did 399000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1001017us (398594.6 ops/sec): 538.1 MB/s Did 84000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1005645us (83528.5 ops/sec): 684.3 MB/s Did 1881000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000325us (1880388.9 ops/sec): 30.1 MB/s Did 404000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1000004us (403998.4 ops/sec): 545.4 MB/s Did 85000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1010048us (84154.4 ops/sec): 689.4 MB/s x86_64, AVX2 --- Old: Did 2375000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000282us (2374330.4 ops/sec): 38.0 MB/s Did 448000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1001865us (447166.0 ops/sec): 603.7 MB/s Did 88000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1005217us (87543.3 ops/sec): 717.2 MB/s Did 2409000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000188us (2408547.2 ops/sec): 38.5 MB/s Did 446000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1001003us (445553.1 ops/sec): 601.5 MB/s Did 90000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1006722us (89399.1 ops/sec): 732.4 MB/s New: Did 2622000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000266us (2621302.7 ops/sec): 41.9 MB/s Did 794000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1000783us (793378.8 ops/sec): 1071.1 MB/s Did 173000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1000176us (172969.6 ops/sec): 1417.0 MB/s Did 2623000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000330us (2622134.7 ops/sec): 42.0 MB/s Did 783000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1000531us (782584.4 ops/sec): 1056.5 MB/s Did 174000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1000840us (173854.0 ops/sec): 1424.2 MB/s arm, Nexus 4 --- Old: Did 388550 ChaCha20-Poly1305 (16 bytes) seal operations in 1000580us (388324.8 ops/sec): 6.2 MB/s Did 90000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1003816us (89657.9 ops/sec): 121.0 MB/s Did 19000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1045750us (18168.8 ops/sec): 148.8 MB/s Did 398500 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000305us (398378.5 ops/sec): 6.4 MB/s Did 90500 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1000305us (90472.4 ops/sec): 122.1 MB/s Did 19000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1043278us (18211.8 ops/sec): 149.2 MB/s New: Did 424788 ChaCha20-Poly1305 (16 bytes) seal operations in 1000641us (424515.9 ops/sec): 6.8 MB/s Did 115000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1001526us (114824.8 ops/sec): 155.0 MB/s Did 27000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1033023us (26136.9 ops/sec): 214.1 MB/s Did 447750 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000549us (447504.3 ops/sec): 7.2 MB/s Did 117500 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1001923us (117274.5 ops/sec): 158.3 MB/s Did 27000 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1025118us (26338.4 ops/sec): 215.8 MB/s aarch64, Nexus 6p (Note we didn't have aarch64 assembly before at all, and still don't have it for Poly1305. Hopefully once that's added this will be faster than the arm numbers...) --- Old: Did 145040 ChaCha20-Poly1305 (16 bytes) seal operations in 1003065us (144596.8 ops/sec): 2.3 MB/s Did 14000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1042605us (13427.9 ops/sec): 18.1 MB/s Did 2618 ChaCha20-Poly1305 (8192 bytes) seal operations in 1093241us (2394.7 ops/sec): 19.6 MB/s Did 148000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000709us (147895.1 ops/sec): 2.4 MB/s Did 14000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1047294us (13367.8 ops/sec): 18.0 MB/s Did 2607 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1090745us (2390.1 ops/sec): 19.6 MB/s New: Did 358000 ChaCha20-Poly1305 (16 bytes) seal operations in 1000769us (357724.9 ops/sec): 5.7 MB/s Did 45000 ChaCha20-Poly1305 (1350 bytes) seal operations in 1021267us (44062.9 ops/sec): 59.5 MB/s Did 8591 ChaCha20-Poly1305 (8192 bytes) seal operations in 1047136us (8204.3 ops/sec): 67.2 MB/s Did 343000 ChaCha20-Poly1305-Old (16 bytes) seal operations in 1000489us (342832.4 ops/sec): 5.5 MB/s Did 44000 ChaCha20-Poly1305-Old (1350 bytes) seal operations in 1008326us (43636.7 ops/sec): 58.9 MB/s Did 8866 ChaCha20-Poly1305-Old (8192 bytes) seal operations in 1083341us (8183.9 ops/sec): 67.0 MB/s Change-Id: I629fe195d072f2c99e8f947578fad6d70823c4c8 Reviewed-on: https://boringssl-review.googlesource.com/7202 Reviewed-by: Adam Langley <agl@google.com> commit 0182ecd346add6019e6559ea6f6e515b54c1d78f Author: David Benjamin <davidben@google.com> Date: Tue Feb 23 11:20:09 2016 -0500 Consistently use named constants in ARM assembly files. Most of the OPENSSL_armcap_P accesses in assembly use named constants from arm_arch.h, but some don't. Consistently use the constants. The dispatch really should be in C, but in the meantime, make it easier to tell what's going on. I'll send this patch upstream so we won't be carrying a diff here. Change-Id: I63c68d2351ea5ce11005813314988e32b6459526 Reviewed-on: https://boringssl-review.googlesource.com/7203 Reviewed-by: Adam Langley <agl@google.com> commit 295960044bc34fa8aeb01cbed64269330fd0cef6 Author: David Benjamin <davidben@google.com> Date: Mon Feb 22 17:32:18 2016 -0500 Fix chacha-armv4.pl. Patch taken from https://rt.openssl.org/Ticket/Display.html?id=4323. Change-Id: Icbaf8f9a0f92da48f213b251b0afa4b0d5aa627d Reviewed-on: https://boringssl-review.googlesource.com/7201 Reviewed-by: Adam Langley <agl@google.com> commit ea4d6863c7d54c96bdd3a7c1a84062c501ea1494 Author: David Benjamin <davidben@google.com> Date: Fri Feb 19 18:32:47 2016 -0500 Check in pristine copies of OpenSSL's chacha-{arm*,x86}.pl. They won't be used as-is. This is just to make the diffs easier to see. Taken from upstream's 4f16039efe3589aa4d63a6f1fab799d0cd9338ca. Change-Id: I34d8be409f9c8f15b8a6da4b2d98ba3e60aa2210 Reviewed-on: https://boringssl-review.googlesource.com/7200 Reviewed-by: Adam Langley <agl@google.com> commit b104517f1dd54e7b269ff12fac8842340bf6614b Author: Adam Langley <agl@google.com> Date: Mon Feb 22 11:48:18 2016 -0800 Add some bug references to the LICENSE file. Add references for some cases where we have explicit permission from authors to use their work. This is just to make things easy for us to find. Change-Id: I47dacc6a80f9d0c960c5b6713a8dc25e1a4e6f0b Reviewed-on: https://boringssl-review.googlesource.com/7191 Reviewed-by: David Benjamin <davidben@google.com> commit 65dcfc7f9b2ae147cf817ecad22dfcab89230d5e Author: Adam Langley <agl@google.com> Date: Mon Feb 22 09:16:57 2016 -0800 Remove CP_UTF8 code for Windows filenames. Thanks to Gisle Vanem for pointing out that this code was broken and could never have compiled. Since it has never worked, and thus has never been used, remove it. Change-Id: Ic274eaf187928765a809690eda8d790b79f939a5 Reviewed-on: https://boringssl-review.googlesource.com/7190 Reviewed-by: David Benjamin <davidben@google.com>
-rw-r--r--.clang-format3
-rw-r--r--.github/PULL_REQUEST_TEMPLATE7
-rw-r--r--BUILDING.md30
-rw-r--r--CMakeLists.txt40
-rw-r--r--FUZZING.md47
-rw-r--r--INCORPORATING.md90
-rw-r--r--LICENSE7
-rw-r--r--README.md1
-rw-r--r--STYLE.md8
-rw-r--r--crypto/CMakeLists.txt55
-rw-r--r--crypto/aes/mode_wrappers.c8
-rw-r--r--crypto/asn1/CMakeLists.txt4
-rw-r--r--crypto/asn1/a_bytes.c4
-rw-r--r--crypto/asn1/a_d2i_fp.c41
-rw-r--r--crypto/asn1/a_gentm.c2
-rw-r--r--crypto/asn1/a_strnid.c1
-rw-r--r--crypto/asn1/a_type.c2
-rw-r--r--crypto/asn1/a_utctm.c2
-rw-r--r--crypto/asn1/asn1_lib.c26
-rw-r--r--crypto/asn1/asn1_locl.h10
-rw-r--r--crypto/asn1/asn1_par.c322
-rw-r--r--crypto/asn1/asn1_test.cc32
-rw-r--r--crypto/asn1/bio_asn1.c477
-rw-r--r--crypto/asn1/bio_ndef.c251
-rw-r--r--crypto/asn1/t_pkey.c110
-rw-r--r--crypto/asn1/tasn_dec.c16
-rw-r--r--crypto/asn1/tasn_enc.c2
-rw-r--r--crypto/asn1/tasn_prn.c596
-rw-r--r--crypto/base64/base64.c526
-rw-r--r--crypto/base64/base64_test.cc354
-rw-r--r--crypto/bio/bio_mem.c5
-rw-r--r--crypto/bio/bio_test.cc6
-rw-r--r--crypto/bio/connect.c15
-rw-r--r--crypto/bio/fd.c37
-rw-r--r--crypto/bio/file.c40
-rw-r--r--crypto/bio/internal.h3
-rw-r--r--crypto/bio/pair.c2
-rw-r--r--crypto/bio/socket.c12
-rw-r--r--crypto/bio/socket_helper.c4
-rw-r--r--crypto/bn/asm/armv4-mont.pl2
-rwxr-xr-x[-rw-r--r--]crypto/bn/asm/rsaz-avx2.pl219
-rwxr-xr-x[-rw-r--r--]crypto/bn/asm/rsaz-x86_64.pl375
-rw-r--r--crypto/bn/asm/x86_64-gcc.c8
-rwxr-xr-x[-rw-r--r--]crypto/bn/asm/x86_64-mont.pl227
-rwxr-xr-x[-rw-r--r--]crypto/bn/asm/x86_64-mont5.pl1276
-rw-r--r--crypto/bn/bn.c12
-rw-r--r--crypto/bn/bn_test.cc6
-rw-r--r--crypto/bn/cmp.c14
-rw-r--r--crypto/bn/convert.c13
-rw-r--r--crypto/bn/div.c206
-rw-r--r--crypto/bn/exponentiation.c465
-rw-r--r--crypto/bn/gcd.c27
-rw-r--r--crypto/bn/generic.c80
-rw-r--r--crypto/bn/internal.h10
-rw-r--r--crypto/bn/montgomery.c118
-rw-r--r--crypto/bn/mul.c3
-rw-r--r--crypto/buf/buf.c46
-rw-r--r--crypto/bytestring/ber.c1
-rw-r--r--crypto/bytestring/bytestring_test.cc7
-rw-r--r--crypto/bytestring/cbs.c29
-rw-r--r--crypto/chacha/CMakeLists.txt46
-rwxr-xr-xcrypto/chacha/asm/chacha-armv4.pl1151
-rwxr-xr-xcrypto/chacha/asm/chacha-armv8.pl1127
-rwxr-xr-xcrypto/chacha/asm/chacha-x86.pl753
-rwxr-xr-xcrypto/chacha/asm/chacha-x86_64.pl1767
-rw-r--r--crypto/chacha/chacha.c170
-rw-r--r--crypto/chacha/chacha_generic.c140
-rw-r--r--crypto/chacha/chacha_test.cc248
-rw-r--r--crypto/chacha/chacha_vec.c328
-rw-r--r--crypto/chacha/chacha_vec_arm.S1447
-rw-r--r--crypto/chacha/chacha_vec_arm_generate.go153
-rw-r--r--crypto/cipher/aead.c25
-rw-r--r--crypto/cipher/aead_test.cc172
-rw-r--r--crypto/cipher/cipher.c4
-rw-r--r--crypto/cipher/cipher_test.cc41
-rw-r--r--crypto/cipher/e_aes.c80
-rw-r--r--crypto/cipher/e_chacha20poly1305.c8
-rw-r--r--crypto/cipher/e_des.c2
-rw-r--r--crypto/cipher/e_null.c2
-rw-r--r--crypto/cipher/e_rc2.c2
-rw-r--r--crypto/cipher/e_rc4.c2
-rw-r--r--crypto/cipher/test/aes_128_gcm_tests.txt2
-rw-r--r--crypto/cipher/test/aes_256_gcm_tests.txt2
-rw-r--r--crypto/cipher/test/cipher_test.txt597
-rw-r--r--crypto/cipher/test/cipher_tests.txt613
-rw-r--r--crypto/cipher/tls_cbc.c42
-rw-r--r--crypto/cmac/cmac_test.cc2
-rw-r--r--crypto/conf/conf.c3
-rw-r--r--crypto/cpu-aarch64-linux.c61
-rw-r--r--crypto/cpu-arm-asm.S32
-rw-r--r--crypto/cpu-arm-linux.c360
-rw-r--r--crypto/cpu-arm.c161
-rw-r--r--crypto/cpu-intel.c8
-rw-r--r--crypto/crypto.c24
-rw-r--r--crypto/curve25519/CMakeLists.txt10
-rw-r--r--crypto/curve25519/curve25519.c508
-rw-r--r--crypto/curve25519/internal.h64
-rw-r--r--crypto/curve25519/spake25519.c464
-rw-r--r--crypto/curve25519/spake25519_test.cc169
-rw-r--r--crypto/curve25519/x25519-x86_64.c21
-rw-r--r--crypto/dh/dh.c19
-rw-r--r--crypto/dh/dh_asn1.c116
-rw-r--r--crypto/dh/dh_test.cc93
-rw-r--r--crypto/digest/digest.c6
-rw-r--r--crypto/directory.h66
-rw-r--r--crypto/directory_posix.c108
-rw-r--r--crypto/directory_win.c144
-rw-r--r--crypto/dsa/dsa.c17
-rw-r--r--crypto/dsa/dsa_asn1.c4
-rwxr-xr-x[-rw-r--r--]crypto/ec/asm/p256-x86_64-asm.pl11
-rw-r--r--crypto/ec/ec.c76
-rw-r--r--crypto/ec/ec_asn1.c134
-rw-r--r--crypto/ec/ec_key.c14
-rw-r--r--crypto/ec/ec_montgomery.c128
-rw-r--r--crypto/ec/ec_test.cc127
-rw-r--r--crypto/ec/example_mul.c4
-rw-r--r--crypto/ec/internal.h20
-rw-r--r--crypto/ec/oct.c22
-rw-r--r--crypto/ec/p224-64.c130
-rw-r--r--crypto/ec/p256-64.c205
-rw-r--r--crypto/ec/p256-x86_64.c45
-rw-r--r--crypto/ec/simple.c257
-rw-r--r--crypto/ec/util-64.c74
-rw-r--r--crypto/ecdsa/ecdsa.c9
-rw-r--r--crypto/ecdsa/ecdsa_asn1.c1
-rw-r--r--crypto/ecdsa/ecdsa_test.cc2
-rw-r--r--crypto/err/asn1.errordata163
-rw-r--r--crypto/err/dh.errordata2
-rw-r--r--crypto/err/err.c6
-rw-r--r--crypto/err/err_data_generate.go9
-rw-r--r--crypto/err/evp.errordata73
-rw-r--r--crypto/err/rsa.errordata92
-rw-r--r--crypto/err/ssl.errordata1
-rw-r--r--crypto/err/x509.errordata41
-rw-r--r--crypto/evp/CMakeLists.txt2
-rw-r--r--crypto/evp/algorithm.c153
-rw-r--r--crypto/evp/evp.c67
-rw-r--r--crypto/evp/evp_asn1.c230
-rw-r--r--crypto/evp/evp_ctx.c5
-rw-r--r--crypto/evp/evp_extra_test.cc365
-rw-r--r--crypto/evp/evp_test.cc13
-rw-r--r--crypto/evp/evp_tests.txt5
-rw-r--r--crypto/evp/internal.h50
-rw-r--r--crypto/evp/p_dsa_asn1.c165
-rw-r--r--crypto/evp/p_ec.c2
-rw-r--r--crypto/evp/p_ec_asn1.c192
-rw-r--r--crypto/evp/p_rsa.c2
-rw-r--r--crypto/evp/p_rsa_asn1.c558
-rw-r--r--crypto/evp/pbkdf_test.cc1
-rw-r--r--crypto/evp/print.c527
-rw-r--r--crypto/ex_data.c4
-rw-r--r--crypto/hkdf/hkdf.c55
-rw-r--r--crypto/hkdf/hkdf_test.c66
-rw-r--r--crypto/hmac/hmac.c11
-rw-r--r--crypto/internal.h110
-rw-r--r--crypto/lhash/lhash_test.c4
-rw-r--r--crypto/md4/md4.c9
-rw-r--r--crypto/mem.c21
-rw-r--r--crypto/modes/asm/aesni-gcm-x86_64.pl46
-rw-r--r--crypto/modes/asm/ghash-x86_64.pl5
-rw-r--r--crypto/modes/cfb.c11
-rw-r--r--crypto/modes/ctr.c28
-rw-r--r--crypto/modes/gcm.c88
-rw-r--r--crypto/modes/gcm_test.c6
-rw-r--r--crypto/modes/internal.h42
-rw-r--r--crypto/modes/ofb.c6
-rw-r--r--crypto/newhope/CMakeLists.txt42
-rw-r--r--crypto/newhope/error_correction.c131
-rw-r--r--crypto/newhope/internal.h71
-rw-r--r--crypto/newhope/newhope.c174
-rw-r--r--crypto/newhope/newhope_statistical_test.cc156
-rw-r--r--crypto/newhope/newhope_test.cc142
-rw-r--r--crypto/newhope/newhope_tests.txt206
-rw-r--r--crypto/newhope/newhope_vectors_test.cc122
-rw-r--r--crypto/newhope/ntt.c148
-rw-r--r--crypto/newhope/poly.c189
-rw-r--r--crypto/newhope/precomp.c306
-rw-r--r--crypto/newhope/reduce.c42
-rw-r--r--crypto/obj/CMakeLists.txt13
-rw-r--r--crypto/obj/README12
-rw-r--r--crypto/obj/obj.c20
-rw-r--r--crypto/obj/obj_dat.h14
-rw-r--r--crypto/obj/obj_dat.pl6
-rw-r--r--crypto/obj/obj_mac.num3
-rw-r--r--crypto/obj/obj_test.cc106
-rw-r--r--crypto/obj/objects.pl40
-rw-r--r--crypto/obj/objects.txt5
-rw-r--r--crypto/pem/pem_lib.c49
-rw-r--r--crypto/pem/pem_pkey.c29
-rwxr-xr-xcrypto/perlasm/x86_64-xlate.pl9
-rw-r--r--crypto/perlasm/x86gas.pl2
-rw-r--r--crypto/pkcs8/CMakeLists.txt2
-rw-r--r--crypto/pkcs8/p5_pbe.c1
-rw-r--r--crypto/pkcs8/p5_pbev2.c1
-rw-r--r--crypto/pkcs8/pkcs12_test.cc2
-rw-r--r--crypto/pkcs8/pkcs8.c182
-rwxr-xr-xcrypto/poly1305/asm/poly1305-armv4.pl1216
-rwxr-xr-xcrypto/poly1305/asm/poly1305-armv8.pl925
-rwxr-xr-xcrypto/poly1305/asm/poly1305-x86.pl1788
-rwxr-xr-xcrypto/poly1305/asm/poly1305-x86_64.pl2235
-rw-r--r--crypto/poly1305/internal.h40
-rw-r--r--crypto/poly1305/poly1305.c17
-rw-r--r--crypto/poly1305/poly1305_arm.c1
-rw-r--r--crypto/poly1305/poly1305_test.cc59
-rw-r--r--crypto/poly1305/poly1305_test.txt52
-rw-r--r--crypto/poly1305/poly1305_tests.txt159
-rw-r--r--crypto/poly1305/poly1305_vec.c6
-rw-r--r--crypto/rand/CMakeLists.txt1
-rw-r--r--crypto/rand/deterministic.c49
-rw-r--r--crypto/rand/rand.c3
-rw-r--r--crypto/rand/urandom.c10
-rw-r--r--crypto/rand/windows.c8
-rw-r--r--crypto/rc4/asm/rc4-586.pl26
-rw-r--r--crypto/refcount_lock.c4
-rw-r--r--crypto/rsa/blinding.c299
-rw-r--r--crypto/rsa/internal.h18
-rw-r--r--crypto/rsa/padding.c15
-rw-r--r--crypto/rsa/rsa.c28
-rw-r--r--crypto/rsa/rsa_asn1.c13
-rw-r--r--crypto/rsa/rsa_impl.c253
-rw-r--r--crypto/rsa/rsa_test.cc62
-rw-r--r--crypto/sha/asm/sha512-armv4.pl2
-rw-r--r--crypto/sha/sha256.c4
-rw-r--r--crypto/sha/sha512.c4
-rw-r--r--crypto/stack/make_macros.sh9
-rw-r--r--crypto/stack/stack.c2
-rw-r--r--crypto/test/file_test.cc16
-rw-r--r--crypto/test/file_test.h10
-rw-r--r--crypto/test/scoped_types.h7
-rw-r--r--crypto/thread.c25
-rw-r--r--crypto/thread_none.c8
-rw-r--r--crypto/thread_pthread.c19
-rw-r--r--crypto/thread_test.c25
-rw-r--r--crypto/thread_win.c119
-rw-r--r--crypto/x509/CMakeLists.txt2
-rw-r--r--crypto/x509/a_sign.c6
-rw-r--r--crypto/x509/a_verify.c4
-rw-r--r--crypto/x509/algorithm.c137
-rw-r--r--crypto/x509/asn1_gen.c3
-rw-r--r--crypto/x509/by_dir.c10
-rw-r--r--crypto/x509/internal.h66
-rw-r--r--crypto/x509/pkcs7_test.c20
-rw-r--r--crypto/x509/rsa_pss.c385
-rw-r--r--crypto/x509/t_x509.c22
-rw-r--r--crypto/x509/x509.c5
-rw-r--r--crypto/x509/x509_lu.c70
-rw-r--r--crypto/x509/x509_obj.c21
-rw-r--r--crypto/x509/x509_test.cc194
-rw-r--r--crypto/x509/x509_txt.c5
-rw-r--r--crypto/x509/x509_vfy.c59
-rw-r--r--crypto/x509/x_crl.c4
-rw-r--r--crypto/x509/x_name.c31
-rw-r--r--crypto/x509/x_pubkey.c11
-rw-r--r--crypto/x509/x_x509.c68
-rw-r--r--crypto/x509v3/pcy_cache.c4
-rw-r--r--crypto/x509v3/tab_test.c1
-rw-r--r--crypto/x509v3/v3_conf.c3
-rw-r--r--crypto/x509v3/v3_cpols.c5
-rw-r--r--crypto/x509v3/v3_prn.c3
-rw-r--r--crypto/x509v3/v3_purp.c4
-rw-r--r--crypto/x509v3/v3_utl.c3
-rw-r--r--crypto/x509v3/v3name_test.c10
-rw-r--r--decrepit/CMakeLists.txt16
-rw-r--r--decrepit/bio/base64_bio.c4
-rw-r--r--decrepit/cast/cast.c4
-rw-r--r--decrepit/dh/CMakeLists.txt9
-rw-r--r--decrepit/dh/dh_decrepit.c103
-rw-r--r--decrepit/dsa/CMakeLists.txt9
-rw-r--r--decrepit/dsa/dsa_decrepit.c105
-rw-r--r--decrepit/evp/CMakeLists.txt1
-rw-r--r--decrepit/evp/dss1.c20
-rw-r--r--decrepit/obj/CMakeLists.txt9
-rw-r--r--decrepit/obj/obj_decrepit.c71
-rw-r--r--decrepit/rc4/CMakeLists.txt9
-rw-r--r--decrepit/rc4/rc4_decrepit.c62
-rw-r--r--decrepit/ripemd/CMakeLists.txt23
-rw-r--r--decrepit/ripemd/internal.h493
-rw-r--r--decrepit/ripemd/ripemd.c324
-rw-r--r--decrepit/ripemd/ripemd_test.cc119
-rw-r--r--decrepit/rsa/rsa_decrepit.c17
-rw-r--r--decrepit/ssl/CMakeLists.txt9
-rw-r--r--decrepit/ssl/ssl_decrepit.c225
-rw-r--r--decrepit/x509/CMakeLists.txt9
-rw-r--r--decrepit/x509/x509_decrepit.c42
-rw-r--r--fuzz/CMakeLists.txt27
-rw-r--r--fuzz/cert.cc22
-rw-r--r--fuzz/cert_corpus/003c6f57b1e485b75bdb524b7c141350a2f86ec2bin903 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/00591f1dde4cf571e013dcd11f40e2944cfc8715bin64 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60bebin0 -> 1080 bytes
-rw-r--r--fuzz/cert_corpus/01705fb53f7cc35f64e5796c78dad8abc6cf25cebin63 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54fbin0 -> 1022 bytes
-rw-r--r--fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408bin0 -> 1039 bytes
-rw-r--r--fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fdebin0 -> 957 bytes
-rw-r--r--fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41bin0 -> 778 bytes
-rw-r--r--fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3bin0 -> 1934 bytes
-rw-r--r--fuzz/cert_corpus/0853174f70d58b195813fbdc716c1a4f4b227ed21
-rw-r--r--fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704bin0 -> 1111 bytes
-rw-r--r--fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144bin0 -> 1316 bytes
-rw-r--r--fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5bin0 -> 1217 bytes
-rw-r--r--fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73ebin0 -> 1959 bytes
-rw-r--r--fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627bin0 -> 1021 bytes
-rw-r--r--fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59bin0 -> 1041 bytes
-rw-r--r--fuzz/cert_corpus/0d538ac33c112193da6c78e9039027f3325e99901
-rw-r--r--fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3cbin0 -> 1185 bytes
-rw-r--r--fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8fbin0 -> 1341 bytes
-rw-r--r--fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1debin0 -> 1186 bytes
-rw-r--r--fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dadbin0 -> 1027 bytes
-rw-r--r--fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1bin0 -> 1212 bytes
-rw-r--r--fuzz/cert_corpus/11cf2fd91b0edc11a509859032ebbfe89675c0c4bin62 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/1233d3b329be1220bff82db29a9497a7000e4b33bin1048 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92bin0 -> 997 bytes
-rw-r--r--fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900bin0 -> 768 bytes
-rw-r--r--fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bcbin0 -> 898 bytes
-rw-r--r--fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6ebbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164acbin0 -> 1850 bytes
-rw-r--r--fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8abin0 -> 1317 bytes
-rw-r--r--fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938bin0 -> 977 bytes
-rw-r--r--fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94ebin0 -> 1200 bytes
-rw-r--r--fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2eabin0 -> 898 bytes
-rw-r--r--fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7bin0 -> 202 bytes
-rw-r--r--fuzz/cert_corpus/1a1cb7c7bc8bbd96a752a6dde3129a9839a0a56d1
-rw-r--r--fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875bin0 -> 1053 bytes
-rw-r--r--fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8bin0 -> 127 bytes
-rw-r--r--fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc21
-rw-r--r--fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0bin0 -> 1106 bytes
-rw-r--r--fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01bin0 -> 958 bytes
-rw-r--r--fuzz/cert_corpus/1dc3882d4bcccb325751803b817489c3715db4cc1
-rw-r--r--fuzz/cert_corpus/1e177827da539595862d41ee1f470e3654a77d04bin64 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/208db41327b2152bd0b3cdb3392358dcc72951f8bin1396 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdcabin0 -> 1204 bytes
-rw-r--r--fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189bin0 -> 1494 bytes
-rw-r--r--fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132bin0 -> 193 bytes
-rw-r--r--fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304bin0 -> 1022 bytes
-rw-r--r--fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4edbin0 -> 182 bytes
-rw-r--r--fuzz/cert_corpus/2569acd835ecb6dfd61f6ce4459ba5f94df685a9bin1052 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69ebin0 -> 1058 bytes
-rw-r--r--fuzz/cert_corpus/266bb871295b34d3bf47110dd8d6c69de7733db0bin64 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4bin0 -> 1850 bytes
-rw-r--r--fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1bin0 -> 64 bytes
-rw-r--r--fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4bin0 -> 887 bytes
-rw-r--r--fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8bin0 -> 1663 bytes
-rw-r--r--fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1bin0 -> 1388 bytes
-rw-r--r--fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8bin0 -> 3 bytes
-rw-r--r--fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2bin0 -> 141 bytes
-rw-r--r--fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f01
-rw-r--r--fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571bin0 -> 707 bytes
-rw-r--r--fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79bin0 -> 12 bytes
-rw-r--r--fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1bin0 -> 1088 bytes
-rw-r--r--fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879bin0 -> 1177 bytes
-rw-r--r--fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436bin0 -> 1081 bytes
-rw-r--r--fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42bin0 -> 1469 bytes
-rw-r--r--fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572bin0 -> 1005 bytes
-rw-r--r--fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999adbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5bbin0 -> 1373 bytes
-rw-r--r--fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9bbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bdbin0 -> 975 bytes
-rw-r--r--fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06bin0 -> 1039 bytes
-rw-r--r--fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9bin0 -> 1569 bytes
-rw-r--r--fuzz/cert_corpus/36827665da414f5d36db7850ae76975eb7d616e91
-rw-r--r--fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17fbin0 -> 770 bytes
-rw-r--r--fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0bin0 -> 1851 bytes
-rw-r--r--fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7bin0 -> 61 bytes
-rw-r--r--fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664cbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4bin0 -> 1111 bytes
-rw-r--r--fuzz/cert_corpus/39b894e9f4745142150a62b7688ac4dfac65375dbin63 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835eebin0 -> 1039 bytes
-rw-r--r--fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33bin0 -> 992 bytes
-rw-r--r--fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541bin0 -> 1631 bytes
-rw-r--r--fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151bin0 -> 686 bytes
-rw-r--r--fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537bin0 -> 993 bytes
-rw-r--r--fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898dbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137bin0 -> 1337 bytes
-rw-r--r--fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645bin0 -> 941 bytes
-rw-r--r--fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89abin0 -> 1044 bytes
-rw-r--r--fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934bin0 -> 1839 bytes
-rw-r--r--fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fabbin0 -> 12 bytes
-rw-r--r--fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119cbin0 -> 1394 bytes
-rw-r--r--fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6bin0 -> 1017 bytes
-rw-r--r--fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3bin0 -> 1328 bytes
-rw-r--r--fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866bin0 -> 2046 bytes
-rw-r--r--fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbbbin0 -> 1151 bytes
-rw-r--r--fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92cbin0 -> 1081 bytes
-rw-r--r--fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991bbin0 -> 1005 bytes
-rw-r--r--fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699fafbin0 -> 1317 bytes
-rw-r--r--fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2bin0 -> 320 bytes
-rw-r--r--fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693adbin0 -> 899 bytes
-rw-r--r--fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bcbin0 -> 1111 bytes
-rw-r--r--fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90bin0 -> 1327 bytes
-rw-r--r--fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7ddbin0 -> 705 bytes
-rw-r--r--fuzz/cert_corpus/4b3fff8f4209aec529055a64cb7b38b89513c725bin1570 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5bin0 -> 279 bytes
-rw-r--r--fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0bin0 -> 1642 bytes
-rw-r--r--fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b51
-rw-r--r--fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6bin0 -> 1607 bytes
-rw-r--r--fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84bin0 -> 1317 bytes
-rw-r--r--fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2bin0 -> 1625 bytes
-rw-r--r--fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057bin0 -> 1780 bytes
-rw-r--r--fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90bin0 -> 1624 bytes
-rw-r--r--fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59cbin0 -> 976 bytes
-rw-r--r--fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a1
-rw-r--r--fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0bin0 -> 1059 bytes
-rw-r--r--fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854bin0 -> 1196 bytes
-rw-r--r--fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2fbin0 -> 1040 bytes
-rw-r--r--fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23bin0 -> 1018 bytes
-rw-r--r--fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92bin0 -> 1631 bytes
-rw-r--r--fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77cafbin0 -> 1217 bytes
-rw-r--r--fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b1
-rw-r--r--fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8bin0 -> 1934 bytes
-rw-r--r--fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422bin0 -> 1055 bytes
-rw-r--r--fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132bbin0 -> 1200 bytes
-rw-r--r--fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8bin0 -> 1492 bytes
-rw-r--r--fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdfbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224bin0 -> 1502 bytes
-rw-r--r--fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb1
-rw-r--r--fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31bin0 -> 1205 bytes
-rw-r--r--fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5bbin0 -> 836 bytes
-rw-r--r--fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4bin0 -> 898 bytes
-rw-r--r--fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9bin0 -> 818 bytes
-rw-r--r--fuzz/cert_corpus/60c9a5ce074daf266315dfa2093b014b43baedd6bin1520 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/60fe312a17b6d5a46ca05116fbc5cfd23977bab4bin2140 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337bin0 -> 160 bytes
-rw-r--r--fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715bin0 -> 12 bytes
-rw-r--r--fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719bbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33bin0 -> 64 bytes
-rw-r--r--fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148bin0 -> 193 bytes
-rw-r--r--fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1bin0 -> 976 bytes
-rw-r--r--fuzz/cert_corpus/6fcf556855dd7013e57ae7a729f43bc9d76d41f1bin986 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7dbin0 -> 1958 bytes
-rw-r--r--fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cdbin0 -> 1044 bytes
-rw-r--r--fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f061
-rw-r--r--fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744bin0 -> 1336 bytes
-rw-r--r--fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330bin0 -> 1302 bytes
-rw-r--r--fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5dbin0 -> 621 bytes
-rw-r--r--fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18bin0 -> 1492 bytes
-rw-r--r--fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5bin0 -> 1777 bytes
-rw-r--r--fuzz/cert_corpus/7359755c6df9a0abc3060bce369564c8ec4542a3bin897 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224bin0 -> 1081 bytes
-rw-r--r--fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5cbin0 -> 1432 bytes
-rw-r--r--fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccdbin0 -> 1137 bytes
-rw-r--r--fuzz/cert_corpus/74ea68736ec375b226f0ca86464d2d43baac3574bin1022 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d751
-rw-r--r--fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9bin0 -> 10 bytes
-rw-r--r--fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876bin0 -> 974 bytes
-rw-r--r--fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144bin0 -> 1098 bytes
-rw-r--r--fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847bin0 -> 1221 bytes
-rw-r--r--fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5fbin0 -> 1020 bytes
-rw-r--r--fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785ebbin0 -> 193 bytes
-rw-r--r--fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988bbin0 -> 23 bytes
-rw-r--r--fuzz/cert_corpus/8275aabe75b73bb398933bf9a106fde4b198d1b1bin1220 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1bin0 -> 1642 bytes
-rw-r--r--fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48bin0 -> 1730 bytes
-rw-r--r--fuzz/cert_corpus/840007514cd63aca9bd6d65fe5d1eb4c58600106bin1041 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264defbin0 -> 1256 bytes
-rw-r--r--fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85bin0 -> 1131 bytes
-rw-r--r--fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/87555b600217d444d85e8a7afece3239a566c6a0bin1006 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57fbin0 -> 244 bytes
-rw-r--r--fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668bin0 -> 767 bytes
-rw-r--r--fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35bin0 -> 1849 bytes
-rw-r--r--fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050eadbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886dbin0 -> 671 bytes
-rw-r--r--fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8fbin0 -> 1839 bytes
-rw-r--r--fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fadebin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665bin0 -> 1469 bytes
-rw-r--r--fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431bin0 -> 71 bytes
-rw-r--r--fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4dbin0 -> 1041 bytes
-rw-r--r--fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3bin0 -> 1631 bytes
-rw-r--r--fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538bin0 -> 1019 bytes
-rw-r--r--fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00bin0 -> 70 bytes
-rw-r--r--fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0abin0 -> 998 bytes
-rw-r--r--fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723adbin0 -> 771 bytes
-rw-r--r--fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394bin0 -> 1096 bytes
-rw-r--r--fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eaebin0 -> 128 bytes
-rw-r--r--fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a931
-rw-r--r--fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bdbin0 -> 262 bytes
-rw-r--r--fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fadbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54dbbin0 -> 144 bytes
-rw-r--r--fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc6311
-rw-r--r--fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9bin0 -> 1041 bytes
-rw-r--r--fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079bin0 -> 1096 bytes
-rw-r--r--fuzz/cert_corpus/9a5618d71d29f45a7dbe3f2b98d66702427faaafbin975 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3bin0 -> 975 bytes
-rw-r--r--fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7dbin0 -> 1112 bytes
-rw-r--r--fuzz/cert_corpus/9d1eb7853324fba4aa29f65e2213c54c44d988a6bin1124 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffdbin0 -> 1004 bytes
-rw-r--r--fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d1551
-rw-r--r--fuzz/cert_corpus/9df5fabe0c5cdf7cf5c427be02ed3cee33b2a0e9bin1187 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/9fad61f53d1256a653b0f9351b6624793089f50cbin1200 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3bin0 -> 195 bytes
-rw-r--r--fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bffbin0 -> 1082 bytes
-rw-r--r--fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420bin0 -> 1088 bytes
-rw-r--r--fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9bin0 -> 1372 bytes
-rw-r--r--fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029bin0 -> 1869 bytes
-rw-r--r--fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f1
-rw-r--r--fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681bin0 -> 884 bytes
-rw-r--r--fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e831
-rw-r--r--fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d41
-rw-r--r--fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741abin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88dbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31abin0 -> 1254 bytes
-rw-r--r--fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbebbin0 -> 996 bytes
-rw-r--r--fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcdbin0 -> 1040 bytes
-rw-r--r--fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457bin0 -> 1040 bytes
-rw-r--r--fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4abin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0abin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9bin0 -> 216 bytes
-rw-r--r--fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746bin0 -> 603 bytes
-rw-r--r--fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85bbin0 -> 2009 bytes
-rw-r--r--fuzz/cert_corpus/ae820c47ddc20ff0be7109c331f04b7d5ddd623abin957 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95ebbin0 -> 70 bytes
-rw-r--r--fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048abin0 -> 1020 bytes
-rw-r--r--fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a2235421
-rw-r--r--fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b991
-rw-r--r--fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74bin0 -> 1342 bytes
-rw-r--r--fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902bin0 -> 969 bytes
-rw-r--r--fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba291
-rw-r--r--fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84bin0 -> 1919 bytes
-rw-r--r--fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fdabin0 -> 959 bytes
-rw-r--r--fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0acbin0 -> 1106 bytes
-rw-r--r--fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7bin0 -> 1002 bytes
-rw-r--r--fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2bin0 -> 1193 bytes
-rw-r--r--fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399bin0 -> 745 bytes
-rw-r--r--fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0bin0 -> 1081 bytes
-rw-r--r--fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7ebin0 -> 71 bytes
-rw-r--r--fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068bin0 -> 896 bytes
-rw-r--r--fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92bin0 -> 1110 bytes
-rw-r--r--fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767cbin0 -> 898 bytes
-rw-r--r--fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092defbin0 -> 976 bytes
-rw-r--r--fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edfbin0 -> 12 bytes
-rw-r--r--fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2bin0 -> 898 bytes
-rw-r--r--fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28bin0 -> 1280 bytes
-rw-r--r--fuzz/cert_corpus/c0bc4e081e8de875ffd9f4e4f611351d790c3316bin1505 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851bbin0 -> 1041 bytes
-rw-r--r--fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea1
-rw-r--r--fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6bin0 -> 1102 bytes
-rw-r--r--fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180bbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4bin0 -> 976 bytes
-rw-r--r--fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3bin0 -> 1853 bytes
-rw-r--r--fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fddbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/c5ed379b9f6794810a09862f48297a9e576014adbin62 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de921
-rw-r--r--fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fbbin0 -> 1373 bytes
-rw-r--r--fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54bin0 -> 2048 bytes
-rw-r--r--fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8bin0 -> 5 bytes
-rw-r--r--fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644bin0 -> 996 bytes
-rw-r--r--fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18cabin0 -> 1041 bytes
-rw-r--r--fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9abin0 -> 1528 bytes
-rw-r--r--fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1cabin0 -> 1378 bytes
-rw-r--r--fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66fbin0 -> 991 bytes
-rw-r--r--fuzz/cert_corpus/d0ff24cb960cd6b725466290c98faec196340ad3bin1055 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0dbin0 -> 562 bytes
-rw-r--r--fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889cbin0 -> 218 bytes
-rw-r--r--fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/d5d316b2ae6ca106895ecfc4d77cab5ee403b624bin957 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15bin0 -> 252 bytes
-rw-r--r--fuzz/cert_corpus/d642d2788c9378b41858bfd84d8f493df5a6ed90bin2071 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724dbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152dbin0 -> 1431 bytes
-rw-r--r--fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796bin0 -> 2048 bytes
-rw-r--r--fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1bin0 -> 990 bytes
-rw-r--r--fuzz/cert_corpus/d9f35e97892b69a6b1f7053907b45bec9aaf878bbin2548 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/daaf3e94dde553128327f392e512eed23d939a06bin1045 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/dc0186c5badd988d5ee4dd4c3013311d301d3104bin62 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48eebin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/dce902110210d2f6bb76f2dba03e7144897f1111bin1557 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674bin0 -> 986 bytes
-rw-r--r--fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4ebin0 -> 1838 bytes
-rw-r--r--fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c791
-rw-r--r--fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945bin0 -> 1766 bytes
-rw-r--r--fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b251
-rw-r--r--fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229bin0 -> 1905 bytes
-rw-r--r--fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddfbin0 -> 112 bytes
-rw-r--r--fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794bin0 -> 766 bytes
-rw-r--r--fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22bin0 -> 1088 bytes
-rw-r--r--fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2bin0 -> 1624 bytes
-rw-r--r--fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cdbin0 -> 1192 bytes
-rw-r--r--fuzz/cert_corpus/ec7f5fea97ac8cca5a49f7833769e026b55916b9bin897 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/eca7916b3e759ecd116bd761c7df90adda331bc5bin1373 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/eccdca719eadb11048cfea5e48e5fd9fa44be622bin63 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53bin0 -> 1177 bytes
-rw-r--r--fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100bin0 -> 1244 bytes
-rw-r--r--fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95bin0 -> 1244 bytes
-rw-r--r--fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44bin0 -> 1088 bytes
-rw-r--r--fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987cbin0 -> 161 bytes
-rw-r--r--fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119bin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741bin0 -> 888 bytes
-rw-r--r--fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8bin0 -> 1224 bytes
-rw-r--r--fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1bin0 -> 1396 bytes
-rw-r--r--fuzz/cert_corpus/f50d7ea12daaf659dc71a82e17daa9cad454be8b1
-rw-r--r--fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567bbin0 -> 1927 bytes
-rw-r--r--fuzz/cert_corpus/fb7209d187e6c93f840abfded54439ea031fe0debin1630 -> 0 bytes
-rw-r--r--fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0bin0 -> 887 bytes
-rw-r--r--fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4acbin0 -> 897 bytes
-rw-r--r--fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547bin0 -> 151 bytes
-rw-r--r--fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2bin0 -> 897 bytes
-rw-r--r--fuzz/client.cc29
-rw-r--r--fuzz/client_corpus/0045429528cdad90f2fea4a05a6a35311af246d8bin3719 -> 0 bytes
-rw-r--r--fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87cbin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801deebin0 -> 2420 bytes
-rw-r--r--fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16bin0 -> 3775 bytes
-rw-r--r--fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2bin0 -> 3202 bytes
-rw-r--r--fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05bin0 -> 3309 bytes
-rw-r--r--fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45bin0 -> 2606 bytes
-rw-r--r--fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5bin0 -> 2721 bytes
-rw-r--r--fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263bin0 -> 3572 bytes
-rw-r--r--fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865bin0 -> 2905 bytes
-rw-r--r--fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078bin0 -> 1015 bytes
-rw-r--r--fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520bin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8bin0 -> 887 bytes
-rw-r--r--fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343bin0 -> 3330 bytes
-rw-r--r--fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6bin0 -> 2491 bytes
-rw-r--r--fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3bin0 -> 3404 bytes
-rw-r--r--fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0dbin0 -> 116 bytes
-rw-r--r--fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968fbin0 -> 736 bytes
-rw-r--r--fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85bin0 -> 951 bytes
-rw-r--r--fuzz/client_corpus/08166819b9de009808ba8aeeb2e11eb6d1b1bba8bin330 -> 0 bytes
-rw-r--r--fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0abin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35bin0 -> 1615 bytes
-rw-r--r--fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740bin0 -> 1092 bytes
-rw-r--r--fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903bin0 -> 3977 bytes
-rw-r--r--fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145bin0 -> 1511 bytes
-rw-r--r--fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099bin0 -> 3676 bytes
-rw-r--r--fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103bin0 -> 3911 bytes
-rw-r--r--fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/0c79672c66964d7747dbf2f2321a2e204a35f68fbin540 -> 0 bytes
-rw-r--r--fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629dbin0 -> 1000 bytes
-rw-r--r--fuzz/client_corpus/0d5c745716044febd8eeac90ae421efc7fc52530bin1311 -> 0 bytes
-rw-r--r--fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/0e8233cf1731cca3af17ab71677c477d877ac384bin3425 -> 0 bytes
-rw-r--r--fuzz/client_corpus/0ecdd5fd1d9a04965be08daa6a8df1450eb2535dbin3433 -> 0 bytes
-rw-r--r--fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51dbin0 -> 161 bytes
-rw-r--r--fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28bin0 -> 3590 bytes
-rw-r--r--fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9fbin0 -> 675 bytes
-rw-r--r--fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04adbin0 -> 3920 bytes
-rw-r--r--fuzz/client_corpus/0ff674842ef580cca7a5a6422808d7b698027131bin3720 -> 0 bytes
-rw-r--r--fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538bin0 -> 3465 bytes
-rw-r--r--fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370bin0 -> 1767 bytes
-rw-r--r--fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720bin0 -> 1616 bytes
-rw-r--r--fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8fbin0 -> 3289 bytes
-rw-r--r--fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8bin0 -> 3994 bytes
-rw-r--r--fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4abin0 -> 1658 bytes
-rw-r--r--fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1bbin0 -> 3407 bytes
-rw-r--r--fuzz/client_corpus/1263ef52964f6480ecfb0703593b43f62ad6e0f0bin3580 -> 0 bytes
-rw-r--r--fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5ebin0 -> 3572 bytes
-rw-r--r--fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbbbin0 -> 1616 bytes
-rw-r--r--fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526bin0 -> 3588 bytes
-rw-r--r--fuzz/client_corpus/1387b2abb0baff44aa00f822361ac1627f59b0abbin3404 -> 0 bytes
-rw-r--r--fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49bin0 -> 3570 bytes
-rw-r--r--fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95ebin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063bbin0 -> 3175 bytes
-rw-r--r--fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6bin0 -> 1602 bytes
-rw-r--r--fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9bin0 -> 3099 bytes
-rw-r--r--fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bfbin0 -> 3189 bytes
-rw-r--r--fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0dbin0 -> 990 bytes
-rw-r--r--fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644bin0 -> 1619 bytes
-rw-r--r--fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7bin0 -> 786 bytes
-rw-r--r--fuzz/client_corpus/170cc10f660a715bbde0e00ad2d20f2c518a9716bin3612 -> 0 bytes
-rw-r--r--fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5abin0 -> 958 bytes
-rw-r--r--fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801bin0 -> 1228 bytes
-rw-r--r--fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6decbin0 -> 1354 bytes
-rw-r--r--fuzz/client_corpus/17f8d2b61c40dd352a6fb9f72e8ab6824a992f3abin3210 -> 0 bytes
-rw-r--r--fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4aebin0 -> 809 bytes
-rw-r--r--fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6dbin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1dbin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924bin0 -> 3386 bytes
-rw-r--r--fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7fbin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/1acd222a42da3a075dffa389d6afb2f42b6e143bbin3677 -> 0 bytes
-rw-r--r--fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38bin0 -> 2039 bytes
-rw-r--r--fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00bbin0 -> 986 bytes
-rw-r--r--fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6bin0 -> 3832 bytes
-rw-r--r--fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069bin0 -> 3470 bytes
-rw-r--r--fuzz/client_corpus/1d79993946951d8c5e37daccdd793c73f8c8b7a4bin3920 -> 0 bytes
-rw-r--r--fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2bin0 -> 925 bytes
-rw-r--r--fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/1eb2aba2bb11920007b64d8c9a2dd5f54c398591bin3572 -> 0 bytes
-rw-r--r--fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7bin0 -> 1511 bytes
-rw-r--r--fuzz/client_corpus/1f0ba9f8642a13aab05da4fb0add5257cfa0622ebin3439 -> 0 bytes
-rw-r--r--fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92bin0 -> 1461 bytes
-rw-r--r--fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55dabin0 -> 3642 bytes
-rw-r--r--fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ffbin0 -> 903 bytes
-rw-r--r--fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9bbin0 -> 3502 bytes
-rw-r--r--fuzz/client_corpus/2188751539674238828d645bbde78b4cef2fa39cbin3759 -> 0 bytes
-rw-r--r--fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73abin0 -> 3677 bytes
-rw-r--r--fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819bin0 -> 1165 bytes
-rw-r--r--fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647dbin0 -> 894 bytes
-rw-r--r--fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89bin0 -> 3022 bytes
-rw-r--r--fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92bin0 -> 3383 bytes
-rw-r--r--fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625bin0 -> 788 bytes
-rw-r--r--fuzz/client_corpus/236017193c5b7a862bc69756b856028eef0f10afbin315 -> 0 bytes
-rw-r--r--fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560bin0 -> 3403 bytes
-rw-r--r--fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0bbin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dcbin0 -> 965 bytes
-rw-r--r--fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740bin0 -> 4037 bytes
-rw-r--r--fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4bin0 -> 1410 bytes
-rw-r--r--fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79bin0 -> 3994 bytes
-rw-r--r--fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873dabin0 -> 750 bytes
-rw-r--r--fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129ebin0 -> 3202 bytes
-rw-r--r--fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bbbin0 -> 2058 bytes
-rw-r--r--fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296dbin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2bin0 -> 3962 bytes
-rw-r--r--fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1bin0 -> 3483 bytes
-rw-r--r--fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7bin0 -> 3795 bytes
-rw-r--r--fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857fbin0 -> 934 bytes
-rw-r--r--fuzz/client_corpus/2ac1d35580c355bdab0b951f07b1983b4bd6b981bin142 -> 0 bytes
-rw-r--r--fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9cbin0 -> 643 bytes
-rw-r--r--fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8abin0 -> 2100 bytes
-rw-r--r--fuzz/client_corpus/2b2b7b4cc764d2141319668022a3a220864f421ebin3881 -> 0 bytes
-rw-r--r--fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205bin0 -> 738 bytes
-rw-r--r--fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6bin0 -> 902 bytes
-rw-r--r--fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552bin0 -> 903 bytes
-rw-r--r--fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8bin0 -> 875 bytes
-rw-r--r--fuzz/client_corpus/2c593c598bad54c9ec436a543910f18adfe1e40fbin3469 -> 0 bytes
-rw-r--r--fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020bin0 -> 3191 bytes
-rw-r--r--fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aabin0 -> 3332 bytes
-rw-r--r--fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/2e113fb2084dbb3623caaa1bc9240417eb1745e7bin3208 -> 0 bytes
-rw-r--r--fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5bin0 -> 3401 bytes
-rw-r--r--fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40ebin0 -> 1864 bytes
-rw-r--r--fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248bin0 -> 3330 bytes
-rw-r--r--fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85abin0 -> 2270 bytes
-rw-r--r--fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66ebin0 -> 3616 bytes
-rw-r--r--fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825bin0 -> 3833 bytes
-rw-r--r--fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224bin0 -> 1952 bytes
-rw-r--r--fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6abin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/31070a7503de09885b27548828871cd7095deae6bin3253 -> 0 bytes
-rw-r--r--fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8bin0 -> 915 bytes
-rw-r--r--fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501bin0 -> 3964 bytes
-rw-r--r--fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39bin0 -> 1918 bytes
-rw-r--r--fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7cbin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02bin0 -> 1027 bytes
-rw-r--r--fuzz/client_corpus/3368ce768ff26ebc4e4e7b3bd1f1574afc71435fbin3381 -> 0 bytes
-rw-r--r--fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31bin0 -> 3908 bytes
-rw-r--r--fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9dbin0 -> 3747 bytes
-rw-r--r--fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203bin0 -> 3572 bytes
-rw-r--r--fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbebin0 -> 2917 bytes
-rw-r--r--fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725bbin0 -> 736 bytes
-rw-r--r--fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0fbin0 -> 3294 bytes
-rw-r--r--fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8bin0 -> 644 bytes
-rw-r--r--fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14bin0 -> 2434 bytes
-rw-r--r--fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12bin0 -> 2057 bytes
-rw-r--r--fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5bin0 -> 898 bytes
-rw-r--r--fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6dbin0 -> 3630 bytes
-rw-r--r--fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308bin0 -> 3447 bytes
-rw-r--r--fuzz/client_corpus/3940f0ddcaac3b00c6ddb06c29483958214a8d08bin3328 -> 0 bytes
-rw-r--r--fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4bin0 -> 3201 bytes
-rw-r--r--fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656bin0 -> 3325 bytes
-rw-r--r--fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809bin0 -> 9134 bytes
-rw-r--r--fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afbbin0 -> 3155 bytes
-rw-r--r--fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438cbin0 -> 986 bytes
-rw-r--r--fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37cbin0 -> 4026 bytes
-rw-r--r--fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834cbin0 -> 3200 bytes
-rw-r--r--fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebbabin0 -> 1014 bytes
-rw-r--r--fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512abin0 -> 736 bytes
-rw-r--r--fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5afbin0 -> 1014 bytes
-rw-r--r--fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495bin0 -> 3271 bytes
-rw-r--r--fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5bin0 -> 1000 bytes
-rw-r--r--fuzz/client_corpus/3c4871d7a5c1819913394d6997693857c117cb24bin3701 -> 0 bytes
-rw-r--r--fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988cbin0 -> 3572 bytes
-rw-r--r--fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3bebbin0 -> 3446 bytes
-rw-r--r--fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80bin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0bin0 -> 1428 bytes
-rw-r--r--fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6fbin0 -> 3964 bytes
-rw-r--r--fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5bbin0 -> 962 bytes
-rw-r--r--fuzz/client_corpus/4105f3698152311e9e23ebec179197475c8910d4bin3501 -> 0 bytes
-rw-r--r--fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5bin0 -> 4072 bytes
-rw-r--r--fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5abin0 -> 3501 bytes
-rw-r--r--fuzz/client_corpus/43288d61a185406eeef5c10298a898755dd108dcbin3590 -> 0 bytes
-rw-r--r--fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fbbin0 -> 3948 bytes
-rw-r--r--fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bdbin0 -> 1373 bytes
-rw-r--r--fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8bin0 -> 3580 bytes
-rw-r--r--fuzz/client_corpus/447ab5b3ef953688fc388dd37555497ce1213a4abin3403 -> 0 bytes
-rw-r--r--fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5bin0 -> 1195 bytes
-rw-r--r--fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872bbin0 -> 944 bytes
-rw-r--r--fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64bin0 -> 1074 bytes
-rw-r--r--fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252bin0 -> 898 bytes
-rw-r--r--fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1bin0 -> 3573 bytes
-rw-r--r--fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cbbin0 -> 3570 bytes
-rw-r--r--fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8bin0 -> 1494 bytes
-rw-r--r--fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552cbin0 -> 1194 bytes
-rw-r--r--fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418bin0 -> 3401 bytes
-rw-r--r--fuzz/client_corpus/480fa3d3cf83d7a161f4a3d863cc5b256c95b0cbbin272 -> 0 bytes
-rw-r--r--fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54bin0 -> 3481 bytes
-rw-r--r--fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01dbin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77bin0 -> 3639 bytes
-rw-r--r--fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4ebin0 -> 4080 bytes
-rw-r--r--fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80bin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35ebin0 -> 675 bytes
-rw-r--r--fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfdbin0 -> 3964 bytes
-rw-r--r--fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0bin0 -> 4029 bytes
-rw-r--r--fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8abin0 -> 1073 bytes
-rw-r--r--fuzz/client_corpus/4ad82ef07c3ced7fa615073827bc04a3e4969a3dbin3880 -> 0 bytes
-rw-r--r--fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714bin0 -> 12560 bytes
-rw-r--r--fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35bin0 -> 4036 bytes
-rw-r--r--fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412bin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178bin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42bin0 -> 953 bytes
-rw-r--r--fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dcbin0 -> 3189 bytes
-rw-r--r--fuzz/client_corpus/4c72c8bec7ac46b94757c9043197afa1b13eaa27bin3839 -> 0 bytes
-rw-r--r--fuzz/client_corpus/4c8d920b2b9c2c43b50561b90e9c6a03689e7171bin3555 -> 0 bytes
-rw-r--r--fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479bin0 -> 3676 bytes
-rw-r--r--fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866ebin0 -> 1041 bytes
-rw-r--r--fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cfbin0 -> 1734 bytes
-rw-r--r--fuzz/client_corpus/4d6fed1b6f36945060b1b4f73ca29e20cf76744dbin3382 -> 0 bytes
-rw-r--r--fuzz/client_corpus/4dbe7996ef1b6fc26351aec25483eebfefb0c678bin1033 -> 0 bytes
-rw-r--r--fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbebin0 -> 3401 bytes
-rw-r--r--fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32bin0 -> 1533 bytes
-rw-r--r--fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/4e53d29f05655cd0f1a746b3ddabd86e479486ffbin2954 -> 0 bytes
-rw-r--r--fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249bbin0 -> 884 bytes
-rw-r--r--fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13bin0 -> 736 bytes
-rw-r--r--fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71bin0 -> 1088 bytes
-rw-r--r--fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9bin0 -> 2752 bytes
-rw-r--r--fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261dbin0 -> 1800 bytes
-rw-r--r--fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55bin0 -> 3099 bytes
-rw-r--r--fuzz/client_corpus/505c17e142df143ed7c625dbb2a03999d335c2c4bin3451 -> 0 bytes
-rw-r--r--fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1bin0 -> 3273 bytes
-rw-r--r--fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebcbin0 -> 3544 bytes
-rw-r--r--fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183bin0 -> 2425 bytes
-rw-r--r--fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78bin0 -> 1132 bytes
-rw-r--r--fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3bin0 -> 3916 bytes
-rw-r--r--fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9bin0 -> 70 bytes
-rw-r--r--fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14bin0 -> 2753 bytes
-rw-r--r--fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350bin0 -> 3259 bytes
-rw-r--r--fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1bin0 -> 3888 bytes
-rw-r--r--fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306bin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608abin0 -> 835 bytes
-rw-r--r--fuzz/client_corpus/55e200ec05782651e9fb7034708fc21048a63cb1bin3810 -> 0 bytes
-rw-r--r--fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44bin0 -> 3775 bytes
-rw-r--r--fuzz/client_corpus/5668dabb85cbf4c3021307c59f8aef76cf7c2cf8bin3414 -> 0 bytes
-rw-r--r--fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9cbin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374abin0 -> 1164 bytes
-rw-r--r--fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0bin0 -> 4095 bytes
-rw-r--r--fuzz/client_corpus/578c44a3c147de923df010f2fc2ab66509a46efbbin3952 -> 0 bytes
-rw-r--r--fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449bin0 -> 1931 bytes
-rw-r--r--fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9bin0 -> 3737 bytes
-rw-r--r--fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2bin0 -> 1176 bytes
-rw-r--r--fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4cbin0 -> 2171 bytes
-rw-r--r--fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87abin0 -> 3200 bytes
-rw-r--r--fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47abin0 -> 2293 bytes
-rw-r--r--fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5bin0 -> 2251 bytes
-rw-r--r--fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fabin0 -> 3648 bytes
-rw-r--r--fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2bin0 -> 1740 bytes
-rw-r--r--fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6fbin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0bin0 -> 1178 bytes
-rw-r--r--fuzz/client_corpus/5c3eff78d2ab5b4cabbbccedb3bde8c213b6e764bin3843 -> 0 bytes
-rw-r--r--fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635bin0 -> 1991 bytes
-rw-r--r--fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77bbin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebaebin0 -> 4029 bytes
-rw-r--r--fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7bin0 -> 493 bytes
-rw-r--r--fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5bbin0 -> 1443 bytes
-rw-r--r--fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3abin0 -> 672 bytes
-rw-r--r--fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/5e5aac66a37640a8f570abd028adfdd9b50ba75abin3681 -> 0 bytes
-rw-r--r--fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331bin0 -> 3164 bytes
-rw-r--r--fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925bin0 -> 3447 bytes
-rw-r--r--fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5bin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabebin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34bbin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4bbin0 -> 3188 bytes
-rw-r--r--fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78cbin0 -> 1426 bytes
-rw-r--r--fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03bin0 -> 1089 bytes
-rw-r--r--fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08bin0 -> 1243 bytes
-rw-r--r--fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343bin0 -> 884 bytes
-rw-r--r--fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56bin0 -> 1863 bytes
-rw-r--r--fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5abin0 -> 1073 bytes
-rw-r--r--fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6bin0 -> 1512 bytes
-rw-r--r--fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6bin0 -> 2434 bytes
-rw-r--r--fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9bin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341abin0 -> 672 bytes
-rw-r--r--fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7dbin0 -> 736 bytes
-rw-r--r--fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caabin0 -> 3465 bytes
-rw-r--r--fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561bin0 -> 3687 bytes
-rw-r--r--fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851abin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153abin0 -> 3501 bytes
-rw-r--r--fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6bbin0 -> 2202 bytes
-rw-r--r--fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613bin0 -> 492 bytes
-rw-r--r--fuzz/client_corpus/674253e9d5eacc5c0133fe872f32c2e8a2ea4cf7bin3776 -> 0 bytes
-rw-r--r--fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2bin0 -> 1512 bytes
-rw-r--r--fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545bin0 -> 1266 bytes
-rw-r--r--fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12bin0 -> 945 bytes
-rw-r--r--fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80bin0 -> 3784 bytes
-rw-r--r--fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11bbin0 -> 1806 bytes
-rw-r--r--fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62bin0 -> 1195 bytes
-rw-r--r--fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262bin0 -> 893 bytes
-rw-r--r--fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbdbin0 -> 3401 bytes
-rw-r--r--fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960abin0 -> 3995 bytes
-rw-r--r--fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045bin0 -> 932 bytes
-rw-r--r--fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecfbin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312bin0 -> 809 bytes
-rw-r--r--fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2ebin0 -> 3483 bytes
-rw-r--r--fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463bbin0 -> 4095 bytes
-rw-r--r--fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363dfbin0 -> 970 bytes
-rw-r--r--fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5abin0 -> 3572 bytes
-rw-r--r--fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcadbin0 -> 3784 bytes
-rw-r--r--fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eecbin0 -> 3570 bytes
-rw-r--r--fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7bin0 -> 4095 bytes
-rw-r--r--fuzz/client_corpus/6fca24aa17c9d63a109d89bf05f7cf847fd3de7ebin3677 -> 0 bytes
-rw-r--r--fuzz/client_corpus/700a646ead0f82d584b5bc69901ea3a4d6dbee52bin574 -> 0 bytes
-rw-r--r--fuzz/client_corpus/7072ff5269664a33f709ca3fc6bb158667c3c421bin159 -> 0 bytes
-rw-r--r--fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5bin0 -> 1496 bytes
-rw-r--r--fuzz/client_corpus/71050f1658866c73590296856c498f54087519ccbin0 -> 1384 bytes
-rw-r--r--fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864bin0 -> 3790 bytes
-rw-r--r--fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4abin0 -> 3403 bytes
-rw-r--r--fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388bin0 -> 943 bytes
-rw-r--r--fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1bin0 -> 883 bytes
-rw-r--r--fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7bin0 -> 2145 bytes
-rw-r--r--fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4bin0 -> 2548 bytes
-rw-r--r--fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14bbin0 -> 2093 bytes
-rw-r--r--fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5bin0 -> 2952 bytes
-rw-r--r--fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0bin0 -> 3501 bytes
-rw-r--r--fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6cbin0 -> 3294 bytes
-rw-r--r--fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43bin0 -> 671 bytes
-rw-r--r--fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4bin0 -> 3401 bytes
-rw-r--r--fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20bin0 -> 3094 bytes
-rw-r--r--fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24bin0 -> 1444 bytes
-rw-r--r--fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186ccbin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/75d5755e499a739b66987b12149f914e04227fdabin3595 -> 0 bytes
-rw-r--r--fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7bin0 -> 933 bytes
-rw-r--r--fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254bin0 -> 1636 bytes
-rw-r--r--fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4bin0 -> 3325 bytes
-rw-r--r--fuzz/client_corpus/7753dbbdf3391950f08197d3158ee144b58ae9d4bin3995 -> 0 bytes
-rw-r--r--fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29bin0 -> 865 bytes
-rw-r--r--fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9bin0 -> 3826 bytes
-rw-r--r--fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6bin0 -> 932 bytes
-rw-r--r--fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088bin0 -> 1616 bytes
-rw-r--r--fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4efbin0 -> 2391 bytes
-rw-r--r--fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3bin0 -> 260 bytes
-rw-r--r--fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210bbin0 -> 3910 bytes
-rw-r--r--fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40bin0 -> 3570 bytes
-rw-r--r--fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35bin0 -> 866 bytes
-rw-r--r--fuzz/client_corpus/79ff7a233e149ae13d67905eda9e5af4ed27fbe0bin3700 -> 0 bytes
-rw-r--r--fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913bin0 -> 4055 bytes
-rw-r--r--fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0bin0 -> 736 bytes
-rw-r--r--fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853bbin0 -> 3797 bytes
-rw-r--r--fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578bin0 -> 1228 bytes
-rw-r--r--fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5dbin0 -> 3943 bytes
-rw-r--r--fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0bin0 -> 1014 bytes
-rw-r--r--fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256bin0 -> 1738 bytes
-rw-r--r--fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01ebin0 -> 1071 bytes
-rw-r--r--fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320dbin0 -> 3200 bytes
-rw-r--r--fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053bin0 -> 1094 bytes
-rw-r--r--fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26bin0 -> 2270 bytes
-rw-r--r--fuzz/client_corpus/7d3b5ce72e5374d1771f33b19dbc5ed20f423aebbin3984 -> 0 bytes
-rw-r--r--fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63bin0 -> 2554 bytes
-rw-r--r--fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0bin0 -> 1126 bytes
-rw-r--r--fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87babin0 -> 3555 bytes
-rw-r--r--fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044dbin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817bbin0 -> 4094 bytes
-rw-r--r--fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1eabin0 -> 3796 bytes
-rw-r--r--fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfabin0 -> 893 bytes
-rw-r--r--fuzz/client_corpus/7f080ab49b7b5feb09319aa348413686b20b8394bin3964 -> 0 bytes
-rw-r--r--fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57cabin0 -> 866 bytes
-rw-r--r--fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86bin0 -> 3881 bytes
-rw-r--r--fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205bin0 -> 986 bytes
-rw-r--r--fuzz/client_corpus/7fd9affa725bf314f60d28ae06bcc038b7dc3dd0bin3909 -> 0 bytes
-rw-r--r--fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6bin0 -> 3289 bytes
-rw-r--r--fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571bin0 -> 1074 bytes
-rw-r--r--fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727bin0 -> 734 bytes
-rw-r--r--fuzz/client_corpus/819b64ad6fe9da24271678ecf337427fe17e95b2bin3586 -> 0 bytes
-rw-r--r--fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270bin0 -> 3573 bytes
-rw-r--r--fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62bin0 -> 3616 bytes
-rw-r--r--fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182dbin0 -> 944 bytes
-rw-r--r--fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8bin0 -> 1816 bytes
-rw-r--r--fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741cbin0 -> 2222 bytes
-rw-r--r--fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3bin0 -> 1875 bytes
-rw-r--r--fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1abin0 -> 3200 bytes
-rw-r--r--fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0bin0 -> 2604 bytes
-rw-r--r--fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86bbin0 -> 1216 bytes
-rw-r--r--fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1dbin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206bin0 -> 3189 bytes
-rw-r--r--fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/862c1aa11fe288ba4d472f1b5e2776a4c68517e6bin1081 -> 0 bytes
-rw-r--r--fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658bin0 -> 3284 bytes
-rw-r--r--fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3fbin0 -> 3702 bytes
-rw-r--r--fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3ebin0 -> 3614 bytes
-rw-r--r--fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3dbin0 -> 4033 bytes
-rw-r--r--fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624bin0 -> 3790 bytes
-rw-r--r--fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832bin0 -> 1193 bytes
-rw-r--r--fuzz/client_corpus/88b816c47071b8c82dc0a24b98529c4623317ef7bin3675 -> 0 bytes
-rw-r--r--fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5bin0 -> 915 bytes
-rw-r--r--fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1ebin0 -> 3491 bytes
-rw-r--r--fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8bin0 -> 3284 bytes
-rw-r--r--fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078bin0 -> 3501 bytes
-rw-r--r--fuzz/client_corpus/8a6f7e1fbb6295fb0a5dacf44d914658beb1e9d1bin3878 -> 0 bytes
-rw-r--r--fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4bin0 -> 857 bytes
-rw-r--r--fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22bin0 -> 1438 bytes
-rw-r--r--fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6bin0 -> 3259 bytes
-rw-r--r--fuzz/client_corpus/8bc268d09be3e8eb8b75e600a65857ad93c50b6fbin3948 -> 0 bytes
-rw-r--r--fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93bebbin0 -> 1870 bytes
-rw-r--r--fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3bin0 -> 3260 bytes
-rw-r--r--fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20bin0 -> 2806 bytes
-rw-r--r--fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4dbin0 -> 1041 bytes
-rw-r--r--fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3bin0 -> 1406 bytes
-rw-r--r--fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708fbin0 -> 2516 bytes
-rw-r--r--fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05bin0 -> 3296 bytes
-rw-r--r--fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400bin0 -> 3677 bytes
-rw-r--r--fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6bin0 -> 3674 bytes
-rw-r--r--fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8bbin0 -> 3616 bytes
-rw-r--r--fuzz/client_corpus/8f8643720d03bae58facfb7876166a5d5d7b5fbfbin179 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9018d7e0774e15a88c894b02d9d9ebd5a713deeabin3189 -> 0 bytes
-rw-r--r--fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760bin0 -> 3938 bytes
-rw-r--r--fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73bin0 -> 3447 bytes
-rw-r--r--fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3bin0 -> 3795 bytes
-rw-r--r--fuzz/client_corpus/91c7d49741905d07a691350e0b5ab9baacfc6273bin3165 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674bin0 -> 1088 bytes
-rw-r--r--fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92bin0 -> 161 bytes
-rw-r--r--fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783cbin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141bin0 -> 1968 bytes
-rw-r--r--fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488bin0 -> 3312 bytes
-rw-r--r--fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbccbin0 -> 809 bytes
-rw-r--r--fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2dbin0 -> 3501 bytes
-rw-r--r--fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3abin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253bin0 -> 3994 bytes
-rw-r--r--fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2cbin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90dbin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/9532c89ac942ba20c7fdd32231364b18ec54f430bin3418 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4bbin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510bbin0 -> 943 bytes
-rw-r--r--fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76bin0 -> 4041 bytes
-rw-r--r--fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71bin0 -> 2118 bytes
-rw-r--r--fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7bin0 -> 3784 bytes
-rw-r--r--fuzz/client_corpus/989c8c11e9167d64d6a4d5572da373d35ed1fdffbin3904 -> 0 bytes
-rw-r--r--fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731bin0 -> 3702 bytes
-rw-r--r--fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25dbin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0bin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cfbin0 -> 3431 bytes
-rw-r--r--fuzz/client_corpus/99dc5a5424282f707e4253be228175472a21586abin3995 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634bin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/9a51f0205f7ce5211db0255cc82b16b5d70bcff8bin3752 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9c7600ab81633b7f346a4fa2a6f51ea19eedaf30bin101 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9cc204eb7db5b083a0fa390a97ae3399cca42dbbbin3698 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3bin0 -> 3225 bytes
-rw-r--r--fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98dbin0 -> 17249 bytes
-rw-r--r--fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2bin0 -> 3921 bytes
-rw-r--r--fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/9f1e488eb682d3e24920c040e815e9a7c22f1d5cbin3775 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98dbin0 -> 3882 bytes
-rw-r--r--fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834bin0 -> 3784 bytes
-rw-r--r--fuzz/client_corpus/9f98a4a0fda63a672bd66ce7e2f16c50c9af1ac4bin3580 -> 0 bytes
-rw-r--r--fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdcbin0 -> 774 bytes
-rw-r--r--fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0bin0 -> 4095 bytes
-rw-r--r--fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1bin0 -> 3208 bytes
-rw-r--r--fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9bin0 -> 3403 bytes
-rw-r--r--fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179bin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862dafbin0 -> 3688 bytes
-rw-r--r--fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486bin0 -> 738 bytes
-rw-r--r--fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261adbin0 -> 3395 bytes
-rw-r--r--fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552bin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bbbin0 -> 1475 bytes
-rw-r--r--fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605bbin0 -> 899 bytes
-rw-r--r--fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928bin0 -> 2537 bytes
-rw-r--r--fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20bin0 -> 945 bytes
-rw-r--r--fuzz/client_corpus/a554b83ba6c67a8a9df612b8885ec028fb525c11bin3189 -> 0 bytes
-rw-r--r--fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3bbin0 -> 3430 bytes
-rw-r--r--fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401dbin0 -> 1011 bytes
-rw-r--r--fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821abin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290bin0 -> 1580 bytes
-rw-r--r--fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdefbin0 -> 3908 bytes
-rw-r--r--fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826bin0 -> 1009 bytes
-rw-r--r--fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305bin0 -> 3425 bytes
-rw-r--r--fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94bin0 -> 1353 bytes
-rw-r--r--fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42ebin0 -> 3165 bytes
-rw-r--r--fuzz/client_corpus/a7bff22ed83e686e0c57edac5be3cb1a5ed4116fbin3200 -> 0 bytes
-rw-r--r--fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641bin0 -> 945 bytes
-rw-r--r--fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98bin0 -> 3809 bytes
-rw-r--r--fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973bin0 -> 1810 bytes
-rw-r--r--fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53bin0 -> 1518 bytes
-rw-r--r--fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7bin0 -> 1300 bytes
-rw-r--r--fuzz/client_corpus/a9658c0476840377572405c1932c87ed66cda245bin3428 -> 0 bytes
-rw-r--r--fuzz/client_corpus/a992d16f1ba3c69f27780a4052836292fdbc0510bin3532 -> 0 bytes
-rw-r--r--fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6bin0 -> 1444 bytes
-rw-r--r--fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585bin0 -> 1011 bytes
-rw-r--r--fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6bin0 -> 856 bytes
-rw-r--r--fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71bin0 -> 3487 bytes
-rw-r--r--fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508bin0 -> 3180 bytes
-rw-r--r--fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872bin0 -> 1445 bytes
-rw-r--r--fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807fbin0 -> 2203 bytes
-rw-r--r--fuzz/client_corpus/ad1c259b96a734170ba88187ac864f61c763ced9bin327 -> 0 bytes
-rw-r--r--fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683abin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/add4ed5e0dafec5bfbe7060139c9ae444a5fd422bin3883 -> 0 bytes
-rw-r--r--fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445bin0 -> 3675 bytes
-rw-r--r--fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055bin0 -> 4094 bytes
-rw-r--r--fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970bin0 -> 869 bytes
-rw-r--r--fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6bin0 -> 3501 bytes
-rw-r--r--fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9bin0 -> 3572 bytes
-rw-r--r--fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84bin0 -> 1070 bytes
-rw-r--r--fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6bin0 -> 3572 bytes
-rw-r--r--fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817bin0 -> 3720 bytes
-rw-r--r--fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52bin0 -> 991 bytes
-rw-r--r--fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8abin0 -> 3631 bytes
-rw-r--r--fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564bin0 -> 644 bytes
-rw-r--r--fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811bin0 -> 3481 bytes
-rw-r--r--fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18bin0 -> 2570 bytes
-rw-r--r--fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6bin0 -> 1192 bytes
-rw-r--r--fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8bin0 -> 1810 bytes
-rw-r--r--fuzz/client_corpus/b4742350fd9936eeec364b2cf2d7a9a9432b4bb4bin3555 -> 0 bytes
-rw-r--r--fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648bin0 -> 108 bytes
-rw-r--r--fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74fbin0 -> 1935 bytes
-rw-r--r--fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713bebin0 -> 3747 bytes
-rw-r--r--fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27dbin0 -> 3520 bytes
-rw-r--r--fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226bin0 -> 3911 bytes
-rw-r--r--fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621bin0 -> 4030 bytes
-rw-r--r--fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941abin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1bin0 -> 7 bytes
-rw-r--r--fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfdebin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9bin0 -> 3053 bytes
-rw-r--r--fuzz/client_corpus/b6f0bc18a3ba91cfd6d1bfab7d93b114a58a29afbin3564 -> 0 bytes
-rw-r--r--fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43bbin0 -> 2541 bytes
-rw-r--r--fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fcbin0 -> 1157 bytes
-rw-r--r--fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683aebin0 -> 3674 bytes
-rw-r--r--fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07abin0 -> 1409 bytes
-rw-r--r--fuzz/client_corpus/b7653eb906619065dee11e795efe3ce8ad464072bin3244 -> 0 bytes
-rw-r--r--fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9bbin0 -> 2481 bytes
-rw-r--r--fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2bin0 -> 1409 bytes
-rw-r--r--fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251bbin0 -> 3401 bytes
-rw-r--r--fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5bin0 -> 900 bytes
-rw-r--r--fuzz/client_corpus/ba2b35cd92fd6d0ee105dfe86441c4999409b417bin83 -> 0 bytes
-rw-r--r--fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828bin0 -> 2364 bytes
-rw-r--r--fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7bin0 -> 3332 bytes
-rw-r--r--fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5cbin0 -> 3189 bytes
-rw-r--r--fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55bin0 -> 161 bytes
-rw-r--r--fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730bin0 -> 985 bytes
-rw-r--r--fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0bin0 -> 3407 bytes
-rw-r--r--fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7cbin0 -> 2656 bytes
-rw-r--r--fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0edbin0 -> 1300 bytes
-rw-r--r--fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0bin0 -> 1830 bytes
-rw-r--r--fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98eabin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/bf9de6b11863f9b35c33ccac6029000515a06e40bin3268 -> 0 bytes
-rw-r--r--fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583bin0 -> 1495 bytes
-rw-r--r--fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8cbin0 -> 3642 bytes
-rw-r--r--fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4dbin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8bin0 -> 3809 bytes
-rw-r--r--fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427ebin0 -> 736 bytes
-rw-r--r--fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86bin0 -> 946 bytes
-rw-r--r--fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8dbin0 -> 1382 bytes
-rw-r--r--fuzz/client_corpus/c2acfea4afeebc8548ca57e7b406b733fdc7efd0bin3236 -> 0 bytes
-rw-r--r--fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523bin0 -> 108 bytes
-rw-r--r--fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/c43bc9792aae5572f7718bd39efb25418b6a29e3bin291 -> 0 bytes
-rw-r--r--fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9bin0 -> 2123 bytes
-rw-r--r--fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224bin0 -> 1229 bytes
-rw-r--r--fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862bin0 -> 1228 bytes
-rw-r--r--fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/c64059ad0a8b3d4b6e953c4d5e35e7c088f6b072bin3701 -> 0 bytes
-rw-r--r--fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8bin0 -> 3447 bytes
-rw-r--r--fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7bin0 -> 2389 bytes
-rw-r--r--fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cbbin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7bin0 -> 1228 bytes
-rw-r--r--fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490bbin0 -> 903 bytes
-rw-r--r--fuzz/client_corpus/c84a90953124137637e9ab5b77a44e174556b9eabin3977 -> 0 bytes
-rw-r--r--fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89bin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/c9d3a1db96c2c8567c4a0ad352b67bc79b864d1ebin3630 -> 0 bytes
-rw-r--r--fuzz/client_corpus/c9de70d1d9ec6220bd9139da63e87fa0ba2bf02bbin3282 -> 0 bytes
-rw-r--r--fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7bin0 -> 670 bytes
-rw-r--r--fuzz/client_corpus/ca70b7405469638eba2d87352235cb91c327b3b7bin3501 -> 0 bytes
-rw-r--r--fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152bin0 -> 3616 bytes
-rw-r--r--fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5cbin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/caff3955e5a402b64c513cf89f6c6178d32f91cabin3614 -> 0 bytes
-rw-r--r--fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48bin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/cd61d1f2d30352c129043a805a48fc77e91bdd6fbin3493 -> 0 bytes
-rw-r--r--fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81bin0 -> 3839 bytes
-rw-r--r--fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41bin0 -> 3920 bytes
-rw-r--r--fuzz/client_corpus/ce87aa069c66ce66a19031e66737ad2c8ba230a3bin18 -> 0 bytes
-rw-r--r--fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565dbin0 -> 1131 bytes
-rw-r--r--fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41bin0 -> 3448 bytes
-rw-r--r--fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60bin0 -> 1846 bytes
-rw-r--r--fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824bbin0 -> 884 bytes
-rw-r--r--fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84bin0 -> 3703 bytes
-rw-r--r--fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290bin0 -> 915 bytes
-rw-r--r--fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00fbin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344bin0 -> 3673 bytes
-rw-r--r--fuzz/client_corpus/d153ecdd0aecb6560ceb29ac482ac648f3c91b3cbin3240 -> 0 bytes
-rw-r--r--fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04bin0 -> 2840 bytes
-rw-r--r--fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6bin0 -> 3407 bytes
-rw-r--r--fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6dbin0 -> 3931 bytes
-rw-r--r--fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024bin0 -> 1717 bytes
-rw-r--r--fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032bin0 -> 3927 bytes
-rw-r--r--fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603bin0 -> 865 bytes
-rw-r--r--fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69bin0 -> 1443 bytes
-rw-r--r--fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694bin0 -> 3425 bytes
-rw-r--r--fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317abin0 -> 3414 bytes
-rw-r--r--fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7bin0 -> 1845 bytes
-rw-r--r--fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52bin0 -> 3677 bytes
-rw-r--r--fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57cbin0 -> 1301 bytes
-rw-r--r--fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7bin0 -> 1996 bytes
-rw-r--r--fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0bin0 -> 1243 bytes
-rw-r--r--fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02bin0 -> 3440 bytes
-rw-r--r--fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4bin0 -> 1219 bytes
-rw-r--r--fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/d6d2b5c6f73c3d83547b1cf3a4ef71aaaa19eb56bin3571 -> 0 bytes
-rw-r--r--fuzz/client_corpus/d6d7771c49302badd8825680a2a1f95bc265707ebin7 -> 0 bytes
-rw-r--r--fuzz/client_corpus/d7975db1a9687110ecbe1a90c604313557dcc3b3bin3540 -> 0 bytes
-rw-r--r--fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10bin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/d7a895d52691c31e12ea463089d855cc6466fd61bin3648 -> 0 bytes
-rw-r--r--fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3bbin0 -> 3563 bytes
-rw-r--r--fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58bbin0 -> 671 bytes
-rw-r--r--fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5bin0 -> 1001 bytes
-rw-r--r--fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4ebin0 -> 672 bytes
-rw-r--r--fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559dbin0 -> 672 bytes
-rw-r--r--fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93dbin0 -> 1195 bytes
-rw-r--r--fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bdbin0 -> 884 bytes
-rw-r--r--fuzz/client_corpus/dc7efdf6cb7e95e7c257c3f850e58e504949e9a8bin3834 -> 0 bytes
-rw-r--r--fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0bin0 -> 3774 bytes
-rw-r--r--fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575fbin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2dbin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30bin0 -> 3580 bytes
-rw-r--r--fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9bin0 -> 491 bytes
-rw-r--r--fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177ababin0 -> 3920 bytes
-rw-r--r--fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856abin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01bin0 -> 3478 bytes
-rw-r--r--fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/df19fb0f0752cebfa3e221eca2396ce74e568c71bin3907 -> 0 bytes
-rw-r--r--fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294bin0 -> 738 bytes
-rw-r--r--fuzz/client_corpus/df3af56fc7423b564ed2c18258e934796f574b2ebin3382 -> 0 bytes
-rw-r--r--fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0bin0 -> 4096 bytes
-rw-r--r--fuzz/client_corpus/df811b530178666cc79c5ca440c9f2aca9fae5bebin3544 -> 0 bytes
-rw-r--r--fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0bin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099bin0 -> 1109 bytes
-rw-r--r--fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679bin0 -> 3427 bytes
-rw-r--r--fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998bin0 -> 3823 bytes
-rw-r--r--fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074bin0 -> 903 bytes
-rw-r--r--fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7dbin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6bin0 -> 3402 bytes
-rw-r--r--fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8bin0 -> 4094 bytes
-rw-r--r--fuzz/client_corpus/e108931e2f35aa964740a5d2d769b9ed09e1d3babin3839 -> 0 bytes
-rw-r--r--fuzz/client_corpus/e250493d1912990f1c388651fa7436bd61b43cf0bin3677 -> 0 bytes
-rw-r--r--fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305bin0 -> 1644 bytes
-rw-r--r--fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897bin0 -> 1444 bytes
-rw-r--r--fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ecbin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/e422ebbe19856f99bf12daa91dfa9374110cc1aebin3832 -> 0 bytes
-rw-r--r--fuzz/client_corpus/e44a2a205da5934fe88f471db4bff606b7b32910bin3312 -> 0 bytes
-rw-r--r--fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4ebin0 -> 3808 bytes
-rw-r--r--fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0bin0 -> 1227 bytes
-rw-r--r--fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8bin0 -> 2270 bytes
-rw-r--r--fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eebbin0 -> 1074 bytes
-rw-r--r--fuzz/client_corpus/e53fb23dfe5472f0f6e04906425108118361c485bin3674 -> 0 bytes
-rw-r--r--fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111bin0 -> 1230 bytes
-rw-r--r--fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07dbin0 -> 1216 bytes
-rw-r--r--fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444bin0 -> 909 bytes
-rw-r--r--fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6abin0 -> 642 bytes
-rw-r--r--fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875bin0 -> 3701 bytes
-rw-r--r--fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0feabin0 -> 787 bytes
-rw-r--r--fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966acbin0 -> 2240 bytes
-rw-r--r--fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478bin0 -> 672 bytes
-rw-r--r--fuzz/client_corpus/e856a78f2e32bd8f0d60a4fe693b36c83c0a8356bin1404 -> 0 bytes
-rw-r--r--fuzz/client_corpus/e88ec440a42915f80706afbc0cc7bf1111db4936bin95 -> 0 bytes
-rw-r--r--fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26bbin0 -> 1220 bytes
-rw-r--r--fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90adbin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670bin0 -> 3492 bytes
-rw-r--r--fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884bin0 -> 889 bytes
-rw-r--r--fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1bin0 -> 1147 bytes
-rw-r--r--fuzz/client_corpus/ecccd730722b03678c74bdf87163035af5d70ecbbin3820 -> 0 bytes
-rw-r--r--fuzz/client_corpus/ecd22a9f8c1f5017f89d6c2288979c96433b3d0cbin3615 -> 0 bytes
-rw-r--r--fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6bin0 -> 675 bytes
-rw-r--r--fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190bin0 -> 3403 bytes
-rw-r--r--fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59bin0 -> 3962 bytes
-rw-r--r--fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265cabin0 -> 3751 bytes
-rw-r--r--fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2fbin0 -> 900 bytes
-rw-r--r--fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786bin0 -> 897 bytes
-rw-r--r--fuzz/client_corpus/ef7bb7e9656aa4b23d6f4a78ea0b6a12acfc5edbbin3643 -> 0 bytes
-rw-r--r--fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/f05f5c9edbc997d109efedb280f5df56d91e3f30bin3662 -> 0 bytes
-rw-r--r--fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5bin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/f221430334f4351262a86cfa0bb3dced4fb50b2fbin186 -> 0 bytes
-rw-r--r--fuzz/client_corpus/f2443da1130f34d948c2897195681f324e1eb14dbin2570 -> 0 bytes
-rw-r--r--fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1bin0 -> 1104 bytes
-rw-r--r--fuzz/client_corpus/f2982b479f4d0426f25b71b7e4ef7199542fba6cbin3837 -> 0 bytes
-rw-r--r--fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3bin0 -> 3809 bytes
-rw-r--r--fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0bin0 -> 3465 bytes
-rw-r--r--fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16bin0 -> 895 bytes
-rw-r--r--fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2bin0 -> 3826 bytes
-rw-r--r--fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0bin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9bin0 -> 737 bytes
-rw-r--r--fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8ebin0 -> 675 bytes
-rw-r--r--fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097abin0 -> 908 bytes
-rw-r--r--fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8bin0 -> 704 bytes
-rw-r--r--fuzz/client_corpus/f5df7fc246fc8d4b89c1cd46c9ef1140ec57ffaebin3418 -> 0 bytes
-rw-r--r--fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944abin0 -> 3964 bytes
-rw-r--r--fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbaebin0 -> 3601 bytes
-rw-r--r--fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4bbin0 -> 3403 bytes
-rw-r--r--fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84febin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3bin0 -> 3501 bytes
-rw-r--r--fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9bin0 -> 689 bytes
-rw-r--r--fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060abin0 -> 3571 bytes
-rw-r--r--fuzz/client_corpus/f8eb6c08a85e0474abf60cd5e222093cfbdd95f8bin3402 -> 0 bytes
-rw-r--r--fuzz/client_corpus/f978108e734598b126868ee1dfba52a2f03f2af7bin3501 -> 0 bytes
-rw-r--r--fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090bin0 -> 5 bytes
-rw-r--r--fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21bin0 -> 1715 bytes
-rw-r--r--fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502abin0 -> 2186 bytes
-rw-r--r--fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31bin0 -> 3615 bytes
-rw-r--r--fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08bin0 -> 3502 bytes
-rw-r--r--fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80bbin0 -> 690 bytes
-rw-r--r--fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afbbin0 -> 1228 bytes
-rw-r--r--fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5abin0 -> 673 bytes
-rw-r--r--fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579bin0 -> 750 bytes
-rw-r--r--fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60bin0 -> 17461 bytes
-rw-r--r--fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749bin0 -> 674 bytes
-rw-r--r--fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561bin0 -> 1732 bytes
-rw-r--r--fuzz/minimise_corpuses.sh31
-rw-r--r--fuzz/pkcs8.cc38
-rw-r--r--fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63bin0 -> 633 bytes
-rw-r--r--fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350bbin0 -> 122 bytes
-rw-r--r--fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3fbin0 -> 137 bytes
-rw-r--r--fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53bin0 -> 691 bytes
-rw-r--r--fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7bin0 -> 528 bytes
-rw-r--r--fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348bin0 -> 185 bytes
-rw-r--r--fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046bin0 -> 241 bytes
-rw-r--r--fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125abbin0 -> 149 bytes
-rw-r--r--fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75bin0 -> 1304 bytes
-rw-r--r--fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08bin0 -> 335 bytes
-rw-r--r--fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36bbin0 -> 344 bytes
-rw-r--r--fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41febin0 -> 146 bytes
-rw-r--r--fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7bin0 -> 78 bytes
-rw-r--r--fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648bin0 -> 66 bytes
-rw-r--r--fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18ebin0 -> 381 bytes
-rw-r--r--fuzz/privkey.cc14
-rw-r--r--fuzz/privkey_corpus/0011b315985d69eb7e3e2eb946d7b17b2ba124d8bin240 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3bin0 -> 2013 bytes
-rw-r--r--fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104bin0 -> 615 bytes
-rw-r--r--fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9bin0 -> 275 bytes
-rw-r--r--fuzz/privkey_corpus/04d89eb4c7cb4e6dc1e26b1104ee2f78c77e573fbin62 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67bin0 -> 559 bytes
-rw-r--r--fuzz/privkey_corpus/0553b1378ca822d924b1ea95c6654e3508faa8bfbin100 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/0555561f448567b597875a17041f0cfc6dd30527bin29 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4bin0 -> 561 bytes
-rw-r--r--fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35bin0 -> 250 bytes
-rw-r--r--fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2bin0 -> 249 bytes
-rw-r--r--fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60bbin0 -> 275 bytes
-rw-r--r--fuzz/privkey_corpus/078f4cb1e10cc91428b751c97f543eaba2303b6f1
-rw-r--r--fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92fbin0 -> 118 bytes
-rw-r--r--fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4fbin0 -> 597 bytes
-rw-r--r--fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346bin0 -> 381 bytes
-rw-r--r--fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5bin0 -> 872 bytes
-rw-r--r--fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95ebin0 -> 1574 bytes
-rw-r--r--fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2fbin0 -> 232 bytes
-rw-r--r--fuzz/privkey_corpus/0e490fa7001442785c829645692993a1f55c9653bin32 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0bin0 -> 275 bytes
-rw-r--r--fuzz/privkey_corpus/103201e00ff234028e8795585d722409ba8b85c3bin56 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/1074eb39d16c92b2d4ae77245a32f63353739780bin245 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673bin0 -> 210 bytes
-rw-r--r--fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4bin0 -> 503 bytes
-rw-r--r--fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7bin0 -> 1193 bytes
-rw-r--r--fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794bin0 -> 365 bytes
-rw-r--r--fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1bin0 -> 365 bytes
-rw-r--r--fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574bin0 -> 381 bytes
-rw-r--r--fuzz/privkey_corpus/1898789ee447b3c8fe5731fdf02c603aba33ca4ebin41 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301bbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489dbin0 -> 277 bytes
-rw-r--r--fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fdbin0 -> 279 bytes
-rw-r--r--fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1bbin0 -> 232 bytes
-rw-r--r--fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01bin0 -> 215 bytes
-rw-r--r--fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73efbin0 -> 745 bytes
-rw-r--r--fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904bin0 -> 503 bytes
-rw-r--r--fuzz/privkey_corpus/272ef5b501f038eccbae4084d7cd476f69c9baa8bin35 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/27ca11aae0b2385e458770be3a4cc8ca2c7d7eb5bin205 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/288788112f0df06a025c8020b3783aa5de18727bbin56 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423bbin0 -> 593 bytes
-rw-r--r--fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8bin0 -> 381 bytes
-rw-r--r--fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4bin0 -> 275 bytes
-rw-r--r--fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9bin0 -> 247 bytes
-rw-r--r--fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183ebin0 -> 413 bytes
-rw-r--r--fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0bin0 -> 385 bytes
-rw-r--r--fuzz/privkey_corpus/2bd1d090ed0b879a80e200d18199361abdb583c6bin106 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/2cc2eb036512e3407569cb670d99d53b77708ffd1
-rw-r--r--fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696bin0 -> 440 bytes
-rw-r--r--fuzz/privkey_corpus/2ddcac6ee1d95669aba11a7960f9b3d2f23801e2bin50 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9bin0 -> 381 bytes
-rw-r--r--fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/2f224b103dee345266651abd8ca972e8e0d5515abin45 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9bin0 -> 365 bytes
-rw-r--r--fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164bin0 -> 448 bytes
-rw-r--r--fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4bin0 -> 108 bytes
-rw-r--r--fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068bin0 -> 857 bytes
-rw-r--r--fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29bin0 -> 596 bytes
-rw-r--r--fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0bin0 -> 372 bytes
-rw-r--r--fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32afbin0 -> 52 bytes
-rw-r--r--fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39bin0 -> 60 bytes
-rw-r--r--fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75bin0 -> 1269 bytes
-rw-r--r--fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19efbin0 -> 121 bytes
-rw-r--r--fuzz/privkey_corpus/359d4453699f8fc738128afd76853e637d453f22bin493 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adfbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735bin0 -> 365 bytes
-rw-r--r--fuzz/privkey_corpus/378d3cdaaeab3bbeeca778259c1fcf1b916c09361
-rw-r--r--fuzz/privkey_corpus/38fd17896ebaa4c75cd71d1255f3194ddc1f8829bin49 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85bin0 -> 614 bytes
-rw-r--r--fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4bin0 -> 652 bytes
-rw-r--r--fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7bin0 -> 150 bytes
-rw-r--r--fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512bin0 -> 413 bytes
-rw-r--r--fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754bin0 -> 1422 bytes
-rw-r--r--fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193bin0 -> 385 bytes
-rw-r--r--fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31bin0 -> 605 bytes
-rw-r--r--fuzz/privkey_corpus/3fdb71ab5aec32080dbc60867a754e57cabc90debin51 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574bbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217bin0 -> 149 bytes
-rw-r--r--fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5bin0 -> 245 bytes
-rw-r--r--fuzz/privkey_corpus/429f95d3029b0242e7ae1c668f64317196d5a442bin121 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/476758eb3f59a8dfa8effeeca7f610d795a697011
-rw-r--r--fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0bin0 -> 366 bytes
-rw-r--r--fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412bin0 -> 211 bytes
-rw-r--r--fuzz/privkey_corpus/4b68c5924a60f7c907987c79af7d972644c5c990bin60 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/4c19e7a0b01f37323b6f19b2e5ef3217de6b350abin58 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/4f653e0b8a3b198d0b2deadec8a6e23635f27032bin171 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1dbbin0 -> 135 bytes
-rw-r--r--fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04bin0 -> 268 bytes
-rw-r--r--fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28bin0 -> 231 bytes
-rw-r--r--fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4ebin0 -> 1592 bytes
-rw-r--r--fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8bin0 -> 567 bytes
-rw-r--r--fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13ebin0 -> 364 bytes
-rw-r--r--fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040bin0 -> 232 bytes
-rw-r--r--fuzz/privkey_corpus/573829cd6df068f7ac72bfe6f17d79f8b5006aa8bin59 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0bin0 -> 502 bytes
-rw-r--r--fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6cbin0 -> 364 bytes
-rw-r--r--fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9bin0 -> 425 bytes
-rw-r--r--fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287bin0 -> 220 bytes
-rw-r--r--fuzz/privkey_corpus/59b889ce764f1da0bbfb4e90c1856b48fc9f1565bin36 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36bin0 -> 279 bytes
-rw-r--r--fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9bin0 -> 248 bytes
-rw-r--r--fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217bin0 -> 132 bytes
-rw-r--r--fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692dbin0 -> 1193 bytes
-rw-r--r--fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0ebin0 -> 250 bytes
-rw-r--r--fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42ebin0 -> 708 bytes
-rw-r--r--fuzz/privkey_corpus/5c99d308d575a71a5b4ccbd13280bb13ac79894fbin54 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841bin0 -> 1192 bytes
-rw-r--r--fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaabin0 -> 210 bytes
-rw-r--r--fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050bbin0 -> 246 bytes
-rw-r--r--fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60becbin0 -> 604 bytes
-rw-r--r--fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c1
-rw-r--r--fuzz/privkey_corpus/616d00f4518e24cbf78f5c7898fae159b97de6b51
-rw-r--r--fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8bin0 -> 701 bytes
-rw-r--r--fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cbbin0 -> 307 bytes
-rw-r--r--fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9bin0 -> 364 bytes
-rw-r--r--fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9bbin0 -> 135 bytes
-rw-r--r--fuzz/privkey_corpus/63d9ecea3f2f5141b1bc4c4ada40381999d2ae78bin24 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/64213f486e58ce1cc0bea2a6f145e6769dbcb93ebin57 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658bin0 -> 223 bytes
-rw-r--r--fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3bin0 -> 364 bytes
-rw-r--r--fuzz/privkey_corpus/6531424fdad457866089d58c9279bd5fe8719ca0bin36 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67bin0 -> 230 bytes
-rw-r--r--fuzz/privkey_corpus/66725ca0c9d2a7fbb3f6660180b7f9d172dd8c641
-rw-r--r--fuzz/privkey_corpus/6778469c6519b69b3741a62e8df40a1091aeffd3bin59 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965bin0 -> 274 bytes
-rw-r--r--fuzz/privkey_corpus/695f506c23c31450f3698f15f5d5dcd0a00e2292bin55 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308bin0 -> 275 bytes
-rw-r--r--fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884bbin0 -> 366 bytes
-rw-r--r--fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1bin0 -> 685 bytes
-rw-r--r--fuzz/privkey_corpus/6e846663b4af1ecf73ba93611d1f9b39f63803e5bin83 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/6f12c3d548d85deae6946b279d85e03491787077bin20 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/6f2f15721e6c0b664759fa65e307c9a8cd20c4641
-rw-r--r--fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606dbin0 -> 125 bytes
-rw-r--r--fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0bbin0 -> 233 bytes
-rw-r--r--fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9bbin0 -> 232 bytes
-rw-r--r--fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ecbin0 -> 178 bytes
-rw-r--r--fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0bbin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/71b67011b691dbde02d398dc730efc2d5205c8371
-rw-r--r--fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3bin0 -> 1422 bytes
-rw-r--r--fuzz/privkey_corpus/74306f8ce43c5b77c55b94ec37204d8be7c7a220bin54 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10bin0 -> 339 bytes
-rw-r--r--fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7bin0 -> 231 bytes
-rw-r--r--fuzz/privkey_corpus/761cde476b5b3f9af80a15150a8cbeb0992a3446bin40 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72eabin0 -> 276 bytes
-rw-r--r--fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ecbin0 -> 364 bytes
-rw-r--r--fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2fbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86bin0 -> 857 bytes
-rw-r--r--fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26bbin0 -> 408 bytes
-rw-r--r--fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70bin0 -> 648 bytes
-rw-r--r--fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462ebin0 -> 277 bytes
-rw-r--r--fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bddbin0 -> 57 bytes
-rw-r--r--fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158bin0 -> 103 bytes
-rw-r--r--fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018bin0 -> 576 bytes
-rw-r--r--fuzz/privkey_corpus/7dad0c94279194dcb34901efc1bfe47e19ace379bin55 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/7de3b5459637fb5839105f571da68411f7b9a4e2bin188 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90bin0 -> 246 bytes
-rw-r--r--fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856bin0 -> 135 bytes
-rw-r--r--fuzz/privkey_corpus/7fbcab532053a01781fdcdf1c8c9c5707479fbda1
-rw-r--r--fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270bin0 -> 231 bytes
-rw-r--r--fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892bin0 -> 516 bytes
-rw-r--r--fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491bbin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fcbin0 -> 125 bytes
-rw-r--r--fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bbbin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eefbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688bin0 -> 307 bytes
-rw-r--r--fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009bin0 -> 135 bytes
-rw-r--r--fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99dbin0 -> 121 bytes
-rw-r--r--fuzz/privkey_corpus/83ce66bb0c9c3bec32b125c66b724522a293989bbin221 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876cbin0 -> 223 bytes
-rw-r--r--fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5bin0 -> 685 bytes
-rw-r--r--fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9bin0 -> 90 bytes
-rw-r--r--fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2cbin0 -> 382 bytes
-rw-r--r--fuzz/privkey_corpus/872f45b8c5fcebb9e7d8e26f3b41e4d42af2a824bin59 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0bin0 -> 640 bytes
-rw-r--r--fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365bin0 -> 150 bytes
-rw-r--r--fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088bin0 -> 384 bytes
-rw-r--r--fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3bin0 -> 171 bytes
-rw-r--r--fuzz/privkey_corpus/897d7068f38f4c9f9d127901f7da58ebbbbe989abin90 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/89af3687b8bb5fa6ed225799fd97cbc79f6678efbin29 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347dbin0 -> 426 bytes
-rw-r--r--fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14cbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/8e7daf81d667f41e4310a12a560b69400b97d85dbin152 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206bin0 -> 375 bytes
-rw-r--r--fuzz/privkey_corpus/8fe2bfb00afe3d66f36bdb951df47f28e4bc60f11
-rw-r--r--fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1ebin0 -> 201 bytes
-rw-r--r--fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4bin0 -> 137 bytes
-rw-r--r--fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/9270672e3b3b0c6dd04c2001646900d392a8f0cdbin106 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afabin0 -> 221 bytes
-rw-r--r--fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3bin0 -> 63 bytes
-rw-r--r--fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594bin0 -> 198 bytes
-rw-r--r--fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23bin0 -> 495 bytes
-rw-r--r--fuzz/privkey_corpus/957768c9faad66620a63f5f529546ae973203c0cbin209 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88bin0 -> 186 bytes
-rw-r--r--fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9bin0 -> 365 bytes
-rw-r--r--fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931fbin0 -> 149 bytes
-rw-r--r--fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49bin0 -> 125 bytes
-rw-r--r--fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02bin0 -> 370 bytes
-rw-r--r--fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6cabin0 -> 63 bytes
-rw-r--r--fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631bin0 -> 494 bytes
-rw-r--r--fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cfbin0 -> 274 bytes
-rw-r--r--fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dacbin0 -> 171 bytes
-rw-r--r--fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0cbin0 -> 283 bytes
-rw-r--r--fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546bin0 -> 125 bytes
-rw-r--r--fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4bin0 -> 1572 bytes
-rw-r--r--fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12cbin0 -> 132 bytes
-rw-r--r--fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425bin0 -> 138 bytes
-rw-r--r--fuzz/privkey_corpus/9ed81784ce2583f8be38e859dce5e95b495a6f5ebin227 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766edbin0 -> 170 bytes
-rw-r--r--fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7bin0 -> 231 bytes
-rw-r--r--fuzz/privkey_corpus/a3f0a9ff5a9ec60daa274d60cfeecdd579401ecebin80 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/a463eb1757724d37c64e0f34e7b8c2f214bf9db21
-rw-r--r--fuzz/privkey_corpus/a4c7ddac15ef72f597bcf6c3e6f287ede7de6119bin56 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0dfbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/a547b12cbdf4c9ad8002e735e5276674a0dc48d1bin34 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfbbin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966beebin0 -> 176 bytes
-rw-r--r--fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555bin0 -> 369 bytes
-rw-r--r--fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2dbin0 -> 381 bytes
-rw-r--r--fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5bin0 -> 711 bytes
-rw-r--r--fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078bin0 -> 1240 bytes
-rw-r--r--fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43abin0 -> 365 bytes
-rw-r--r--fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042bin0 -> 365 bytes
-rw-r--r--fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6bin0 -> 577 bytes
-rw-r--r--fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fadbin0 -> 410 bytes
-rw-r--r--fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4dbin0 -> 1193 bytes
-rw-r--r--fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82bin0 -> 277 bytes
-rw-r--r--fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544bin0 -> 89 bytes
-rw-r--r--fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908bin0 -> 604 bytes
-rw-r--r--fuzz/privkey_corpus/ac4c5ab934f6f54f4337c1fd1194a979bffec24dbin53 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ac74cf6269b94ccb419933a32bd7d8c9452dce2ebin34 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ad691a66d0a57b9737701d8b431e48a9a9b98a5abin24 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534ebin0 -> 201 bytes
-rw-r--r--fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bfbin0 -> 210 bytes
-rw-r--r--fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451bin0 -> 689 bytes
-rw-r--r--fuzz/privkey_corpus/b0af7aec354da869abfb72e1ac8586c079101d78bin231 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57dbin0 -> 153 bytes
-rw-r--r--fuzz/privkey_corpus/b2c7dc902172c6beea66a96df921d559acce2e1d1
-rw-r--r--fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238bin0 -> 50 bytes
-rw-r--r--fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321bin0 -> 195 bytes
-rw-r--r--fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898cbin0 -> 596 bytes
-rw-r--r--fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636bin0 -> 154 bytes
-rw-r--r--fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185bin0 -> 216 bytes
-rw-r--r--fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6bin0 -> 269 bytes
-rw-r--r--fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4bin0 -> 495 bytes
-rw-r--r--fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4bin0 -> 45 bytes
-rw-r--r--fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3bin0 -> 768 bytes
-rw-r--r--fuzz/privkey_corpus/b92cebe5be4c47d05ae4ea152c198b4d5978f22fbin110 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfcabin0 -> 493 bytes
-rw-r--r--fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711ebin0 -> 447 bytes
-rw-r--r--fuzz/privkey_corpus/bb27d0460c1351c8fc37f87f26db293fbe57f0a8bin80 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/bc30b3e987eff679901a24d19a205048f2ca54babin40 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/bdc3b30e8d1a278f81ebe78c4b5e44aaef55c4e1bin146 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273bin0 -> 369 bytes
-rw-r--r--fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064fbin0 -> 1324 bytes
-rw-r--r--fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591eebin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188fbin0 -> 271 bytes
-rw-r--r--fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b1
-rw-r--r--fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caecebin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050bin0 -> 271 bytes
-rw-r--r--fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3bin0 -> 51 bytes
-rw-r--r--fuzz/privkey_corpus/c638138e56beeacb40af3cd20050b8a3f5036992bin19 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71bin0 -> 150 bytes
-rw-r--r--fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75bin0 -> 276 bytes
-rw-r--r--fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7bbin0 -> 152 bytes
-rw-r--r--fuzz/privkey_corpus/ca03fe7c55904c73f9ff1eadf2e192e0eb411e0cbin15 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ca6887f6d21cf4ecdebe7ac1900c1c49ee16c6b21
-rw-r--r--fuzz/privkey_corpus/cab3b9db9caea2b6998acc6755d0bcaa20a2ba48bin56 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2bbin0 -> 171 bytes
-rw-r--r--fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19bin0 -> 382 bytes
-rw-r--r--fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acfbin0 -> 119 bytes
-rw-r--r--fuzz/privkey_corpus/cc719b2377a9c7bf6b598fd1a0385a128be673dcbin118 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/cd7337d143156288c8f0236cc15ce647b652e739bin24 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016bin0 -> 238 bytes
-rw-r--r--fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62bin0 -> 380 bytes
-rw-r--r--fuzz/privkey_corpus/ce70afddf822af8cf9e69bffb31e1fc24e636be1bin61 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643bin0 -> 476 bytes
-rw-r--r--fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5bin0 -> 350 bytes
-rw-r--r--fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1bin0 -> 1341 bytes
-rw-r--r--fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedbbin0 -> 150 bytes
-rw-r--r--fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2bbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/d3b57fed5ac21ef3efb48176f09412eb8c042c0cbin70 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32bin0 -> 353 bytes
-rw-r--r--fuzz/privkey_corpus/d512a5050e4f5f699c7388a740671286aa571c6e1
-rw-r--r--fuzz/privkey_corpus/d5908176a8cf6c8fa4d500ab81e0fc66a927b74abin50 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ecbin0 -> 232 bytes
-rw-r--r--fuzz/privkey_corpus/d77a9ea971ce9b7fb6c73339ab715c1e7475c7351
-rw-r--r--fuzz/privkey_corpus/d86de6972bc8bd6f0df835199ab0aae303f3f8d4bin132 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35bin0 -> 364 bytes
-rw-r--r--fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0bin0 -> 472 bytes
-rw-r--r--fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28bin0 -> 515 bytes
-rw-r--r--fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375bin0 -> 153 bytes
-rw-r--r--fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44bin0 -> 1368 bytes
-rw-r--r--fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112bin0 -> 118 bytes
-rw-r--r--fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7bin0 -> 461 bytes
-rw-r--r--fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2bin0 -> 600 bytes
-rw-r--r--fuzz/privkey_corpus/db6c91a81049a4c819e086b54513d20446691ab9bin35 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fdbin0 -> 150 bytes
-rw-r--r--fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151bin0 -> 233 bytes
-rw-r--r--fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041bin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7bin0 -> 150 bytes
-rw-r--r--fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091bin0 -> 433 bytes
-rw-r--r--fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798dbin0 -> 517 bytes
-rw-r--r--fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54bin0 -> 370 bytes
-rw-r--r--fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10bin0 -> 273 bytes
-rw-r--r--fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36dbin0 -> 150 bytes
-rw-r--r--fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5bin0 -> 277 bytes
-rw-r--r--fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660cbin0 -> 232 bytes
-rw-r--r--fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0adbin0 -> 381 bytes
-rw-r--r--fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464bin0 -> 384 bytes
-rw-r--r--fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dcbin0 -> 228 bytes
-rw-r--r--fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7bin0 -> 596 bytes
-rw-r--r--fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/ea36122710fd32c98c091a6d3851b347d9dce5a5bin46 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477bin0 -> 334 bytes
-rw-r--r--fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94bin0 -> 2012 bytes
-rw-r--r--fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424bin0 -> 216 bytes
-rw-r--r--fuzz/privkey_corpus/ec97391303bce6e2ce9f61eaf52fd06fef0ab82bbin16 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7bin0 -> 197 bytes
-rw-r--r--fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400dbin0 -> 233 bytes
-rw-r--r--fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96bin0 -> 274 bytes
-rw-r--r--fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8bin0 -> 1446 bytes
-rw-r--r--fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9edbin0 -> 126 bytes
-rw-r--r--fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61dbin0 -> 402 bytes
-rw-r--r--fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076bbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162dbin0 -> 56 bytes
-rw-r--r--fuzz/privkey_corpus/f34aa93e1616ffaf490c9c24826fcc5c637655f41
-rw-r--r--fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985ebin0 -> 592 bytes
-rw-r--r--fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34bbin0 -> 134 bytes
-rw-r--r--fuzz/privkey_corpus/f56e3afd3eece26c160ae0b80b545edbbaa35a7bbin32 -> 0 bytes
-rw-r--r--fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bdbin0 -> 601 bytes
-rw-r--r--fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bdbin0 -> 380 bytes
-rw-r--r--fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7bin0 -> 278 bytes
-rw-r--r--fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634ebin0 -> 247 bytes
-rw-r--r--fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1ebin0 -> 379 bytes
-rw-r--r--fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848abin0 -> 325 bytes
-rw-r--r--fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7cebin0 -> 245 bytes
-rw-r--r--fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420dbin0 -> 45 bytes
-rw-r--r--fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5ebin0 -> 249 bytes
-rw-r--r--fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208bin0 -> 133 bytes
-rw-r--r--fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4bin0 -> 206 bytes
-rw-r--r--fuzz/privkey_corpus/fe7d7ae7b073e7076b8dd729ff7627431162b5c3bin50 -> 0 bytes
-rw-r--r--fuzz/read_pem.cc36
-rw-r--r--fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e21
-rw-r--r--fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d1
-rw-r--r--fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3bin0 -> 371 bytes
-rw-r--r--fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e33
-rw-r--r--fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0bin0 -> 394 bytes
-rw-r--r--fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f43
-rw-r--r--fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a7
-rw-r--r--fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237dbin0 -> 405 bytes
-rw-r--r--fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f8
-rw-r--r--fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e117
-rw-r--r--fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc3217
-rw-r--r--fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e845
-rw-r--r--fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed54
-rw-r--r--fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67bin0 -> 470 bytes
-rw-r--r--fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4bin0 -> 281 bytes
-rw-r--r--fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe5278915
-rw-r--r--fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8bin0 -> 512 bytes
-rw-r--r--fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933bin0 -> 358 bytes
-rw-r--r--fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b31
-rw-r--r--fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f3
-rw-r--r--fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeedbin0 -> 471 bytes
-rw-r--r--fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c11114
-rw-r--r--fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f5
-rw-r--r--fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f04
-rw-r--r--fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f131211
-rw-r--r--fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a11
-rw-r--r--fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef252
-rw-r--r--fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea11811
-rw-r--r--fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d79814
-rw-r--r--fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2bin0 -> 325 bytes
-rw-r--r--fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18bin0 -> 418 bytes
-rw-r--r--fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64bin0 -> 463 bytes
-rw-r--r--fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb15
-rw-r--r--fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d2
-rw-r--r--fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588bin0 -> 275 bytes
-rw-r--r--fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e34
-rw-r--r--fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d455967
-rw-r--r--fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18bin0 -> 315 bytes
-rw-r--r--fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2bin0 -> 388 bytes
-rw-r--r--fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208cbin0 -> 377 bytes
-rw-r--r--fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e815
-rw-r--r--fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55bin0 -> 439 bytes
-rw-r--r--fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96bin0 -> 481 bytes
-rw-r--r--fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e6
-rw-r--r--fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f47607
-rw-r--r--fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb6815
-rw-r--r--fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d9075
-rw-r--r--fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c16
-rw-r--r--fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2bin0 -> 362 bytes
-rw-r--r--fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b802
-rw-r--r--fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e66
-rw-r--r--fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa9153
-rw-r--r--fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567bin0 -> 511 bytes
-rw-r--r--fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda33
-rw-r--r--fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b211261
-rw-r--r--fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70bbin0 -> 403 bytes
-rw-r--r--fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e84812110
-rw-r--r--fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f33
-rw-r--r--fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bdbin0 -> 446 bytes
-rw-r--r--fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232febin0 -> 507 bytes
-rw-r--r--fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c3
-rw-r--r--fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5dbbin0 -> 358 bytes
-rw-r--r--fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b14
-rw-r--r--fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f3717
-rw-r--r--fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad8
-rw-r--r--fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d34913
-rw-r--r--fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f14
-rw-r--r--fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57ebin0 -> 314 bytes
-rw-r--r--fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e7855
-rw-r--r--fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1bin0 -> 369 bytes
-rw-r--r--fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33fbin0 -> 405 bytes
-rw-r--r--fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6bin0 -> 234 bytes
-rw-r--r--fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f35
-rw-r--r--fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae71112
-rw-r--r--fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5bin0 -> 315 bytes
-rw-r--r--fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158afbin0 -> 419 bytes
-rw-r--r--fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca5
-rw-r--r--fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46bin0 -> 386 bytes
-rw-r--r--fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3cbin0 -> 358 bytes
-rw-r--r--fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad14
-rw-r--r--fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b3
-rw-r--r--fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009cebin0 -> 385 bytes
-rw-r--r--fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b96
-rw-r--r--fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c39903858
-rw-r--r--fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa5132
-rw-r--r--fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5cbin0 -> 424 bytes
-rw-r--r--fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b918
-rw-r--r--fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf016
-rw-r--r--fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b712051
-rw-r--r--fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf3479291
-rw-r--r--fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1bin0 -> 358 bytes
-rw-r--r--fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26abin0 -> 314 bytes
-rw-r--r--fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e120
-rw-r--r--fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e07
-rw-r--r--fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c1
-rw-r--r--fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89bin0 -> 462 bytes
-rw-r--r--fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5bin0 -> 445 bytes
-rw-r--r--fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214dbin0 -> 358 bytes
-rw-r--r--fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a4217
-rw-r--r--fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e4
-rw-r--r--fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695bin0 -> 386 bytes
-rw-r--r--fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce7433
-rw-r--r--fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c8
-rw-r--r--fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678fbin0 -> 430 bytes
-rw-r--r--fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2cbin0 -> 410 bytes
-rw-r--r--fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb31
-rw-r--r--fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb1
-rw-r--r--fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f87
-rw-r--r--fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6acabin0 -> 429 bytes
-rw-r--r--fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd51
-rw-r--r--fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e6
-rw-r--r--fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d05845
-rw-r--r--fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fcbin0 -> 385 bytes
-rw-r--r--fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e2
-rw-r--r--fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5bin0 -> 481 bytes
-rw-r--r--fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f9
-rw-r--r--fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f15
-rw-r--r--fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf18
-rw-r--r--fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772dedbin0 -> 511 bytes
-rw-r--r--fuzz/server.cc28
-rw-r--r--fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49cbin0 -> 513 bytes
-rw-r--r--fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9abbin0 -> 233 bytes
-rw-r--r--fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2bbin0 -> 206 bytes
-rw-r--r--fuzz/server_corpus/0319960c7e36d77b16ed5e8ca21c9661020837a2bin177 -> 0 bytes
-rw-r--r--fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9bin0 -> 465 bytes
-rw-r--r--fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480bin0 -> 676 bytes
-rw-r--r--fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27bin0 -> 208 bytes
-rw-r--r--fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78dbin0 -> 247 bytes
-rw-r--r--fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719cbin0 -> 294 bytes
-rw-r--r--fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400ebin0 -> 211 bytes
-rw-r--r--fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8febin0 -> 27 bytes
-rw-r--r--fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6bin0 -> 209 bytes
-rw-r--r--fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44bin0 -> 877 bytes
-rw-r--r--fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baabin0 -> 408 bytes
-rw-r--r--fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efebin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578fbin0 -> 835 bytes
-rw-r--r--fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87adbin0 -> 192 bytes
-rw-r--r--fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785fbin0 -> 331 bytes
-rw-r--r--fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4cbin0 -> 1355 bytes
-rw-r--r--fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cfbin0 -> 367 bytes
-rw-r--r--fuzz/server_corpus/0c64a61be4a1b249f51c495042b62b6693589e2abin2467 -> 0 bytes
-rw-r--r--fuzz/server_corpus/0cc23c401fcdf25c2e4dc4bbe343039b1689998bbin37 -> 0 bytes
-rw-r--r--fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822bin0 -> 311 bytes
-rw-r--r--fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93abin0 -> 799 bytes
-rw-r--r--fuzz/server_corpus/0d1120af6afd2b1cab54482c2b8cccd4db904fe9bin604 -> 0 bytes
-rw-r--r--fuzz/server_corpus/0dbf6ef7bd2d0ffae28bff580783d478c82ec5adbin193 -> 0 bytes
-rw-r--r--fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8bin0 -> 111 bytes
-rw-r--r--fuzz/server_corpus/0faa1b0050add2d921b24a9f50181d605cf6f2ee1
-rw-r--r--fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16bin0 -> 282 bytes
-rw-r--r--fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906bin0 -> 663 bytes
-rw-r--r--fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1bin0 -> 631 bytes
-rw-r--r--fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546bin0 -> 334 bytes
-rw-r--r--fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489bin0 -> 589 bytes
-rw-r--r--fuzz/server_corpus/152e065473369bd8a6a060d8641db52699a0dec4bin180 -> 0 bytes
-rw-r--r--fuzz/server_corpus/155dbc7d80f78358598985efc616ee1c9a95b732bin505 -> 0 bytes
-rw-r--r--fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdacbin0 -> 235 bytes
-rw-r--r--fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4bin0 -> 368 bytes
-rw-r--r--fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659bin0 -> 2699 bytes
-rw-r--r--fuzz/server_corpus/16baa1a9d032ff13f4c97dbde84fd9771756c20ebin24 -> 0 bytes
-rw-r--r--fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506bin0 -> 265 bytes
-rw-r--r--fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39cbin0 -> 212 bytes
-rw-r--r--fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffdbin0 -> 192 bytes
-rw-r--r--fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97bin0 -> 588 bytes
-rw-r--r--fuzz/server_corpus/1d676a51656b8d4ef24a461e29c9fed2807f7e50bin528 -> 0 bytes
-rw-r--r--fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33cbin0 -> 491 bytes
-rw-r--r--fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3bin0 -> 2036 bytes
-rw-r--r--fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0affbin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/1e40a60f3553be1e5ed6f95b369b49e75ffc97e7bin224 -> 0 bytes
-rw-r--r--fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537bin0 -> 169 bytes
-rw-r--r--fuzz/server_corpus/2053722a3a832b256088576903f78b3a521036efbin727 -> 0 bytes
-rw-r--r--fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4bin0 -> 234 bytes
-rw-r--r--fuzz/server_corpus/20cf74e48a97d8db12cbbc66c6c7f5eb8bba9ee0bin477 -> 0 bytes
-rw-r--r--fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4dbin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1bin0 -> 307 bytes
-rw-r--r--fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0bin0 -> 214 bytes
-rw-r--r--fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29bin0 -> 979 bytes
-rw-r--r--fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59bbin0 -> 1157 bytes
-rw-r--r--fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08cbin0 -> 738 bytes
-rw-r--r--fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dffbin0 -> 107 bytes
-rw-r--r--fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513abin0 -> 250 bytes
-rw-r--r--fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3bin0 -> 27 bytes
-rw-r--r--fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/28e593bf15b1e6b2a1f7a6dd21a449965d89d31bbin3822 -> 0 bytes
-rw-r--r--fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3bin0 -> 822 bytes
-rw-r--r--fuzz/server_corpus/297c57f486feb89ef6b6b2dbba3f512275276b2fbin323 -> 0 bytes
-rw-r--r--fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24bin0 -> 310 bytes
-rw-r--r--fuzz/server_corpus/2b7d9ae0424f5301bd7ab12386cf24dbf142f7e5bin198 -> 0 bytes
-rw-r--r--fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390bin0 -> 863 bytes
-rw-r--r--fuzz/server_corpus/2c6ecbe428cdf047527f655527a9c73ccca9e2e1bin183 -> 0 bytes
-rw-r--r--fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651bin0 -> 236 bytes
-rw-r--r--fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2abin0 -> 365 bytes
-rw-r--r--fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41bin0 -> 266 bytes
-rw-r--r--fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508ebin0 -> 366 bytes
-rw-r--r--fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7bin0 -> 513 bytes
-rw-r--r--fuzz/server_corpus/319a6b4d218465966a29b5152fe9eb83003a41febin41 -> 0 bytes
-rw-r--r--fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dcbin0 -> 348 bytes
-rw-r--r--fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3bin0 -> 499 bytes
-rw-r--r--fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768bin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6dabin0 -> 838 bytes
-rw-r--r--fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9bin0 -> 375 bytes
-rw-r--r--fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9bin0 -> 167 bytes
-rw-r--r--fuzz/server_corpus/33d623eb76b1539ff7e44ce81784b5ef42b70df4bin868 -> 0 bytes
-rw-r--r--fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43bin0 -> 309 bytes
-rw-r--r--fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7cbin0 -> 429 bytes
-rw-r--r--fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206bin0 -> 538 bytes
-rw-r--r--fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3bin0 -> 1985 bytes
-rw-r--r--fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515dbin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3bin0 -> 500 bytes
-rw-r--r--fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770bin0 -> 308 bytes
-rw-r--r--fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89bin0 -> 1545 bytes
-rw-r--r--fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661bin0 -> 480 bytes
-rw-r--r--fuzz/server_corpus/37dbd1d658bb90da84a14aeb9f24db0200c20c4dbin378 -> 0 bytes
-rw-r--r--fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14bin0 -> 502 bytes
-rw-r--r--fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74bbin0 -> 137 bytes
-rw-r--r--fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528bin0 -> 434 bytes
-rw-r--r--fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5ebin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2bin0 -> 210 bytes
-rw-r--r--fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1bin0 -> 427 bytes
-rw-r--r--fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843bin0 -> 371 bytes
-rw-r--r--fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294bin0 -> 243 bytes
-rw-r--r--fuzz/server_corpus/3d1395e75201e8329b26520c1488a92b0cb14f0dbin207 -> 0 bytes
-rw-r--r--fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/3e62dce3a399b97744c41563672fb3b67a3981fcbin186 -> 0 bytes
-rw-r--r--fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7bin0 -> 377 bytes
-rw-r--r--fuzz/server_corpus/3fd252919651c9895feba5659a564fc1f4f7d3c6bin85 -> 0 bytes
-rw-r--r--fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9bin0 -> 622 bytes
-rw-r--r--fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9bin0 -> 28 bytes
-rw-r--r--fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929bin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384bin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44bin0 -> 321 bytes
-rw-r--r--fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348bin0 -> 528 bytes
-rw-r--r--fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814bin0 -> 211 bytes
-rw-r--r--fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81bin0 -> 1354 bytes
-rw-r--r--fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550bin0 -> 3535 bytes
-rw-r--r--fuzz/server_corpus/48b6e6c2a8d277c48f6272981d3ac13458bda2fcbin225 -> 0 bytes
-rw-r--r--fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6bin0 -> 368 bytes
-rw-r--r--fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61bin0 -> 608 bytes
-rw-r--r--fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5bin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345bin0 -> 2320 bytes
-rw-r--r--fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1bin0 -> 644 bytes
-rw-r--r--fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39bebin0 -> 352 bytes
-rw-r--r--fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99ddbin0 -> 191 bytes
-rw-r--r--fuzz/server_corpus/4d0beb8342107afedf7ad91e13c3b8d2cf558ecfbin344 -> 0 bytes
-rw-r--r--fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110dbin0 -> 267 bytes
-rw-r--r--fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caabin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72bin0 -> 169 bytes
-rw-r--r--fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553bin0 -> 352 bytes
-rw-r--r--fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/53f52c2e3ddcfb9734487f3efdb568de0a689cc4bin552 -> 0 bytes
-rw-r--r--fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbfbin0 -> 3980 bytes
-rw-r--r--fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838bin0 -> 167 bytes
-rw-r--r--fuzz/server_corpus/56b58b030f049497826cad828107c886c244e5c3bin653 -> 0 bytes
-rw-r--r--fuzz/server_corpus/57662bdb72f6c06ac58cdd7d97a165b101a3b4a6bin270 -> 0 bytes
-rw-r--r--fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cdbin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6bin0 -> 155 bytes
-rw-r--r--fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281bin0 -> 379 bytes
-rw-r--r--fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604bin0 -> 207 bytes
-rw-r--r--fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8bin0 -> 25 bytes
-rw-r--r--fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879bin0 -> 234 bytes
-rw-r--r--fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7abin0 -> 217 bytes
-rw-r--r--fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adfbin0 -> 169 bytes
-rw-r--r--fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0bin0 -> 551 bytes
-rw-r--r--fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8bin0 -> 142 bytes
-rw-r--r--fuzz/server_corpus/5f467faeb38fe5ca5d024a5a6816b79da9767732bin2010 -> 0 bytes
-rw-r--r--fuzz/server_corpus/5f87f3a402d733e677621e099eb9dd4903170ad6bin1773 -> 0 bytes
-rw-r--r--fuzz/server_corpus/5f9e63c922f729be467f5c33991ba7ddc675513fbin28 -> 0 bytes
-rw-r--r--fuzz/server_corpus/5fb64e97081500493ecb3941672157d9c99ca14ebin412 -> 0 bytes
-rw-r--r--fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902bin0 -> 335 bytes
-rw-r--r--fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644ebin0 -> 250 bytes
-rw-r--r--fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591fbin0 -> 608 bytes
-rw-r--r--fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7eebin0 -> 454 bytes
-rw-r--r--fuzz/server_corpus/6297728e4a0eafcbd2cbda655014c10578b8a035bin25 -> 0 bytes
-rw-r--r--fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485bin0 -> 356 bytes
-rw-r--r--fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8eabin0 -> 167 bytes
-rw-r--r--fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3bin0 -> 294 bytes
-rw-r--r--fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7bin0 -> 512 bytes
-rw-r--r--fuzz/server_corpus/669cc7dc49dbbd7ad6019ffcf7396981b830c0a2bin3981 -> 0 bytes
-rw-r--r--fuzz/server_corpus/678c4b5373f970b0e5b0231045e2318886f0443bbin742 -> 0 bytes
-rw-r--r--fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10bin0 -> 435 bytes
-rw-r--r--fuzz/server_corpus/687ad0e578cd6c67aa8ab45d79c5f05efa7b09a4bin182 -> 0 bytes
-rw-r--r--fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739fbin0 -> 221 bytes
-rw-r--r--fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78bin0 -> 387 bytes
-rw-r--r--fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02cebin0 -> 27 bytes
-rw-r--r--fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7bin0 -> 224 bytes
-rw-r--r--fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753bin0 -> 307 bytes
-rw-r--r--fuzz/server_corpus/6d52942721bf6fe08707bc9704f9b5a217604040bin184 -> 0 bytes
-rw-r--r--fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5cbin0 -> 328 bytes
-rw-r--r--fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06bin0 -> 183 bytes
-rw-r--r--fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532cbin0 -> 206 bytes
-rw-r--r--fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0bin0 -> 355 bytes
-rw-r--r--fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359bin0 -> 310 bytes
-rw-r--r--fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890bin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7abin0 -> 390 bytes
-rw-r--r--fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83bebin0 -> 232 bytes
-rw-r--r--fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634bin0 -> 24 bytes
-rw-r--r--fuzz/server_corpus/71c04cb636abfba7a375ee53fff441976b476782bin183 -> 0 bytes
-rw-r--r--fuzz/server_corpus/7313ac031df5c44dc34dd2b00f934df695099a50bin579 -> 0 bytes
-rw-r--r--fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aadbin0 -> 822 bytes
-rw-r--r--fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69afbin0 -> 230 bytes
-rw-r--r--fuzz/server_corpus/779a028692898b11fe8b382387de47ab5975a96fbin41 -> 0 bytes
-rw-r--r--fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232bin0 -> 148 bytes
-rw-r--r--fuzz/server_corpus/78866cc7c4e60906cf1d7de6bc6dde5dfc32b829bin511 -> 0 bytes
-rw-r--r--fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58bin0 -> 275 bytes
-rw-r--r--fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93ebin0 -> 250 bytes
-rw-r--r--fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762dbin0 -> 1296 bytes
-rw-r--r--fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2bin0 -> 306 bytes
-rw-r--r--fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457fbin0 -> 2049 bytes
-rw-r--r--fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10bin0 -> 321 bytes
-rw-r--r--fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35bin0 -> 497 bytes
-rw-r--r--fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02bin0 -> 419 bytes
-rw-r--r--fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943abin0 -> 2413 bytes
-rw-r--r--fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2bin0 -> 350 bytes
-rw-r--r--fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079bin0 -> 308 bytes
-rw-r--r--fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538ebin0 -> 198 bytes
-rw-r--r--fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1abin0 -> 388 bytes
-rw-r--r--fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629bin0 -> 215 bytes
-rw-r--r--fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9bin0 -> 572 bytes
-rw-r--r--fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27bin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095bin0 -> 224 bytes
-rw-r--r--fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1bin0 -> 218 bytes
-rw-r--r--fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097bin0 -> 2595 bytes
-rw-r--r--fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77bin0 -> 306 bytes
-rw-r--r--fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01bin0 -> 676 bytes
-rw-r--r--fuzz/server_corpus/8aa81c0c002cac098bd1edd10c052fb57e69679c1
-rw-r--r--fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9bin0 -> 297 bytes
-rw-r--r--fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6bin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4cbin0 -> 182 bytes
-rw-r--r--fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338bin0 -> 107 bytes
-rw-r--r--fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4bin0 -> 335 bytes
-rw-r--r--fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779bin0 -> 215 bytes
-rw-r--r--fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006bin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/92eaac1d235e5124e25bb36027fbf6e25084f386bin229 -> 0 bytes
-rw-r--r--fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86bin0 -> 309 bytes
-rw-r--r--fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41dbin0 -> 298 bytes
-rw-r--r--fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726bin0 -> 63 bytes
-rw-r--r--fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358bin0 -> 515 bytes
-rw-r--r--fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13cabin0 -> 333 bytes
-rw-r--r--fuzz/server_corpus/98aa9c388466c7236d35ce5efb9082bc1346a6861
-rw-r--r--fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335bin0 -> 182 bytes
-rw-r--r--fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcbbin0 -> 11 bytes
-rw-r--r--fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0bin0 -> 465 bytes
-rw-r--r--fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74bin0 -> 364 bytes
-rw-r--r--fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3adbin0 -> 325 bytes
-rw-r--r--fuzz/server_corpus/9db1a56028c509382bc7c788278a58eab7165331bin269 -> 0 bytes
-rw-r--r--fuzz/server_corpus/9ee8b26d5f9c65fb5c4464b19a868b524923029cbin792 -> 0 bytes
-rw-r--r--fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4cbin0 -> 231 bytes
-rw-r--r--fuzz/server_corpus/9fc76fdbf45c5c3b5464b9c0a94bb28945f7e0dcbin456 -> 0 bytes
-rw-r--r--fuzz/server_corpus/a04653e24258549b1a8030ed1bc0bdf91df94d87bin44 -> 0 bytes
-rw-r--r--fuzz/server_corpus/a07be10e0f08da224595bfa5e686165755f2de77bin780 -> 0 bytes
-rw-r--r--fuzz/server_corpus/a239133c8b8600e62206633d3da02c8fd7a46399bin475 -> 0 bytes
-rw-r--r--fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732bbin0 -> 496 bytes
-rw-r--r--fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3acbin0 -> 604 bytes
-rw-r--r--fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5bin0 -> 223 bytes
-rw-r--r--fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39acbin0 -> 852 bytes
-rw-r--r--fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9bin0 -> 210 bytes
-rw-r--r--fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1abin0 -> 180 bytes
-rw-r--r--fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786bbin0 -> 368 bytes
-rw-r--r--fuzz/server_corpus/a894fe7af5ae98da6ae8220acd2284105b637607bin193 -> 0 bytes
-rw-r--r--fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085fbin0 -> 250 bytes
-rw-r--r--fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715bin0 -> 414 bytes
-rw-r--r--fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cbbin0 -> 355 bytes
-rw-r--r--fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75bin0 -> 309 bytes
-rw-r--r--fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498bin0 -> 510 bytes
-rw-r--r--fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79bin0 -> 625 bytes
-rw-r--r--fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221bbin0 -> 450 bytes
-rw-r--r--fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27bin0 -> 603 bytes
-rw-r--r--fuzz/server_corpus/b15e07a299b22507059c03efdfcba56e4451ce38bin720 -> 0 bytes
-rw-r--r--fuzz/server_corpus/b31b285a8d1786c2cf196026bfbec9858c6b22e3bin736 -> 0 bytes
-rw-r--r--fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74bin0 -> 388 bytes
-rw-r--r--fuzz/server_corpus/b4bfe396d8dc5ac821725464c5fb36a09fe0530cbin169 -> 0 bytes
-rw-r--r--fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518cbin0 -> 169 bytes
-rw-r--r--fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938bin0 -> 182 bytes
-rw-r--r--fuzz/server_corpus/b63a416f846daa9a2dcb166848461797dba4e312bin1277 -> 0 bytes
-rw-r--r--fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571bin0 -> 702 bytes
-rw-r--r--fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9bbin0 -> 205 bytes
-rw-r--r--fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902fbin0 -> 298 bytes
-rw-r--r--fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368bin0 -> 847 bytes
-rw-r--r--fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32bin0 -> 231 bytes
-rw-r--r--fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257bin0 -> 809 bytes
-rw-r--r--fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5ebin0 -> 269 bytes
-rw-r--r--fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7ebin0 -> 238 bytes
-rw-r--r--fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bfbin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9cbin0 -> 234 bytes
-rw-r--r--fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8bin0 -> 642 bytes
-rw-r--r--fuzz/server_corpus/bd35db56de383d4c9ec3c2834270f4a062385022bin3795 -> 0 bytes
-rw-r--r--fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7fbin0 -> 143 bytes
-rw-r--r--fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72bin0 -> 339 bytes
-rw-r--r--fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246bin0 -> 567 bytes
-rw-r--r--fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0bin0 -> 1158 bytes
-rw-r--r--fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abbbin0 -> 254 bytes
-rw-r--r--fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8dbin0 -> 167 bytes
-rw-r--r--fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8bin0 -> 182 bytes
-rw-r--r--fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84bin0 -> 255 bytes
-rw-r--r--fuzz/server_corpus/c403d080cf1affbebce0dddc32091a8f5cbeae9fbin419 -> 0 bytes
-rw-r--r--fuzz/server_corpus/c410f6d6cfad7593f57d1ddb73d9d9eca03e5267bin826 -> 0 bytes
-rw-r--r--fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25bin0 -> 181 bytes
-rw-r--r--fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40eebin0 -> 182 bytes
-rw-r--r--fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671bin0 -> 224 bytes
-rw-r--r--fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122bin0 -> 236 bytes
-rw-r--r--fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3acbin0 -> 280 bytes
-rw-r--r--fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7bin0 -> 195 bytes
-rw-r--r--fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/c94f15684be5de1fe2272367a968c9bfc6bc4064bin224 -> 0 bytes
-rw-r--r--fuzz/server_corpus/c9cf42a05289ee11b545fb3b7a33620e7609791ebin234 -> 0 bytes
-rw-r--r--fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590dbin0 -> 167 bytes
-rw-r--r--fuzz/server_corpus/cb4ea46b40db7f46626bcf377a30484adc2f04641
-rw-r--r--fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800bin0 -> 245 bytes
-rw-r--r--fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dcbin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743bin0 -> 167 bytes
-rw-r--r--fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75bin0 -> 190 bytes
-rw-r--r--fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912bin0 -> 749 bytes
-rw-r--r--fuzz/server_corpus/d033c7d8801423bf221f9c3100a11f430e77ae7fbin192 -> 0 bytes
-rw-r--r--fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9bin0 -> 141 bytes
-rw-r--r--fuzz/server_corpus/d05db6bc123e01b5d8369d712adb0bd381a37cbdbin192 -> 0 bytes
-rw-r--r--fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488cebin0 -> 424 bytes
-rw-r--r--fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6bin0 -> 920 bytes
-rw-r--r--fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9bin0 -> 263 bytes
-rw-r--r--fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079bin0 -> 368 bytes
-rw-r--r--fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799bin0 -> 194 bytes
-rw-r--r--fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767ebin0 -> 424 bytes
-rw-r--r--fuzz/server_corpus/d3b4953343a95775199eb405d5949cb03a3578d8bin89 -> 0 bytes
-rw-r--r--fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773bin0 -> 244 bytes
-rw-r--r--fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72bin0 -> 429 bytes
-rw-r--r--fuzz/server_corpus/d5b66a02820057294711f8c80650bd921b8c8600bin207 -> 0 bytes
-rw-r--r--fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60bin0 -> 200 bytes
-rw-r--r--fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447bin0 -> 355 bytes
-rw-r--r--fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27bin0 -> 284 bytes
-rw-r--r--fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8bin0 -> 35 bytes
-rw-r--r--fuzz/server_corpus/d89bbcf5a9f5e1684061db8481080ded6fa79f13bin167 -> 0 bytes
-rw-r--r--fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1bin0 -> 195 bytes
-rw-r--r--fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0bin0 -> 226 bytes
-rw-r--r--fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677bin0 -> 224 bytes
-rw-r--r--fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434bin0 -> 461 bytes
-rw-r--r--fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9abin0 -> 630 bytes
-rw-r--r--fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3ebin0 -> 364 bytes
-rw-r--r--fuzz/server_corpus/dc429b08b66a1dcdd8d09991a41c041f00f1a671bin742 -> 0 bytes
-rw-r--r--fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5bin0 -> 352 bytes
-rw-r--r--fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5fbin0 -> 286 bytes
-rw-r--r--fuzz/server_corpus/dd2546c77bfdc7ce8418aee8d4b637a854cc20c7bin2801 -> 0 bytes
-rw-r--r--fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155bin0 -> 266 bytes
-rw-r--r--fuzz/server_corpus/df656c7ba5c20e78362830e3ef5b4fc39e80f6a0bin497 -> 0 bytes
-rw-r--r--fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0ebin0 -> 325 bytes
-rw-r--r--fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1bin0 -> 253 bytes
-rw-r--r--fuzz/server_corpus/e19d0f7a58cf60af5ab08b380a1a4fce93c28930bin462 -> 0 bytes
-rw-r--r--fuzz/server_corpus/e208b4ef816f4d964426345d782bc3a9d009e515bin179 -> 0 bytes
-rw-r--r--fuzz/server_corpus/e28cb4459b7e5473200931b48e935805a8e6981bbin362 -> 0 bytes
-rw-r--r--fuzz/server_corpus/e2f78c652cc04edb51f9afaf8a1cf45e87d64ca8bin980 -> 0 bytes
-rw-r--r--fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11bin0 -> 200 bytes
-rw-r--r--fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846ebin0 -> 819 bytes
-rw-r--r--fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60bin0 -> 182 bytes
-rw-r--r--fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bfbin0 -> 383 bytes
-rw-r--r--fuzz/server_corpus/e5b19696b772ec3b5f68e10e5022a65377d1edf7bin183 -> 0 bytes
-rw-r--r--fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3cbin0 -> 374 bytes
-rw-r--r--fuzz/server_corpus/e7d86d43ca9db0835b3060862e06f653f9ec66acbin254 -> 0 bytes
-rw-r--r--fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2bbin0 -> 182 bytes
-rw-r--r--fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557bin0 -> 305 bytes
-rw-r--r--fuzz/server_corpus/ea7ea348e64152ab70f5f54bcc1da81915a22506bin169 -> 0 bytes
-rw-r--r--fuzz/server_corpus/eab0cce27bc8b7edbfe0052aecb05edb3f0b941dbin3468 -> 0 bytes
-rw-r--r--fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874bin0 -> 358 bytes
-rw-r--r--fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976bin0 -> 366 bytes
-rw-r--r--fuzz/server_corpus/ed379815625c97a8821c47db565c7b4284e1fe1dbin176 -> 0 bytes
-rw-r--r--fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41decbin0 -> 343 bytes
-rw-r--r--fuzz/server_corpus/ee6080e7aa0f9fd158ce42f1917f20332244d69cbin182 -> 0 bytes
-rw-r--r--fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4bin0 -> 107 bytes
-rw-r--r--fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679dbin0 -> 223 bytes
-rw-r--r--fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18bin0 -> 282 bytes
-rw-r--r--fuzz/server_corpus/f07ec159fd7bbb172e2821d911a9981ed26d90a1bin2050 -> 0 bytes
-rw-r--r--fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30bin0 -> 356 bytes
-rw-r--r--fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86bin0 -> 230 bytes
-rw-r--r--fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691bbin0 -> 274 bytes
-rw-r--r--fuzz/server_corpus/f3395540f28e50b851c15db0aad8443aa2b2a70fbin200 -> 0 bytes
-rw-r--r--fuzz/server_corpus/f393d580ec06b3de83b72825b22087c99fbd18b3bin276 -> 0 bytes
-rw-r--r--fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134abin0 -> 500 bytes
-rw-r--r--fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322bin0 -> 393 bytes
-rw-r--r--fuzz/server_corpus/f5bd02993373de994d1ef28348706b7193a1509ebin26 -> 0 bytes
-rw-r--r--fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9bin0 -> 411 bytes
-rw-r--r--fuzz/server_corpus/f7e8f0def8a249d042f68fe2a0b5e31d23fbafeebin1440 -> 0 bytes
-rw-r--r--fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6bin0 -> 335 bytes
-rw-r--r--fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0bbin0 -> 1889 bytes
-rw-r--r--fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149ebin0 -> 2392 bytes
-rw-r--r--fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82bin0 -> 1063 bytes
-rw-r--r--fuzz/server_corpus/f9d559051861eb3b763b00700696e730beb170b1bin9 -> 0 bytes
-rw-r--r--fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1bin0 -> 296 bytes
-rw-r--r--fuzz/server_corpus/fa3f57c938561581946d3707058b7f7b8686d259bin167 -> 0 bytes
-rw-r--r--fuzz/server_corpus/fa556d46b2eca915290c9cbadc192ea9c1917117bin3472 -> 0 bytes
-rw-r--r--fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685bin0 -> 304 bytes
-rw-r--r--fuzz/server_corpus/fae5fdce7b5b57550c05aab5d8ac738beb4eaa1abin456 -> 0 bytes
-rw-r--r--fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99bin0 -> 234 bytes
-rw-r--r--fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38bin0 -> 470 bytes
-rw-r--r--fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61bin0 -> 192 bytes
-rw-r--r--fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07dbbin0 -> 315 bytes
-rw-r--r--fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602bin0 -> 277 bytes
-rw-r--r--fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0fbin0 -> 543 bytes
-rw-r--r--fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439bin0 -> 459 bytes
-rw-r--r--fuzz/server_corpus/ffd7d5299d017ec7104e3e6a744f4b946461e7f3bin402 -> 0 bytes
-rw-r--r--fuzz/spki.cc38
-rw-r--r--fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263eebin0 -> 120 bytes
-rw-r--r--fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3abin0 -> 608 bytes
-rw-r--r--fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548fbin0 -> 162 bytes
-rw-r--r--fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587bin0 -> 91 bytes
-rw-r--r--fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0cbin0 -> 444 bytes
-rw-r--r--fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915bin0 -> 302 bytes
-rw-r--r--fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00bin0 -> 158 bytes
-rw-r--r--fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6bin0 -> 80 bytes
-rw-r--r--include/openssl/aead.h124
-rw-r--r--include/openssl/arm_arch.h6
-rw-r--r--include/openssl/asn1.h224
-rw-r--r--include/openssl/asn1t.h12
-rw-r--r--include/openssl/base.h29
-rw-r--r--include/openssl/base64.h37
-rw-r--r--include/openssl/bio.h65
-rw-r--r--include/openssl/bn.h44
-rw-r--r--include/openssl/buf.h4
-rw-r--r--include/openssl/bytestring.h5
-rw-r--r--include/openssl/chacha.h4
-rw-r--r--include/openssl/cipher.h2
-rw-r--r--include/openssl/conf.h4
-rw-r--r--include/openssl/cpu.h35
-rw-r--r--include/openssl/crypto.h20
-rw-r--r--include/openssl/curve25519.h89
-rw-r--r--include/openssl/dh.h55
-rw-r--r--include/openssl/digest.h13
-rw-r--r--include/openssl/dsa.h9
-rw-r--r--include/openssl/ec.h47
-rw-r--r--include/openssl/ec_key.h19
-rw-r--r--include/openssl/evp.h124
-rw-r--r--include/openssl/hkdf.h28
-rw-r--r--include/openssl/hmac.h2
-rw-r--r--include/openssl/md4.h4
-rw-r--r--include/openssl/mem.h7
-rw-r--r--include/openssl/newhope.h147
-rw-r--r--include/openssl/nid.h4166
-rw-r--r--include/openssl/obj.h28
-rw-r--r--include/openssl/obj_mac.h4160
-rw-r--r--include/openssl/opensslconf.h60
-rw-r--r--include/openssl/opensslfeatures.h60
-rw-r--r--include/openssl/pem.h5
-rw-r--r--include/openssl/rand.h6
-rw-r--r--include/openssl/rc4.h6
-rw-r--r--include/openssl/ripemd.h107
-rw-r--r--include/openssl/rsa.h155
-rw-r--r--include/openssl/ssl.h196
-rw-r--r--include/openssl/ssl3.h30
-rw-r--r--include/openssl/stack_macros.h600
-rw-r--r--include/openssl/thread.h37
-rw-r--r--include/openssl/time_support.h1
-rw-r--r--include/openssl/tls1.h29
-rw-r--r--include/openssl/x509.h53
-rw-r--r--include/openssl/x509_vfy.h14
-rw-r--r--include/openssl/x509v3.h2
-rw-r--r--ssl/CMakeLists.txt12
-rw-r--r--ssl/d1_both.c308
-rw-r--r--ssl/d1_clnt.c561
-rw-r--r--ssl/d1_lib.c45
-rw-r--r--ssl/d1_meth.c5
-rw-r--r--ssl/d1_pkt.c498
-rw-r--r--ssl/d1_srtp.c7
-rw-r--r--ssl/d1_srvr.c476
-rw-r--r--ssl/dtls_record.c53
-rw-r--r--ssl/handshake_client.c2107
-rw-r--r--ssl/handshake_server.c2225
-rw-r--r--ssl/internal.h423
-rw-r--r--ssl/s3_both.c232
-rw-r--r--ssl/s3_clnt.c2090
-rw-r--r--ssl/s3_enc.c3
-rw-r--r--ssl/s3_lib.c224
-rw-r--r--ssl/s3_meth.c5
-rw-r--r--ssl/s3_pkt.c336
-rw-r--r--ssl/s3_srvr.c2272
-rw-r--r--ssl/ssl_aead_ctx.c57
-rw-r--r--ssl/ssl_buffer.c32
-rw-r--r--ssl/ssl_cert.c51
-rw-r--r--ssl/ssl_cipher.c208
-rw-r--r--ssl/ssl_ecdh.c323
-rw-r--r--ssl/ssl_file.c48
-rw-r--r--ssl/ssl_lib.c688
-rw-r--r--ssl/ssl_rsa.c5
-rw-r--r--ssl/ssl_session.c29
-rw-r--r--ssl/ssl_stat.c68
-rw-r--r--ssl/ssl_test.cc265
-rw-r--r--ssl/t1_enc.c3
-rw-r--r--ssl/t1_lib.c348
-rw-r--r--ssl/test/README.md35
-rw-r--r--ssl/test/bssl_shim.cc211
-rw-r--r--ssl/test/packeted_bio.cc218
-rw-r--r--ssl/test/packeted_bio.h27
-rw-r--r--ssl/test/runner/alert.go1
-rw-r--r--ssl/test/runner/chacha20_poly1305.go14
-rw-r--r--ssl/test/runner/chacha20_poly1305_test.go14
-rw-r--r--ssl/test/runner/cipher_suites.go33
-rw-r--r--ssl/test/runner/common.go32
-rw-r--r--ssl/test/runner/conn.go21
-rw-r--r--ssl/test/runner/deterministic.go37
-rw-r--r--ssl/test/runner/dtls.go9
-rw-r--r--ssl/test/runner/handshake_client.go19
-rw-r--r--ssl/test/runner/handshake_server.go29
-rw-r--r--ssl/test/runner/key_agreement.go215
-rw-r--r--ssl/test/runner/newhope/newhope.go319
-rw-r--r--ssl/test/runner/newhope/newhope_test.go154
-rw-r--r--ssl/test/runner/newhope/reconciliation.go132
-rw-r--r--ssl/test/runner/recordingconn.go25
-rw-r--r--ssl/test/runner/runner.go651
-rw-r--r--ssl/test/runner/runner_test.go14
-rw-r--r--ssl/test/test_config.cc7
-rw-r--r--ssl/test/test_config.h4
-rw-r--r--ssl/tls_record.c204
-rw-r--r--third_party/android-cmake/AndroidNdkGdb.cmake96
-rw-r--r--third_party/android-cmake/AndroidNdkModules.cmake58
-rw-r--r--third_party/android-cmake/LICENSE30
-rw-r--r--third_party/android-cmake/README.google12
-rw-r--r--third_party/android-cmake/README.md240
-rw-r--r--third_party/android-cmake/android.toolchain.cmake1693
-rw-r--r--third_party/android-cmake/ndk_links.md211
-rw-r--r--tool/digest.cc16
-rw-r--r--tool/internal.h37
-rw-r--r--tool/pkcs12.cc12
-rw-r--r--tool/rand.cc2
-rw-r--r--tool/speed.cc86
-rw-r--r--tool/tool.cc17
-rw-r--r--tool/transport_common.cc25
-rw-r--r--util/all_tests.go62
-rw-r--r--util/all_tests.json13
-rw-r--r--util/bot/DEPS9
-rw-r--r--util/bot/UPDATING47
-rw-r--r--util/bot/cmake-linux64.tar.gz.sha12
-rw-r--r--util/bot/cmake-mac.tar.gz.sha12
-rw-r--r--util/bot/cmake-win32.zip.sha12
-rwxr-xr-xutil/bot/go/bootstrap.py2
-rw-r--r--util/bot/perl-win32.zip.sha12
-rw-r--r--util/bot/update_clang.py2
-rw-r--r--util/bot/vs_toolchain.py26
-rw-r--r--util/doc.config2
-rw-r--r--util/doc.css5
-rw-r--r--util/doc.go20
-rwxr-xr-xutil/generate-asm-lcov.py152
-rwxr-xr-xutil/generate-coverage.sh60
-rw-r--r--util/generate_build_files.py303
-rw-r--r--util/run_android_tests.go315
2410 files changed, 42677 insertions, 24081 deletions
diff --git a/.clang-format b/.clang-format
index 43032d44..5865a706 100644
--- a/.clang-format
+++ b/.clang-format
@@ -2,3 +2,6 @@ BasedOnStyle: Google
MaxEmptyLinesToKeep: 3
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
+DerivePointerAlignment: false
+PointerAlignment: Right
+
diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE
new file mode 100644
index 00000000..6c101eab
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE
@@ -0,0 +1,7 @@
+Please do not send pull requests to the BoringSSL repository.
+
+We do, however, take contributions gladly.
+
+See https://boringssl.googlesource.com/boringssl/+/master/CONTRIBUTING.md
+
+Thanks!
diff --git a/BUILDING.md b/BUILDING.md
index d40df9ef..5631ded8 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -24,22 +24,16 @@
by CMake, it may be configured explicitly by setting
`CMAKE_ASM_NASM_COMPILER`.
- * A C compiler is required. On Windows, MSVC 12 (Visual Studio 2013) or later
+ * A C compiler is required. On Windows, MSVC 14 (Visual Studio 2015) or later
with Platform SDK 8.1 or later are supported. Recent versions of GCC (4.8+)
and Clang should work on non-Windows platforms, and maybe on Windows too.
+ To build the tests, you also need a C++ compiler with C++11 support.
* [Go](https://golang.org/dl/) is required. If not found by CMake, the go
executable may be configured explicitly by setting `GO_EXECUTABLE`.
- * If you change crypto/chacha/chacha\_vec.c, you will need the
- arm-linux-gnueabihf-gcc compiler:
-
- ```
- wget https://releases.linaro.org/14.11/components/toolchain/binaries/arm-linux-gnueabihf/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz && \
- echo bc4ca2ced084d2dc12424815a4442e19cb1422db87068830305d90075feb1a3b gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz | sha256sum -c && \
- tar xf gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz && \
- sudo mv gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf /opt/
- ```
+ * To build the x86 and x86\_64 assembly, your assembler must support AVX2
+ instructions. If using GNU binutils, you must have 2.22 or later.
## Building
@@ -89,18 +83,18 @@ It's possible to build BoringSSL with the Android NDK using CMake. This has
been tested with version 10d of the NDK.
Unpack the Android NDK somewhere and export `ANDROID_NDK` to point to the
-directory. Clone https://github.com/taka-no-me/android-cmake into `util/`. Then
-make a build directory as above and run CMake *twice* like this:
+directory. Then make a build directory as above and run CMake like this:
- cmake -DANDROID_NATIVE_API_LEVEL=android-9 \
- -DANDROID_ABI=armeabi-v7a \
- -DCMAKE_TOOLCHAIN_FILE=../util/android-cmake/android.toolchain.cmake \
+ cmake -DANDROID_ABI=armeabi-v7a \
+ -DCMAKE_TOOLCHAIN_FILE=../third_party/android-cmake/android.toolchain.cmake \
-DANDROID_NATIVE_API_LEVEL=16 \
-GNinja ..
-Once you've run that twice, Ninja should produce Android-compatible binaries.
-You can replace `armeabi-v7a` in the above with `arm64-v8a` to build aarch64
-binaries.
+Once you've run that, Ninja should produce Android-compatible binaries. You
+can replace `armeabi-v7a` in the above with `arm64-v8a` and use API level 21 or
+higher to build aarch64 binaries.
+
+For other options, see [android-cmake's documentation](./third_party/android-cmake/README.md).
## Known Limitations on Windows
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 17776ae8..ac045dfd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,6 +57,7 @@ elseif(MSVC)
"C4365" # '=' : conversion from 'size_t' to 'int',
# signed/unsigned mismatch
"C4389" # '!=' : signed/unsigned mismatch
+ "C4464" # relative include path contains '..'
"C4510" # 'argument' : default constructor could not be generated
"C4512" # 'argument' : assignment operator could not be generated
"C4514" # 'function': unreferenced inline function has been removed
@@ -64,6 +65,7 @@ elseif(MSVC)
# side-effect" caused by FD_* macros.
"C4610" # struct 'argument' can never be instantiated - user defined
# constructor required.
+ "C4623" # default constructor was implicitly defined as deleted
"C4625" # copy constructor could not be generated because a base class
# copy constructor is inaccessible or deleted
"C4626" # assignment operator could not be generated because a base class
@@ -74,16 +76,22 @@ elseif(MSVC)
"C4800" # 'int' : forcing value to bool 'true' or 'false'
# (performance warning)
"C4820" # 'bytes' bytes padding added after construct 'member_name'
- "C4996" # 'read': The POSIX name for this item is deprecated. Instead,
- # use the ISO C++ conformant name: _read.
- )
+ "C5027" # move assignment operator was implicitly defined as deleted
+ )
+ set(MSVC_LEVEL4_WARNINGS_LIST
+ # See https://connect.microsoft.com/VisualStudio/feedback/details/1217660/warning-c4265-when-using-functional-header
+ "C4265" # class has virtual functions, but destructor is not virtual
+ )
string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
${MSVC_DISABLED_WARNINGS_LIST})
- set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
- set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
+ string(REPLACE "C" " -w4" MSVC_LEVEL4_WARNINGS_STR
+ ${MSVC_LEVEL4_WARNINGS_LIST})
+ set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
+ set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
add_definitions(-D_HAS_EXCEPTIONS=0)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-DNOMINMAX)
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Allow use of fopen
endif()
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.99") OR
@@ -92,9 +100,18 @@ if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.9
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
endif()
-if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR
- CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_XOPEN_SOURCE=700")
+if(CMAKE_COMPILER_IS_GNUCXX)
+ if ((CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR
+ CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
+ else()
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+ endif()
+endif()
+
+# pthread_rwlock_t requires a feature flag.
+if(NOT WIN32)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=700")
endif()
if(FUZZ)
@@ -102,8 +119,11 @@ if(FUZZ)
message("You need to build with Clang for fuzzing to work")
endif()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls")
+ add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE)
+ set(RUNNER_ARGS "-fuzzer")
+
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
link_directories(.)
endif()
diff --git a/FUZZING.md b/FUZZING.md
index 4bd15a37..9f4edef1 100644
--- a/FUZZING.md
+++ b/FUZZING.md
@@ -13,9 +13,9 @@ CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 ..
In order for the fuzz tests to link, the linker needs to find libFuzzer. This is not commonly provided and you may need to download the [Clang source code](http://llvm.org/releases/download.html) and do the following:
```
-cd llvm-3.7.0.src/lib
-clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
-ar q libFuzzer.a *.o
+svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
+clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
+ar ruv libFuzzer.a Fuzzer*.o
```
Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory.
@@ -23,18 +23,41 @@ Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory.
From the `build/` directory, you can then run the fuzzers. For example:
```
-./fuzz/cert -max_len=4000 -jobs=32 -workers=32 ../fuzz/cert_corpus/
+./fuzz/cert -max_len=3072 -jobs=32 -workers=32 ../fuzz/cert_corpus/
```
-The `max_len` argument is often important because, without it, libFuzzer defaults to limiting all test cases to 64 bytes, which is often insufficient for the formats that we wish to fuzz. The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing.
+The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing. By default, libFuzzer uses the largest test in the corpus (or 64 if empty) as the maximum test case length. The `max_len` argument overrides this.
+
+The recommended values of `max_len` for each test are:
+
+| Test | `max_len` value |
+|------------|-----------------|
+| `cert` | 3072 |
+| `client` | 20000 |
+| `pkcs8` | 2048 |
+| `privkey` | 2048 |
+| `server` | 4096 |
+| `spki` | 1024 |
+| `read_pem` | 512 |
+
+These were determined by rounding up the length of the largest case in the corpus.
There are directories in `fuzz/` for each of the fuzzing tests which contain seed files for fuzzing. Some of the seed files were generated manually but many of them are “interesting” results generated by the fuzzing itself. (Where “interesting” means that it triggered a previously unknown path in the code.)
-Here are the recommended values of `max_len` for each test.
+## Minimising the corpuses
+
+When a large number of new seeds are available, it's a good idea to minimise the corpus so that different seeds that trigger the same code paths can be deduplicated.
+
+In order to minimise all the corpuses, build for fuzzing and run `./fuzz/minimise_corpuses.sh`. Note that minimisation is, oddly, often not idempotent for unknown reasons.
+
+## Fuzzer mode
+
+When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` defined. This modifies the library, particularly the TLS stack, to be more friendly to fuzzers. It will:
+
+* Replace `RAND_bytes` with a deterministic PRNG. Call `RAND_reset_for_fuzzing()` at the start of fuzzers which use `RAND_bytes` to reset the PRNG state.
+
+* Modify the TLS stack to perform all signature checks (CertificateVerify and ServerKeyExchange) and the Finished check, but always act as if the check succeeded.
+
+* Treat every cipher as the NULL cipher.
-| Test | `max_len` value |
-|-----------|-----------------|
-| `privkey` | 2048 |
-| `cert` | 3072 |
-| `server` | 1024 |
-| `client` | 4096 |
+This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol.
diff --git a/INCORPORATING.md b/INCORPORATING.md
new file mode 100644
index 00000000..d53f2b52
--- /dev/null
+++ b/INCORPORATING.md
@@ -0,0 +1,90 @@
+# Incorporating BoringSSL into a project
+
+**Note**: if your target project is not a Google project then first read the
+[main README](/README.md) about the purpose of BoringSSL.
+
+## Directory layout
+
+Typically projects create a `third_party/boringssl` directory to put
+BoringSSL-specific files into. The source code of BoringSSL itself goes into
+`third_party/boringssl/src`, either by copying or as a
+[submodule](https://git-scm.com/docs/git-submodule).
+
+It's generally a mistake to put BoringSSL's source code into
+`third_party/boringssl` directly because pre-built files and custom build files
+need to go somewhere and merging these with the BoringSSL source code makes
+updating things more complex.
+
+## Build support
+
+BoringSSL is designed to work with many different build systems. Currently,
+different projects use [GYP](https://gyp.gsrc.io/),
+[GN](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/quick_start.md),
+[Bazel](http://bazel.io/) and [Make](https://www.gnu.org/software/make/) to
+build BoringSSL, without too much pain.
+
+The development build system is CMake and the CMake build knows how to
+automatically generate the intermediate files that BoringSSL needs. However,
+outside of the CMake environment, these intermediates are generated once and
+checked into the incorporating project's source repository. This avoids
+incorporating projects needing to support Perl and Go in their build systems.
+
+The script [`util/generate_build_files.py`](/util/generate_build_files.py)
+expects to be run from the `third_party/boringssl` directory and to find the
+BoringSSL source code in `src/`. You should pass it a single argument: the name
+of the build system that you're using. If you don't use any of the supported
+build systems then you should augment `generate_build_files.py` with support
+for it.
+
+The script will pregenerate the intermediate files (see
+[BUILDING.md](/BUILDING.md) for details about which tools will need to be
+installed) and output helper files for that build system. It doesn't generate a
+complete build script, just file and test lists, which change often. For
+example, see the
+[file](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated.gni)
+and
+[test](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated_tests.gni)
+lists generated for GN in Chromium.
+
+Generally one checks in these generated files alongside the hand-written build
+files. Periodically an engineer updates the BoringSSL revision, regenerates
+these files and checks in the updated result. As an example, see how this is
+done [in Chromium](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/).
+
+## Defines
+
+BoringSSL does not present a lot of configurability in order to reduce the
+number of configurations that need to be tested. But there are a couple of
+\#defines that you may wish to set:
+
+`OPENSSL_NO_ASM` prevents the use of assembly code (although it's up to you to
+ensure that the build system doesn't link it in if you wish to reduce binary
+size). This will have a significant performance impact but can be useful if you
+wish to use tools like
+[AddressSanitizer](http://clang.llvm.org/docs/AddressSanitizer.html) that
+interact poorly with assembly code.
+
+`OPENSSL_SMALL` removes some code that is especially large at some performance
+cost.
+
+## Symbols
+
+You cannot link multiple versions of BoringSSL or OpenSSL into a single binary
+without dealing with symbol conflicts. If you are statically linking multiple
+versions together, there's not a lot that can be done because C doesn't have a
+module system.
+
+If you are using multiple versions in a single binary, in different shared
+objects, ensure you build BoringSSL with `-fvisibility=hidden` and do not
+export any of BoringSSL's symbols. This will prevent any collisions with other
+verisons that may be included in other shared objects. Note that this requires
+that all callers of BoringSSL APIs live in the same shared object as BoringSSL.
+
+If you require that BoringSSL APIs be used across shared object boundaries,
+continue to build with `-fvisibility=hidden` but define
+`BORINGSSL_SHARED_LIBRARY` in both BoringSSL and consumers. BoringSSL's own
+source files (but *not* consumers' source files) must also build with
+`BORINGSSL_IMPLEMENTATION` defined. This will export BoringSSL's public symbols
+in the resulting shared object while hiding private symbols. However note that,
+as with a static link, this precludes dynamically linking with another version
+of BoringSSL or OpenSSL.
diff --git a/LICENSE b/LICENSE
index b242dcb1..a25996f7 100644
--- a/LICENSE
+++ b/LICENSE
@@ -14,6 +14,13 @@ for the actual license texts. Actually both licenses are BSD-style Open Source
licenses. In case of any license issues related to OpenSSL please contact
openssl-core@openssl.org.
+The following are Google-internal bug numbers where explicit permission from
+some authors is recorded for use of their work. (This is purely for our own
+record keeping.)
+ 27287199
+ 27287880
+ 27287883
+
OpenSSL License
---------------
diff --git a/README.md b/README.md
index e306da9b..4caedb76 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,7 @@ There are other files in this directory which might be helpful:
* [PORTING.md](/PORTING.md): how to port OpenSSL-using code to BoringSSL.
* [BUILDING.md](/BUILDING.md): how to build BoringSSL
+ * [INCORPORATING.md](/INCORPORATING.md): how to incorporate BoringSSL into a project.
* [STYLE.md](/STYLE.md): rules and guidelines for coding style.
* include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
* [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
diff --git a/STYLE.md b/STYLE.md
index 4d2c5de4..17295b4f 100644
--- a/STYLE.md
+++ b/STYLE.md
@@ -14,10 +14,10 @@ concerned, balance consistency within a module with the benefits of a
given rule. Module-wide deviations on naming should be respected while
integer and return value conventions take precedence over consistency.
-Some modules have seen few changes, so they still retain the original
-indentation style for now. When editing these, try to retain the
-original style. For Emacs, `doc/c-indentation.el` from OpenSSL may be
-helpful in this.
+Modules from OpenSSL's legacy ASN.1 and X.509 stack are retained for
+compatibility and left largely unmodified. To ease importing patches from
+upstream, they match OpenSSL's new indentation style. For Emacs,
+`doc/openssl-c-indent.el` from OpenSSL may be helpful in this.
## Language
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 23a1a505..94e47ea1 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -22,6 +22,7 @@ elseif(UNIX)
endif()
set(ASM_EXT S)
enable_language(ASM)
+ set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack")
else()
if (CMAKE_CL_64)
message("Using nasm")
@@ -53,39 +54,6 @@ function(perlasm dest src)
)
endfunction()
-if (${ARCH} STREQUAL "x86_64")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-intel.c
- )
-endif()
-
-if (${ARCH} STREQUAL "x86")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-intel.c
- )
-endif()
-
-if (${ARCH} STREQUAL "arm")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-arm.c
- cpu-arm-asm.S
- )
-endif()
-
-if (${ARCH} STREQUAL "aarch64")
- set(
- CRYPTO_ARCH_SOURCES
-
- cpu-arm.c
- )
-endif()
-
# Level 0.1 - depends on nothing outside this set.
add_subdirectory(stack)
add_subdirectory(lhash)
@@ -106,6 +74,7 @@ add_subdirectory(conf)
add_subdirectory(chacha)
add_subdirectory(poly1305)
add_subdirectory(curve25519)
+add_subdirectory(newhope)
# Level 1, depends only on 0.*
add_subdirectory(digest)
@@ -182,16 +151,19 @@ set(
$<TARGET_OBJECTS:pem>
$<TARGET_OBJECTS:x509>
$<TARGET_OBJECTS:x509v3>
- $<TARGET_OBJECTS:pkcs8>
+ $<TARGET_OBJECTS:pkcs8_lib>
+ $<TARGET_OBJECTS:newhope>
PARENT_SCOPE
)
add_library(
crypto-objects OBJECT
+ cpu-aarch64-linux.c
+ cpu-arm.c
+ cpu-arm-linux.c
+ cpu-intel.c
crypto.c
- directory_posix.c
- directory_win.c
ex_data.c
mem.c
refcount_c11.c
@@ -210,9 +182,11 @@ add_library(
add_library(
crypto
+ cpu-aarch64-linux.c
+ cpu-arm.c
+ cpu-arm-linux.c
+ cpu-intel.c
crypto.c
- directory_posix.c
- directory_win.c
ex_data.c
mem.c
refcount_c11.c
@@ -223,8 +197,6 @@ add_library(
thread_win.c
time_support.c
- ${CRYPTO_ARCH_SOURCES}
-
$<TARGET_OBJECTS:stack>
$<TARGET_OBJECTS:lhash>
$<TARGET_OBJECTS:err>
@@ -263,7 +235,8 @@ add_library(
$<TARGET_OBJECTS:pem>
$<TARGET_OBJECTS:x509>
$<TARGET_OBJECTS:x509v3>
- $<TARGET_OBJECTS:pkcs8>
+ $<TARGET_OBJECTS:pkcs8_lib>
+ $<TARGET_OBJECTS:newhope>
)
if(NOT MSVC AND NOT ANDROID)
diff --git a/crypto/aes/mode_wrappers.c b/crypto/aes/mode_wrappers.c
index dc657dcd..4929920f 100644
--- a/crypto/aes/mode_wrappers.c
+++ b/crypto/aes/mode_wrappers.c
@@ -96,13 +96,17 @@ void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int *num) {
- CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
+ unsigned num_u = (unsigned)(*num);
+ CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u,
(block128_f)AES_encrypt);
+ *num = (int)num_u;
}
void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int *num,
int enc) {
- CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
+ unsigned num_u = (unsigned)(*num);
+ CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc,
(block128_f)AES_encrypt);
+ *num = (int)num_u;
}
diff --git a/crypto/asn1/CMakeLists.txt b/crypto/asn1/CMakeLists.txt
index bd16f872..90fe01f5 100644
--- a/crypto/asn1/CMakeLists.txt
+++ b/crypto/asn1/CMakeLists.txt
@@ -26,18 +26,14 @@ add_library(
asn1_lib.c
asn1_par.c
asn_pack.c
- bio_asn1.c
- bio_ndef.c
f_enum.c
f_int.c
f_string.c
t_bitst.c
- t_pkey.c
tasn_dec.c
tasn_enc.c
tasn_fre.c
tasn_new.c
- tasn_prn.c
tasn_typ.c
tasn_utl.c
x_bignum.c
diff --git a/crypto/asn1/a_bytes.c b/crypto/asn1/a_bytes.c
index 7e2f85dc..e6b2f2e9 100644
--- a/crypto/asn1/a_bytes.c
+++ b/crypto/asn1/a_bytes.c
@@ -202,13 +202,13 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
} else {
if (len != 0) {
if ((ret->length < len) || (ret->data == NULL)) {
- if (ret->data != NULL)
- OPENSSL_free(ret->data);
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
+ if (ret->data != NULL)
+ OPENSSL_free(ret->data);
} else
s = ret->data;
memcpy(s, p, (int)len);
diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c
index f8845d8a..b5449719 100644
--- a/crypto/asn1/a_d2i_fp.c
+++ b/crypto/asn1/a_d2i_fp.c
@@ -141,6 +141,7 @@ void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
#endif
#define HEADER_SIZE 8
+#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
BUF_MEM *b;
@@ -217,28 +218,42 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
/* suck in c.slen bytes of data */
want = c.slen;
if (want > (len - off)) {
+ size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
want -= (len - off);
if (want > INT_MAX /* BIO_read takes an int length */ ||
len + want < len) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
- if (!BUF_MEM_grow_clean(b, len + want)) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
while (want > 0) {
- i = BIO_read(in, &(b->data[len]), want);
- if (i <= 0) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
- goto err;
- }
/*
- * This can't overflow because |len+want| didn't
- * overflow.
+ * Read content in chunks of increasing size
+ * so we can return an error for EOF without
+ * having to allocate the entire content length
+ * in one go.
*/
- len += i;
- want -= i;
+ size_t chunk = want > chunk_max ? chunk_max : want;
+
+ if (!BUF_MEM_grow_clean(b, len + chunk)) {
+ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ want -= chunk;
+ while (chunk > 0) {
+ i = BIO_read(in, &(b->data[len]), chunk);
+ if (i <= 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
+ goto err;
+ }
+ /*
+ * This can't overflow because |len+want| didn't
+ * overflow.
+ */
+ len += i;
+ chunk -= i;
+ }
+ if (chunk_max < INT_MAX/2)
+ chunk_max *= 2;
}
}
if (off + c.slen < off) {
diff --git a/crypto/asn1/a_gentm.c b/crypto/asn1/a_gentm.c
index 09e4f171..ee6b3db5 100644
--- a/crypto/asn1/a_gentm.c
+++ b/crypto/asn1/a_gentm.c
@@ -63,6 +63,8 @@
#include <openssl/mem.h>
#include <openssl/time_support.h>
+#include "asn1_locl.h"
+
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
{
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c
index ba1224ef..c558bce6 100644
--- a/crypto/asn1/a_strnid.c
+++ b/crypto/asn1/a_strnid.c
@@ -247,6 +247,7 @@ int ASN1_STRING_TABLE_add(int nid,
}
tmp->flags = flags | STABLE_FLAGS_MALLOC;
tmp->nid = nid;
+ tmp->minsize = tmp->maxsize = -1;
new_nid = 1;
} else
tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c
index ecd47342..734ff8b4 100644
--- a/crypto/asn1/a_type.c
+++ b/crypto/asn1/a_type.c
@@ -122,9 +122,7 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
result = a->value.boolean - b->value.boolean;
break;
case V_ASN1_INTEGER:
- case V_ASN1_NEG_INTEGER:
case V_ASN1_ENUMERATED:
- case V_ASN1_NEG_ENUMERATED:
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
case V_ASN1_SEQUENCE:
diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c
index 35eb1c9b..5a55bd24 100644
--- a/crypto/asn1/a_utctm.c
+++ b/crypto/asn1/a_utctm.c
@@ -63,6 +63,8 @@
#include <openssl/mem.h>
#include <openssl/time_support.h>
+#include "asn1_locl.h"
+
#if 0
int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
{
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index 0025a676..b637e795 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -63,9 +63,15 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-/* Cross-module errors from crypto/x509/i2d_pr.c */
+/* Cross-module errors from crypto/x509/i2d_pr.c. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
+/* Cross-module errors from crypto/x509/algorithm.c. */
+OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE);
/*
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
* these once asn1_gen.c is gone.
@@ -95,7 +101,7 @@ OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG);
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE);
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
- int max);
+ long max);
static void asn1_put_length(unsigned char **pp, int length);
static int _asn1_check_infinite_end(const unsigned char **p, long len)
@@ -167,7 +173,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
*ptag = tag;
*pclass = xclass;
- if (!asn1_get_length(&p, &inf, plength, (int)max))
+ if (!asn1_get_length(&p, &inf, plength, max))
goto err;
if (inf && !(ret & V_ASN1_CONSTRUCTED))
@@ -195,14 +201,14 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
}
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
- int max)
+ long max)
{
const unsigned char *p = *pp;
unsigned long ret = 0;
- unsigned int i;
+ unsigned long i;
if (max-- < 1)
- return (0);
+ return 0;
if (*p == 0x80) {
*inf = 1;
ret = 0;
@@ -211,15 +217,11 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
*inf = 0;
i = *p & 0x7f;
if (*(p++) & 0x80) {
- if (i > sizeof(long))
+ if (i > sizeof(ret) || max < (long)i)
return 0;
- if (max-- == 0)
- return (0);
while (i-- > 0) {
ret <<= 8L;
ret |= *(p++);
- if (max-- == 0)
- return (0);
}
} else
ret = i;
@@ -228,7 +230,7 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
return 0;
*pp = p;
*rl = (long)ret;
- return (1);
+ return 1;
}
/*
diff --git a/crypto/asn1/asn1_locl.h b/crypto/asn1/asn1_locl.h
index 49eceb6b..982bfd60 100644
--- a/crypto/asn1/asn1_locl.h
+++ b/crypto/asn1/asn1_locl.h
@@ -61,13 +61,3 @@
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
-
-/* ASN1 print context structure */
-
-struct asn1_pctx_st {
- unsigned long flags;
- unsigned long nm_flags;
- unsigned long cert_flags;
- unsigned long oid_flags;
- unsigned long str_flags;
-} /* ASN1_PCTX */ ;
diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c
index fbdaae84..b1a01eda 100644
--- a/crypto/asn1/asn1_par.c
+++ b/crypto/asn1/asn1_par.c
@@ -56,328 +56,6 @@
#include <openssl/asn1.h>
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-#define ASN1_PARSE_MAXDEPTH 128
-
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
- int indent);
-static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
- int offset, int depth, int indent, int dump);
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
- int indent)
-{
- static const char fmt[] = "%-18s";
- char str[128];
- const char *p;
-
- if (constructed & V_ASN1_CONSTRUCTED)
- p = "cons: ";
- else
- p = "prim: ";
- if (BIO_write(bp, p, 6) < 6)
- goto err;
- BIO_indent(bp, indent, 128);
-
- p = str;
- if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- BIO_snprintf(str, sizeof str, "priv [ %d ] ", tag);
- else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- BIO_snprintf(str, sizeof str, "cont [ %d ]", tag);
- else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- BIO_snprintf(str, sizeof str, "appl [ %d ]", tag);
- else if (tag > 30)
- BIO_snprintf(str, sizeof str, "<ASN1 %d>", tag);
- else
- p = ASN1_tag2str(tag);
-
- if (BIO_printf(bp, fmt, p) <= 0)
- goto err;
- return (1);
- err:
- return (0);
-}
-
-int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
-{
- return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0));
-}
-
-int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
- int dump)
-{
- return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump));
-}
-
-static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
- int offset, int depth, int indent, int dump)
-{
- const unsigned char *p, *ep, *tot, *op, *opp;
- long len;
- int tag, xclass, ret = 0;
- int nl, hl, j, r;
- ASN1_OBJECT *o = NULL;
- ASN1_OCTET_STRING *os = NULL;
- /* ASN1_BMPSTRING *bmp=NULL; */
- int dump_indent;
-
-#if 0
- dump_indent = indent;
-#else
- dump_indent = 6; /* Because we know BIO_dump_indent() */
-#endif
-
- if (depth > ASN1_PARSE_MAXDEPTH) {
- BIO_puts(bp, "BAD RECURSION DEPTH\n");
- return 0;
- }
-
- p = *pp;
- tot = p + length;
- op = p - 1;
- while ((p < tot) && (op < p)) {
- op = p;
- j = ASN1_get_object(&p, &len, &tag, &xclass, length);
-#ifdef LINT
- j = j;
-#endif
- if (j & 0x80) {
- if (BIO_puts(bp, "Error in encoding\n") <= 0)
- goto end;
- ret = 0;
- goto end;
- }
- hl = (p - op);
- length -= hl;
- /*
- * if j == 0x21 it is a constructed indefinite length object
- */
- if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
- <= 0)
- goto end;
-
- if (j != (V_ASN1_CONSTRUCTED | 1)) {
- if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
- depth, (long)hl, len) <= 0)
- goto end;
- } else {
- if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
- goto end;
- }
- if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
- goto end;
- if (j & V_ASN1_CONSTRUCTED) {
- ep = p + len;
- if (BIO_puts(bp, "\n") <= 0)
- goto end;
- if (len > length) {
- BIO_printf(bp, "length is greater than %ld\n", length);
- ret = 0;
- goto end;
- }
- if ((j == 0x21) && (len == 0)) {
- for (;;) {
- r = asn1_parse2(bp, &p, (long)(tot - p),
- offset + (p - *pp), depth + 1,
- indent, dump);
- if (r == 0) {
- ret = 0;
- goto end;
- }
- if ((r == 2) || (p >= tot))
- break;
- }
- } else
- while (p < ep) {
- r = asn1_parse2(bp, &p, (long)len,
- offset + (p - *pp), depth + 1,
- indent, dump);
- if (r == 0) {
- ret = 0;
- goto end;
- }
- }
- } else if (xclass != 0) {
- p += len;
- if (BIO_puts(bp, "\n") <= 0)
- goto end;
- } else {
- nl = 0;
- if ((tag == V_ASN1_PRINTABLESTRING) ||
- (tag == V_ASN1_T61STRING) ||
- (tag == V_ASN1_IA5STRING) ||
- (tag == V_ASN1_VISIBLESTRING) ||
- (tag == V_ASN1_NUMERICSTRING) ||
- (tag == V_ASN1_UTF8STRING) ||
- (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
- if (BIO_puts(bp, ":") <= 0)
- goto end;
- if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
- != (int)len)
- goto end;
- } else if (tag == V_ASN1_OBJECT) {
- opp = op;
- if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
- if (BIO_puts(bp, ":") <= 0)
- goto end;
- i2a_ASN1_OBJECT(bp, o);
- } else {
- if (BIO_puts(bp, ":BAD OBJECT") <= 0)
- goto end;
- }
- } else if (tag == V_ASN1_BOOLEAN) {
- int ii;
-
- opp = op;
- ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
- if (ii < 0) {
- if (BIO_puts(bp, "Bad boolean\n") <= 0)
- goto end;
- }
- BIO_printf(bp, ":%d", ii);
- } else if (tag == V_ASN1_BMPSTRING) {
- /* do the BMP thang */
- } else if (tag == V_ASN1_OCTET_STRING) {
- int i, printable = 1;
-
- opp = op;
- os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
- if (os != NULL && os->length > 0) {
- opp = os->data;
- /*
- * testing whether the octet string is printable
- */
- for (i = 0; i < os->length; i++) {
- if (((opp[i] < ' ') &&
- (opp[i] != '\n') &&
- (opp[i] != '\r') &&
- (opp[i] != '\t')) || (opp[i] > '~')) {
- printable = 0;
- break;
- }
- }
- if (printable)
- /* printable string */
- {
- if (BIO_puts(bp, ":") <= 0)
- goto end;
- if (BIO_write(bp, (const char *)opp, os->length) <= 0)
- goto end;
- } else if (!dump)
- /*
- * not printable => print octet string as hex dump
- */
- {
- if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
- goto end;
- for (i = 0; i < os->length; i++) {
- if (BIO_printf(bp, "%02X", opp[i]) <= 0)
- goto end;
- }
- } else
- /* print the normal dump */
- {
- if (!nl) {
- if (BIO_puts(bp, "\n") <= 0)
- goto end;
- }
- if (!BIO_hexdump(bp, opp,
- ((dump == -1 || dump >
- os->length) ? os->length : dump),
- dump_indent))
- goto end;
- nl = 1;
- }
- }
- if (os != NULL) {
- M_ASN1_OCTET_STRING_free(os);
- os = NULL;
- }
- } else if (tag == V_ASN1_INTEGER) {
- ASN1_INTEGER *bs;
- int i;
-
- opp = op;
- bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
- if (bs != NULL) {
- if (BIO_puts(bp, ":") <= 0)
- goto end;
- if (bs->type == V_ASN1_NEG_INTEGER)
- if (BIO_puts(bp, "-") <= 0)
- goto end;
- for (i = 0; i < bs->length; i++) {
- if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
- goto end;
- }
- if (bs->length == 0) {
- if (BIO_puts(bp, "00") <= 0)
- goto end;
- }
- } else {
- if (BIO_puts(bp, "BAD INTEGER") <= 0)
- goto end;
- }
- M_ASN1_INTEGER_free(bs);
- } else if (tag == V_ASN1_ENUMERATED) {
- ASN1_ENUMERATED *bs;
- int i;
-
- opp = op;
- bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
- if (bs != NULL) {
- if (BIO_puts(bp, ":") <= 0)
- goto end;
- if (bs->type == V_ASN1_NEG_ENUMERATED)
- if (BIO_puts(bp, "-") <= 0)
- goto end;
- for (i = 0; i < bs->length; i++) {
- if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
- goto end;
- }
- if (bs->length == 0) {
- if (BIO_puts(bp, "00") <= 0)
- goto end;
- }
- } else {
- if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
- goto end;
- }
- M_ASN1_ENUMERATED_free(bs);
- } else if (len > 0 && dump) {
- if (!nl) {
- if (BIO_puts(bp, "\n") <= 0)
- goto end;
- }
- if (!BIO_hexdump(bp, p,
- ((dump == -1 || dump > len) ? len : dump),
- dump_indent))
- goto end;
- nl = 1;
- }
-
- if (!nl) {
- if (BIO_puts(bp, "\n") <= 0)
- goto end;
- }
- p += len;
- if ((tag == V_ASN1_EOC) && (xclass == 0)) {
- ret = 2; /* End of sequence */
- goto end;
- }
- }
- length -= len;
- }
- ret = 1;
- end:
- if (o != NULL)
- ASN1_OBJECT_free(o);
- if (os != NULL)
- M_ASN1_OCTET_STRING_free(os);
- *pp = p;
- return (ret);
-}
const char *ASN1_tag2str(int tag)
{
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc
index 1044f7b2..8b024427 100644
--- a/crypto/asn1/asn1_test.cc
+++ b/crypto/asn1/asn1_test.cc
@@ -21,6 +21,11 @@
#include "../test/scoped_types.h"
+// kTag128 is an ASN.1 structure with a universal tag with number 128.
+static const uint8_t kTag128[] = {
+ 0x1f, 0x81, 0x00, 0x01, 0x00,
+};
+
// kTag258 is an ASN.1 structure with a universal tag with number 258.
static const uint8_t kTag258[] = {
0x1f, 0x82, 0x02, 0x01, 0x00,
@@ -29,13 +34,38 @@ static const uint8_t kTag258[] = {
static_assert(V_ASN1_NEG_INTEGER == 258,
"V_ASN1_NEG_INTEGER changed. Update kTag258 to collide with it.");
-bool TestLargeTags() {
+// kTagOverflow is an ASN.1 structure with a universal tag with number 2^35-1,
+// which will not fit in an int.
+static const uint8_t kTagOverflow[] = {
+ 0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
+};
+
+static bool TestLargeTags() {
const uint8_t *p = kTag258;
ScopedASN1_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;
}
+ 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;
+ }
+ 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;
}
diff --git a/crypto/asn1/bio_asn1.c b/crypto/asn1/bio_asn1.c
deleted file mode 100644
index 03cc9a6e..00000000
--- a/crypto/asn1/bio_asn1.c
+++ /dev/null
@@ -1,477 +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 <assert.h>
-#include <string.h>
-
-#include <openssl/bio.h>
-#include <openssl/mem.h>
-
-/* Must be large enough for biggest tag+length */
-#define DEFAULT_ASN1_BUF_SIZE 20
-
-typedef enum {
- ASN1_STATE_START,
- ASN1_STATE_PRE_COPY,
- ASN1_STATE_HEADER,
- ASN1_STATE_HEADER_COPY,
- ASN1_STATE_DATA_COPY,
- ASN1_STATE_POST_COPY,
- ASN1_STATE_DONE
-} asn1_bio_state_t;
-
-typedef struct BIO_ASN1_EX_FUNCS_st {
- asn1_ps_func *ex_func;
- asn1_ps_func *ex_free_func;
-} BIO_ASN1_EX_FUNCS;
-
-typedef struct BIO_ASN1_BUF_CTX_t {
- /* Internal state */
- asn1_bio_state_t state;
- /* Internal buffer */
- unsigned char *buf;
- /* Size of buffer */
- int bufsize;
- /* Current position in buffer */
- int bufpos;
- /* Current buffer length */
- int buflen;
- /* Amount of data to copy */
- int copylen;
- /* Class and tag to use */
- int asn1_class, asn1_tag;
- asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
- /* Extra buffer for prefix and suffix data */
- unsigned char *ex_buf;
- int ex_len;
- int ex_pos;
- void *ex_arg;
-} BIO_ASN1_BUF_CTX;
-
-static int asn1_bio_write(BIO *h, const char *buf, int num);
-static int asn1_bio_read(BIO *h, char *buf, int size);
-static int asn1_bio_puts(BIO *h, const char *str);
-static int asn1_bio_gets(BIO *h, char *str, int size);
-static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
-static int asn1_bio_new(BIO *h);
-static int asn1_bio_free(BIO *data);
-static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb fp);
-
-static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
-static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *cleanup, asn1_bio_state_t next);
-static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *setup,
- asn1_bio_state_t ex_state,
- asn1_bio_state_t other_state);
-
-static const BIO_METHOD methods_asn1 = {
- BIO_TYPE_ASN1,
- "asn1",
- asn1_bio_write,
- asn1_bio_read,
- asn1_bio_puts,
- asn1_bio_gets,
- asn1_bio_ctrl,
- asn1_bio_new,
- asn1_bio_free,
- asn1_bio_callback_ctrl,
-};
-
-const BIO_METHOD *BIO_f_asn1(void)
-{
- return (&methods_asn1);
-}
-
-static int asn1_bio_new(BIO *b)
-{
- BIO_ASN1_BUF_CTX *ctx;
- ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
- if (!ctx)
- return 0;
- if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
- OPENSSL_free(ctx);
- return 0;
- }
- b->init = 1;
- b->ptr = (char *)ctx;
- b->flags = 0;
- return 1;
-}
-
-static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
-{
- ctx->buf = OPENSSL_malloc(size);
- if (!ctx->buf)
- return 0;
- ctx->bufsize = size;
- ctx->bufpos = 0;
- ctx->buflen = 0;
- ctx->copylen = 0;
- ctx->asn1_class = V_ASN1_UNIVERSAL;
- ctx->asn1_tag = V_ASN1_OCTET_STRING;
- ctx->ex_buf = 0;
- ctx->ex_pos = 0;
- ctx->ex_len = 0;
- ctx->state = ASN1_STATE_START;
- return 1;
-}
-
-static int asn1_bio_free(BIO *b)
-{
- BIO_ASN1_BUF_CTX *ctx;
- ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
- if (ctx == NULL)
- return 0;
- if (ctx->buf)
- OPENSSL_free(ctx->buf);
- OPENSSL_free(ctx);
- b->init = 0;
- b->ptr = NULL;
- b->flags = 0;
- return 1;
-}
-
-static int asn1_bio_write(BIO *b, const char *in, int inl)
-{
- BIO_ASN1_BUF_CTX *ctx;
- int wrmax, wrlen, ret;
- unsigned char *p;
- if (!in || (inl < 0) || (b->next_bio == NULL))
- return 0;
- ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
- if (ctx == NULL)
- return 0;
-
- wrlen = 0;
- ret = -1;
-
- for (;;) {
- switch (ctx->state) {
-
- /* Setup prefix data, call it */
- case ASN1_STATE_START:
- if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
- ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
- return 0;
- break;
-
- /* Copy any pre data first */
- case ASN1_STATE_PRE_COPY:
-
- ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
- ASN1_STATE_HEADER);
-
- if (ret <= 0)
- goto done;
-
- break;
-
- case ASN1_STATE_HEADER:
- ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
- assert(ctx->buflen <= ctx->bufsize);
- p = ctx->buf;
- ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
- ctx->copylen = inl;
- ctx->state = ASN1_STATE_HEADER_COPY;
-
- break;
-
- case ASN1_STATE_HEADER_COPY:
- ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
- if (ret <= 0)
- goto done;
-
- ctx->buflen -= ret;
- if (ctx->buflen)
- ctx->bufpos += ret;
- else {
- ctx->bufpos = 0;
- ctx->state = ASN1_STATE_DATA_COPY;
- }
-
- break;
-
- case ASN1_STATE_DATA_COPY:
-
- if (inl > ctx->copylen)
- wrmax = ctx->copylen;
- else
- wrmax = inl;
- ret = BIO_write(b->next_bio, in, wrmax);
- if (ret <= 0)
- break;
- wrlen += ret;
- ctx->copylen -= ret;
- in += ret;
- inl -= ret;
-
- if (ctx->copylen == 0)
- ctx->state = ASN1_STATE_HEADER;
-
- if (inl == 0)
- goto done;
-
- break;
-
- default:
- BIO_clear_retry_flags(b);
- return 0;
-
- }
-
- }
-
- done:
- BIO_clear_retry_flags(b);
- BIO_copy_next_retry(b);
-
- return (wrlen > 0) ? wrlen : ret;
-
-}
-
-static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *cleanup, asn1_bio_state_t next)
-{
- int ret;
- if (ctx->ex_len <= 0)
- return 1;
- for (;;) {
- ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
- if (ret <= 0)
- break;
- ctx->ex_len -= ret;
- if (ctx->ex_len > 0)
- ctx->ex_pos += ret;
- else {
- if (cleanup)
- cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
- ctx->state = next;
- ctx->ex_pos = 0;
- break;
- }
- }
- return ret;
-}
-
-static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
- asn1_ps_func *setup,
- asn1_bio_state_t ex_state,
- asn1_bio_state_t other_state)
-{
- if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
- BIO_clear_retry_flags(b);
- return 0;
- }
- if (ctx->ex_len > 0)
- ctx->state = ex_state;
- else
- ctx->state = other_state;
- return 1;
-}
-
-static int asn1_bio_read(BIO *b, char *in, int inl)
-{
- if (!b->next_bio)
- return 0;
- return BIO_read(b->next_bio, in, inl);
-}
-
-static int asn1_bio_puts(BIO *b, const char *str)
-{
- return asn1_bio_write(b, str, strlen(str));
-}
-
-static int asn1_bio_gets(BIO *b, char *str, int size)
-{
- if (!b->next_bio)
- return 0;
- return BIO_gets(b->next_bio, str, size);
-}
-
-static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb fp)
-{
- if (b->next_bio == NULL)
- return (0);
- return BIO_callback_ctrl(b->next_bio, cmd, fp);
-}
-
-static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
-{
- BIO_ASN1_BUF_CTX *ctx;
- BIO_ASN1_EX_FUNCS *ex_func;
- long ret = 1;
- ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
- if (ctx == NULL)
- return 0;
- switch (cmd) {
-
- case BIO_C_SET_PREFIX:
- ex_func = arg2;
- ctx->prefix = ex_func->ex_func;
- ctx->prefix_free = ex_func->ex_free_func;
- break;
-
- case BIO_C_GET_PREFIX:
- ex_func = arg2;
- ex_func->ex_func = ctx->prefix;
- ex_func->ex_free_func = ctx->prefix_free;
- break;
-
- case BIO_C_SET_SUFFIX:
- ex_func = arg2;
- ctx->suffix = ex_func->ex_func;
- ctx->suffix_free = ex_func->ex_free_func;
- break;
-
- case BIO_C_GET_SUFFIX:
- ex_func = arg2;
- ex_func->ex_func = ctx->suffix;
- ex_func->ex_free_func = ctx->suffix_free;
- break;
-
- case BIO_C_SET_EX_ARG:
- ctx->ex_arg = arg2;
- break;
-
- case BIO_C_GET_EX_ARG:
- *(void **)arg2 = ctx->ex_arg;
- break;
-
- case BIO_CTRL_FLUSH:
- if (!b->next_bio)
- return 0;
-
- /* Call post function if possible */
- if (ctx->state == ASN1_STATE_HEADER) {
- if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
- ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
- return 0;
- }
-
- if (ctx->state == ASN1_STATE_POST_COPY) {
- ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
- ASN1_STATE_DONE);
- if (ret <= 0)
- return ret;
- }
-
- if (ctx->state == ASN1_STATE_DONE)
- return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
- else {
- BIO_clear_retry_flags(b);
- return 0;
- }
- break;
-
- default:
- if (!b->next_bio)
- return 0;
- return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
-
- }
-
- return ret;
-}
-
-static int asn1_bio_set_ex(BIO *b, int cmd,
- asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
-{
- BIO_ASN1_EX_FUNCS extmp;
- extmp.ex_func = ex_func;
- extmp.ex_free_func = ex_free_func;
- return BIO_ctrl(b, cmd, 0, &extmp);
-}
-
-static int asn1_bio_get_ex(BIO *b, int cmd,
- asn1_ps_func **ex_func,
- asn1_ps_func **ex_free_func)
-{
- BIO_ASN1_EX_FUNCS extmp;
- int ret;
- ret = BIO_ctrl(b, cmd, 0, &extmp);
- if (ret > 0) {
- *ex_func = extmp.ex_func;
- *ex_free_func = extmp.ex_free_func;
- }
- return ret;
-}
-
-int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
- asn1_ps_func *prefix_free)
-{
- return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
-}
-
-int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
- asn1_ps_func **pprefix_free)
-{
- return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
-}
-
-int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
- asn1_ps_func *suffix_free)
-{
- return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
-}
-
-int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
- asn1_ps_func **psuffix_free)
-{
- return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
-}
diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c
deleted file mode 100644
index 81a8aa7c..00000000
--- a/crypto/asn1/bio_ndef.c
+++ /dev/null
@@ -1,251 +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 <assert.h>
-
-#include <openssl/asn1t.h>
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-/* Experimental NDEF ASN1 BIO support routines */
-
-/*
- * The usage is quite simple, initialize an ASN1 structure, get a BIO from it
- * then any data written through the BIO will end up translated to
- * approptiate format on the fly. The data is streamed out and does *not*
- * need to be all held in memory at once. When the BIO is flushed the output
- * is finalized and any signatures etc written out. The BIO is a 'proper'
- * BIO and can handle non blocking I/O correctly. The usage is simple. The
- * implementation is *not*...
- */
-
-/* BIO support data stored in the ASN1 BIO ex_arg */
-
-typedef struct ndef_aux_st {
- /* ASN1 structure this BIO refers to */
- ASN1_VALUE *val;
- const ASN1_ITEM *it;
- /* Top of the BIO chain */
- BIO *ndef_bio;
- /* Output BIO */
- BIO *out;
- /* Boundary where content is inserted */
- unsigned char **boundary;
- /* DER buffer start */
- unsigned char *derbuf;
-} NDEF_SUPPORT;
-
-static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
- void *parg);
-static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
- void *parg);
-
-BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
-{
- NDEF_SUPPORT *ndef_aux = NULL;
- BIO *asn_bio = NULL;
- const ASN1_AUX *aux = it->funcs;
- ASN1_STREAM_ARG sarg;
-
- if (!aux || !aux->asn1_cb) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
- return NULL;
- }
- ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
- asn_bio = BIO_new(BIO_f_asn1());
-
- /* ASN1 bio needs to be next to output BIO */
-
- out = BIO_push(asn_bio, out);
-
- if (!ndef_aux || !asn_bio || !out)
- goto err;
-
- BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
- BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
-
- /*
- * Now let callback prepend any digest, cipher etc BIOs ASN1 structure
- * needs.
- */
-
- sarg.out = out;
- sarg.ndef_bio = NULL;
- sarg.boundary = NULL;
-
- if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
- goto err;
-
- ndef_aux->val = val;
- ndef_aux->it = it;
- ndef_aux->ndef_bio = sarg.ndef_bio;
- ndef_aux->boundary = sarg.boundary;
- ndef_aux->out = out;
-
- BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
-
- return sarg.ndef_bio;
-
- err:
- if (asn_bio)
- BIO_free(asn_bio);
- if (ndef_aux)
- OPENSSL_free(ndef_aux);
- return NULL;
-}
-
-static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
-{
- NDEF_SUPPORT *ndef_aux;
- unsigned char *p;
- int derlen;
-
- if (!parg)
- return 0;
-
- ndef_aux = *(NDEF_SUPPORT **)parg;
-
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
- p = OPENSSL_malloc(derlen);
- if (p == NULL)
- return 0;
-
- ndef_aux->derbuf = p;
- *pbuf = p;
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
-
- if (!*ndef_aux->boundary)
- return 0;
-
- *plen = *ndef_aux->boundary - *pbuf;
-
- return 1;
-}
-
-static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
- void *parg)
-{
- NDEF_SUPPORT *ndef_aux;
-
- if (!parg)
- return 0;
-
- ndef_aux = *(NDEF_SUPPORT **)parg;
-
- if (ndef_aux->derbuf)
- OPENSSL_free(ndef_aux->derbuf);
-
- ndef_aux->derbuf = NULL;
- *pbuf = NULL;
- *plen = 0;
- return 1;
-}
-
-static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
- void *parg)
-{
- NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
- if (!ndef_prefix_free(b, pbuf, plen, parg))
- return 0;
- OPENSSL_free(*pndef_aux);
- *pndef_aux = NULL;
- return 1;
-}
-
-static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
-{
- NDEF_SUPPORT *ndef_aux;
- unsigned char *p;
- int derlen;
- const ASN1_AUX *aux;
- ASN1_STREAM_ARG sarg;
-
- if (!parg)
- return 0;
-
- ndef_aux = *(NDEF_SUPPORT **)parg;
-
- aux = ndef_aux->it->funcs;
-
- /* Finalize structures */
- sarg.ndef_bio = ndef_aux->ndef_bio;
- sarg.out = ndef_aux->out;
- sarg.boundary = ndef_aux->boundary;
- if (aux->asn1_cb(ASN1_OP_STREAM_POST,
- &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
- return 0;
-
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
- p = OPENSSL_malloc(derlen);
- if (p == NULL)
- return 0;
-
- ndef_aux->derbuf = p;
- *pbuf = p;
- derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
-
- if (!*ndef_aux->boundary)
- return 0;
- *pbuf = *ndef_aux->boundary;
- *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
-
- return 1;
-}
diff --git a/crypto/asn1/t_pkey.c b/crypto/asn1/t_pkey.c
deleted file mode 100644
index 2c420894..00000000
--- a/crypto/asn1/t_pkey.c
+++ /dev/null
@@ -1,110 +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/bio.h>
-#include <openssl/mem.h>
-
-int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
- unsigned char *buf, int off)
-{
- int n, i;
- const char *neg;
-
- if (num == NULL)
- return (1);
- neg = (BN_is_negative(num)) ? "-" : "";
- if (!BIO_indent(bp, off, 128))
- return 0;
- if (BN_is_zero(num)) {
- if (BIO_printf(bp, "%s 0\n", number) <= 0)
- return 0;
- return 1;
- }
-
- if (BN_num_bytes(num) <= sizeof(long)) {
- if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg,
- (unsigned long)num->d[0], neg,
- (unsigned long)num->d[0])
- <= 0)
- return (0);
- } else {
- buf[0] = 0;
- if (BIO_printf(bp, "%s%s", number,
- (neg[0] == '-') ? " (Negative)" : "") <= 0)
- return (0);
- n = BN_bn2bin(num, &buf[1]);
-
- if (buf[1] & 0x80)
- n++;
- else
- buf++;
-
- for (i = 0; i < n; i++) {
- if ((i % 15) == 0) {
- if (BIO_puts(bp, "\n") <= 0 || !BIO_indent(bp, off + 4, 128))
- return 0;
- }
- if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":")
- <= 0)
- return (0);
- }
- if (BIO_write(bp, "\n", 1) <= 0)
- return (0);
- }
- return (1);
-}
diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c
index fd07fa24..616b587c 100644
--- a/crypto/asn1/tasn_dec.c
+++ b/crypto/asn1/tasn_dec.c
@@ -706,13 +706,12 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
const unsigned char **in, long inlen,
const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
int ret = 0, utype;
long plen;
char cst, inf, free_cont = 0;
const unsigned char *p;
- BUF_MEM buf;
+ BUF_MEM buf = {0, NULL, 0 };
const unsigned char *cont = NULL;
long len;
if (!pval) {
@@ -786,7 +785,6 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
} else {
len = p - cont + plen;
p += plen;
- buf.data = NULL;
}
} else if (cst) {
if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
@@ -797,9 +795,8 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
return 0;
}
- buf.length = 0;
- buf.max = 0;
- buf.data = NULL;
+ /* Free any returned 'buf' content */
+ free_cont = 1;
/*
* Should really check the internal tags are correct but some things
* may get this wrong. The relevant specs say that constructed string
@@ -807,18 +804,16 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
* So instead just check for UNIVERSAL class and ignore the tag.
*/
if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) {
- free_cont = 1;
goto err;
}
len = buf.length;
/* Append a final null to string */
if (!BUF_MEM_grow_clean(&buf, len + 1)) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
buf.data[len] = 0;
cont = (const unsigned char *)buf.data;
- free_cont = 1;
} else {
cont = p;
len = plen;
@@ -826,6 +821,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
}
/* We now have content length and type: translate into a structure */
+ /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */
if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
goto err;
@@ -898,9 +894,7 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
break;
case V_ASN1_INTEGER:
- case V_ASN1_NEG_INTEGER:
case V_ASN1_ENUMERATED:
- case V_ASN1_NEG_ENUMERATED:
tint = (ASN1_INTEGER **)pval;
if (!c2i_ASN1_INTEGER(tint, &cont, len))
goto err;
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index a56d08ed..409d1388 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -609,9 +609,7 @@ int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
break;
case V_ASN1_INTEGER:
- case V_ASN1_NEG_INTEGER:
case V_ASN1_ENUMERATED:
- case V_ASN1_NEG_ENUMERATED:
/*
* These are all have the same content format as ASN1_INTEGER
*/
diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c
deleted file mode 100644
index dd20cb4d..00000000
--- a/crypto/asn1/tasn_prn.c
+++ /dev/null
@@ -1,596 +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 <time.h>
-
-#include <openssl/asn1t.h>
-#include <openssl/err.h>
-#include <openssl/obj.h>
-#include <openssl/mem.h>
-
-#include "asn1_locl.h"
-
-/*
- * Print routines.
- */
-
-/* ASN1_PCTX routines */
-
-static ASN1_PCTX default_pctx = {
- ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */
- 0, /* nm_flags */
- 0, /* cert_flags */
- 0, /* oid_flags */
- 0 /* str_flags */
-};
-
-ASN1_PCTX *ASN1_PCTX_new(void)
-{
- ASN1_PCTX *ret;
- ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- ret->flags = 0;
- ret->nm_flags = 0;
- ret->cert_flags = 0;
- ret->oid_flags = 0;
- ret->str_flags = 0;
- return ret;
-}
-
-void ASN1_PCTX_free(ASN1_PCTX *p)
-{
- OPENSSL_free(p);
-}
-
-unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
-{
- return p->flags;
-}
-
-void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
-{
- p->flags = flags;
-}
-
-unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
-{
- return p->nm_flags;
-}
-
-void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
-{
- p->nm_flags = flags;
-}
-
-unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
-{
- return p->cert_flags;
-}
-
-void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
-{
- p->cert_flags = flags;
-}
-
-unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
-{
- return p->oid_flags;
-}
-
-void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
-{
- p->oid_flags = flags;
-}
-
-unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
-{
- return p->str_flags;
-}
-
-void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
-{
- p->str_flags = flags;
-}
-
-/* Main print routines */
-
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_ITEM *it,
- const char *fname, const char *sname,
- int nohdr, const ASN1_PCTX *pctx);
-
-int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
-
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
- const ASN1_ITEM *it, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx);
-
-static int asn1_print_fsname(BIO *out, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx);
-
-int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
- const ASN1_ITEM *it, const ASN1_PCTX *pctx)
-{
- const char *sname;
- if (pctx == NULL)
- pctx = &default_pctx;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
- sname = NULL;
- else
- sname = it->sname;
- return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx);
-}
-
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_ITEM *it,
- const char *fname, const char *sname,
- int nohdr, const ASN1_PCTX *pctx)
-{
- const ASN1_TEMPLATE *tt;
- const ASN1_EXTERN_FUNCS *ef;
- ASN1_VALUE **tmpfld;
- const ASN1_AUX *aux = it->funcs;
- ASN1_aux_cb *asn1_cb;
- ASN1_PRINT_ARG parg;
- int i;
- if (aux && aux->asn1_cb) {
- parg.out = out;
- parg.indent = indent;
- parg.pctx = pctx;
- asn1_cb = aux->asn1_cb;
- } else
- asn1_cb = 0;
-
- if (*fld == NULL) {
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
- if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
- if (BIO_puts(out, "<ABSENT>\n") <= 0)
- return 0;
- }
- return 1;
- }
-
- switch (it->itype) {
- case ASN1_ITYPE_PRIMITIVE:
- if (it->templates) {
- if (!asn1_template_print_ctx(out, fld, indent,
- it->templates, pctx))
- return 0;
- break;
- }
- /* fall thru */
- case ASN1_ITYPE_MSTRING:
- if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx))
- return 0;
- break;
-
- case ASN1_ITYPE_EXTERN:
- if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
- /* Use new style print routine if possible */
- ef = it->funcs;
- if (ef && ef->asn1_ex_print) {
- i = ef->asn1_ex_print(out, fld, indent, "", pctx);
- if (!i)
- return 0;
- if ((i == 2) && (BIO_puts(out, "\n") <= 0))
- return 0;
- return 1;
- } else if (sname &&
- BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
- return 0;
- break;
-
- case ASN1_ITYPE_CHOICE:
-#if 0
- if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
-#endif
- /* CHOICE type, get selector */
- i = asn1_get_choice_selector(fld, it);
- /* This should never happen... */
- if ((i < 0) || (i >= it->tcount)) {
- if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0)
- return 0;
- return 1;
- }
- tt = it->templates + i;
- tmpfld = asn1_get_field_ptr(fld, tt);
- if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
- return 0;
- break;
-
- case ASN1_ITYPE_SEQUENCE:
- case ASN1_ITYPE_NDEF_SEQUENCE:
- if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
- if (fname || sname) {
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
- if (BIO_puts(out, " {\n") <= 0)
- return 0;
- } else {
- if (BIO_puts(out, "\n") <= 0)
- return 0;
- }
- }
-
- if (asn1_cb) {
- i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
- if (i == 0)
- return 0;
- if (i == 2)
- return 1;
- }
-
- /* Print each field entry */
- for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
- const ASN1_TEMPLATE *seqtt;
- seqtt = asn1_do_adb(fld, tt, 1);
- if (!seqtt)
- return 0;
- tmpfld = asn1_get_field_ptr(fld, seqtt);
- if (!asn1_template_print_ctx(out, tmpfld,
- indent + 2, seqtt, pctx))
- return 0;
- }
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
- if (BIO_printf(out, "%*s}\n", indent, "") < 0)
- return 0;
- }
-
- if (asn1_cb) {
- i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
- if (i == 0)
- return 0;
- }
- break;
-
- default:
- BIO_printf(out, "Unprocessed type %d\n", it->itype);
- return 0;
- }
-
- return 1;
-}
-
-int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
- const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
-{
- int flags;
- size_t i;
- const char *sname, *fname;
- flags = tt->flags;
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
- sname = ASN1_ITEM_ptr(tt->item)->sname;
- else
- sname = NULL;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
- fname = NULL;
- else
- fname = tt->field_name;
- if (flags & ASN1_TFLG_SK_MASK) {
- const char *tname;
- ASN1_VALUE *skitem;
- STACK_OF(ASN1_VALUE) *stack;
-
- /* SET OF, SEQUENCE OF */
- if (fname) {
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
- if (flags & ASN1_TFLG_SET_OF)
- tname = "SET";
- else
- tname = "SEQUENCE";
- if (BIO_printf(out, "%*s%s OF %s {\n",
- indent, "", tname, tt->field_name) <= 0)
- return 0;
- } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0)
- return 0;
- }
- stack = (STACK_OF(ASN1_VALUE) *)*fld;
- for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
- if ((i > 0) && (BIO_puts(out, "\n") <= 0))
- return 0;
-
- skitem = sk_ASN1_VALUE_value(stack, i);
- if (!asn1_item_print_ctx(out, &skitem, indent + 2,
- ASN1_ITEM_ptr(tt->item), NULL, NULL, 1,
- pctx))
- return 0;
- }
- if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
- return 0;
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
- if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
- return 0;
- }
- return 1;
- }
- return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
- fname, sname, 0, pctx);
-}
-
-static int asn1_print_fsname(BIO *out, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx)
-{
- static char spaces[] = " ";
- const int nspaces = sizeof(spaces) - 1;
-
-#if 0
- if (!sname && !fname)
- return 1;
-#endif
-
- while (indent > nspaces) {
- if (BIO_write(out, spaces, nspaces) != nspaces)
- return 0;
- indent -= nspaces;
- }
- if (BIO_write(out, spaces, indent) != indent)
- return 0;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
- sname = NULL;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
- fname = NULL;
- if (!sname && !fname)
- return 1;
- if (fname) {
- if (BIO_puts(out, fname) <= 0)
- return 0;
- }
- if (sname) {
- if (fname) {
- if (BIO_printf(out, " (%s)", sname) <= 0)
- return 0;
- } else {
- if (BIO_puts(out, sname) <= 0)
- return 0;
- }
- }
- if (BIO_write(out, ": ", 2) != 2)
- return 0;
- return 1;
-}
-
-static int asn1_print_boolean_ctx(BIO *out, int boolval,
- const ASN1_PCTX *pctx)
-{
- const char *str;
- switch (boolval) {
- case -1:
- str = "BOOL ABSENT";
- break;
-
- case 0:
- str = "FALSE";
- break;
-
- default:
- str = "TRUE";
- break;
-
- }
-
- if (BIO_puts(out, str) <= 0)
- return 0;
- return 1;
-
-}
-
-static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
- const ASN1_PCTX *pctx)
-{
- BIGNUM *bn = NULL;
- char *s = NULL;
- int ret = 1;
-
- bn = ASN1_INTEGER_to_BN(str, NULL);
- if (bn == NULL) {
- return 0;
- }
- s = BN_bn2dec(bn);
- BN_free(bn);
- if (s == NULL) {
- return 0;
- }
-
- if (BIO_puts(out, s) <= 0) {
- ret = 0;
- }
- OPENSSL_free(s);
- return ret;
-}
-
-static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
- const ASN1_PCTX *pctx)
-{
- char objbuf[80];
- const char *ln;
- ln = OBJ_nid2ln(OBJ_obj2nid(oid));
- if (!ln)
- ln = "";
- OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
- if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
- return 0;
- return 1;
-}
-
-static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
- const ASN1_PCTX *pctx)
-{
- if (str->type == V_ASN1_BIT_STRING) {
- if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0)
- return 0;
- } else if (BIO_puts(out, "\n") <= 0)
- return 0;
- if (str->length > 0
- && !BIO_hexdump(out, str->data, str->length, indent + 2)) {
- return 0;
- }
- return 1;
-}
-
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
- const ASN1_ITEM *it, int indent,
- const char *fname, const char *sname,
- const ASN1_PCTX *pctx)
-{
- long utype;
- ASN1_STRING *str;
- int ret = 1, needlf = 1;
- const char *pname;
- const ASN1_PRIMITIVE_FUNCS *pf;
- pf = it->funcs;
- if (!asn1_print_fsname(out, indent, fname, sname, pctx))
- return 0;
- if (pf && pf->prim_print)
- return pf->prim_print(out, fld, it, indent, pctx);
- str = (ASN1_STRING *)*fld;
- if (it->itype == ASN1_ITYPE_MSTRING)
- utype = str->type & ~V_ASN1_NEG;
- else
- utype = it->utype;
- if (utype == V_ASN1_ANY) {
- ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
- utype = atype->type;
- fld = &atype->value.asn1_value;
- str = (ASN1_STRING *)*fld;
- if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
- pname = NULL;
- else
- pname = ASN1_tag2str(utype);
- } else {
- if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
- pname = ASN1_tag2str(utype);
- else
- pname = NULL;
- }
-
- if (utype == V_ASN1_NULL) {
- if (BIO_puts(out, "NULL\n") <= 0)
- return 0;
- return 1;
- }
-
- if (pname) {
- if (BIO_puts(out, pname) <= 0)
- return 0;
- if (BIO_puts(out, ":") <= 0)
- return 0;
- }
-
- switch (utype) {
- case V_ASN1_BOOLEAN:
- {
- int boolval = *(int *)fld;
- if (boolval == -1)
- boolval = it->size;
- ret = asn1_print_boolean_ctx(out, boolval, pctx);
- }
- break;
-
- case V_ASN1_INTEGER:
- case V_ASN1_ENUMERATED:
- ret = asn1_print_integer_ctx(out, str, pctx);
- break;
-
- case V_ASN1_UTCTIME:
- ret = ASN1_UTCTIME_print(out, str);
- break;
-
- case V_ASN1_GENERALIZEDTIME:
- ret = ASN1_GENERALIZEDTIME_print(out, str);
- break;
-
- case V_ASN1_OBJECT:
- ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
- break;
-
- case V_ASN1_OCTET_STRING:
- case V_ASN1_BIT_STRING:
- ret = asn1_print_obstring_ctx(out, str, indent, pctx);
- needlf = 0;
- break;
-
- case V_ASN1_SEQUENCE:
- case V_ASN1_SET:
- case V_ASN1_OTHER:
- if (BIO_puts(out, "\n") <= 0)
- return 0;
- if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0)
- ret = 0;
- needlf = 0;
- break;
-
- default:
- ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
-
- }
- if (!ret)
- return 0;
- if (needlf && BIO_puts(out, "\n") <= 0)
- return 0;
- return 1;
-}
diff --git a/crypto/base64/base64.c b/crypto/base64/base64.c
index 4822fb89..0763a3e4 100644
--- a/crypto/base64/base64.c
+++ b/crypto/base64/base64.c
@@ -60,118 +60,119 @@
#include <limits.h>
#include <string.h>
+#include <openssl/type_check.h>
+
+
+/* Encoding. */
static const unsigned char data_bin2ascii[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f])
-/* 64 char lines
- * pad input with 0
- * left over chars are set to =
- * 1 byte => xx==
- * 2 bytes => xxx=
- * 3 bytes => xxxx
- */
-#define BIN_PER_LINE (64/4*3)
-#define CHUNKS_PER_LINE (64/4)
-#define CHAR_PER_LINE (64+1)
-
-/* 0xF0 is a EOLN
- * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
- * 0xF2 is EOF
- * 0xE0 is ignore at start of line.
- * 0xFF is error */
-
-#define B64_EOLN 0xF0
-#define B64_CR 0xF1
-#define B64_EOF 0xF2
-#define B64_WS 0xE0
-#define B64_ERROR 0xFF
-#define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3)
-
-static const uint8_t data_ascii2bin[128] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF,
- 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
- 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
- 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
+OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0,
+ data_length_must_be_multiple_of_base64_chunk_size);
-static uint8_t conv_ascii2bin(uint8_t a) {
- if (a >= 128) {
- return 0xFF;
+int EVP_EncodedLength(size_t *out_len, size_t len) {
+ if (len + 2 < len) {
+ return 0;
+ }
+ len += 2;
+ len /= 3;
+
+ if (((len << 2) >> 2) != len) {
+ return 0;
+ }
+ len <<= 2;
+
+ if (len + 1 < len) {
+ return 0;
}
- return data_ascii2bin[a];
+ len++;
+
+ *out_len = len;
+ return 1;
}
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
- ctx->length = 48;
- ctx->num = 0;
- ctx->line_num = 0;
+ memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
}
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, size_t in_len) {
- unsigned i, j;
- unsigned total = 0;
+ size_t total = 0;
*out_len = 0;
if (in_len == 0) {
return;
}
- assert(ctx->length <= sizeof(ctx->enc_data));
+ assert(ctx->data_used < sizeof(ctx->data));
- if (ctx->num + in_len < ctx->length) {
- memcpy(&ctx->enc_data[ctx->num], in, in_len);
- ctx->num += in_len;
+ if (sizeof(ctx->data) - ctx->data_used > in_len) {
+ memcpy(&ctx->data[ctx->data_used], in, in_len);
+ ctx->data_used += in_len;
return;
}
- if (ctx->num != 0) {
- i = ctx->length - ctx->num;
- memcpy(&ctx->enc_data[ctx->num], in, i);
- in += i;
- in_len -= i;
- j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
- ctx->num = 0;
- out += j;
+
+ if (ctx->data_used != 0) {
+ const size_t todo = sizeof(ctx->data) - ctx->data_used;
+ memcpy(&ctx->data[ctx->data_used], in, todo);
+ in += todo;
+ in_len -= todo;
+
+ size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data));
+ ctx->data_used = 0;
+
+ out += encoded;
*(out++) = '\n';
*out = '\0';
- total = j + 1;
+
+ total = encoded + 1;
}
- while (in_len >= ctx->length) {
- j = EVP_EncodeBlock(out, in, ctx->length);
- in += ctx->length;
- in_len -= ctx->length;
- out += j;
+
+ while (in_len >= sizeof(ctx->data)) {
+ size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data));
+ in += sizeof(ctx->data);
+ in_len -= sizeof(ctx->data);
+
+ out += encoded;
*(out++) = '\n';
*out = '\0';
- total += j + 1;
+
+ if (total + encoded + 1 < total) {
+ *out_len = 0;
+ return;
+ }
+
+ total += encoded + 1;
}
+
if (in_len != 0) {
- memcpy(&ctx->enc_data[0], in, in_len);
+ memcpy(ctx->data, in, in_len);
+ }
+
+ ctx->data_used = in_len;
+
+ if (total > INT_MAX) {
+ /* We cannot signal an error, but we can at least avoid making *out_len
+ * negative. */
+ total = 0;
}
- ctx->num = in_len;
*out_len = total;
}
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
- unsigned ret = 0;
-
- if (ctx->num != 0) {
- ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
- out[ret++] = '\n';
- out[ret] = '\0';
- ctx->num = 0;
+ if (ctx->data_used == 0) {
+ *out_len = 0;
+ return;
}
- *out_len = ret;
+
+ size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used);
+ out[encoded++] = '\n';
+ out[encoded] = '\0';
+ ctx->data_used = 0;
+ *out_len = encoded;
}
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
@@ -206,246 +207,223 @@ size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
return ret;
}
+
+/* Decoding. */
+
int EVP_DecodedLength(size_t *out_len, size_t len) {
if (len % 4 != 0) {
return 0;
}
+
*out_len = (len / 4) * 3;
return 1;
}
-int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
- const uint8_t *in, size_t in_len) {
- uint8_t a, b, c, d;
- size_t pad_len = 0, len = 0, max_len, i;
- uint32_t l;
+void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
+ memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
+}
+
+/* kBase64ASCIIToBinData maps characters (c < 128) to their base64 value, or
+ * else 0xff if they are invalid. As a special case, the padding character
+ * ('=') is mapped to zero. */
+static const uint8_t kBase64ASCIIToBinData[128] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
+ 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+static uint8_t base64_ascii_to_bin(uint8_t a) {
+ if (a >= 128) {
+ return 0xFF;
+ }
+
+ return kBase64ASCIIToBinData[a];
+}
- if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) {
+/* base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
+ * data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
+ * number of bytes written, which will be less than three if the quad ended
+ * with padding. It returns one on success or zero on error. */
+static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
+ const uint8_t *in) {
+ const uint8_t a = base64_ascii_to_bin(in[0]);
+ const uint8_t b = base64_ascii_to_bin(in[1]);
+ const uint8_t c = base64_ascii_to_bin(in[2]);
+ const uint8_t d = base64_ascii_to_bin(in[3]);
+ if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) {
return 0;
}
- for (i = 0; i < in_len; i += 4) {
- a = conv_ascii2bin(*(in++));
- b = conv_ascii2bin(*(in++));
- if (i + 4 == in_len && in[1] == '=') {
- if (in[0] == '=') {
- pad_len = 2;
- } else {
- pad_len = 1;
- }
- }
- if (pad_len < 2) {
- c = conv_ascii2bin(*(in++));
- } else {
- c = 0;
- }
- if (pad_len < 1) {
- d = conv_ascii2bin(*(in++));
- } else {
- d = 0;
- }
- if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) {
+ const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 |
+ ((uint32_t)c) << 6 | (uint32_t)d;
+
+ const unsigned padding_pattern = (in[0] == '=') << 3 |
+ (in[1] == '=') << 2 |
+ (in[2] == '=') << 1 |
+ (in[3] == '=');
+
+ switch (padding_pattern) {
+ case 0:
+ /* The common case of no padding. */
+ *out_num_bytes = 3;
+ out[0] = v >> 16;
+ out[1] = v >> 8;
+ out[2] = v;
+ break;
+
+ case 1: /* xxx= */
+ *out_num_bytes = 2;
+ out[0] = v >> 16;
+ out[1] = v >> 8;
+ break;
+
+ case 3: /* xx== */
+ *out_num_bytes = 1;
+ out[0] = v >> 16;
+ break;
+
+ default:
return 0;
- }
- l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) |
- (((uint32_t)c) << 6L) | (((uint32_t)d)));
- *(out++) = (uint8_t)(l >> 16L) & 0xff;
- if (pad_len < 2) {
- *(out++) = (uint8_t)(l >> 8L) & 0xff;
- }
- if (pad_len < 1) {
- *(out++) = (uint8_t)(l) & 0xff;
- }
- len += 3 - pad_len;
}
- *out_len = len;
- return 1;
-}
-void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
- ctx->length = 30;
- ctx->num = 0;
- ctx->line_num = 0;
- ctx->expect_nl = 0;
+ return 1;
}
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, size_t in_len) {
- int seof = -1, eof = 0, rv = -1, v, tmp, exp_nl;
- uint8_t *d;
- unsigned i, n, ln, ret = 0;
-
- n = ctx->num;
- d = ctx->enc_data;
- ln = ctx->line_num;
- exp_nl = ctx->expect_nl;
-
- /* last line of input. */
- if (in_len == 0 || (n == 0 && conv_ascii2bin(in[0]) == B64_EOF)) {
- rv = 0;
- goto end;
+ *out_len = 0;
+
+ if (ctx->error_encountered) {
+ return -1;
}
- /* We parse the input data */
+ size_t bytes_out = 0, i;
for (i = 0; i < in_len; i++) {
- /* If the current line is > 80 characters, scream alot */
- if (ln >= 80) {
- rv = -1;
- goto end;
+ const char c = in[i];
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ continue;
}
- /* Get char and put it into the buffer */
- tmp = *(in++);
- v = conv_ascii2bin(tmp);
- /* only save the good data :-) */
- if (!B64_NOT_BASE64(v)) {
- assert(n < sizeof(ctx->enc_data));
- d[n++] = tmp;
- ln++;
- } else if (v == B64_ERROR) {
- rv = -1;
- goto end;
+ if (base64_ascii_to_bin(c) == 0xff || ctx->eof_seen) {
+ ctx->error_encountered = 1;
+ return -1;
}
- /* have we seen a '=' which is 'definitly' the last
- * input line. seof will point to the character that
- * holds it. and eof will hold how many characters to
- * chop off. */
- if (tmp == '=') {
- if (seof == -1) {
- seof = n;
- }
- eof++;
- if (eof > 2) {
- /* There are, at most, two equals signs at the end of base64 data. */
- rv = -1;
- goto end;
+ ctx->data[ctx->data_used++] = c;
+ if (ctx->data_used == 4) {
+ size_t num_bytes_resulting;
+ if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) {
+ ctx->error_encountered = 1;
+ return -1;
}
- }
- if (v == B64_CR) {
- ln = 0;
- if (exp_nl) {
- continue;
- }
- }
+ ctx->data_used = 0;
+ bytes_out += num_bytes_resulting;
+ out += num_bytes_resulting;
- /* eoln */
- if (v == B64_EOLN) {
- ln = 0;
- if (exp_nl) {
- exp_nl = 0;
- continue;
- }
- }
- exp_nl = 0;
-
- /* If we are at the end of input and it looks like a
- * line, process it. */
- if ((i + 1) == in_len && (((n & 3) == 0) || eof)) {
- v = B64_EOF;
- /* In case things were given us in really small
- records (so two '=' were given in separate
- updates), eof may contain the incorrect number
- of ending bytes to skip, so let's redo the count */
- eof = 0;
- if (d[n - 1] == '=') {
- eof++;
+ if (num_bytes_resulting < 3) {
+ ctx->eof_seen = 1;
}
- if (d[n - 2] == '=') {
- eof++;
- }
- /* There will never be more than two '=' */
}
+ }
- if ((v == B64_EOF && (n & 3) == 0) || n >= 64) {
- /* This is needed to work correctly on 64 byte input
- * lines. We process the line and then need to
- * accept the '\n' */
- if (v != B64_EOF && n >= 64) {
- exp_nl = 1;
- }
- if (n > 0) {
- /* TODO(davidben): Switch this to EVP_DecodeBase64. */
- v = EVP_DecodeBlock(out, d, n);
- n = 0;
- if (v < 0) {
- rv = 0;
- goto end;
- }
- if (eof > v) {
- rv = -1;
- goto end;
- }
- ret += (v - eof);
- } else {
- eof = 1;
- v = 0;
- }
+ if (bytes_out > INT_MAX) {
+ ctx->error_encountered = 1;
+ *out_len = 0;
+ return -1;
+ }
+ *out_len = bytes_out;
- /* This is the case where we have had a short
- * but valid input line */
- if (v < (int)ctx->length && eof) {
- rv = 0;
- goto end;
- } else {
- ctx->length = v;
- }
+ if (ctx->eof_seen) {
+ return 0;
+ }
- if (seof >= 0) {
- rv = 0;
- goto end;
- }
- out += v;
- }
+ return 1;
+}
+
+int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
+ *out_len = 0;
+ if (ctx->error_encountered || ctx->data_used != 0) {
+ return -1;
}
- rv = 1;
-
-end:
- *out_len = ret;
- ctx->num = n;
- ctx->line_num = ln;
- ctx->expect_nl = exp_nl;
- return rv;
+
+ return 1;
}
-int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) {
- int i;
+int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
+ const uint8_t *in, size_t in_len) {
+ *out_len = 0;
- *outl = 0;
- if (ctx->num != 0) {
- /* TODO(davidben): Switch this to EVP_DecodeBase64. */
- i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
- if (i < 0) {
- return -1;
+ if (in_len % 4 != 0) {
+ return 0;
+ }
+
+ size_t max_len;
+ if (!EVP_DecodedLength(&max_len, in_len) ||
+ max_out < max_len) {
+ return 0;
+ }
+
+ size_t i, bytes_out = 0;
+ for (i = 0; i < in_len; i += 4) {
+ size_t num_bytes_resulting;
+
+ if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) {
+ return 0;
+ }
+
+ bytes_out += num_bytes_resulting;
+ out += num_bytes_resulting;
+ if (num_bytes_resulting != 3 && i != in_len - 4) {
+ return 0;
}
- ctx->num = 0;
- *outl = i;
- return 1;
- } else {
- return 1;
}
+
+ *out_len = bytes_out;
+ return 1;
}
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
- size_t dst_len;
+ /* Trim spaces and tabs from the beginning of the input. */
+ while (src_len > 0) {
+ if (src[0] != ' ' && src[0] != '\t') {
+ break;
+ }
- /* trim white space from the start of the line. */
- while (conv_ascii2bin(*src) == B64_WS && src_len > 0) {
src++;
src_len--;
}
- /* strip off stuff at the end of the line
- * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
- while (src_len > 3 && B64_NOT_BASE64(conv_ascii2bin(src[src_len - 1]))) {
- src_len--;
- }
+ /* Trim newlines, spaces and tabs from the end of the line. */
+ while (src_len > 0) {
+ switch (src[src_len-1]) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ src_len--;
+ continue;
+ }
- if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) {
- return -1;
+ break;
}
- if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
+
+ size_t dst_len;
+ if (!EVP_DecodedLength(&dst_len, src_len) ||
+ dst_len > INT_MAX ||
+ !EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
return -1;
}
@@ -458,21 +436,3 @@ int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
return dst_len;
}
-
-int EVP_EncodedLength(size_t *out_len, size_t len) {
- if (len + 2 < len) {
- return 0;
- }
- len += 2;
- len /= 3;
- if (((len << 2) >> 2) != len) {
- return 0;
- }
- len <<= 2;
- if (len + 1 < len) {
- return 0;
- }
- len++;
- *out_len = len;
- return 1;
-}
diff --git a/crypto/base64/base64_test.cc b/crypto/base64/base64_test.cc
index da016e66..a6087732 100644
--- a/crypto/base64/base64_test.cc
+++ b/crypto/base64/base64_test.cc
@@ -15,76 +15,203 @@
#include <stdio.h>
#include <string.h>
+#include <string>
+#include <vector>
+
#include <openssl/base64.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
+enum encoding_relation {
+ // canonical indicates that the encoding is the expected encoding of the
+ // input.
+ canonical,
+ // valid indicates that the encoding is /a/ valid encoding of the input, but
+ // need not be the canonical one.
+ valid,
+ // invalid indicates that the encoded data is valid.
+ invalid,
+};
+
struct TestVector {
+ enum encoding_relation relation;
const char *decoded;
const char *encoded;
};
// Test vectors from RFC 4648.
static const TestVector kTestVectors[] = {
- { "", "" },
- { "f" , "Zg==" },
- { "fo", "Zm8=" },
- { "foo", "Zm9v" },
- { "foob", "Zm9vYg==" },
- { "fooba", "Zm9vYmE=" },
- { "foobar", "Zm9vYmFy" },
+ {canonical, "", ""},
+ {canonical, "f", "Zg==\n"},
+ {canonical, "fo", "Zm8=\n"},
+ {canonical, "foo", "Zm9v\n"},
+ {canonical, "foob", "Zm9vYg==\n"},
+ {canonical, "fooba", "Zm9vYmE=\n"},
+ {canonical, "foobar", "Zm9vYmFy\n"},
+ {valid, "foobar", "Zm9vYmFy\n\n"},
+ {valid, "foobar", " Zm9vYmFy\n\n"},
+ {valid, "foobar", " Z m 9 v Y m F y\n\n"},
+ {invalid, "", "Zm9vYmFy=\n"},
+ {invalid, "", "Zm9vYmFy==\n"},
+ {invalid, "", "Zm9vYmFy===\n"},
+ {invalid, "", "Z"},
+ {invalid, "", "Z\n"},
+ {invalid, "", "ab!c"},
+ {invalid, "", "ab=c"},
+ {invalid, "", "abc"},
+
+ {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n"},
+ {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n"},
+ {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n"},
+ {invalid, "",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n==\n"},
+ {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
+ "4eHh4eHh4\n"},
+ {canonical,
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
+ "4eHh4eHh4eHh4eA==\n"},
+ {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh"
+ "4eHh4eHh4eHh4eA==\n"},
+ {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e"
+ "Hh4eHh4eHh4eA==\n"},
+ {invalid, "",
+ "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=="
+ "\neHh4eHh4eHh4eHh4eHh4eHh4\n"},
+
+ // A '-' has traditionally been treated as the end of the data by OpenSSL
+ // and anything following would be ignored. BoringSSL does not accept this
+ // non-standard extension.
+ {invalid, "", "Zm9vYmFy-anythinggoes"},
+ {invalid, "", "Zm9vYmFy\n-anythinggoes"},
+
+ // CVE-2015-0292
+ {invalid, "",
+ "ZW5jb2RlIG1lCg==========================================================="
+ "=======\n"},
};
static const size_t kNumTests = sizeof(kTestVectors) / sizeof(kTestVectors[0]);
-static bool TestEncode() {
- for (size_t i = 0; i < kNumTests; i++) {
+// RemoveNewlines returns a copy of |in| with all '\n' characters removed.
+static std::string RemoveNewlines(const char *in) {
+ std::string ret;
+ const size_t in_len = strlen(in);
+
+ size_t i;
+ for (i = 0; i < in_len; i++) {
+ if (in[i] != '\n') {
+ ret.push_back(in[i]);
+ }
+ }
+
+ return ret;
+}
+
+static bool TestEncodeBlock() {
+ for (unsigned i = 0; i < kNumTests; i++) {
const TestVector *t = &kTestVectors[i];
- uint8_t out[9];
- size_t len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded,
- strlen(t->decoded));
- if (len != strlen(t->encoded) ||
- memcmp(out, t->encoded, len) != 0) {
+ if (t->relation != canonical) {
+ continue;
+ }
+
+ const size_t decoded_len = strlen(t->decoded);
+ size_t max_encoded_len;
+ if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
+ fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i);
+ return false;
+ }
+
+ std::vector<uint8_t> out_vec(max_encoded_len);
+ uint8_t *out = out_vec.data();
+ size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len);
+
+ std::string encoded(RemoveNewlines(t->encoded));
+ if (len != encoded.size() ||
+ memcmp(out, encoded.data(), len) != 0) {
fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
- t->decoded, (int)len, (const char*)out, t->encoded);
+ t->decoded, (int)len, (const char*)out, encoded.c_str());
return false;
}
}
+
return true;
}
-static bool TestDecode() {
- uint8_t out[6];
+static bool TestDecodeBase64() {
size_t len;
- for (size_t i = 0; i < kNumTests; i++) {
- // Test the normal API.
+ for (unsigned i = 0; i < kNumTests; i++) {
const TestVector *t = &kTestVectors[i];
- size_t expected_len = strlen(t->decoded);
- if (!EVP_DecodeBase64(out, &len, sizeof(out),
- (const uint8_t*)t->encoded, strlen(t->encoded))) {
- fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
- return false;
+
+ if (t->relation == valid) {
+ // The non-canonical encodings will generally have odd whitespace etc
+ // that |EVP_DecodeBase64| will reject.
+ continue;
}
- if (len != strlen(t->decoded) ||
- memcmp(out, t->decoded, len) != 0) {
- fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
- t->encoded, (int)len, (const char*)out, t->decoded);
- return false;
+
+ const std::string encoded(RemoveNewlines(t->encoded));
+ std::vector<uint8_t> out_vec(encoded.size());
+ uint8_t *out = out_vec.data();
+
+ int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
+ (const uint8_t *)encoded.data(), encoded.size());
+
+ if (t->relation == invalid) {
+ if (ok) {
+ fprintf(stderr, "decode(\"%s\") didn't fail but should have\n",
+ encoded.c_str());
+ return false;
+ }
+ } else if (t->relation == canonical) {
+ if (!ok) {
+ fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str());
+ return false;
+ }
+
+ if (len != strlen(t->decoded) ||
+ memcmp(out, t->decoded, len) != 0) {
+ fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
+ encoded.c_str(), (int)len, (const char*)out, t->decoded);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool TestDecodeBlock() {
+ for (unsigned i = 0; i < kNumTests; i++) {
+ const TestVector *t = &kTestVectors[i];
+ if (t->relation != canonical) {
+ continue;
}
+ std::string encoded(RemoveNewlines(t->encoded));
+
+ std::vector<uint8_t> out_vec(encoded.size());
+ uint8_t *out = out_vec.data();
+
// Test that the padding behavior of the deprecated API is preserved.
- int ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded,
- strlen(t->encoded));
+ int ret =
+ EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
if (ret < 0) {
- fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
+ fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded);
return false;
}
if (ret % 3 != 0) {
fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
return false;
}
+ size_t expected_len = strlen(t->decoded);
if (expected_len % 3 != 0) {
ret -= 3 - (expected_len % 3);
}
@@ -96,19 +223,155 @@ static bool TestDecode() {
}
}
- if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a!bc", 4)) {
- fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
- return false;
- }
+ return true;
+}
+
+static bool TestEncodeDecode() {
+ for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
+ const TestVector *t = &kTestVectors[test_num];
+
+ EVP_ENCODE_CTX ctx;
+ const size_t decoded_len = strlen(t->decoded);
+
+ if (t->relation == canonical) {
+ size_t max_encoded_len;
+ if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
+ fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num);
+ return false;
+ }
+
+ // EVP_EncodeUpdate will output new lines every 64 bytes of output so we
+ // need slightly more than |EVP_EncodedLength| returns. */
+ max_encoded_len += (max_encoded_len + 63) >> 6;
+ std::vector<uint8_t> out_vec(max_encoded_len);
+ uint8_t *out = out_vec.data();
+
+ EVP_EncodeInit(&ctx);
+
+ int out_len;
+ EVP_EncodeUpdate(&ctx, out, &out_len,
+ reinterpret_cast<const uint8_t *>(t->decoded),
+ decoded_len);
+ size_t total = out_len;
+
+ EVP_EncodeFinal(&ctx, out + total, &out_len);
+ total += out_len;
+
+ if (total != strlen(t->encoded) || memcmp(out, t->encoded, total) != 0) {
+ fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n",
+ test_num, out, static_cast<unsigned>(total));
+ return false;
+ }
+ }
+
+ std::vector<uint8_t> out_vec(strlen(t->encoded));
+ uint8_t *out = out_vec.data();
+
+ EVP_DecodeInit(&ctx);
+ int out_len;
+ size_t total = 0;
+ int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
+ reinterpret_cast<const uint8_t *>(t->encoded),
+ strlen(t->encoded));
+ if (ret != -1) {
+ total = out_len;
+ ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
+ total += out_len;
+ }
+
+ switch (t->relation) {
+ case canonical:
+ case valid:
+ if (ret == -1) {
+ fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num);
+ return false;
+ }
+ if (total != decoded_len || memcmp(out, t->decoded, decoded_len)) {
+ fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n",
+ test_num);
+ return false;
+ }
+ break;
- if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a=bc", 4)) {
- fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
- return false;
+ case invalid:
+ if (ret != -1) {
+ fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num);
+ return false;
+ }
+ break;
+ }
}
- if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"abc", 4)) {
- fprintf(stderr, "Failed to reject invalid input length.\n");
- return false;
+ return true;
+}
+
+static bool TestDecodeUpdateStreaming() {
+ for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
+ const TestVector *t = &kTestVectors[test_num];
+ if (t->relation == invalid) {
+ continue;
+ }
+
+ const size_t encoded_len = strlen(t->encoded);
+
+ std::vector<uint8_t> out(encoded_len);
+
+ for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
+ size_t out_len = 0;
+ EVP_ENCODE_CTX ctx;
+ EVP_DecodeInit(&ctx);
+
+ for (size_t i = 0; i < encoded_len;) {
+ size_t todo = encoded_len - i;
+ if (todo > chunk_size) {
+ todo = chunk_size;
+ }
+
+ int bytes_written;
+ int ret = EVP_DecodeUpdate(
+ &ctx, out.data() + out_len, &bytes_written,
+ reinterpret_cast<const uint8_t *>(t->encoded + i), todo);
+ i += todo;
+
+ switch (ret) {
+ case -1:
+ fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num);
+ return 0;
+ case 0:
+ out_len += bytes_written;
+ if (i == encoded_len ||
+ (i + 1 == encoded_len && t->encoded[i] == '\n') ||
+ /* If there was an '-' in the input (which means “EOF”) then
+ * this loop will continue to test that |EVP_DecodeUpdate| will
+ * ignore the remainder of the input. */
+ strchr(t->encoded, '-') != nullptr) {
+ break;
+ }
+
+ fprintf(stderr,
+ "#%u: EVP_DecodeUpdate returned zero before end of "
+ "encoded data\n",
+ test_num);
+ return 0;
+ default:
+ out_len += bytes_written;
+ }
+ }
+
+ int bytes_written;
+ int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
+ if (ret == -1) {
+ fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num);
+ return 0;
+ }
+ out_len += bytes_written;
+
+ if (out_len != strlen(t->decoded) ||
+ memcmp(out.data(), t->decoded, out_len) != 0) {
+ fprintf(stderr, "#%u: incorrect output\n", test_num);
+ return 0;
+ }
+ }
}
return true;
@@ -117,8 +380,11 @@ static bool TestDecode() {
int main(void) {
CRYPTO_library_init();
- if (!TestEncode() ||
- !TestDecode()) {
+ if (!TestEncodeBlock() ||
+ !TestDecodeBase64() ||
+ !TestDecodeBlock() ||
+ !TestDecodeUpdateStreaming() ||
+ !TestEncodeDecode()) {
return 1;
}
diff --git a/crypto/bio/bio_mem.c b/crypto/bio/bio_mem.c
index 6864f6f1..844fba7e 100644
--- a/crypto/bio/bio_mem.c
+++ b/crypto/bio/bio_mem.c
@@ -64,7 +64,7 @@
#include <openssl/mem.h>
-BIO *BIO_new_mem_buf(void *buf, int len) {
+BIO *BIO_new_mem_buf(const void *buf, int len) {
BIO *ret;
BUF_MEM *b;
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
@@ -80,7 +80,8 @@ BIO *BIO_new_mem_buf(void *buf, int len) {
}
b = (BUF_MEM *)ret->ptr;
- b->data = buf;
+ /* BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to. */
+ b->data = (void *)buf;
b->length = size;
b->max = size;
diff --git a/crypto/bio/bio_test.cc b/crypto/bio/bio_test.cc
index bc755c10..f2eb20ba 100644
--- a/crypto/bio/bio_test.cc
+++ b/crypto/bio/bio_test.cc
@@ -27,10 +27,10 @@
#include <unistd.h>
#else
#include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/bio.h>
@@ -331,7 +331,7 @@ static bool TestPrintf() {
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
size_t expected_len, size_t max_len) {
- ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(data), data_len));
+ ScopedBIO bio(BIO_new_mem_buf(data, data_len));
uint8_t *out;
size_t out_len;
diff --git a/crypto/bio/connect.c b/crypto/bio/connect.c
index 0b0bf131..7e544474 100644
--- a/crypto/bio/connect.c
+++ b/crypto/bio/connect.c
@@ -58,7 +58,6 @@
#include <assert.h>
#include <errno.h>
-#include <stdio.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
@@ -67,10 +66,10 @@
#include <arpa/inet.h>
#include <unistd.h>
#else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/buf.h>
@@ -539,6 +538,16 @@ int BIO_set_conn_port(BIO *bio, const char *port_str) {
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str);
}
+int BIO_set_conn_int_port(BIO *bio, const int *port) {
+ char buf[DECIMAL_SIZE(int) + 1];
+ BIO_snprintf(buf, sizeof(buf), "%d", *port);
+ return BIO_set_conn_port(bio, buf);
+}
+
int BIO_set_nbio(BIO *bio, int on) {
return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
}
+
+int BIO_do_connect(BIO *bio) {
+ return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL);
+}
diff --git a/crypto/bio/fd.c b/crypto/bio/fd.c
index 0b3484c9..13833df5 100644
--- a/crypto/bio/fd.c
+++ b/crypto/bio/fd.c
@@ -63,15 +63,17 @@
#include <unistd.h>
#else
#include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+#include "internal.h"
+
static int bio_fd_non_fatal_error(int err) {
if (
@@ -106,20 +108,25 @@ static int bio_fd_non_fatal_error(int err) {
}
#if defined(OPENSSL_WINDOWS)
-int bio_fd_should_retry(int i) {
- if (i == -1) {
- return bio_fd_non_fatal_error((int)GetLastError());
- }
- return 0;
-}
+ #define BORINGSSL_ERRNO (int)GetLastError()
+ #define BORINGSSL_CLOSE _close
+ #define BORINGSSL_LSEEK _lseek
+ #define BORINGSSL_READ _read
+ #define BORINGSSL_WRITE _write
#else
+ #define BORINGSSL_ERRNO errno
+ #define BORINGSSL_CLOSE close
+ #define BORINGSSL_LSEEK lseek
+ #define BORINGSSL_READ read
+ #define BORINGSSL_WRITE write
+#endif
+
int bio_fd_should_retry(int i) {
if (i == -1) {
- return bio_fd_non_fatal_error(errno);
+ return bio_fd_non_fatal_error(BORINGSSL_ERRNO);
}
return 0;
}
-#endif
BIO *BIO_new_fd(int fd, int close_flag) {
BIO *ret = BIO_new(BIO_s_fd());
@@ -143,7 +150,7 @@ static int fd_free(BIO *bio) {
if (bio->shutdown) {
if (bio->init) {
- close(bio->num);
+ BORINGSSL_CLOSE(bio->num);
}
bio->init = 0;
}
@@ -153,7 +160,7 @@ static int fd_free(BIO *bio) {
static int fd_read(BIO *b, char *out, int outl) {
int ret = 0;
- ret = read(b->num, out, outl);
+ ret = BORINGSSL_READ(b->num, out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
@@ -165,7 +172,7 @@ static int fd_read(BIO *b, char *out, int outl) {
}
static int fd_write(BIO *b, const char *in, int inl) {
- int ret = write(b->num, in, inl);
+ int ret = BORINGSSL_WRITE(b->num, in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
@@ -186,14 +193,14 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
case BIO_C_FILE_SEEK:
ret = 0;
if (b->init) {
- ret = (long)lseek(b->num, num, SEEK_SET);
+ ret = (long)BORINGSSL_LSEEK(b->num, num, SEEK_SET);
}
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = 0;
if (b->init) {
- ret = (long)lseek(b->num, 0, SEEK_CUR);
+ ret = (long)BORINGSSL_LSEEK(b->num, 0, SEEK_CUR);
}
break;
case BIO_C_SET_FD:
diff --git a/crypto/bio/file.c b/crypto/bio/file.c
index 9e29b43c..b903bc28 100644
--- a/crypto/bio/file.c
+++ b/crypto/bio/file.c
@@ -87,47 +87,11 @@
#define BIO_FP_WRITE 0x04
#define BIO_FP_APPEND 0x08
-static FILE *open_file(const char *filename, const char *mode) {
-#if defined(OPENSSL_WINDOWS) && defined(CP_UTF8)
- int sz, len_0 = (int)strlen(filename) + 1;
- DWORD flags;
-
- /* Basically there are three cases to cover: a) filename is pure ASCII
- * string; b) actual UTF-8 encoded string and c) locale-ized string, i.e. one
- * containing 8-bit characters that are meaningful in current system locale.
- * If filename is pure ASCII or real UTF-8 encoded string,
- * MultiByteToWideChar succeeds and _wfopen works. If filename is locale-ized
- * string, chances are that MultiByteToWideChar fails reporting
- * ERROR_NO_UNICODE_TRANSLATION, in which case we fall back to fopen... */
- if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS),
- filename, len_0, NULL, 0)) > 0 ||
- (GetLastError() == ERROR_INVALID_FLAGS &&
- (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), filename, len_0, NULL,
- 0)) > 0)) {
- WCHAR wmode[8];
- WCHAR *wfilename = _alloca(sz * sizeof(WCHAR));
-
- if (MultiByteToWideChar(CP_UTF8, flags, filename, len_0, wfilename, sz) &&
- MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, wmode,
- sizeof(wmode) / sizeof(wmode[0])) &&
- (file = _wfopen(wfilename, wmode)) == NULL &&
- (errno == ENOENT ||
- errno == EBADF)) /* UTF-8 decode succeeded, but no file, filename
- * could still have been locale-ized... */
- return fopen(filename, mode);
- } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
- return fopen(filename, mode);
- }
-#else
- return fopen(filename, mode);
-#endif
-}
-
BIO *BIO_new_file(const char *filename, const char *mode) {
BIO *ret;
FILE *file;
- file = open_file(filename, mode);
+ file = fopen(filename, mode);
if (file == NULL) {
OPENSSL_PUT_SYSTEM_ERROR();
@@ -256,7 +220,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
ret = 0;
break;
}
- fp = open_file(ptr, p);
+ fp = fopen(ptr, p);
if (fp == NULL) {
OPENSSL_PUT_SYSTEM_ERROR();
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
diff --git a/crypto/bio/internal.h b/crypto/bio/internal.h
index d9a34f18..4ec77fad 100644
--- a/crypto/bio/internal.h
+++ b/crypto/bio/internal.h
@@ -67,6 +67,9 @@ typedef unsigned short u_short;
#include <sys/types.h>
#include <sys/socket.h>
#else
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <winsock2.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
typedef int socklen_t;
#endif
diff --git a/crypto/bio/pair.c b/crypto/bio/pair.c
index fba4be2c..2da2d203 100644
--- a/crypto/bio/pair.c
+++ b/crypto/bio/pair.c
@@ -742,7 +742,7 @@ static const BIO_METHOD methods_biop = {
bio_free, NULL /* no bio_callback_ctrl */
};
-const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
+static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
BIO** bio2_p, size_t writebuf2) {
diff --git a/crypto/bio/socket.c b/crypto/bio/socket.c
index 98f32a62..0520c3e8 100644
--- a/crypto/bio/socket.c
+++ b/crypto/bio/socket.c
@@ -63,9 +63,9 @@
#if !defined(OPENSSL_WINDOWS)
#include <unistd.h>
#else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#pragma comment(lib, "Ws2_32.lib")
#endif
@@ -110,7 +110,11 @@ static int sock_read(BIO *b, char *out, int outl) {
}
bio_clear_socket_error();
+#if defined(OPENSSL_WINDOWS)
ret = recv(b->num, out, outl, 0);
+#else
+ ret = read(b->num, out, outl);
+#endif
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
@@ -124,7 +128,11 @@ static int sock_write(BIO *b, const char *in, int inl) {
int ret;
bio_clear_socket_error();
+#if defined(OPENSSL_WINDOWS)
ret = send(b->num, in, inl, 0);
+#else
+ ret = write(b->num, in, inl);
+#endif
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
diff --git a/crypto/bio/socket_helper.c b/crypto/bio/socket_helper.c
index 4ddc094d..95007884 100644
--- a/crypto/bio/socket_helper.c
+++ b/crypto/bio/socket_helper.c
@@ -26,10 +26,10 @@
#include <netdb.h>
#include <unistd.h>
#else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include "internal.h"
diff --git a/crypto/bn/asm/armv4-mont.pl b/crypto/bn/asm/armv4-mont.pl
index afcbdf62..b7511128 100644
--- a/crypto/bn/asm/armv4-mont.pl
+++ b/crypto/bn/asm/armv4-mont.pl
@@ -107,7 +107,7 @@ bn_mul_mont:
#ifdef __APPLE__
ldr r0,[r0]
#endif
- tst r0,#1 @ NEON available?
+ tst r0,#ARMV7_NEON @ NEON available?
ldmia sp, {r0,r2}
beq .Lialu
add sp,sp,#8
diff --git a/crypto/bn/asm/rsaz-avx2.pl b/crypto/bn/asm/rsaz-avx2.pl
index bbceccb3..6b57bd0b 100644..100755
--- a/crypto/bn/asm/rsaz-avx2.pl
+++ b/crypto/bn/asm/rsaz-avx2.pl
@@ -427,7 +427,7 @@ $TEMP2 = $B2;
$TEMP3 = $Y1;
$TEMP4 = $Y2;
$code.=<<___;
- #we need to fix indexes 32-39 to avoid overflow
+ # we need to fix indices 32-39 to avoid overflow
vmovdqu 32*8(%rsp), $ACC8 # 32*8-192($tp0),
vmovdqu 32*9(%rsp), $ACC1 # 32*9-192($tp0)
vmovdqu 32*10(%rsp), $ACC2 # 32*10-192($tp0)
@@ -1576,68 +1576,128 @@ rsaz_1024_scatter5_avx2:
.type rsaz_1024_gather5_avx2,\@abi-omnipotent
.align 32
rsaz_1024_gather5_avx2:
+ vzeroupper
+ mov %rsp,%r11
___
$code.=<<___ if ($win64);
lea -0x88(%rsp),%rax
- vzeroupper
.LSEH_begin_rsaz_1024_gather5:
# I can't trust assembler to use specific encoding:-(
- .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
- .byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6,-0x20(%rax)
- .byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7,-0x10(%rax)
- .byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8,0(%rax)
- .byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9,0x10(%rax)
- .byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10,0x20(%rax)
- .byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11,0x30(%rax)
- .byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12,0x40(%rax)
- .byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13,0x50(%rax)
- .byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14,0x60(%rax)
- .byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15,0x70(%rax)
+ .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax),%rsp
+ .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6,-0x20(%rax)
+ .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7,-0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8,0(%rax)
+ .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9,0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10,0x20(%rax)
+ .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11,0x30(%rax)
+ .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12,0x40(%rax)
+ .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13,0x50(%rax)
+ .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14,0x60(%rax)
+ .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15,0x70(%rax)
___
$code.=<<___;
- lea .Lgather_table(%rip),%r11
- mov $power,%eax
- and \$3,$power
- shr \$2,%eax # cache line number
- shl \$4,$power # offset within cache line
-
- vmovdqu -32(%r11),%ymm7 # .Lgather_permd
- vpbroadcastb 8(%r11,%rax), %xmm8
- vpbroadcastb 7(%r11,%rax), %xmm9
- vpbroadcastb 6(%r11,%rax), %xmm10
- vpbroadcastb 5(%r11,%rax), %xmm11
- vpbroadcastb 4(%r11,%rax), %xmm12
- vpbroadcastb 3(%r11,%rax), %xmm13
- vpbroadcastb 2(%r11,%rax), %xmm14
- vpbroadcastb 1(%r11,%rax), %xmm15
-
- lea 64($inp,$power),$inp
- mov \$64,%r11 # size optimization
- mov \$9,%eax
- jmp .Loop_gather_1024
+ lea -0x100(%rsp),%rsp
+ and \$-32, %rsp
+ lea .Linc(%rip), %r10
+ lea -128(%rsp),%rax # control u-op density
+
+ vmovd $power, %xmm4
+ vmovdqa (%r10),%ymm0
+ vmovdqa 32(%r10),%ymm1
+ vmovdqa 64(%r10),%ymm5
+ vpbroadcastd %xmm4,%ymm4
+
+ vpaddd %ymm5, %ymm0, %ymm2
+ vpcmpeqd %ymm4, %ymm0, %ymm0
+ vpaddd %ymm5, %ymm1, %ymm3
+ vpcmpeqd %ymm4, %ymm1, %ymm1
+ vmovdqa %ymm0, 32*0+128(%rax)
+ vpaddd %ymm5, %ymm2, %ymm0
+ vpcmpeqd %ymm4, %ymm2, %ymm2
+ vmovdqa %ymm1, 32*1+128(%rax)
+ vpaddd %ymm5, %ymm3, %ymm1
+ vpcmpeqd %ymm4, %ymm3, %ymm3
+ vmovdqa %ymm2, 32*2+128(%rax)
+ vpaddd %ymm5, %ymm0, %ymm2
+ vpcmpeqd %ymm4, %ymm0, %ymm0
+ vmovdqa %ymm3, 32*3+128(%rax)
+ vpaddd %ymm5, %ymm1, %ymm3
+ vpcmpeqd %ymm4, %ymm1, %ymm1
+ vmovdqa %ymm0, 32*4+128(%rax)
+ vpaddd %ymm5, %ymm2, %ymm8
+ vpcmpeqd %ymm4, %ymm2, %ymm2
+ vmovdqa %ymm1, 32*5+128(%rax)
+ vpaddd %ymm5, %ymm3, %ymm9
+ vpcmpeqd %ymm4, %ymm3, %ymm3
+ vmovdqa %ymm2, 32*6+128(%rax)
+ vpaddd %ymm5, %ymm8, %ymm10
+ vpcmpeqd %ymm4, %ymm8, %ymm8
+ vmovdqa %ymm3, 32*7+128(%rax)
+ vpaddd %ymm5, %ymm9, %ymm11
+ vpcmpeqd %ymm4, %ymm9, %ymm9
+ vpaddd %ymm5, %ymm10, %ymm12
+ vpcmpeqd %ymm4, %ymm10, %ymm10
+ vpaddd %ymm5, %ymm11, %ymm13
+ vpcmpeqd %ymm4, %ymm11, %ymm11
+ vpaddd %ymm5, %ymm12, %ymm14
+ vpcmpeqd %ymm4, %ymm12, %ymm12
+ vpaddd %ymm5, %ymm13, %ymm15
+ vpcmpeqd %ymm4, %ymm13, %ymm13
+ vpcmpeqd %ymm4, %ymm14, %ymm14
+ vpcmpeqd %ymm4, %ymm15, %ymm15
+
+ vmovdqa -32(%r10),%ymm7 # .Lgather_permd
+ lea 128($inp), $inp
+ mov \$9,$power
-.align 32
.Loop_gather_1024:
- vpand -64($inp), %xmm8,%xmm0
- vpand ($inp), %xmm9,%xmm1
- vpand 64($inp), %xmm10,%xmm2
- vpand ($inp,%r11,2), %xmm11,%xmm3
- vpor %xmm0,%xmm1,%xmm1
- vpand 64($inp,%r11,2), %xmm12,%xmm4
- vpor %xmm2,%xmm3,%xmm3
- vpand ($inp,%r11,4), %xmm13,%xmm5
- vpor %xmm1,%xmm3,%xmm3
- vpand 64($inp,%r11,4), %xmm14,%xmm6
- vpor %xmm4,%xmm5,%xmm5
- vpand -128($inp,%r11,8), %xmm15,%xmm2
- lea ($inp,%r11,8),$inp
- vpor %xmm3,%xmm5,%xmm5
- vpor %xmm2,%xmm6,%xmm6
- vpor %xmm5,%xmm6,%xmm6
- vpermd %ymm6,%ymm7,%ymm6
- vmovdqu %ymm6,($out)
+ vmovdqa 32*0-128($inp), %ymm0
+ vmovdqa 32*1-128($inp), %ymm1
+ vmovdqa 32*2-128($inp), %ymm2
+ vmovdqa 32*3-128($inp), %ymm3
+ vpand 32*0+128(%rax), %ymm0, %ymm0
+ vpand 32*1+128(%rax), %ymm1, %ymm1
+ vpand 32*2+128(%rax), %ymm2, %ymm2
+ vpor %ymm0, %ymm1, %ymm4
+ vpand 32*3+128(%rax), %ymm3, %ymm3
+ vmovdqa 32*4-128($inp), %ymm0
+ vmovdqa 32*5-128($inp), %ymm1
+ vpor %ymm2, %ymm3, %ymm5
+ vmovdqa 32*6-128($inp), %ymm2
+ vmovdqa 32*7-128($inp), %ymm3
+ vpand 32*4+128(%rax), %ymm0, %ymm0
+ vpand 32*5+128(%rax), %ymm1, %ymm1
+ vpand 32*6+128(%rax), %ymm2, %ymm2
+ vpor %ymm0, %ymm4, %ymm4
+ vpand 32*7+128(%rax), %ymm3, %ymm3
+ vpand 32*8-128($inp), %ymm8, %ymm0
+ vpor %ymm1, %ymm5, %ymm5
+ vpand 32*9-128($inp), %ymm9, %ymm1
+ vpor %ymm2, %ymm4, %ymm4
+ vpand 32*10-128($inp),%ymm10, %ymm2
+ vpor %ymm3, %ymm5, %ymm5
+ vpand 32*11-128($inp),%ymm11, %ymm3
+ vpor %ymm0, %ymm4, %ymm4
+ vpand 32*12-128($inp),%ymm12, %ymm0
+ vpor %ymm1, %ymm5, %ymm5
+ vpand 32*13-128($inp),%ymm13, %ymm1
+ vpor %ymm2, %ymm4, %ymm4
+ vpand 32*14-128($inp),%ymm14, %ymm2
+ vpor %ymm3, %ymm5, %ymm5
+ vpand 32*15-128($inp),%ymm15, %ymm3
+ lea 32*16($inp), $inp
+ vpor %ymm0, %ymm4, %ymm4
+ vpor %ymm1, %ymm5, %ymm5
+ vpor %ymm2, %ymm4, %ymm4
+ vpor %ymm3, %ymm5, %ymm5
+
+ vpor %ymm5, %ymm4, %ymm4
+ vextracti128 \$1, %ymm4, %xmm5 # upper half is cleared
+ vpor %xmm4, %xmm5, %xmm5
+ vpermd %ymm5,%ymm7,%ymm5
+ vmovdqu %ymm5,($out)
lea 32($out),$out
- dec %eax
+ dec $power
jnz .Loop_gather_1024
vpxor %ymm0,%ymm0,%ymm0
@@ -1645,20 +1705,20 @@ $code.=<<___;
vzeroupper
___
$code.=<<___ if ($win64);
- movaps (%rsp),%xmm6
- movaps 0x10(%rsp),%xmm7
- movaps 0x20(%rsp),%xmm8
- movaps 0x30(%rsp),%xmm9
- movaps 0x40(%rsp),%xmm10
- movaps 0x50(%rsp),%xmm11
- movaps 0x60(%rsp),%xmm12
- movaps 0x70(%rsp),%xmm13
- movaps 0x80(%rsp),%xmm14
- movaps 0x90(%rsp),%xmm15
- lea 0xa8(%rsp),%rsp
+ movaps -0xa8(%r11),%xmm6
+ movaps -0x98(%r11),%xmm7
+ movaps -0x88(%r11),%xmm8
+ movaps -0x78(%r11),%xmm9
+ movaps -0x68(%r11),%xmm10
+ movaps -0x58(%r11),%xmm11
+ movaps -0x48(%r11),%xmm12
+ movaps -0x38(%r11),%xmm13
+ movaps -0x28(%r11),%xmm14
+ movaps -0x18(%r11),%xmm15
.LSEH_end_rsaz_1024_gather5:
___
$code.=<<___;
+ lea (%r11),%rsp
ret
.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
___
@@ -1692,8 +1752,10 @@ $code.=<<___;
.long 0,2,4,6,7,7,7,7
.Lgather_permd:
.long 0,7,1,7,2,7,3,7
-.Lgather_table:
- .byte 0,0,0,0,0,0,0,0, 0xff,0,0,0,0,0,0,0
+.Linc:
+ .long 0,0,0,0, 1,1,1,1
+ .long 2,2,2,2, 3,3,3,3
+ .long 4,4,4,4, 4,4,4,4
.align 64
___
@@ -1821,18 +1883,19 @@ rsaz_se_handler:
.rva rsaz_se_handler
.rva .Lmul_1024_body,.Lmul_1024_epilogue
.LSEH_info_rsaz_1024_gather5:
- .byte 0x01,0x33,0x16,0x00
- .byte 0x36,0xf8,0x09,0x00 #vmovaps 0x90(rsp),xmm15
- .byte 0x31,0xe8,0x08,0x00 #vmovaps 0x80(rsp),xmm14
- .byte 0x2c,0xd8,0x07,0x00 #vmovaps 0x70(rsp),xmm13
- .byte 0x27,0xc8,0x06,0x00 #vmovaps 0x60(rsp),xmm12
- .byte 0x22,0xb8,0x05,0x00 #vmovaps 0x50(rsp),xmm11
- .byte 0x1d,0xa8,0x04,0x00 #vmovaps 0x40(rsp),xmm10
- .byte 0x18,0x98,0x03,0x00 #vmovaps 0x30(rsp),xmm9
- .byte 0x13,0x88,0x02,0x00 #vmovaps 0x20(rsp),xmm8
- .byte 0x0e,0x78,0x01,0x00 #vmovaps 0x10(rsp),xmm7
- .byte 0x09,0x68,0x00,0x00 #vmovaps 0x00(rsp),xmm6
- .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8
+ .byte 0x01,0x36,0x17,0x0b
+ .byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
+ .byte 0x31,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14
+ .byte 0x2c,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13
+ .byte 0x27,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12
+ .byte 0x22,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11
+ .byte 0x1d,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10
+ .byte 0x18,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9
+ .byte 0x13,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8
+ .byte 0x0e,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7
+ .byte 0x09,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6
+ .byte 0x04,0x01,0x15,0x00 # sub rsp,0xa8
+ .byte 0x00,0xb3,0x00,0x00 # set_frame r11
___
}
diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl
index 4113d533..c38bde95 100644..100755
--- a/crypto/bn/asm/rsaz-x86_64.pl
+++ b/crypto/bn/asm/rsaz-x86_64.pl
@@ -902,9 +902,76 @@ rsaz_512_mul_gather4:
push %r14
push %r15
- mov $pwr, $pwr
- subq \$128+24, %rsp
+ subq \$`128+24+($win64?0xb0:0)`, %rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,0xa0(%rsp)
+ movaps %xmm7,0xb0(%rsp)
+ movaps %xmm8,0xc0(%rsp)
+ movaps %xmm9,0xd0(%rsp)
+ movaps %xmm10,0xe0(%rsp)
+ movaps %xmm11,0xf0(%rsp)
+ movaps %xmm12,0x100(%rsp)
+ movaps %xmm13,0x110(%rsp)
+ movaps %xmm14,0x120(%rsp)
+ movaps %xmm15,0x130(%rsp)
+___
+$code.=<<___;
.Lmul_gather4_body:
+ movd $pwr,%xmm8
+ movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002
+ movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000
+
+ pshufd \$0,%xmm8,%xmm8 # broadcast $power
+ movdqa %xmm1,%xmm7
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..15 to $power
+#
+for($i=0;$i<4;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+ movdqa %xmm7,%xmm`$i+3`
+___
+}
+for(;$i<7;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+___
+}
+$code.=<<___;
+ pcmpeqd %xmm8,%xmm7
+
+ movdqa 16*0($bp),%xmm8
+ movdqa 16*1($bp),%xmm9
+ movdqa 16*2($bp),%xmm10
+ movdqa 16*3($bp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4($bp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5($bp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6($bp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7($bp),%xmm15
+ leaq 128($bp), %rbp
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
___
$code.=<<___ if ($addx);
movl \$0x80100,%r11d
@@ -913,45 +980,38 @@ $code.=<<___ if ($addx);
je .Lmulx_gather
___
$code.=<<___;
- movl 64($bp,$pwr,4), %eax
- movq $out, %xmm0 # off-load arguments
- movl ($bp,$pwr,4), %ebx
- movq $mod, %xmm1
- movq $n0, 128(%rsp)
+ movq %xmm8,%rbx
+
+ movq $n0, 128(%rsp) # off-load arguments
+ movq $out, 128+8(%rsp)
+ movq $mod, 128+16(%rsp)
- shlq \$32, %rax
- or %rax, %rbx
movq ($ap), %rax
movq 8($ap), %rcx
- leaq 128($bp,$pwr,4), %rbp
mulq %rbx # 0 iteration
movq %rax, (%rsp)
movq %rcx, %rax
movq %rdx, %r8
mulq %rbx
- movd (%rbp), %xmm4
addq %rax, %r8
movq 16($ap), %rax
movq %rdx, %r9
adcq \$0, %r9
mulq %rbx
- movd 64(%rbp), %xmm5
addq %rax, %r9
movq 24($ap), %rax
movq %rdx, %r10
adcq \$0, %r10
mulq %rbx
- pslldq \$4, %xmm5
addq %rax, %r10
movq 32($ap), %rax
movq %rdx, %r11
adcq \$0, %r11
mulq %rbx
- por %xmm5, %xmm4
addq %rax, %r11
movq 40($ap), %rax
movq %rdx, %r12
@@ -964,14 +1024,12 @@ $code.=<<___;
adcq \$0, %r13
mulq %rbx
- leaq 128(%rbp), %rbp
addq %rax, %r13
movq 56($ap), %rax
movq %rdx, %r14
adcq \$0, %r14
mulq %rbx
- movq %xmm4, %rbx
addq %rax, %r14
movq ($ap), %rax
movq %rdx, %r15
@@ -983,6 +1041,35 @@ $code.=<<___;
.align 32
.Loop_mul_gather:
+ movdqa 16*0(%rbp),%xmm8
+ movdqa 16*1(%rbp),%xmm9
+ movdqa 16*2(%rbp),%xmm10
+ movdqa 16*3(%rbp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4(%rbp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5(%rbp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6(%rbp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7(%rbp),%xmm15
+ leaq 128(%rbp), %rbp
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
+ movq %xmm8,%rbx
+
mulq %rbx
addq %rax, %r8
movq 8($ap), %rax
@@ -991,7 +1078,6 @@ $code.=<<___;
adcq \$0, %r8
mulq %rbx
- movd (%rbp), %xmm4
addq %rax, %r9
movq 16($ap), %rax
adcq \$0, %rdx
@@ -1000,7 +1086,6 @@ $code.=<<___;
adcq \$0, %r9
mulq %rbx
- movd 64(%rbp), %xmm5
addq %rax, %r10
movq 24($ap), %rax
adcq \$0, %rdx
@@ -1009,7 +1094,6 @@ $code.=<<___;
adcq \$0, %r10
mulq %rbx
- pslldq \$4, %xmm5
addq %rax, %r11
movq 32($ap), %rax
adcq \$0, %rdx
@@ -1018,7 +1102,6 @@ $code.=<<___;
adcq \$0, %r11
mulq %rbx
- por %xmm5, %xmm4
addq %rax, %r12
movq 40($ap), %rax
adcq \$0, %rdx
@@ -1043,7 +1126,6 @@ $code.=<<___;
adcq \$0, %r14
mulq %rbx
- movq %xmm4, %rbx
addq %rax, %r15
movq ($ap), %rax
adcq \$0, %rdx
@@ -1051,7 +1133,6 @@ $code.=<<___;
movq %rdx, %r15
adcq \$0, %r15
- leaq 128(%rbp), %rbp
leaq 8(%rdi), %rdi
decl %ecx
@@ -1066,8 +1147,8 @@ $code.=<<___;
movq %r14, 48(%rdi)
movq %r15, 56(%rdi)
- movq %xmm0, $out
- movq %xmm1, %rbp
+ movq 128+8(%rsp), $out
+ movq 128+16(%rsp), %rbp
movq (%rsp), %r8
movq 8(%rsp), %r9
@@ -1085,45 +1166,37 @@ $code.=<<___ if ($addx);
.align 32
.Lmulx_gather:
- mov 64($bp,$pwr,4), %eax
- movq $out, %xmm0 # off-load arguments
- lea 128($bp,$pwr,4), %rbp
- mov ($bp,$pwr,4), %edx
- movq $mod, %xmm1
- mov $n0, 128(%rsp)
+ movq %xmm8,%rdx
+
+ mov $n0, 128(%rsp) # off-load arguments
+ mov $out, 128+8(%rsp)
+ mov $mod, 128+16(%rsp)
- shl \$32, %rax
- or %rax, %rdx
mulx ($ap), %rbx, %r8 # 0 iteration
mov %rbx, (%rsp)
xor %edi, %edi # cf=0, of=0
mulx 8($ap), %rax, %r9
- movd (%rbp), %xmm4
mulx 16($ap), %rbx, %r10
- movd 64(%rbp), %xmm5
adcx %rax, %r8
mulx 24($ap), %rax, %r11
- pslldq \$4, %xmm5
adcx %rbx, %r9
mulx 32($ap), %rbx, %r12
- por %xmm5, %xmm4
adcx %rax, %r10
mulx 40($ap), %rax, %r13
adcx %rbx, %r11
mulx 48($ap), %rbx, %r14
- lea 128(%rbp), %rbp
adcx %rax, %r12
mulx 56($ap), %rax, %r15
- movq %xmm4, %rdx
adcx %rbx, %r13
adcx %rax, %r14
+ .byte 0x67
mov %r8, %rbx
adcx %rdi, %r15 # %rdi is 0
@@ -1132,24 +1205,48 @@ $code.=<<___ if ($addx);
.align 32
.Loop_mulx_gather:
- mulx ($ap), %rax, %r8
+ movdqa 16*0(%rbp),%xmm8
+ movdqa 16*1(%rbp),%xmm9
+ movdqa 16*2(%rbp),%xmm10
+ movdqa 16*3(%rbp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4(%rbp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5(%rbp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6(%rbp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7(%rbp),%xmm15
+ leaq 128(%rbp), %rbp
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
+ movq %xmm8,%rdx
+
+ .byte 0xc4,0x62,0xfb,0xf6,0x86,0x00,0x00,0x00,0x00 # mulx ($ap), %rax, %r8
adcx %rax, %rbx
adox %r9, %r8
mulx 8($ap), %rax, %r9
- .byte 0x66,0x0f,0x6e,0xa5,0x00,0x00,0x00,0x00 # movd (%rbp), %xmm4
adcx %rax, %r8
adox %r10, %r9
mulx 16($ap), %rax, %r10
- movd 64(%rbp), %xmm5
- lea 128(%rbp), %rbp
adcx %rax, %r9
adox %r11, %r10
.byte 0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00 # mulx 24($ap), %rax, %r11
- pslldq \$4, %xmm5
- por %xmm5, %xmm4
adcx %rax, %r10
adox %r12, %r11
@@ -1163,10 +1260,10 @@ $code.=<<___ if ($addx);
.byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14
adcx %rax, %r13
+ .byte 0x67
adox %r15, %r14
mulx 56($ap), %rax, %r15
- movq %xmm4, %rdx
mov %rbx, 64(%rsp,%rcx,8)
adcx %rax, %r14
adox %rdi, %r15
@@ -1185,10 +1282,10 @@ $code.=<<___ if ($addx);
mov %r14, 64+48(%rsp)
mov %r15, 64+56(%rsp)
- movq %xmm0, $out
- movq %xmm1, %rbp
+ mov 128(%rsp), %rdx # pull arguments
+ mov 128+8(%rsp), $out
+ mov 128+16(%rsp), %rbp
- mov 128(%rsp), %rdx # pull $n0
mov (%rsp), %r8
mov 8(%rsp), %r9
mov 16(%rsp), %r10
@@ -1216,6 +1313,21 @@ $code.=<<___;
call __rsaz_512_subtract
leaq 128+24+48(%rsp), %rax
+___
+$code.=<<___ if ($win64);
+ movaps 0xa0-0xc8(%rax),%xmm6
+ movaps 0xb0-0xc8(%rax),%xmm7
+ movaps 0xc0-0xc8(%rax),%xmm8
+ movaps 0xd0-0xc8(%rax),%xmm9
+ movaps 0xe0-0xc8(%rax),%xmm10
+ movaps 0xf0-0xc8(%rax),%xmm11
+ movaps 0x100-0xc8(%rax),%xmm12
+ movaps 0x110-0xc8(%rax),%xmm13
+ movaps 0x120-0xc8(%rax),%xmm14
+ movaps 0x130-0xc8(%rax),%xmm15
+ lea 0xb0(%rax),%rax
+___
+$code.=<<___;
movq -48(%rax), %r15
movq -40(%rax), %r14
movq -32(%rax), %r13
@@ -1245,7 +1357,7 @@ rsaz_512_mul_scatter4:
mov $pwr, $pwr
subq \$128+24, %rsp
.Lmul_scatter4_body:
- leaq ($tbl,$pwr,4), $tbl
+ leaq ($tbl,$pwr,8), $tbl
movq $out, %xmm0 # off-load arguments
movq $mod, %xmm1
movq $tbl, %xmm2
@@ -1316,30 +1428,14 @@ $code.=<<___;
call __rsaz_512_subtract
- movl %r8d, 64*0($inp) # scatter
- shrq \$32, %r8
- movl %r9d, 64*2($inp)
- shrq \$32, %r9
- movl %r10d, 64*4($inp)
- shrq \$32, %r10
- movl %r11d, 64*6($inp)
- shrq \$32, %r11
- movl %r12d, 64*8($inp)
- shrq \$32, %r12
- movl %r13d, 64*10($inp)
- shrq \$32, %r13
- movl %r14d, 64*12($inp)
- shrq \$32, %r14
- movl %r15d, 64*14($inp)
- shrq \$32, %r15
- movl %r8d, 64*1($inp)
- movl %r9d, 64*3($inp)
- movl %r10d, 64*5($inp)
- movl %r11d, 64*7($inp)
- movl %r12d, 64*9($inp)
- movl %r13d, 64*11($inp)
- movl %r14d, 64*13($inp)
- movl %r15d, 64*15($inp)
+ movq %r8, 128*0($inp) # scatter
+ movq %r9, 128*1($inp)
+ movq %r10, 128*2($inp)
+ movq %r11, 128*3($inp)
+ movq %r12, 128*4($inp)
+ movq %r13, 128*5($inp)
+ movq %r14, 128*6($inp)
+ movq %r15, 128*7($inp)
leaq 128+24+48(%rsp), %rax
movq -48(%rax), %r15
@@ -1943,16 +2039,14 @@ $code.=<<___;
.type rsaz_512_scatter4,\@abi-omnipotent
.align 16
rsaz_512_scatter4:
- leaq ($out,$power,4), $out
+ leaq ($out,$power,8), $out
movl \$8, %r9d
jmp .Loop_scatter
.align 16
.Loop_scatter:
movq ($inp), %rax
leaq 8($inp), $inp
- movl %eax, ($out)
- shrq \$32, %rax
- movl %eax, 64($out)
+ movq %rax, ($out)
leaq 128($out), $out
decl %r9d
jnz .Loop_scatter
@@ -1963,22 +2057,106 @@ rsaz_512_scatter4:
.type rsaz_512_gather4,\@abi-omnipotent
.align 16
rsaz_512_gather4:
- leaq ($inp,$power,4), $inp
+___
+$code.=<<___ if ($win64);
+.LSEH_begin_rsaz_512_gather4:
+ .byte 0x48,0x81,0xec,0xa8,0x00,0x00,0x00 # sub $0xa8,%rsp
+ .byte 0x0f,0x29,0x34,0x24 # movaps %xmm6,(%rsp)
+ .byte 0x0f,0x29,0x7c,0x24,0x10 # movaps %xmm7,0x10(%rsp)
+ .byte 0x44,0x0f,0x29,0x44,0x24,0x20 # movaps %xmm8,0x20(%rsp)
+ .byte 0x44,0x0f,0x29,0x4c,0x24,0x30 # movaps %xmm9,0x30(%rsp)
+ .byte 0x44,0x0f,0x29,0x54,0x24,0x40 # movaps %xmm10,0x40(%rsp)
+ .byte 0x44,0x0f,0x29,0x5c,0x24,0x50 # movaps %xmm11,0x50(%rsp)
+ .byte 0x44,0x0f,0x29,0x64,0x24,0x60 # movaps %xmm12,0x60(%rsp)
+ .byte 0x44,0x0f,0x29,0x6c,0x24,0x70 # movaps %xmm13,0x70(%rsp)
+ .byte 0x44,0x0f,0x29,0xb4,0x24,0x80,0,0,0 # movaps %xmm14,0x80(%rsp)
+ .byte 0x44,0x0f,0x29,0xbc,0x24,0x90,0,0,0 # movaps %xmm15,0x90(%rsp)
+___
+$code.=<<___;
+ movd $power,%xmm8
+ movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002
+ movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000
+
+ pshufd \$0,%xmm8,%xmm8 # broadcast $power
+ movdqa %xmm1,%xmm7
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..15 to $power
+#
+for($i=0;$i<4;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+ movdqa %xmm7,%xmm`$i+3`
+___
+}
+for(;$i<7;$i++) {
+$code.=<<___;
+ paddd %xmm`$i`,%xmm`$i+1`
+ pcmpeqd %xmm8,%xmm`$i`
+___
+}
+$code.=<<___;
+ pcmpeqd %xmm8,%xmm7
movl \$8, %r9d
jmp .Loop_gather
.align 16
.Loop_gather:
- movl ($inp), %eax
- movl 64($inp), %r8d
+ movdqa 16*0($inp),%xmm8
+ movdqa 16*1($inp),%xmm9
+ movdqa 16*2($inp),%xmm10
+ movdqa 16*3($inp),%xmm11
+ pand %xmm0,%xmm8
+ movdqa 16*4($inp),%xmm12
+ pand %xmm1,%xmm9
+ movdqa 16*5($inp),%xmm13
+ pand %xmm2,%xmm10
+ movdqa 16*6($inp),%xmm14
+ pand %xmm3,%xmm11
+ movdqa 16*7($inp),%xmm15
leaq 128($inp), $inp
- shlq \$32, %r8
- or %r8, %rax
- movq %rax, ($out)
+ pand %xmm4,%xmm12
+ pand %xmm5,%xmm13
+ pand %xmm6,%xmm14
+ pand %xmm7,%xmm15
+ por %xmm10,%xmm8
+ por %xmm11,%xmm9
+ por %xmm12,%xmm8
+ por %xmm13,%xmm9
+ por %xmm14,%xmm8
+ por %xmm15,%xmm9
+
+ por %xmm9,%xmm8
+ pshufd \$0x4e,%xmm8,%xmm9
+ por %xmm9,%xmm8
+ movq %xmm8,($out)
leaq 8($out), $out
decl %r9d
jnz .Loop_gather
+___
+$code.=<<___ if ($win64);
+ movaps 0x00(%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ movaps 0x40(%rsp),%xmm10
+ movaps 0x50(%rsp),%xmm11
+ movaps 0x60(%rsp),%xmm12
+ movaps 0x70(%rsp),%xmm13
+ movaps 0x80(%rsp),%xmm14
+ movaps 0x90(%rsp),%xmm15
+ add \$0xa8,%rsp
+___
+$code.=<<___;
ret
+.LSEH_end_rsaz_512_gather4:
.size rsaz_512_gather4,.-rsaz_512_gather4
+
+.align 64
+.Linc:
+ .long 0,0, 1,1
+ .long 2,2, 2,2
___
}
@@ -2026,6 +2204,18 @@ se_handler:
lea 128+24+48(%rax),%rax
+ lea .Lmul_gather4_epilogue(%rip),%rbx
+ cmp %r10,%rbx
+ jne .Lse_not_in_mul_gather4
+
+ lea 0xb0(%rax),%rax
+
+ lea -48-0xa8(%rax),%rsi
+ lea 512($context),%rdi
+ mov \$20,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lse_not_in_mul_gather4:
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -2077,7 +2267,7 @@ se_handler:
pop %rdi
pop %rsi
ret
-.size sqr_handler,.-sqr_handler
+.size se_handler,.-se_handler
.section .pdata
.align 4
@@ -2101,6 +2291,10 @@ se_handler:
.rva .LSEH_end_rsaz_512_mul_by_one
.rva .LSEH_info_rsaz_512_mul_by_one
+ .rva .LSEH_begin_rsaz_512_gather4
+ .rva .LSEH_end_rsaz_512_gather4
+ .rva .LSEH_info_rsaz_512_gather4
+
.section .xdata
.align 8
.LSEH_info_rsaz_512_sqr:
@@ -2123,6 +2317,19 @@ se_handler:
.byte 9,0,0,0
.rva se_handler
.rva .Lmul_by_one_body,.Lmul_by_one_epilogue # HandlerData[]
+.LSEH_info_rsaz_512_gather4:
+ .byte 0x01,0x46,0x16,0x00
+ .byte 0x46,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
+ .byte 0x3d,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14
+ .byte 0x34,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13
+ .byte 0x2e,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12
+ .byte 0x28,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11
+ .byte 0x22,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10
+ .byte 0x1c,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9
+ .byte 0x16,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8
+ .byte 0x10,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7
+ .byte 0x0b,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6
+ .byte 0x07,0x01,0x15,0x00 # sub rsp,0xa8
___
}
diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c
index d78a8514..214c12af 100644
--- a/crypto/bn/asm/x86_64-gcc.c
+++ b/crypto/bn/asm/x86_64-gcc.c
@@ -186,14 +186,6 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
}
}
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
- BN_ULONG ret, waste;
-
- asm("divq %4" : "=a"(ret), "=d"(waste) : "a"(l), "d"(h), "g"(d) : "cc");
-
- return ret;
-}
-
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int n) {
BN_ULONG ret;
diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl
index 04c4beaf..1ca2b1ef 100644..100755
--- a/crypto/bn/asm/x86_64-mont.pl
+++ b/crypto/bn/asm/x86_64-mont.pl
@@ -761,100 +761,126 @@ bn_sqr8x_mont:
# 4096. this is done to allow memory disambiguation logic
# do its job.
#
- lea -64(%rsp,$num,4),%r11
+ lea -64(%rsp,$num,2),%r11
mov ($n0),$n0 # *n0
sub $aptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lsqr8x_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
jmp .Lsqr8x_sp_done
.align 32
.Lsqr8x_sp_alt:
- lea 4096-64(,$num,4),%r10 # 4096-frame-4*$num
- lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
+ lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rsp
.Lsqr8x_sp_done:
and \$-64,%rsp
- mov $num,%r10
+ mov $num,%r10
neg $num
- lea 64(%rsp,$num,2),%r11 # copy of modulus
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.Lsqr8x_body:
- mov $num,$i
- movq %r11, %xmm2 # save pointer to modulus copy
- shr \$3+2,$i
- mov OPENSSL_ia32cap_P+8(%rip),%eax
- jmp .Lsqr8x_copy_n
-
-.align 32
-.Lsqr8x_copy_n:
- movq 8*0($nptr),%xmm0
- movq 8*1($nptr),%xmm1
- movq 8*2($nptr),%xmm3
- movq 8*3($nptr),%xmm4
- lea 8*4($nptr),$nptr
- movdqa %xmm0,16*0(%r11)
- movdqa %xmm1,16*1(%r11)
- movdqa %xmm3,16*2(%r11)
- movdqa %xmm4,16*3(%r11)
- lea 16*4(%r11),%r11
- dec $i
- jnz .Lsqr8x_copy_n
-
+ movq $nptr, %xmm2 # save pointer to modulus
pxor %xmm0,%xmm0
movq $rptr,%xmm1 # save $rptr
movq %r10, %xmm3 # -$num
___
$code.=<<___ if ($addx);
+ mov OPENSSL_ia32cap_P+8(%rip),%eax
and \$0x80100,%eax
cmp \$0x80100,%eax
jne .Lsqr8x_nox
call bn_sqrx8x_internal # see x86_64-mont5 module
-
- pxor %xmm0,%xmm0
- lea 48(%rsp),%rax
- lea 64(%rsp,$num,2),%rdx
- shr \$3+2,$num
- mov 40(%rsp),%rsi # restore %rsp
- jmp .Lsqr8x_zero
+ # %rax top-most carry
+ # %rbp nptr
+ # %rcx -8*num
+ # %r8 end of tp[2*num]
+ lea (%r8,%rcx),%rbx
+ mov %rcx,$num
+ mov %rcx,%rdx
+ movq %xmm1,$rptr
+ sar \$3+2,%rcx # %cf=0
+ jmp .Lsqr8x_sub
.align 32
.Lsqr8x_nox:
___
$code.=<<___;
call bn_sqr8x_internal # see x86_64-mont5 module
+ # %rax top-most carry
+ # %rbp nptr
+ # %r8 -8*num
+ # %rdi end of tp[2*num]
+ lea (%rdi,$num),%rbx
+ mov $num,%rcx
+ mov $num,%rdx
+ movq %xmm1,$rptr
+ sar \$3+2,%rcx # %cf=0
+ jmp .Lsqr8x_sub
+.align 32
+.Lsqr8x_sub:
+ mov 8*0(%rbx),%r12
+ mov 8*1(%rbx),%r13
+ mov 8*2(%rbx),%r14
+ mov 8*3(%rbx),%r15
+ lea 8*4(%rbx),%rbx
+ sbb 8*0(%rbp),%r12
+ sbb 8*1(%rbp),%r13
+ sbb 8*2(%rbp),%r14
+ sbb 8*3(%rbp),%r15
+ lea 8*4(%rbp),%rbp
+ mov %r12,8*0($rptr)
+ mov %r13,8*1($rptr)
+ mov %r14,8*2($rptr)
+ mov %r15,8*3($rptr)
+ lea 8*4($rptr),$rptr
+ inc %rcx # preserves %cf
+ jnz .Lsqr8x_sub
+
+ sbb \$0,%rax # top-most carry
+ lea (%rbx,$num),%rbx # rewind
+ lea ($rptr,$num),$rptr # rewind
+
+ movq %rax,%xmm1
pxor %xmm0,%xmm0
- lea 48(%rsp),%rax
- lea 64(%rsp,$num,2),%rdx
- shr \$3+2,$num
+ pshufd \$0,%xmm1,%xmm1
mov 40(%rsp),%rsi # restore %rsp
- jmp .Lsqr8x_zero
+ jmp .Lsqr8x_cond_copy
.align 32
-.Lsqr8x_zero:
- movdqa %xmm0,16*0(%rax) # wipe t
- movdqa %xmm0,16*1(%rax)
- movdqa %xmm0,16*2(%rax)
- movdqa %xmm0,16*3(%rax)
- lea 16*4(%rax),%rax
- movdqa %xmm0,16*0(%rdx) # wipe n
- movdqa %xmm0,16*1(%rdx)
- movdqa %xmm0,16*2(%rdx)
- movdqa %xmm0,16*3(%rdx)
- lea 16*4(%rdx),%rdx
- dec $num
- jnz .Lsqr8x_zero
+.Lsqr8x_cond_copy:
+ movdqa 16*0(%rbx),%xmm2
+ movdqa 16*1(%rbx),%xmm3
+ lea 16*2(%rbx),%rbx
+ movdqu 16*0($rptr),%xmm4
+ movdqu 16*1($rptr),%xmm5
+ lea 16*2($rptr),$rptr
+ movdqa %xmm0,-16*2(%rbx) # zero tp
+ movdqa %xmm0,-16*1(%rbx)
+ movdqa %xmm0,-16*2(%rbx,%rdx)
+ movdqa %xmm0,-16*1(%rbx,%rdx)
+ pcmpeqd %xmm1,%xmm0
+ pand %xmm1,%xmm2
+ pand %xmm1,%xmm3
+ pand %xmm0,%xmm4
+ pand %xmm0,%xmm5
+ pxor %xmm0,%xmm0
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+ movdqu %xmm4,-16*2($rptr)
+ movdqu %xmm5,-16*1($rptr)
+ add \$32,$num
+ jnz .Lsqr8x_cond_copy
mov \$1,%rax
mov -48(%rsi),%r15
@@ -1121,64 +1147,75 @@ $code.=<<___;
adc $zero,%r15 # modulo-scheduled
sub 0*8($tptr),$zero # pull top-most carry
adc %r15,%r14
- mov -8($nptr),$mi
sbb %r15,%r15 # top-most carry
mov %r14,-1*8($tptr)
cmp 16(%rsp),$bptr
jne .Lmulx4x_outer
- sub %r14,$mi # compare top-most words
- sbb $mi,$mi
- or $mi,%r15
-
- neg $num
- xor %rdx,%rdx
+ lea 64(%rsp),$tptr
+ sub $num,$nptr # rewind $nptr
+ neg %r15
+ mov $num,%rdx
+ shr \$3+2,$num # %cf=0
mov 32(%rsp),$rptr # restore rp
+ jmp .Lmulx4x_sub
+
+.align 32
+.Lmulx4x_sub:
+ mov 8*0($tptr),%r11
+ mov 8*1($tptr),%r12
+ mov 8*2($tptr),%r13
+ mov 8*3($tptr),%r14
+ lea 8*4($tptr),$tptr
+ sbb 8*0($nptr),%r11
+ sbb 8*1($nptr),%r12
+ sbb 8*2($nptr),%r13
+ sbb 8*3($nptr),%r14
+ lea 8*4($nptr),$nptr
+ mov %r11,8*0($rptr)
+ mov %r12,8*1($rptr)
+ mov %r13,8*2($rptr)
+ mov %r14,8*3($rptr)
+ lea 8*4($rptr),$rptr
+ dec $num # preserves %cf
+ jnz .Lmulx4x_sub
+
+ sbb \$0,%r15 # top-most carry
lea 64(%rsp),$tptr
+ sub %rdx,$rptr # rewind
+ movq %r15,%xmm1
pxor %xmm0,%xmm0
- mov 0*8($nptr,$num),%r8
- mov 1*8($nptr,$num),%r9
- neg %r8
- jmp .Lmulx4x_sub_entry
+ pshufd \$0,%xmm1,%xmm1
+ mov 40(%rsp),%rsi # restore %rsp
+ jmp .Lmulx4x_cond_copy
.align 32
-.Lmulx4x_sub:
- mov 0*8($nptr,$num),%r8
- mov 1*8($nptr,$num),%r9
- not %r8
-.Lmulx4x_sub_entry:
- mov 2*8($nptr,$num),%r10
- not %r9
- and %r15,%r8
- mov 3*8($nptr,$num),%r11
- not %r10
- and %r15,%r9
- not %r11
- and %r15,%r10
- and %r15,%r11
-
- neg %rdx # mov %rdx,%cf
- adc 0*8($tptr),%r8
- adc 1*8($tptr),%r9
- movdqa %xmm0,($tptr)
- adc 2*8($tptr),%r10
- adc 3*8($tptr),%r11
- movdqa %xmm0,16($tptr)
- lea 4*8($tptr),$tptr
- sbb %rdx,%rdx # mov %cf,%rdx
-
- mov %r8,0*8($rptr)
- mov %r9,1*8($rptr)
- mov %r10,2*8($rptr)
- mov %r11,3*8($rptr)
- lea 4*8($rptr),$rptr
+.Lmulx4x_cond_copy:
+ movdqa 16*0($tptr),%xmm2
+ movdqa 16*1($tptr),%xmm3
+ lea 16*2($tptr),$tptr
+ movdqu 16*0($rptr),%xmm4
+ movdqu 16*1($rptr),%xmm5
+ lea 16*2($rptr),$rptr
+ movdqa %xmm0,-16*2($tptr) # zero tp
+ movdqa %xmm0,-16*1($tptr)
+ pcmpeqd %xmm1,%xmm0
+ pand %xmm1,%xmm2
+ pand %xmm1,%xmm3
+ pand %xmm0,%xmm4
+ pand %xmm0,%xmm5
+ pxor %xmm0,%xmm0
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+ movdqu %xmm4,-16*2($rptr)
+ movdqu %xmm5,-16*1($rptr)
+ sub \$32,%rdx
+ jnz .Lmulx4x_cond_copy
- add \$32,$num
- jnz .Lmulx4x_sub
+ mov %rdx,($tptr)
- mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
mov -48(%rsi),%r15
mov -40(%rsi),%r14
diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl
index 3c5a8fc9..ced3acba 100644..100755
--- a/crypto/bn/asm/x86_64-mont5.pl
+++ b/crypto/bn/asm/x86_64-mont5.pl
@@ -86,58 +86,111 @@ $code.=<<___;
.Lmul_enter:
mov ${num}d,${num}d
mov %rsp,%rax
- mov `($win64?56:8)`(%rsp),%r10d # load 7th argument
+ movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument
+ lea .Linc(%rip),%r10
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
+
lea 2($num),%r11
neg %r11
- lea (%rsp,%r11,8),%rsp # tp=alloca(8*(num+2))
+ lea -264(%rsp,%r11,8),%rsp # tp=alloca(8*(num+2)+256+8)
and \$-1024,%rsp # minimize TLB usage
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
.Lmul_body:
- mov $bp,%r12 # reassign $bp
+ lea 128($bp),%r12 # reassign $bp (+size optimization)
___
$bp="%r12";
$STRIDE=2**5*8; # 5 is "window size"
$N=$STRIDE/4; # should match cache line size
$code.=<<___;
- mov %r10,%r11
- shr \$`log($N/8)/log(2)`,%r10
- and \$`$N/8-1`,%r11
- not %r10
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
- lea 96($bp,%r11,8),$bp # pointer within 1st cache line
- movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
- movq 8(%rax,%r10,8),%xmm5 # cache line contains element
- movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,%r10,8),%xmm7
-
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
+ movdqa 0(%r10),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%r10),%xmm1 # 00000002000000020000000200000002
+ lea 24-112(%rsp,$num,8),%r10# place the mask after tp[num+3] (+ICache optimization)
+ and \$-16,%r10
+
+ pshufd \$0,%xmm5,%xmm5 # broadcast index
+ movdqa %xmm1,%xmm4
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
+ .byte 0x67
+ movdqa %xmm4,%xmm3
+___
+for($k=0;$k<$STRIDE/16-4;$k+=4) {
+$code.=<<___;
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($k+0)+112`(%r10)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($k+1)+112`(%r10)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($k+2)+112`(%r10)
+ movdqa %xmm4,%xmm2
+
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0
+ movdqa %xmm3,`16*($k+3)+112`(%r10)
+ movdqa %xmm4,%xmm3
+___
+}
+$code.=<<___; # last iteration can be optimized
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1
+ movdqa %xmm0,`16*($k+0)+112`(%r10)
+
+ paddd %xmm2,%xmm3
+ .byte 0x67
+ pcmpeqd %xmm5,%xmm2
+ movdqa %xmm1,`16*($k+1)+112`(%r10)
+
+ pcmpeqd %xmm5,%xmm3
+ movdqa %xmm2,`16*($k+2)+112`(%r10)
+ pand `16*($k+0)-128`($bp),%xmm0 # while it's still in register
+
+ pand `16*($k+1)-128`($bp),%xmm1
+ pand `16*($k+2)-128`($bp),%xmm2
+ movdqa %xmm3,`16*($k+3)+112`(%r10)
+ pand `16*($k+3)-128`($bp),%xmm3
por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+for($k=0;$k<$STRIDE/16-4;$k+=4) {
+$code.=<<___;
+ movdqa `16*($k+0)-128`($bp),%xmm4
+ movdqa `16*($k+1)-128`($bp),%xmm5
+ movdqa `16*($k+2)-128`($bp),%xmm2
+ pand `16*($k+0)+112`(%r10),%xmm4
+ movdqa `16*($k+3)-128`($bp),%xmm3
+ pand `16*($k+1)+112`(%r10),%xmm5
+ por %xmm4,%xmm0
+ pand `16*($k+2)+112`(%r10),%xmm2
+ por %xmm5,%xmm1
+ pand `16*($k+3)+112`(%r10),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+}
+$code.=<<___;
+ por %xmm1,%xmm0
+ pshufd \$0x4e,%xmm0,%xmm1
+ por %xmm1,%xmm0
lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
-
movq %xmm0,$m0 # m0=bp[0]
mov ($n0),$n0 # pull n0[0] value
@@ -146,29 +199,14 @@ $code.=<<___;
xor $i,$i # i=0
xor $j,$j # j=0
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
-
mov $n0,$m1
mulq $m0 # ap[0]*bp[0]
mov %rax,$lo0
mov ($np),%rax
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
-
imulq $lo0,$m1 # "tp[0]"*n0
mov %rdx,$hi0
- por %xmm2,%xmm0
- lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
-
mulq $m1 # np[0]*m1
add %rax,$lo0 # discarded
mov 8($ap),%rax
@@ -199,16 +237,14 @@ $code.=<<___;
mulq $m1 # np[j]*m1
cmp $num,$j
- jne .L1st
-
- movq %xmm0,$m0 # bp[1]
+ jne .L1st # note that upon exit $j==$num, so
+ # they can be used interchangeably
add %rax,$hi1
- mov ($ap),%rax # ap[0]
adc \$0,%rdx
add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0]
adc \$0,%rdx
- mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov $hi1,-16(%rsp,$num,8) # tp[num-1]
mov %rdx,$hi1
mov $lo0,$hi0
@@ -222,33 +258,48 @@ $code.=<<___;
jmp .Louter
.align 16
.Louter:
+ lea 24+128(%rsp,$num,8),%rdx # where 256-byte mask is (+size optimization)
+ and \$-16,%rdx
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+for($k=0;$k<$STRIDE/16;$k+=4) {
+$code.=<<___;
+ movdqa `16*($k+0)-128`($bp),%xmm0
+ movdqa `16*($k+1)-128`($bp),%xmm1
+ movdqa `16*($k+2)-128`($bp),%xmm2
+ movdqa `16*($k+3)-128`($bp),%xmm3
+ pand `16*($k+0)-128`(%rdx),%xmm0
+ pand `16*($k+1)-128`(%rdx),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($k+2)-128`(%rdx),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($k+3)-128`(%rdx),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
+ lea $STRIDE($bp),$bp
+
+ mov ($ap),%rax # ap[0]
+ movq %xmm0,$m0 # m0=bp[i]
+
xor $j,$j # j=0
mov $n0,$m1
mov (%rsp),$lo0
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
-
mulq $m0 # ap[0]*bp[i]
add %rax,$lo0 # ap[0]*bp[i]+tp[0]
mov ($np),%rax
adc \$0,%rdx
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
-
imulq $lo0,$m1 # tp[0]*n0
mov %rdx,$hi0
- por %xmm2,%xmm0
- lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
-
mulq $m1 # np[0]*m1
add %rax,$lo0 # discarded
mov 8($ap),%rax
@@ -282,17 +333,14 @@ $code.=<<___;
mulq $m1 # np[j]*m1
cmp $num,$j
- jne .Linner
-
- movq %xmm0,$m0 # bp[i+1]
-
+ jne .Linner # note that upon exit $j==$num, so
+ # they can be used interchangeably
add %rax,$hi1
- mov ($ap),%rax # ap[0]
adc \$0,%rdx
add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j]
- mov (%rsp,$j,8),$lo0
+ mov (%rsp,$num,8),$lo0
adc \$0,%rdx
- mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov $hi1,-16(%rsp,$num,8) # tp[num-1]
mov %rdx,$hi1
xor %rdx,%rdx
@@ -338,12 +386,7 @@ $code.=<<___;
mov 8(%rsp,$num,8),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -365,8 +408,8 @@ bn_mul4x_mont_gather5:
.Lmul4x_enter:
___
$code.=<<___ if ($addx);
- and \$0x80100,%r11d
- cmp \$0x80100,%r11d
+ and \$0x80108,%r11d
+ cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1
je .Lmulx4x_enter
___
$code.=<<___;
@@ -378,39 +421,34 @@ $code.=<<___;
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
+
.byte 0x67
- mov ${num}d,%r10d
- shl \$3,${num}d
- shl \$3+2,%r10d # 4*$num
+ shl \$3,${num}d # convert $num to bytes
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num # -$num
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic. [excessive frame is allocated in order
- # to allow bn_from_mont8x to clear it.]
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra [num] is allocated in order
+ # to align with bn_power5's frame, which is cleansed after
+ # completing exponentiation. Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $ap,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmul4xsp_alt
- sub %r11,%rsp # align with $ap
- lea -64(%rsp,$num,2),%rsp # alloca(128+num*8)
+ sub %r11,%rsp # align with $rp
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
jmp .Lmul4xsp_done
.align 32
.Lmul4xsp_alt:
- lea 4096-64(,$num,2),%r10
- lea -64(%rsp,$num,2),%rsp # alloca(128+num*8)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -426,12 +464,7 @@ $code.=<<___;
mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -446,9 +479,10 @@ $code.=<<___;
.type mul4x_internal,\@abi-omnipotent
.align 32
mul4x_internal:
- shl \$5,$num
- mov `($win64?56:8)`(%rax),%r10d # load 7th argument
- lea 256(%rdx,$num),%r13
+ shl \$5,$num # $num was in bytes
+ movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument, index
+ lea .Linc(%rip),%rax
+ lea 128(%rdx,$num),%r13 # end of powers table (+size optimization)
shr \$5,$num # restore $num
___
$bp="%r12";
@@ -456,44 +490,92 @@ ___
$N=$STRIDE/4; # should match cache line size
$tp=$i;
$code.=<<___;
- mov %r10,%r11
- shr \$`log($N/8)/log(2)`,%r10
- and \$`$N/8-1`,%r11
- not %r10
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
- lea 96(%rdx,%r11,8),$bp # pointer within 1st cache line
- movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
- movq 8(%rax,%r10,8),%xmm5 # cache line contains element
- add \$7,%r11
- movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,%r10,8),%xmm7
- and \$7,%r11
-
- movq `0*$STRIDE/4-96`($bp),%xmm0
- lea $STRIDE($bp),$tp # borrow $tp
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bp),%xmm3
- pand %xmm6,%xmm2
- .byte 0x67
- por %xmm1,%xmm0
- movq `0*$STRIDE/4-96`($tp),%xmm1
- .byte 0x67
- pand %xmm7,%xmm3
- .byte 0x67
- por %xmm2,%xmm0
- movq `1*$STRIDE/4-96`($tp),%xmm2
+ movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002
+ lea 88-112(%rsp,$num),%r10 # place the mask after tp[num+1] (+ICache optimization)
+ lea 128(%rdx),$bp # size optimization
+
+ pshufd \$0,%xmm5,%xmm5 # broadcast index
+ movdqa %xmm1,%xmm4
+ .byte 0x67,0x67
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
.byte 0x67
- pand %xmm4,%xmm1
+ movdqa %xmm4,%xmm3
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+ movdqa %xmm4,%xmm2
+
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ movdqa %xmm4,%xmm3
+___
+}
+$code.=<<___; # last iteration can be optimized
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+
+ paddd %xmm2,%xmm3
.byte 0x67
- por %xmm3,%xmm0
- movq `2*$STRIDE/4-96`($tp),%xmm3
+ pcmpeqd %xmm5,%xmm2
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+ pcmpeqd %xmm5,%xmm3
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+ pand `16*($i+0)-128`($bp),%xmm0 # while it's still in register
+
+ pand `16*($i+1)-128`($bp),%xmm1
+ pand `16*($i+2)-128`($bp),%xmm2
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ pand `16*($i+3)-128`($bp),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bp),%xmm4
+ movdqa `16*($i+1)-128`($bp),%xmm5
+ movdqa `16*($i+2)-128`($bp),%xmm2
+ pand `16*($i+0)+112`(%r10),%xmm4
+ movdqa `16*($i+3)-128`($bp),%xmm3
+ pand `16*($i+1)+112`(%r10),%xmm5
+ por %xmm4,%xmm0
+ pand `16*($i+2)+112`(%r10),%xmm2
+ por %xmm5,%xmm1
+ pand `16*($i+3)+112`(%r10),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+}
+$code.=<<___;
+ por %xmm1,%xmm0
+ pshufd \$0x4e,%xmm0,%xmm1
+ por %xmm1,%xmm0
+ lea $STRIDE($bp),$bp
movq %xmm0,$m0 # m0=bp[0]
- movq `3*$STRIDE/4-96`($tp),%xmm0
+
mov %r13,16+8(%rsp) # save end of b[num]
mov $rp, 56+8(%rsp) # save $rp
@@ -507,26 +589,10 @@ $code.=<<___;
mov %rax,$A[0]
mov ($np),%rax
- pand %xmm5,%xmm2
- pand %xmm6,%xmm3
- por %xmm2,%xmm1
-
imulq $A[0],$m1 # "tp[0]"*n0
- ##############################################################
- # $tp is chosen so that writing to top-most element of the
- # vector occurs just "above" references to powers table,
- # "above" modulo cache-line size, which effectively precludes
- # possibility of memory disambiguation logic failure when
- # accessing the table.
- #
- lea 64+8(%rsp,%r11,8),$tp
+ lea 64+8(%rsp),$tp
mov %rdx,$A[1]
- pand %xmm7,%xmm0
- por %xmm3,%xmm1
- lea 2*$STRIDE($bp),$bp
- por %xmm1,%xmm0
-
mulq $m1 # np[0]*m1
add %rax,$A[0] # discarded
mov 8($ap,$num),%rax
@@ -535,7 +601,7 @@ $code.=<<___;
mulq $m0
add %rax,$A[1]
- mov 16*1($np),%rax # interleaved with 0, therefore 16*n
+ mov 8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -545,7 +611,7 @@ $code.=<<___;
adc \$0,%rdx
add $A[1],$N[1]
lea 4*8($num),$j # j=4
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov $N[1],($tp)
mov %rdx,$N[0]
@@ -555,7 +621,7 @@ $code.=<<___;
.L1st4x:
mulq $m0 # ap[j]*bp[0]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
lea 32($tp),$tp
adc \$0,%rdx
mov %rdx,$A[1]
@@ -571,7 +637,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[1]
- mov -16*1($np),%rax
+ mov -8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -586,7 +652,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[0]
- mov 16*0($np),%rax
+ mov 8*0($np),%rax
adc \$0,%rdx
mov %rdx,$A[1]
@@ -601,7 +667,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[1]
- mov 16*1($np),%rax
+ mov 8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -610,7 +676,7 @@ $code.=<<___;
mov 16($ap,$j),%rax
adc \$0,%rdx
add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov $N[1],($tp) # tp[j-1]
mov %rdx,$N[0]
@@ -620,7 +686,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
lea 32($tp),$tp
adc \$0,%rdx
mov %rdx,$A[1]
@@ -636,7 +702,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[0]
add %rax,$A[1]
- mov -16*1($np),%rax
+ mov -8*1($np),%rax
adc \$0,%rdx
mov %rdx,$A[0]
@@ -649,8 +715,7 @@ $code.=<<___;
mov $N[1],-16($tp) # tp[j-1]
mov %rdx,$N[0]
- movq %xmm0,$m0 # bp[1]
- lea ($np,$num,2),$np # rewind $np
+ lea ($np,$num),$np # rewind $np
xor $N[1],$N[1]
add $A[0],$N[0]
@@ -661,6 +726,33 @@ $code.=<<___;
.align 32
.Louter4x:
+ lea 16+128($tp),%rdx # where 256-byte mask is (+size optimization)
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bp),%xmm0
+ movdqa `16*($i+1)-128`($bp),%xmm1
+ movdqa `16*($i+2)-128`($bp),%xmm2
+ movdqa `16*($i+3)-128`($bp),%xmm3
+ pand `16*($i+0)-128`(%rdx),%xmm0
+ pand `16*($i+1)-128`(%rdx),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($i+2)-128`(%rdx),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($i+3)-128`(%rdx),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
+ lea $STRIDE($bp),$bp
+ movq %xmm0,$m0 # m0=bp[i]
+
mov ($tp,$num),$A[0]
mov $n0,$m1
mulq $m0 # ap[0]*bp[i]
@@ -668,25 +760,11 @@ $code.=<<___;
mov ($np),%rax
adc \$0,%rdx
- movq `0*$STRIDE/4-96`($bp),%xmm0
- movq `1*$STRIDE/4-96`($bp),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bp),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bp),%xmm3
-
imulq $A[0],$m1 # tp[0]*n0
- .byte 0x67
mov %rdx,$A[1]
mov $N[1],($tp) # store upmost overflow bit
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
- por %xmm2,%xmm0
lea ($tp,$num),$tp # rewind $tp
- lea $STRIDE($bp),$bp
- por %xmm3,%xmm0
mulq $m1 # np[0]*m1
add %rax,$A[0] # "$N[0]", discarded
@@ -696,7 +774,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
- mov 16*1($np),%rax # interleaved with 0, therefore 16*n
+ mov 8*1($np),%rax
adc \$0,%rdx
add 8($tp),$A[1] # +tp[1]
adc \$0,%rdx
@@ -708,7 +786,7 @@ $code.=<<___;
adc \$0,%rdx
add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j]
lea 4*8($num),$j # j=4
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov %rdx,$N[0]
jmp .Linner4x
@@ -717,7 +795,7 @@ $code.=<<___;
.Linner4x:
mulq $m0 # ap[j]*bp[i]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
adc \$0,%rdx
add 16($tp),$A[0] # ap[j]*bp[i]+tp[j]
lea 32($tp),$tp
@@ -735,7 +813,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
- mov -16*1($np),%rax
+ mov -8*1($np),%rax
adc \$0,%rdx
add -8($tp),$A[1]
adc \$0,%rdx
@@ -752,7 +830,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[0]
- mov 16*0($np),%rax
+ mov 8*0($np),%rax
adc \$0,%rdx
add ($tp),$A[0] # ap[j]*bp[i]+tp[j]
adc \$0,%rdx
@@ -769,7 +847,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
- mov 16*1($np),%rax
+ mov 8*1($np),%rax
adc \$0,%rdx
add 8($tp),$A[1]
adc \$0,%rdx
@@ -780,7 +858,7 @@ $code.=<<___;
mov 16($ap,$j),%rax
adc \$0,%rdx
add $A[1],$N[1]
- lea 16*4($np),$np
+ lea 8*4($np),$np
adc \$0,%rdx
mov $N[0],-8($tp) # tp[j-1]
mov %rdx,$N[0]
@@ -790,7 +868,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[0]
- mov -16*2($np),%rax
+ mov -8*2($np),%rax
adc \$0,%rdx
add 16($tp),$A[0] # ap[j]*bp[i]+tp[j]
lea 32($tp),$tp
@@ -809,7 +887,7 @@ $code.=<<___;
mulq $m0 # ap[j]*bp[i]
add %rax,$A[1]
mov $m1,%rax
- mov -16*1($np),$m1
+ mov -8*1($np),$m1
adc \$0,%rdx
add -8($tp),$A[1]
adc \$0,%rdx
@@ -824,9 +902,8 @@ $code.=<<___;
mov $N[0],-24($tp) # tp[j-1]
mov %rdx,$N[0]
- movq %xmm0,$m0 # bp[i+1]
mov $N[1],-16($tp) # tp[j-1]
- lea ($np,$num,2),$np # rewind $np
+ lea ($np,$num),$np # rewind $np
xor $N[1],$N[1]
add $A[0],$N[0]
@@ -840,16 +917,23 @@ $code.=<<___;
___
if (1) {
$code.=<<___;
+ xor %rax,%rax
sub $N[0],$m1 # compare top-most words
adc $j,$j # $j is zero
or $j,$N[1]
- xor \$1,$N[1]
+ sub $N[1],%rax # %rax=-$N[1]
lea ($tp,$num),%rbx # tptr in .sqr4x_sub
- lea ($np,$N[1],8),%rbp # nptr in .sqr4x_sub
+ mov ($np),%r12
+ lea ($np),%rbp # nptr in .sqr4x_sub
mov %r9,%rcx
- sar \$3+2,%rcx # cf=0
+ sar \$3+2,%rcx
mov 56+8(%rsp),%rdi # rptr in .sqr4x_sub
- jmp .Lsqr4x_sub
+ dec %r12 # so that after 'not' we get -n[0]
+ xor %r10,%r10
+ mov 8*1(%rbp),%r13
+ mov 8*2(%rbp),%r14
+ mov 8*3(%rbp),%r15
+ jmp .Lsqr4x_sub_entry
___
} else {
my @ri=("%rax",$bp,$m0,$m1);
@@ -916,8 +1000,8 @@ bn_power5:
___
$code.=<<___ if ($addx);
mov OPENSSL_ia32cap_P+8(%rip),%r11d
- and \$0x80100,%r11d
- cmp \$0x80100,%r11d
+ and \$0x80108,%r11d
+ cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1
je .Lpowerx5_enter
___
$code.=<<___;
@@ -928,38 +1012,32 @@ $code.=<<___;
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10d # 3*$num
neg $num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic.
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $aptr,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwr_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
jmp .Lpwr_sp_done
.align 32
.Lpwr_sp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -981,16 +1059,21 @@ $code.=<<___;
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.Lpower5_body:
- movq $rptr,%xmm1 # save $rptr
+ movq $rptr,%xmm1 # save $rptr, used in sqr8x
movq $nptr,%xmm2 # save $nptr
- movq %r10, %xmm3 # -$num
+ movq %r10, %xmm3 # -$num, used in sqr8x
movq $bptr,%xmm4
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
call __bn_sqr8x_internal
+ call __bn_post4x_internal
movq %xmm2,$nptr
movq %xmm4,$bptr
@@ -1551,9 +1634,9 @@ my ($nptr,$tptr,$carry,$m0)=("%rbp","%rdi","%rsi","%rbx");
$code.=<<___;
movq %xmm2,$nptr
-sqr8x_reduction:
+__bn_sqr8x_reduction:
xor %rax,%rax
- lea ($nptr,$num,2),%rcx # end of n[]
+ lea ($nptr,$num),%rcx # end of n[]
lea 48+8(%rsp,$num,2),%rdx # end of t[] buffer
mov %rcx,0+8(%rsp)
lea 48+8(%rsp,$num),$tptr # end of initial t[] window
@@ -1579,21 +1662,21 @@ sqr8x_reduction:
.byte 0x67
mov $m0,%r8
imulq 32+8(%rsp),$m0 # n0*a[0]
- mov 16*0($nptr),%rax # n[0]
+ mov 8*0($nptr),%rax # n[0]
mov \$8,%ecx
jmp .L8x_reduce
.align 32
.L8x_reduce:
mulq $m0
- mov 16*1($nptr),%rax # n[1]
+ mov 8*1($nptr),%rax # n[1]
neg %r8
mov %rdx,%r8
adc \$0,%r8
mulq $m0
add %rax,%r9
- mov 16*2($nptr),%rax
+ mov 8*2($nptr),%rax
adc \$0,%rdx
add %r9,%r8
mov $m0,48-8+8(%rsp,%rcx,8) # put aside n0*a[i]
@@ -1602,7 +1685,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r10
- mov 16*3($nptr),%rax
+ mov 8*3($nptr),%rax
adc \$0,%rdx
add %r10,%r9
mov 32+8(%rsp),$carry # pull n0, borrow $carry
@@ -1611,7 +1694,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r11
- mov 16*4($nptr),%rax
+ mov 8*4($nptr),%rax
adc \$0,%rdx
imulq %r8,$carry # modulo-scheduled
add %r11,%r10
@@ -1620,7 +1703,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r12
- mov 16*5($nptr),%rax
+ mov 8*5($nptr),%rax
adc \$0,%rdx
add %r12,%r11
mov %rdx,%r12
@@ -1628,7 +1711,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r13
- mov 16*6($nptr),%rax
+ mov 8*6($nptr),%rax
adc \$0,%rdx
add %r13,%r12
mov %rdx,%r13
@@ -1636,7 +1719,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r14
- mov 16*7($nptr),%rax
+ mov 8*7($nptr),%rax
adc \$0,%rdx
add %r14,%r13
mov %rdx,%r14
@@ -1645,7 +1728,7 @@ sqr8x_reduction:
mulq $m0
mov $carry,$m0 # n0*a[i]
add %rax,%r15
- mov 16*0($nptr),%rax # n[0]
+ mov 8*0($nptr),%rax # n[0]
adc \$0,%rdx
add %r15,%r14
mov %rdx,%r15
@@ -1654,7 +1737,7 @@ sqr8x_reduction:
dec %ecx
jnz .L8x_reduce
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
xor %rax,%rax
mov 8+8(%rsp),%rdx # pull end of t[]
cmp 0+8(%rsp),$nptr # end of n[]?
@@ -1673,21 +1756,21 @@ sqr8x_reduction:
mov 48+56+8(%rsp),$m0 # pull n0*a[0]
mov \$8,%ecx
- mov 16*0($nptr),%rax
+ mov 8*0($nptr),%rax
jmp .L8x_tail
.align 32
.L8x_tail:
mulq $m0
add %rax,%r8
- mov 16*1($nptr),%rax
+ mov 8*1($nptr),%rax
mov %r8,($tptr) # save result
mov %rdx,%r8
adc \$0,%r8
mulq $m0
add %rax,%r9
- mov 16*2($nptr),%rax
+ mov 8*2($nptr),%rax
adc \$0,%rdx
add %r9,%r8
lea 8($tptr),$tptr # $tptr++
@@ -1696,7 +1779,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r10
- mov 16*3($nptr),%rax
+ mov 8*3($nptr),%rax
adc \$0,%rdx
add %r10,%r9
mov %rdx,%r10
@@ -1704,7 +1787,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r11
- mov 16*4($nptr),%rax
+ mov 8*4($nptr),%rax
adc \$0,%rdx
add %r11,%r10
mov %rdx,%r11
@@ -1712,7 +1795,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r12
- mov 16*5($nptr),%rax
+ mov 8*5($nptr),%rax
adc \$0,%rdx
add %r12,%r11
mov %rdx,%r12
@@ -1720,7 +1803,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r13
- mov 16*6($nptr),%rax
+ mov 8*6($nptr),%rax
adc \$0,%rdx
add %r13,%r12
mov %rdx,%r13
@@ -1728,7 +1811,7 @@ sqr8x_reduction:
mulq $m0
add %rax,%r14
- mov 16*7($nptr),%rax
+ mov 8*7($nptr),%rax
adc \$0,%rdx
add %r14,%r13
mov %rdx,%r14
@@ -1739,14 +1822,14 @@ sqr8x_reduction:
add %rax,%r15
adc \$0,%rdx
add %r15,%r14
- mov 16*0($nptr),%rax # pull n[0]
+ mov 8*0($nptr),%rax # pull n[0]
mov %rdx,%r15
adc \$0,%r15
dec %ecx
jnz .L8x_tail
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
mov 8+8(%rsp),%rdx # pull end of t[]
cmp 0+8(%rsp),$nptr # end of n[]?
jae .L8x_tail_done # break out of loop
@@ -1792,7 +1875,7 @@ sqr8x_reduction:
adc 8*6($tptr),%r14
adc 8*7($tptr),%r15
adc \$0,%rax # top-most carry
- mov -16($nptr),%rcx # np[num-1]
+ mov -8($nptr),%rcx # np[num-1]
xor $carry,$carry
movq %xmm2,$nptr # restore $nptr
@@ -1810,6 +1893,8 @@ sqr8x_reduction:
cmp %rdx,$tptr # end of t[]?
jb .L8x_reduction_loop
+ ret
+.size bn_sqr8x_internal,.-bn_sqr8x_internal
___
}
##############################################################
@@ -1818,48 +1903,62 @@ ___
{
my ($tptr,$nptr)=("%rbx","%rbp");
$code.=<<___;
- #xor %rsi,%rsi # %rsi was $carry above
- sub %r15,%rcx # compare top-most words
+.type __bn_post4x_internal,\@abi-omnipotent
+.align 32
+__bn_post4x_internal:
+ mov 8*0($nptr),%r12
lea (%rdi,$num),$tptr # %rdi was $tptr above
- adc %rsi,%rsi
mov $num,%rcx
- or %rsi,%rax
movq %xmm1,$rptr # restore $rptr
- xor \$1,%rax
+ neg %rax
movq %xmm1,$aptr # prepare for back-to-back call
- lea ($nptr,%rax,8),$nptr
- sar \$3+2,%rcx # cf=0
- jmp .Lsqr4x_sub
+ sar \$3+2,%rcx
+ dec %r12 # so that after 'not' we get -n[0]
+ xor %r10,%r10
+ mov 8*1($nptr),%r13
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+ jmp .Lsqr4x_sub_entry
-.align 32
+.align 16
.Lsqr4x_sub:
- .byte 0x66
- mov 8*0($tptr),%r12
- mov 8*1($tptr),%r13
- sbb 16*0($nptr),%r12
- mov 8*2($tptr),%r14
- sbb 16*1($nptr),%r13
- mov 8*3($tptr),%r15
- lea 8*4($tptr),$tptr
- sbb 16*2($nptr),%r14
+ mov 8*0($nptr),%r12
+ mov 8*1($nptr),%r13
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+.Lsqr4x_sub_entry:
+ lea 8*4($nptr),$nptr
+ not %r12
+ not %r13
+ not %r14
+ not %r15
+ and %rax,%r12
+ and %rax,%r13
+ and %rax,%r14
+ and %rax,%r15
+
+ neg %r10 # mov %r10,%cf
+ adc 8*0($tptr),%r12
+ adc 8*1($tptr),%r13
+ adc 8*2($tptr),%r14
+ adc 8*3($tptr),%r15
mov %r12,8*0($rptr)
- sbb 16*3($nptr),%r15
- lea 16*4($nptr),$nptr
+ lea 8*4($tptr),$tptr
mov %r13,8*1($rptr)
+ sbb %r10,%r10 # mov %cf,%r10
mov %r14,8*2($rptr)
mov %r15,8*3($rptr)
lea 8*4($rptr),$rptr
inc %rcx # pass %cf
jnz .Lsqr4x_sub
-___
-}
-$code.=<<___;
+
mov $num,%r10 # prepare for back-to-back call
neg $num # restore $num
ret
-.size bn_sqr8x_internal,.-bn_sqr8x_internal
+.size __bn_post4x_internal,.-__bn_post4x_internal
___
+}
{
$code.=<<___;
.globl bn_from_montgomery
@@ -1883,39 +1982,32 @@ bn_from_mont8x:
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- .byte 0x67
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic.
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). The stack is allocated to aligned with
+ # bn_power5's frame, and as bn_from_montgomery happens to be
+ # last operation, we use the opportunity to cleanse it.
#
- lea -64(%rsp,$num,2),%r11
- sub $aptr,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lfrom_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lfrom_sp_done
.align 32
.Lfrom_sp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -1969,12 +2061,13 @@ $code.=<<___;
___
$code.=<<___ if ($addx);
mov OPENSSL_ia32cap_P+8(%rip),%r11d
- and \$0x80100,%r11d
- cmp \$0x80100,%r11d
+ and \$0x80108,%r11d
+ cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1
jne .Lfrom_mont_nox
lea (%rax,$num),$rptr
- call sqrx8x_reduction
+ call __bn_sqrx8x_reduction
+ call __bn_postx4x_internal
pxor %xmm0,%xmm0
lea 48(%rsp),%rax
@@ -1985,7 +2078,8 @@ $code.=<<___ if ($addx);
.Lfrom_mont_nox:
___
$code.=<<___;
- call sqr8x_reduction
+ call __bn_sqr8x_reduction
+ call __bn_post4x_internal
pxor %xmm0,%xmm0
lea 48(%rsp),%rax
@@ -2025,7 +2119,6 @@ $code.=<<___;
.align 32
bn_mulx4x_mont_gather5:
.Lmulx4x_enter:
- .byte 0x67
mov %rsp,%rax
push %rbx
push %rbp
@@ -2033,40 +2126,33 @@ bn_mulx4x_mont_gather5:
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- .byte 0x67
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num # -$num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers a[num], ret[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic. [excessive frame is allocated in order
- # to allow bn_from_mont8x to clear it.]
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra [num] is allocated in order
+ # to align with bn_power5's frame, which is cleansed after
+ # completing exponentiation. Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $ap,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmulx4xsp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lmulx4xsp_done
-.align 32
.Lmulx4xsp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -2092,12 +2178,7 @@ $code.=<<___;
mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -2112,14 +2193,16 @@ $code.=<<___;
.type mulx4x_internal,\@abi-omnipotent
.align 32
mulx4x_internal:
- .byte 0x4c,0x89,0x8c,0x24,0x08,0x00,0x00,0x00 # mov $num,8(%rsp) # save -$num
- .byte 0x67
+ mov $num,8(%rsp) # save -$num (it was in bytes)
+ mov $num,%r10
neg $num # restore $num
shl \$5,$num
- lea 256($bp,$num),%r13
+ neg %r10 # restore $num
+ lea 128($bp,$num),%r13 # end of powers table (+size optimization)
shr \$5+5,$num
- mov `($win64?56:8)`(%rax),%r10d # load 7th argument
+ movd `($win64?56:8)`(%rax),%xmm5 # load 7th argument
sub \$1,$num
+ lea .Linc(%rip),%rax
mov %r13,16+8(%rsp) # end of b[num]
mov $num,24+8(%rsp) # inner counter
mov $rp, 56+8(%rsp) # save $rp
@@ -2130,52 +2213,92 @@ my $rptr=$bptr;
my $STRIDE=2**5*8; # 5 is "window size"
my $N=$STRIDE/4; # should match cache line size
$code.=<<___;
- mov %r10,%r11
- shr \$`log($N/8)/log(2)`,%r10
- and \$`$N/8-1`,%r11
- not %r10
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
- lea 96($bp,%r11,8),$bptr # pointer within 1st cache line
- movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
- movq 8(%rax,%r10,8),%xmm5 # cache line contains element
- add \$7,%r11
- movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,%r10,8),%xmm7
- and \$7,%r11
-
- movq `0*$STRIDE/4-96`($bptr),%xmm0
- lea $STRIDE($bptr),$tptr # borrow $tptr
- movq `1*$STRIDE/4-96`($bptr),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bptr),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bptr),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- movq `0*$STRIDE/4-96`($tptr),%xmm1
- pand %xmm7,%xmm3
- por %xmm2,%xmm0
- movq `1*$STRIDE/4-96`($tptr),%xmm2
- por %xmm3,%xmm0
- .byte 0x67,0x67
- pand %xmm4,%xmm1
- movq `2*$STRIDE/4-96`($tptr),%xmm3
+ movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002
+ lea 88-112(%rsp,%r10),%r10 # place the mask after tp[num+1] (+ICache optimizaton)
+ lea 128($bp),$bptr # size optimization
+ pshufd \$0,%xmm5,%xmm5 # broadcast index
+ movdqa %xmm1,%xmm4
+ .byte 0x67
+ movdqa %xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+ .byte 0x67
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
+ movdqa %xmm4,%xmm3
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+ movdqa %xmm4,%xmm2
+
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ movdqa %xmm4,%xmm3
+___
+}
+$code.=<<___; # last iteration can be optimized
+ .byte 0x67
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1
+ movdqa %xmm0,`16*($i+0)+112`(%r10)
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2
+ movdqa %xmm1,`16*($i+1)+112`(%r10)
+
+ pcmpeqd %xmm5,%xmm3
+ movdqa %xmm2,`16*($i+2)+112`(%r10)
+
+ pand `16*($i+0)-128`($bptr),%xmm0 # while it's still in register
+ pand `16*($i+1)-128`($bptr),%xmm1
+ pand `16*($i+2)-128`($bptr),%xmm2
+ movdqa %xmm3,`16*($i+3)+112`(%r10)
+ pand `16*($i+3)-128`($bptr),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bptr),%xmm4
+ movdqa `16*($i+1)-128`($bptr),%xmm5
+ movdqa `16*($i+2)-128`($bptr),%xmm2
+ pand `16*($i+0)+112`(%r10),%xmm4
+ movdqa `16*($i+3)-128`($bptr),%xmm3
+ pand `16*($i+1)+112`(%r10),%xmm5
+ por %xmm4,%xmm0
+ pand `16*($i+2)+112`(%r10),%xmm2
+ por %xmm5,%xmm1
+ pand `16*($i+3)+112`(%r10),%xmm3
+ por %xmm2,%xmm0
+ por %xmm3,%xmm1
+___
+}
+$code.=<<___;
+ pxor %xmm1,%xmm0
+ pshufd \$0x4e,%xmm0,%xmm1
+ por %xmm1,%xmm0
+ lea $STRIDE($bptr),$bptr
movq %xmm0,%rdx # bp[0]
- movq `3*$STRIDE/4-96`($tptr),%xmm0
- lea 2*$STRIDE($bptr),$bptr # next &b[i]
- pand %xmm5,%xmm2
- .byte 0x67,0x67
- pand %xmm6,%xmm3
- ##############################################################
- # $tptr is chosen so that writing to top-most element of the
- # vector occurs just "above" references to powers table,
- # "above" modulo cache-line size, which effectively precludes
- # possibility of memory disambiguation logic failure when
- # accessing the table.
- #
- lea 64+8*4+8(%rsp,%r11,8),$tptr
+ lea 64+8*4+8(%rsp),$tptr
mov %rdx,$bi
mulx 0*8($aptr),$mi,%rax # a[0]*b[0]
@@ -2191,37 +2314,31 @@ $code.=<<___;
xor $zero,$zero # cf=0, of=0
mov $mi,%rdx
- por %xmm2,%xmm1
- pand %xmm7,%xmm0
- por %xmm3,%xmm1
mov $bptr,8+8(%rsp) # off-load &b[i]
- por %xmm1,%xmm0
- .byte 0x48,0x8d,0xb6,0x20,0x00,0x00,0x00 # lea 4*8($aptr),$aptr
+ lea 4*8($aptr),$aptr
adcx %rax,%r13
adcx $zero,%r14 # cf=0
- mulx 0*16($nptr),%rax,%r10
+ mulx 0*8($nptr),%rax,%r10
adcx %rax,%r15 # discarded
adox %r11,%r10
- mulx 1*16($nptr),%rax,%r11
+ mulx 1*8($nptr),%rax,%r11
adcx %rax,%r10
adox %r12,%r11
- mulx 2*16($nptr),%rax,%r12
+ mulx 2*8($nptr),%rax,%r12
mov 24+8(%rsp),$bptr # counter value
- .byte 0x66
mov %r10,-8*4($tptr)
adcx %rax,%r11
adox %r13,%r12
- mulx 3*16($nptr),%rax,%r15
- .byte 0x67,0x67
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
mov %r11,-8*3($tptr)
adcx %rax,%r12
adox $zero,%r15 # of=0
- .byte 0x48,0x8d,0x89,0x40,0x00,0x00,0x00 # lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
mov %r12,-8*2($tptr)
- #jmp .Lmulx4x_1st
+ jmp .Lmulx4x_1st
.align 32
.Lmulx4x_1st:
@@ -2241,30 +2358,29 @@ $code.=<<___;
lea 4*8($tptr),$tptr
adox %r15,%r10
- mulx 0*16($nptr),%rax,%r15
+ mulx 0*8($nptr),%rax,%r15
adcx %rax,%r10
adox %r15,%r11
- mulx 1*16($nptr),%rax,%r15
+ mulx 1*8($nptr),%rax,%r15
adcx %rax,%r11
adox %r15,%r12
- mulx 2*16($nptr),%rax,%r15
+ mulx 2*8($nptr),%rax,%r15
mov %r10,-5*8($tptr)
adcx %rax,%r12
mov %r11,-4*8($tptr)
adox %r15,%r13
- mulx 3*16($nptr),%rax,%r15
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
mov %r12,-3*8($tptr)
adcx %rax,%r13
adox $zero,%r15
- lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
mov %r13,-2*8($tptr)
dec $bptr # of=0, pass cf
jnz .Lmulx4x_1st
mov 8(%rsp),$num # load -num
- movq %xmm0,%rdx # bp[1]
adc $zero,%r15 # modulo-scheduled
lea ($aptr,$num),$aptr # rewind $aptr
add %r15,%r14
@@ -2275,6 +2391,34 @@ $code.=<<___;
.align 32
.Lmulx4x_outer:
+ lea 16-256($tptr),%r10 # where 256-byte mask is (+density control)
+ pxor %xmm4,%xmm4
+ .byte 0x67,0x67
+ pxor %xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`($bptr),%xmm0
+ movdqa `16*($i+1)-128`($bptr),%xmm1
+ movdqa `16*($i+2)-128`($bptr),%xmm2
+ pand `16*($i+0)+256`(%r10),%xmm0
+ movdqa `16*($i+3)-128`($bptr),%xmm3
+ pand `16*($i+1)+256`(%r10),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($i+2)+256`(%r10),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($i+3)+256`(%r10),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
+ lea $STRIDE($bptr),$bptr
+ movq %xmm0,%rdx # m0=bp[i]
+
mov $zero,($tptr) # save top-most carry
lea 4*8($tptr,$num),$tptr # rewind $tptr
mulx 0*8($aptr),$mi,%r11 # a[0]*b[i]
@@ -2289,54 +2433,37 @@ $code.=<<___;
mulx 3*8($aptr),%rdx,%r14
adox -2*8($tptr),%r12
adcx %rdx,%r13
- lea ($nptr,$num,2),$nptr # rewind $nptr
+ lea ($nptr,$num),$nptr # rewind $nptr
lea 4*8($aptr),$aptr
adox -1*8($tptr),%r13
adcx $zero,%r14
adox $zero,%r14
- .byte 0x67
mov $mi,%r15
imulq 32+8(%rsp),$mi # "t[0]"*n0
- movq `0*$STRIDE/4-96`($bptr),%xmm0
- .byte 0x67,0x67
mov $mi,%rdx
- movq `1*$STRIDE/4-96`($bptr),%xmm1
- .byte 0x67
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-96`($bptr),%xmm2
- .byte 0x67
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-96`($bptr),%xmm3
- add \$$STRIDE,$bptr # next &b[i]
- .byte 0x67
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
xor $zero,$zero # cf=0, of=0
mov $bptr,8+8(%rsp) # off-load &b[i]
- mulx 0*16($nptr),%rax,%r10
+ mulx 0*8($nptr),%rax,%r10
adcx %rax,%r15 # discarded
adox %r11,%r10
- mulx 1*16($nptr),%rax,%r11
+ mulx 1*8($nptr),%rax,%r11
adcx %rax,%r10
adox %r12,%r11
- mulx 2*16($nptr),%rax,%r12
+ mulx 2*8($nptr),%rax,%r12
adcx %rax,%r11
adox %r13,%r12
- mulx 3*16($nptr),%rax,%r15
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
- por %xmm2,%xmm0
mov 24+8(%rsp),$bptr # counter value
mov %r10,-8*4($tptr)
- por %xmm3,%xmm0
adcx %rax,%r12
mov %r11,-8*3($tptr)
adox $zero,%r15 # of=0
mov %r12,-8*2($tptr)
- lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
jmp .Lmulx4x_inner
.align 32
@@ -2361,20 +2488,20 @@ $code.=<<___;
adcx $zero,%r14 # cf=0
adox %r15,%r10
- mulx 0*16($nptr),%rax,%r15
+ mulx 0*8($nptr),%rax,%r15
adcx %rax,%r10
adox %r15,%r11
- mulx 1*16($nptr),%rax,%r15
+ mulx 1*8($nptr),%rax,%r15
adcx %rax,%r11
adox %r15,%r12
- mulx 2*16($nptr),%rax,%r15
+ mulx 2*8($nptr),%rax,%r15
mov %r10,-5*8($tptr)
adcx %rax,%r12
adox %r15,%r13
mov %r11,-4*8($tptr)
- mulx 3*16($nptr),%rax,%r15
+ mulx 3*8($nptr),%rax,%r15
mov $bi,%rdx
- lea 4*16($nptr),$nptr
+ lea 4*8($nptr),$nptr
mov %r12,-3*8($tptr)
adcx %rax,%r13
adox $zero,%r15
@@ -2384,7 +2511,6 @@ $code.=<<___;
jnz .Lmulx4x_inner
mov 0+8(%rsp),$num # load -num
- movq %xmm0,%rdx # bp[i+1]
adc $zero,%r15 # modulo-scheduled
sub 0*8($tptr),$bptr # pull top-most carry to %cf
mov 8+8(%rsp),$bptr # re-load &b[i]
@@ -2397,20 +2523,26 @@ $code.=<<___;
cmp %r10,$bptr
jb .Lmulx4x_outer
- mov -16($nptr),%r10
+ mov -8($nptr),%r10
+ mov $zero,%r8
+ mov ($nptr,$num),%r12
+ lea ($nptr,$num),%rbp # rewind $nptr
+ mov $num,%rcx
+ lea ($tptr,$num),%rdi # rewind $tptr
+ xor %eax,%eax
xor %r15,%r15
sub %r14,%r10 # compare top-most words
adc %r15,%r15
- or %r15,$zero
- xor \$1,$zero
- lea ($tptr,$num),%rdi # rewind $tptr
- lea ($nptr,$num,2),$nptr # rewind $nptr
- .byte 0x67,0x67
- sar \$3+2,$num # cf=0
- lea ($nptr,$zero,8),%rbp
+ or %r15,%r8
+ sar \$3+2,%rcx
+ sub %r8,%rax # %rax=-%r8
mov 56+8(%rsp),%rdx # restore rp
- mov $num,%rcx
- jmp .Lsqrx4x_sub # common post-condition
+ dec %r12 # so that after 'not' we get -n[0]
+ mov 8*1(%rbp),%r13
+ xor %r8,%r8
+ mov 8*2(%rbp),%r14
+ mov 8*3(%rbp),%r15
+ jmp .Lsqrx4x_sub_entry # common post-condition
.size mulx4x_internal,.-mulx4x_internal
___
} {
@@ -2434,7 +2566,6 @@ $code.=<<___;
.align 32
bn_powerx5:
.Lpowerx5_enter:
- .byte 0x67
mov %rsp,%rax
push %rbx
push %rbp
@@ -2442,39 +2573,32 @@ bn_powerx5:
push %r13
push %r14
push %r15
-___
-$code.=<<___ if ($win64);
- lea -0x28(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
-___
-$code.=<<___;
- .byte 0x67
- mov ${num}d,%r10d
+
shl \$3,${num}d # convert $num to bytes
- shl \$3+2,%r10d # 4*$num
+ lea ($num,$num,2),%r10 # 3*$num in bytes
neg $num
mov ($n0),$n0 # *n0
##############################################################
- # ensure that stack frame doesn't alias with $aptr+4*$num
- # modulo 4096, which covers ret[num], am[num] and n[2*num]
- # (see bn_exp.c). this is done to allow memory disambiguation
- # logic do its magic.
+ # Ensure that stack frame doesn't alias with $rptr+3*$num
+ # modulo 4096, which covers ret[num], am[num] and n[num]
+ # (see bn_exp.c). This is done to allow memory disambiguation
+ # logic do its magic. [Extra 256 bytes is for power mask
+ # calculated from 7th argument, the index.]
#
- lea -64(%rsp,$num,2),%r11
- sub $aptr,%r11
+ lea -320(%rsp,$num,2),%r11
+ sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwrx_sp_alt
sub %r11,%rsp # align with $aptr
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lpwrx_sp_done
.align 32
.Lpwrx_sp_alt:
- lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
- lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ lea 4096-320(,$num,2),%r10
+ lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
@@ -2505,10 +2629,15 @@ $code.=<<___;
.Lpowerx5_body:
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
call __bn_sqrx8x_internal
+ call __bn_postx4x_internal
mov %r10,$num # -num
mov $aptr,$rptr
@@ -2520,12 +2649,7 @@ $code.=<<___;
mov 40(%rsp),%rsi # restore %rsp
mov \$1,%rax
-___
-$code.=<<___ if ($win64);
- movaps -88(%rsi),%xmm6
- movaps -72(%rsi),%xmm7
-___
-$code.=<<___;
+
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
@@ -2959,11 +3083,11 @@ my ($nptr,$carry,$m0)=("%rbp","%rsi","%rdx");
$code.=<<___;
movq %xmm2,$nptr
-sqrx8x_reduction:
+__bn_sqrx8x_reduction:
xor %eax,%eax # initial top-most carry bit
mov 32+8(%rsp),%rbx # n0
mov 48+8(%rsp),%rdx # "%r8", 8*0($tptr)
- lea -128($nptr,$num,2),%rcx # end of n[]
+ lea -8*8($nptr,$num),%rcx # end of n[]
#lea 48+8(%rsp,$num,2),$tptr # end of t[] buffer
mov %rcx, 0+8(%rsp) # save end of n[]
mov $tptr,8+8(%rsp) # save end of t[]
@@ -2992,23 +3116,23 @@ sqrx8x_reduction:
.align 32
.Lsqrx8x_reduce:
mov %r8, %rbx
- mulx 16*0($nptr),%rax,%r8 # n[0]
+ mulx 8*0($nptr),%rax,%r8 # n[0]
adcx %rbx,%rax # discarded
adox %r9,%r8
- mulx 16*1($nptr),%rbx,%r9 # n[1]
+ mulx 8*1($nptr),%rbx,%r9 # n[1]
adcx %rbx,%r8
adox %r10,%r9
- mulx 16*2($nptr),%rbx,%r10
+ mulx 8*2($nptr),%rbx,%r10
adcx %rbx,%r9
adox %r11,%r10
- mulx 16*3($nptr),%rbx,%r11
+ mulx 8*3($nptr),%rbx,%r11
adcx %rbx,%r10
adox %r12,%r11
- .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x40,0x00,0x00,0x00 # mulx 16*4($nptr),%rbx,%r12
+ .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rbx,%r12
mov %rdx,%rax
mov %r8,%rdx
adcx %rbx,%r11
@@ -3018,15 +3142,15 @@ sqrx8x_reduction:
mov %rax,%rdx
mov %rax,64+48+8(%rsp,%rcx,8) # put aside n0*a[i]
- mulx 16*5($nptr),%rax,%r13
+ mulx 8*5($nptr),%rax,%r13
adcx %rax,%r12
adox %r14,%r13
- mulx 16*6($nptr),%rax,%r14
+ mulx 8*6($nptr),%rax,%r14
adcx %rax,%r13
adox %r15,%r14
- mulx 16*7($nptr),%rax,%r15
+ mulx 8*7($nptr),%rax,%r15
mov %rbx,%rdx
adcx %rax,%r14
adox $carry,%r15 # $carry is 0
@@ -3042,7 +3166,7 @@ sqrx8x_reduction:
mov 48+8(%rsp),%rdx # pull n0*a[0]
add 8*0($tptr),%r8
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
mov \$-8,%rcx
adcx 8*1($tptr),%r9
adcx 8*2($tptr),%r10
@@ -3061,35 +3185,35 @@ sqrx8x_reduction:
.align 32
.Lsqrx8x_tail:
mov %r8,%rbx
- mulx 16*0($nptr),%rax,%r8
+ mulx 8*0($nptr),%rax,%r8
adcx %rax,%rbx
adox %r9,%r8
- mulx 16*1($nptr),%rax,%r9
+ mulx 8*1($nptr),%rax,%r9
adcx %rax,%r8
adox %r10,%r9
- mulx 16*2($nptr),%rax,%r10
+ mulx 8*2($nptr),%rax,%r10
adcx %rax,%r9
adox %r11,%r10
- mulx 16*3($nptr),%rax,%r11
+ mulx 8*3($nptr),%rax,%r11
adcx %rax,%r10
adox %r12,%r11
- .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x40,0x00,0x00,0x00 # mulx 16*4($nptr),%rax,%r12
+ .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 8*4($nptr),%rax,%r12
adcx %rax,%r11
adox %r13,%r12
- mulx 16*5($nptr),%rax,%r13
+ mulx 8*5($nptr),%rax,%r13
adcx %rax,%r12
adox %r14,%r13
- mulx 16*6($nptr),%rax,%r14
+ mulx 8*6($nptr),%rax,%r14
adcx %rax,%r13
adox %r15,%r14
- mulx 16*7($nptr),%rax,%r15
+ mulx 8*7($nptr),%rax,%r15
mov 72+48+8(%rsp,%rcx,8),%rdx # pull n0*a[i]
adcx %rax,%r14
adox $carry,%r15
@@ -3105,7 +3229,7 @@ sqrx8x_reduction:
sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
mov 48+8(%rsp),%rdx # pull n0*a[0]
- lea 16*8($nptr),$nptr
+ lea 8*8($nptr),$nptr
adc 8*0($tptr),%r8
adc 8*1($tptr),%r9
adc 8*2($tptr),%r10
@@ -3141,7 +3265,7 @@ sqrx8x_reduction:
adc 8*0($tptr),%r8
movq %xmm3,%rcx
adc 8*1($tptr),%r9
- mov 16*7($nptr),$carry
+ mov 8*7($nptr),$carry
movq %xmm2,$nptr # restore $nptr
adc 8*2($tptr),%r10
adc 8*3($tptr),%r11
@@ -3167,6 +3291,8 @@ sqrx8x_reduction:
lea 8*8($tptr,%rcx),$tptr # start of current t[] window
cmp 8+8(%rsp),%r8 # end of t[]?
jb .Lsqrx8x_reduction_loop
+ ret
+.size bn_sqrx8x_internal,.-bn_sqrx8x_internal
___
}
##############################################################
@@ -3174,52 +3300,59 @@ ___
#
{
my ($rptr,$nptr)=("%rdx","%rbp");
-my @ri=map("%r$_",(10..13));
-my @ni=map("%r$_",(14..15));
$code.=<<___;
- xor %ebx,%ebx
- sub %r15,%rsi # compare top-most words
- adc %rbx,%rbx
+.align 32
+__bn_postx4x_internal:
+ mov 8*0($nptr),%r12
mov %rcx,%r10 # -$num
- or %rbx,%rax
mov %rcx,%r9 # -$num
- xor \$1,%rax
- sar \$3+2,%rcx # cf=0
+ neg %rax
+ sar \$3+2,%rcx
#lea 48+8(%rsp,%r9),$tptr
- lea ($nptr,%rax,8),$nptr
movq %xmm1,$rptr # restore $rptr
movq %xmm1,$aptr # prepare for back-to-back call
- jmp .Lsqrx4x_sub
+ dec %r12 # so that after 'not' we get -n[0]
+ mov 8*1($nptr),%r13
+ xor %r8,%r8
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+ jmp .Lsqrx4x_sub_entry
-.align 32
+.align 16
.Lsqrx4x_sub:
- .byte 0x66
- mov 8*0($tptr),%r12
- mov 8*1($tptr),%r13
- sbb 16*0($nptr),%r12
- mov 8*2($tptr),%r14
- sbb 16*1($nptr),%r13
- mov 8*3($tptr),%r15
- lea 8*4($tptr),$tptr
- sbb 16*2($nptr),%r14
+ mov 8*0($nptr),%r12
+ mov 8*1($nptr),%r13
+ mov 8*2($nptr),%r14
+ mov 8*3($nptr),%r15
+.Lsqrx4x_sub_entry:
+ andn %rax,%r12,%r12
+ lea 8*4($nptr),$nptr
+ andn %rax,%r13,%r13
+ andn %rax,%r14,%r14
+ andn %rax,%r15,%r15
+
+ neg %r8 # mov %r8,%cf
+ adc 8*0($tptr),%r12
+ adc 8*1($tptr),%r13
+ adc 8*2($tptr),%r14
+ adc 8*3($tptr),%r15
mov %r12,8*0($rptr)
- sbb 16*3($nptr),%r15
- lea 16*4($nptr),$nptr
+ lea 8*4($tptr),$tptr
mov %r13,8*1($rptr)
+ sbb %r8,%r8 # mov %cf,%r8
mov %r14,8*2($rptr)
mov %r15,8*3($rptr)
lea 8*4($rptr),$rptr
inc %rcx
jnz .Lsqrx4x_sub
-___
-}
-$code.=<<___;
+
neg %r9 # restore $num
ret
-.size bn_sqrx8x_internal,.-bn_sqrx8x_internal
+.size __bn_postx4x_internal,.-__bn_postx4x_internal
___
+}
}}}
{
my ($inp,$num,$tbl,$idx)=$win64?("%rcx","%edx","%r8", "%r9d") : # Win64 order
@@ -3249,56 +3382,91 @@ bn_scatter5:
.globl bn_gather5
.type bn_gather5,\@abi-omnipotent
-.align 16
+.align 32
bn_gather5:
-___
-$code.=<<___ if ($win64);
-.LSEH_begin_bn_gather5:
+.LSEH_begin_bn_gather5: # Win64 thing, but harmless in other cases
# I can't trust assembler to use specific encoding:-(
- .byte 0x48,0x83,0xec,0x28 #sub \$0x28,%rsp
- .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp)
- .byte 0x0f,0x29,0x7c,0x24,0x10 #movdqa %xmm7,0x10(%rsp)
+ .byte 0x4c,0x8d,0x14,0x24 #lea (%rsp),%r10
+ .byte 0x48,0x81,0xec,0x08,0x01,0x00,0x00 #sub $0x108,%rsp
+ lea .Linc(%rip),%rax
+ and \$-16,%rsp # shouldn't be formally required
+
+ movd $idx,%xmm5
+ movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000
+ movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002
+ lea 128($tbl),%r11 # size optimization
+ lea 128(%rsp),%rax # size optimization
+
+ pshufd \$0,%xmm5,%xmm5 # broadcast $idx
+ movdqa %xmm1,%xmm4
+ movdqa %xmm1,%xmm2
___
+########################################################################
+# calculate mask by comparing 0..31 to $idx and save result to stack
+#
+for($i=0;$i<$STRIDE/16;$i+=4) {
$code.=<<___;
- mov $idx,%r11d
- shr \$`log($N/8)/log(2)`,$idx
- and \$`$N/8-1`,%r11
- not $idx
- lea .Lmagic_masks(%rip),%rax
- and \$`2**5/($N/8)-1`,$idx # 5 is "window size"
- lea 128($tbl,%r11,8),$tbl # pointer within 1st cache line
- movq 0(%rax,$idx,8),%xmm4 # set of masks denoting which
- movq 8(%rax,$idx,8),%xmm5 # cache line contains element
- movq 16(%rax,$idx,8),%xmm6 # denoted by 7th argument
- movq 24(%rax,$idx,8),%xmm7
+ paddd %xmm0,%xmm1
+ pcmpeqd %xmm5,%xmm0 # compare to 1,0
+___
+$code.=<<___ if ($i);
+ movdqa %xmm3,`16*($i-1)-128`(%rax)
+___
+$code.=<<___;
+ movdqa %xmm4,%xmm3
+
+ paddd %xmm1,%xmm2
+ pcmpeqd %xmm5,%xmm1 # compare to 3,2
+ movdqa %xmm0,`16*($i+0)-128`(%rax)
+ movdqa %xmm4,%xmm0
+
+ paddd %xmm2,%xmm3
+ pcmpeqd %xmm5,%xmm2 # compare to 5,4
+ movdqa %xmm1,`16*($i+1)-128`(%rax)
+ movdqa %xmm4,%xmm1
+
+ paddd %xmm3,%xmm0
+ pcmpeqd %xmm5,%xmm3 # compare to 7,6
+ movdqa %xmm2,`16*($i+2)-128`(%rax)
+ movdqa %xmm4,%xmm2
+___
+}
+$code.=<<___;
+ movdqa %xmm3,`16*($i-1)-128`(%rax)
jmp .Lgather
-.align 16
-.Lgather:
- movq `0*$STRIDE/4-128`($tbl),%xmm0
- movq `1*$STRIDE/4-128`($tbl),%xmm1
- pand %xmm4,%xmm0
- movq `2*$STRIDE/4-128`($tbl),%xmm2
- pand %xmm5,%xmm1
- movq `3*$STRIDE/4-128`($tbl),%xmm3
- pand %xmm6,%xmm2
- por %xmm1,%xmm0
- pand %xmm7,%xmm3
- .byte 0x67,0x67
- por %xmm2,%xmm0
- lea $STRIDE($tbl),$tbl
- por %xmm3,%xmm0
+.align 32
+.Lgather:
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+ movdqa `16*($i+0)-128`(%r11),%xmm0
+ movdqa `16*($i+1)-128`(%r11),%xmm1
+ movdqa `16*($i+2)-128`(%r11),%xmm2
+ pand `16*($i+0)-128`(%rax),%xmm0
+ movdqa `16*($i+3)-128`(%r11),%xmm3
+ pand `16*($i+1)-128`(%rax),%xmm1
+ por %xmm0,%xmm4
+ pand `16*($i+2)-128`(%rax),%xmm2
+ por %xmm1,%xmm5
+ pand `16*($i+3)-128`(%rax),%xmm3
+ por %xmm2,%xmm4
+ por %xmm3,%xmm5
+___
+}
+$code.=<<___;
+ por %xmm5,%xmm4
+ lea $STRIDE(%r11),%r11
+ pshufd \$0x4e,%xmm4,%xmm0
+ por %xmm4,%xmm0
movq %xmm0,($out) # m0=bp[0]
lea 8($out),$out
sub \$1,$num
jnz .Lgather
-___
-$code.=<<___ if ($win64);
- movaps (%rsp),%xmm6
- movaps 0x10(%rsp),%xmm7
- lea 0x28(%rsp),%rsp
-___
-$code.=<<___;
+
+ lea (%r10),%rsp
ret
.LSEH_end_bn_gather5:
.size bn_gather5,.-bn_gather5
@@ -3306,9 +3474,9 @@ ___
}
$code.=<<___;
.align 64
-.Lmagic_masks:
- .long 0,0, 0,0, 0,0, -1,-1
- .long 0,0, 0,0, 0,0, 0,0
+.Linc:
+ .long 0,0, 1,1
+ .long 2,2, 2,2
.asciz "Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
___
@@ -3356,19 +3524,16 @@ mul_handler:
lea .Lmul_epilogue(%rip),%r10
cmp %r10,%rbx
- jb .Lbody_40
+ ja .Lbody_40
mov 192($context),%r10 # pull $num
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
+
jmp .Lbody_proceed
.Lbody_40:
mov 40(%rax),%rax # pull saved stack pointer
.Lbody_proceed:
-
- movaps -88(%rax),%xmm0
- movaps -72(%rax),%xmm1
-
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -3381,8 +3546,6 @@ mul_handler:
mov %r13,224($context) # restore context->R13
mov %r14,232($context) # restore context->R14
mov %r15,240($context) # restore context->R15
- movups %xmm0,512($context) # restore context->Xmm6
- movups %xmm1,528($context) # restore context->Xmm7
.Lcommon_seh_tail:
mov 8(%rax),%rdi
@@ -3493,10 +3656,9 @@ ___
$code.=<<___;
.align 8
.LSEH_info_bn_gather5:
- .byte 0x01,0x0d,0x05,0x00
- .byte 0x0d,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7
- .byte 0x08,0x68,0x00,0x00 #movaps (rsp),xmm6
- .byte 0x04,0x42,0x00,0x00 #sub rsp,0x28
+ .byte 0x01,0x0b,0x03,0x0a
+ .byte 0x0b,0x01,0x21,0x00 # sub rsp,0x108
+ .byte 0x04,0xa3,0x00,0x00 # lea r10,(rsp)
.align 8
___
}
diff --git a/crypto/bn/bn.c b/crypto/bn/bn.c
index 2263701f..0ecaf825 100644
--- a/crypto/bn/bn.c
+++ b/crypto/bn/bn.c
@@ -266,6 +266,18 @@ int BN_set_word(BIGNUM *bn, BN_ULONG value) {
return 1;
}
+int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
+ if (bn_wexpand(bn, num) == NULL) {
+ return 0;
+ }
+ memmove(bn->d, words, num * sizeof(BN_ULONG));
+ /* |bn_wexpand| verified that |num| isn't too large. */
+ bn->top = (int)num;
+ bn_correct_top(bn);
+ bn->neg = 0;
+ return 1;
+}
+
int BN_is_negative(const BIGNUM *bn) {
return bn->neg != 0;
}
diff --git a/crypto/bn/bn_test.cc b/crypto/bn/bn_test.cc
index fe8cfd05..d909ee28 100644
--- a/crypto/bn/bn_test.cc
+++ b/crypto/bn/bn_test.cc
@@ -850,11 +850,17 @@ static bool test_div_word(FILE *fp) {
return false;
}
BN_ULONG s = b->d[0];
+ BN_ULONG rmod = BN_mod_word(b.get(), s);
BN_ULONG r = BN_div_word(b.get(), s);
if (r == (BN_ULONG)-1) {
return false;
}
+ if (rmod != r) {
+ fprintf(stderr, "Mod (word) test failed!\n");
+ return false;
+ }
+
if (fp != NULL) {
BN_print_fp(fp, a.get());
puts_fp(fp, " / ");
diff --git a/crypto/bn/cmp.c b/crypto/bn/cmp.c
index fce72339..121c894c 100644
--- a/crypto/bn/cmp.c
+++ b/crypto/bn/cmp.c
@@ -56,6 +56,8 @@
#include <openssl/bn.h>
+#include <openssl/mem.h>
+
#include "internal.h"
@@ -198,3 +200,15 @@ int BN_is_word(const BIGNUM *bn, BN_ULONG w) {
int BN_is_odd(const BIGNUM *bn) {
return bn->top > 0 && (bn->d[0] & 1) == 1;
}
+
+int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) {
+ if (a->top != b->top) {
+ return 0;
+ }
+
+ int limbs_are_equal =
+ CRYPTO_memcmp(a->d, b->d, (size_t)a->top * sizeof(a->d[0])) == 0;
+
+ return constant_time_select_int(constant_time_eq_int(a->neg, b->neg),
+ limbs_are_equal, 0);
+}
diff --git a/crypto/bn/convert.c b/crypto/bn/convert.c
index 542f523f..9125bf84 100644
--- a/crypto/bn/convert.c
+++ b/crypto/bn/convert.c
@@ -577,12 +577,14 @@ BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
return NULL;
}
+ int out_is_alloced = 0;
if (out == NULL) {
out = BN_new();
- }
- if (out == NULL) {
- OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
- return NULL;
+ if (out == NULL) {
+ OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ out_is_alloced = 1;
}
if (in_len == 0) {
@@ -592,6 +594,9 @@ BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
in += 4;
if (BN_bin2bn(in, in_len, out) == NULL) {
+ if (out_is_alloced) {
+ BN_free(out);
+ }
return NULL;
}
out->neg = ((*in) & 0x80) != 0;
diff --git a/crypto/bn/div.c b/crypto/bn/div.c
index 5a239bce..e824458b 100644
--- a/crypto/bn/div.c
+++ b/crypto/bn/div.c
@@ -56,55 +56,126 @@
#include <openssl/bn.h>
+#include <assert.h>
#include <limits.h>
#include <openssl/err.h>
#include "internal.h"
-#define asm __asm__
-
-#if !defined(OPENSSL_NO_ASM)
-# if defined(__GNUC__) && __GNUC__>=2
-# if defined(OPENSSL_X86)
- /*
- * There were two reasons for implementing this template:
- * - GNU C generates a call to a function (__udivdi3 to be exact)
- * in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
- * understand why...);
- * - divl doesn't only calculate quotient, but also leaves
- * remainder in %edx which we can definitely use here:-)
- *
- * <appro@fy.chalmers.se>
- */
-#undef div_asm
-# define div_asm(n0,n1,d0) \
- ({ asm volatile ( \
- "divl %4" \
- : "=a"(q), "=d"(rem) \
- : "a"(n1), "d"(n0), "g"(d0) \
- : "cc"); \
- q; \
- })
-# define REMAINDER_IS_ALREADY_CALCULATED
-# elif defined(OPENSSL_X86_64)
- /*
- * Same story here, but it's 128-bit by 64-bit division. Wow!
- * <appro@fy.chalmers.se>
- */
-# undef div_asm
-# define div_asm(n0,n1,d0) \
- ({ asm volatile ( \
- "divq %4" \
- : "=a"(q), "=d"(rem) \
- : "a"(n1), "d"(n0), "g"(d0) \
- : "cc"); \
- q; \
- })
-# define REMAINDER_IS_ALREADY_CALCULATED
-# endif /* __<cpu> */
-# endif /* __GNUC__ */
-#endif /* OPENSSL_NO_ASM */
+#if !defined(BN_ULLONG)
+/* bn_div_words divides a double-width |h|,|l| by |d| and returns the result,
+ * which must fit in a |BN_ULONG|. */
+static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
+ BN_ULONG dh, dl, q, ret = 0, th, tl, t;
+ int i, count = 2;
+
+ if (d == 0) {
+ return BN_MASK2;
+ }
+
+ i = BN_num_bits_word(d);
+ assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
+
+ i = BN_BITS2 - i;
+ if (h >= d) {
+ h -= d;
+ }
+
+ if (i) {
+ d <<= i;
+ h = (h << i) | (l >> (BN_BITS2 - i));
+ l <<= i;
+ }
+ dh = (d & BN_MASK2h) >> BN_BITS4;
+ dl = (d & BN_MASK2l);
+ for (;;) {
+ if ((h >> BN_BITS4) == dh) {
+ q = BN_MASK2l;
+ } else {
+ q = h / dh;
+ }
+
+ th = q * dh;
+ tl = dl * q;
+ for (;;) {
+ t = h - th;
+ if ((t & BN_MASK2h) ||
+ ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
+ break;
+ }
+ q--;
+ th -= dh;
+ tl -= dl;
+ }
+ t = (tl >> BN_BITS4);
+ tl = (tl << BN_BITS4) & BN_MASK2h;
+ th += t;
+
+ if (l < tl) {
+ th++;
+ }
+ l -= tl;
+ if (h < th) {
+ h += d;
+ q--;
+ }
+ h -= th;
+
+ if (--count == 0) {
+ break;
+ }
+
+ ret = q << BN_BITS4;
+ h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
+ l = (l & BN_MASK2l) << BN_BITS4;
+ }
+
+ ret |= q;
+ return ret;
+}
+#endif /* !defined(BN_ULLONG) */
+
+static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
+ BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) {
+ /* GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when
+ * the |BN_ULLONG|-based C code is used.
+ *
+ * GCC bugs:
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897
+ * * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668
+ *
+ * Clang bugs:
+ * * https://llvm.org/bugs/show_bug.cgi?id=6397
+ * * https://llvm.org/bugs/show_bug.cgi?id=12418
+ *
+ * These issues aren't specific to x86 and x86_64, so it might be worthwhile
+ * to add more assembly language implementations. */
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__)
+ __asm__ volatile (
+ "divl %4"
+ : "=a"(*quotient_out), "=d"(*rem_out)
+ : "a"(n1), "d"(n0), "g"(d0)
+ : "cc" );
+#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
+ __asm__ volatile (
+ "divq %4"
+ : "=a"(*quotient_out), "=d"(*rem_out)
+ : "a"(n1), "d"(n0), "g"(d0)
+ : "cc" );
+#else
+#if defined(BN_ULLONG)
+ BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
+ *quotient_out = (BN_ULONG)(n / d0);
+#else
+ *quotient_out = bn_div_words(n0, n1, d0);
+#endif
+ *rem_out = n1 - (*quotient_out * d0);
+#endif
+}
/* BN_div computes dv := num / divisor, rounding towards
* zero, and sets up rm such that dv*divisor + rm = num holds.
@@ -260,23 +331,10 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
q = BN_MASK2;
} else {
/* n0 < d0 */
-#ifdef BN_ULLONG
- BN_ULLONG t2;
-
-#if defined(BN_ULLONG) && !defined(div_asm)
- q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0);
-#else
- q = div_asm(n0, n1, d0);
-#endif
-
-#ifndef REMAINDER_IS_ALREADY_CALCULATED
- /* rem doesn't have to be BN_ULLONG. The least we know it's less that d0,
- * isn't it? */
- rem = (n1 - q * d0) & BN_MASK2;
-#endif
-
- t2 = (BN_ULLONG)d1 * q;
+ bn_div_rem_words(&q, &rem, n0, n1, d0);
+#ifdef BN_ULLONG
+ BN_ULLONG t2 = (BN_ULLONG)d1 * q;
for (;;) {
if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) {
break;
@@ -290,13 +348,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
}
#else /* !BN_ULLONG */
BN_ULONG t2l, t2h;
-
- q = bn_div_words(n0, n1, d0);
-
- rem = (n1 - q * d0) & BN_MASK2;
-
BN_UMULT_LOHI(t2l, t2h, d1, q);
-
for (;;) {
if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) {
break;
@@ -556,7 +608,7 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
return 0;
}
- /* normalize input (so bn_div_words doesn't complain) */
+ /* normalize input for |bn_div_rem_words|. */
j = BN_BITS2 - BN_num_bits_word(w);
w <<= j;
if (!BN_lshift(a, a, j)) {
@@ -564,10 +616,10 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
}
for (i = a->top - 1; i >= 0; i--) {
- BN_ULONG l, d;
-
- l = a->d[i];
- d = bn_div_words(ret, l, w);
+ BN_ULONG l = a->d[i];
+ BN_ULONG d;
+ BN_ULONG unused_rem;
+ bn_div_rem_words(&d, &unused_rem, ret, l, w);
ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
a->d[i] = d;
}
@@ -592,6 +644,20 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
return (BN_ULONG) -1;
}
+#ifndef BN_ULLONG
+ /* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back
+ * to using |BN_div_word|. */
+ if (w > ((BN_ULONG)1 << BN_BITS4)) {
+ BIGNUM *tmp = BN_dup(a);
+ if (tmp == NULL) {
+ return (BN_ULONG)-1;
+ }
+ ret = BN_div_word(tmp, w);
+ BN_free(tmp);
+ return ret;
+ }
+#endif
+
w &= BN_MASK2;
for (i = a->top - 1; i >= 0; i--) {
#ifndef BN_ULLONG
diff --git a/crypto/bn/exponentiation.c b/crypto/bn/exponentiation.c
index f7100ac3..eedc88e8 100644
--- a/crypto/bn/exponentiation.c
+++ b/crypto/bn/exponentiation.c
@@ -209,6 +209,7 @@ static void BN_RECP_CTX_init(BN_RECP_CTX *recp) {
BN_init(&recp->N);
BN_init(&recp->Nr);
recp->num_bits = 0;
+ recp->shift = 0;
recp->flags = 0;
}
@@ -575,41 +576,7 @@ err:
int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
BN_CTX *ctx) {
- /* For even modulus m = 2^k*m_odd, it might make sense to compute
- * a^p mod m_odd and a^p mod 2^k separately (with Montgomery
- * exponentiation for the odd part), using appropriate exponent
- * reductions, and combine the results using the CRT.
- *
- * For now, we use Montgomery only if the modulus is odd; otherwise,
- * exponentiation using the reciprocal-based quick remaindering
- * algorithm is used.
- *
- * (Timing obtained with expspeed.c [computations a^p mod m
- * where a, p, m are of the same length: 256, 512, 1024, 2048,
- * 4096, 8192 bits], compared to the running time of the
- * standard algorithm:
- *
- * BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration]
- * 55 .. 77 % [UltraSparc processor, but
- * debug-solaris-sparcv8-gcc conf.]
- *
- * BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration]
- * 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
- *
- * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
- * at 2048 and more bits, but at 512 and 1024 bits, it was
- * slower even than the standard algorithm!
- *
- * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
- * should be obtained when the new Montgomery reduction code
- * has been integrated into OpenSSL.) */
-
if (BN_is_odd(m)) {
- if (a->top == 1 && !a->neg && BN_get_flags(p, BN_FLG_CONSTTIME) == 0) {
- BN_ULONG A = a->d[0];
- return BN_mod_exp_mont_word(r, A, p, m, ctx, NULL);
- }
-
return BN_mod_exp_mont(r, a, p, m, ctx, NULL);
}
@@ -787,29 +754,65 @@ err:
* pattern as far as cache lines are concerned. The following functions are
* used to transfer a BIGNUM from/to that table. */
static int copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, int idx,
- int width) {
- size_t i, j;
+ int window) {
+ int i, j;
+ const int width = 1 << window;
+ BN_ULONG *table = (BN_ULONG *) buf;
if (top > b->top) {
top = b->top; /* this works because 'buf' is explicitly zeroed */
}
- for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
- buf[j] = ((unsigned char *)b->d)[i];
+
+ for (i = 0, j = idx; i < top; i++, j += width) {
+ table[j] = b->d[i];
}
return 1;
}
static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
- int width) {
- size_t i, j;
+ int window) {
+ int i, j;
+ const int width = 1 << window;
+ volatile BN_ULONG *table = (volatile BN_ULONG *)buf;
if (bn_wexpand(b, top) == NULL) {
return 0;
}
- for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
- ((unsigned char *)b->d)[i] = buf[j];
+ if (window <= 3) {
+ for (i = 0; i < top; i++, table += width) {
+ BN_ULONG acc = 0;
+
+ for (j = 0; j < width; j++) {
+ acc |= table[j] & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
+ }
+
+ b->d[i] = acc;
+ }
+ } else {
+ int xstride = 1 << (window - 2);
+ BN_ULONG y0, y1, y2, y3;
+
+ i = idx >> (window - 2); /* equivalent of idx / xstride */
+ idx &= xstride - 1; /* equivalent of idx % xstride */
+
+ y0 = (BN_ULONG)0 - (constant_time_eq_int(i, 0) & 1);
+ y1 = (BN_ULONG)0 - (constant_time_eq_int(i, 1) & 1);
+ y2 = (BN_ULONG)0 - (constant_time_eq_int(i, 2) & 1);
+ y3 = (BN_ULONG)0 - (constant_time_eq_int(i, 3) & 1);
+
+ for (i = 0; i < top; i++, table += width) {
+ BN_ULONG acc = 0;
+
+ for (j = 0; j < xstride; j++) {
+ acc |= ((table[j + 0 * xstride] & y0) | (table[j + 1 * xstride] & y1) |
+ (table[j + 2 * xstride] & y2) | (table[j + 3 * xstride] & y3)) &
+ ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
+ }
+
+ b->d[i] = acc;
+ }
}
b->top = top;
@@ -891,8 +894,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
return BN_one(rr);
}
- BN_CTX_start(ctx);
-
/* Allocate a montgomery context if it was not supplied by the caller. */
if (mont == NULL) {
new_mont = BN_MONT_CTX_new();
@@ -935,9 +936,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
#if defined(OPENSSL_BN_ASM_MONT5)
if (window >= 5) {
window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */
- if ((top & 7) == 0) {
- powerbufLen += 2 * top * sizeof(m->d[0]);
- }
+ /* reserve space for mont->N.d[] copy */
+ powerbufLen += top * sizeof(mont->N.d[0]);
}
#endif
@@ -1008,7 +1008,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as
* 512-bit RSA is hardly relevant, we omit it to spare size... */
if (window == 5 && top > 1) {
- const BN_ULONG *np = mont->N.d, *n0 = mont->n0, *np2;
+ const BN_ULONG *n0 = mont->n0;
+ BN_ULONG *np;
/* BN_to_montgomery can contaminate words above .top
* [in BN_DEBUG[_DEBUG] build]... */
@@ -1019,14 +1020,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
tmp.d[i] = 0;
}
- if (top & 7) {
- np2 = np;
- } else {
- BN_ULONG *np_double = am.d + top;
- for (i = 0; i < top; i++) {
- np_double[2 * i] = np[i];
- }
- np2 = np_double;
+ /* copy mont->N.d[] to improve cache locality */
+ for (np = am.d + top, i = 0; i < top; i++) {
+ np[i] = mont->N.d[i];
}
bn_scatter5(tmp.d, top, powerbuf, 0);
@@ -1041,7 +1037,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
for (i = 3; i < 8; i += 2) {
int j;
- bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+ bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
for (j = 2 * i; j < 32; j *= 2) {
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
@@ -1049,13 +1045,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
}
for (; i < 16; i += 2) {
- bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+ bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_scatter5(tmp.d, top, powerbuf, 2 * i);
}
for (; i < 32; i += 2) {
- bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+ bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
bn_scatter5(tmp.d, top, powerbuf, i);
}
@@ -1103,7 +1099,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
wvalue >>= (bits - 4) & 7;
wvalue &= 0x1f;
bits -= 5;
- bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+ bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
}
while (bits >= 0) {
/* Read five bits from |bits-4| through |bits|, inclusive. */
@@ -1112,11 +1108,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
wvalue >>= first_bit & 7;
wvalue &= 0x1f;
bits -= 5;
- bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+ bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
}
}
- ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np2, n0, top);
+ ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top);
tmp.top = top;
bn_correct_top(&tmp);
if (ret) {
@@ -1128,8 +1124,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
} else
#endif
{
- if (!copy_to_prebuf(&tmp, top, powerbuf, 0, numPowers) ||
- !copy_to_prebuf(&am, top, powerbuf, 1, numPowers)) {
+ if (!copy_to_prebuf(&tmp, top, powerbuf, 0, window) ||
+ !copy_to_prebuf(&am, top, powerbuf, 1, window)) {
goto err;
}
@@ -1140,13 +1136,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
*/
if (window > 1) {
if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) ||
- !copy_to_prebuf(&tmp, top, powerbuf, 2, numPowers)) {
+ !copy_to_prebuf(&tmp, top, powerbuf, 2, window)) {
goto err;
}
for (i = 3; i < numPowers; i++) {
/* Calculate a^i = a^(i-1) * a */
if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) ||
- !copy_to_prebuf(&tmp, top, powerbuf, i, numPowers)) {
+ !copy_to_prebuf(&tmp, top, powerbuf, i, window)) {
goto err;
}
}
@@ -1156,7 +1152,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) {
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
}
- if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, numPowers)) {
+ if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, window)) {
goto err;
}
@@ -1175,7 +1171,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
/* Fetch the appropriate pre-computed value from the pre-buf */
- if (!copy_from_prebuf(&am, top, powerbuf, wvalue, numPowers)) {
+ if (!copy_from_prebuf(&am, top, powerbuf, wvalue, window)) {
goto err;
}
@@ -1198,158 +1194,27 @@ err:
OPENSSL_cleanse(powerbuf, powerbufLen);
OPENSSL_free(powerbufFree);
}
- BN_CTX_end(ctx);
return (ret);
}
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
const BN_MONT_CTX *mont) {
- BN_MONT_CTX *new_mont = NULL;
- int b, bits, ret = 0;
- int r_is_one;
- BN_ULONG w, next_w;
- BIGNUM *d, *r, *t;
- BIGNUM *swap_tmp;
-#define BN_MOD_MUL_WORD(r, w, m) \
- (BN_mul_word(r, (w)) && \
- (/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \
- (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
- /* BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is
- * probably more overhead than always using BN_mod (which uses BN_copy if a
- * similar test returns true). We can use BN_mod and do not need BN_nnmod
- * because our accumulator is never negative (the result of BN_mod does not
- * depend on the sign of the modulus). */
-#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
- (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
-
- if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
- /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
- OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
-
- if (!BN_is_odd(m)) {
- OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
- return 0;
- }
+ BIGNUM a_bignum;
+ BN_init(&a_bignum);
- if (m->top == 1) {
- a %= m->d[0]; /* make sure that 'a' is reduced */
- }
-
- bits = BN_num_bits(p);
- if (bits == 0) {
- /* x**0 mod 1 is still zero. */
- if (BN_is_one(m)) {
- BN_zero(rr);
- return 1;
- }
- return BN_one(rr);
- }
- if (a == 0) {
- BN_zero(rr);
- return 1;
- }
+ int ret = 0;
- BN_CTX_start(ctx);
- d = BN_CTX_get(ctx);
- r = BN_CTX_get(ctx);
- t = BN_CTX_get(ctx);
- if (d == NULL || r == NULL || t == NULL) {
+ if (!BN_set_word(&a_bignum, a)) {
+ OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
goto err;
}
- /* Allocate a montgomery context if it was not supplied by the caller. */
- if (mont == NULL) {
- new_mont = BN_MONT_CTX_new();
- if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
- goto err;
- }
- mont = new_mont;
- }
-
- r_is_one = 1; /* except for Montgomery factor */
-
- /* bits-1 >= 0 */
-
- /* The result is accumulated in the product r*w. */
- w = a; /* bit 'bits-1' of 'p' is always set */
- for (b = bits - 2; b >= 0; b--) {
- /* First, square r*w. */
- next_w = w * w;
- if ((next_w / w) != w) {
- /* overflow */
- if (r_is_one) {
- if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
- goto err;
- }
- r_is_one = 0;
- } else {
- if (!BN_MOD_MUL_WORD(r, w, m)) {
- goto err;
- }
- }
- next_w = 1;
- }
-
- w = next_w;
- if (!r_is_one) {
- if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
- goto err;
- }
- }
-
- /* Second, multiply r*w by 'a' if exponent bit is set. */
- if (BN_is_bit_set(p, b)) {
- next_w = w * a;
- if ((next_w / a) != w) {
- /* overflow */
- if (r_is_one) {
- if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
- goto err;
- }
- r_is_one = 0;
- } else {
- if (!BN_MOD_MUL_WORD(r, w, m)) {
- goto err;
- }
- }
- next_w = a;
- }
- w = next_w;
- }
- }
-
- /* Finally, set r:=r*w. */
- if (w != 1) {
- if (r_is_one) {
- if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
- goto err;
- }
- r_is_one = 0;
- } else {
- if (!BN_MOD_MUL_WORD(r, w, m)) {
- goto err;
- }
- }
- }
-
- if (r_is_one) {
- /* can happen only if a == 1*/
- if (!BN_one(rr)) {
- goto err;
- }
- } else {
- if (!BN_from_montgomery(rr, r, mont, ctx)) {
- goto err;
- }
- }
- ret = 1;
+ ret = BN_mod_exp_mont(rr, &a_bignum, p, m, ctx, mont);
err:
- BN_MONT_CTX_free(new_mont);
- BN_CTX_end(ctx);
+ BN_free(&a_bignum);
+
return ret;
}
@@ -1358,36 +1223,11 @@ err:
int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
BN_CTX *ctx, const BN_MONT_CTX *mont) {
- int i, j, bits, b, bits1, bits2, ret = 0, wpos1, wpos2, window1, window2,
- wvalue1, wvalue2;
- int r_is_one = 1;
- BIGNUM *d, *r;
- const BIGNUM *a_mod_m;
- /* Tables of variables obtained from 'ctx' */
- BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE];
- BN_MONT_CTX *new_mont = NULL;
-
- if (!(m->d[0] & 1)) {
- OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
- return 0;
- }
- bits1 = BN_num_bits(p1);
- bits2 = BN_num_bits(p2);
- if (bits1 == 0 && bits2 == 0) {
- ret = BN_one(rr);
- return ret;
- }
-
- bits = (bits1 > bits2) ? bits1 : bits2;
+ BIGNUM tmp;
+ BN_init(&tmp);
- BN_CTX_start(ctx);
- d = BN_CTX_get(ctx);
- r = BN_CTX_get(ctx);
- val1[0] = BN_CTX_get(ctx);
- val2[0] = BN_CTX_get(ctx);
- if (!d || !r || !val1[0] || !val2[0]) {
- goto err;
- }
+ int ret = 0;
+ BN_MONT_CTX *new_mont = NULL;
/* Allocate a montgomery context if it was not supplied by the caller. */
if (mont == NULL) {
@@ -1398,156 +1238,21 @@ int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
mont = new_mont;
}
- window1 = BN_window_bits_for_exponent_size(bits1);
- window2 = BN_window_bits_for_exponent_size(bits2);
-
- /* Build table for a1: val1[i] := a1^(2*i + 1) mod m for i = 0 ..
- * 2^(window1-1) */
- if (a1->neg || BN_ucmp(a1, m) >= 0) {
- if (!BN_mod(val1[0], a1, m, ctx)) {
- goto err;
- }
- a_mod_m = val1[0];
- } else {
- a_mod_m = a1;
- }
-
- if (BN_is_zero(a_mod_m)) {
- BN_zero(rr);
- ret = 1;
- goto err;
- }
-
- if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx)) {
+ /* BN_mod_mul_montgomery removes one Montgomery factor, so passing one
+ * Montgomery-encoded and one non-Montgomery-encoded value gives a
+ * non-Montgomery-encoded result. */
+ if (!BN_mod_exp_mont(rr, a1, p1, m, ctx, mont) ||
+ !BN_mod_exp_mont(&tmp, a2, p2, m, ctx, mont) ||
+ !BN_to_montgomery(rr, rr, mont, ctx) ||
+ !BN_mod_mul_montgomery(rr, rr, &tmp, mont, ctx)) {
goto err;
}
- if (window1 > 1) {
- if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx)) {
- goto err;
- }
-
- j = 1 << (window1 - 1);
- for (i = 1; i < j; i++) {
- if (((val1[i] = BN_CTX_get(ctx)) == NULL) ||
- !BN_mod_mul_montgomery(val1[i], val1[i - 1], d, mont, ctx)) {
- goto err;
- }
- }
- }
-
- /* Build table for a2: val2[i] := a2^(2*i + 1) mod m for i = 0 ..
- * 2^(window2-1) */
- if (a2->neg || BN_ucmp(a2, m) >= 0) {
- if (!BN_mod(val2[0], a2, m, ctx)) {
- goto err;
- }
- a_mod_m = val2[0];
- } else {
- a_mod_m = a2;
- }
-
- if (BN_is_zero(a_mod_m)) {
- BN_zero(rr);
- ret = 1;
- goto err;
- }
-
- if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx)) {
- goto err;
- }
-
- if (window2 > 1) {
- if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx)) {
- goto err;
- }
-
- j = 1 << (window2 - 1);
- for (i = 1; i < j; i++) {
- if (((val2[i] = BN_CTX_get(ctx)) == NULL) ||
- !BN_mod_mul_montgomery(val2[i], val2[i - 1], d, mont, ctx)) {
- goto err;
- }
- }
- }
-
- /* Now compute the power product, using independent windows. */
- r_is_one = 1;
- wvalue1 = 0; /* The 'value' of the first window */
- wvalue2 = 0; /* The 'value' of the second window */
- wpos1 = 0; /* If wvalue1 > 0, the bottom bit of the first window */
- wpos2 = 0; /* If wvalue2 > 0, the bottom bit of the second window */
-
- if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) {
- goto err;
- }
-
- for (b = bits - 1; b >= 0; b--) {
- if (!r_is_one) {
- if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
- goto err;
- }
- }
-
- if (!wvalue1 && BN_is_bit_set(p1, b)) {
- /* consider bits b-window1+1 .. b for this window */
- i = b - window1 + 1;
- /* works for i<0 */
- while (!BN_is_bit_set(p1, i)) {
- i++;
- }
- wpos1 = i;
- wvalue1 = 1;
- for (i = b - 1; i >= wpos1; i--) {
- wvalue1 <<= 1;
- if (BN_is_bit_set(p1, i)) {
- wvalue1++;
- }
- }
- }
-
- if (!wvalue2 && BN_is_bit_set(p2, b)) {
- /* consider bits b-window2+1 .. b for this window */
- i = b - window2 + 1;
- while (!BN_is_bit_set(p2, i)) {
- i++;
- }
- wpos2 = i;
- wvalue2 = 1;
- for (i = b - 1; i >= wpos2; i--) {
- wvalue2 <<= 1;
- if (BN_is_bit_set(p2, i)) {
- wvalue2++;
- }
- }
- }
-
- if (wvalue1 && b == wpos1) {
- /* wvalue1 is odd and < 2^window1 */
- if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1], mont, ctx)) {
- goto err;
- }
- wvalue1 = 0;
- r_is_one = 0;
- }
-
- if (wvalue2 && b == wpos2) {
- /* wvalue2 is odd and < 2^window2 */
- if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1], mont, ctx)) {
- goto err;
- }
- wvalue2 = 0;
- r_is_one = 0;
- }
- }
-
- if (!BN_from_montgomery(rr, r, mont, ctx)) {
- goto err;
- }
ret = 1;
err:
BN_MONT_CTX_free(new_mont);
- BN_CTX_end(ctx);
+ BN_free(&tmp);
+
return ret;
}
diff --git a/crypto/bn/gcd.c b/crypto/bn/gcd.c
index 41ca6d21..c9a7123f 100644
--- a/crypto/bn/gcd.c
+++ b/crypto/bn/gcd.c
@@ -668,6 +668,12 @@ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, int *out_no_inverse,
sign = -sign;
}
+ if (!BN_is_one(A)) {
+ *out_no_inverse = 1;
+ OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
+ goto err;
+ }
+
/*
* The while loop (Euclid's algorithm) ends when
* A == gcd(a,n);
@@ -683,22 +689,17 @@ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, int *out_no_inverse,
}
/* Now Y*a == A (mod |n|). */
- if (BN_is_one(A)) {
- /* Y*a == 1 (mod |n|) */
- if (!Y->neg && BN_ucmp(Y, n) < 0) {
- if (!BN_copy(R, Y)) {
- goto err;
- }
- } else {
- if (!BN_nnmod(R, Y, n, ctx)) {
- goto err;
- }
+ /* Y*a == 1 (mod |n|) */
+ if (!Y->neg && BN_ucmp(Y, n) < 0) {
+ if (!BN_copy(R, Y)) {
+ goto err;
}
} else {
- *out_no_inverse = 1;
- OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
- goto err;
+ if (!BN_nnmod(R, Y, n, ctx)) {
+ goto err;
+ }
}
+
ret = R;
err:
diff --git a/crypto/bn/generic.c b/crypto/bn/generic.c
index cf2db8b8..f552d99f 100644
--- a/crypto/bn/generic.c
+++ b/crypto/bn/generic.c
@@ -202,86 +202,6 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
}
}
-#if defined(BN_ULLONG)
-
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
- return (BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2) | l) / (BN_ULLONG)d);
-}
-
-#else
-
-/* Divide h,l by d and return the result. */
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
- BN_ULONG dh, dl, q, ret = 0, th, tl, t;
- int i, count = 2;
-
- if (d == 0) {
- return BN_MASK2;
- }
-
- i = BN_num_bits_word(d);
- assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
-
- i = BN_BITS2 - i;
- if (h >= d) {
- h -= d;
- }
-
- if (i) {
- d <<= i;
- h = (h << i) | (l >> (BN_BITS2 - i));
- l <<= i;
- }
- dh = (d & BN_MASK2h) >> BN_BITS4;
- dl = (d & BN_MASK2l);
- for (;;) {
- if ((h >> BN_BITS4) == dh) {
- q = BN_MASK2l;
- } else {
- q = h / dh;
- }
-
- th = q * dh;
- tl = dl * q;
- for (;;) {
- t = h - th;
- if ((t & BN_MASK2h) ||
- ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
- break;
- }
- q--;
- th -= dh;
- tl -= dl;
- }
- t = (tl >> BN_BITS4);
- tl = (tl << BN_BITS4) & BN_MASK2h;
- th += t;
-
- if (l < tl) {
- th++;
- }
- l -= tl;
- if (h < th) {
- h += d;
- q--;
- }
- h -= th;
-
- if (--count == 0) {
- break;
- }
-
- ret = q << BN_BITS4;
- h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
- l = (l & BN_MASK2l) << BN_BITS4;
- }
-
- ret |= q;
- return ret;
-}
-
-#endif /* !defined(BN_ULLONG) */
-
#ifdef BN_ULLONG
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int n) {
diff --git a/crypto/bn/internal.h b/crypto/bn/internal.h
index 5c9baa4f..8b1c8660 100644
--- a/crypto/bn/internal.h
+++ b/crypto/bn/internal.h
@@ -126,9 +126,9 @@
#include <openssl/base.h>
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <intrin.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#pragma intrinsic(__umulh, _umul128)
#endif
@@ -192,10 +192,14 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
#endif
+
+/* bn_set_words sets |bn| to the value encoded in the |num| words in |words|,
+ * least significant word first. */
+int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num);
+
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
diff --git a/crypto/bn/montgomery.c b/crypto/bn/montgomery.c
index d956d62b..7c3b420c 100644
--- a/crypto/bn/montgomery.c
+++ b/crypto/bn/montgomery.c
@@ -289,14 +289,14 @@ err:
return ret;
}
-BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
- const BIGNUM *mod, BN_CTX *bn_ctx) {
+int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
+ const BIGNUM *mod, BN_CTX *bn_ctx) {
CRYPTO_MUTEX_lock_read(lock);
BN_MONT_CTX *ctx = *pmont;
- CRYPTO_MUTEX_unlock(lock);
+ CRYPTO_MUTEX_unlock_read(lock);
if (ctx) {
- return ctx;
+ return 1;
}
CRYPTO_MUTEX_lock_write(lock);
@@ -317,8 +317,8 @@ BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
*pmont = ctx;
out:
- CRYPTO_MUTEX_unlock(lock);
- return ctx;
+ CRYPTO_MUTEX_unlock_write(lock);
+ return ctx != NULL;
}
int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
@@ -326,14 +326,12 @@ int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
}
-#if 0
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
const BN_MONT_CTX *mont) {
- const BIGNUM *n;
BN_ULONG *ap, *np, *rp, n0, v, carry;
int nl, max, i;
- n = &mont->N;
+ const BIGNUM *n = &mont->N;
nl = n->top;
if (nl == 0) {
ret->top = 0;
@@ -376,13 +374,13 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
{
BN_ULONG *nrp;
- size_t m;
+ uintptr_t m;
v = bn_sub_words(rp, ap, np, nl) - carry;
/* if subtraction result is real, then trick unconditional memcpy below to
* perform in-place "refresh" instead of actual copy. */
- m = (0 - (size_t)v);
- nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m));
+ m = (0u - (uintptr_t)v);
+ nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_t)ap & m));
for (i = 0, nl -= 4; i < nl; i += 4) {
BN_ULONG t1, t2, t3, t4;
@@ -411,103 +409,25 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
return 1;
}
-#endif
-
-#define PTR_SIZE_INT size_t
-
-static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
- {
- BN_ULONG *ap,*np,*rp,n0,v,carry;
- int nl,max,i;
-
- const BIGNUM *n = &mont->N;
- nl=n->top;
- if (nl == 0) { ret->top=0; return(1); }
- max=(2*nl); /* carry is stored separately */
- if (bn_wexpand(r,max) == NULL) return(0);
-
- r->neg^=n->neg;
- np=n->d;
- rp=r->d;
-
- /* clear the top words of T */
-#if 1
- for (i=r->top; i<max; i++) /* memset? XXX */
- rp[i]=0;
-#else
- memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
-#endif
-
- r->top=max;
- n0=mont->n0[0];
-
- for (carry=0, i=0; i<nl; i++, rp++)
- {
- v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
- v = (v+carry+rp[nl])&BN_MASK2;
- carry |= (v != rp[nl]);
- carry &= (v <= rp[nl]);
- rp[nl]=v;
- }
-
- if (bn_wexpand(ret,nl) == NULL) return(0);
- ret->top=nl;
- ret->neg=r->neg;
-
- rp=ret->d;
- ap=&(r->d[nl]);
-
- {
- BN_ULONG *nrp;
- size_t m;
-
- v=bn_sub_words(rp,ap,np,nl)-carry;
- /* if subtraction result is real, then
- * trick unconditional memcpy below to perform in-place
- * "refresh" instead of actual copy. */
- m=(0-(size_t)v);
- nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
-
- for (i=0,nl-=4; i<nl; i+=4)
- {
- BN_ULONG t1,t2,t3,t4;
-
- t1=nrp[i+0];
- t2=nrp[i+1];
- t3=nrp[i+2]; ap[i+0]=0;
- t4=nrp[i+3]; ap[i+1]=0;
- rp[i+0]=t1; ap[i+2]=0;
- rp[i+1]=t2; ap[i+3]=0;
- rp[i+2]=t3;
- rp[i+3]=t4;
- }
- for (nl+=4; i<nl; i++)
- rp[i]=nrp[i], ap[i]=0;
- }
- bn_correct_top(r);
- bn_correct_top(ret);
-
- return(1);
- }
-
-int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
+int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont,
BN_CTX *ctx) {
- int retn = 0;
+ int ret = 0;
BIGNUM *t;
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
- if (t == NULL) {
- return 0;
+ if (t == NULL ||
+ !BN_copy(t, a)) {
+ goto err;
}
- if (BN_copy(t, a)) {
- retn = BN_from_montgomery_word(ret, t, mont);
- }
+ ret = BN_from_montgomery_word(r, t, mont);
+
+err:
BN_CTX_end(ctx);
- return retn;
+ return ret;
}
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
diff --git a/crypto/bn/mul.c b/crypto/bn/mul.c
index d2d8fd8c..06e53ee0 100644
--- a/crypto/bn/mul.c
+++ b/crypto/bn/mul.c
@@ -66,7 +66,8 @@
#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL
-void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
+static void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b,
+ int nb) {
BN_ULONG *rr;
if (na < nb) {
diff --git a/crypto/buf/buf.c b/crypto/buf/buf.c
index b918f01f..efe9952a 100644
--- a/crypto/buf/buf.c
+++ b/crypto/buf/buf.c
@@ -88,34 +88,26 @@ void BUF_MEM_free(BUF_MEM *buf) {
OPENSSL_free(buf);
}
-static size_t buf_mem_grow(BUF_MEM *buf, size_t len, char clean) {
- char *new_buf;
- size_t n, alloc_size;
-
- if (buf->length >= len) {
- buf->length = len;
- return len;
- }
- if (buf->max >= len) {
- memset(&buf->data[buf->length], 0, len - buf->length);
- buf->length = len;
- return len;
+static int buf_mem_reserve(BUF_MEM *buf, size_t cap, int clean) {
+ if (buf->max >= cap) {
+ return 1;
}
- n = len + 3;
- if (n < len) {
+ size_t n = cap + 3;
+ if (n < cap) {
/* overflow */
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return 0;
}
n = n / 3;
- alloc_size = n * 4;
+ size_t alloc_size = n * 4;
if (alloc_size / 4 != n) {
/* overflow */
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return 0;
}
+ char *new_buf;
if (buf->data == NULL) {
new_buf = OPENSSL_malloc(alloc_size);
} else {
@@ -128,14 +120,26 @@ static size_t buf_mem_grow(BUF_MEM *buf, size_t len, char clean) {
if (new_buf == NULL) {
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
- len = 0;
- } else {
- buf->data = new_buf;
- buf->max = alloc_size;
- memset(&buf->data[buf->length], 0, len - buf->length);
- buf->length = len;
+ return 0;
}
+ buf->data = new_buf;
+ buf->max = alloc_size;
+ return 1;
+}
+
+int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) {
+ return buf_mem_reserve(buf, cap, 0 /* don't clear old buffer contents. */);
+}
+
+static size_t buf_mem_grow(BUF_MEM *buf, size_t len, int clean) {
+ if (!buf_mem_reserve(buf, len, clean)) {
+ return 0;
+ }
+ if (buf->length < len) {
+ memset(&buf->data[buf->length], 0, len - buf->length);
+ }
+ buf->length = len;
return len;
}
diff --git a/crypto/bytestring/ber.c b/crypto/bytestring/ber.c
index 2a968e16..04fcac6a 100644
--- a/crypto/bytestring/ber.c
+++ b/crypto/bytestring/ber.c
@@ -34,6 +34,7 @@ static int is_string_type(unsigned tag) {
switch (tag & 0x1f) {
case CBS_ASN1_BITSTRING:
case CBS_ASN1_OCTETSTRING:
+ case CBS_ASN1_UTF8STRING:
case CBS_ASN1_NUMERICSTRING:
case CBS_ASN1_PRINTABLESTRING:
case CBS_ASN1_T16STRING:
diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc
index 84ecffcd..e1d16f49 100644
--- a/crypto/bytestring/bytestring_test.cc
+++ b/crypto/bytestring/bytestring_test.cc
@@ -43,7 +43,7 @@ static bool TestSkip() {
}
static bool TestGetUint() {
- static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
uint8_t u8;
uint16_t u16;
uint32_t u32;
@@ -58,7 +58,10 @@ static bool TestGetUint() {
u32 == 0x40506 &&
CBS_get_u32(&data, &u32) &&
u32 == 0x708090a &&
- !CBS_get_u8(&data, &u8);
+ CBS_get_last_u8(&data, &u8) &&
+ u8 == 0xb &&
+ !CBS_get_u8(&data, &u8) &&
+ !CBS_get_last_u8(&data, &u8);
}
static bool TestGetPrefixed() {
diff --git a/crypto/bytestring/cbs.c b/crypto/bytestring/cbs.c
index 5e0c538a..c86afbda 100644
--- a/crypto/bytestring/cbs.c
+++ b/crypto/bytestring/cbs.c
@@ -128,6 +128,15 @@ int CBS_get_u32(CBS *cbs, uint32_t *out) {
return cbs_get_u(cbs, out, 4);
}
+int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
+ if (cbs->len == 0) {
+ return 0;
+ }
+ *out = cbs->data[cbs->len - 1];
+ cbs->len--;
+ return 1;
+}
+
int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
const uint8_t *v;
if (!cbs_get(cbs, &v, len)) {
@@ -181,8 +190,14 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
return 0;
}
+ /* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
+ * number no greater than 30.
+ *
+ * If the number portion is 31 (0x1f, the largest value that fits in the
+ * allotted bits), then the tag is more than one byte long and the
+ * continuation bytes contain the tag number. This parser only supports tag
+ * numbers less than 31 (and thus single-byte tags). */
if ((tag & 0x1f) == 0x1f) {
- /* Long form tags are not supported. */
return 0;
}
@@ -191,6 +206,8 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
}
size_t len;
+ /* The format for the length encoding is specified in ITU-T X.690 section
+ * 8.1.3. */
if ((length_byte & 0x80) == 0) {
/* Short form length. */
len = ((size_t) length_byte) + 2;
@@ -198,7 +215,9 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
*out_header_len = 2;
}
} else {
- /* Long form length. */
+ /* The high bit indicate that this is the long form, while the next 7 bits
+ * encode the number of subsequent octets used to encode the length (ITU-T
+ * X.690 clause 8.1.3.5.b). */
const size_t num_bytes = length_byte & 0x7f;
uint32_t len32;
@@ -210,12 +229,18 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
return CBS_get_bytes(cbs, out, 2);
}
+ /* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
+ * used as the first byte of the length. If this parser encounters that
+ * value, num_bytes will be parsed as 127, which will fail the check below.
+ */
if (num_bytes == 0 || num_bytes > 4) {
return 0;
}
if (!cbs_get_u(&header, &len32, num_bytes)) {
return 0;
}
+ /* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
+ * with the minimum number of octets. */
if (len32 < 128) {
/* Length should have used short-form encoding. */
return 0;
diff --git a/crypto/chacha/CMakeLists.txt b/crypto/chacha/CMakeLists.txt
index 266e8699..73cfc31e 100644
--- a/crypto/chacha/CMakeLists.txt
+++ b/crypto/chacha/CMakeLists.txt
@@ -4,7 +4,31 @@ if (${ARCH} STREQUAL "arm")
set(
CHACHA_ARCH_SOURCES
- chacha_vec_arm.S
+ chacha-armv4.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "aarch64")
+ set(
+ CHACHA_ARCH_SOURCES
+
+ chacha-armv8.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ CHACHA_ARCH_SOURCES
+
+ chacha-x86.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ CHACHA_ARCH_SOURCES
+
+ chacha-x86_64.${ASM_EXT}
)
endif()
@@ -13,8 +37,24 @@ add_library(
OBJECT
- chacha_generic.c
- chacha_vec.c
+ chacha.c
${CHACHA_ARCH_SOURCES}
)
+
+if(ENABLE_TESTS)
+add_executable(
+ chacha_test
+
+ chacha_test.cc
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(chacha_test crypto)
+add_dependencies(all_tests chacha_test)
+endif()
+
+perlasm(chacha-armv4.${ASM_EXT} asm/chacha-armv4.pl)
+perlasm(chacha-armv8.${ASM_EXT} asm/chacha-armv8.pl)
+perlasm(chacha-x86.${ASM_EXT} asm/chacha-x86.pl)
+perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl)
diff --git a/crypto/chacha/asm/chacha-armv4.pl b/crypto/chacha/asm/chacha-armv4.pl
new file mode 100755
index 00000000..b190445d
--- /dev/null
+++ b/crypto/chacha/asm/chacha-armv4.pl
@@ -0,0 +1,1151 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# December 2014
+#
+# ChaCha20 for ARMv4.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# IALU/gcc-4.4 1xNEON 3xNEON+1xIALU
+#
+# Cortex-A5 19.3(*)/+95% 21.8 14.1
+# Cortex-A8 10.5(*)/+160% 13.9 6.35
+# Cortex-A9 12.9(**)/+110% 14.3 6.50
+# Cortex-A15 11.0/+40% 16.0 5.00
+# Snapdragon S4 11.5/+125% 13.6 4.90
+#
+# (*) most "favourable" result for aligned data on little-endian
+# processor, result for misaligned data is 10-15% lower;
+# (**) this result is a trade-off: it can be improved by 20%,
+# but then Snapdragon S4 and Cortex-A8 results get
+# 20-25% worse;
+
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
+
+sub AUTOLOAD() # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+ my $arg = pop;
+ $arg = "#$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+my @x=map("r$_",(0..7,"x","x","x","x",12,"x",14,"x"));
+my @t=map("r$_",(8..11));
+
+sub ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my $odd = $d0&1;
+my ($xc,$xc_) = (@t[0..1]);
+my ($xd,$xd_) = $odd ? (@t[2],@x[$d1]) : (@x[$d0],@t[2]);
+my @ret;
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' are permanently allocated in registers, @x[0..7],
+ # while 'c's and pair of 'd's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end. If you observe 'd' column, you'll
+ # notice that 15 and 13 are reused in next pair of rounds.
+ # This is why these two are chosen for offloading to memory,
+ # to make loads count more.
+ push @ret,(
+ "&add (@x[$a0],@x[$a0],@x[$b0])",
+ "&mov ($xd,$xd,'ror#16')",
+ "&add (@x[$a1],@x[$a1],@x[$b1])",
+ "&mov ($xd_,$xd_,'ror#16')",
+ "&eor ($xd,$xd,@x[$a0],'ror#16')",
+ "&eor ($xd_,$xd_,@x[$a1],'ror#16')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b0],@x[$b0],'ror#20')",
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b1],@x[$b1],'ror#20')",
+ "&eor (@x[$b0],@x[$b0],$xc,'ror#20')",
+ "&eor (@x[$b1],@x[$b1],$xc_,'ror#20')",
+
+ "&add (@x[$a0],@x[$a0],@x[$b0])",
+ "&mov ($xd,$xd,'ror#24')",
+ "&add (@x[$a1],@x[$a1],@x[$b1])",
+ "&mov ($xd_,$xd_,'ror#24')",
+ "&eor ($xd,$xd,@x[$a0],'ror#24')",
+ "&eor ($xd_,$xd_,@x[$a1],'ror#24')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b0],@x[$b0],'ror#25')" );
+ push @ret,(
+ "&str ($xd,'[sp,#4*(16+$d0)]')",
+ "&ldr ($xd,'[sp,#4*(16+$d2)]')" ) if ($odd);
+ push @ret,(
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b1],@x[$b1],'ror#25')" );
+ push @ret,(
+ "&str ($xd_,'[sp,#4*(16+$d1)]')",
+ "&ldr ($xd_,'[sp,#4*(16+$d3)]')" ) if (!$odd);
+ push @ret,(
+ "&eor (@x[$b0],@x[$b0],$xc,'ror#25')",
+ "&eor (@x[$b1],@x[$b1],$xc_,'ror#25')" );
+
+ $xd=@x[$d2] if (!$odd);
+ $xd_=@x[$d3] if ($odd);
+ push @ret,(
+ "&str ($xc,'[sp,#4*(16+$c0)]')",
+ "&ldr ($xc,'[sp,#4*(16+$c2)]')",
+ "&add (@x[$a2],@x[$a2],@x[$b2])",
+ "&mov ($xd,$xd,'ror#16')",
+ "&str ($xc_,'[sp,#4*(16+$c1)]')",
+ "&ldr ($xc_,'[sp,#4*(16+$c3)]')",
+ "&add (@x[$a3],@x[$a3],@x[$b3])",
+ "&mov ($xd_,$xd_,'ror#16')",
+ "&eor ($xd,$xd,@x[$a2],'ror#16')",
+ "&eor ($xd_,$xd_,@x[$a3],'ror#16')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b2],@x[$b2],'ror#20')",
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b3],@x[$b3],'ror#20')",
+ "&eor (@x[$b2],@x[$b2],$xc,'ror#20')",
+ "&eor (@x[$b3],@x[$b3],$xc_,'ror#20')",
+
+ "&add (@x[$a2],@x[$a2],@x[$b2])",
+ "&mov ($xd,$xd,'ror#24')",
+ "&add (@x[$a3],@x[$a3],@x[$b3])",
+ "&mov ($xd_,$xd_,'ror#24')",
+ "&eor ($xd,$xd,@x[$a2],'ror#24')",
+ "&eor ($xd_,$xd_,@x[$a3],'ror#24')",
+
+ "&add ($xc,$xc,$xd)",
+ "&mov (@x[$b2],@x[$b2],'ror#25')",
+ "&add ($xc_,$xc_,$xd_)",
+ "&mov (@x[$b3],@x[$b3],'ror#25')",
+ "&eor (@x[$b2],@x[$b2],$xc,'ror#25')",
+ "&eor (@x[$b3],@x[$b3],$xc_,'ror#25')" );
+
+ @ret;
+}
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+#if defined(__thumb2__)
+.syntax unified
+.thumb
+#else
+.code 32
+#endif
+
+#if defined(__thumb2__) || defined(__clang__)
+#define ldrhsb ldrbhs
+#endif
+
+.align 5
+.Lsigma:
+.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 @ endian-neutral
+.Lone:
+.long 1,0,0,0
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-.LChaCha20_ctr32
+#else
+.word -1
+#endif
+
+.globl ChaCha20_ctr32
+.type ChaCha20_ctr32,%function
+.align 5
+ChaCha20_ctr32:
+.LChaCha20_ctr32:
+ ldr r12,[sp,#0] @ pull pointer to counter and nonce
+ stmdb sp!,{r0-r2,r4-r11,lr}
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+ sub r14,pc,#16 @ ChaCha20_ctr32
+#else
+ adr r14,.LChaCha20_ctr32
+#endif
+ cmp r2,#0 @ len==0?
+#ifdef __thumb2__
+ itt eq
+#endif
+ addeq sp,sp,#4*3
+ beq .Lno_data
+#if __ARM_MAX_ARCH__>=7
+ cmp r2,#192 @ test len
+ bls .Lshort
+ ldr r4,[r14,#-32]
+ ldr r4,[r14,r4]
+# ifdef __APPLE__
+ ldr r4,[r4]
+# endif
+ tst r4,#ARMV7_NEON
+ bne .LChaCha20_neon
+.Lshort:
+#endif
+ ldmia r12,{r4-r7} @ load counter and nonce
+ sub sp,sp,#4*(16) @ off-load area
+ sub r14,r14,#64 @ .Lsigma
+ stmdb sp!,{r4-r7} @ copy counter and nonce
+ ldmia r3,{r4-r11} @ load key
+ ldmia r14,{r0-r3} @ load sigma
+ stmdb sp!,{r4-r11} @ copy key
+ stmdb sp!,{r0-r3} @ copy sigma
+ str r10,[sp,#4*(16+10)] @ off-load "@x[10]"
+ str r11,[sp,#4*(16+11)] @ off-load "@x[11]"
+ b .Loop_outer_enter
+
+.align 4
+.Loop_outer:
+ ldmia sp,{r0-r9} @ load key material
+ str @t[3],[sp,#4*(32+2)] @ save len
+ str r12, [sp,#4*(32+1)] @ save inp
+ str r14, [sp,#4*(32+0)] @ save out
+.Loop_outer_enter:
+ ldr @t[3], [sp,#4*(15)]
+ ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load
+ ldr @t[2], [sp,#4*(13)]
+ ldr @x[14],[sp,#4*(14)]
+ str @t[3], [sp,#4*(16+15)]
+ mov @t[3],#10
+ b .Loop
+
+.align 4
+.Loop:
+ subs @t[3],@t[3],#1
+___
+ foreach (&ROUND(0, 4, 8,12)) { eval; }
+ foreach (&ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ bne .Loop
+
+ ldr @t[3],[sp,#4*(32+2)] @ load len
+
+ str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store
+ str @t[1], [sp,#4*(16+9)]
+ str @x[12],[sp,#4*(16+12)]
+ str @t[2], [sp,#4*(16+13)]
+ str @x[14],[sp,#4*(16+14)]
+
+ @ at this point we have first half of 512-bit result in
+ @ @x[0-7] and second half at sp+4*(16+8)
+
+ cmp @t[3],#64 @ done yet?
+#ifdef __thumb2__
+ itete lo
+#endif
+ addlo r12,sp,#4*(0) @ shortcut or ...
+ ldrhs r12,[sp,#4*(32+1)] @ ... load inp
+ addlo r14,sp,#4*(0) @ shortcut or ...
+ ldrhs r14,[sp,#4*(32+0)] @ ... load out
+
+ ldr @t[0],[sp,#4*(0)] @ load key material
+ ldr @t[1],[sp,#4*(1)]
+
+#if __ARM_ARCH__>=6 || !defined(__ARMEB__)
+# if __ARM_ARCH__<7
+ orr @t[2],r12,r14
+ tst @t[2],#3 @ are input and output aligned?
+ ldr @t[2],[sp,#4*(2)]
+ bne .Lunaligned
+ cmp @t[3],#64 @ restore flags
+# else
+ ldr @t[2],[sp,#4*(2)]
+# endif
+ ldr @t[3],[sp,#4*(3)]
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @x[1],@x[1],@t[1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[0],@x[0],@t[0] @ xor with input
+ eorhs @x[1],@x[1],@t[1]
+ add @t[0],sp,#4*(4)
+ str @x[0],[r14],#16 @ store output
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[2],@x[2],@t[2]
+ eorhs @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[1],[r14,#-12]
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @x[5],@x[5],@t[1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[4],@x[4],@t[0]
+ eorhs @x[5],@x[5],@t[1]
+ add @t[0],sp,#4*(8)
+ str @x[4],[r14],#16 @ store output
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[6],@x[6],@t[2]
+ eorhs @x[7],@x[7],@t[3]
+ str @x[5],[r14,#-12]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[6],[r14,#-8]
+ add @x[0],sp,#4*(16+8)
+ str @x[7],[r14,#-4]
+
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @x[1],@x[1],@t[1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+# ifdef __thumb2__
+ itt hi
+# endif
+ strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it
+ strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[0],@x[0],@t[0]
+ eorhs @x[1],@x[1],@t[1]
+ add @t[0],sp,#4*(12)
+ str @x[0],[r14],#16 @ store output
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[2],@x[2],@t[2]
+ eorhs @x[3],@x[3],@t[3]
+ str @x[1],[r14,#-12]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @x[5],@x[5],@t[1]
+# ifdef __thumb2__
+ itt hi
+# endif
+ addhi @t[0],@t[0],#1 @ next counter value
+ strhi @t[0],[sp,#4*(12)] @ save next counter value
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[0],[r12],#16 @ load input
+ ldrhs @t[1],[r12,#-12]
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhs @t[2],[r12,#-8]
+ ldrhs @t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[4],@x[4],@t[0]
+ eorhs @x[5],@x[5],@t[1]
+# ifdef __thumb2__
+ it ne
+# endif
+ ldrne @t[0],[sp,#4*(32+2)] @ re-load len
+# ifdef __thumb2__
+ itt hs
+# endif
+ eorhs @x[6],@x[6],@t[2]
+ eorhs @x[7],@x[7],@t[3]
+ str @x[4],[r14],#16 @ store output
+ str @x[5],[r14,#-12]
+# ifdef __thumb2__
+ it hs
+# endif
+ subhs @t[3],@t[0],#64 @ len-=64
+ str @x[6],[r14,#-8]
+ str @x[7],[r14,#-4]
+ bhi .Loop_outer
+
+ beq .Ldone
+# if __ARM_ARCH__<7
+ b .Ltail
+
+.align 4
+.Lunaligned: @ unaligned endian-neutral path
+ cmp @t[3],#64 @ restore flags
+# endif
+#endif
+#if __ARM_ARCH__<7
+ ldr @t[3],[sp,#4*(3)]
+___
+for ($i=0;$i<16;$i+=4) {
+my $j=$i&0x7;
+
+$code.=<<___ if ($i==4);
+ add @x[0],sp,#4*(16+8)
+___
+$code.=<<___ if ($i==8);
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+# ifdef __thumb2__
+ itt hi
+# endif
+ strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]"
+ strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]"
+___
+$code.=<<___;
+ add @x[$j+0],@x[$j+0],@t[0] @ accumulate key material
+___
+$code.=<<___ if ($i==12);
+# ifdef __thumb2__
+ itt hi
+# endif
+ addhi @t[0],@t[0],#1 @ next counter value
+ strhi @t[0],[sp,#4*(12)] @ save next counter value
+___
+$code.=<<___;
+ add @x[$j+1],@x[$j+1],@t[1]
+ add @x[$j+2],@x[$j+2],@t[2]
+# ifdef __thumb2__
+ itete lo
+# endif
+ eorlo @t[0],@t[0],@t[0] @ zero or ...
+ ldrhsb @t[0],[r12],#16 @ ... load input
+ eorlo @t[1],@t[1],@t[1]
+ ldrhsb @t[1],[r12,#-12]
+
+ add @x[$j+3],@x[$j+3],@t[3]
+# ifdef __thumb2__
+ itete lo
+# endif
+ eorlo @t[2],@t[2],@t[2]
+ ldrhsb @t[2],[r12,#-8]
+ eorlo @t[3],@t[3],@t[3]
+ ldrhsb @t[3],[r12,#-4]
+
+ eor @x[$j+0],@t[0],@x[$j+0] @ xor with input (or zero)
+ eor @x[$j+1],@t[1],@x[$j+1]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[0],[r12,#-15] @ load more input
+ ldrhsb @t[1],[r12,#-11]
+ eor @x[$j+2],@t[2],@x[$j+2]
+ strb @x[$j+0],[r14],#16 @ store output
+ eor @x[$j+3],@t[3],@x[$j+3]
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[2],[r12,#-7]
+ ldrhsb @t[3],[r12,#-3]
+ strb @x[$j+1],[r14,#-12]
+ eor @x[$j+0],@t[0],@x[$j+0],lsr#8
+ strb @x[$j+2],[r14,#-8]
+ eor @x[$j+1],@t[1],@x[$j+1],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[0],[r12,#-14] @ load more input
+ ldrhsb @t[1],[r12,#-10]
+ strb @x[$j+3],[r14,#-4]
+ eor @x[$j+2],@t[2],@x[$j+2],lsr#8
+ strb @x[$j+0],[r14,#-15]
+ eor @x[$j+3],@t[3],@x[$j+3],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[2],[r12,#-6]
+ ldrhsb @t[3],[r12,#-2]
+ strb @x[$j+1],[r14,#-11]
+ eor @x[$j+0],@t[0],@x[$j+0],lsr#8
+ strb @x[$j+2],[r14,#-7]
+ eor @x[$j+1],@t[1],@x[$j+1],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[0],[r12,#-13] @ load more input
+ ldrhsb @t[1],[r12,#-9]
+ strb @x[$j+3],[r14,#-3]
+ eor @x[$j+2],@t[2],@x[$j+2],lsr#8
+ strb @x[$j+0],[r14,#-14]
+ eor @x[$j+3],@t[3],@x[$j+3],lsr#8
+# ifdef __thumb2__
+ itt hs
+# endif
+ ldrhsb @t[2],[r12,#-5]
+ ldrhsb @t[3],[r12,#-1]
+ strb @x[$j+1],[r14,#-10]
+ strb @x[$j+2],[r14,#-6]
+ eor @x[$j+0],@t[0],@x[$j+0],lsr#8
+ strb @x[$j+3],[r14,#-2]
+ eor @x[$j+1],@t[1],@x[$j+1],lsr#8
+ strb @x[$j+0],[r14,#-13]
+ eor @x[$j+2],@t[2],@x[$j+2],lsr#8
+ strb @x[$j+1],[r14,#-9]
+ eor @x[$j+3],@t[3],@x[$j+3],lsr#8
+ strb @x[$j+2],[r14,#-5]
+ strb @x[$j+3],[r14,#-1]
+___
+$code.=<<___ if ($i<12);
+ add @t[0],sp,#4*(4+$i)
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+___
+}
+$code.=<<___;
+# ifdef __thumb2__
+ it ne
+# endif
+ ldrne @t[0],[sp,#4*(32+2)] @ re-load len
+# ifdef __thumb2__
+ it hs
+# endif
+ subhs @t[3],@t[0],#64 @ len-=64
+ bhi .Loop_outer
+
+ beq .Ldone
+#endif
+
+.Ltail:
+ ldr r12,[sp,#4*(32+1)] @ load inp
+ add @t[1],sp,#4*(0)
+ ldr r14,[sp,#4*(32+0)] @ load out
+
+.Loop_tail:
+ ldrb @t[2],[@t[1]],#1 @ read buffer on stack
+ ldrb @t[3],[r12],#1 @ read input
+ subs @t[0],@t[0],#1
+ eor @t[3],@t[3],@t[2]
+ strb @t[3],[r14],#1 @ store output
+ bne .Loop_tail
+
+.Ldone:
+ add sp,sp,#4*(32+3)
+.Lno_data:
+ ldmia sp!,{r4-r11,pc}
+.size ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+{{{
+my ($a0,$b0,$c0,$d0,$a1,$b1,$c1,$d1,$a2,$b2,$c2,$d2,$t0,$t1,$t2,$t3) =
+ map("q$_",(0..15));
+
+sub NEONROUND {
+my $odd = pop;
+my ($a,$b,$c,$d,$t)=@_;
+
+ (
+ "&vadd_i32 ($a,$a,$b)",
+ "&veor ($d,$d,$a)",
+ "&vrev32_16 ($d,$d)", # vrot ($d,16)
+
+ "&vadd_i32 ($c,$c,$d)",
+ "&veor ($t,$b,$c)",
+ "&vshr_u32 ($b,$t,20)",
+ "&vsli_32 ($b,$t,12)",
+
+ "&vadd_i32 ($a,$a,$b)",
+ "&veor ($t,$d,$a)",
+ "&vshr_u32 ($d,$t,24)",
+ "&vsli_32 ($d,$t,8)",
+
+ "&vadd_i32 ($c,$c,$d)",
+ "&veor ($t,$b,$c)",
+ "&vshr_u32 ($b,$t,25)",
+ "&vsli_32 ($b,$t,7)",
+
+ "&vext_8 ($c,$c,$c,8)",
+ "&vext_8 ($b,$b,$b,$odd?12:4)",
+ "&vext_8 ($d,$d,$d,$odd?4:12)"
+ );
+}
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
+.type ChaCha20_neon,%function
+.align 5
+ChaCha20_neon:
+ ldr r12,[sp,#0] @ pull pointer to counter and nonce
+ stmdb sp!,{r0-r2,r4-r11,lr}
+.LChaCha20_neon:
+ adr r14,.Lsigma
+ vstmdb sp!,{d8-d15} @ ABI spec says so
+ stmdb sp!,{r0-r3}
+
+ vld1.32 {$b0-$c0},[r3] @ load key
+ ldmia r3,{r4-r11} @ load key
+
+ sub sp,sp,#4*(16+16)
+ vld1.32 {$d0},[r12] @ load counter and nonce
+ add r12,sp,#4*8
+ ldmia r14,{r0-r3} @ load sigma
+ vld1.32 {$a0},[r14]! @ load sigma
+ vld1.32 {$t0},[r14] @ one
+ vst1.32 {$c0-$d0},[r12] @ copy 1/2key|counter|nonce
+ vst1.32 {$a0-$b0},[sp] @ copy sigma|1/2key
+
+ str r10,[sp,#4*(16+10)] @ off-load "@x[10]"
+ str r11,[sp,#4*(16+11)] @ off-load "@x[11]"
+ vshl.i32 $t1#lo,$t0#lo,#1 @ two
+ vstr $t0#lo,[sp,#4*(16+0)]
+ vshl.i32 $t2#lo,$t0#lo,#2 @ four
+ vstr $t1#lo,[sp,#4*(16+2)]
+ vmov $a1,$a0
+ vstr $t2#lo,[sp,#4*(16+4)]
+ vmov $a2,$a0
+ vmov $b1,$b0
+ vmov $b2,$b0
+ b .Loop_neon_enter
+
+.align 4
+.Loop_neon_outer:
+ ldmia sp,{r0-r9} @ load key material
+ cmp @t[3],#64*2 @ if len<=64*2
+ bls .Lbreak_neon @ switch to integer-only
+ vmov $a1,$a0
+ str @t[3],[sp,#4*(32+2)] @ save len
+ vmov $a2,$a0
+ str r12, [sp,#4*(32+1)] @ save inp
+ vmov $b1,$b0
+ str r14, [sp,#4*(32+0)] @ save out
+ vmov $b2,$b0
+.Loop_neon_enter:
+ ldr @t[3], [sp,#4*(15)]
+ vadd.i32 $d1,$d0,$t0 @ counter+1
+ ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load
+ vmov $c1,$c0
+ ldr @t[2], [sp,#4*(13)]
+ vmov $c2,$c0
+ ldr @x[14],[sp,#4*(14)]
+ vadd.i32 $d2,$d1,$t0 @ counter+2
+ str @t[3], [sp,#4*(16+15)]
+ mov @t[3],#10
+ add @x[12],@x[12],#3 @ counter+3
+ b .Loop_neon
+
+.align 4
+.Loop_neon:
+ subs @t[3],@t[3],#1
+___
+ my @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,0);
+ my @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,0);
+ my @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,0);
+ my @thread3=&ROUND(0,4,8,12);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+
+ @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,1);
+ @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,1);
+ @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,1);
+ @thread3=&ROUND(0,5,10,15);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+$code.=<<___;
+ bne .Loop_neon
+
+ add @t[3],sp,#32
+ vld1.32 {$t0-$t1},[sp] @ load key material
+ vld1.32 {$t2-$t3},[@t[3]]
+
+ ldr @t[3],[sp,#4*(32+2)] @ load len
+
+ str @t[0], [sp,#4*(16+8)] @ modulo-scheduled store
+ str @t[1], [sp,#4*(16+9)]
+ str @x[12],[sp,#4*(16+12)]
+ str @t[2], [sp,#4*(16+13)]
+ str @x[14],[sp,#4*(16+14)]
+
+ @ at this point we have first half of 512-bit result in
+ @ @x[0-7] and second half at sp+4*(16+8)
+
+ ldr r12,[sp,#4*(32+1)] @ load inp
+ ldr r14,[sp,#4*(32+0)] @ load out
+
+ vadd.i32 $a0,$a0,$t0 @ accumulate key material
+ vadd.i32 $a1,$a1,$t0
+ vadd.i32 $a2,$a2,$t0
+ vldr $t0#lo,[sp,#4*(16+0)] @ one
+
+ vadd.i32 $b0,$b0,$t1
+ vadd.i32 $b1,$b1,$t1
+ vadd.i32 $b2,$b2,$t1
+ vldr $t1#lo,[sp,#4*(16+2)] @ two
+
+ vadd.i32 $c0,$c0,$t2
+ vadd.i32 $c1,$c1,$t2
+ vadd.i32 $c2,$c2,$t2
+ vadd.i32 $d1#lo,$d1#lo,$t0#lo @ counter+1
+ vadd.i32 $d2#lo,$d2#lo,$t1#lo @ counter+2
+
+ vadd.i32 $d0,$d0,$t3
+ vadd.i32 $d1,$d1,$t3
+ vadd.i32 $d2,$d2,$t3
+
+ cmp @t[3],#64*4
+ blo .Ltail_neon
+
+ vld1.8 {$t0-$t1},[r12]! @ load input
+ mov @t[3],sp
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0 @ xor with input
+ veor $b0,$b0,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a1,$a1,$t0
+ vst1.8 {$a0-$b0},[r14]! @ store output
+ veor $b1,$b1,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c1,$c1,$t2
+ vst1.8 {$c0-$d0},[r14]!
+ veor $d1,$d1,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a2,$a2,$t0
+ vld1.32 {$a0-$b0},[@t[3]]! @ load for next iteration
+ veor $t0#hi,$t0#hi,$t0#hi
+ vldr $t0#lo,[sp,#4*(16+4)] @ four
+ veor $b2,$b2,$t1
+ vld1.32 {$c0-$d0},[@t[3]]
+ veor $c2,$c2,$t2
+ vst1.8 {$a1-$b1},[r14]!
+ veor $d2,$d2,$t3
+ vst1.8 {$c1-$d1},[r14]!
+
+ vadd.i32 $d0#lo,$d0#lo,$t0#lo @ next counter value
+ vldr $t0#lo,[sp,#4*(16+0)] @ one
+
+ ldmia sp,{@t[0]-@t[3]} @ load key material
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ ldr @t[0],[r12],#16 @ load input
+ vst1.8 {$a2-$b2},[r14]!
+ add @x[1],@x[1],@t[1]
+ ldr @t[1],[r12,#-12]
+ vst1.8 {$c2-$d2},[r14]!
+ add @x[2],@x[2],@t[2]
+ ldr @t[2],[r12,#-8]
+ add @x[3],@x[3],@t[3]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+ eor @x[0],@x[0],@t[0] @ xor with input
+ add @t[0],sp,#4*(4)
+ eor @x[1],@x[1],@t[1]
+ str @x[0],[r14],#16 @ store output
+ eor @x[2],@x[2],@t[2]
+ str @x[1],[r14,#-12]
+ eor @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ ldr @t[0],[r12],#16 @ load input
+ add @x[5],@x[5],@t[1]
+ ldr @t[1],[r12,#-12]
+ add @x[6],@x[6],@t[2]
+ ldr @t[2],[r12,#-8]
+ add @x[7],@x[7],@t[3]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ eor @x[4],@x[4],@t[0]
+ add @t[0],sp,#4*(8)
+ eor @x[5],@x[5],@t[1]
+ str @x[4],[r14],#16 @ store output
+ eor @x[6],@x[6],@t[2]
+ str @x[5],[r14,#-12]
+ eor @x[7],@x[7],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[6],[r14,#-8]
+ add @x[0],sp,#4*(16+8)
+ str @x[7],[r14,#-4]
+
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ ldr @t[0],[r12],#16 @ load input
+ add @x[1],@x[1],@t[1]
+ ldr @t[1],[r12,#-12]
+# ifdef __thumb2__
+ it hi
+# endif
+ strhi @t[2],[sp,#4*(16+10)] @ copy "@x[10]" while at it
+ add @x[2],@x[2],@t[2]
+ ldr @t[2],[r12,#-8]
+# ifdef __thumb2__
+ it hi
+# endif
+ strhi @t[3],[sp,#4*(16+11)] @ copy "@x[11]" while at it
+ add @x[3],@x[3],@t[3]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+# endif
+ eor @x[0],@x[0],@t[0]
+ add @t[0],sp,#4*(12)
+ eor @x[1],@x[1],@t[1]
+ str @x[0],[r14],#16 @ store output
+ eor @x[2],@x[2],@t[2]
+ str @x[1],[r14,#-12]
+ eor @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+ str @x[2],[r14,#-8]
+ str @x[3],[r14,#-4]
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @t[0],@t[0],#4 @ next counter value
+ add @x[5],@x[5],@t[1]
+ str @t[0],[sp,#4*(12)] @ save next counter value
+ ldr @t[0],[r12],#16 @ load input
+ add @x[6],@x[6],@t[2]
+ add @x[4],@x[4],#3 @ counter+3
+ ldr @t[1],[r12,#-12]
+ add @x[7],@x[7],@t[3]
+ ldr @t[2],[r12,#-8]
+ ldr @t[3],[r12,#-4]
+# ifdef __ARMEB__
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ eor @x[4],@x[4],@t[0]
+# ifdef __thumb2__
+ it hi
+# endif
+ ldrhi @t[0],[sp,#4*(32+2)] @ re-load len
+ eor @x[5],@x[5],@t[1]
+ eor @x[6],@x[6],@t[2]
+ str @x[4],[r14],#16 @ store output
+ eor @x[7],@x[7],@t[3]
+ str @x[5],[r14,#-12]
+ sub @t[3],@t[0],#64*4 @ len-=64*4
+ str @x[6],[r14,#-8]
+ str @x[7],[r14,#-4]
+ bhi .Loop_neon_outer
+
+ b .Ldone_neon
+
+.align 4
+.Lbreak_neon:
+ @ harmonize NEON and integer-only stack frames: load data
+ @ from NEON frame, but save to integer-only one; distance
+ @ between the two is 4*(32+4+16-32)=4*(20).
+
+ str @t[3], [sp,#4*(20+32+2)] @ save len
+ add @t[3],sp,#4*(32+4)
+ str r12, [sp,#4*(20+32+1)] @ save inp
+ str r14, [sp,#4*(20+32+0)] @ save out
+
+ ldr @x[12],[sp,#4*(16+10)]
+ ldr @x[14],[sp,#4*(16+11)]
+ vldmia @t[3],{d8-d15} @ fulfill ABI requirement
+ str @x[12],[sp,#4*(20+16+10)] @ copy "@x[10]"
+ str @x[14],[sp,#4*(20+16+11)] @ copy "@x[11]"
+
+ ldr @t[3], [sp,#4*(15)]
+ ldr @x[12],[sp,#4*(12)] @ modulo-scheduled load
+ ldr @t[2], [sp,#4*(13)]
+ ldr @x[14],[sp,#4*(14)]
+ str @t[3], [sp,#4*(20+16+15)]
+ add @t[3],sp,#4*(20)
+ vst1.32 {$a0-$b0},[@t[3]]! @ copy key
+ add sp,sp,#4*(20) @ switch frame
+ vst1.32 {$c0-$d0},[@t[3]]
+ mov @t[3],#10
+ b .Loop @ go integer-only
+
+.align 4
+.Ltail_neon:
+ cmp @t[3],#64*3
+ bhs .L192_or_more_neon
+ cmp @t[3],#64*2
+ bhs .L128_or_more_neon
+ cmp @t[3],#64*1
+ bhs .L64_or_more_neon
+
+ add @t[0],sp,#4*(8)
+ vst1.8 {$a0-$b0},[sp]
+ add @t[2],sp,#4*(0)
+ vst1.8 {$c0-$d0},[@t[0]]
+ b .Loop_tail_neon
+
+.align 4
+.L64_or_more_neon:
+ vld1.8 {$t0-$t1},[r12]!
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0
+ veor $b0,$b0,$t1
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vst1.8 {$a0-$b0},[r14]!
+ vst1.8 {$c0-$d0},[r14]!
+
+ beq .Ldone_neon
+
+ add @t[0],sp,#4*(8)
+ vst1.8 {$a1-$b1},[sp]
+ add @t[2],sp,#4*(0)
+ vst1.8 {$c1-$d1},[@t[0]]
+ sub @t[3],@t[3],#64*1 @ len-=64*1
+ b .Loop_tail_neon
+
+.align 4
+.L128_or_more_neon:
+ vld1.8 {$t0-$t1},[r12]!
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0
+ veor $b0,$b0,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a1,$a1,$t0
+ veor $b1,$b1,$t1
+ vst1.8 {$a0-$b0},[r14]!
+ veor $c1,$c1,$t2
+ vst1.8 {$c0-$d0},[r14]!
+ veor $d1,$d1,$t3
+ vst1.8 {$a1-$b1},[r14]!
+ vst1.8 {$c1-$d1},[r14]!
+
+ beq .Ldone_neon
+
+ add @t[0],sp,#4*(8)
+ vst1.8 {$a2-$b2},[sp]
+ add @t[2],sp,#4*(0)
+ vst1.8 {$c2-$d2},[@t[0]]
+ sub @t[3],@t[3],#64*2 @ len-=64*2
+ b .Loop_tail_neon
+
+.align 4
+.L192_or_more_neon:
+ vld1.8 {$t0-$t1},[r12]!
+ vld1.8 {$t2-$t3},[r12]!
+ veor $a0,$a0,$t0
+ veor $b0,$b0,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c0,$c0,$t2
+ veor $d0,$d0,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a1,$a1,$t0
+ veor $b1,$b1,$t1
+ vld1.8 {$t0-$t1},[r12]!
+ veor $c1,$c1,$t2
+ vst1.8 {$a0-$b0},[r14]!
+ veor $d1,$d1,$t3
+ vld1.8 {$t2-$t3},[r12]!
+
+ veor $a2,$a2,$t0
+ vst1.8 {$c0-$d0},[r14]!
+ veor $b2,$b2,$t1
+ vst1.8 {$a1-$b1},[r14]!
+ veor $c2,$c2,$t2
+ vst1.8 {$c1-$d1},[r14]!
+ veor $d2,$d2,$t3
+ vst1.8 {$a2-$b2},[r14]!
+ vst1.8 {$c2-$d2},[r14]!
+
+ beq .Ldone_neon
+
+ ldmia sp,{@t[0]-@t[3]} @ load key material
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(4)
+ add @x[1],@x[1],@t[1]
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(8)
+ add @x[5],@x[5],@t[1]
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ stmia sp,{@x[0]-@x[7]}
+ add @x[0],sp,#4*(16+8)
+
+ ldmia @x[0],{@x[0]-@x[7]} @ load second half
+
+ add @x[0],@x[0],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(12)
+ add @x[1],@x[1],@t[1]
+ add @x[2],@x[2],@t[2]
+ add @x[3],@x[3],@t[3]
+ ldmia @t[0],{@t[0]-@t[3]} @ load key material
+
+ add @x[4],@x[4],@t[0] @ accumulate key material
+ add @t[0],sp,#4*(8)
+ add @x[5],@x[5],@t[1]
+ add @x[4],@x[4],#3 @ counter+3
+ add @x[6],@x[6],@t[2]
+ add @x[7],@x[7],@t[3]
+ ldr @t[3],[sp,#4*(32+2)] @ re-load len
+# ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[1],@x[1]
+ rev @x[2],@x[2]
+ rev @x[3],@x[3]
+ rev @x[4],@x[4]
+ rev @x[5],@x[5]
+ rev @x[6],@x[6]
+ rev @x[7],@x[7]
+# endif
+ stmia @t[0],{@x[0]-@x[7]}
+ add @t[2],sp,#4*(0)
+ sub @t[3],@t[3],#64*3 @ len-=64*3
+
+.Loop_tail_neon:
+ ldrb @t[0],[@t[2]],#1 @ read buffer on stack
+ ldrb @t[1],[r12],#1 @ read input
+ subs @t[3],@t[3],#1
+ eor @t[0],@t[0],@t[1]
+ strb @t[0],[r14],#1 @ store ouput
+ bne .Loop_tail_neon
+
+.Ldone_neon:
+ add sp,sp,#4*(32+4)
+ vldmia sp,{d8-d15}
+ add sp,sp,#4*(16+3)
+ ldmia sp!,{r4-r11,pc}
+.size ChaCha20_neon,.-ChaCha20_neon
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+}}}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/crypto/chacha/asm/chacha-armv8.pl b/crypto/chacha/asm/chacha-armv8.pl
new file mode 100755
index 00000000..215d9657
--- /dev/null
+++ b/crypto/chacha/asm/chacha-armv8.pl
@@ -0,0 +1,1127 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# June 2015
+#
+# ChaCha20 for ARMv8.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU
+#
+# Apple A7 5.50/+49% 3.33 1.70
+# Cortex-A53 8.40/+80% 4.72 4.72(*)
+# Cortex-A57 8.06/+43% 4.90 4.43(**)
+# Denver 4.50/+82% 2.63 2.67(*)
+# X-Gene 9.50/+46% 8.82 8.89(*)
+#
+# (*) it's expected that doubling interleave factor doesn't help
+# all processors, only those with higher NEON latency and
+# higher instruction issue rate;
+# (**) expected improvement was actually higher;
+
+$flavour=shift;
+$output=shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+sub AUTOLOAD() # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+ my $arg = pop;
+ $arg = "#$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+my ($out,$inp,$len,$key,$ctr) = map("x$_",(0..4));
+
+my @x=map("x$_",(5..17,19..21));
+my @d=map("x$_",(22..28,30));
+
+sub ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+
+ (
+ "&add_32 (@x[$a0],@x[$a0],@x[$b0])",
+ "&add_32 (@x[$a1],@x[$a1],@x[$b1])",
+ "&add_32 (@x[$a2],@x[$a2],@x[$b2])",
+ "&add_32 (@x[$a3],@x[$a3],@x[$b3])",
+ "&eor_32 (@x[$d0],@x[$d0],@x[$a0])",
+ "&eor_32 (@x[$d1],@x[$d1],@x[$a1])",
+ "&eor_32 (@x[$d2],@x[$d2],@x[$a2])",
+ "&eor_32 (@x[$d3],@x[$d3],@x[$a3])",
+ "&ror_32 (@x[$d0],@x[$d0],16)",
+ "&ror_32 (@x[$d1],@x[$d1],16)",
+ "&ror_32 (@x[$d2],@x[$d2],16)",
+ "&ror_32 (@x[$d3],@x[$d3],16)",
+
+ "&add_32 (@x[$c0],@x[$c0],@x[$d0])",
+ "&add_32 (@x[$c1],@x[$c1],@x[$d1])",
+ "&add_32 (@x[$c2],@x[$c2],@x[$d2])",
+ "&add_32 (@x[$c3],@x[$c3],@x[$d3])",
+ "&eor_32 (@x[$b0],@x[$b0],@x[$c0])",
+ "&eor_32 (@x[$b1],@x[$b1],@x[$c1])",
+ "&eor_32 (@x[$b2],@x[$b2],@x[$c2])",
+ "&eor_32 (@x[$b3],@x[$b3],@x[$c3])",
+ "&ror_32 (@x[$b0],@x[$b0],20)",
+ "&ror_32 (@x[$b1],@x[$b1],20)",
+ "&ror_32 (@x[$b2],@x[$b2],20)",
+ "&ror_32 (@x[$b3],@x[$b3],20)",
+
+ "&add_32 (@x[$a0],@x[$a0],@x[$b0])",
+ "&add_32 (@x[$a1],@x[$a1],@x[$b1])",
+ "&add_32 (@x[$a2],@x[$a2],@x[$b2])",
+ "&add_32 (@x[$a3],@x[$a3],@x[$b3])",
+ "&eor_32 (@x[$d0],@x[$d0],@x[$a0])",
+ "&eor_32 (@x[$d1],@x[$d1],@x[$a1])",
+ "&eor_32 (@x[$d2],@x[$d2],@x[$a2])",
+ "&eor_32 (@x[$d3],@x[$d3],@x[$a3])",
+ "&ror_32 (@x[$d0],@x[$d0],24)",
+ "&ror_32 (@x[$d1],@x[$d1],24)",
+ "&ror_32 (@x[$d2],@x[$d2],24)",
+ "&ror_32 (@x[$d3],@x[$d3],24)",
+
+ "&add_32 (@x[$c0],@x[$c0],@x[$d0])",
+ "&add_32 (@x[$c1],@x[$c1],@x[$d1])",
+ "&add_32 (@x[$c2],@x[$c2],@x[$d2])",
+ "&add_32 (@x[$c3],@x[$c3],@x[$d3])",
+ "&eor_32 (@x[$b0],@x[$b0],@x[$c0])",
+ "&eor_32 (@x[$b1],@x[$b1],@x[$c1])",
+ "&eor_32 (@x[$b2],@x[$b2],@x[$c2])",
+ "&eor_32 (@x[$b3],@x[$b3],@x[$c3])",
+ "&ror_32 (@x[$b0],@x[$b0],25)",
+ "&ror_32 (@x[$b1],@x[$b1],25)",
+ "&ror_32 (@x[$b2],@x[$b2],25)",
+ "&ror_32 (@x[$b3],@x[$b3],25)"
+ );
+}
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+
+.extern OPENSSL_armcap_P
+
+.align 5
+.Lsigma:
+.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral
+.Lone:
+.long 1,0,0,0
+.LOPENSSL_armcap_P:
+#ifdef __ILP32__
+.long OPENSSL_armcap_P-.
+#else
+.quad OPENSSL_armcap_P-.
+#endif
+.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+
+.globl ChaCha20_ctr32
+.type ChaCha20_ctr32,%function
+.align 5
+ChaCha20_ctr32:
+ cbz $len,.Labort
+ adr @x[0],.LOPENSSL_armcap_P
+ cmp $len,#192
+ b.lo .Lshort
+#ifdef __ILP32__
+ ldrsw @x[1],[@x[0]]
+#else
+ ldr @x[1],[@x[0]]
+#endif
+ ldr w17,[@x[1],@x[0]]
+ tst w17,#ARMV7_NEON
+ b.ne ChaCha20_neon
+
+.Lshort:
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+
+ adr @x[0],.Lsigma
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#64
+
+ ldp @d[0],@d[1],[@x[0]] // load sigma
+ ldp @d[2],@d[3],[$key] // load key
+ ldp @d[4],@d[5],[$key,#16]
+ ldp @d[6],@d[7],[$ctr] // load counter
+#ifdef __ARMEB__
+ ror @d[2],@d[2],#32
+ ror @d[3],@d[3],#32
+ ror @d[4],@d[4],#32
+ ror @d[5],@d[5],#32
+ ror @d[6],@d[6],#32
+ ror @d[7],@d[7],#32
+#endif
+
+.Loop_outer:
+ mov.32 @x[0],@d[0] // unpack key block
+ lsr @x[1],@d[0],#32
+ mov.32 @x[2],@d[1]
+ lsr @x[3],@d[1],#32
+ mov.32 @x[4],@d[2]
+ lsr @x[5],@d[2],#32
+ mov.32 @x[6],@d[3]
+ lsr @x[7],@d[3],#32
+ mov.32 @x[8],@d[4]
+ lsr @x[9],@d[4],#32
+ mov.32 @x[10],@d[5]
+ lsr @x[11],@d[5],#32
+ mov.32 @x[12],@d[6]
+ lsr @x[13],@d[6],#32
+ mov.32 @x[14],@d[7]
+ lsr @x[15],@d[7],#32
+
+ mov $ctr,#10
+ subs $len,$len,#64
+.Loop:
+ sub $ctr,$ctr,#1
+___
+ foreach (&ROUND(0, 4, 8,12)) { eval; }
+ foreach (&ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ cbnz $ctr,.Loop
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ add @x[1],@x[1],@d[0],lsr#32
+ add.32 @x[2],@x[2],@d[1]
+ add @x[3],@x[3],@d[1],lsr#32
+ add.32 @x[4],@x[4],@d[2]
+ add @x[5],@x[5],@d[2],lsr#32
+ add.32 @x[6],@x[6],@d[3]
+ add @x[7],@x[7],@d[3],lsr#32
+ add.32 @x[8],@x[8],@d[4]
+ add @x[9],@x[9],@d[4],lsr#32
+ add.32 @x[10],@x[10],@d[5]
+ add @x[11],@x[11],@d[5],lsr#32
+ add.32 @x[12],@x[12],@d[6]
+ add @x[13],@x[13],@d[6],lsr#32
+ add.32 @x[14],@x[14],@d[7]
+ add @x[15],@x[15],@d[7],lsr#32
+
+ b.lo .Ltail
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor @x[10],@x[10],@x[11]
+ eor @x[12],@x[12],@x[13]
+ eor @x[14],@x[14],@x[15]
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#1 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ stp @x[8],@x[10],[$out,#32]
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+
+ b.hi .Loop_outer
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+.Labort:
+ ret
+
+.align 4
+.Ltail:
+ add $len,$len,#64
+.Less_than_64:
+ sub $out,$out,#1
+ add $inp,$inp,$len
+ add $out,$out,$len
+ add $ctr,sp,$len
+ neg $len,$len
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ stp @x[0],@x[2],[sp,#0]
+ stp @x[4],@x[6],[sp,#16]
+ stp @x[8],@x[10],[sp,#32]
+ stp @x[12],@x[14],[sp,#48]
+
+.Loop_tail:
+ ldrb w10,[$inp,$len]
+ ldrb w11,[$ctr,$len]
+ add $len,$len,#1
+ eor w10,w10,w11
+ strb w10,[$out,$len]
+ cbnz $len,.Loop_tail
+
+ stp xzr,xzr,[sp,#0]
+ stp xzr,xzr,[sp,#16]
+ stp xzr,xzr,[sp,#32]
+ stp xzr,xzr,[sp,#48]
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+.size ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+{{{
+my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) =
+ map("v$_.4s",(0..7,16..23));
+my (@K)=map("v$_.4s",(24..30));
+my $ONE="v31.4s";
+
+sub NEONROUND {
+my $odd = pop;
+my ($a,$b,$c,$d,$t)=@_;
+
+ (
+ "&add ('$a','$a','$b')",
+ "&eor ('$d','$d','$a')",
+ "&rev32_16 ('$d','$d')", # vrot ($d,16)
+
+ "&add ('$c','$c','$d')",
+ "&eor ('$t','$b','$c')",
+ "&ushr ('$b','$t',20)",
+ "&sli ('$b','$t',12)",
+
+ "&add ('$a','$a','$b')",
+ "&eor ('$t','$d','$a')",
+ "&ushr ('$d','$t',24)",
+ "&sli ('$d','$t',8)",
+
+ "&add ('$c','$c','$d')",
+ "&eor ('$t','$b','$c')",
+ "&ushr ('$b','$t',25)",
+ "&sli ('$b','$t',7)",
+
+ "&ext ('$c','$c','$c',8)",
+ "&ext ('$d','$d','$d',$odd?4:12)",
+ "&ext ('$b','$b','$b',$odd?12:4)"
+ );
+}
+
+$code.=<<___;
+
+.type ChaCha20_neon,%function
+.align 5
+ChaCha20_neon:
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+
+ adr @x[0],.Lsigma
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ cmp $len,#512
+ b.hs .L512_or_more_neon
+
+ sub sp,sp,#64
+
+ ldp @d[0],@d[1],[@x[0]] // load sigma
+ ld1 {@K[0]},[@x[0]],#16
+ ldp @d[2],@d[3],[$key] // load key
+ ldp @d[4],@d[5],[$key,#16]
+ ld1 {@K[1],@K[2]},[$key]
+ ldp @d[6],@d[7],[$ctr] // load counter
+ ld1 {@K[3]},[$ctr]
+ ld1 {$ONE},[@x[0]]
+#ifdef __ARMEB__
+ rev64 @K[0],@K[0]
+ ror @d[2],@d[2],#32
+ ror @d[3],@d[3],#32
+ ror @d[4],@d[4],#32
+ ror @d[5],@d[5],#32
+ ror @d[6],@d[6],#32
+ ror @d[7],@d[7],#32
+#endif
+ add @K[3],@K[3],$ONE // += 1
+ add @K[4],@K[3],$ONE
+ add @K[5],@K[4],$ONE
+ shl $ONE,$ONE,#2 // 1 -> 4
+
+.Loop_outer_neon:
+ mov.32 @x[0],@d[0] // unpack key block
+ lsr @x[1],@d[0],#32
+ mov $A0,@K[0]
+ mov.32 @x[2],@d[1]
+ lsr @x[3],@d[1],#32
+ mov $A1,@K[0]
+ mov.32 @x[4],@d[2]
+ lsr @x[5],@d[2],#32
+ mov $A2,@K[0]
+ mov.32 @x[6],@d[3]
+ mov $B0,@K[1]
+ lsr @x[7],@d[3],#32
+ mov $B1,@K[1]
+ mov.32 @x[8],@d[4]
+ mov $B2,@K[1]
+ lsr @x[9],@d[4],#32
+ mov $D0,@K[3]
+ mov.32 @x[10],@d[5]
+ mov $D1,@K[4]
+ lsr @x[11],@d[5],#32
+ mov $D2,@K[5]
+ mov.32 @x[12],@d[6]
+ mov $C0,@K[2]
+ lsr @x[13],@d[6],#32
+ mov $C1,@K[2]
+ mov.32 @x[14],@d[7]
+ mov $C2,@K[2]
+ lsr @x[15],@d[7],#32
+
+ mov $ctr,#10
+ subs $len,$len,#256
+.Loop_neon:
+ sub $ctr,$ctr,#1
+___
+ my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+ my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+ my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+ my @thread3=&ROUND(0,4,8,12);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+ @thread3=&ROUND(0,5,10,15);
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread3));
+ eval(shift(@thread1)); eval(shift(@thread3));
+ eval(shift(@thread2)); eval(shift(@thread3));
+ }
+$code.=<<___;
+ cbnz $ctr,.Loop_neon
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ add $A0,$A0,@K[0]
+ add @x[1],@x[1],@d[0],lsr#32
+ add $A1,$A1,@K[0]
+ add.32 @x[2],@x[2],@d[1]
+ add $A2,$A2,@K[0]
+ add @x[3],@x[3],@d[1],lsr#32
+ add $C0,$C0,@K[2]
+ add.32 @x[4],@x[4],@d[2]
+ add $C1,$C1,@K[2]
+ add @x[5],@x[5],@d[2],lsr#32
+ add $C2,$C2,@K[2]
+ add.32 @x[6],@x[6],@d[3]
+ add $D0,$D0,@K[3]
+ add @x[7],@x[7],@d[3],lsr#32
+ add.32 @x[8],@x[8],@d[4]
+ add $D1,$D1,@K[4]
+ add @x[9],@x[9],@d[4],lsr#32
+ add.32 @x[10],@x[10],@d[5]
+ add $D2,$D2,@K[5]
+ add @x[11],@x[11],@d[5],lsr#32
+ add.32 @x[12],@x[12],@d[6]
+ add $B0,$B0,@K[1]
+ add @x[13],@x[13],@d[6],lsr#32
+ add.32 @x[14],@x[14],@d[7]
+ add $B1,$B1,@K[1]
+ add @x[15],@x[15],@d[7],lsr#32
+ add $B2,$B2,@K[1]
+
+ b.lo .Ltail_neon
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor $A0,$A0,$T0
+ eor @x[10],@x[10],@x[11]
+ eor $B0,$B0,$T1
+ eor @x[12],@x[12],@x[13]
+ eor $C0,$C0,$T2
+ eor @x[14],@x[14],@x[15]
+ eor $D0,$D0,$T3
+ ld1.8 {$T0-$T3},[$inp],#64
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#4 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ add @K[3],@K[3],$ONE // += 4
+ stp @x[8],@x[10],[$out,#32]
+ add @K[4],@K[4],$ONE
+ stp @x[12],@x[14],[$out,#48]
+ add @K[5],@K[5],$ONE
+ add $out,$out,#64
+
+ st1.8 {$A0-$D0},[$out],#64
+ ld1.8 {$A0-$D0},[$inp],#64
+
+ eor $A1,$A1,$T0
+ eor $B1,$B1,$T1
+ eor $C1,$C1,$T2
+ eor $D1,$D1,$T3
+ st1.8 {$A1-$D1},[$out],#64
+
+ eor $A2,$A2,$A0
+ eor $B2,$B2,$B0
+ eor $C2,$C2,$C0
+ eor $D2,$D2,$D0
+ st1.8 {$A2-$D2},[$out],#64
+
+ b.hi .Loop_outer_neon
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+
+.Ltail_neon:
+ add $len,$len,#256
+ cmp $len,#64
+ b.lo .Less_than_64
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor @x[10],@x[10],@x[11]
+ eor @x[12],@x[12],@x[13]
+ eor @x[14],@x[14],@x[15]
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#4 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ stp @x[8],@x[10],[$out,#32]
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+ b.eq .Ldone_neon
+ sub $len,$len,#64
+ cmp $len,#64
+ b.lo .Less_than_128
+
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor $A0,$A0,$T0
+ eor $B0,$B0,$T1
+ eor $C0,$C0,$T2
+ eor $D0,$D0,$T3
+ st1.8 {$A0-$D0},[$out],#64
+ b.eq .Ldone_neon
+ sub $len,$len,#64
+ cmp $len,#64
+ b.lo .Less_than_192
+
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor $A1,$A1,$T0
+ eor $B1,$B1,$T1
+ eor $C1,$C1,$T2
+ eor $D1,$D1,$T3
+ st1.8 {$A1-$D1},[$out],#64
+ b.eq .Ldone_neon
+ sub $len,$len,#64
+
+ st1.8 {$A2-$D2},[sp]
+ b .Last_neon
+
+.Less_than_128:
+ st1.8 {$A0-$D0},[sp]
+ b .Last_neon
+.Less_than_192:
+ st1.8 {$A1-$D1},[sp]
+ b .Last_neon
+
+.align 4
+.Last_neon:
+ sub $out,$out,#1
+ add $inp,$inp,$len
+ add $out,$out,$len
+ add $ctr,sp,$len
+ neg $len,$len
+
+.Loop_tail_neon:
+ ldrb w10,[$inp,$len]
+ ldrb w11,[$ctr,$len]
+ add $len,$len,#1
+ eor w10,w10,w11
+ strb w10,[$out,$len]
+ cbnz $len,.Loop_tail_neon
+
+ stp xzr,xzr,[sp,#0]
+ stp xzr,xzr,[sp,#16]
+ stp xzr,xzr,[sp,#32]
+ stp xzr,xzr,[sp,#48]
+
+.Ldone_neon:
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+.size ChaCha20_neon,.-ChaCha20_neon
+___
+{
+my ($T0,$T1,$T2,$T3,$T4,$T5)=@K;
+my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,
+ $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23));
+
+$code.=<<___;
+.type ChaCha20_512_neon,%function
+.align 5
+ChaCha20_512_neon:
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+
+ adr @x[0],.Lsigma
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+
+.L512_or_more_neon:
+ sub sp,sp,#128+64
+
+ ldp @d[0],@d[1],[@x[0]] // load sigma
+ ld1 {@K[0]},[@x[0]],#16
+ ldp @d[2],@d[3],[$key] // load key
+ ldp @d[4],@d[5],[$key,#16]
+ ld1 {@K[1],@K[2]},[$key]
+ ldp @d[6],@d[7],[$ctr] // load counter
+ ld1 {@K[3]},[$ctr]
+ ld1 {$ONE},[@x[0]]
+#ifdef __ARMEB__
+ rev64 @K[0],@K[0]
+ ror @d[2],@d[2],#32
+ ror @d[3],@d[3],#32
+ ror @d[4],@d[4],#32
+ ror @d[5],@d[5],#32
+ ror @d[6],@d[6],#32
+ ror @d[7],@d[7],#32
+#endif
+ add @K[3],@K[3],$ONE // += 1
+ stp @K[0],@K[1],[sp,#0] // off-load key block, invariant part
+ add @K[3],@K[3],$ONE // not typo
+ str @K[2],[sp,#32]
+ add @K[4],@K[3],$ONE
+ add @K[5],@K[4],$ONE
+ add @K[6],@K[5],$ONE
+ shl $ONE,$ONE,#2 // 1 -> 4
+
+ stp d8,d9,[sp,#128+0] // meet ABI requirements
+ stp d10,d11,[sp,#128+16]
+ stp d12,d13,[sp,#128+32]
+ stp d14,d15,[sp,#128+48]
+
+ sub $len,$len,#512 // not typo
+
+.Loop_outer_512_neon:
+ mov $A0,@K[0]
+ mov $A1,@K[0]
+ mov $A2,@K[0]
+ mov $A3,@K[0]
+ mov $A4,@K[0]
+ mov $A5,@K[0]
+ mov $B0,@K[1]
+ mov.32 @x[0],@d[0] // unpack key block
+ mov $B1,@K[1]
+ lsr @x[1],@d[0],#32
+ mov $B2,@K[1]
+ mov.32 @x[2],@d[1]
+ mov $B3,@K[1]
+ lsr @x[3],@d[1],#32
+ mov $B4,@K[1]
+ mov.32 @x[4],@d[2]
+ mov $B5,@K[1]
+ lsr @x[5],@d[2],#32
+ mov $D0,@K[3]
+ mov.32 @x[6],@d[3]
+ mov $D1,@K[4]
+ lsr @x[7],@d[3],#32
+ mov $D2,@K[5]
+ mov.32 @x[8],@d[4]
+ mov $D3,@K[6]
+ lsr @x[9],@d[4],#32
+ mov $C0,@K[2]
+ mov.32 @x[10],@d[5]
+ mov $C1,@K[2]
+ lsr @x[11],@d[5],#32
+ add $D4,$D0,$ONE // +4
+ mov.32 @x[12],@d[6]
+ add $D5,$D1,$ONE // +4
+ lsr @x[13],@d[6],#32
+ mov $C2,@K[2]
+ mov.32 @x[14],@d[7]
+ mov $C3,@K[2]
+ lsr @x[15],@d[7],#32
+ mov $C4,@K[2]
+ stp @K[3],@K[4],[sp,#48] // off-load key block, variable part
+ mov $C5,@K[2]
+ str @K[5],[sp,#80]
+
+ mov $ctr,#5
+ subs $len,$len,#512
+.Loop_upper_neon:
+ sub $ctr,$ctr,#1
+___
+ my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+ my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+ my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+ my @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0);
+ my @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0);
+ my @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0);
+ my @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+ my $diff = ($#thread0+1)*6 - $#thread67 - 1;
+ my $i = 0;
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+ @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1);
+ @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1);
+ @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1);
+ @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+$code.=<<___;
+ cbnz $ctr,.Loop_upper_neon
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ add @x[1],@x[1],@d[0],lsr#32
+ add.32 @x[2],@x[2],@d[1]
+ add @x[3],@x[3],@d[1],lsr#32
+ add.32 @x[4],@x[4],@d[2]
+ add @x[5],@x[5],@d[2],lsr#32
+ add.32 @x[6],@x[6],@d[3]
+ add @x[7],@x[7],@d[3],lsr#32
+ add.32 @x[8],@x[8],@d[4]
+ add @x[9],@x[9],@d[4],lsr#32
+ add.32 @x[10],@x[10],@d[5]
+ add @x[11],@x[11],@d[5],lsr#32
+ add.32 @x[12],@x[12],@d[6]
+ add @x[13],@x[13],@d[6],lsr#32
+ add.32 @x[14],@x[14],@d[7]
+ add @x[15],@x[15],@d[7],lsr#32
+
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add @x[2],@x[2],@x[3],lsl#32
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add @x[4],@x[4],@x[5],lsl#32
+ add @x[6],@x[6],@x[7],lsl#32
+ ldp @x[5],@x[7],[$inp,#16]
+ add @x[8],@x[8],@x[9],lsl#32
+ add @x[10],@x[10],@x[11],lsl#32
+ ldp @x[9],@x[11],[$inp,#32]
+ add @x[12],@x[12],@x[13],lsl#32
+ add @x[14],@x[14],@x[15],lsl#32
+ ldp @x[13],@x[15],[$inp,#48]
+ add $inp,$inp,#64
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor @x[10],@x[10],@x[11]
+ eor @x[12],@x[12],@x[13]
+ eor @x[14],@x[14],@x[15]
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#1 // increment counter
+ mov.32 @x[0],@d[0] // unpack key block
+ lsr @x[1],@d[0],#32
+ stp @x[4],@x[6],[$out,#16]
+ mov.32 @x[2],@d[1]
+ lsr @x[3],@d[1],#32
+ stp @x[8],@x[10],[$out,#32]
+ mov.32 @x[4],@d[2]
+ lsr @x[5],@d[2],#32
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+ mov.32 @x[6],@d[3]
+ lsr @x[7],@d[3],#32
+ mov.32 @x[8],@d[4]
+ lsr @x[9],@d[4],#32
+ mov.32 @x[10],@d[5]
+ lsr @x[11],@d[5],#32
+ mov.32 @x[12],@d[6]
+ lsr @x[13],@d[6],#32
+ mov.32 @x[14],@d[7]
+ lsr @x[15],@d[7],#32
+
+ mov $ctr,#5
+.Loop_lower_neon:
+ sub $ctr,$ctr,#1
+___
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+ @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0);
+ @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0);
+ @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0);
+ @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+
+ @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+ @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+ @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+ @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1);
+ @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1);
+ @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1);
+ @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+ foreach (@thread0) {
+ eval; eval(shift(@thread67));
+ eval(shift(@thread1)); eval(shift(@thread67));
+ eval(shift(@thread2)); eval(shift(@thread67));
+ eval(shift(@thread3)); eval(shift(@thread67));
+ eval(shift(@thread4)); eval(shift(@thread67));
+ eval(shift(@thread5)); eval(shift(@thread67));
+ }
+$code.=<<___;
+ cbnz $ctr,.Loop_lower_neon
+
+ add.32 @x[0],@x[0],@d[0] // accumulate key block
+ ldp @K[0],@K[1],[sp,#0]
+ add @x[1],@x[1],@d[0],lsr#32
+ ldp @K[2],@K[3],[sp,#32]
+ add.32 @x[2],@x[2],@d[1]
+ ldp @K[4],@K[5],[sp,#64]
+ add @x[3],@x[3],@d[1],lsr#32
+ add $A0,$A0,@K[0]
+ add.32 @x[4],@x[4],@d[2]
+ add $A1,$A1,@K[0]
+ add @x[5],@x[5],@d[2],lsr#32
+ add $A2,$A2,@K[0]
+ add.32 @x[6],@x[6],@d[3]
+ add $A3,$A3,@K[0]
+ add @x[7],@x[7],@d[3],lsr#32
+ add $A4,$A4,@K[0]
+ add.32 @x[8],@x[8],@d[4]
+ add $A5,$A5,@K[0]
+ add @x[9],@x[9],@d[4],lsr#32
+ add $C0,$C0,@K[2]
+ add.32 @x[10],@x[10],@d[5]
+ add $C1,$C1,@K[2]
+ add @x[11],@x[11],@d[5],lsr#32
+ add $C2,$C2,@K[2]
+ add.32 @x[12],@x[12],@d[6]
+ add $C3,$C3,@K[2]
+ add @x[13],@x[13],@d[6],lsr#32
+ add $C4,$C4,@K[2]
+ add.32 @x[14],@x[14],@d[7]
+ add $C5,$C5,@K[2]
+ add @x[15],@x[15],@d[7],lsr#32
+ add $D4,$D4,$ONE // +4
+ add @x[0],@x[0],@x[1],lsl#32 // pack
+ add $D5,$D5,$ONE // +4
+ add @x[2],@x[2],@x[3],lsl#32
+ add $D0,$D0,@K[3]
+ ldp @x[1],@x[3],[$inp,#0] // load input
+ add $D1,$D1,@K[4]
+ add @x[4],@x[4],@x[5],lsl#32
+ add $D2,$D2,@K[5]
+ add @x[6],@x[6],@x[7],lsl#32
+ add $D3,$D3,@K[6]
+ ldp @x[5],@x[7],[$inp,#16]
+ add $D4,$D4,@K[3]
+ add @x[8],@x[8],@x[9],lsl#32
+ add $D5,$D5,@K[4]
+ add @x[10],@x[10],@x[11],lsl#32
+ add $B0,$B0,@K[1]
+ ldp @x[9],@x[11],[$inp,#32]
+ add $B1,$B1,@K[1]
+ add @x[12],@x[12],@x[13],lsl#32
+ add $B2,$B2,@K[1]
+ add @x[14],@x[14],@x[15],lsl#32
+ add $B3,$B3,@K[1]
+ ldp @x[13],@x[15],[$inp,#48]
+ add $B4,$B4,@K[1]
+ add $inp,$inp,#64
+ add $B5,$B5,@K[1]
+
+#ifdef __ARMEB__
+ rev @x[0],@x[0]
+ rev @x[2],@x[2]
+ rev @x[4],@x[4]
+ rev @x[6],@x[6]
+ rev @x[8],@x[8]
+ rev @x[10],@x[10]
+ rev @x[12],@x[12]
+ rev @x[14],@x[14]
+#endif
+ ld1.8 {$T0-$T3},[$inp],#64
+ eor @x[0],@x[0],@x[1]
+ eor @x[2],@x[2],@x[3]
+ eor @x[4],@x[4],@x[5]
+ eor @x[6],@x[6],@x[7]
+ eor @x[8],@x[8],@x[9]
+ eor $A0,$A0,$T0
+ eor @x[10],@x[10],@x[11]
+ eor $B0,$B0,$T1
+ eor @x[12],@x[12],@x[13]
+ eor $C0,$C0,$T2
+ eor @x[14],@x[14],@x[15]
+ eor $D0,$D0,$T3
+ ld1.8 {$T0-$T3},[$inp],#64
+
+ stp @x[0],@x[2],[$out,#0] // store output
+ add @d[6],@d[6],#7 // increment counter
+ stp @x[4],@x[6],[$out,#16]
+ stp @x[8],@x[10],[$out,#32]
+ stp @x[12],@x[14],[$out,#48]
+ add $out,$out,#64
+ st1.8 {$A0-$D0},[$out],#64
+
+ ld1.8 {$A0-$D0},[$inp],#64
+ eor $A1,$A1,$T0
+ eor $B1,$B1,$T1
+ eor $C1,$C1,$T2
+ eor $D1,$D1,$T3
+ st1.8 {$A1-$D1},[$out],#64
+
+ ld1.8 {$A1-$D1},[$inp],#64
+ eor $A2,$A2,$A0
+ ldp @K[0],@K[1],[sp,#0]
+ eor $B2,$B2,$B0
+ ldp @K[2],@K[3],[sp,#32]
+ eor $C2,$C2,$C0
+ eor $D2,$D2,$D0
+ st1.8 {$A2-$D2},[$out],#64
+
+ ld1.8 {$A2-$D2},[$inp],#64
+ eor $A3,$A3,$A1
+ eor $B3,$B3,$B1
+ eor $C3,$C3,$C1
+ eor $D3,$D3,$D1
+ st1.8 {$A3-$D3},[$out],#64
+
+ ld1.8 {$A3-$D3},[$inp],#64
+ eor $A4,$A4,$A2
+ eor $B4,$B4,$B2
+ eor $C4,$C4,$C2
+ eor $D4,$D4,$D2
+ st1.8 {$A4-$D4},[$out],#64
+
+ shl $A0,$ONE,#1 // 4 -> 8
+ eor $A5,$A5,$A3
+ eor $B5,$B5,$B3
+ eor $C5,$C5,$C3
+ eor $D5,$D5,$D3
+ st1.8 {$A5-$D5},[$out],#64
+
+ add @K[3],@K[3],$A0 // += 8
+ add @K[4],@K[4],$A0
+ add @K[5],@K[5],$A0
+ add @K[6],@K[6],$A0
+
+ b.hs .Loop_outer_512_neon
+
+ adds $len,$len,#512
+ ushr $A0,$ONE,#2 // 4 -> 1
+
+ ldp d8,d9,[sp,#128+0] // meet ABI requirements
+ ldp d10,d11,[sp,#128+16]
+ ldp d12,d13,[sp,#128+32]
+ ldp d14,d15,[sp,#128+48]
+
+ stp @K[0],$ONE,[sp,#0] // wipe off-load area
+ stp @K[0],$ONE,[sp,#32]
+ stp @K[0],$ONE,[sp,#64]
+
+ b.eq .Ldone_512_neon
+
+ cmp $len,#192
+ sub @K[3],@K[3],$A0 // -= 1
+ sub @K[4],@K[4],$A0
+ sub @K[5],@K[5],$A0
+ add sp,sp,#128
+ b.hs .Loop_outer_neon
+
+ eor @K[1],@K[1],@K[1]
+ eor @K[2],@K[2],@K[2]
+ eor @K[3],@K[3],@K[3]
+ eor @K[4],@K[4],@K[4]
+ eor @K[5],@K[5],@K[5]
+ eor @K[6],@K[6],@K[6]
+ b .Loop_outer
+
+.Ldone_512_neon:
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#128+64
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#96
+ ret
+.size ChaCha20_512_neon,.-ChaCha20_512_neon
+___
+}
+}}}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ (s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or
+ (m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or
+ (s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or
+ (m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or
+ (s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1));
+
+ #s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
+
+ print $_,"\n";
+}
+close STDOUT; # flush
diff --git a/crypto/chacha/asm/chacha-x86.pl b/crypto/chacha/asm/chacha-x86.pl
new file mode 100755
index 00000000..edce43dc
--- /dev/null
+++ b/crypto/chacha/asm/chacha-x86.pl
@@ -0,0 +1,753 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# January 2015
+#
+# ChaCha20 for x86.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# 1xIALU/gcc 4xSSSE3
+# Pentium 17.5/+80%
+# PIII 14.2/+60%
+# P4 18.6/+84%
+# Core2 9.56/+89% 4.83
+# Westmere 9.50/+45% 3.35
+# Sandy Bridge 10.5/+47% 3.20
+# Haswell 8.15/+50% 2.83
+# Silvermont 17.4/+36% 8.35
+# Sledgehammer 10.2/+54%
+# Bulldozer 13.4/+50% 4.38(*)
+#
+# (*) Bulldozer actually executes 4xXOP code path that delivers 3.55;
+#
+# Modified from upstream OpenSSL to remove the XOP code.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386");
+
+$xmm=$ymm=0;
+for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+$ymm=$xmm;
+
+$a="eax";
+($b,$b_)=("ebx","ebp");
+($c,$c_)=("ecx","esi");
+($d,$d_)=("edx","edi");
+
+sub QUARTERROUND {
+my ($ai,$bi,$ci,$di,$i)=@_;
+my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next
+my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
+
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+
+ if ($i==0) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==3) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
+ } elsif ($i==4) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==7) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
+ }
+
+ #&add ($a,$b); # see elsewhere
+ &xor ($d,$a);
+ &mov (&DWP(4*$cp,"esp"),$c_) if ($ai>0 && $ai<3);
+ &rol ($d,16);
+ &mov (&DWP(4*$bp,"esp"),$b_) if ($i!=0);
+ &add ($c,$d);
+ &mov ($c_,&DWP(4*$cn,"esp")) if ($ai>0 && $ai<3);
+ &xor ($b,$c);
+ &mov ($d_,&DWP(4*$dn,"esp")) if ($di!=$dn);
+ &rol ($b,12);
+ &mov ($b_,&DWP(4*$bn,"esp")) if ($i<7);
+ &mov ($b_,&DWP(128,"esp")) if ($i==7); # loop counter
+ &add ($a,$b);
+ &xor ($d,$a);
+ &mov (&DWP(4*$ai,"esp"),$a);
+ &rol ($d,8);
+ &mov ($a,&DWP(4*$an,"esp"));
+ &add ($c,$d);
+ &mov (&DWP(4*$di,"esp"),$d) if ($di!=$dn);
+ &mov ($d_,$d) if ($di==$dn);
+ &xor ($b,$c);
+ &add ($a,$b_) if ($i<7); # elsewhere
+ &rol ($b,7);
+
+ ($b,$b_)=($b_,$b);
+ ($c,$c_)=($c_,$c);
+ ($d,$d_)=($d_,$d);
+}
+
+&static_label("ssse3_shortcut");
+&static_label("ssse3_data");
+&static_label("pic_point");
+
+&function_begin("ChaCha20_ctr32");
+ &xor ("eax","eax");
+ &cmp ("eax",&wparam(2)); # len==0?
+ &je (&label("no_data"));
+if ($xmm) {
+ &call (&label("pic_point"));
+&set_label("pic_point");
+ &blindpop("eax");
+ &picmeup("ebp","OPENSSL_ia32cap_P","eax",&label("pic_point"));
+ &test (&DWP(0,"ebp"),1<<24); # test FXSR bit
+ &jz (&label("x86"));
+ &test (&DWP(4,"ebp"),1<<9); # test SSSE3 bit
+ &jz (&label("x86"));
+ &jmp (&label("ssse3_shortcut"));
+&set_label("x86");
+}
+ &mov ("esi",&wparam(3)); # key
+ &mov ("edi",&wparam(4)); # counter and nonce
+
+ &stack_push(33);
+
+ &mov ("eax",&DWP(4*0,"esi")); # copy key
+ &mov ("ebx",&DWP(4*1,"esi"));
+ &mov ("ecx",&DWP(4*2,"esi"));
+ &mov ("edx",&DWP(4*3,"esi"));
+ &mov (&DWP(64+4*4,"esp"),"eax");
+ &mov (&DWP(64+4*5,"esp"),"ebx");
+ &mov (&DWP(64+4*6,"esp"),"ecx");
+ &mov (&DWP(64+4*7,"esp"),"edx");
+ &mov ("eax",&DWP(4*4,"esi"));
+ &mov ("ebx",&DWP(4*5,"esi"));
+ &mov ("ecx",&DWP(4*6,"esi"));
+ &mov ("edx",&DWP(4*7,"esi"));
+ &mov (&DWP(64+4*8,"esp"),"eax");
+ &mov (&DWP(64+4*9,"esp"),"ebx");
+ &mov (&DWP(64+4*10,"esp"),"ecx");
+ &mov (&DWP(64+4*11,"esp"),"edx");
+ &mov ("eax",&DWP(4*0,"edi")); # copy counter and nonce
+ &mov ("ebx",&DWP(4*1,"edi"));
+ &mov ("ecx",&DWP(4*2,"edi"));
+ &mov ("edx",&DWP(4*3,"edi"));
+ &sub ("eax",1);
+ &mov (&DWP(64+4*12,"esp"),"eax");
+ &mov (&DWP(64+4*13,"esp"),"ebx");
+ &mov (&DWP(64+4*14,"esp"),"ecx");
+ &mov (&DWP(64+4*15,"esp"),"edx");
+ &jmp (&label("entry"));
+
+&set_label("outer_loop",16);
+ &mov (&wparam(1),$b); # save input
+ &mov (&wparam(0),$a); # save output
+ &mov (&wparam(2),$c); # save len
+&set_label("entry");
+ &mov ($a,0x61707865);
+ &mov (&DWP(4*1,"esp"),0x3320646e);
+ &mov (&DWP(4*2,"esp"),0x79622d32);
+ &mov (&DWP(4*3,"esp"),0x6b206574);
+
+ &mov ($b, &DWP(64+4*5,"esp")); # copy key material
+ &mov ($b_,&DWP(64+4*6,"esp"));
+ &mov ($c, &DWP(64+4*10,"esp"));
+ &mov ($c_,&DWP(64+4*11,"esp"));
+ &mov ($d, &DWP(64+4*13,"esp"));
+ &mov ($d_,&DWP(64+4*14,"esp"));
+ &mov (&DWP(4*5,"esp"),$b);
+ &mov (&DWP(4*6,"esp"),$b_);
+ &mov (&DWP(4*10,"esp"),$c);
+ &mov (&DWP(4*11,"esp"),$c_);
+ &mov (&DWP(4*13,"esp"),$d);
+ &mov (&DWP(4*14,"esp"),$d_);
+
+ &mov ($b, &DWP(64+4*7,"esp"));
+ &mov ($d_,&DWP(64+4*15,"esp"));
+ &mov ($d, &DWP(64+4*12,"esp"));
+ &mov ($b_,&DWP(64+4*4,"esp"));
+ &mov ($c, &DWP(64+4*8,"esp"));
+ &mov ($c_,&DWP(64+4*9,"esp"));
+ &add ($d,1); # counter value
+ &mov (&DWP(4*7,"esp"),$b);
+ &mov (&DWP(4*15,"esp"),$d_);
+ &mov (&DWP(64+4*12,"esp"),$d); # save counter value
+
+ &mov ($b,10); # loop counter
+ &jmp (&label("loop"));
+
+&set_label("loop",16);
+ &add ($a,$b_); # elsewhere
+ &mov (&DWP(128,"esp"),$b); # save loop counter
+ &mov ($b,$b_);
+ &QUARTERROUND(0, 4, 8, 12, 0);
+ &QUARTERROUND(1, 5, 9, 13, 1);
+ &QUARTERROUND(2, 6,10, 14, 2);
+ &QUARTERROUND(3, 7,11, 15, 3);
+ &QUARTERROUND(0, 5,10, 15, 4);
+ &QUARTERROUND(1, 6,11, 12, 5);
+ &QUARTERROUND(2, 7, 8, 13, 6);
+ &QUARTERROUND(3, 4, 9, 14, 7);
+ &dec ($b);
+ &jnz (&label("loop"));
+
+ &mov ($b,&wparam(2)); # load len
+
+ &add ($a,0x61707865); # accumulate key material
+ &add ($b_,&DWP(64+4*4,"esp"));
+ &add ($c, &DWP(64+4*8,"esp"));
+ &add ($c_,&DWP(64+4*9,"esp"));
+
+ &cmp ($b,64);
+ &jb (&label("tail"));
+
+ &mov ($b,&wparam(1)); # load input pointer
+ &add ($d, &DWP(64+4*12,"esp"));
+ &add ($d_,&DWP(64+4*14,"esp"));
+
+ &xor ($a, &DWP(4*0,$b)); # xor with input
+ &xor ($b_,&DWP(4*4,$b));
+ &mov (&DWP(4*0,"esp"),$a);
+ &mov ($a,&wparam(0)); # load output pointer
+ &xor ($c, &DWP(4*8,$b));
+ &xor ($c_,&DWP(4*9,$b));
+ &xor ($d, &DWP(4*12,$b));
+ &xor ($d_,&DWP(4*14,$b));
+ &mov (&DWP(4*4,$a),$b_); # write output
+ &mov (&DWP(4*8,$a),$c);
+ &mov (&DWP(4*9,$a),$c_);
+ &mov (&DWP(4*12,$a),$d);
+ &mov (&DWP(4*14,$a),$d_);
+
+ &mov ($b_,&DWP(4*1,"esp"));
+ &mov ($c, &DWP(4*2,"esp"));
+ &mov ($c_,&DWP(4*3,"esp"));
+ &mov ($d, &DWP(4*5,"esp"));
+ &mov ($d_,&DWP(4*6,"esp"));
+ &add ($b_,0x3320646e); # accumulate key material
+ &add ($c, 0x79622d32);
+ &add ($c_,0x6b206574);
+ &add ($d, &DWP(64+4*5,"esp"));
+ &add ($d_,&DWP(64+4*6,"esp"));
+ &xor ($b_,&DWP(4*1,$b));
+ &xor ($c, &DWP(4*2,$b));
+ &xor ($c_,&DWP(4*3,$b));
+ &xor ($d, &DWP(4*5,$b));
+ &xor ($d_,&DWP(4*6,$b));
+ &mov (&DWP(4*1,$a),$b_);
+ &mov (&DWP(4*2,$a),$c);
+ &mov (&DWP(4*3,$a),$c_);
+ &mov (&DWP(4*5,$a),$d);
+ &mov (&DWP(4*6,$a),$d_);
+
+ &mov ($b_,&DWP(4*7,"esp"));
+ &mov ($c, &DWP(4*10,"esp"));
+ &mov ($c_,&DWP(4*11,"esp"));
+ &mov ($d, &DWP(4*13,"esp"));
+ &mov ($d_,&DWP(4*15,"esp"));
+ &add ($b_,&DWP(64+4*7,"esp"));
+ &add ($c, &DWP(64+4*10,"esp"));
+ &add ($c_,&DWP(64+4*11,"esp"));
+ &add ($d, &DWP(64+4*13,"esp"));
+ &add ($d_,&DWP(64+4*15,"esp"));
+ &xor ($b_,&DWP(4*7,$b));
+ &xor ($c, &DWP(4*10,$b));
+ &xor ($c_,&DWP(4*11,$b));
+ &xor ($d, &DWP(4*13,$b));
+ &xor ($d_,&DWP(4*15,$b));
+ &lea ($b,&DWP(4*16,$b));
+ &mov (&DWP(4*7,$a),$b_);
+ &mov ($b_,&DWP(4*0,"esp"));
+ &mov (&DWP(4*10,$a),$c);
+ &mov ($c,&wparam(2)); # len
+ &mov (&DWP(4*11,$a),$c_);
+ &mov (&DWP(4*13,$a),$d);
+ &mov (&DWP(4*15,$a),$d_);
+ &mov (&DWP(4*0,$a),$b_);
+ &lea ($a,&DWP(4*16,$a));
+ &sub ($c,64);
+ &jnz (&label("outer_loop"));
+
+ &jmp (&label("done"));
+
+&set_label("tail");
+ &add ($d, &DWP(64+4*12,"esp"));
+ &add ($d_,&DWP(64+4*14,"esp"));
+ &mov (&DWP(4*0,"esp"),$a);
+ &mov (&DWP(4*4,"esp"),$b_);
+ &mov (&DWP(4*8,"esp"),$c);
+ &mov (&DWP(4*9,"esp"),$c_);
+ &mov (&DWP(4*12,"esp"),$d);
+ &mov (&DWP(4*14,"esp"),$d_);
+
+ &mov ($b_,&DWP(4*1,"esp"));
+ &mov ($c, &DWP(4*2,"esp"));
+ &mov ($c_,&DWP(4*3,"esp"));
+ &mov ($d, &DWP(4*5,"esp"));
+ &mov ($d_,&DWP(4*6,"esp"));
+ &add ($b_,0x3320646e); # accumulate key material
+ &add ($c, 0x79622d32);
+ &add ($c_,0x6b206574);
+ &add ($d, &DWP(64+4*5,"esp"));
+ &add ($d_,&DWP(64+4*6,"esp"));
+ &mov (&DWP(4*1,"esp"),$b_);
+ &mov (&DWP(4*2,"esp"),$c);
+ &mov (&DWP(4*3,"esp"),$c_);
+ &mov (&DWP(4*5,"esp"),$d);
+ &mov (&DWP(4*6,"esp"),$d_);
+
+ &mov ($b_,&DWP(4*7,"esp"));
+ &mov ($c, &DWP(4*10,"esp"));
+ &mov ($c_,&DWP(4*11,"esp"));
+ &mov ($d, &DWP(4*13,"esp"));
+ &mov ($d_,&DWP(4*15,"esp"));
+ &add ($b_,&DWP(64+4*7,"esp"));
+ &add ($c, &DWP(64+4*10,"esp"));
+ &add ($c_,&DWP(64+4*11,"esp"));
+ &add ($d, &DWP(64+4*13,"esp"));
+ &add ($d_,&DWP(64+4*15,"esp"));
+ &mov (&DWP(4*7,"esp"),$b_);
+ &mov ($b_,&wparam(1)); # load input
+ &mov (&DWP(4*10,"esp"),$c);
+ &mov ($c,&wparam(0)); # load output
+ &mov (&DWP(4*11,"esp"),$c_);
+ &xor ($c_,$c_);
+ &mov (&DWP(4*13,"esp"),$d);
+ &mov (&DWP(4*15,"esp"),$d_);
+
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+&set_label("tail_loop");
+ &movb ("al",&BP(0,$c_,$b_));
+ &movb ("dl",&BP(0,"esp",$c_));
+ &lea ($c_,&DWP(1,$c_));
+ &xor ("al","dl");
+ &mov (&BP(-1,$c,$c_),"al");
+ &dec ($b);
+ &jnz (&label("tail_loop"));
+
+&set_label("done");
+ &stack_pop(33);
+&set_label("no_data");
+&function_end("ChaCha20_ctr32");
+
+if ($xmm) {
+my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7));
+my ($out,$inp,$len)=("edi","esi","ecx");
+
+sub QUARTERROUND_SSSE3 {
+my ($ai,$bi,$ci,$di,$i)=@_;
+my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next
+my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
+
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+
+ if ($i==0) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==3) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
+ } elsif ($i==4) {
+ my $j=4;
+ ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
+ } elsif ($i==7) {
+ my $j=0;
+ ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
+ }
+
+ #&paddd ($xa,$xb); # see elsewhere
+ #&pxor ($xd,$xa); # see elsewhere
+ &movdqa(&QWP(16*$cp-128,"ebx"),$xc_) if ($ai>0 && $ai<3);
+ &pshufb ($xd,&QWP(0,"eax")); # rot16
+ &movdqa(&QWP(16*$bp-128,"ebx"),$xb_) if ($i!=0);
+ &paddd ($xc,$xd);
+ &movdqa($xc_,&QWP(16*$cn-128,"ebx")) if ($ai>0 && $ai<3);
+ &pxor ($xb,$xc);
+ &movdqa($xb_,&QWP(16*$bn-128,"ebx")) if ($i<7);
+ &movdqa ($xa_,$xb); # borrow as temporary
+ &pslld ($xb,12);
+ &psrld ($xa_,20);
+ &por ($xb,$xa_);
+ &movdqa($xa_,&QWP(16*$an-128,"ebx"));
+ &paddd ($xa,$xb);
+ &movdqa($xd_,&QWP(16*$dn-128,"ebx")) if ($di!=$dn);
+ &pxor ($xd,$xa);
+ &movdqa (&QWP(16*$ai-128,"ebx"),$xa);
+ &pshufb ($xd,&QWP(16,"eax")); # rot8
+ &paddd ($xc,$xd);
+ &movdqa (&QWP(16*$di-128,"ebx"),$xd) if ($di!=$dn);
+ &movdqa ($xd_,$xd) if ($di==$dn);
+ &pxor ($xb,$xc);
+ &paddd ($xa_,$xb_) if ($i<7); # elsewhere
+ &movdqa ($xa,$xb); # borrow as temporary
+ &pslld ($xb,7);
+ &psrld ($xa,25);
+ &pxor ($xd_,$xa_) if ($i<7); # elsewhere
+ &por ($xb,$xa);
+
+ ($xa,$xa_)=($xa_,$xa);
+ ($xb,$xb_)=($xb_,$xb);
+ ($xc,$xc_)=($xc_,$xc);
+ ($xd,$xd_)=($xd_,$xd);
+}
+
+&function_begin("ChaCha20_ssse3");
+&set_label("ssse3_shortcut");
+ &mov ($out,&wparam(0));
+ &mov ($inp,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ("edx",&wparam(3)); # key
+ &mov ("ebx",&wparam(4)); # counter and nonce
+
+ &mov ("ebp","esp");
+ &stack_push (131);
+ &and ("esp",-64);
+ &mov (&DWP(512,"esp"),"ebp");
+
+ &lea ("eax",&DWP(&label("ssse3_data")."-".
+ &label("pic_point"),"eax"));
+ &movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce
+
+ &cmp ($len,64*4);
+ &jb (&label("1x"));
+
+ &mov (&DWP(512+4,"esp"),"edx"); # offload pointers
+ &mov (&DWP(512+8,"esp"),"ebx");
+ &sub ($len,64*4); # bias len
+ &lea ("ebp",&DWP(256+128,"esp")); # size optimization
+
+ &movdqu ("xmm7",&QWP(0,"edx")); # key
+ &pshufd ("xmm0","xmm3",0x00);
+ &pshufd ("xmm1","xmm3",0x55);
+ &pshufd ("xmm2","xmm3",0xaa);
+ &pshufd ("xmm3","xmm3",0xff);
+ &paddd ("xmm0",&QWP(16*3,"eax")); # fix counters
+ &pshufd ("xmm4","xmm7",0x00);
+ &pshufd ("xmm5","xmm7",0x55);
+ &psubd ("xmm0",&QWP(16*4,"eax"));
+ &pshufd ("xmm6","xmm7",0xaa);
+ &pshufd ("xmm7","xmm7",0xff);
+ &movdqa (&QWP(16*12-128,"ebp"),"xmm0");
+ &movdqa (&QWP(16*13-128,"ebp"),"xmm1");
+ &movdqa (&QWP(16*14-128,"ebp"),"xmm2");
+ &movdqa (&QWP(16*15-128,"ebp"),"xmm3");
+ &movdqu ("xmm3",&QWP(16,"edx")); # key
+ &movdqa (&QWP(16*4-128,"ebp"),"xmm4");
+ &movdqa (&QWP(16*5-128,"ebp"),"xmm5");
+ &movdqa (&QWP(16*6-128,"ebp"),"xmm6");
+ &movdqa (&QWP(16*7-128,"ebp"),"xmm7");
+ &movdqa ("xmm7",&QWP(16*2,"eax")); # sigma
+ &lea ("ebx",&DWP(128,"esp")); # size optimization
+
+ &pshufd ("xmm0","xmm3",0x00);
+ &pshufd ("xmm1","xmm3",0x55);
+ &pshufd ("xmm2","xmm3",0xaa);
+ &pshufd ("xmm3","xmm3",0xff);
+ &pshufd ("xmm4","xmm7",0x00);
+ &pshufd ("xmm5","xmm7",0x55);
+ &pshufd ("xmm6","xmm7",0xaa);
+ &pshufd ("xmm7","xmm7",0xff);
+ &movdqa (&QWP(16*8-128,"ebp"),"xmm0");
+ &movdqa (&QWP(16*9-128,"ebp"),"xmm1");
+ &movdqa (&QWP(16*10-128,"ebp"),"xmm2");
+ &movdqa (&QWP(16*11-128,"ebp"),"xmm3");
+ &movdqa (&QWP(16*0-128,"ebp"),"xmm4");
+ &movdqa (&QWP(16*1-128,"ebp"),"xmm5");
+ &movdqa (&QWP(16*2-128,"ebp"),"xmm6");
+ &movdqa (&QWP(16*3-128,"ebp"),"xmm7");
+
+ &lea ($inp,&DWP(128,$inp)); # size optimization
+ &lea ($out,&DWP(128,$out)); # size optimization
+ &jmp (&label("outer_loop"));
+
+&set_label("outer_loop",16);
+ #&movdqa ("xmm0",&QWP(16*0-128,"ebp")); # copy key material
+ &movdqa ("xmm1",&QWP(16*1-128,"ebp"));
+ &movdqa ("xmm2",&QWP(16*2-128,"ebp"));
+ &movdqa ("xmm3",&QWP(16*3-128,"ebp"));
+ #&movdqa ("xmm4",&QWP(16*4-128,"ebp"));
+ &movdqa ("xmm5",&QWP(16*5-128,"ebp"));
+ &movdqa ("xmm6",&QWP(16*6-128,"ebp"));
+ &movdqa ("xmm7",&QWP(16*7-128,"ebp"));
+ #&movdqa (&QWP(16*0-128,"ebx"),"xmm0");
+ &movdqa (&QWP(16*1-128,"ebx"),"xmm1");
+ &movdqa (&QWP(16*2-128,"ebx"),"xmm2");
+ &movdqa (&QWP(16*3-128,"ebx"),"xmm3");
+ #&movdqa (&QWP(16*4-128,"ebx"),"xmm4");
+ &movdqa (&QWP(16*5-128,"ebx"),"xmm5");
+ &movdqa (&QWP(16*6-128,"ebx"),"xmm6");
+ &movdqa (&QWP(16*7-128,"ebx"),"xmm7");
+ #&movdqa ("xmm0",&QWP(16*8-128,"ebp"));
+ #&movdqa ("xmm1",&QWP(16*9-128,"ebp"));
+ &movdqa ("xmm2",&QWP(16*10-128,"ebp"));
+ &movdqa ("xmm3",&QWP(16*11-128,"ebp"));
+ &movdqa ("xmm4",&QWP(16*12-128,"ebp"));
+ &movdqa ("xmm5",&QWP(16*13-128,"ebp"));
+ &movdqa ("xmm6",&QWP(16*14-128,"ebp"));
+ &movdqa ("xmm7",&QWP(16*15-128,"ebp"));
+ &paddd ("xmm4",&QWP(16*4,"eax")); # counter value
+ #&movdqa (&QWP(16*8-128,"ebx"),"xmm0");
+ #&movdqa (&QWP(16*9-128,"ebx"),"xmm1");
+ &movdqa (&QWP(16*10-128,"ebx"),"xmm2");
+ &movdqa (&QWP(16*11-128,"ebx"),"xmm3");
+ &movdqa (&QWP(16*12-128,"ebx"),"xmm4");
+ &movdqa (&QWP(16*13-128,"ebx"),"xmm5");
+ &movdqa (&QWP(16*14-128,"ebx"),"xmm6");
+ &movdqa (&QWP(16*15-128,"ebx"),"xmm7");
+ &movdqa (&QWP(16*12-128,"ebp"),"xmm4"); # save counter value
+
+ &movdqa ($xa, &QWP(16*0-128,"ebp"));
+ &movdqa ($xd, "xmm4");
+ &movdqa ($xb_,&QWP(16*4-128,"ebp"));
+ &movdqa ($xc, &QWP(16*8-128,"ebp"));
+ &movdqa ($xc_,&QWP(16*9-128,"ebp"));
+
+ &mov ("edx",10); # loop counter
+ &nop ();
+
+&set_label("loop",16);
+ &paddd ($xa,$xb_); # elsewhere
+ &movdqa ($xb,$xb_);
+ &pxor ($xd,$xa); # elsewhere
+ &QUARTERROUND_SSSE3(0, 4, 8, 12, 0);
+ &QUARTERROUND_SSSE3(1, 5, 9, 13, 1);
+ &QUARTERROUND_SSSE3(2, 6,10, 14, 2);
+ &QUARTERROUND_SSSE3(3, 7,11, 15, 3);
+ &QUARTERROUND_SSSE3(0, 5,10, 15, 4);
+ &QUARTERROUND_SSSE3(1, 6,11, 12, 5);
+ &QUARTERROUND_SSSE3(2, 7, 8, 13, 6);
+ &QUARTERROUND_SSSE3(3, 4, 9, 14, 7);
+ &dec ("edx");
+ &jnz (&label("loop"));
+
+ &movdqa (&QWP(16*4-128,"ebx"),$xb_);
+ &movdqa (&QWP(16*8-128,"ebx"),$xc);
+ &movdqa (&QWP(16*9-128,"ebx"),$xc_);
+ &movdqa (&QWP(16*12-128,"ebx"),$xd);
+ &movdqa (&QWP(16*14-128,"ebx"),$xd_);
+
+ my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7));
+
+ #&movdqa ($xa0,&QWP(16*0-128,"ebx")); # it's there
+ &movdqa ($xa1,&QWP(16*1-128,"ebx"));
+ &movdqa ($xa2,&QWP(16*2-128,"ebx"));
+ &movdqa ($xa3,&QWP(16*3-128,"ebx"));
+
+ for($i=0;$i<256;$i+=64) {
+ &paddd ($xa0,&QWP($i+16*0-128,"ebp")); # accumulate key material
+ &paddd ($xa1,&QWP($i+16*1-128,"ebp"));
+ &paddd ($xa2,&QWP($i+16*2-128,"ebp"));
+ &paddd ($xa3,&QWP($i+16*3-128,"ebp"));
+
+ &movdqa ($xt2,$xa0); # "de-interlace" data
+ &punpckldq ($xa0,$xa1);
+ &movdqa ($xt3,$xa2);
+ &punpckldq ($xa2,$xa3);
+ &punpckhdq ($xt2,$xa1);
+ &punpckhdq ($xt3,$xa3);
+ &movdqa ($xa1,$xa0);
+ &punpcklqdq ($xa0,$xa2); # "a0"
+ &movdqa ($xa3,$xt2);
+ &punpcklqdq ($xt2,$xt3); # "a2"
+ &punpckhqdq ($xa1,$xa2); # "a1"
+ &punpckhqdq ($xa3,$xt3); # "a3"
+
+ #($xa2,$xt2)=($xt2,$xa2);
+
+ &movdqu ($xt0,&QWP(64*0-128,$inp)); # load input
+ &movdqu ($xt1,&QWP(64*1-128,$inp));
+ &movdqu ($xa2,&QWP(64*2-128,$inp));
+ &movdqu ($xt3,&QWP(64*3-128,$inp));
+ &lea ($inp,&QWP($i<192?16:(64*4-16*3),$inp));
+ &pxor ($xt0,$xa0);
+ &movdqa ($xa0,&QWP($i+16*4-128,"ebx")) if ($i<192);
+ &pxor ($xt1,$xa1);
+ &movdqa ($xa1,&QWP($i+16*5-128,"ebx")) if ($i<192);
+ &pxor ($xt2,$xa2);
+ &movdqa ($xa2,&QWP($i+16*6-128,"ebx")) if ($i<192);
+ &pxor ($xt3,$xa3);
+ &movdqa ($xa3,&QWP($i+16*7-128,"ebx")) if ($i<192);
+ &movdqu (&QWP(64*0-128,$out),$xt0); # store output
+ &movdqu (&QWP(64*1-128,$out),$xt1);
+ &movdqu (&QWP(64*2-128,$out),$xt2);
+ &movdqu (&QWP(64*3-128,$out),$xt3);
+ &lea ($out,&QWP($i<192?16:(64*4-16*3),$out));
+ }
+ &sub ($len,64*4);
+ &jnc (&label("outer_loop"));
+
+ &add ($len,64*4);
+ &jz (&label("done"));
+
+ &mov ("ebx",&DWP(512+8,"esp")); # restore pointers
+ &lea ($inp,&DWP(-128,$inp));
+ &mov ("edx",&DWP(512+4,"esp"));
+ &lea ($out,&DWP(-128,$out));
+
+ &movd ("xmm2",&DWP(16*12-128,"ebp")); # counter value
+ &movdqu ("xmm3",&QWP(0,"ebx"));
+ &paddd ("xmm2",&QWP(16*6,"eax")); # +four
+ &pand ("xmm3",&QWP(16*7,"eax"));
+ &por ("xmm3","xmm2"); # counter value
+{
+my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7));
+
+sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot16);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,20);
+ &pslld ($t,12);
+ &por ($b,$t);
+
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot24);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,25);
+ &pslld ($t,7);
+ &por ($b,$t);
+}
+
+&set_label("1x");
+ &movdqa ($a,&QWP(16*2,"eax")); # sigma
+ &movdqu ($b,&QWP(0,"edx"));
+ &movdqu ($c,&QWP(16,"edx"));
+ #&movdqu ($d,&QWP(0,"ebx")); # already loaded
+ &movdqa ($rot16,&QWP(0,"eax"));
+ &movdqa ($rot24,&QWP(16,"eax"));
+ &mov (&DWP(16*3,"esp"),"ebp");
+
+ &movdqa (&QWP(16*0,"esp"),$a);
+ &movdqa (&QWP(16*1,"esp"),$b);
+ &movdqa (&QWP(16*2,"esp"),$c);
+ &movdqa (&QWP(16*3,"esp"),$d);
+ &mov ("edx",10);
+ &jmp (&label("loop1x"));
+
+&set_label("outer1x",16);
+ &movdqa ($d,&QWP(16*5,"eax")); # one
+ &movdqa ($a,&QWP(16*0,"esp"));
+ &movdqa ($b,&QWP(16*1,"esp"));
+ &movdqa ($c,&QWP(16*2,"esp"));
+ &paddd ($d,&QWP(16*3,"esp"));
+ &mov ("edx",10);
+ &movdqa (&QWP(16*3,"esp"),$d);
+ &jmp (&label("loop1x"));
+
+&set_label("loop1x",16);
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b00111001);
+ &pshufd ($d,$d,0b10010011);
+ &nop ();
+
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b10010011);
+ &pshufd ($d,$d,0b00111001);
+
+ &dec ("edx");
+ &jnz (&label("loop1x"));
+
+ &paddd ($a,&QWP(16*0,"esp"));
+ &paddd ($b,&QWP(16*1,"esp"));
+ &paddd ($c,&QWP(16*2,"esp"));
+ &paddd ($d,&QWP(16*3,"esp"));
+
+ &cmp ($len,64);
+ &jb (&label("tail"));
+
+ &movdqu ($t,&QWP(16*0,$inp));
+ &movdqu ($t1,&QWP(16*1,$inp));
+ &pxor ($a,$t); # xor with input
+ &movdqu ($t,&QWP(16*2,$inp));
+ &pxor ($b,$t1);
+ &movdqu ($t1,&QWP(16*3,$inp));
+ &pxor ($c,$t);
+ &pxor ($d,$t1);
+ &lea ($inp,&DWP(16*4,$inp)); # inp+=64
+
+ &movdqu (&QWP(16*0,$out),$a); # write output
+ &movdqu (&QWP(16*1,$out),$b);
+ &movdqu (&QWP(16*2,$out),$c);
+ &movdqu (&QWP(16*3,$out),$d);
+ &lea ($out,&DWP(16*4,$out)); # inp+=64
+
+ &sub ($len,64);
+ &jnz (&label("outer1x"));
+
+ &jmp (&label("done"));
+
+&set_label("tail");
+ &movdqa (&QWP(16*0,"esp"),$a);
+ &movdqa (&QWP(16*1,"esp"),$b);
+ &movdqa (&QWP(16*2,"esp"),$c);
+ &movdqa (&QWP(16*3,"esp"),$d);
+
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+ &xor ("ebp","ebp");
+
+&set_label("tail_loop");
+ &movb ("al",&BP(0,"esp","ebp"));
+ &movb ("dl",&BP(0,$inp,"ebp"));
+ &lea ("ebp",&DWP(1,"ebp"));
+ &xor ("al","dl");
+ &movb (&BP(-1,$out,"ebp"),"al");
+ &dec ($len);
+ &jnz (&label("tail_loop"));
+}
+&set_label("done");
+ &mov ("esp",&DWP(512,"esp"));
+&function_end("ChaCha20_ssse3");
+
+&align (64);
+&set_label("ssse3_data");
+&data_byte(0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd);
+&data_byte(0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe);
+&data_word(0x61707865,0x3320646e,0x79622d32,0x6b206574);
+&data_word(0,1,2,3);
+&data_word(4,4,4,4);
+&data_word(1,0,0,0);
+&data_word(4,0,0,0);
+&data_word(0,-1,-1,-1);
+&align (64);
+}
+&asciz ("ChaCha20 for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
diff --git a/crypto/chacha/asm/chacha-x86_64.pl b/crypto/chacha/asm/chacha-x86_64.pl
new file mode 100755
index 00000000..55b726d2
--- /dev/null
+++ b/crypto/chacha/asm/chacha-x86_64.pl
@@ -0,0 +1,1767 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# November 2014
+#
+# ChaCha20 for x86_64.
+#
+# Performance in cycles per byte out of large buffer.
+#
+# IALU/gcc 4.8(i) 1xSSSE3/SSE2 4xSSSE3 8xAVX2
+#
+# P4 9.48/+99% -/22.7(ii) -
+# Core2 7.83/+55% 7.90/8.08 4.35
+# Westmere 7.19/+50% 5.60/6.70 3.00
+# Sandy Bridge 8.31/+42% 5.45/6.76 2.72
+# Ivy Bridge 6.71/+46% 5.40/6.49 2.41
+# Haswell 5.92/+43% 5.20/6.45 2.42 1.23
+# Silvermont 12.0/+33% 7.75/7.40 7.03(iii)
+# Sledgehammer 7.28/+52% -/14.2(ii) -
+# Bulldozer 9.66/+28% 9.85/11.1 3.06(iv)
+# VIA Nano 10.5/+46% 6.72/8.60 6.05
+#
+# (i) compared to older gcc 3.x one can observe >2x improvement on
+# most platforms;
+# (ii) as it can be seen, SSE2 performance is too low on legacy
+# processors; NxSSE2 results are naturally better, but not
+# impressively better than IALU ones, which is why you won't
+# find SSE2 code below;
+# (iii) this is not optimal result for Atom because of MSROM
+# limitations, SSE2 can do better, but gain is considered too
+# low to justify the [maintenance] effort;
+# (iv) Bulldozer actually executes 4xXOP code path that delivers 2.20;
+#
+# Modified from upstream OpenSSL to remove the XOP code.
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+$avx = 2;
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+# input parameter block
+($out,$inp,$len,$key,$counter)=("%rdi","%rsi","%rdx","%rcx","%r8");
+
+$code.=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.align 64
+.Lzero:
+.long 0,0,0,0
+.Lone:
+.long 1,0,0,0
+.Linc:
+.long 0,1,2,3
+.Lfour:
+.long 4,4,4,4
+.Lincy:
+.long 0,2,4,6,1,3,5,7
+.Leight:
+.long 8,8,8,8,8,8,8,8
+.Lrot16:
+.byte 0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd
+.Lrot24:
+.byte 0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe
+.Lsigma:
+.asciz "expand 32-byte k"
+.asciz "ChaCha20 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+___
+
+sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
+ my $arg = pop;
+ $arg = "\$$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
+}
+
+@x=("%eax","%ebx","%ecx","%edx",map("%r${_}d",(8..11)),
+ "%nox","%nox","%nox","%nox",map("%r${_}d",(12..15)));
+@t=("%esi","%edi");
+
+sub ROUND { # critical path is 24 cycles per round
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_)=map("\"$_\"",@t);
+my @x=map("\"$_\"",@x);
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' and 'd's are permanently allocated in registers,
+ # @x[0..7,12..15], while 'c's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end.
+
+ # Normally instructions would be interleaved to favour in-order
+ # execution. Generally out-of-order cores manage it gracefully,
+ # but not this time for some reason. As in-order execution
+ # cores are dying breed, old Atom is the only one around,
+ # instructions are left uninterleaved. Besides, Atom is better
+ # off executing 1xSSSE3 code anyway...
+
+ (
+ "&add (@x[$a0],@x[$b0])", # Q1
+ "&xor (@x[$d0],@x[$a0])",
+ "&rol (@x[$d0],16)",
+ "&add (@x[$a1],@x[$b1])", # Q2
+ "&xor (@x[$d1],@x[$a1])",
+ "&rol (@x[$d1],16)",
+
+ "&add ($xc,@x[$d0])",
+ "&xor (@x[$b0],$xc)",
+ "&rol (@x[$b0],12)",
+ "&add ($xc_,@x[$d1])",
+ "&xor (@x[$b1],$xc_)",
+ "&rol (@x[$b1],12)",
+
+ "&add (@x[$a0],@x[$b0])",
+ "&xor (@x[$d0],@x[$a0])",
+ "&rol (@x[$d0],8)",
+ "&add (@x[$a1],@x[$b1])",
+ "&xor (@x[$d1],@x[$a1])",
+ "&rol (@x[$d1],8)",
+
+ "&add ($xc,@x[$d0])",
+ "&xor (@x[$b0],$xc)",
+ "&rol (@x[$b0],7)",
+ "&add ($xc_,@x[$d1])",
+ "&xor (@x[$b1],$xc_)",
+ "&rol (@x[$b1],7)",
+
+ "&mov (\"4*$c0(%rsp)\",$xc)", # reload pair of 'c's
+ "&mov (\"4*$c1(%rsp)\",$xc_)",
+ "&mov ($xc,\"4*$c2(%rsp)\")",
+ "&mov ($xc_,\"4*$c3(%rsp)\")",
+
+ "&add (@x[$a2],@x[$b2])", # Q3
+ "&xor (@x[$d2],@x[$a2])",
+ "&rol (@x[$d2],16)",
+ "&add (@x[$a3],@x[$b3])", # Q4
+ "&xor (@x[$d3],@x[$a3])",
+ "&rol (@x[$d3],16)",
+
+ "&add ($xc,@x[$d2])",
+ "&xor (@x[$b2],$xc)",
+ "&rol (@x[$b2],12)",
+ "&add ($xc_,@x[$d3])",
+ "&xor (@x[$b3],$xc_)",
+ "&rol (@x[$b3],12)",
+
+ "&add (@x[$a2],@x[$b2])",
+ "&xor (@x[$d2],@x[$a2])",
+ "&rol (@x[$d2],8)",
+ "&add (@x[$a3],@x[$b3])",
+ "&xor (@x[$d3],@x[$a3])",
+ "&rol (@x[$d3],8)",
+
+ "&add ($xc,@x[$d2])",
+ "&xor (@x[$b2],$xc)",
+ "&rol (@x[$b2],7)",
+ "&add ($xc_,@x[$d3])",
+ "&xor (@x[$b3],$xc_)",
+ "&rol (@x[$b3],7)"
+ );
+}
+
+########################################################################
+# Generic code path that handles all lengths on pre-SSSE3 processors.
+$code.=<<___;
+.globl ChaCha20_ctr32
+.type ChaCha20_ctr32,\@function,5
+.align 64
+ChaCha20_ctr32:
+ cmp \$0,$len
+ je .Lno_data
+ mov OPENSSL_ia32cap_P+4(%rip),%r10
+ test \$`1<<(41-32)`,%r10d
+ jnz .LChaCha20_ssse3
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ sub \$64+24,%rsp
+
+ #movdqa .Lsigma(%rip),%xmm0
+ movdqu ($key),%xmm1
+ movdqu 16($key),%xmm2
+ movdqu ($counter),%xmm3
+ movdqa .Lone(%rip),%xmm4
+
+ #movdqa %xmm0,4*0(%rsp) # key[0]
+ movdqa %xmm1,4*4(%rsp) # key[1]
+ movdqa %xmm2,4*8(%rsp) # key[2]
+ movdqa %xmm3,4*12(%rsp) # key[3]
+ mov $len,%rbp # reassign $len
+ jmp .Loop_outer
+
+.align 32
+.Loop_outer:
+ mov \$0x61707865,@x[0] # 'expa'
+ mov \$0x3320646e,@x[1] # 'nd 3'
+ mov \$0x79622d32,@x[2] # '2-by'
+ mov \$0x6b206574,@x[3] # 'te k'
+ mov 4*4(%rsp),@x[4]
+ mov 4*5(%rsp),@x[5]
+ mov 4*6(%rsp),@x[6]
+ mov 4*7(%rsp),@x[7]
+ movd %xmm3,@x[12]
+ mov 4*13(%rsp),@x[13]
+ mov 4*14(%rsp),@x[14]
+ mov 4*15(%rsp),@x[15]
+
+ mov %rbp,64+0(%rsp) # save len
+ mov \$10,%ebp
+ mov $inp,64+8(%rsp) # save inp
+ movq %xmm2,%rsi # "@x[8]"
+ mov $out,64+16(%rsp) # save out
+ mov %rsi,%rdi
+ shr \$32,%rdi # "@x[9]"
+ jmp .Loop
+
+.align 32
+.Loop:
+___
+ foreach (&ROUND (0, 4, 8,12)) { eval; }
+ foreach (&ROUND (0, 5,10,15)) { eval; }
+ &dec ("%ebp");
+ &jnz (".Loop");
+
+$code.=<<___;
+ mov @t[1],4*9(%rsp) # modulo-scheduled
+ mov @t[0],4*8(%rsp)
+ mov 64(%rsp),%rbp # load len
+ movdqa %xmm2,%xmm1
+ mov 64+8(%rsp),$inp # load inp
+ paddd %xmm4,%xmm3 # increment counter
+ mov 64+16(%rsp),$out # load out
+
+ add \$0x61707865,@x[0] # 'expa'
+ add \$0x3320646e,@x[1] # 'nd 3'
+ add \$0x79622d32,@x[2] # '2-by'
+ add \$0x6b206574,@x[3] # 'te k'
+ add 4*4(%rsp),@x[4]
+ add 4*5(%rsp),@x[5]
+ add 4*6(%rsp),@x[6]
+ add 4*7(%rsp),@x[7]
+ add 4*12(%rsp),@x[12]
+ add 4*13(%rsp),@x[13]
+ add 4*14(%rsp),@x[14]
+ add 4*15(%rsp),@x[15]
+ paddd 4*8(%rsp),%xmm1
+
+ cmp \$64,%rbp
+ jb .Ltail
+
+ xor 4*0($inp),@x[0] # xor with input
+ xor 4*1($inp),@x[1]
+ xor 4*2($inp),@x[2]
+ xor 4*3($inp),@x[3]
+ xor 4*4($inp),@x[4]
+ xor 4*5($inp),@x[5]
+ xor 4*6($inp),@x[6]
+ xor 4*7($inp),@x[7]
+ movdqu 4*8($inp),%xmm0
+ xor 4*12($inp),@x[12]
+ xor 4*13($inp),@x[13]
+ xor 4*14($inp),@x[14]
+ xor 4*15($inp),@x[15]
+ lea 4*16($inp),$inp # inp+=64
+ pxor %xmm1,%xmm0
+
+ movdqa %xmm2,4*8(%rsp)
+ movd %xmm3,4*12(%rsp)
+
+ mov @x[0],4*0($out) # write output
+ mov @x[1],4*1($out)
+ mov @x[2],4*2($out)
+ mov @x[3],4*3($out)
+ mov @x[4],4*4($out)
+ mov @x[5],4*5($out)
+ mov @x[6],4*6($out)
+ mov @x[7],4*7($out)
+ movdqu %xmm0,4*8($out)
+ mov @x[12],4*12($out)
+ mov @x[13],4*13($out)
+ mov @x[14],4*14($out)
+ mov @x[15],4*15($out)
+ lea 4*16($out),$out # out+=64
+
+ sub \$64,%rbp
+ jnz .Loop_outer
+
+ jmp .Ldone
+
+.align 16
+.Ltail:
+ mov @x[0],4*0(%rsp)
+ mov @x[1],4*1(%rsp)
+ xor %rbx,%rbx
+ mov @x[2],4*2(%rsp)
+ mov @x[3],4*3(%rsp)
+ mov @x[4],4*4(%rsp)
+ mov @x[5],4*5(%rsp)
+ mov @x[6],4*6(%rsp)
+ mov @x[7],4*7(%rsp)
+ movdqa %xmm1,4*8(%rsp)
+ mov @x[12],4*12(%rsp)
+ mov @x[13],4*13(%rsp)
+ mov @x[14],4*14(%rsp)
+ mov @x[15],4*15(%rsp)
+
+.Loop_tail:
+ movzb ($inp,%rbx),%eax
+ movzb (%rsp,%rbx),%edx
+ lea 1(%rbx),%rbx
+ xor %edx,%eax
+ mov %al,-1($out,%rbx)
+ dec %rbp
+ jnz .Loop_tail
+
+.Ldone:
+ add \$64+24,%rsp
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+.Lno_data:
+ ret
+.size ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+########################################################################
+# SSSE3 code path that handles shorter lengths
+{
+my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("%xmm$_",(0..7));
+
+sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot16);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,20);
+ &pslld ($t,12);
+ &por ($b,$t);
+
+ &paddd ($a,$b);
+ &pxor ($d,$a);
+ &pshufb ($d,$rot24);
+
+ &paddd ($c,$d);
+ &pxor ($b,$c);
+ &movdqa ($t,$b);
+ &psrld ($b,25);
+ &pslld ($t,7);
+ &por ($b,$t);
+}
+
+my $xframe = $win64 ? 32+32+8 : 24;
+
+$code.=<<___;
+.type ChaCha20_ssse3,\@function,5
+.align 32
+ChaCha20_ssse3:
+.LChaCha20_ssse3:
+___
+$code.=<<___;
+ cmp \$128,$len # we might throw away some data,
+ ja .LChaCha20_4x # but overall it won't be slower
+
+.Ldo_sse3_after_all:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ sub \$64+$xframe,%rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,64+32(%rsp)
+ movaps %xmm7,64+48(%rsp)
+___
+$code.=<<___;
+ movdqa .Lsigma(%rip),$a
+ movdqu ($key),$b
+ movdqu 16($key),$c
+ movdqu ($counter),$d
+ movdqa .Lrot16(%rip),$rot16
+ movdqa .Lrot24(%rip),$rot24
+
+ movdqa $a,0x00(%rsp)
+ movdqa $b,0x10(%rsp)
+ movdqa $c,0x20(%rsp)
+ movdqa $d,0x30(%rsp)
+ mov \$10,%ebp
+ jmp .Loop_ssse3
+
+.align 32
+.Loop_outer_ssse3:
+ movdqa .Lone(%rip),$d
+ movdqa 0x00(%rsp),$a
+ movdqa 0x10(%rsp),$b
+ movdqa 0x20(%rsp),$c
+ paddd 0x30(%rsp),$d
+ mov \$10,%ebp
+ movdqa $d,0x30(%rsp)
+ jmp .Loop_ssse3
+
+.align 32
+.Loop_ssse3:
+___
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b00111001);
+ &pshufd ($d,$d,0b10010011);
+ &nop ();
+
+ &SSSE3ROUND();
+ &pshufd ($c,$c,0b01001110);
+ &pshufd ($b,$b,0b10010011);
+ &pshufd ($d,$d,0b00111001);
+
+ &dec ("%ebp");
+ &jnz (".Loop_ssse3");
+
+$code.=<<___;
+ paddd 0x00(%rsp),$a
+ paddd 0x10(%rsp),$b
+ paddd 0x20(%rsp),$c
+ paddd 0x30(%rsp),$d
+
+ cmp \$64,$len
+ jb .Ltail_ssse3
+
+ movdqu 0x00($inp),$t
+ movdqu 0x10($inp),$t1
+ pxor $t,$a # xor with input
+ movdqu 0x20($inp),$t
+ pxor $t1,$b
+ movdqu 0x30($inp),$t1
+ lea 0x40($inp),$inp # inp+=64
+ pxor $t,$c
+ pxor $t1,$d
+
+ movdqu $a,0x00($out) # write output
+ movdqu $b,0x10($out)
+ movdqu $c,0x20($out)
+ movdqu $d,0x30($out)
+ lea 0x40($out),$out # out+=64
+
+ sub \$64,$len
+ jnz .Loop_outer_ssse3
+
+ jmp .Ldone_ssse3
+
+.align 16
+.Ltail_ssse3:
+ movdqa $a,0x00(%rsp)
+ movdqa $b,0x10(%rsp)
+ movdqa $c,0x20(%rsp)
+ movdqa $d,0x30(%rsp)
+ xor %rbx,%rbx
+
+.Loop_tail_ssse3:
+ movzb ($inp,%rbx),%eax
+ movzb (%rsp,%rbx),%ecx
+ lea 1(%rbx),%rbx
+ xor %ecx,%eax
+ mov %al,-1($out,%rbx)
+ dec $len
+ jnz .Loop_tail_ssse3
+
+.Ldone_ssse3:
+___
+$code.=<<___ if ($win64);
+ movaps 64+32(%rsp),%xmm6
+ movaps 64+48(%rsp),%xmm7
+___
+$code.=<<___;
+ add \$64+$xframe,%rsp
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ ret
+.size ChaCha20_ssse3,.-ChaCha20_ssse3
+___
+}
+
+########################################################################
+# SSSE3 code path that handles longer messages.
+{
+# assign variables to favor Atom front-end
+my ($xd0,$xd1,$xd2,$xd3, $xt0,$xt1,$xt2,$xt3,
+ $xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3)=map("%xmm$_",(0..15));
+my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+ "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3);
+
+sub SSSE3_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3);
+my @x=map("\"$_\"",@xx);
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' and 'd's are permanently allocated in registers,
+ # @x[0..7,12..15], while 'c's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end.
+
+ (
+ "&paddd (@x[$a0],@x[$b0])", # Q1
+ "&paddd (@x[$a1],@x[$b1])", # Q2
+ "&pxor (@x[$d0],@x[$a0])",
+ "&pxor (@x[$d1],@x[$a1])",
+ "&pshufb (@x[$d0],$t1)",
+ "&pshufb (@x[$d1],$t1)",
+
+ "&paddd ($xc,@x[$d0])",
+ "&paddd ($xc_,@x[$d1])",
+ "&pxor (@x[$b0],$xc)",
+ "&pxor (@x[$b1],$xc_)",
+ "&movdqa ($t0,@x[$b0])",
+ "&pslld (@x[$b0],12)",
+ "&psrld ($t0,20)",
+ "&movdqa ($t1,@x[$b1])",
+ "&pslld (@x[$b1],12)",
+ "&por (@x[$b0],$t0)",
+ "&psrld ($t1,20)",
+ "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip)
+ "&por (@x[$b1],$t1)",
+
+ "&paddd (@x[$a0],@x[$b0])",
+ "&paddd (@x[$a1],@x[$b1])",
+ "&pxor (@x[$d0],@x[$a0])",
+ "&pxor (@x[$d1],@x[$a1])",
+ "&pshufb (@x[$d0],$t0)",
+ "&pshufb (@x[$d1],$t0)",
+
+ "&paddd ($xc,@x[$d0])",
+ "&paddd ($xc_,@x[$d1])",
+ "&pxor (@x[$b0],$xc)",
+ "&pxor (@x[$b1],$xc_)",
+ "&movdqa ($t1,@x[$b0])",
+ "&pslld (@x[$b0],7)",
+ "&psrld ($t1,25)",
+ "&movdqa ($t0,@x[$b1])",
+ "&pslld (@x[$b1],7)",
+ "&por (@x[$b0],$t1)",
+ "&psrld ($t0,25)",
+ "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip)
+ "&por (@x[$b1],$t0)",
+
+ "&movdqa (\"`16*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's
+ "&movdqa (\"`16*($c1-8)`(%rsp)\",$xc_)",
+ "&movdqa ($xc,\"`16*($c2-8)`(%rsp)\")",
+ "&movdqa ($xc_,\"`16*($c3-8)`(%rsp)\")",
+
+ "&paddd (@x[$a2],@x[$b2])", # Q3
+ "&paddd (@x[$a3],@x[$b3])", # Q4
+ "&pxor (@x[$d2],@x[$a2])",
+ "&pxor (@x[$d3],@x[$a3])",
+ "&pshufb (@x[$d2],$t1)",
+ "&pshufb (@x[$d3],$t1)",
+
+ "&paddd ($xc,@x[$d2])",
+ "&paddd ($xc_,@x[$d3])",
+ "&pxor (@x[$b2],$xc)",
+ "&pxor (@x[$b3],$xc_)",
+ "&movdqa ($t0,@x[$b2])",
+ "&pslld (@x[$b2],12)",
+ "&psrld ($t0,20)",
+ "&movdqa ($t1,@x[$b3])",
+ "&pslld (@x[$b3],12)",
+ "&por (@x[$b2],$t0)",
+ "&psrld ($t1,20)",
+ "&movdqa ($t0,'(%r11)')", # .Lrot24(%rip)
+ "&por (@x[$b3],$t1)",
+
+ "&paddd (@x[$a2],@x[$b2])",
+ "&paddd (@x[$a3],@x[$b3])",
+ "&pxor (@x[$d2],@x[$a2])",
+ "&pxor (@x[$d3],@x[$a3])",
+ "&pshufb (@x[$d2],$t0)",
+ "&pshufb (@x[$d3],$t0)",
+
+ "&paddd ($xc,@x[$d2])",
+ "&paddd ($xc_,@x[$d3])",
+ "&pxor (@x[$b2],$xc)",
+ "&pxor (@x[$b3],$xc_)",
+ "&movdqa ($t1,@x[$b2])",
+ "&pslld (@x[$b2],7)",
+ "&psrld ($t1,25)",
+ "&movdqa ($t0,@x[$b3])",
+ "&pslld (@x[$b3],7)",
+ "&por (@x[$b2],$t1)",
+ "&psrld ($t0,25)",
+ "&movdqa ($t1,'(%r10)')", # .Lrot16(%rip)
+ "&por (@x[$b3],$t0)"
+ );
+}
+
+my $xframe = $win64 ? 0xa0 : 0;
+
+$code.=<<___;
+.type ChaCha20_4x,\@function,5
+.align 32
+ChaCha20_4x:
+.LChaCha20_4x:
+ mov %r10,%r11
+___
+$code.=<<___ if ($avx>1);
+ shr \$32,%r10 # OPENSSL_ia32cap_P+8
+ test \$`1<<5`,%r10 # test AVX2
+ jnz .LChaCha20_8x
+___
+$code.=<<___;
+ cmp \$192,$len
+ ja .Lproceed4x
+
+ and \$`1<<26|1<<22`,%r11 # isolate XSAVE+MOVBE
+ cmp \$`1<<22`,%r11 # check for MOVBE without XSAVE
+ je .Ldo_sse3_after_all # to detect Atom
+
+.Lproceed4x:
+ lea -0x78(%rsp),%r11
+ sub \$0x148+$xframe,%rsp
+___
+ ################ stack layout
+ # +0x00 SIMD equivalent of @x[8-12]
+ # ...
+ # +0x40 constant copy of key[0-2] smashed by lanes
+ # ...
+ # +0x100 SIMD counters (with nonce smashed by lanes)
+ # ...
+ # +0x140
+$code.=<<___ if ($win64);
+ movaps %xmm6,-0x30(%r11)
+ movaps %xmm7,-0x20(%r11)
+ movaps %xmm8,-0x10(%r11)
+ movaps %xmm9,0x00(%r11)
+ movaps %xmm10,0x10(%r11)
+ movaps %xmm11,0x20(%r11)
+ movaps %xmm12,0x30(%r11)
+ movaps %xmm13,0x40(%r11)
+ movaps %xmm14,0x50(%r11)
+ movaps %xmm15,0x60(%r11)
+___
+$code.=<<___;
+ movdqa .Lsigma(%rip),$xa3 # key[0]
+ movdqu ($key),$xb3 # key[1]
+ movdqu 16($key),$xt3 # key[2]
+ movdqu ($counter),$xd3 # key[3]
+ lea 0x100(%rsp),%rcx # size optimization
+ lea .Lrot16(%rip),%r10
+ lea .Lrot24(%rip),%r11
+
+ pshufd \$0x00,$xa3,$xa0 # smash key by lanes...
+ pshufd \$0x55,$xa3,$xa1
+ movdqa $xa0,0x40(%rsp) # ... and offload
+ pshufd \$0xaa,$xa3,$xa2
+ movdqa $xa1,0x50(%rsp)
+ pshufd \$0xff,$xa3,$xa3
+ movdqa $xa2,0x60(%rsp)
+ movdqa $xa3,0x70(%rsp)
+
+ pshufd \$0x00,$xb3,$xb0
+ pshufd \$0x55,$xb3,$xb1
+ movdqa $xb0,0x80-0x100(%rcx)
+ pshufd \$0xaa,$xb3,$xb2
+ movdqa $xb1,0x90-0x100(%rcx)
+ pshufd \$0xff,$xb3,$xb3
+ movdqa $xb2,0xa0-0x100(%rcx)
+ movdqa $xb3,0xb0-0x100(%rcx)
+
+ pshufd \$0x00,$xt3,$xt0 # "$xc0"
+ pshufd \$0x55,$xt3,$xt1 # "$xc1"
+ movdqa $xt0,0xc0-0x100(%rcx)
+ pshufd \$0xaa,$xt3,$xt2 # "$xc2"
+ movdqa $xt1,0xd0-0x100(%rcx)
+ pshufd \$0xff,$xt3,$xt3 # "$xc3"
+ movdqa $xt2,0xe0-0x100(%rcx)
+ movdqa $xt3,0xf0-0x100(%rcx)
+
+ pshufd \$0x00,$xd3,$xd0
+ pshufd \$0x55,$xd3,$xd1
+ paddd .Linc(%rip),$xd0 # don't save counters yet
+ pshufd \$0xaa,$xd3,$xd2
+ movdqa $xd1,0x110-0x100(%rcx)
+ pshufd \$0xff,$xd3,$xd3
+ movdqa $xd2,0x120-0x100(%rcx)
+ movdqa $xd3,0x130-0x100(%rcx)
+
+ jmp .Loop_enter4x
+
+.align 32
+.Loop_outer4x:
+ movdqa 0x40(%rsp),$xa0 # re-load smashed key
+ movdqa 0x50(%rsp),$xa1
+ movdqa 0x60(%rsp),$xa2
+ movdqa 0x70(%rsp),$xa3
+ movdqa 0x80-0x100(%rcx),$xb0
+ movdqa 0x90-0x100(%rcx),$xb1
+ movdqa 0xa0-0x100(%rcx),$xb2
+ movdqa 0xb0-0x100(%rcx),$xb3
+ movdqa 0xc0-0x100(%rcx),$xt0 # "$xc0"
+ movdqa 0xd0-0x100(%rcx),$xt1 # "$xc1"
+ movdqa 0xe0-0x100(%rcx),$xt2 # "$xc2"
+ movdqa 0xf0-0x100(%rcx),$xt3 # "$xc3"
+ movdqa 0x100-0x100(%rcx),$xd0
+ movdqa 0x110-0x100(%rcx),$xd1
+ movdqa 0x120-0x100(%rcx),$xd2
+ movdqa 0x130-0x100(%rcx),$xd3
+ paddd .Lfour(%rip),$xd0 # next SIMD counters
+
+.Loop_enter4x:
+ movdqa $xt2,0x20(%rsp) # SIMD equivalent of "@x[10]"
+ movdqa $xt3,0x30(%rsp) # SIMD equivalent of "@x[11]"
+ movdqa (%r10),$xt3 # .Lrot16(%rip)
+ mov \$10,%eax
+ movdqa $xd0,0x100-0x100(%rcx) # save SIMD counters
+ jmp .Loop4x
+
+.align 32
+.Loop4x:
+___
+ foreach (&SSSE3_lane_ROUND(0, 4, 8,12)) { eval; }
+ foreach (&SSSE3_lane_ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ dec %eax
+ jnz .Loop4x
+
+ paddd 0x40(%rsp),$xa0 # accumulate key material
+ paddd 0x50(%rsp),$xa1
+ paddd 0x60(%rsp),$xa2
+ paddd 0x70(%rsp),$xa3
+
+ movdqa $xa0,$xt2 # "de-interlace" data
+ punpckldq $xa1,$xa0
+ movdqa $xa2,$xt3
+ punpckldq $xa3,$xa2
+ punpckhdq $xa1,$xt2
+ punpckhdq $xa3,$xt3
+ movdqa $xa0,$xa1
+ punpcklqdq $xa2,$xa0 # "a0"
+ movdqa $xt2,$xa3
+ punpcklqdq $xt3,$xt2 # "a2"
+ punpckhqdq $xa2,$xa1 # "a1"
+ punpckhqdq $xt3,$xa3 # "a3"
+___
+ ($xa2,$xt2)=($xt2,$xa2);
+$code.=<<___;
+ paddd 0x80-0x100(%rcx),$xb0
+ paddd 0x90-0x100(%rcx),$xb1
+ paddd 0xa0-0x100(%rcx),$xb2
+ paddd 0xb0-0x100(%rcx),$xb3
+
+ movdqa $xa0,0x00(%rsp) # offload $xaN
+ movdqa $xa1,0x10(%rsp)
+ movdqa 0x20(%rsp),$xa0 # "xc2"
+ movdqa 0x30(%rsp),$xa1 # "xc3"
+
+ movdqa $xb0,$xt2
+ punpckldq $xb1,$xb0
+ movdqa $xb2,$xt3
+ punpckldq $xb3,$xb2
+ punpckhdq $xb1,$xt2
+ punpckhdq $xb3,$xt3
+ movdqa $xb0,$xb1
+ punpcklqdq $xb2,$xb0 # "b0"
+ movdqa $xt2,$xb3
+ punpcklqdq $xt3,$xt2 # "b2"
+ punpckhqdq $xb2,$xb1 # "b1"
+ punpckhqdq $xt3,$xb3 # "b3"
+___
+ ($xb2,$xt2)=($xt2,$xb2);
+ my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1);
+$code.=<<___;
+ paddd 0xc0-0x100(%rcx),$xc0
+ paddd 0xd0-0x100(%rcx),$xc1
+ paddd 0xe0-0x100(%rcx),$xc2
+ paddd 0xf0-0x100(%rcx),$xc3
+
+ movdqa $xa2,0x20(%rsp) # keep offloading $xaN
+ movdqa $xa3,0x30(%rsp)
+
+ movdqa $xc0,$xt2
+ punpckldq $xc1,$xc0
+ movdqa $xc2,$xt3
+ punpckldq $xc3,$xc2
+ punpckhdq $xc1,$xt2
+ punpckhdq $xc3,$xt3
+ movdqa $xc0,$xc1
+ punpcklqdq $xc2,$xc0 # "c0"
+ movdqa $xt2,$xc3
+ punpcklqdq $xt3,$xt2 # "c2"
+ punpckhqdq $xc2,$xc1 # "c1"
+ punpckhqdq $xt3,$xc3 # "c3"
+___
+ ($xc2,$xt2)=($xt2,$xc2);
+ ($xt0,$xt1)=($xa2,$xa3); # use $xaN as temporary
+$code.=<<___;
+ paddd 0x100-0x100(%rcx),$xd0
+ paddd 0x110-0x100(%rcx),$xd1
+ paddd 0x120-0x100(%rcx),$xd2
+ paddd 0x130-0x100(%rcx),$xd3
+
+ movdqa $xd0,$xt2
+ punpckldq $xd1,$xd0
+ movdqa $xd2,$xt3
+ punpckldq $xd3,$xd2
+ punpckhdq $xd1,$xt2
+ punpckhdq $xd3,$xt3
+ movdqa $xd0,$xd1
+ punpcklqdq $xd2,$xd0 # "d0"
+ movdqa $xt2,$xd3
+ punpcklqdq $xt3,$xt2 # "d2"
+ punpckhqdq $xd2,$xd1 # "d1"
+ punpckhqdq $xt3,$xd3 # "d3"
+___
+ ($xd2,$xt2)=($xt2,$xd2);
+$code.=<<___;
+ cmp \$64*4,$len
+ jb .Ltail4x
+
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ lea 0x80($inp),$inp # size optimization
+ pxor 0x10(%rsp),$xt0
+ pxor $xb1,$xt1
+ pxor $xc1,$xt2
+ pxor $xd1,$xt3
+
+ movdqu $xt0,0x40($out)
+ movdqu 0x00($inp),$xt0
+ movdqu $xt1,0x50($out)
+ movdqu 0x10($inp),$xt1
+ movdqu $xt2,0x60($out)
+ movdqu 0x20($inp),$xt2
+ movdqu $xt3,0x70($out)
+ lea 0x80($out),$out # size optimization
+ movdqu 0x30($inp),$xt3
+ pxor 0x20(%rsp),$xt0
+ pxor $xb2,$xt1
+ pxor $xc2,$xt2
+ pxor $xd2,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ lea 0x80($inp),$inp # inp+=64*4
+ pxor 0x30(%rsp),$xt0
+ pxor $xb3,$xt1
+ pxor $xc3,$xt2
+ pxor $xd3,$xt3
+ movdqu $xt0,0x40($out)
+ movdqu $xt1,0x50($out)
+ movdqu $xt2,0x60($out)
+ movdqu $xt3,0x70($out)
+ lea 0x80($out),$out # out+=64*4
+
+ sub \$64*4,$len
+ jnz .Loop_outer4x
+
+ jmp .Ldone4x
+
+.Ltail4x:
+ cmp \$192,$len
+ jae .L192_or_more4x
+ cmp \$128,$len
+ jae .L128_or_more4x
+ cmp \$64,$len
+ jae .L64_or_more4x
+
+ #movdqa 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ xor %r10,%r10
+ #movdqa $xt0,0x00(%rsp)
+ movdqa $xb0,0x10(%rsp)
+ movdqa $xc0,0x20(%rsp)
+ movdqa $xd0,0x30(%rsp)
+ jmp .Loop_tail4x
+
+.align 32
+.L64_or_more4x:
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaxN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+ movdqu $xt0,0x00($out)
+ movdqu $xt1,0x10($out)
+ movdqu $xt2,0x20($out)
+ movdqu $xt3,0x30($out)
+ je .Ldone4x
+
+ movdqa 0x10(%rsp),$xt0 # $xaN is offloaded, remember?
+ lea 0x40($inp),$inp # inp+=64*1
+ xor %r10,%r10
+ movdqa $xt0,0x00(%rsp)
+ movdqa $xb1,0x10(%rsp)
+ lea 0x40($out),$out # out+=64*1
+ movdqa $xc1,0x20(%rsp)
+ sub \$64,$len # len-=64*1
+ movdqa $xd1,0x30(%rsp)
+ jmp .Loop_tail4x
+
+.align 32
+.L128_or_more4x:
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ pxor 0x10(%rsp),$xt0
+ pxor $xb1,$xt1
+ pxor $xc1,$xt2
+ pxor $xd1,$xt3
+ movdqu $xt0,0x40($out)
+ movdqu $xt1,0x50($out)
+ movdqu $xt2,0x60($out)
+ movdqu $xt3,0x70($out)
+ je .Ldone4x
+
+ movdqa 0x20(%rsp),$xt0 # $xaN is offloaded, remember?
+ lea 0x80($inp),$inp # inp+=64*2
+ xor %r10,%r10
+ movdqa $xt0,0x00(%rsp)
+ movdqa $xb2,0x10(%rsp)
+ lea 0x80($out),$out # out+=64*2
+ movdqa $xc2,0x20(%rsp)
+ sub \$128,$len # len-=64*2
+ movdqa $xd2,0x30(%rsp)
+ jmp .Loop_tail4x
+
+.align 32
+.L192_or_more4x:
+ movdqu 0x00($inp),$xt0 # xor with input
+ movdqu 0x10($inp),$xt1
+ movdqu 0x20($inp),$xt2
+ movdqu 0x30($inp),$xt3
+ pxor 0x00(%rsp),$xt0 # $xaN is offloaded, remember?
+ pxor $xb0,$xt1
+ pxor $xc0,$xt2
+ pxor $xd0,$xt3
+
+ movdqu $xt0,0x00($out)
+ movdqu 0x40($inp),$xt0
+ movdqu $xt1,0x10($out)
+ movdqu 0x50($inp),$xt1
+ movdqu $xt2,0x20($out)
+ movdqu 0x60($inp),$xt2
+ movdqu $xt3,0x30($out)
+ movdqu 0x70($inp),$xt3
+ lea 0x80($inp),$inp # size optimization
+ pxor 0x10(%rsp),$xt0
+ pxor $xb1,$xt1
+ pxor $xc1,$xt2
+ pxor $xd1,$xt3
+
+ movdqu $xt0,0x40($out)
+ movdqu 0x00($inp),$xt0
+ movdqu $xt1,0x50($out)
+ movdqu 0x10($inp),$xt1
+ movdqu $xt2,0x60($out)
+ movdqu 0x20($inp),$xt2
+ movdqu $xt3,0x70($out)
+ lea 0x80($out),$out # size optimization
+ movdqu 0x30($inp),$xt3
+ pxor 0x20(%rsp),$xt0
+ pxor $xb2,$xt1
+ pxor $xc2,$xt2
+ pxor $xd2,$xt3
+ movdqu $xt0,0x00($out)
+ movdqu $xt1,0x10($out)
+ movdqu $xt2,0x20($out)
+ movdqu $xt3,0x30($out)
+ je .Ldone4x
+
+ movdqa 0x30(%rsp),$xt0 # $xaN is offloaded, remember?
+ lea 0x40($inp),$inp # inp+=64*3
+ xor %r10,%r10
+ movdqa $xt0,0x00(%rsp)
+ movdqa $xb3,0x10(%rsp)
+ lea 0x40($out),$out # out+=64*3
+ movdqa $xc3,0x20(%rsp)
+ sub \$192,$len # len-=64*3
+ movdqa $xd3,0x30(%rsp)
+
+.Loop_tail4x:
+ movzb ($inp,%r10),%eax
+ movzb (%rsp,%r10),%ecx
+ lea 1(%r10),%r10
+ xor %ecx,%eax
+ mov %al,-1($out,%r10)
+ dec $len
+ jnz .Loop_tail4x
+
+.Ldone4x:
+___
+$code.=<<___ if ($win64);
+ lea 0x140+0x30(%rsp),%r11
+ movaps -0x30(%r11),%xmm6
+ movaps -0x20(%r11),%xmm7
+ movaps -0x10(%r11),%xmm8
+ movaps 0x00(%r11),%xmm9
+ movaps 0x10(%r11),%xmm10
+ movaps 0x20(%r11),%xmm11
+ movaps 0x30(%r11),%xmm12
+ movaps 0x40(%r11),%xmm13
+ movaps 0x50(%r11),%xmm14
+ movaps 0x60(%r11),%xmm15
+___
+$code.=<<___;
+ add \$0x148+$xframe,%rsp
+ ret
+.size ChaCha20_4x,.-ChaCha20_4x
+___
+}
+
+########################################################################
+# AVX2 code path
+if ($avx>1) {
+my ($xb0,$xb1,$xb2,$xb3, $xd0,$xd1,$xd2,$xd3,
+ $xa0,$xa1,$xa2,$xa3, $xt0,$xt1,$xt2,$xt3)=map("%ymm$_",(0..15));
+my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+ "%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3);
+
+sub AVX2_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3);
+my @x=map("\"$_\"",@xx);
+
+ # Consider order in which variables are addressed by their
+ # index:
+ #
+ # a b c d
+ #
+ # 0 4 8 12 < even round
+ # 1 5 9 13
+ # 2 6 10 14
+ # 3 7 11 15
+ # 0 5 10 15 < odd round
+ # 1 6 11 12
+ # 2 7 8 13
+ # 3 4 9 14
+ #
+ # 'a', 'b' and 'd's are permanently allocated in registers,
+ # @x[0..7,12..15], while 'c's are maintained in memory. If
+ # you observe 'c' column, you'll notice that pair of 'c's is
+ # invariant between rounds. This means that we have to reload
+ # them once per round, in the middle. This is why you'll see
+ # bunch of 'c' stores and loads in the middle, but none in
+ # the beginning or end.
+
+ (
+ "&vpaddd (@x[$a0],@x[$a0],@x[$b0])", # Q1
+ "&vpxor (@x[$d0],@x[$a0],@x[$d0])",
+ "&vpshufb (@x[$d0],@x[$d0],$t1)",
+ "&vpaddd (@x[$a1],@x[$a1],@x[$b1])", # Q2
+ "&vpxor (@x[$d1],@x[$a1],@x[$d1])",
+ "&vpshufb (@x[$d1],@x[$d1],$t1)",
+
+ "&vpaddd ($xc,$xc,@x[$d0])",
+ "&vpxor (@x[$b0],$xc,@x[$b0])",
+ "&vpslld ($t0,@x[$b0],12)",
+ "&vpsrld (@x[$b0],@x[$b0],20)",
+ "&vpor (@x[$b0],$t0,@x[$b0])",
+ "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d1])",
+ "&vpxor (@x[$b1],$xc_,@x[$b1])",
+ "&vpslld ($t1,@x[$b1],12)",
+ "&vpsrld (@x[$b1],@x[$b1],20)",
+ "&vpor (@x[$b1],$t1,@x[$b1])",
+
+ "&vpaddd (@x[$a0],@x[$a0],@x[$b0])",
+ "&vpxor (@x[$d0],@x[$a0],@x[$d0])",
+ "&vpshufb (@x[$d0],@x[$d0],$t0)",
+ "&vpaddd (@x[$a1],@x[$a1],@x[$b1])",
+ "&vpxor (@x[$d1],@x[$a1],@x[$d1])",
+ "&vpshufb (@x[$d1],@x[$d1],$t0)",
+
+ "&vpaddd ($xc,$xc,@x[$d0])",
+ "&vpxor (@x[$b0],$xc,@x[$b0])",
+ "&vpslld ($t1,@x[$b0],7)",
+ "&vpsrld (@x[$b0],@x[$b0],25)",
+ "&vpor (@x[$b0],$t1,@x[$b0])",
+ "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d1])",
+ "&vpxor (@x[$b1],$xc_,@x[$b1])",
+ "&vpslld ($t0,@x[$b1],7)",
+ "&vpsrld (@x[$b1],@x[$b1],25)",
+ "&vpor (@x[$b1],$t0,@x[$b1])",
+
+ "&vmovdqa (\"`32*($c0-8)`(%rsp)\",$xc)", # reload pair of 'c's
+ "&vmovdqa (\"`32*($c1-8)`(%rsp)\",$xc_)",
+ "&vmovdqa ($xc,\"`32*($c2-8)`(%rsp)\")",
+ "&vmovdqa ($xc_,\"`32*($c3-8)`(%rsp)\")",
+
+ "&vpaddd (@x[$a2],@x[$a2],@x[$b2])", # Q3
+ "&vpxor (@x[$d2],@x[$a2],@x[$d2])",
+ "&vpshufb (@x[$d2],@x[$d2],$t1)",
+ "&vpaddd (@x[$a3],@x[$a3],@x[$b3])", # Q4
+ "&vpxor (@x[$d3],@x[$a3],@x[$d3])",
+ "&vpshufb (@x[$d3],@x[$d3],$t1)",
+
+ "&vpaddd ($xc,$xc,@x[$d2])",
+ "&vpxor (@x[$b2],$xc,@x[$b2])",
+ "&vpslld ($t0,@x[$b2],12)",
+ "&vpsrld (@x[$b2],@x[$b2],20)",
+ "&vpor (@x[$b2],$t0,@x[$b2])",
+ "&vbroadcasti128($t0,'(%r11)')", # .Lrot24(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d3])",
+ "&vpxor (@x[$b3],$xc_,@x[$b3])",
+ "&vpslld ($t1,@x[$b3],12)",
+ "&vpsrld (@x[$b3],@x[$b3],20)",
+ "&vpor (@x[$b3],$t1,@x[$b3])",
+
+ "&vpaddd (@x[$a2],@x[$a2],@x[$b2])",
+ "&vpxor (@x[$d2],@x[$a2],@x[$d2])",
+ "&vpshufb (@x[$d2],@x[$d2],$t0)",
+ "&vpaddd (@x[$a3],@x[$a3],@x[$b3])",
+ "&vpxor (@x[$d3],@x[$a3],@x[$d3])",
+ "&vpshufb (@x[$d3],@x[$d3],$t0)",
+
+ "&vpaddd ($xc,$xc,@x[$d2])",
+ "&vpxor (@x[$b2],$xc,@x[$b2])",
+ "&vpslld ($t1,@x[$b2],7)",
+ "&vpsrld (@x[$b2],@x[$b2],25)",
+ "&vpor (@x[$b2],$t1,@x[$b2])",
+ "&vbroadcasti128($t1,'(%r10)')", # .Lrot16(%rip)
+ "&vpaddd ($xc_,$xc_,@x[$d3])",
+ "&vpxor (@x[$b3],$xc_,@x[$b3])",
+ "&vpslld ($t0,@x[$b3],7)",
+ "&vpsrld (@x[$b3],@x[$b3],25)",
+ "&vpor (@x[$b3],$t0,@x[$b3])"
+ );
+}
+
+my $xframe = $win64 ? 0xb0 : 8;
+
+$code.=<<___;
+.type ChaCha20_8x,\@function,5
+.align 32
+ChaCha20_8x:
+.LChaCha20_8x:
+ mov %rsp,%r10
+ sub \$0x280+$xframe,%rsp
+ and \$-32,%rsp
+___
+$code.=<<___ if ($win64);
+ lea 0x290+0x30(%rsp),%r11
+ movaps %xmm6,-0x30(%r11)
+ movaps %xmm7,-0x20(%r11)
+ movaps %xmm8,-0x10(%r11)
+ movaps %xmm9,0x00(%r11)
+ movaps %xmm10,0x10(%r11)
+ movaps %xmm11,0x20(%r11)
+ movaps %xmm12,0x30(%r11)
+ movaps %xmm13,0x40(%r11)
+ movaps %xmm14,0x50(%r11)
+ movaps %xmm15,0x60(%r11)
+___
+$code.=<<___;
+ vzeroupper
+ mov %r10,0x280(%rsp)
+
+ ################ stack layout
+ # +0x00 SIMD equivalent of @x[8-12]
+ # ...
+ # +0x80 constant copy of key[0-2] smashed by lanes
+ # ...
+ # +0x200 SIMD counters (with nonce smashed by lanes)
+ # ...
+ # +0x280 saved %rsp
+
+ vbroadcasti128 .Lsigma(%rip),$xa3 # key[0]
+ vbroadcasti128 ($key),$xb3 # key[1]
+ vbroadcasti128 16($key),$xt3 # key[2]
+ vbroadcasti128 ($counter),$xd3 # key[3]
+ lea 0x100(%rsp),%rcx # size optimization
+ lea 0x200(%rsp),%rax # size optimization
+ lea .Lrot16(%rip),%r10
+ lea .Lrot24(%rip),%r11
+
+ vpshufd \$0x00,$xa3,$xa0 # smash key by lanes...
+ vpshufd \$0x55,$xa3,$xa1
+ vmovdqa $xa0,0x80-0x100(%rcx) # ... and offload
+ vpshufd \$0xaa,$xa3,$xa2
+ vmovdqa $xa1,0xa0-0x100(%rcx)
+ vpshufd \$0xff,$xa3,$xa3
+ vmovdqa $xa2,0xc0-0x100(%rcx)
+ vmovdqa $xa3,0xe0-0x100(%rcx)
+
+ vpshufd \$0x00,$xb3,$xb0
+ vpshufd \$0x55,$xb3,$xb1
+ vmovdqa $xb0,0x100-0x100(%rcx)
+ vpshufd \$0xaa,$xb3,$xb2
+ vmovdqa $xb1,0x120-0x100(%rcx)
+ vpshufd \$0xff,$xb3,$xb3
+ vmovdqa $xb2,0x140-0x100(%rcx)
+ vmovdqa $xb3,0x160-0x100(%rcx)
+
+ vpshufd \$0x00,$xt3,$xt0 # "xc0"
+ vpshufd \$0x55,$xt3,$xt1 # "xc1"
+ vmovdqa $xt0,0x180-0x200(%rax)
+ vpshufd \$0xaa,$xt3,$xt2 # "xc2"
+ vmovdqa $xt1,0x1a0-0x200(%rax)
+ vpshufd \$0xff,$xt3,$xt3 # "xc3"
+ vmovdqa $xt2,0x1c0-0x200(%rax)
+ vmovdqa $xt3,0x1e0-0x200(%rax)
+
+ vpshufd \$0x00,$xd3,$xd0
+ vpshufd \$0x55,$xd3,$xd1
+ vpaddd .Lincy(%rip),$xd0,$xd0 # don't save counters yet
+ vpshufd \$0xaa,$xd3,$xd2
+ vmovdqa $xd1,0x220-0x200(%rax)
+ vpshufd \$0xff,$xd3,$xd3
+ vmovdqa $xd2,0x240-0x200(%rax)
+ vmovdqa $xd3,0x260-0x200(%rax)
+
+ jmp .Loop_enter8x
+
+.align 32
+.Loop_outer8x:
+ vmovdqa 0x80-0x100(%rcx),$xa0 # re-load smashed key
+ vmovdqa 0xa0-0x100(%rcx),$xa1
+ vmovdqa 0xc0-0x100(%rcx),$xa2
+ vmovdqa 0xe0-0x100(%rcx),$xa3
+ vmovdqa 0x100-0x100(%rcx),$xb0
+ vmovdqa 0x120-0x100(%rcx),$xb1
+ vmovdqa 0x140-0x100(%rcx),$xb2
+ vmovdqa 0x160-0x100(%rcx),$xb3
+ vmovdqa 0x180-0x200(%rax),$xt0 # "xc0"
+ vmovdqa 0x1a0-0x200(%rax),$xt1 # "xc1"
+ vmovdqa 0x1c0-0x200(%rax),$xt2 # "xc2"
+ vmovdqa 0x1e0-0x200(%rax),$xt3 # "xc3"
+ vmovdqa 0x200-0x200(%rax),$xd0
+ vmovdqa 0x220-0x200(%rax),$xd1
+ vmovdqa 0x240-0x200(%rax),$xd2
+ vmovdqa 0x260-0x200(%rax),$xd3
+ vpaddd .Leight(%rip),$xd0,$xd0 # next SIMD counters
+
+.Loop_enter8x:
+ vmovdqa $xt2,0x40(%rsp) # SIMD equivalent of "@x[10]"
+ vmovdqa $xt3,0x60(%rsp) # SIMD equivalent of "@x[11]"
+ vbroadcasti128 (%r10),$xt3
+ vmovdqa $xd0,0x200-0x200(%rax) # save SIMD counters
+ mov \$10,%eax
+ jmp .Loop8x
+
+.align 32
+.Loop8x:
+___
+ foreach (&AVX2_lane_ROUND(0, 4, 8,12)) { eval; }
+ foreach (&AVX2_lane_ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+ dec %eax
+ jnz .Loop8x
+
+ lea 0x200(%rsp),%rax # size optimization
+ vpaddd 0x80-0x100(%rcx),$xa0,$xa0 # accumulate key
+ vpaddd 0xa0-0x100(%rcx),$xa1,$xa1
+ vpaddd 0xc0-0x100(%rcx),$xa2,$xa2
+ vpaddd 0xe0-0x100(%rcx),$xa3,$xa3
+
+ vpunpckldq $xa1,$xa0,$xt2 # "de-interlace" data
+ vpunpckldq $xa3,$xa2,$xt3
+ vpunpckhdq $xa1,$xa0,$xa0
+ vpunpckhdq $xa3,$xa2,$xa2
+ vpunpcklqdq $xt3,$xt2,$xa1 # "a0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "a1"
+ vpunpcklqdq $xa2,$xa0,$xa3 # "a2"
+ vpunpckhqdq $xa2,$xa0,$xa0 # "a3"
+___
+ ($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2);
+$code.=<<___;
+ vpaddd 0x100-0x100(%rcx),$xb0,$xb0
+ vpaddd 0x120-0x100(%rcx),$xb1,$xb1
+ vpaddd 0x140-0x100(%rcx),$xb2,$xb2
+ vpaddd 0x160-0x100(%rcx),$xb3,$xb3
+
+ vpunpckldq $xb1,$xb0,$xt2
+ vpunpckldq $xb3,$xb2,$xt3
+ vpunpckhdq $xb1,$xb0,$xb0
+ vpunpckhdq $xb3,$xb2,$xb2
+ vpunpcklqdq $xt3,$xt2,$xb1 # "b0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "b1"
+ vpunpcklqdq $xb2,$xb0,$xb3 # "b2"
+ vpunpckhqdq $xb2,$xb0,$xb0 # "b3"
+___
+ ($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2);
+$code.=<<___;
+ vperm2i128 \$0x20,$xb0,$xa0,$xt3 # "de-interlace" further
+ vperm2i128 \$0x31,$xb0,$xa0,$xb0
+ vperm2i128 \$0x20,$xb1,$xa1,$xa0
+ vperm2i128 \$0x31,$xb1,$xa1,$xb1
+ vperm2i128 \$0x20,$xb2,$xa2,$xa1
+ vperm2i128 \$0x31,$xb2,$xa2,$xb2
+ vperm2i128 \$0x20,$xb3,$xa3,$xa2
+ vperm2i128 \$0x31,$xb3,$xa3,$xb3
+___
+ ($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3);
+ my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1);
+$code.=<<___;
+ vmovdqa $xa0,0x00(%rsp) # offload $xaN
+ vmovdqa $xa1,0x20(%rsp)
+ vmovdqa 0x40(%rsp),$xc2 # $xa0
+ vmovdqa 0x60(%rsp),$xc3 # $xa1
+
+ vpaddd 0x180-0x200(%rax),$xc0,$xc0
+ vpaddd 0x1a0-0x200(%rax),$xc1,$xc1
+ vpaddd 0x1c0-0x200(%rax),$xc2,$xc2
+ vpaddd 0x1e0-0x200(%rax),$xc3,$xc3
+
+ vpunpckldq $xc1,$xc0,$xt2
+ vpunpckldq $xc3,$xc2,$xt3
+ vpunpckhdq $xc1,$xc0,$xc0
+ vpunpckhdq $xc3,$xc2,$xc2
+ vpunpcklqdq $xt3,$xt2,$xc1 # "c0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "c1"
+ vpunpcklqdq $xc2,$xc0,$xc3 # "c2"
+ vpunpckhqdq $xc2,$xc0,$xc0 # "c3"
+___
+ ($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2);
+$code.=<<___;
+ vpaddd 0x200-0x200(%rax),$xd0,$xd0
+ vpaddd 0x220-0x200(%rax),$xd1,$xd1
+ vpaddd 0x240-0x200(%rax),$xd2,$xd2
+ vpaddd 0x260-0x200(%rax),$xd3,$xd3
+
+ vpunpckldq $xd1,$xd0,$xt2
+ vpunpckldq $xd3,$xd2,$xt3
+ vpunpckhdq $xd1,$xd0,$xd0
+ vpunpckhdq $xd3,$xd2,$xd2
+ vpunpcklqdq $xt3,$xt2,$xd1 # "d0"
+ vpunpckhqdq $xt3,$xt2,$xt2 # "d1"
+ vpunpcklqdq $xd2,$xd0,$xd3 # "d2"
+ vpunpckhqdq $xd2,$xd0,$xd0 # "d3"
+___
+ ($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2);
+$code.=<<___;
+ vperm2i128 \$0x20,$xd0,$xc0,$xt3 # "de-interlace" further
+ vperm2i128 \$0x31,$xd0,$xc0,$xd0
+ vperm2i128 \$0x20,$xd1,$xc1,$xc0
+ vperm2i128 \$0x31,$xd1,$xc1,$xd1
+ vperm2i128 \$0x20,$xd2,$xc2,$xc1
+ vperm2i128 \$0x31,$xd2,$xc2,$xd2
+ vperm2i128 \$0x20,$xd3,$xc3,$xc2
+ vperm2i128 \$0x31,$xd3,$xc3,$xd3
+___
+ ($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3);
+ ($xb0,$xb1,$xb2,$xb3,$xc0,$xc1,$xc2,$xc3)=
+ ($xc0,$xc1,$xc2,$xc3,$xb0,$xb1,$xb2,$xb3);
+ ($xa0,$xa1)=($xt2,$xt3);
+$code.=<<___;
+ vmovdqa 0x00(%rsp),$xa0 # $xaN was offloaded, remember?
+ vmovdqa 0x20(%rsp),$xa1
+
+ cmp \$64*8,$len
+ jb .Ltail8x
+
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ vpxor 0x00($inp),$xa1,$xa1
+ vpxor 0x20($inp),$xb1,$xb1
+ vpxor 0x40($inp),$xc1,$xc1
+ vpxor 0x60($inp),$xd1,$xd1
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa1,0x00($out)
+ vmovdqu $xb1,0x20($out)
+ vmovdqu $xc1,0x40($out)
+ vmovdqu $xd1,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ vpxor 0x00($inp),$xa2,$xa2
+ vpxor 0x20($inp),$xb2,$xb2
+ vpxor 0x40($inp),$xc2,$xc2
+ vpxor 0x60($inp),$xd2,$xd2
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa2,0x00($out)
+ vmovdqu $xb2,0x20($out)
+ vmovdqu $xc2,0x40($out)
+ vmovdqu $xd2,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ vpxor 0x00($inp),$xa3,$xa3
+ vpxor 0x20($inp),$xb3,$xb3
+ vpxor 0x40($inp),$xc3,$xc3
+ vpxor 0x60($inp),$xd3,$xd3
+ lea 0x80($inp),$inp # size optimization
+ vmovdqu $xa3,0x00($out)
+ vmovdqu $xb3,0x20($out)
+ vmovdqu $xc3,0x40($out)
+ vmovdqu $xd3,0x60($out)
+ lea 0x80($out),$out # size optimization
+
+ sub \$64*8,$len
+ jnz .Loop_outer8x
+
+ jmp .Ldone8x
+
+.Ltail8x:
+ cmp \$448,$len
+ jae .L448_or_more8x
+ cmp \$384,$len
+ jae .L384_or_more8x
+ cmp \$320,$len
+ jae .L320_or_more8x
+ cmp \$256,$len
+ jae .L256_or_more8x
+ cmp \$192,$len
+ jae .L192_or_more8x
+ cmp \$128,$len
+ jae .L128_or_more8x
+ cmp \$64,$len
+ jae .L64_or_more8x
+
+ xor %r10,%r10
+ vmovdqa $xa0,0x00(%rsp)
+ vmovdqa $xb0,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L64_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ je .Ldone8x
+
+ lea 0x40($inp),$inp # inp+=64*1
+ xor %r10,%r10
+ vmovdqa $xc0,0x00(%rsp)
+ lea 0x40($out),$out # out+=64*1
+ sub \$64,$len # len-=64*1
+ vmovdqa $xd0,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L128_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ je .Ldone8x
+
+ lea 0x80($inp),$inp # inp+=64*2
+ xor %r10,%r10
+ vmovdqa $xa1,0x00(%rsp)
+ lea 0x80($out),$out # out+=64*2
+ sub \$128,$len # len-=64*2
+ vmovdqa $xb1,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L192_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ je .Ldone8x
+
+ lea 0xc0($inp),$inp # inp+=64*3
+ xor %r10,%r10
+ vmovdqa $xc1,0x00(%rsp)
+ lea 0xc0($out),$out # out+=64*3
+ sub \$192,$len # len-=64*3
+ vmovdqa $xd1,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L256_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ je .Ldone8x
+
+ lea 0x100($inp),$inp # inp+=64*4
+ xor %r10,%r10
+ vmovdqa $xa2,0x00(%rsp)
+ lea 0x100($out),$out # out+=64*4
+ sub \$256,$len # len-=64*4
+ vmovdqa $xb2,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L320_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vpxor 0x100($inp),$xa2,$xa2
+ vpxor 0x120($inp),$xb2,$xb2
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ vmovdqu $xa2,0x100($out)
+ vmovdqu $xb2,0x120($out)
+ je .Ldone8x
+
+ lea 0x140($inp),$inp # inp+=64*5
+ xor %r10,%r10
+ vmovdqa $xc2,0x00(%rsp)
+ lea 0x140($out),$out # out+=64*5
+ sub \$320,$len # len-=64*5
+ vmovdqa $xd2,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L384_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vpxor 0x100($inp),$xa2,$xa2
+ vpxor 0x120($inp),$xb2,$xb2
+ vpxor 0x140($inp),$xc2,$xc2
+ vpxor 0x160($inp),$xd2,$xd2
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ vmovdqu $xa2,0x100($out)
+ vmovdqu $xb2,0x120($out)
+ vmovdqu $xc2,0x140($out)
+ vmovdqu $xd2,0x160($out)
+ je .Ldone8x
+
+ lea 0x180($inp),$inp # inp+=64*6
+ xor %r10,%r10
+ vmovdqa $xa3,0x00(%rsp)
+ lea 0x180($out),$out # out+=64*6
+ sub \$384,$len # len-=64*6
+ vmovdqa $xb3,0x20(%rsp)
+ jmp .Loop_tail8x
+
+.align 32
+.L448_or_more8x:
+ vpxor 0x00($inp),$xa0,$xa0 # xor with input
+ vpxor 0x20($inp),$xb0,$xb0
+ vpxor 0x40($inp),$xc0,$xc0
+ vpxor 0x60($inp),$xd0,$xd0
+ vpxor 0x80($inp),$xa1,$xa1
+ vpxor 0xa0($inp),$xb1,$xb1
+ vpxor 0xc0($inp),$xc1,$xc1
+ vpxor 0xe0($inp),$xd1,$xd1
+ vpxor 0x100($inp),$xa2,$xa2
+ vpxor 0x120($inp),$xb2,$xb2
+ vpxor 0x140($inp),$xc2,$xc2
+ vpxor 0x160($inp),$xd2,$xd2
+ vpxor 0x180($inp),$xa3,$xa3
+ vpxor 0x1a0($inp),$xb3,$xb3
+ vmovdqu $xa0,0x00($out)
+ vmovdqu $xb0,0x20($out)
+ vmovdqu $xc0,0x40($out)
+ vmovdqu $xd0,0x60($out)
+ vmovdqu $xa1,0x80($out)
+ vmovdqu $xb1,0xa0($out)
+ vmovdqu $xc1,0xc0($out)
+ vmovdqu $xd1,0xe0($out)
+ vmovdqu $xa2,0x100($out)
+ vmovdqu $xb2,0x120($out)
+ vmovdqu $xc2,0x140($out)
+ vmovdqu $xd2,0x160($out)
+ vmovdqu $xa3,0x180($out)
+ vmovdqu $xb3,0x1a0($out)
+ je .Ldone8x
+
+ lea 0x1c0($inp),$inp # inp+=64*7
+ xor %r10,%r10
+ vmovdqa $xc3,0x00(%rsp)
+ lea 0x1c0($out),$out # out+=64*7
+ sub \$448,$len # len-=64*7
+ vmovdqa $xd3,0x20(%rsp)
+
+.Loop_tail8x:
+ movzb ($inp,%r10),%eax
+ movzb (%rsp,%r10),%ecx
+ lea 1(%r10),%r10
+ xor %ecx,%eax
+ mov %al,-1($out,%r10)
+ dec $len
+ jnz .Loop_tail8x
+
+.Ldone8x:
+ vzeroall
+___
+$code.=<<___ if ($win64);
+ lea 0x290+0x30(%rsp),%r11
+ movaps -0x30(%r11),%xmm6
+ movaps -0x20(%r11),%xmm7
+ movaps -0x10(%r11),%xmm8
+ movaps 0x00(%r11),%xmm9
+ movaps 0x10(%r11),%xmm10
+ movaps 0x20(%r11),%xmm11
+ movaps 0x30(%r11),%xmm12
+ movaps 0x40(%r11),%xmm13
+ movaps 0x50(%r11),%xmm14
+ movaps 0x60(%r11),%xmm15
+___
+$code.=<<___;
+ mov 0x280(%rsp),%rsp
+ ret
+.size ChaCha20_8x,.-ChaCha20_8x
+___
+}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/%x#%y/%x/go;
+
+ print $_,"\n";
+}
+
+close STDOUT;
diff --git a/crypto/chacha/chacha.c b/crypto/chacha/chacha.c
new file mode 100644
index 00000000..15620894
--- /dev/null
+++ b/crypto/chacha/chacha.c
@@ -0,0 +1,170 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+/* Adapted from the public domain, estream code by D. Bernstein. */
+
+#include <openssl/chacha.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/cpu.h>
+
+#include "../internal.h"
+
+
+#define U8TO32_LITTLE(p) \
+ (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
+ ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+
+/* ChaCha20_ctr32 is defined in asm/chacha-*.pl. */
+void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint32_t key[8], const uint32_t counter[4]);
+
+void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t key[32], const uint8_t nonce[12],
+ uint32_t counter) {
+ assert(!buffers_alias(out, in_len, in, in_len) || in == out);
+
+ uint32_t counter_nonce[4]; counter_nonce[0] = counter;
+ counter_nonce[1] = U8TO32_LITTLE(nonce + 0);
+ counter_nonce[2] = U8TO32_LITTLE(nonce + 4);
+ counter_nonce[3] = U8TO32_LITTLE(nonce + 8);
+
+ const uint32_t *key_ptr = (const uint32_t *)key;
+#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
+ /* The assembly expects the key to be four-byte aligned. */
+ uint32_t key_u32[8];
+ if ((((uintptr_t)key) & 3) != 0) {
+ key_u32[0] = U8TO32_LITTLE(key + 0);
+ key_u32[1] = U8TO32_LITTLE(key + 4);
+ key_u32[2] = U8TO32_LITTLE(key + 8);
+ key_u32[3] = U8TO32_LITTLE(key + 12);
+ key_u32[4] = U8TO32_LITTLE(key + 16);
+ key_u32[5] = U8TO32_LITTLE(key + 20);
+ key_u32[6] = U8TO32_LITTLE(key + 24);
+ key_u32[7] = U8TO32_LITTLE(key + 28);
+
+ key_ptr = key_u32;
+ }
+#endif
+
+ ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce);
+}
+
+#else
+
+/* sigma contains the ChaCha constants, which happen to be an ASCII string. */
+static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
+ '2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
+
+#define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
+#define XOR(v, w) ((v) ^ (w))
+#define PLUS(x, y) ((x) + (y))
+#define PLUSONE(v) (PLUS((v), 1))
+
+#define U32TO8_LITTLE(p, v) \
+ { \
+ (p)[0] = (v >> 0) & 0xff; \
+ (p)[1] = (v >> 8) & 0xff; \
+ (p)[2] = (v >> 16) & 0xff; \
+ (p)[3] = (v >> 24) & 0xff; \
+ }
+
+/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
+#define QUARTERROUND(a,b,c,d) \
+ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
+ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
+ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
+ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
+
+/* chacha_core performs 20 rounds of ChaCha on the input words in
+ * |input| and writes the 64 output bytes to |output|. */
+static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
+ uint32_t x[16];
+ int i;
+
+ memcpy(x, input, sizeof(uint32_t) * 16);
+ for (i = 20; i > 0; i -= 2) {
+ QUARTERROUND(0, 4, 8, 12)
+ QUARTERROUND(1, 5, 9, 13)
+ QUARTERROUND(2, 6, 10, 14)
+ QUARTERROUND(3, 7, 11, 15)
+ QUARTERROUND(0, 5, 10, 15)
+ QUARTERROUND(1, 6, 11, 12)
+ QUARTERROUND(2, 7, 8, 13)
+ QUARTERROUND(3, 4, 9, 14)
+ }
+
+ for (i = 0; i < 16; ++i) {
+ x[i] = PLUS(x[i], input[i]);
+ }
+ for (i = 0; i < 16; ++i) {
+ U32TO8_LITTLE(output + 4 * i, x[i]);
+ }
+}
+
+void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t key[32], const uint8_t nonce[12],
+ uint32_t counter) {
+ assert(!buffers_alias(out, in_len, in, in_len) || in == out);
+
+ uint32_t input[16];
+ uint8_t buf[64];
+ size_t todo, i;
+
+ input[0] = U8TO32_LITTLE(sigma + 0);
+ input[1] = U8TO32_LITTLE(sigma + 4);
+ input[2] = U8TO32_LITTLE(sigma + 8);
+ input[3] = U8TO32_LITTLE(sigma + 12);
+
+ input[4] = U8TO32_LITTLE(key + 0);
+ input[5] = U8TO32_LITTLE(key + 4);
+ input[6] = U8TO32_LITTLE(key + 8);
+ input[7] = U8TO32_LITTLE(key + 12);
+
+ input[8] = U8TO32_LITTLE(key + 16);
+ input[9] = U8TO32_LITTLE(key + 20);
+ input[10] = U8TO32_LITTLE(key + 24);
+ input[11] = U8TO32_LITTLE(key + 28);
+
+ input[12] = counter;
+ input[13] = U8TO32_LITTLE(nonce + 0);
+ input[14] = U8TO32_LITTLE(nonce + 4);
+ input[15] = U8TO32_LITTLE(nonce + 8);
+
+ while (in_len > 0) {
+ todo = sizeof(buf);
+ if (in_len < todo) {
+ todo = in_len;
+ }
+
+ chacha_core(buf, input);
+ for (i = 0; i < todo; i++) {
+ out[i] = in[i] ^ buf[i];
+ }
+
+ out += todo;
+ in += todo;
+ in_len -= todo;
+
+ input[12]++;
+ }
+}
+
+#endif
diff --git a/crypto/chacha/chacha_generic.c b/crypto/chacha/chacha_generic.c
deleted file mode 100644
index f262033c..00000000
--- a/crypto/chacha/chacha_generic.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* Adapted from the public domain, estream code by D. Bernstein. */
-
-#include <openssl/chacha.h>
-
-#include <string.h>
-
-#include <openssl/cpu.h>
-
-
-#if defined(OPENSSL_WINDOWS) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || !defined(__SSE2__)
-
-/* sigma contains the ChaCha constants, which happen to be an ASCII string. */
-static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
- '2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
-
-#define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
-#define XOR(v, w) ((v) ^ (w))
-#define PLUS(x, y) ((x) + (y))
-#define PLUSONE(v) (PLUS((v), 1))
-
-#define U32TO8_LITTLE(p, v) \
- { \
- (p)[0] = (v >> 0) & 0xff; \
- (p)[1] = (v >> 8) & 0xff; \
- (p)[2] = (v >> 16) & 0xff; \
- (p)[3] = (v >> 24) & 0xff; \
- }
-
-#define U8TO32_LITTLE(p) \
- (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
- ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
-
-/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
-#define QUARTERROUND(a,b,c,d) \
- x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
- x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
- x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
- x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
-
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-/* Defined in chacha_vec.c */
-void CRYPTO_chacha_20_neon(uint8_t *out, const uint8_t *in, size_t in_len,
- const uint8_t key[32], const uint8_t nonce[12],
- uint32_t counter);
-#endif
-
-/* chacha_core performs 20 rounds of ChaCha on the input words in
- * |input| and writes the 64 output bytes to |output|. */
-static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
- uint32_t x[16];
- int i;
-
- memcpy(x, input, sizeof(uint32_t) * 16);
- for (i = 20; i > 0; i -= 2) {
- QUARTERROUND(0, 4, 8, 12)
- QUARTERROUND(1, 5, 9, 13)
- QUARTERROUND(2, 6, 10, 14)
- QUARTERROUND(3, 7, 11, 15)
- QUARTERROUND(0, 5, 10, 15)
- QUARTERROUND(1, 6, 11, 12)
- QUARTERROUND(2, 7, 8, 13)
- QUARTERROUND(3, 4, 9, 14)
- }
-
- for (i = 0; i < 16; ++i) {
- x[i] = PLUS(x[i], input[i]);
- }
- for (i = 0; i < 16; ++i) {
- U32TO8_LITTLE(output + 4 * i, x[i]);
- }
-}
-
-void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
- const uint8_t key[32], const uint8_t nonce[12],
- uint32_t counter) {
- uint32_t input[16];
- uint8_t buf[64];
- size_t todo, i;
-
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_capable()) {
- CRYPTO_chacha_20_neon(out, in, in_len, key, nonce, counter);
- return;
- }
-#endif
-
- input[0] = U8TO32_LITTLE(sigma + 0);
- input[1] = U8TO32_LITTLE(sigma + 4);
- input[2] = U8TO32_LITTLE(sigma + 8);
- input[3] = U8TO32_LITTLE(sigma + 12);
-
- input[4] = U8TO32_LITTLE(key + 0);
- input[5] = U8TO32_LITTLE(key + 4);
- input[6] = U8TO32_LITTLE(key + 8);
- input[7] = U8TO32_LITTLE(key + 12);
-
- input[8] = U8TO32_LITTLE(key + 16);
- input[9] = U8TO32_LITTLE(key + 20);
- input[10] = U8TO32_LITTLE(key + 24);
- input[11] = U8TO32_LITTLE(key + 28);
-
- input[12] = counter;
- input[13] = U8TO32_LITTLE(nonce + 0);
- input[14] = U8TO32_LITTLE(nonce + 4);
- input[15] = U8TO32_LITTLE(nonce + 8);
-
- while (in_len > 0) {
- todo = sizeof(buf);
- if (in_len < todo) {
- todo = in_len;
- }
-
- chacha_core(buf, input);
- for (i = 0; i < todo; i++) {
- out[i] = in[i] ^ buf[i];
- }
-
- out += todo;
- in += todo;
- in_len -= todo;
-
- input[12]++;
- }
-}
-
-#endif /* OPENSSL_WINDOWS || !OPENSSL_X86_64 && !OPENSSL_X86 || !__SSE2__ */
diff --git a/crypto/chacha/chacha_test.cc b/crypto/chacha/chacha_test.cc
new file mode 100644
index 00000000..0a5972f7
--- /dev/null
+++ b/crypto/chacha/chacha_test.cc
@@ -0,0 +1,248 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+
+#include <openssl/crypto.h>
+#include <openssl/chacha.h>
+
+
+static const uint8_t kKey[32] = {
+ 0x98, 0xbe, 0xf1, 0x46, 0x9b, 0xe7, 0x26, 0x98, 0x37, 0xa4, 0x5b,
+ 0xfb, 0xc9, 0x2a, 0x5a, 0x6a, 0xc7, 0x62, 0x50, 0x7c, 0xf9, 0x64,
+ 0x43, 0xbf, 0x33, 0xb9, 0x6b, 0x1b, 0xd4, 0xc6, 0xf8, 0xf6,
+};
+
+static const uint8_t kNonce[12] = {
+ 0x44, 0xe7, 0x92, 0xd6, 0x33, 0x35, 0xab, 0xb1, 0x58, 0x2e, 0x92, 0x53,
+};
+
+static uint32_t kCounter = 42;
+
+static const uint8_t kInput[] = {
+ 0x58, 0x28, 0xd5, 0x30, 0x36, 0x2c, 0x60, 0x55, 0x29, 0xf8, 0xe1, 0x8c,
+ 0xae, 0x15, 0x15, 0x26, 0xf2, 0x3a, 0x73, 0xa0, 0xf3, 0x12, 0xa3, 0x88,
+ 0x5f, 0x2b, 0x74, 0x23, 0x3d, 0xc9, 0x05, 0x23, 0xc6, 0x54, 0x49, 0x1e,
+ 0x44, 0x88, 0x14, 0xd9, 0xda, 0x37, 0x15, 0xdc, 0xb7, 0xe4, 0x23, 0xb3,
+ 0x9d, 0x7e, 0x16, 0x68, 0x35, 0xfc, 0x02, 0x6d, 0xcc, 0x8a, 0xe5, 0xdd,
+ 0x5f, 0xe4, 0xd2, 0x56, 0x6f, 0x12, 0x9c, 0x9c, 0x7d, 0x6a, 0x38, 0x48,
+ 0xbd, 0xdf, 0xd9, 0xac, 0x1b, 0xa2, 0x4d, 0xc5, 0x43, 0x04, 0x3c, 0xd7,
+ 0x99, 0xe1, 0xa7, 0x13, 0x9c, 0x51, 0xc2, 0x6d, 0xf9, 0xcf, 0x07, 0x3b,
+ 0xe4, 0xbf, 0x93, 0xa3, 0xa9, 0xb4, 0xc5, 0xf0, 0x1a, 0xe4, 0x8d, 0x5f,
+ 0xc6, 0xc4, 0x7c, 0x69, 0x7a, 0xde, 0x1a, 0xc1, 0xc9, 0xcf, 0xc2, 0x4e,
+ 0x7a, 0x25, 0x2c, 0x32, 0xe9, 0x17, 0xba, 0x68, 0xf1, 0x37, 0x5d, 0x62,
+ 0x84, 0x46, 0xf5, 0x80, 0x7f, 0x1a, 0x71, 0xf7, 0xbe, 0x72, 0x4b, 0xb8,
+ 0x1c, 0xfe, 0x3e, 0xbd, 0xae, 0x0d, 0x73, 0x0d, 0x87, 0x4a, 0x31, 0xc3,
+ 0x3d, 0x46, 0x6f, 0xb3, 0xd7, 0x6b, 0xe3, 0xb8, 0x70, 0x17, 0x8e, 0x7a,
+ 0x6a, 0x0e, 0xbf, 0xa8, 0xbc, 0x2b, 0xdb, 0xfa, 0x4f, 0xb6, 0x26, 0x20,
+ 0xee, 0x63, 0xf0, 0x6d, 0x26, 0xac, 0x6a, 0x18, 0x37, 0x6e, 0x59, 0x81,
+ 0xd1, 0x60, 0xe6, 0x40, 0xd5, 0x6d, 0x68, 0xba, 0x8b, 0x65, 0x4a, 0xf9,
+ 0xf1, 0xae, 0x56, 0x24, 0x8f, 0xe3, 0x8e, 0xe7, 0x7e, 0x6f, 0xcf, 0x92,
+ 0xdf, 0xa9, 0x75, 0x3a, 0xd6, 0x2e, 0x1c, 0xaf, 0xf2, 0xd6, 0x8b, 0x39,
+ 0xad, 0xd2, 0x5d, 0xfb, 0xd7, 0xdf, 0x05, 0x57, 0x0d, 0xf7, 0xf6, 0x8f,
+ 0x2d, 0x14, 0xb0, 0x4e, 0x1a, 0x3c, 0x77, 0x04, 0xcd, 0x3c, 0x5c, 0x58,
+ 0x52, 0x10, 0x6f, 0xcf, 0x5c, 0x03, 0xc8, 0x5f, 0x85, 0x2b, 0x05, 0x82,
+ 0x60, 0xda, 0xcc, 0xcd, 0xd6, 0x88, 0xbf, 0xc0, 0x10, 0xb3, 0x6f, 0x54,
+ 0x54, 0x42, 0xbc, 0x4b, 0x77, 0x21, 0x4d, 0xee, 0x87, 0x45, 0x06, 0x4c,
+ 0x60, 0x38, 0xd2, 0x7e, 0x1d, 0x30, 0x6c, 0x55, 0xf0, 0x38, 0x80, 0x1c,
+ 0xde, 0x3d, 0xea, 0x68, 0x3e, 0xf6, 0x3e, 0x59, 0xcf, 0x0d, 0x08, 0xae,
+ 0x8c, 0x02, 0x0b, 0xc1, 0x72, 0x6a, 0xb4, 0x6d, 0xf3, 0xf7, 0xb3, 0xef,
+ 0x3a, 0xb1, 0x06, 0xf2, 0xf4, 0xd6, 0x69, 0x7b, 0x3e, 0xa2, 0x16, 0x31,
+ 0x31, 0x79, 0xb6, 0x33, 0xa9, 0xca, 0x8a, 0xa8, 0xbe, 0xf3, 0xe9, 0x38,
+ 0x28, 0xd1, 0xe1, 0x3b, 0x4e, 0x2e, 0x47, 0x35, 0xa4, 0x61, 0x14, 0x1e,
+ 0x42, 0x2c, 0x49, 0x55, 0xea, 0xe3, 0xb3, 0xce, 0x39, 0xd3, 0xb3, 0xef,
+ 0x4a, 0x4d, 0x78, 0x49, 0xbd, 0xf6, 0x7c, 0x0a, 0x2c, 0xd3, 0x26, 0xcb,
+ 0xd9, 0x6a, 0xad, 0x63, 0x93, 0xa7, 0x29, 0x92, 0xdc, 0x1f, 0xaf, 0x61,
+ 0x82, 0x80, 0x74, 0xb2, 0x9c, 0x4a, 0x86, 0x73, 0x50, 0xd8, 0xd1, 0xff,
+ 0xee, 0x1a, 0xe2, 0xdd, 0xa2, 0x61, 0xbd, 0x10, 0xc3, 0x5f, 0x67, 0x9f,
+ 0x29, 0xe4, 0xd3, 0x70, 0xe5, 0x67, 0x3a, 0xd2, 0x20, 0x00, 0xcc, 0x25,
+ 0x15, 0x96, 0x54, 0x45, 0x85, 0xed, 0x82, 0x88, 0x3b, 0x9f, 0x3b, 0xc3,
+ 0x04, 0xd4, 0x23, 0xb1, 0x0d, 0xdc, 0xc8, 0x26, 0x9d, 0x28, 0xb3, 0x25,
+ 0x4d, 0x52, 0xe5, 0x33, 0xf3, 0xed, 0x2c, 0xb8, 0x1a, 0xcf, 0xc3, 0x52,
+ 0xb4, 0x2f, 0xc7, 0x79, 0x96, 0x14, 0x7d, 0x72, 0x27, 0x72, 0x85, 0xea,
+ 0x6d, 0x41, 0xa0, 0x22, 0x13, 0x6d, 0x06, 0x83, 0xa4, 0xdd, 0x0f, 0x69,
+ 0xd2, 0x01, 0xcd, 0xc6, 0xb8, 0x64, 0x5c, 0x2c, 0x79, 0xd1, 0xc7, 0xd3,
+ 0x31, 0xdb, 0x2c, 0xff, 0xda, 0xd0, 0x69, 0x31, 0xad, 0x83, 0x5f, 0xed,
+ 0x6a, 0x97, 0xe4, 0x00, 0x43, 0xb0, 0x2e, 0x97, 0xae, 0x00, 0x5f, 0x5c,
+ 0xb9, 0xe8, 0x39, 0x80, 0x10, 0xca, 0x0c, 0xfa, 0xf0, 0xb5, 0xcd, 0xaa,
+ 0x27, 0x11, 0x60, 0xd9, 0x21, 0x86, 0x93, 0x91, 0x9f, 0x2d, 0x1a, 0x8e,
+ 0xde, 0x0b, 0xb5, 0xcb, 0x05, 0x24, 0x30, 0x45, 0x4d, 0x11, 0x75, 0xfd,
+ 0xe5, 0xa0, 0xa9, 0x4e, 0x3a, 0x8c, 0x3b, 0x52, 0x5a, 0x37, 0x18, 0x05,
+ 0x4a, 0x7a, 0x09, 0x6a, 0xe6, 0xd5, 0xa9, 0xa6, 0x71, 0x47, 0x4c, 0x50,
+ 0xe1, 0x3e, 0x8a, 0x21, 0x2b, 0x4f, 0x0e, 0xe3, 0xcb, 0x72, 0xc5, 0x28,
+ 0x3e, 0x5a, 0x33, 0xec, 0x48, 0x92, 0x2e, 0xa1, 0x24, 0x57, 0x09, 0x0f,
+ 0x01, 0x85, 0x3b, 0x34, 0x39, 0x7e, 0xc7, 0x90, 0x62, 0xe2, 0xdc, 0x5d,
+ 0x0a, 0x2c, 0x51, 0x26, 0x95, 0x3a, 0x95, 0x92, 0xa5, 0x39, 0x8f, 0x0c,
+ 0x83, 0x0b, 0x9d, 0x38, 0xab, 0x98, 0x2a, 0xc4, 0x01, 0xc4, 0x0d, 0x77,
+ 0x13, 0xcb, 0xca, 0xf1, 0x28, 0x31, 0x52, 0x75, 0x27, 0x2c, 0xf0, 0x04,
+ 0x86, 0xc8, 0xf3, 0x3d, 0xf2, 0x9d, 0x8f, 0x55, 0x52, 0x40, 0x3f, 0xaa,
+ 0x22, 0x7f, 0xe7, 0x69, 0x3b, 0xee, 0x44, 0x09, 0xde, 0xff, 0xb0, 0x69,
+ 0x3a, 0xae, 0x74, 0xe9, 0x9d, 0x33, 0xae, 0x8b, 0x6d, 0x60, 0x04, 0xff,
+ 0x53, 0x3f, 0x88, 0xe9, 0x63, 0x9b, 0xb1, 0x6d, 0x2c, 0x22, 0x15, 0x5a,
+ 0x15, 0xd9, 0xe5, 0xcb, 0x03, 0x78, 0x3c, 0xca, 0x59, 0x8c, 0xc8, 0xc2,
+ 0x86, 0xff, 0xd2, 0x79, 0xd6, 0xc6, 0xec, 0x5b, 0xbb, 0xa0, 0xae, 0x01,
+ 0x20, 0x09, 0x2e, 0x38, 0x5d, 0xda, 0x5d, 0xe0, 0x59, 0x4e, 0xe5, 0x8b,
+ 0x84, 0x8f, 0xb6, 0xe0, 0x56, 0x9f, 0x21, 0xa1, 0xcf, 0xb2, 0x0f, 0x2c,
+ 0x93, 0xf8, 0xcf, 0x37, 0xc1, 0x9f, 0x32, 0x98, 0x21, 0x65, 0x52, 0x66,
+ 0x6e, 0xd3, 0x71, 0x98, 0x55, 0xb9, 0x46, 0x9f, 0x1a, 0x35, 0xc4, 0x47,
+ 0x69, 0x62, 0x70, 0x4b, 0x77, 0x9e, 0xe4, 0x21, 0xe6, 0x32, 0x5a, 0x26,
+ 0x05, 0xba, 0x57, 0x53, 0xd7, 0x9b, 0x55, 0x3c, 0xbb, 0x53, 0x79, 0x60,
+ 0x9c, 0xc8, 0x4d, 0xf7, 0xf5, 0x1d, 0x54, 0x02, 0x91, 0x68, 0x0e, 0xaa,
+ 0xca, 0x5a, 0x78, 0x0c, 0x28, 0x9a, 0xc3, 0xac, 0x49, 0xc0, 0xf4, 0x85,
+ 0xee, 0x59, 0x76, 0x7e, 0x28, 0x4e, 0xf1, 0x5c, 0x63, 0xf7, 0xce, 0x0e,
+ 0x2c, 0x21, 0xa0, 0x58, 0xe9, 0x01, 0xfd, 0xeb, 0xd1, 0xaf, 0xe6, 0xef,
+ 0x93, 0xb3, 0x95, 0x51, 0x60, 0xa2, 0x74, 0x40, 0x15, 0xe5, 0xf4, 0x0a,
+ 0xca, 0x6d, 0x9a, 0x37, 0x42, 0x4d, 0x5a, 0x58, 0x49, 0x0f, 0xe9, 0x02,
+ 0xfc, 0x77, 0xd8, 0x59, 0xde, 0xdd, 0xad, 0x4b, 0x99, 0x2e, 0x64, 0x73,
+ 0xad, 0x42, 0x2f, 0xf3, 0x2c, 0x0d, 0x49, 0xe4, 0x2e, 0x6c, 0xa4, 0x73,
+ 0x75, 0x18, 0x14, 0x85, 0xbb, 0x64, 0xb4, 0xa1, 0xb0, 0x6e, 0x01, 0xc0,
+ 0xcf, 0x17, 0x9c, 0xc5, 0x28, 0xc3, 0x2d, 0x6c, 0x17, 0x2a, 0x3d, 0x06,
+ 0x5c, 0xf3, 0xb4, 0x49, 0x75, 0xad, 0x17, 0x69, 0xd4, 0xca, 0x65, 0xae,
+ 0x44, 0x71, 0xa5, 0xf6, 0x0d, 0x0f, 0x8e, 0x37, 0xc7, 0x43, 0xce, 0x6b,
+ 0x08, 0xe9, 0xd1, 0x34, 0x48, 0x8f, 0xc9, 0xfc, 0xf3, 0x5d, 0x2d, 0xec,
+ 0x62, 0xd3, 0xf0, 0xb3, 0xfe, 0x2e, 0x40, 0x55, 0x76, 0x54, 0xc7, 0xb4,
+ 0x61, 0x16, 0xcc, 0x7c, 0x1c, 0x19, 0x24, 0xe6, 0x4d, 0xd4, 0xc3, 0x77,
+ 0x67, 0x1f, 0x3c, 0x74, 0x79, 0xa1, 0xf8, 0x85, 0x88, 0x1d, 0x6f, 0xa4,
+ 0x7e, 0x2c, 0x21, 0x9f, 0x49, 0xf5, 0xaa, 0x4e, 0xf3, 0x4a, 0xfa, 0x9d,
+ 0xbe, 0xf6, 0xce, 0xda, 0xb5, 0xab, 0x39, 0xbd, 0x16, 0x41, 0xa9, 0x4a,
+ 0xac, 0x09, 0x01, 0xca,
+};
+static const uint8_t kOutput[] = {
+ 0x54, 0x30, 0x6a, 0x13, 0xda, 0x59, 0x6b, 0x6d, 0x59, 0x49, 0xc8, 0xc5,
+ 0xab, 0x26, 0xd4, 0x8a, 0xad, 0xc0, 0x3d, 0xaf, 0x14, 0xb9, 0x15, 0xb8,
+ 0xca, 0xdf, 0x17, 0xa7, 0x03, 0xd3, 0xc5, 0x06, 0x01, 0xef, 0x21, 0xdd,
+ 0xa3, 0x0b, 0x9e, 0x48, 0xb8, 0x5e, 0x0b, 0x87, 0x9f, 0x95, 0x23, 0x68,
+ 0x85, 0x69, 0xd2, 0x5d, 0xaf, 0x57, 0xe9, 0x27, 0x11, 0x3d, 0x49, 0xfa,
+ 0xf1, 0x08, 0xcc, 0x15, 0xec, 0x1d, 0x19, 0x16, 0x12, 0x9b, 0xc8, 0x66,
+ 0x1f, 0xfa, 0x2c, 0x93, 0xf4, 0x99, 0x11, 0x27, 0x31, 0x0e, 0xd8, 0x46,
+ 0x47, 0x40, 0x11, 0x70, 0x01, 0xca, 0xe8, 0x5b, 0xc5, 0x91, 0xc8, 0x3a,
+ 0xdc, 0xaa, 0xf3, 0x4b, 0x80, 0xe5, 0xbc, 0x03, 0xd0, 0x89, 0x72, 0xbc,
+ 0xce, 0x2a, 0x76, 0x0c, 0xf5, 0xda, 0x4c, 0x10, 0x06, 0x35, 0x41, 0xb1,
+ 0xe6, 0xb4, 0xaa, 0x7a, 0xef, 0xf0, 0x62, 0x4a, 0xc5, 0x9f, 0x2c, 0xaf,
+ 0xb8, 0x2f, 0xd9, 0xd1, 0x01, 0x7a, 0x36, 0x2f, 0x3e, 0x83, 0xa5, 0xeb,
+ 0x81, 0x70, 0xa0, 0x57, 0x17, 0x46, 0xea, 0x9e, 0xcb, 0x0e, 0x74, 0xd3,
+ 0x44, 0x57, 0x1d, 0x40, 0x06, 0xf8, 0xb7, 0xcb, 0x5f, 0xf4, 0x79, 0xbd,
+ 0x11, 0x19, 0xd6, 0xee, 0xf8, 0xb0, 0xaa, 0xdd, 0x00, 0x62, 0xad, 0x3b,
+ 0x88, 0x9a, 0x88, 0x5b, 0x1b, 0x07, 0xc9, 0xae, 0x9e, 0xa6, 0x94, 0xe5,
+ 0x55, 0xdb, 0x45, 0x23, 0xb9, 0x2c, 0xcd, 0x29, 0xd3, 0x54, 0xc3, 0x88,
+ 0x1e, 0x5f, 0x52, 0xf2, 0x09, 0x00, 0x26, 0x26, 0x1a, 0xed, 0xf5, 0xc2,
+ 0xa9, 0x7d, 0xf9, 0x21, 0x5a, 0xaf, 0x6d, 0xab, 0x8e, 0x16, 0x84, 0x96,
+ 0xb5, 0x4f, 0xcf, 0x1e, 0xa3, 0xaf, 0x08, 0x9f, 0x79, 0x86, 0xc3, 0xbe,
+ 0x0c, 0x70, 0xcb, 0x8f, 0xf3, 0xc5, 0xf8, 0xe8, 0x4b, 0x21, 0x7d, 0x18,
+ 0xa9, 0xed, 0x8b, 0xfb, 0x6b, 0x5a, 0x6f, 0x26, 0x0b, 0x56, 0x04, 0x7c,
+ 0xfe, 0x0e, 0x1e, 0xc1, 0x3f, 0x82, 0xc5, 0x73, 0xbd, 0x53, 0x0c, 0xf0,
+ 0xe2, 0xc9, 0xf3, 0x3d, 0x1b, 0x6d, 0xba, 0x70, 0xc1, 0x6d, 0xb6, 0x00,
+ 0x28, 0xe1, 0xc4, 0x78, 0x62, 0x04, 0xda, 0x23, 0x86, 0xc3, 0xda, 0x74,
+ 0x3d, 0x7c, 0xd6, 0x76, 0x29, 0xb2, 0x27, 0x2e, 0xb2, 0x35, 0x42, 0x60,
+ 0x82, 0xcf, 0x30, 0x2c, 0x59, 0xe4, 0xe3, 0xd0, 0x74, 0x1f, 0x58, 0xe8,
+ 0xda, 0x47, 0x45, 0x73, 0x1c, 0x05, 0x93, 0xae, 0x75, 0xbe, 0x1f, 0x81,
+ 0xd8, 0xb7, 0xb3, 0xff, 0xfc, 0x8b, 0x52, 0x9e, 0xed, 0x8b, 0x37, 0x9f,
+ 0xe0, 0xb8, 0xa2, 0x66, 0xe1, 0x6a, 0xc5, 0x1f, 0x1d, 0xf0, 0xde, 0x3f,
+ 0x3d, 0xb0, 0x28, 0xf3, 0xaa, 0x4e, 0x4d, 0x31, 0xb0, 0x26, 0x79, 0x2b,
+ 0x08, 0x0f, 0xe9, 0x2f, 0x79, 0xb3, 0xc8, 0xdd, 0xa7, 0x89, 0xa8, 0xa8,
+ 0x1d, 0x59, 0x0e, 0x4f, 0x1e, 0x93, 0x1f, 0x70, 0x7f, 0x4e, 0x7e, 0xfe,
+ 0xb8, 0xca, 0x63, 0xe0, 0xa6, 0x05, 0xcc, 0xd7, 0xde, 0x2a, 0x49, 0x31,
+ 0x78, 0x5c, 0x5f, 0x44, 0xb2, 0x9b, 0x91, 0x99, 0x14, 0x29, 0x63, 0x09,
+ 0x12, 0xdd, 0x02, 0xd9, 0x7b, 0xe9, 0xf5, 0x12, 0x07, 0xd0, 0xe7, 0xe6,
+ 0xe8, 0xdd, 0xda, 0xa4, 0x73, 0xc4, 0x8e, 0xbd, 0x7b, 0xb7, 0xbb, 0xcb,
+ 0x83, 0x2f, 0x43, 0xf6, 0x1c, 0x50, 0xae, 0x9b, 0x2e, 0x52, 0x80, 0x18,
+ 0x85, 0xa8, 0x23, 0x52, 0x7a, 0x6a, 0xf7, 0x42, 0x36, 0xca, 0x91, 0x5a,
+ 0x3d, 0x2a, 0xa0, 0x35, 0x7d, 0x70, 0xfc, 0x4c, 0x18, 0x7c, 0x57, 0x72,
+ 0xcf, 0x9b, 0x29, 0xd6, 0xd0, 0xb4, 0xd7, 0xe6, 0x89, 0x70, 0x69, 0x22,
+ 0x5e, 0x45, 0x09, 0x4d, 0x49, 0x87, 0x84, 0x5f, 0x8a, 0x5f, 0xe4, 0x15,
+ 0xd3, 0xe3, 0x72, 0xaf, 0xb2, 0x30, 0x9c, 0xc1, 0xff, 0x8e, 0x6d, 0x2a,
+ 0x76, 0x9e, 0x08, 0x03, 0x7e, 0xe0, 0xc3, 0xc2, 0x97, 0x06, 0x6b, 0x33,
+ 0x2b, 0x08, 0xe3, 0xd5, 0x0b, 0xd8, 0x32, 0x67, 0x61, 0x10, 0xed, 0x6b,
+ 0xed, 0x50, 0xef, 0xd7, 0x1c, 0x1b, 0xe0, 0x6d, 0xa1, 0x64, 0x19, 0x34,
+ 0x2f, 0xe4, 0xe8, 0x54, 0xbf, 0x84, 0x0e, 0xdf, 0x0e, 0x8b, 0xd8, 0xdd,
+ 0x77, 0x96, 0xb8, 0x54, 0xab, 0xf2, 0x95, 0x59, 0x0d, 0x0d, 0x0a, 0x15,
+ 0x6e, 0x01, 0xf2, 0x24, 0xab, 0xa0, 0xd8, 0xdf, 0x38, 0xea, 0x97, 0x58,
+ 0x76, 0x88, 0xbe, 0xaf, 0x45, 0xe3, 0x56, 0x4f, 0x68, 0xe8, 0x4b, 0xe7,
+ 0x2b, 0x22, 0x18, 0x96, 0x82, 0x89, 0x25, 0x34, 0xd1, 0xdd, 0x08, 0xea,
+ 0x7e, 0x21, 0xef, 0x57, 0x55, 0x43, 0xf7, 0xfa, 0xca, 0x1c, 0xde, 0x99,
+ 0x2e, 0x8b, 0xd8, 0xc3, 0xcf, 0x89, 0x4d, 0xfc, 0x3b, 0x7d, 0x4a, 0xc9,
+ 0x99, 0xc4, 0x31, 0xb6, 0x7a, 0xae, 0xf8, 0x49, 0xb2, 0x46, 0xc1, 0x60,
+ 0x05, 0x75, 0xf3, 0x3d, 0xf2, 0xc9, 0x84, 0xa4, 0xb9, 0x8a, 0x87, 0x2a,
+ 0x87, 0x5c, 0x0a, 0xbc, 0x51, 0x7d, 0x9a, 0xf5, 0xc9, 0x24, 0x2d, 0x5e,
+ 0xe6, 0xc6, 0xe3, 0xcd, 0x7e, 0xe4, 0xaf, 0x8a, 0x6c, 0x00, 0x04, 0xc8,
+ 0xd7, 0xa5, 0xad, 0xfa, 0xb2, 0x08, 0x4a, 0x26, 0x9b, 0x7c, 0xd0, 0xc6,
+ 0x13, 0xb1, 0xb9, 0x65, 0x3f, 0x70, 0x30, 0xf9, 0x98, 0x9d, 0x87, 0x99,
+ 0x57, 0x71, 0x3e, 0xb1, 0xc3, 0x24, 0xf0, 0xa6, 0xa2, 0x60, 0x9d, 0x66,
+ 0xd2, 0x5f, 0xae, 0xe3, 0x94, 0x87, 0xea, 0xd1, 0xea, 0x0d, 0x2a, 0x77,
+ 0xef, 0x31, 0xcc, 0xeb, 0xf9, 0x0c, 0xdc, 0x9c, 0x12, 0x80, 0xbb, 0xb0,
+ 0x8e, 0xab, 0x9a, 0x04, 0xcd, 0x4b, 0x95, 0x4f, 0x7a, 0x0b, 0x53, 0x7c,
+ 0x16, 0xcc, 0x0e, 0xb1, 0x73, 0x10, 0xdd, 0xaa, 0x76, 0x94, 0x90, 0xd9,
+ 0x8b, 0x66, 0x41, 0x31, 0xed, 0x8c, 0x7d, 0x74, 0xc4, 0x33, 0xfa, 0xc3,
+ 0x43, 0x8d, 0x10, 0xbc, 0x84, 0x4d, 0x0e, 0x95, 0x32, 0xdf, 0x17, 0x43,
+ 0x6d, 0xd2, 0x5e, 0x12, 0xb9, 0xed, 0x33, 0xd9, 0x97, 0x6f, 0x4a, 0xcd,
+ 0xc3, 0xcd, 0x81, 0x34, 0xbe, 0x7e, 0xa2, 0xd0, 0xa7, 0x91, 0x5d, 0x90,
+ 0xf6, 0x5e, 0x4a, 0x25, 0x0f, 0xcc, 0x24, 0xeb, 0xe1, 0xe4, 0x62, 0x6c,
+ 0x8f, 0x45, 0x36, 0x97, 0x5d, 0xda, 0x20, 0x2b, 0x86, 0x00, 0x8c, 0x94,
+ 0xa9, 0x6a, 0x69, 0xb2, 0xe9, 0xbb, 0x82, 0x8e, 0x41, 0x95, 0xb4, 0xb7,
+ 0xf1, 0x55, 0x52, 0x30, 0x39, 0x48, 0xb3, 0x25, 0x82, 0xa9, 0x10, 0x27,
+ 0x89, 0xb5, 0xe5, 0x1f, 0xab, 0x72, 0x3c, 0x70, 0x08, 0xce, 0xe6, 0x61,
+ 0xbf, 0x19, 0xc8, 0x90, 0x2b, 0x29, 0x30, 0x3e, 0xb8, 0x4c, 0x33, 0xf0,
+ 0xf0, 0x15, 0x2e, 0xb7, 0x25, 0xca, 0x99, 0x4b, 0x6f, 0x4b, 0x41, 0x50,
+ 0xee, 0x56, 0x99, 0xcf, 0x2b, 0xa4, 0xc4, 0x7c, 0x5c, 0xa6, 0xd4, 0x67,
+ 0x04, 0x5c, 0x5d, 0x5f, 0x26, 0x9e, 0x0f, 0xe2, 0x58, 0x68, 0x4c, 0x30,
+ 0xcd, 0xef, 0x46, 0xdb, 0x37, 0x6f, 0xbb, 0xc4, 0x80, 0xca, 0x8a, 0x54,
+ 0x5d, 0x71, 0x9d, 0x0c, 0xe8, 0xb8, 0x2c, 0x10, 0x90, 0x44, 0xa4, 0x88,
+ 0x3f, 0xbc, 0x15, 0x3c, 0xd2, 0xca, 0x0e, 0xc3, 0xe4, 0x6e, 0xef, 0xb0,
+ 0xcb, 0xfd, 0x61, 0x7c, 0x27, 0xf2, 0x25, 0xea, 0x71, 0x6d, 0xf7, 0x49,
+ 0x9c, 0x81, 0x27, 0xf0, 0x61, 0x33, 0xcf, 0x55, 0x68, 0xd3, 0x73, 0xa4,
+ 0xed, 0x35, 0x65, 0x2a, 0xf2, 0x3e, 0xcf, 0x90, 0x98, 0x54, 0x6d, 0x95,
+ 0x6a, 0x0c, 0x9c, 0x24, 0x0e, 0xb4, 0xb7, 0x9b, 0x8d, 0x6e, 0x1c, 0xbc,
+ 0xeb, 0x17, 0x10, 0x86, 0xda, 0x91, 0x6d, 0x89, 0x4c, 0xeb, 0xf5, 0x50,
+ 0x8f, 0x40, 0xcf, 0x4a,
+};
+
+static_assert(sizeof(kInput) == sizeof(kOutput),
+ "Input and output lengths don't match.");
+
+static bool TestChaCha20(size_t len) {
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
+ CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter);
+ if (memcmp(buf.get(), kOutput, len) != 0) {
+ fprintf(stderr, "Mismatch at length %zu.\n", len);
+ return false;
+ }
+
+ // Test in-place.
+ memcpy(buf.get(), kInput, len);
+ CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter);
+ if (memcmp(buf.get(), kOutput, len) != 0) {
+ fprintf(stderr, "Mismatch at length %zu, in-place.\n", len);
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ // Run the test with the test vector at all lengths.
+ for (size_t len = 0; len <= sizeof(kInput); len++) {
+ if (!TestChaCha20(len)) {
+ return 1;
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/crypto/chacha/chacha_vec.c b/crypto/chacha/chacha_vec.c
deleted file mode 100644
index 90d62002..00000000
--- a/crypto/chacha/chacha_vec.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* ====================================================================
- *
- * When updating this file, also update chacha_vec_arm.S
- *
- * ==================================================================== */
-
-
-/* This implementation is by Ted Krovetz and was submitted to SUPERCOP and
- * marked as public domain. It was been altered to allow for non-aligned inputs
- * and to allow the block counter to be passed in specifically. */
-
-#include <openssl/chacha.h>
-
-#include "../internal.h"
-
-
-#if defined(ASM_GEN) || \
- !defined(OPENSSL_WINDOWS) && \
- (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) && defined(__SSE2__)
-
-#define CHACHA_RNDS 20 /* 8 (high speed), 20 (conservative), 12 (middle) */
-
-/* Architecture-neutral way to specify 16-byte vector of ints */
-typedef unsigned vec __attribute__((vector_size(16)));
-
-/* This implementation is designed for Neon, SSE and AltiVec machines. The
- * following specify how to do certain vector operations efficiently on
- * each architecture, using intrinsics.
- * This implementation supports parallel processing of multiple blocks,
- * including potentially using general-purpose registers. */
-#if __ARM_NEON__
-#include <string.h>
-#include <arm_neon.h>
-#define GPR_TOO 1
-#define VBPI 2
-#define ONE (vec) vsetq_lane_u32(1, vdupq_n_u32(0), 0)
-#define LOAD_ALIGNED(m) (vec)(*((vec *)(m)))
-#define LOAD(m) ({ \
- memcpy(alignment_buffer, m, 16); \
- LOAD_ALIGNED(alignment_buffer); \
- })
-#define STORE(m, r) ({ \
- (*((vec *)(alignment_buffer))) = (r); \
- memcpy(m, alignment_buffer, 16); \
- })
-#define ROTV1(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 1)
-#define ROTV2(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 2)
-#define ROTV3(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 3)
-#define ROTW16(x) (vec) vrev32q_u16((uint16x8_t)x)
-#if __clang__
-#define ROTW7(x) (x << ((vec) {7, 7, 7, 7})) ^ (x >> ((vec) {25, 25, 25, 25}))
-#define ROTW8(x) (x << ((vec) {8, 8, 8, 8})) ^ (x >> ((vec) {24, 24, 24, 24}))
-#define ROTW12(x) \
- (x << ((vec) {12, 12, 12, 12})) ^ (x >> ((vec) {20, 20, 20, 20}))
-#else
-#define ROTW7(x) \
- (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 7), (uint32x4_t)x, 25)
-#define ROTW8(x) \
- (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 8), (uint32x4_t)x, 24)
-#define ROTW12(x) \
- (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 12), (uint32x4_t)x, 20)
-#endif
-#elif __SSE2__
-#include <emmintrin.h>
-#define GPR_TOO 0
-#if __clang__
-#define VBPI 4
-#else
-#define VBPI 3
-#endif
-#define ONE (vec) _mm_set_epi32(0, 0, 0, 1)
-#define LOAD(m) (vec) _mm_loadu_si128((const __m128i *)(m))
-#define LOAD_ALIGNED(m) (vec) _mm_load_si128((const __m128i *)(m))
-#define STORE(m, r) _mm_storeu_si128((__m128i *)(m), (__m128i)(r))
-#define ROTV1(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(0, 3, 2, 1))
-#define ROTV2(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(1, 0, 3, 2))
-#define ROTV3(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(2, 1, 0, 3))
-#define ROTW7(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 7) ^ _mm_srli_epi32((__m128i)x, 25))
-#define ROTW12(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 12) ^ _mm_srli_epi32((__m128i)x, 20))
-#if __SSSE3__
-#include <tmmintrin.h>
-#define ROTW8(x) \
- (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, \
- 11, 6, 5, 4, 7, 2, 1, 0, 3))
-#define ROTW16(x) \
- (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, \
- 10, 5, 4, 7, 6, 1, 0, 3, 2))
-#else
-#define ROTW8(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 8) ^ _mm_srli_epi32((__m128i)x, 24))
-#define ROTW16(x) \
- (vec)(_mm_slli_epi32((__m128i)x, 16) ^ _mm_srli_epi32((__m128i)x, 16))
-#endif
-#else
-#error-- Implementation supports only machines with neon or SSE2
-#endif
-
-#ifndef REVV_BE
-#define REVV_BE(x) (x)
-#endif
-
-#ifndef REVW_BE
-#define REVW_BE(x) (x)
-#endif
-
-#define BPI (VBPI + GPR_TOO) /* Blocks computed per loop iteration */
-
-#define DQROUND_VECTORS(a,b,c,d) \
- a += b; d ^= a; d = ROTW16(d); \
- c += d; b ^= c; b = ROTW12(b); \
- a += b; d ^= a; d = ROTW8(d); \
- c += d; b ^= c; b = ROTW7(b); \
- b = ROTV1(b); c = ROTV2(c); d = ROTV3(d); \
- a += b; d ^= a; d = ROTW16(d); \
- c += d; b ^= c; b = ROTW12(b); \
- a += b; d ^= a; d = ROTW8(d); \
- c += d; b ^= c; b = ROTW7(b); \
- b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
-
-#define QROUND_WORDS(a,b,c,d) \
- a = a+b; d ^= a; d = d<<16 | d>>16; \
- c = c+d; b ^= c; b = b<<12 | b>>20; \
- a = a+b; d ^= a; d = d<< 8 | d>>24; \
- c = c+d; b ^= c; b = b<< 7 | b>>25;
-
-#define WRITE_XOR(in, op, d, v0, v1, v2, v3) \
- STORE(op + d + 0, LOAD(in + d + 0) ^ REVV_BE(v0)); \
- STORE(op + d + 4, LOAD(in + d + 4) ^ REVV_BE(v1)); \
- STORE(op + d + 8, LOAD(in + d + 8) ^ REVV_BE(v2)); \
- STORE(op + d +12, LOAD(in + d +12) ^ REVV_BE(v3));
-
-#if __ARM_NEON__
-/* For ARM, we can't depend on NEON support, so this function is compiled with
- * a different name, along with the generic code, and can be enabled at
- * run-time. */
-void CRYPTO_chacha_20_neon(
-#else
-void CRYPTO_chacha_20(
-#endif
- uint8_t *out,
- const uint8_t *in,
- size_t inlen,
- const uint8_t key[32],
- const uint8_t nonce[12],
- uint32_t counter)
- {
- unsigned iters, i;
- unsigned *op = (unsigned *)out;
- const unsigned *ip = (const unsigned *)in;
- const unsigned *kp = (const unsigned *)key;
-#if defined(__ARM_NEON__)
- uint32_t np[3];
- alignas(16) uint8_t alignment_buffer[16];
-#endif
- vec s0, s1, s2, s3;
- alignas(16) unsigned chacha_const[] =
- {0x61707865,0x3320646E,0x79622D32,0x6B206574};
-#if defined(__ARM_NEON__)
- memcpy(np, nonce, 12);
-#endif
- s0 = LOAD_ALIGNED(chacha_const);
- s1 = LOAD(&((const vec*)kp)[0]);
- s2 = LOAD(&((const vec*)kp)[1]);
- s3 = (vec){
- counter,
- ((const uint32_t*)nonce)[0],
- ((const uint32_t*)nonce)[1],
- ((const uint32_t*)nonce)[2]
- };
-
- for (iters = 0; iters < inlen/(BPI*64); iters++)
- {
-#if GPR_TOO
- register unsigned x0, x1, x2, x3, x4, x5, x6, x7, x8,
- x9, x10, x11, x12, x13, x14, x15;
-#endif
-#if VBPI > 2
- vec v8,v9,v10,v11;
-#endif
-#if VBPI > 3
- vec v12,v13,v14,v15;
-#endif
-
- vec v0,v1,v2,v3,v4,v5,v6,v7;
- v4 = v0 = s0; v5 = v1 = s1; v6 = v2 = s2; v3 = s3;
- v7 = v3 + ONE;
-#if VBPI > 2
- v8 = v4; v9 = v5; v10 = v6;
- v11 = v7 + ONE;
-#endif
-#if VBPI > 3
- v12 = v8; v13 = v9; v14 = v10;
- v15 = v11 + ONE;
-#endif
-#if GPR_TOO
- x0 = chacha_const[0]; x1 = chacha_const[1];
- x2 = chacha_const[2]; x3 = chacha_const[3];
- x4 = kp[0]; x5 = kp[1]; x6 = kp[2]; x7 = kp[3];
- x8 = kp[4]; x9 = kp[5]; x10 = kp[6]; x11 = kp[7];
- x12 = counter+BPI*iters+(BPI-1); x13 = np[0];
- x14 = np[1]; x15 = np[2];
-#endif
- for (i = CHACHA_RNDS/2; i; i--)
- {
- DQROUND_VECTORS(v0,v1,v2,v3)
- DQROUND_VECTORS(v4,v5,v6,v7)
-#if VBPI > 2
- DQROUND_VECTORS(v8,v9,v10,v11)
-#endif
-#if VBPI > 3
- DQROUND_VECTORS(v12,v13,v14,v15)
-#endif
-#if GPR_TOO
- QROUND_WORDS( x0, x4, x8,x12)
- QROUND_WORDS( x1, x5, x9,x13)
- QROUND_WORDS( x2, x6,x10,x14)
- QROUND_WORDS( x3, x7,x11,x15)
- QROUND_WORDS( x0, x5,x10,x15)
- QROUND_WORDS( x1, x6,x11,x12)
- QROUND_WORDS( x2, x7, x8,x13)
- QROUND_WORDS( x3, x4, x9,x14)
-#endif
- }
-
- WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
- s3 += ONE;
- WRITE_XOR(ip, op, 16, v4+s0, v5+s1, v6+s2, v7+s3)
- s3 += ONE;
-#if VBPI > 2
- WRITE_XOR(ip, op, 32, v8+s0, v9+s1, v10+s2, v11+s3)
- s3 += ONE;
-#endif
-#if VBPI > 3
- WRITE_XOR(ip, op, 48, v12+s0, v13+s1, v14+s2, v15+s3)
- s3 += ONE;
-#endif
- ip += VBPI*16;
- op += VBPI*16;
-#if GPR_TOO
- op[0] = REVW_BE(REVW_BE(ip[0]) ^ (x0 + chacha_const[0]));
- op[1] = REVW_BE(REVW_BE(ip[1]) ^ (x1 + chacha_const[1]));
- op[2] = REVW_BE(REVW_BE(ip[2]) ^ (x2 + chacha_const[2]));
- op[3] = REVW_BE(REVW_BE(ip[3]) ^ (x3 + chacha_const[3]));
- op[4] = REVW_BE(REVW_BE(ip[4]) ^ (x4 + kp[0]));
- op[5] = REVW_BE(REVW_BE(ip[5]) ^ (x5 + kp[1]));
- op[6] = REVW_BE(REVW_BE(ip[6]) ^ (x6 + kp[2]));
- op[7] = REVW_BE(REVW_BE(ip[7]) ^ (x7 + kp[3]));
- op[8] = REVW_BE(REVW_BE(ip[8]) ^ (x8 + kp[4]));
- op[9] = REVW_BE(REVW_BE(ip[9]) ^ (x9 + kp[5]));
- op[10] = REVW_BE(REVW_BE(ip[10]) ^ (x10 + kp[6]));
- op[11] = REVW_BE(REVW_BE(ip[11]) ^ (x11 + kp[7]));
- op[12] = REVW_BE(REVW_BE(ip[12]) ^ (x12 + counter+BPI*iters+(BPI-1)));
- op[13] = REVW_BE(REVW_BE(ip[13]) ^ (x13 + np[0]));
- op[14] = REVW_BE(REVW_BE(ip[14]) ^ (x14 + np[1]));
- op[15] = REVW_BE(REVW_BE(ip[15]) ^ (x15 + np[2]));
- s3 += ONE;
- ip += 16;
- op += 16;
-#endif
- }
-
- for (iters = inlen%(BPI*64)/64; iters != 0; iters--)
- {
- vec v0 = s0, v1 = s1, v2 = s2, v3 = s3;
- for (i = CHACHA_RNDS/2; i; i--)
- {
- DQROUND_VECTORS(v0,v1,v2,v3);
- }
- WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
- s3 += ONE;
- ip += 16;
- op += 16;
- }
-
- inlen = inlen % 64;
- if (inlen)
- {
- alignas(16) vec buf[4];
- vec v0,v1,v2,v3;
- v0 = s0; v1 = s1; v2 = s2; v3 = s3;
- for (i = CHACHA_RNDS/2; i; i--)
- {
- DQROUND_VECTORS(v0,v1,v2,v3);
- }
-
- if (inlen >= 16)
- {
- STORE(op + 0, LOAD(ip + 0) ^ REVV_BE(v0 + s0));
- if (inlen >= 32)
- {
- STORE(op + 4, LOAD(ip + 4) ^ REVV_BE(v1 + s1));
- if (inlen >= 48)
- {
- STORE(op + 8, LOAD(ip + 8) ^
- REVV_BE(v2 + s2));
- buf[3] = REVV_BE(v3 + s3);
- }
- else
- buf[2] = REVV_BE(v2 + s2);
- }
- else
- buf[1] = REVV_BE(v1 + s1);
- }
- else
- buf[0] = REVV_BE(v0 + s0);
-
- for (i=inlen & ~15; i<inlen; i++)
- ((char *)op)[i] = ((const char *)ip)[i] ^ ((const char *)buf)[i];
- }
- }
-
-#endif /* ASM_GEN || !OPENSSL_WINDOWS && (OPENSSL_X86_64 || OPENSSL_X86) && SSE2 */
diff --git a/crypto/chacha/chacha_vec_arm.S b/crypto/chacha/chacha_vec_arm.S
deleted file mode 100644
index f18c867e..00000000
--- a/crypto/chacha/chacha_vec_arm.S
+++ /dev/null
@@ -1,1447 +0,0 @@
-# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
-# needed to support switching on NEON code at runtime. If the whole of OpenSSL
-# were to be compiled with the needed flags to build chacha_vec.c, then it
-# wouldn't be possible to run on non-NEON systems.
-#
-# This file was generated by chacha_vec_arm_generate.go using the following
-# compiler command:
-#
-# /opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -O3 -mcpu=cortex-a8 -mfpu=neon -fpic -DASM_GEN -I ../../include -S chacha_vec.c -o -
-
-#if !defined(OPENSSL_NO_ASM)
-#if defined(__arm__)
-
- .syntax unified
- .cpu cortex-a8
- .eabi_attribute 27, 3
-
-# EABI attribute 28 sets whether VFP register arguments were used to build this
-# file. If object files are inconsistent on this point, the linker will refuse
-# to link them. Thus we report whatever the compiler expects since we don't use
-# VFP arguments.
-
-#if defined(__ARM_PCS_VFP)
- .eabi_attribute 28, 1
-#else
- .eabi_attribute 28, 0
-#endif
-
- .fpu neon
- .eabi_attribute 20, 1
- .eabi_attribute 21, 1
- .eabi_attribute 23, 3
- .eabi_attribute 24, 1
- .eabi_attribute 25, 1
- .eabi_attribute 26, 2
- .eabi_attribute 30, 2
- .eabi_attribute 34, 1
- .eabi_attribute 18, 4
- .thumb
- .file "chacha_vec.c"
- .text
- .align 2
- .global CRYPTO_chacha_20_neon
- .hidden CRYPTO_chacha_20_neon
- .thumb
- .thumb_func
- .type CRYPTO_chacha_20_neon, %function
-CRYPTO_chacha_20_neon:
- @ args = 8, pretend = 0, frame = 160
- @ frame_needed = 1, uses_anonymous_args = 0
- push {r4, r5, r6, r7, r8, r9, r10, fp, lr}
- mov r9, r3
- vpush.64 {d8, d9, d10, d11, d12, d13, d14, d15}
- mov r10, r2
- ldr r4, .L91+16
- mov fp, r1
- mov r8, r9
-.LPIC16:
- add r4, pc
- sub sp, sp, #164
- add r7, sp, #0
- sub sp, sp, #112
- add lr, r7, #148
- str r0, [r7, #80]
- str r1, [r7, #12]
- str r2, [r7, #8]
- ldmia r4, {r0, r1, r2, r3}
- add r4, sp, #15
- bic r4, r4, #15
- ldr r6, [r7, #264]
- str r4, [r7, #88]
- mov r5, r4
- adds r4, r4, #64
- add ip, r5, #80
- str r9, [r7, #56]
- stmia r4, {r0, r1, r2, r3}
- movw r4, #43691
- ldr r0, [r6] @ unaligned
- movt r4, 43690
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- str ip, [r7, #84]
- stmia lr!, {r0, r1, r2}
- mov lr, ip
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r0, [r9] @ unaligned
- vldr d24, [r5, #64]
- vldr d25, [r5, #72]
- umull r4, r5, r10, r4
- stmia ip!, {r0, r1, r2, r3}
- ldr r0, [r8, #16]! @ unaligned
- ldr r2, [r7, #88]
- ldr r4, [r7, #268]
- ldr r1, [r8, #4] @ unaligned
- vldr d26, [r2, #80]
- vldr d27, [r2, #88]
- ldr r3, [r8, #12] @ unaligned
- ldr r2, [r8, #8] @ unaligned
- stmia lr!, {r0, r1, r2, r3}
- ldr r3, [r6]
- ldr r1, [r6, #4]
- ldr r6, [r6, #8]
- str r3, [r7, #68]
- str r3, [r7, #132]
- lsrs r3, r5, #7
- str r6, [r7, #140]
- str r6, [r7, #60]
- ldr r6, [r7, #88]
- str r4, [r7, #128]
- str r1, [r7, #136]
- str r1, [r7, #64]
- vldr d28, [r6, #80]
- vldr d29, [r6, #88]
- vldr d22, [r7, #128]
- vldr d23, [r7, #136]
- beq .L26
- mov r5, r6
- lsls r2, r3, #8
- sub r3, r2, r3, lsl #6
- ldr r2, [r5, #68]
- ldr r6, [r6, #64]
- vldr d0, .L91
- vldr d1, .L91+8
- str r2, [r7, #48]
- ldr r2, [r5, #72]
- str r3, [r7, #4]
- str r6, [r7, #52]
- str r2, [r7, #44]
- adds r2, r4, #2
- str r2, [r7, #72]
- ldr r2, [r5, #76]
- str fp, [r7, #76]
- str r2, [r7, #40]
- ldr r2, [r7, #80]
- adds r3, r2, r3
- str r3, [r7, #16]
-.L4:
- ldr r5, [r7, #56]
- add r8, r7, #40
- ldr r4, [r7, #68]
- vadd.i32 q3, q11, q0
- ldmia r8, {r8, r9, r10, fp}
- mov r1, r5
- ldr r2, [r5, #4]
- vmov q8, q14 @ v4si
- ldr r3, [r5]
- vmov q1, q13 @ v4si
- ldr r6, [r1, #28]
- vmov q9, q12 @ v4si
- mov r0, r2
- ldr r2, [r5, #8]
- str r4, [r7, #112]
- movs r1, #10
- ldr r4, [r7, #72]
- vmov q2, q11 @ v4si
- ldr lr, [r5, #20]
- vmov q15, q14 @ v4si
- str r3, [r7, #108]
- vmov q5, q13 @ v4si
- str r2, [r7, #116]
- vmov q10, q12 @ v4si
- ldr r2, [r5, #12]
- ldr ip, [r5, #16]
- ldr r3, [r7, #64]
- ldr r5, [r5, #24]
- str r6, [r7, #120]
- str r1, [r7, #92]
- ldr r6, [r7, #60]
- str r4, [r7, #100]
- ldr r1, [r7, #116]
- ldr r4, [r7, #108]
- str r8, [r7, #96]
- mov r8, r10
- str lr, [r7, #104]
- mov r10, r9
- mov lr, r3
- mov r9, r5
- str r6, [r7, #124]
- b .L92
-.L93:
- .align 3
-.L91:
- .word 1
- .word 0
- .word 0
- .word 0
- .word .LANCHOR0-(.LPIC16+4)
-.L92:
-.L3:
- vadd.i32 q9, q9, q1
- add r3, r8, r0
- vadd.i32 q10, q10, q5
- add r5, fp, r4
- veor q3, q3, q9
- mov r6, r3
- veor q2, q2, q10
- ldr r3, [r7, #96]
- str r5, [r7, #116]
- add r10, r10, r1
- vrev32.16 q3, q3
- str r6, [r7, #108]
- vadd.i32 q8, q8, q3
- vrev32.16 q2, q2
- vadd.i32 q15, q15, q2
- mov fp, r3
- ldr r3, [r7, #100]
- veor q4, q8, q1
- veor q6, q15, q5
- add fp, fp, r2
- eors r3, r3, r5
- mov r5, r6
- ldr r6, [r7, #112]
- vshl.i32 q1, q4, #12
- vshl.i32 q5, q6, #12
- ror r3, r3, #16
- eors r6, r6, r5
- eor lr, lr, r10
- vsri.32 q1, q4, #20
- mov r5, r6
- ldr r6, [r7, #124]
- vsri.32 q5, q6, #20
- str r3, [r7, #124]
- eor r6, r6, fp
- ror r5, r5, #16
- vadd.i32 q9, q9, q1
- ror lr, lr, #16
- ror r3, r6, #16
- ldr r6, [r7, #124]
- vadd.i32 q10, q10, q5
- add r9, r9, lr
- veor q4, q9, q3
- add ip, ip, r6
- ldr r6, [r7, #104]
- veor q6, q10, q2
- eor r4, ip, r4
- str r3, [r7, #104]
- vshl.i32 q3, q4, #8
- eor r1, r9, r1
- mov r8, r6
- ldr r6, [r7, #120]
- vshl.i32 q2, q6, #8
- ror r4, r4, #20
- add r6, r6, r3
- vsri.32 q3, q4, #24
- str r6, [r7, #100]
- eors r2, r2, r6
- ldr r6, [r7, #116]
- vsri.32 q2, q6, #24
- add r8, r8, r5
- ror r2, r2, #20
- adds r6, r4, r6
- vadd.i32 q4, q8, q3
- eor r0, r8, r0
- vadd.i32 q15, q15, q2
- mov r3, r6
- ldr r6, [r7, #108]
- veor q6, q4, q1
- ror r0, r0, #20
- str r3, [r7, #112]
- veor q5, q15, q5
- adds r6, r0, r6
- str r6, [r7, #120]
- mov r6, r3
- ldr r3, [r7, #124]
- vshl.i32 q8, q6, #7
- add fp, fp, r2
- eors r3, r3, r6
- ldr r6, [r7, #120]
- vshl.i32 q1, q5, #7
- ror r1, r1, #20
- eors r5, r5, r6
- vsri.32 q8, q6, #25
- ldr r6, [r7, #104]
- ror r3, r3, #24
- ror r5, r5, #24
- vsri.32 q1, q5, #25
- str r5, [r7, #116]
- eor r6, fp, r6
- ldr r5, [r7, #116]
- add r10, r10, r1
- add ip, r3, ip
- vext.32 q8, q8, q8, #1
- str ip, [r7, #124]
- add ip, r5, r8
- ldr r5, [r7, #100]
- eor lr, r10, lr
- ror r6, r6, #24
- vext.32 q1, q1, q1, #1
- add r8, r6, r5
- vadd.i32 q9, q9, q8
- ldr r5, [r7, #124]
- vext.32 q3, q3, q3, #3
- vadd.i32 q10, q10, q1
- ror lr, lr, #24
- eor r0, ip, r0
- vext.32 q2, q2, q2, #3
- add r9, r9, lr
- eors r4, r4, r5
- veor q3, q9, q3
- ldr r5, [r7, #112]
- eor r1, r9, r1
- ror r0, r0, #25
- veor q2, q10, q2
- adds r5, r0, r5
- vext.32 q4, q4, q4, #2
- str r5, [r7, #112]
- ldr r5, [r7, #120]
- ror r1, r1, #25
- vrev32.16 q3, q3
- eor r2, r8, r2
- vext.32 q15, q15, q15, #2
- adds r5, r1, r5
- vadd.i32 q4, q4, q3
- ror r4, r4, #25
- vrev32.16 q2, q2
- str r5, [r7, #100]
- vadd.i32 q15, q15, q2
- eors r3, r3, r5
- ldr r5, [r7, #112]
- add fp, fp, r4
- veor q8, q4, q8
- ror r2, r2, #25
- veor q1, q15, q1
- eor lr, fp, lr
- eors r6, r6, r5
- ror r3, r3, #16
- ldr r5, [r7, #116]
- add r10, r10, r2
- str r3, [r7, #120]
- ror lr, lr, #16
- ldr r3, [r7, #120]
- eor r5, r10, r5
- vshl.i32 q5, q8, #12
- add ip, lr, ip
- vshl.i32 q6, q1, #12
- str ip, [r7, #104]
- add ip, r3, r8
- str ip, [r7, #116]
- ldr r3, [r7, #124]
- ror r5, r5, #16
- vsri.32 q5, q8, #20
- ror r6, r6, #16
- add ip, r5, r3
- ldr r3, [r7, #104]
- vsri.32 q6, q1, #20
- add r9, r9, r6
- eor r2, ip, r2
- eors r4, r4, r3
- ldr r3, [r7, #116]
- eor r0, r9, r0
- vadd.i32 q9, q9, q5
- ror r4, r4, #20
- eors r1, r1, r3
- vadd.i32 q10, q10, q6
- ror r3, r2, #20
- str r3, [r7, #108]
- ldr r3, [r7, #112]
- veor q3, q9, q3
- ror r0, r0, #20
- add r8, r4, fp
- veor q2, q10, q2
- add fp, r0, r3
- ldr r3, [r7, #100]
- ror r1, r1, #20
- mov r2, r8
- vshl.i32 q8, q3, #8
- str r8, [r7, #96]
- add r8, r1, r3
- ldr r3, [r7, #108]
- vmov q1, q6 @ v4si
- vshl.i32 q6, q2, #8
- eor r6, fp, r6
- add r10, r10, r3
- ldr r3, [r7, #120]
- vsri.32 q8, q3, #24
- eor lr, r2, lr
- eor r3, r8, r3
- ror r2, r6, #24
- vsri.32 q6, q2, #24
- eor r5, r10, r5
- str r2, [r7, #124]
- ror r2, r3, #24
- ldr r3, [r7, #104]
- vmov q3, q8 @ v4si
- vadd.i32 q15, q15, q6
- ror lr, lr, #24
- vadd.i32 q8, q4, q8
- ror r6, r5, #24
- add r5, lr, r3
- ldr r3, [r7, #124]
- veor q4, q8, q5
- add ip, ip, r6
- vmov q2, q6 @ v4si
- add r9, r9, r3
- veor q6, q15, q1
- ldr r3, [r7, #116]
- vshl.i32 q1, q4, #7
- str r2, [r7, #100]
- add r3, r3, r2
- str r3, [r7, #120]
- vshl.i32 q5, q6, #7
- eors r1, r1, r3
- ldr r3, [r7, #108]
- vsri.32 q1, q4, #25
- eors r4, r4, r5
- eor r0, r9, r0
- eor r2, ip, r3
- vsri.32 q5, q6, #25
- ldr r3, [r7, #92]
- ror r4, r4, #25
- str r6, [r7, #112]
- ror r0, r0, #25
- subs r3, r3, #1
- str r5, [r7, #104]
- ror r1, r1, #25
- ror r2, r2, #25
- vext.32 q15, q15, q15, #2
- str r3, [r7, #92]
- vext.32 q2, q2, q2, #1
- vext.32 q8, q8, q8, #2
- vext.32 q3, q3, q3, #1
- vext.32 q5, q5, q5, #3
- vext.32 q1, q1, q1, #3
- bne .L3
- ldr r3, [r7, #84]
- vadd.i32 q4, q12, q10
- str r9, [r7, #92]
- mov r9, r10
- mov r10, r8
- ldr r8, [r7, #96]
- str lr, [r7, #96]
- mov lr, r5
- ldr r5, [r7, #52]
- vadd.i32 q5, q13, q5
- ldr r6, [r7, #76]
- vadd.i32 q15, q14, q15
- add fp, fp, r5
- ldr r5, [r7, #48]
- str r3, [r7, #104]
- vadd.i32 q7, q14, q8
- ldr r3, [r6, #12] @ unaligned
- add r10, r10, r5
- str r0, [r7, #36]
- vadd.i32 q2, q11, q2
- ldr r0, [r6] @ unaligned
- vadd.i32 q6, q12, q9
- ldr r5, [r7, #104]
- vadd.i32 q1, q13, q1
- str r1, [r7, #116]
- vadd.i32 q11, q11, q0
- ldr r1, [r6, #4] @ unaligned
- str r2, [r7, #32]
- vadd.i32 q3, q11, q3
- ldr r2, [r6, #8] @ unaligned
- vadd.i32 q11, q11, q0
- str r4, [r7, #108]
- ldr r4, [r7, #100]
- vadd.i32 q11, q11, q0
- stmia r5!, {r0, r1, r2, r3}
- ldr r2, [r7, #88]
- ldr r3, [r7, #44]
- ldr r5, [r7, #84]
- vldr d20, [r2, #80]
- vldr d21, [r2, #88]
- add r3, r9, r3
- str r3, [r7, #104]
- veor q10, q10, q4
- ldr r3, [r7, #40]
- add r3, r8, r3
- str r3, [r7, #100]
- ldr r3, [r7, #72]
- vstr d20, [r2, #80]
- vstr d21, [r2, #88]
- adds r1, r4, r3
- str r1, [r7, #28]
- ldmia r5!, {r0, r1, r2, r3}
- ldr r4, [r7, #68]
- ldr r5, [r7, #112]
- ldr r8, [r7, #84]
- add r5, r5, r4
- ldr r4, [r7, #96]
- str r5, [r7, #24]
- ldr r5, [r7, #64]
- add r4, r4, r5
- ldr r5, [r7, #60]
- str r4, [r7, #96]
- ldr r4, [r7, #124]
- add r4, r4, r5
- str r4, [r7, #20]
- ldr r4, [r7, #80]
- mov r5, r8
- str r0, [r4] @ unaligned
- mov r0, r4
- str r1, [r4, #4] @ unaligned
- mov r4, r8
- str r2, [r0, #8] @ unaligned
- mov r8, r0
- str r3, [r0, #12] @ unaligned
- mov r9, r4
- ldr r0, [r6, #16]! @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r6, [r7, #76]
- stmia r5!, {r0, r1, r2, r3}
- mov r5, r8
- ldr r3, [r7, #88]
- vldr d20, [r3, #80]
- vldr d21, [r3, #88]
- veor q10, q10, q5
- vstr d20, [r3, #80]
- vstr d21, [r3, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- str r0, [r8, #16] @ unaligned
- str r1, [r8, #20] @ unaligned
- str r2, [r8, #24] @ unaligned
- str r3, [r8, #28] @ unaligned
- mov r8, r5
- ldr r0, [r6, #32]! @ unaligned
- mov r5, r9
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #76]
- stmia r5!, {r0, r1, r2, r3}
- mov r5, r8
- ldr r1, [r7, #88]
- vldr d16, [r1, #80]
- vldr d17, [r1, #88]
- veor q15, q8, q15
- vstr d30, [r1, #80]
- vstr d31, [r1, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- str r0, [r8, #32] @ unaligned
- str r1, [r8, #36] @ unaligned
- str r2, [r8, #40] @ unaligned
- str r3, [r8, #44] @ unaligned
- mov r8, r5
- ldr r0, [r6, #48]! @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #76]
- stmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- ldr r1, [r7, #88]
- str r9, [r7, #112]
- vldr d18, [r1, #80]
- vldr d19, [r1, #88]
- veor q9, q9, q2
- vstr d18, [r1, #80]
- vstr d19, [r1, #88]
- ldmia r9!, {r0, r1, r2, r3}
- str r0, [r5, #48] @ unaligned
- str r1, [r5, #52] @ unaligned
- str r2, [r5, #56] @ unaligned
- str r3, [r5, #60] @ unaligned
- ldr r0, [r6, #64]! @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #76]
- mov r9, r6
- mov r6, r4
- stmia r6!, {r0, r1, r2, r3}
- mov r6, r4
- ldr r1, [r7, #88]
- vldr d18, [r1, #80]
- vldr d19, [r1, #88]
- veor q9, q9, q6
- vstr d18, [r1, #80]
- vstr d19, [r1, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r6
- str r3, [r5, #76] @ unaligned
- mov r3, r9
- str r2, [r5, #72] @ unaligned
- str r0, [r5, #64] @ unaligned
- str r1, [r5, #68] @ unaligned
- mov r5, r4
- ldr r0, [r3, #80]! @ unaligned
- mov r9, r3
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- mov r9, r4
- ldr r6, [r7, #76]
- str r9, [r7, #124]
- stmia r5!, {r0, r1, r2, r3}
- mov r5, r8
- ldr r1, [r7, #88]
- vldr d18, [r1, #80]
- vldr d19, [r1, #88]
- veor q1, q9, q1
- vstr d2, [r1, #80]
- vstr d3, [r1, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- str r0, [r8, #80] @ unaligned
- str r1, [r8, #84] @ unaligned
- str r2, [r8, #88] @ unaligned
- str r3, [r8, #92] @ unaligned
- ldr r0, [r6, #96]! @ unaligned
- ldr r3, [r6, #12] @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r6, [r7, #76]
- stmia r4!, {r0, r1, r2, r3}
- mov r4, r9
- ldr r3, [r7, #88]
- vldr d16, [r3, #80]
- vldr d17, [r3, #88]
- veor q8, q8, q7
- vstr d16, [r3, #80]
- vstr d17, [r3, #88]
- ldmia r9!, {r0, r1, r2, r3}
- str r0, [r5, #96] @ unaligned
- str r1, [r5, #100] @ unaligned
- str r2, [r5, #104] @ unaligned
- str r3, [r5, #108] @ unaligned
- ldr r0, [r6, #112]! @ unaligned
- ldr r1, [r6, #4] @ unaligned
- ldr r2, [r6, #8] @ unaligned
- ldr r3, [r6, #12] @ unaligned
- mov r6, r4
- stmia r6!, {r0, r1, r2, r3}
- mov r6, r5
- ldr r3, [r7, #88]
- vldr d16, [r3, #80]
- vldr d17, [r3, #88]
- veor q8, q8, q3
- vstr d16, [r3, #80]
- vstr d17, [r3, #88]
- ldmia r4!, {r0, r1, r2, r3}
- mov r4, r5
- mov r8, r4
- str r2, [r5, #120] @ unaligned
- ldr r2, [r7, #76]
- str r0, [r5, #112] @ unaligned
- str r1, [r5, #116] @ unaligned
- str r3, [r5, #124] @ unaligned
- ldr r3, [r2, #128]
- ldr r1, [r7, #104]
- eor r3, fp, r3
- str r3, [r5, #128]
- ldr r3, [r2, #132]
- mov r5, r2
- eor r3, r10, r3
- str r3, [r6, #132]
- ldr r3, [r2, #136]
- mov r6, r5
- eors r1, r1, r3
- str r1, [r8, #136]
- ldr r1, [r7, #56]
- ldr r3, [r2, #140]
- ldr r2, [r7, #100]
- ldr r0, [r7, #108]
- eors r3, r3, r2
- str r3, [r4, #140]
- ldr r3, [r1]
- ldr r2, [r5, #144]
- mov r8, r0
- add r8, r8, r3
- mov r5, r6
- mov r3, r8
- eors r2, r2, r3
- str r2, [r4, #144]
- ldr r3, [r6, #148]
- ldr r2, [r1, #4]
- ldr r6, [r7, #36]
- add r6, r6, r2
- eors r3, r3, r6
- mov r6, r1
- str r3, [r4, #148]
- ldr r2, [r1, #8]
- ldr r1, [r7, #116]
- ldr r3, [r5, #152]
- mov r8, r1
- add r8, r8, r2
- ldr r1, [r7, #32]
- mov r2, r8
- eors r3, r3, r2
- str r3, [r4, #152]
- mov r8, r4
- ldr r2, [r6, #12]
- ldr r3, [r5, #156]
- add r1, r1, r2
- eors r3, r3, r1
- str r3, [r4, #156]
- ldr r2, [r6, #16]
- mov r1, r4
- ldr r3, [r5, #160]
- mov r4, r5
- add ip, ip, r2
- mov r5, r6
- eor r3, ip, r3
- str r3, [r1, #160]
- ldr r2, [r6, #20]
- ldr r3, [r4, #164]
- add lr, lr, r2
- ldr r2, [r7, #92]
- eor r3, lr, r3
- str r3, [r1, #164]
- ldr r6, [r5, #24]
- mov lr, r4
- ldr r3, [r4, #168]
- add r2, r2, r6
- ldr r6, [r7, #120]
- eors r3, r3, r2
- str r3, [r1, #168]
- ldr r5, [r5, #28]
- ldr r3, [r4, #172]
- add r6, r6, r5
- eors r3, r3, r6
- str r3, [r1, #172]
- ldr r4, [r4, #176]
- ldr r0, [r7, #28]
- ldr r5, [r7, #24]
- eors r4, r4, r0
- str r4, [r8, #176]
- ldr r0, [lr, #180]
- ldr r2, [r7, #96]
- eors r0, r0, r5
- str r0, [r8, #180]
- ldr r1, [lr, #184]
- ldr r4, [r7, #20]
- eors r1, r1, r2
- str r1, [r8, #184]
- ldr r2, [lr, #188]
- add r1, lr, #192
- ldr r3, [r7, #72]
- eors r2, r2, r4
- str r2, [r8, #188]
- ldr r2, [r7, #16]
- adds r3, r3, #3
- str r3, [r7, #72]
- mov r3, r8
- adds r3, r3, #192
- str r1, [r7, #76]
- cmp r2, r3
- str r3, [r7, #80]
- bne .L4
- ldr r3, [r7, #12]
- ldr r2, [r7, #4]
- add r3, r3, r2
- str r3, [r7, #12]
-.L2:
- ldr r1, [r7, #8]
- movw r2, #43691
- movt r2, 43690
- umull r2, r3, r1, r2
- lsr fp, r3, #7
- lsl r3, fp, #8
- sub fp, r3, fp, lsl #6
- rsb fp, fp, r1
- lsrs fp, fp, #6
- beq .L6
- ldr r5, [r7, #12]
- ldr r4, [r7, #16]
- ldr r6, [r7, #88]
- ldr lr, [r7, #84]
- vldr d30, .L94
- vldr d31, .L94+8
- str fp, [r7, #120]
- str fp, [r7, #124]
-.L8:
- vmov q2, q11 @ v4si
- movs r3, #10
- vmov q8, q14 @ v4si
- vmov q9, q13 @ v4si
- vmov q10, q12 @ v4si
-.L7:
- vadd.i32 q10, q10, q9
- subs r3, r3, #1
- veor q3, q2, q10
- vrev32.16 q3, q3
- vadd.i32 q8, q8, q3
- veor q9, q8, q9
- vshl.i32 q2, q9, #12
- vsri.32 q2, q9, #20
- vadd.i32 q10, q10, q2
- veor q3, q10, q3
- vshl.i32 q9, q3, #8
- vsri.32 q9, q3, #24
- vadd.i32 q8, q8, q9
- vext.32 q9, q9, q9, #3
- veor q2, q8, q2
- vext.32 q8, q8, q8, #2
- vshl.i32 q3, q2, #7
- vsri.32 q3, q2, #25
- vext.32 q3, q3, q3, #1
- vadd.i32 q10, q10, q3
- veor q9, q10, q9
- vrev32.16 q9, q9
- vadd.i32 q8, q8, q9
- veor q3, q8, q3
- vshl.i32 q2, q3, #12
- vsri.32 q2, q3, #20
- vadd.i32 q10, q10, q2
- vmov q3, q2 @ v4si
- veor q9, q10, q9
- vshl.i32 q2, q9, #8
- vsri.32 q2, q9, #24
- vadd.i32 q8, q8, q2
- vext.32 q2, q2, q2, #1
- veor q3, q8, q3
- vext.32 q8, q8, q8, #2
- vshl.i32 q9, q3, #7
- vsri.32 q9, q3, #25
- vext.32 q9, q9, q9, #3
- bne .L7
- ldr r0, [r5] @ unaligned
- vadd.i32 q1, q12, q10
- ldr r1, [r5, #4] @ unaligned
- mov ip, lr
- ldr r2, [r5, #8] @ unaligned
- mov r9, lr
- ldr r3, [r5, #12] @ unaligned
- mov r10, r5
- vadd.i32 q9, q13, q9
- mov r8, lr
- vadd.i32 q8, q14, q8
- stmia ip!, {r0, r1, r2, r3}
- mov ip, lr
- vldr d20, [r6, #80]
- vldr d21, [r6, #88]
- vadd.i32 q3, q11, q2
- veor q10, q10, q1
- vadd.i32 q11, q11, q15
- vstr d20, [r6, #80]
- vstr d21, [r6, #88]
- ldmia r9!, {r0, r1, r2, r3}
- mov r9, r5
- str r0, [r4] @ unaligned
- str r1, [r4, #4] @ unaligned
- str r2, [r4, #8] @ unaligned
- str r3, [r4, #12] @ unaligned
- ldr r0, [r10, #16]! @ unaligned
- ldr r1, [r10, #4] @ unaligned
- ldr r2, [r10, #8] @ unaligned
- ldr r3, [r10, #12] @ unaligned
- add r10, r4, #48
- adds r4, r4, #64
- stmia r8!, {r0, r1, r2, r3}
- mov r8, lr
- vldr d20, [r6, #80]
- vldr d21, [r6, #88]
- veor q10, q10, q9
- vstr d20, [r6, #80]
- vstr d21, [r6, #88]
- ldmia ip!, {r0, r1, r2, r3}
- mov ip, lr
- str r0, [r4, #-48] @ unaligned
- str r1, [r4, #-44] @ unaligned
- str r2, [r4, #-40] @ unaligned
- str r3, [r4, #-36] @ unaligned
- ldr r0, [r9, #32]! @ unaligned
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- mov r9, r5
- adds r5, r5, #64
- stmia r8!, {r0, r1, r2, r3}
- mov r8, lr
- vldr d18, [r6, #80]
- vldr d19, [r6, #88]
- veor q9, q9, q8
- vstr d18, [r6, #80]
- vstr d19, [r6, #88]
- ldmia ip!, {r0, r1, r2, r3}
- mov ip, lr
- str r0, [r4, #-32] @ unaligned
- str r1, [r4, #-28] @ unaligned
- str r2, [r4, #-24] @ unaligned
- str r3, [r4, #-20] @ unaligned
- ldr r0, [r9, #48]! @ unaligned
- ldr r1, [r9, #4] @ unaligned
- ldr r2, [r9, #8] @ unaligned
- ldr r3, [r9, #12] @ unaligned
- stmia r8!, {r0, r1, r2, r3}
- vldr d16, [r6, #80]
- vldr d17, [r6, #88]
- veor q8, q8, q3
- vstr d16, [r6, #80]
- vstr d17, [r6, #88]
- ldmia ip!, {r0, r1, r2, r3}
- str r0, [r4, #-16] @ unaligned
- str r1, [r4, #-12] @ unaligned
- str r3, [r10, #12] @ unaligned
- ldr r3, [r7, #124]
- str r2, [r10, #8] @ unaligned
- cmp r3, #1
- beq .L87
- movs r3, #1
- str r3, [r7, #124]
- b .L8
-.L95:
- .align 3
-.L94:
- .word 1
- .word 0
- .word 0
- .word 0
-.L87:
- ldr fp, [r7, #120]
- ldr r3, [r7, #12]
- lsl fp, fp, #6
- add r3, r3, fp
- str r3, [r7, #12]
- ldr r3, [r7, #16]
- add r3, r3, fp
- str r3, [r7, #16]
-.L6:
- ldr r3, [r7, #8]
- ands r9, r3, #63
- beq .L1
- vmov q3, q11 @ v4si
- movs r3, #10
- vmov q8, q14 @ v4si
- mov r5, r9
- vmov q15, q13 @ v4si
- vmov q10, q12 @ v4si
-.L10:
- vadd.i32 q10, q10, q15
- subs r3, r3, #1
- veor q9, q3, q10
- vrev32.16 q9, q9
- vadd.i32 q8, q8, q9
- veor q15, q8, q15
- vshl.i32 q3, q15, #12
- vsri.32 q3, q15, #20
- vadd.i32 q10, q10, q3
- veor q15, q10, q9
- vshl.i32 q9, q15, #8
- vsri.32 q9, q15, #24
- vadd.i32 q8, q8, q9
- vext.32 q9, q9, q9, #3
- veor q3, q8, q3
- vext.32 q8, q8, q8, #2
- vshl.i32 q15, q3, #7
- vsri.32 q15, q3, #25
- vext.32 q15, q15, q15, #1
- vadd.i32 q10, q10, q15
- veor q9, q10, q9
- vrev32.16 q9, q9
- vadd.i32 q8, q8, q9
- veor q15, q8, q15
- vshl.i32 q3, q15, #12
- vsri.32 q3, q15, #20
- vadd.i32 q10, q10, q3
- vmov q15, q3 @ v4si
- veor q9, q10, q9
- vshl.i32 q3, q9, #8
- vsri.32 q3, q9, #24
- vadd.i32 q8, q8, q3
- vext.32 q3, q3, q3, #1
- veor q9, q8, q15
- vext.32 q8, q8, q8, #2
- vshl.i32 q15, q9, #7
- vsri.32 q15, q9, #25
- vext.32 q15, q15, q15, #3
- bne .L10
- cmp r5, #15
- mov r9, r5
- bhi .L88
- vadd.i32 q12, q12, q10
- ldr r3, [r7, #88]
- vst1.64 {d24-d25}, [r3:128]
-.L14:
- ldr r3, [r7, #8]
- and r2, r3, #48
- cmp r9, r2
- bls .L1
- ldr r6, [r7, #16]
- add r3, r2, #16
- ldr r1, [r7, #12]
- rsb ip, r2, r9
- adds r0, r1, r2
- mov r4, r6
- add r1, r1, r3
- add r4, r4, r2
- add r3, r3, r6
- cmp r0, r3
- it cc
- cmpcc r4, r1
- ite cs
- movcs r3, #1
- movcc r3, #0
- cmp ip, #18
- ite ls
- movls r3, #0
- andhi r3, r3, #1
- cmp r3, #0
- beq .L16
- and r1, r0, #7
- mov r3, r2
- negs r1, r1
- and r1, r1, #15
- cmp r1, ip
- it cs
- movcs r1, ip
- cmp r1, #0
- beq .L17
- ldr r5, [r7, #88]
- cmp r1, #1
- ldrb r0, [r0] @ zero_extendqisi2
- add r3, r2, #1
- ldrb lr, [r5, r2] @ zero_extendqisi2
- mov r6, r5
- eor r0, lr, r0
- strb r0, [r4]
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #2
- ldrb r4, [r5, r3] @ zero_extendqisi2
- ldr r5, [r7, #16]
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #2
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #3
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #3
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #4
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #4
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #5
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #5
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #6
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #6
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #7
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #7
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #8
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #8
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #9
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #9
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #10
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #10
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #11
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #11
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #12
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #12
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #13
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #13
- beq .L17
- ldr r0, [r7, #12]
- cmp r1, #15
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #14
- bne .L17
- ldr r0, [r7, #12]
- ldrb r4, [r6, r3] @ zero_extendqisi2
- ldrb r0, [r0, r3] @ zero_extendqisi2
- eors r0, r0, r4
- strb r0, [r5, r3]
- add r3, r2, #15
-.L17:
- rsb r4, r1, ip
- add r0, ip, #-1
- sub r6, r4, #16
- subs r0, r0, r1
- cmp r0, #14
- lsr r6, r6, #4
- add r6, r6, #1
- lsl lr, r6, #4
- bls .L19
- add r2, r2, r1
- ldr r1, [r7, #12]
- ldr r5, [r7, #16]
- cmp r6, #1
- add r0, r1, r2
- ldr r1, [r7, #88]
- add r1, r1, r2
- vld1.64 {d18-d19}, [r0:64]
- add r2, r2, r5
- vld1.8 {q8}, [r1]
- veor q8, q8, q9
- vst1.8 {q8}, [r2]
- beq .L20
- add r8, r1, #16
- add ip, r2, #16
- vldr d18, [r0, #16]
- vldr d19, [r0, #24]
- cmp r6, #2
- vld1.8 {q8}, [r8]
- veor q8, q8, q9
- vst1.8 {q8}, [ip]
- beq .L20
- add r8, r1, #32
- add ip, r2, #32
- vldr d18, [r0, #32]
- vldr d19, [r0, #40]
- cmp r6, #3
- vld1.8 {q8}, [r8]
- veor q8, q8, q9
- vst1.8 {q8}, [ip]
- beq .L20
- adds r1, r1, #48
- adds r2, r2, #48
- vldr d18, [r0, #48]
- vldr d19, [r0, #56]
- vld1.8 {q8}, [r1]
- veor q8, q8, q9
- vst1.8 {q8}, [r2]
-.L20:
- cmp lr, r4
- add r3, r3, lr
- beq .L1
-.L19:
- ldr r4, [r7, #88]
- adds r2, r3, #1
- ldr r1, [r7, #12]
- cmp r2, r9
- ldr r5, [r7, #16]
- ldrb r0, [r4, r3] @ zero_extendqisi2
- ldrb r1, [r1, r3] @ zero_extendqisi2
- eor r1, r1, r0
- strb r1, [r5, r3]
- bcs .L1
- ldr r0, [r7, #12]
- adds r1, r3, #2
- mov r6, r4
- cmp r9, r1
- ldrb r4, [r4, r2] @ zero_extendqisi2
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- adds r2, r3, #3
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- adds r1, r3, #4
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- adds r2, r3, #5
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- adds r1, r3, #6
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- adds r2, r3, #7
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- add r1, r3, #8
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- add r2, r3, #9
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- add r1, r3, #10
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- add r2, r3, #11
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r0, [r7, #12]
- add r1, r3, #12
- ldrb r4, [r6, r2] @ zero_extendqisi2
- cmp r9, r1
- ldrb r0, [r0, r2] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r2]
- bls .L1
- ldr r0, [r7, #12]
- add r2, r3, #13
- ldrb r4, [r6, r1] @ zero_extendqisi2
- cmp r9, r2
- ldrb r0, [r0, r1] @ zero_extendqisi2
- eor r0, r0, r4
- strb r0, [r5, r1]
- bls .L1
- ldr r1, [r7, #12]
- adds r3, r3, #14
- ldrb r0, [r6, r2] @ zero_extendqisi2
- cmp r9, r3
- ldrb r1, [r1, r2] @ zero_extendqisi2
- eor r1, r1, r0
- strb r1, [r5, r2]
- bls .L1
- ldr r2, [r7, #88]
- ldrb r1, [r2, r3] @ zero_extendqisi2
- ldr r2, [r7, #12]
- ldrb r2, [r2, r3] @ zero_extendqisi2
- eors r2, r2, r1
- ldr r1, [r7, #16]
- strb r2, [r1, r3]
-.L1:
- adds r7, r7, #164
- mov sp, r7
- @ sp needed
- vldm sp!, {d8-d15}
- pop {r4, r5, r6, r7, r8, r9, r10, fp, pc}
-.L88:
- ldr r5, [r7, #12]
- vadd.i32 q12, q12, q10
- ldr r4, [r7, #84]
- cmp r9, #31
- ldr r0, [r5] @ unaligned
- ldr r1, [r5, #4] @ unaligned
- mov r6, r4
- ldr r2, [r5, #8] @ unaligned
- ldr r3, [r5, #12] @ unaligned
- stmia r6!, {r0, r1, r2, r3}
- ldr r2, [r7, #88]
- ldr r6, [r7, #16]
- vldr d18, [r2, #80]
- vldr d19, [r2, #88]
- veor q9, q9, q12
- vstr d18, [r2, #80]
- vstr d19, [r2, #88]
- ldmia r4!, {r0, r1, r2, r3}
- str r1, [r6, #4] @ unaligned
- mov r1, r6
- str r0, [r6] @ unaligned
- str r2, [r6, #8] @ unaligned
- str r3, [r6, #12] @ unaligned
- bhi .L89
- vadd.i32 q13, q13, q15
- ldr r3, [r7, #88]
- vstr d26, [r3, #16]
- vstr d27, [r3, #24]
- b .L14
-.L16:
- subs r3, r2, #1
- ldr r2, [r7, #12]
- add r2, r2, r9
- mov r5, r2
- ldr r2, [r7, #88]
- add r2, r2, r3
- mov r3, r2
-.L24:
- ldrb r1, [r0], #1 @ zero_extendqisi2
- ldrb r2, [r3, #1]! @ zero_extendqisi2
- cmp r0, r5
- eor r2, r2, r1
- strb r2, [r4], #1
- bne .L24
- adds r7, r7, #164
- mov sp, r7
- @ sp needed
- vldm sp!, {d8-d15}
- pop {r4, r5, r6, r7, r8, r9, r10, fp, pc}
-.L26:
- ldr r3, [r7, #80]
- str r3, [r7, #16]
- b .L2
-.L89:
- mov r3, r5
- ldr r4, [r7, #84]
- ldr r0, [r3, #16]! @ unaligned
- add lr, r1, #16
- mov r5, r1
- vadd.i32 q13, q13, q15
- mov r6, r4
- cmp r9, #47
- ldr r1, [r3, #4] @ unaligned
- ldr r2, [r3, #8] @ unaligned
- ldr r3, [r3, #12] @ unaligned
- stmia r6!, {r0, r1, r2, r3}
- ldr r2, [r7, #88]
- vldr d18, [r2, #80]
- vldr d19, [r2, #88]
- veor q13, q9, q13
- vstr d26, [r2, #80]
- vstr d27, [r2, #88]
- ldmia r4!, {r0, r1, r2, r3}
- str r0, [r5, #16] @ unaligned
- str r1, [lr, #4] @ unaligned
- str r2, [lr, #8] @ unaligned
- str r3, [lr, #12] @ unaligned
- bhi .L90
- vadd.i32 q8, q14, q8
- ldr r3, [r7, #88]
- vstr d16, [r3, #32]
- vstr d17, [r3, #40]
- b .L14
-.L90:
- ldr r3, [r7, #12]
- add lr, r5, #32
- ldr r4, [r7, #84]
- vadd.i32 q8, q14, q8
- ldr r5, [r7, #88]
- vadd.i32 q11, q11, q3
- ldr r0, [r3, #32]! @ unaligned
- mov r6, r4
- vstr d22, [r5, #48]
- vstr d23, [r5, #56]
- ldr r1, [r3, #4] @ unaligned
- ldr r2, [r3, #8] @ unaligned
- ldr r3, [r3, #12] @ unaligned
- stmia r4!, {r0, r1, r2, r3}
- vldr d18, [r5, #80]
- vldr d19, [r5, #88]
- veor q9, q9, q8
- ldr r4, [r7, #16]
- vstr d18, [r5, #80]
- vstr d19, [r5, #88]
- ldmia r6!, {r0, r1, r2, r3}
- str r0, [r4, #32] @ unaligned
- str r1, [lr, #4] @ unaligned
- str r2, [lr, #8] @ unaligned
- str r3, [lr, #12] @ unaligned
- b .L14
- .size CRYPTO_chacha_20_neon, .-CRYPTO_chacha_20_neon
- .section .rodata
- .align 2
-.LANCHOR0 = . + 0
-.LC0:
- .word 1634760805
- .word 857760878
- .word 2036477234
- .word 1797285236
- .ident "GCC: (Linaro GCC 2014.11) 4.9.3 20141031 (prerelease)"
- .section .note.GNU-stack,"",%progbits
-
-#endif /* __arm__ */
-#endif /* !OPENSSL_NO_ASM */
diff --git a/crypto/chacha/chacha_vec_arm_generate.go b/crypto/chacha/chacha_vec_arm_generate.go
deleted file mode 100644
index 82aa847f..00000000
--- a/crypto/chacha/chacha_vec_arm_generate.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) 2014, Google Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// This package generates chacha_vec_arm.S from chacha_vec.c. Install the
-// arm-linux-gnueabihf-gcc compiler as described in BUILDING.md. Then:
-// `(cd crypto/chacha && go run chacha_vec_arm_generate.go)`.
-
-package main
-
-import (
- "bufio"
- "bytes"
- "os"
- "os/exec"
- "strings"
-)
-
-const defaultCompiler = "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
-
-func main() {
- compiler := defaultCompiler
- if len(os.Args) > 1 {
- compiler = os.Args[1]
- }
-
- args := []string{
- "-O3",
- "-mcpu=cortex-a8",
- "-mfpu=neon",
- "-fpic",
- "-DASM_GEN",
- "-I", "../../include",
- "-S", "chacha_vec.c",
- "-o", "-",
- }
-
- output, err := os.OpenFile("chacha_vec_arm.S", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
- if err != nil {
- panic(err)
- }
- defer output.Close()
-
- output.WriteString(preamble)
- output.WriteString(compiler)
- output.WriteString(" ")
- output.WriteString(strings.Join(args, " "))
- output.WriteString("\n\n#if !defined(OPENSSL_NO_ASM)\n")
- output.WriteString("#if defined(__arm__)\n\n")
-
- cmd := exec.Command(compiler, args...)
- cmd.Stderr = os.Stderr
- asm, err := cmd.StdoutPipe()
- if err != nil {
- panic(err)
- }
- if err := cmd.Start(); err != nil {
- panic(err)
- }
-
- attr28 := []byte(".eabi_attribute 28,")
- globalDirective := []byte(".global\t")
- newLine := []byte("\n")
- attr28Handled := false
-
- scanner := bufio.NewScanner(asm)
- for scanner.Scan() {
- line := scanner.Bytes()
-
- if bytes.Contains(line, attr28) {
- output.WriteString(attr28Block)
- attr28Handled = true
- continue
- }
-
- output.Write(line)
- output.Write(newLine)
-
- if i := bytes.Index(line, globalDirective); i >= 0 {
- output.Write(line[:i])
- output.WriteString(".hidden\t")
- output.Write(line[i+len(globalDirective):])
- output.Write(newLine)
- }
- }
-
- if err := scanner.Err(); err != nil {
- panic(err)
- }
-
- if !attr28Handled {
- panic("EABI attribute 28 not seen in processing")
- }
-
- if err := cmd.Wait(); err != nil {
- panic(err)
- }
-
- output.WriteString(trailer)
-}
-
-const preamble = `# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
-# needed to support switching on NEON code at runtime. If the whole of OpenSSL
-# were to be compiled with the needed flags to build chacha_vec.c, then it
-# wouldn't be possible to run on non-NEON systems.
-#
-# This file was generated by chacha_vec_arm_generate.go using the following
-# compiler command:
-#
-# `
-
-const attr28Block = `
-# EABI attribute 28 sets whether VFP register arguments were used to build this
-# file. If object files are inconsistent on this point, the linker will refuse
-# to link them. Thus we report whatever the compiler expects since we don't use
-# VFP arguments.
-
-#if defined(__ARM_PCS_VFP)
- .eabi_attribute 28, 1
-#else
- .eabi_attribute 28, 0
-#endif
-
-`
-
-const trailer = `
-#endif /* __arm__ */
-#endif /* !OPENSSL_NO_ASM */
-`
diff --git a/crypto/cipher/aead.c b/crypto/cipher/aead.c
index b1db83d2..57eecc1b 100644
--- a/crypto/cipher/aead.c
+++ b/crypto/cipher/aead.c
@@ -20,6 +20,7 @@
#include <openssl/err.h>
#include "internal.h"
+#include "../internal.h"
size_t EVP_AEAD_key_length(const EVP_AEAD *aead) { return aead->key_len; }
@@ -80,21 +81,15 @@ void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) {
ctx->aead = NULL;
}
-/* check_alias returns 0 if |out| points within the buffer determined by |in|
- * and |in_len| and 1 otherwise.
- *
- * When processing, there's only an issue if |out| points within in[:in_len]
- * and isn't equal to |in|. If that's the case then writing the output will
- * stomp input that hasn't been read yet.
- *
- * This function checks for that case. */
-static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out) {
- if (out <= in) {
- return 1;
- } else if (in + in_len <= out) {
+/* check_alias returns 1 if |out| is compatible with |in| and 0 otherwise. If
+ * |in| and |out| alias, we require that |in| == |out|. */
+static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out,
+ size_t out_len) {
+ if (!buffers_alias(in, in_len, out, out_len)) {
return 1;
}
- return 0;
+
+ return in == out;
}
int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
@@ -108,7 +103,7 @@ int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
goto error;
}
- if (!check_alias(in, in_len, out)) {
+ if (!check_alias(in, in_len, out, max_out_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
goto error;
}
@@ -130,7 +125,7 @@ int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
- if (!check_alias(in, in_len, out)) {
+ if (!check_alias(in, in_len, out, max_out_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
goto error;
}
diff --git a/crypto/cipher/aead_test.cc b/crypto/cipher/aead_test.cc
index 79d7110d..8bad93f5 100644
--- a/crypto/cipher/aead_test.cc
+++ b/crypto/cipher/aead_test.cc
@@ -192,37 +192,139 @@ static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
return 1;
}
-struct AEADName {
+static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
+ const size_t key_len = EVP_AEAD_key_length(aead);
+ const size_t nonce_len = EVP_AEAD_nonce_length(aead);
+ const size_t max_overhead = EVP_AEAD_max_overhead(aead);
+
+ std::vector<uint8_t> key(key_len, 'a');
+ ScopedEVP_AEAD_CTX ctx;
+ if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
+ return false;
+ }
+
+ static const uint8_t kPlaintext[260] =
+ "testing123456testing123456testing123456testing123456testing123456testing"
+ "123456testing123456testing123456testing123456testing123456testing123456t"
+ "esting123456testing123456testing123456testing123456testing123456testing1"
+ "23456testing123456testing123456testing12345";
+ const std::vector<size_t> offsets = {
+ 0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
+ 64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
+ };
+
+ std::vector<uint8_t> nonce(nonce_len, 'b');
+ std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
+ size_t valid_encryption_len;
+ if (!EVP_AEAD_CTX_seal(
+ ctx.get(), valid_encryption.data(), &valid_encryption_len,
+ sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len,
+ kPlaintext, sizeof(kPlaintext), nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n");
+ return false;
+ }
+
+ // Test with out != in which we expect to fail.
+ std::vector<uint8_t> buffer(2 + valid_encryption_len);
+ uint8_t *in = buffer.data() + 1;
+ uint8_t *out1 = buffer.data();
+ uint8_t *out2 = buffer.data() + 2;
+
+ memcpy(in, kPlaintext, sizeof(kPlaintext));
+ size_t out_len;
+ if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len,
+ sizeof(kPlaintext) + max_overhead, nonce.data(),
+ nonce_len, in, sizeof(kPlaintext), nullptr, 0) ||
+ EVP_AEAD_CTX_seal(ctx.get(), out2, &out_len,
+ sizeof(kPlaintext) + max_overhead, nonce.data(),
+ nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal unexpectedly succeeded.\n");
+ return false;
+ }
+ ERR_clear_error();
+
+ memcpy(in, valid_encryption.data(), valid_encryption_len);
+ if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len,
+ nonce.data(), nonce_len, in, valid_encryption_len,
+ nullptr, 0) ||
+ EVP_AEAD_CTX_open(ctx.get(), out2, &out_len, valid_encryption_len,
+ nonce.data(), nonce_len, in, valid_encryption_len,
+ nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_open unexpectedly succeeded.\n");
+ return false;
+ }
+ ERR_clear_error();
+
+ // Test with out == in, which we expect to work.
+ memcpy(in, kPlaintext, sizeof(kPlaintext));
+
+ if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
+ sizeof(kPlaintext) + max_overhead, nonce.data(),
+ nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal failed in-place.\n");
+ return false;
+ }
+
+ if (out_len != valid_encryption_len ||
+ memcmp(in, valid_encryption.data(), out_len) != 0) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n");
+ return false;
+ }
+
+ memcpy(in, valid_encryption.data(), valid_encryption_len);
+ if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
+ nonce.data(), nonce_len, in, valid_encryption_len,
+ nullptr, 0)) {
+ fprintf(stderr, "EVP_AEAD_CTX_open failed in-place.\n");
+ return false;
+ }
+
+ if (out_len != sizeof(kPlaintext) ||
+ memcmp(in, kPlaintext, out_len) != 0) {
+ fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n");
+ return false;
+ }
+
+ return true;
+}
+
+struct KnownAEAD {
const char name[40];
const EVP_AEAD *(*func)(void);
+ // limited_implementation indicates that tests that assume a generic AEAD
+ // interface should not be performed. For example, the key-wrap AEADs only
+ // handle inputs that are a multiple of eight bytes in length and the
+ // SSLv3/TLS AEADs have the concept of “direction”.
+ bool limited_implementation;
};
-static const struct AEADName kAEADs[] = {
- { "aes-128-gcm", EVP_aead_aes_128_gcm },
- { "aes-256-gcm", EVP_aead_aes_256_gcm },
- { "chacha20-poly1305", EVP_aead_chacha20_poly1305 },
- { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old },
- { "rc4-md5-tls", EVP_aead_rc4_md5_tls },
- { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls },
- { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls },
- { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv },
- { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls },
- { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls },
- { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv },
- { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls },
- { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls },
- { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls },
- { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv },
- { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3 },
- { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3 },
- { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3 },
- { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3 },
- { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3 },
- { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap },
- { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap },
- { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256 },
- { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256 },
- { "", NULL },
+static const struct KnownAEAD kAEADs[] = {
+ { "aes-128-gcm", EVP_aead_aes_128_gcm, false },
+ { "aes-256-gcm", EVP_aead_aes_256_gcm, false },
+ { "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
+ { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
+ { "rc4-md5-tls", EVP_aead_rc4_md5_tls, true },
+ { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls, true },
+ { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
+ { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true },
+ { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true },
+ { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true },
+ { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true },
+ { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true },
+ { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true },
+ { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true },
+ { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true },
+ { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3, true },
+ { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3, true },
+ { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true },
+ { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true },
+ { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true },
+ { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap, true },
+ { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap, true },
+ { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false },
+ { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false },
+ { "", NULL, false },
};
int main(int argc, char **argv) {
@@ -233,22 +335,28 @@ int main(int argc, char **argv) {
return 1;
}
- const EVP_AEAD *aead;
+ const struct KnownAEAD *known_aead;
for (unsigned i = 0;; i++) {
- const struct AEADName &aead_name = kAEADs[i];
- if (aead_name.func == NULL) {
+ known_aead = &kAEADs[i];
+ if (known_aead->func == NULL) {
fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
return 2;
}
- if (strcmp(aead_name.name, argv[1]) == 0) {
- aead = aead_name.func();
+ if (strcmp(known_aead->name, argv[1]) == 0) {
break;
}
}
+ const EVP_AEAD *const aead = known_aead->func();
+
if (!TestCleanupAfterInitFailure(aead)) {
return 1;
}
+ if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
+ fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
+ return 1;
+ }
+
return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
}
diff --git a/crypto/cipher/cipher.c b/crypto/cipher/cipher.c
index 44018675..f61c59f4 100644
--- a/crypto/cipher/cipher.c
+++ b/crypto/cipher/cipher.c
@@ -61,7 +61,7 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
@@ -284,7 +284,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
bl = ctx->cipher->block_size;
assert(bl <= (int)sizeof(ctx->buf));
if (i != 0) {
- if (i + in_len < bl) {
+ if (bl - i > in_len) {
memcpy(&ctx->buf[i], in, in_len);
ctx->buf_len += in_len;
*out_len = 0;
diff --git a/crypto/cipher/cipher_test.cc b/crypto/cipher/cipher_test.cc
index 7b4944cb..fa384c69 100644
--- a/crypto/cipher/cipher_test.cc
+++ b/crypto/cipher/cipher_test.cc
@@ -109,7 +109,7 @@ static const EVP_CIPHER *GetCipher(const std::string &name) {
static bool TestOperation(FileTest *t,
const EVP_CIPHER *cipher,
bool encrypt,
- bool streaming,
+ size_t chunk_size,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &iv,
const std::vector<uint8_t> &plaintext,
@@ -170,16 +170,21 @@ static bool TestOperation(FileTest *t,
t->PrintLine("Operation failed.");
return false;
}
- if (streaming) {
- for (size_t i = 0; i < in->size(); i++) {
- uint8_t c = (*in)[i];
+ if (chunk_size != 0) {
+ for (size_t i = 0; i < in->size();) {
+ size_t todo = chunk_size;
+ if (i + todo > in->size()) {
+ todo = in->size() - i;
+ }
+
int len;
- if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len, &c,
- 1)) {
+ if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
+ in->data() + i, todo)) {
t->PrintLine("Operation failed.");
return false;
}
result_len1 += len;
+ i += todo;
}
} else if (!in->empty() &&
!EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
@@ -258,20 +263,20 @@ static bool TestCipher(FileTest *t, void *arg) {
}
}
- // By default, both directions are run, unless overridden by the operation.
- if (operation != kDecrypt) {
- if (!TestOperation(t, cipher, true /* encrypt */, false /* single-shot */,
- key, iv, plaintext, ciphertext, aad, tag) ||
- !TestOperation(t, cipher, true /* encrypt */, true /* streaming */, key,
- iv, plaintext, ciphertext, aad, tag)) {
+ const std::vector<size_t> chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16,
+ 17, 31, 32, 33, 63, 64, 65, 512};
+
+ for (size_t chunk_size : chunk_sizes) {
+ // By default, both directions are run, unless overridden by the operation.
+ if (operation != kDecrypt &&
+ !TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
+ plaintext, ciphertext, aad, tag)) {
return false;
}
- }
- if (operation != kEncrypt) {
- if (!TestOperation(t, cipher, false /* decrypt */, false /* single-shot */,
- key, iv, plaintext, ciphertext, aad, tag) ||
- !TestOperation(t, cipher, false /* decrypt */, true /* streaming */,
- key, iv, plaintext, ciphertext, aad, tag)) {
+
+ if (operation != kEncrypt &&
+ !TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
+ plaintext, ciphertext, aad, tag)) {
return false;
}
}
diff --git a/crypto/cipher/e_aes.c b/crypto/cipher/e_aes.c
index f7b6fa31..24c4d8a3 100644
--- a/crypto/cipher/e_aes.c
+++ b/crypto/cipher/e_aes.c
@@ -54,7 +54,7 @@
#include <openssl/cpu.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
@@ -67,6 +67,8 @@
#endif
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) /* Unreachable code. */
+
typedef struct {
union {
double align;
@@ -252,22 +254,6 @@ void aesni_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length,
void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int enc);
-void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
- const void *key, const uint8_t *ivec);
-
-#if defined(OPENSSL_X86_64)
-size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], uint64_t *Xi);
-#define AES_gcm_encrypt aesni_gcm_encrypt
-size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], uint64_t *Xi);
-#define AES_gcm_decrypt aesni_gcm_decrypt
-void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
- size_t len);
-#define AES_GCM_ASM(gctx) \
- (gctx->ctr == aesni_ctr32_encrypt_blocks && gctx->gcm.ghash == gcm_ghash_avx)
-#endif /* OPENSSL_X86_64 */
-
#else
/* On other platforms, aesni_capable() will always return false and so the
@@ -288,8 +274,7 @@ static void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
#endif
static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
- const uint8_t *iv, int enc)
- OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+ const uint8_t *iv, int enc) {
int ret, mode;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
@@ -384,17 +369,15 @@ static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
size_t len) {
- unsigned num = (unsigned)ctx->num;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
if (dat->stream.ctr) {
- CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
- dat->stream.ctr);
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf,
+ &ctx->num, dat->stream.ctr);
} else {
- CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
+ CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num,
dat->block);
}
- ctx->num = (int)num;
return 1;
}
@@ -410,8 +393,7 @@ static char aesni_capable(void);
static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
block128_f *out_block, const uint8_t *key,
- size_t key_len)
- OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+ size_t key_len) {
if (aesni_capable()) {
aesni_set_encrypt_key(key, key_len * 8, aes_key);
if (gcm_ctx != NULL) {
@@ -651,57 +633,23 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
}
} else if (ctx->encrypt) {
if (gctx->ctr) {
- size_t bulk = 0;
-#if defined(AES_GCM_ASM)
- if (len >= 32 && AES_GCM_ASM(gctx)) {
- size_t res = (16 - gctx->gcm.mres) % 16;
-
- if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
- return -1;
- }
-
- bulk = AES_gcm_encrypt(in + res, out + res, len - res, &gctx->ks.ks,
- gctx->gcm.Yi.c, gctx->gcm.Xi.u);
- gctx->gcm.len.u[1] += bulk;
- bulk += res;
- }
-#endif
- if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk, gctx->ctr)) {
+ if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
+ gctx->ctr)) {
return -1;
}
} else {
- size_t bulk = 0;
- if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk)) {
+ if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
return -1;
}
}
} else {
if (gctx->ctr) {
- size_t bulk = 0;
-#if defined(AES_GCM_ASM)
- if (len >= 16 && AES_GCM_ASM(gctx)) {
- size_t res = (16 - gctx->gcm.mres) % 16;
-
- if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
- return -1;
- }
-
- bulk = AES_gcm_decrypt(in + res, out + res, len - res, &gctx->ks.ks,
- gctx->gcm.Yi.c, gctx->gcm.Xi.u);
- gctx->gcm.len.u[1] += bulk;
- bulk += res;
- }
-#endif
- if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk, gctx->ctr)) {
+ if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
+ gctx->ctr)) {
return -1;
}
} else {
- size_t bulk = 0;
- if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
- out + bulk, len - bulk)) {
+ if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
return -1;
}
}
diff --git a/crypto/cipher/e_chacha20poly1305.c b/crypto/cipher/e_chacha20poly1305.c
index de8c9b4b..852b2c64 100644
--- a/crypto/cipher/e_chacha20poly1305.c
+++ b/crypto/cipher/e_chacha20poly1305.c
@@ -117,7 +117,7 @@ static int seal_impl(aead_poly1305_update poly1305_update,
* 32-bits and this produces a warning because it's always false.
* Casting to uint64_t inside the conditional is not sufficient to stop
* the warning. */
- if (in_len_64 >= (1ull << 32) * 64 - 64) {
+ if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
@@ -162,7 +162,7 @@ static int open_impl(aead_poly1305_update poly1305_update,
* 32-bits and this produces a warning because it's always false.
* Casting to uint64_t inside the conditional is not sufficient to stop
* the warning. */
- if (in_len_64 >= (1ull << 32) * 64 - 64) {
+ if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
@@ -244,10 +244,6 @@ const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
return &aead_chacha20_poly1305;
}
-const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void) {
- return EVP_aead_chacha20_poly1305();
-}
-
static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad,
size_t ad_len, const uint8_t *ciphertext,
size_t ciphertext_len) {
diff --git a/crypto/cipher/e_des.c b/crypto/cipher/e_des.c
index b1d312c3..2ba2bed3 100644
--- a/crypto/cipher/e_des.c
+++ b/crypto/cipher/e_des.c
@@ -56,7 +56,7 @@
#include <openssl/cipher.h>
#include <openssl/des.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/crypto/cipher/e_null.c b/crypto/cipher/e_null.c
index cfe1d1b2..3d6a24c3 100644
--- a/crypto/cipher/e_null.c
+++ b/crypto/cipher/e_null.c
@@ -58,7 +58,7 @@
#include <string.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/crypto/cipher/e_rc2.c b/crypto/cipher/e_rc2.c
index 8ca7bba6..67418d54 100644
--- a/crypto/cipher/e_rc2.c
+++ b/crypto/cipher/e_rc2.c
@@ -55,7 +55,7 @@
* [including the GNU Public Licence.] */
#include <openssl/cipher.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/crypto/cipher/e_rc4.c b/crypto/cipher/e_rc4.c
index 3a2c166a..e7c2ccaf 100644
--- a/crypto/cipher/e_rc4.c
+++ b/crypto/cipher/e_rc4.c
@@ -58,7 +58,7 @@
#include <string.h>
#include <openssl/cipher.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rc4.h>
diff --git a/crypto/cipher/test/aes_128_gcm_tests.txt b/crypto/cipher/test/aes_128_gcm_tests.txt
index 0e33c911..eac9aa92 100644
--- a/crypto/cipher/test/aes_128_gcm_tests.txt
+++ b/crypto/cipher/test/aes_128_gcm_tests.txt
@@ -1,4 +1,4 @@
-# The AES-128-GCM test cases from cipher_test.txt have been merged into this
+# The AES-128-GCM test cases from cipher_tests.txt have been merged into this
# file.
KEY: d480429666d48b400633921c5407d1d1
diff --git a/crypto/cipher/test/aes_256_gcm_tests.txt b/crypto/cipher/test/aes_256_gcm_tests.txt
index dbcee814..30fd422d 100644
--- a/crypto/cipher/test/aes_256_gcm_tests.txt
+++ b/crypto/cipher/test/aes_256_gcm_tests.txt
@@ -1,4 +1,4 @@
-# The AES-256-GCM test cases from cipher_test.txt have been merged into this
+# The AES-256-GCM test cases from cipher_tests.txt have been merged into this
# file.
KEY: e5ac4a32c67e425ac4b143c83c6f161312a97d88d634afdf9f4da5bd35223f01
diff --git a/crypto/cipher/test/cipher_test.txt b/crypto/cipher/test/cipher_test.txt
deleted file mode 100644
index 21fffdb1..00000000
--- a/crypto/cipher/test/cipher_test.txt
+++ /dev/null
@@ -1,597 +0,0 @@
-# RC4 tests (from rc4test)
-Cipher = RC4
-Key = 0123456789abcdef0123456789abcdef
-Plaintext = 0123456789abcdef
-Ciphertext = 75b7878099e0c596
-
-Cipher = RC4
-Key = 0123456789abcdef0123456789abcdef
-Plaintext = 0000000000000000
-Ciphertext = 7494c2e7104b0879
-
-Cipher = RC4
-Key = 00000000000000000000000000000000
-Plaintext = 0000000000000000
-Ciphertext = de188941a3375d3a
-
-Cipher = RC4
-Key = ef012345ef012345ef012345ef012345
-Plaintext = 0000000000000000000000000000000000000000
-Ciphertext = d6a141a7ec3c38dfbd615a1162e1c7ba36b67858
-
-Cipher = RC4
-Key = 0123456789abcdef0123456789abcdef
-Plaintext = 123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678
-Ciphertext = 66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf
-
-Cipher = RC4
-Key = ef012345ef012345ef012345ef012345
-Plaintext = 00000000000000000000
-Ciphertext = d6a141a7ec3c38dfbd61
-
-
-# DES EDE3 CBC tests (from destest)
-Cipher = DES-EDE3-CBC
-Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210
-IV = fedcba9876543210
-Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
-Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675
-
-
-# DES EDE CBC tests
-Cipher = DES-EDE-CBC
-Key = 0123456789abcdeff1e0d3c2b5a49786
-IV = fedcba9876543210
-Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
-Ciphertext = 7948C0DA4FE91CD815DCA96DBC9B60A857EB954F4DEB08EB98722642AE69257B
-
-
-# DES EDE tests
-Cipher = DES-EDE
-Key = 0123456789abcdeff1e0d3c2b5a49786
-IV = fedcba9876543210
-Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
-Ciphertext = 22E889402E28422F8167AD279D90A566DA75B734E12C671FC2669AECB3E4FE8F
-
-
-# AES 128 ECB tests (from FIPS-197 test vectors, encrypt)
-Cipher = AES-128-ECB
-Key = 000102030405060708090A0B0C0D0E0F
-Operation = ENCRYPT
-Plaintext = 00112233445566778899AABBCCDDEEFF
-Ciphertext = 69C4E0D86A7B0430D8CDB78070B4C55A
-
-
-# AES 256 ECB tests (from FIPS-197 test vectors, encrypt)
-Cipher = AES-256-ECB
-Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-Operation = ENCRYPT
-Plaintext = 00112233445566778899AABBCCDDEEFF
-Ciphertext = 8EA2B7CA516745BFEAFC49904B496089
-
-
-# AES tests from NIST document SP800-38A
-# For all ECB encrypts and decrypts, the transformed sequence is
-# AES-bits-ECB:key::plaintext:ciphertext:encdec
-# ECB-AES128.Encrypt and ECB-AES128.Decrypt
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 3AD77BB40D7A3660A89ECAF32466EF97
-
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = F5D3D58503B9699DE785895A96FDBAAF
-
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 43B1CD7F598ECE23881B00E3ED030688
-
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 7B0C785E27E8AD3F8223207104725DD4
-
-
-# ECB-AES256.Encrypt and ECB-AES256.Decrypt
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = F3EED1BDB5D2A03C064B5A7E3DB181F8
-
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 591CCB10D410ED26DC5BA74A31362870
-
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = B6ED21B99CA6F4F9F153E7B1BEAFED1D
-
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 23304B7A39F9F3FF067D8D8F9E24ECC7
-
-
-# For all CBC encrypts and decrypts, the transformed sequence is
-# AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec
-# CBC-AES128.Encrypt and CBC-AES128.Decrypt
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 000102030405060708090A0B0C0D0E0F
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 7649ABAC8119B246CEE98E9B12E9197D
-
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 7649ABAC8119B246CEE98E9B12E9197D
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 5086CB9B507219EE95DB113A917678B2
-
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 5086CB9B507219EE95DB113A917678B2
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 73BED6B8E3C1743B7116E69E22229516
-
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 73BED6B8E3C1743B7116E69E22229516
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 3FF1CAA1681FAC09120ECA307586E1A7
-
-
-# CBC-AES256.Encrypt and CBC-AES256.Decrypt
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 000102030405060708090A0B0C0D0E0F
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = F58C4C04D6E5F1BA779EABFB5F7BFBD6
-
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = F58C4C04D6E5F1BA779EABFB5F7BFBD6
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 9CFC4E967EDB808D679F777BC6702C7D
-
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 9CFC4E967EDB808D679F777BC6702C7D
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 39F23369A9D9BACFA530E26304231461
-
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 39F23369A9D9BACFA530E26304231461
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = B2EB05E2C39BE9FCDA6C19078C6A9D1B
-
-
-# AES Counter test vectors from RFC3686
-Cipher = AES-128-CTR
-Key = AE6852F8121067CC4BF7A5765577F39E
-IV = 00000030000000000000000000000001
-Operation = ENCRYPT
-Plaintext = 53696E676C6520626C6F636B206D7367
-Ciphertext = E4095D4FB7A7B3792D6175A3261311B8
-
-Cipher = AES-128-CTR
-Key = 7E24067817FAE0D743D6CE1F32539163
-IV = 006CB6DBC0543B59DA48D90B00000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-Ciphertext = 5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28
-
-Cipher = AES-128-CTR
-Key = 7691BE035E5020A8AC6E618529F9A0DC
-IV = 00E0017B27777F3F4A1786F000000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
-Ciphertext = C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F
-
-Cipher = AES-256-CTR
-Key = 776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104
-IV = 00000060DB5672C97AA8F0B200000001
-Operation = ENCRYPT
-Plaintext = 53696E676C6520626C6F636B206D7367
-Ciphertext = 145AD01DBF824EC7560863DC71E3E0C0
-
-Cipher = AES-256-CTR
-Key = F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884
-IV = 00FAAC24C1585EF15A43D87500000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-Ciphertext = F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C
-
-Cipher = AES-256-CTR
-Key = FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D
-IV = 001CC5B751A51D70A1C1114800000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
-Ciphertext = EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8
-
-
-# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext =
-Ciphertext =
-AAD =
-Tag = 58e2fccefa7e3061367f1d57a4e7455a
-
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 00000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78
-AAD =
-Tag = ab6e47d42cec13bdf53a67b21257bddf
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
-Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
-AAD =
-Tag = 4d5c2af327cd64a62cf35abd2ba6fab4
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 5bc94fbc3221a5db94fae95ae7121a47
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbad
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 3612d2e79e3b0785561be14aaca2fccb
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 619cc5aefffe0bfa462af43c1699d050
-
-Cipher = AES-256-GCM
-Key = 0000000000000000000000000000000000000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext =
-Ciphertext =
-AAD =
-Tag = 530f8afbc74536b9a963b4f1c4cb738b
-
-Cipher = AES-256-GCM
-Key = 0000000000000000000000000000000000000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 00000000000000000000000000000000
-Ciphertext = cea7403d4d606b6e074ec5d3baf39d18
-AAD =
-Tag = d0d1c8a799996bf0265b98b5d48ab919
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
-Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
-AAD =
-Tag = b094dac5d93471bdec1a502270e3cc6c
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 76fc6ece0f4e1768cddf8853bb2d551b
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbad
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 3a337dbf46a792c45e454913fe2ea8f2
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a
-
-# local add-ons, primarily streaming ghash tests
-# 128 bytes aad
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext =
-Ciphertext =
-AAD = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
-Tag = 5fea793a2d6f974d37e68e0cb8ff9492
-
-# 48 bytes plaintext
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0
-AAD =
-Tag = 9dd0a376b08e40eb00c35f29f9ea61a4
-
-# 80 bytes plaintext
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291
-AAD =
-Tag = 98885a3a22bd4742fe7b72172193b163
-
-# 128 bytes plaintext
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40
-AAD =
-Tag = cac45f60e31efd3b5a43b98a22ce1aa1
-
-# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606
-AAD =
-Tag = 566f8ef683078bfdeeffa869d751a017
-
-# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c
-AAD =
-Tag = 8b307f6b33286d0ab026a9ed3fe1e85f
-
-# 80 bytes plaintext, submitted by Intel
-Cipher = AES-128-GCM
-Key = 843ffcf5d2b72694d19ed01d01249412
-IV = dbcca32ebf9b804617c3aa9e
-Plaintext = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
-Ciphertext = 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5
-AAD = 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f
-Tag = 3b629ccfbc1119b7319e1dce2cd6fd6d
-
-Cipher = AES-128-GCM
-Key = 31323334353637383930313233343536
-IV = 31323334353637383930313233343536
-Plaintext = 48656c6c6f2c20576f726c64
-Ciphertext = cec189d0e8419b90fb16d555
-Tag = 32893832a8d609224d77c2e56a922282
-AAD =
-
-# OFB tests from OpenSSL upstream.
-
-# OFB-AES128.Encrypt
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = ENCRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 50FE67CC996D32B6DA0937E99BAFEC60
-Operation = ENCRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 7789508D16918F03F53C52DAC54ED825
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = D9A4DADA0892239F6B8B3D7680E15674
-Operation = ENCRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = A78819583F0308E7A6BF36B1386ABF23
-Operation = ENCRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
-
-# OFB-AES128.Decrypt
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = DECRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 50FE67CC996D32B6DA0937E99BAFEC60
-Operation = DECRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 7789508D16918F03F53C52DAC54ED825
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = D9A4DADA0892239F6B8B3D7680E15674
-Operation = DECRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = A78819583F0308E7A6BF36B1386ABF23
-Operation = DECRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
-
-# OFB-AES256.Encrypt
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = ENCRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
-Operation = ENCRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = E1C656305ED1A7A6563805746FE03EDC
-Operation = ENCRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 41635BE625B48AFC1666DD42A09D96E7
-Operation = ENCRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 0126141D67F37BE8538F5A8BE740E484
-
-
-# OFB-AES256.Decrypt
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = DECRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
-Operation = DECRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = E1C656305ED1A7A6563805746FE03EDC
-Operation = DECRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 41635BE625B48AFC1666DD42A09D96E7
-Operation = DECRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 0126141D67F37BE8538F5A8BE740E484
-
-
-# AES-192 CBC-mode test from upstream OpenSSL.
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = 000102030405060708090A0B0C0D0E0F
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 4F021DB243BC633D7178183A9FA071E8
-
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = 4F021DB243BC633D7178183A9FA071E8
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = B4D9ADA9AD7DEDF4E5E738763F69145A
-
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = B4D9ADA9AD7DEDF4E5E738763F69145A
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 571B242012FB7AE07FA9BAAC3DF102E0
-
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = 571B242012FB7AE07FA9BAAC3DF102E0
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 08B0E27988598881D920A9E64F5615CD
-
-
-# AES-192-ECB tests from FIPS-197
-Cipher = AES-192-ECB
-Key = 000102030405060708090A0B0C0D0E0F1011121314151617
-Operation = ENCRYPT
-Plaintext = 00112233445566778899AABBCCDDEEFF
-Ciphertext = DDA97CA4864CDFE06EAF70A0EC0D7191
-
-
-# AES-192-ECB tests from NIST document SP800-38A
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = BD334F1D6E45F25FF712A214571FA5CC
-
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 974104846D0AD3AD7734ECB3ECEE4EEF
-
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = EF7AFD2270E2E60ADCE0BA2FACE6444E
-
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 9A4B41BA738D6C72FB16691603C18E0E
-
-# DES ECB tests
-
-Cipher = DES-ECB
-Key = 0000000000000000
-Plaintext = 0000000000000000
-Ciphertext = 8CA64DE9C1B123A7
-
-Cipher = DES-ECB
-Key = FFFFFFFFFFFFFFFF
-Plaintext = FFFFFFFFFFFFFFFF
-Ciphertext = 7359B2163E4EDC58
-
-Cipher = DES-ECB
-Key = 3000000000000000
-Plaintext = 1000000000000001
-Ciphertext = 958E6E627A05557B
-
-Cipher = DES-ECB
-Key = 1111111111111111
-Plaintext = 1111111111111111
-Ciphertext = F40379AB9E0EC533
-
-Cipher = DES-ECB
-Key = 0123456789ABCDEF
-Plaintext = 1111111111111111
-Ciphertext = 17668DFC7292532D
-
-Cipher = DES-ECB
-Key = 1111111111111111
-Plaintext = 0123456789ABCDEF
-Ciphertext = 8A5AE1F81AB8F2DD
-
-Cipher = DES-ECB
-Key = FEDCBA9876543210
-Plaintext = 0123456789ABCDEF
-Ciphertext = ED39D950FA74BCC4
diff --git a/crypto/cipher/test/cipher_tests.txt b/crypto/cipher/test/cipher_tests.txt
new file mode 100644
index 00000000..0a940f14
--- /dev/null
+++ b/crypto/cipher/test/cipher_tests.txt
@@ -0,0 +1,613 @@
+# RC4 tests (from rc4test)
+Cipher = RC4
+Key = 0123456789abcdef0123456789abcdef
+Plaintext = 0123456789abcdef
+Ciphertext = 75b7878099e0c596
+
+Cipher = RC4
+Key = 0123456789abcdef0123456789abcdef
+Plaintext = 0000000000000000
+Ciphertext = 7494c2e7104b0879
+
+Cipher = RC4
+Key = 00000000000000000000000000000000
+Plaintext = 0000000000000000
+Ciphertext = de188941a3375d3a
+
+Cipher = RC4
+Key = ef012345ef012345ef012345ef012345
+Plaintext = 0000000000000000000000000000000000000000
+Ciphertext = d6a141a7ec3c38dfbd615a1162e1c7ba36b67858
+
+Cipher = RC4
+Key = 0123456789abcdef0123456789abcdef
+Plaintext = 123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678
+Ciphertext = 66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf
+
+Cipher = RC4
+Key = ef012345ef012345ef012345ef012345
+Plaintext = 00000000000000000000
+Ciphertext = d6a141a7ec3c38dfbd61
+
+
+# DES EDE3 CBC tests (from destest)
+Cipher = DES-EDE3-CBC
+Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210
+IV = fedcba9876543210
+Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
+Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675
+
+
+# DES EDE CBC tests
+Cipher = DES-EDE-CBC
+Key = 0123456789abcdeff1e0d3c2b5a49786
+IV = fedcba9876543210
+Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
+Ciphertext = 7948C0DA4FE91CD815DCA96DBC9B60A857EB954F4DEB08EB98722642AE69257B
+
+
+# DES EDE tests
+Cipher = DES-EDE
+Key = 0123456789abcdeff1e0d3c2b5a49786
+IV = fedcba9876543210
+Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
+Ciphertext = 22E889402E28422F8167AD279D90A566DA75B734E12C671FC2669AECB3E4FE8F
+
+
+# AES 128 ECB tests (from FIPS-197 test vectors, encrypt)
+Cipher = AES-128-ECB
+Key = 000102030405060708090A0B0C0D0E0F
+Operation = ENCRYPT
+Plaintext = 00112233445566778899AABBCCDDEEFF
+Ciphertext = 69C4E0D86A7B0430D8CDB78070B4C55A
+
+
+# AES 256 ECB tests (from FIPS-197 test vectors, encrypt)
+Cipher = AES-256-ECB
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Operation = ENCRYPT
+Plaintext = 00112233445566778899AABBCCDDEEFF
+Ciphertext = 8EA2B7CA516745BFEAFC49904B496089
+
+
+# AES tests from NIST document SP800-38A
+# For all ECB encrypts and decrypts, the transformed sequence is
+# AES-bits-ECB:key::plaintext:ciphertext:encdec
+# ECB-AES128.Encrypt and ECB-AES128.Decrypt
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 3AD77BB40D7A3660A89ECAF32466EF97
+
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = F5D3D58503B9699DE785895A96FDBAAF
+
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 43B1CD7F598ECE23881B00E3ED030688
+
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 7B0C785E27E8AD3F8223207104725DD4
+
+
+# ECB-AES256.Encrypt and ECB-AES256.Decrypt
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = F3EED1BDB5D2A03C064B5A7E3DB181F8
+
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 591CCB10D410ED26DC5BA74A31362870
+
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = B6ED21B99CA6F4F9F153E7B1BEAFED1D
+
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 23304B7A39F9F3FF067D8D8F9E24ECC7
+
+
+# For all CBC encrypts and decrypts, the transformed sequence is
+# AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec
+# CBC-AES128.Encrypt and CBC-AES128.Decrypt
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 000102030405060708090A0B0C0D0E0F
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 7649ABAC8119B246CEE98E9B12E9197D
+
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 7649ABAC8119B246CEE98E9B12E9197D
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 5086CB9B507219EE95DB113A917678B2
+
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 5086CB9B507219EE95DB113A917678B2
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 73BED6B8E3C1743B7116E69E22229516
+
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 73BED6B8E3C1743B7116E69E22229516
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 3FF1CAA1681FAC09120ECA307586E1A7
+
+
+# CBC-AES256.Encrypt and CBC-AES256.Decrypt
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 000102030405060708090A0B0C0D0E0F
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = F58C4C04D6E5F1BA779EABFB5F7BFBD6
+
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = F58C4C04D6E5F1BA779EABFB5F7BFBD6
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 9CFC4E967EDB808D679F777BC6702C7D
+
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 9CFC4E967EDB808D679F777BC6702C7D
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 39F23369A9D9BACFA530E26304231461
+
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 39F23369A9D9BACFA530E26304231461
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = B2EB05E2C39BE9FCDA6C19078C6A9D1B
+
+
+# AES Counter test vectors from RFC3686
+Cipher = AES-128-CTR
+Key = AE6852F8121067CC4BF7A5765577F39E
+IV = 00000030000000000000000000000001
+Operation = ENCRYPT
+Plaintext = 53696E676C6520626C6F636B206D7367
+Ciphertext = E4095D4FB7A7B3792D6175A3261311B8
+
+Cipher = AES-128-CTR
+Key = 7E24067817FAE0D743D6CE1F32539163
+IV = 006CB6DBC0543B59DA48D90B00000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Ciphertext = 5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28
+
+Cipher = AES-128-CTR
+Key = 7691BE035E5020A8AC6E618529F9A0DC
+IV = 00E0017B27777F3F4A1786F000000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
+Ciphertext = C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F
+
+Cipher = AES-256-CTR
+Key = 776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104
+IV = 00000060DB5672C97AA8F0B200000001
+Operation = ENCRYPT
+Plaintext = 53696E676C6520626C6F636B206D7367
+Ciphertext = 145AD01DBF824EC7560863DC71E3E0C0
+
+Cipher = AES-256-CTR
+Key = F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884
+IV = 00FAAC24C1585EF15A43D87500000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Ciphertext = F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C
+
+Cipher = AES-256-CTR
+Key = FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D
+IV = 001CC5B751A51D70A1C1114800000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
+Ciphertext = EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8
+
+
+# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext =
+Ciphertext =
+AAD =
+Tag = 58e2fccefa7e3061367f1d57a4e7455a
+
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 00000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78
+AAD =
+Tag = ab6e47d42cec13bdf53a67b21257bddf
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
+AAD =
+Tag = 4d5c2af327cd64a62cf35abd2ba6fab4
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 5bc94fbc3221a5db94fae95ae7121a47
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbad
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 3612d2e79e3b0785561be14aaca2fccb
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 619cc5aefffe0bfa462af43c1699d050
+
+Cipher = AES-128-GCM
+Key = 3de7b368783bd7287f2b9b731814c876
+IV = 90dedcfff100eb1f1db9d935
+Plaintext = 8d766795cadc0961c0f448c62df3827eef3a8664599b3adbaab0cfd63875bceb8f992b4f7447dca10ddd716aa0bc4fe925e1aa3e3fd1d5c430c650fe3546d6b9a24d576a857c5f04e8c0a3b149df277aa19cfa64ee235891d3b8ec0e840d268b1e70dd8a4bf97628a0c7aea38aa21eeb8fb1a8437f2abfee05e0d2c30659e312ec03d30da51b7c19073a2341c17df806e27e796d581143d39e4de8d3f8d46aa6d6fc1a98d94fa69b92dab751d930cc12de21fb1a7468af09e3c12ff6c3db3967d10cf140bc46f17a16e24b010b6cba5ebf777341c52042596ee53008389c48d9690ab9f5625795c3e588f72f7a1670b2b25a9f4eee1c8845ac90f1bf47ae4ea4b607a50aca88ed304cbb700d02d5486139b0bc81ec042e574abf986972fa008b83ef22dbfe720c2f2f6355c87c975932cec545ebed657e5e7570c503e9aa7f0b87d0b2648e421ed1d34749637c95d1e931af8925236387e50454f0ba2e22ed05f90450fad46f4eb7ddb08656511dd065c0f852a7e42f618a961a6c6bec42226c6b6043580b009ec9837cf99844cb74794a82c269ff648e0bae9ae50256a0ad98ad9f5a35057b3004ac96f469f9ee966dadc16dc47616586cf242706df96bb2f7ee43d3bd1c65d2eac7b82ef242e77ab509afb9639e5f3995380e926305729ca762c487f4411ec2a9c688b8347e5287216dbb38c3fe2281a89fcb47ee2ee7ddf79bfa3ab61cd56a00981019bbcea8aa0444eb75958e5fa56ea0036d2de4950a7db886f4a318b433bd41e00905ab158171e0ef13172293bdf70064b9dc7b243bf9dc927589bf9e99468d1cb330639dbff1850cc51929b8971b0b2ede9d06bc5f6ba39d4551b587f09bf6f8206e8f1524f55714612581d6aa45d8fb83425f84a736576deeecafdcbfbb8670d14cd2ab2a7f8b7f374c07881b7bac2605fd5ff7ff7cf43e30cf49910961a9079c0343b8601be8c3e9fe38f49fdab0b7e1a8c1536cf84e4d80d26ae5ec37570839b5cda02929221898d611525c3a88fc444167ffc532b256cdd0a8f31ff08097d75b629fab99c9e1062d1d9962b211e15ec8709934029c4934e64db8d7a2f32e23dc541be306e9a57a3419115994cbc3a8f8d5ea2a6f45b9ea9ac0e51ed0c6680fa029f4552a6c8665aab00ab77928342e7284c321e9500ad4774ef1fed0f596d5aea371fe1793271aef38cde55547f34701a525526e83a72673385a85f44db511bc87ce1f831fc6ccf8204ca4f4a20eac09897aae93684f14ede21bcaf40a09c08012b92600d6a839ebdf8bdca7b34192c6c50bad8796b3be3c375dbae6217815d2c75cc878d39b4e842d4eaa5f5df2242cf230e44a240e18e47827f089b18bf880fd41a2516eac8e6ba3fc2db64a4bc28789860d7b18d9edeae8b3059f4d945b15d0ee27b1f74842dd1df117fe83a8fdade23a47c93902eedc4d33f2dbfcd1996e6dc1458409fde2302830e8d44c58c5ae67486b9950dd938f14c38bc4c9484fdc4ded93a0f90875773453fc14d428cd6e7beb0c705d61229d2b3df09632ebb30b325fefe2aebbf2a7aa8e4ad46277ca4b8b078818b63d04e7652057f6cbbab7c43ac355537e0d3918b4a73c00dbe6b30a27ee7a6fa213d3347ae478e8edc323404b8322b9c7b0173ed61c38ed25f3576a675d527d22edd51d6dfa5767560d3a50a91226338e8c4e6436eedbcd3d2efe9dc1e686b15d2f57d553abcfda57dc316ca453a690f20148f0dfa20c1c4a58240aaf7195095fedfa56d839d0230d55ce9a8ca1b9d1acd6fe98d583148ba0f4a4e3413c76e6ec57ddb79428d3a90079f64d3321c791f60d501c3fd02c8403f0f5e6c6836bbc96430c1b48e83350c3a3cfd017f15bee3e4bb1295d821dc98b85ab3145555cce2c34a8142fe50f8db19918b514a165d12ff6301fb2296788760ac0b6d9e3a57770ad5111cde5d24b6321918cb0b0887a282b827a8749733171914b000e7d3c0edad1d42ca60da37f0698554bb2a1749f73b3120dbeaa32951f8217a781a200467d5b569d16f56fc9b7dff0ac524f03fee0617f4c692d94613b1e13b18075dc9f0d32811d4a8949a95f6b5fa46aeb83597adb409e68b2a0177c36dcc95dcb2e7dd4fb7337ff97c013364fe139e185014948fa698741d822044fa3f6978b16afd18138c845587c405ebf7a6cd1c28610ce67e992ed49e406658a0a202feed9709500d064b6f53eecfca57dd4b38363ce3aae9d59126d8ae7e140a373851188ae28c909181d0ac64770df70dd2475809350cb367825b59d521d5e457b4e36aea6dedd90a2266898b753b57fa359d43cd388e7d6c7ed90bc4c2af34ceafe88a3af6ac376fec35f1240f08af4f3eb30bc53dd68e5762e6d39e6b16f63003fbe0bee828d0d7adc58c41e857c2c44702215b202701fc696eae021af19c79e59c3e32627cd571f5db99b17f1772b5d746196befabb0b7446687827f3315b391d5dff069b1c39c00bb143218ef458e3b397e1c99640d57fc8db2e0083d3d22ed4111a8fc9e0e6f55fe6a56e946dbee43909bdd7d516fdf756ed8099ba80b1e17a5e279119345104379a36962ca9c8b2a53c414d79eb09fe79862ca749a9eabd9185ad1df57215945882f5894868a134bfc35c835e040e77ecf077d6a98a73ee022963d70b036be3fe5718280ae52c5d751211b22950c0597aaedd35af41f7dd5999e5f7ee34a37edcf97df54a46742b0252b196eaee454ff0c30685b15f8de087de208906be1d971f0fd89f7cdff2af0bdc96759d6889fba9ef092ad1c8deab0404562a7f3977d211c28dfd1573aebd5427a8773f03986101703fa19cd4ab96a381c76a747f63b63f7a9a3a08e251cdc593a024f63b443b76d17dd9e151809da3c582fbd334fa6dd0221b6d410c6a78ba95bb0154bb8999f619f2e084a6b9755ceee4ca3c7e0481a47776c8814f13054e627e37630d593bd09d5f10a049c66c9999f4b0b037e81ef70615d674c7c7975972994a053c069675fad3fae5ae3e779233b70254fb87f25d44c104afc3d5911b8b695173f9337130e39a02cf97356cb817f6cd23f55ef74dd06bd24ce5887a7001ef576262ffaa99f9bb5e3f55bda2aa0f199115909af48bb4d6b1a0a0847774515302cafebe75aad1f63362b1f38141e8721851c3ef1a247931b3b450581eb5d09027b9e3ba60ae9801d629b74991b7fd65520eac561d47115a85141d9a757bc75710bedff1630561ae05254ea541a7ff1846ed5e164834417556dd562c45543c88d8030bb56451fd5b3cbf10fb0164c5288789d2aac7e7a836e79bc3dd401a8e3e05aa6714ffb2dfddb3037c35fa1ebed62a073b2da42133f2620ae88de5e3f46cc69f2b9b3c9b88e39b8b108059ac6bd493be5f7a39f6b53ee825f4593b77ec9238f5ab804d533f48803e7d8187291ee25cfac4da5d8c9279517adfb09c422f6d704711726c73828a5082b4c7b3d85611b8f496d3e0f78c5c4f1dd1c722b1b11d55861f232beee6aaef8a00fd2eeeb45f182af191ca6de8eaa25ceda5451416fbf6d1abc0670b8c10e2815076f271044c690bdcb64856b91265bac202043a28f6bbeb807535aad4bd89e572a9427c826b170d3862f4cca70ddffb4769d6593a1cc6c42fd06cf68642835fe474a23e6f63df316f8361bab959b768d78e20c03c2a99913c162a9662bd9981eee55922f36792de0af68da04ab49dca72e3d9b0de79df828b433bcf6be073f851a36418c03a717d54d48c1014ccb793577c8393b7cb53cad6bc7060a54cc6363734f6ad388763519ca09b533078d3cfa61d7bdd4c4dd0ffe64d68d501b55903d3f4a1f310a3826ac2ca700de01d656188dcf577fd1b63e305614b8d13471f6f84a5d4b12c5e119870a63d1e3dbd39d3b5c26b09f9d80f8a59ce836b20bc933496923d278a022c00f3aac204d07d2e5075bbcef1e4820d633a3a2b35974f72a033484a91a1d6a9913239c93e5783b01833073c98f358e3465efd5087af37ad60b7285550e776d67ea7019e788776c5a456102358c32eb4e7c28096af88b9a20d8ce379ba3928a10ffd539c106f4927e7ac0f382c74017d6e4438fb128c660affd45e9bb68452de72b574eeffe3ce239d0718908c3800bc7e8ecd2fc7d9754171506017fd7868594c9373a96579fed475a28811649ce5dc8a3107bd0d8578748878ce4998684620931dc3981a2499568c2f61174c3b3fc46a7010468e8ff75c08cd43ac764d95e2ad1659f9db62e9554f811e0f43bb74779d923c8c243d12a5314d3c0c6ec84fe60e1d2b2e2b20d3e64054d62049ef9233ff55223a319c285e4e3f4c98dc95b2ca81230d7fed9bb99fd7d97430eb32c9c11647992bd85dcb47cfd58ea3e221d095bcf9374a6baa7c8333581f62b9e489282483023fdd18451f09bec764146b587209160b3d1d7a3d2e145fdb640c4bc382541e0d84255122d51a710887ebe1ccf29d41b4dd7fd7368d68ada250d3968d6f0971f0849c13c09abadb9db8b08960a18f84f0346ea0aa71227afa55b90cabc062d549b616400d36450b19adb67d7358e48c043fa1135abfca89374c906f8d1a6a845debf6b37f055d390b029c7f4524958bdf8d7e2755dde3b957f0926f9d3b8821ba96044d3cad2d637b973bfb657fcc06ff44c17965acf572ab7a0c87604c7dd1cfd136a0ad02b22e8ef320e101ea09772588e8c5b4d88f40fe1be18d27146a2b9559491949671700cebff9a709f297c2621ca9d5d1749623abc20a326ff5be55cb9435c03bf49b147b1e0a4a918bfdc3642df90b396a474f81d75c953d87b3f3b4e31fced630bd7c481c63acbb84dd31249101ac5277a36dcdfc80d8d9a2e928e9b2d65bb257bce97ccda83b187da8a7886dc96eab93d0864d88c358105f9cfe1ad0f0a8508b5b3985ff95de652e684da970b57669aa3fdfbe590a631522abe8246393639709a9a6cd549e78e3c2d1acf84643e9f554c5e076f75a5c1dce1be20a66722d0b896837b7036509ab8d473d5d2b7a8374d6a575f69d54afe3e7e18f4faf4e917be8a74e55c271b96d966e0c0b883f84b3ef2e4f278daeda2efd3ce770801d2c4bda5eb9b646deeab9fa55324e917e63e4eb6aeb4176cb4e43af3db61aea1546fbf16e76a12fcdbe726b565710e3f9866551023e5fbac0038678717e6ab4d3e92dcc53049e8cb65c00216d31a8869ff4d3539313fe2fd7ce0f53b255e3659e7dfc5f92b7627dd9ba42972f0ba72b888932d870ab97226040c4c0f4826be131fe1d2cdc21005ec2addd7796f0927501251ab26b0e5f3f9d2a1cb346a774e18bc233cc89aa69f5f70e3d5c17098eed350ec419c82837153b5c7f5813bf5918defc8df143063f3fe45125deded2b15892d5cebce589b60f2ada0f9d608983e8d107d8e6482b5f542c6650b014445e8c055aac142f16cfc59229fc9626f7aaa40cefacef777e494e13dfa93d27c201788ca9f60e572af8d65ffb513473dade5fe494cbf7377bd1ed03db2571d65af3be4b0bf27c1f069797bfb67ef0bd8a88c6286af6712c106df9c418d88054e3b46c88296a2e63894d6bee0dda8833c373d6a1b27637e1510fea3eb2fb34ae27354571369653a282a8d19f2c34f9e5ec34555b4ed24327dc5d246df13736bd41021697104f80c85bd0ae920e9aeb4e628fb8aec269d55858df149af298b06d61250b043c8a14a15f0646d0aaa18109d031c449e66dd7336044dbdec912b1bb615fae2a3df480bd64cbed74be65c8f1acac247e80bbaeb6f9dab38c6addf4f3b094d5934ef5c9749053b9159e280034e601731a12d6688ff27ee3581ae289de424d16676fb750d2ccd5b3f964dd77bdefc15bb204e2350632822384cc194cf9130f1ee81bfc3887d3366ec0b48cbbe0fe674281ae7445f03791887873659825680448f162452cef57d783821a73047078a8cf94c416850092ac772ef0b2e48517ef101ee0681b5259aa27fd56edf3c01e6dba6298ccc91b09bb304b637eccf8c673b816e74bd7f8ceffa6b17ab03df7ee9ca4098d24d044015a07df782a309cb6761528272632a6e1323c4e18284b463dfcabed708e4fc95cef133865cdbec8bfdde100621c65a92762cc3141ff37b66dea8fa6e3aad61dcbf3b512467c4773d36e58989e12a636389c1678c191137a5f7f59668c8a527dddcdd0c3fbb14cf48b8f3ea306850a5eda76c57aad06312d7bbfc18969d7b611f512358a7bdf959cc2f41de1c408133ef02b1fb2cdf8efe9973c27536434e56fc1bb4880db7fe901087b53ef3c0de18aafa47c25f1cd62c362f2e5da41c2dbff0e13adaba26c1e0829f027dc0320442e851eaed9507b70ac17180725349f6ea7b59bf39c095a9d10790e87221c7c2d24b8bca184ee95a3ef7449aad6c1d905f688498ae7a0cd1b01f76dabc342fb2be0295ca1484bece3c9b8a1b91e53de2d2587f3607a7f348f5cbefaa7a6dcf61bbbcae9444e2d25a77b016cbd1508c8cd319e9812b43b0bbca52df155d418dacb6ab1360a9e605fb53c6e20588a10bef42d884989e836b2ff16fbcdd2c1704f75dc8c1ac2cc6aeb92726f5d46e4784c70e1e249c102be6da506e5e3c2cef6a8bc4a60dac7adf3cacca8679f8f792ddc27613e44a70fd849b7617e042da46d65a3e6cf425f59b83cbae5b6e911142abd13a0a8cdf06d041435ee20e2ca417e905d2dc49c15b863ae5920ff7f9380a86bb0c86b69a000c157cd35245bf71f9dfdefbd1760af90ec3e554ebc511aebf650633221ca9157226f613f41406872765f8d7b916ff3877266f017b8d840dca0697ec3dffce7912ea9eafb62cc2f2d0a112c9bc0727444b47b62766bddf5b5f26d391f653b6894b069069979d0cf8cc7fc4143626a8420bc0a3866db3860096cc128d620ceff059d1614487004adbdf6b0c4428ac8897dcf16e6b11a692a6b465a92b40010f3480b444d4d2e24b0af8467666905c2a6233bdd6502521b621d3cdd4a5e1f268d65bf6a1879608ffd3abf635c5f0948f3cec7e087485c72b00258ba69783cfe7d611bc41c27814ef5674185791dbe626e1f276cf2c399a4eb264f19c77ee95d94252f546528f629188318e9ede65a927aafd2f2af56ff32c0ef39862d2f92268bc9400afa8ddeff591f3ef99681263a33b873bd9e01a59c8b281da30875245cbffee5268563c7f6f20b9e22d998934131dd219624d3cef6df2f3d2d6401833f72c619d6f763837141dbf93179d0f01375581ebe227185166aa7988eb9fd453d510ca6616cc013d551d23a33a4241e85aac3201284344977d496d768f5d920c5670b1d8bb608efc1b99abd261afb0a4ebe191605cc5c2e20523a13b3b94dd1fb24a27009d9a5b6329336f3516a327642386ba64c8769da1324a8a3d1f304cf0700df2b3e38215a954523e1d40ae96d0046e2929a815bf70785e94bc9b89246ab6aded60d65170eeb49b0ee0a57ee2e57db92409105c25f2d0c1a17b5556d06511bd0991a426258372c7f2b402dd533a75aa175524eb5d6b9575300b81fdb2258bd74429add8aa477bd1182db57107d411d16147defc3582861c68f5ce82e0a0316edd5d0f3cf36825a2c79a33e376cce2e63274b3b41bcbdd755845ad9ed2a3bdacb6fa3fa9484b7b60edeb1d9ef84772e78e39adca14c9fa0bb3ad1f1c17fb9449270e9b4c97b5b320839947fc73853fc58304ee9c9e86f3775f5469554d5006eb7ce9d02d5f900c771806c275ee7022e2b55d111338dd93ad51d14008df4c13d8c03fd9bb3689607e5cbdd499c3a372b487af74cb140f6300cd2dc2acda07277ea3dab57ecf09f1a8f2d6abf7c44fcdaa6dcb1f6e791164004b20b3b4c860f409c1483c7044b6fa445f7224606894e386ba08057a387b48920d4de203b1acc4dbe2b0b4cbdc3f7d7bbb097abbf81e01db09e120eab83def925a059cdb513efe6bc93f0579ebf75638df3c3d7f9eba3c36a169e9d88495c452888853640d93ee70f254f86e2d2d3fbb5e8883b36fbd2da105cf3a75cfe998068203186bb37f1d1ebead8ce1f9383b816f1da2fd0a9e01377b6ebfed4f05bec08b4ff9b90e385736fd13a3af7980c21b0dab58decea8e9545af5d0fb11bb51aeda2c8616960e8f6f84e6c2fc4f50d7e413afe030f75475509fbcf49cbe14445d267994fd3f38f41a1339f2895c0b2969a9bf9c59b85e629486c7bb5107c7a6b069793be7690f7a7c96c93b09a9d610594a156ab27a32d5557a5b1ec8920761cd2f559ad808dff3da64717ea5f10fba87b8ff2712ce322eb3c288939e0007f779a3920f45fdd533369f6f85a8cce21f91552fe03702ef81a926af0e402b418fbb25a6a3dad0ec18ec663126b3f48c341e2725abfeae865352d5ad275a9e3ca20393c64d118968023daac84bdc724a3c522d97a5878ed788cf8e44f80f8803d57584d8c8688cff24dd8c0e881b62d16ea30104d62007a4bec051da7fdc95d1df8556ebdf607383a0825ae503e24661ceb8ba773b793360c3f4ed3b761bd372570cb17e7c2030f07b0b45a7974e45ee6fcf5bd7ae9e9abde5421b42cff6af0c6eb7fc73f4deb67bb4e0b3dc9b4008da30c67071243cda649091a14b89bdacf2ae98dd230e932d9b277d6968c65e0006a8ff63f283f2cd9c21615dfd82e0b24af6ff559c97922a3d112ff0ef4af9d6583bec1f84d1aa8bbae705b9bcf458f5d93059b90fc2217ab27d0072a38aec3229d13266beb3015ac2389a06dec3120c6c04e540886091597919da293a4a8c0812d6cd336d5c5faeb64162ec0459e252d219bed78c4b6bb61c1213939bb3cca12a625ce5a45001d7408f6d40fa9466377caa43afe961b5c1602679220258fae72a8de2ac69c0dc97c90c270e306dbd8eb681ba9c092896b19a8d42665b94ff4d5b8b188f19f7c44abc8f88d4ad7b5df1cce3465de377072c70dd20dbd6779336f05ce328ad741d1e4606dce7065347df111c7d3282c8a3fa4a9458561c04d1056cd53ec5a8ddd6bd4434ac910c69cea0443fd09ee32d1256da44ab7896867a0c97fe4faa4a53b6db5cbfe3812a6667f04cd318f3da127a0dd46170cfbaadfcca863e0d4240ebec1cb2a5952881fe89804892d36dc5bd6484cc78db41bed868ed1b321a680a293bc29c420cffb5305d15fba05c76c2138b986f799b6a3d061658e498204c2b641f2f2ba73d633538eef6b5a01117951eedb7611742c120ff24261bea605e94d21e452ddb9ad27af08ed972b7d5e1eae010ec5d83e4505f6a2b7d9a0bb32a1fbba32a2a8c7823e736a69f516b781fb5354be4b0a67343c009a09b8f656c34ab895f9213531fdeee911d677d1cbc5e72c0fd1ad1f3b4b8bc735e14c3f75f1828ea28c90cda40e0cbdc40dec37031ff3d50305d5a8bba1d53d2f176895e53faa3067129a5c97505799967e55e4e9d87faf5920d71055009fd060ad06691b78583f63881b566d4a06b639c55796b23531ea79c6de24092c0e6fb4d3dc739f6d82ee3ee39f229de4c844aba36432d6119be0d2f02e5f72ef1d95fb2494522a7221e18e92cf22e00010ffd93b89fe60b6895a37fca91aa2fefa8debdae3147fe4f01a6adbfa0a59a5203516b2cc7de5faf821a2e72d43beafa30ac379791ad1e5da3286abecfc7a546b80191b7b892cdd01c25e95506471f5eb74568257439aea03300e80699909cc06db2fd607f3279651f7392f80bf4fc61d66f0dfed7b7db09744139d7374d3cdd18d153dede2a65f26130506acc51d5c721a7989485a145dac9565ef6d3cc938c5a51f31ccc88bb0739920ef8f0a01145f4ddccc74790a22a3099a4b57e31b3a01b4118c9e6c393c1304cc51ca1784db5633eb96ccdc88f8b732815b92c9072dbeb61a2cc1e6b2e7098d883e6174f5af7bd4f129389250926e041ba94d1ac543aab6525f151294060791fd26b668d09302c3482c78e5f3271c0150c437b4e78b1cff6f2b8660dc310965f2df14a1f2ad45cd2759433c4f3952402fefd79fff00dd309c3f09a58600223441c11693cdeeaf0a6100d38d612a759a8e01f753982803af30c7470f7bfd1ccf2c08aa0b187382d25868a9fdf729da10bb0aa0e1cd9c6e695eb2c80c6b6ce62737c3e655246edbce5b8f7ae21c473762db0969dc216a93d4db239f67dea74a1de21d50336793d1ae45e931d975bc706ea718a2ab10d66a59d9d23f76969d870ac279611246ed3aab0f79e11611b312624d78b88a9d1a49dc68d6968f7428c33f0a7a65675826422f7ac058101d2f85663de331345b3a25cf76b7c8fe0988a13278be9599b8e4708526b44a70bc31ac5c278ab739e3e6f0927b72507f34b0034e7fdf43364c466bb75b559e03d4d18c864714eb6061f83a6331b3f59dd62f39bfc2529d5cc68bb6ce63db1075105cbd7d7c4d4ab68c9e65a32092e34e76c3178382a965f49386bd4aae307128242a2ffe3022fd7dc1a824b330b9f032d55573c2f004a6905178a2479ba8a2d5b3140ed5f3e10d986265d8b4cf262295658f301b4d36281611d9c61624928da9abc51ff9a6eb481310511772fcb1c1786203d25295e4a319b9c6d65ccc966b4c5795e6e30b2b3ae8246c38b4a911d1904145de63dbd4470fac47f8ee3eeb3f58b5e665c26a316362382ccc6bf8db7699fa3334cb2ce61c746a7d3af24d8030df6759835f5890b7dd1de538cac1dfe843ad06eba2e887f08d9a49b39246fb26eff5cacc937d63c8d0136f7a8ed2af4cf473f3f0d9064f97fb4fe9938d631f7cea3c617c38771553eddd606ab80bf792f34b44111933796fe1fb8bb104223a4de9e16e17321ea7f8de3306e75a2bc79aa5e9c0ec8dde9b3dd1f2ae42a6a278410afa8fb62c16282f1e3dc1e2f8c28d4538a75b5da7645101253dd43aaa150b273f73e505d490490314606264c737bb344b616a80a4931825043a740ea4f75847e98cc99c6880d3085787903e54c63e90b60f03192234ab20cb41c70c6e82b00e0575a1bb0b0f435831c9ceb9dacd1fab8a7328eb3e28533d5bfbeace430e21758cac204631bf033752f947f78ac2bbd9423c2baf4dea22fcc65c96c332ece9abb20fed504643e82f3ba0fff213635910789a2fe1f2cedef68799fcf4a86d63ab0ccd395d6d4f393f7ee8905eb77df32d97592fb34ac86dcf20cbe5afbf9e9cff37bc34d75af046a09a1781cbf51ee2e0b0f40096d85413a30de974c4d1d16ec06c0fad00716c4e10f8dae46ef3cf27ccde74502b657d3dd26b5481d9787f5c6034083ff88807896da55fd2c951a28f15c8c9e6c86ab50c369e5ba4f6311de505c07c7b85573b5a539785820c672557cee4b58dcda948fb51c95674c23f1275b423ee5bf3a646df19bb5dfa22747857fb5c605669f334d116710bd9f1495e242bf47d6b607c1c9d9c706ee770808484ba552c978ef64daabb642a7caddf5a55facba474b8a63577ac817dc57e48ab072bc6a2cc5f5ae96edc45af41c896cecd8acfc36604db3b7fed9d2d17d429f94bd2542b194a3d3405f46c1021ecf6bb907fdfb4b53fe445d5adb18501aa772c9ba75619214384260306ab68a5ab59161b
+Ciphertext = 66c03198b3422cf3fd8291080f6fb3ebd9ad863e41cdff169becde726946a342ffa0ee547a27bae28cc782d95a90b0a618f717e3beb577354bd91e00a7a57485588265ad2dd0ab946926fea7c754c42751ec7247ee84c17262c0ed092186ec57d6044f0ac9deb21da6714ec7452e441e687e138ff144ea95636286263685419afd35f002830765d810b6f60e8dee0e6879995e9272c798b067d5f99f49e460b86d67c641f48240b61a16dc7cc27b048e8b8e8e80016470ecd2fc4225e29bb127ab48dfe7e7d5a65542176dd7ad40c07ac8b92891d595bbd7afb63fb6f9e1c2aa2fc659aa101f9b6a5c346625acec86fccf17f0d45809f3b9ee81572e5627f1afeed4ba96c6d3ed7e9232358dec01a1231ae7b94ad4675239f3b456adccec439b3cdd45504c5475bbc77dfd242e5e9671d103ba71a4601a7322e0e295357f335fa8d5651d528dda66575d106308338993e615b1c5bd7e95bf3f755ff726b4ac6dd5a43ef061ac9783f8f2804c68f66486f5844969103a36278ee0d10798bf8a802d3fee3a31294bf00ee74f087749ab3325c027d42b55b197469a5312bdc5c9b316b20093154e66605941d58f4db8d46a815c06f209c1dce2363771b5a794dd8d17e93a2fa7b194c6a0b79793c06f002638e5e3052365221232cc4b30adf161cc6e7865cf02911e2ac9b0a75f000e7ef3aa4f3c7438433513da7246d421f208b179763651f18e22a793961e5976a74744696912f22915244fcfbefdc472baee0be1e591d6503f2d9511ee1eededd9f5547c95eb94de134d0c2186109935207a23b2b8420a5858d831ed78202be855cc6b98d6663c1c52e1a0022ed7ebe0eea6b107da4cf50c1c7fced9744a914a66d4604a081587ce4b7e0f96ed408b8a9a2964314b1334a123d5184889958e6467a6d16e7615e5364e09aab75994e2758345511113321a3436db79351c63a282095ec6b99b6d775a5c09ea3f3225716e39e14df260bdefb2ecfe9a65c73ab4b3712ec842e43ccdfb535e3685fa39b4912719e67bbe195e5f0fe6c3aaada2d81b669c4565921f6c183d708b50c3f7172ba841815e9351fe5fbfe2fb1fabeb7cec9bd1dcf2d6332372f1b972b5144aa7ed6c5a985132f9a54469097e2e981b9e75a7df48fa79d0736c6f8a201c7c7d0ac8ac6512a7089514bf58442dbae0529135a7f2455e0ee5716c6610bd7600b3159197bcb20ca055695a36597bf7d3b18ecd08031b4ce3a643951e231c7ad15481e32ed7a3edd2b379c8e96d3288d5b93b562972a04f1b7e0abcc5090cb8655422cf5e9dac0b49678138faec81c78f113255eaa6110e95406a7e7417a6e221a8ec7fb9d55643bd589ace2da70fcb41722e66e0efce932cd7a34218375b6dfa3df1747953b24a41f94e50b84bad4d130d5dab4194665338e06f102f46badc5dad7aa06edb01f8a31244dceebe5e2006d6ab4a31582ff46731b19071c08ad1db79ba018687f3e6afbe703b1de26c11bc8b62fd6b2fa3219fa7190379504820abc97ff6c034f7850e2c7fd335462725db6748fe45920c213c539356b691f22eb490faca24e99f0a044a9f727d0786566ad00635983692ef324bbf1f80c42b269e9d5a8df3249873c51521c81400c729ed7a5e73995928abe94d189cddf2774f1735bc2060bb2240e558699c365dee45fa68801e6a1745e03736ced1b89fc2755565e3b36c2102594d43c451122d94f4a263664bd26b2fb5bc7700319f6b08796864f92d0fdb41710910bbc13aa9cc7baac3b48a24e4f3573f315448c317c149ddb433d9ddd2a2f0cfc81c22d3dab31f184975355b41e4b36fd8f22e8efa01d61a5cbb0e4fcdd273cdf68ac73fee745faff44d44d93c5a111aefe4a5ca8e8e7c075ffdb738cc5b6466dff78ddd837c72c54941707b04d60bc126a3a2fae9540ec2e4672ae13de0d927a7bd363f8abb5a56364d6d564df90a46df9fd59e2c54d5bcb8280415257a6976d8fb24c33330af32600cd1559e0eb05d55b34be456d434bca98252fa531486ce2a24c8bdea1d57d93a550ec586920903a39ca61cbfbce79b8f3a5b1653794872b2c614458177e748f8dfd43840e5bb0d608c26389347673fd0b005f60f52c56731ee5faec6c8d0617fb53d5f2415c2e7906ea0e6d0066354b213b3e94f4dfc311e4ec6afa7e8d1c69a63cccf8326741456a5e0bd0a359b7a37c117f7892969ad7b70cba9bea0a975ada7cf67e0d7255be8d2c6e7b8788b9ff14c5d1449d6173e07b5f9d94560d46f474ab2a67056fe9f4a9fd617a617d23143adb4e7ea35f2d5cc1398fb9ed43ddcd10f28debb27eb13533110005e6c78ca4a874db68c65081ecb8bff1b64eb1e2d7b76a1da3b375dce8a92d32a6277ed847879345717b9649f27e846a701549311c7e69a96d61df616157a114bdf1663ad93a26c28e1a62ee4a7c72bccb9785639eaf1e569decf777bb0548ad9ee36788cfa1150eee3ca3c96f09052ba2300cfb7526b9424b6f7418c27a1e9bc13e4d9868e5c330c051c3885e44714bddf7cb090fbd0f36b826aacbe191dc8c35c219e19fe736198c29dc4fa1a98b5fb1805dc29ecd02f74d4510a3928448b5ee61b5991e46644850a4885bb1ee272883faf27962430de1922d0883e7e80215cf5fe7e8f3fd0e2a49bd50727af793cb7e5b40860e80a1fbb9d5b5696bdf2f741909ab5a713de47716332df6c4f78288edcd6ea130d895fdb2f29f94635bbf2061de55f1801bd6a24294aa199d78021a1ba771c651de4bc08f032fe6ad7a5caf6a6afc6de649b901f783a0ee0fea9b803beeb0f431400d0707f159d7dc29c0c334a918fa08a653137a4a8bc86066c8800e1d171f1dbddf1fab8a3eff6b5023da96f002e7e217e826fa378b15dc8a376db30228f5d6b629f331a162d63e53e5b5bd7ff9ec098b4314285908281930ff0a8aa86a6d89411e6b5bc6b9c9e931623ccca6741fd6d36311e6a8e323a37ad40b7a2797b84694e736d9c135e52d149c760e727598726378cd674b0f4df1c361de0a12a2b8232e611d789bfbea699e8e77b99f3449609caff3d6ef7233df8cfc624376c905eea46c6f77c0b01d288868a19db77e227dbb5bfea5cc3f49d219c7477f7f2b3447b0b8efe08eab8f69579d727555e547c13ec7ae13b83386f2adf634140c311b6e2759cfb9c8aca1c32bb7c002d0f46ecc526916589a29e328ded9679c2163838f071b5b85b35e5e7d99c3c45d25bb9d37d7bafb8350ad4695a6e0cb7ea7d93868c30bb54e301e21147696b7dda156226a5ef8c62121e6b2cad0c4e192116192012468eaad46bea69a140aa3cb9056dec87c911636a1e55695b9e5a27c63cd8c03f31570d4b7507d13731ea31f082b33c6db8dd6e22282f9790be41350a96abfc4dc3de78e0a698930f540dbda3fee923a463a4c4a66bf00bb2cdd6d22b62a47af96b78b1f0f0a174e4ec5b785b3820f47d3c8cc1691d4751ce4e4ab78a4551956158a36717dc35488e890d0631241906db565603205e054815aaaaf17945c3372dfc7193369871e2e88fb84c15a2b9071101e1208177fc18397e6af17b5843e1fa75392d8d3ed214975d50f2b19c24e83f010f8c394ec1edbb1cb912e61627d2760b0e630b986bba2ae113b8f3b51ba00ddc495520274a85e6f6fa7573ac4ec6e2a86a1da9199ceb007aa6f132e5ab8ab8fdca7c829f452ff17524fec475b8f485b29fc6f0d972eea4ce98e242b5d58f6ddc1b3a71256de1c584c9914a3cf1e469f0033165d934fae68a7559011dac7a4e0c72e3b398fab8f8cc2fb67963b0f9220f410e5ba13026a27288a1d49edfaa51e8f220503fb5ec476147cbea975994fffde3ddc51bb189c470078978d238f5287fb2629d23989875d74b006a4122f6a342c996d4a244e8c5e4b804a44c301ac4d6054181a07964b279e0a44c158364395a2ead40053d2f3350ea0529a57552ed835513f533ee0c4b94ef674f31851616a4fa2d0302d13cd4aabf5f96ce28219c0b5bc0e5410fe0fa387ba1009a6f2280f9e7bbe20c33be5eb411a5f6327714b3443b4152cbc54c4012473237dd98b0490fc4228ded74afc81be2a58a22e03ca987faef5310e474f4f5a183f6b7ebede5a8df8a0f94a87a41852826b29466fd761f40b416ad0f263dd34e5497867766a361af1654c3fcd6ee7e6bb3f72d64cc980f04305b63bd574f116d1aa35b4bd642cab0cde6a29139aaa163805c6c40384313d4ec6027c891023083988c1b0d2edbdd9b1afe102fbda285a6f897efff72a0d7fc19a3cb6756cfaa2371e13be3cd167cddb90d525cba7da69608b9995cef92a6424a14df6b860ef0f09830fd7189497a432347680de0f463c0aff82df8098cc4f7753f7680c8c7374d01046b05c63be73f3a1623be778fdb0bdb90d4fb4b458af2890d15f108b0927304c91c8d62cb148c35cc93797db3ef9bba1014d89859a91da0c0a971f330600d71565d30e9c9ea8c07e7f629e1a6d578da04d37e597261cae8ab7d9a952bbf71573f1bf70e064f36c032cc624e3c980e5ea46d36232d61a57fa598347b7fb6b28401e34628b051d6ca3dea190d1d3c343fcc83175f70f77a8fc5e8791b9788989df1e37cc4881648f4fc673772003079adae55c83cf02a894b98561e4a6e4416bea3df18d6f702ad5c4f40faedec6b53cfdb5b3a52d7d43b97ee23ccfa2d30c7264ec555b15f1d9e7e19cd9890a7e8e01ff21d3b8b451e50932f189a420d18e7c7e2f103332c78c84600e5e8fdedd84f055a8b39be9a52782d47c6205c0de41644b09c0931f2da269a7e58e669f3b61ebda28ab8e3f9b83ff3d2bce37864af494860b2f01b000abeb737fbeaf8f9fa6378366606dcd0fc33031b94f9a7a0e562c08ea720a671ff92520047f69b138b4e032c3828874ec4c29e49aab302089956566372b20c0216b601c3958ed9691bbd89f1df45c6613d469e3b9758a70c860fddf768b10a6bf70237a454a2c0b70dd5d02da612a91fc5731513012a4a6fbc16d01550bdfdccaeca22bba104ccf6aeb19f21d4cdd3da231af8ec5bf2a726ee9cc7c85b8ed46d2f6fa4f1b010b2561fb69690d5a9df76d729450a6e139962bdaa2bec0254c5a252b97e7ce7eab1817f454c6121130952b8c40628065dc9b77b0f953552f5aa3ff983b6a51a51dd87c2b51a18e14adb8c80e002d0b47c61cb357babbbe3ed51d371941a8f111837ecf0e45020cb941de170c4a1b5e61bb928b1b11a8d902febd2ba016771f171b8a7ae825fcc4642d95649d53675d0027822e4ff79ffd302bfab1a0ff26f3648c7ab00c10f8d95f21e40ca2b40691bd4be79bb9ccc0bf760a05be4728bbc0a64e585207d1d09393a80d5f574442d6a933966777ab05f699c4e84aabbf753059287e7261d972745906a4fd8967bfc80ae9b6ec2ee1b22a81775f4f24999987365ae2dfb6739902ed51b9a4394fdf29f216c34567102d9db301661b09b728a79e377cf4bdfcf5c83b110a2e267abf6d40947e643ae2ff0c244af168c9f33e7685474ac30611ef95f218e0dd280899a92a41e7a759d03ce3709c2a140ebd35e199f1dbb96f7351cbe1f3de8da8c49758a49b9e724ebd3220ed6f51112944f70c0d1e9178f68a2c9476a913de00abbd1f5bcffa646f926da77a9e9fbdf81cdeaf7f9b13e843afefbca81c93614f8f1675325965b5836b8a77620a5ff162e25366718d8da7781e1a7e01fe2e9e56cf958c6273473abf5c2c8c7fb209307544e1c0726d5571e521621b18b6da3064b473423536b1b76ed75b21b4ee205d7ab5f081bada63062706bd155672dccf84614210d72660095437c6bc2213d9c904a4ba1bfda14d350fa3dce7141e817a50859b1a74aa64560b2ebc67add9f945b6e85577589817078c8ae54a9fc311593d2cbdb6692b089ee6264cebcc7719753f80e30dbe48b64fcfd1037fb9ddab69a5ff9e5898bd8aa947d9ad827c26df67c6786edcacb3478a20bded1ad8c48018ae0d439bb5afad5d39bb8fbaf22d72ffd759c4fa2e94a5a89f41358ebdc4c3aea5110f1965a049fdadff9cf703eabe9628e2680fa4e70320d304ecaed13f513f27220db1916ca1500f1c2e091671fb71329dec0bd6e310c83e67af61b8ab60ee1a8d559a508d174648b1bca451ef0ab0ee2ef74f4fcfaad1cc5ea6cadb8f1bffcb1f2c05122011ebbf6abc16838e452fc47653821589da4cb5bbac10deeea3ba0e0a6241338e64cc78d7a923d018e8b5b51c4442070e5b0e6f1e8c2b83791e930899c5897a602c401c1b85827962ff56d19c06f5af033059bc7fb1bd29b65f66aa5b4397834e846935e523b16438a42c1f990ebe4f83182163ca5fc60a4c6d77fc182e81fcda943a962e9e7f00f6399728b48bbe38d8178fae3582c8d9998e49df5f28e32d541636df3cdc8ac00df45db12da2e5e76f366c1ea8667ba5f3542d21f58ead7c55d06a4b35251b8f77dd34d3de262947379107a06d2f4891ffa0ad3a3e5bb2bbbb978af4953310d4cbe5525ab344ebb98ed24d003600de8f3af36ff3d0a7efeada963845d573685bec2221403b994f97b1e714fd7dccc300b62c2a516e9c6780983062eddde0178e93fcbb2ed4f06f60767356a11d22ca37078fda1ddb3cb907d1020f62ba85d09044574ba28aa3df36988eb8a41e4305e5b0687abe43a90e4f68f0374b6b05049aff5b065d7688cbbfb0e96ab03df38903bfa1c269f43a114085eb4596aec87ced88701b42f0b7426389727308bf10aee9d8f15ebdc411ce1e764a290a12faa2d7c1126dc7b5076f219b826ac8d380b69af7f95d69fc3929a97f5c7da1db6270e9ee1f2a5f7fa3a1b6bfcca00463655121f681d3a627d03efdf0b5fd045fb153bc4488a9a8b7264373c710ebfdb1c267fdca37723b21d5c3eaef48e784bd76e27c133cbc24d114f610c79f2a1f2c30d87ddba395887030b65097ca5566eb0361e70615b46d4b86c2759f1cc2efa3915b4cebdf51a745fb3c6cec69a1fda2ec5e884dce228e30af362815d2d8b59a14f89606bc77439042109369a9648db7d71024ed6df06c8ebd22e8623f48feea77f48b5e88827fafa84b0564151a5997b7f29c4d3d18068e34f2690a293d54003d0ea8f3bab9387ca72212cedb5f4602ad047dbffae2ab3a4cd2865bf896cd96f78b90e4017eb7e3c7092320c0a37f81dd65a5c4817a4e7053e6d2bcb23b11e09f681587f3a9361e974ad54b88c72c296629b1ab754d25be15e87c414cff975fafb3d7cb68167b21f1889685a48966705222b525fa47143b00041df94817c275d93c2550fdd82471cb3cc1b5644338060b767e807bca902c180b3e535c77be2651b3962287b6d1f6403033de4e0aa3a20615ab59d290f4b167325959c1524ef216dda2ffce86b50cb6b56b62a20a043d9d78c704479c22340151df5a1907670f8d4f8c90d93f7b5d94d04a4d383914867aa3c0e5ac85fc299a4d2801a3f80f4b0f046fb62c1c8c539a83b21c7549df0afe200537b52c80ebdbad8a438e430cf876cbbfee9ceb1bc5270577c27d53b40ac153cab377a565b1a9fbdee8bf8e94839c0fc04f7f664383bc90d56ccd1cc01b465c250b158b5e6f321c20db245602d10aab80c553d52f17282b095b5e2234c6c689a84b096112100359816cef7e92029fdfc048058f847cd2f2369ceec9fd171a0487bd7acfed6b0319832df6d59affbfd460ce8d12e4171da0f094e872a2888fe74925c5ef0621c4edad337f7006086748913b24d4d48ce36e662fefbe672b6d476456b1fbac6d80030ab93da93acb4a7e10f955547e7e20a0abcdbf909f05a2ee2e0b7485fa16be652b9d9fbfbf01f082488a81022bdb69af9e6fbe753e9eb92a1762afbb4df49f83ffc0cf03db563aa96fc5ba1af6d4d7eede6067749e8ecec79b63e09742e29e99e1c960dfb0688b0222c49ed919379ac66e3fa1c72645122d1664721e78fefdd1224c0b886f6e214e37d268ca9acab76ab3adc9f5549e5dcdbb3d31ac34ac472894d004eed71f88ca2377fcfa48d3ae43805dc612891dadd06c263ed8617194f890bcbb964f010d277ddce1f6682e661577ecd51a4d5421f00935a5b24fef0ea1809fa5c4fe9cf8c453046f61136ec8872915d2462157d73a205d56d77bb83cf16b88cadf6430c0e5397fae1f91a6a11b177bf04b065a2e55df81d5c086ec8dc8a0a660eed37d41fe4d8b3e3f22238e2a63b6e4feee1fe9a140ed37b2be4193f75c2d038aac7f6b7dad2a3b37e5b9b660615ec1db77a9b7ab416f43e66c872b71cb67c9245c757dc87723ab3b9544fdd8a16c9486e8ec3c4a44cefd98535d6e5683426c1cc8c888b8e0c2e7528bd7eb89b80d9e00969efd2f0a0fb09845426edf0d1d9a0809648e7e46ea0a8c9988bf9df475be12a72c7326c1f2bf01afafb190cf6f649133c7dc14ecf9b8c971135bd303c8894bac637e08257d45e1b68edf550d896c41682c002396e8f1eb7c1e2f4e0ed9b8b7010fc7847e6fb1c5907c17b2d2b7cd24c96f47406bd04cfcb2099d82dc2902d6f91e2f8f3a05bc62019af536309e7847fc06c10dbf7272a1509079fd16bb16a85ae2e078f97f9ce66bba66d6329c7ee70f9688f6d91aa38b25c7f4884658a72ad8cbf96d7d7a9652673273ee1b3d4d17780dfe9ca865416e318bdcbe9efd8e071fcb15ceb0743df5af4f7d598b31e38677e65af61c1109fdbb11fb11e3952e6c3ae8abc3f894ccdf205ae55dafce1dd05dca6b899877f57d712223dde4e7fdec7e0ed4f0a29ad359e318eb36ddb42fb205adca400f5b2615947c4f0ede95788093a1152d88acbbbb272750823151e245354e658452a95f21fef05bbfd98a10c1c975ad1a08c59fa3efa9fc73588407a83d0b26a53f1b4115f83780bc70ee2619d7374ca45b9e200055df1b93977e17aca89a009110a6e74caec7f86114f91975bc6e8bcdc7267ed2920cf12cd7137840628e1b8a0ea181dfef18dc5f74e752f842ea91bdce4b420ee709bca72c4514e92bcff55902e5529d77fd95f5837c8f4fffce80c813630550a0dde24092a25f65eba90790a06f4d4c3e739aaa8194a147fb32e81c71d3e8def79251c33637661b0a621a2a6b302dea00d34a9dbe9b621c1dabd0464e85241aa6712d90b4287cb23c17bf1e4d0e6dbed372e6b49c4a843305b3b0e5cab0b0964a93ad0bbc99ee711afa7f2d0a296a375fdb3176c65a957ddd9b88e9d57df736acdeb02a71b924cc2e972f51ba68a597215678573bede9ca5b3a0a2461b2d3b9ea57a5af8c91d40779bf917ded32f14a66d96e28e1415fea1e9306654c6b84d8a64243a5271c1f11590423c718961aecf5f659b49f67efa78e02ef2524d0966ebcc446d73d49ab7ec31f0c009069d14ccd63f926169291b83a3e37610054b0b964741e2ed8771d20bfa225eac0280b4d5af0c09d3218bd497a035536f5af0816884d606f1a872b8161a266466b56e0be8b80a7bde65ac706eea8cacf1749e5e71ff9fa3e69ce878427a0728d44e666eff977026abfe18cf3ad156a943b917e72ad65725a9a8d60b7b5740494fa63143a7f2a94fe6d8b319be55d6fe1a988244deb798f345f30dcafdb6af9e9cee9e35733274bdf3896750897371563ed2516c4ca6c3c3c994b48cc94b67e8129d234a0e19dabe39e500214c0ed5f0e5d61b2f58d7355d147102d93b2689bc5185dd4c0a18efd11a307b887d4d0fa84fd992731b3a80dbd027dd36cd6933766c537e8e9e27d35d5187e8276b0f59fbe7b6d629d3416b782e7981d85e1e890853c3aa94a93c1667a55044ae42badefab979fe7d525c6a180307c5ee3a9c3933038028c3e1d15d1e78fbf53b6ea61ac5e02db0161719398a31570c55f73cb47ddec8f99e3e14af5adb8d5cd179f4204d080331e75bd391b19d38eb81f148c36af3e8a3ebe76209bb75c9741a89b5d0708bb0fbb0945fc6fcd6ce142d19faf0947c338dbc8d976963281866b5216421c00cbd77c0907d1e16f5e925319cf6c62f8c6e8eff0c2f831c504e7a1c0df09a54e2af708ceef39ed7d0f63d83429e9b0920c03cf85c2244f2fbac3958847113bed577dbde8992cd91be5833c75faedd5e2005d4f7b66fab8fa9305927406f863d1795dfe04028940b765bd79de6972dc7094fe1c2503a73d7b50208835216c23aab3e47094587549fdd74bb50ae21cd1354daab632fd0907e63f4c2b2d39d7fdc4fc216bfa742b4608238623cb7fa01bd851c1e7ad5ef5215173a71f363fbb7dae8092486f4a1549e32ae53b14c1343ff7fb5e2b1487d9c594a1b56e22625d275e41535534d225b7b2c9deeb0d30dba7188cf75d680d4545ed05044a0661c690a37fa14a73ba8c68357e2c948e290b5d9a4b51822824614ef2938d19ea4b650041f59f3b548f0a305b86f55e69760f37f09dfdad62651aa5fd84eef28a4431136b34a49c9bf1f2891364f86b0aae70b0414e821e3db1533b0f1db5fd232308bf118f858aab5ae974c10583f61b283a3870eb82aaa8ea3c4e2ee3c3a3d7169aa8e975ddee7f620f6c5bcf3eaaef0101b62cd54495cb8809052c9e3151690cff7c1efcc4f63b22472111a7c5d9d7d2a2be951510f60dec8c426f14700c8630f8a14dfd359addf5d9b7ae031a745ecb4e17321b385799c90f924c4780287ac187530a40b064064b9036cc46e3f87c4d23aeeed1bc22a5411c7c503594d5d1261eb9fc4da242493beee9f671485a978a32e965faf9b0e2c13f78e31e1630b72d35b4be691e90b3798e18223c1b514b39a8e1eeb7897c22fdee1e33fc76e2b2f9298ad4fd89f44163aaab23d754d98c7890e58708b81b3832aee31aeca85e76416133710aeba0e5d9f17695e607d09ae3f94be191553bc39c6df03cefb4ee05516fc02d66c9866e4eb0d89a662e309379a347159db2e070abceee226f2b8b62847ef7c51d69c5f12eb567fa13af4b4f90b3f3d9d4b6a3f68bc4dd77075081e2e99833c18b154d0d6ac360141de2a25af61d551f10a34e03e1419a37409b4c177c51a8d248157b411868eb607c34d2daaa453a0954fade5eac45d5f21f50efba8bbc9c87ff0435c70f064b42cb2d158384fe0a4d9c90030ace7723af0a6c8faecd8f97f9850e2a489a94ebcc655301e2e14711de9eb08726638a9ddb57160c5545c152a26860a17dd18172bfac138a300f60431fc49eff18c93f71400e887f878f4dd637cf5df8c1e2b12c0f87e31ba2754ac1748479eda0c4184b528554106128320dcce349939e5e6cd3434f86dc7adfee28c008a21ddf9d0dbc87ceb14cc3afbef1e06fb3f9908a4b14f5e6c43b23ba783b75a6cbfa2ebac6533661b8c1143a34e8e2a9723389c4b7087dc07701c53b169894551084aedbb423bcce2f470881fdc7240c26b3b76fd6cfeebf8eb2828b4741e5e8698b19fa0a44703cb4e4c8ed6a7e4d6063f5fab724e08a159f4f04a2f351dcfb6335ae6697dbeca25c76b55e6ec9045eaaa8706902df492b8c8cfbf68c4cc1be5d1e5a173262e38bde051656ea85ffe35d97f1b25f6a47381bc327a946f7cbf6210adfd957b2921
+AAD = 85ddde4720659e80e25168585a354eb1e021c0b5d2ee289f2314dd5aae52bdf1fd44755bb56a6e659111a1d4b4da73315bde01c7d2c15a4f7114aefd68c141049fac27acfdca24e65c51fb1c27d307cd948e13af2963166bbc9411401d124f1ddf20f890db5611385257f52aa05c09b467e3ae886decf5744ec3749e5879f2a60017f601bbee11a66604d5f3d521d2c48cea1794f77366f29c7bd12a8aa51d34a4f3fb52809561b527016bc6badf9d136156c330e1d69d1aab98c7caa9cb46e782a898b4c66e4ee3e2445fbfacaadf9a8f73c4cbcb2a1ceb604ba5637b51337fcbe0fc366da98e805ceeb29feaf05420113b16e1005079c0e88af33f5970b3d7a8b51d0d9f5120a0795063db508171b75ed07705ac6d6bfe4ecc59243091d48865536515e036860affa880bfc91aae2fd1700de15994792aefc4a176e5d49d0f9135c7d670f3cb8798bfbe83fe73de7427e0f3e6a2df561cfa15ffe6ae80d5016096c8875b0beac8cee8fb530fb421b9a8ada4d551a528d0a0b521086f5a2db371a3bf12a2ef861f831fcb44cb2baede907a9306d3e5a3af796e0a50ba2c8dd61fb03727df5f0654d837dabee2fd90eecb7b2e8f303b0d57f97dc6a52d8281574d8457c89c6a9f5d80e0bd86c90ed39b1db4253affee614e8cf1ff05166c66e7d2a2aa2fe8a81c4741339683debe189c126e7f553a5f2dc16fc16672f74aebf94c7e3041c758fbc6d0c7f71c192cfd0fb2ec52d0a0705b05815d567f3d19f9b5d553a2adce9a79159b0e38980851bf64e97f896c028a6df8363cf1f13f4654265a7b0c0b24198efcf4418c32772bafd3980dbc689fab12e85b3ef4a491e2e5ffaa2fadaaf3deb392105a42380797d3b41ef61303a6016b269ec9a9f6e3f26070ff33cb467435ecb325dc7e18728a5c2e882e720c8f876fef10f5bffd5a925cdc9689d934272019e90e3a3bbf63a295f207faa5c014e1517c7d5c18c3ed70e92304d51944dcd3604c999d4aa8d8dbf2a4c69cbbc08635c968a20dcb80f438d43c57851c4cafec0b9568dd6c19932fd3f1294afd16f019f20e40ec87f6f5dffc7717470614b2de6e9000969e6b7e561cf91c06dd379a09c6c25c7841330dc78fc5be1d9b86581a81f55c0289531128638441fc98a1ad9472d74e2be2f874aff2fcf9c941502f59f716185a4c39289ca368c6dbf5257b5dc5e57a420792c26e602e4ecbc4f17c8787004eb88ea091d6b6ddc3c85dc110b5d1f46f6e1d872723176f4c73664ecb4219258fedce19ae22360354fa4894fe51d69434c2e58e1ec665b5cc33bb295053c591b474b6ae178c8834667bef971604279440170ebf3e739a4ff19704e5886767f81edce95a3dd93d1147995e7eb6c794b7be136658ed23cec7c374705ec0d8479dfb44cc7213076668e5fbe6a508537a9157815c6e5187b89f
+Tag = 469e3ef168a64945f76d7a2013f27b68
+
+Cipher = AES-256-GCM
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext =
+Ciphertext =
+AAD =
+Tag = 530f8afbc74536b9a963b4f1c4cb738b
+
+Cipher = AES-256-GCM
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 00000000000000000000000000000000
+Ciphertext = cea7403d4d606b6e074ec5d3baf39d18
+AAD =
+Tag = d0d1c8a799996bf0265b98b5d48ab919
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+AAD =
+Tag = b094dac5d93471bdec1a502270e3cc6c
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 76fc6ece0f4e1768cddf8853bb2d551b
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbad
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 3a337dbf46a792c45e454913fe2ea8f2
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a
+
+# local add-ons, primarily streaming ghash tests
+# 128 bytes aad
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext =
+Ciphertext =
+AAD = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+Tag = 5fea793a2d6f974d37e68e0cb8ff9492
+
+# 48 bytes plaintext
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0
+AAD =
+Tag = 9dd0a376b08e40eb00c35f29f9ea61a4
+
+# 80 bytes plaintext
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291
+AAD =
+Tag = 98885a3a22bd4742fe7b72172193b163
+
+# 128 bytes plaintext
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40
+AAD =
+Tag = cac45f60e31efd3b5a43b98a22ce1aa1
+
+# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606
+AAD =
+Tag = 566f8ef683078bfdeeffa869d751a017
+
+# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c
+AAD =
+Tag = 8b307f6b33286d0ab026a9ed3fe1e85f
+
+# 80 bytes plaintext, submitted by Intel
+Cipher = AES-128-GCM
+Key = 843ffcf5d2b72694d19ed01d01249412
+IV = dbcca32ebf9b804617c3aa9e
+Plaintext = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
+Ciphertext = 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5
+AAD = 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f
+Tag = 3b629ccfbc1119b7319e1dce2cd6fd6d
+
+Cipher = AES-128-GCM
+Key = 31323334353637383930313233343536
+IV = 31323334353637383930313233343536
+Plaintext = 48656c6c6f2c20576f726c64
+Ciphertext = cec189d0e8419b90fb16d555
+Tag = 32893832a8d609224d77c2e56a922282
+AAD =
+
+Cipher = AES-256-GCM
+Key = 53a6f0d9b8a81818f2fd7525acd65acbaac82684cda4fd357b1ceb6146b31ee4
+IV = 05d8a92b5a510c3a3dacbbc0
+Plaintext = ac0ae17d3d0ee5935e18675c36d9e43967f6da38dddec14c7ec574ff8473e11ae5019e638232323c175b7672a7462df6709f5014bbe12a1370a1ffb570177927106f995dc8f35bd6e6228de7c16acb71e583c87477dcc7b17a908ce01543496c2cab8a14a21c43b18fab52d8a882dd1d999b4275db34c7f32bcba624d128580d7566a2da4bcfcc4136d58816c437d21e90456fc86381b946b8955f0448e83564165a629cb2edb978e5941010ee9153b054ee429b315058334ad7899aacedbc0bf423de69f57c633b56033c6531dde29258694045c46a797987471ae6af8fee8ad0c1be4149605064aaebafd1c5592e61beca9b5c7771410a276c3ae517490735ddd6af499ff705b9fa68d50650e60c19f5ae2c88dbb6d612afc7be28a5f55556a2163b6f66609f7d9ba7e97c074ea39a618727421fbfbb6453ffeefa643decf11404764515d28fce8ba66b8c85d077c47a54125a38bcb6b0adf6d248ba0a9ea129c887c66ef537c45e9fd3c17ce352e3936cf139e13a5946a7dc9dcb6423ca6a051bf560cfc572ef366940e71c81aa302cb9701f9a5206e9eacfe9835bdacb6425d058022a27fe73e5edeeba98c7a3edb761578ab2ad5a442c2dc1cb3c143c6f18dbe525fedd2a9cee0ada3b2c116465c5cca9a7e5d4374b29aa4ad8adaff8d6b0d1ac3990685240ce022faaa07241f9ff445566b9e0463350792cadcafd5fdf5c37706c0025b3c627185b356d39dcb2244b15566e6e3f8942f730fd6d855daa1456fe294f9156c4b5131e5bde7f2d938ceb6c7f5deb0f847a98b7fd11a3f5d0163eef9bbeb83cfc96dd8eedd447901ff4d3a35c0ea1f691b01385eb39fd265f756bbd77bb61b1741db0502947b4b985382a08a5916da809a8afd3fb1d78d9e16f8e37f51aba100d031d9da8613e9cd2cc621025b47150b3e76775ab23412d74334bcd79746cf601407481310a923047ac68a4e6a7f7b96bcd85bb6f24e38f03c80ad41a0a581b4246ea4715ee561cdc5384a51a6fc9ed8569ba6b12bcd95e6202ecf834dd9062ec539cc8cc4ed64ab9ff85998da0e63161e7391b14de47dfde41523b6c614618bf2fd1edd68a5de1c03c4181569b6c361d955c637abbf4efdb5dbf2f0dd2544329c44b77081a48f53231fa9d4cf6f2186427e469d0cfbcd698f7e7cf773240dd2b807a2fe699f0ceb4a2339e9cde01114b2aa5c3591a82a3a27b308e1e7f092af8ad97bbe7b28d78ecd80c0c0a28372193d66bdbadc0b58e4d5408acace53bd5e12101fcb25754f8c545340fbbd1328287044a29d18f40a24b4084febebe228b67cefd970df6d44ffdc033a50534e5977bda660c589c6e3c3a28b4c500b29ff4a1c3eaefb068784a29914ecab7868a43999833b0b37ae79afe58875a0425262e0ec7e10ee8a6bc1c97d332bc2a6195de239a166486a3c1ad8de3a026e5b1757f9a778a511024a260c9809ae3b22d78f18ac483281a796b1ccbfe7a9b9f357d12d340e20bdf2037e8bb91ef858cdf2eb9d7161a756d8c244c55524f8f5be2e4f18641bc4c2409c14816846c4655be716276d8356e516640da49e8412fcfc7ac0e084a079129b23e54952d8030e1f8ceaafcd322dfb4bd189bb5d940ac83231de0585783387d0642a245183f7a251779bdb12c63e9edbf3d0c94281140598fea9e73e951ce650c984cfb1398f8813abf8f8827af5eb64a65dfd1305bccc45086438ac439a9265790fb225c509ce3c9d39e25d2276d7f3c06d7cc28d33b2c21bb38b50dca5b10afc09da83ba12ee878e0f6054e8d3e78d731671de4f9d5a7b97298b01f37c7e78e5fcf5188554bcf5d42559d3b15153bb3cd5a0d1cc4a96d02ae8b1b115d1ff617b6ad894ce0585f46a2a5f4cc1b83065c1d7b5d2f25f3f4bf9966b4c7d7156931861d5edd199c126f1ee4ff6345023419d0a4c87f3388fcfbecbb6c1e2f4745922b88085d21d4551e4c127eb423db87a51c9f9a140f8a7415dbd70c4b0173e687a40f895404f2203e14ccd61e0e5b0d5aa3fbd1c8affb5807d787d840916ece24c56c50d3d9ed9f19d73f2c80c461b5b3c07dedcdb41402c3826a958d74be48382dc741dcf3e0eb8955397da33941fc47288147736d778914a57effbafccd4cf293e6ed1c7d19b55433bc0363e41546b3638a4c630eb35dc6a074f90185cb9daaa6eab54825a4daf76f49ad918e90e5777a826d6d5d52f32f7ceaf818f87251ab4d1b5406ae94e41cc97fe022b144f26335829d9c81725b3daead621a0df71313d18214ff8dc687a7ab86b8eec3070ee1ca9f62005a0cc15ca6e2f4fd893de8fd91f6210f6c96a576024678535c962a2dab06f56be377dfa74bca089adb7327abd05c3ad7646b5e9e6fc2f29916b34c8642f3c0caedb53b8f30c2a77d1757103b7ed156cdc703911366b02cde87ce7343886987f7a8c028921a7b87c5c0aca7ada34970a6d0d32eb1b177ed8e64c1fc6839b9d08acec19560bf4a815ca6187635f0cabb8bf062e8216d3b09b7abd99e956734129e16a7c4f3beb850fe2b1548729355f9015c9bba336d3e26a27b3d75d75722f7a8170d15ebf77f325c97778a5a9d7c76d3e101eeae354e54e6fa60b58cbdd900751854ede326b58fa5caca073c630f3719d6f52afe675f10d464e8b58e5fde75a4f225063ca48d76efd1b645e4bc89d98215beae765601f635a3bc8cfc08d74722f3d95ccb4cb4e3ea977d0c534a4abb866fb9a31771222cfd998231c30bd16b6844ef71038b67d72c910cca40db7260dff0b74162449a9e2cf15d7dfbfb3a685080e6c83ff4341c95819c0317502ed49af7ae688b52c9866518f74d69b4144500ab9d5a0829b9287d5fb67b78801119ddae7a76e80be8c4dbcec7866ffa7d081406e51cf617be061530b539cca7e1ef9118cc06e8eb2a01425b45947a1d2332e360acd0654bba8f1fa43ece68467690d36f6802a32f03f9ea056e57fd548dd4a3225ad5006c6c931aef1990639498dc88a23895ff1f75520a8009dbde4debc20ecc546e378eb7ed5ea3740d2244036588471d96e4751390b6b76b39816d853944cb5677b493b36de9736ba0fa404ad4b3a7d7c54d0c15072c040064b871401b25b88559d059a9519c7e2446b0d110a4aba9c12555e5f620680d1fea2359bc85cd15b5c0bfd6b3715d647514118cd60483dbc9c83e285192108f4ea6bcbee1f0935044610c68d052ccaba23258d09465d5521e2664d59358621ebbb8f28a4627362c8397f0a9852e5d8daf53a961d4ee66299e2b54d8adf5134ceedef57011f810aea76262422236c3e1a478a759584c7880fb3f32389c4bd4b637caad7b2bd6fd295aefb150754799434e99e0fd45c1cc4698ab14d1f63eeb06e53797cbdddd45e7f87e85b45a3dd0df6335c3b1addee87ba953bde29ed98042d745c1465a967ef922993798966e1c8b96ad6f68404136be0caa2264e24d8d93aa1b99da9316c7780904753d4e0b45cf282b43a0c91bc9ff83cb25cacea2ea72563b2e759b69cabbb6a50d6a0a5ba545622e5ce576cc301ba35afadbfd1e26668782e1d741feed8aae894b564a425141442fb8470b325cf7c8e1552973463bf4e67a2ad58d15417e418bb91d2df4b1310a0a70ac744bbb4245efd2ae642609079a44cbf6be19809a5ff7ad6847432368c9749cfb336ddcc0e6f52a699b910cd24671f38af5dc39268a3c87771f07d53bf220b7c2d5058cc7b0bcd492abfedf9bb295ec304107130f0e98dacaac6dab998b511f176d48daeb81db53643ad194690b6e28c5ed2927e09a1e959c494b90db401681f67bf1e23fe9ef4c903f666ef39332a91a25c63efe9bc518e9aff61842007dda72dcc0264aa47543c0a8b1f0d25749ddfbed487282241140d4c64def1831c4d75ca975fdb03258ddd013445e08bfb479a516b011fe3a12e4bfca439407c0022889e46914cd41a4d92a25eaa57a55bc7337e5fbbd11584dca34adb5643105c8171e53cf04b1412c3107e72330ebf1b52f524b4e72570cfdc0ab179991f3782d05091ea57b1a233048bf062e88939cfeefb61e8beaa90395faf61c4d974b23723a4a5cd39d70f92620f8f4f27bc99ca67bed7fb6e594913991ca3025480ad791bc94a0def36fca491a206440ec31e32bb85850c3606c875708309be63c2b4f5c477521aa08e1d059cedaafe4fbef5523b79f88b57d0c81bbdd09202095f10f13e2609e833ff41b862b2214c22e8f2b04a363b38d26bf95c07b184b9f909ad3a92122e158d3566d2204b22d4f2f3ce11a65544ccecb01a4a5ef62bc969fddcb648224a5c7bd94f8da9a7d4df393d880f537a377888874c19dad357a0564d303a5c1485c1451ea55d68779dc0c11c7c38025660684ba3f70cbbab00d15b34c0f2342207ad548eacb32ebad95292e85211a8669b586d05b0d0b9f278a35ea4d78e97fd5dafca6b72d8e1fbf3e704a60a8ec60befe2e3e4d3d37f9d33a0feb88add59f0171ddeba0b79a52feb9a1f4a7a6ee7c6927bd10968fba788a807409346a0fccd4f7daac3c8591fc689aed881829d479e8d360cdb5819d5eac718a6f860f2d9ef6a0d36ef6e10efbb37819bb7b03ab7649173447b2cd47f3433a2422b1611dff91cee0b10c6d060d4e84a9e3f4dc194514cb67f1e3985be05c845fc92b41955d0f61aeba6268789998bbf341a8b37af48f07b13a676a11d27330529cabcd52365842be559857cbc2a63a4ea1c77fa8619040e79705c5b51f473e13b73fc09c28598e070dbbb63ce884c2843ec365d4c5bebbf815ee3314dde0bab6b0a71a398e2d9ee8ba2f832863fae7eb0c18adcdd17f1dee0df29a8409acabf516c8e6dfea5a264c1c6657f774c86a14cf96eecac18a41b1650a9e652c6c9264b03aa2fd30e333a9f24cd6b0313358e3c00943a1de63ca970b7da2cb8a0fd1109cefbf12176f5dfb59457480428b194e88449bffd8b8d87d05d30f9ffe9ac3a7442b0df3418acf9165b14242489a54b6b47ea543fed5de74a00f61ab2af553b60d8d21c76c42052c72e4841bd94cf88185c39287c04d05f6336ae581cf7528a59b2874795caca79f5600ac64ad5820a91c711ae5a1c3762028242c5c8a9aae89177ec4db5785cd07402d45805a2e2e970059e4e6483074df1bcc01f57470fb66f45ab475ebb5343b727168e355a6c25d42384e39802d7b4a8c54ac94d82de12f8de13630ec8c19f008f98c505dbbfb21b363472e23d0147d1ac555f0981e2bfd07c62d097acf930094dcf239a40699421b207ac2575b7edf9b1d772ab066362820c182c2c5097a47d1dd25ca9e0dd9c3ae94e9a8f0dece74cdeeec3a17803d5e11f037820ea20364234079286a7c291f3424292b0eec3e956513cc6b078a76a3b8ab42c5fb5efdcea1d438f7ae08507275b48f9588a15be763ad094885269efa7330f6fc9d4746997c98d9f5feeb6dff2734d75afc6a11196b35bb9fd0c0af428cacef0df2c5ad4e5fb4559f0f93af2fafad6fb77f453238f409ec71a912350d7b62952e4858927f620d31569242615345265ff1cbbd7fdfaff35a45732628da663bfff3d3af3d7b537337754554458a2d1af0e16aa8ad9436096f42e243109cad32fac1adc58d714cd3d0d8483c783006991f3da263ef5ae1ff2ea06584e45849d64a07170675c29f0b2abcf1eedbb63b6f5d9dba600996c7d5edce9ac69448d05c0704fb9f84e831b60c376b8a5d33ea22030e2dd3dd421d8e0a810a77c085a3861fcba214a8baf592d624d673fb34f906581d923d80b06186db8ce5fbef2bb750166f7556adfe93d4951a825d55b0bf92c9f25776df784f6aec808ae221cc98d05ce988fe6a13ff96083dba15500e149409b54345274e3633fa8f6685d6fed40c20a5c5705f8b37099a5949846ca15def5a6a427eb4eec72747f116366adcb9b74d3de0b125bdee23ca98ee6312f41fa3d9bba43a8d343552c969c41f766ab4341a42ec4cd6f4d1d4c4b1f16979e5389fea36a150580418d95520506fe0cb1a1d861e09d21c57d88c46e10a3c5ad1aedc8f2743f5c06f10d6da9b2bb3ec783c6f5788ce9400795022cdcec197f9dd3ee4cd26531e7f057b6d9418a0c52ecdb35a24a2a079b3d396017feca8b31aa55e3d5ef79c9ea9ccc7e3d0b47f28f273276666fa1763b3a452672fedc94557d984c3353344a8bc9fc833dee685e33d63540d0801d8068cf66cc48ddcb0d42cec881eae36fc2614f96ad67fceb5c98ec33fbade0e3049178d503c13c2d5d71f32f4582d1cb0f47a2ace578b903796768a906998bed2995798251d7eb92faacc19255bf12c0024a94971c185841113faa288beb7e58d4a98289630fb3d230f936eb1b9d9c7b94b5ac9d3a211c0b454a26e29bdffb522548a65e8dde3730918fdf0575245e71ba013ce08f6e698342a61a81b1355d2483e97c06462cae1cdc7787f4bcee4396a08dac9c14981f2a8f4614a31b019c83782d5d8370acf9db467d9d95e8efbe44274fefde5860c2333cf81593a2ada9f5bb6c2362ba97fd7c3e5bc836c327c66b57c0f023efc0c0ff6feae0e625df2f4e21057060170c844c86412700d7d337b1f7835a0dafee5206cbd76104c5a36623c7783213f8dd457b5e69a86b74030a27b3c30074242b1d97e65a233885a681ec5a8532bce9dca1998dc32c6b40dd997b99a6ed6288e0b9b09447e356bc5345b2133571e65d47db2c736a391970879103d4137cab6c0724b8e67064167cd5521f32135fb6ca43c1e118adcded8227c9dbfdc18cdce154108eba5d8c60e5362e8fffc5c9ae6ac2572188617e4ce0f432e2476c74a4227af64b58e0ebafaf0b1ce01723ecd36a2a4167b7991e28b6a9e81992fcaf7b4b906d0361add02104db83914f28baea26b50561faa46293ba5247e8263ac0347509c36405747866d2fa2beef44f366108f6a4047e282a477c28654511075ddfaad9b9844e18e67320a831e647d923b2720d65ddd9ece165c222231d3c3e7f0001d15e3c690e9831ceb369a8edf183133814bfd20dd25d50973bda58ad03c4cbda8008556fc653ef401ff76ee858c1f79a0b09b4232768e72dd06e42078923d5647cb310bb644feb24d6b7e9d1167c3676cd96f79965a066aca314089db60bdc40c2be4b69c569ec76b3bb74a43fe731bc869c9222ab5404304a513d4f7d2ec5af278f7c3d664fcde579bba7bd472bdc00a1eb4c46ff69fb7e45e5712919e8656a8887afa28cadd66461fc57f53d574c92105818a89f210d7e8aee6de2e78228b2cb03b850a6e77627f70f51bb919bddf61837a978dd4cec2db138c657214ac07b67134bd53b071e2bffa3608a0b0bac88b0ddcfc1ba4dea17191c9ad76ab8de72118893256a7e13e15a3bf98bb5757a78c58328cc4b380f3786f22c6be81884d213ec3cc2784583a47a4003a59ebea08bd06e290a892c937448e664dac672942b068b839593c442f6e1d22875e01859cd24c17d108696a3196ea4794ddfdf25721d3dd3e754d1ea884e5086479819452991403a39014297fcc734e56f8daae4d49d5c47016fc3ead550783df895542229ff3b034b5b722ae2a2b04ba70e42c174e9ddb89ffa60024aa16f297ac9383b2ccad53de4bbe4ea2fa3fe3d059d16b4b4fe9959ba3c4e58922e7fa2673f50be5b636ee7c79b445471ddf5b851ec3ac505980bb184c8fe44c7776ae9aab4e66ce31fe1bc00efced390a82f96b4866e31ba3ff832a25b1e1d00ec44bf525ae523b7102ba60c1d3a2e2bed004524afc90a064b325a258eb36315b1496c748f5407e922914787acb8b47bdc495e521518e0637eac4b1b4fe1adede145181ec7ef038d48c473d6f296b349d7cf874d329c71f272883eb7e77ff303957e159fd417d5055d82687448950dd149e1074a1785518ebaf7ac167e07f1f559893a20d133b59aa294efebdae1e19a30ec9a3e257203eb9a854096395825ef4d1e4ecf1f8daeadfa049ea6c435c50d67fd21c6f6b11a8be46502f0dda1715f5349df5330454316498660b7996432e679c73f1af33e529ac669496bde538890cc093122842e3e2e4bff937708dd4b1b1d3fc066a63824266461e4af9245032d690aac0ea5636c29606473820ee57b112e2bd68c0ce1936b7e76a7873cad678b26b560d7bb10a7dcad3f69bbf226faf2f572c105741a121fa1c55ff30b2d0b7339ed9aa4c9a3671e6e4b572800afcbc8764b16f0a61c4c1ff24c3b64992cd84f39d1a4d5532a7dbd9f7bc847258a33c509a945e53236cbc46b61fc6fad662c523eef0c1eaa4bc0a49610c8d09659e7bdfa858d2494dc3da0a54fcce229951d366fd17f4120f27ac77e5e6b777693641a853eacec09cc4dc08ff6ba22295acec61c5e6215eaf2a3a012461eaade8faa9cba630c5ce2bee6f1a4676d54b4a38b7b5cfb6c98106a4882ed88153a4f0bad3e0f3d04dc1ae5318e3b8f4ab1d122a548eed47f70edad1a164a9c5c3eb10fdecb24b0b68005b2e958980481834c4f673478d3f47d07836d3c1c513dd920042381f70f1a68671acee2fdd453a7552eba497af27127999a13a33104f0086390e01635d1a0b79d92dd43211c74047804e82d9ab26f97ee88e664871dab52a2a79443e39f06a6e8ac9d5e986252529b389d9ed0b2f55fb16ca65f6e90cc9a149065f499630f973996c1e2b6c53f2ab391b7d78cc6926b1684d066a3a74b86b3b633baaf3730acd28deaf18fb926e1ec9c1f8a2345103cc4cbec05345db57c5adcf062412f289607f5fa41194f69bc2f426a30c7a6f8d1027ee8dc96c9957e90fbd9b16475b82dfd8698195159bd7b4860004beb1fa85e6843eca1acbbb0b8c7ec0b865ed108e297a2d5f915304167e18d01e51497e6e3ea76ae99bcb849f7595fa74c2a6263e2bef65f1063bce05483980ed51eac5289307117f17e99d761337e9b1fb625a1b900e6179f3b02de57a0b5f52352298c8a2d2c816182ec169d2b9c0490097ad98e2edc99c6df683a4b5b6eb73ccee0aaf07e8cf8f2f632381ac407c5c578bc1c5a8d0915dc231b01b92dbd25c2bfd412995780582793736572f1e23ef690bfe6872c2572285cd737a4be91f4dcafef09232de77b315d73f5beb23d03625e031d2438081222b063c343f52565ae314ac47a4fe518b45d0c12f2ceabc5e05c20f607b97035afbe0e29249e47961d9cf9b385c065966b0c7ea91cfa9ed1b55a58b9aaa9de080ca05c6405fdf15bcef74177226eb225a47d532bcbc82a5ffed7fd86c2609b146d86f566d0b84f638d46d6eb696bfbbc62c4fc981a94c1d6ccb9f3f7ed7976ea7e8ff1d2a2d79986fb27f1401f25d5a83f64844fa9e839fc8855007b417b261d325b6e7cb124b27ede8ad18d2b6da8bfc4d4f50c3960d5a1c82e4557b16d05471602d2a31462e4bac9535c9a57389ae0613a674815c2ec10c19f529c9274896dfe49ab06889da517d482145ed8f57ba4b7c0434ce24090ef2459682a4f6342ecc382b4cd3409c3415bcb7f1bbaadfb7ec308eea8b6cb2912469b707c99a55c1754db0650616754735b85a41433a30b28e3946754f90caeb03c7579fc9982e6ec5501d6f23e0f2b6392acc435907d79ea11eb6955723a81c4f02bfc78e2eeb1d0408f8f06b4d2f6d20d90f7698c4e58bcfa993884424f8fcb602ef35d23737fb6aff220927e28c19043ae708fd9755256a8a1660d9c5827bab1b836a10aa23aea9c92fa3b25428b3791c5d25f3f1b63befd5480ac4192c966350edceea8938ecc608e0f063d16d427049ad62625f5177470e7a0d811e8d4273aea8f7377d51db07fc34d9f18497a0c2b5c0bc5e8778e06bf7460f0487eed54d661d74346eeada9090957159b86f8b68183e33d0c3fc134d87e068badd8789d4c7adb829fe08e4558bada5ef3f526afb2c7b6184244af0d07aa5cb525c519ed32298bb6241d900ead0532b0b1fc77a6577963e7a44627ed326741af254ab957ca0298a74323d2ee4f1bca70e20ff796491424e108e03c20f2eed7374c0aa2474a91f3ced6f46165c886a510734d606ceaa08822bfced69def33cea3662512fb42ecefee341d1b499b826ad882542374b032e907a7e6a4dddc4620a5d1002b5aee25711fd2dd6e9d4e90ee350f2889d6c1f4328e4b711fc919ef3c655311637b83b4eff39c157e0510807ec61714b843bc9eb22a0f4dac7e5cc07b8e9ed587b701d9aca2a239e76ac9a16338b74d50578956e06b1ac35ee3b822ca779922d89de7d915afd7d80831e8534b8f8a2eaed252fd862abc99aadde62d4520d9a7c3c3da86081fc36927de60e3479096a2b5025b9a789da01da969cfb0ab2f252c82db9e6663dce3888146b365080f649cf94f991312817147d8f0d1774d8d44ba4afd846060df2de1d1043659c3b94b1eff51fff84e5a81a0c635aedcf677285e0d722e3335449fd0f49a41264fb963ea5bba31dae469c789047812071d8853291fd8003cc31a8968ce7acb68a6e0172ba6ee0e9dedbebeb62143047336c5a91c77085afb01fc075938b306d7e36383ecdfda55b9b5dfdab53aa34000289c398f617a146c4a06404737600484d8d4ea960061ec2cb575dc485f65f275540d0ce7550da08417632b6f0f7d044f6f719ff839aa3e5c9db94d45225a1cf0bdb0c5bffa781572ad605ad37aa988240858c9493dee9f00ed281e93532d89aba5e9e59ec430cdd5edfdfc2ef65e094eeab71cc40b59c997943a0e0dbbc80f1e11834bf3b53153ba1c1f0ccf63b3c802439b2ef1430be6994300d9b2efe4b84e25bd3bf8a566d4851e7fff57cada544d722438e8980a31563ef0558fdd8db9bdd6f1a3e34f06104b680f63c1f80a08ec6ed74bca69bb1023fe63d24c7e7a14ce85db6e21173f2ddf14f233f3787a37e4b347e4d64907fc0a23c3da017c81c27df9fafd4695886d0ddec8c47982912eceef886ab5680a130bfacbf3c67bb4f0cc118274bdfed43bbc2ba56f048d6a390e48932469b30ac84fdfc2e812f32d00a85349bb22f2d8091e64282fca1b40811db756059de5d03861d6a22cfc6289097d23c26c5e3f000f9b34a0e1b28a1269d8673d09107b29ccaa1adc8939bdca312c69ae4a238f45410d8f1b27392d594ceea2a6b42899ee5c5857965b29bea1bc413da618899b1894f2adff3b3a7b05a626e50e42379f5d0e0a148ded33d815f59d1401b197a85656466eaf88ed30d1ad4a87985570291efbb3a2c6f22c0b111e65c843ca3c6179e94335f0f91d4696e1a31107948a042f55f264c32a35e719668483957c9c8e13fd01e5f751870a509f5f06ba41ad63cbd5f706f25b1e598f6c9709ee6bab627211bc38494962e930779ed4ea2a8471d309c4c4f0603238959cb13476b673489696c87ad9da5fef0d6467145a77ae0b1089c8626988278a85be3292680d9d7e4c6866f19b78595d611f15f9a5e37b3d145d5aff4a5b58a3286bd25a862904817afe8e9b9105584af15f54554ca5e7dceaa0fbd1111aae126d74f68bb6f0ce98094dc9a59a31d9526729efa171beda9ac5b7db9118aa94b9b5ad58dc20ae1c328e31269244d636139
+Ciphertext = d248b9e47c303f735b0d29f6111a742d93509ae051466688d56b587104a74fab1b259da64475fc0d2c3e28d87ca4edfeaa5715c23dc0e5281eb0c0c14e22182bb02f9f7d3c24555cd6a3ff766c774e67730a920db5f85d47dc23bbbee460f0922cd7ddba81ccbe727b4b489e79a19db2d012dad2a732273dafabc0fbded3c47dbe5b6b585570c39eb62850dc47f4aa0c29bf5fadf334041fdd4658fa6cc29a81192a53dcf47c03ddca9d03b33b06e5b3808be77925b7e7d8cf51fa939e023161d969f92430917d73f3aa10b83d5b7402410280561a27c376ce0b5151a51be2ef4eb9057eed25a0715436233615dcad1559fdbd81042544441857cdf46d72f5f50ee552cfd3bf166c530e57fd97f34e2e71bff8a90b30b4c4cc3e843b0f06e4eb2ff82675e428f5303aa9141dbeb615cf6aca5540fd7cb756fe5f9b08a4abdc6eb90b2eaef51c21eb9ae79a0e44b0755b3ed48f5e6e57f3148ce02501528dd3dd2b0bbec2650710a183e38510990002ce6498dc5ce7bf33d699dd18b66c0f8031d958b11d678674c355a635f4b5e8d863785f5dc2f99eba9ce74595493c017697344b651dcc2a0b1d5386b73abd8bb2dc77a2d92173d3688d0d704da9e44a6385af9fb3a81db68822b1eac9ab284f0155c20f6bc34af85d8518d0dfd32fdaece1379abca339a00e1326b624b3e4050be5db8dced5e6c4b88b82b6ee2a48c373d236ea3565ecc072e953ffe01b624c6ecbf534678aad9c3f8a07d7dd7232134b6b397d0c96ab5f795f9e3af65b96e7a765283d8081dab9f953113abe06e8d150bf9a8416d8932fac17b032dc346be43736dbf066ed239328803510f6f62bc8abc92f6df9a82c02cbf85de91739bc8d7805d392341be99798079419540dc952fa0d3ceca4b806ab1db3b717f0d720038343465a8bc0da8e8964e58634e8a2d6c99230af2ac7c89acd3f86a22075dc40818028f3c632b36a39c0e064e3ca2a078c617a3e73aaea56ef11114f9efaac90a3ec8f8d9b18921a80d74b09ada83efee127f41179dc6c19c7965f3e7f43e22f636534b123e9246172f9920f253d2a2652a5e8c337ff93b2d479bef5e96e972a9b9cd8af057c750bd711010d59ce065ad50fdd487b5dde616301d0ae6373b6f9efae99d8972f242dd7a6bc61caee70201869be202fd384a992478dfc133b84171f013244c5d17585934aed3b43b818926246227d255bf832ff481f5f8d074ab159a11d6d17ed0ac50f727b870db966e0373bd3b1eecbf9ed66aa66caf33ac57cffe4ac6df3cf7b0e54ac54be4f3d50f61b33557c2990c908a710c85000ef6fa62716960daf918ae3d81ee60b3813e65673bd911ce468510bd230b9c2d215afe86ec12e49e0ae87e4235baf3df237188f5e0af2e61c22a4bf77190dd5dc804b4cc330b360c3dc093ef208c37d299ea0cd2ba906084011e16ac5f4fc9646538d5b538a99546d34a4599c8529c1524fc4b394d6a9cd762855905233ed92e72c8b538372ffe2f0df7085eb074616c7e695d7de40779e384d5fdb49fe02385424ea991dc05c6ae813f76c673eb45d6105bcdcfdbf04dcdd20caa6e30efcf3537bcf72947e1ac37d1e8c600ba9238569a4b3afa590d61acceb2572da85885146a142c8f8c60afe4d53ee4d61f33c47e5a99da9a346bcfbd013754ef39a4d7f16c4c5fbfa53d7f180c16e2b64f97dcfd65349939b5fc167c7a78926f638f1893fe9a81e897beea3258a4175d14f41dc123ddd846e45a87f35154db8a5ac27c7a0fc95d3b3113cfa9e7c828f83a1f0d91ab7789c33be5f55ecbb8eb0c81bcc0fccc880011b21000e2f10773388b198ce79c5d694472d3ef6b2e55c342b29c70e4f33fe59e2e0bd3f9ef617733dd3329a0e426338d9c007bcdd382522cb96e59b223825a39b01b52809f5e8518f64b81c99022d8215b5c435d87cc1a57bd440b31a19b197b277b2072968595ccd64c135ae1b218046e27a7f2685d013ce3173efd07586dc72a28ac4792e804d44f9efd785ef005213df928560a20daa4c24ab07f081479270a0dcee3c26331c48a164e4b9d79a7c30c77ab06b00e9b72c190d35fb873bc095d5e6231a89b52a0737a99532079bcc72ee221b48f0d0d9ba9105f981beb4225f6efc1230d6da10fd2b58a65112a98e4bbbe1accd6e8589eb6d9c771bb911cccf42aa6cbc68d1976f0da7eff1e70277e8c5f83734ec1efb2b00708fef08e986bd6519a0fa4b5772e585ac8e37fd2a2af07aa382579498b3b75863fe792461492b8e71c4a1a2f4421705696a96601317cfff1632784b5d75fc2036ed3fa650354620781b9fcfd53f1927223fa045edf4abe7b2144512f3e3aee99f7ac3e46028bc2427aeb18e9cb40db57b696ea884658abc9b7bae0d8117f93074a3ef903528f8b55c7687cf9f0119a1f246cc9e993219c6384359e7e5e639bb294b264048060224ae168d7b9f1f795c07eaafcddb10b61ac2be3ab3e1fddf75c1f47559f38d24f0c773d0e8bc5fa85d7d33e3aa8d0f15583b8c1e7aab6f5d0e085b7175678bf11cfee8eb069b78220377819e3f4d28eb833d3d21efff543d5c6357fffb4a8fdd6ce399fca42e2d71c53c50f6b20bcbaa1650b57ff483837c39a37d5e978393c332b43021508b8ef27773164d69d0af3c0dfdc125cf30a7c49a7d8e5320d68a35e80cdfd62a0b7ce6a412f08c8062e35265fad5d1f226d590e9b068d09e48772711d7dbd786a38c0325b3d5665c2ff45ad0a20c174dc5739896ac727b34f11c7af299d36d30c69bbdc35770138cf891cfdd8123489fdef2dfaffa9c2548ebd60b0f0bcedff44691979b4e92b364753120364dc2e3b895095da828e8659575a85cca587ba05ca625480f977a6fe10181ab6ce005defbcd8894f8c71811909cd6b56eb7ffe327f46793a9e98bd7fe8951400276bb9c7607f8ba1e633034b73d7f0d040197c3f346394eba68c8accccefe05f59cb7ea9ab1ae2e172d8f466ee21c6531cec2c9dfeebc477a6d98195c28bccc1d5e23ae50e3a1ddd7de189e36ffe0e387df7be43427b194b16e18b42eacd517bba78edc9f56a2c7e89e6f13513718869da7c8c529bc337217a69e14e35cf97ff7db2c23700347f0a33ad25a299fc52b35f63949735ad864aa127053797541864b07168f89ffb7ba5c9a8bfbcb4248383a95f45461a7aee9c658c5679205f47144ba4a06175e746037b8cb6556f06405e0d537d0f2bcd898dd5fb987d96dbce33001a50abff5b9cb0161dbfe30f5df5a161ddd8a750b0cb33898c110415881fc81239f2e25440bca41a5bc46fbd3787e6c8fe8a463415cd9a82be368a02566da740dca8e40e686e1213d9c15de2d3556a1e1180b298ba3074b4ab93e469dd9a39ac0c8a173b04a5ad913e72e4d7b5ff520f108e1a1747c11b6b2fcfaa89b3ef7e669f8ad9620364b4f4f0f9ab274e76bdd631df033357a24723653e427324d907a9eceb3c375c43ee36cdeb046a6374be19ab04922da93d4dc07c5914df06fee97dd813f5fd501ca75e3c5ad53574837f2e51ba6a257134e8ee0f4127c59840ba8b1bb13592dcbe47aea50e453c7837e91bb12ad1c74fd0f149479bc0334c511a822145690a3a408caa32671ed05c2dd219ea360c67727c1fe6a6cd842301761e94bedc73f93de7091b8b6d2783a788313b2fa12595904bf5d1167a5ddc4ee151b1522de60b7293b72a62c4d08b396ed682b6a6262a212ddc8c70dbec1a972cedc09f593e21d843279561884f9759a593da7b17a147db7559f19d5d6f43ea98012872f974306037dc0d344c55403b35a5903f766359341bee5bccb696fc0fd1c7aa8803e4c2f9e6e23d386d3a202027c5792e355592efab9330af330392a7c91e3cacc4e645359edafd78b77829374cd4b644817322b7650696fa763a0cc7143f9ec7e2f6ab3c9ec2443b0c0b0a31e9eeafb7bb8c375232357f08256959a10a6d4bc98d6cd9314a2ce7feaa8c0eb1eeb15047f715d6ae9ebd64238d648ed6bc50617a360d8ff9a01aa0ce0e29338d34bb9612751445372ac6d74837c7d2d67729760216ee33476cce1a154086ec31d986cc5a14e86561c6929554fb280646164bb03e8e52588a1b947960a77d61c2d2499212a742e1a5b78805b5b64fed141d3c4834301b8a8bef31ce65edb539fd9469b590a6980d0d1bd29e34a09f87438059a09b1ea234d1bb29882e67599fc1e417db9d86332077cfb05fe440ad1243e26a67a0ea30e63cdee8850a543d76e810140547412fb1400ac87a10e3bc77d3918750a5cc3e7a0efbd736c7ed4139cd5855ddba47143362bf40b91fcbf27222017c1552360466483e67ed125745724cc713c713dcf7ef6ea3081d65d8d78b903382717848bee7410431e1040ec92373f75a1bf229816f55dcfffb6e6da33ed8e1e8b05f9348cdcd6938f053eb9f93e0de639e922627bf61a6688f9649bb9cdfce6236a176db8b9b53ce4b5f9eb9c0680c92128bd327aa7f04a745025faaf117a18d5664027ab0e3f5898b834e1a75cd4b4087637733416f8bac1ccd67cb4457005945676d03f76fd0453fdb9968643fec98d28da7c8cd7070a803b14a2459f073ea075fd023a896d3306fdabc54416e95907103cd2fb642e301c71cc48e8eabedaae356582761a14e0b3b0ef1de06002c2acf594c85820ae3a094e5b4680566b592221543c1dc5192d6b208e86b5aca91d4e3454564eedb3b8208169ce97e1632b864f1d9d4c4c4c0fd4bcc5206e8f6d64c7cdf212d718cb5b7c7ee21593ada3f33f5952e12bba4f46cb99044978fe75349c6ca735db35891351d7e5f02a93354bc45a9ec756453f053cb87430b3e9211807f81ad99b6fceb8ef1b2d655910e1f5fd22f2ee90e42abab230f8f39a8345eed6ad294a0d32416a253f829093ecae209bc1dbfadae04a373080f9ea8394a28ddfe1134309bb53ae571d2019ff2bd4be94f8176d90987fcebad323f0b2921b85b2610852973f383a2ff4a5fa82a77b13cfd50a33f29164a9ff409422cc4cbd772132856cbd08470b220ace957a6b8e02c8003d750539a38a8df19a5b662907b72e3098d77c2fc3ece0693b47ff19ce911a93b6adce75653d48ace6af10b8f1141437f9206658707b16794e349db3f1a02606ea167d0213ce3644f64ced64de3799b1729210fc31ba1811b0c226306f2466b230ae35e6d8fa11c8f932e27da8cb1bd311919bf9178ef08bb7a2b4ca2d2e6e9585ee9f916991cfcd4862f5de9fbbc63bee6edbdcfcec9173a252eb59fc6d6e58258ca8b2a4475acfc1e09a0c9566d23d92e9ada97de51895bfb0867c42025c8d089c65bba67f4dd84d7c5155a930329345cdf3b1d6e910e730df273e183190beb900344bbce8c3bdb13a7e4ecbe967a61d47921aa55bac2bbb24e3e03d386ddbfafb3b32235b5ed922ed6ac2c89ded1316b69079b826507d708a6cca14ce2244a67be90fb91ddcb0c97432703729bceb432bc856f5eb9d2f169800a04283b080f0e053670a21468df9414fda9f4153eaf1669a19ede7925f832280800f0063ceee34b9d3b0f8da2012525fa7927e76bda71954714d5f51405b920391eca2ad71160acef4091878b907974573b4cf1b377baca0340ab0e4ec546fcaa6130603ad633c3ef980e88d8f44ec5de743cdc6cd9e0e4cbdb97a5c076be9ada8f26bc54d711facec16a2401292cc167bb98cdd320ec9321414bd97498f6d9b54dbb45ffe4b3e3f88260657ee23e19de48a93595c8e3a289a02d76a27ceead05d591633464709aca117c26aa49b64667f2a3b6371984f813d7098fae7a6ba1841775b52314a06c80b4c994ef8100e233ab3115ba2c39b97f2d5082a145720ad0b12b8a7cb275ba848b3fae14fc0c82bf0353195c056b302e508982f73a8519cca722892482b9d9e6a58bfb4d862fa393eabe6aedeae1be5ed772ea3c94a0df1d9684a131c35246c68b32e46aaf89f3649e58b2e99bd6bb3923d3ab43cbf73b6b3d19fe3b62bef178f46c79ba85e23ee4b25bc561e8fa97f51605bc0b210b02aa28242e81dae9489076d259f17d25b93b0e8a2010584d907314e3bd55482f0fa43d37ae9535629d28d6f837360bb35ec869d2a959789dc49b9c8c515942a1e03650566b736551a5180a60279bdb0ff9c387beebeb9e59ed930b3746464a010a6f7ef1de3c7d76fc6899b1e5ed98213813ffb333d969ad72fd8537ef4e12ca7b78d35c24f44ac82da4a7116492ca2efd86ee6a4474014e72a5cfeee7f729b77cfdd1a5d10a03f3cf28f1d314fca36d31ef2ecb3cfccecbcdfd22367b0a0e04435654286ae3d4fee13f56bb7cdab40b4e1dd01f9ef857f94a67c1e237e24819949935ff3bd73b0461ee9020fd0a2db2cc6312ace97e4a8a33c295271453a12822db8d1438f22ed0d466150990dcb39ed042424eef7a1210c83224c856923e3251484a81a15cddb4d7ada8bb7968dcc8f85e39ca99ece8ce2ed7753fcee6900cc9b7b5691f2d67ef9be13f70d195bbd0047908025df01b4f4d581fd59239836578627d9d585ebe9b053d807e9d3ba25405029a148938a746636decdade02b1afb5ccbf2f0e14a27c98a1e130d9208bbf7da4bb4e572927eb348568921d4a3309a2c24f367c935c2a8e1524c3024ff350ac7da8d2849586817bc9d46a08a21aef035a6151e608ed93b1556a484e455819f9ac2fb155020738962e7255a82a0854b31fe20cdd351c10a33eb693c9be1a51a932e04d0364ced41ee1bf800d0c12ab5eb37fe52563666e52827720e856d4f24eb06e0aba446910aabbe36513f2274362fedba4c19398433029495284ccb499bb559a9cdbc94a0d1b733136969a743945a04e1d2d4e77fed21550af35f22651c7de802eab7a3942d7ec55a3a5002bde8d5cccc1d4ac4bb7f4926615fcece543fe5d9092d2c4f50d94fd9868775a072f4a5bcf2e5fd10795f7f172a3341ce33505ba68e7ebedc9c1e9165864244ed31bbe5c308dceff858cc42010ad8c281a24689cf2dee8a549b1abab9981d70a912174944b403ce664d8608b2f723150f5c12164e4caf28676e7a25c3928ca2a4dbe96355ef8f282e57888d40715df07bd8b5895549ad957e758abf868def1c1f5e260d26498616e2ac962bcaa33b879874569f198a91ce4e50fc50da77fea1df9f9ea900c834dcdd462d338efcf8e612aedebf254fac596507d175d30a90543627cfcef6852c7cda8b430e255c4d6d417de31eb5dba123e3ce9e2269867d9a94fdcd8ccac40a9451953085109f5ae0c3e04daadb4a2a47b0e176917660eb3c9f1aae0ec6b00635fa387e056623947c0621f0a12e86fac1881ed1dc1b9f523388d6b6596a152b3e732c561972879dcd3f0232ef0773a4fb195a90c3186c4688ea58967ce7f18386b80bd38e90cfd4cb899337ab27cba8db6523e979b4c449645bb2f320ccd28578bc7ec38f47225273fa61a2e5df97c4d76c556fbe2b0fd30e615f5fc82c3de7194caed9f5946c151c22b7a0c48f4a7cf78aa153414f2913c5eb95e3dbcea7ca544272cd13a1c52fa87759aeb430aab144fab418c835344605df3a044825965ca15de6ba0e59b2080f5844b2d110d71587e19acf14264cec2de5b8c77d18893215d1c1da0a940e7c2ee429a99e2633c216aecb7675a2314a09044951ca5a8eac798f8878fb5ea65f4ddccac53ee0c786e597169079fb6e8ceb37a71580b0904a97450909ca454a690821e249aebb75449e582fe1b30f1fa9f6464bdef654daa5ede6d4f223f4589ea25a25f4672cfbe974d51008bce296628556f55d26646e40b59f40e3149273760b40806ace3b5171e0b79865c6adb53513da2f24c4115de243150cec76107b48ca8da19117f00b5870e67eb8357e43c1b7b593c9875795d46ede26a109e05406b69fda988947e49ab195f22454c3c743c2ec51b91370b4df8d38653b353e51bb83215d122bcfa591009c007bbb6124bc590fed3f9c5699180b3b1424ad02f7c90a149b77d22dea5c996aba675c2a1a20e206d9c25d9446247d495a26486c0d0bfb09d0b5a1a177a09fa749dc36cee73af0116a6b779c2b827512a04ff0f60b483edbcdb33d2a18339463c498ae67ffa9da0aa3f3beb6bc99212f9e6961afde89045520b1f3f2e2761666a333d76030f443f53322f099035584a60978ef8b49f46d7d4d8c5c758ea52a04b59c1a3a1c2f9df3f3b6f5c45cf4b3547043b18c1d615a2c965c3918d090cc72946e8fd0b938e60e03464f4bc71fb719a1d173b0931930e58bf7f6d4403971d36b40f83be6b57244a7029e1d41dc908764d57a5442557218b509faeda4e9fcf31debbc54ae671ef636871233f29e0013c0e33933543f4b59df1978ec89b109c3977b0cf938b7f6166d6c93be5e87684a703c8b7b5fe1a8bfe153a179b55575ff05e599b39e32ed10d958699a1ffe07136081f0719b18c69dc74f66f211103e9c544f3c81a88ba9f66a9bc7017d9ca9e2cd97634052694a598476b99daf1cdfb6122869375ca5873d32d5c1e07d9b5b380b4f09dbe04478cfb1a13853eafacfed70c8abcd444ed095f78d07c0e8b4093be95c3aa24b2e5b6bfe3a06e9d2d9fedfcfeac4cea2490627e6da6a5cca383351952f654ce2b0ad359c0f7f4ad3f8d1d4a030a947d4a2e417bb79102729115cc8b6558c3362b1d805fb48ce4858deff97677e60375ed13e150a12ee7dcc8ccc64d9710c7f516555c1f7a1a08f0d7c6fd21f864fcf28c8f748c40494e01fc32006f977a5100577f86a484d11b82c90cfe6b4d6b1902fef486cc6f3e033904e150e67283e49a5382961dabd244412ca9657b48796e476a82443167e277d5a65c0c563a6abca77d316e5d3ab639a1ecfb1110af2d29f146508bd9874486dbb56328d6f59479e2766692821660462aa60b6bc8a710707ceeb0ea6429e5113e03c9f41ce0d69c7589deb547527673e8a9f9a9a74e9e4bbcabf2e306b35504c1da99730ae86e94cd047b2e6ea5e97e63a492430d37ec446434fb3b066adde08b17d7d903ad194a4a863d6cfe181a45c8c97b5062bf7c4e44d69c0d1a7e1f5029b805b7c21d1b5e56e697999a32557870ebaae8d87dcb5ca5eea2c5547a16b3f30ef9df8df821028c106f86e091050ff8b6ea4171e59dc2592d405073bea53f8ea62edf112dfbc7ca69809db8005783d63557d3d90d123a944be395c1dc3b5e1476dff188346327769fea65f3cf9363e88ed67335870ec8ef13eb9d9ff5317c4e24dfce9d11699e5f47b4233cc8f9d1b915e716a5730a5898ee65d30b1628b484a5e82eda95a590964a8d8bc89dd3c5cf6c4f9137b8c6ee9d6a692e0c0d1d858dd5b3c12de48badade4d01bff312c56ce3ddb34b0fdde3b0c2706fc292b9fac7e1a0dcd0b6534c968117f7de15eba84d2754e4bcb8093a5440297605598659f686075e2b1b464b6b3ec68abb13cde263b1c607545c45746338b9b207b5c381da690f653b35e363e1249551ad938b9fd7b0a944151cda07127bf9ba76958e926472f4aa1de8512ce834cfcae5414b226f23acdb1fe5cf685d2201b78167ad35fc1da282744c2a43cc49d49242f968f7e06de14455e7ef5adedc5b33184346018114e2d1fc7a5349e378da9b2af5b328c213888652aca9f1145363809eca7c1fd8e64a5cc3255418736e048a731f3053db77971f67014e6121a8e464833e5dbd02ea6caf385e43e9f378bfba657986bf852b32adb55e35a2675bfc8d70d43a902032a61f59f57dad2dd7d7963322136233200cb9a90c952074e9ba0fc0654f1b6fd6f7f0eb77c0fa6d8143213ce6e8b0c178f73e17a7c64839f9bebca2fc955ea8ae406a13b80a9045fa8d129fd859faa46fd27c48bde7b890f98ee938c0d78889f84181ae2f5711304fe554d4251bbc6437ced59d577a2a1f26da736193c3674adb13cef9f4cb4aa6585c4d6874b0309ecde300493b1642c595746f09e03977c8902f3a4a877db1153b248f295a0ca2f1e437d15fcab8fd77c5f967304efb5c4920b990674ae61b954af40be17a8559dc377c591b68067fdcaf2d27bd9a22041b981a84be3de50d5962b58f8c4a22fa05192c5ac99a0a9423284fe62a3a59f085136cec72cda2a53af106a2eb5bda28b6e02c299118cd91714c2e7d045346c78d9ed1b41c73231a21e42c298949f70122277f4134ed5c56639edbf3c3e717310e3d1f03dc5a94e64c4ce148bc5c6bde64eb80b17d5979892786a31225eb89bf9f5a582bcf65b83ff7aa361ccd9238d144f6a22a3f77dd8a01382df4ee90a2057dd310a6b0c4b81dfc92a2cc0c606d3be8b18fbe64ddfdf2004eeabea892be2f914edd1edd8e8829dc7704d71bbaaf08c41824dd0f4b34c9eedead9e10e53bfc6fc0bd37417de0c5c71cff0754d672f29c262d8e27b524427e12bc4e4705ab311d3bedcb1ddd09a3ca0c268c05c64951b7d724a9dafe4d249aaabda91d68633aaab845bf78f9a22d467c7e0c5fc70fc9a318b01d7492efea7fffd329d70692e76647ae665c62b280da0d62f870a52e4dc4cd92c9150c96aab16f8c23475e3152d4debb41b6756f000c3d8aceef18b49e295be7a71da1eeadf4eb96509d45d7cc42af4b7013d8bb445f577e8d4cff92770b8ba0e451f3e24c6d981efdb68c7f2dfafee40b8a425955796e369f0d4da3e998c1626ae0fa583334475f1fdde68ca211c3f2e9afb003f553191702e11f8b731c89ea26059ea4466f2bd0a1a5601025ca9417006bca5c9a57dfdba44c603ef9ad38922623b40feda036d84425c47fa42973e348a180a7570e1215044c375313ab08d6f521052dda415707ebb74d6c4774e039bb04cadc2799224bde1802e2ee2a018032e3a341700c0fa2aa28bf93cc479231efe7da0e9f68e572415348c08cf648117e9b6d1267fef6617f5927252c86cc087775db3e30180feb5ce7e1ac9c3761161e07a4853aa6d97e525aa88302954cf9390fde81f8e11d97a11c79e3bad261364c18890dd1f8fc71127edefe3571518a42be611a46a0426a33221aa25a0ae6514daaf96038cb59aaba898de49e3b215a4464e0af614e638c2d9b6e676ec427fc906bc516331a18121f306a5246d179e2d3d0f38ab8393f7ea5a2d24585e7cca649637b9983924a15483c167e8780f8dd7aa1154cbf731745a8d8d54a8c4f8d854371bb8172303f9ba3c8c7cfe8c378ee56bc35c6376aafe907d3294ee9a8786281b7deff78ff125761f1a31d0e8fffe04a52a7574eeb8679670ca3bfb740167a559488d4337819613d32752d8a89013622f6a8d70f3c64b84a4215f4b7bb282a2d17c36a326167e3270757b8f1d9a0137bfc5ec278e8ca35a69e49779cfc25b95a89cc18732b5b9d1986b18878c57e118506909207207ad0b4edf32fb2b35b6e70546f45d0849bd139ffff9d8ae547787e7b51403b54f110e2ac65468cd0910d80a4e321deafd46e9af19609bee1efa41b762b8ace989dd681503539e7d9948664cf7a73ffac9ce2a34b514253c4f21bbccd38057a6d68732930dcdfc9a32219b53339d100db0037a8bbd101e71f5054f3
+AAD = 7b3b9c07148fcd897f657ecfcc87e530191536b8e77f9309e8d7323888b3b21477f2ab7c885c105d9c29ac96aed23b366f9fde4177401b7038c6770c7bd2ee8b4335105cc0eab9e367f0cea90d6f1ae3fa76cd21ceb9f3500ce7fb4b2a3f9e90f900a231ec693aeced7afb6821391d1f5b1b957895777aa7a2b71d9571c00336f26d54d756392cdb74bfb67d5a621d517db20441f74d0940180baf613b09452f64224f8af7bbc864ab4a8434ff624d0c0646ee07132fd376506951899bde975df8c836ab4ed9cc084f1f6d500ad56345d2f250a0d6991b9e458c62b6023191f341c8659e8a38c878cfac12b032674503df9c9bb01c4340c709eb6dd7c74907d769a317f4dd7317843c47bdb4c5e1f07f2380d464b0c47269389cc8a43a09adba86f6aa8f44c8fe514e73b5fe8d344769c1aa20a4538ecfbf47562ca79fa497b0f02f103f75522db9ead50d56dbe86997d6085f1b5aa7a4cab9e51a1247ce4f724a14983b6bafd17369fac973c6be268e20d800de870928e100990ebb0d3bedfceda36c64be3a729b603bce677a49e8caf282c9159b6e3e1e775129bd30dc3f5c9849535d86a27474be03bb5749b4c0115e2614f8feaa7405cc69b1de479b3b57e551f876a9c8c57ab9879cc68bb2ea110b2e77e59dd6a65eaa67cc4d4b2f4d6e646b2a298d3c80fb43969275d4414734e74726145dab06124c040656c39a94846e8fd58d326f4f9eafe5b95d85254765a21993f55070fcb9e85db5d42ab6b9464ce66de3f236dd2a0a26c4e5535dbdcd6eb350209a65aee785c6647ad4103d092a8ac932470880eb314f7c98cdff34fdf35ee2d36f09bd443b5defad7a5acb9df55965421fd043def6f4771e1bb27385b30ba22c0d8972aead6b654085a7dd3b60c4004a0dae22e25100e54e0badd0cadf909799329ddff699de8066dd6c3822d80c73c52d87e6fcbdb2dbbf852e37804b1256e23e76dbe43f30be4a577bc23c7941a3d708d1e1f579e9c6eebc219c74768168f6790a41f883790e08cd1e88ad09a544eb97b3d1d5af67eea666b9c027e5c7c976921189b955a9e605f6cc9c012c1c2e197c5b02504cb9ffbcb0f3ed778d540d5194fdf5d38dba6340c93da7c5501a082689616f337d8b59c2a92c25e777515726e1d7f6cc9552693cc7c30f1294b37f97d49814250d6c1e3eb335c5d214ef3641739d508b87106eaaf367902433a148ca962ec694409acb82d7749e1c88938ad382d0ca6e6cbe8255746832fe737c3e71dae8397f260c98d4a292a126ec21935c24096d2f91ae114194af659455d8a4206197495a28474dd2809debf5f550d77ffac2b0db521559910c352f23472d7aa9f4dbbdb158f40aa36912cbd918ae4c642e76d78d57ade1075c4fe1086ddee3d554353b4693bbcef1cfa87e49890838c36156af0edf384b0413d6d7aa
+Tag = 51cbcf4a2fd82f221de1bfebf86a8c24
+
+# OFB tests from OpenSSL upstream.
+
+# OFB-AES128.Encrypt
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = ENCRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 50FE67CC996D32B6DA0937E99BAFEC60
+Operation = ENCRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 7789508D16918F03F53C52DAC54ED825
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = D9A4DADA0892239F6B8B3D7680E15674
+Operation = ENCRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = A78819583F0308E7A6BF36B1386ABF23
+Operation = ENCRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
+
+# OFB-AES128.Decrypt
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = DECRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 50FE67CC996D32B6DA0937E99BAFEC60
+Operation = DECRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 7789508D16918F03F53C52DAC54ED825
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = D9A4DADA0892239F6B8B3D7680E15674
+Operation = DECRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = A78819583F0308E7A6BF36B1386ABF23
+Operation = DECRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
+
+# OFB-AES256.Encrypt
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = ENCRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
+Operation = ENCRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = E1C656305ED1A7A6563805746FE03EDC
+Operation = ENCRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 41635BE625B48AFC1666DD42A09D96E7
+Operation = ENCRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 0126141D67F37BE8538F5A8BE740E484
+
+
+# OFB-AES256.Decrypt
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = DECRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
+Operation = DECRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = E1C656305ED1A7A6563805746FE03EDC
+Operation = DECRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 41635BE625B48AFC1666DD42A09D96E7
+Operation = DECRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 0126141D67F37BE8538F5A8BE740E484
+
+
+# AES-192 CBC-mode test from upstream OpenSSL.
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = 000102030405060708090A0B0C0D0E0F
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 4F021DB243BC633D7178183A9FA071E8
+
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = 4F021DB243BC633D7178183A9FA071E8
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = B4D9ADA9AD7DEDF4E5E738763F69145A
+
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = B4D9ADA9AD7DEDF4E5E738763F69145A
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 571B242012FB7AE07FA9BAAC3DF102E0
+
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = 571B242012FB7AE07FA9BAAC3DF102E0
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 08B0E27988598881D920A9E64F5615CD
+
+
+# AES-192-ECB tests from FIPS-197
+Cipher = AES-192-ECB
+Key = 000102030405060708090A0B0C0D0E0F1011121314151617
+Operation = ENCRYPT
+Plaintext = 00112233445566778899AABBCCDDEEFF
+Ciphertext = DDA97CA4864CDFE06EAF70A0EC0D7191
+
+
+# AES-192-ECB tests from NIST document SP800-38A
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = BD334F1D6E45F25FF712A214571FA5CC
+
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 974104846D0AD3AD7734ECB3ECEE4EEF
+
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = EF7AFD2270E2E60ADCE0BA2FACE6444E
+
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 9A4B41BA738D6C72FB16691603C18E0E
+
+# DES ECB tests
+
+Cipher = DES-ECB
+Key = 0000000000000000
+Plaintext = 0000000000000000
+Ciphertext = 8CA64DE9C1B123A7
+
+Cipher = DES-ECB
+Key = FFFFFFFFFFFFFFFF
+Plaintext = FFFFFFFFFFFFFFFF
+Ciphertext = 7359B2163E4EDC58
+
+Cipher = DES-ECB
+Key = 3000000000000000
+Plaintext = 1000000000000001
+Ciphertext = 958E6E627A05557B
+
+Cipher = DES-ECB
+Key = 1111111111111111
+Plaintext = 1111111111111111
+Ciphertext = F40379AB9E0EC533
+
+Cipher = DES-ECB
+Key = 0123456789ABCDEF
+Plaintext = 1111111111111111
+Ciphertext = 17668DFC7292532D
+
+Cipher = DES-ECB
+Key = 1111111111111111
+Plaintext = 0123456789ABCDEF
+Ciphertext = 8A5AE1F81AB8F2DD
+
+Cipher = DES-ECB
+Key = FEDCBA9876543210
+Plaintext = 0123456789ABCDEF
+Ciphertext = ED39D950FA74BCC4
diff --git a/crypto/cipher/tls_cbc.c b/crypto/cipher/tls_cbc.c
index e6aaabc8..fbc93fa6 100644
--- a/crypto/cipher/tls_cbc.c
+++ b/crypto/cipher/tls_cbc.c
@@ -54,10 +54,11 @@
#include <string.h>
#include <openssl/digest.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/sha.h>
#include "../internal.h"
+#include "internal.h"
/* TODO(davidben): unsigned should be size_t. The various constant_time
@@ -176,6 +177,45 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
* + md_size = 256 + 48 (since SHA-384 is the largest hash) = 304. */
assert(rotate_offset <= 304);
+ /* Below is an SMT-LIB2 verification that the Barrett reductions below are
+ * correct within this range:
+ *
+ * (define-fun barrett (
+ * (x (_ BitVec 32))
+ * (mul (_ BitVec 32))
+ * (shift (_ BitVec 32))
+ * (divisor (_ BitVec 32)) ) (_ BitVec 32)
+ * (let ((q (bvsub x (bvmul divisor (bvlshr (bvmul x mul) shift))) ))
+ * (ite (bvuge q divisor)
+ * (bvsub q divisor)
+ * q)))
+ *
+ * (declare-fun x () (_ BitVec 32))
+ *
+ * (assert (or
+ * (let (
+ * (divisor (_ bv20 32))
+ * (mul (_ bv25 32))
+ * (shift (_ bv9 32))
+ * (limit (_ bv853 32)))
+ *
+ * (and (bvule x limit) (not (= (bvurem x divisor)
+ * (barrett x mul shift divisor)))))
+ *
+ * (let (
+ * (divisor (_ bv48 32))
+ * (mul (_ bv10 32))
+ * (shift (_ bv9 32))
+ * (limit (_ bv768 32)))
+ *
+ * (and (bvule x limit) (not (= (bvurem x divisor)
+ * (barrett x mul shift divisor)))))
+ * ))
+ *
+ * (check-sat)
+ * (get-model)
+ */
+
if (md_size == 16) {
rotate_offset &= 15;
} else if (md_size == 20) {
diff --git a/crypto/cmac/cmac_test.cc b/crypto/cmac/cmac_test.cc
index 53f45d15..2496f2a9 100644
--- a/crypto/cmac/cmac_test.cc
+++ b/crypto/cmac/cmac_test.cc
@@ -44,7 +44,7 @@ static int test(const char *name, const uint8_t *key, size_t key_len,
}
ScopedCMAC_CTX ctx(CMAC_CTX_new());
- if (!CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) {
+ if (!ctx || !CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) {
fprintf(stderr, "%s: CMAC_Init failed.\n", name);
return 0;
}
diff --git a/crypto/conf/conf.c b/crypto/conf/conf.c
index 6bdcc4dc..e4fc428b 100644
--- a/crypto/conf/conf.c
+++ b/crypto/conf/conf.c
@@ -65,6 +65,7 @@
#include <openssl/mem.h>
#include "conf_def.h"
+#include "internal.h"
static uint32_t conf_value_hash(const CONF_VALUE *v) {
@@ -152,7 +153,7 @@ void NCONF_free(CONF *conf) {
OPENSSL_free(conf);
}
-CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
+static CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
STACK_OF(CONF_VALUE) *sk = NULL;
int ok = 0;
CONF_VALUE *v = NULL, *old_value;
diff --git a/crypto/cpu-aarch64-linux.c b/crypto/cpu-aarch64-linux.c
new file mode 100644
index 00000000..1b0f3955
--- /dev/null
+++ b/crypto/cpu-aarch64-linux.c
@@ -0,0 +1,61 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <sys/auxv.h>
+
+#include <openssl/arm_arch.h>
+
+#include "internal.h"
+
+
+extern uint32_t OPENSSL_armcap_P;
+
+void OPENSSL_cpuid_setup(void) {
+ unsigned long hwcap = getauxval(AT_HWCAP);
+
+ /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
+ * these values. */
+ static const unsigned long kNEON = 1 << 1;
+ static const unsigned long kAES = 1 << 3;
+ static const unsigned long kPMULL = 1 << 4;
+ static const unsigned long kSHA1 = 1 << 5;
+ static const unsigned long kSHA256 = 1 << 6;
+
+ if ((hwcap & kNEON) == 0) {
+ /* Matching OpenSSL, if NEON is missing, don't report other features
+ * either. */
+ return;
+ }
+
+ OPENSSL_armcap_P |= ARMV7_NEON;
+
+ if (hwcap & kAES) {
+ OPENSSL_armcap_P |= ARMV8_AES;
+ }
+ if (hwcap & kPMULL) {
+ OPENSSL_armcap_P |= ARMV8_PMULL;
+ }
+ if (hwcap & kSHA1) {
+ OPENSSL_armcap_P |= ARMV8_SHA1;
+ }
+ if (hwcap & kSHA256) {
+ OPENSSL_armcap_P |= ARMV8_SHA256;
+ }
+}
+
+#endif /* OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP */
diff --git a/crypto/cpu-arm-asm.S b/crypto/cpu-arm-asm.S
deleted file mode 100644
index faf3ad89..00000000
--- a/crypto/cpu-arm-asm.S
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-#if !defined(OPENSSL_NO_ASM) && defined(__arm__)
-
-.syntax unified
-.cpu cortex-a8
-.fpu neon
-.text
-.thumb
-.align 2
-.global CRYPTO_arm_neon_probe
-.hidden CRYPTO_arm_neon_probe
-.type CRYPTO_arm_neon_probe, %function
-.thumb_func
-CRYPTO_arm_neon_probe:
- vorr q1, q1, q1
- bx lr
-.section .note.GNU-stack,"",%progbits
-
-#endif /* !OPENSSL_NO_ASM && __arm__ */
diff --git a/crypto/cpu-arm-linux.c b/crypto/cpu-arm-linux.c
new file mode 100644
index 00000000..73c38ecc
--- /dev/null
+++ b/crypto/cpu-arm-linux.c
@@ -0,0 +1,360 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <openssl/arm_arch.h>
+#include <openssl/buf.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+
+#define HWCAP_NEON (1 << 12)
+
+/* See /usr/include/asm/hwcap.h on an ARM installation for the source of
+ * these values. */
+#define HWCAP2_AES (1 << 0)
+#define HWCAP2_PMULL (1 << 1)
+#define HWCAP2_SHA1 (1 << 2)
+#define HWCAP2_SHA2 (1 << 3)
+
+/* |getauxval| is not available on Android until API level 20. Link it as a weak
+ * symbol and use other methods as fallback. */
+unsigned long getauxval(unsigned long type) __attribute__((weak));
+
+static int open_eintr(const char *path, int flags) {
+ int ret;
+ do {
+ ret = open(path, flags);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+static ssize_t read_eintr(int fd, void *out, size_t len) {
+ ssize_t ret;
+ do {
+ ret = read(fd, out, len);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+}
+
+/* read_full reads exactly |len| bytes from |fd| to |out|. On error or end of
+ * file, it returns zero. */
+static int read_full(int fd, void *out, size_t len) {
+ char *outp = out;
+ while (len > 0) {
+ ssize_t ret = read_eintr(fd, outp, len);
+ if (ret <= 0) {
+ return 0;
+ }
+ outp += ret;
+ len -= ret;
+ }
+ return 1;
+}
+
+/* read_file opens |path| and reads until end-of-file. On success, it returns
+ * one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the
+ * contents. Otherwise, it returns zero. */
+static int read_file(char **out_ptr, size_t *out_len, const char *path) {
+ int fd = open_eintr(path, O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ static const size_t kReadSize = 1024;
+ int ret = 0;
+ size_t cap = kReadSize, len = 0;
+ char *buf = OPENSSL_malloc(cap);
+ if (buf == NULL) {
+ goto err;
+ }
+
+ for (;;) {
+ if (cap - len < kReadSize) {
+ size_t new_cap = cap * 2;
+ if (new_cap < cap) {
+ goto err;
+ }
+ char *new_buf = OPENSSL_realloc(buf, new_cap);
+ if (new_buf == NULL) {
+ goto err;
+ }
+ buf = new_buf;
+ cap = new_cap;
+ }
+
+ ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize);
+ if (bytes_read < 0) {
+ goto err;
+ }
+ if (bytes_read == 0) {
+ break;
+ }
+ len += bytes_read;
+ }
+
+ *out_ptr = buf;
+ *out_len = len;
+ ret = 1;
+ buf = NULL;
+
+err:
+ OPENSSL_free(buf);
+ close(fd);
+ return ret;
+}
+
+/* getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. */
+static unsigned long getauxval_proc(unsigned long type) {
+ int fd = open_eintr("/proc/self/auxv", O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ struct {
+ unsigned long tag;
+ unsigned long value;
+ } entry;
+
+ for (;;) {
+ if (!read_full(fd, &entry, sizeof(entry)) ||
+ (entry.tag == 0 && entry.value == 0)) {
+ break;
+ }
+ if (entry.tag == type) {
+ close(fd);
+ return entry.value;
+ }
+ }
+ close(fd);
+ return 0;
+}
+
+typedef struct {
+ const char *data;
+ size_t len;
+} STRING_PIECE;
+
+static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) {
+ size_t b_len = strlen(b);
+ return a->len == b_len && memcmp(a->data, b, b_len) == 0;
+}
+
+/* STRING_PIECE_split finds the first occurence of |sep| in |in| and, if found,
+ * sets |*out_left| and |*out_right| to |in| split before and after it. It
+ * returns one if |sep| was found and zero otherwise. */
+static int STRING_PIECE_split(STRING_PIECE *out_left, STRING_PIECE *out_right,
+ const STRING_PIECE *in, char sep) {
+ const char *p = memchr(in->data, sep, in->len);
+ if (p == NULL) {
+ return 0;
+ }
+ /* |out_left| or |out_right| may alias |in|, so make a copy. */
+ STRING_PIECE in_copy = *in;
+ out_left->data = in_copy.data;
+ out_left->len = p - in_copy.data;
+ out_right->data = in_copy.data + out_left->len + 1;
+ out_right->len = in_copy.len - out_left->len - 1;
+ return 1;
+}
+
+/* STRING_PIECE_trim removes leading and trailing whitespace from |s|. */
+static void STRING_PIECE_trim(STRING_PIECE *s) {
+ while (s->len != 0 && (s->data[0] == ' ' || s->data[0] == '\t')) {
+ s->data++;
+ s->len--;
+ }
+ while (s->len != 0 &&
+ (s->data[s->len - 1] == ' ' || s->data[s->len - 1] == '\t')) {
+ s->len--;
+ }
+}
+
+/* extract_cpuinfo_field extracts a /proc/cpuinfo field named |field| from
+ * |in|. If found, it sets |*out| to the value and returns one. Otherwise, it
+ * returns zero. */
+static int extract_cpuinfo_field(STRING_PIECE *out, const STRING_PIECE *in,
+ const char *field) {
+ /* Process |in| one line at a time. */
+ STRING_PIECE remaining = *in, line;
+ while (STRING_PIECE_split(&line, &remaining, &remaining, '\n')) {
+ STRING_PIECE key, value;
+ if (!STRING_PIECE_split(&key, &value, &line, ':')) {
+ continue;
+ }
+ STRING_PIECE_trim(&key);
+ if (STRING_PIECE_equals(&key, field)) {
+ STRING_PIECE_trim(&value);
+ *out = value;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field,
+ const char *value) {
+ STRING_PIECE extracted;
+ return extract_cpuinfo_field(&extracted, cpuinfo, field) &&
+ STRING_PIECE_equals(&extracted, value);
+}
+
+/* has_list_item treats |list| as a space-separated list of items and returns
+ * one if |item| is contained in |list| and zero otherwise. */
+static int has_list_item(const STRING_PIECE *list, const char *item) {
+ STRING_PIECE remaining = *list, feature;
+ while (STRING_PIECE_split(&feature, &remaining, &remaining, ' ')) {
+ if (STRING_PIECE_equals(&feature, item)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) {
+ if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) {
+ /* This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always
+ * available on ARMv8. Linux omits required features, so reading the
+ * "Features" line does not work. (For simplicity, use strict equality. We
+ * assume everything running on future ARM architectures will have a
+ * working |getauxval|.) */
+ return HWCAP_NEON;
+ }
+
+ STRING_PIECE features;
+ if (extract_cpuinfo_field(&features, cpuinfo, "Features") &&
+ has_list_item(&features, "neon")) {
+ return HWCAP_NEON;
+ }
+ return 0;
+}
+
+static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) {
+ STRING_PIECE features;
+ if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) {
+ return 0;
+ }
+
+ unsigned long ret = 0;
+ if (has_list_item(&features, "aes")) {
+ ret |= HWCAP2_AES;
+ }
+ if (has_list_item(&features, "pmull")) {
+ ret |= HWCAP2_PMULL;
+ }
+ if (has_list_item(&features, "sha1")) {
+ ret |= HWCAP2_SHA1;
+ }
+ if (has_list_item(&features, "sha2")) {
+ ret |= HWCAP2_SHA2;
+ }
+ return ret;
+}
+
+/* has_broken_neon returns one if |in| matches a CPU known to have a broken
+ * NEON unit. See https://crbug.com/341598. */
+static int has_broken_neon(const STRING_PIECE *cpuinfo) {
+ return cpuinfo_field_equals(cpuinfo, "CPU implementer", "0x51") &&
+ cpuinfo_field_equals(cpuinfo, "CPU architecture", "7") &&
+ cpuinfo_field_equals(cpuinfo, "CPU variant", "0x1") &&
+ cpuinfo_field_equals(cpuinfo, "CPU part", "0x04d") &&
+ cpuinfo_field_equals(cpuinfo, "CPU revision", "0");
+}
+
+extern uint32_t OPENSSL_armcap_P;
+
+static int g_has_broken_neon;
+
+void OPENSSL_cpuid_setup(void) {
+ char *cpuinfo_data;
+ size_t cpuinfo_len;
+ if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) {
+ return;
+ }
+ STRING_PIECE cpuinfo;
+ cpuinfo.data = cpuinfo_data;
+ cpuinfo.len = cpuinfo_len;
+
+ /* |getauxval| is not available on Android until API level 20. If it is
+ * unavailable, read from /proc/self/auxv as a fallback. This is unreadable
+ * on some versions of Android, so further fall back to /proc/cpuinfo.
+ *
+ * See
+ * https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2
+ * and b/13679666 (Google-internal) for details. */
+ unsigned long hwcap = 0;
+ if (getauxval != NULL) {
+ hwcap = getauxval(AT_HWCAP);
+ }
+ if (hwcap == 0) {
+ hwcap = getauxval_proc(AT_HWCAP);
+ }
+ if (hwcap == 0) {
+ hwcap = get_hwcap_cpuinfo(&cpuinfo);
+ }
+
+ /* Clear NEON support if known broken. */
+ g_has_broken_neon = has_broken_neon(&cpuinfo);
+ if (g_has_broken_neon) {
+ hwcap &= ~HWCAP_NEON;
+ }
+
+ /* Matching OpenSSL, only report other features if NEON is present. */
+ if (hwcap & HWCAP_NEON) {
+ OPENSSL_armcap_P |= ARMV7_NEON;
+
+ /* Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to
+ * /proc/cpuinfo. See https://crbug.com/596156. */
+ unsigned long hwcap2 = 0;
+ if (getauxval != NULL) {
+ hwcap2 = getauxval(AT_HWCAP2);
+ }
+ if (hwcap2 == 0) {
+ hwcap2 = get_hwcap2_cpuinfo(&cpuinfo);
+ }
+
+ if (hwcap2 & HWCAP2_AES) {
+ OPENSSL_armcap_P |= ARMV8_AES;
+ }
+ if (hwcap2 & HWCAP2_PMULL) {
+ OPENSSL_armcap_P |= ARMV8_PMULL;
+ }
+ if (hwcap2 & HWCAP2_SHA1) {
+ OPENSSL_armcap_P |= ARMV8_SHA1;
+ }
+ if (hwcap2 & HWCAP2_SHA2) {
+ OPENSSL_armcap_P |= ARMV8_SHA256;
+ }
+ }
+
+ OPENSSL_free(cpuinfo_data);
+}
+
+int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; }
+
+#endif /* OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP */
diff --git a/crypto/cpu-arm.c b/crypto/cpu-arm.c
index 675d174e..ef395eae 100644
--- a/crypto/cpu-arm.c
+++ b/crypto/cpu-arm.c
@@ -17,52 +17,15 @@
#if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \
!defined(OPENSSL_STATIC_ARMCAP)
-#include <inttypes.h>
-#include <string.h>
-
-#include <setjmp.h>
-#include <signal.h>
-
#include <openssl/arm_arch.h>
-/* We can't include <sys/auxv.h> because the Android SDK version against which
- * Chromium builds is too old to have it. Instead we define all the constants
- * that we need and have a weak pointer to getauxval. */
-
-unsigned long getauxval(unsigned long type) __attribute__((weak));
-
extern uint32_t OPENSSL_armcap_P;
char CRYPTO_is_NEON_capable_at_runtime(void) {
return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
}
-static char g_set_neon_called = 0;
-
-void CRYPTO_set_NEON_capable(char neon_capable) {
- g_set_neon_called = 1;
-
- if (neon_capable) {
- OPENSSL_armcap_P |= ARMV7_NEON;
- } else {
- OPENSSL_armcap_P &= ~ARMV7_NEON;
- }
-}
-
-char CRYPTO_is_NEON_functional(void) {
- static const uint32_t kWantFlags = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
- return (OPENSSL_armcap_P & kWantFlags) == kWantFlags;
-}
-
-void CRYPTO_set_NEON_functional(char neon_functional) {
- if (neon_functional) {
- OPENSSL_armcap_P |= ARMV7_NEON_FUNCTIONAL;
- } else {
- OPENSSL_armcap_P &= ~ARMV7_NEON_FUNCTIONAL;
- }
-}
-
int CRYPTO_is_ARMv8_AES_capable(void) {
return (OPENSSL_armcap_P & ARMV8_AES) != 0;
}
@@ -71,129 +34,5 @@ int CRYPTO_is_ARMv8_PMULL_capable(void) {
return (OPENSSL_armcap_P & ARMV8_PMULL) != 0;
}
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM)
-
-static sigjmp_buf sigill_jmp;
-
-static void sigill_handler(int signal) {
- siglongjmp(sigill_jmp, signal);
-}
-
-void CRYPTO_arm_neon_probe(void);
-
-// probe_for_NEON returns 1 if a NEON instruction runs successfully. Because
-// getauxval doesn't exist on Android until Jelly Bean, supporting NEON on
-// older devices requires this.
-static int probe_for_NEON(void) {
- int supported = 0;
-
- sigset_t sigmask;
- sigfillset(&sigmask);
- sigdelset(&sigmask, SIGILL);
- sigdelset(&sigmask, SIGTRAP);
- sigdelset(&sigmask, SIGFPE);
- sigdelset(&sigmask, SIGBUS);
- sigdelset(&sigmask, SIGSEGV);
-
- struct sigaction sigill_original_action, sigill_action;
- memset(&sigill_action, 0, sizeof(sigill_action));
- sigill_action.sa_handler = sigill_handler;
- sigill_action.sa_mask = sigmask;
-
- sigset_t original_sigmask;
- sigprocmask(SIG_SETMASK, &sigmask, &original_sigmask);
-
- if (sigsetjmp(sigill_jmp, 1 /* save signals */) == 0) {
- sigaction(SIGILL, &sigill_action, &sigill_original_action);
-
- // This function cannot be inline asm because GCC will refuse to compile
- // inline NEON instructions unless building with -mfpu=neon, which would
- // defeat the point of probing for support at runtime.
- CRYPTO_arm_neon_probe();
- supported = 1;
- }
- // Note that Android up to and including Lollipop doesn't restore the signal
- // mask correctly after returning from a sigsetjmp. So that would need to be
- // set again here if more probes were added.
- // See https://android-review.googlesource.com/#/c/127624/
-
- sigaction(SIGILL, &sigill_original_action, NULL);
- sigprocmask(SIG_SETMASK, &original_sigmask, NULL);
-
- return supported;
-}
-
-#else
-
-static int probe_for_NEON(void) {
- return 0;
-}
-
-#endif /* !OPENSSL_NO_ASM && OPENSSL_ARM */
-
-void OPENSSL_cpuid_setup(void) {
- if (getauxval == NULL) {
- // On ARM, but not AArch64, try a NEON instruction and see whether it works
- // in order to probe for NEON support.
- //
- // Note that |CRYPTO_is_NEON_capable| can be true even if
- // |CRYPTO_set_NEON_capable| has never been called if the code was compiled
- // with NEON support enabled (e.g. -mfpu=neon).
- if (!g_set_neon_called && !CRYPTO_is_NEON_capable() && probe_for_NEON()) {
- OPENSSL_armcap_P |= ARMV7_NEON;
- }
- return;
- }
-
- static const unsigned long AT_HWCAP = 16;
- unsigned long hwcap = getauxval(AT_HWCAP);
-
-#if defined(OPENSSL_ARM)
- static const unsigned long kNEON = 1 << 12;
- if ((hwcap & kNEON) == 0) {
- return;
- }
-
- /* In 32-bit mode, the ARMv8 feature bits are in a different aux vector
- * value. */
- static const unsigned long AT_HWCAP2 = 26;
- hwcap = getauxval(AT_HWCAP2);
-
- /* See /usr/include/asm/hwcap.h on an ARM installation for the source of
- * these values. */
- static const unsigned long kAES = 1 << 0;
- static const unsigned long kPMULL = 1 << 1;
- static const unsigned long kSHA1 = 1 << 2;
- static const unsigned long kSHA256 = 1 << 3;
-#elif defined(OPENSSL_AARCH64)
- /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
- * these values. */
- static const unsigned long kNEON = 1 << 1;
- static const unsigned long kAES = 1 << 3;
- static const unsigned long kPMULL = 1 << 4;
- static const unsigned long kSHA1 = 1 << 5;
- static const unsigned long kSHA256 = 1 << 6;
-
- if ((hwcap & kNEON) == 0) {
- return;
- }
-#endif
-
- OPENSSL_armcap_P |= ARMV7_NEON;
-
- if (hwcap & kAES) {
- OPENSSL_armcap_P |= ARMV8_AES;
- }
- if (hwcap & kPMULL) {
- OPENSSL_armcap_P |= ARMV8_PMULL;
- }
- if (hwcap & kSHA1) {
- OPENSSL_armcap_P |= ARMV8_SHA1;
- }
- if (hwcap & kSHA256) {
- OPENSSL_armcap_P |= ARMV8_SHA256;
- }
-}
-
#endif /* (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) &&
!defined(OPENSSL_STATIC_ARMCAP) */
diff --git a/crypto/cpu-intel.c b/crypto/cpu-intel.c
index 6614f63f..f2e0c4cb 100644
--- a/crypto/cpu-intel.c
+++ b/crypto/cpu-intel.c
@@ -64,17 +64,19 @@
#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
#include <inttypes.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <immintrin.h>
#include <intrin.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
+#include "internal.h"
+
/* OPENSSL_cpuid runs the cpuid instruction. |leaf| is passed in as EAX and ECX
* is set to zero. It writes EAX, EBX, ECX, and EDX to |*out_eax| through
diff --git a/crypto/crypto.c b/crypto/crypto.c
index da8807db..c9f2bc87 100644
--- a/crypto/crypto.c
+++ b/crypto/crypto.c
@@ -63,7 +63,7 @@ uint32_t OPENSSL_ia32cap_P[4] = {0};
uint32_t OPENSSL_armcap_P =
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__)
- ARMV7_NEON | ARMV7_NEON_FUNCTIONAL |
+ ARMV7_NEON |
#endif
#if defined(OPENSSL_STATIC_ARMCAP_AES)
ARMV8_AES |
@@ -79,10 +79,8 @@ uint32_t OPENSSL_armcap_P =
#endif
0;
-#elif defined(__ARM_NEON__)
-uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
#else
-uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
+uint32_t OPENSSL_armcap_P = 0;
#endif
#endif
@@ -125,6 +123,22 @@ void CRYPTO_library_init(void) {
#endif
}
+int CRYPTO_is_confidential_build(void) {
+#if defined(BORINGSSL_CONFIDENTIAL)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+int CRYPTO_has_asm(void) {
+#if defined(OPENSSL_NO_ASM)
+ return 0;
+#else
+ return 1;
+#endif
+}
+
const char *SSLeay_version(int unused) {
return "BoringSSL";
}
@@ -140,3 +154,5 @@ int CRYPTO_malloc_init(void) {
void ENGINE_load_builtin_engines(void) {}
void OPENSSL_load_builtin_modules(void) {}
+
+int FIPS_mode(void) { return 0; }
diff --git a/crypto/curve25519/CMakeLists.txt b/crypto/curve25519/CMakeLists.txt
index 90c5705e..7260edca 100644
--- a/crypto/curve25519/CMakeLists.txt
+++ b/crypto/curve25519/CMakeLists.txt
@@ -22,6 +22,7 @@ add_library(
OBJECT
curve25519.c
+ spake25519.c
x25519-x86_64.c
${CURVE25519_ARCH_SOURCES}
@@ -46,4 +47,13 @@ add_executable(
target_link_libraries(x25519_test crypto)
add_dependencies(all_tests x25519_test)
+
+add_executable(
+ spake25519_test
+
+ spake25519_test.cc
+)
+
+target_link_libraries(spake25519_test crypto)
+add_dependencies(all_tests spake25519_test)
endif()
diff --git a/crypto/curve25519/curve25519.c b/crypto/curve25519/curve25519.c
index 61bbdced..1dd1b3ed 100644
--- a/crypto/curve25519/curve25519.c
+++ b/crypto/curve25519/curve25519.c
@@ -31,11 +31,10 @@
#include "internal.h"
-/* fe means field element. Here the field is \Z/(2^255-19). An element t,
- * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
- * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
- * context. */
-typedef int32_t fe[10];
+static const int64_t kBottom25Bits = INT64_C(0x1ffffff);
+static const int64_t kBottom26Bits = INT64_C(0x3ffffff);
+static const int64_t kTop39Bits = INT64_C(0xfffffffffe000000);
+static const int64_t kTop38Bits = INT64_C(0xfffffffffc000000);
static uint64_t load_3(const uint8_t *in) {
uint64_t result;
@@ -77,17 +76,17 @@ static void fe_frombytes(fe h, const uint8_t *s) {
int64_t carry8;
int64_t carry9;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -135,16 +134,6 @@ static void fe_tobytes(uint8_t *s, const fe h) {
int32_t h8 = h[8];
int32_t h9 = h[9];
int32_t q;
- int32_t carry0;
- int32_t carry1;
- int32_t carry2;
- int32_t carry3;
- int32_t carry4;
- int32_t carry5;
- int32_t carry6;
- int32_t carry7;
- int32_t carry8;
- int32_t carry9;
q = (19 * h9 + (((int32_t) 1) << 24)) >> 25;
q = (h0 + q) >> 26;
@@ -162,16 +151,16 @@ static void fe_tobytes(uint8_t *s, const fe h) {
h0 += 19 * q;
/* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
- carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
- carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
- carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
- carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
- carry9 = h9 >> 25; h9 -= carry9 << 25;
+ h1 += h0 >> 26; h0 &= kBottom26Bits;
+ h2 += h1 >> 25; h1 &= kBottom25Bits;
+ h3 += h2 >> 26; h2 &= kBottom26Bits;
+ h4 += h3 >> 25; h3 &= kBottom25Bits;
+ h5 += h4 >> 26; h4 &= kBottom26Bits;
+ h6 += h5 >> 25; h5 &= kBottom25Bits;
+ h7 += h6 >> 26; h6 &= kBottom26Bits;
+ h8 += h7 >> 25; h7 &= kBottom25Bits;
+ h9 += h8 >> 26; h8 &= kBottom26Bits;
+ h9 &= kBottom25Bits;
/* h10 = carry9 */
/* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
@@ -182,32 +171,32 @@ static void fe_tobytes(uint8_t *s, const fe h) {
s[0] = h0 >> 0;
s[1] = h0 >> 8;
s[2] = h0 >> 16;
- s[3] = (h0 >> 24) | (h1 << 2);
+ s[3] = (h0 >> 24) | ((uint32_t)(h1) << 2);
s[4] = h1 >> 6;
s[5] = h1 >> 14;
- s[6] = (h1 >> 22) | (h2 << 3);
+ s[6] = (h1 >> 22) | ((uint32_t)(h2) << 3);
s[7] = h2 >> 5;
s[8] = h2 >> 13;
- s[9] = (h2 >> 21) | (h3 << 5);
+ s[9] = (h2 >> 21) | ((uint32_t)(h3) << 5);
s[10] = h3 >> 3;
s[11] = h3 >> 11;
- s[12] = (h3 >> 19) | (h4 << 6);
+ s[12] = (h3 >> 19) | ((uint32_t)(h4) << 6);
s[13] = h4 >> 2;
s[14] = h4 >> 10;
s[15] = h4 >> 18;
s[16] = h5 >> 0;
s[17] = h5 >> 8;
s[18] = h5 >> 16;
- s[19] = (h5 >> 24) | (h6 << 1);
+ s[19] = (h5 >> 24) | ((uint32_t)(h6) << 1);
s[20] = h6 >> 7;
s[21] = h6 >> 15;
- s[22] = (h6 >> 23) | (h7 << 3);
+ s[22] = (h6 >> 23) | ((uint32_t)(h7) << 3);
s[23] = h7 >> 5;
s[24] = h7 >> 13;
- s[25] = (h7 >> 21) | (h8 << 4);
+ s[25] = (h7 >> 21) | ((uint32_t)(h8) << 4);
s[26] = h8 >> 4;
s[27] = h8 >> 12;
- s[28] = (h8 >> 20) | (h9 << 6);
+ s[28] = (h8 >> 20) | ((uint32_t)(h9) << 6);
s[29] = h9 >> 2;
s[30] = h9 >> 10;
s[31] = h9 >> 18;
@@ -447,46 +436,46 @@ static void fe_mul(fe h, const fe f, const fe g) {
* |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
* i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
/* |h0| <= 2^25 */
/* |h4| <= 2^25 */
/* |h1| <= 1.71*2^59 */
/* |h5| <= 1.71*2^59 */
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
/* |h1| <= 2^24; from now on fits into int32 */
/* |h5| <= 2^24; from now on fits into int32 */
/* |h2| <= 1.41*2^60 */
/* |h6| <= 1.41*2^60 */
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
/* |h2| <= 2^25; from now on fits into int32 unchanged */
/* |h6| <= 2^25; from now on fits into int32 unchanged */
/* |h3| <= 1.71*2^59 */
/* |h7| <= 1.71*2^59 */
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
/* |h3| <= 2^24; from now on fits into int32 unchanged */
/* |h7| <= 2^24; from now on fits into int32 unchanged */
/* |h4| <= 1.72*2^34 */
/* |h8| <= 1.41*2^60 */
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
/* |h4| <= 2^25; from now on fits into int32 unchanged */
/* |h8| <= 2^25; from now on fits into int32 unchanged */
/* |h5| <= 1.01*2^24 */
/* |h9| <= 1.71*2^59 */
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
/* |h9| <= 2^24; from now on fits into int32 unchanged */
/* |h0| <= 1.1*2^39 */
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
/* |h0| <= 2^25; from now on fits into int32 unchanged */
/* |h1| <= 1.01*2^24 */
@@ -612,24 +601,24 @@ static void fe_sq(fe h, const fe f) {
int64_t carry8;
int64_t carry9;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -880,24 +869,24 @@ static void fe_sq2(fe h, const fe f) {
h8 += h8;
h9 += h9;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -974,52 +963,7 @@ static void fe_pow22523(fe out, const fe z) {
fe_mul(out, t0, z);
}
-/* ge means group element.
-
- * Here the group is the set of pairs (x,y) of field elements (see fe.h)
- * satisfying -x^2 + y^2 = 1 + d x^2y^2
- * where d = -121665/121666.
- *
- * Representations:
- * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
- * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
- * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
- * ge_precomp (Duif): (y+x,y-x,2dxy) */
-
-typedef struct {
- fe X;
- fe Y;
- fe Z;
-} ge_p2;
-
-typedef struct {
- fe X;
- fe Y;
- fe Z;
- fe T;
-} ge_p3;
-
-typedef struct {
- fe X;
- fe Y;
- fe Z;
- fe T;
-} ge_p1p1;
-
-typedef struct {
- fe yplusx;
- fe yminusx;
- fe xy2d;
-} ge_precomp;
-
-typedef struct {
- fe YplusX;
- fe YminusX;
- fe Z;
- fe T2d;
-} ge_cached;
-
-static void ge_tobytes(uint8_t *s, const ge_p2 *h) {
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h) {
fe recip;
fe x;
fe y;
@@ -1049,7 +993,7 @@ static const fe d = {-10913610, 13857413, -15372611, 6949391, 114729,
static const fe sqrtm1 = {-32595792, -7943725, 9377950, 3500415, 12389472,
-272473, -25146209, -2005654, 326686, 11406482};
-static int ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
fe u;
fe v;
fe v3;
@@ -1105,6 +1049,13 @@ static void ge_p3_0(ge_p3 *h) {
fe_0(h->T);
}
+static void ge_cached_0(ge_cached *h) {
+ fe_1(h->YplusX);
+ fe_1(h->YminusX);
+ fe_1(h->Z);
+ fe_0(h->T2d);
+}
+
static void ge_precomp_0(ge_precomp *h) {
fe_1(h->yplusx);
fe_1(h->yminusx);
@@ -1122,7 +1073,7 @@ static const fe d2 = {-21827239, -5839606, -30745221, 13898782, 229458,
15978800, -12551817, -6495438, 29715968, 9444199};
/* r = p */
-static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
@@ -1130,20 +1081,27 @@ static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
}
/* r = p */
-static void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
}
/* r = p */
-static void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
}
+/* r = p */
+static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) {
+ ge_p3 t;
+ x25519_ge_p1p1_to_p3(&t, p);
+ x25519_ge_p3_to_cached(r, &t);
+}
+
/* r = 2 * p */
static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
fe t0;
@@ -1199,7 +1157,7 @@ static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
}
/* r = p + q */
-static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
@@ -1216,7 +1174,7 @@ static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
}
/* r = p - q */
-static void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
@@ -1242,12 +1200,64 @@ static uint8_t equal(signed char b, signed char c) {
return y;
}
-static void cmov(ge_precomp *t, ge_precomp *u, uint8_t b) {
+static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) {
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
}
+void x25519_ge_scalarmult_small_precomp(
+ ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) {
+ /* precomp_table is first expanded into matching |ge_precomp|
+ * elements. */
+ ge_precomp multiples[15];
+
+ unsigned i;
+ for (i = 0; i < 15; i++) {
+ const uint8_t *bytes = &precomp_table[i*(2 * 32)];
+ fe x, y;
+ fe_frombytes(x, bytes);
+ fe_frombytes(y, bytes + 32);
+
+ ge_precomp *out = &multiples[i];
+ fe_add(out->yplusx, y, x);
+ fe_sub(out->yminusx, y, x);
+ fe_mul(out->xy2d, x, y);
+ fe_mul(out->xy2d, out->xy2d, d2);
+ }
+
+ /* See the comment above |k25519SmallPrecomp| about the structure of the
+ * precomputed elements. This loop does 64 additions and 64 doublings to
+ * calculate the result. */
+ ge_p3_0(h);
+
+ for (i = 63; i < 64; i--) {
+ unsigned j;
+ signed char index = 0;
+
+ for (j = 0; j < 4; j++) {
+ const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
+ index |= (bit << j);
+ }
+
+ ge_precomp e;
+ ge_precomp_0(&e);
+
+ for (j = 1; j < 16; j++) {
+ cmov(&e, &multiples[j-1], equal(index, j));
+ }
+
+ ge_cached cached;
+ ge_p1p1 r;
+ x25519_ge_p3_to_cached(&cached, h);
+ x25519_ge_add(&r, h, &cached);
+ x25519_ge_p1p1_to_p3(h, &r);
+
+ ge_madd(&r, h, &e);
+ x25519_ge_p1p1_to_p3(h, &r);
+ }
+}
+
#if defined(OPENSSL_SMALL)
/* This block of code replaces the standard base-point table with a much smaller
@@ -1341,61 +1351,14 @@ static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {
0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25,
};
-static void ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
- /* k25519SmallPrecomp is first expanded into matching |ge_precomp|
- * elements. */
- ge_precomp multiples[15];
-
- unsigned i;
- for (i = 0; i < 15; i++) {
- const uint8_t *bytes = &k25519SmallPrecomp[i*(2 * 32)];
- fe x, y;
- fe_frombytes(x, bytes);
- fe_frombytes(y, bytes + 32);
-
- ge_precomp *out = &multiples[i];
- fe_add(out->yplusx, y, x);
- fe_sub(out->yminusx, y, x);
- fe_mul(out->xy2d, x, y);
- fe_mul(out->xy2d, out->xy2d, d2);
- }
-
- /* See the comment above |k25519SmallPrecomp| about the structure of the
- * precomputed elements. This loop does 64 additions and 64 doublings to
- * calculate the result. */
- ge_p3_0(h);
-
- for (i = 63; i < 64; i--) {
- unsigned j;
- signed char index = 0;
-
- for (j = 0; j < 4; j++) {
- const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
- index |= (bit << j);
- }
-
- ge_precomp e;
- ge_precomp_0(&e);
-
- for (j = 1; j < 16; j++) {
- cmov(&e, &multiples[j-1], equal(index, j));
- }
-
- ge_cached cached;
- ge_p1p1 r;
- ge_p3_to_cached(&cached, h);
- ge_add(&r, h, &cached);
- ge_p1p1_to_p3(h, &r);
-
- ge_madd(&r, h, &e);
- ge_p1p1_to_p3(h, &r);
- }
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
+ x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp);
}
#else
/* k25519Precomp[i][j] = (j+1)*256^i*B */
-static ge_precomp k25519Precomp[32][8] = {
+static const ge_precomp k25519Precomp[32][8] = {
{
{
{25967493, -14356035, 29566456, 3660896, -12694345, 4014787,
@@ -3519,7 +3482,7 @@ static uint8_t negative(signed char b) {
static void table_select(ge_precomp *t, int pos, signed char b) {
ge_precomp minust;
uint8_t bnegative = negative(b);
- uint8_t babs = b - (((-bnegative) & b) << 1);
+ uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);
ge_precomp_0(t);
cmov(t, &k25519Precomp[pos][0], equal(babs, 1));
@@ -3542,7 +3505,7 @@ static void table_select(ge_precomp *t, int pos, signed char b) {
*
* Preconditions:
* a[31] <= 127 */
-static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
signed char e[64];
signed char carry;
ge_p1p1 r;
@@ -3571,27 +3534,88 @@ static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
for (i = 1; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
- ge_p1p1_to_p3(h, &r);
+ x25519_ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
- ge_p1p1_to_p2(&s, &r);
+ x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
- ge_p1p1_to_p2(&s, &r);
+ x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
- ge_p1p1_to_p2(&s, &r);
+ x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
- ge_p1p1_to_p3(h, &r);
+ x25519_ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
- ge_p1p1_to_p3(h, &r);
+ x25519_ge_p1p1_to_p3(h, &r);
}
}
#endif
+static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) {
+ fe_cmov(t->YplusX, u->YplusX, b);
+ fe_cmov(t->YminusX, u->YminusX, b);
+ fe_cmov(t->Z, u->Z, b);
+ fe_cmov(t->T2d, u->T2d, b);
+}
+
+/* r = scalar * A.
+ * where a = a[0]+256*a[1]+...+256^31 a[31]. */
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A) {
+ ge_p2 Ai_p2[8];
+ ge_cached Ai[16];
+ ge_p1p1 t;
+
+ ge_cached_0(&Ai[0]);
+ x25519_ge_p3_to_cached(&Ai[1], A);
+ ge_p3_to_p2(&Ai_p2[1], A);
+
+ unsigned i;
+ for (i = 2; i < 16; i += 2) {
+ ge_p2_dbl(&t, &Ai_p2[i / 2]);
+ ge_p1p1_to_cached(&Ai[i], &t);
+ if (i < 8) {
+ x25519_ge_p1p1_to_p2(&Ai_p2[i], &t);
+ }
+ x25519_ge_add(&t, A, &Ai[i]);
+ ge_p1p1_to_cached(&Ai[i + 1], &t);
+ if (i < 7) {
+ x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t);
+ }
+ }
+
+ ge_p2_0(r);
+ ge_p3 u;
+
+ for (i = 0; i < 256; i += 4) {
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p2(r, &t);
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p2(r, &t);
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p2(r, &t);
+ ge_p2_dbl(&t, r);
+ x25519_ge_p1p1_to_p3(&u, &t);
+
+ uint8_t index = scalar[31 - i/8];
+ index >>= 4 - (i & 4);
+ index &= 0xf;
+
+ unsigned j;
+ ge_cached selected;
+ ge_cached_0(&selected);
+ for (j = 0; j < 16; j++) {
+ cmov_cached(&selected, &Ai[j], equal(j, index));
+ }
+
+ x25519_ge_add(&t, &u, &selected);
+ x25519_ge_p1p1_to_p2(r, &t);
+ }
+}
+
static void slide(signed char *r, const uint8_t *a) {
int i;
int b;
@@ -3626,7 +3650,7 @@ static void slide(signed char *r, const uint8_t *a) {
}
}
-static ge_precomp Bi[8] = {
+static const ge_precomp Bi[8] = {
{
{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626,
-11754271, -6079156, 2047605},
@@ -3697,8 +3721,8 @@ static ge_precomp Bi[8] = {
* where a = a[0]+256*a[1]+...+256^31 a[31].
* and b = b[0]+256*b[1]+...+256^31 b[31].
* B is the Ed25519 base point (x,4/5) with x positive. */
-void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
- const ge_p3 *A, const uint8_t *b) {
+static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
+ const ge_p3 *A, const uint8_t *b) {
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
@@ -3710,30 +3734,30 @@ void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
slide(aslide, a);
slide(bslide, b);
- ge_p3_to_cached(&Ai[0], A);
+ x25519_ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
- ge_p1p1_to_p3(&A2, &t);
- ge_add(&t, &A2, &Ai[0]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[1], &u);
- ge_add(&t, &A2, &Ai[1]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[2], &u);
- ge_add(&t, &A2, &Ai[2]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[3], &u);
- ge_add(&t, &A2, &Ai[3]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[4], &u);
- ge_add(&t, &A2, &Ai[4]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[5], &u);
- ge_add(&t, &A2, &Ai[5]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[6], &u);
- ge_add(&t, &A2, &Ai[6]);
- ge_p1p1_to_p3(&u, &t);
- ge_p3_to_cached(&Ai[7], &u);
+ x25519_ge_p1p1_to_p3(&A2, &t);
+ x25519_ge_add(&t, &A2, &Ai[0]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[1], &u);
+ x25519_ge_add(&t, &A2, &Ai[1]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[2], &u);
+ x25519_ge_add(&t, &A2, &Ai[2]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[3], &u);
+ x25519_ge_add(&t, &A2, &Ai[3]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[4], &u);
+ x25519_ge_add(&t, &A2, &Ai[4]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[5], &u);
+ x25519_ge_add(&t, &A2, &Ai[5]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[6], &u);
+ x25519_ge_add(&t, &A2, &Ai[6]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
@@ -3747,22 +3771,22 @@ void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
ge_p2_dbl(&t, r);
if (aslide[i] > 0) {
- ge_p1p1_to_p3(&u, &t);
- ge_add(&t, &u, &Ai[aslide[i] / 2]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if (aslide[i] < 0) {
- ge_p1p1_to_p3(&u, &t);
- ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+ x25519_ge_p1p1_to_p3(&u, &t);
+ x25519_ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if (bslide[i] > 0) {
- ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if (bslide[i] < 0) {
- ge_p1p1_to_p3(&u, &t);
+ x25519_ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
- ge_p1p1_to_p2(r, &t);
+ x25519_ge_p1p1_to_p2(r, &t);
}
}
@@ -3776,7 +3800,7 @@ void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
* s[0]+256*s[1]+...+256^31*s[31] = s mod l
* where l = 2^252 + 27742317777372353535851937790883648493.
* Overwrites s in place. */
-static void sc_reduce(uint8_t *s) {
+void x25519_sc_reduce(uint8_t *s) {
int64_t s0 = 2097151 & load_3(s);
int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
@@ -4610,7 +4634,7 @@ void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) {
az[31] |= 64;
ge_p3 A;
- ge_scalarmult_base(&A, az);
+ x25519_ge_scalarmult_base(&A, az);
ge_p3_tobytes(out_public_key, &A);
memcpy(out_private_key, seed, 32);
@@ -4633,9 +4657,9 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
uint8_t nonce[SHA512_DIGEST_LENGTH];
SHA512_Final(nonce, &hash_ctx);
- sc_reduce(nonce);
+ x25519_sc_reduce(nonce);
ge_p3 R;
- ge_scalarmult_base(&R, nonce);
+ x25519_ge_scalarmult_base(&R, nonce);
ge_p3_tobytes(out_sig, &R);
SHA512_Init(&hash_ctx);
@@ -4645,7 +4669,7 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
uint8_t hram[SHA512_DIGEST_LENGTH];
SHA512_Final(hram, &hash_ctx);
- sc_reduce(hram);
+ x25519_sc_reduce(hram);
sc_muladd(out_sig + 32, hram, az, nonce);
return 1;
@@ -4655,7 +4679,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[64], const uint8_t public_key[32]) {
ge_p3 A;
if ((signature[63] & 224) != 0 ||
- ge_frombytes_vartime(&A, public_key) != 0) {
+ x25519_ge_frombytes_vartime(&A, public_key) != 0) {
return 0;
}
@@ -4677,13 +4701,13 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
uint8_t h[SHA512_DIGEST_LENGTH];
SHA512_Final(h, &hash_ctx);
- sc_reduce(h);
+ x25519_sc_reduce(h);
ge_p2 R;
ge_double_scalarmult_vartime(&R, h, &A, scopy);
uint8_t rcheck[32];
- ge_tobytes(rcheck, &R);
+ x25519_ge_tobytes(rcheck, &R);
return CRYPTO_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
}
@@ -4753,17 +4777,17 @@ static void fe_mul121666(fe h, fe f) {
int64_t carry8;
int64_t carry9;
- carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
- carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
- carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
- carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
- carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+ carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+ carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+ carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+ carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
- carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
- carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
- carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
- carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
- carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+ carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+ carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+ carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+ carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
h[0] = h0;
h[1] = h1;
@@ -4887,7 +4911,7 @@ void X25519_public_from_private(uint8_t out_public_value[32],
e[31] |= 64;
ge_p3 A;
- ge_scalarmult_base(&A, e);
+ x25519_ge_scalarmult_base(&A, e);
/* We only need the u-coordinate of the curve25519 point. The map is
* u=(y+1)/(1-y). Since y=Y/Z, this gives u=(Z+Y)/(Z-Y). */
diff --git a/crypto/curve25519/internal.h b/crypto/curve25519/internal.h
index 27994b7b..ea206a3e 100644
--- a/crypto/curve25519/internal.h
+++ b/crypto/curve25519/internal.h
@@ -37,6 +37,70 @@ void x25519_NEON(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]);
#endif
+/* fe means field element. Here the field is \Z/(2^255-19). An element t,
+ * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+ * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+ * context. */
+typedef int32_t fe[10];
+
+/* ge means group element.
+
+ * Here the group is the set of pairs (x,y) of field elements (see fe.h)
+ * satisfying -x^2 + y^2 = 1 + d x^2y^2
+ * where d = -121665/121666.
+ *
+ * Representations:
+ * ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
+ * ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+ * ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+ * ge_precomp (Duif): (y+x,y-x,2dxy) */
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+} ge_p2;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p3;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p1p1;
+
+typedef struct {
+ fe yplusx;
+ fe yminusx;
+ fe xy2d;
+} ge_precomp;
+
+typedef struct {
+ fe YplusX;
+ fe YminusX;
+ fe Z;
+ fe T2d;
+} ge_cached;
+
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h);
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s);
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_scalarmult_small_precomp(
+ ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]);
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]);
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A);
+void x25519_sc_reduce(uint8_t *s);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/crypto/curve25519/spake25519.c b/crypto/curve25519/spake25519.c
new file mode 100644
index 00000000..617418cf
--- /dev/null
+++ b/crypto/curve25519/spake25519.c
@@ -0,0 +1,464 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/curve25519.h>
+
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+
+
+/* The following precomputation tables are for the following
+ * points used in the SPAKE2 protocol.
+ *
+ * N:
+ * x: 49918732221787544735331783592030787422991506689877079631459872391322455579424
+ * y: 54629554431565467720832445949441049581317094546788069926228343916274969994000
+ * encoded: 10e3df0ae37d8e7a99b5fe74b44672103dbddcbd06af680d71329a11693bc778
+ *
+ * M:
+ * x: 31406539342727633121250288103050113562375374900226415211311216773867585644232
+ * y: 21177308356423958466833845032658859666296341766942662650232962324899758529114
+ * encoded: 5ada7e4bf6ddd9adb6626d32131c6b5c51a1e347a3478f53cfcf441b88eed12e
+ *
+ * These points and their precomputation tables are generated with the
+ * following Python code. For a description of the precomputation table,
+ * see curve25519.c in this directory.
+ *
+ * Exact copies of the source code are kept in bug 27296743.
+ *
+ * import hashlib
+ * import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py
+ *
+ * SEED_N = 'edwards25519 point generation seed (N)'
+ * SEED_M = 'edwards25519 point generation seed (M)'
+ *
+ * def genpoint(seed):
+ * v = hashlib.sha256(seed).digest()
+ * it = 1
+ * while True:
+ * try:
+ * x,y = E.decodepoint(v)
+ * except Exception, e:
+ * print e
+ * it += 1
+ * v = hashlib.sha256(v).digest()
+ * continue
+ * print "Found in %d iterations:" % it
+ * print " x = %d" % x
+ * print " y = %d" % y
+ * print " Encoded (hex)"
+ * print E.encodepoint((x,y)).encode('hex')
+ * return (x,y)
+ *
+ * def gentable(P):
+ * t = []
+ * for i in range(1,16):
+ * k = (i >> 3 & 1) * (1 << 192) + \
+ * (i >> 2 & 1) * (1 << 128) + \
+ * (i >> 1 & 1) * (1 << 64) + \
+ * (i & 1)
+ * t.append(E.scalarmult(P, k))
+ * return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t)
+ *
+ * def printtable(table, name):
+ * print "static const uint8_t %s[15 * 2 * 32] = {" % name,
+ * for i in range(15 * 2 * 32):
+ * if i % 12 == 0:
+ * print "\n ",
+ * print " 0x%02x," % ord(table[i]),
+ * print "\n};"
+ *
+ * if __name__ == "__main__":
+ * print "Searching for N"
+ * N = genpoint(SEED_N)
+ * print "Generating precomputation table for N"
+ * Ntable = gentable(N)
+ * printtable(Ntable, "kSpakeNSmallPrecomp")
+ *
+ * print "Searching for M"
+ * M = genpoint(SEED_M)
+ * print "Generating precomputation table for M"
+ * Mtable = gentable(M)
+ * printtable(Mtable, "kSpakeMSmallPrecomp")
+ */
+static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = {
+ 0x20, 0x1b, 0xc5, 0xb3, 0x43, 0x17, 0x71, 0x10, 0x44, 0x1e, 0x73, 0xb3,
+ 0xae, 0x3f, 0xbf, 0x9f, 0xf5, 0x44, 0xc8, 0x13, 0x8f, 0xd1, 0x01, 0xc2,
+ 0x8a, 0x1a, 0x6d, 0xea, 0x4d, 0x00, 0x5d, 0x6e, 0x10, 0xe3, 0xdf, 0x0a,
+ 0xe3, 0x7d, 0x8e, 0x7a, 0x99, 0xb5, 0xfe, 0x74, 0xb4, 0x46, 0x72, 0x10,
+ 0x3d, 0xbd, 0xdc, 0xbd, 0x06, 0xaf, 0x68, 0x0d, 0x71, 0x32, 0x9a, 0x11,
+ 0x69, 0x3b, 0xc7, 0x78, 0x93, 0xf1, 0x57, 0x97, 0x6e, 0xf0, 0x6e, 0x45,
+ 0x37, 0x4a, 0xf4, 0x0b, 0x18, 0x51, 0xf5, 0x4f, 0x67, 0x3c, 0xdc, 0xec,
+ 0x84, 0xed, 0xd0, 0xeb, 0xca, 0xfb, 0xdb, 0xff, 0x7f, 0xeb, 0xa8, 0x23,
+ 0x68, 0x87, 0x13, 0x64, 0x6a, 0x10, 0xf7, 0x45, 0xe0, 0x0f, 0x32, 0x21,
+ 0x59, 0x7c, 0x0e, 0x50, 0xad, 0x56, 0xd7, 0x12, 0x69, 0x7b, 0x58, 0xf8,
+ 0xb9, 0x3b, 0xa5, 0xbb, 0x4d, 0x1b, 0x87, 0x1c, 0x46, 0xa7, 0x17, 0x9d,
+ 0x6d, 0x84, 0x45, 0xbe, 0x7f, 0x95, 0xd2, 0x34, 0xcd, 0x89, 0x95, 0xc0,
+ 0xf0, 0xd3, 0xdf, 0x6e, 0x10, 0x4a, 0xe3, 0x7b, 0xce, 0x7f, 0x40, 0x27,
+ 0xc7, 0x2b, 0xab, 0x66, 0x03, 0x59, 0xb4, 0x7b, 0xc7, 0xc7, 0xf0, 0x39,
+ 0x9a, 0x33, 0x35, 0xbf, 0xcc, 0x2f, 0xf3, 0x2e, 0x68, 0x9d, 0x53, 0x5c,
+ 0x88, 0x52, 0xe3, 0x77, 0x90, 0xa1, 0x27, 0x85, 0xc5, 0x74, 0x7f, 0x23,
+ 0x0e, 0x93, 0x01, 0x3e, 0xe7, 0x2e, 0x2e, 0x95, 0xf3, 0x0d, 0xc2, 0x25,
+ 0x25, 0x39, 0x39, 0x3d, 0x6e, 0x8e, 0x89, 0xbd, 0xe8, 0xbb, 0x67, 0x5e,
+ 0x8c, 0x66, 0x8b, 0x63, 0x28, 0x1e, 0x4e, 0x74, 0x85, 0xa8, 0xaf, 0x0f,
+ 0x12, 0x5d, 0xb6, 0x8a, 0x83, 0x1a, 0x77, 0x76, 0x5e, 0x62, 0x8a, 0xa7,
+ 0x3c, 0xb8, 0x05, 0x57, 0x2b, 0xaf, 0x36, 0x2e, 0x10, 0x90, 0xb2, 0x39,
+ 0xb4, 0x3e, 0x75, 0x6d, 0x3a, 0xa8, 0x31, 0x35, 0xc2, 0x1e, 0x8f, 0xc2,
+ 0x79, 0x89, 0x35, 0x16, 0x26, 0xd1, 0xc7, 0x0b, 0x04, 0x1f, 0x1d, 0xf9,
+ 0x9c, 0x05, 0xa6, 0x6b, 0xb5, 0x19, 0x5a, 0x24, 0x6d, 0x91, 0xc5, 0x31,
+ 0xfd, 0xc5, 0xfa, 0xe7, 0xa6, 0xcb, 0x0e, 0x4b, 0x18, 0x0d, 0x94, 0xc7,
+ 0xee, 0x1d, 0x46, 0x1f, 0x92, 0xb1, 0xb2, 0x4a, 0x2b, 0x43, 0x37, 0xfe,
+ 0xc2, 0x15, 0x11, 0x89, 0xef, 0x59, 0x73, 0x3c, 0x06, 0x76, 0x78, 0xcb,
+ 0xa6, 0x0d, 0x79, 0x5f, 0x28, 0x0b, 0x5b, 0x8c, 0x9e, 0xe4, 0xaa, 0x51,
+ 0x9a, 0x42, 0x6f, 0x11, 0x50, 0x3d, 0x01, 0xd6, 0x21, 0xc0, 0x99, 0x5e,
+ 0x1a, 0xe8, 0x81, 0x25, 0x80, 0xeb, 0xed, 0x5d, 0x37, 0x47, 0x30, 0x70,
+ 0xa0, 0x4e, 0x0b, 0x43, 0x17, 0xbe, 0xb6, 0x47, 0xe7, 0x2a, 0x62, 0x9d,
+ 0x5d, 0xa6, 0xc5, 0x33, 0x62, 0x9d, 0x56, 0x24, 0x9d, 0x1d, 0xb2, 0x13,
+ 0xbc, 0x17, 0x66, 0x43, 0xd1, 0x68, 0xd5, 0x3b, 0x17, 0x69, 0x17, 0xa6,
+ 0x06, 0x9e, 0x12, 0xb8, 0x7c, 0xd5, 0xaf, 0x3e, 0x21, 0x1b, 0x31, 0xeb,
+ 0x0b, 0xa4, 0x98, 0x1c, 0xf2, 0x6a, 0x5e, 0x7c, 0x9b, 0x45, 0x8f, 0xb2,
+ 0x12, 0x06, 0xd5, 0x8c, 0x1d, 0xb2, 0xa7, 0x57, 0x5f, 0x2f, 0x4f, 0xdb,
+ 0x52, 0x99, 0x7c, 0x58, 0x01, 0x5f, 0xf2, 0xa5, 0xf6, 0x51, 0x86, 0x21,
+ 0x2f, 0x5b, 0x8d, 0x6a, 0xae, 0x83, 0x34, 0x6d, 0x58, 0x4b, 0xef, 0xfe,
+ 0xbf, 0x73, 0x5d, 0xdb, 0xc4, 0x97, 0x2a, 0x85, 0xf3, 0x6c, 0x46, 0x42,
+ 0xb3, 0x90, 0xc1, 0x57, 0x97, 0x50, 0x35, 0xb1, 0x9d, 0xb7, 0xc7, 0x3c,
+ 0x85, 0x6d, 0x6c, 0xfd, 0xce, 0xb0, 0xc9, 0xa2, 0x77, 0xee, 0xc3, 0x6b,
+ 0x0c, 0x37, 0xfa, 0x30, 0x91, 0xd1, 0x2c, 0xb8, 0x5e, 0x7f, 0x81, 0x5f,
+ 0x87, 0xfd, 0x18, 0x02, 0x5a, 0x30, 0x4e, 0x62, 0xbc, 0x65, 0xc6, 0xce,
+ 0x1a, 0xcf, 0x2b, 0xaa, 0x56, 0x3e, 0x4d, 0xcf, 0xba, 0x62, 0x5f, 0x9a,
+ 0xd0, 0x72, 0xff, 0xef, 0x28, 0xbd, 0xbe, 0xd8, 0x57, 0x3d, 0xf5, 0x57,
+ 0x7d, 0xe9, 0x71, 0x31, 0xec, 0x98, 0x90, 0x94, 0xd9, 0x54, 0xbf, 0x84,
+ 0x0b, 0xe3, 0x06, 0x47, 0x19, 0x9a, 0x13, 0x1d, 0xef, 0x9d, 0x13, 0xf3,
+ 0xdb, 0xc3, 0x5c, 0x72, 0x9e, 0xed, 0x24, 0xaa, 0x64, 0xed, 0xe7, 0x0d,
+ 0xa0, 0x7c, 0x73, 0xba, 0x9b, 0x86, 0xa7, 0x3b, 0x55, 0xab, 0x58, 0x30,
+ 0xf1, 0x15, 0x81, 0x83, 0x2f, 0xf9, 0x62, 0x84, 0x98, 0x66, 0xf6, 0x55,
+ 0x21, 0xd8, 0xf2, 0x25, 0x64, 0x71, 0x4b, 0x12, 0x76, 0x59, 0xc5, 0xaa,
+ 0x93, 0x67, 0xc3, 0x86, 0x25, 0xab, 0x4e, 0x4b, 0xf6, 0xd8, 0x3f, 0x44,
+ 0x2e, 0x11, 0xe0, 0xbd, 0x6a, 0xf2, 0x5d, 0xf5, 0xf9, 0x53, 0xea, 0xa4,
+ 0xc8, 0xd9, 0x50, 0x33, 0x81, 0xd9, 0xa8, 0x2d, 0x91, 0x7d, 0x13, 0x2a,
+ 0x11, 0xcf, 0xde, 0x3f, 0x0a, 0xd2, 0xbc, 0x33, 0xb2, 0x62, 0x53, 0xea,
+ 0x77, 0x88, 0x43, 0x66, 0x27, 0x43, 0x85, 0xe9, 0x5f, 0x55, 0xf5, 0x2a,
+ 0x8a, 0xac, 0xdf, 0xff, 0x9b, 0x4c, 0x96, 0x9c, 0xa5, 0x7a, 0xce, 0xd5,
+ 0x79, 0x18, 0xf1, 0x0b, 0x58, 0x95, 0x7a, 0xe7, 0xd3, 0x74, 0x65, 0x0b,
+ 0xa4, 0x64, 0x30, 0xe8, 0x5c, 0xfc, 0x55, 0x56, 0xee, 0x14, 0x14, 0xd3,
+ 0x45, 0x3b, 0xf8, 0xde, 0x05, 0x3e, 0xb9, 0x3c, 0xd7, 0x6a, 0x52, 0x72,
+ 0x5b, 0x39, 0x09, 0xbe, 0x82, 0x23, 0x10, 0x4a, 0xb7, 0xc3, 0xdc, 0x4c,
+ 0x5d, 0xc9, 0xf1, 0x14, 0x83, 0xf9, 0x0b, 0x9b, 0xe9, 0x23, 0x84, 0x6a,
+ 0xc4, 0x08, 0x3d, 0xda, 0x3d, 0x12, 0x95, 0x87, 0x18, 0xa4, 0x7d, 0x3f,
+ 0x23, 0xde, 0xd4, 0x1e, 0xa8, 0x47, 0xc3, 0x71, 0xdb, 0xf5, 0x03, 0x6c,
+ 0x57, 0xe7, 0xa4, 0x43, 0x82, 0x33, 0x7b, 0x62, 0x46, 0x7d, 0xf7, 0x10,
+ 0x69, 0x18, 0x38, 0x27, 0x9a, 0x6f, 0x38, 0xac, 0xfa, 0x92, 0xc5, 0xae,
+ 0x66, 0xa6, 0x73, 0x95, 0x15, 0x0e, 0x4c, 0x04, 0xb6, 0xfc, 0xf5, 0xc7,
+ 0x21, 0x3a, 0x99, 0xdb, 0x0e, 0x36, 0xf0, 0x56, 0xbc, 0x75, 0xf9, 0x87,
+ 0x9b, 0x11, 0x18, 0x92, 0x64, 0x1a, 0xe7, 0xc7, 0xab, 0x5a, 0xc7, 0x26,
+ 0x7f, 0x13, 0x98, 0x42, 0x52, 0x43, 0xdb, 0xc8, 0x6d, 0x0b, 0xb7, 0x31,
+ 0x93, 0x24, 0xd6, 0xe8, 0x24, 0x1f, 0x6f, 0x21, 0xa7, 0x8c, 0xeb, 0xdb,
+ 0x83, 0xb8, 0x89, 0xe3, 0xc1, 0xd7, 0x69, 0x3b, 0x02, 0x6b, 0x54, 0x0f,
+ 0x84, 0x2f, 0xb5, 0x5c, 0x17, 0x77, 0xbe, 0xe5, 0x61, 0x0d, 0xc5, 0xdf,
+ 0x3b, 0xcf, 0x3e, 0x93, 0x4f, 0xf5, 0x89, 0xb9, 0x5a, 0xc5, 0x29, 0x31,
+ 0xc0, 0xc2, 0xff, 0xe5, 0x3f, 0xa6, 0xac, 0x03, 0xca, 0xf5, 0xff, 0xe0,
+ 0x36, 0xce, 0xf3, 0xe2, 0xb7, 0x9c, 0x02, 0xe9, 0x9e, 0xd2, 0xbc, 0x87,
+ 0x2f, 0x3d, 0x9a, 0x1d, 0x8f, 0xc5, 0x72, 0xb8, 0xa2, 0x01, 0xd4, 0x68,
+ 0xb1, 0x84, 0x16, 0x10, 0xf6, 0xf3, 0x52, 0x25, 0xd9, 0xdc, 0x4c, 0xdd,
+ 0x0f, 0xd6, 0x4a, 0xcf, 0x60, 0x96, 0x7e, 0xcc, 0x42, 0x0f, 0x64, 0x9d,
+ 0x72, 0x46, 0x04, 0x07, 0xf2, 0x5b, 0xf4, 0x07, 0xd1, 0xf4, 0x59, 0x71,
+};
+
+static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = {
+ 0xc8, 0xa6, 0x63, 0xc5, 0x97, 0xf1, 0xee, 0x40, 0xab, 0x62, 0x42, 0xee,
+ 0x25, 0x6f, 0x32, 0x6c, 0x75, 0x2c, 0xa7, 0xd3, 0xbd, 0x32, 0x3b, 0x1e,
+ 0x11, 0x9c, 0xbd, 0x04, 0xa9, 0x78, 0x6f, 0x45, 0x5a, 0xda, 0x7e, 0x4b,
+ 0xf6, 0xdd, 0xd9, 0xad, 0xb6, 0x62, 0x6d, 0x32, 0x13, 0x1c, 0x6b, 0x5c,
+ 0x51, 0xa1, 0xe3, 0x47, 0xa3, 0x47, 0x8f, 0x53, 0xcf, 0xcf, 0x44, 0x1b,
+ 0x88, 0xee, 0xd1, 0x2e, 0x03, 0x89, 0xaf, 0xc0, 0x61, 0x2d, 0x9e, 0x35,
+ 0xeb, 0x0e, 0x03, 0xe0, 0xb7, 0xfb, 0xa5, 0xbc, 0x44, 0xbe, 0x0c, 0x89,
+ 0x0a, 0x0f, 0xd6, 0x59, 0x47, 0x9e, 0xe6, 0x3d, 0x36, 0x9d, 0xff, 0x44,
+ 0x5e, 0xac, 0xab, 0xe5, 0x3a, 0xd5, 0xb0, 0x35, 0x9f, 0x6d, 0x7f, 0xba,
+ 0xc0, 0x85, 0x0e, 0xf4, 0x70, 0x3f, 0x13, 0x90, 0x4c, 0x50, 0x1a, 0xee,
+ 0xc5, 0xeb, 0x69, 0xfe, 0x98, 0x42, 0x87, 0x1d, 0xce, 0x6c, 0x29, 0xaa,
+ 0x2b, 0x31, 0xc2, 0x38, 0x7b, 0x6b, 0xee, 0x88, 0x0b, 0xba, 0xce, 0xa8,
+ 0xca, 0x19, 0x60, 0x1b, 0x16, 0xf1, 0x25, 0x1e, 0xcf, 0x63, 0x66, 0x1e,
+ 0xbb, 0x63, 0xeb, 0x7d, 0xca, 0xd2, 0xb4, 0x23, 0x5a, 0x01, 0x6f, 0x05,
+ 0xd1, 0xdc, 0x41, 0x73, 0x75, 0xc0, 0xfd, 0x30, 0x91, 0x52, 0x68, 0x96,
+ 0x45, 0xb3, 0x66, 0x01, 0x3b, 0x53, 0x89, 0x3c, 0x69, 0xbc, 0x6c, 0x69,
+ 0xe3, 0x51, 0x8f, 0xe3, 0xd2, 0x84, 0xd5, 0x28, 0x66, 0xb5, 0xe6, 0x06,
+ 0x09, 0xfe, 0x6d, 0xb0, 0x72, 0x16, 0xe0, 0x8a, 0xce, 0x61, 0x65, 0xa9,
+ 0x21, 0x32, 0x48, 0xdc, 0x7a, 0x1d, 0xe1, 0x38, 0x7f, 0x8c, 0x75, 0x88,
+ 0x3d, 0x08, 0xa9, 0x4a, 0x6f, 0x3d, 0x9f, 0x7f, 0x3f, 0xbd, 0x57, 0x6b,
+ 0x19, 0xce, 0x3f, 0x4a, 0xc9, 0xd3, 0xf9, 0x6e, 0x72, 0x7b, 0x5b, 0x74,
+ 0xea, 0xbe, 0x9c, 0x7a, 0x6d, 0x9c, 0x40, 0x49, 0xe6, 0xfb, 0x2a, 0x1a,
+ 0x75, 0x70, 0xe5, 0x4e, 0xed, 0x74, 0xe0, 0x75, 0xac, 0xc0, 0xb1, 0x11,
+ 0x3e, 0xf2, 0xaf, 0x88, 0x4d, 0x66, 0xb6, 0xf6, 0x15, 0x4f, 0x3c, 0x6c,
+ 0x77, 0xae, 0x47, 0x51, 0x63, 0x9a, 0xfe, 0xe1, 0xb4, 0x1a, 0x12, 0xdf,
+ 0xe9, 0x54, 0x8d, 0x3b, 0x30, 0x2a, 0x75, 0xe3, 0xe5, 0x29, 0xb1, 0x4c,
+ 0xb0, 0x7c, 0x6d, 0xb5, 0xae, 0x85, 0xdb, 0x1e, 0x38, 0x55, 0x96, 0xa5,
+ 0x5b, 0x9f, 0x15, 0x23, 0x28, 0x36, 0xb8, 0xa2, 0x41, 0xb4, 0xd7, 0x19,
+ 0x91, 0x8d, 0x26, 0x3e, 0xca, 0x9c, 0x05, 0x7a, 0x2b, 0x60, 0x45, 0x86,
+ 0x8b, 0xee, 0x64, 0x6f, 0x5c, 0x09, 0x4d, 0x4b, 0x5a, 0x7f, 0xb0, 0xc3,
+ 0x26, 0x9d, 0x8b, 0xb8, 0x83, 0x69, 0xcf, 0x16, 0x72, 0x62, 0x3e, 0x5e,
+ 0x53, 0x4f, 0x9c, 0x73, 0x76, 0xfc, 0x19, 0xef, 0xa0, 0x74, 0x3a, 0x11,
+ 0x1e, 0xd0, 0x4d, 0xb7, 0x87, 0xa1, 0xd6, 0x87, 0x6c, 0x0e, 0x6c, 0x8c,
+ 0xe9, 0xa0, 0x44, 0xc4, 0x72, 0x3e, 0x73, 0x17, 0x13, 0xd1, 0x4e, 0x3d,
+ 0x8e, 0x1d, 0x5a, 0x8b, 0x75, 0xcb, 0x59, 0x2c, 0x47, 0x87, 0x15, 0x41,
+ 0xfe, 0x08, 0xe9, 0xa6, 0x97, 0x17, 0x08, 0x26, 0x6a, 0xb5, 0xbb, 0x73,
+ 0xaa, 0xb8, 0x5b, 0x65, 0x65, 0x5b, 0x30, 0x9e, 0x62, 0x59, 0x02, 0xf8,
+ 0xb8, 0x0f, 0x32, 0x10, 0xc1, 0x36, 0x08, 0x52, 0x98, 0x4a, 0x1e, 0xf0,
+ 0xab, 0x21, 0x5e, 0xde, 0x16, 0x0c, 0xda, 0x09, 0x99, 0x6b, 0x9e, 0xc0,
+ 0x90, 0xa5, 0x5a, 0xcc, 0xb0, 0xb7, 0xbb, 0xd2, 0x8b, 0x5f, 0xd3, 0x3b,
+ 0x3e, 0x8c, 0xa5, 0x71, 0x66, 0x06, 0xe3, 0x28, 0xd4, 0xf8, 0x3f, 0xe5,
+ 0x27, 0xdf, 0xfe, 0x0f, 0x09, 0xb2, 0x8a, 0x09, 0x5a, 0x23, 0x61, 0x0d,
+ 0x2d, 0xf5, 0x44, 0xf1, 0x5c, 0xf8, 0x82, 0x4e, 0xdc, 0x78, 0x7a, 0xab,
+ 0xc3, 0x57, 0x91, 0xaf, 0x65, 0x6e, 0x71, 0xf1, 0x44, 0xbf, 0xed, 0x43,
+ 0x50, 0xb4, 0x67, 0x48, 0xef, 0x5a, 0x10, 0x46, 0x81, 0xb4, 0x0c, 0xc8,
+ 0x48, 0xed, 0x99, 0x7a, 0x45, 0xa5, 0x92, 0xc3, 0x69, 0xd6, 0xd7, 0x8a,
+ 0x20, 0x1b, 0xeb, 0x8f, 0xb2, 0xff, 0xec, 0x6d, 0x76, 0x04, 0xf8, 0xc2,
+ 0x58, 0x9b, 0xf2, 0x20, 0x53, 0xc4, 0x74, 0x91, 0x19, 0xdd, 0x2d, 0x12,
+ 0x53, 0xc7, 0x6e, 0xd0, 0x02, 0x51, 0x3c, 0xa6, 0x7d, 0x80, 0x75, 0x6b,
+ 0x1d, 0xdf, 0xf8, 0x6a, 0x52, 0xbb, 0x81, 0xf8, 0x30, 0x45, 0xef, 0x51,
+ 0x85, 0x36, 0xbe, 0x8e, 0xcf, 0x0b, 0x9a, 0x46, 0xe8, 0x3f, 0x99, 0xfd,
+ 0xf7, 0xd9, 0x3e, 0x84, 0xe5, 0xe3, 0x37, 0xcf, 0x98, 0x7f, 0xeb, 0x5e,
+ 0x5a, 0x53, 0x77, 0x1c, 0x20, 0xdc, 0xf1, 0x20, 0x99, 0xec, 0x60, 0x40,
+ 0x93, 0xef, 0x5c, 0x1c, 0x81, 0xe2, 0xa5, 0xad, 0x2a, 0xc2, 0xdb, 0x6b,
+ 0xc1, 0x7e, 0x8f, 0xa9, 0x23, 0x5b, 0xd9, 0x0d, 0xfe, 0xa0, 0xac, 0x11,
+ 0x28, 0xba, 0x8e, 0x92, 0x07, 0x2d, 0x07, 0x40, 0x83, 0x14, 0x4c, 0x35,
+ 0x8d, 0xd0, 0x11, 0xff, 0x98, 0xdb, 0x00, 0x30, 0x6f, 0x65, 0xb6, 0xa0,
+ 0x7f, 0x9c, 0x08, 0xb8, 0xce, 0xb3, 0xa8, 0x42, 0xd3, 0x84, 0x45, 0xe1,
+ 0xe3, 0x8f, 0xa6, 0x89, 0x21, 0xd7, 0x74, 0x02, 0x4d, 0x64, 0xdf, 0x54,
+ 0x15, 0x9e, 0xba, 0x12, 0x49, 0x09, 0x41, 0xf6, 0x10, 0x24, 0xa1, 0x84,
+ 0x15, 0xfd, 0x68, 0x6a, 0x57, 0x66, 0xb3, 0x6d, 0x4c, 0xea, 0xbf, 0xbc,
+ 0x60, 0x3f, 0x52, 0x1c, 0x44, 0x1b, 0xc0, 0x4a, 0x25, 0xe3, 0xd9, 0x4c,
+ 0x9a, 0x74, 0xad, 0xfc, 0x9e, 0x8d, 0x0b, 0x18, 0x66, 0x24, 0xd1, 0x06,
+ 0xac, 0x68, 0xc1, 0xae, 0x14, 0xce, 0xb1, 0xf3, 0x86, 0x9f, 0x87, 0x11,
+ 0xd7, 0x9f, 0x30, 0x92, 0xdb, 0xec, 0x0b, 0x4a, 0xe8, 0xf6, 0x53, 0x36,
+ 0x68, 0x12, 0x11, 0x5e, 0xe0, 0x34, 0xa4, 0xff, 0x00, 0x0a, 0x26, 0xb8,
+ 0x62, 0x79, 0x9c, 0x0c, 0xd5, 0xe5, 0xf5, 0x1c, 0x1a, 0x16, 0x84, 0x4d,
+ 0x8e, 0x5d, 0x31, 0x7e, 0xf7, 0xe2, 0xd3, 0xa1, 0x41, 0x90, 0x61, 0x5d,
+ 0x04, 0xb2, 0x9a, 0x18, 0x9e, 0x54, 0xfb, 0xd1, 0x61, 0x95, 0x1b, 0x08,
+ 0xca, 0x7c, 0x49, 0x44, 0x74, 0x1d, 0x2f, 0xca, 0xc4, 0x7a, 0xe1, 0x8b,
+ 0x2f, 0xbb, 0x96, 0xee, 0x19, 0x8a, 0x5d, 0xfb, 0x3e, 0x82, 0xe7, 0x15,
+ 0xdb, 0x29, 0x14, 0xee, 0xc9, 0x4d, 0x9a, 0xfb, 0x9f, 0x8a, 0xbb, 0x17,
+ 0x37, 0x1b, 0x6e, 0x28, 0x6c, 0xf9, 0xff, 0xb5, 0xb5, 0x8b, 0x9d, 0x88,
+ 0x20, 0x08, 0x10, 0xd7, 0xca, 0x58, 0xf6, 0xe1, 0x32, 0x91, 0x6f, 0x36,
+ 0xc0, 0xad, 0xc1, 0x57, 0x5d, 0x76, 0x31, 0x43, 0xf3, 0xdd, 0xec, 0xf1,
+ 0xa9, 0x79, 0xe9, 0xe9, 0x85, 0xd7, 0x91, 0xc7, 0x31, 0x62, 0x3c, 0xd2,
+ 0x90, 0x2c, 0x9c, 0xa4, 0x56, 0x37, 0x7b, 0xbe, 0x40, 0x58, 0xc0, 0x81,
+ 0x83, 0x22, 0xe8, 0x13, 0x79, 0x18, 0xdb, 0x3a, 0x1b, 0x31, 0x0d, 0x00,
+ 0x6c, 0x22, 0x62, 0x75, 0x70, 0xd8, 0x96, 0x59, 0x99, 0x44, 0x79, 0x71,
+ 0xa6, 0x76, 0x81, 0x28, 0xb2, 0x65, 0xe8, 0x47, 0x14, 0xc6, 0x39, 0x06,
+};
+
+enum spake2_state_t {
+ spake2_state_init = 0,
+ spake2_state_msg_generated,
+ spake2_state_key_generated,
+};
+
+struct spake2_ctx_st {
+ uint8_t private_key[32];
+ uint8_t my_msg[32];
+ uint8_t password_scalar[32];
+ uint8_t password_hash[SHA512_DIGEST_LENGTH];
+ uint8_t *my_name;
+ size_t my_name_len;
+ uint8_t *their_name;
+ size_t their_name_len;
+ enum spake2_role_t my_role;
+ enum spake2_state_t state;
+};
+
+SPAKE2_CTX *SPAKE2_CTX_new(enum spake2_role_t my_role,
+ const uint8_t *my_name, size_t my_name_len,
+ const uint8_t *their_name, size_t their_name_len) {
+ SPAKE2_CTX *ctx = OPENSSL_malloc(sizeof(SPAKE2_CTX));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ memset(ctx, 0, sizeof(SPAKE2_CTX));
+ ctx->my_role = my_role;
+
+ CBS my_name_cbs, their_name_cbs;
+ CBS_init(&my_name_cbs, my_name, my_name_len);
+ CBS_init(&their_name_cbs, their_name, their_name_len);
+ if (!CBS_stow(&my_name_cbs, &ctx->my_name, &ctx->my_name_len) ||
+ !CBS_stow(&their_name_cbs, &ctx->their_name, &ctx->their_name_len)) {
+ SPAKE2_CTX_free(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void SPAKE2_CTX_free(SPAKE2_CTX *ctx) {
+ if (ctx == NULL) {
+ return;
+ }
+
+ OPENSSL_free(ctx->my_name);
+ OPENSSL_free(ctx->their_name);
+ OPENSSL_free(ctx);
+}
+
+/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian
+ * order. */
+static void left_shift_3(uint8_t n[32]) {
+ uint8_t carry = 0;
+ unsigned i;
+
+ for (i = 0; i < 32; i++) {
+ const uint8_t next_carry = n[i] >> 5;
+ n[i] = (n[i] << 3) | carry;
+ carry = next_carry;
+ }
+}
+
+int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len,
+ size_t max_out_len, const uint8_t *password,
+ size_t password_len) {
+ if (ctx->state != spake2_state_init) {
+ return 0;
+ }
+
+ if (max_out_len < sizeof(ctx->my_msg)) {
+ return 0;
+ }
+
+ uint8_t private_tmp[64];
+ RAND_bytes(private_tmp, sizeof(private_tmp));
+ x25519_sc_reduce(private_tmp);
+ /* Multiply by the cofactor (eight) so that we'll clear it when operating on
+ * the peer's point later in the protocol. */
+ left_shift_3(private_tmp);
+ memcpy(ctx->private_key, private_tmp, sizeof(ctx->private_key));
+
+ ge_p3 P;
+ x25519_ge_scalarmult_base(&P, ctx->private_key);
+
+ /* mask = h(password) * <N or M>. */
+ uint8_t password_tmp[SHA512_DIGEST_LENGTH];
+ SHA512(password, password_len, password_tmp);
+ memcpy(ctx->password_hash, password_tmp, sizeof(ctx->password_hash));
+ x25519_sc_reduce(password_tmp);
+ memcpy(ctx->password_scalar, password_tmp, sizeof(ctx->password_scalar));
+
+ ge_p3 mask;
+ x25519_ge_scalarmult_small_precomp(&mask, ctx->password_scalar,
+ ctx->my_role == spake2_role_alice
+ ? kSpakeMSmallPrecomp
+ : kSpakeNSmallPrecomp);
+
+ /* P* = P + mask. */
+ ge_cached mask_cached;
+ x25519_ge_p3_to_cached(&mask_cached, &mask);
+ ge_p1p1 Pstar;
+ x25519_ge_add(&Pstar, &P, &mask_cached);
+
+ /* Encode P* */
+ ge_p2 Pstar_proj;
+ x25519_ge_p1p1_to_p2(&Pstar_proj, &Pstar);
+ x25519_ge_tobytes(ctx->my_msg, &Pstar_proj);
+
+ memcpy(out, ctx->my_msg, sizeof(ctx->my_msg));
+ *out_len = sizeof(ctx->my_msg);
+ ctx->state = spake2_state_msg_generated;
+
+ return 1;
+}
+
+static void update_with_length_prefix(SHA512_CTX *sha, const uint8_t *data,
+ const size_t len) {
+ uint8_t len_le[8];
+ size_t l = len;
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ len_le[i] = l & 0xff;
+ l >>= 8;
+ }
+
+ SHA512_Update(sha, len_le, sizeof(len_le));
+ SHA512_Update(sha, data, len);
+}
+
+int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, size_t *out_key_len,
+ size_t max_out_key_len, const uint8_t *their_msg,
+ size_t their_msg_len) {
+ if (ctx->state != spake2_state_msg_generated ||
+ their_msg_len != 32) {
+ return 0;
+ }
+
+ ge_p3 Qstar;
+ if (0 != x25519_ge_frombytes_vartime(&Qstar, their_msg)) {
+ /* Point received from peer was not on the curve. */
+ return 0;
+ }
+
+ /* Unmask peer's value. */
+ ge_p3 peers_mask;
+ x25519_ge_scalarmult_small_precomp(&peers_mask, ctx->password_scalar,
+ ctx->my_role == spake2_role_alice
+ ? kSpakeNSmallPrecomp
+ : kSpakeMSmallPrecomp);
+
+ ge_cached peers_mask_cached;
+ x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask);
+
+ ge_p1p1 Q_compl;
+ ge_p3 Q_ext;
+ x25519_ge_sub(&Q_compl, &Qstar, &peers_mask_cached);
+ x25519_ge_p1p1_to_p3(&Q_ext, &Q_compl);
+
+ ge_p2 dh_shared;
+ x25519_ge_scalarmult(&dh_shared, ctx->private_key, &Q_ext);
+
+ uint8_t dh_shared_encoded[32];
+ x25519_ge_tobytes(dh_shared_encoded, &dh_shared);
+
+ SHA512_CTX sha;
+ SHA512_Init(&sha);
+ if (ctx->my_role == spake2_role_alice) {
+ update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
+ update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
+ update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
+ update_with_length_prefix(&sha, their_msg, 32);
+ } else {
+ update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
+ update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
+ update_with_length_prefix(&sha, their_msg, 32);
+ update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
+ }
+ update_with_length_prefix(&sha, dh_shared_encoded, sizeof(dh_shared_encoded));
+ update_with_length_prefix(&sha, ctx->password_hash,
+ sizeof(ctx->password_hash));
+
+ uint8_t key[SHA512_DIGEST_LENGTH];
+ SHA512_Final(key, &sha);
+
+ size_t to_copy = max_out_key_len;
+ if (to_copy > sizeof(key)) {
+ to_copy = sizeof(key);
+ }
+ memcpy(out_key, key, to_copy);
+ *out_key_len = to_copy;
+ ctx->state = spake2_state_key_generated;
+
+ return 1;
+}
diff --git a/crypto/curve25519/spake25519_test.cc b/crypto/curve25519/spake25519_test.cc
new file mode 100644
index 00000000..d97a8602
--- /dev/null
+++ b/crypto/curve25519/spake25519_test.cc
@@ -0,0 +1,169 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/curve25519.h>
+#include "../test/scoped_types.h"
+
+
+struct SPAKE2Run {
+ bool Run() {
+ ScopedSPAKE2_CTX alice(SPAKE2_CTX_new(
+ spake2_role_alice,
+ reinterpret_cast<const uint8_t *>(alice_names.first.data()),
+ alice_names.first.size(),
+ reinterpret_cast<const uint8_t *>(alice_names.second.data()),
+ alice_names.second.size()));
+ ScopedSPAKE2_CTX bob(SPAKE2_CTX_new(
+ spake2_role_bob,
+ reinterpret_cast<const uint8_t *>(bob_names.first.data()),
+ bob_names.first.size(),
+ reinterpret_cast<const uint8_t *>(bob_names.second.data()),
+ bob_names.second.size()));
+
+ if (!alice || !bob) {
+ return false;
+ }
+
+ uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
+ uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE];
+ size_t alice_msg_len, bob_msg_len;
+
+ if (!SPAKE2_generate_msg(
+ alice.get(), alice_msg, &alice_msg_len, sizeof(alice_msg),
+ reinterpret_cast<const uint8_t *>(alice_password.data()),
+ alice_password.size()) ||
+ !SPAKE2_generate_msg(
+ bob.get(), bob_msg, &bob_msg_len, sizeof(bob_msg),
+ reinterpret_cast<const uint8_t *>(bob_password.data()),
+ bob_password.size())) {
+ return false;
+ }
+
+ if (alice_corrupt_msg_bit >= 0 &&
+ static_cast<size_t>(alice_corrupt_msg_bit) < 8 * alice_msg_len) {
+ alice_msg[alice_corrupt_msg_bit/8] ^= 1 << (alice_corrupt_msg_bit & 7);
+ }
+
+ uint8_t alice_key[64], bob_key[64];
+ size_t alice_key_len, bob_key_len;
+
+ if (!SPAKE2_process_msg(alice.get(), alice_key, &alice_key_len,
+ sizeof(alice_key), bob_msg, bob_msg_len) ||
+ !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len, sizeof(bob_key),
+ alice_msg, alice_msg_len)) {
+ return false;
+ }
+
+ key_matches_ = (alice_key_len == bob_key_len &&
+ memcmp(alice_key, bob_key, alice_key_len) == 0);
+
+ return true;
+ }
+
+ bool key_matches() const {
+ return key_matches_;
+ }
+
+ std::string alice_password = "password";
+ std::string bob_password = "password";
+ std::pair<std::string, std::string> alice_names = {"alice", "bob"};
+ std::pair<std::string, std::string> bob_names = {"bob", "alice"};
+ int alice_corrupt_msg_bit = -1;
+
+ private:
+ bool key_matches_ = false;
+};
+
+static bool TestSPAKE2() {
+ for (unsigned i = 0; i < 20; i++) {
+ SPAKE2Run spake2;
+ if (!spake2.Run()) {
+ fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+ return false;
+ }
+
+ if (!spake2.key_matches()) {
+ fprintf(stderr, "Key didn't match for equal passwords.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool TestWrongPassword() {
+ SPAKE2Run spake2;
+ spake2.bob_password = "wrong password";
+ if (!spake2.Run()) {
+ fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+ return false;
+ }
+
+ if (spake2.key_matches()) {
+ fprintf(stderr, "Key matched for unequal passwords.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestWrongNames() {
+ SPAKE2Run spake2;
+ spake2.alice_names.second = "charlie";
+ spake2.bob_names.second = "charlie";
+ if (!spake2.Run()) {
+ fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+ return false;
+ }
+
+ if (spake2.key_matches()) {
+ fprintf(stderr, "Key matched for unequal names.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestCorruptMessages() {
+ for (int i = 0; i < 8 * SPAKE2_MAX_MSG_SIZE; i++) {
+ SPAKE2Run spake2;
+ spake2.alice_corrupt_msg_bit = i;
+ if (spake2.Run() && spake2.key_matches()) {
+ fprintf(stderr, "Passed after corrupting Alice's message, bit %d\n", i);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down. */
+
+int main(int argc, char **argv) {
+ if (!TestSPAKE2() ||
+ !TestWrongPassword() ||
+ !TestWrongNames() ||
+ !TestCorruptMessages()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/crypto/curve25519/x25519-x86_64.c b/crypto/curve25519/x25519-x86_64.c
index 9776c755..1bd86a09 100644
--- a/crypto/curve25519/x25519-x86_64.c
+++ b/crypto/curve25519/x25519-x86_64.c
@@ -1,3 +1,24 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+/* This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
+ * 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
+ * public domain but this file has the ISC license just to keep licencing
+ * simple.
+ *
+ * The field functions are shared by Ed25519 and X25519 where possible. */
+
#include <openssl/curve25519.h>
#include <string.h>
diff --git a/crypto/dh/dh.c b/crypto/dh/dh.c
index aed8720b..94eb3643 100644
--- a/crypto/dh/dh.c
+++ b/crypto/dh/dh.c
@@ -236,7 +236,6 @@ int DH_generate_key(DH *dh) {
int generate_new_key = 0;
unsigned l;
BN_CTX *ctx = NULL;
- BN_MONT_CTX *mont = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
BIGNUM local_priv;
@@ -269,9 +268,8 @@ int DH_generate_key(DH *dh) {
pub_key = dh->pub_key;
}
- mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
- dh->p, ctx);
- if (!mont) {
+ if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+ dh->p, ctx)) {
goto err;
}
@@ -293,7 +291,8 @@ int DH_generate_key(DH *dh) {
}
BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME);
- if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx, mont)) {
+ if (!BN_mod_exp_mont_consttime(pub_key, dh->g, &local_priv, dh->p, ctx,
+ dh->method_mont_p)) {
goto err;
}
@@ -318,7 +317,6 @@ err:
int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
BN_CTX *ctx = NULL;
- BN_MONT_CTX *mont = NULL;
BIGNUM *shared_key;
int ret = -1;
int check_result;
@@ -344,9 +342,8 @@ int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
goto err;
}
- mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
- dh->p, ctx);
- if (!mont) {
+ if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+ dh->p, ctx)) {
goto err;
}
@@ -356,8 +353,8 @@ int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
}
BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME);
- if (!BN_mod_exp_mont(shared_key, peers_key, &local_priv, dh->p, ctx,
- mont)) {
+ if (!BN_mod_exp_mont_consttime(shared_key, peers_key, &local_priv, dh->p, ctx,
+ dh->method_mont_p)) {
OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
goto err;
}
diff --git a/crypto/dh/dh_asn1.c b/crypto/dh/dh_asn1.c
index 73cd4df7..1a147eea 100644
--- a/crypto/dh/dh_asn1.c
+++ b/crypto/dh/dh_asn1.c
@@ -55,30 +55,106 @@
#include <openssl/dh.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-
-#include "internal.h"
-
-/* Override the default free and new methods */
-static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg) {
- if (operation == ASN1_OP_NEW_PRE) {
- *pval = (ASN1_VALUE *)DH_new();
- if (*pval) {
- return 2;
+#include <assert.h>
+#include <limits.h>
+
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+
+#include "../bytestring/internal.h"
+
+
+static int parse_integer(CBS *cbs, BIGNUM **out) {
+ assert(*out == NULL);
+ *out = BN_new();
+ if (*out == NULL) {
+ return 0;
+ }
+ return BN_parse_asn1_unsigned(cbs, *out);
+}
+
+static int marshal_integer(CBB *cbb, BIGNUM *bn) {
+ if (bn == NULL) {
+ /* A DH object may be missing some components. */
+ OPENSSL_PUT_ERROR(DH, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ return BN_marshal_asn1(cbb, bn);
+}
+
+DH *DH_parse_parameters(CBS *cbs) {
+ DH *ret = DH_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ CBS child;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !parse_integer(&child, &ret->p) ||
+ !parse_integer(&child, &ret->g)) {
+ goto err;
+ }
+
+ uint64_t priv_length;
+ if (CBS_len(&child) != 0) {
+ if (!CBS_get_asn1_uint64(&child, &priv_length) ||
+ priv_length > UINT_MAX) {
+ goto err;
}
+ ret->priv_length = (unsigned)priv_length;
+ }
+
+ if (CBS_len(&child) != 0) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+ DH_free(ret);
+ return NULL;
+}
+
+int DH_marshal_parameters(CBB *cbb, const DH *dh) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !marshal_integer(&child, dh->p) ||
+ !marshal_integer(&child, dh->g) ||
+ (dh->priv_length != 0 &&
+ !CBB_add_asn1_uint64(&child, dh->priv_length)) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DH, DH_R_ENCODE_ERROR);
return 0;
- } else if (operation == ASN1_OP_FREE_PRE) {
- DH_free((DH *)*pval);
- *pval = NULL;
- return 2;
}
return 1;
}
-ASN1_SEQUENCE_cb(DHparams, dh_cb) = {
- ASN1_SIMPLE(DH, p, BIGNUM), ASN1_SIMPLE(DH, g, BIGNUM),
- ASN1_OPT(DH, priv_length, ZLONG)} ASN1_SEQUENCE_END_cb(DH, DHparams);
+DH *d2i_DHparams(DH **out, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DH *ret = DH_parse_parameters(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out != NULL) {
+ DH_free(*out);
+ *out = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams)
+int i2d_DHparams(const DH *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DH_marshal_parameters(&cbb, in)) {
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
diff --git a/crypto/dh/dh_test.cc b/crypto/dh/dh_test.cc
index 885bd32b..1c244283 100644
--- a/crypto/dh/dh_test.cc
+++ b/crypto/dh/dh_test.cc
@@ -62,6 +62,7 @@
#include <vector>
#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -73,13 +74,15 @@
static bool RunBasicTests();
static bool RunRFC5114Tests();
static bool TestBadY();
+static bool TestASN1();
int main(int argc, char *argv[]) {
CRYPTO_library_init();
if (!RunBasicTests() ||
!RunRFC5114Tests() ||
- !TestBadY()) {
+ !TestBadY() ||
+ !TestASN1()) {
ERR_print_errors_fp(stderr);
return 1;
}
@@ -533,3 +536,91 @@ static bool TestBadY() {
return true;
}
+
+static bool BIGNUMEqualsHex(const BIGNUM *bn, const char *hex) {
+ BIGNUM *hex_bn = NULL;
+ if (!BN_hex2bn(&hex_bn, hex)) {
+ return false;
+ }
+ ScopedBIGNUM free_hex_bn(hex_bn);
+ return BN_cmp(bn, hex_bn) == 0;
+}
+
+static bool TestASN1() {
+ // kParams are a set of Diffie-Hellman parameters generated with
+ // openssl dhparam 256
+ static const uint8_t kParams[] = {
+ 0x30, 0x26, 0x02, 0x21, 0x00, 0xd7, 0x20, 0x34, 0xa3, 0x27,
+ 0x4f, 0xdf, 0xbf, 0x04, 0xfd, 0x24, 0x68, 0x25, 0xb6, 0x56,
+ 0xd8, 0xab, 0x2a, 0x41, 0x2d, 0x74, 0x0a, 0x52, 0x08, 0x7c,
+ 0x40, 0x71, 0x4e, 0xd2, 0x57, 0x93, 0x13, 0x02, 0x01, 0x02,
+ };
+
+ CBS cbs;
+ CBS_init(&cbs, kParams, sizeof(kParams));
+ ScopedDH dh(DH_parse_parameters(&cbs));
+ if (!dh || CBS_len(&cbs) != 0 ||
+ !BIGNUMEqualsHex(
+ dh->p,
+ "d72034a3274fdfbf04fd246825b656d8ab2a412d740a52087c40714ed2579313") ||
+ !BIGNUMEqualsHex(dh->g, "2") || dh->priv_length != 0) {
+ return false;
+ }
+
+ ScopedCBB cbb;
+ uint8_t *der;
+ size_t der_len;
+ if (!CBB_init(cbb.get(), 0) ||
+ !DH_marshal_parameters(cbb.get(), dh.get()) ||
+ !CBB_finish(cbb.get(), &der, &der_len)) {
+ return false;
+ }
+ ScopedOpenSSLBytes free_der(der);
+ if (der_len != sizeof(kParams) || memcmp(der, kParams, der_len) != 0) {
+ return false;
+ }
+
+ // kParamsDSA are a set of Diffie-Hellman parameters generated with
+ // openssl dhparam 256 -dsaparam
+ static const uint8_t kParamsDSA[] = {
+ 0x30, 0x81, 0x89, 0x02, 0x41, 0x00, 0x93, 0xf3, 0xc1, 0x18, 0x01, 0xe6,
+ 0x62, 0xb6, 0xd1, 0x46, 0x9a, 0x2c, 0x72, 0xea, 0x31, 0xd9, 0x18, 0x10,
+ 0x30, 0x28, 0x63, 0xe2, 0x34, 0x7d, 0x80, 0xca, 0xee, 0x82, 0x2b, 0x19,
+ 0x3c, 0x19, 0xbb, 0x42, 0x83, 0x02, 0x70, 0xdd, 0xdb, 0x8c, 0x03, 0xab,
+ 0xe9, 0x9c, 0xc4, 0x00, 0x4d, 0x70, 0x5f, 0x52, 0x03, 0x31, 0x2c, 0xa4,
+ 0x67, 0x34, 0x51, 0x95, 0x2a, 0xac, 0x11, 0xe2, 0x6a, 0x55, 0x02, 0x40,
+ 0x44, 0xc8, 0x10, 0x53, 0x44, 0x32, 0x31, 0x63, 0xd8, 0xd1, 0x8c, 0x75,
+ 0xc8, 0x98, 0x53, 0x3b, 0x5b, 0x4a, 0x2a, 0x0a, 0x09, 0xe7, 0xd0, 0x3c,
+ 0x53, 0x72, 0xa8, 0x6b, 0x70, 0x41, 0x9c, 0x26, 0x71, 0x44, 0xfc, 0x7f,
+ 0x08, 0x75, 0xe1, 0x02, 0xab, 0x74, 0x41, 0xe8, 0x2a, 0x3d, 0x3c, 0x26,
+ 0x33, 0x09, 0xe4, 0x8b, 0xb4, 0x41, 0xec, 0xa6, 0xa8, 0xba, 0x1a, 0x07,
+ 0x8a, 0x77, 0xf5, 0x5f, 0x02, 0x02, 0x00, 0xa0,
+ };
+
+ CBS_init(&cbs, kParamsDSA, sizeof(kParamsDSA));
+ dh.reset(DH_parse_parameters(&cbs));
+ if (!dh || CBS_len(&cbs) != 0 ||
+ !BIGNUMEqualsHex(dh->p,
+ "93f3c11801e662b6d1469a2c72ea31d91810302863e2347d80caee8"
+ "22b193c19bb42830270dddb8c03abe99cc4004d705f5203312ca467"
+ "3451952aac11e26a55") ||
+ !BIGNUMEqualsHex(dh->g,
+ "44c8105344323163d8d18c75c898533b5b4a2a0a09e7d03c5372a86"
+ "b70419c267144fc7f0875e102ab7441e82a3d3c263309e48bb441ec"
+ "a6a8ba1a078a77f55f") ||
+ dh->priv_length != 160) {
+ return false;
+ }
+
+ if (!CBB_init(cbb.get(), 0) ||
+ !DH_marshal_parameters(cbb.get(), dh.get()) ||
+ !CBB_finish(cbb.get(), &der, &der_len)) {
+ return false;
+ }
+ ScopedOpenSSLBytes free_der2(der);
+ if (der_len != sizeof(kParamsDSA) || memcmp(der, kParamsDSA, der_len) != 0) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/crypto/digest/digest.c b/crypto/digest/digest.c
index eb71b073..fdd9fe55 100644
--- a/crypto/digest/digest.c
+++ b/crypto/digest/digest.c
@@ -60,7 +60,6 @@
#include <string.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
#include <openssl/mem.h>
#include "internal.h"
@@ -166,6 +165,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) {
if (ctx->digest != type) {
if (ctx->digest && ctx->digest->ctx_size > 0) {
OPENSSL_free(ctx->md_data);
+ ctx->md_data = NULL;
}
ctx->digest = type;
if (type->ctx_size > 0) {
@@ -231,11 +231,11 @@ const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) {
return ctx->digest;
}
-unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx) {
+size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx) {
return EVP_MD_size(EVP_MD_CTX_md(ctx));
}
-unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) {
+size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) {
return EVP_MD_block_size(EVP_MD_CTX_md(ctx));
}
diff --git a/crypto/directory.h b/crypto/directory.h
deleted file mode 100644
index 29123ea9..00000000
--- a/crypto/directory.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copied from Richard Levitte's (richard@levitte.org) LP library. All
- * symbol names have been changed, with permission from the author. */
-
-/* $LP: LPlib/source/LPdir.h,v 1.1 2004/06/14 08:56:04 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS 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.
- */
-
-#ifndef OPENSSL_HEADER_DIRECTORY_H
-#define OPENSSL_HEADER_DIRECTORY_H
-
-#include <openssl/base.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/* Directory functions abstract the O/S specific operations for opening and
- * reading directories in the filesystem. */
-
-
-/* OPENSSL_dir_context_st is an opaque structure that represents an open
- * directory and a position in that directory. */
-typedef struct OPENSSL_dir_context_st OPENSSL_DIR_CTX;
-
-/* OPENSSL_DIR_read reads a single filename from |ctx|. On the first call,
- * |directory| must be given and |*ctx| must be NULL. Subsequent calls with the
- * same |*ctx| will return subsequent file names until it returns NULL to
- * indicate EOF. The strings returned reference a buffer internal to the
- * |OPENSSL_DIR_CTX| and will be overridden by subsequent calls. */
-OPENSSL_EXPORT const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx,
- const char *directory);
-
-/* OPENSSL_DIR_end closes |*ctx|. It returns one on success and zero on
- * error. */
-OPENSSL_EXPORT int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx);
-
-
-#if defined(__cplusplus)
-} /* extern C */
-#endif
-
-#endif /* OPENSSL_HEADER_DIRECTORY_H */
diff --git a/crypto/directory_posix.c b/crypto/directory_posix.c
deleted file mode 100644
index b944b692..00000000
--- a/crypto/directory_posix.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* $LP: LPlib/source/LPdir_unix.c,v 1.11 2004/09/23 22:07:22 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``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 COPYRIGHT
- * OWNER 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. */
-
-#if !defined(_POSIX_C_SOURCE)
-#define _POSIX_C_SOURCE 201409 /* for readdir_r */
-#endif
-
-#include "directory.h"
-
-
-#if !defined(OPENSSL_WINDOWS)
-
-#include <dirent.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(OPENSSL_PNACL)
-/* pnacl doesn't include readdir_r! So we do the best we can. */
-int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
- errno = 0;
- *result = readdir(dirp);
- if (*result != NULL) {
- return 0;
- }
- if (errno) {
- return 1;
- }
- return 0;
-}
-#endif
-
-struct OPENSSL_dir_context_st {
- DIR *dir;
- struct dirent dirent;
-};
-
-const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
- struct dirent *dirent;
-
- if (ctx == NULL || directory == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- errno = 0;
- if (*ctx == NULL) {
- *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
- if (*ctx == NULL) {
- errno = ENOMEM;
- return 0;
- }
- memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
-
- (*ctx)->dir = opendir(directory);
- if ((*ctx)->dir == NULL) {
- int save_errno = errno; /* Probably not needed, but I'm paranoid */
- free(*ctx);
- *ctx = NULL;
- errno = save_errno;
- return 0;
- }
- }
-
- if (readdir_r((*ctx)->dir, &(*ctx)->dirent, &dirent) != 0 ||
- dirent == NULL) {
- return 0;
- }
-
- return (*ctx)->dirent.d_name;
-}
-
-int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
- if (ctx != NULL && *ctx != NULL) {
- int r = closedir((*ctx)->dir);
- free(*ctx);
- *ctx = NULL;
- return r == 0;
- }
-
- errno = EINVAL;
- return 0;
-}
-
-#endif /* !OPENSSL_WINDOWS */
diff --git a/crypto/directory_win.c b/crypto/directory_win.c
deleted file mode 100644
index 4ebacf21..00000000
--- a/crypto/directory_win.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* $LP: LPlib/source/LPdir_win.c,v 1.10 2004/08/26 13:36:05 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``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 COPYRIGHT
- * OWNER 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.
- */
-
-#include "directory.h"
-
-
-#if defined(OPENSSL_WINDOWS)
-
-#pragma warning(push, 3)
-#include <windows.h>
-#pragma warning(pop)
-#include <errno.h>
-#include <string.h>
-#include <tchar.h>
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-#include <openssl/mem.h>
-
-
-struct OPENSSL_dir_context_st {
- WIN32_FIND_DATA ctx;
- HANDLE handle;
- char entry_name[NAME_MAX + 1];
-};
-
-const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
- if (ctx == NULL || directory == NULL) {
- errno = EINVAL;
- return 0;
- }
-
- errno = 0;
- if (*ctx == NULL) {
- *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
- if (*ctx == NULL) {
- errno = ENOMEM;
- return 0;
- }
- memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
-
- if (sizeof(TCHAR) != sizeof(char)) {
- TCHAR *wdir = NULL;
- /* len_0 denotes string length *with* trailing 0 */
- size_t index = 0, len_0 = strlen(directory) + 1;
-
- wdir = (TCHAR *)malloc(len_0 * sizeof(TCHAR));
- if (wdir == NULL) {
- free(*ctx);
- *ctx = NULL;
- errno = ENOMEM;
- return 0;
- }
-
- if (!MultiByteToWideChar(CP_ACP, 0, directory, len_0, (WCHAR *)wdir,
- len_0)) {
- for (index = 0; index < len_0; index++) {
- wdir[index] = (TCHAR)directory[index];
- }
- }
-
- (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
-
- free(wdir);
- } else {
- (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
- }
-
- if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
- free(*ctx);
- *ctx = NULL;
- errno = EINVAL;
- return 0;
- }
- } else {
- if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
- return 0;
- }
- }
-
- if (sizeof(TCHAR) != sizeof(char)) {
- TCHAR *wdir = (*ctx)->ctx.cFileName;
- size_t index, len_0 = 0;
-
- while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) {
- len_0++;
- }
- len_0++;
-
- if (!WideCharToMultiByte(CP_ACP, 0, (WCHAR *)wdir, len_0,
- (*ctx)->entry_name, sizeof((*ctx)->entry_name),
- NULL, 0)) {
- for (index = 0; index < len_0; index++) {
- (*ctx)->entry_name[index] = (char)wdir[index];
- }
- }
- } else {
- strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
- sizeof((*ctx)->entry_name) - 1);
- }
-
- (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
-
- return (*ctx)->entry_name;
-}
-
-int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
- if (ctx != NULL && *ctx != NULL) {
- FindClose((*ctx)->handle);
- free(*ctx);
- *ctx = NULL;
- return 1;
- }
- errno = EINVAL;
- return 0;
-}
-
-#endif /* OPENSSL_WINDOWS */
diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c
index 979079d8..1de0071e 100644
--- a/crypto/dsa/dsa.c
+++ b/crypto/dsa/dsa.c
@@ -591,7 +591,6 @@ int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
size_t digest_len, DSA_SIG *sig, const DSA *dsa) {
BN_CTX *ctx;
BIGNUM u1, u2, t1;
- BN_MONT_CTX *mont = NULL;
int ret = 0;
unsigned i;
@@ -662,15 +661,14 @@ int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
goto err;
}
- mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
- (CRYPTO_MUTEX *)&dsa->method_mont_p_lock,
- dsa->p, ctx);
- if (!mont) {
+ if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
+ ctx)) {
goto err;
}
if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx,
- mont)) {
+ dsa->method_mont_p)) {
goto err;
}
@@ -823,9 +821,9 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
BN_set_flags(&k, BN_FLG_CONSTTIME);
- if (BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
- (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
- ctx) == NULL) {
+ if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
+ ctx)) {
goto err;
}
@@ -847,6 +845,7 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
goto err;
}
+ BN_set_flags(&kq, BN_FLG_CONSTTIME);
K = &kq;
if (!BN_mod_exp_mont(r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p)) {
diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c
index 7615fca2..ff5ee003 100644
--- a/crypto/dsa/dsa_asn1.c
+++ b/crypto/dsa/dsa_asn1.c
@@ -248,6 +248,7 @@ int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!DSA_SIG_marshal(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
@@ -275,6 +276,7 @@ int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!DSA_marshal_public_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
@@ -302,6 +304,7 @@ int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!DSA_marshal_private_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
@@ -329,6 +332,7 @@ int i2d_DSAparams(const DSA *in, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!DSA_marshal_parameters(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
diff --git a/crypto/ec/asm/p256-x86_64-asm.pl b/crypto/ec/asm/p256-x86_64-asm.pl
index 361a84b2..50a5fe6e 100644..100755
--- a/crypto/ec/asm/p256-x86_64-asm.pl
+++ b/crypto/ec/asm/p256-x86_64-asm.pl
@@ -1729,6 +1729,7 @@ $code.=<<___;
push %r15
sub \$32*5+8, %rsp
+.Lpoint_double_shortcut$x:
movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr.x
mov $a_ptr, $b_ptr # backup copy
movdqu 0x10($a_ptr), %xmm1
@@ -2019,6 +2020,7 @@ $code.=<<___;
mov 0x40+8*1($b_ptr), $acc6
mov 0x40+8*2($b_ptr), $acc7
mov 0x40+8*3($b_ptr), $acc0
+ movq $b_ptr, %xmm1
lea 0x40-$bias($b_ptr), $a_ptr
lea $Z1sqr(%rsp), $r_ptr # Z1^2
@@ -2074,7 +2076,7 @@ $code.=<<___;
test $acc0, $acc0
jnz .Ladd_proceed$x # (in1infty || in2infty)?
test $acc1, $acc1
- jz .Ladd_proceed$x # is_equal(S1,S2)?
+ jz .Ladd_double$x # is_equal(S1,S2)?
movq %xmm0, $r_ptr # restore $r_ptr
pxor %xmm0, %xmm0
@@ -2087,6 +2089,13 @@ $code.=<<___;
jmp .Ladd_done$x
.align 32
+.Ladd_double$x:
+ movq %xmm1, $a_ptr # restore $a_ptr
+ movq %xmm0, $r_ptr # restore $r_ptr
+ add \$`32*(18-5)`, %rsp # difference in frame sizes
+ jmp .Lpoint_double_shortcut$x
+
+.align 32
.Ladd_proceed$x:
`&load_for_sqr("$R(%rsp)", "$src0")`
lea $Rsqr(%rsp), $r_ptr # R^2
diff --git a/crypto/ec/ec.c b/crypto/ec/ec.c
index ca3ce373..8f3fa6e1 100644
--- a/crypto/ec/ec.c
+++ b/crypto/ec/ec.c
@@ -73,7 +73,7 @@
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
#include "../internal.h"
@@ -228,10 +228,25 @@ static const struct curve_data P521 = {
#endif
const struct built_in_curve OPENSSL_built_in_curves[] = {
- {NID_secp521r1, &P521, 0},
- {NID_secp384r1, &P384, 0},
{
- NID_X9_62_prime256v1, &P256,
+ NID_secp521r1,
+ /* 1.3.132.0.35 */
+ {0x2b, 0x81, 0x04, 0x00, 0x23}, 5,
+ &P521,
+ NULL,
+ },
+ {
+ NID_secp384r1,
+ /* 1.3.132.0.34 */
+ {0x2b, 0x81, 0x04, 0x00, 0x22}, 5,
+ &P384,
+ NULL,
+ },
+ {
+ NID_X9_62_prime256v1,
+ /* 1.2.840.10045.3.1.7 */
+ {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, 8,
+ &P256,
#if defined(BORINGSSL_USE_INT128_CODE)
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
!defined(OPENSSL_SMALL)
@@ -240,18 +255,21 @@ const struct built_in_curve OPENSSL_built_in_curves[] = {
EC_GFp_nistp256_method,
#endif
#else
- 0,
+ NULL,
#endif
},
{
- NID_secp224r1, &P224,
+ NID_secp224r1,
+ /* 1.3.132.0.33 */
+ {0x2b, 0x81, 0x04, 0x00, 0x21}, 5,
+ &P224,
#if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL)
EC_GFp_nistp224_method,
#else
- 0,
+ NULL,
#endif
},
- {NID_undef, 0, 0},
+ {NID_undef, {0}, 0, NULL, NULL},
};
/* built_in_curve_scalar_field_monts contains Montgomery contexts for
@@ -350,8 +368,8 @@ EC_GROUP *ec_group_new(const EC_METHOD *meth) {
return ret;
}
-static EC_GROUP *ec_group_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *ctx) {
+EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx) {
const EC_METHOD *meth = EC_GFp_mont_method();
EC_GROUP *ret;
@@ -371,35 +389,49 @@ static EC_GROUP *ec_group_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
return ret;
}
+int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
+ const BIGNUM *order, const BIGNUM *cofactor) {
+ if (group->curve_name != NID_undef || group->generator != NULL) {
+ /* |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by
+ * |EC_GROUP_new_curve_GFp| and may only used once on each group. */
+ return 0;
+ }
+
+ group->generator = EC_POINT_new(group);
+ return group->generator != NULL &&
+ EC_POINT_copy(group->generator, generator) &&
+ BN_copy(&group->order, order) &&
+ BN_copy(&group->cofactor, cofactor);
+}
+
EC_GROUP *EC_GROUP_new_arbitrary(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, const BIGNUM *gx,
const BIGNUM *gy, const BIGNUM *order,
const BIGNUM *cofactor) {
- EC_GROUP *ret = NULL;
- BN_CTX *ctx;
-
- ctx = BN_CTX_new();
+ BN_CTX *ctx = BN_CTX_new();
if (ctx == NULL) {
- goto err;
+ return NULL;
}
- ret = ec_group_new_curve_GFp(p, a, b, ctx);
+ EC_POINT *generator = NULL;
+ EC_GROUP *ret = EC_GROUP_new_curve_GFp(p, a, b, ctx);
if (ret == NULL) {
goto err;
}
- ret->generator = EC_POINT_new(ret);
- if (ret->generator == NULL ||
- !EC_POINT_set_affine_coordinates_GFp(ret, ret->generator, gx, gy, ctx) ||
- !BN_copy(&ret->order, order) ||
- !BN_copy(&ret->cofactor, cofactor)) {
+ generator = EC_POINT_new(ret);
+ if (generator == NULL ||
+ !EC_POINT_set_affine_coordinates_GFp(ret, generator, gx, gy, ctx) ||
+ !EC_GROUP_set_generator(ret, generator, order, cofactor)) {
goto err;
}
+ EC_POINT_free(generator);
BN_CTX_free(ctx);
return ret;
err:
+ EC_POINT_free(generator);
EC_GROUP_free(ret);
BN_CTX_free(ctx);
return NULL;
@@ -438,7 +470,7 @@ static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) {
goto err;
}
} else {
- if ((group = ec_group_new_curve_GFp(p, a, b, ctx)) == NULL) {
+ if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
goto err;
}
diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c
index a29a2dcf..f31e1587 100644
--- a/crypto/ec/ec_asn1.c
+++ b/crypto/ec/ec_asn1.c
@@ -60,7 +60,7 @@
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
#include "../bytestring/internal.h"
@@ -207,14 +207,9 @@ int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
}
if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) {
- int curve_nid = EC_GROUP_get_curve_name(key->group);
- if (curve_nid == NID_undef) {
- OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
- return 0;
- }
CBB child;
if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) ||
- !OBJ_nid2cbb(&child, curve_nid) ||
+ !EC_KEY_marshal_curve_name(&child, key->group) ||
!CBB_flush(&ec_private_key)) {
OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
return 0;
@@ -260,6 +255,9 @@ static int is_unsigned_integer(const CBS *cbs) {
return 1;
}
+/* kPrimeFieldOID is the encoding of 1.2.840.10045.1.1. */
+static const uint8_t kPrimeField[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01};
+
static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a,
CBS *out_b, CBS *out_base_x,
CBS *out_base_y, CBS *out_order) {
@@ -272,7 +270,8 @@ static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a,
version != 1 ||
!CBS_get_asn1(&params, &field_id, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) ||
- OBJ_cbs2nid(&field_type) != NID_X9_62_prime_field ||
+ CBS_len(&field_type) != sizeof(kPrimeField) ||
+ memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) != 0 ||
!CBS_get_asn1(&field_id, out_prime, CBS_ASN1_INTEGER) ||
!is_unsigned_integer(out_prime) ||
CBS_len(&field_id) != 0 ||
@@ -324,51 +323,86 @@ static int integers_equal(const CBS *a, const uint8_t *b, size_t b_len) {
return CBS_mem_equal(&a_copy, b, b_len);
}
-EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
- if (CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
- /* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
- * of named curves.
- *
- * TODO(davidben): Remove support for this. */
- CBS prime, a, b, base_x, base_y, order;
- if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y,
- &order)) {
- return NULL;
- }
+EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) {
+ CBS named_curve;
+ if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ return NULL;
+ }
- /* Look for a matching prime curve. */
- unsigned i;
- for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
- const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
- const unsigned param_len = curve->data->param_len;
- /* |curve->data->data| is ordered p, a, b, x, y, order, each component
- * zero-padded up to the field length. Although SEC 1 states that the
- * Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes
- * |a| and |b|, so this comparison must allow omitting leading zeros.
- * (This is relevant for P-521 whose |b| has a leading 0.) */
- if (integers_equal(&prime, curve->data->data, param_len) &&
- integers_equal(&a, curve->data->data + param_len, param_len) &&
- integers_equal(&b, curve->data->data + param_len * 2, param_len) &&
- integers_equal(&base_x, curve->data->data + param_len * 3,
- param_len) &&
- integers_equal(&base_y, curve->data->data + param_len * 4,
- param_len) &&
- integers_equal(&order, curve->data->data + param_len * 5,
- param_len)) {
- return EC_GROUP_new_by_curve_name(curve->nid);
- }
+ /* Look for a matching curve. */
+ unsigned i;
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+ if (CBS_len(&named_curve) == curve->oid_len &&
+ memcmp(CBS_data(&named_curve), curve->oid, curve->oid_len) == 0) {
+ return EC_GROUP_new_by_curve_name(curve->nid);
}
+ }
+
+ OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+ return NULL;
+}
+int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) {
+ int nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef) {
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
- return NULL;
+ return 0;
}
- CBS named_curve;
- if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) {
- OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+ unsigned i;
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+ if (curve->nid == nid) {
+ CBB child;
+ return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) &&
+ CBB_add_bytes(&child, curve->oid, curve->oid_len) &&
+ CBB_flush(cbb);
+ }
+ }
+
+ OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+ return 0;
+}
+
+EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
+ if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
+ return EC_KEY_parse_curve_name(cbs);
+ }
+
+ /* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
+ * of named curves.
+ *
+ * TODO(davidben): Remove support for this. */
+ CBS prime, a, b, base_x, base_y, order;
+ if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y,
+ &order)) {
return NULL;
}
- return EC_GROUP_new_by_curve_name(OBJ_cbs2nid(&named_curve));
+
+ /* Look for a matching prime curve. */
+ unsigned i;
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+ const unsigned param_len = curve->data->param_len;
+ /* |curve->data->data| is ordered p, a, b, x, y, order, each component
+ * zero-padded up to the field length. Although SEC 1 states that the
+ * Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes
+ * |a| and |b|, so this comparison must allow omitting leading zeros. (This
+ * is relevant for P-521 whose |b| has a leading 0.) */
+ if (integers_equal(&prime, curve->data->data, param_len) &&
+ integers_equal(&a, curve->data->data + param_len, param_len) &&
+ integers_equal(&b, curve->data->data + param_len * 2, param_len) &&
+ integers_equal(&base_x, curve->data->data + param_len * 3, param_len) &&
+ integers_equal(&base_y, curve->data->data + param_len * 4, param_len) &&
+ integers_equal(&order, curve->data->data + param_len * 5, param_len)) {
+ return EC_GROUP_new_by_curve_name(curve->nid);
+ }
+ }
+
+ OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+ return NULL;
}
EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) {
@@ -401,6 +435,7 @@ int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
@@ -440,15 +475,10 @@ int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
return -1;
}
- int curve_nid = EC_GROUP_get_curve_name(key->group);
- if (curve_nid == NID_undef) {
- OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
- return -1;
- }
-
CBB cbb;
if (!CBB_init(&cbb, 0) ||
- !OBJ_nid2cbb(&cbb, curve_nid)) {
+ !EC_KEY_marshal_curve_name(&cbb, key->group)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index f01bf6b4..fee71fed 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -365,15 +365,24 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
return 0;
}
ctx = BN_CTX_new();
+
+ if (ctx == NULL) {
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
point = EC_POINT_new(key->group);
- if (ctx == NULL ||
- point == NULL) {
+ if (point == NULL) {
goto err;
}
tx = BN_CTX_get(ctx);
ty = BN_CTX_get(ctx);
+ if (tx == NULL ||
+ ty == NULL) {
+ goto err;
+ }
if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) ||
!EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) {
@@ -398,6 +407,7 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
ok = 1;
err:
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
EC_POINT_free(point);
return ok;
diff --git a/crypto/ec/ec_montgomery.c b/crypto/ec/ec_montgomery.c
index 62b0d7f6..35df3651 100644
--- a/crypto/ec/ec_montgomery.c
+++ b/crypto/ec/ec_montgomery.c
@@ -79,23 +79,18 @@ int ec_GFp_mont_group_init(EC_GROUP *group) {
ok = ec_GFp_simple_group_init(group);
group->mont = NULL;
- group->one = NULL;
return ok;
}
void ec_GFp_mont_group_finish(EC_GROUP *group) {
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
- BN_free(group->one);
- group->one = NULL;
ec_GFp_simple_group_finish(group);
}
int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
BN_MONT_CTX_free(dest->mont);
dest->mont = NULL;
- BN_clear_free(dest->one);
- dest->one = NULL;
if (!ec_GFp_simple_group_copy(dest, src)) {
return 0;
@@ -110,12 +105,6 @@ int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
goto err;
}
}
- if (src->one != NULL) {
- dest->one = BN_dup(src->one);
- if (dest->one == NULL) {
- goto err;
- }
- }
return 1;
@@ -129,13 +118,10 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
BN_CTX *new_ctx = NULL;
BN_MONT_CTX *mont = NULL;
- BIGNUM *one = NULL;
int ret = 0;
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
- BN_free(group->one);
- group->one = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
@@ -152,29 +138,20 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
}
- one = BN_new();
- if (one == NULL || !BN_to_montgomery(one, BN_value_one(), mont, ctx)) {
- goto err;
- }
group->mont = mont;
mont = NULL;
- group->one = one;
- one = NULL;
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
if (!ret) {
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
- BN_free(group->one);
- group->one = NULL;
}
err:
BN_CTX_free(new_ctx);
BN_MONT_CTX_free(mont);
- BN_free(one);
return ret;
}
@@ -218,19 +195,6 @@ int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
return BN_from_montgomery(r, a, group->mont, ctx);
}
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
- BN_CTX *ctx) {
- if (group->one == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
- return 0;
- }
-
- if (!BN_copy(r, group->one)) {
- return 0;
- }
- return 1;
-}
-
static int ec_GFp_mont_check_pub_key_order(const EC_GROUP *group,
const EC_POINT* pub_key,
BN_CTX *ctx) {
@@ -251,20 +215,108 @@ err:
return ret;
}
+static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
+ if (EC_POINT_is_at_infinity(group, point)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
+ return 0;
+ }
+
+ BN_CTX *new_ctx = NULL;
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ }
+
+ int ret = 0;
+
+ BN_CTX_start(ctx);
+
+ if (BN_cmp(&point->Z, &group->one) == 0) {
+ /* |point| is already affine. */
+ if (x != NULL && !BN_from_montgomery(x, &point->X, group->mont, ctx)) {
+ goto err;
+ }
+ if (y != NULL && !BN_from_montgomery(y, &point->Y, group->mont, ctx)) {
+ goto err;
+ }
+ } else {
+ /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
+
+ BIGNUM *Z_1 = BN_CTX_get(ctx);
+ BIGNUM *Z_2 = BN_CTX_get(ctx);
+ BIGNUM *Z_3 = BN_CTX_get(ctx);
+ if (Z_1 == NULL ||
+ Z_2 == NULL ||
+ Z_3 == NULL) {
+ goto err;
+ }
+
+ /* The straightforward way to calculate the inverse of a Montgomery-encoded
+ * value where the result is Montgomery-encoded is:
+ *
+ * |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|.
+ *
+ * This is equivalent, but more efficient, because |BN_from_montgomery|
+ * is more efficient (at least in theory) than |BN_to_montgomery|, since it
+ * doesn't have to do the multiplication before the reduction. */
+ if (!BN_from_montgomery(Z_1, &point->Z, group->mont, ctx) ||
+ !BN_from_montgomery(Z_1, Z_1, group->mont, ctx) ||
+ !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) {
+ goto err;
+ }
+
+ if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, group->mont, ctx)) {
+ goto err;
+ }
+
+ /* Instead of using |BN_from_montgomery| to convert the |x| coordinate
+ * and then calling |BN_from_montgomery| again to convert the |y|
+ * coordinate below, convert the common factor |Z_2| once now, saving one
+ * reduction. */
+ if (!BN_from_montgomery(Z_2, Z_2, group->mont, ctx)) {
+ goto err;
+ }
+
+ if (x != NULL) {
+ if (!BN_mod_mul_montgomery(x, &point->X, Z_2, group->mont, ctx)) {
+ goto err;
+ }
+ }
+
+ if (y != NULL) {
+ if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, group->mont, ctx) ||
+ !BN_mod_mul_montgomery(y, &point->Y, Z_3, group->mont, ctx)) {
+ goto err;
+ }
+ }
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
const EC_METHOD *EC_GFp_mont_method(void) {
static const EC_METHOD ret = {
ec_GFp_mont_group_init,
ec_GFp_mont_group_finish,
ec_GFp_mont_group_copy,
ec_GFp_mont_group_set_curve,
- ec_GFp_simple_point_get_affine_coordinates,
+ ec_GFp_mont_point_get_affine_coordinates,
ec_wNAF_mul /* XXX: Not constant time. */,
ec_GFp_mont_check_pub_key_order,
ec_GFp_mont_field_mul,
ec_GFp_mont_field_sqr,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
- ec_GFp_mont_field_set_to_one,
};
return &ret;
diff --git a/crypto/ec/ec_test.cc b/crypto/ec/ec_test.cc
index d45e193a..ce9d99f3 100644
--- a/crypto/ec/ec_test.cc
+++ b/crypto/ec/ec_test.cc
@@ -122,7 +122,7 @@ static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
return true;
}
-bool Testd2i_ECPrivateKey() {
+static bool Testd2i_ECPrivateKey() {
ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithoutPublic,
sizeof(kECKeyWithoutPublic));
if (!key) {
@@ -349,23 +349,32 @@ static bool TestArbitraryCurve() {
0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
};
+ ScopedBN_CTX ctx(BN_CTX_new());
ScopedBIGNUM p(BN_bin2bn(kP, sizeof(kP), nullptr));
ScopedBIGNUM a(BN_bin2bn(kA, sizeof(kA), nullptr));
ScopedBIGNUM b(BN_bin2bn(kB, sizeof(kB), nullptr));
- ScopedBIGNUM x(BN_bin2bn(kX, sizeof(kX), nullptr));
- ScopedBIGNUM y(BN_bin2bn(kY, sizeof(kY), nullptr));
+ ScopedBIGNUM gx(BN_bin2bn(kX, sizeof(kX), nullptr));
+ ScopedBIGNUM gy(BN_bin2bn(kY, sizeof(kY), nullptr));
ScopedBIGNUM order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
ScopedBIGNUM cofactor(BN_new());
- if (!p || !a || !b || !x || !y || !order || !cofactor ||
+ if (!ctx || !p || !a || !b || !gx || !gy || !order || !cofactor ||
!BN_set_word(cofactor.get(), 1)) {
return false;
}
- ScopedEC_GROUP group(EC_GROUP_new_arbitrary(p.get(), a.get(), b.get(),
- x.get(), y.get(), order.get(),
- cofactor.get()));
+
+ ScopedEC_GROUP group(
+ EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
if (!group) {
return false;
}
+ ScopedEC_POINT generator(EC_POINT_new(group.get()));
+ if (!generator ||
+ !EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(),
+ gx.get(), gy.get(), ctx.get()) ||
+ !EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
+ cofactor.get())) {
+ return false;
+ }
// |group| should not have a curve name.
if (EC_GROUP_get_curve_name(group.get()) != NID_undef) {
@@ -375,7 +384,8 @@ static bool TestArbitraryCurve() {
// Copy |key| to |key2| using |group|.
ScopedEC_KEY key2(EC_KEY_new());
ScopedEC_POINT point(EC_POINT_new(group.get()));
- if (!key2 || !point ||
+ ScopedBIGNUM x(BN_new()), y(BN_new());
+ if (!key2 || !point || !x || !y ||
!EC_KEY_set_group(key2.get(), group.get()) ||
!EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) ||
!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
@@ -394,6 +404,101 @@ static bool TestArbitraryCurve() {
return false;
}
+ // Repeat the process for |EC_GROUP_new_arbitrary|.
+ group.reset(EC_GROUP_new_arbitrary(p.get(), a.get(), b.get(), gx.get(),
+ gy.get(), order.get(), cofactor.get()));
+ if (!group) {
+ return false;
+ }
+
+ // |group| should not have a curve name.
+ if (EC_GROUP_get_curve_name(group.get()) != NID_undef) {
+ return false;
+ }
+
+ // Copy |key| to |key2| using |group|.
+ key2.reset(EC_KEY_new());
+ point.reset(EC_POINT_new(group.get()));
+ if (!key2 || !point ||
+ !EC_KEY_set_group(key2.get(), group.get()) ||
+ !EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) ||
+ !EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(),
+ y.get(), nullptr) ||
+ !EC_KEY_set_public_key(key2.get(), point.get())) {
+ fprintf(stderr, "Could not copy key.\n");
+ return false;
+ }
+
+ // The key must be valid according to the new group too.
+ if (!EC_KEY_check_key(key2.get())) {
+ fprintf(stderr, "Copied key is not valid.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestAddingEqualPoints(int nid) {
+ ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
+ if (!key) {
+ return false;
+ }
+
+ const EC_GROUP *const group = EC_KEY_get0_group(key.get());
+
+ if (!EC_KEY_generate_key(key.get())) {
+ fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid);
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ ScopedEC_POINT p1(EC_POINT_new(group));
+ ScopedEC_POINT p2(EC_POINT_new(group));
+ ScopedEC_POINT double_p1(EC_POINT_new(group));
+ ScopedEC_POINT p1_plus_p2(EC_POINT_new(group));
+ if (!p1 || !p2 || !double_p1 || !p1_plus_p2) {
+ return false;
+ }
+
+ if (!EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())) ||
+ !EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))) {
+ fprintf(stderr, "EC_POINT_COPY failed with nid %d\n", nid);
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ ScopedBN_CTX ctx(BN_CTX_new());
+ if (!ctx) {
+ return false;
+ }
+
+ if (!EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()) ||
+ !EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())) {
+ fprintf(stderr, "Point operation failed with nid %d\n", nid);
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()) != 0) {
+ fprintf(stderr, "A+A != 2A for nid %d", nid);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ForEachCurve(bool (*test_func)(int nid)) {
+ const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
+ std::vector<EC_builtin_curve> curves(num_curves);
+ EC_get_builtin_curves(curves.data(), num_curves);
+
+ for (const auto& curve : curves) {
+ if (!test_func(curve.nid)) {
+ fprintf(stderr, "Test failed for %s\n", curve.comment);
+ return false;
+ }
+ }
+
return true;
}
@@ -403,10 +508,8 @@ int main(void) {
if (!Testd2i_ECPrivateKey() ||
!TestZeroPadding() ||
!TestSpecifiedCurve() ||
- !TestSetAffine(NID_secp224r1) ||
- !TestSetAffine(NID_X9_62_prime256v1) ||
- !TestSetAffine(NID_secp384r1) ||
- !TestSetAffine(NID_secp521r1) ||
+ !ForEachCurve(TestSetAffine) ||
+ !ForEachCurve(TestAddingEqualPoints) ||
!TestArbitraryCurve()) {
fprintf(stderr, "failed\n");
return 1;
diff --git a/crypto/ec/example_mul.c b/crypto/ec/example_mul.c
index ebb724fa..a2bdd527 100644
--- a/crypto/ec/example_mul.c
+++ b/crypto/ec/example_mul.c
@@ -70,10 +70,10 @@
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/ec.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
-int example_EC_POINT_mul(void) {
+static int example_EC_POINT_mul(void) {
/* This example ensures that 10×∞ + G = G, in P-256. */
EC_GROUP *group = NULL;
EC_POINT *p = NULL, *result = NULL;
diff --git a/crypto/ec/internal.h b/crypto/ec/internal.h
index 2b788c1c..f2cbb961 100644
--- a/crypto/ec/internal.h
+++ b/crypto/ec/internal.h
@@ -116,7 +116,6 @@ struct ec_method_st {
BN_CTX *); /* e.g. to Montgomery */
int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *); /* e.g. from Montgomery */
- int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
} /* EC_METHOD */;
const EC_METHOD* EC_GFp_mont_method(void);
@@ -141,7 +140,8 @@ struct ec_group_st {
int a_is_minus3; /* enable optimized point arithmetics for special case */
BN_MONT_CTX *mont; /* Montgomery structure. */
- BIGNUM *one; /* The value one */
+
+ BIGNUM one; /* The value one. */
} /* EC_GROUP */;
struct ec_point_st {
@@ -151,7 +151,6 @@ struct ec_point_st {
BIGNUM Y;
BIGNUM Z; /* Jacobian projective coordinates:
* (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */
- int Z_is_one; /* enable optimized point arithmetics for special case */
} /* EC_POINT */;
EC_GROUP *ec_group_new(const EC_METHOD *meth);
@@ -190,9 +189,6 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *,
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *);
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *,
- const EC_POINT *, BIGNUM *x,
- BIGNUM *y, BN_CTX *);
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
const BIGNUM *x, int y_bit,
BN_CTX *);
@@ -227,22 +223,12 @@ int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx);
-void ec_GFp_nistp_points_make_affine_internal(
- size_t num, void *point_array, size_t felem_size, void *tmp_felems,
- void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
- void (*felem_assign)(void *out, const void *in),
- void (*felem_square)(void *out, const void *in),
- void (*felem_mul)(void *out, const void *in1, const void *in2),
- void (*felem_inv)(void *out, const void *in),
- void (*felem_contract)(void *out, const void *in));
-
void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in);
const EC_METHOD *EC_GFp_nistp224_method(void);
@@ -285,6 +271,8 @@ struct curve_data {
struct built_in_curve {
int nid;
+ uint8_t oid[8];
+ uint8_t oid_len;
const struct curve_data *data;
const EC_METHOD *(*method)(void);
};
diff --git a/crypto/ec/oct.c b/crypto/ec/oct.c
index 9e18535a..bf1957ca 100644
--- a/crypto/ec/oct.c
+++ b/crypto/ec/oct.c
@@ -281,10 +281,15 @@ int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
}
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x_,
+ EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx) {
+ if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
+ return 0;
+ }
+
BN_CTX *new_ctx = NULL;
- BIGNUM *tmp1, *tmp2, *x, *y;
+ BIGNUM *tmp1, *tmp2, *y;
int ret = 0;
ERR_clear_error();
@@ -301,7 +306,6 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
BN_CTX_start(ctx);
tmp1 = BN_CTX_get(ctx);
tmp2 = BN_CTX_get(ctx);
- x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL) {
goto err;
@@ -312,19 +316,15 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
* so y is one of the square roots of x^3 + a*x + b. */
/* tmp1 := x^3 */
- if (!BN_nnmod(x, x_, &group->field, ctx)) {
- goto err;
- }
-
if (group->meth->field_decode == 0) {
/* field_{sqr,mul} work on standard representation */
- if (!group->meth->field_sqr(group, tmp2, x_, ctx) ||
- !group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) {
+ if (!group->meth->field_sqr(group, tmp2, x, ctx) ||
+ !group->meth->field_mul(group, tmp1, tmp2, x, ctx)) {
goto err;
}
} else {
- if (!BN_mod_sqr(tmp2, x_, &group->field, ctx) ||
- !BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) {
+ if (!BN_mod_sqr(tmp2, x, &group->field, ctx) ||
+ !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) {
goto err;
}
}
diff --git a/crypto/ec/p224-64.c b/crypto/ec/p224-64.c
index 9de6cd49..7bf889c9 100644
--- a/crypto/ec/p224-64.c
+++ b/crypto/ec/p224-64.c
@@ -26,7 +26,6 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <string.h>
@@ -193,7 +192,7 @@ static void bin28_to_felem(felem out, const u8 in[28]) {
}
static void felem_to_bin28(u8 out[28], const felem in) {
- unsigned i;
+ size_t i;
for (i = 0; i < 7; ++i) {
out[i] = in[0] >> (8 * i);
out[i + 7] = in[1] >> (8 * i);
@@ -203,8 +202,8 @@ static void felem_to_bin28(u8 out[28], const felem in) {
}
/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
-static void flip_endian(u8 *out, const u8 *in, unsigned len) {
- unsigned i;
+static void flip_endian(u8 *out, const u8 *in, size_t len) {
+ size_t i;
for (i = 0; i < len; ++i) {
out[i] = in[len - 1 - i];
}
@@ -215,7 +214,7 @@ static int BN_to_felem(felem out, const BIGNUM *bn) {
/* BN_bn2bin eats leading zeroes */
felem_bytearray b_out;
memset(b_out, 0, sizeof(b_out));
- unsigned num_bytes = BN_num_bytes(bn);
+ size_t num_bytes = BN_num_bytes(bn);
if (num_bytes > sizeof(b_out) ||
BN_is_negative(bn)) {
OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE);
@@ -242,13 +241,6 @@ static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) {
* expected to be correct in general - e.g., multiplication with a large scalar
* will cause an overflow. */
-static void felem_one(felem out) {
- out[0] = 1;
- out[1] = 0;
- out[2] = 0;
- out[3] = 0;
-}
-
static void felem_assign(felem out, const felem in) {
out[0] = in[0];
out[1] = in[1];
@@ -460,18 +452,6 @@ static void felem_reduce(felem out, const widefelem in) {
out[3] = output[3];
}
-static void felem_square_reduce(felem out, const felem in) {
- widefelem tmp;
- felem_square(tmp, in);
- felem_reduce(out, tmp);
-}
-
-static void felem_mul_reduce(felem out, const felem in1, const felem in2) {
- widefelem tmp;
- felem_mul(tmp, in1, in2);
- felem_reduce(out, tmp);
-}
-
/* Reduce to unique minimal representation.
* Requires 0 <= in < 2*p (always call felem_reduce first) */
static void felem_contract(felem out, const felem in) {
@@ -539,16 +519,12 @@ static limb felem_is_zero(const felem in) {
return (zero | two224m96p1 | two225m97p2);
}
-static limb felem_is_zero_int(const felem in) {
- return (int)(felem_is_zero(in) & ((limb)1));
-}
-
/* Invert a field element */
/* Computation chain copied from djb's code */
static void felem_inv(felem out, const felem in) {
felem ftmp, ftmp2, ftmp3, ftmp4;
widefelem tmp;
- unsigned i;
+ size_t i;
felem_square(tmp, in);
felem_reduce(ftmp, tmp); /* 2 */
@@ -628,7 +604,7 @@ static void felem_inv(felem out, const felem in) {
* if icopy == 1, copy in to out,
* if icopy == 0, copy out to itself. */
static void copy_conditional(felem out, const felem in, limb icopy) {
- unsigned i;
+ size_t i;
/* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */
const limb copy = -icopy;
for (i = 0; i < 4; ++i) {
@@ -885,12 +861,12 @@ static void point_add(felem x3, felem y3, felem z3, const felem x1,
/* select_point selects the |idx|th point from a precomputation table and
* copies it to out. */
-static void select_point(const u64 idx, unsigned int size,
+static void select_point(const u64 idx, size_t size,
const felem pre_comp[/*size*/][3], felem out[3]) {
- unsigned i, j;
limb *outlimbs = &out[0][0];
memset(outlimbs, 0, 3 * sizeof(felem));
+ size_t i;
for (i = 0; i < size; i++) {
const limb *inlimbs = &pre_comp[i][0][0];
u64 mask = i ^ idx;
@@ -899,6 +875,7 @@ static void select_point(const u64 idx, unsigned int size,
mask |= mask >> 1;
mask &= 1;
mask--;
+ size_t j;
for (j = 0; j < 4 * 3; j++) {
outlimbs[j] |= inlimbs[j] & mask;
}
@@ -906,7 +883,7 @@ static void select_point(const u64 idx, unsigned int size,
}
/* get_bit returns the |i|th bit in |in| */
-static char get_bit(const felem_bytearray in, unsigned i) {
+static char get_bit(const felem_bytearray in, size_t i) {
if (i >= 224) {
return 0;
}
@@ -920,11 +897,8 @@ static char get_bit(const felem_bytearray in, unsigned i) {
* Output point (X, Y, Z) is stored in x_out, y_out, z_out */
static void batch_mul(felem x_out, felem y_out, felem z_out,
const felem_bytearray scalars[],
- const unsigned num_points, const u8 *g_scalar,
- const int mixed, const felem pre_comp[][17][3]) {
- int i, skip;
- unsigned num;
- unsigned gen_mul = (g_scalar != NULL);
+ const size_t num_points, const u8 *g_scalar,
+ const felem pre_comp[][17][3]) {
felem nq[3], tmp[4];
u64 bits;
u8 sign, digit;
@@ -935,15 +909,16 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
/* Loop over all scalars msb-to-lsb, interleaving additions
* of multiples of the generator (two in each of the last 28 rounds)
* and additions of other points multiples (every 5th round). */
- skip = 1; /* save two point operations in the first round */
- for (i = (num_points ? 220 : 27); i >= 0; --i) {
+ int skip = 1; /* save two point operations in the first round */
+ size_t i = num_points != 0 ? 220 : 27;
+ for (;;) {
/* double */
if (!skip) {
point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
}
/* add multiples of the generator */
- if (gen_mul && (i <= 27)) {
+ if (g_scalar != NULL && i <= 27) {
/* first, look 28 bits upwards */
bits = get_bit(g_scalar, i + 196) << 3;
bits |= get_bit(g_scalar, i + 140) << 2;
@@ -972,8 +947,9 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
}
/* do other additions every 5 doublings */
- if (num_points && (i % 5 == 0)) {
+ if (num_points != 0 && i % 5 == 0) {
/* loop over all scalars */
+ size_t num;
for (num = 0; num < num_points; ++num) {
bits = get_bit(scalars[num], i + 4) << 5;
bits |= get_bit(scalars[num], i + 3) << 4;
@@ -989,14 +965,19 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
copy_conditional(tmp[1], tmp[3], sign);
if (!skip) {
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], mixed, tmp[0],
- tmp[1], tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */,
+ tmp[0], tmp[1], tmp[2]);
} else {
memcpy(nq, tmp, 3 * sizeof(felem));
skip = 0;
}
}
}
+
+ if (i == 0) {
+ break;
+ }
+ --i;
}
felem_assign(x_out, nq[0]);
felem_assign(y_out, nq[1]);
@@ -1005,10 +986,10 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
* (X', Y') = (X/Z^2, Y/Z^3) */
-int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx) {
+static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
felem z1, z2, x_in, y_in, x_out, y_out;
widefelem tmp;
@@ -1047,23 +1028,12 @@ int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
return 1;
}
-static void make_points_affine(size_t num, felem points[/*num*/][3],
- felem tmp_felems[/*num+1*/]) {
- /* Runs in constant time, unless an input is the point at infinity
- * (which normally shouldn't happen). */
- ec_GFp_nistp_points_make_affine_internal(
- num, points, sizeof(felem), tmp_felems, (void (*)(void *))felem_one,
- (int (*)(const void *))felem_is_zero_int,
- (void (*)(void *, const void *))felem_assign,
- (void (*)(void *, const void *))felem_square_reduce,
- (void (*)(void *, const void *, const void *))felem_mul_reduce,
- (void (*)(void *, const void *))felem_inv,
- (void (*)(void *, const void *))felem_contract);
-}
-
-int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *g_scalar, const EC_POINT *p_,
- const BIGNUM *p_scalar_, BN_CTX *ctx) {
+static int ec_GFp_nistp224_points_mul(const EC_GROUP *group,
+ EC_POINT *r,
+ const BIGNUM *g_scalar,
+ const EC_POINT *p_,
+ const BIGNUM *p_scalar_,
+ BN_CTX *ctx) {
/* TODO: This function used to take |points| and |scalars| as arrays of
* |num| elements. The code below should be simplified to work in terms of
* |p_| and |p_scalar_|. */
@@ -1072,17 +1042,12 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL;
int ret = 0;
- int j;
- unsigned i;
- int mixed = 0;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *z, *tmp_scalar;
felem_bytearray g_secret;
felem_bytearray *secrets = NULL;
felem(*pre_comp)[17][3] = NULL;
- felem *tmp_felems = NULL;
felem_bytearray tmp;
- unsigned num_bytes;
size_t num_points = num;
felem x_in, y_in, z_in, x_out, y_out, z_out;
const EC_POINT *p = NULL;
@@ -1105,19 +1070,10 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
}
if (num_points > 0) {
- if (num_points >= 3) {
- /* unless we precompute multiples for just one or two points,
- * converting those into affine form is time well spent */
- mixed = 1;
- }
secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
pre_comp = OPENSSL_malloc(num_points * sizeof(felem[17][3]));
- if (mixed) {
- tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem));
- }
if (secrets == NULL ||
- pre_comp == NULL ||
- (mixed && tmp_felems == NULL)) {
+ pre_comp == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1126,6 +1082,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
* i.e., they contribute nothing to the linear combination */
memset(secrets, 0, num_points * sizeof(felem_bytearray));
memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem));
+ size_t i;
for (i = 0; i < num_points; ++i) {
if (i == num) {
/* the generator */
@@ -1138,6 +1095,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
}
if (p_scalar != NULL && p != NULL) {
+ size_t num_bytes;
/* reduce g_scalar to 0 <= g_scalar < 2^224 */
if (BN_num_bits(p_scalar) > 224 || BN_is_negative(p_scalar)) {
/* this is an unusual input, and we don't guarantee
@@ -1163,6 +1121,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
felem_assign(pre_comp[i][1][1], y_out);
felem_assign(pre_comp[i][1][2], z_out);
+ size_t j;
for (j = 2; j <= 16; ++j) {
if (j & 1) {
point_add(pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
@@ -1177,14 +1136,11 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
}
}
}
-
- if (mixed) {
- make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
- }
}
if (g_scalar != NULL) {
memset(g_secret, 0, sizeof(g_secret));
+ size_t num_bytes;
/* reduce g_scalar to 0 <= g_scalar < 2^224 */
if (BN_num_bits(g_scalar) > 224 || BN_is_negative(g_scalar)) {
/* this is an unusual input, and we don't guarantee constant-timeness */
@@ -1200,7 +1156,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
flip_endian(g_secret, tmp, num_bytes);
}
batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
- num_points, g_scalar != NULL ? g_secret : NULL, mixed,
+ num_points, g_scalar != NULL ? g_secret : NULL,
(const felem(*)[17][3])pre_comp);
/* reduce the output to its unique minimal representation */
@@ -1220,7 +1176,6 @@ err:
BN_CTX_free(new_ctx);
OPENSSL_free(secrets);
OPENSSL_free(pre_comp);
- OPENSSL_free(tmp_felems);
return ret;
}
@@ -1235,8 +1190,7 @@ const EC_METHOD *EC_GFp_nistp224_method(void) {
ec_GFp_simple_field_mul,
ec_GFp_simple_field_sqr,
0 /* field_encode */,
- 0 /* field_decode */,
- 0 /* field_set_to_one */};
+ 0 /* field_decode */};
return &ret;
}
diff --git a/crypto/ec/p256-64.c b/crypto/ec/p256-64.c
index b94e226e..c4259b62 100644
--- a/crypto/ec/p256-64.c
+++ b/crypto/ec/p256-64.c
@@ -27,7 +27,6 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <string.h>
@@ -94,8 +93,8 @@ static void smallfelem_to_bin32(u8 out[32], const smallfelem in) {
}
/* To preserve endianness when using BN_bn2bin and BN_bin2bn. */
-static void flip_endian(u8 *out, const u8 *in, unsigned len) {
- unsigned i;
+static void flip_endian(u8 *out, const u8 *in, size_t len) {
+ size_t i;
for (i = 0; i < len; ++i) {
out[i] = in[len - 1 - i];
}
@@ -111,7 +110,7 @@ static int BN_to_felem(felem out, const BIGNUM *bn) {
felem_bytearray b_out;
/* BN_bn2bin eats leading zeroes */
memset(b_out, 0, sizeof(b_out));
- unsigned num_bytes = BN_num_bytes(bn);
+ size_t num_bytes = BN_num_bytes(bn);
if (num_bytes > sizeof(b_out)) {
OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
@@ -134,20 +133,6 @@ static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) {
/* Field operations. */
-static void smallfelem_one(smallfelem out) {
- out[0] = 1;
- out[1] = 0;
- out[2] = 0;
- out[3] = 0;
-}
-
-static void smallfelem_assign(smallfelem out, const smallfelem in) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- out[3] = in[3];
-}
-
static void felem_assign(felem out, const felem in) {
out[0] = in[0];
out[1] = in[1];
@@ -343,8 +328,7 @@ static void felem_shrink(smallfelem out, const felem in) {
* conditionally subtract kPrime if tmp[3] is large enough. */
high = tmp[3] >> 64;
/* As tmp[3] < 2^65, high is either 1 or 0 */
- high <<= 63;
- high >>= 63;
+ high = ~(high - 1);
/* high is:
* all ones if the high word of tmp[3] is 1
* all zeros if the high word of tmp[3] if 0 */
@@ -735,7 +719,7 @@ static void felem_contract(smallfelem out, const felem in) {
* each u64, from most-significant to least significant. For each one, if
* all words so far have been equal (m is all ones) then a non-equal
* result is the answer. Otherwise we continue. */
- unsigned i;
+ size_t i;
for (i = 3; i < 4; i--) {
u64 equal;
uint128_t a = ((uint128_t)kPrime[i]) - out[i];
@@ -779,25 +763,6 @@ static void felem_contract(smallfelem out, const felem in) {
subtract_u64(&out[3], &carry, result & kPrime[3]);
}
-static void smallfelem_square_contract(smallfelem out, const smallfelem in) {
- longfelem longtmp;
- felem tmp;
-
- smallfelem_square(longtmp, in);
- felem_reduce(tmp, longtmp);
- felem_contract(out, tmp);
-}
-
-static void smallfelem_mul_contract(smallfelem out, const smallfelem in1,
- const smallfelem in2) {
- longfelem longtmp;
- felem tmp;
-
- smallfelem_mul(longtmp, in1, in2);
- felem_reduce(tmp, longtmp);
- felem_contract(out, tmp);
-}
-
/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
* otherwise.
* On entry:
@@ -834,10 +799,6 @@ static limb smallfelem_is_zero(const smallfelem small) {
return result;
}
-static int smallfelem_is_zero_int(const smallfelem small) {
- return (int)(smallfelem_is_zero(small) & ((limb)1));
-}
-
/* felem_inv calculates |out| = |in|^{-1}
*
* Based on Fermat's Little Theorem:
@@ -849,7 +810,7 @@ static void felem_inv(felem out, const felem in) {
/* each e_I will hold |in|^{2^I - 1} */
felem e2, e4, e8, e16, e32, e64;
longfelem tmp;
- unsigned i;
+ size_t i;
felem_square(tmp, in);
felem_reduce(ftmp, tmp); /* 2^1 */
@@ -937,14 +898,6 @@ static void felem_inv(felem out, const felem in) {
felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */
}
-static void smallfelem_inv_contract(smallfelem out, const smallfelem in) {
- felem tmp;
-
- smallfelem_expand(tmp, in);
- felem_inv(tmp, tmp);
- felem_contract(out, tmp);
-}
-
/* Group operations
* ----------------
*
@@ -1055,7 +1008,7 @@ static void point_double_small(smallfelem x_out, smallfelem y_out,
/* copy_conditional copies in to out iff mask is all ones. */
static void copy_conditional(felem out, const felem in, limb mask) {
- unsigned i;
+ size_t i;
for (i = 0; i < NLIMBS; ++i) {
const limb tmp = mask & (in[i] ^ out[i]);
out[i] ^= tmp;
@@ -1064,7 +1017,7 @@ static void copy_conditional(felem out, const felem in, limb mask) {
/* copy_small_conditional copies in to out iff mask is all ones. */
static void copy_small_conditional(felem out, const smallfelem in, limb mask) {
- unsigned i;
+ size_t i;
const u64 mask64 = mask;
for (i = 0; i < NLIMBS; ++i) {
out[i] = ((limb)(in[i] & mask64)) | (out[i] & ~mask);
@@ -1448,12 +1401,13 @@ static const smallfelem g_pre_comp[2][16][3] = {
/* select_point selects the |idx|th point from a precomputation table and
* copies it to out. */
-static void select_point(const u64 idx, unsigned int size,
- const smallfelem pre_comp[16][3], smallfelem out[3]) {
- unsigned i, j;
+static void select_point(const u64 idx, size_t size,
+ const smallfelem pre_comp[/*size*/][3],
+ smallfelem out[3]) {
u64 *outlimbs = &out[0][0];
memset(outlimbs, 0, 3 * sizeof(smallfelem));
+ size_t i;
for (i = 0; i < size; i++) {
const u64 *inlimbs = (const u64 *)&pre_comp[i][0][0];
u64 mask = i ^ idx;
@@ -1462,6 +1416,7 @@ static void select_point(const u64 idx, unsigned int size,
mask |= mask >> 1;
mask &= 1;
mask--;
+ size_t j;
for (j = 0; j < NLIMBS * 3; j++) {
outlimbs[j] |= inlimbs[j] & mask;
}
@@ -1483,10 +1438,8 @@ static char get_bit(const felem_bytearray in, int i) {
* Output point (X, Y, Z) is stored in x_out, y_out, z_out. */
static void batch_mul(felem x_out, felem y_out, felem z_out,
const felem_bytearray scalars[],
- const unsigned num_points, const u8 *g_scalar,
- const int mixed, const smallfelem pre_comp[][17][3]) {
- int i, skip;
- unsigned num, gen_mul = (g_scalar != NULL);
+ const size_t num_points, const u8 *g_scalar,
+ const smallfelem pre_comp[][17][3]) {
felem nq[3], ftmp;
smallfelem tmp[3];
u64 bits;
@@ -1499,16 +1452,16 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
* of the generator (two in each of the last 32 rounds) and additions of
* other points multiples (every 5th round). */
- skip = 1; /* save two point operations in the first
- * round */
- for (i = (num_points ? 255 : 31); i >= 0; --i) {
+ int skip = 1; /* save two point operations in the first round */
+ size_t i = num_points != 0 ? 255 : 31;
+ for (;;) {
/* double */
if (!skip) {
point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
}
/* add multiples of the generator */
- if (gen_mul && i <= 31) {
+ if (g_scalar != NULL && i <= 31) {
/* first, look 32 bits upwards */
bits = get_bit(g_scalar, i + 224) << 3;
bits |= get_bit(g_scalar, i + 160) << 2;
@@ -1518,9 +1471,8 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
select_point(bits, 16, g_pre_comp[1], tmp);
if (!skip) {
- /* Arg 1 below is for "mixed" */
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
- tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
+ tmp[0], tmp[1], tmp[2]);
} else {
smallfelem_expand(nq[0], tmp[0]);
smallfelem_expand(nq[1], tmp[1]);
@@ -1535,14 +1487,14 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
bits |= get_bit(g_scalar, i);
/* select the point to add, in constant time */
select_point(bits, 16, g_pre_comp[0], tmp);
- /* Arg 1 below is for "mixed" */
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
- tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0],
+ tmp[1], tmp[2]);
}
/* do other additions every 5 doublings */
- if (num_points && (i % 5 == 0)) {
+ if (num_points != 0 && i % 5 == 0) {
/* loop over all scalars */
+ size_t num;
for (num = 0; num < num_points; ++num) {
bits = get_bit(scalars[num], i + 4) << 5;
bits |= get_bit(scalars[num], i + 3) << 4;
@@ -1560,8 +1512,8 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
felem_contract(tmp[1], ftmp);
if (!skip) {
- point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], mixed, tmp[0],
- tmp[1], tmp[2]);
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */,
+ tmp[0], tmp[1], tmp[2]);
} else {
smallfelem_expand(nq[0], tmp[0]);
smallfelem_expand(nq[1], tmp[1]);
@@ -1570,6 +1522,11 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
}
}
}
+
+ if (i == 0) {
+ break;
+ }
+ --i;
}
felem_assign(x_out, nq[0]);
felem_assign(y_out, nq[1]);
@@ -1583,10 +1540,10 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
* (X/Z^2, Y/Z^3). */
-int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point,
- BIGNUM *x, BIGNUM *y,
- BN_CTX *ctx) {
+static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
felem z1, z2, x_in, y_in;
smallfelem x_out, y_out;
longfelem tmp;
@@ -1603,45 +1560,38 @@ int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
felem_inv(z2, z1);
felem_square(tmp, z2);
felem_reduce(z1, tmp);
- felem_mul(tmp, x_in, z1);
- felem_reduce(x_in, tmp);
- felem_contract(x_out, x_in);
- if (x != NULL && !smallfelem_to_BN(x, x_out)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- return 0;
+
+ if (x != NULL) {
+ felem_mul(tmp, x_in, z1);
+ felem_reduce(x_in, tmp);
+ felem_contract(x_out, x_in);
+ if (!smallfelem_to_BN(x, x_out)) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+ return 0;
+ }
}
- felem_mul(tmp, z1, z2);
- felem_reduce(z1, tmp);
- felem_mul(tmp, y_in, z1);
- felem_reduce(y_in, tmp);
- felem_contract(y_out, y_in);
- if (y != NULL && !smallfelem_to_BN(y, y_out)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- return 0;
+
+ if (y != NULL) {
+ felem_mul(tmp, z1, z2);
+ felem_reduce(z1, tmp);
+ felem_mul(tmp, y_in, z1);
+ felem_reduce(y_in, tmp);
+ felem_contract(y_out, y_in);
+ if (!smallfelem_to_BN(y, y_out)) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+ return 0;
+ }
}
- return 1;
-}
-/* points below is of size |num|, and tmp_smallfelems is of size |num+1| */
-static void make_points_affine(size_t num, smallfelem points[][3],
- smallfelem tmp_smallfelems[]) {
- /* Runs in constant time, unless an input is the point at infinity (which
- * normally shouldn't happen). */
- ec_GFp_nistp_points_make_affine_internal(
- num, points, sizeof(smallfelem), tmp_smallfelems,
- (void (*)(void *))smallfelem_one,
- (int (*)(const void *))smallfelem_is_zero_int,
- (void (*)(void *, const void *))smallfelem_assign,
- (void (*)(void *, const void *))smallfelem_square_contract,
- (void (*)(void *, const void *, const void *))smallfelem_mul_contract,
- (void (*)(void *, const void *))smallfelem_inv_contract,
- /* nothing to contract */
- (void (*)(void *, const void *))smallfelem_assign);
+ return 1;
}
-int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *g_scalar, const EC_POINT *p_,
- const BIGNUM *p_scalar_, BN_CTX *ctx) {
+static int ec_GFp_nistp256_points_mul(const EC_GROUP *group,
+ EC_POINT *r,
+ const BIGNUM *g_scalar,
+ const EC_POINT *p_,
+ const BIGNUM *p_scalar_,
+ BN_CTX *ctx) {
/* TODO: This function used to take |points| and |scalars| as arrays of
* |num| elements. The code below should be simplified to work in terms of |p|
* and |p_scalar|. */
@@ -1650,16 +1600,12 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL;
int ret = 0;
- int j;
- int mixed = 0;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *z, *tmp_scalar;
felem_bytearray g_secret;
felem_bytearray *secrets = NULL;
smallfelem(*pre_comp)[17][3] = NULL;
- smallfelem *tmp_smallfelems = NULL;
felem_bytearray tmp;
- unsigned i, num_bytes;
size_t num_points = num;
smallfelem x_in, y_in, z_in;
felem x_out, y_out, z_out;
@@ -1682,19 +1628,9 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
}
if (num_points > 0) {
- if (num_points >= 3) {
- /* unless we precompute multiples for just one or two points,
- * converting those into affine form is time well spent */
- mixed = 1;
- }
secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
pre_comp = OPENSSL_malloc(num_points * sizeof(smallfelem[17][3]));
- if (mixed) {
- tmp_smallfelems =
- OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem));
- }
- if (secrets == NULL || pre_comp == NULL ||
- (mixed && tmp_smallfelems == NULL)) {
+ if (secrets == NULL || pre_comp == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1703,6 +1639,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
* i.e., they contribute nothing to the linear combination. */
memset(secrets, 0, num_points * sizeof(felem_bytearray));
memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem));
+ size_t i;
for (i = 0; i < num_points; ++i) {
if (i == num) {
/* we didn't have a valid precomputation, so we pick the generator. */
@@ -1714,6 +1651,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
p_scalar = scalars[i];
}
if (p_scalar != NULL && p != NULL) {
+ size_t num_bytes;
/* reduce g_scalar to 0 <= g_scalar < 2^256 */
if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) {
/* this is an unusual input, and we don't guarantee
@@ -1736,6 +1674,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
felem_shrink(pre_comp[i][1][0], x_out);
felem_shrink(pre_comp[i][1][1], y_out);
felem_shrink(pre_comp[i][1][2], z_out);
+ size_t j;
for (j = 2; j <= 16; ++j) {
if (j & 1) {
point_add_small(pre_comp[i][j][0], pre_comp[i][j][1],
@@ -1751,12 +1690,11 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
}
}
}
- if (mixed) {
- make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems);
- }
}
if (g_scalar != NULL) {
+ size_t num_bytes;
+
memset(g_secret, 0, sizeof(g_secret));
/* reduce g_scalar to 0 <= g_scalar < 2^256 */
if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) {
@@ -1773,7 +1711,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
flip_endian(g_secret, tmp, num_bytes);
}
batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
- num_points, g_scalar != NULL ? g_secret : NULL, mixed,
+ num_points, g_scalar != NULL ? g_secret : NULL,
(const smallfelem(*)[17][3])pre_comp);
/* reduce the output to its unique minimal representation */
@@ -1793,7 +1731,6 @@ err:
BN_CTX_free(new_ctx);
OPENSSL_free(secrets);
OPENSSL_free(pre_comp);
- OPENSSL_free(tmp_smallfelems);
return ret;
}
@@ -1807,7 +1744,7 @@ const EC_METHOD *EC_GFp_nistp256_method(void) {
ec_GFp_nistp256_points_mul,
0 /* check_pub_key_order */,
ec_GFp_simple_field_mul, ec_GFp_simple_field_sqr,
- 0 /* field_encode */, 0 /* field_decode */, 0 /* field_set_to_one */
+ 0 /* field_encode */, 0 /* field_decode */,
};
return &ret;
diff --git a/crypto/ec/p256-x86_64.c b/crypto/ec/p256-x86_64.c
index ca967b31..e1afec48 100644
--- a/crypto/ec/p256-x86_64.c
+++ b/crypto/ec/p256-x86_64.c
@@ -205,9 +205,7 @@ static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS],
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
- ecp_nistz256_mul_mont(res, res, in);
-
- memcpy(r, res, sizeof(res));
+ ecp_nistz256_mul_mont(r, res, in);
}
/* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and
@@ -390,17 +388,6 @@ static int ecp_nistz256_points_mul(
BN_CTX *new_ctx = NULL;
int ctx_started = 0;
- /* Need 256 bits for space for all coordinates. */
- if (bn_wexpand(&r->X, P256_LIMBS) == NULL ||
- bn_wexpand(&r->Y, P256_LIMBS) == NULL ||
- bn_wexpand(&r->Z, P256_LIMBS) == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- r->X.top = P256_LIMBS;
- r->Y.top = P256_LIMBS;
- r->Z.top = P256_LIMBS;
-
if (g_scalar != NULL) {
if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) {
if (ctx == NULL) {
@@ -494,15 +481,12 @@ static int ecp_nistz256_points_mul(
}
}
- memcpy(r->X.d, p.p.X, sizeof(p.p.X));
- memcpy(r->Y.d, p.p.Y, sizeof(p.p.Y));
- memcpy(r->Z.d, p.p.Z, sizeof(p.p.Z));
-
/* Not constant-time, but we're only operating on the public output. */
- bn_correct_top(&r->X);
- bn_correct_top(&r->Y);
- bn_correct_top(&r->Z);
- r->Z_is_one = BN_is_one(&r->Z);
+ if (!bn_set_words(&r->X, p.p.X, P256_LIMBS) ||
+ !bn_set_words(&r->Y, p.p.Y, P256_LIMBS) ||
+ !bn_set_words(&r->Z, p.p.Z, P256_LIMBS)) {
+ return 0;
+ }
ret = 1;
@@ -518,8 +502,6 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx) {
BN_ULONG z_inv2[P256_LIMBS];
BN_ULONG z_inv3[P256_LIMBS];
- BN_ULONG x_aff[P256_LIMBS];
- BN_ULONG y_aff[P256_LIMBS];
BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS];
if (EC_POINT_is_at_infinity(group, point)) {
@@ -536,7 +518,12 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point,
ecp_nistz256_mod_inverse(z_inv3, point_z);
ecp_nistz256_sqr_mont(z_inv2, z_inv3);
- ecp_nistz256_mul_mont(x_aff, z_inv2, point_x);
+
+ /* Instead of using |ecp_nistz256_from_mont| to convert the |x| coordinate
+ * and then calling |ecp_nistz256_from_mont| again to convert the |y|
+ * coordinate below, convert the common factor |z_inv2| once now, saving one
+ * reduction. */
+ ecp_nistz256_from_mont(z_inv2, z_inv2);
if (x != NULL) {
if (bn_wexpand(x, P256_LIMBS) == NULL) {
@@ -544,19 +531,20 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point,
return 0;
}
x->top = P256_LIMBS;
- ecp_nistz256_from_mont(x->d, x_aff);
+ x->neg = 0;
+ ecp_nistz256_mul_mont(x->d, z_inv2, point_x);
bn_correct_top(x);
}
if (y != NULL) {
ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2);
- ecp_nistz256_mul_mont(y_aff, z_inv3, point_y);
if (bn_wexpand(y, P256_LIMBS) == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
return 0;
}
y->top = P256_LIMBS;
- ecp_nistz256_from_mont(y->d, y_aff);
+ y->neg = 0;
+ ecp_nistz256_mul_mont(y->d, z_inv3, point_y);
bn_correct_top(y);
}
@@ -576,7 +564,6 @@ const EC_METHOD *EC_GFp_nistz256_method(void) {
ec_GFp_mont_field_sqr,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
- ec_GFp_mont_field_set_to_one,
};
return &ret;
diff --git a/crypto/ec/simple.c b/crypto/ec/simple.c
index 4eb612eb..4508d83f 100644
--- a/crypto/ec/simple.c
+++ b/crypto/ec/simple.c
@@ -82,16 +82,16 @@
* field_sqr methods will be used for multiplication, and field_encode and
* field_decode (if defined) will be used for converting between
* representations.
-
- * Functions ec_GFp_simple_points_make_affine() and
- * ec_GFp_simple_point_get_affine_coordinates() specifically assume that if a
- * non-trivial representation is used, it is a Montgomery representation (i.e.
- * 'encoding' means multiplying by some factor R). */
+ *
+ * Functions here specifically assume that if a non-trivial representation is
+ * used, it is a Montgomery representation (i.e. 'encoding' means multiplying
+ * by some factor R). */
int ec_GFp_simple_group_init(EC_GROUP *group) {
BN_init(&group->field);
BN_init(&group->a);
BN_init(&group->b);
+ BN_init(&group->one);
group->a_is_minus3 = 0;
return 1;
}
@@ -100,12 +100,14 @@ void ec_GFp_simple_group_finish(EC_GROUP *group) {
BN_free(&group->field);
BN_free(&group->a);
BN_free(&group->b);
+ BN_free(&group->one);
}
int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
if (!BN_copy(&dest->field, &src->field) ||
!BN_copy(&dest->a, &src->a) ||
- !BN_copy(&dest->b, &src->b)) {
+ !BN_copy(&dest->b, &src->b) ||
+ !BN_copy(&dest->one, &src->one)) {
return 0;
}
@@ -172,6 +174,14 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
}
group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
+ if (group->meth->field_encode != NULL) {
+ if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) {
+ goto err;
+ }
+ } else if (!BN_copy(&group->one, BN_value_one())) {
+ goto err;
+ }
+
ret = 1;
err:
@@ -228,7 +238,6 @@ int ec_GFp_simple_point_init(EC_POINT *point) {
BN_init(&point->X);
BN_init(&point->Y);
BN_init(&point->Z);
- point->Z_is_one = 0;
return 1;
}
@@ -243,7 +252,6 @@ void ec_GFp_simple_point_clear_finish(EC_POINT *point) {
BN_clear_free(&point->X);
BN_clear_free(&point->Y);
BN_clear_free(&point->Z);
- point->Z_is_one = 0;
}
int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) {
@@ -252,18 +260,32 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) {
!BN_copy(&dest->Z, &src->Z)) {
return 0;
}
- dest->Z_is_one = src->Z_is_one;
return 1;
}
int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,
EC_POINT *point) {
- point->Z_is_one = 0;
BN_zero(&point->Z);
return 1;
}
+static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out,
+ const BIGNUM *in, BN_CTX *ctx) {
+ if (in == NULL) {
+ return 1;
+ }
+ if (BN_is_negative(in) ||
+ BN_cmp(in, &group->field) >= 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE);
+ return 0;
+ }
+ if (group->meth->field_encode) {
+ return group->meth->field_encode(group, out, in, ctx);
+ }
+ return BN_copy(out, in) != NULL;
+}
+
int ec_GFp_simple_set_Jprojective_coordinates_GFp(
const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y,
const BIGNUM *z, BN_CTX *ctx) {
@@ -277,43 +299,10 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(
}
}
- if (x != NULL) {
- if (!BN_nnmod(&point->X, x, &group->field, ctx)) {
- goto err;
- }
- if (group->meth->field_encode &&
- !group->meth->field_encode(group, &point->X, &point->X, ctx)) {
- goto err;
- }
- }
-
- if (y != NULL) {
- if (!BN_nnmod(&point->Y, y, &group->field, ctx)) {
- goto err;
- }
- if (group->meth->field_encode &&
- !group->meth->field_encode(group, &point->Y, &point->Y, ctx)) {
- goto err;
- }
- }
-
- if (z != NULL) {
- int Z_is_one;
-
- if (!BN_nnmod(&point->Z, z, &group->field, ctx)) {
- goto err;
- }
- Z_is_one = BN_is_one(&point->Z);
- if (group->meth->field_encode) {
- if (Z_is_one && (group->meth->field_set_to_one != 0)) {
- if (!group->meth->field_set_to_one(group, &point->Z, ctx)) {
- goto err;
- }
- } else if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) {
- goto err;
- }
- }
- point->Z_is_one = Z_is_one;
+ if (!set_Jprojective_coordinate_GFp(group, &point->X, x, ctx) ||
+ !set_Jprojective_coordinate_GFp(group, &point->Y, y, ctx) ||
+ !set_Jprojective_coordinate_GFp(group, &point->Z, z, ctx)) {
+ goto err;
}
ret = 1;
@@ -379,109 +368,6 @@ int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
BN_value_one(), ctx);
}
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
- const EC_POINT *point, BIGNUM *x,
- BIGNUM *y, BN_CTX *ctx) {
- BN_CTX *new_ctx = NULL;
- BIGNUM *Z, *Z_1, *Z_2, *Z_3;
- const BIGNUM *Z_;
- int ret = 0;
-
- if (EC_POINT_is_at_infinity(group, point)) {
- OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
- return 0;
- }
-
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL) {
- return 0;
- }
- }
-
- BN_CTX_start(ctx);
- Z = BN_CTX_get(ctx);
- Z_1 = BN_CTX_get(ctx);
- Z_2 = BN_CTX_get(ctx);
- Z_3 = BN_CTX_get(ctx);
- if (Z == NULL || Z_1 == NULL || Z_2 == NULL || Z_3 == NULL) {
- goto err;
- }
-
- /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
-
- if (group->meth->field_decode) {
- if (!group->meth->field_decode(group, Z, &point->Z, ctx)) {
- goto err;
- }
- Z_ = Z;
- } else {
- Z_ = &point->Z;
- }
-
- if (BN_is_one(Z_)) {
- if (group->meth->field_decode) {
- if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) {
- goto err;
- }
- if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) {
- goto err;
- }
- } else {
- if (x != NULL && !BN_copy(x, &point->X)) {
- goto err;
- }
- if (y != NULL && !BN_copy(y, &point->Y)) {
- goto err;
- }
- }
- } else {
- if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- goto err;
- }
-
- if (group->meth->field_encode == 0) {
- /* field_sqr works on standard representation */
- if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) {
- goto err;
- }
- } else if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) {
- goto err;
- }
-
- /* in the Montgomery case, field_mul will cancel out Montgomery factor in
- * X: */
- if (x != NULL && !group->meth->field_mul(group, x, &point->X, Z_2, ctx)) {
- goto err;
- }
-
- if (y != NULL) {
- if (group->meth->field_encode == 0) {
- /* field_mul works on standard representation */
- if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) {
- goto err;
- }
- } else if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) {
- goto err;
- }
-
- /* in the Montgomery case, field_mul will cancel out Montgomery factor in
- * Y: */
- if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) {
- goto err;
- }
- }
- }
-
- ret = 1;
-
-err:
- BN_CTX_end(ctx);
- BN_CTX_free(new_ctx);
- return ret;
-}
-
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx) {
int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
@@ -531,7 +417,9 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
*/
/* n1, n2 */
- if (b->Z_is_one) {
+ int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;
+
+ if (b_Z_is_one) {
if (!BN_copy(n1, &a->X) || !BN_copy(n2, &a->Y)) {
goto end;
}
@@ -552,7 +440,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
}
/* n3, n4 */
- if (a->Z_is_one) {
+ int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
+ if (a_Z_is_one) {
if (!BN_copy(n3, &b->X) || !BN_copy(n4, &b->Y)) {
goto end;
}
@@ -590,7 +479,6 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
} else {
/* a is the inverse of b */
BN_zero(&r->Z);
- r->Z_is_one = 0;
ret = 1;
goto end;
}
@@ -605,16 +493,16 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
/* 'n8' = n2 + n4 */
/* Z_r */
- if (a->Z_is_one && b->Z_is_one) {
+ if (a_Z_is_one && b_Z_is_one) {
if (!BN_copy(&r->Z, n5)) {
goto end;
}
} else {
- if (a->Z_is_one) {
+ if (a_Z_is_one) {
if (!BN_copy(n0, &b->Z)) {
goto end;
}
- } else if (b->Z_is_one) {
+ } else if (b_Z_is_one) {
if (!BN_copy(n0, &a->Z)) {
goto end;
}
@@ -625,7 +513,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
goto end;
}
}
- r->Z_is_one = 0;
+
/* Z_r = Z_a * Z_b * n5 */
/* X_r */
@@ -685,7 +573,6 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (EC_POINT_is_at_infinity(group, a)) {
BN_zero(&r->Z);
- r->Z_is_one = 0;
return 1;
}
@@ -715,7 +602,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
*/
/* n1 */
- if (a->Z_is_one) {
+ if (BN_cmp(&a->Z, &group->one) == 0) {
if (!field_sqr(group, n0, &a->X, ctx) ||
!BN_mod_lshift1_quick(n1, n0, p) ||
!BN_mod_add_quick(n0, n0, n1, p) ||
@@ -748,7 +635,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
}
/* Z_r */
- if (a->Z_is_one) {
+ if (BN_cmp(&a->Z, &group->one) == 0) {
if (!BN_copy(n0, &a->Y)) {
goto err;
}
@@ -758,7 +645,6 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (!BN_mod_lshift1_quick(&r->Z, n0, p)) {
goto err;
}
- r->Z_is_one = 0;
/* Z_r = 2 * Y_a * Z_a */
/* n2 */
@@ -810,7 +696,7 @@ int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
}
int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
- return !point->Z_is_one && BN_is_zero(&point->Z);
+ return BN_is_zero(&point->Z);
}
int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
@@ -821,7 +707,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
const BIGNUM *p;
BN_CTX *new_ctx = NULL;
BIGNUM *rh, *tmp, *Z4, *Z6;
- int ret = -1;
+ int ret = 0;
if (EC_POINT_is_at_infinity(group, point)) {
return 1;
@@ -834,7 +720,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
- return -1;
+ return 0;
}
}
@@ -862,7 +748,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
goto err;
}
- if (!point->Z_is_one) {
+ if (BN_cmp(&point->Z, &group->one) != 0) {
if (!field_sqr(group, tmp, &point->Z, ctx) ||
!field_sqr(group, Z4, tmp, ctx) ||
!field_mul(group, Z6, Z4, tmp, ctx)) {
@@ -891,8 +777,6 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
goto err;
}
} else {
- /* point->Z_is_one */
-
/* rh := (rh + a)*X */
if (!BN_mod_add_quick(rh, rh, &group->a, p) ||
!field_mul(group, rh, rh, &point->X, ctx)) {
@@ -941,7 +825,10 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
return 1;
}
- if (a->Z_is_one && b->Z_is_one) {
+ int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
+ int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;
+
+ if (a_Z_is_one && b_Z_is_one) {
return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
}
@@ -970,7 +857,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
* (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
*/
- if (!b->Z_is_one) {
+ if (!b_Z_is_one) {
if (!field_sqr(group, Zb23, &b->Z, ctx) ||
!field_mul(group, tmp1, &a->X, Zb23, ctx)) {
goto end;
@@ -979,7 +866,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
} else {
tmp1_ = &a->X;
}
- if (!a->Z_is_one) {
+ if (!a_Z_is_one) {
if (!field_sqr(group, Za23, &a->Z, ctx) ||
!field_mul(group, tmp2, &b->X, Za23, ctx)) {
goto end;
@@ -996,7 +883,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
}
- if (!b->Z_is_one) {
+ if (!b_Z_is_one) {
if (!field_mul(group, Zb23, Zb23, &b->Z, ctx) ||
!field_mul(group, tmp1, &a->Y, Zb23, ctx)) {
goto end;
@@ -1005,7 +892,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
} else {
tmp1_ = &a->Y;
}
- if (!a->Z_is_one) {
+ if (!a_Z_is_one) {
if (!field_mul(group, Za23, Za23, &a->Z, ctx) ||
!field_mul(group, tmp2, &b->Y, Za23, ctx)) {
goto end;
@@ -1036,7 +923,8 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
BIGNUM *x, *y;
int ret = 0;
- if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) {
+ if (BN_cmp(&point->Z, &group->one) == 0 ||
+ EC_POINT_is_at_infinity(group, point)) {
return 1;
}
@@ -1058,7 +946,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
goto err;
}
- if (!point->Z_is_one) {
+ if (BN_cmp(&point->Z, &group->one) != 0) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -1117,14 +1005,8 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
goto err;
}
} else {
- if (group->meth->field_set_to_one != 0) {
- if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) {
- goto err;
- }
- } else {
- if (!BN_one(prod_Z[0])) {
- goto err;
- }
+ if (BN_copy(prod_Z[0], &group->one) == NULL) {
+ goto err;
}
}
@@ -1195,16 +1077,9 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
goto err;
}
- if (group->meth->field_set_to_one != NULL) {
- if (!group->meth->field_set_to_one(group, &p->Z, ctx)) {
- goto err;
- }
- } else {
- if (!BN_one(&p->Z)) {
- goto err;
- }
+ if (BN_copy(&p->Z, &group->one) == NULL) {
+ goto err;
}
- p->Z_is_one = 1;
}
}
diff --git a/crypto/ec/util-64.c b/crypto/ec/util-64.c
index 171b0631..40062712 100644
--- a/crypto/ec/util-64.c
+++ b/crypto/ec/util-64.c
@@ -21,80 +21,6 @@
#include "internal.h"
-/* Convert an array of points into affine coordinates. (If the point at
- * infinity is found (Z = 0), it remains unchanged.) This function is
- * essentially an equivalent to EC_POINTs_make_affine(), but works with the
- * internal representation of points as used by ecp_nistp###.c rather than
- * with (BIGNUM-based) EC_POINT data structures. point_array is the
- * input/output buffer ('num' points in projective form, i.e. three
- * coordinates each), based on an internal representation of field elements
- * of size 'felem_size'. tmp_felems needs to point to a temporary array of
- * 'num'+1 field elements for storage of intermediate values. */
-void ec_GFp_nistp_points_make_affine_internal(
- size_t num, void *point_array, size_t felem_size, void *tmp_felems,
- void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
- void (*felem_assign)(void *out, const void *in),
- void (*felem_square)(void *out, const void *in),
- void (*felem_mul)(void *out, const void *in1, const void *in2),
- void (*felem_inv)(void *out, const void *in),
- void (*felem_contract)(void *out, const void *in)) {
- int i = 0;
-
-#define tmp_felem(I) (&((char *)tmp_felems)[(I)*felem_size])
-#define X(I) (&((char *)point_array)[3 * (I)*felem_size])
-#define Y(I) (&((char *)point_array)[(3 * (I) + 1) * felem_size])
-#define Z(I) (&((char *)point_array)[(3 * (I) + 2) * felem_size])
-
- if (!felem_is_zero(Z(0))) {
- felem_assign(tmp_felem(0), Z(0));
- } else {
- felem_one(tmp_felem(0));
- }
-
- for (i = 1; i < (int)num; i++) {
- if (!felem_is_zero(Z(i))) {
- felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));
- } else {
- felem_assign(tmp_felem(i), tmp_felem(i - 1));
- }
- }
- /* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any
- * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1. */
-
- felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));
- for (i = num - 1; i >= 0; i--) {
- if (i > 0) {
- /* tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i)
- * is the inverse of the product of Z(0) .. Z(i). */
- /* 1/Z(i) */
- felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));
- } else {
- felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
- }
-
- if (!felem_is_zero(Z(i))) {
- if (i > 0) {
- /* For next iteration, replace tmp_felem(i-1) by its inverse. */
- felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i));
- }
-
- /* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1). */
- felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
- felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
- felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
- felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
- felem_contract(X(i), X(i));
- felem_contract(Y(i), Y(i));
- felem_one(Z(i));
- } else {
- if (i > 0) {
- /* For next iteration, replace tmp_felem(i-1) by its inverse. */
- felem_assign(tmp_felem(i - 1), tmp_felem(i));
- }
- }
- }
-}
-
/* This function looks at 5+1 scalar bits (5 current, 1 adjacent less
* significant bit), and recodes them into a signed digit for use in fast point
* multiplication: the use of signed rather than unsigned digits means that
diff --git a/crypto/ecdsa/ecdsa.c b/crypto/ecdsa/ecdsa.c
index 8ce23db7..70cb1189 100644
--- a/crypto/ecdsa/ecdsa.c
+++ b/crypto/ecdsa/ecdsa.c
@@ -79,10 +79,6 @@ int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
int ret = 0;
uint8_t *der = NULL;
- if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
- return eckey->ecdsa_meth->verify(digest, digest_len, sig, sig_len, eckey);
- }
-
/* Decode the ECDSA signature. */
s = ECDSA_SIG_from_bytes(sig, sig_len);
if (s == NULL) {
@@ -148,11 +144,6 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
const EC_GROUP *group;
const EC_POINT *pub_key;
- if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
- OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
- return 0;
- }
-
/* check input values */
if ((group = EC_KEY_get0_group(eckey)) == NULL ||
(pub_key = EC_KEY_get0_public_key(eckey)) == NULL ||
diff --git a/crypto/ecdsa/ecdsa_asn1.c b/crypto/ecdsa/ecdsa_asn1.c
index 3a47257a..d41a5366 100644
--- a/crypto/ecdsa/ecdsa_asn1.c
+++ b/crypto/ecdsa/ecdsa_asn1.c
@@ -220,6 +220,7 @@ int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!ECDSA_SIG_marshal(&cbb, sig)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
diff --git a/crypto/ecdsa/ecdsa_test.cc b/crypto/ecdsa/ecdsa_test.cc
index bef91c93..8d7827df 100644
--- a/crypto/ecdsa/ecdsa_test.cc
+++ b/crypto/ecdsa/ecdsa_test.cc
@@ -59,7 +59,7 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include "../test/scoped_types.h"
diff --git a/crypto/err/asn1.errordata b/crypto/err/asn1.errordata
index b1b04375..c304b2ca 100644
--- a/crypto/err/asn1.errordata
+++ b/crypto/err/asn1.errordata
@@ -6,82 +6,87 @@ ASN1,104,BMPSTRING_IS_WRONG_LENGTH
ASN1,105,BN_LIB
ASN1,106,BOOLEAN_IS_WRONG_LENGTH
ASN1,107,BUFFER_TOO_SMALL
-ASN1,108,DECODE_ERROR
-ASN1,109,DEPTH_EXCEEDED
-ASN1,110,ENCODE_ERROR
-ASN1,111,ERROR_GETTING_TIME
-ASN1,112,EXPECTING_AN_ASN1_SEQUENCE
-ASN1,113,EXPECTING_AN_INTEGER
-ASN1,114,EXPECTING_AN_OBJECT
-ASN1,115,EXPECTING_A_BOOLEAN
-ASN1,116,EXPECTING_A_TIME
-ASN1,117,EXPLICIT_LENGTH_MISMATCH
-ASN1,118,EXPLICIT_TAG_NOT_CONSTRUCTED
-ASN1,119,FIELD_MISSING
-ASN1,120,FIRST_NUM_TOO_LARGE
-ASN1,121,HEADER_TOO_LONG
-ASN1,122,ILLEGAL_BITSTRING_FORMAT
-ASN1,123,ILLEGAL_BOOLEAN
-ASN1,124,ILLEGAL_CHARACTERS
-ASN1,125,ILLEGAL_FORMAT
-ASN1,126,ILLEGAL_HEX
-ASN1,127,ILLEGAL_IMPLICIT_TAG
-ASN1,128,ILLEGAL_INTEGER
-ASN1,129,ILLEGAL_NESTED_TAGGING
-ASN1,130,ILLEGAL_NULL
-ASN1,131,ILLEGAL_NULL_VALUE
-ASN1,132,ILLEGAL_OBJECT
-ASN1,133,ILLEGAL_OPTIONAL_ANY
-ASN1,134,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE
-ASN1,135,ILLEGAL_TAGGED_ANY
-ASN1,136,ILLEGAL_TIME_VALUE
-ASN1,137,INTEGER_NOT_ASCII_FORMAT
-ASN1,138,INTEGER_TOO_LARGE_FOR_LONG
-ASN1,139,INVALID_BIT_STRING_BITS_LEFT
-ASN1,140,INVALID_BMPSTRING_LENGTH
-ASN1,141,INVALID_DIGIT
-ASN1,142,INVALID_MODIFIER
-ASN1,143,INVALID_NUMBER
-ASN1,144,INVALID_OBJECT_ENCODING
-ASN1,145,INVALID_SEPARATOR
-ASN1,146,INVALID_TIME_FORMAT
-ASN1,147,INVALID_UNIVERSALSTRING_LENGTH
-ASN1,148,INVALID_UTF8STRING
-ASN1,149,LIST_ERROR
-ASN1,150,MISSING_ASN1_EOS
-ASN1,151,MISSING_EOC
-ASN1,152,MISSING_SECOND_NUMBER
-ASN1,153,MISSING_VALUE
-ASN1,154,MSTRING_NOT_UNIVERSAL
-ASN1,155,MSTRING_WRONG_TAG
-ASN1,156,NESTED_ASN1_ERROR
-ASN1,157,NESTED_ASN1_STRING
-ASN1,158,NON_HEX_CHARACTERS
-ASN1,159,NOT_ASCII_FORMAT
-ASN1,160,NOT_ENOUGH_DATA
-ASN1,161,NO_MATCHING_CHOICE_TYPE
-ASN1,162,NULL_IS_WRONG_LENGTH
-ASN1,163,OBJECT_NOT_ASCII_FORMAT
-ASN1,164,ODD_NUMBER_OF_CHARS
-ASN1,165,SECOND_NUMBER_TOO_LARGE
-ASN1,166,SEQUENCE_LENGTH_MISMATCH
-ASN1,167,SEQUENCE_NOT_CONSTRUCTED
-ASN1,168,SEQUENCE_OR_SET_NEEDS_CONFIG
-ASN1,169,SHORT_LINE
-ASN1,170,STREAMING_NOT_SUPPORTED
-ASN1,171,STRING_TOO_LONG
-ASN1,172,STRING_TOO_SHORT
-ASN1,173,TAG_VALUE_TOO_HIGH
-ASN1,174,TIME_NOT_ASCII_FORMAT
-ASN1,175,TOO_LONG
-ASN1,176,TYPE_NOT_CONSTRUCTED
-ASN1,177,TYPE_NOT_PRIMITIVE
-ASN1,178,UNEXPECTED_EOC
-ASN1,179,UNIVERSALSTRING_IS_WRONG_LENGTH
-ASN1,180,UNKNOWN_FORMAT
-ASN1,181,UNKNOWN_TAG
-ASN1,182,UNSUPPORTED_ANY_DEFINED_BY_TYPE
-ASN1,183,UNSUPPORTED_PUBLIC_KEY_TYPE
-ASN1,184,UNSUPPORTED_TYPE
-ASN1,185,WRONG_TAG
-ASN1,186,WRONG_TYPE
+ASN1,108,CONTEXT_NOT_INITIALISED
+ASN1,109,DECODE_ERROR
+ASN1,110,DEPTH_EXCEEDED
+ASN1,111,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED
+ASN1,112,ENCODE_ERROR
+ASN1,113,ERROR_GETTING_TIME
+ASN1,114,EXPECTING_AN_ASN1_SEQUENCE
+ASN1,115,EXPECTING_AN_INTEGER
+ASN1,116,EXPECTING_AN_OBJECT
+ASN1,117,EXPECTING_A_BOOLEAN
+ASN1,118,EXPECTING_A_TIME
+ASN1,119,EXPLICIT_LENGTH_MISMATCH
+ASN1,120,EXPLICIT_TAG_NOT_CONSTRUCTED
+ASN1,121,FIELD_MISSING
+ASN1,122,FIRST_NUM_TOO_LARGE
+ASN1,123,HEADER_TOO_LONG
+ASN1,124,ILLEGAL_BITSTRING_FORMAT
+ASN1,125,ILLEGAL_BOOLEAN
+ASN1,126,ILLEGAL_CHARACTERS
+ASN1,127,ILLEGAL_FORMAT
+ASN1,128,ILLEGAL_HEX
+ASN1,129,ILLEGAL_IMPLICIT_TAG
+ASN1,130,ILLEGAL_INTEGER
+ASN1,131,ILLEGAL_NESTED_TAGGING
+ASN1,132,ILLEGAL_NULL
+ASN1,133,ILLEGAL_NULL_VALUE
+ASN1,134,ILLEGAL_OBJECT
+ASN1,135,ILLEGAL_OPTIONAL_ANY
+ASN1,136,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE
+ASN1,137,ILLEGAL_TAGGED_ANY
+ASN1,138,ILLEGAL_TIME_VALUE
+ASN1,139,INTEGER_NOT_ASCII_FORMAT
+ASN1,140,INTEGER_TOO_LARGE_FOR_LONG
+ASN1,141,INVALID_BIT_STRING_BITS_LEFT
+ASN1,142,INVALID_BMPSTRING_LENGTH
+ASN1,143,INVALID_DIGIT
+ASN1,144,INVALID_MODIFIER
+ASN1,145,INVALID_NUMBER
+ASN1,146,INVALID_OBJECT_ENCODING
+ASN1,147,INVALID_SEPARATOR
+ASN1,148,INVALID_TIME_FORMAT
+ASN1,149,INVALID_UNIVERSALSTRING_LENGTH
+ASN1,150,INVALID_UTF8STRING
+ASN1,151,LIST_ERROR
+ASN1,152,MISSING_ASN1_EOS
+ASN1,153,MISSING_EOC
+ASN1,154,MISSING_SECOND_NUMBER
+ASN1,155,MISSING_VALUE
+ASN1,156,MSTRING_NOT_UNIVERSAL
+ASN1,157,MSTRING_WRONG_TAG
+ASN1,158,NESTED_ASN1_ERROR
+ASN1,159,NESTED_ASN1_STRING
+ASN1,160,NON_HEX_CHARACTERS
+ASN1,161,NOT_ASCII_FORMAT
+ASN1,162,NOT_ENOUGH_DATA
+ASN1,163,NO_MATCHING_CHOICE_TYPE
+ASN1,164,NULL_IS_WRONG_LENGTH
+ASN1,165,OBJECT_NOT_ASCII_FORMAT
+ASN1,166,ODD_NUMBER_OF_CHARS
+ASN1,167,SECOND_NUMBER_TOO_LARGE
+ASN1,168,SEQUENCE_LENGTH_MISMATCH
+ASN1,169,SEQUENCE_NOT_CONSTRUCTED
+ASN1,170,SEQUENCE_OR_SET_NEEDS_CONFIG
+ASN1,171,SHORT_LINE
+ASN1,172,STREAMING_NOT_SUPPORTED
+ASN1,173,STRING_TOO_LONG
+ASN1,174,STRING_TOO_SHORT
+ASN1,175,TAG_VALUE_TOO_HIGH
+ASN1,176,TIME_NOT_ASCII_FORMAT
+ASN1,177,TOO_LONG
+ASN1,178,TYPE_NOT_CONSTRUCTED
+ASN1,179,TYPE_NOT_PRIMITIVE
+ASN1,180,UNEXPECTED_EOC
+ASN1,181,UNIVERSALSTRING_IS_WRONG_LENGTH
+ASN1,182,UNKNOWN_FORMAT
+ASN1,183,UNKNOWN_MESSAGE_DIGEST_ALGORITHM
+ASN1,184,UNKNOWN_SIGNATURE_ALGORITHM
+ASN1,185,UNKNOWN_TAG
+ASN1,186,UNSUPPORTED_ANY_DEFINED_BY_TYPE
+ASN1,187,UNSUPPORTED_PUBLIC_KEY_TYPE
+ASN1,188,UNSUPPORTED_TYPE
+ASN1,189,WRONG_PUBLIC_KEY_TYPE
+ASN1,190,WRONG_TAG
+ASN1,191,WRONG_TYPE
diff --git a/crypto/err/dh.errordata b/crypto/err/dh.errordata
index 571e218a..9e1b87d8 100644
--- a/crypto/err/dh.errordata
+++ b/crypto/err/dh.errordata
@@ -1,4 +1,6 @@
DH,100,BAD_GENERATOR
+DH,104,DECODE_ERROR
+DH,105,ENCODE_ERROR
DH,101,INVALID_PUBKEY
DH,102,MODULUS_TOO_LARGE
DH,103,NO_PRIVATE_VALUE
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 9221bf17..48d631f4 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -114,9 +114,9 @@
#include <string.h>
#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/mem.h>
@@ -325,7 +325,7 @@ int ERR_get_next_error_library(void) {
CRYPTO_STATIC_MUTEX_lock_write(&global_next_library_mutex);
ret = global_next_library++;
- CRYPTO_STATIC_MUTEX_unlock(&global_next_library_mutex);
+ CRYPTO_STATIC_MUTEX_unlock_write(&global_next_library_mutex);
return ret;
}
diff --git a/crypto/err/err_data_generate.go b/crypto/err/err_data_generate.go
index 24e0d66f..893ebffe 100644
--- a/crypto/err/err_data_generate.go
+++ b/crypto/err/err_data_generate.go
@@ -18,6 +18,7 @@ import (
"bufio"
"bytes"
"errors"
+ "flag"
"fmt"
"io"
"os"
@@ -26,6 +27,8 @@ import (
"strings"
)
+var verbose = flag.Bool("verbose", false, "If true, prints a status message at the end.")
+
// libraryNames must be kept in sync with the enum in err.h. The generated code
// will contain static assertions to enforce this.
var libraryNames = []string{
@@ -138,7 +141,9 @@ type stringWriter interface {
func (st *stringList) WriteTo(out stringWriter, name string) {
list := st.buildList()
- fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
+ if *verbose {
+ fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
+ }
values := "kOpenSSL" + name + "Values"
out.WriteString("const uint32_t " + values + "[] = {\n")
@@ -215,6 +220,8 @@ func (e *errorData) readErrorDataFile(filename string) error {
}
func main() {
+ flag.Parse()
+
e := &errorData{
reasons: newStringList(),
libraryMap: make(map[string]uint32),
diff --git a/crypto/err/evp.errordata b/crypto/err/evp.errordata
index cfb81b15..a482f769 100644
--- a/crypto/err/evp.errordata
+++ b/crypto/err/evp.errordata
@@ -1,47 +1,30 @@
-EVP,151,BN_DECODE_ERROR
EVP,100,BUFFER_TOO_SMALL
EVP,101,COMMAND_NOT_SUPPORTED
-EVP,146,CONTEXT_NOT_INITIALISED
-EVP,143,DECODE_ERROR
-EVP,104,DIFFERENT_KEY_TYPES
-EVP,105,DIFFERENT_PARAMETERS
-EVP,147,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED
-EVP,155,ENCODE_ERROR
-EVP,107,EXPECTING_AN_EC_KEY_KEY
-EVP,141,EXPECTING_AN_RSA_KEY
-EVP,109,EXPECTING_A_DH_KEY
-EVP,110,EXPECTING_A_DSA_KEY
-EVP,111,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
-EVP,112,INVALID_CURVE
-EVP,113,INVALID_DIGEST_LENGTH
-EVP,114,INVALID_DIGEST_TYPE
-EVP,115,INVALID_KEYBITS
-EVP,116,INVALID_MGF1_MD
-EVP,142,INVALID_OPERATION
-EVP,118,INVALID_PADDING_MODE
-EVP,119,INVALID_PSS_PARAMETERS
-EVP,144,INVALID_PSS_SALTLEN
-EVP,121,INVALID_SALT_LENGTH
-EVP,122,INVALID_TRAILER
-EVP,123,KEYS_NOT_SET
-EVP,124,MISSING_PARAMETERS
-EVP,125,NO_DEFAULT_DIGEST
-EVP,126,NO_KEY_SET
-EVP,127,NO_MDC2_SUPPORT
-EVP,128,NO_NID_FOR_CURVE
-EVP,129,NO_OPERATION_SET
-EVP,130,NO_PARAMETERS_SET
-EVP,131,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
-EVP,132,OPERATON_NOT_INITIALIZED
-EVP,152,PARAMETER_ENCODING_ERROR
-EVP,133,UNKNOWN_DIGEST
-EVP,134,UNKNOWN_MASK_DIGEST
-EVP,150,UNKNOWN_MESSAGE_DIGEST_ALGORITHM
-EVP,145,UNKNOWN_PUBLIC_KEY_TYPE
-EVP,149,UNKNOWN_SIGNATURE_ALGORITHM
-EVP,138,UNSUPPORTED_ALGORITHM
-EVP,139,UNSUPPORTED_MASK_ALGORITHM
-EVP,140,UNSUPPORTED_MASK_PARAMETER
-EVP,153,UNSUPPORTED_PUBLIC_KEY_TYPE
-EVP,154,UNSUPPORTED_SIGNATURE_TYPE
-EVP,148,WRONG_PUBLIC_KEY_TYPE
+EVP,102,DECODE_ERROR
+EVP,103,DIFFERENT_KEY_TYPES
+EVP,104,DIFFERENT_PARAMETERS
+EVP,105,ENCODE_ERROR
+EVP,106,EXPECTING_AN_EC_KEY_KEY
+EVP,107,EXPECTING_AN_RSA_KEY
+EVP,108,EXPECTING_A_DSA_KEY
+EVP,109,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
+EVP,110,INVALID_DIGEST_LENGTH
+EVP,111,INVALID_DIGEST_TYPE
+EVP,112,INVALID_KEYBITS
+EVP,113,INVALID_MGF1_MD
+EVP,114,INVALID_OPERATION
+EVP,115,INVALID_PADDING_MODE
+EVP,116,INVALID_PSS_SALTLEN
+EVP,117,KEYS_NOT_SET
+EVP,118,MISSING_PARAMETERS
+EVP,119,NO_DEFAULT_DIGEST
+EVP,120,NO_KEY_SET
+EVP,121,NO_MDC2_SUPPORT
+EVP,122,NO_NID_FOR_CURVE
+EVP,123,NO_OPERATION_SET
+EVP,124,NO_PARAMETERS_SET
+EVP,125,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
+EVP,126,OPERATON_NOT_INITIALIZED
+EVP,127,UNKNOWN_PUBLIC_KEY_TYPE
+EVP,128,UNSUPPORTED_ALGORITHM
+EVP,129,UNSUPPORTED_PUBLIC_KEY_TYPE
diff --git a/crypto/err/rsa.errordata b/crypto/err/rsa.errordata
index c19f73c7..62d286cc 100644
--- a/crypto/err/rsa.errordata
+++ b/crypto/err/rsa.errordata
@@ -1,46 +1,46 @@
-RSA,143,BAD_ENCODING
-RSA,100,BAD_E_VALUE
-RSA,101,BAD_FIXED_HEADER_DECRYPT
-RSA,102,BAD_PAD_BYTE_COUNT
-RSA,103,BAD_RSA_PARAMETERS
-RSA,104,BAD_SIGNATURE
-RSA,145,BAD_VERSION
-RSA,105,BLOCK_TYPE_IS_NOT_01
-RSA,106,BN_NOT_INITIALIZED
-RSA,142,CANNOT_RECOVER_MULTI_PRIME_KEY
-RSA,107,CRT_PARAMS_ALREADY_GIVEN
-RSA,108,CRT_VALUES_INCORRECT
-RSA,109,DATA_LEN_NOT_EQUAL_TO_MOD_LEN
-RSA,110,DATA_TOO_LARGE
-RSA,111,DATA_TOO_LARGE_FOR_KEY_SIZE
-RSA,112,DATA_TOO_LARGE_FOR_MODULUS
-RSA,113,DATA_TOO_SMALL
-RSA,114,DATA_TOO_SMALL_FOR_KEY_SIZE
-RSA,115,DIGEST_TOO_BIG_FOR_RSA_KEY
-RSA,116,D_E_NOT_CONGRUENT_TO_1
-RSA,117,EMPTY_PUBLIC_KEY
-RSA,144,ENCODE_ERROR
-RSA,118,FIRST_OCTET_INVALID
-RSA,119,INCONSISTENT_SET_OF_CRT_VALUES
-RSA,120,INTERNAL_ERROR
-RSA,121,INVALID_MESSAGE_LENGTH
-RSA,122,KEY_SIZE_TOO_SMALL
-RSA,123,LAST_OCTET_INVALID
-RSA,124,MODULUS_TOO_LARGE
-RSA,141,MUST_HAVE_AT_LEAST_TWO_PRIMES
-RSA,125,NO_PUBLIC_EXPONENT
-RSA,126,NULL_BEFORE_BLOCK_MISSING
-RSA,127,N_NOT_EQUAL_P_Q
-RSA,128,OAEP_DECODING_ERROR
-RSA,129,ONLY_ONE_OF_P_Q_GIVEN
-RSA,130,OUTPUT_BUFFER_TOO_SMALL
-RSA,131,PADDING_CHECK_FAILED
-RSA,132,PKCS_DECODING_ERROR
-RSA,133,SLEN_CHECK_FAILED
-RSA,134,SLEN_RECOVERY_FAILED
-RSA,135,TOO_LONG
-RSA,136,TOO_MANY_ITERATIONS
-RSA,137,UNKNOWN_ALGORITHM_TYPE
-RSA,138,UNKNOWN_PADDING_TYPE
-RSA,139,VALUE_MISSING
-RSA,140,WRONG_SIGNATURE_LENGTH
+RSA,100,BAD_ENCODING
+RSA,101,BAD_E_VALUE
+RSA,102,BAD_FIXED_HEADER_DECRYPT
+RSA,103,BAD_PAD_BYTE_COUNT
+RSA,104,BAD_RSA_PARAMETERS
+RSA,105,BAD_SIGNATURE
+RSA,106,BAD_VERSION
+RSA,107,BLOCK_TYPE_IS_NOT_01
+RSA,108,BN_NOT_INITIALIZED
+RSA,109,CANNOT_RECOVER_MULTI_PRIME_KEY
+RSA,110,CRT_PARAMS_ALREADY_GIVEN
+RSA,111,CRT_VALUES_INCORRECT
+RSA,112,DATA_LEN_NOT_EQUAL_TO_MOD_LEN
+RSA,113,DATA_TOO_LARGE
+RSA,114,DATA_TOO_LARGE_FOR_KEY_SIZE
+RSA,115,DATA_TOO_LARGE_FOR_MODULUS
+RSA,116,DATA_TOO_SMALL
+RSA,117,DATA_TOO_SMALL_FOR_KEY_SIZE
+RSA,118,DIGEST_TOO_BIG_FOR_RSA_KEY
+RSA,119,D_E_NOT_CONGRUENT_TO_1
+RSA,120,EMPTY_PUBLIC_KEY
+RSA,121,ENCODE_ERROR
+RSA,122,FIRST_OCTET_INVALID
+RSA,123,INCONSISTENT_SET_OF_CRT_VALUES
+RSA,124,INTERNAL_ERROR
+RSA,125,INVALID_MESSAGE_LENGTH
+RSA,126,KEY_SIZE_TOO_SMALL
+RSA,127,LAST_OCTET_INVALID
+RSA,128,MODULUS_TOO_LARGE
+RSA,129,MUST_HAVE_AT_LEAST_TWO_PRIMES
+RSA,130,NO_PUBLIC_EXPONENT
+RSA,131,NULL_BEFORE_BLOCK_MISSING
+RSA,132,N_NOT_EQUAL_P_Q
+RSA,133,OAEP_DECODING_ERROR
+RSA,134,ONLY_ONE_OF_P_Q_GIVEN
+RSA,135,OUTPUT_BUFFER_TOO_SMALL
+RSA,136,PADDING_CHECK_FAILED
+RSA,137,PKCS_DECODING_ERROR
+RSA,138,SLEN_CHECK_FAILED
+RSA,139,SLEN_RECOVERY_FAILED
+RSA,140,TOO_LONG
+RSA,141,TOO_MANY_ITERATIONS
+RSA,142,UNKNOWN_ALGORITHM_TYPE
+RSA,143,UNKNOWN_PADDING_TYPE
+RSA,144,VALUE_MISSING
+RSA,145,WRONG_SIGNATURE_LENGTH
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index 3766bb98..dfe4ac81 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -108,6 +108,7 @@ SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING
SSL,207,SERVERHELLO_TLSEXT
SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED
SSL,209,SESSION_MAY_NOT_BE_CREATED
+SSL,250,SHUTDOWN_WHILE_IN_INIT
SSL,210,SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER
SSL,211,SRTP_COULD_NOT_ALLOCATE_PROFILES
SSL,212,SRTP_UNKNOWN_PROTECTION_PROFILE
diff --git a/crypto/err/x509.errordata b/crypto/err/x509.errordata
index f4828ce8..5687c30c 100644
--- a/crypto/err/x509.errordata
+++ b/crypto/err/x509.errordata
@@ -10,28 +10,27 @@ X509,108,IDP_MISMATCH
X509,109,INVALID_BIT_STRING_BITS_LEFT
X509,110,INVALID_DIRECTORY
X509,111,INVALID_FIELD_NAME
-X509,112,INVALID_TRUST
-X509,113,ISSUER_MISMATCH
-X509,114,KEY_TYPE_MISMATCH
-X509,115,KEY_VALUES_MISMATCH
-X509,116,LOADING_CERT_DIR
-X509,117,LOADING_DEFAULTS
-X509,118,METHOD_NOT_SUPPORTED
+X509,112,INVALID_PSS_PARAMETERS
+X509,113,INVALID_TRUST
+X509,114,ISSUER_MISMATCH
+X509,115,KEY_TYPE_MISMATCH
+X509,116,KEY_VALUES_MISMATCH
+X509,117,LOADING_CERT_DIR
+X509,118,LOADING_DEFAULTS
+X509,135,NAME_TOO_LONG
X509,119,NEWER_CRL_NOT_NEWER
X509,120,NOT_PKCS7_SIGNED_DATA
X509,121,NO_CERTIFICATES_INCLUDED
X509,122,NO_CERT_SET_FOR_US_TO_VERIFY
-X509,136,NO_CRLS_INCLUDED
-X509,123,NO_CRL_NUMBER
-X509,124,PUBLIC_KEY_DECODE_ERROR
-X509,125,PUBLIC_KEY_ENCODE_ERROR
-X509,126,SHOULD_RETRY
-X509,127,UNABLE_TO_FIND_PARAMETERS_IN_CHAIN
-X509,128,UNABLE_TO_GET_CERTS_PUBLIC_KEY
-X509,129,UNKNOWN_KEY_TYPE
-X509,130,UNKNOWN_NID
-X509,131,UNKNOWN_PURPOSE_ID
-X509,132,UNKNOWN_TRUST_ID
-X509,133,UNSUPPORTED_ALGORITHM
-X509,134,WRONG_LOOKUP_TYPE
-X509,135,WRONG_TYPE
+X509,123,NO_CRLS_INCLUDED
+X509,124,NO_CRL_NUMBER
+X509,125,PUBLIC_KEY_DECODE_ERROR
+X509,126,PUBLIC_KEY_ENCODE_ERROR
+X509,127,SHOULD_RETRY
+X509,128,UNKNOWN_KEY_TYPE
+X509,129,UNKNOWN_NID
+X509,130,UNKNOWN_PURPOSE_ID
+X509,131,UNKNOWN_TRUST_ID
+X509,132,UNSUPPORTED_ALGORITHM
+X509,133,WRONG_LOOKUP_TYPE
+X509,134,WRONG_TYPE
diff --git a/crypto/evp/CMakeLists.txt b/crypto/evp/CMakeLists.txt
index d47a7e2d..1174be63 100644
--- a/crypto/evp/CMakeLists.txt
+++ b/crypto/evp/CMakeLists.txt
@@ -5,7 +5,6 @@ add_library(
OBJECT
- algorithm.c
digestsign.c
evp.c
evp_asn1.c
@@ -16,6 +15,7 @@ add_library(
p_rsa.c
p_rsa_asn1.c
pbkdf.c
+ print.c
sign.c
)
diff --git a/crypto/evp/algorithm.c b/crypto/evp/algorithm.c
deleted file mode 100644
index 63bc77af..00000000
--- a/crypto/evp/algorithm.c
+++ /dev/null
@@ -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/evp.h>
-
-#include <assert.h>
-
-#include <openssl/asn1.h>
-#include <openssl/err.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
-
-#include "internal.h"
-
-
-int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
- const EVP_MD *digest;
- EVP_PKEY *pkey;
- int sign_nid, paramtype;
-
- digest = EVP_MD_CTX_md(ctx);
- pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
- if (!digest || !pkey) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_CONTEXT_NOT_INITIALISED);
- return 0;
- }
-
- if (pkey->ameth->digest_sign_algorithm) {
- switch (pkey->ameth->digest_sign_algorithm(ctx, algor)) {
- case EVP_DIGEST_SIGN_ALGORITHM_ERROR:
- return 0;
- case EVP_DIGEST_SIGN_ALGORITHM_SUCCESS:
- return 1;
- case EVP_DIGEST_SIGN_ALGORITHM_DEFAULT:
- /* Use default behavior. */
- break;
- default:
- assert(0);
- }
- }
-
- /* Default behavior: look up the OID for the algorithm/hash pair and encode
- * that. */
- if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
- pkey->ameth->pkey_id)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
- return 0;
- }
-
- if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) {
- paramtype = V_ASN1_NULL;
- } else {
- paramtype = V_ASN1_UNDEF;
- }
-
- X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
- return 1;
-}
-
-int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
- X509_ALGOR *algor,
- EVP_PKEY *pkey) {
- int digest_nid, pkey_nid;
- const EVP_PKEY_ASN1_METHOD *ameth;
- const EVP_MD *digest;
-
- /* Convert signature OID into digest and public key OIDs */
- if (!OBJ_find_sigid_algs(OBJ_obj2nid(algor->algorithm), &digest_nid,
- &pkey_nid)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
- return 0;
- }
-
- /* Check public key OID matches public key type */
- ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
- if (ameth == NULL || ameth->pkey_id != pkey->ameth->pkey_id) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_WRONG_PUBLIC_KEY_TYPE);
- return 0;
- }
-
- /* NID_undef signals that there are custom parameters to set. */
- if (digest_nid == NID_undef) {
- if (!pkey->ameth || !pkey->ameth->digest_verify_init_from_algorithm) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
- return 0;
- }
-
- return pkey->ameth->digest_verify_init_from_algorithm(ctx, algor, pkey);
- }
-
- /* Otherwise, initialize with the digest from the OID. */
- digest = EVP_get_digestbynid(digest_nid);
- if (digest == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
- return 0;
- }
-
- return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey);
-}
-
diff --git a/crypto/evp/evp.c b/crypto/evp/evp.c
index fa842120..ee207f9b 100644
--- a/crypto/evp/evp.c
+++ b/crypto/evp/evp.c
@@ -59,12 +59,11 @@
#include <assert.h>
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rsa.h>
#include <openssl/thread.h>
@@ -195,8 +194,10 @@ int EVP_PKEY_id(const EVP_PKEY *pkey) {
return pkey->type;
}
-/* TODO(fork): remove the first argument. */
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine, int nid) {
+/* evp_pkey_asn1_find returns the ASN.1 method table for the given |nid|, which
+ * should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
+ * unknown. */
+static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) {
switch (nid) {
case EVP_PKEY_RSA:
return &rsa_asn1_meth;
@@ -210,7 +211,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine, int nid) {
}
int EVP_PKEY_type(int nid) {
- const EVP_PKEY_ASN1_METHOD *meth = EVP_PKEY_asn1_find(NULL, nid);
+ const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(nid);
if (meth == NULL) {
return NID_undef;
}
@@ -309,21 +310,6 @@ int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) {
return key != NULL;
}
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pengine,
- const char *name,
- size_t len) {
- if (len == 3 && memcmp(name, "RSA", 3) == 0) {
- return &rsa_asn1_meth;
- }
- if (len == 2 && memcmp(name, "EC", 2) == 0) {
- return &ec_asn1_meth;
- }
- if (len == 3 && memcmp(name, "DSA", 3) == 0) {
- return &dsa_asn1_meth;
- }
- return NULL;
-}
-
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
const EVP_PKEY_ASN1_METHOD *ameth;
@@ -331,10 +317,10 @@ int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
free_it(pkey);
}
- ameth = EVP_PKEY_asn1_find(NULL, type);
+ ameth = evp_pkey_asn1_find(type);
if (ameth == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
- ERR_add_error_dataf("algorithm %d (%s)", type, OBJ_nid2sn(type));
+ ERR_add_error_dataf("algorithm %d", type);
return 0;
}
@@ -358,41 +344,6 @@ int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
return -2;
}
-static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
- const char *kstr) {
- BIO_indent(out, indent, 128);
- BIO_printf(out, "%s algorithm \"%s\" unsupported\n", kstr,
- OBJ_nid2ln(pkey->type));
- return 1;
-}
-
-int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx) {
- if (pkey->ameth && pkey->ameth->pub_print) {
- return pkey->ameth->pub_print(out, pkey, indent, pctx);
- }
-
- return print_unsupported(out, pkey, indent, "Public Key");
-}
-
-int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx) {
- if (pkey->ameth && pkey->ameth->priv_print) {
- return pkey->ameth->priv_print(out, pkey, indent, pctx);
- }
-
- return print_unsupported(out, pkey, indent, "Private Key");
-}
-
-int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx) {
- if (pkey->ameth && pkey->ameth->param_print) {
- return pkey->ameth->param_print(out, pkey, indent, pctx);
- }
-
- return print_unsupported(out, pkey, indent, "Parameters");
-}
-
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
(void *)md);
@@ -405,6 +356,8 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
void OpenSSL_add_all_algorithms(void) {}
+void OPENSSL_add_all_algorithms_conf(void) {}
+
void OpenSSL_add_all_ciphers(void) {}
void OpenSSL_add_all_digests(void) {}
diff --git a/crypto/evp/evp_asn1.c b/crypto/evp/evp_asn1.c
index ed7ae8b7..3681d4fc 100644
--- a/crypto/evp/evp_asn1.c
+++ b/crypto/evp/evp_asn1.c
@@ -56,22 +56,50 @@
#include <openssl/evp.h>
-#include <openssl/asn1.h>
+#include <string.h>
+
#include <openssl/bytestring.h>
+#include <openssl/dsa.h>
+#include <openssl/ec_key.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
+#include <openssl/rsa.h>
#include "internal.h"
+static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = {
+ &rsa_asn1_meth,
+ &ec_asn1_meth,
+ &dsa_asn1_meth,
+};
+
+static int parse_key_type(CBS *cbs, int *out_type) {
+ CBS oid;
+ if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) {
+ return 0;
+ }
+
+ unsigned i;
+ for (i = 0; i < sizeof(kASN1Methods)/sizeof(kASN1Methods[0]); i++) {
+ const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i];
+ if (CBS_len(&oid) == method->oid_len &&
+ memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) {
+ *out_type = method->pkey_id;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
/* Parse the SubjectPublicKeyInfo. */
- CBS spki, algorithm, oid, key;
+ CBS spki, algorithm, key;
+ int type;
uint8_t padding;
if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !parse_key_type(&algorithm, &type) ||
!CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) ||
CBS_len(&spki) != 0 ||
/* Every key type defined encodes the key as a byte string with the same
@@ -85,7 +113,7 @@ EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
/* Set up an |EVP_PKEY| of the appropriate type. */
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL ||
- !EVP_PKEY_set_type(ret, OBJ_cbs2nid(&oid))) {
+ !EVP_PKEY_set_type(ret, type)) {
goto err;
}
@@ -106,7 +134,7 @@ err:
}
int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
- if (key->ameth->pub_encode == NULL) {
+ if (key->ameth == NULL || key->ameth->pub_encode == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
@@ -116,13 +144,14 @@ int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
/* Parse the PrivateKeyInfo. */
- CBS pkcs8, algorithm, oid, key;
+ CBS pkcs8, algorithm, key;
uint64_t version;
+ int type;
if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_uint64(&pkcs8, &version) ||
version != 0 ||
!CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !parse_key_type(&algorithm, &type) ||
!CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return NULL;
@@ -133,7 +162,7 @@ EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
/* Set up an |EVP_PKEY| of the appropriate type. */
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL ||
- !EVP_PKEY_set_type(ret, OBJ_cbs2nid(&oid))) {
+ !EVP_PKEY_set_type(ret, type)) {
goto err;
}
@@ -154,7 +183,7 @@ err:
}
int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
- if (key->ameth->priv_encode == NULL) {
+ if (key->ameth == NULL || key->ameth->priv_encode == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
@@ -162,107 +191,134 @@ int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
return key->ameth->priv_encode(cbb, key);
}
-EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
- long len) {
- EVP_PKEY *ret;
-
- if (out == NULL || *out == NULL) {
- ret = EVP_PKEY_new();
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_EVP_LIB);
- return NULL;
- }
- } else {
- ret = *out;
- }
-
- if (!EVP_PKEY_set_type(ret, type)) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
- goto err;
+static EVP_PKEY *old_priv_decode(CBS *cbs, int type) {
+ EVP_PKEY *ret = EVP_PKEY_new();
+ if (ret == NULL) {
+ return NULL;
}
- const uint8_t *in = *inp;
- /* If trying to remove |old_priv_decode|, note that some code depends on this
- * function writing into |*out| and the |priv_decode| path doesn't support
- * that. */
- if (!ret->ameth->old_priv_decode ||
- !ret->ameth->old_priv_decode(ret, &in, len)) {
- if (ret->ameth->priv_decode) {
- /* Reset |in| in case |old_priv_decode| advanced it on error. */
- in = *inp;
- PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &in, len);
- if (!p8) {
+ switch (type) {
+ case EVP_PKEY_EC: {
+ EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL);
+ if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) {
+ EC_KEY_free(ec_key);
goto err;
}
- EVP_PKEY_free(ret);
- ret = EVP_PKCS82PKEY(p8);
- PKCS8_PRIV_KEY_INFO_free(p8);
- if (ret == NULL) {
+ return ret;
+ }
+ case EVP_PKEY_DSA: {
+ DSA *dsa = DSA_parse_private_key(cbs);
+ if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) {
+ DSA_free(dsa);
goto err;
}
- } else {
- OPENSSL_PUT_ERROR(EVP, ERR_R_ASN1_LIB);
+ return ret;
+ }
+ case EVP_PKEY_RSA: {
+ RSA *rsa = RSA_parse_private_key(cbs);
+ if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
+ RSA_free(rsa);
+ goto err;
+ }
+ return ret;
+ }
+ default:
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
+ }
+
+err:
+ EVP_PKEY_free(ret);
+ return NULL;
+}
+
+EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
+ long len) {
+ if (len < 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ return NULL;
+ }
+
+ /* Parse with the legacy format. */
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ EVP_PKEY *ret = old_priv_decode(&cbs, type);
+ if (ret == NULL) {
+ /* Try again with PKCS#8. */
+ ERR_clear_error();
+ CBS_init(&cbs, *inp, (size_t)len);
+ ret = EVP_parse_private_key(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (ret->type != type) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
+ EVP_PKEY_free(ret);
+ return NULL;
}
}
if (out != NULL) {
+ EVP_PKEY_free(*out);
*out = ret;
}
- *inp = in;
+ *inp = CBS_data(&cbs);
return ret;
+}
-err:
- if (out == NULL || *out != ret) {
- EVP_PKEY_free(ret);
+/* num_elements parses one SEQUENCE from |in| and returns the number of elements
+ * in it. On parse error, it returns zero. */
+static size_t num_elements(const uint8_t *in, size_t in_len) {
+ CBS cbs, sequence;
+ CBS_init(&cbs, in, (size_t)in_len);
+
+ if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
+ return 0;
}
- return NULL;
+
+ size_t count = 0;
+ while (CBS_len(&sequence) > 0) {
+ if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) {
+ return 0;
+ }
+
+ count++;
+ }
+
+ return count;
}
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
- STACK_OF(ASN1_TYPE) *inkey;
- const uint8_t *p;
- int keytype;
- p = *inp;
-
- /* Dirty trick: read in the ASN1 data into out STACK_OF(ASN1_TYPE):
- * by analyzing it we can determine the passed structure: this
- * assumes the input is surrounded by an ASN1 SEQUENCE. */
- inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, len);
- /* Since we only need to discern "traditional format" RSA and DSA
- * keys we can just count the elements. */
- if (sk_ASN1_TYPE_num(inkey) == 6) {
- keytype = EVP_PKEY_DSA;
- } else if (sk_ASN1_TYPE_num(inkey) == 4) {
- keytype = EVP_PKEY_EC;
- } else if (sk_ASN1_TYPE_num(inkey) == 3) {
- /* This seems to be PKCS8, not traditional format */
- p = *inp;
- PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
- EVP_PKEY *ret;
-
- sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
- if (!p8) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return NULL;
- }
- ret = EVP_PKCS82PKEY(p8);
- PKCS8_PRIV_KEY_INFO_free(p8);
- if (ret == NULL) {
- return NULL;
- }
+ if (len < 0) {
+ OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+ return NULL;
+ }
- *inp = p;
- if (out) {
+ /* Parse the input as a PKCS#8 PrivateKeyInfo. */
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ EVP_PKEY *ret = EVP_parse_private_key(&cbs);
+ if (ret != NULL) {
+ if (out != NULL) {
+ EVP_PKEY_free(*out);
*out = ret;
}
+ *inp = CBS_data(&cbs);
return ret;
- } else {
- keytype = EVP_PKEY_RSA;
}
+ ERR_clear_error();
- sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
- return d2i_PrivateKey(keytype, out, inp, len);
+ /* Count the elements to determine the legacy key format. */
+ switch (num_elements(*inp, (size_t)len)) {
+ case 4:
+ return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);
+
+ case 6:
+ return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len);
+
+ default:
+ return d2i_PrivateKey(EVP_PKEY_RSA, out, inp, len);
+ }
}
int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
diff --git a/crypto/evp/evp_ctx.c b/crypto/evp/evp_ctx.c
index b06eefd6..f510f6c7 100644
--- a/crypto/evp/evp_ctx.c
+++ b/crypto/evp/evp_ctx.c
@@ -56,12 +56,10 @@
#include <openssl/evp.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include "internal.h"
@@ -98,8 +96,7 @@ static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) {
if (pmeth == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
- const char *name = OBJ_nid2sn(id);
- ERR_add_error_dataf("algorithm %d (%s)", id, name);
+ ERR_add_error_dataf("algorithm %d", id);
return NULL;
}
diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc
index 19e4cf6a..9bc36ad8 100644
--- a/crypto/evp/evp_extra_test.cc
+++ b/crypto/evp/evp_extra_test.cc
@@ -26,7 +26,6 @@
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include "../test/scoped_types.h"
@@ -178,142 +177,6 @@ static const uint8_t kSignature[] = {
0x55, 0xa7, 0xab, 0x45, 0x02, 0x97, 0x60, 0x42,
};
-// kExamplePSSCert is an example self-signed certificate, signed with
-// kExampleRSAKeyDER using RSA-PSS with default hash functions.
-static const uint8_t kExamplePSSCert[] = {
- 0x30, 0x82, 0x02, 0x62, 0x30, 0x82, 0x01, 0xc6, 0xa0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x09, 0x00, 0x8d, 0xea, 0x53, 0x24, 0xfa, 0x48, 0x87, 0xf3,
- 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
- 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02, 0x01, 0x6a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
- 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f,
- 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20,
- 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31,
- 0x34, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39, 0x35, 0x35, 0x5a,
- 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39,
- 0x35, 0x35, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
- 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
- 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
- 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
- 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
- 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4,
- 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d,
- 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83,
- 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c,
- 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf,
- 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33,
- 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7,
- 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77,
- 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52,
- 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c,
- 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64,
- 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e,
- 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd0,
- 0x41, 0xfb, 0x89, 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49,
- 0x11, 0xf9, 0x55, 0x81, 0x78, 0x1f, 0x13, 0x30, 0x1f, 0x06, 0x03, 0x55,
- 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xd0, 0x41, 0xfb, 0x89,
- 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49, 0x11, 0xf9, 0x55,
- 0x81, 0x78, 0x1f, 0x13, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
- 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86,
- 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02,
- 0x01, 0x6a, 0x03, 0x81, 0x81, 0x00, 0x49, 0x4c, 0xb6, 0x45, 0x97, 0x20,
- 0x35, 0xb3, 0x50, 0x64, 0x0d, 0x3f, 0xec, 0x5f, 0x95, 0xd5, 0x84, 0xcb,
- 0x11, 0x7c, 0x03, 0xd7, 0xa6, 0xe6, 0xfa, 0x24, 0x95, 0x9f, 0x31, 0xb0,
- 0xb5, 0xec, 0x66, 0x41, 0x51, 0x18, 0x21, 0x91, 0xbb, 0xe0, 0xaf, 0xf0,
- 0xc5, 0xb7, 0x59, 0x41, 0xd4, 0xdb, 0xa4, 0xd2, 0x64, 0xa7, 0x54, 0x0f,
- 0x8c, 0xf7, 0xe1, 0xd3, 0x3b, 0x1a, 0xb7, 0x0e, 0x9d, 0x9a, 0xde, 0x50,
- 0xa1, 0x9f, 0x0a, 0xf0, 0xda, 0x34, 0x0e, 0x34, 0x7d, 0x76, 0x07, 0xfe,
- 0x5a, 0xfb, 0xf9, 0x58, 0x9b, 0xc9, 0x50, 0x84, 0x01, 0xa0, 0x05, 0x4d,
- 0x67, 0x42, 0x0b, 0xf8, 0xe4, 0x05, 0xcf, 0xaf, 0x8b, 0x71, 0x31, 0xf1,
- 0x0f, 0x6e, 0xc9, 0x24, 0x27, 0x9b, 0xac, 0x04, 0xd7, 0x64, 0x0d, 0x30,
- 0x4e, 0x11, 0x93, 0x40, 0x39, 0xbb, 0x72, 0xb2, 0xfe, 0x6b, 0xe4, 0xae,
- 0x8c, 0x16,
-};
-
-// kBadPSSCert is an example RSA-PSS certificate with bad parameters.
-static const uint8_t kBadPSSCert[] = {
- 0x30, 0x82, 0x03, 0x76, 0x30, 0x82, 0x02, 0x3a, 0xa0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x09, 0x00, 0xd7, 0x30, 0x64, 0xbc, 0x9f, 0x12, 0xfe, 0xc3,
- 0x30, 0x3e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
- 0x0a, 0x30, 0x31, 0xa0, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
- 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa1, 0x1a, 0x30, 0x18, 0x06, 0x09,
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0b, 0x06,
- 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa2, 0x04,
- 0x02, 0x02, 0x00, 0xde, 0x30, 0x27, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03,
- 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6e,
- 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x50, 0x53, 0x53, 0x20, 0x63, 0x65,
- 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1e, 0x17,
- 0x0d, 0x31, 0x35, 0x31, 0x31, 0x30, 0x34, 0x31, 0x36, 0x30, 0x32, 0x33,
- 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x32, 0x30, 0x34, 0x31, 0x36,
- 0x30, 0x32, 0x33, 0x35, 0x5a, 0x30, 0x27, 0x31, 0x25, 0x30, 0x23, 0x06,
- 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49,
- 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x50, 0x53, 0x53, 0x20, 0x63,
- 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x82,
- 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
- 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0xda, 0x33, 0xb5, 0x87,
- 0xa9, 0x50, 0x80, 0x18, 0x02, 0x00, 0xfb, 0x32, 0xf5, 0x29, 0x6b, 0xef,
- 0x01, 0x24, 0xeb, 0x86, 0x5a, 0xbe, 0xd5, 0xe3, 0xdd, 0x3b, 0xbc, 0x2c,
- 0xad, 0x65, 0xf6, 0x2a, 0x26, 0x28, 0x4d, 0x8a, 0xc9, 0x61, 0x39, 0xf1,
- 0x84, 0xb9, 0xe7, 0xd3, 0x0a, 0xc7, 0xa8, 0x0a, 0x6d, 0xef, 0xd9, 0xcb,
- 0x20, 0x11, 0xbb, 0x71, 0xf4, 0xa1, 0xc9, 0x9a, 0x85, 0x1c, 0xe6, 0x3f,
- 0x23, 0x39, 0x58, 0x3c, 0xc5, 0x6d, 0xfa, 0x03, 0xe8, 0xdb, 0xdd, 0xe0,
- 0xc3, 0xde, 0x85, 0x76, 0xce, 0x49, 0x06, 0xc8, 0xe1, 0x8e, 0x4c, 0x86,
- 0x9c, 0xec, 0xab, 0xf4, 0xe5, 0x27, 0xb4, 0x5a, 0xaf, 0xc4, 0x36, 0xd3,
- 0x20, 0x81, 0x54, 0xee, 0x8f, 0x48, 0x77, 0x10, 0xf8, 0x79, 0xd6, 0xaa,
- 0x8d, 0x1b, 0xfe, 0x7d, 0xe8, 0x15, 0x13, 0xe0, 0x7b, 0xf6, 0x90, 0xe4,
- 0xe2, 0xcd, 0x2e, 0x8e, 0xc9, 0x3a, 0x75, 0x42, 0xed, 0x0a, 0x0f, 0x51,
- 0xb2, 0xdd, 0x2e, 0x70, 0x61, 0x68, 0xd7, 0xd9, 0xab, 0xf9, 0xbe, 0xe4,
- 0x75, 0xb7, 0xe7, 0xf2, 0x96, 0x7b, 0xd9, 0x93, 0x43, 0x24, 0xfb, 0x9e,
- 0x55, 0xda, 0xd4, 0x01, 0x6c, 0x3d, 0xa2, 0x59, 0x7a, 0xd5, 0x47, 0x18,
- 0x7e, 0x4e, 0xf9, 0x5d, 0xda, 0xcb, 0x93, 0xa2, 0x65, 0x2f, 0x8d, 0x46,
- 0xad, 0x81, 0xdc, 0xf0, 0xa9, 0x5f, 0x5d, 0xfe, 0x37, 0x80, 0x64, 0x2a,
- 0x41, 0xfa, 0xe9, 0x1e, 0x48, 0x38, 0x22, 0x1d, 0x9c, 0x23, 0xa5, 0xad,
- 0xda, 0x78, 0x45, 0x18, 0x0c, 0xeb, 0x95, 0xca, 0x2b, 0xcc, 0xb9, 0x62,
- 0x40, 0x85, 0x09, 0x44, 0x88, 0x4c, 0xf2, 0x1e, 0x08, 0x80, 0x37, 0xe9,
- 0x06, 0x96, 0x8f, 0x75, 0x54, 0x0b, 0xa9, 0x2d, 0xa9, 0x15, 0xb5, 0xda,
- 0xe5, 0xe4, 0x23, 0xaa, 0x2c, 0x89, 0xc1, 0xa9, 0x36, 0xbc, 0x9f, 0x02,
- 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03,
- 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2b, 0x75, 0xf3, 0x43, 0x78,
- 0xa0, 0x65, 0x2d, 0xe4, 0xb6, 0xf3, 0x07, 0x04, 0x38, 0x21, 0xaf, 0xb6,
- 0xe1, 0x5f, 0x7b, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
- 0x30, 0x16, 0x80, 0x14, 0x2b, 0x75, 0xf3, 0x43, 0x78, 0xa0, 0x65, 0x2d,
- 0xe4, 0xb6, 0xf3, 0x07, 0x04, 0x38, 0x21, 0xaf, 0xb6, 0xe1, 0x5f, 0x7b,
- 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01,
- 0x01, 0xff, 0x30, 0x31, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x0a, 0x30, 0x24, 0xa0, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60,
- 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa1, 0x0d, 0x30, 0x0b,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0xa2,
- 0x04, 0x02, 0x02, 0x00, 0xde, 0x03, 0x82, 0x01, 0x01, 0x00, 0x08, 0xc1,
- 0xb6, 0x6f, 0x74, 0x94, 0x6c, 0x60, 0x75, 0xd8, 0xdc, 0xe1, 0x7b, 0xbf,
- 0x9d, 0xb5, 0xd7, 0x14, 0x75, 0x6c, 0xdb, 0x35, 0x5c, 0x1e, 0xff, 0xe6,
- 0xa8, 0xe6, 0x68, 0x42, 0x41, 0x81, 0xf6, 0xbf, 0xc1, 0x56, 0x02, 0xdb,
- 0xc6, 0x11, 0xeb, 0x15, 0x9d, 0xa9, 0x1c, 0x61, 0x25, 0x6d, 0x46, 0x0f,
- 0x7e, 0x27, 0xdd, 0x4b, 0xdc, 0xed, 0x07, 0xbd, 0xde, 0xd5, 0xde, 0x09,
- 0xf8, 0xfd, 0xbd, 0xa3, 0x4c, 0x81, 0xa9, 0xf7, 0x78, 0xff, 0x01, 0x80,
- 0x73, 0xf2, 0x40, 0xf2, 0xa8, 0x27, 0xe8, 0x00, 0x04, 0x3b, 0xf5, 0xe7,
- 0xa6, 0x58, 0x45, 0x79, 0x34, 0x49, 0x42, 0xd2, 0xd9, 0x56, 0x5e, 0xf9,
- 0x0a, 0x41, 0xd7, 0x81, 0x41, 0x94, 0x77, 0x78, 0x7e, 0x00, 0x3b, 0xca,
- 0xb5, 0xc0, 0x6e, 0x5b, 0xd7, 0x52, 0x52, 0x77, 0x1a, 0x52, 0xb8, 0x0d,
- 0x29, 0x1f, 0x2e, 0xfe, 0x1f, 0xf6, 0xb0, 0xc1, 0xb7, 0xf1, 0x15, 0x98,
- 0x0f, 0x30, 0x5d, 0x74, 0x2f, 0xfa, 0xe9, 0x84, 0xda, 0xde, 0xbe, 0xca,
- 0x91, 0x55, 0x1f, 0x5b, 0xbc, 0xaa, 0x45, 0x07, 0xc4, 0x2e, 0x21, 0x8a,
- 0x75, 0xc9, 0xbe, 0x6e, 0x39, 0x53, 0x10, 0xcb, 0x2f, 0x4b, 0xe1, 0x21,
- 0x1e, 0xea, 0x7d, 0x0b, 0x36, 0xe9, 0xa0, 0x2c, 0x76, 0x17, 0x1f, 0x69,
- 0x34, 0xfb, 0x45, 0x63, 0x7c, 0x84, 0x39, 0xb4, 0x21, 0x98, 0xbd, 0x49,
- 0xca, 0x80, 0x91, 0x5a, 0xa0, 0x44, 0xef, 0x91, 0xb3, 0x14, 0xf6, 0xd1,
- 0x6a, 0x2b, 0xb1, 0xe5, 0x4a, 0x44, 0x92, 0x7b, 0x3e, 0x8b, 0x7b, 0x6b,
- 0x90, 0x6b, 0x2c, 0x67, 0x3b, 0x0e, 0xb9, 0x5a, 0x87, 0x35, 0x33, 0x59,
- 0x94, 0x2f, 0x7e, 0xf6, 0x13, 0xc7, 0x22, 0x87, 0x3d, 0x50, 0xc9, 0x80,
- 0x40, 0xda, 0x35, 0xbc, 0x62, 0x16, 0xdc, 0xd5, 0x95, 0xa1, 0xe1, 0x9b,
- 0x68, 0x9f,
-};
-
// kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8
// PrivateKeyInfo.
static const uint8_t kExampleRSAKeyPKCS8[] = {
@@ -558,162 +421,6 @@ static bool TestEVP_DigestVerifyInit(void) {
return true;
}
-// TestAlgorithmRoundtrip signs a message using an already-initialized
-// |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
-// AlgorithmIdentifier to verify the signature.
-static bool TestAlgorithmRoundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
- if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
- return false;
- }
-
- // Save the algorithm.
- ScopedX509_ALGOR algor(X509_ALGOR_new());
- if (!algor || !EVP_DigestSignAlgorithm(md_ctx, algor.get())) {
- return false;
- }
-
- // Determine the size of the signature.
- size_t sig_len = 0;
- if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
- return false;
- }
- // Sanity check for testing.
- if (sig_len != (size_t)EVP_PKEY_size(pkey)) {
- fprintf(stderr, "sig_len mismatch\n");
- return false;
- }
-
- std::vector<uint8_t> sig;
- sig.resize(sig_len);
- if (!EVP_DigestSignFinal(md_ctx, sig.data(), &sig_len)) {
- return false;
- }
- sig.resize(sig_len);
-
- // Ensure that the signature round-trips.
- ScopedEVP_MD_CTX md_ctx_verify;
- if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx_verify.get(), algor.get(),
- pkey) ||
- !EVP_DigestVerifyUpdate(md_ctx_verify.get(), kMsg, sizeof(kMsg)) ||
- !EVP_DigestVerifyFinal(md_ctx_verify.get(), sig.data(), sig_len)) {
- return false;
- }
-
- return true;
-}
-
-static bool TestEVP_DigestSignAlgorithm(void) {
- ScopedEVP_PKEY pkey = LoadExampleRSAKey();
-
- // Test a simple AlgorithmIdentifier.
- ScopedEVP_MD_CTX md_ctx;
- if (!pkey ||
- !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
- !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
- fprintf(stderr, "RSA with SHA-256 failed\n");
- return false;
- }
-
- // Test RSA-PSS with custom parameters.
- md_ctx.Reset();
- EVP_PKEY_CTX *pkey_ctx;
- if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
- pkey.get()) ||
- !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
- !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) ||
- !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
- fprintf(stderr, "RSA-PSS failed\n");
- return false;
- }
-
- return true;
-}
-
-static bool ParseCertificate(CBS *out_tbs_cert,
- ScopedEVP_PKEY *out_pubkey,
- ScopedX509_ALGOR *out_algor,
- CBS *out_signature,
- const CBS *in_) {
- CBS in = *in_;
- CBS cert_body, tbs_cert, algorithm, signature;
- if (!CBS_get_asn1(&in, &cert_body, CBS_ASN1_SEQUENCE) ||
- CBS_len(&in) != 0 ||
- !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) ||
- !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) ||
- CBS_len(&cert_body) != 0) {
- return false;
- }
-
- CBS tbs_cert_copy = tbs_cert;
- CBS tbs_cert_body, discard, spki;
- if (!CBS_get_asn1(&tbs_cert_copy, &tbs_cert_body, CBS_ASN1_SEQUENCE) ||
- CBS_len(&tbs_cert_copy) != 0 ||
- !CBS_get_optional_asn1(
- &tbs_cert_body, &discard, NULL,
- CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
- !CBS_get_asn1(&tbs_cert_body, &discard /* serialNumber */,
- CBS_ASN1_INTEGER) ||
- !CBS_get_asn1(&tbs_cert_body, &discard /* signature */,
- CBS_ASN1_SEQUENCE) ||
- !CBS_get_any_asn1_element(&tbs_cert_body, &discard /* issuer */,
- NULL, NULL) ||
- !CBS_get_asn1(&tbs_cert_body, &discard /* validity */,
- CBS_ASN1_SEQUENCE) ||
- !CBS_get_any_asn1_element(&tbs_cert_body, &discard /* subject */,
- NULL, NULL) ||
- !CBS_get_asn1_element(&tbs_cert_body, &spki, CBS_ASN1_SEQUENCE)) {
- return false;
- }
-
- const uint8_t *derp = CBS_data(&spki);
- ScopedEVP_PKEY pubkey(d2i_PUBKEY(NULL, &derp, CBS_len(&spki)));
- if (!pubkey || derp != CBS_data(&spki) + CBS_len(&spki)) {
- return false;
- }
-
- derp = CBS_data(&algorithm);
- ScopedX509_ALGOR algor(d2i_X509_ALGOR(NULL, &derp, CBS_len(&algorithm)));
- if (!algor || derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
- return false;
- }
-
- // Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
- // leading phase byte is just a zero.
- uint8_t padding;
- if (!CBS_get_u8(&signature, &padding) || padding != 0) {
- return false;
- }
-
- *out_tbs_cert = tbs_cert;
- *out_pubkey = std::move(pubkey);
- *out_algor = std::move(algor);
- *out_signature = signature;
- return true;
-}
-
-static bool TestEVP_DigestVerifyInitFromAlgorithm(void) {
- CBS in, tbs_cert, signature;
- ScopedEVP_PKEY pkey;
- ScopedX509_ALGOR algor;
- CBS_init(&in, kExamplePSSCert, sizeof(kExamplePSSCert));
- if (!ParseCertificate(&tbs_cert, &pkey, &algor, &signature, &in)) {
- fprintf(stderr, "Failed to parse certificate\n");
- return false;
- }
-
- ScopedEVP_MD_CTX md_ctx;
- if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
- pkey.get()) ||
- !EVP_DigestVerifyUpdate(md_ctx.get(), CBS_data(&tbs_cert),
- CBS_len(&tbs_cert)) ||
- !EVP_DigestVerifyFinal(md_ctx.get(), CBS_data(&signature),
- CBS_len(&signature))) {
- return false;
- }
- return true;
-}
-
static bool TestVerifyRecover() {
ScopedEVP_PKEY pkey = LoadExampleRSAKey();
if (!pkey) {
@@ -792,26 +499,6 @@ static bool TestVerifyRecover() {
return true;
}
-static bool TestBadPSSParameters(void) {
- CBS in, tbs_cert, signature;
- ScopedEVP_PKEY pkey;
- ScopedX509_ALGOR algor;
- CBS_init(&in, kBadPSSCert, sizeof(kBadPSSCert));
- if (!ParseCertificate(&tbs_cert, &pkey, &algor, &signature, &in)) {
- fprintf(stderr, "Failed to parse certificate\n");
- return false;
- }
-
- ScopedEVP_MD_CTX md_ctx;
- if (EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
- pkey.get())) {
- fprintf(stderr, "Unexpectedly processed bad signature parameters\n");
- return false;
- }
- ERR_clear_error();
- return true;
-}
-
static bool TestValidPrivateKey(const uint8_t *input, size_t input_len,
int expected_id) {
const uint8_t *p = input;
@@ -899,6 +586,25 @@ static bool TestEVP_PKCS82PKEY(void) {
return true;
}
+// TestEVPMarshalEmptyPublicKey tests |EVP_marshal_public_key| on an empty key.
+static bool TestEVPMarshalEmptyPublicKey(void) {
+ ScopedEVP_PKEY empty(EVP_PKEY_new());
+ if (!empty) {
+ return false;
+ }
+ 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;
+}
+
// Testd2i_PrivateKey tests |d2i_PrivateKey|.
static bool Testd2i_PrivateKey(void) {
const uint8_t *derp = kExampleRSAKeyDER;
@@ -953,6 +659,15 @@ static bool Testd2i_PrivateKey(void) {
}
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;
+ }
+ ERR_clear_error();
+
return true;
}
@@ -971,30 +686,12 @@ int main(void) {
return 1;
}
- if (!TestEVP_DigestSignAlgorithm()) {
- fprintf(stderr, "EVP_DigestSignInit failed\n");
- ERR_print_errors_fp(stderr);
- return 1;
- }
-
- if (!TestEVP_DigestVerifyInitFromAlgorithm()) {
- fprintf(stderr, "EVP_DigestVerifyInitFromAlgorithm 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 (!TestBadPSSParameters()) {
- fprintf(stderr, "TestBadPSSParameters failed\n");
- ERR_print_errors_fp(stderr);
- return 1;
- }
-
if (!Testd2i_AutoPrivateKey()) {
fprintf(stderr, "Testd2i_AutoPrivateKey failed\n");
ERR_print_errors_fp(stderr);
@@ -1007,6 +704,12 @@ int main(void) {
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);
diff --git a/crypto/evp/evp_test.cc b/crypto/evp/evp_test.cc
index a7dac2bf..b01d1e47 100644
--- a/crypto/evp/evp_test.cc
+++ b/crypto/evp/evp_test.cc
@@ -51,30 +51,27 @@
* ====================================================================
*/
+#include <openssl/evp.h>
+
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable: 4702)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(push))
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
#include <map>
#include <string>
#include <utility>
#include <vector>
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(pop))
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
-#include <openssl/evp.h>
#include "../test/file_test.h"
#include "../test/scoped_types.h"
diff --git a/crypto/evp/evp_tests.txt b/crypto/evp/evp_tests.txt
index f0601b21..7c316d81 100644
--- a/crypto/evp/evp_tests.txt
+++ b/crypto/evp/evp_tests.txt
@@ -54,6 +54,11 @@ PublicKey = P-256-SPKI
Input = 3082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
Error = DECODE_ERROR
+# The same as above, but with trailing data after the curve name.
+PublicKey = P-256-SPKI
+Input = 305b301506072a8648ce3d020106082a8648ce3d0301070500034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = DECODE_ERROR
+
# A DSA private key.
PrivateKey = DSA-1024
Type = DSA
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
index 7fe707e1..0783143d 100644
--- a/crypto/evp/internal.h
+++ b/crypto/evp/internal.h
@@ -59,36 +59,17 @@
#include <openssl/base.h>
+#include <openssl/rsa.h>
+
#if defined(__cplusplus)
extern "C" {
#endif
-/* These values are flags for EVP_PKEY_ASN1_METHOD.flags. */
-
-/* ASN1_PKEY_SIGPARAM_NULL controls whether the default behavior of
- * EVP_DigestSignAlgorithm writes an explicit NULL parameter in the
- * AlgorithmIdentifier. */
-#define ASN1_PKEY_SIGPARAM_NULL 0x1
-
-/* evp_digest_sign_algorithm_result_t is the return value of the
- * digest_sign_algorithm function in EVP_PKEY_ASN1_METHOD. */
-typedef enum {
- /* EVP_DIGEST_SIGN_ALGORITHM_ERROR signals an error. */
- EVP_DIGEST_SIGN_ALGORITHM_ERROR = 0,
- /* EVP_DIGEST_SIGN_ALGORITHM_SUCCESS signals that the parameters were
- * serialized in the AlgorithmIdentifier. */
- EVP_DIGEST_SIGN_ALGORITHM_SUCCESS = 1,
- /* EVP_DIGEST_SIGN_ALGORITHM_DEFAULT signals that the parameters are
- * serialized using the default behavior. */
- EVP_DIGEST_SIGN_ALGORITHM_DEFAULT = 2,
-} evp_digest_sign_algorithm_result_t;
-
struct evp_pkey_asn1_method_st {
int pkey_id;
- unsigned long pkey_flags;
-
- const char *pem_str;
+ uint8_t oid[9];
+ uint8_t oid_len;
/* pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo
* and writes the result into |out|. It returns one on success and zero on
@@ -104,7 +85,6 @@ struct evp_pkey_asn1_method_st {
int (*pub_encode)(CBB *out, const EVP_PKEY *key);
int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
- int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
/* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the
* result into |out|. It returns one on success and zero on error. |params| is
@@ -116,9 +96,6 @@ struct evp_pkey_asn1_method_st {
* |out|. It returns one on success and zero on error. */
int (*priv_encode)(CBB *out, const EVP_PKEY *key);
- int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx);
-
/* pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by
* custom implementations which do not expose key material and parameters.*/
int (*pkey_opaque)(const EVP_PKEY *pk);
@@ -135,27 +112,8 @@ struct evp_pkey_asn1_method_st {
int (*param_missing)(const EVP_PKEY *pk);
int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
- int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *pctx);
- int (*sig_print)(BIO *out, const X509_ALGOR *sigalg, const ASN1_STRING *sig,
- int indent, ASN1_PCTX *pctx);
-
void (*pkey_free)(EVP_PKEY *pkey);
-
- /* Legacy functions for old PEM */
-
- int (*old_priv_decode)(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen);
-
- /* Converting parameters to/from AlgorithmIdentifier (X509_ALGOR). */
- int (*digest_verify_init_from_algorithm)(EVP_MD_CTX *ctx,
- X509_ALGOR *algor,
- EVP_PKEY *pkey);
- evp_digest_sign_algorithm_result_t (*digest_sign_algorithm)(
- EVP_MD_CTX *ctx,
- X509_ALGOR *algor);
-
} /* EVP_PKEY_ASN1_METHOD */;
diff --git a/crypto/evp/p_dsa_asn1.c b/crypto/evp/p_dsa_asn1.c
index 09f69090..1f022f1a 100644
--- a/crypto/evp/p_dsa_asn1.c
+++ b/crypto/evp/p_dsa_asn1.c
@@ -55,16 +55,11 @@
#include <openssl/evp.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
#include <openssl/digest.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
#include "internal.h"
@@ -111,10 +106,11 @@ static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) {
const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL;
/* See RFC 5480, section 2. */
- CBB spki, algorithm, key_bitstring;
+ CBB spki, algorithm, oid, key_bitstring;
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&algorithm, NID_dsa) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
(has_params &&
!DSA_marshal_parameters(&algorithm, dsa)) ||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
@@ -177,11 +173,12 @@ static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
}
/* See PKCS#11, v2.40, section 2.5. */
- CBB pkcs8, algorithm, private_key;
+ CBB pkcs8, algorithm, oid, private_key;
if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
!CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&algorithm, NID_dsa) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
!DSA_marshal_parameters(&algorithm, dsa) ||
!CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
!BN_marshal_asn1(&private_key, dsa->priv_key) ||
@@ -245,157 +242,17 @@ static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
-static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
- size_t i;
-
- if (!b) {
- return;
- }
- i = BN_num_bytes(b);
- if (*pbuflen < i) {
- *pbuflen = i;
- }
-}
-
-static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
- uint8_t *m = NULL;
- int ret = 0;
- size_t buf_len = 0;
- const char *ktype = NULL;
-
- const BIGNUM *priv_key, *pub_key;
-
- priv_key = NULL;
- if (ptype == 2) {
- priv_key = x->priv_key;
- }
-
- pub_key = NULL;
- if (ptype > 0) {
- pub_key = x->pub_key;
- }
-
- ktype = "DSA-Parameters";
- if (ptype == 2) {
- ktype = "Private-Key";
- } else if (ptype == 1) {
- ktype = "Public-Key";
- }
-
- update_buflen(x->p, &buf_len);
- update_buflen(x->q, &buf_len);
- update_buflen(x->g, &buf_len);
- update_buflen(priv_key, &buf_len);
- update_buflen(pub_key, &buf_len);
-
- m = OPENSSL_malloc(buf_len + 10);
- if (m == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (priv_key) {
- if (!BIO_indent(bp, off, 128) ||
- BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
- goto err;
- }
- }
-
- if (!ASN1_bn_print(bp, "priv:", priv_key, m, off) ||
- !ASN1_bn_print(bp, "pub: ", pub_key, m, off) ||
- !ASN1_bn_print(bp, "P: ", x->p, m, off) ||
- !ASN1_bn_print(bp, "Q: ", x->q, m, off) ||
- !ASN1_bn_print(bp, "G: ", x->g, m, off)) {
- goto err;
- }
- ret = 1;
-
-err:
- OPENSSL_free(m);
- return ret;
-}
-
-static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
-}
-
-static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
-}
-
-static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
-}
-
-static int old_dsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen) {
- DSA *dsa;
- dsa = d2i_DSAPrivateKey(NULL, pder, derlen);
- if (dsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_DSA_LIB);
- return 0;
- }
- EVP_PKEY_assign_DSA(pkey, dsa);
- return 1;
-}
-
-static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
- const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
- DSA_SIG *dsa_sig;
- const uint8_t *p;
-
- if (!sig) {
- return BIO_puts(bp, "\n") > 0;
- }
-
- p = sig->data;
- dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
- if (dsa_sig == NULL) {
- return X509_signature_dump(bp, sig, indent);
- }
-
- int rv = 0;
- size_t buf_len = 0;
- uint8_t *m = NULL;
-
- update_buflen(dsa_sig->r, &buf_len);
- update_buflen(dsa_sig->s, &buf_len);
- m = OPENSSL_malloc(buf_len + 10);
- if (m == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (BIO_write(bp, "\n", 1) != 1 ||
- !ASN1_bn_print(bp, "r: ", dsa_sig->r, m, indent) ||
- !ASN1_bn_print(bp, "s: ", dsa_sig->s, m, indent)) {
- goto err;
- }
- rv = 1;
-
-err:
- OPENSSL_free(m);
- DSA_SIG_free(dsa_sig);
- return rv;
-}
-
const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
EVP_PKEY_DSA,
- 0,
-
- "DSA",
+ /* 1.2.840.10040.4.1 */
+ {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7,
dsa_pub_decode,
dsa_pub_encode,
dsa_pub_cmp,
- dsa_pub_print,
dsa_priv_decode,
dsa_priv_encode,
- dsa_priv_print,
NULL /* pkey_opaque */,
NULL /* pkey_supports_digest */,
@@ -406,12 +263,6 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
dsa_missing_parameters,
dsa_copy_parameters,
dsa_cmp_parameters,
- dsa_param_print,
- dsa_sig_print,
int_dsa_free,
- old_dsa_priv_decode,
-
- NULL /* digest_verify_init_from_algorithm */,
- NULL /* digest_sign_algorithm */,
};
diff --git a/crypto/evp/p_ec.c b/crypto/evp/p_ec.c
index 49521827..f92c87cf 100644
--- a/crypto/evp/p_ec.c
+++ b/crypto/evp/p_ec.c
@@ -66,7 +66,7 @@
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
#include "../ec/internal.h"
diff --git a/crypto/evp/p_ec_asn1.c b/crypto/evp/p_ec_asn1.c
index 14f38396..8d44dcdc 100644
--- a/crypto/evp/p_ec_asn1.c
+++ b/crypto/evp/p_ec_asn1.c
@@ -55,16 +55,12 @@
#include <openssl/evp.h>
-#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
#include "internal.h"
@@ -72,19 +68,15 @@
static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
const EC_KEY *ec_key = key->pkey.ec;
const EC_GROUP *group = EC_KEY_get0_group(ec_key);
- int curve_nid = EC_GROUP_get_curve_name(group);
- if (curve_nid == NID_undef) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
- return 0;
- }
const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
/* See RFC 5480, section 2. */
- CBB spki, algorithm, key_bitstring;
+ CBB spki, algorithm, oid, key_bitstring;
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&algorithm, NID_X9_62_id_ecPublicKey) ||
- !OBJ_nid2cbb(&algorithm, curve_nid) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+ !EC_KEY_marshal_curve_name(&algorithm, group) ||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
!CBB_add_u8(&key_bitstring, 0 /* padding */) ||
!EC_POINT_point2cbb(&key_bitstring, group, public_key,
@@ -101,31 +93,33 @@ static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* See RFC 5480, section 2. */
/* The parameters are a named curve. */
- CBS named_curve;
- if (!CBS_get_asn1(params, &named_curve, CBS_ASN1_OBJECT) ||
- CBS_len(params) != 0) {
+ EC_POINT *point = NULL;
+ EC_KEY *eckey = NULL;
+ EC_GROUP *group = EC_KEY_parse_curve_name(params);
+ if (group == NULL || CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- return 0;
+ goto err;
}
- EC_KEY *eckey = EC_KEY_new_by_curve_name(OBJ_cbs2nid(&named_curve));
- if (eckey == NULL) {
- return 0;
+ eckey = EC_KEY_new();
+ if (eckey == NULL || !EC_KEY_set_group(eckey, group)) {
+ goto err;
}
- EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(eckey));
+ point = EC_POINT_new(group);
if (point == NULL ||
- !EC_POINT_oct2point(EC_KEY_get0_group(eckey), point, CBS_data(key),
- CBS_len(key), NULL) ||
+ !EC_POINT_oct2point(group, point, CBS_data(key), CBS_len(key), NULL) ||
!EC_KEY_set_public_key(eckey, point)) {
goto err;
}
+ EC_GROUP_free(group);
EC_POINT_free(point);
EVP_PKEY_assign_EC_KEY(out, eckey);
return 1;
err:
+ EC_GROUP_free(group);
EC_POINT_free(point);
EC_KEY_free(eckey);
return 0;
@@ -169,11 +163,6 @@ static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
const EC_KEY *ec_key = key->pkey.ec;
- int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
- if (curve_nid == NID_undef) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
- return 0;
- }
/* Omit the redundant copy of the curve name. This contradicts RFC 5915 but
* aligns with PKCS #11. SEC 1 only says they may be omitted if known by other
@@ -182,12 +171,13 @@ static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS;
/* See RFC 5915. */
- CBB pkcs8, algorithm, private_key;
+ CBB pkcs8, algorithm, oid, private_key;
if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
!CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&algorithm, NID_X9_62_id_ecPublicKey) ||
- !OBJ_nid2cbb(&algorithm, curve_nid) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+ !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) ||
!CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
!EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
!CBB_flush(out)) {
@@ -237,153 +227,21 @@ static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); }
-static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
- uint8_t *buffer = NULL;
- const char *ecstr;
- size_t buf_len = 0, i;
- int ret = 0, reason = ERR_R_BIO_LIB;
- BN_CTX *ctx = NULL;
- const EC_GROUP *group;
- const EC_POINT *public_key;
- const BIGNUM *priv_key;
- uint8_t *pub_key_bytes = NULL;
- size_t pub_key_bytes_len = 0;
-
- if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
- reason = ERR_R_PASSED_NULL_PARAMETER;
- goto err;
- }
-
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
-
- if (ktype > 0) {
- public_key = EC_KEY_get0_public_key(x);
- if (public_key != NULL) {
- pub_key_bytes_len = EC_POINT_point2oct(
- group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
- if (pub_key_bytes_len == 0) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
- if (pub_key_bytes == NULL) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- pub_key_bytes_len =
- EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
- pub_key_bytes, pub_key_bytes_len, ctx);
- if (pub_key_bytes_len == 0) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- buf_len = pub_key_bytes_len;
- }
- }
-
- if (ktype == 2) {
- priv_key = EC_KEY_get0_private_key(x);
- if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
- buf_len = i;
- }
- } else {
- priv_key = NULL;
- }
-
- if (ktype > 0) {
- buf_len += 10;
- if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
- reason = ERR_R_MALLOC_FAILURE;
- goto err;
- }
- }
- if (ktype == 2) {
- ecstr = "Private-Key";
- } else if (ktype == 1) {
- ecstr = "Public-Key";
- } else {
- ecstr = "ECDSA-Parameters";
- }
-
- if (!BIO_indent(bp, off, 128)) {
- goto err;
- }
- const BIGNUM *order = EC_GROUP_get0_order(group);
- if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
- goto err;
- }
-
- if ((priv_key != NULL) &&
- !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) {
- goto err;
- }
- if (pub_key_bytes != NULL) {
- BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
- }
- /* TODO(fork): implement */
- /*
- if (!ECPKParameters_print(bp, group, off))
- goto err; */
- ret = 1;
-
-err:
- if (!ret) {
- OPENSSL_PUT_ERROR(EVP, reason);
- }
- OPENSSL_free(pub_key_bytes);
- BN_CTX_free(ctx);
- OPENSSL_free(buffer);
- return ret;
-}
-
-static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
-}
-
-static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
-}
-
-
-static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
-}
-
static int eckey_opaque(const EVP_PKEY *pkey) {
return EC_KEY_is_opaque(pkey->pkey.ec);
}
-static int old_ec_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen) {
- EC_KEY *ec;
- if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
- return 0;
- }
- EVP_PKEY_assign_EC_KEY(pkey, ec);
- return 1;
-}
-
const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
EVP_PKEY_EC,
- 0,
- "EC",
+ /* 1.2.840.10045.2.1 */
+ {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7,
eckey_pub_decode,
eckey_pub_encode,
eckey_pub_cmp,
- eckey_pub_print,
eckey_priv_decode,
eckey_priv_encode,
- eckey_priv_print,
eckey_opaque,
0 /* pkey_supports_digest */,
@@ -394,12 +252,6 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
ec_missing_parameters,
ec_copy_parameters,
ec_cmp_parameters,
- eckey_param_print,
- 0,
int_ec_free,
- old_ec_priv_decode,
-
- NULL /* digest_verify_init_from_algorithm */,
- NULL /* digest_sign_algorithm */,
};
diff --git a/crypto/evp/p_rsa.c b/crypto/evp/p_rsa.c
index 629c33a6..a2106572 100644
--- a/crypto/evp/p_rsa.c
+++ b/crypto/evp/p_rsa.c
@@ -64,7 +64,7 @@
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rsa.h>
#include "../rsa/internal.h"
diff --git a/crypto/evp/p_rsa_asn1.c b/crypto/evp/p_rsa_asn1.c
index 6848cc47..2c4b266d 100644
--- a/crypto/evp/p_rsa_asn1.c
+++ b/crypto/evp/p_rsa_asn1.c
@@ -55,15 +55,12 @@
#include <openssl/evp.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include "../rsa/internal.h"
#include "internal.h"
@@ -71,10 +68,11 @@
static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
/* See RFC 3279, section 2.3.1. */
- CBB spki, algorithm, null, key_bitstring;
+ CBB spki, algorithm, oid, null, key_bitstring;
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&algorithm, NID_rsaEncryption) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
!CBB_add_u8(&key_bitstring, 0 /* padding */) ||
@@ -122,11 +120,12 @@ static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
}
static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) {
- CBB pkcs8, algorithm, null, private_key;
+ CBB pkcs8, algorithm, oid, null, private_key;
if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
!CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&algorithm, NID_rsaEncryption) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
!CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
!RSA_marshal_private_key(&private_key, key->pkey.rsa) ||
@@ -177,548 +176,17 @@ static int rsa_bits(const EVP_PKEY *pkey) {
static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
-static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
- size_t i;
-
- if (!b) {
- return;
- }
-
- i = BN_num_bytes(b);
- if (*pbuflen < i) {
- *pbuflen = i;
- }
-}
-
-static int do_rsa_print(BIO *out, const RSA *rsa, int off,
- int include_private) {
- char *str;
- const char *s;
- uint8_t *m = NULL;
- int ret = 0, mod_len = 0;
- size_t buf_len = 0;
-
- update_buflen(rsa->n, &buf_len);
- update_buflen(rsa->e, &buf_len);
-
- if (include_private) {
- update_buflen(rsa->d, &buf_len);
- update_buflen(rsa->p, &buf_len);
- update_buflen(rsa->q, &buf_len);
- update_buflen(rsa->dmp1, &buf_len);
- update_buflen(rsa->dmq1, &buf_len);
- update_buflen(rsa->iqmp, &buf_len);
-
- if (rsa->additional_primes != NULL) {
- size_t i;
-
- for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
- i++) {
- const RSA_additional_prime *ap =
- sk_RSA_additional_prime_value(rsa->additional_primes, i);
- update_buflen(ap->prime, &buf_len);
- update_buflen(ap->exp, &buf_len);
- update_buflen(ap->coeff, &buf_len);
- }
- }
- }
-
- m = OPENSSL_malloc(buf_len + 10);
- if (m == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (rsa->n != NULL) {
- mod_len = BN_num_bits(rsa->n);
- }
-
- if (!BIO_indent(out, off, 128)) {
- goto err;
- }
-
- if (include_private && rsa->d) {
- if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
- goto err;
- }
- str = "modulus:";
- s = "publicExponent:";
- } else {
- if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
- goto err;
- }
- str = "Modulus:";
- s = "Exponent:";
- }
- if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
- !ASN1_bn_print(out, s, rsa->e, m, off)) {
- goto err;
- }
-
- if (include_private) {
- if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
- !ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
- !ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
- !ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
- !ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
- !ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
- goto err;
- }
-
- if (rsa->additional_primes != NULL &&
- sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
- size_t i;
-
- if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
- goto err;
- }
- for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
- i++) {
- const RSA_additional_prime *ap =
- sk_RSA_additional_prime_value(rsa->additional_primes, i);
-
- if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
- (unsigned)(i + 3)) <= 0 ||
- !ASN1_bn_print(out, "prime:", ap->prime, m, off) ||
- !ASN1_bn_print(out, "exponent:", ap->exp, m, off) ||
- !ASN1_bn_print(out, "coeff:", ap->coeff, m, off)) {
- goto err;
- }
- }
- }
- }
- ret = 1;
-
-err:
- OPENSSL_free(m);
- return ret;
-}
-
-static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
-}
-
-
-static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
- ASN1_PCTX *ctx) {
- return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
-}
-
-/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
-static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
- const uint8_t *p;
- int plen;
-
- if (alg == NULL || alg->parameter == NULL ||
- OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
- alg->parameter->type != V_ASN1_SEQUENCE) {
- return NULL;
- }
-
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
- return d2i_X509_ALGOR(NULL, &p, plen);
-}
-
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
- X509_ALGOR **pmaskHash) {
- const uint8_t *p;
- int plen;
- RSA_PSS_PARAMS *pss;
-
- *pmaskHash = NULL;
-
- if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE) {
- return NULL;
- }
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
- pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
-
- if (!pss) {
- return NULL;
- }
-
- *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
-
- return pss;
-}
-
-static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
- X509_ALGOR *maskHash, int indent) {
- int rv = 0;
-
- if (!pss) {
- if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
- return 0;
- }
- return 1;
- }
-
- if (BIO_puts(bp, "\n") <= 0 ||
- !BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Hash Algorithm: ") <= 0) {
- goto err;
- }
-
- if (pss->hashAlgorithm) {
- if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
- goto err;
- }
-
- if (BIO_puts(bp, "\n") <= 0 ||
- !BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Mask Algorithm: ") <= 0) {
- goto err;
- }
-
- if (pss->maskGenAlgorithm) {
- if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
- BIO_puts(bp, " with ") <= 0) {
- goto err;
- }
-
- if (maskHash) {
- if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "INVALID") <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
- goto err;
- }
- BIO_puts(bp, "\n");
-
- if (!BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Salt Length: 0x") <= 0) {
- goto err;
- }
-
- if (pss->saltLength) {
- if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "14 (default)") <= 0) {
- goto err;
- }
- BIO_puts(bp, "\n");
-
- if (!BIO_indent(bp, indent, 128) ||
- BIO_puts(bp, "Trailer Field: 0x") <= 0) {
- goto err;
- }
-
- if (pss->trailerField) {
- if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
- goto err;
- }
- } else if (BIO_puts(bp, "BC (default)") <= 0) {
- goto err;
- }
- BIO_puts(bp, "\n");
-
- rv = 1;
-
-err:
- return rv;
-}
-
-static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
- const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
- if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss) {
- int rv;
- RSA_PSS_PARAMS *pss;
- X509_ALGOR *maskHash;
-
- pss = rsa_pss_decode(sigalg, &maskHash);
- rv = rsa_pss_param_print(bp, pss, maskHash, indent);
- RSA_PSS_PARAMS_free(pss);
- X509_ALGOR_free(maskHash);
- if (!rv) {
- return 0;
- }
- } else if (!sig && BIO_puts(bp, "\n") <= 0) {
- return 0;
- }
-
- if (sig) {
- return X509_signature_dump(bp, sig, indent);
- }
- return 1;
-}
-
-static int old_rsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
- int derlen) {
- RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
- if (rsa == NULL) {
- OPENSSL_PUT_ERROR(EVP, ERR_R_RSA_LIB);
- return 0;
- }
- EVP_PKEY_assign_RSA(pkey, rsa);
- return 1;
-}
-
-/* allocate and set algorithm ID from EVP_MD, default SHA1 */
-static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
- if (EVP_MD_type(md) == NID_sha1) {
- return 1;
- }
- *palg = X509_ALGOR_new();
- if (!*palg) {
- return 0;
- }
- X509_ALGOR_set_md(*palg, md);
- return 1;
-}
-
-/* Allocate and set MGF1 algorithm ID from EVP_MD */
-static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
- X509_ALGOR *algtmp = NULL;
- ASN1_STRING *stmp = NULL;
- *palg = NULL;
-
- if (EVP_MD_type(mgf1md) == NID_sha1) {
- return 1;
- }
- /* need to embed algorithm ID inside another */
- if (!rsa_md_to_algor(&algtmp, mgf1md) ||
- !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
- goto err;
- }
- *palg = X509_ALGOR_new();
- if (!*palg) {
- goto err;
- }
- X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
- stmp = NULL;
-
-err:
- ASN1_STRING_free(stmp);
- X509_ALGOR_free(algtmp);
- if (*palg) {
- return 1;
- }
-
- return 0;
-}
-
-/* convert algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
- const EVP_MD *md;
- if (!alg) {
- return EVP_sha1();
- }
- md = EVP_get_digestbyobj(alg->algorithm);
- if (md == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_DIGEST);
- }
- return md;
-}
-
-/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
- const EVP_MD *md;
- if (!alg) {
- return EVP_sha1();
- }
- /* Check mask and lookup mask hash algorithm */
- if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_MASK_ALGORITHM);
- return NULL;
- }
- if (!maskHash) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_MASK_PARAMETER);
- return NULL;
- }
- md = EVP_get_digestbyobj(maskHash->algorithm);
- if (md == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_MASK_DIGEST);
- return NULL;
- }
- return md;
-}
-
-/* rsa_ctx_to_pss converts EVP_PKEY_CTX in PSS mode into corresponding
- * algorithm parameter, suitable for setting as an AlgorithmIdentifier. */
-static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) {
- const EVP_MD *sigmd, *mgf1md;
- RSA_PSS_PARAMS *pss = NULL;
- ASN1_STRING *os = NULL;
- EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
- int saltlen, rv = 0;
-
- if (!EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) ||
- !EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) ||
- !EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) {
- goto err;
- }
-
- if (saltlen == -1) {
- saltlen = EVP_MD_size(sigmd);
- } else if (saltlen == -2) {
- saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
- if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
- saltlen--;
- }
- } else {
- goto err;
- }
-
- pss = RSA_PSS_PARAMS_new();
- if (!pss) {
- goto err;
- }
-
- if (saltlen != 20) {
- pss->saltLength = ASN1_INTEGER_new();
- if (!pss->saltLength ||
- !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
- goto err;
- }
- }
-
- if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
- !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
- goto err;
- }
-
- /* Finally create string with pss parameter encoding. */
- if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
- goto err;
- }
- rv = 1;
-
-err:
- if (pss) {
- RSA_PSS_PARAMS_free(pss);
- }
- if (rv) {
- return os;
- }
- if (os) {
- ASN1_STRING_free(os);
- }
- return NULL;
-}
-
-/* From PSS AlgorithmIdentifier set public key parameters. */
-static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
- int ret = 0;
- int saltlen;
- const EVP_MD *mgf1md = NULL, *md = NULL;
- RSA_PSS_PARAMS *pss;
- X509_ALGOR *maskHash;
- EVP_PKEY_CTX *pkctx;
-
- /* Sanity check: make sure it is PSS */
- if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
- return 0;
- }
- /* Decode PSS parameters */
- pss = rsa_pss_decode(sigalg, &maskHash);
- if (pss == NULL) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_PARAMETERS);
- goto err;
- }
-
- mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
- if (!mgf1md) {
- goto err;
- }
- md = rsa_algor_to_md(pss->hashAlgorithm);
- if (!md) {
- goto err;
- }
-
- saltlen = 20;
- if (pss->saltLength) {
- saltlen = ASN1_INTEGER_get(pss->saltLength);
-
- /* Could perform more salt length sanity checks but the main
- * RSA routines will trap other invalid values anyway. */
- if (saltlen < 0) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SALT_LENGTH);
- goto err;
- }
- }
-
- /* low-level routines support only trailer field 0xbc (value 1)
- * and PKCS#1 says we should reject any other value anyway. */
- if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_TRAILER);
- goto err;
- }
-
- if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
- !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
- !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
- !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
- goto err;
- }
-
- ret = 1;
-
-err:
- RSA_PSS_PARAMS_free(pss);
- if (maskHash) {
- X509_ALGOR_free(maskHash);
- }
- return ret;
-}
-
-/* Customised RSA AlgorithmIdentifier handling. This is called when a signature
- * is encountered requiring special handling. We currently only handle PSS. */
-static int rsa_digest_verify_init_from_algorithm(EVP_MD_CTX *ctx,
- X509_ALGOR *sigalg,
- EVP_PKEY *pkey) {
- /* Sanity check: make sure it is PSS */
- if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
- OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
- return 0;
- }
- return rsa_pss_to_ctx(ctx, sigalg, pkey);
-}
-
-static evp_digest_sign_algorithm_result_t rsa_digest_sign_algorithm(
- EVP_MD_CTX *ctx, X509_ALGOR *sigalg) {
- int pad_mode;
- EVP_PKEY_CTX *pkctx = ctx->pctx;
- if (!EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode)) {
- return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
- }
- if (pad_mode == RSA_PKCS1_PSS_PADDING) {
- ASN1_STRING *os1 = rsa_ctx_to_pss(pkctx);
- if (!os1) {
- return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
- }
- X509_ALGOR_set0(sigalg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os1);
- return EVP_DIGEST_SIGN_ALGORITHM_SUCCESS;
- }
-
- /* Other padding schemes use the default behavior. */
- return EVP_DIGEST_SIGN_ALGORITHM_DEFAULT;
-}
-
const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
EVP_PKEY_RSA,
- ASN1_PKEY_SIGPARAM_NULL,
-
- "RSA",
+ /* 1.2.840.113549.1.1.1 */
+ {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, 9,
rsa_pub_decode,
rsa_pub_encode,
rsa_pub_cmp,
- rsa_pub_print,
rsa_priv_decode,
rsa_priv_encode,
- rsa_priv_print,
rsa_opaque,
rsa_supports_digest,
@@ -726,13 +194,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
int_rsa_size,
rsa_bits,
- 0,0,0,0,
+ 0,0,0,
- rsa_sig_print,
int_rsa_free,
-
- old_rsa_priv_decode,
-
- rsa_digest_verify_init_from_algorithm,
- rsa_digest_sign_algorithm,
};
diff --git a/crypto/evp/pbkdf_test.cc b/crypto/evp/pbkdf_test.cc
index a6fe3dc1..438ab644 100644
--- a/crypto/evp/pbkdf_test.cc
+++ b/crypto/evp/pbkdf_test.cc
@@ -15,7 +15,6 @@
#include <stdio.h>
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
diff --git a/crypto/evp/print.c b/crypto/evp/print.c
new file mode 100644
index 00000000..56521ec5
--- /dev/null
+++ b/crypto/evp/print.c
@@ -0,0 +1,527 @@
+/* ====================================================================
+ * Copyright (c) 2006 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/evp.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/mem.h>
+#include <openssl/rsa.h>
+
+#include "../rsa/internal.h"
+
+
+static int bn_print(BIO *bp, const char *number, const BIGNUM *num,
+ uint8_t *buf, int off) {
+ if (num == NULL) {
+ return 1;
+ }
+
+ if (!BIO_indent(bp, off, 128)) {
+ return 0;
+ }
+ if (BN_is_zero(num)) {
+ if (BIO_printf(bp, "%s 0\n", number) <= 0) {
+ return 0;
+ }
+ return 1;
+ }
+
+ if (BN_num_bytes(num) <= sizeof(long)) {
+ const char *neg = BN_is_negative(num) ? "-" : "";
+ if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg,
+ (unsigned long)num->d[0], neg,
+ (unsigned long)num->d[0]) <= 0) {
+ return 0;
+ }
+ } else {
+ buf[0] = 0;
+ if (BIO_printf(bp, "%s%s", number,
+ (BN_is_negative(num)) ? " (Negative)" : "") <= 0) {
+ return 0;
+ }
+ int n = BN_bn2bin(num, &buf[1]);
+
+ if (buf[1] & 0x80) {
+ n++;
+ } else {
+ buf++;
+ }
+
+ int i;
+ for (i = 0; i < n; i++) {
+ if ((i % 15) == 0) {
+ if (BIO_puts(bp, "\n") <= 0 ||
+ !BIO_indent(bp, off + 4, 128)) {
+ return 0;
+ }
+ }
+ if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":") <= 0) {
+ return 0;
+ }
+ }
+ if (BIO_write(bp, "\n", 1) <= 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
+ size_t i;
+
+ if (!b) {
+ return;
+ }
+
+ i = BN_num_bytes(b);
+ if (*pbuflen < i) {
+ *pbuflen = i;
+ }
+}
+
+/* RSA keys. */
+
+static int do_rsa_print(BIO *out, const RSA *rsa, int off,
+ int include_private) {
+ const char *s, *str;
+ uint8_t *m = NULL;
+ int ret = 0, mod_len = 0;
+ size_t buf_len = 0;
+
+ update_buflen(rsa->n, &buf_len);
+ update_buflen(rsa->e, &buf_len);
+
+ if (include_private) {
+ update_buflen(rsa->d, &buf_len);
+ update_buflen(rsa->p, &buf_len);
+ update_buflen(rsa->q, &buf_len);
+ update_buflen(rsa->dmp1, &buf_len);
+ update_buflen(rsa->dmq1, &buf_len);
+ update_buflen(rsa->iqmp, &buf_len);
+
+ if (rsa->additional_primes != NULL) {
+ size_t i;
+
+ for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
+ i++) {
+ const RSA_additional_prime *ap =
+ sk_RSA_additional_prime_value(rsa->additional_primes, i);
+ update_buflen(ap->prime, &buf_len);
+ update_buflen(ap->exp, &buf_len);
+ update_buflen(ap->coeff, &buf_len);
+ }
+ }
+ }
+
+ m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+ if (m == NULL) {
+ OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (rsa->n != NULL) {
+ mod_len = BN_num_bits(rsa->n);
+ }
+
+ if (!BIO_indent(out, off, 128)) {
+ goto err;
+ }
+
+ if (include_private && rsa->d) {
+ if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
+ goto err;
+ }
+ str = "modulus:";
+ s = "publicExponent:";
+ } else {
+ if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
+ goto err;
+ }
+ str = "Modulus:";
+ s = "Exponent:";
+ }
+ if (!bn_print(out, str, rsa->n, m, off) ||
+ !bn_print(out, s, rsa->e, m, off)) {
+ goto err;
+ }
+
+ if (include_private) {
+ if (!bn_print(out, "privateExponent:", rsa->d, m, off) ||
+ !bn_print(out, "prime1:", rsa->p, m, off) ||
+ !bn_print(out, "prime2:", rsa->q, m, off) ||
+ !bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
+ !bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
+ !bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
+ goto err;
+ }
+
+ if (rsa->additional_primes != NULL &&
+ sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
+ size_t i;
+
+ if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
+ goto err;
+ }
+ for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
+ i++) {
+ const RSA_additional_prime *ap =
+ sk_RSA_additional_prime_value(rsa->additional_primes, i);
+
+ if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
+ (unsigned)(i + 3)) <= 0 ||
+ !bn_print(out, "prime:", ap->prime, m, off) ||
+ !bn_print(out, "exponent:", ap->exp, m, off) ||
+ !bn_print(out, "coeff:", ap->coeff, m, off)) {
+ goto err;
+ }
+ }
+ }
+ }
+ ret = 1;
+
+err:
+ OPENSSL_free(m);
+ return ret;
+}
+
+static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
+}
+
+static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
+}
+
+
+/* DSA keys. */
+
+static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
+ uint8_t *m = NULL;
+ int ret = 0;
+ size_t buf_len = 0;
+ const char *ktype = NULL;
+
+ const BIGNUM *priv_key, *pub_key;
+
+ priv_key = NULL;
+ if (ptype == 2) {
+ priv_key = x->priv_key;
+ }
+
+ pub_key = NULL;
+ if (ptype > 0) {
+ pub_key = x->pub_key;
+ }
+
+ ktype = "DSA-Parameters";
+ if (ptype == 2) {
+ ktype = "Private-Key";
+ } else if (ptype == 1) {
+ ktype = "Public-Key";
+ }
+
+ update_buflen(x->p, &buf_len);
+ update_buflen(x->q, &buf_len);
+ update_buflen(x->g, &buf_len);
+ update_buflen(priv_key, &buf_len);
+ update_buflen(pub_key, &buf_len);
+
+ m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+ if (m == NULL) {
+ OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (priv_key) {
+ if (!BIO_indent(bp, off, 128) ||
+ BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
+ goto err;
+ }
+ }
+
+ if (!bn_print(bp, "priv:", priv_key, m, off) ||
+ !bn_print(bp, "pub: ", pub_key, m, off) ||
+ !bn_print(bp, "P: ", x->p, m, off) ||
+ !bn_print(bp, "Q: ", x->q, m, off) ||
+ !bn_print(bp, "G: ", x->g, m, off)) {
+ goto err;
+ }
+ ret = 1;
+
+err:
+ OPENSSL_free(m);
+ return ret;
+}
+
+static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
+}
+
+static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
+}
+
+static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
+}
+
+
+/* EC keys. */
+
+static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
+ uint8_t *buffer = NULL;
+ const char *ecstr;
+ size_t buf_len = 0, i;
+ int ret = 0, reason = ERR_R_BIO_LIB;
+ BIGNUM *order = NULL;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ const BIGNUM *priv_key;
+ uint8_t *pub_key_bytes = NULL;
+ size_t pub_key_bytes_len = 0;
+
+ if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
+ reason = ERR_R_PASSED_NULL_PARAMETER;
+ goto err;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+
+ if (ktype > 0) {
+ public_key = EC_KEY_get0_public_key(x);
+ if (public_key != NULL) {
+ pub_key_bytes_len = EC_POINT_point2oct(
+ group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
+ if (pub_key_bytes_len == 0) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
+ if (pub_key_bytes == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ pub_key_bytes_len =
+ EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
+ pub_key_bytes, pub_key_bytes_len, ctx);
+ if (pub_key_bytes_len == 0) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ buf_len = pub_key_bytes_len;
+ }
+ }
+
+ if (ktype == 2) {
+ priv_key = EC_KEY_get0_private_key(x);
+ if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
+ buf_len = i;
+ }
+ } else {
+ priv_key = NULL;
+ }
+
+ if (ktype > 0) {
+ buf_len += 10;
+ if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ }
+ if (ktype == 2) {
+ ecstr = "Private-Key";
+ } else if (ktype == 1) {
+ ecstr = "Public-Key";
+ } else {
+ ecstr = "ECDSA-Parameters";
+ }
+
+ if (!BIO_indent(bp, off, 128)) {
+ goto err;
+ }
+ order = BN_new();
+ if (order == NULL || !EC_GROUP_get_order(group, order, NULL) ||
+ BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
+ goto err;
+ }
+
+ if ((priv_key != NULL) &&
+ !bn_print(bp, "priv:", priv_key, buffer, off)) {
+ goto err;
+ }
+ if (pub_key_bytes != NULL) {
+ BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
+ }
+ /* TODO(fork): implement */
+ /*
+ if (!ECPKParameters_print(bp, group, off))
+ goto err; */
+ ret = 1;
+
+err:
+ if (!ret) {
+ OPENSSL_PUT_ERROR(EVP, reason);
+ }
+ OPENSSL_free(pub_key_bytes);
+ BN_free(order);
+ BN_CTX_free(ctx);
+ OPENSSL_free(buffer);
+ return ret;
+}
+
+static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
+}
+
+static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
+}
+
+
+static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
+}
+
+
+typedef struct {
+ int type;
+ int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
+ int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx);
+ int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx);
+} EVP_PKEY_PRINT_METHOD;
+
+static EVP_PKEY_PRINT_METHOD kPrintMethods[] = {
+ {
+ EVP_PKEY_RSA,
+ rsa_pub_print,
+ rsa_priv_print,
+ NULL /* param_print */,
+ },
+ {
+ EVP_PKEY_DSA,
+ dsa_pub_print,
+ dsa_priv_print,
+ dsa_param_print,
+ },
+ {
+ EVP_PKEY_EC,
+ eckey_pub_print,
+ eckey_priv_print,
+ eckey_param_print,
+ },
+};
+
+static size_t kPrintMethodsLen =
+ sizeof(kPrintMethods) / sizeof(kPrintMethods[0]);
+
+static EVP_PKEY_PRINT_METHOD *find_method(int type) {
+ size_t i;
+ for (i = 0; i < kPrintMethodsLen; i++) {
+ if (kPrintMethods[i].type == type) {
+ return &kPrintMethods[i];
+ }
+ }
+ return NULL;
+}
+
+static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
+ const char *kstr) {
+ BIO_indent(out, indent, 128);
+ BIO_printf(out, "%s algorithm unsupported\n", kstr);
+ return 1;
+}
+
+int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx) {
+ EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+ if (method != NULL && method->pub_print != NULL) {
+ return method->pub_print(out, pkey, indent, pctx);
+ }
+ return print_unsupported(out, pkey, indent, "Public Key");
+}
+
+int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx) {
+ EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+ if (method != NULL && method->priv_print != NULL) {
+ return method->priv_print(out, pkey, indent, pctx);
+ }
+ return print_unsupported(out, pkey, indent, "Private Key");
+}
+
+int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *pctx) {
+ EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+ if (method != NULL && method->param_print != NULL) {
+ return method->param_print(out, pkey, indent, pctx);
+ }
+ return print_unsupported(out, pkey, indent, "Parameters");
+}
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index 8fa12402..d67abba2 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -163,7 +163,7 @@ int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, int *out_index,
ret = 1;
err:
- CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&ex_data_class->lock);
return ret;
}
@@ -217,7 +217,7 @@ static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out,
if (n > 0) {
*out = sk_CRYPTO_EX_DATA_FUNCS_dup(ex_data_class->meth);
}
- CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&ex_data_class->lock);
if (n > 0 && *out == NULL) {
OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
diff --git a/crypto/hkdf/hkdf.c b/crypto/hkdf/hkdf.c
index f9cdcb0b..d80834d8 100644
--- a/crypto/hkdf/hkdf.c
+++ b/crypto/hkdf/hkdf.c
@@ -21,22 +21,50 @@
#include <openssl/hmac.h>
-int HKDF(uint8_t *out_key, size_t out_len,
- const EVP_MD *digest,
- const uint8_t *secret, size_t secret_len,
- const uint8_t *salt, size_t salt_len,
- const uint8_t *info, size_t info_len) {
+int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
+ const uint8_t *secret, size_t secret_len, const uint8_t *salt,
+ size_t salt_len, const uint8_t *info, size_t info_len) {
+ /* https://tools.ietf.org/html/rfc5869#section-2 */
+ uint8_t prk[EVP_MAX_MD_SIZE];
+ size_t prk_len;
+
+ if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt,
+ salt_len) ||
+ !HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int HKDF_extract(uint8_t *out_key, size_t *out_len, const EVP_MD *digest,
+ const uint8_t *secret, size_t secret_len, const uint8_t *salt,
+ size_t salt_len) {
/* https://tools.ietf.org/html/rfc5869#section-2.2 */
+
+ /* If salt is not given, HashLength zeros are used. However, HMAC does that
+ * internally already so we can ignore it.*/
+ unsigned len;
+ if (HMAC(digest, salt, salt_len, secret, secret_len, out_key, &len) == NULL) {
+ OPENSSL_PUT_ERROR(HKDF, ERR_R_HMAC_LIB);
+ return 0;
+ }
+ *out_len = len;
+ assert(*out_len == EVP_MD_size(digest));
+ return 1;
+}
+
+int HKDF_expand(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
+ uint8_t *prk, size_t prk_len, const uint8_t *info,
+ size_t info_len) {
+ /* https://tools.ietf.org/html/rfc5869#section-2.3 */
const size_t digest_len = EVP_MD_size(digest);
- uint8_t prk[EVP_MAX_MD_SIZE], previous[EVP_MAX_MD_SIZE];
+ uint8_t previous[EVP_MAX_MD_SIZE];
size_t n, done = 0;
- unsigned i, prk_len;
+ unsigned i;
int ret = 0;
HMAC_CTX hmac;
- /* If salt is not given, HashLength zeros are used. However, HMAC does that
- * internally already so we can ignore it.*/
-
/* Expand key material to desired length. */
n = (out_len + digest_len - 1) / digest_len;
if (out_len + digest_len < out_len || n > 255) {
@@ -45,13 +73,6 @@ int HKDF(uint8_t *out_key, size_t out_len,
}
HMAC_CTX_init(&hmac);
-
- /* Extract input keying material into pseudorandom key |prk|. */
- if (HMAC(digest, salt, salt_len, secret, secret_len, prk, &prk_len) == NULL) {
- goto out;
- }
- assert(prk_len == digest_len);
-
if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL)) {
goto out;
}
diff --git a/crypto/hkdf/hkdf_test.c b/crypto/hkdf/hkdf_test.c
index a4abf1c4..a0f75a96 100644
--- a/crypto/hkdf/hkdf_test.c
+++ b/crypto/hkdf/hkdf_test.c
@@ -20,6 +20,8 @@
#include <openssl/err.h>
#include <openssl/hkdf.h>
+#include "../test/test_util.h"
+
typedef struct {
const EVP_MD *(*md_func)(void);
@@ -29,6 +31,8 @@ typedef struct {
const size_t salt_len;
const uint8_t info[80];
const size_t info_len;
+ const uint8_t prk[EVP_MAX_MD_SIZE];
+ const size_t prk_len;
const size_t out_len;
const uint8_t out[82];
} hkdf_test_vector_t;
@@ -48,6 +52,11 @@ static const hkdf_test_vector_t kTests[] = {
{
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
}, 10,
+ {
+ 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d,
+ 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31,
+ 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5,
+ }, 32,
42, {
0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64,
0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
@@ -84,6 +93,11 @@ static const hkdf_test_vector_t kTests[] = {
0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
}, 80,
+ {
+ 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c,
+ 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01,
+ 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44,
+ }, 32,
82, {
0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c,
0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
@@ -106,6 +120,11 @@ static const hkdf_test_vector_t kTests[] = {
{
0,
}, 0,
+ {
+ 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d,
+ 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77,
+ 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04
+ }, 32,
42, {
0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a,
0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
@@ -125,6 +144,10 @@ static const hkdf_test_vector_t kTests[] = {
{
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
}, 10,
+ {
+ 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb,
+ 0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43
+ }, 20,
42, {
0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56,
0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
@@ -161,6 +184,10 @@ static const hkdf_test_vector_t kTests[] = {
0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
}, 80,
+ {
+ 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b,
+ 0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6,
+ }, 20,
82, {
0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5,
0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
@@ -183,6 +210,10 @@ static const hkdf_test_vector_t kTests[] = {
{
0,
}, 0,
+ {
+ 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7,
+ 0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01,
+ }, 20,
42, {
0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98,
0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
@@ -202,6 +233,10 @@ static const hkdf_test_vector_t kTests[] = {
{
0,
}, 0,
+ {
+ 0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e,
+ 0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd,
+ }, 20,
42, {
0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a,
0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
@@ -212,13 +247,36 @@ static const hkdf_test_vector_t kTests[] = {
};
int main(void) {
- uint8_t buf[82];
- size_t i;
+ uint8_t buf[82], prk[EVP_MAX_MD_SIZE];
+ size_t i, prk_len;
CRYPTO_library_init();
for (i = 0; i < sizeof(kTests) / sizeof(kTests[0]); i++) {
const hkdf_test_vector_t *test = &kTests[i];
+ if (!HKDF_extract(prk, &prk_len, test->md_func(), test->ikm, test->ikm_len,
+ test->salt, test->salt_len)) {
+ fprintf(stderr, "Call to HKDF_extract failed\n");
+ ERR_print_errors_fp(stderr);
+ return 1;
+ }
+ if (prk_len != test->prk_len ||
+ memcmp(prk, test->prk, test->prk_len) != 0) {
+ fprintf(stderr, "%zu: Resulting PRK does not match test vector\n", i);
+ return 1;
+ }
+ if (!HKDF_expand(buf, test->out_len, test->md_func(), prk, prk_len,
+ test->info, test->info_len)) {
+ fprintf(stderr, "Call to HKDF_expand failed\n");
+ ERR_print_errors_fp(stderr);
+ return 1;
+ }
+ if (memcmp(buf, test->out, test->out_len) != 0) {
+ fprintf(stderr,
+ "%zu: Resulting key material does not match test vector\n", i);
+ return 1;
+ }
+
if (!HKDF(buf, test->out_len, test->md_func(), test->ikm, test->ikm_len,
test->salt, test->salt_len, test->info, test->info_len)) {
fprintf(stderr, "Call to HKDF failed\n");
@@ -226,8 +284,8 @@ int main(void) {
return 1;
}
if (memcmp(buf, test->out, test->out_len) != 0) {
- fprintf(stderr, "%u: Resulting key material does not match test vector\n",
- (unsigned)i);
+ fprintf(stderr,
+ "%zu: Resulting key material does not match test vector\n", i);
return 1;
}
}
diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c
index be2dccec..bccc5c02 100644
--- a/crypto/hmac/hmac.c
+++ b/crypto/hmac/hmac.c
@@ -59,6 +59,7 @@
#include <assert.h>
#include <string.h>
+#include <openssl/digest.h>
#include <openssl/mem.h>
@@ -115,8 +116,8 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
* case. Fix to API to avoid this. */
if (md != ctx->md || key != NULL) {
size_t i;
- uint8_t pad[HMAC_MAX_MD_CBLOCK];
- uint8_t key_block[HMAC_MAX_MD_CBLOCK];
+ uint8_t pad[EVP_MAX_MD_BLOCK_SIZE];
+ uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE];
unsigned key_block_len;
size_t block_size = EVP_MD_block_size(md);
@@ -134,11 +135,11 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
key_block_len = (unsigned)key_len;
}
/* Keys are then padded with zeros. */
- if (key_block_len != HMAC_MAX_MD_CBLOCK) {
+ if (key_block_len != EVP_MAX_MD_BLOCK_SIZE) {
memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len);
}
- for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
+ for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) {
pad[i] = 0x36 ^ key_block[i];
}
if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) ||
@@ -146,7 +147,7 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
return 0;
}
- for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
+ for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) {
pad[i] = 0x5c ^ key_block[i];
}
if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) ||
diff --git a/crypto/internal.h b/crypto/internal.h
index 2229e19e..e35fb7bd 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -123,9 +123,9 @@
#if defined(OPENSSL_NO_THREADS)
#elif defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#else
#include <pthread.h>
#endif
@@ -135,48 +135,6 @@ extern "C" {
#endif
-/* MSVC's C4701 warning about the use of *potentially*--as opposed to
- * *definitely*--uninitialized values sometimes has false positives. Usually
- * the false positives can and should be worked around by simplifying the
- * control flow. When that is not practical, annotate the function containing
- * the code that triggers the warning with
- * OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS after its parameters:
- *
- * void f() OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS {
- * ...
- * }
- *
- * Note that MSVC's control flow analysis seems to operate on a whole-function
- * basis, so the annotation must be placed on the entire function, not just a
- * block within the function. */
-#if defined(_MSC_VER)
-#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS \
- __pragma(warning(suppress:4701))
-#else
-#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
-#endif
-
-/* MSVC will sometimes correctly detect unreachable code and issue a warning,
- * which breaks the build since we treat errors as warnings, in some rare cases
- * where we want to allow the dead code to continue to exist. In these
- * situations, annotate the function containing the unreachable code with
- * OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS after its parameters:
- *
- * void f() OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
- * ...
- * }
- *
- * Note that MSVC's reachability analysis seems to operate on a whole-function
- * basis, so the annotation must be placed on the entire function, not just a
- * block within the function. */
-#if defined(_MSC_VER)
-#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS \
- __pragma(warning(suppress:4702))
-#else
-#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS
-#endif
-
-
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \
defined(OPENSSL_AARCH64)
/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */
@@ -194,6 +152,19 @@ typedef __uint128_t uint128_t;
#endif
+/* buffers_alias returns one if |a| and |b| alias and zero otherwise. */
+static inline int buffers_alias(const uint8_t *a, size_t a_len,
+ const uint8_t *b, size_t b_len) {
+ /* Cast |a| and |b| to integers. In C, pointer comparisons between unrelated
+ * objects are undefined whereas pointer to integer conversions are merely
+ * implementation-defined. We assume the implementation defined it in a sane
+ * way. */
+ uintptr_t a_u = (uintptr_t)a;
+ uintptr_t b_u = (uintptr_t)b;
+ return a_u + a_len > b_u && b_u + b_len > a_u;
+}
+
+
/* Constant-time utility functions.
*
* The following methods return a bitmask of all ones (0xff...f) for true and 0
@@ -336,12 +307,22 @@ static inline int constant_time_select_int(unsigned int mask, int a, int b) {
/* Thread-safe initialisation. */
+/* Android's mingw-w64 has some prototypes for INIT_ONCE, but is missing
+ * others. Work around the missing ones.
+ *
+ * TODO(davidben): Remove this once Android's mingw-w64 is upgraded. See
+ * b/26523949. */
+#if defined(__MINGW32__) && !defined(INIT_ONCE_STATIC_INIT)
+typedef RTL_RUN_ONCE INIT_ONCE;
+#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT
+#endif
+
#if defined(OPENSSL_NO_THREADS)
typedef uint32_t CRYPTO_once_t;
#define CRYPTO_ONCE_INIT 0
#elif defined(OPENSSL_WINDOWS)
-typedef volatile LONG CRYPTO_once_t;
-#define CRYPTO_ONCE_INIT 0
+typedef INIT_ONCE CRYPTO_once_t;
+#define CRYPTO_ONCE_INIT INIT_ONCE_STATIC_INIT
#else
typedef pthread_once_t CRYPTO_once_t;
#define CRYPTO_ONCE_INIT PTHREAD_ONCE_INIT
@@ -387,22 +368,19 @@ OPENSSL_EXPORT int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count);
* |CRYPTO_STATIC_MUTEX_INIT|.
*
* |CRYPTO_MUTEX| can appear in public structures and so is defined in
- * thread.h.
- *
- * The global lock is a different type because there's no static initialiser
- * value on Windows for locks, so global locks have to be coupled with a
- * |CRYPTO_once_t| to ensure that the lock is setup before use. This is done
- * automatically by |CRYPTO_STATIC_MUTEX_lock_*|. */
+ * thread.h as a structure large enough to fit the real type. The global lock is
+ * a different type so it may be initialized with platform initializer macros.*/
#if defined(OPENSSL_NO_THREADS)
-struct CRYPTO_STATIC_MUTEX {};
-#define CRYPTO_STATIC_MUTEX_INIT {}
+struct CRYPTO_STATIC_MUTEX {
+ char padding; /* Empty structs have different sizes in C and C++. */
+};
+#define CRYPTO_STATIC_MUTEX_INIT { 0 }
#elif defined(OPENSSL_WINDOWS)
struct CRYPTO_STATIC_MUTEX {
- CRYPTO_once_t once;
- CRITICAL_SECTION lock;
+ SRWLOCK lock;
};
-#define CRYPTO_STATIC_MUTEX_INIT { CRYPTO_ONCE_INIT, { 0 } }
+#define CRYPTO_STATIC_MUTEX_INIT { SRWLOCK_INIT }
#else
struct CRYPTO_STATIC_MUTEX {
pthread_rwlock_t lock;
@@ -415,16 +393,18 @@ struct CRYPTO_STATIC_MUTEX {
OPENSSL_EXPORT void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock);
/* CRYPTO_MUTEX_lock_read locks |lock| such that other threads may also have a
- * read lock, but none may have a write lock. (On Windows, read locks are
- * actually fully exclusive.) */
+ * read lock, but none may have a write lock. */
OPENSSL_EXPORT void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock);
/* CRYPTO_MUTEX_lock_write locks |lock| such that no other thread has any type
* of lock on it. */
OPENSSL_EXPORT void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock);
-/* CRYPTO_MUTEX_unlock unlocks |lock|. */
-OPENSSL_EXPORT void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock);
+/* CRYPTO_MUTEX_unlock_read unlocks |lock| for reading. */
+OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_MUTEX_unlock_write unlocks |lock| for writing. */
+OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock);
/* CRYPTO_MUTEX_cleanup releases all resources held by |lock|. */
OPENSSL_EXPORT void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock);
@@ -443,8 +423,12 @@ OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_read(
OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_write(
struct CRYPTO_STATIC_MUTEX *lock);
-/* CRYPTO_STATIC_MUTEX_unlock unlocks |lock|. */
-OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock(
+/* CRYPTO_STATIC_MUTEX_unlock_read unlocks |lock| for reading. */
+OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_read(
+ struct CRYPTO_STATIC_MUTEX *lock);
+
+/* CRYPTO_STATIC_MUTEX_unlock_write unlocks |lock| for writing. */
+OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_write(
struct CRYPTO_STATIC_MUTEX *lock);
diff --git a/crypto/lhash/lhash_test.c b/crypto/lhash/lhash_test.c
index 63748e73..309b765d 100644
--- a/crypto/lhash/lhash_test.c
+++ b/crypto/lhash/lhash_test.c
@@ -152,7 +152,11 @@ int main(int argc, char **argv) {
case 1:
s = rand_string();
lh_insert(lh, (void **)&s1, s);
+#if defined(OPENSSL_WINDOWS)
+ dummy_lh_insert(&dummy_lh, &s2, _strdup(s));
+#else
dummy_lh_insert(&dummy_lh, &s2, strdup(s));
+#endif
if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
fprintf(stderr, "lh_insert failure\n");
diff --git a/crypto/md4/md4.c b/crypto/md4/md4.c
index 86a540b4..f79da9fd 100644
--- a/crypto/md4/md4.c
+++ b/crypto/md4/md4.c
@@ -60,6 +60,15 @@
#include <string.h>
+uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out) {
+ MD4_CTX ctx;
+ MD4_Init(&ctx);
+ MD4_Update(&ctx, data, len);
+ MD4_Final(out, &ctx);
+
+ return out;
+}
+
/* Implemented from RFC1186 The MD4 Message-Digest Algorithm. */
int MD4_Init(MD4_CTX *md4) {
diff --git a/crypto/mem.c b/crypto/mem.c
index df8e0e33..527edd93 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -66,9 +66,17 @@
#include <string.h>
#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+
+/* Work around a clang-cl bug: SecureZeroMemory() below uses __stosb() but
+ * windows.h only declares that intrinsic and then uses `#pragma intrinsic` for
+ * it. clang-cl doesn't implement `#pragma intrinsic` yet; it instead defines
+ * the function as an always-inline symbol in its intrin.h.
+ * TODO(thakis): Remove this once http://llvm.org/PR19898 is fixed.
+ */
+#include <intrin.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
#else
#include <strings.h>
#endif
@@ -118,12 +126,11 @@ void OPENSSL_cleanse(void *ptr, size_t len) {
}
int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) {
- size_t i;
const uint8_t *a = in_a;
const uint8_t *b = in_b;
uint8_t x = 0;
- for (i = 0; i < len; i++) {
+ for (size_t i = 0; i < len; i++) {
x |= a[i] ^ b[i];
}
@@ -147,8 +154,6 @@ uint32_t OPENSSL_hash32(const void *ptr, size_t len) {
return h;
}
-char *OPENSSL_strdup(const char *s) { return strdup(s); }
-
size_t OPENSSL_strnlen(const char *s, size_t len) {
size_t i;
@@ -163,6 +168,8 @@ size_t OPENSSL_strnlen(const char *s, size_t len) {
#if defined(OPENSSL_WINDOWS)
+char *OPENSSL_strdup(const char *s) { return _strdup(s); }
+
int OPENSSL_strcasecmp(const char *a, const char *b) {
return _stricmp(a, b);
}
@@ -173,6 +180,8 @@ int OPENSSL_strncasecmp(const char *a, const char *b, size_t n) {
#else
+char *OPENSSL_strdup(const char *s) { return strdup(s); }
+
int OPENSSL_strcasecmp(const char *a, const char *b) {
return strcasecmp(a, b);
}
diff --git a/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/modes/asm/aesni-gcm-x86_64.pl
index 26135e6c..5d58bbbb 100644
--- a/crypto/modes/asm/aesni-gcm-x86_64.pl
+++ b/crypto/modes/asm/aesni-gcm-x86_64.pl
@@ -41,11 +41,12 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
+# This must be kept in sync with |$avx| in ghash-x86_64.pl; otherwise tags will
+# be computed incorrectly.
+#
# In upstream, this is controlled by shelling out to the compiler to check
# versions, but BoringSSL is intended to be used with pre-generated perlasm
# output, so this isn't useful anyway.
-#
-# TODO(davidben): Enable this after testing. $avx goes up to 2.
$avx = 0;
open OUT,"| \"$^X\" $xlate $flavour $output";
@@ -96,6 +97,23 @@ _aesni_ctr32_ghash_6x:
vpxor $rndkey,$inout3,$inout3
vmovups 0x10-0x80($key),$T2 # borrow $T2 for $rndkey
vpclmulqdq \$0x01,$Hkey,$Z3,$Z2
+
+ # At this point, the current block of 96 (0x60) bytes has already been
+ # loaded into registers. Concurrently with processing it, we want to
+ # load the next 96 bytes of input for the next round. Obviously, we can
+ # only do this if there are at least 96 more bytes of input beyond the
+ # input we're currently processing, or else we'd read past the end of
+ # the input buffer. Here, we set |%r12| to 96 if there are at least 96
+ # bytes of input beyond the 96 bytes we're already processing, and we
+ # set |%r12| to 0 otherwise. In the case where we set |%r12| to 96,
+ # we'll read in the next block so that it is in registers for the next
+ # loop iteration. In the case where we set |%r12| to 0, we'll re-read
+ # the current block and then ignore what we re-read.
+ #
+ # At this point, |$in0| points to the current (already read into
+ # registers) block, and |$end0| points to 2*96 bytes before the end of
+ # the input. Thus, |$in0| > |$end0| means that we do not have the next
+ # 96-byte block to read in, and |$in0| <= |$end0| means we do.
xor %r12,%r12
cmp $in0,$end0
@@ -388,6 +406,9 @@ $code.=<<___;
.align 32
aesni_gcm_decrypt:
xor $ret,$ret
+
+ # We call |_aesni_ctr32_ghash_6x|, which requires at least 96 (0x60)
+ # bytes of input.
cmp \$0x60,$len # minimal accepted length
jb .Lgcm_dec_abort
@@ -442,7 +463,15 @@ $code.=<<___;
vmovdqu 0x50($inp),$Z3 # I[5]
lea ($inp),$in0
vmovdqu 0x40($inp),$Z0
+
+ # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0)
+ # bytes before the end of the input. Note, in particular, that this is
+ # correct even if |$len| is not an even multiple of 96 or 16. XXX: This
+ # seems to require that |$inp| + |$len| >= 2*96 (0xc0); i.e. |$inp| must
+ # not be near the very beginning of the address space when |$len| < 2*96
+ # (0xc0).
lea -0xc0($inp,$len),$end0
+
vmovdqu 0x30($inp),$Z1
shr \$4,$len
xor $ret,$ret
@@ -598,6 +627,10 @@ _aesni_ctr32_6x:
.align 32
aesni_gcm_encrypt:
xor $ret,$ret
+
+ # We call |_aesni_ctr32_6x| twice, each call consuming 96 bytes of
+ # input. Then we call |_aesni_ctr32_ghash_6x|, which requires at
+ # least 96 more bytes of input.
cmp \$0x60*3,$len # minimal accepted length
jb .Lgcm_enc_abort
@@ -647,7 +680,16 @@ $code.=<<___;
.Lenc_no_key_aliasing:
lea ($out),$in0
+
+ # |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0)
+ # bytes before the end of the input. Note, in particular, that this is
+ # correct even if |$len| is not an even multiple of 96 or 16. Unlike in
+ # the decryption case, there's no caveat that |$out| must not be near
+ # the very beginning of the address space, because we know that
+ # |$len| >= 3*96 from the check above, and so we know
+ # |$out| + |$len| >= 2*96 (0xc0).
lea -0xc0($out,$len),$end0
+
shr \$4,$len
call _aesni_ctr32_6x
diff --git a/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl
index e42ca321..5a11fb94 100644
--- a/crypto/modes/asm/ghash-x86_64.pl
+++ b/crypto/modes/asm/ghash-x86_64.pl
@@ -90,11 +90,12 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
+# This must be kept in sync with |$avx| in aesni-gcm-x86_64.pl; otherwise tags
+# will be computed incorrectly.
+#
# In upstream, this is controlled by shelling out to the compiler to check
# versions, but BoringSSL is intended to be used with pre-generated perlasm
# output, so this isn't useful anyway.
-#
-# TODO(davidben): Enable this after testing. $avx goes up to 2.
$avx = 0;
open OUT,"| \"$^X\" $xlate $flavour $output";
diff --git a/crypto/modes/cfb.c b/crypto/modes/cfb.c
index c58614ba..51b883e8 100644
--- a/crypto/modes/cfb.c
+++ b/crypto/modes/cfb.c
@@ -57,14 +57,13 @@
OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size);
void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num, int enc,
- block128_f block) {
- unsigned int n;
+ const void *key, uint8_t ivec[16], unsigned *num,
+ int enc, block128_f block) {
size_t l = 0;
assert(in && out && key && ivec && num);
- n = *num;
+ unsigned n = *num;
if (enc) {
while (n && len) {
@@ -199,7 +198,7 @@ static void cfbr_encrypt_block(const uint8_t *in, uint8_t *out, unsigned nbits,
/* N.B. This expects the input to be packed, MS bit first */
void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block) {
size_t n;
uint8_t c[1], d[1];
@@ -217,7 +216,7 @@ void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const void *key,
- unsigned char ivec[16], int *num, int enc,
+ unsigned char ivec[16], unsigned *num, int enc,
block128_f block) {
size_t n;
diff --git a/crypto/modes/ctr.c b/crypto/modes/ctr.c
index 0baed5d4..b84e72c5 100644
--- a/crypto/modes/ctr.c
+++ b/crypto/modes/ctr.c
@@ -59,17 +59,13 @@
/* increment counter (128-bit int) by 1 */
static void ctr128_inc(uint8_t *counter) {
- uint32_t n = 16;
- uint8_t c;
+ uint32_t n = 16, c = 1;
do {
--n;
- c = counter[n];
- ++c;
- counter[n] = c;
- if (c) {
- return;
- }
+ c += counter[n];
+ counter[n] = (uint8_t) c;
+ c >>= 8;
} while (n);
}
@@ -104,7 +100,7 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
}
#if STRICT_ALIGNMENT
- if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ if (((size_t)in | (size_t)out | (size_t)ecount_buf) % sizeof(size_t) != 0) {
size_t l = 0;
while (l < len) {
if (n == 0) {
@@ -124,7 +120,7 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
while (len >= 16) {
(*block)(ivec, ecount_buf, key);
ctr128_inc(ivec);
- for (; n < 16; n += sizeof(size_t)) {
+ for (n = 0; n < 16; n += sizeof(size_t)) {
*(size_t *)(out + n) = *(const size_t *)(in + n) ^
*(const size_t *)(ecount_buf + n);
}
@@ -146,17 +142,13 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
/* increment upper 96 bits of 128-bit counter by 1 */
static void ctr96_inc(uint8_t *counter) {
- uint32_t n = 12;
- uint8_t c;
+ uint32_t n = 12, c = 1;
do {
--n;
- c = counter[n];
- ++c;
- counter[n] = c;
- if (c) {
- return;
- }
+ c += counter[n];
+ counter[n] = (uint8_t) c;
+ c >>= 8;
} while (n);
}
diff --git a/crypto/modes/gcm.c b/crypto/modes/gcm.c
index 8cc138dc..b8571313 100644
--- a/crypto/modes/gcm.c
+++ b/crypto/modes/gcm.c
@@ -55,6 +55,7 @@
#include <openssl/cpu.h>
#include "internal.h"
+#include "../internal.h"
#if !defined(OPENSSL_NO_ASM) && \
@@ -337,7 +338,18 @@ void gcm_ghash_clmul(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
#else
void gcm_init_avx(u128 Htable[16], const uint64_t Xi[2]);
void gcm_gmult_avx(uint64_t Xi[2], const u128 Htable[16]);
-void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, size_t len);
+void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
+ size_t len);
+#define AESNI_GCM
+static int aesni_gcm_enabled(GCM128_CONTEXT *ctx, ctr128_f stream) {
+ return stream == aesni_ctr32_encrypt_blocks &&
+ ctx->ghash == gcm_ghash_avx;
+}
+
+size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], uint64_t *Xi);
+size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], uint64_t *Xi);
#endif
#if defined(OPENSSL_X86)
@@ -380,14 +392,14 @@ void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
static int neon_capable(void) {
return 0;
}
-void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) {
+static void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) {
abort();
}
-void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) {
+static void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) {
abort();
}
-void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
- size_t len) {
+static void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16],
+ const uint8_t *inp, size_t len) {
abort();
}
#endif
@@ -405,17 +417,6 @@ void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
#endif
#endif
-GCM128_CONTEXT *CRYPTO_gcm128_new(const void *key, block128_f block) {
- GCM128_CONTEXT *ret;
-
- ret = OPENSSL_malloc(sizeof(GCM128_CONTEXT));
- if (ret != NULL) {
- CRYPTO_gcm128_init(ret, key, block);
- }
-
- return ret;
-}
-
void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key,
block128_f block) {
const union {
@@ -991,12 +992,6 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
ctx->ares = 0;
}
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
-
n = ctx->mres;
if (n) {
while (n && len) {
@@ -1011,6 +1006,24 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
return 1;
}
}
+
+#if defined(AESNI_GCM)
+ if (aesni_gcm_enabled(ctx, stream)) {
+ /* |aesni_gcm_encrypt| may not process all the input given to it. It may
+ * not process *any* of its input if it is deemed too small. */
+ size_t bulk = aesni_gcm_encrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u);
+ in += bulk;
+ out += bulk;
+ len -= bulk;
+ }
+#endif
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = ctx->Yi.d[3];
+ }
+
#if defined(GHASH)
while (len >= GHASH_CHUNK) {
(*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
@@ -1100,12 +1113,6 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
ctx->ares = 0;
}
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
-
n = ctx->mres;
if (n) {
while (n && len) {
@@ -1122,6 +1129,24 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
return 1;
}
}
+
+#if defined(AESNI_GCM)
+ if (aesni_gcm_enabled(ctx, stream)) {
+ /* |aesni_gcm_decrypt| may not process all the input given to it. It may
+ * not process *any* of its input if it is deemed too small. */
+ size_t bulk = aesni_gcm_decrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u);
+ in += bulk;
+ out += bulk;
+ len -= bulk;
+ }
+#endif
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = ctx->Yi.d[3];
+ }
+
#if defined(GHASH)
while (len >= GHASH_CHUNK) {
GHASH(ctx, in, GHASH_CHUNK);
@@ -1235,13 +1260,6 @@ void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len) {
memcpy(tag, ctx->Xi.c, len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c));
}
-void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx) {
- if (ctx) {
- OPENSSL_cleanse(ctx, sizeof(*ctx));
- OPENSSL_free(ctx);
- }
-}
-
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
int crypto_gcm_clmul_enabled(void) {
#ifdef GHASH_ASM
diff --git a/crypto/modes/gcm_test.c b/crypto/modes/gcm_test.c
index 9414ac6e..19c295b5 100644
--- a/crypto/modes/gcm_test.c
+++ b/crypto/modes/gcm_test.c
@@ -282,8 +282,8 @@ static int decode_hex(uint8_t **out, size_t *out_len, const char *in,
uint8_t v, v2;
if (!from_hex(&v, in[i]) ||
!from_hex(&v2, in[i+1])) {
- fprintf(stderr, "%u: invalid hex digit in %s around offset %u.\n",
- test_num, description, (unsigned)i);
+ fprintf(stderr, "%u: invalid hex digit in %s around offset %zu.\n",
+ test_num, description, i);
goto err;
}
buf[i/2] = (v << 4) | v2;
@@ -336,7 +336,7 @@ static int run_test_case(unsigned test_num, const struct test_case *test) {
}
out = OPENSSL_malloc(plaintext_len);
- if (out == NULL) {
+ if (plaintext_len != 0 && out == NULL) {
goto out;
}
if (AES_set_encrypt_key(key, key_len*8, &aes_key)) {
diff --git a/crypto/modes/internal.h b/crypto/modes/internal.h
index 7255a7ca..430d0401 100644
--- a/crypto/modes/internal.h
+++ b/crypto/modes/internal.h
@@ -121,9 +121,9 @@ extern "C" {
#endif
#elif defined(_MSC_VER)
#if _MSC_VER >= 1300
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <intrin.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
#define BSWAP8(x) _byteswap_uint64((uint64_t)(x))
#define BSWAP4(x) _byteswap_ulong((uint32_t)(x))
@@ -179,16 +179,6 @@ struct gcm128_context {
block128_f block;
};
-struct ccm128_context {
- union {
- uint64_t u[2];
- uint8_t c[16];
- } nonce, cmac;
- uint64_t blocks;
- block128_f block;
- void *key;
-};
-
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
/* crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is
* used. */
@@ -210,7 +200,7 @@ typedef void (*ctr128_f)(const uint8_t *in, uint8_t *out, size_t blocks,
* incremented by this function. */
void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const void *key, uint8_t ivec[16],
- uint8_t ecount_buf[16], unsigned int *num,
+ uint8_t ecount_buf[16], unsigned *num,
block128_f block);
/* CRYPTO_ctr128_encrypt_ctr32 acts like |CRYPTO_ctr128_encrypt| but takes
@@ -219,7 +209,7 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
* function. */
void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
const void *key, uint8_t ivec[16],
- uint8_t ecount_buf[16], unsigned int *num,
+ uint8_t ecount_buf[16], unsigned *num,
ctr128_f ctr);
@@ -232,11 +222,6 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
typedef struct gcm128_context GCM128_CONTEXT;
-/* CRYPTO_gcm128_new allocates a fresh |GCM128_CONTEXT| and calls
- * |CRYPTO_gcm128_init|. It returns the new context, or NULL on error. */
-OPENSSL_EXPORT GCM128_CONTEXT *CRYPTO_gcm128_new(const void *key,
- block128_f block);
-
/* CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with
* the given key. */
OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key,
@@ -297,9 +282,6 @@ OPENSSL_EXPORT int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag,
OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag,
size_t len);
-/* CRYPTO_gcm128_release clears and frees |ctx|. */
-OPENSSL_EXPORT void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx);
-
/* CBC. */
@@ -331,7 +313,7 @@ void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
* call. */
void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out,
size_t len, const void *key, uint8_t ivec[16],
- int *num, block128_f block);
+ unsigned *num, block128_f block);
/* CFB. */
@@ -341,21 +323,21 @@ void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out,
* |len| be a multiple of any value and any partial blocks are stored in |ivec|
* and |*num|, the latter must be zero before the initial call. */
void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num, int enc,
- block128_f block);
+ const void *key, uint8_t ivec[16], unsigned *num,
+ int enc, block128_f block);
/* CRYPTO_cfb128_8_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
* from |in| to |out| using |block| in CFB-8 mode. Prior to the first call
* |num| should be set to zero. */
void CRYPTO_cfb128_8_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block);
/* CRYPTO_cfb128_1_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
* from |in| to |out| using |block| in CFB-1 mode. Prior to the first call
* |num| should be set to zero. */
void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block);
size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len,
@@ -363,6 +345,12 @@ size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len,
block128_f block);
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
+ const void *key, const uint8_t *ivec);
+#endif
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/crypto/modes/ofb.c b/crypto/modes/ofb.c
index 63c3165a..2c5bdc9a 100644
--- a/crypto/modes/ofb.c
+++ b/crypto/modes/ofb.c
@@ -56,13 +56,11 @@
OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size);
void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int *num,
+ const void *key, uint8_t ivec[16], unsigned *num,
block128_f block) {
- unsigned int n;
-
assert(in && out && key && ivec && num);
- n = *num;
+ unsigned n = *num;
while (n && len) {
*(out++) = *(in++) ^ ivec[n];
diff --git a/crypto/newhope/CMakeLists.txt b/crypto/newhope/CMakeLists.txt
new file mode 100644
index 00000000..0f080f8c
--- /dev/null
+++ b/crypto/newhope/CMakeLists.txt
@@ -0,0 +1,42 @@
+add_library(
+ newhope
+
+ OBJECT
+
+ error_correction.c
+ newhope.c
+ ntt.c
+ poly.c
+ precomp.c
+ reduce.c
+)
+
+if(ENABLE_TESTS)
+add_executable(
+ newhope_test
+
+ newhope_test.cc
+ $<TARGET_OBJECTS:test_support>
+)
+
+add_executable(
+ newhope_statistical_test
+
+ newhope_statistical_test.cc
+ $<TARGET_OBJECTS:test_support>
+)
+
+add_executable(
+ newhope_vectors_test
+
+ newhope_vectors_test.cc
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(newhope_test crypto)
+target_link_libraries(newhope_statistical_test crypto)
+target_link_libraries(newhope_vectors_test crypto)
+add_dependencies(all_tests newhope_test)
+add_dependencies(all_tests newhope_statistical_test)
+add_dependencies(all_tests newhope_vectors_test)
+endif()
diff --git a/crypto/newhope/error_correction.c b/crypto/newhope/error_correction.c
new file mode 100644
index 00000000..2b822b0b
--- /dev/null
+++ b/crypto/newhope/error_correction.c
@@ -0,0 +1,131 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string.h>
+
+#include <openssl/base.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+
+
+/* See paper for details on the error reconciliation */
+
+static int32_t abs_32(int32_t v) {
+ int32_t mask = v >> 31;
+ return (v ^ mask) - mask;
+}
+
+static int32_t f(int32_t* v0, int32_t* v1, int32_t x) {
+ int32_t xit, t, r, b;
+
+ /* Next 6 lines compute t = x/PARAM_Q */
+ b = x * 2730;
+ t = b >> 25;
+ b = x - t * 12289;
+ b = 12288 - b;
+ b >>= 31;
+ t -= b;
+
+ r = t & 1;
+ xit = (t >> 1);
+ *v0 = xit + r; /* v0 = round(x/(2*PARAM_Q)) */
+
+ t -= 1;
+ r = t & 1;
+ *v1 = (t >> 1) + r;
+
+ return abs_32(x - ((*v0) * 2 * PARAM_Q));
+}
+
+static int32_t g(int32_t x) {
+ int32_t t, c, b;
+
+ /* Next 6 lines compute t = x/(4*PARAM_Q); */
+ b = x * 2730;
+ t = b >> 27;
+ b = x - t * 49156;
+ b = 49155 - b;
+ b >>= 31;
+ t -= b;
+
+ c = t & 1;
+ t = (t >> 1) + c; /* t = round(x/(8*PARAM_Q)) */
+
+ t *= 8 * PARAM_Q;
+
+ return abs_32(t - x);
+}
+
+static int16_t LDDecode(int32_t xi0, int32_t xi1, int32_t xi2, int32_t xi3) {
+ int32_t t;
+
+ t = g(xi0);
+ t += g(xi1);
+ t += g(xi2);
+ t += g(xi3);
+
+ t -= 8 * PARAM_Q;
+ t >>= 31;
+ return t & 1;
+}
+
+void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v,
+ const uint8_t rand[32]) {
+ int32_t v0[4], v1[4], v_tmp[4], k;
+ uint8_t rbit;
+ unsigned i;
+
+ for (i = 0; i < 256; i++) {
+ rbit = (rand[i >> 3] >> (i & 7)) & 1;
+
+ k = f(v0 + 0, v1 + 0, 8 * v->coeffs[0 + i] + 4 * rbit);
+ k += f(v0 + 1, v1 + 1, 8 * v->coeffs[256 + i] + 4 * rbit);
+ k += f(v0 + 2, v1 + 2, 8 * v->coeffs[512 + i] + 4 * rbit);
+ k += f(v0 + 3, v1 + 3, 8 * v->coeffs[768 + i] + 4 * rbit);
+
+ k = (2 * PARAM_Q - 1 - k) >> 31;
+
+ v_tmp[0] = ((~k) & v0[0]) ^ (k & v1[0]);
+ v_tmp[1] = ((~k) & v0[1]) ^ (k & v1[1]);
+ v_tmp[2] = ((~k) & v0[2]) ^ (k & v1[2]);
+ v_tmp[3] = ((~k) & v0[3]) ^ (k & v1[3]);
+
+ c->coeffs[0 + i] = (v_tmp[0] - v_tmp[3]) & 3;
+ c->coeffs[256 + i] = (v_tmp[1] - v_tmp[3]) & 3;
+ c->coeffs[512 + i] = (v_tmp[2] - v_tmp[3]) & 3;
+ c->coeffs[768 + i] = (-k + 2 * v_tmp[3]) & 3;
+ }
+}
+
+void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v,
+ const NEWHOPE_POLY* c) {
+ int i;
+ int32_t tmp[4];
+
+ memset(key, 0, NEWHOPE_KEY_LENGTH);
+
+ for (i = 0; i < 256; i++) {
+ tmp[0] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[0 + i] -
+ PARAM_Q * (2 * c->coeffs[0 + i] + c->coeffs[768 + i]);
+ tmp[1] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[256 + i] -
+ PARAM_Q * (2 * c->coeffs[256 + i] + c->coeffs[768 + i]);
+ tmp[2] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[512 + i] -
+ PARAM_Q * (2 * c->coeffs[512 + i] + c->coeffs[768 + i]);
+ tmp[3] = 16 * PARAM_Q + 8 * (int32_t)v->coeffs[768 + i] -
+ PARAM_Q * (c->coeffs[768 + i]);
+
+ key[i >> 3] |= LDDecode(tmp[0], tmp[1], tmp[2], tmp[3]) << (i & 7);
+ }
+}
diff --git a/crypto/newhope/internal.h b/crypto/newhope/internal.h
new file mode 100644
index 00000000..eb170c06
--- /dev/null
+++ b/crypto/newhope/internal.h
@@ -0,0 +1,71 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_NEWHOPE_INTERNAL_H
+#define OPENSSL_HEADER_NEWHOPE_INTERNAL_H
+
+#include <openssl/newhope.h>
+#include <openssl/sha.h>
+
+#include "../internal.h"
+
+
+/* The number of polynomial coefficients. */
+#define PARAM_N 1024
+
+/* The width the noise distribution. */
+#define PARAM_K 16
+
+/* Modulus. */
+#define PARAM_Q 12289
+
+/* Polynomial coefficients in unpacked form. */
+struct newhope_poly_st {
+ uint16_t coeffs[PARAM_N];
+};
+
+/* SEED_LENGTH is the length of the AES-CTR seed used to derive a polynomial. */
+#define SEED_LENGTH 32
+
+/* newhope_poly_uniform generates the polynomial |a| using AES-CTR mode with the
+ * seed
+ * |seed|. (In the reference implementation this was done with SHAKE-128.) */
+void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed);
+
+void newhope_helprec(NEWHOPE_POLY* c, const NEWHOPE_POLY* v,
+ const uint8_t rbits[32]);
+
+/* newhope_reconcile performs the error-reconciliation step using the input |v|
+ * and
+ * reconciliation data |c|, writing the resulting key to |key|. */
+void newhope_reconcile(uint8_t* key, const NEWHOPE_POLY* v,
+ const NEWHOPE_POLY* c);
+
+/* newhope_poly_invntt performs the inverse of NTT(r) in-place. */
+void newhope_poly_invntt(NEWHOPE_POLY* r);
+
+void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b);
+void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b);
+
+uint16_t newhope_montgomery_reduce(uint32_t a);
+uint16_t newhope_barrett_reduce(uint16_t a);
+
+void newhope_bitrev_vector(uint16_t* poly);
+void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors);
+void newhope_ntt(uint16_t* poly, const uint16_t* omegas);
+
+
+#endif /* OPENSSL_HEADER_NEWHOPE_INTERNAL_H */
diff --git a/crypto/newhope/newhope.c b/crypto/newhope/newhope.c
new file mode 100644
index 00000000..7edb7eb7
--- /dev/null
+++ b/crypto/newhope/newhope.c
@@ -0,0 +1,174 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+
+
+NEWHOPE_POLY *NEWHOPE_POLY_new(void) {
+ return (NEWHOPE_POLY *)OPENSSL_malloc(sizeof(NEWHOPE_POLY));
+}
+
+void NEWHOPE_POLY_free(NEWHOPE_POLY *p) { OPENSSL_free(p); }
+
+/* Encodes reconciliation data from |c| into |r|. */
+static void encode_rec(const NEWHOPE_POLY *c, uint8_t *r) {
+ int i;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ r[i] = c->coeffs[4 * i] | (c->coeffs[4 * i + 1] << 2) |
+ (c->coeffs[4 * i + 2] << 4) | (c->coeffs[4 * i + 3] << 6);
+ }
+}
+
+/* Decodes reconciliation data from |r| into |c|. */
+static void decode_rec(const uint8_t *r, NEWHOPE_POLY *c) {
+ int i;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ c->coeffs[4 * i + 0] = r[i] & 0x03;
+ c->coeffs[4 * i + 1] = (r[i] >> 2) & 0x03;
+ c->coeffs[4 * i + 2] = (r[i] >> 4) & 0x03;
+ c->coeffs[4 * i + 3] = (r[i] >> 6);
+ }
+}
+
+void NEWHOPE_offer(uint8_t *offermsg, NEWHOPE_POLY *s) {
+ NEWHOPE_POLY_noise_ntt(s);
+
+ /* The first part of the offer message is the seed, which compactly encodes
+ * a. */
+ NEWHOPE_POLY a;
+ uint8_t *seed = &offermsg[NEWHOPE_POLY_LENGTH];
+ RAND_bytes(seed, SEED_LENGTH);
+ newhope_poly_uniform(&a, seed);
+
+ NEWHOPE_POLY e;
+ NEWHOPE_POLY_noise_ntt(&e);
+
+ /* The second part of the offer message is the polynomial pk = a*s+e */
+ NEWHOPE_POLY pk;
+ NEWHOPE_offer_computation(&pk, s, &e, &a);
+ NEWHOPE_POLY_tobytes(offermsg, &pk);
+}
+
+int NEWHOPE_accept(uint8_t key[SHA256_DIGEST_LENGTH],
+ uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH],
+ const uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH],
+ size_t msg_len) {
+ if (msg_len != NEWHOPE_OFFERMSG_LENGTH) {
+ return 0;
+ }
+
+ /* Decode the |offermsg|, generating the same |a| as the peer, from the peer's
+ * seed. */
+ NEWHOPE_POLY pk, a;
+ NEWHOPE_offer_frommsg(&pk, &a, offermsg);
+
+ /* Generate noise polynomials used to generate our key. */
+ NEWHOPE_POLY sp, ep, epp;
+ NEWHOPE_POLY_noise_ntt(&sp);
+ NEWHOPE_POLY_noise_ntt(&ep);
+ NEWHOPE_POLY_noise(&epp); /* intentionally not NTT */
+
+ /* Generate random bytes used for reconciliation. (The reference
+ * implementation calls ChaCha20 here.) */
+ uint8_t rand[32];
+ RAND_bytes(rand, sizeof(rand));
+
+ /* Encode |bp| and |c| as the |acceptmsg|. */
+ NEWHOPE_POLY bp, c;
+ uint8_t k[NEWHOPE_KEY_LENGTH];
+ NEWHOPE_accept_computation(k, &bp, &c, &sp, &ep, &epp, rand, &pk, &a);
+ NEWHOPE_POLY_tobytes(acceptmsg, &bp);
+ encode_rec(&c, &acceptmsg[NEWHOPE_POLY_LENGTH]);
+
+ SHA256_CTX ctx;
+ if (!SHA256_Init(&ctx) ||
+ !SHA256_Update(&ctx, k, NEWHOPE_KEY_LENGTH) ||
+ !SHA256_Final(key, &ctx)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int NEWHOPE_finish(uint8_t key[SHA256_DIGEST_LENGTH], const NEWHOPE_POLY *sk,
+ const uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH],
+ size_t msg_len) {
+ if (msg_len != NEWHOPE_ACCEPTMSG_LENGTH) {
+ return 0;
+ }
+
+ /* Decode the accept message into |bp| and |c|. */
+ NEWHOPE_POLY bp, c;
+ NEWHOPE_POLY_frombytes(&bp, acceptmsg);
+ decode_rec(&acceptmsg[NEWHOPE_POLY_LENGTH], &c);
+
+ uint8_t k[NEWHOPE_KEY_LENGTH];
+ NEWHOPE_finish_computation(k, sk, &bp, &c);
+ SHA256_CTX ctx;
+ if (!SHA256_Init(&ctx) ||
+ !SHA256_Update(&ctx, k, NEWHOPE_KEY_LENGTH) ||
+ !SHA256_Final(key, &ctx)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+void NEWHOPE_offer_computation(NEWHOPE_POLY *out_pk,
+ const NEWHOPE_POLY *s, const NEWHOPE_POLY *e,
+ const NEWHOPE_POLY *a) {
+ NEWHOPE_POLY r;
+ newhope_poly_pointwise(&r, s, a);
+ newhope_poly_add(out_pk, e, &r);
+}
+
+void NEWHOPE_accept_computation(
+ uint8_t k[NEWHOPE_KEY_LENGTH], NEWHOPE_POLY *bp,
+ NEWHOPE_POLY *reconciliation,
+ const NEWHOPE_POLY *sp, const NEWHOPE_POLY *ep, const NEWHOPE_POLY *epp,
+ const uint8_t rand[32],
+ const NEWHOPE_POLY *pk, const NEWHOPE_POLY *a) {
+ /* bp = a*s' + e' */
+ newhope_poly_pointwise(bp, a, sp);
+ newhope_poly_add(bp, bp, ep);
+
+ /* v = pk * s' + e'' */
+ NEWHOPE_POLY v;
+ newhope_poly_pointwise(&v, pk, sp);
+ newhope_poly_invntt(&v);
+ newhope_poly_add(&v, &v, epp);
+ newhope_helprec(reconciliation, &v, rand);
+ newhope_reconcile(k, &v, reconciliation);
+}
+
+void NEWHOPE_finish_computation(uint8_t k[NEWHOPE_KEY_LENGTH],
+ const NEWHOPE_POLY *sk, const NEWHOPE_POLY *bp,
+ const NEWHOPE_POLY *reconciliation) {
+ NEWHOPE_POLY v;
+ newhope_poly_pointwise(&v, sk, bp);
+ newhope_poly_invntt(&v);
+ newhope_reconcile(k, &v, reconciliation);
+}
+
+void NEWHOPE_offer_frommsg(NEWHOPE_POLY *out_pk, NEWHOPE_POLY *out_a,
+ const uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH]) {
+ NEWHOPE_POLY_frombytes(out_pk, offermsg);
+ const uint8_t *seed = offermsg + NEWHOPE_POLY_LENGTH;
+ newhope_poly_uniform(out_a, seed);
+}
diff --git a/crypto/newhope/newhope_statistical_test.cc b/crypto/newhope/newhope_statistical_test.cc
new file mode 100644
index 00000000..44fac48a
--- /dev/null
+++ b/crypto/newhope/newhope_statistical_test.cc
@@ -0,0 +1,156 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string>
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+
+#include "../test/scoped_types.h"
+#include "internal.h"
+
+
+static const unsigned kNumTests = 1000;
+
+static bool TestNoise(void) {
+ printf("noise distribution:\n");
+
+ size_t buckets[1 + 2 * PARAM_K];
+ memset(buckets, 0, sizeof(buckets));
+ for (size_t i = 0; i < kNumTests; i++) {
+ NEWHOPE_POLY s;
+ NEWHOPE_POLY_noise(&s);
+ for (int j = 0; j < PARAM_N; j++) {
+ uint16_t value = (s.coeffs[j] + PARAM_K) % PARAM_Q;
+ buckets[value]++;
+ }
+ }
+
+ int64_t sum = 0, square_sum = 0;
+ for (int64_t i = 0; i < 1 + 2 * PARAM_K; i++) {
+ sum += (i - PARAM_K) * (int64_t) buckets[i];
+ square_sum += (i - PARAM_K) * (i - PARAM_K) * (int64_t) buckets[i];
+ }
+ double mean = double(sum) / double(PARAM_N * kNumTests);
+
+ double expected_variance = 0.5 * 0.5 * double(PARAM_K * 2);
+ double variance = double(square_sum) / double(PARAM_N * kNumTests) - mean * mean;
+
+ for (size_t i = 0; i < 1 + 2 * PARAM_K; i++) {
+ std::string dots;
+ for (size_t j = 0; j < 79 * buckets[i] / buckets[PARAM_K]; j++) {
+ dots += "+";
+ }
+ printf("%+zd\t%zd\t%s\n", i - PARAM_K, buckets[i], dots.c_str());
+ }
+ printf("mean: got %f, want %f\n", mean, 0.0);
+ printf("variance: got %f, want %f\n", variance, expected_variance);
+ printf("\n");
+
+ if (mean < -0.5 || 0.5 < mean) {
+ fprintf(stderr, "mean out of range: %f\n", mean);
+ return false;
+ }
+
+ if (variance < expected_variance - 1.0 || expected_variance + 1.0 < variance) {
+ fprintf(stderr, "variance out of range: got %f, want %f\n", variance,
+ expected_variance);
+ return false;
+ }
+ return true;
+}
+
+static int Hamming32(const uint8_t key[NEWHOPE_KEY_LENGTH]) {
+ static int kHamming[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+ };
+
+ int r = 0;
+ for(int i = 0; i < NEWHOPE_KEY_LENGTH; i++) {
+ r += kHamming[key[i]];
+ }
+ return r;
+}
+
+static bool TestKeys(void) {
+ printf("keys (prior to whitening):\n");
+
+ uint8_t key[NEWHOPE_KEY_LENGTH];
+ uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH];
+
+ ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new()), pk(NEWHOPE_POLY_new()),
+ sp(NEWHOPE_POLY_new()), ep(NEWHOPE_POLY_new()), epp(NEWHOPE_POLY_new()),
+ a(NEWHOPE_POLY_new()), bp(NEWHOPE_POLY_new()), rec(NEWHOPE_POLY_new());
+
+ int ones = 0;
+ for (size_t i = 0; i < kNumTests; i++) {
+ NEWHOPE_offer(offermsg, sk.get());
+ NEWHOPE_offer_frommsg(pk.get(), a.get(), offermsg);
+
+ NEWHOPE_POLY_noise_ntt(sp.get());
+ NEWHOPE_POLY_noise_ntt(ep.get());
+ NEWHOPE_POLY_noise(epp.get()); /* intentionally not NTT */
+
+ uint8_t rand[32];
+ RAND_bytes(rand, 32);
+
+ NEWHOPE_accept_computation(key, bp.get(), rec.get(),
+ sp.get(), ep.get(), epp.get(), rand,
+ pk.get(), a.get());
+ ones += Hamming32(key);
+ }
+
+ int bits = NEWHOPE_KEY_LENGTH * 8 * kNumTests;
+ int diff = bits - 2 * ones;
+ double fraction = (double) abs(diff) / bits;
+ printf("ones: %d\n", ones);
+ printf("zeroes: %d\n", (bits - ones));
+ printf("diff: got %d (%f), want 0\n", diff, fraction);
+ printf("\n");
+
+ if (fraction > 0.01) {
+ fprintf(stderr, "key bias is too high (%f)\n", fraction);
+ return false;
+ }
+
+ return true;
+}
+
+int main(void) {
+ if (!TestKeys() ||
+ !TestNoise()) {
+ return 1;
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/crypto/newhope/newhope_test.cc b/crypto/newhope/newhope_test.cc
new file mode 100644
index 00000000..6637393f
--- /dev/null
+++ b/crypto/newhope/newhope_test.cc
@@ -0,0 +1,142 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+
+#include "../test/scoped_types.h"
+#include "internal.h"
+
+
+// Set to 10 for quick execution. Tested up to 1,000,000.
+static const int kNumTests = 10;
+
+static bool TestKeys(void) {
+ // Alice generates a public key.
+ ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new());
+ uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH];
+ NEWHOPE_offer(offer_msg, sk.get());
+
+ // Bob derives a secret key and creates a response.
+ uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH];
+ uint8_t accept_key[SHA256_DIGEST_LENGTH];
+ if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) {
+ fprintf(stderr, "ERROR accept key exchange failed\n");
+ return false;
+ }
+
+ // Alice uses Bob's response to get her secret key.
+ uint8_t offer_key[SHA256_DIGEST_LENGTH];
+ if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) {
+ fprintf(stderr, "ERROR finish key exchange failed\n");
+ return false;
+ }
+
+ if (memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH) != 0) {
+ fprintf(stderr, "ERROR keys did not agree\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestInvalidSK(void) {
+ // Alice generates a public key.
+ uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH];
+ ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new());
+ NEWHOPE_offer(offer_msg, sk.get());
+
+ // Bob derives a secret key and creates a response.
+ uint8_t accept_key[SHA256_DIGEST_LENGTH];
+ uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH];
+ if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) {
+ fprintf(stderr, "ERROR accept key exchange failed\n");
+ return false;
+ }
+
+ // Corrupt the secret key. It turns out that you need to corrupt a lot of
+ // bits to ensure that the key exchange always fails!
+ sk->coeffs[PARAM_N - 1] = 0;
+ sk->coeffs[PARAM_N - 2] = 0;
+ sk->coeffs[PARAM_N - 3] = 0;
+ sk->coeffs[PARAM_N - 4] = 0;
+
+ // Alice uses Bob's response to get her secret key.
+ uint8_t offer_key[SHA256_DIGEST_LENGTH];
+ if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) {
+ fprintf(stderr, "ERROR finish key exchange failed\n");
+ return false;
+ }
+
+ if (memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH) == 0) {
+ fprintf(stderr, "ERROR keys agreed despite corrupt sk\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestInvalidAcceptMsg(void) {
+ // Alice generates a public key.
+ ScopedNEWHOPE_POLY sk(NEWHOPE_POLY_new());
+ uint8_t offer_msg[NEWHOPE_OFFERMSG_LENGTH];
+ NEWHOPE_offer(offer_msg, sk.get());
+
+ // Bob derives a secret key and creates a response.
+ uint8_t accept_key[SHA256_DIGEST_LENGTH];
+ uint8_t accept_msg[NEWHOPE_ACCEPTMSG_LENGTH];
+ if (!NEWHOPE_accept(accept_key, accept_msg, offer_msg, sizeof(offer_msg))) {
+ fprintf(stderr, "ERROR accept key exchange failed\n");
+ return false;
+ }
+
+ // Corrupt the (polynomial part of the) accept message. It turns out that
+ // you need to corrupt a lot of bits to ensure that the key exchange always
+ // fails!
+ accept_msg[PARAM_N - 1] = 0;
+ accept_msg[PARAM_N - 2] = 0;
+ accept_msg[PARAM_N - 3] = 0;
+ accept_msg[PARAM_N - 4] = 0;
+
+ // Alice uses Bob's response to get her secret key.
+ uint8_t offer_key[SHA256_DIGEST_LENGTH];
+ if (!NEWHOPE_finish(offer_key, sk.get(), accept_msg, sizeof(accept_msg))) {
+ fprintf(stderr, "ERROR finish key exchange failed\n");
+ return false;
+ }
+
+ if (!memcmp(offer_key, accept_key, SHA256_DIGEST_LENGTH)) {
+ fprintf(stderr, "ERROR keys agreed despite corrupt accept message\n");
+ return false;
+ }
+
+ return true;
+}
+
+int main(void) {
+ for (int i = 0; i < kNumTests; i++) {
+ if (!TestKeys() ||
+ !TestInvalidSK() ||
+ !TestInvalidAcceptMsg()) {
+ return 1;
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/crypto/newhope/newhope_tests.txt b/crypto/newhope/newhope_tests.txt
new file mode 100644
index 00000000..20d9c037
--- /dev/null
+++ b/crypto/newhope/newhope_tests.txt
@@ -0,0 +1,206 @@
+# These vectors were generated by the reference implementation, lightly modified
+# to emit the arguments expected by BoringSSL's implementation. Most important,
+# this bypasses the random number generation and key whitening steps, which
+# differ between the two implementations, and focuses on the common and
+# interoperable part.
+
+InRandA = 420c3c6b581c9f4466cd807170629a84b681aa1063a341062aa37956d70ae68befe87727d99fc92e7c29e215c5f13b722587c0d675d79190096a280a192aa4f4e65f982a59130f9266d22e4e8cd9ef195b45813cc8233a253f8a752548529b463226d3ebcf422870739095d567e7f6a512630c6766aa2668e8477a78865849e0b16bd0e4919d1d7da0c5d8005104e6e4d6b6855590e5c6a4e649dc4a0ef5b5ae140251c26b8c32001ed7ad13cda56b94c3294010c84ab54fba1888686384d40e310eb6363b9b23057782805f62e378c27ab98f223324add836772c3e81b8212bdae3c864a59c6e63a72327c42e69711ffcb3b6d04c00293e91d76c50ef9fdf33fd382c769835e0bd4821f65e66797075915f138a6b49051ec406ea750d50384d5d4ce2c9c536d45d3f7a704c6cae8d82f07bc5590f908b308d8c1b8d5e9ee3931d2d55145236f10688ae192f531755b310ccaf3891125af5decb1adbaa85224c47b73c3c8d7fa92ae1635d03d64d73c600486b336c8a511a7e1675a3dec9fcde711601ab73fc4d788d9de3d9f8fe185b87e920550d705f89f3188d1a69f9efc036666d7f5321d71b7eb5436f9bbab400884c08c59bd0a9458fe1e2b7b73d1e2a5ca4b21be5d48125613f0884d15eea9393a4dbb225bb66e5da5d3d98fb20c10761fe0efa5cf00498b29a662df8f8f17a4de3851fa425552aca9544aa89c89981d0f85636f67a862ee4eb844579f5c0f1b9bc0d647b15223aaf0c9edce88815273a0b064772b46dfc933a4dd8db90aa585097b2c6c0564ca90164a43d798403426544bb66637597dcf92a747b7b5ce1f7ba266f5c482d73e8f8b27920a627d1e9154ea745c213988f405ac2a19ec0a37388f8f67cbd9bd7c64222bd14a664eb5146a0645ccb542c21bde65bd2093a9b7622158a9504b0f230276ae1afd7ba6d7267a546e8c08dbdf168be439fe9263427752658d225a2062202ad567235685ab76585b04151f65a63016c9981a635116ab7766789a066d40d122805178f6840ec225e22dc5147d09ed9a53d8582e0e15b25b9a163178314205722adad9e9798c1306adcc002ab59e146302f0e08124945a18bfb10666c6b429124c5f5e61b98e2e8e6defd58b0dd377924f6a8d788c5887c306cf5864931b171936ae80f4911d483ccc804c112a0bc88a80621b0a1a9f8dd9f44f4f84687c54b533b4614d82741fb78006cdd137c422e5441c4513de3ae8a4cf4db9c679fb90c986f97abe8e1060d0392b668de010a0f9f1447445557c2f069f76e285a94f257ed368a70ae2922926c9452c01fa1fad6aac2db43daa67d68b31f3889acd8649a0c7389336d5d6904715984020470493a18fc84aa2bc61e352184714d0f5f46df0e3fa5a3a8a852f981135399d5df8d44b46abd6bfc164c4587e2a79ae255dadd09f964809c57e753105e2575bc987d924f3d7b9bd90747d1b61ce06a56ba60f1813463c418a3ad09821846b6c2b5057aca1939f255acca579b310fc91d112b6669088a66299fb227a7ca15c686604bf47c10d6c4aa1b56d03a7fe23217294866ea820646c372579955ccc16471159b83d8ba016c114c10c961221c28a956fce40806780e043883349d8e8baf8f308610be18c6103a454c8f30cb9465cc9d3be2935e347fc691a503b4c92d311d29abba18497283e646c3ab030a1dcfd295a29bc6517dde0cb295ea89639824c7fa99a968dd7a1aeb1983925258f3d7853517d6b5db4060783b27c949b80989561303d95cea8059e5e7fa520c2d3141fec406d88535d7060b1f4ebbd08cc7687e3d83040c97005d450f4405c557c9e0b71f047ffac98aa6ffea1f5598223163ea918ad5319bb919d9633254156aae2c527521664a6e54abae312e704b0fd335014a66ad8d22bc9862a0d239a9deb2a011553fe38f0100be4705f0a25580ade9b4b24705264326030b06d512f2d4c815ed36827d1078c57882369c1c2129ee1e1f8d51d45ab0d573820f9618fc2a45c25769f99ca51554efa5d086d039655b6a23874e18d02bb3b28a2d43a293b7e0b32d5c5000a222ddb92f945f0bc40a49427d8ab084de1e89cf9c70c9d39e1f902844811bca5775ad2f73ca884314846d474ef957a4d98eb4c98eb94f9cc6b6edd101b78d9a4b5986626752363b3e2c030bc5b0eb49e558d55ebaa92e1627cc166790aba847725bb487d08930714922d764eeae45c2a4157311ae4fdf4995c7781559cd149124a86843682df807d60ee922471be84d830e1cbed3055e281a19b855121977435f057000329a9a0458e51fca4dac4fa36303c02967d7551759b153f653ca653f7016d427ed7bdc6c49896741853148338688a62745e144c2840cb2fd22aabacbd6e7378074da23a68689664d5e804307beeaaef7454101d34c28441ee8456384a752992494ec2c4d4381c3ba3441357d8c545baec472eac58ca0f665992d64e1e1342c639863a09779e88349afa0418f667aebc22b92e7722e956793653992ab5768c170e8e564
+InNoiseS = 2e6f8b71cc4ab67f9816984bce92458263794396bd66ec320565045122d1a427408678dc565386f2f993fb14e1422366ade64536811cf943271a185b747eb2d62d13b6d5028b755179d538f915bce3fd7b1e4a2d6d4e6bf29d06554a010502a70a516fd7c6564b323723eb2a8570ceb98603208a349c685ddc1366b55da84b801ec8a5ea3882c6668a394d98b4a1036946ad618f1cf427a9a05676dbc615acb25c53cb83a117964065618b213f1e4851dcf2663638315859704a44b5785bcff0f7fd2a6eff292c2950fc817d5a4b7bccd014d95c4565abf86a6e8cd2b32e9594482e46e505e57932d30ed6639853c74ff2138b122fc46f54c183f11858ebdb2b871ca916109922ea7e3556e63d95028c62d2652c0b9f35af121da795121d5872043711b6a56639e169eb41d9780f6462d140cc7ddeabaed49d9c4e4284d07132d92fc39b98a5c5cd278023e3a1fdfd8875e0a7a2effe4dd3e2897be58520d99c36308caead22987d959a480db2cb76488cf14e4c9bc92887d5107c6df91ab69abd9a11a50a91b41138c22ed8281c58ae49a512c5c203f563bc7950147ded01a7078f8ebeb324e6e305295522df6eb91035ace84be894fa824fe6415b664e1873f3a4ace6f2f5aaad6d121a489688d3c7d307ab2414b79822305f8842339540f42e089df2c1bf0620ec7a306f36b2d4b27c72439875109d6dfbcbc43358f068108555e0f7e2b047140a589cc4be815227c9a29eaf7914e381513e5d9d00fd3296ee894c9641d2b00e79f62f2f62d8b5ade28bdc26fc6e3711c2fe3694ec9c461e28b5524c59fd2a0ff2ff599c04d8b882f23a5ecf917d080130214c262d3826a616f093acfb64fc6c9c82c36708a628c652cbf0ec8911e902caa2e805268b8144e595f1bbfcccbdb8b7a64af5e101fb113e8abec686c1ee7c2a539593b6f80549be9d8b814f360d71d6bbeb569db2e94d52405b8895da9a02495a01ac93ce9847503e107f6b81fa598c539409a7873af606315f82b9eac49b68a6b9f214a84d58083e067edd52d167d1ea65969cb7a40299062a732d2fbfb26139570c97151187741b9d020113651e2ed0cc279893348b2592531a6a1874c317ec638b42339890205705a52099aebb745f2689c54954f32620598048557aafd940650451b5a0e246f683e507d72080ac8b92ea399023f4ca93dbfb54637cd0301171d124d34a48f0db1a2c5f5ae5725271249a1198347b724b22817f649fcc4b02ec374b10b0524e08a9a41771741c2234d6324856c1aad86051d831e62333162aa2a32905d618e76c353a496829e3cc7a07a66b975364907e6da5d983e65004a392b1b8ce692ce1b24030a6756d60f6972a2e8aefef7d761e15645043d7720d1d756d1713b06c16712716f9204e29b2f8a45172b0498328a0d1b8a7a664079123b9851059add99e2209b4911359f42659e24def8cda7bd4da1ae34fa7669f8218d786b8b9ca16520ad54b5553b92cc99541e6f51caec0176729687977979c4726abf5321344edd66f0e03bea512c6dd54b9d6c80f932d4e58e75f8bf97b3e0e15e412704b691334d10541cb7037eb653f084d96afa4c3ab78d2468e4242fbdb24b05db81815280ef458871dbad0c938719a855d80c3392506ac313b755e13e6d587d0e9c11775e8d588cb048f60c64c564024570b474ab83d9a8d2fc7a0eb465803aa2b643a15c59e3f156ad133aca6c9c968d1493d601fa59591c8d0aea49a697a2e7426c36d24f343b292ed2201bb1f2638a2923c8220e0321f081cf465f98b5f69ff3ab78574646e828487f40c6f4d7c28be30391f083e78640a28f7066ab9aac6138a106dc9c3497c38efbcf007062de29a4b7a38397d0305a04b5fca5f51ddf6b026dd9aa1ef88a394aea54f20be3800d488af630522dfbe8306a10f7178ce06c097a3d7ca62b7169365486b4a23c52c1017fd4513268e4a20c5702b8d624d028098bed550389ad8b987c26a0a0bca7478f3c8b5a4c926a2c10c34662de11b7a260539727e75304c0c28b15e7cc6105da18ab6ba720eb6e0bfce3b220f7f68bcbd845ac8c7d166a837c46714721c227b5bd263d2a6fd54c7a7f26267597953943ef22cb9607f65eb829b5e4ae84b1a263c69a77b16827a7dda44bad604831dee420100d2ab45d822cca55378fffc7377d57c381dd92661eb2271599a68f4a5c4811ad16f27c16103ee9e7a802e9011f7fa542f4799d65c448245424c9698fd3d10cde7cbcf6885f6d630e1a7248ca7ab16b6cd8d262e1cc20243d46c5e1c2aa508c22b6aacfa0a4b8c60e2056bc3365c5f3acc45c61b2d12778bdbaac7744423af4b32f52eafd9a7835400ae42d424d8a46c0c03acefe9a684f903f5c8761616cc82e05de264cb7278529f3c3255b8095f64a2f3f5299b3365efb356d856b04731a8c77845336db8c1952a6ee91b64578d620af6052a700989a2338041e767098c996ce97a6f9907c284bd4acd688937617003afb95af11447629d71222919bcd5b4204a
+InNoiseE = ec87b3c754016deb580970f1a4368e1befd757ba3720cfb430599d152515761942bd92cad5a6aaefbe10888f6cb7d4112044c2c1e973a9376cab5d17e746ade95e0ae29cceb213494a98e9985409452d91a0794ecbd947039459aed8227cdad69a175666302007ba6f195968c8244c251bc84e8aaf8298654c71b852e253ab286d74d95c934344c85123b44c59ac7772e5baa0b827b197b0b6763016e1765381bb0127f478989c7ab95ad88b5a3c5480a35b16ca8c1fe061727398120c774a8b13307804f06aac48d8b1867265275143d1a126694bf6e5d25b25850e4428593f2cee882b2dc914c7158a6604de4ff643db6a9c286a585710e004b83e63049ef0c902585d55ba708cf292576430b77a86ace85bcd72a95856af4491674a750b438860c7805ea177ac98f1980e98bc1f92a3c4d284e5414689f26d265d23f02322d0a0c8eb60a4f31227e4c5467494a850dc027ea59616135c2db689294ab033201a4298fd02126866a38d814b959bee0a1bd045ca6f47f57a663019196ae7124c357364cc1140213b1a0c9c3651f882f050fb450948710211bb520b3c27d4a078e8bbe4b4c829b1e11199ae5d9ce441ad9c4d456664ca38d15607afcd66b0dc1635e6f0a744c8a0710bba49d00a860a46e3180bed85d8a134a7676ea65d420122e14488d21190092da666a225721213da7cce85ee51ad303e418bdda631d96e94958d749994699bafc6586c652d82e3a2e8d5e9a836606e265ffa5b292db623b8cc3690a90f81d8c59ef1097eb2fe5144d26f3fb30b2253e9d39d708c887665ca2ea9d9415b2aee7adb12794a420c21752a2068bd98ba55276405030684eb3dad424707f7e95b552a8f1aa6696560822f4e4ac551855d4a8d65b334a1174adce5b941a5249ba3e5393fd099cd9dd5589761100ae40c275c344b4d9fd7e95136bb8609f6e458ac04ef59fd22a7d23b6ca3f5b0ede97ee8c1f2c70bee77c213f611a1899d191c302606c61e09d562a3f8e6899398ef3918c259d6950da390aa57e9112652035a03772a422359fe570ce6168374ed3e1ccf299633ba0adde0eec22129bb354fccb7974600ae8232b698492acbe28024671a7f03a0a196bf790ec3d217bb279eb4f6ea041b62d054e19a39658cc671bf15b9d4af6a5a482c49ab18419630afa2b714528ab02326633f70008c8ad77a2a8e4cad9ee226b8ca58f8189508a199129b097d90603536412eec9af1327bc46efac7ffc42894837de833993562616f61cfc8557b5f04b2e5e56ea0e5fb2106e834b70bdd6a1d45a19c020190fd069e950fdd13982994f841f6a4563a470ad65659984dbda7802209dac690ec1d33a099c676d0c0b6866de62b35250683bd363e38804ab077a61944529bb022926c228cbad041f0bbd8de4de790d01dd651ce133d641f45109d3099b82b905fb66aef2111929609e8f4a228262596524be270408c1f7a4d0db3ccc44c78ecbea76fadf63599018f22e99645b07847ee187e71ef72216d52427ac20858efafa1d89cc834bdd8b7f102ca3a08a331f8a2896d148bab795f8d098122d2c640a58221297a536b262bd0e9d4b184d81465ef9b2ae12ab0a71fb2b94bf097db1a2feb7be25de709c1e7e5ceb72c401f0713501cef040c5bccb64146c2cc48b6010496868b10a8fc9ac5438b34ba6970af8cbcf59ae07a72c0a5b0d31663f7212faa22954611abb43380cdb3e8e91ee2194d81efcf20a37b9c5e2f457babe49200772deb96d00857c06d3c8412c844d28654a1a77e2885c044c32581a438df44a1c7f567086687f0fc795fc20e7861b5fe26cb10d2b329ccad97e858e0720233844368ca503a58fc48ac3712bc1c01490c64b37a2f1f9f65a78c983b628568c025c83031e222895bf00decc3d99503887c9080a6269de9ae332a09e2f6be0c8ae34d70ef695b5f17b9f4f6a60443945e6ae69ea4750f65302d9d6a7cee8ae01ba54207645ed0e4e556badf3ac1d82c2a8e0042734c7a275c2a61c00f728eaf90830bcbc5737c22d17842252cfb8570f55ed18eaf5218825a7d81bb00eee79cfe92ee82189712665bfc593ebbb84d420ca07d0594ceb400e75be3774eac5e4925967c5a2e04625f69f5a8a5981dd1173af8a8f42671e73d7684feeec1658f147a09569825e90993bd5cf15491cc06ef6de889dd78bd1d22fcb874843ef6e59766095610d5d247f9be1ab709e621b476923a2647fca9f53da8c78b6d08c179b1be2c2d0a304960922d6ac8e2f61f9c08600bcca591f8de995519ee355a53ba7108f44a6297d2b931d07a96c9c0866c44843f06814b8ae00c5a598f03cd3a5fe5a9f615de8da4f0c4d6d6e2242a62e776033b2061e6af2468fd65a580854afbea8c82c549a0276ee0723bc5233ba4c506b365709b9d15403522ce98de9d3aaf8da8813b7111582b75fab1115d9cedbeba735e3c8de4a7730aac543b0aacf39620a00b686f79b5b48c63a54005c5010b92e980a8e275ac24ab163a14b8acd16a41c7da648f
+OutPK = bc8dcdf734ed3f2091a723a0b57fd80c53ba783e9b8f285214dc9805d528f47a6d622c54e160405fcd098ee293f34936927e9e33c7845d33e4d511c4ec8569af4d3af4f3c8165d9262993ef68dc74f2e0a963561320b6c40bbd639526201c952dc5f6e56c3975dccbb6968a566a35629f4867c88700a774dc26025302062db4d391bc4c8adfa270bb609122c45e35dd7cdf25e7b09170891fc0662e5b254731473a4ec5945177d817ad769670a4c6537839e720256b5cd5c8548c3de36d38a543a4f225ee2d526738436afdd80fc6aec16529853a20b1494a1c4589535d89eb9eb9c0008ae519e5d101ef4239c8f78d96746d196568c528bda9d9895b61633cbdc99a44fe794b43b600b4116bd617bb95e935b798a212a305f6e608bdcd09bd725ac7999784f06a05cf156ee93a78ad9c5af0e593be56af5677eb70195f025a87822c443d2a041ad4ae7e37a4a65651a056e3a667c720cd504dfe4ad4d54ba89a5c41e545f13ce34e614bd32029939a2ad98bacb066c71a01a462c45ec9564884649a1671797641895ab0c69d3664e4e42af843d5a7ae8ceb369f2405e6c111f70d7356c57a98086d9996650d0e89a64e003454c5857dc0183cbc4b305a24a5f8c8d8cc8c8b54ee9a2d73a2daa96a9c2eb3ba6298594d5a9ba58a587ce1cc4f34afebcfaee9858112d222106030b5d2923780df294ecd589df9039b2aeac35e640ac90d4b10d1e6b6f903df28898c84f759d3c9830aa6e4934f2a88f5bec4488a6021440271b986d44764825a1c7a62bac0e6812a0f64c10e21a1810ee19f36f931742747ec9997741cbec6def679364c1919307d4361aae1a880706061710417e144a1495f13e372268e2ba017a99d3c9025883445d8f148da36fd55a311e9f8104a974cf993c87029ca7d5ae1fb5cf0d4e6fc985fa6a5839d3d7addacd1c75cc5f903358c01e2c4f72499bfa58646a26e13c152b27e8acf3aa85adfc53b5009459b6b6e6e6311bc9732b823e084708938516d6b9451d4b1799f3a1c2ac60f70cfb8b92c55eb8d81b06bca5a64393a6d7386e1f1e20530310d8ab3f6d0d5bf06a7715ce157a9f622f164d6b1566ba82abaec91be9ac3ebe5a8b75f349600ee12e2685d505548cb66008b8318705c890810e4d04e784c2913c026642344647f8b97ea6ff7a0376b135dd1f9332887316e42da8ed32b42b1a42e4c5b4160457b2d898cd41b5df0ffa970183a59b26272002b2836866d32f696623a768116c2691d1666ac882b974e3cdd0d08e5e7d210db2f5d7349c5b130038e09e0a8fad2db1111d731944b3d6692671490a6af15cc69c1a29863b22e8a6de87239539ce0ceca541e6c4515821af61103ede0e3156ac71d3a29e3a8e4b84f4850b20d193ea55dc073a9d83c846ce3f55dc083ae93612c02f72117a4693a4c023f8e824b5500f61509094a89bab8d531ec8aef5291ac9ebd44cb0a2c9413274007488f32b12f459c5e10b849004902ac03273ce86a7a91a17ab46590ace5b4bd5333d8f5481e4e05fc94b5e68db79e30e6c08dd3c0578ec4fc0c55d6850313c8215b052a22d2f778dace1e33441406d5772a28a7ed892b867dd4c9e2818ff259e115bd4026437cffd7ef65dc4044e9830e64149e34cb695cddde34336b8bb40c00c15bfbdaded1593293a6d166ad39d8336b1178ed121bb13a98ea31a46d9f4817b3d8454e26bf405a32f51c15d1d419112ccd2af006e415bd5e3cfb67aa9d5ec64fc599b026934f7dbba1f4c120558364057a5cc5f901b2c0d411dcbe02342bfe32416277e1937e69a3e87f6ea0f214534f278a022231354653e3537e72b75923be4472a1275cb3cad4cf361dfe6be8c6fec69bd824f2a4d84878acac5e97287805279bdd92f48e8d1342f1a3cd8c711f837be0f188ed54071f9441b2b11b0acbc0c3510b4c4c5beababd27c7176f00c2396a3b81ecd9135e1f0171cd97976415671b28d63cb67996626f088f2de42125989581086dd29e87c6f4ee507537e2c9ac8e0f9827b9454770add19de3c3f8c093e85a93e9aeba6e157e38d8a42cb8893efc9ac78d79b9a02fc0500e4466a2942109de0f351ae313a534db4762802220ec7efd5bdc62ec04810e950dc16dc9f0ccafb6eb4a75db6f412ad3575094e8175290e70688f6780be7388846fc98a394c28ce11f51bc8b1cf54df58f06d4aebe2e185b2b48dd2d39483fe584b56dc1509c26ca5f89aacd27ba102232695a74e0613f91ceba0b385a0c59e60f24fce013b0646ba4d1e38e86a0962b065227b1f2a82e9d594e4125fa7660e7683a9a6d5f8ca7f9fc11f98828ab5f0edf94370e951c5e044190d367e4056ee54b97199d067505258aa5684db9dd24ea1ad52cc8744f5b2683584c131d244311a55985bf09c75d7237ab0607e334d6626278fb21a0150ebaa7ab0b78081bd43c706731ea3ccf9678822ade40320d51c040c9f1072c42562d18c894725ee7105da06e5b694420a639d67f8a1062491620238b0199b1a917b219049
+
+InPK = bc8dcdf734ed3f2091a723a0b57fd80c53ba783e9b8f285214dc9805d528f47a6d622c54e160405fcd098ee293f34936927e9e33c7845d33e4d511c4ec8569af4d3af4f3c8165d9262993ef68dc74f2e0a963561320b6c40bbd639526201c952dc5f6e56c3975dccbb6968a566a35629f4867c88700a774dc26025302062db4d391bc4c8adfa270bb609122c45e35dd7cdf25e7b09170891fc0662e5b254731473a4ec5945177d817ad769670a4c6537839e720256b5cd5c8548c3de36d38a543a4f225ee2d526738436afdd80fc6aec16529853a20b1494a1c4589535d89eb9eb9c0008ae519e5d101ef4239c8f78d96746d196568c528bda9d9895b61633cbdc99a44fe794b43b600b4116bd617bb95e935b798a212a305f6e608bdcd09bd725ac7999784f06a05cf156ee93a78ad9c5af0e593be56af5677eb70195f025a87822c443d2a041ad4ae7e37a4a65651a056e3a667c720cd504dfe4ad4d54ba89a5c41e545f13ce34e614bd32029939a2ad98bacb066c71a01a462c45ec9564884649a1671797641895ab0c69d3664e4e42af843d5a7ae8ceb369f2405e6c111f70d7356c57a98086d9996650d0e89a64e003454c5857dc0183cbc4b305a24a5f8c8d8cc8c8b54ee9a2d73a2daa96a9c2eb3ba6298594d5a9ba58a587ce1cc4f34afebcfaee9858112d222106030b5d2923780df294ecd589df9039b2aeac35e640ac90d4b10d1e6b6f903df28898c84f759d3c9830aa6e4934f2a88f5bec4488a6021440271b986d44764825a1c7a62bac0e6812a0f64c10e21a1810ee19f36f931742747ec9997741cbec6def679364c1919307d4361aae1a880706061710417e144a1495f13e372268e2ba017a99d3c9025883445d8f148da36fd55a311e9f8104a974cf993c87029ca7d5ae1fb5cf0d4e6fc985fa6a5839d3d7addacd1c75cc5f903358c01e2c4f72499bfa58646a26e13c152b27e8acf3aa85adfc53b5009459b6b6e6e6311bc9732b823e084708938516d6b9451d4b1799f3a1c2ac60f70cfb8b92c55eb8d81b06bca5a64393a6d7386e1f1e20530310d8ab3f6d0d5bf06a7715ce157a9f622f164d6b1566ba82abaec91be9ac3ebe5a8b75f349600ee12e2685d505548cb66008b8318705c890810e4d04e784c2913c026642344647f8b97ea6ff7a0376b135dd1f9332887316e42da8ed32b42b1a42e4c5b4160457b2d898cd41b5df0ffa970183a59b26272002b2836866d32f696623a768116c2691d1666ac882b974e3cdd0d08e5e7d210db2f5d7349c5b130038e09e0a8fad2db1111d731944b3d6692671490a6af15cc69c1a29863b22e8a6de87239539ce0ceca541e6c4515821af61103ede0e3156ac71d3a29e3a8e4b84f4850b20d193ea55dc073a9d83c846ce3f55dc083ae93612c02f72117a4693a4c023f8e824b5500f61509094a89bab8d531ec8aef5291ac9ebd44cb0a2c9413274007488f32b12f459c5e10b849004902ac03273ce86a7a91a17ab46590ace5b4bd5333d8f5481e4e05fc94b5e68db79e30e6c08dd3c0578ec4fc0c55d6850313c8215b052a22d2f778dace1e33441406d5772a28a7ed892b867dd4c9e2818ff259e115bd4026437cffd7ef65dc4044e9830e64149e34cb695cddde34336b8bb40c00c15bfbdaded1593293a6d166ad39d8336b1178ed121bb13a98ea31a46d9f4817b3d8454e26bf405a32f51c15d1d419112ccd2af006e415bd5e3cfb67aa9d5ec64fc599b026934f7dbba1f4c120558364057a5cc5f901b2c0d411dcbe02342bfe32416277e1937e69a3e87f6ea0f214534f278a022231354653e3537e72b75923be4472a1275cb3cad4cf361dfe6be8c6fec69bd824f2a4d84878acac5e97287805279bdd92f48e8d1342f1a3cd8c711f837be0f188ed54071f9441b2b11b0acbc0c3510b4c4c5beababd27c7176f00c2396a3b81ecd9135e1f0171cd97976415671b28d63cb67996626f088f2de42125989581086dd29e87c6f4ee507537e2c9ac8e0f9827b9454770add19de3c3f8c093e85a93e9aeba6e157e38d8a42cb8893efc9ac78d79b9a02fc0500e4466a2942109de0f351ae313a534db4762802220ec7efd5bdc62ec04810e950dc16dc9f0ccafb6eb4a75db6f412ad3575094e8175290e70688f6780be7388846fc98a394c28ce11f51bc8b1cf54df58f06d4aebe2e185b2b48dd2d39483fe584b56dc1509c26ca5f89aacd27ba102232695a74e0613f91ceba0b385a0c59e60f24fce013b0646ba4d1e38e86a0962b065227b1f2a82e9d594e4125fa7660e7683a9a6d5f8ca7f9fc11f98828ab5f0edf94370e951c5e044190d367e4056ee54b97199d067505258aa5684db9dd24ea1ad52cc8744f5b2683584c131d244311a55985bf09c75d7237ab0607e334d6626278fb21a0150ebaa7ab0b78081bd43c706731ea3ccf9678822ade40320d51c040c9f1072c42562d18c894725ee7105da06e5b694420a639d67f8a1062491620238b0199b1a917b219049
+InA = 420c3c6b581c9f4466cd807170629a84b681aa1063a341062aa37956d70ae68befe87727d99fc92e7c29e215c5f13b722587c0d675d79190096a280a192aa4f4e65f982a59130f9266d22e4e8cd9ef195b45813cc8233a253f8a752548529b463226d3ebcf422870739095d567e7f6a512630c6766aa2668e8477a78865849e0b16bd0e4919d1d7da0c5d8005104e6e4d6b6855590e5c6a4e649dc4a0ef5b5ae140251c26b8c32001ed7ad13cda56b94c3294010c84ab54fba1888686384d40e310eb6363b9b23057782805f62e378c27ab98f223324add836772c3e81b8212bdae3c864a59c6e63a72327c42e69711ffcb3b6d04c00293e91d76c50ef9fdf33fd382c769835e0bd4821f65e66797075915f138a6b49051ec406ea750d50384d5d4ce2c9c536d45d3f7a704c6cae8d82f07bc5590f908b308d8c1b8d5e9ee3931d2d55145236f10688ae192f531755b310ccaf3891125af5decb1adbaa85224c47b73c3c8d7fa92ae1635d03d64d73c600486b336c8a511a7e1675a3dec9fcde711601ab73fc4d788d9de3d9f8fe185b87e920550d705f89f3188d1a69f9efc036666d7f5321d71b7eb5436f9bbab400884c08c59bd0a9458fe1e2b7b73d1e2a5ca4b21be5d48125613f0884d15eea9393a4dbb225bb66e5da5d3d98fb20c10761fe0efa5cf00498b29a662df8f8f17a4de3851fa425552aca9544aa89c89981d0f85636f67a862ee4eb844579f5c0f1b9bc0d647b15223aaf0c9edce88815273a0b064772b46dfc933a4dd8db90aa585097b2c6c0564ca90164a43d798403426544bb66637597dcf92a747b7b5ce1f7ba266f5c482d73e8f8b27920a627d1e9154ea745c213988f405ac2a19ec0a37388f8f67cbd9bd7c64222bd14a664eb5146a0645ccb542c21bde65bd2093a9b7622158a9504b0f230276ae1afd7ba6d7267a546e8c08dbdf168be439fe9263427752658d225a2062202ad567235685ab76585b04151f65a63016c9981a635116ab7766789a066d40d122805178f6840ec225e22dc5147d09ed9a53d8582e0e15b25b9a163178314205722adad9e9798c1306adcc002ab59e146302f0e08124945a18bfb10666c6b429124c5f5e61b98e2e8e6defd58b0dd377924f6a8d788c5887c306cf5864931b171936ae80f4911d483ccc804c112a0bc88a80621b0a1a9f8dd9f44f4f84687c54b533b4614d82741fb78006cdd137c422e5441c4513de3ae8a4cf4db9c679fb90c986f97abe8e1060d0392b668de010a0f9f1447445557c2f069f76e285a94f257ed368a70ae2922926c9452c01fa1fad6aac2db43daa67d68b31f3889acd8649a0c7389336d5d6904715984020470493a18fc84aa2bc61e352184714d0f5f46df0e3fa5a3a8a852f981135399d5df8d44b46abd6bfc164c4587e2a79ae255dadd09f964809c57e753105e2575bc987d924f3d7b9bd90747d1b61ce06a56ba60f1813463c418a3ad09821846b6c2b5057aca1939f255acca579b310fc91d112b6669088a66299fb227a7ca15c686604bf47c10d6c4aa1b56d03a7fe23217294866ea820646c372579955ccc16471159b83d8ba016c114c10c961221c28a956fce40806780e043883349d8e8baf8f308610be18c6103a454c8f30cb9465cc9d3be2935e347fc691a503b4c92d311d29abba18497283e646c3ab030a1dcfd295a29bc6517dde0cb295ea89639824c7fa99a968dd7a1aeb1983925258f3d7853517d6b5db4060783b27c949b80989561303d95cea8059e5e7fa520c2d3141fec406d88535d7060b1f4ebbd08cc7687e3d83040c97005d450f4405c557c9e0b71f047ffac98aa6ffea1f5598223163ea918ad5319bb919d9633254156aae2c527521664a6e54abae312e704b0fd335014a66ad8d22bc9862a0d239a9deb2a011553fe38f0100be4705f0a25580ade9b4b24705264326030b06d512f2d4c815ed36827d1078c57882369c1c2129ee1e1f8d51d45ab0d573820f9618fc2a45c25769f99ca51554efa5d086d039655b6a23874e18d02bb3b28a2d43a293b7e0b32d5c5000a222ddb92f945f0bc40a49427d8ab084de1e89cf9c70c9d39e1f902844811bca5775ad2f73ca884314846d474ef957a4d98eb4c98eb94f9cc6b6edd101b78d9a4b5986626752363b3e2c030bc5b0eb49e558d55ebaa92e1627cc166790aba847725bb487d08930714922d764eeae45c2a4157311ae4fdf4995c7781559cd149124a86843682df807d60ee922471be84d830e1cbed3055e281a19b855121977435f057000329a9a0458e51fca4dac4fa36303c02967d7551759b153f653ca653f7016d427ed7bdc6c49896741853148338688a62745e144c2840cb2fd22aabacbd6e7378074da23a68689664d5e804307beeaaef7454101d34c28441ee8456384a752992494ec2c4d4381c3ba3441357d8c545baec472eac58ca0f665992d64e1e1342c639863a09779e88349afa0418f667aebc22b92e7722e956793653992ab5768c170e8e564
+InNoiseSP = b1e6653ab5f2447f5ca626e751a87a4b61dbcc0637a84ff2a9eb2d26e99d642bb6d18b0f0c7f4b29a2a671a88f3723ec76fce25f3ac5c681d1de5909d68ca63991af658c4d1e6ea18df2e97675e4840fc5667c353d8d11a92f6da0aad1e4a104066bb3c82ea9fca43d9c837741010924e5cfc3a235045edf4bf2a5187861fa974dbaca44873e93f9b498f2129111978a7d841e1da8362110c1ba1cd9467b7e664d6485b63a0fa2555e51bbc126b811f19dca151df2bbe8675e992bfc4dac16c207044234120c36b94fbe9fccccd2d6ac293497260de16d0843d2679201520208705b9f1be4debb05893b4622bd9a56c0922bb72508b7ee4278f6410300ae47bba8b086c54a6fcb0202563b42ce667ce869cfa00e3041dc09f08d1a926cad88f5d88037081a2c98053aab975868fa5e4c3ba6febc2f469462ef95a05a8ea492c24615fb4b20699c187718065ae3a6ce3fe3ddcdf257661093d8a712a91aaefe6b17083dacb09011f580b23e6c05cf56457195aa2465bd32769c86d19146062a7a26a756233a301e3e31ccf33268003871e44549df44ba2f025f5a95f8356185e6935df047f3e05f585e515531653255770402ee467e696ec5992a24be84aa5dbffc081c118d865a03016eb2abe0b3ae9413e51971503f1ce58b88f194c1ac7378b7c62a48155c18355d4ea50f4d49a8756399a17717d68a76592d7c02024c7cdd13075b61b98d6055fc64990d36de2769e220b902544fff89bd3a6fcc930be2975c36c25dfe4a38243c95209b2784010a8ea5ae3af906058c563f51ca99b892d523f4a4fa79942a38539b6656d95582901cccb28d63ee45c4c13ef9c22429bd1c1727cd7b203f1936fcefe8d9da9016c58c8ba916e5624d2bb151249527a31f9a866cd278bce94791cfb1263fcd3a15e03a1e50420b157e0478818ae5968d06746ac14352740e258715f1a7a54c5d9849f61204bdb50d55ea545df435fa6efa575e2157b7eb5df2305512c4a91112422824c50411b1b4c5a670e9bb848c395f6d09215b30d954280a0ea720706f8bcc6ed6983ebcf95650d1ed163e3505693abb788879047fb088eabb80e99443120d6a2f166c136bda3e825292c815a668dfd74ea013e62da1a8e036c2c077b11a591a9ec195d3c02258fa817a5ee1d94b0fc4be254387069784b7358f0888dbba567a1db5372c24a7d66a315be8f16f65a46a08986191668b2249ad6d3d87240c4047d59f648a790a7536b9e145c95997058db3679ce3a3691b8f528c36f8269686835deaf32a080dc45fd8fbc1a260998fe9c58c832d52923649954efe60f2d059bc119e07b41917a60eb2a7ad1b84cc9c8a5df830f4a16bc7abad4ab0d5246c9fc2c2d0cd120657d25a3ace31e653aed39b822ea9cc37e6d67c2168c64cb63ade7016ee4a1679c25d1a947901bf4100dc6d1eb69ef88ba9cfd309a385af4baefbc8bb48861199bc810390446367b127921e7f70071cb36775a054d327d71b9d9879e82d1721a686118faf08b400316514d9008248b6375245464d89a6fd8be7725ee1bc6e51963a1a20181ad6eb54a76c019e2fe0c9a981381818d2f6de38011a2bdf2b7391b19ee37f1485e1715a17a3b9b65843470aa3d766f0b4b48a0a566ee8962fcd46c2dfbca77e003b5bccc45a53d874633e899363d497741282a33b66cd01bc306b310d442968121914d9c715f00c1809cc84460fb23c00a9c4b6cc6806cbe3198a9721bfb4d10f14572aa9406023abe1f2282d2cf6c1791a88810b5f8568b123e84144b6aab07657c1d57a473d53e54dccd32aeea0210e7f50ee098dd797b079eddd236ad0675698949f50ce5899dda92611df2b0002e043eba7f05a447e20f2d673c5d0e29b758ebf7959b168e1cb0ad218fe80861a4eb1c665aa7618c09014e893cac6d9487d0d5c8a090035f8c549a80af46158f90de1891579d50839384c4b3bdb66263463c7ca03257acbdfe5a233b98db00c412371bc32788bb9b536f27dc24c2e328f85287acbe2d28add4f4e4908b177b54e994521e53001b63dad66f82ca476612a47f690c09d1109cac06f510d684132c8764e88b0ea5525509472cc27d696412c2172996af3495285ebcbf0499396211d9a1183910262c267d020cf70a09097df20cc41a4d79acb536051b65ad12122e2586028547a6bc2420e97d6f4b6123c42229fec6775bd6fb6c51140bff9b2d19388a5554aa83316556109a544eb67e403a9d59a3619fafbce218b3e47d73829c65a196c87d66ba16079151887d9667abe006646ff1ea7b65ddb2ba39d7a6899fe82b6e8112509ea09fab937be208e6015029143688513836cb1016a12572348b997ac4a52384c60b05933e91650697203106467088d451e145ba368bdda6808d36f7d99120fb349300d949bcd8a18c5001eab4488dbc6ce5beb47733609429e9c895e749141238d044fe08a0d1b662b9e767a65a53767e6924d2d1a88eaab2b6e902309036a6b87bc0a7d9d1e81f8d56b9fac7361e2b837
+InNoiseEP = ec67edf27a627e3d6101bbf3f07462e567d1fb24819f549b56922c94641e03c5a90a9e4ded6385f1dea354a97571acc95144eccf6341f42cb8001ddbd2152e5fe9375b6cc01ff0a8ee6545dd1ebe834c6bd860565da3ff58bbdc4ad502de4b7f795ac8de9236822cafe0819d9a7a721c845a9133aff25ef3e75789927214aa0ce6b52591a0f1a104c5da1ebc4e96a65a5d00b4b65365a2e586519f641d17aae4041cea14573b448bda8688588f8495daeb90e1b704a6786ecfb4968682782947bae6847868ace2e111396fc3da551160d56ea6545ab825aaa53a282c2166842b710fbe331a65438b139d9b79815d6660081091f565d1cd65944b9d99429a9198aa2874818b86fb0bd07e16ee14980d79215d958a4ba4385a130c14f8871090deacfb4aa43a9242a09fa8549c19ef5b7139132c62d05128904d0e96e80e54c54a8627bb1b36e6aeb507fc49a8e98671727bc9bb932a7e0bc39e7e81e69e48f596cba6fc4984501a2d49a5be0309d8e434584669af04230797ec7aff98425b4f6a78f78c8455f97273b95e4f97681c11e35ffa533f887cebd95406887a4d78e9594694622d828ffa58516e986ae41f06b004adcaa4db09cf1e3829943859b50d6f5386e31643f210e3ab017b6c3d3de2699aa1a5c47e01907284ff5a194c2f0a743a6888041217e6d2c4584f6050f6665da7782a4a63bc580d1d421248f18940526d45c59e143c835e44e83c6a41b806840725ad43b208496a9ab14667598c97006c00ce0f8a71ad51051840f4c5a2b5ac240af17671d806181b9a6a831a209c52a4b1df3d7f591abd87e6ba422ba8fc77393ea2eb5ed786b6eea749e084dbee8519b5846530da1d0054d683591fda950c99de294471855c0bc774801a2debe19de54ae6a9da175d92fa809152e41ed5d521b57fd1e79a9cb8bb1ee678b4d204524ed97e093f3da40399a24ab468392403769947693182181c0b0c467f0329d7517292240c4a5616db815cdc82f929140d0a511b19407a22a7c2a1caa9783c5985d5947a6bfa5241631182eff0164b9f14602d7a13925146913f70083109e7b4582914821e532841e539ce5e826ad0683b62ee2ca51bca3cc88f1f27c5be927220c0c3495e7bd958ff10effe94d59fe1fadc5a5923e1301b1f4a125fabd6c4dcc4618ddfbf7b5f0ab37d9769a029c90f738a4c949b082a2f6276aa911a1a21cda9c2a2806c35abea606faab2b189420a7b3c48806d2393c9fe67176681490b4a9e340aa68b4dd4aafadd01c4d88c360019aa90ce59612cc30f6004da46ed40acd4a53aa1369687799f150516dee99820044e2a87683b12454afbab7a649498796f00d23314b062bae57a995ab27eafde22e3a4a240be4560821bb64551279b62f326a62adf55d8da21644b68dc93a8a5ab21e10304de99a17c666c1ae81a18d927ecdb9708b3c1dbf9ca21e55af3c3aab449ec089fd672fa3c3d38b82f8186ddf17ec5944c21de687ecae803c7a32a1c5f1546f6387eb32d1c75d006cd6e8b9c6d399c402c6c65e9e512628272e930a4c240989f0bb7fadad62dd4a9e4a4b9ca0c106a1cd8e7842ac8c0dc2a26f6b3f96b484861be2f0981cbf07b6a9598601285885924506d0b8b693a0f590b12a71de0674c2ebb85a094806c57b338b026253b881a34b5915f22d62ca0f231732a851c51295a66f6453865de154323960bc66f7e60c79a2615db49a2b7ad80647e007a909b129750581c1ba4eff7e79675311d3b0961ca335c9a9e54b59911894cef01bace82a6259643c3725d5f6eafc7de7225324e14035adc9f43dc586334dc1c1952ca861939a6f8cdb1f47f321d9be91372989d50b79dce772741870b8fbd1140f812a342b1606b6921bb8d3986d816197e1959c156318ca2c0eda96ba84f7cd2df147a2d3eee5472c548b066665b3a173e2c33970df3c3e25e043542585206f4250ec54978c398731983736165da2628c6d19a035a0e6e8e6147a59055ded74c146655309a28dce3b6cc5c1a6d18c52be99f74abe2f5534832451494647b4e2ed9931fc2fc2d530101ef97d92670cfd5d1d9b95412595a9e6871202e70ada42698aa52b181beb5fe260306271c8b6c5eaa3f257f5080f5866159f9b2470c0a83eda50745d02be4016414979a80be53da68a172882003b788b28a6abf4d1de8c850325f25c309e12c27d2a1464bfcac812e61960130bdbae3907904b6ba3d1ee35b7734428e3a86f6b1b6a079896622c171b29a87a899e12dc929dce6d669630276dba5ebe4636e36e940ea65fc7a2978e4f6d4660c532608f6707c81b15ae7c9787948ad1c6481e978100208497c19d69924e741393722b1880ddd94c2eb75b65b2fce25d63451eb1f0068debd8fa25383462f4295b3ee17b094693dca876e75091a019368388175f025594c8fd2f8a81244868f4229926fb2d4992519eca660accb71739dab701052929c8c375ad8f8763d58611ad8b4e394422d1aadc88055c43decce2a907fc8bdde6b5a5759bd9a
+InNoiseEPP = fbafff0b0003000180fffbff0a00038000b0ffeebffd2f0130000800fe2f00100000c00100000000030000b0002000ecbf03c0fffbfff2bf0240fefbffeebf040000f0fff6bf0180ffdbff060006c0000000fcbffe2f0000000300ffafff4b000000ff2f015000fcbf0600003c0008000600002000fcbf01c0ff0b000700007000f0ff06000340ff6b0008000440ff0b000400008000f0ff0a00014000000000c00200000c001400fc2f000c00fbbffeafff1b00fcbf0440ff1b000c000140002000fcbffe2f00bcff0a00fc2fff0b000300ffefff0b0004000180ff2b00f8bf0100003c000800ffefff1b000400000000ecff0e0000b0002000100001000000000c000070fffbff06000300007000f8bf0070010000fbbf00b0000000fcbf00f0ff0b00070006c001200000c00280002000000000f000100004000030001c000800ffefff3b001000f92f00c0fff6bf044000f0ff120005c0ff5b00f4bf0300001c0000000080fffbff020002c0fffbff06000400010000f0bfff6f000000fcbf0000020000f8bf007000f0ff0e0000c0ff0b000400004000c0fffebf01c0ff0b00f4bf007000000003c005c000100004000000000000140000c0004000f4bf0500004c00180005c00040000000020000300000c00180ff0b00fcbf04800100001c0000400000000b0000c0ff1b00ecbf003001300010000030004c00000003800010000400028000f0ff0e000140ff9bff06000540fedbff02c00380001000f8bffe6f00a0ff02c00080ff0b00fbbfff6f004000f0bf0040ffebfffabf01c0fffbff12000040ffdbff0200000000000000c0003000d0fffebf05c0ff0b000b000030ffdbfff2bf028000f0ff0e0003400020000c00ff2f00ccff120000f0ffdbff06000100ff5b0000c001000000000400fe2f00000014000180ff4b00fcbf00b0fffbff0200020001200000c0fbaf00c0ff0a00030000fcff020000c0ff0b001b00fcef000000040000c0ffdbff06000380fffbfffebf000000fcff0e0000b0000000f0bf01c00050000400fd2fff0b000f00040000f0ff02000100011000080002c000300000000200000c0000c0ff2fff0b000f0008c0000000100007c0ff0b00f7bffdef008000f4bf0280ff3b000400feefff0b000800ff2f013000180000b0ff0b000f0001c0001000000000b0ff2b00100002000120000800003000ecff060000c0ffebfffabf02400000000c0000c000000003c0fe2f00f0fff6bf00000000000b000280fffbff02c00030fffbff020002c0ff0b00f7bf0200ffbbff060000b0ff0b00f7bffe6fffdbff02c0faaf0000000c0004c000100010000080ffebfffebf003000ecfffabf05c0fefbff1e00f96f00500004000080ff2b000400010001000003c0038001e0ff1200ffef00c0fffebf0100ff2b00f4bffd6f00d0ff02c000000000000400030000e0ff020007c0ff0b000000fe2f01200000c0fd6f00e0fff6bf0070004000040001400020000c000100002c00f0bf03400030000800038000e0ff020000f0ff0b00fcbf000000ecff02c0ffafff4b0004000140ff6b00f4bf00800020000800000000fcfff6bf02800020000400020000f0ff02c0048000300008000070ff2b000400020000c0fffebffd2f00e0ff0e0000f0ffcbff02c00240000000040002c0ff3b0000000100003c00fcbfff2f000c00f8bf0600004c00080000f00000000800004000e0ffeebfffafff1b000000fe2f004000080002c000c0ff0600fd2f0180000000fd6f002000080000c0ff6b000400040000ccff1200ffef00f0ff02000140002000000002000100000b0000700010000000ff2f00ecff0200fd6f00f0ff0200003001000003c0000001100010000140ff5b00040002c0ff0b000b00ff2f0000000f00ff2f002c00f4bfff2f004000fcbf018000000000000500000c000000034001000018000480fffbfffabf007001e0fffebf050000e0ff0a00000000c0ff1600ff2f002c000400024000f0fffebf0030fffbfff6bf03800010000c0000c0ff1b0000000300001c0000c00280fffbff0600014000000003c0fdafff3b000400fb2f00f0ff020000c0ffdbfff2bf00300010000400060000fcfffebf004000300004000080ff0b00efbf02c00120000400ffafff5b0000c0044000e0ff1a00008001e0ff0e00034000f0ff0a0000b0ff0b00f7bf018000000003000340004000fcbf0030000c0000c0038000d0ff0600fe2f0100000b00feaf004000f8bf0100001000000008c000f0ff0e00000000c0fffebf0280fffbff12000080ffdbff06000380ff4b00f4bf0100000c00f0bf04000200001000ffaf000000f8bf030000fcff02c0007000d0fffebf0380000000fcbfffafff7b000c00028000000004000200002c00fcbfffef002000fcbf02400030000c00fd2f00fcff0a00030000e0ff0a0003c0ffabffeebf0240000000f3bffd2f00ecff16000140ffbbff0a00010001f0ff0600ffefff2b001000
+InRand = 51c3483b5f31a30d7cc8457959f83f0d3848d0d82a9af0371d9e54519ccc6e45
+OutPK = ac839551f2d26b42e6bab93668afac931834e5d0230e84f450cb25ae52a0e32850da5f44d42cda563e95a64f0e18636a43c50e0d79a7d69a15c5a43a9d2d8db99bd0a43d3d60cecd0ae499aa5c2280daa1ca09b927a8e84abd068e684d0f025d606f60632d85f70e7301444d1495351d018c690aa2ac9e8da8d598dafc87d4921adb9eec3818d91e981da53a9be7fb9053f5a0b107225bff688e01eb1dd0245d30fb2680b2baad0e81495bd21a0d5cf24b96b830b12971a0478902bd6277104e3b11e138b523e5d9d8d6bb4d099c66e92693371558b2ee3222f58db087a1ba2953c8a147b8b21714ece87242d47523c004071306b6eb14358be901b0a88d9e12ccc682d204533a2fe87b578b449bd88a6af1a1c0787a8914dc85ee81ae6cbd53a0f0cbbb3d7aa8965bd7c34c6507d3709211129d802c2eab3e3e1a589948130665b4ff9cb9a050701a0aa3dc62b4999b29a4b604205c0f995d27411260bd93abc5d2566a4b9141c75ba03e28e3223ed9a661bfa9589826a10d525b5332b59f6163ce559ac3cb9cb0352b55d633d5517885c0bb9ea5aeef9f0a586fc0a171ae5b5bf7f6576caa6067b76ab5682a8260d0be3c80219ec7746a9accc6ad47d2994615cae6590214b29f230cb881ec7d59c29be2c5380e3c15ef34a3543dc751e2182a4e397c6d02b0df746741cebc41e6d59f045e8a71086140c212aae224d53eda4812d3ee2c120ceaf7d82814a163dd23682f6902320372e3dacd1cdd4b2d835d493300ec572944d44ee0892d712c144c4706ac47a5307abc08f9f0fd905a6b26af28c050232fe707e08c8217774612e9d5e9206697b8612bf2bff7d50282683ca6d3ecb088bd3eb917e37e4a449a294c6bfa5b6519a0dca0101872c10efed1d9607b102cdacdd893c72e804a96781ad08c89966fb07591696a389948363450bbda9b903aec4d47be629143d7ba1b2f260b88dcd182d345aec4a928766c5bd89b35980fcddae4b80f322e9d2b87d0dd9539330d82c930b15e0bd9b05a73fe6426e9da685b540e3c1d35448aa4a0119bfa30c6326877abf850ed1822ae000132b1501a69865329c74a2b03eea490f6fd1891214d73ba6a4ca5e0db87c70c63a619f7075d348969eb46bb9f5d34926df75586fa49f3cc3975053eba33107a714d627075883bc44f6267ce16971ac5f0ad3c481f421afc9c1a12aef556392d2497ef884abc7a8b8fde85229d42896abbe913b23ec32a136ae3117fdbeca943f91db8c5c41d0037e8a7bf42eba1df45295ed7cc876cda4b07e25106f97435614200e2a74c5781987770c2d0157e558cb64c20029d6774853e2c5da3da0a0973d4bd53e35f96c171002e4312fa6c518fc909690b8fd06436e5b8da9dc297c8cdb7146daa29ad15eefb0f2168b8a3a6c7243a8714106d35adaa29206ad2509ee61f082c5739385d9fcb0b2ab0f5fc8dab55dc670484871c69fcd361987ff1cb6797ae3e51d9974ca6b5087f9a229519e9008ccbef4ab6daa24fcae95be3c4a1167b5e1c460da56b642362e7ed8c7eba8100d793e52bab2082b40e3d8340905dd4dbf660119081160739b281cd16f7a8bd020f69e06aa79505870771fa4219008b9d1ca1b0bd28afe029f299e037dd82c0aa17781009591ce628242f74a0ba1526c100e26caba892868da9680b07904545aeda84154384886a4d55118e7948fa2cdaa586f29c25e4fa317ecd3a995c793921106a7d8dc3b2fe3432214bb339614a579661dbbbf07104afa6ad0201ad4b6fd80e90427e6102eb1c02c4d62fbc25464760b6368da0fcb26cb5903eadf6d284328d9867ce610a026d65c1f80a4c7482799e1d3827f945dc6f4a49d6e6667ac5ade72d8804a81830d49c85bd9c431d38372a90198463d2f17a10f1961aa01d0495bf6e8c098248ae5d0740d7c7b266481438e49bf44edf5f9ef345920339a60495c70613aa2ce2988ca67e66572267dcb1aeeaa6146a2a6e69bbe60243fbe2141a6ff802bd581a4d8b351558608ad1db2f0a818c7fea8b49d3e3b17779ce6b5a84a100f368826b15462f0b9f466a947171ac8c0f214f5e25d2c9fe3374e4b121c82d26b45a6fd122662880966b07ca3ea54d1a6c98ae4071866a2c028bd745fd5c91eec2164bb00c1d19131769d196b8f513cec2dbdc562ca2d82261860115d693e232ada6f8446c073e4c1529d34479a5640c648b0b74d1da3a480941ea584d42608bb8e7ddceaed49a9d81d30654866abb70e1924db0c615932f463b749253a4981050ea498ada4edd6728a44538f7982e1b6927d637da0ebb593aa5fa1813c7834027309d1212c7fa29f7204d1da46de261250ad8c0bb725f46742c14f0881d88702fa43efa706406e7c5082bd82a03c92240a01c115a6faef5830ab109491aeadb01ec562b67fc5ac3c529a9db48369788369013d4d298ac375ed33e44371a31b21585c7112c85aae85ea7206c28ee48a7c253561efd56d7652da8b72d082ed40ebc595d6bd2942440ae674804016a6e5d
+OutRec = 0040001000040001c00010000c0000800020000c000180001000040003c0001000080001800030000c000300002000040000400030000c0001400010000c0001c00020000000034000000000000000002000080000000030000c00018000300000000140001000080001c000200004000380001000000001c00000000c00008000200008000080003000080003c00030000400014000100004000280000000000002800020000000030000000000000000002000040000400000000c00010000000008000040003000080000c00000000c000180002000000002c00010000c0003400020000000004000200000000300002000000001c00000000c00004000300008000000000000080003c0003000000002000010000c000340002000040002c00000000000038000100004000280002000000000c00030000400034000200008000280001000080003c0002000080003400000000c0000800010000c0001c0003000080003c0000000040003800000000c000280002000040002000020000c00000000000000000100001000080001000000000c000340000000000003c00020000000030000000008000040001000040001c00010000c0002c0003000080002800020000c0001400000000400004000200008000380000000040001800000000400014000000000000040003000080001000020000c0002800020000c0000c0003000000001000030000c0001c00030000c000280002000080000000030000c0000c000200004000200000000000001c00000000c0001c000300000000140002000080000400000000400010000000004000300003000040002c00020000c0003c000000008000280001000080003400000000000038000300004000380001000080000c0001000040000c00010000c00028000200008000340001000040000800020000c00024000000004000380000000000001c000300008000300001000000000c00010000c0003c0002000000003c000000008000280003000040003000020000400034000000008000300003000040001800000000c000300000000000003400010000c0003400020000c0002400010000c000140000000000003400000000c0001400030000c0000c00020000c0001400020000c000300003000000003c00000000c0000000030000c0000800020000400028000300000000240003000080003c00000000c00008000000004000100001000080002c0001000040003000020000c000280001000000001000020000c0001800000000c0000400010000c00030000100004000080002000080001800030000c0002c00030000c0002000030000c0000c0000000080003c0001000080001c0003000000000800020000c00018000000004000040000000000003c000200008000380000000000000000020000c0001000030000c0000c00020000c0003800010000800004000100008000380002000000003800010000c0002800020000000008000300008000340003000000002c00010000c000300001000080003c0003000040001c0003000040002000010000400010000100000000140001000080003c000200008000100001000000001c000100008000380000000000001400010000400020000100000000300001000040002800010000800000000200008000040003000040002800010000c0000400030000c000200001000000002c000100008000080000000000003000010000c0002800020000c0001000010000c0002800000000000038000200000000080001000040000800020000c0003000000000000010000300004000100001000000000800000000c00008000200004000040001000040002400030000400038000000000000140001000000002000010000c0002400000000000008000200000000280002000000001c0001000040001800020000c00038000100008000040003000040002c0003000040002000020000800030000200004000340002000040001c000200008000300003000040003800030000400008000100000000100001000000000c0002000040003400020000c000100002000080002c00020000000014000200004000000000000080002c0001000040000c0001000000000c000100004000340000000080001c00010000c0000c000300004000180003000000003800020000c000080003000040001000000000c0001400010000000010000100004000240000000000003c0003000000001400020000c0003c000300008000100003000080003c00010000800038000200008000380000000040002c0001000080000c000300004000280002000000001400030000c000040000000000000400000000c000140000000000002800030000c0001c00000000c000300001000000001800020000000018000300000000000001000080003400020000c0000c0003000000002400010000000008000000008000380001000080000400010000c00
+Key = 11e452a7b206e159ac85ea8b6553d01e246d084cad52fb7b29028d79962091dd
+
+InNoiseS = 2e6f8b71cc4ab67f9816984bce92458263794396bd66ec320565045122d1a427408678dc565386f2f993fb14e1422366ade64536811cf943271a185b747eb2d62d13b6d5028b755179d538f915bce3fd7b1e4a2d6d4e6bf29d06554a010502a70a516fd7c6564b323723eb2a8570ceb98603208a349c685ddc1366b55da84b801ec8a5ea3882c6668a394d98b4a1036946ad618f1cf427a9a05676dbc615acb25c53cb83a117964065618b213f1e4851dcf2663638315859704a44b5785bcff0f7fd2a6eff292c2950fc817d5a4b7bccd014d95c4565abf86a6e8cd2b32e9594482e46e505e57932d30ed6639853c74ff2138b122fc46f54c183f11858ebdb2b871ca916109922ea7e3556e63d95028c62d2652c0b9f35af121da795121d5872043711b6a56639e169eb41d9780f6462d140cc7ddeabaed49d9c4e4284d07132d92fc39b98a5c5cd278023e3a1fdfd8875e0a7a2effe4dd3e2897be58520d99c36308caead22987d959a480db2cb76488cf14e4c9bc92887d5107c6df91ab69abd9a11a50a91b41138c22ed8281c58ae49a512c5c203f563bc7950147ded01a7078f8ebeb324e6e305295522df6eb91035ace84be894fa824fe6415b664e1873f3a4ace6f2f5aaad6d121a489688d3c7d307ab2414b79822305f8842339540f42e089df2c1bf0620ec7a306f36b2d4b27c72439875109d6dfbcbc43358f068108555e0f7e2b047140a589cc4be815227c9a29eaf7914e381513e5d9d00fd3296ee894c9641d2b00e79f62f2f62d8b5ade28bdc26fc6e3711c2fe3694ec9c461e28b5524c59fd2a0ff2ff599c04d8b882f23a5ecf917d080130214c262d3826a616f093acfb64fc6c9c82c36708a628c652cbf0ec8911e902caa2e805268b8144e595f1bbfcccbdb8b7a64af5e101fb113e8abec686c1ee7c2a539593b6f80549be9d8b814f360d71d6bbeb569db2e94d52405b8895da9a02495a01ac93ce9847503e107f6b81fa598c539409a7873af606315f82b9eac49b68a6b9f214a84d58083e067edd52d167d1ea65969cb7a40299062a732d2fbfb26139570c97151187741b9d020113651e2ed0cc279893348b2592531a6a1874c317ec638b42339890205705a52099aebb745f2689c54954f32620598048557aafd940650451b5a0e246f683e507d72080ac8b92ea399023f4ca93dbfb54637cd0301171d124d34a48f0db1a2c5f5ae5725271249a1198347b724b22817f649fcc4b02ec374b10b0524e08a9a41771741c2234d6324856c1aad86051d831e62333162aa2a32905d618e76c353a496829e3cc7a07a66b975364907e6da5d983e65004a392b1b8ce692ce1b24030a6756d60f6972a2e8aefef7d761e15645043d7720d1d756d1713b06c16712716f9204e29b2f8a45172b0498328a0d1b8a7a664079123b9851059add99e2209b4911359f42659e24def8cda7bd4da1ae34fa7669f8218d786b8b9ca16520ad54b5553b92cc99541e6f51caec0176729687977979c4726abf5321344edd66f0e03bea512c6dd54b9d6c80f932d4e58e75f8bf97b3e0e15e412704b691334d10541cb7037eb653f084d96afa4c3ab78d2468e4242fbdb24b05db81815280ef458871dbad0c938719a855d80c3392506ac313b755e13e6d587d0e9c11775e8d588cb048f60c64c564024570b474ab83d9a8d2fc7a0eb465803aa2b643a15c59e3f156ad133aca6c9c968d1493d601fa59591c8d0aea49a697a2e7426c36d24f343b292ed2201bb1f2638a2923c8220e0321f081cf465f98b5f69ff3ab78574646e828487f40c6f4d7c28be30391f083e78640a28f7066ab9aac6138a106dc9c3497c38efbcf007062de29a4b7a38397d0305a04b5fca5f51ddf6b026dd9aa1ef88a394aea54f20be3800d488af630522dfbe8306a10f7178ce06c097a3d7ca62b7169365486b4a23c52c1017fd4513268e4a20c5702b8d624d028098bed550389ad8b987c26a0a0bca7478f3c8b5a4c926a2c10c34662de11b7a260539727e75304c0c28b15e7cc6105da18ab6ba720eb6e0bfce3b220f7f68bcbd845ac8c7d166a837c46714721c227b5bd263d2a6fd54c7a7f26267597953943ef22cb9607f65eb829b5e4ae84b1a263c69a77b16827a7dda44bad604831dee420100d2ab45d822cca55378fffc7377d57c381dd92661eb2271599a68f4a5c4811ad16f27c16103ee9e7a802e9011f7fa542f4799d65c448245424c9698fd3d10cde7cbcf6885f6d630e1a7248ca7ab16b6cd8d262e1cc20243d46c5e1c2aa508c22b6aacfa0a4b8c60e2056bc3365c5f3acc45c61b2d12778bdbaac7744423af4b32f52eafd9a7835400ae42d424d8a46c0c03acefe9a684f903f5c8761616cc82e05de264cb7278529f3c3255b8095f64a2f3f5299b3365efb356d856b04731a8c77845336db8c1952a6ee91b64578d620af6052a700989a2338041e767098c996ce97a6f9907c284bd4acd688937617003afb95af11447629d71222919bcd5b4204a
+InPK = ac839551f2d26b42e6bab93668afac931834e5d0230e84f450cb25ae52a0e32850da5f44d42cda563e95a64f0e18636a43c50e0d79a7d69a15c5a43a9d2d8db99bd0a43d3d60cecd0ae499aa5c2280daa1ca09b927a8e84abd068e684d0f025d606f60632d85f70e7301444d1495351d018c690aa2ac9e8da8d598dafc87d4921adb9eec3818d91e981da53a9be7fb9053f5a0b107225bff688e01eb1dd0245d30fb2680b2baad0e81495bd21a0d5cf24b96b830b12971a0478902bd6277104e3b11e138b523e5d9d8d6bb4d099c66e92693371558b2ee3222f58db087a1ba2953c8a147b8b21714ece87242d47523c004071306b6eb14358be901b0a88d9e12ccc682d204533a2fe87b578b449bd88a6af1a1c0787a8914dc85ee81ae6cbd53a0f0cbbb3d7aa8965bd7c34c6507d3709211129d802c2eab3e3e1a589948130665b4ff9cb9a050701a0aa3dc62b4999b29a4b604205c0f995d27411260bd93abc5d2566a4b9141c75ba03e28e3223ed9a661bfa9589826a10d525b5332b59f6163ce559ac3cb9cb0352b55d633d5517885c0bb9ea5aeef9f0a586fc0a171ae5b5bf7f6576caa6067b76ab5682a8260d0be3c80219ec7746a9accc6ad47d2994615cae6590214b29f230cb881ec7d59c29be2c5380e3c15ef34a3543dc751e2182a4e397c6d02b0df746741cebc41e6d59f045e8a71086140c212aae224d53eda4812d3ee2c120ceaf7d82814a163dd23682f6902320372e3dacd1cdd4b2d835d493300ec572944d44ee0892d712c144c4706ac47a5307abc08f9f0fd905a6b26af28c050232fe707e08c8217774612e9d5e9206697b8612bf2bff7d50282683ca6d3ecb088bd3eb917e37e4a449a294c6bfa5b6519a0dca0101872c10efed1d9607b102cdacdd893c72e804a96781ad08c89966fb07591696a389948363450bbda9b903aec4d47be629143d7ba1b2f260b88dcd182d345aec4a928766c5bd89b35980fcddae4b80f322e9d2b87d0dd9539330d82c930b15e0bd9b05a73fe6426e9da685b540e3c1d35448aa4a0119bfa30c6326877abf850ed1822ae000132b1501a69865329c74a2b03eea490f6fd1891214d73ba6a4ca5e0db87c70c63a619f7075d348969eb46bb9f5d34926df75586fa49f3cc3975053eba33107a714d627075883bc44f6267ce16971ac5f0ad3c481f421afc9c1a12aef556392d2497ef884abc7a8b8fde85229d42896abbe913b23ec32a136ae3117fdbeca943f91db8c5c41d0037e8a7bf42eba1df45295ed7cc876cda4b07e25106f97435614200e2a74c5781987770c2d0157e558cb64c20029d6774853e2c5da3da0a0973d4bd53e35f96c171002e4312fa6c518fc909690b8fd06436e5b8da9dc297c8cdb7146daa29ad15eefb0f2168b8a3a6c7243a8714106d35adaa29206ad2509ee61f082c5739385d9fcb0b2ab0f5fc8dab55dc670484871c69fcd361987ff1cb6797ae3e51d9974ca6b5087f9a229519e9008ccbef4ab6daa24fcae95be3c4a1167b5e1c460da56b642362e7ed8c7eba8100d793e52bab2082b40e3d8340905dd4dbf660119081160739b281cd16f7a8bd020f69e06aa79505870771fa4219008b9d1ca1b0bd28afe029f299e037dd82c0aa17781009591ce628242f74a0ba1526c100e26caba892868da9680b07904545aeda84154384886a4d55118e7948fa2cdaa586f29c25e4fa317ecd3a995c793921106a7d8dc3b2fe3432214bb339614a579661dbbbf07104afa6ad0201ad4b6fd80e90427e6102eb1c02c4d62fbc25464760b6368da0fcb26cb5903eadf6d284328d9867ce610a026d65c1f80a4c7482799e1d3827f945dc6f4a49d6e6667ac5ade72d8804a81830d49c85bd9c431d38372a90198463d2f17a10f1961aa01d0495bf6e8c098248ae5d0740d7c7b266481438e49bf44edf5f9ef345920339a60495c70613aa2ce2988ca67e66572267dcb1aeeaa6146a2a6e69bbe60243fbe2141a6ff802bd581a4d8b351558608ad1db2f0a818c7fea8b49d3e3b17779ce6b5a84a100f368826b15462f0b9f466a947171ac8c0f214f5e25d2c9fe3374e4b121c82d26b45a6fd122662880966b07ca3ea54d1a6c98ae4071866a2c028bd745fd5c91eec2164bb00c1d19131769d196b8f513cec2dbdc562ca2d82261860115d693e232ada6f8446c073e4c1529d34479a5640c648b0b74d1da3a480941ea584d42608bb8e7ddceaed49a9d81d30654866abb70e1924db0c615932f463b749253a4981050ea498ada4edd6728a44538f7982e1b6927d637da0ebb593aa5fa1813c7834027309d1212c7fa29f7204d1da46de261250ad8c0bb725f46742c14f0881d88702fa43efa706406e7c5082bd82a03c92240a01c115a6faef5830ab109491aeadb01ec562b67fc5ac3c529a9db48369788369013d4d298ac375ed33e44371a31b21585c7112c85aae85ea7206c28ee48a7c253561efd56d7652da8b72d082ed40ebc595d6bd2942440ae674804016a6e5d
+InRec = 0040001000040001c00010000c0000800020000c000180001000040003c0001000080001800030000c000300002000040000400030000c0001400010000c0001c00020000000034000000000000000002000080000000030000c00018000300000000140001000080001c000200004000380001000000001c00000000c00008000200008000080003000080003c00030000400014000100004000280000000000002800020000000030000000000000000002000040000400000000c00010000000008000040003000080000c00000000c000180002000000002c00010000c0003400020000000004000200000000300002000000001c00000000c00004000300008000000000000080003c0003000000002000010000c000340002000040002c00000000000038000100004000280002000000000c00030000400034000200008000280001000080003c0002000080003400000000c0000800010000c0001c0003000080003c0000000040003800000000c000280002000040002000020000c00000000000000000100001000080001000000000c000340000000000003c00020000000030000000008000040001000040001c00010000c0002c0003000080002800020000c0001400000000400004000200008000380000000040001800000000400014000000000000040003000080001000020000c0002800020000c0000c0003000000001000030000c0001c00030000c000280002000080000000030000c0000c000200004000200000000000001c00000000c0001c000300000000140002000080000400000000400010000000004000300003000040002c00020000c0003c000000008000280001000080003400000000000038000300004000380001000080000c0001000040000c00010000c00028000200008000340001000040000800020000c00024000000004000380000000000001c000300008000300001000000000c00010000c0003c0002000000003c000000008000280003000040003000020000400034000000008000300003000040001800000000c000300000000000003400010000c0003400020000c0002400010000c000140000000000003400000000c0001400030000c0000c00020000c0001400020000c000300003000000003c00000000c0000000030000c0000800020000400028000300000000240003000080003c00000000c00008000000004000100001000080002c0001000040003000020000c000280001000000001000020000c0001800000000c0000400010000c00030000100004000080002000080001800030000c0002c00030000c0002000030000c0000c0000000080003c0001000080001c0003000000000800020000c00018000000004000040000000000003c000200008000380000000000000000020000c0001000030000c0000c00020000c0003800010000800004000100008000380002000000003800010000c0002800020000000008000300008000340003000000002c00010000c000300001000080003c0003000040001c0003000040002000010000400010000100000000140001000080003c000200008000100001000000001c000100008000380000000000001400010000400020000100000000300001000040002800010000800000000200008000040003000040002800010000c0000400030000c000200001000000002c000100008000080000000000003000010000c0002800020000c0001000010000c0002800000000000038000200000000080001000040000800020000c0003000000000000010000300004000100001000000000800000000c00008000200004000040001000040002400030000400038000000000000140001000000002000010000c0002400000000000008000200000000280002000000001c0001000040001800020000c00038000100008000040003000040002c0003000040002000020000800030000200004000340002000040001c000200008000300003000040003800030000400008000100000000100001000000000c0002000040003400020000c000100002000080002c00020000000014000200004000000000000080002c0001000040000c0001000000000c000100004000340000000080001c00010000c0000c000300004000180003000000003800020000c000080003000040001000000000c0001400010000000010000100004000240000000000003c0003000000001400020000c0003c000300008000100003000080003c00010000800038000200008000380000000040002c0001000080000c000300004000280002000000001400030000c000040000000000000400000000c000140000000000002800030000c0001c00000000c000300001000000001800020000000018000300000000000001000080003400020000c0000c0003000000002400010000000008000000008000380001000080000400010000c00
+Key = 11e452a7b206e159ac85ea8b6553d01e246d084cad52fb7b29028d79962091dd
+
+InRandA = 16598e075b0e7c09cd899080a945dbe249066492b8c9829f42e7d131c5017540839464989c68ba38dd2365e97c6b03c83f2fa68c84cb8c70a05e961772ccaf358dbbea4f043fa5d8db73c062932cce55f07ec98cfd84b1b2d13c33e94d94a616318b1e400f42b7424e256655d1d810114842d92882dd4d286a2f9ae8e065bac291bb133d462c531c4b902a664d5d31817828ae784b9dd1cdf193824f5578345a33b34a07e7add5246d933330f9a25b72c79f57920da7be25408b26b42a142248c4bec048ada2ff02fbd9414ac16c490ca636082e27c7e502a3a027c822b0bc558d0a48680d89ace313195b8bbd5e7d144d394890594a07e8a6f266562c628744a1e85492e97bd9444d7a69dc74c3005053d81ce2f358d54c84159f48c0f26c3e58aa2a3fc012fa5ada92e0ee63a39c189b61b129fea5ea2243e077e598f9e2dc95a8e31c632ab1b975740685e5d389b785cb95e572e6951f11e401d598b359464a0645882375c667e416c4b2b684269235a29890d85cf6c16c554501f709d09654a6001ac7a2ae52e3c3f275e01eb0366ff80bc34d96a6a877a925690ead51da259710bbcc1c4675b9a97ce6e8b93b4a4c93e7d95ba2ca42adc3a0a5431b05b0e818a04a655db5986514d3b9b905e50c0e9919818efa1d867ab90e190b0fd55704f18791143822a771711289a7009d2c0eff5e09f99c520ce791ba00c8046a0f5e2f30af489c565229f99bc66a42608345769a353f4079906d6d27334a5b11eee821a398b56ab310791d86d5b2925c62ed2d17e28fb89720d180654c394de526dc1558545a796807d33f86ae96953d06dd2a5913a0b9a99846960ac6f6453a125eaa0f4e475a82149485569bd5261084e76dca5291548ccd22f4a2f218d5084342387c1a78a04403c1b8215a9899859e5c1c75e359cace8069e4c85aa8b6a846218a4338ac58447758cd2807c8b1cedbf0319fba190d49dcc554788558c943c65ab65edb113e3656ca1ba6c6344910d26a441f41426afd7bfa103353037057396ad70237d854ee80661a406d0b85c29bca460cb44b5e90e500d10c9dd106d1a10d49b4046178ce003b18eac14517c5aeb2854ef8fcd6362a0e3513cfd24c1f151045f0f1a7fb1554283a5682ed6e75f1a0edbad88f822632b90be8d458c6dcbe1f865f4b265ab27e2fc4bec75eee311261e3f52264014656094205b193315be6a3e5114663429e8823697d504b71fa9ad615acdd36625720ab40956501d998a3fe8037c7bb75032a4d53767b701ab3c150179bd50aa5553a4a272e48c71539d7da256e041ddd9a85b0a8d9dcdbcbdff94d80a4d8e5cefd292fe938f04cad77ba2ac86b57dc5660ee05f7220812ba6a70a2ca1cbc5f1736a5cf293f1acf96268df65e3e92362843d81337c88053aeed7ab2831b98f8494190eff3272d687c171af50468c49578a05a7be6c237460f93f9ab7553981761d483064233e7d4fad5104f5b001ac03ede1776ec0096ba323b765ea74a8c2d9a0d91e130ac9a4807dc6a8376fc362f4645d614d80f3f55e2cb49866a62ada62ae74d9288160bd5cc1d49b88a3326c5f447f9d47405a1b8b9eb23bd03c03e207c09cb59cd4dab8755d8d016bd198e45d1d5ec6017a61fed12b719970fda2a89874662a7e16ea11b185377c37977a1ed0af78fa3042dc17e192e4b3b2f7212964e36d357555d445348c2759d8e3bc1ba94d9e047ad8a40a05bae9f918187039bed17086ea457d1954d4c5575e9ca58040c129bc6fef20fe628d6d8eddead751729fa7d710802db77c1cdc47176512b098fc524024448230e4e95880fb5e375fa7f8300ff67b05861b605636aa04c167b4700b50656054c4ca323534921679aebb3be185412cd9ec0218046e224cd1b886d6a74d0e4479fe502d7038ea08a9a67da97eaf09e59046f6efa65348085d80d1832ed720eefc294365dad860b4afb412a0d7109e90f224cf87fc84338e15ad99e4d523651e0202aca201e98c9e440a4a07274c8dc95146a2e37a8841b6b6d48431f88373ecb7ff13b2c1c366aacf477e58a33af37c3ad1e8e708a10e5685878ce5db4074838b68907176239b6bfba643d88aac92bde285cf142952a135fce2308d9bcfcdb21955eb0342b6f9f18caf8b6f408c6c15cb976108097ba52ca2af509b489d379b27deb0470e6c40cd62021a74cedaae3dda546f6b86c1e5271d011d9145c55d407b359141d5cfeab5c820f221d199764fa369242efdae1210dd7e4cc66c3deb0ba8442bbd27c0e688415f2ddb961e72044b8846c911816b87384260dc81b717a5eed06724e8d5334008fcce70985b3c29166cd5f01e2901f44ce0f75ce0038d48353c2e7512bbc5acce012b90984d2558386a2a33a2e69a3c68e3daf841876a4a668f25cb061b1dc289c863b050351a0ddd787e3f9711d92e61037f180b0820adab8afd5a5fd2e7f198e6e1b9c8291012ef543585371128c62917167ba43a96aa42b296958753a91d16f5cba922d58cd8d2d1621922d
+InNoiseS = 819fc864be3149721adb2aafc882e380dcf06d756412c8a01283e20e6ac1a396c0e14228016352fab19a6b41009a054ebc5ad9a4dbb34014e1df2a7388be6d9593d71860109479801ea9c464ba476edb713664a3245822999c2d8490db2aa7874aaaaf4cc0a1a3fc4617ed5c86f25985078fe7d6f791984d55944621aa86fa6d07763f2e57122e50d89235b3a5ad9bc47684b5f1a0d9005b059b70038f319e31137bc116d7229cab130a331403eaa76aa2a5225b7c9e7f57470b029ebd8a402f55a83e10d6290c391cb90c549c1de65bf83ac64253674c2804701c5bb1e616bc806b72224d8d1c43e049ca146cae42c75569c6797073dcde9028345ce38021a535daa7288018e56b16406a4e8869bbc656070e2699625d14ba996e81431a2d0a14e2405a082e40e13fa2b37a1ecf9a3923a68e1d990b812a1ffe9a674df40029747d846ffc894238b9279901c21489b975aa670448a4766a484918ed7551f9ee7a66bc26b88b002c7bd8f51f9b8c42a8e3ba214815bd687648459f10f2a391856ec3c5bc1a358980b1aea10ab26e430663ecc38018323f2c36daafaa1ce252774913ac30b6d27564c5c20e11e74606b1c1075ba60e451756591d443ec60ce49398d7b4ba3dd000630aab95b8111652e0c110fc04059a68a5c17c5e0a8382f3a32de475f01082a2fe62264b6841a44da669475348dbfda93a9304c502abf4b1710a5b27cc39a8f0e705a4633c5fc65951e4c7f86525c0d760079a75aa587a32ff0e9b82ccfb324a7e8abe9eadb940e10da2ce00f82362b26e8447a1eba21643c0b0e02a2d1190ef51db4a5969aa5c50d2bbe64d8fce2186f2647dff4aea76b78d33fbdf7d74bfca0cb20125eb5a74b1b26d68e3531db09f634bd134603438492df7c4d1a7402f7559e0a4ac8b8e0c417569478eae95226a747d7ead94390c5633041b27559d1e27bfe9104209897e3700edeba72d6f496cd87b7d446a1569b490dd8abadea4096b67396ec8c269bbb7f264bc9d9af9423829a149c3433b215528a90bb1a44878a2c84a35e23220eace1072dbb03c7c1f6059da627e9ca408c572b03ba1ee726739d8b32229f4ebc87c9b7fddff1652a24d02868c50f7cca61da9fdcabf6e733a1d90fa49d66fe8e73d80b0b6a567ace5b62b4e12cf1c5e738199881795ceabe2a517ab2009a90999ac002a40147ec93511e5b484b38213b09200549e1e386b9aad924605721498c0c2105a5129c0877aefdc25319380735eaa680a97c0b51abca6605a9af4d9167e87cb14a6c7424b4d427fe4db4e5fe9867004833a159069a3f6592c232a4e2db38512bee2a9b991d415352b26d83115e92d6567e0d943c67f8ae7b694c1e6beb1e857267311310426713a842e46aec68c0b4e9825a3133273c76475804aed47f31c36f8eba860a600967953152372cc1cdf893e325ec92d14ca45a9135a9c5b5cab4413fdac9f90cbd74be6beeacb6b248d328f081efbe6f268672cc244c04fd6509f2df12628b4a1c9e614eb1c6157d8981e9a6a019e2cd745733765582e92a518b2785056c7e932fc860f162c4c62e738baef86e588e3155515e0fedb0bcd997094d93b122d7d54c01296704e38b4ee47d0b67d5cc784f95a3b845969c1cf9ae3364a314f8aab0a19279c1784f6dfdc77c4e65fe5f43a77a8cabed319cd69ce96ebe04b254465da81e561103b242a2ca971927371d985327b850c998965327d18273f66c4f98281070e940ddbe46e8a4dac8130c4690b561f7193b3518cc464f096e720097dab1a17b4d4bb2ad6abf84b39246f470fe4589410a52888c6c00163d16df7c2225ea8071b9154a0fa340a29cc4bae8a37640c86f9ee7ebb1fda52040b09979a85a1b09f5432c884296191167e1802949857d1490c862ebaf40104a9cd22425338a27de46c08e34299090679fb115d473947831052dd883805d70625944e1723de9217857ab05aa2f70461982527d7d07db403b960800991fa06d7299a77447043eacdb52036082403867f0a182031179cedf1de9d0a5da71782718d6c874dd359be309f7090a94835e10f732c9dc9dff59abe1ed8441680117811f2d909d53a29a26bf47756444424f548e89abebaa25652e10c6373127e489d0d2123e278d05c842ac99ec321b6ed6af94eafc6216a54f62f00e0dfdd44b40eaf85cbed5819c0e553537182b1d9f9548c0e08845ffe8aa53631f76814d759a55fc9d020d2148415b61634864e6e590f5fec73cbca732c1fd19329d90e7821dd106515442d4698b957f697b2c9fb652826283287a064ae861c9c96c58261c20c51d642c5e0e09e84288dc2fd16550787a8d6b1929adfeb1b2392854977ade19af270825f9a20c6c2c5685b08b4f7c27123494a0365bdf50d8acc29f53afe2ee3a743c0b19d7d6613a39a19a20884d98086a5ae633e1a150a2fe2ad5853614b3ce94fbe401be3223d260a5a6994c321366e6daeb06f166989acf825aede985d4ab7b1948d81f7eb27e946948f5dec13765bd203
+InNoiseE = dc9f14a1206da08c2b96b75e5d74d3c5c6b5f5583beb6d67d5db42b7529d062a43192d945a769500e257641e1eb74db99eff89ce0812c958738c45d753c8389d535e1595467b57cd6e75ddf9ae2eeabec6d119545bee4a6196916c14ef934756eaa4d015a783ae9940728d687223447c041c8f60fcf4440cd1c9f138724147a17c2406e57b5a054230653890a014e2200fda3ed3ad0c53ed18aa00a861b66c0c1be983737326320dcc84f914fde4157c48aee7686552c2261e580d988677c1ea18d7e04b711932d0789075b3d67ef34b1e1745c7fc597dc422258faab8edd85d2917b762136a62d5a61df989629f3996cf24d7d240d4d2e5270b5927b727a242f16584c15a142a5fb87b955c5da059b82bdd509374d53e90c5899504c506979f4a000287b8b7f3ce8d64bd066bae117ef3b4cc0caa97dd8614f02cdb57559a11bc222e5cf882026c3597471cba5cb653c665db66abe67073cac8d2c8325d5cc5d259a5a88a1a03e6f8d7c9a7991b83f2fff57054acd8e0434d1729989d0b7b4d27802550654719b79a55abe58736a4646e36d2a5e19307517ddb4b2c69f9203a18b07cadc39603c759f100b28f9c744345085e86f578829a3c0c0136c75dd209615cc399276171e448b626181aa575a7ada14b7865ce62b06363995a0a0d78e07414204b9e1af8d78c3a27d9c9ba54401744ccfd969efd00cf4f5e96c2e84510006a52908881b0a04ac9bb31b2234f769791e92dee6dfa77d71aa97c56caa98b3e4b5029324b570da91d0a4a64f4f518e4e7d660a368514a8750306af83e034d4e975f58765381a7e5dec50c91a68548352e8fdb40d000a50da373a1ddf1eb2227f6004410fd351756e2c760db9e038e9a0d69820c69ea177345b70e72d0edae137446b6b1a7d584fdaa4a50e5af7ba61c5c1386fcfb2325b87546ce1a7901148edd875b5e1693196d7f29c67caa9ee9e604ee0051792302fa7ab812a86b811590deade5a89be2e1c61e6942c8e0bcb2a5435dac7333688b98155b52936c79b3e67753ddd612e5486fa59d92763fceda460d1d59381203fb4bb13b8567f8c5e67e4addc587d9dc78923f0ba902cf015b43a7976751042dd05d3fe87fe0abdf41a4272de09d090831035d094c05528101dffc53501698938bb9a0889fbe266c1a134cd13173883104a5c830f49671923bea9f66507653f2e59f20ffc9bffe43149354198f24d52118bfa0a07f551eba245d46328f5bb79920816d025b28f90d68dca36bca1b393db89d028ab2264c00e3a03a7a74361c25ea962bc147aa255bc3bf2c77d6666e90d304b1298044ebb50076c69f08669269b2b2a7a846ae7687facc9d99d61a24c7d891b6e3e6a78be9343b1f269d6ea8f6a4d588115051bb453c2d34346b7a79a58556af009789ea260e668d721a2dd14f429fd991d2dab08ca44234ef7896eb097f2841493f565f5eb649a0b39425af5a19d089e3c4f8381c2e38dde698602229a5a613884a92517393de89e3f234930fc3c7da7b7299566678371b62a790c3cd64565e13279015e537fc63f64ac4b96ee285de818ea8dcd6942862c83b377cb0d609db996ad60c2d5023ab5c6aa004acb86271a03f8e5c8e514d602662e42a106a7602ede316d3a7e919b7984004d2aa8494644a5390418174668b4b48104f86d795c02aa93768c0bcc97721af092017faa5720a93ac8218b3c855460c529b5184a70fe4ed355b6e1fe00dac5942995d9c6f3eb5501975e22cee248321b59b563c913b7027bb10f3716fb294d6dea9a52bdc8258689461c92016d8de9bbb8390344b9506e07f2d2c95245a8762827f034ab6e53f38a8aba872aaefd589ab6c86526f6146e94af09417a48a04eae574ffe533a3c53fe9027a0401aec5453b0213d49917f1ff3294cb9d911540a88b630cb7a4bf0057ff29b983bac2102ea58acad6ee9cdb1536cb7e7203b09c41bb856471b9d0ab34d965405f6ca24854f4188b2854e20fad6ae8c404438b82214f62cb51ed5d5215c430dace71863c580653ad309f6f57bc0904fe9eab19ba11ec50560ac22860d8086a8388c4c2682480fd279c065c49ae208d96f813669141199af5786eb58e94d946db10b4dc5dea981fd16eee5dabdb6a464ad963c55204f5ae74085cb02e280e10a6a588fce4b437c804550058a89206401ad81d8b75067648d3ec385e469977e55e9fe2a37200dfdeb3b02ab55178ad12ad6ee99572423088aff8253681a19d4a1d699d554b1ba265a196717aa00d4783b8a47c03a42fa06c64a864157884e740378be46f772c092f6fd06f39d44850639e8dd19af8a2a1e8344a2b786bf7d7ca2450c04965e049919acc92d2d2ca212b5c3be0d035010bc478e028f390147800bb62560974c9222cd0e455d7ca5b6f6e5b87b386a6ac44b054f0f416550260a7fcc22465e7cb3200e297144db7e1f5609ddc00bb25bc753329a4c764f29c2f6bdcafd2fba66e6809c32124c5417741744090ce1b6828d00370e6b760a09da6f73089
+OutPK = 7b4db63984b59c5f4c76202fbdb360ed6a27ee1d9395e7721787e4b0d7ed20c9937214a4690ae10bce3a621f08d37706945b1912e0dfa911bde2a1099ac611131dcff41abe5a16d33978094874b852743799d6316c873bf2f8e17827ddac9b33da6a4a5229e01e6d85f1973f4aa7cdbb45934dcb680a625fc4a715dfc0804e8a2f644694390c14e053a8ea5e65a4168a52629fece156b3ab995ac385c7a8ab0c60969ae05563956fd0a3f1d5b009a05a5c1ac384f85c8bafcb9bc3d856de6f39e8c7f908d7acd743ee058e38cad1b0640c0ccd2e5a13e640bdac1dbac4a08cba19038f49175817e00d69092b26395a96be87af3c8bc08cddf4faf21c19147e08eb1d796ec96c624b657687552b702164705782cda3142213254414a6bf0d17edaa692690ba78c4e46ab936d03a7dd785f27576754a0dfa5079517c0b264a20f65c1ea211870a0af071e2234e967a70945e01fb9460cc9b49d66e1b253a2fb709d674c45e588f2420013abe918e4c09f9e1e9aaf0d91daafb158193c14e8622b583dea1a3a8f6997ac5cbf640d0504e3629b1387e70286a244300b4141cbf9e45d87ec26992ecd7b44de2a2b02fd2aacc9565c990c0e300407255e04901102446e3d128aa684d878a1a5d087b51af20907ddaa44190d7113d7af655b7e2244a96b1117df9ce63e5d4612ed0d953358e81178b65f0c46d5e8abf414518169e5726247cc0298d140f2ced8059baadddc21a1521468a0887b09860f8011defcf06879573aac97a8084aea2b915cab6c4f900de1fb7e164b97976219178e4a17abc1a8c3938e1744a240f7446627549176f66c2e946becbaa200c90ba07a892607910363558ca43a9da560b8742667dc981b842dd07b76d2bd1abdc005bc1b1b587b3a3ae4d39bb4d7c218ad27acd522d71dbe953964468e15cb5464042b45118eaaa5fab1d3bbc917d9b57b33be2e56dc062804bb5064fd48b6d68dad551e12ff329fdc5971813121aa4c48fb75f30236d4946d593c8a295900f6a49f143d62a5a682ce686eee16457ef90380cb61d09a1ca514c4646ae5f0a1448c5bec2996f1328da72809e3f0a13344d5e6699786b386211e170b44cfd985ed473ba2a962e4c6b6170a53c638584dcf0438516cbac9ac1c028159087d17b8b403a949a50a0d170aa7d66cd5a97c83231012fa4c49a724b01caf7839a45655df3f7f9caaa192d94e9b40d05352137a9d2906712c25bda8c5522a59f8b190c400b2febbdcb1cd0154e1fe59935842a3cca3aca97fa46fc081a08a37aa6b310e6d07f3694a60ee142b9f86df643256888ad5540817fd3abb4a4ed88b4e8d5b983d8db27e517d1964cdbb377e6681354c23a016dbd15ed9fd287b084b4682dc6bba72e2de24eecf9f5cd0a378bdeeb477da863408e707af9b97424832a69d0280767bd10aae8be374897d6f70a107acc5aa5e4655c32ccfb288dfe6dd0c44434bd15b9c7a02a2565f96d7ce38126f3a425ebd133d55d561bea5a2db19619167e2614a93ca8b0bc4576cb1d225ca8c990a36a2ea86d4797eb71d242f3e04b6177d932dd4ca7a01974636342dc239a5d393f141f610fbc35b243c057a1fa80a3d83c10620c6c880cf9a354c25b368d98d636f1521524c7a3a3be0757dec839ec3c15cb66efa82c8931c384581a6d324e13e471545515a2a008d9c24b857e32659980a40e3a39197029b8e452aac99aeaf5b58651c82bb0ddf68950654c4be82837d000daf1e4c89d1691c757a4cd57db8e0389818c6a80492db4544e6ab764a0181ccead3306e1c0f2665d4e28d09ba7ba513047c501763678ca9bb0a8a4967e4f6e6760d7ac58e5e2ccdbf5784ec84a148052593d6c89b4b3c70411e51bf664fed6af66d220838cb2769565667b2b0a3b31c598f8582078a25092164275aab4178a6a1d083f0f50237a5fa63d3080ab2510b04cd1c42af9ec321d566d4e6851d0a919da49323d196a314d83d1aedc23b6d5140825e54cfa8b1032a0a88ec1a2b116eaf51d0c050c9011862c45c69c9106d425bdd561a415100d401e76a728de8c3198d34607685d290f30c5c3fc07ca07d8f779ae929a0bd3c17eed78e8c472892f3d05a6c8051646c4912f11efba3cf0a561ad7b3697468b2f5be4b20a68884a82ed4a2978b49be5983bc16462b3ea04453521b824c33aba2e5d0e4a4b9c753da12c532ba88993f4507561f2fb2c7d9339043f727ba4749d97e350de064eeb539db2c10d2282adb54908adab2328dff4082d7d85eb194820ed3bbaa9aad149e6055d1ed5335ca8adebd9703949ba1a3981bcab3816a0bee550455fa4343a9c9de43ba673cb1d1f301f9a48978cce66895db5be1ae4e9eeb142f405863228b0bf932afb804ac87f5d8b3eb4c1ad4f4919410b998820f86e35d7d54d60292897130646bc9a888d65e3491bab5d5ba4cd0c74888b94e0d66445e9ef58566b568bd6847bd87e141aec81e3009ef60d4adc1412ae3d81338be513737c6244aa3478125159186387db3d8875
+
+InPK = 7b4db63984b59c5f4c76202fbdb360ed6a27ee1d9395e7721787e4b0d7ed20c9937214a4690ae10bce3a621f08d37706945b1912e0dfa911bde2a1099ac611131dcff41abe5a16d33978094874b852743799d6316c873bf2f8e17827ddac9b33da6a4a5229e01e6d85f1973f4aa7cdbb45934dcb680a625fc4a715dfc0804e8a2f644694390c14e053a8ea5e65a4168a52629fece156b3ab995ac385c7a8ab0c60969ae05563956fd0a3f1d5b009a05a5c1ac384f85c8bafcb9bc3d856de6f39e8c7f908d7acd743ee058e38cad1b0640c0ccd2e5a13e640bdac1dbac4a08cba19038f49175817e00d69092b26395a96be87af3c8bc08cddf4faf21c19147e08eb1d796ec96c624b657687552b702164705782cda3142213254414a6bf0d17edaa692690ba78c4e46ab936d03a7dd785f27576754a0dfa5079517c0b264a20f65c1ea211870a0af071e2234e967a70945e01fb9460cc9b49d66e1b253a2fb709d674c45e588f2420013abe918e4c09f9e1e9aaf0d91daafb158193c14e8622b583dea1a3a8f6997ac5cbf640d0504e3629b1387e70286a244300b4141cbf9e45d87ec26992ecd7b44de2a2b02fd2aacc9565c990c0e300407255e04901102446e3d128aa684d878a1a5d087b51af20907ddaa44190d7113d7af655b7e2244a96b1117df9ce63e5d4612ed0d953358e81178b65f0c46d5e8abf414518169e5726247cc0298d140f2ced8059baadddc21a1521468a0887b09860f8011defcf06879573aac97a8084aea2b915cab6c4f900de1fb7e164b97976219178e4a17abc1a8c3938e1744a240f7446627549176f66c2e946becbaa200c90ba07a892607910363558ca43a9da560b8742667dc981b842dd07b76d2bd1abdc005bc1b1b587b3a3ae4d39bb4d7c218ad27acd522d71dbe953964468e15cb5464042b45118eaaa5fab1d3bbc917d9b57b33be2e56dc062804bb5064fd48b6d68dad551e12ff329fdc5971813121aa4c48fb75f30236d4946d593c8a295900f6a49f143d62a5a682ce686eee16457ef90380cb61d09a1ca514c4646ae5f0a1448c5bec2996f1328da72809e3f0a13344d5e6699786b386211e170b44cfd985ed473ba2a962e4c6b6170a53c638584dcf0438516cbac9ac1c028159087d17b8b403a949a50a0d170aa7d66cd5a97c83231012fa4c49a724b01caf7839a45655df3f7f9caaa192d94e9b40d05352137a9d2906712c25bda8c5522a59f8b190c400b2febbdcb1cd0154e1fe59935842a3cca3aca97fa46fc081a08a37aa6b310e6d07f3694a60ee142b9f86df643256888ad5540817fd3abb4a4ed88b4e8d5b983d8db27e517d1964cdbb377e6681354c23a016dbd15ed9fd287b084b4682dc6bba72e2de24eecf9f5cd0a378bdeeb477da863408e707af9b97424832a69d0280767bd10aae8be374897d6f70a107acc5aa5e4655c32ccfb288dfe6dd0c44434bd15b9c7a02a2565f96d7ce38126f3a425ebd133d55d561bea5a2db19619167e2614a93ca8b0bc4576cb1d225ca8c990a36a2ea86d4797eb71d242f3e04b6177d932dd4ca7a01974636342dc239a5d393f141f610fbc35b243c057a1fa80a3d83c10620c6c880cf9a354c25b368d98d636f1521524c7a3a3be0757dec839ec3c15cb66efa82c8931c384581a6d324e13e471545515a2a008d9c24b857e32659980a40e3a39197029b8e452aac99aeaf5b58651c82bb0ddf68950654c4be82837d000daf1e4c89d1691c757a4cd57db8e0389818c6a80492db4544e6ab764a0181ccead3306e1c0f2665d4e28d09ba7ba513047c501763678ca9bb0a8a4967e4f6e6760d7ac58e5e2ccdbf5784ec84a148052593d6c89b4b3c70411e51bf664fed6af66d220838cb2769565667b2b0a3b31c598f8582078a25092164275aab4178a6a1d083f0f50237a5fa63d3080ab2510b04cd1c42af9ec321d566d4e6851d0a919da49323d196a314d83d1aedc23b6d5140825e54cfa8b1032a0a88ec1a2b116eaf51d0c050c9011862c45c69c9106d425bdd561a415100d401e76a728de8c3198d34607685d290f30c5c3fc07ca07d8f779ae929a0bd3c17eed78e8c472892f3d05a6c8051646c4912f11efba3cf0a561ad7b3697468b2f5be4b20a68884a82ed4a2978b49be5983bc16462b3ea04453521b824c33aba2e5d0e4a4b9c753da12c532ba88993f4507561f2fb2c7d9339043f727ba4749d97e350de064eeb539db2c10d2282adb54908adab2328dff4082d7d85eb194820ed3bbaa9aad149e6055d1ed5335ca8adebd9703949ba1a3981bcab3816a0bee550455fa4343a9c9de43ba673cb1d1f301f9a48978cce66895db5be1ae4e9eeb142f405863228b0bf932afb804ac87f5d8b3eb4c1ad4f4919410b998820f86e35d7d54d60292897130646bc9a888d65e3491bab5d5ba4cd0c74888b94e0d66445e9ef58566b568bd6847bd87e141aec81e3009ef60d4adc1412ae3d81338be513737c6244aa3478125159186387db3d8875
+InA = 16598e075b0e7c09cd899080a945dbe249066492b8c9829f42e7d131c5017540839464989c68ba38dd2365e97c6b03c83f2fa68c84cb8c70a05e961772ccaf358dbbea4f043fa5d8db73c062932cce55f07ec98cfd84b1b2d13c33e94d94a616318b1e400f42b7424e256655d1d810114842d92882dd4d286a2f9ae8e065bac291bb133d462c531c4b902a664d5d31817828ae784b9dd1cdf193824f5578345a33b34a07e7add5246d933330f9a25b72c79f57920da7be25408b26b42a142248c4bec048ada2ff02fbd9414ac16c490ca636082e27c7e502a3a027c822b0bc558d0a48680d89ace313195b8bbd5e7d144d394890594a07e8a6f266562c628744a1e85492e97bd9444d7a69dc74c3005053d81ce2f358d54c84159f48c0f26c3e58aa2a3fc012fa5ada92e0ee63a39c189b61b129fea5ea2243e077e598f9e2dc95a8e31c632ab1b975740685e5d389b785cb95e572e6951f11e401d598b359464a0645882375c667e416c4b2b684269235a29890d85cf6c16c554501f709d09654a6001ac7a2ae52e3c3f275e01eb0366ff80bc34d96a6a877a925690ead51da259710bbcc1c4675b9a97ce6e8b93b4a4c93e7d95ba2ca42adc3a0a5431b05b0e818a04a655db5986514d3b9b905e50c0e9919818efa1d867ab90e190b0fd55704f18791143822a771711289a7009d2c0eff5e09f99c520ce791ba00c8046a0f5e2f30af489c565229f99bc66a42608345769a353f4079906d6d27334a5b11eee821a398b56ab310791d86d5b2925c62ed2d17e28fb89720d180654c394de526dc1558545a796807d33f86ae96953d06dd2a5913a0b9a99846960ac6f6453a125eaa0f4e475a82149485569bd5261084e76dca5291548ccd22f4a2f218d5084342387c1a78a04403c1b8215a9899859e5c1c75e359cace8069e4c85aa8b6a846218a4338ac58447758cd2807c8b1cedbf0319fba190d49dcc554788558c943c65ab65edb113e3656ca1ba6c6344910d26a441f41426afd7bfa103353037057396ad70237d854ee80661a406d0b85c29bca460cb44b5e90e500d10c9dd106d1a10d49b4046178ce003b18eac14517c5aeb2854ef8fcd6362a0e3513cfd24c1f151045f0f1a7fb1554283a5682ed6e75f1a0edbad88f822632b90be8d458c6dcbe1f865f4b265ab27e2fc4bec75eee311261e3f52264014656094205b193315be6a3e5114663429e8823697d504b71fa9ad615acdd36625720ab40956501d998a3fe8037c7bb75032a4d53767b701ab3c150179bd50aa5553a4a272e48c71539d7da256e041ddd9a85b0a8d9dcdbcbdff94d80a4d8e5cefd292fe938f04cad77ba2ac86b57dc5660ee05f7220812ba6a70a2ca1cbc5f1736a5cf293f1acf96268df65e3e92362843d81337c88053aeed7ab2831b98f8494190eff3272d687c171af50468c49578a05a7be6c237460f93f9ab7553981761d483064233e7d4fad5104f5b001ac03ede1776ec0096ba323b765ea74a8c2d9a0d91e130ac9a4807dc6a8376fc362f4645d614d80f3f55e2cb49866a62ada62ae74d9288160bd5cc1d49b88a3326c5f447f9d47405a1b8b9eb23bd03c03e207c09cb59cd4dab8755d8d016bd198e45d1d5ec6017a61fed12b719970fda2a89874662a7e16ea11b185377c37977a1ed0af78fa3042dc17e192e4b3b2f7212964e36d357555d445348c2759d8e3bc1ba94d9e047ad8a40a05bae9f918187039bed17086ea457d1954d4c5575e9ca58040c129bc6fef20fe628d6d8eddead751729fa7d710802db77c1cdc47176512b098fc524024448230e4e95880fb5e375fa7f8300ff67b05861b605636aa04c167b4700b50656054c4ca323534921679aebb3be185412cd9ec0218046e224cd1b886d6a74d0e4479fe502d7038ea08a9a67da97eaf09e59046f6efa65348085d80d1832ed720eefc294365dad860b4afb412a0d7109e90f224cf87fc84338e15ad99e4d523651e0202aca201e98c9e440a4a07274c8dc95146a2e37a8841b6b6d48431f88373ecb7ff13b2c1c366aacf477e58a33af37c3ad1e8e708a10e5685878ce5db4074838b68907176239b6bfba643d88aac92bde285cf142952a135fce2308d9bcfcdb21955eb0342b6f9f18caf8b6f408c6c15cb976108097ba52ca2af509b489d379b27deb0470e6c40cd62021a74cedaae3dda546f6b86c1e5271d011d9145c55d407b359141d5cfeab5c820f221d199764fa369242efdae1210dd7e4cc66c3deb0ba8442bbd27c0e688415f2ddb961e72044b8846c911816b87384260dc81b717a5eed06724e8d5334008fcce70985b3c29166cd5f01e2901f44ce0f75ce0038d48353c2e7512bbc5acce012b90984d2558386a2a33a2e69a3c68e3daf841876a4a668f25cb061b1dc289c863b050351a0ddd787e3f9711d92e61037f180b0820adab8afd5a5fd2e7f198e6e1b9c8291012ef543585371128c62917167ba43a96aa42b296958753a91d16f5cba922d58cd8d2d1621922d
+InNoiseSP = 2ed210c039786d1ec41d71737a4b8292d1686c60529403f5780d3292398c5da63f30ba6a67115432a95b5b59e1c981bc40b755ee043840591cde37a3b3ba8e0c82c297fbf569af43d5f2ac2c50aa0fce00d6f23a155a57c1ea9d6ad9649a23e482741ca773d07f52bde1dd9206fd41783e6849666cba022e6c3b84bed2060e0a57a38a255e7998c9d4c32d0d22980652ba2ca899eaaa69e28eb92cc0b6f9ea48725d1d41a86fea16bc12cd9b7efd5be446221b1b023570da87c3f2d2b49804c9f4abb5bae0823bb8cd066c492f1b64f1c95bc2202b3149d520478ef8f2dfcd4600d4c95481d99daba1fc389f8898a16d2e03fb7842e599c414162602e868c968ff3d06170f3eb845583f05e18d02be726e02051d25a9ac48856f7f33c1596c8f86a5ca98352f4c95ea0a13769398853878f62052eb8ebe57637610886331d5bfc4707d58f3f8b50dbc63c0f6d6213da93189b7c65c755a8a516ac9ec7d918aa53bc191ec6879c75273e31972f3d5d3652ec824be0490c2814abe918caa37e65e4c5dc42316e67d8638e6f2aae10a75c3adc9f2a92a11f4efc6262e1d609ae3a2e3358242f36d08d047911699ee00c319e22b7de9c9d1a0a40e78cf0bbbde864c6986cbf2fad8a50e429c794ff6a06b1f65b275523af0a14b4917f97ec51ac8d1a8da6cba92bef44a28b234dfd1160684461090c72790459247ef0d782331735a01c7194d6923d65be972a0d811900b3ef3000879c1eadbc3f06463772b822104bd32520ee9131efe630c2e40e06cae62b2c95204a4f0b3326bc6036cb53103402925da36a1ed822fd63dacb220e5f5f862ec123946a0a000612de19afe6361e52eeaecb4c40ec617344e3f4af8b16f3086347363b21ccb44b0cbdeae894f0a85b1cb6e68b6596ed29f418cb745a63ace6033a5a19d5479f4a3bacd9a7b39413dd4a21ac132b04d69e62ea8841963715c5e81705e35f496a712ca0a025dae4ad3d3a43b03acc6c0dee55b27936340211c9d55a43ab2acd6b47fad52fac08e3f7e5af0b1196062364cb730a79d097308551b8d4424fe1aa15b07f95afd076dca7430a95a0e2e8b2b78a1d254c184ef4d9a7fc2ab840476541aaf6d71d24e98d40d578675e004a18a9c2b40e1a85adc1da3f892911b887a8270f6beba60fc599f640cc7d3caf5589c8a0d911f6a35ac1492045c54fec2472f076f08c8ae15f9a684e0dfa98eae1d0112854601c92ef8805d112370c143a8a570a80b93a4d01c32ba416740a930042224d47ca0c058822c088d01c13287ab5bee6310fa17ee0a45053f99a7a3672d24a4594ce9a6db96bb0a9858d037d9b03db92417f728c1e58bc24829f1c73465fed9a49aaba0ba2e9606b6e2c16b23054a571c5565729d80793fd875f70074fa8dac536d67b491152d15790233d9fa4234d4cefffb52106ff65b965a857e0e3294962a35e4a782d5b67b6cce0876600b435176703f8f2b46417eaf41832dc6a3e4a481daa54224ea4e0c2894633d5493fa9f09d9a4ea40108644e0a6d434a6edbc07316e9ca2cf99a7dff61e39d93fd408940047626fc0b70082ac612d04db5c40805b5b176ab16f4f483f11aac0473ce84b79ee0db1049db25bbc047bd56fad872a0aaeb6ce3f894d02431b24f49b6255a99c865a3666287e74ddfb6a5e40111824f44b77ceacc1caab124390928da4abeab49198cacf408a6fb118609735a419f94589ca8ad1928907734eaf76e5e69a2ca75564530d7ac991a3a211f433ff9006daee25b0245943c394951786c37af063d0306a8d56e6ab862d0d0069f459904edbca539643a69ad0da4f9ab1906cabd2a22263bd41aba937f9fea83355ae32e3f49c7507c79775c4326a2715356b1b880c79dd0d58177839a21aa6a2fd726a318ab2c849c2004041e591a0c637abedea31f9e97958aaae0393c48934a94fd9d9c0ae6d871ee8c7e8b8a92c13862ee2a025dd668393fea8b6d09106d320bbf0889d73422c441cdfe66aa0127cce695b3a59da27dee407b837c47b52673142a4799ec8eae5607bf8bfdec37748793052abe594c51e0d67f424d013a640222604f8f1a2f97fe90a6a9897005d75452be1b940786013d61085b50de4819f36a3e80a93a162705f961e9e0e22b61b14164f06b9f3a9e23ae10e9648e1c92c70a92582b44d012e9d79ea7d067461a72103a0744766c2f1625ade67726d8e2927e8a8bfc56f20d9b83ae9d7aa121ac2439a424e2acd2233230936a3d7908d699582e3da922a0eafc0a3b8912d17ec1b043f4801bd0aa73789b263c3d9b5c3e08575c25642b38128927b8004746365ba536256f42b01bf58d661d0b8b0b3542b61f50b92782a8ddad8e9a4865dcefd08d7b43b0960ad5af436253fe7db64396d83481002c8dae47cf8a9a4196bb4a51f00e5c462059a7647229b548e5d04c06966956a0548189a6a0d59b1c05c80c6751976408bf4d649de7e60e909d11c1a8309e1c955a34d8beda46a47597c7ef9e3c965915c09c983d8d5c3e22f
+InNoiseEP = d6d8b161e8b409512642cb760a3fd3d00d19e4067a48850e88533eb4c6489ac45bc0846650116500303bb19c96b2f8ea0f1f939fb26411bdb40a50654ebc5d4eac55d8b3dc5327eb5a642eed5761ac7695d02a1d266491d63e515518c1cbc400d2231e1d9163208a5c6ba32a471815aaee089ce4fe0c921125232908eea86059ea99e116b9261841e264a43aa2136dca03ad235d2ccf4095bc9ab1eaeea623e6af79db4ad67af97d73c34698ea1c0f13cd52d05c6a61eb284469f8b00af6c24ac6c5a4281ec9290895564a96d6f8bae1389cfccea802499c2e9e8be0cb50743c835b4e670fb82930c7fdf6e3da7d0e50ec0444d68dafd62571f1e4a2ddee6e8687b4b18228d3c21cf152f5e3b442cdd8afdbe31a7002f876c8e662f4682dafc5477f843fb44db1dae122e37945dd465b97ec41824364f79474b2bff2567a05a66eacc3ae13e333ea6889565189feca2050cb1f0abde21115dae186cd728b73e00452981a39a1e8aa04b0da22f26eb3cbb35c7959959558d6821d4b0a1ba426be7b6623646352947d5562fa4189caa8b812b5a89106274c0aaf02eae228969f946a2d1da600216058956d460366a9b6df6e223d59e0a30d22bbbc21d5427eb2b48dd367649b267330273e73b342551daed107bff228402033cac3fa0fa31e58ba56bd5725167e28852da5c58271dbee696785ed77a35f804e684ef452462d6444574362c99135fa59565b9dec543a25661121e49da42487aaa509b95d26eec71ffe4e4f0f578907fe6c40ecc862fc7e78ea5eb9366a5d1c0aa729da74e07b51dfe4ca54e03b04543f53a612012dda1ce517610b755d9f38d35ebce0cd89b7f2fc2386e5659be02a03e0195a05e1d222f2949fc95921bf211633d4de7c3f2ec7aa50df7592660a81b827b2030aead161ff29a34ea6df36ffaa5560d6a2e033226c30cbd2d776c9651dc42006ef140aa62fd37accc05cd307d2f64b3e0580a0df4b47751b3da41f7aec11219a9ea77baa3050d1aba37549704fbf6982bb294618c01f0953663157bea914ea6b0027642625a70ee6be3a899192378a1d9bd8e578b802237e558811f1a0610b5b0f6bbe3139f2defd8614a419b99597fbb38e0a088124d8f29c14661785888c5579ccd995461b1637cdd49ec49b700fc49671f37e985f72231255b62e78cd045b9b4d3c3d4ee294bad23194714b5f73dcf4a4d5612060301ea6b9931f81d8f5b4a32521fb0de6b9902b76f136796fd382d23163fc08e6e955e754a9b7816ac5172e5a41805d33732dbe910b862b6661bc72200c9a7b11821c65a90255077492a6d864aab89447016989a6ae4072084d4f438040237ea9d5b6f25152824f927afee5483a20750b994a3936a2466a05be166bc7a809cf88162e8eb1f22168a8262e36198a4519ba621b8787061564d013a07be92a74064b5bbf20a500a4eb4be5812b8d432d33a3d835630ae9d0d5f6a67c607b0aaf2d30ac6546e14f7e719ba2df78e7ca5ba25c4b6861be97349e7bc964860db41dba835a4403245b7b07c64d987698e8f02b999add2f0bfb42a244ea0f43e4c64cb5359478244f78a129c5c476abd5b36b6a82424bc07efa50e615f1cc65240c5c9216253f65c22042e1d1a7d4e657ca821c5f3da26a04ef0c96de9f60b9fafa56e19dfff8c43c173b12b8ab429e8dbdd3c4a978c89912d0ad98b6163604c52a6320d868391ec323e5c89d015e89e7a2a267f9168293d315a97a102a13c0a91e6f9d3f51925471ffdb0225c1f5b70094d211d9d27ef4d23e421bbaa1408aa478d4611a2d19f7e8b71e17d9aba5e39a2a620f6d7468ebca1b65488177590c3de42d8cb0dc3ca6d55eadd560158dbe53f380b805b34bd55d9255dc98ac204f470e06171e8a0a25c29c9eaba9719510dc8e2bc9026675060d4be392566b6c43ab83edf2dfc44cdf065963fa7cb11f152dabe87502e194ca241a4e823e110f53b1448f1fc09e204316bc8d4eb7559ea47806287ac463949d8a4dea242ed6495ac5b3aa85f2885d0d1935614a8d8c0d6cc8b93a7a3264741a0c8c3dcea7bba25c62678c80e46b52f97e2911b7056235138e20640217a6241097c598537e612b0fb6d8b7c665678e8c1b92f142d30b7e0b65cabbcee0d180dc02855f8ba9831612351bd84b76d9b89ebf4abdcaa5b9b7fe295fd6e5c8740e4ff713cfbd89d2a1adc8b9391ce76cd2a384aa35aaac6441fc522a47ae7cd9b11ea22ccc1efbd6853637448a04fed08be92fc748bcd98b1f8304a52756a7dfcd42f9a8426246def0bab7ee43dc238656904662695703265cc506b6d02568208c9ff5d006db90b48c9e22a53766717772ac05666d4927be969803418a8ffaaf76e799e069145f793ae4406d1bd7c8a7a9b11005ec0ab5fbc6ad4363b60aeeca0cac2ecf987dbc4222dd7f7398c573c166007b9f15bd90eeb195c40e72ecc62d274b389d2c188696bbcc9f26223fb68c448912ca34b1c43640f90f6a52173a9eba97e6a65a2d8f438815a5262e4f
+InNoiseEPP = 00f0ff2b0000c0058000200000c0010000600000c00180000000fcbffc6f01f0fff6bf00b0ff0b000000ff2f000c000c00feafffebff02000070fffbfffebf000000200000000200011000fcbf0030000c0003c0003000b0ff12000100ff6b00ecbf00c00110000400007000b0fff6bffeaf000000070000300040001000014000e0fffabf004000e0fffebfff2f002c00fcbf00f0ff2b00fcbf02c0ff1b0000c002400110000c00fe2f00d0ff06000400000c00140006c0ff0b000300fe6f01400008000030003c000800ffefff1b00f8bf00b000c0ff0e00ffefff0b00f8bf010001100000000100001c000400ffafff2b0000c000300000000800ffef0000000b000400001c00fcbf0000010000fbbfff2f00acff02c00000fe0b001700fd2f01000003000000ffabff06000100004c0000c00140010000fcbf0040ff0b0003000100003c00040000000000000f0002c0ff1b00000003c0ff2b000000fcaf00c0ff120000f00050001800014001e0fffabf020001000003000100001c000800018000e0fffabffe2fffdbff0600fe6f0000000c000140010000f3bf030000f0ff1a000180ff0b000400007000e0ff1200028000f0ff02c00080ff3b00f8bf0070fffbff0a00fe2f003c00fcbf00f0ff1b00080001c000d0fff6bf02c0fe1b0000c0feef0000001300feaf00f0fff6bffe2fff2b000000ffefff2b0000c00100004000040000c0ff0b00ffbf0200004000040000c000e0ff0200fd2f00fcff0e00068000300000c00200001c000c00ffefff1b0018000600003000f8bffcaf000000f7bffc2f00fcfffebf02800000000c0001c0ff4b00ecbf04c0fffbff0200fe2f00c0fffebf00f000200000000400001c00fcbf0070ff4b00140000c0ff1b00140000b0ffbbff0600010000f0ff120000800000000b00034000700004000180003000f8bf0000ff5b00000000f0fefbff160000b0003000080000f0fd1b000c00ffafff0b00070001800100000400024000d0ff0e000200002c00f8bf01800000000c00028000e0ff120000f0fe2b0000c00740ffebffeebffcaf000000f8bf007000500000000040003000f8bfff6fff4b00fcbfff6ffffbff0a00feef00300004000180fffbff06000080002000f4bf03800000000800ff6f000000fcbffd6f0020001000018000f0ff06000100002c000c000000003c000800ff2f01200000c0007001e0ff02c003400090ff02c0fd2f003c00fcbf0500020000fbbfffaf00200008000300013000f0bf040000bcff1e00ff6fff0b00030004c0ff2b00040000700010000c00fe2f002000f0bf050001f0ff020000c0ff0b0003c00100010000f8bffd2f000000000005000170000400020000fcff0a00028001200000c006c0ffebff0600008000100000c0fe2f006c0000c0faaf0000002300fe2f00100008000180ff4b000800050001200008000080ff0b00f8bf00f0fe0b00f8bffcefffdbff02c0fd6fff1b00f4bf00c0000000f8bfffafff1b00fcbf040000e0ff1e00024000c0ffeebf01000040000c00030000000003c0fdef00100000c00880003000f8bffc2f0130000800ffaffffbff02c00400001c001000003000ecfffabf0240ff1b001400ff2f002000040002400020000c0000b0012000fcbf010000fcfffebf03800040000000feeffffbff0a00010001000000c00380ff0b000b0000b00120000400fcafffdbfffebfffaf0010000000ff2f001c000400030001e0fffabf0080010000ffbffeaf0010000400fe2f00dcff02000200003c00040003c0ff2b0000c0feefff0b0000c00180ff0b00070000c0fe0b00fcbffe2f02300000c000c0fffbff02c00200001c00040000c0000000f4bf038000400000c0fc2f00e0fff6bffe6f00d0fff6bf02c0fe0b00070002000050000800fc6f00d0ff0e000080fe2b00f4bf00000000000c00050000300000c00040010000f4bf014001100000c000c00010000000ff2f000000ffbf000001d0fffebf00000040001400020000f0ff0e000000ff0b00ffbf010000000007000280ff0b000b00fe6fff0b000700ff6f01f0fff6bf040001300000000200000c0003c000c0ff0b0007000780014000fcbf00c00010000400fe2f01f0ff0600ff6f0030000c00007000e0fffebf0040000000ffbf00400000000700ffefff1b00fcbf05c000f0ff0e000200000c00f7bf01c00010000000fc6f003000f4bffc2f001000f0bf0030010000030002800010000c00ff6f00000004000040001000e8bf01400000000000ffafff3b00000000b0004000f8bf00b001f0ff1200fc6f002000ecbf0000000c000000040000bcfff2bffa6f0040000800ff2f00300000000000003c001400008000f0ff120004400000000c00fdafff1b00e4bf030001200000c0ff2f010000fcbffeaf0130000800feef00000003c0028000b0ff02c0feef000000fcbf00b000f0ff0200034000000003c0010001400000c00700000c00fcbfff6f0030000c00
+InRand = 7329c31474ae53402ff402d394b9567d25ab9fadeaca5a4f39805974ee711114
+OutPK = 4a1de2132f661340403d82cb585b995cd9b1e55500474cafe43c0c0c30594a673d283cdcd7b427c52c99bb6a319256203072c8c9eb9582bcff2029566fbdbb390438f9570e9e0d41a8508a846ff9e4729530d58431dc3f183b04bdec9420898961a54dc20277b764bc3263e992e1649075e49fc62b793c74014aeb25cc26fa22d3c9e6c0902c1ec424425e9921113a0b11dc16e70c0c37c699a1fac49d846f8479f56ed2842a9c9feb290a238c99278a29becabb4d5241c3b496f00d7394ebb5c62caa4b6b68a4477426af6b59a0b55b2041a3a12a60f8c191354dc0abf24e4b1eabf82aa1941adfa450fb9e92af32681a679db4b5f281b76673725d9e596ab4cf8a448ec53148b5225a77d78d93b4ac748842db60cf80690fcb02da11559e17c34a79c3d94cf112f8e190782b4f9362172cee959e8c16c3e4c9492d5d304418c1bddd929bc557c89e5865e4550e0272912a5cd88a18108a2dead400c548761467371709a6ecc797b6cb383b8c530902d1618bccdde989ea75940b8ec3e5de652fa5274827d28048e5aa4b6ab1aa50d9e986331e927be94971cbed86868c5bcfd59b520f1347629224689bc583e7fb10642aa597c021022a4d954fdc10b312ab6267ae621de96ae42337e2e64c2d63141b58deac9f6f6f20e03c500ab647ce02f04c0779914dba1a4ca288d206986ae17715c37113ad727ed8ec887af2c58fb1c6079243106e3c957366b5595195e80e120e4d9debe9b2d9c52eafd66b1c422fa2932ce69f4890e004bec53968af64596d89b575035047e11f41515fbda8fd832b338b517b926b1187fedca03b8a9a724cd04288ef9661eb3a6c492dc5d16d94364260d28176214d494228e8929d069a10de59933c6bcba2de70beee7904a19da3c120675206d8347c912e79419754603159dd1cc34774157f7d0dfdb48114022b5903b993412759530ebafa0aaf1a0d2545f426abe3c1f5e949c54a722c05c200e0876f5d04da5b4d093da15d93587c88bb65a250c7da11aee77f5818a51381ea9a81b1fa4bb513f2c022e696b18ffb60c4ad3d9ca40ee745da79d6a880a932344a5e5372eb25059a7910d036104c1ff4956ba2358d5b17cee3076b11219fdb37f3fcdebc6353de299315516799b5b24f901de88d0fe113a6b21389f6c8eaea6a9f596c7b688961b418b5fa3782366c631d8b006905f618fc458ad87e6ac4a5b2f5ac28894828381f0aa26c0c21f148350cec11e5e39bde902584a2788f7e31941b7d52ce7e14e366c9772108adfa5f2823250e7fc965aab81162212d1ce245dfba74fbc67b7bcd821ec5984a75f5c9359348a333cb8586ca1c2a7a665c0aa6d29999b4b540a619251696a1bce815a287e2f801b36c8ce9bfb115bcd91efa22bd84a24752768e0937d1475361d8dd6aab55ceb4fbc5bff3d42ca85f955a5c9618faef90aac71db8c0d184b4422c96189124ba7fdad9c440bd2a966684fb84dc76c12db5570afda885ed7d09a35414c000e2323f0d588a8c4a40b46c679a24e8c32b5022bd2aacd4732e9f69a4e970c0e188d6141ff3892c698c6f33647dcc915088b9f43c4540a668e293a06e65b811e86b6ff466175295516bc2ac3dd0ab4350645d03aedac83e609125a1295ae7667c384a45ab77fa8700e739e5655253ad681258cc06b062117140afce9b4244860510755b9555326ba4be03568e509aff5001bf00370a06d6033e945669213443a34894d3f355a74a0cd551a918b837dab47608229b8f4f3ceb2ac478eda449a03744bb79077aaa875216888bb7c551ae06264c8d205aa5a1a76c7603b31a81e2e2cfa37c527ab3c534bbbae210812f6c1601b49174ed8a19159d72050c56900dfda35ae2baf78f8e0627c0fff839ec64ace027f2086d356084b8f3de9a59d26592425b096d38dd9044ae9ea2de966af0077e5add4289670c5aa16e9d9c61abc1abccd060440b363ea1cbc2f636ac4cffee0dd94d050a555bdb23f71199de9e44b90c351315495494d9266861427f80d87a966fc118151d659df787e9c5dcb6259fcd7381b7c906d5083b9149705644abe895b8005b2aa3ebc772562d8804050725cd60e54d5c56a79032edeb3d28c2c0bf1a5d765738299df565452527d5b8fb1804eb7ecd167ed57427fceeb426d6cb917acc4757da781098691304495f910bd52d356f61c9c9dc43c66e2429e6f57e1c632f4005448cbf95b74897e947abe126e0eaa6a40c559722d9a5b9b04f7be2a3a102a94e4961c69589a94684a1d155a02b8fdeb362882e75a71b9bf8fc2748c4e73852de28cd8726ca96b82c57d1e36225bd8ba44358536fba4b710bd8d4a9a9b2e1c99f26e62164794af4464df9584666aff8ee34b65d69a21028ac649657ee73c9550da69bbd4566399264465fa1b8358b8bcb92fb8978aa4a04df60b0bc5705c1e6e1851905cf1d70460a1d7e88d487a18ae1228f4278430b52127aea496afa4496e7628800dba95a1dc9f17b305ab82e19b593d9d6992264fe29d15157
+OutRec = 01c00000000800038000100000000180001000080002c00010000400020000300000000340000000080003000010000c0002c0000000040000c00030000c0003000020000c0002800030000c00018000100000000100003000080001800000000c0002000030000400010000000008000300001000000000800020000c0002800030000c0001800020000c0003c00030000c000180001000000003400020000c00000000100004000000002000080002c00000000c00000000100000000100002000000000800010000c0003c00030000c0003400010000400038000200000000240003000000002c000200008000100002000040002c000200000000100000000080002c00020000c0002000010000c000240003000000003400010000000010000100008000380000000040001c0002000080003000000000c0000400010000c00038000100004000040001000000003c000100004000300000000040000400000000c0003c00020000c0002800010000800034000200004000300002000080001000010000c0001800020000c00014000000004000380000000080001c00010000800028000300000000180000000000002c00000000c0001400020000c00020000300008000080001000040001400020000000028000000000000000001000040003c00030000c0000800000000c00004000100000000280001000040002c00020000c0000c00000000c0000c0002000000003c000300008000000001000000000c0000000040002c00020000c0000400010000400010000100004000000001000040001400030000000024000300000000340001000000002400020000c00034000000004000340001000080001000010000800000000100004000280001000040002c000300004000180001000080000000030000c0002c000300008000280003000040002c0000000000002400000000c0000800020000c00008000300008000140000000040001000020000c00000000000000000140002000080001c000300004000340003000000001c0003000000002800000000c0002000010000c0003000020000c0003c000000000000180003000000002400000000c000040001000080003c00000000800004000000004000080003000080001c000100004000040001000000003c0000000080001c000000000000200003000040000c0003000040001000000000800008000300004000280001000040002c00010000c000380002000000001c0001000080003c00010000000000000200000000380003000080001000000000000014000000008000140003000080003000010000800008000300000000080001000080003c0002000040001c00000000c0000000000000c0002c000300004000180001000040003c00020000400034000100008000040000000000002000010000c0001400010000c0000400030000c00024000200004000100003000000001800000000c000240001000000000c0002000080001c0001000040002c000000008000000002000040003000020000400014000200000000180003000040000800000000c000380002000080000000000000c0002800010000c000280002000080003000030000c0001400010000000004000000004000340003000040000c00030000c000080003000000003800010000c00018000100008000300001000080000c000100000000040002000040003800010000c00008000200008000280000000000000c000200004000080001000000001400030000400000000000008000340002000040003800000000400010000200000000340002000040000c00000000c0001c00010000c0003c0003000080001000030000c000380002000000002800010000c000340003000080002800030000000010000200004000240001000040001000030000c00024000200000000140002000080003400030000c0001c00030000c0003c00000000000020000300004000380002000040000c000100008000280001000000001c0000000080001400000000c0001000010000c00014000300000000240000000000000c00000000800004000100008000100000000040000400020000c00018000300000000240002000040003800030000000034000000004000000002000040000400030000c0000c0003000080002c0001000040003c00030000c0000c000300008000040003000040001400010000c000180000000040000400030000c00004000300004000000003000080001c00010000c00018000000000000100002000080003c0003000000002c0000000040000400020000c00028000200000000380002000080000400000000c0003800030000c00034000000004000140000000080002000010000c000080002000000003c0001000040001800000000c00028000200004000140000000000000800020000400004000000004000240001000000001000000000c0002800000000c00
+Key = 20eae83d111358edd1ef4c2dd731ec8ab172c5baabb832d8198b7f8f615a6939
+
+InNoiseS = 819fc864be3149721adb2aafc882e380dcf06d756412c8a01283e20e6ac1a396c0e14228016352fab19a6b41009a054ebc5ad9a4dbb34014e1df2a7388be6d9593d71860109479801ea9c464ba476edb713664a3245822999c2d8490db2aa7874aaaaf4cc0a1a3fc4617ed5c86f25985078fe7d6f791984d55944621aa86fa6d07763f2e57122e50d89235b3a5ad9bc47684b5f1a0d9005b059b70038f319e31137bc116d7229cab130a331403eaa76aa2a5225b7c9e7f57470b029ebd8a402f55a83e10d6290c391cb90c549c1de65bf83ac64253674c2804701c5bb1e616bc806b72224d8d1c43e049ca146cae42c75569c6797073dcde9028345ce38021a535daa7288018e56b16406a4e8869bbc656070e2699625d14ba996e81431a2d0a14e2405a082e40e13fa2b37a1ecf9a3923a68e1d990b812a1ffe9a674df40029747d846ffc894238b9279901c21489b975aa670448a4766a484918ed7551f9ee7a66bc26b88b002c7bd8f51f9b8c42a8e3ba214815bd687648459f10f2a391856ec3c5bc1a358980b1aea10ab26e430663ecc38018323f2c36daafaa1ce252774913ac30b6d27564c5c20e11e74606b1c1075ba60e451756591d443ec60ce49398d7b4ba3dd000630aab95b8111652e0c110fc04059a68a5c17c5e0a8382f3a32de475f01082a2fe62264b6841a44da669475348dbfda93a9304c502abf4b1710a5b27cc39a8f0e705a4633c5fc65951e4c7f86525c0d760079a75aa587a32ff0e9b82ccfb324a7e8abe9eadb940e10da2ce00f82362b26e8447a1eba21643c0b0e02a2d1190ef51db4a5969aa5c50d2bbe64d8fce2186f2647dff4aea76b78d33fbdf7d74bfca0cb20125eb5a74b1b26d68e3531db09f634bd134603438492df7c4d1a7402f7559e0a4ac8b8e0c417569478eae95226a747d7ead94390c5633041b27559d1e27bfe9104209897e3700edeba72d6f496cd87b7d446a1569b490dd8abadea4096b67396ec8c269bbb7f264bc9d9af9423829a149c3433b215528a90bb1a44878a2c84a35e23220eace1072dbb03c7c1f6059da627e9ca408c572b03ba1ee726739d8b32229f4ebc87c9b7fddff1652a24d02868c50f7cca61da9fdcabf6e733a1d90fa49d66fe8e73d80b0b6a567ace5b62b4e12cf1c5e738199881795ceabe2a517ab2009a90999ac002a40147ec93511e5b484b38213b09200549e1e386b9aad924605721498c0c2105a5129c0877aefdc25319380735eaa680a97c0b51abca6605a9af4d9167e87cb14a6c7424b4d427fe4db4e5fe9867004833a159069a3f6592c232a4e2db38512bee2a9b991d415352b26d83115e92d6567e0d943c67f8ae7b694c1e6beb1e857267311310426713a842e46aec68c0b4e9825a3133273c76475804aed47f31c36f8eba860a600967953152372cc1cdf893e325ec92d14ca45a9135a9c5b5cab4413fdac9f90cbd74be6beeacb6b248d328f081efbe6f268672cc244c04fd6509f2df12628b4a1c9e614eb1c6157d8981e9a6a019e2cd745733765582e92a518b2785056c7e932fc860f162c4c62e738baef86e588e3155515e0fedb0bcd997094d93b122d7d54c01296704e38b4ee47d0b67d5cc784f95a3b845969c1cf9ae3364a314f8aab0a19279c1784f6dfdc77c4e65fe5f43a77a8cabed319cd69ce96ebe04b254465da81e561103b242a2ca971927371d985327b850c998965327d18273f66c4f98281070e940ddbe46e8a4dac8130c4690b561f7193b3518cc464f096e720097dab1a17b4d4bb2ad6abf84b39246f470fe4589410a52888c6c00163d16df7c2225ea8071b9154a0fa340a29cc4bae8a37640c86f9ee7ebb1fda52040b09979a85a1b09f5432c884296191167e1802949857d1490c862ebaf40104a9cd22425338a27de46c08e34299090679fb115d473947831052dd883805d70625944e1723de9217857ab05aa2f70461982527d7d07db403b960800991fa06d7299a77447043eacdb52036082403867f0a182031179cedf1de9d0a5da71782718d6c874dd359be309f7090a94835e10f732c9dc9dff59abe1ed8441680117811f2d909d53a29a26bf47756444424f548e89abebaa25652e10c6373127e489d0d2123e278d05c842ac99ec321b6ed6af94eafc6216a54f62f00e0dfdd44b40eaf85cbed5819c0e553537182b1d9f9548c0e08845ffe8aa53631f76814d759a55fc9d020d2148415b61634864e6e590f5fec73cbca732c1fd19329d90e7821dd106515442d4698b957f697b2c9fb652826283287a064ae861c9c96c58261c20c51d642c5e0e09e84288dc2fd16550787a8d6b1929adfeb1b2392854977ade19af270825f9a20c6c2c5685b08b4f7c27123494a0365bdf50d8acc29f53afe2ee3a743c0b19d7d6613a39a19a20884d98086a5ae633e1a150a2fe2ad5853614b3ce94fbe401be3223d260a5a6994c321366e6daeb06f166989acf825aede985d4ab7b1948d81f7eb27e946948f5dec13765bd203
+InPK = 4a1de2132f661340403d82cb585b995cd9b1e55500474cafe43c0c0c30594a673d283cdcd7b427c52c99bb6a319256203072c8c9eb9582bcff2029566fbdbb390438f9570e9e0d41a8508a846ff9e4729530d58431dc3f183b04bdec9420898961a54dc20277b764bc3263e992e1649075e49fc62b793c74014aeb25cc26fa22d3c9e6c0902c1ec424425e9921113a0b11dc16e70c0c37c699a1fac49d846f8479f56ed2842a9c9feb290a238c99278a29becabb4d5241c3b496f00d7394ebb5c62caa4b6b68a4477426af6b59a0b55b2041a3a12a60f8c191354dc0abf24e4b1eabf82aa1941adfa450fb9e92af32681a679db4b5f281b76673725d9e596ab4cf8a448ec53148b5225a77d78d93b4ac748842db60cf80690fcb02da11559e17c34a79c3d94cf112f8e190782b4f9362172cee959e8c16c3e4c9492d5d304418c1bddd929bc557c89e5865e4550e0272912a5cd88a18108a2dead400c548761467371709a6ecc797b6cb383b8c530902d1618bccdde989ea75940b8ec3e5de652fa5274827d28048e5aa4b6ab1aa50d9e986331e927be94971cbed86868c5bcfd59b520f1347629224689bc583e7fb10642aa597c021022a4d954fdc10b312ab6267ae621de96ae42337e2e64c2d63141b58deac9f6f6f20e03c500ab647ce02f04c0779914dba1a4ca288d206986ae17715c37113ad727ed8ec887af2c58fb1c6079243106e3c957366b5595195e80e120e4d9debe9b2d9c52eafd66b1c422fa2932ce69f4890e004bec53968af64596d89b575035047e11f41515fbda8fd832b338b517b926b1187fedca03b8a9a724cd04288ef9661eb3a6c492dc5d16d94364260d28176214d494228e8929d069a10de59933c6bcba2de70beee7904a19da3c120675206d8347c912e79419754603159dd1cc34774157f7d0dfdb48114022b5903b993412759530ebafa0aaf1a0d2545f426abe3c1f5e949c54a722c05c200e0876f5d04da5b4d093da15d93587c88bb65a250c7da11aee77f5818a51381ea9a81b1fa4bb513f2c022e696b18ffb60c4ad3d9ca40ee745da79d6a880a932344a5e5372eb25059a7910d036104c1ff4956ba2358d5b17cee3076b11219fdb37f3fcdebc6353de299315516799b5b24f901de88d0fe113a6b21389f6c8eaea6a9f596c7b688961b418b5fa3782366c631d8b006905f618fc458ad87e6ac4a5b2f5ac28894828381f0aa26c0c21f148350cec11e5e39bde902584a2788f7e31941b7d52ce7e14e366c9772108adfa5f2823250e7fc965aab81162212d1ce245dfba74fbc67b7bcd821ec5984a75f5c9359348a333cb8586ca1c2a7a665c0aa6d29999b4b540a619251696a1bce815a287e2f801b36c8ce9bfb115bcd91efa22bd84a24752768e0937d1475361d8dd6aab55ceb4fbc5bff3d42ca85f955a5c9618faef90aac71db8c0d184b4422c96189124ba7fdad9c440bd2a966684fb84dc76c12db5570afda885ed7d09a35414c000e2323f0d588a8c4a40b46c679a24e8c32b5022bd2aacd4732e9f69a4e970c0e188d6141ff3892c698c6f33647dcc915088b9f43c4540a668e293a06e65b811e86b6ff466175295516bc2ac3dd0ab4350645d03aedac83e609125a1295ae7667c384a45ab77fa8700e739e5655253ad681258cc06b062117140afce9b4244860510755b9555326ba4be03568e509aff5001bf00370a06d6033e945669213443a34894d3f355a74a0cd551a918b837dab47608229b8f4f3ceb2ac478eda449a03744bb79077aaa875216888bb7c551ae06264c8d205aa5a1a76c7603b31a81e2e2cfa37c527ab3c534bbbae210812f6c1601b49174ed8a19159d72050c56900dfda35ae2baf78f8e0627c0fff839ec64ace027f2086d356084b8f3de9a59d26592425b096d38dd9044ae9ea2de966af0077e5add4289670c5aa16e9d9c61abc1abccd060440b363ea1cbc2f636ac4cffee0dd94d050a555bdb23f71199de9e44b90c351315495494d9266861427f80d87a966fc118151d659df787e9c5dcb6259fcd7381b7c906d5083b9149705644abe895b8005b2aa3ebc772562d8804050725cd60e54d5c56a79032edeb3d28c2c0bf1a5d765738299df565452527d5b8fb1804eb7ecd167ed57427fceeb426d6cb917acc4757da781098691304495f910bd52d356f61c9c9dc43c66e2429e6f57e1c632f4005448cbf95b74897e947abe126e0eaa6a40c559722d9a5b9b04f7be2a3a102a94e4961c69589a94684a1d155a02b8fdeb362882e75a71b9bf8fc2748c4e73852de28cd8726ca96b82c57d1e36225bd8ba44358536fba4b710bd8d4a9a9b2e1c99f26e62164794af4464df9584666aff8ee34b65d69a21028ac649657ee73c9550da69bbd4566399264465fa1b8358b8bcb92fb8978aa4a04df60b0bc5705c1e6e1851905cf1d70460a1d7e88d487a18ae1228f4278430b52127aea496afa4496e7628800dba95a1dc9f17b305ab82e19b593d9d6992264fe29d15157
+InRec = 01c00000000800038000100000000180001000080002c00010000400020000300000000340000000080003000010000c0002c0000000040000c00030000c0003000020000c0002800030000c00018000100000000100003000080001800000000c0002000030000400010000000008000300001000000000800020000c0002800030000c0001800020000c0003c00030000c000180001000000003400020000c00000000100004000000002000080002c00000000c00000000100000000100002000000000800010000c0003c00030000c0003400010000400038000200000000240003000000002c000200008000100002000040002c000200000000100000000080002c00020000c0002000010000c000240003000000003400010000000010000100008000380000000040001c0002000080003000000000c0000400010000c00038000100004000040001000000003c000100004000300000000040000400000000c0003c00020000c0002800010000800034000200004000300002000080001000010000c0001800020000c00014000000004000380000000080001c00010000800028000300000000180000000000002c00000000c0001400020000c00020000300008000080001000040001400020000000028000000000000000001000040003c00030000c0000800000000c00004000100000000280001000040002c00020000c0000c00000000c0000c0002000000003c000300008000000001000000000c0000000040002c00020000c0000400010000400010000100004000000001000040001400030000000024000300000000340001000000002400020000c00034000000004000340001000080001000010000800000000100004000280001000040002c000300004000180001000080000000030000c0002c000300008000280003000040002c0000000000002400000000c0000800020000c00008000300008000140000000040001000020000c00000000000000000140002000080001c000300004000340003000000001c0003000000002800000000c0002000010000c0003000020000c0003c000000000000180003000000002400000000c000040001000080003c00000000800004000000004000080003000080001c000100004000040001000000003c0000000080001c000000000000200003000040000c0003000040001000000000800008000300004000280001000040002c00010000c000380002000000001c0001000080003c00010000000000000200000000380003000080001000000000000014000000008000140003000080003000010000800008000300000000080001000080003c0002000040001c00000000c0000000000000c0002c000300004000180001000040003c00020000400034000100008000040000000000002000010000c0001400010000c0000400030000c00024000200004000100003000000001800000000c000240001000000000c0002000080001c0001000040002c000000008000000002000040003000020000400014000200000000180003000040000800000000c000380002000080000000000000c0002800010000c000280002000080003000030000c0001400010000000004000000004000340003000040000c00030000c000080003000000003800010000c00018000100008000300001000080000c000100000000040002000040003800010000c00008000200008000280000000000000c000200004000080001000000001400030000400000000000008000340002000040003800000000400010000200000000340002000040000c00000000c0001c00010000c0003c0003000080001000030000c000380002000000002800010000c000340003000080002800030000000010000200004000240001000040001000030000c00024000200000000140002000080003400030000c0001c00030000c0003c00000000000020000300004000380002000040000c000100008000280001000000001c0000000080001400000000c0001000010000c00014000300000000240000000000000c00000000800004000100008000100000000040000400020000c00018000300000000240002000040003800030000000034000000004000000002000040000400030000c0000c0003000080002c0001000040003c00030000c0000c000300008000040003000040001400010000c000180000000040000400030000c00004000300004000000003000080001c00010000c00018000000000000100002000080003c0003000000002c0000000040000400020000c00028000200000000380002000080000400000000c0003800030000c00034000000004000140000000080002000010000c000080002000000003c0001000040001800000000c00028000200004000140000000000000800020000400004000000004000240001000000001000000000c0002800000000c00
+Key = 20eae83d111358edd1ef4c2dd731ec8ab172c5baabb832d8198b7f8f615a6939
+
+InRandA = 312dee62b48992a86afc71cfed062c85e5f76ce279f42a4e0561540685c1cf72fcde7f4720ef87581496c59d3cf0d14a745aa1f23292c56ca380c12045b184669164c73c3a2492af440a78453a1012fca13d290be6122cb832ba9de59019b8d0a40b6e2a8a99483931b5ee2b4971256cc31107c2cb14503e079d27570e37ac03c2aabce21990c0e4693c2a4c0eeded78361503d9023fd60edc742463daa39d32826ba8eb136dc02e6fcad62aaec67d9392a958ee094ba90b53b78c7496941644a04e7654ef51d18b66c80d4b55d9c3d5153760e8cb8495182e0a8ce50327142e286c27303ce56edaa6f74683cd8d10ef12d9970c30352574c06bde230f00d089214c6ad913333430a903f5253f13fcc4249b50efd5f0ad0c7b450713f84190e722c8b368b044744ee5c04172719d48a2919d3815c0c47a04848011c5843ea755007b9458a7c82340a243045d017946651ed32172980e353495df914ad64c2ad4ba925e4abd2b2fddb544386e4dd65feae8e2b0ccd0a2d2742c8666266762b4b6713b17240b5776278a6e1ad4c2d42ed64d32b14cbc66e7cc8844510a30faa9bfc179566034865ff0f7fc5510ca31e3093d39ca23c5c5d2e4b5b61b1c41be690b3822f6624cc99c2754710893f01105682c8685c11e36536114f07261e1e6a659f7e25c59824af93030a773450567a6c5a7f0150c7331cd4f60566c13a2320f2bcf6536e6b16ede24c3cb69f451de672451367969a6dd6d0afa58afc7daa9b6fc450d802ba879fc22207289783a79e614d3cd4f6ab0652a6a17bbb7f9659d4f14241a08382a549f4ac102ad0f8d8dd9706f0db4efa9c2dbbb9885b4e961289961ba8b8887d0b9dd20f5101e0890012d39a9e115c87a255001287b08b29ed9989b670b802e485813155bf1398c0b0409be7c1cba4b0a388014bf5bd5218199e63afc8d5a1548342fa14fa0e135ac7e05a5b9e1c475b6e7e30c1a75d630c05b43125b75410d055744f35805232183d57915a0e6a28eba865c61201baeb03cac68fb23fe6090f67f80cdb5039bc45638afa0a36520ac20c9ebd3a0d55d3c46d0ca48e52de52bbe70c3c911fceaf6b96a2e748a69b9d94bde44d5d5fda738226d3768a5d96a0e20b112af01ff59bbdf9c9bbbcea6af9ac22b74c2721222c07842296c5a1de44053eea0870b94ec94a1b0b1710e3dabfa3aab9c49ac1b3e019b712c8da748b1859b2aa5590ec4a7e78f1f1461f4b23015a5a9f5dd2e2624be2098580cf8de4b470a799a7e6c8753bb02b10c1dc1e70bc26e9c6d89039d282a8edd20274b5dbee6184327249664742e733a6d7d7e01100b638408b3d0479e80980d58c026a347fad6733de51b013f983455e257215adc3761624288cbfe8cda20459104bd18958415f2c120704cae55d2ff9637fb599835745869c127a4522e1e26fa0eb8f04c8a6cce41b09be1b1965c05a6551f74530986b6d7adfc53ff80bbb018b56e66665df1b0455b25d34c18b4b5b616051af4ca559010da68b8fdc6bf998b39f0def85c9fd9db86960d9ac5d99ae685bd2686546b6391c08426dfdeb133de4939689c67c569a2f7958ae70d31b5620db92963e0af8e2c25377258aee1051c9adc749a0d1e87d1b1bc0c9a5c13468b408172832cd893e025076b77d5a496b1776053fbac2a8251c5773632b91c7505bcabb57605ae2280e30b94131b63fca8caa8b6ed8477e60cb5005c48d91952b25caf5c2c8743be2e6754b712c0710d4f9f94317fa24a411271f8b4e8669241d6ba9cf65b7493fba1adcd0b4faaaca6bb2d8d79cb4e233d704a6725e5a4f19e1f498a96e783817b470140c0a25551650cd88ae4fd330b4212f6d848ae902ff662573a0ca7a6cc63898a6eaccfb97613456309e32e800fa039735a486962c9a58493afb7b9dc0c4bd9b12bff7e767b8f6f42f7bd53d0837a7574ddafd04cde42234a4919981cfb6d8841a3c063e03a52bf8598b0f12d6a28f82a4177a5ee7c3c2af1f0675685f8ab3c41cdec3046081b268f7999d9a17555826aa6052b8357d0b68b606a1d503d6627bbe608a4ccf94851502946390448779e9ffbc99a8d66874e988774b508ee66a03c5c94ca6224a618caa1ad9e69091ca4aaf840b856e2c1742a0ef0b067eca80849e7145ea574c093a12736bd207a51f51379bcb2ac2f08532e5097b6e0455516b0aa27c2af52f406b3f29cdaa7cc9609becf1821dd9c9839221b86f01c6c1c93169bc0fc6f0864adf9cfd1966e00cd52fad9a9f522ca821a2a2dab40fab8e199aaac12e2f1154032a49c5ea7a4ec2341051714136ab7e5193de862f12005881933b4601603daf7056e2c8582ce56b2a9aca49b5f3411cb182fd85f5e586bbc8124cac764eefe16242de424d5f89d1f5ace352829554c6cf10b488c5e7513dcf4a2685c904dc0727b040d14e7d92115ec256b590ff1a9b2295d4e7be92638b21fd55d8ad23165318d844b252523fca19961b9d60cd76597541ca04dd310080127a2ab8145fe9a8ba5a4
+InNoiseS = c1e9a276ceae5b944e79f8c57ab825a58ba9d01a23cedd5b2b2172a3f8ac35e80b5a3f84c034e226219e78e800453f3ab95329bfe0f4c17246ab6193db9dbe324b5f07f0998d6d83d24208d1b51298b5166c66258d26d86278843e3ddd13da7ebe0ed24902765149465113fee9461a84af1a68c8bf76769603e82a21a693fb0442bb70f599d8982076b9fc36a42c46b75db8b1699544e557fe21330ee6b53bd2310e6dee459b7a6fb55cd640ab1881334542aa920a8ac4e77c87c60ab1c98ae888f42134db67a7b809c69fc81194c487f24b61a011b086d058cb4556b582c54e4f047f50531416539ea7c1f04e7db95bacd3afb616812285354344167ee4745512601dfdae2a9afaf531b40e16d86569420b2805722ad890ed17308035c8943a0daad4e8c8325e8cd7d0263803879ebf420df2b761a86939b4e19ab161ae22bc045acd0af1985dca8230a752150191b20890d0788b9e8e299d08fbd7664e9645c43940c1b06d1c8251cf859d158fb5b515e40c0aaccd90b370020383b71298cdb335803d4b58fd3c8217435218b6b970d180a284d17b7f61ebeb9a46b8bc476bf321010f06128c02e171763dcd10b655aa2542213b6467800f134284da21622f6c20c522d1d05adf9bed5b7a6d63a3ab7236074e1f9b999138ac258900eeaf68a8328ed5084a23cf7cbd851ba7c222d1975363a0770cc446e7c4ef51e49457eaab2ef1fce02a1629c68b12d1aaa3a9bf041a765030d0e2a719ca712fec479ae3f5a4c2caba024ddc2c4c2c354bfb5c55b62daccb7a068adb03253437f87438643ee9d86929d5681b52b87664ace83a2672daae7c1f6c6aa2c486f9e3bb31c4f27b32d047a6af990e08d36e3a8fadb376cecf67989c4977d33d56db106107de6e89849646132a23858514a8931ebd4383d2635f90b2f17b7d92eae259e6ab4da034992a1b6ff215254e78a930fa6cf12283b7d23c73e08788a645b55268ca37e6c49227bb5f2f536caeab9344b7904519509990616250f127201bf5631ec28f5b9b7897870282b69bb46a8854bb5a66f626f9b5a394e062e4208c194cd1b963747216d8975f28a2480dc04a0f31462287d463ab14969827aa2f4fc4c30e977153e9e992688c8ad0b5c3efd17a4b95ec910881311649e223dd8d9348e11f0183560b345a4064c1205d4d41fa5b2b5c60e00dfdb2f31199d8897ea960fd78e6000b7bbb94720d275d9bbc819ca124dcf706a27615209cea60b952fb90455a2bbe3d311b9da08798491684a6291e915aa80b1983d6190610a094173575a7772587408338571e8e248a0b255c18a2cf4684040d215f88da53e9a6114903c3683d3eed814de857742e76a95282d87877289abbe54efdbc9d1961b1176cb5066d3f0bf7556be86106d1d6e9a8bfa8d5fbecf460095821989abd55b60261c8287a137feaedb0515e45694721081851957e88d105db0d974d5d5cd5a9386a8a037f315abe3b809b7f1b6656ac2d269452a39868e66b8e49543584f0667614a9f0aef09a7d956370a6a58353b70196498924bfa073ad687b1ee1a768ecabb7ab15f22fbc71579f7463429d69670d2ec605119f319574e572ee229f6241fab912addb1b83d71bd143149408abb1c15bde84ef93e6d2693c9423d99128832629e6d75b682e0e0181a0dcf442b4c27c32846431a3a6d8690f1c188a9a4274bf284bf12bf0a0dc9672d358b1b6243a631fdefa6464f9463c89f7e423ce03fcd5dd22fd606372296b024baa86c8c922071842a5084a799392ad39880a8b50d9386c7d60f3920db18c1feceda8d72e36e3db48858c00b0e921e35a09e1b16bc54428e0f119b7cd07466af576ec1908f489206e8fcb16580a8271d612ef272f8a5e18c947e10ff2263b08e46527b42d1c993774ed4139ccc0b39566adbacdd1aacb0eb2aceb6dacaa2cb1818b53e8e4b2995ddbc4f399f86d80e6644a2550d129f0a21e84f8950aed8cdd59fd1d09470ea43a19ca7f6a8de69422f0b3078a87a3129a8d819478a470d0624593620182087f57c62450c5f1121486c377648c3e5118e59659c56fd408dee705beae9b412467884904c1488cea3fc51696471ef154f9547ee6ee4636ae578f0611b4311c83e744f186ce2013e8eb00633a3a9223e39ea9107a13639a4dc0457116d20899da92e623b64240d090460a43d88476564c630f99a049f5ce5e34d645c8890e71099f16ebc72121aa044685fdf187e166155736bc1429c85cab2c808c0a1eda3bfbcc737395b4845031807b872407381212efa6856b69b145db0c4fa936ad6f05a824c10f500ad9e91cca8b7c0d57e38c3b82a8bc6d8132b6ae16381604ebfbfd8e8416177ca560e2983963fb1b25ae28d85071d251493e4c27a34319f04eb387a592e62c95b7e8b426dffe2b6d2ca89a71e091bb15c542ad9cb4211cd789b95c13972b9aea65e12051af44020f52971e61324245e9154d528879e559644ec8f7470e06a6d897cb84a13a656ecd55a69dad7234c79da3450a4d
+InNoiseE = b123f788afbd9623d25ab427c24266da1a3104cead00810400d2c49d3a0ccdd384345791ac7f18527ea9968bcf80a5ecbc5b9830a46989995409b4c674442c820498c56acd262fcd76487e79186163bea2d9fd39a90f8d067da930e8ae17ab53cab136acf4c052613794e58c9b2d2d2cd087bca67714a6958189da4be411241d22b59fe2a571982203dda53ae4a19684ff5a6f461b5df8065d8fc10ccfc58c5a82b194e67663ed26dcebe96960287e2345a102d9712a1688f915e59e84608471cabc182963d809636669bf58ce70867c8d093ee4681416ca1daeacee7996aa15c8e5e4980621241354e8d6424a6cc42720683b509fb5a26566b1d17cd6c02367cfd67348128973544429c48a77f842f93eb9c2ea51ab5e0adde93a3abfdabae3dc6b73fa20a21b9e5984945621a49b0ba465f279b440c0c43f3252656d300429429c859aacd889127c880fe62167ba2afda491f25fac8cd09ae3c540c802b366be5787a264dbdc5608ca5863d5a964a39f58b5f84d122af9d11a8e63a2a5da74b205e7827baa9c23c9d6428117be6ebc6a204bd1243c406de5962e3c40a2561cfb612e45584d8d3b51a84e13d57ba4cba4077912f35654b62f5acd9c40368e12a45d14f661bab0aa1b03d547a430cf92b69424a4202e092f943e1d88b60d4f04c3345c6bec4cb1f3959d3d4041354bf492d318ebd3cbe4b6d02efd49d16e2c47a988233f39731fd68e8964758223a0e86829b1307b2b0828090849a5037b73cc49558ecebc25881d4dae4dca4967d81c7c623871315d0347ec9d9a74e2864a0542e4930036f487c8d980d043611dfe2b5e554678d1dcb75e3e489c6f6192275ca935d04c0af8a48e17cf6dd807d9a0df204889c2cc71e291d0b2db7dbe978729fb9130455bd91144405c8c7b006a69a258a0dc9bdfa20824b1665778896d41816e90348b88e811ee1e001692624f3d27ed5115545bb80928413a4a1dcb0d00e92ea29b55c7a2b4801a54776d63422650039044ef7baeee3bce2cbca65928252415e3f131e17d0625e155315144195c48f0317c22346595a360cc8f8be07f492e1e3a31e066074f3170a4e954f5af0672db877f1726d9b3e304b85ad81a80715b7272f13d9bbe2b1055535578ed19bd32327e9a9659d317b129545c8f2d1600da2cb4a5fc73452c839297695b211d52a021c5b283c97d4443f2523df1252fde96b1007467fec8a6157dc6426ee63fb8a56239cdc202a18c591fec875c39f98081d7ed08466344a48b244f40836eadaf219bb7f81ab67459a7189568047d811938feb0542cde5333b932ba2cdef78ada3d36cd10b2b553c025f4ae3e07ac82042cabdeea9fa69a0ad6048b6c113e2317808278f29d679ecb0b6bbd5a84e8f94b059a0a510a389add6e3f97d49a38646041802a13757bc69f16916d320f258d81ecb0484fb46098d2b64b171e418388fea898349d29d4e3452ff2a273810d24ae118d3de6364b3dea83d4a124340be5be610af4351f38acc2073880fea0705ae68c550a7488dc8de10be321987c47fd36949c8dc20603b73ed20699da946a5449b9220be249c9c1609bceea464fa834d9565bd7f9cd1b95e349978a8aa727a03f74778698164d9e537c04aae48333a0265563b1a7c8e3ec3043d5277fc79fa876d6c464c4d17e7d745cfd20f3786c65e546eb74565984aaff0550427a074bafc6bc583806a2eb5acb151deeca2c35a8fa2efaefda17f5242df2c2f6a4baf16b2d689995ce7896ec93c0f81901a0789ca76814b49c8d56d846546472984603d521924841def323a36c1c0d23f551151124c40c1cd964481888aca737640128cc9b6feb821855cf1392b5ad0071fe6389386ded227eeb8f4af27a2fa6128fc4c0a9578484182830d97594ca8b856c3c860d9896383649aceb8240aa500dbf1b540d0820a232d4e86b676ecd59b94993452b1e20152385784af462b806434398262ee884d4dbaf1c5f9e5404d13f9c5a5e83ffb39eb26a5414cab5f479653bc916d95b49b5d8a621e95a588246052602da45a080d3f928c4c4820d455a31673924dcced89af2a4bc2a815621fc4d9500eaf499d2f42ee7938a28dfd8089acc467bcd104a93a097b211a4767f9846a75cecac405e35228efd3ecb0ed72a85cd3607832f4b5c6e8d7b97319afa1836eca366343a896439de14d3ce3e2f0740e3bb79e9ab275e2b7523f6528d0ae6d22185ad89a61d5541ee33940e3e9ae556891f09090a22f4bdb303dea398bc99790a1333555d9a50aabde3b9e6238200b8254a8eb8c2920711a04978508615a3a6803b5ae4125890fa1ddb2e7ada364a05dfc13d645f8d8c7aed656a62c4a1f0804bc4405c2cbb5ff068d0e4979f232508a6166deea5c10149567b3b8b0ceb967d002ed3deb381c68a8d0fe71ad4301fb815c2a5c9f46f0ddca0d8f20205b38aa1b0fd32b0f6e91ed8f4b0b6ae5f02523772599e50f1f770aca9705cb563600863a81f4f74073ca4374cc89737f2601e0214e143920a
+OutPK = 535792f6599d034f5ed9e9b5c5b3c10110f32ec45aad4ad1315f9268a65f8b97d6f1b2d4200711378574d62e6c9b71b16ad3d5b70bbe4a8f538646973f5c076028a0e7386962f49059e3dc20bc724f4ad20eb9402a5d1df57c09762ecc2804a9fe11c42f085a174c2f0dc98be0bea24e3e20b1f88df0545f59bee80282b166861a43ca8273a6013f760fb2bef65c37789b1aaf02220dc155d153884a40359e511e9c23a6f2434916190a11fa75320d6945af461a921ed2ea3068cacc33822147e9b8cc59f4c958483039a50d145d5b7974136255185478587528697cc20f989a2912c6324ad4273690b34baee43c26dfcf01dcbc4dab41407bf246942dd41d1926b24150aad8892b58116895ef53bf281088439c8947189d00879e931192379b9633a1235452fa283718f692a7f566272575be6076a995ca80149841abbc43d7941d810b07687b0e1e9e6d2d439c1d1c8a47f486a41a2443e7d95962224af6562c23e6e5533c2a82009d241424daff48325aab87867924d0ed1b57166934afdaa52296ab097aa2181328f88995b4095519f7545518add8610e0aa5ad32776986fab0a9b83cd860f054318b1de8e366df454bc26d8672dc89b4aa268066067e2727469d32463253f0aae277bead7f9d1090d215e6b3a116268617766b75263c4ab6ec010918e566696a93dd2267d30321897e8507fb348511276df33497726bb4c1d4d38f0049a5cf4cb5841c61e96dec029218579b100539be5216891914606f1a97cfabc284167e8ccf1acde59d0c61542085a6ec490913500e488a389940a376d1d799b4332e470a44190ea2a435770feca6bb46ded13790206fccedca4192a77948eee594ce6e064f49f5e7bd85baa272a67db9a68a5d9b44ee0495fb434579bb9a2c6be16c79d1545b85226b469bb857e2115317bdc91c0c2333c1e7000f476c522685b52d98dacf7325241900f08ac60aa225f52ee134978617c78d68726d76ad7e27b7776c1827674d267a1f0551f503ee960b3e3a7aa19af0640e3cdc1381f74542a13b6629d337c2980f40ba664461a982c5e736ba4d841c248ec345b05f9b46669a44043903453f03dda48e236d6714bd4e7fa89912d991a1696e40bd82fc0669b7d883840d624a74ed7fd7d6b57a549c231a2a4c1fd5aad98699607be149d65244644656d93f0173c02f53cd1c79b62e80ecd82cf5774a69e05ae0ea7a1c02352d499821894e9286d4077af49e9441acfad4b21465dc0dd359b07fc4617cc316e1a4954b55542bf07d818efec0ea15abbd04e2e90230ac6f6dde24084238cdc56649f1209f0ea0e3611c2abf8d45710184f4a54a22202652ae4a5ee9f720b4a023fe4493c6d22971b693f0fb9a194a8c9a41789b1d7fd020faa3c936a91de323d0290c84ff978695b09643512f6205a1e1150d842521718c0544812a6855ba63cfe15cb2bfb16dd9aaa54b1ce8302f568062c14122d767082afaad9c3d85ad148e969a1b0ed8d19516427f297ab8eb1e719e81a2b6e6da0148a933e830fd16650c66a3b2d57b4c0269504c11121c4ad1a0c839b8650416850deda33fa31d35d7442fdac994daef5127b3eab1a1587034a5ebe7911ec46139ef3b4b8c8a9889ed2412172d3c8a163f413d1dadf51c3e60df100cfd2474730cc63aa221b863b2a2271b8b1109610d417f489ecbeed2362385c127625c0d50a0ebc3fda5a5d1e645e890924dd38044eb645887795a02b6b0ac48fe813f17a47c7b53e58d15176110fc9b16b503f297b4dc6b28fe1148e96ffbd408e41489d201c590b2285c0309832a3e22a7441c70501857f1ca0744a0e20910683bf023b6397485246600f161d927d0d9c34d7bfa59fc7326b450edd9ba45b621a3ce9315914c798d96a98d55544051536cf082674e13ea14d8b028bdbe99451d0774cc85354afa87f3648d36c9b8a657bd595e2ea80061b6a9059baf41a652961265aa42882d926fcd4b91860a229ec22561d596b26950976b08719ced1e8469536d43f9a8a69998ae4ebe435739b811474b1c48721bae7aa36d40655a9ea69a1a5894033953f0d6e488d1d62133a9c309c3d49e8c4cae0acba512519d11a0997e81215cf55ac0ccaa055d6deb039c672ea8ec81b34a175b45c9448d45a1479c84d95031216c0b8f30cc286859daff9a6a8e4d836d5ea33cc030532de579560846311e7b496a501bec2de3ba760d3f0e609659f4109f0fc1f6c70df56eb6122bc08082784748f375fa9859bb2b6207a9550bea67af4bbd141a5e591ea83d392af2675575ba4e19636bf6c1670a813414d08b5fc989e49d8840ecba24a6d192d63a11bb6167a610f786a769039c83d99d9f0fc6fa89ee21a475c7960918fe5e70dea2da3c5985aa63f6889886a4b8631eab5910b9f0578ac94c919a5c42167435be09c487e496465213bb5e9db5d8658abc2a6416c68e873a8a3e224c9c18bea9b8c983c53654e5df65e065205721dc199cc442440b6727b610822cc9f4d044511e7fd673f168cd26
+
+InPK = 535792f6599d034f5ed9e9b5c5b3c10110f32ec45aad4ad1315f9268a65f8b97d6f1b2d4200711378574d62e6c9b71b16ad3d5b70bbe4a8f538646973f5c076028a0e7386962f49059e3dc20bc724f4ad20eb9402a5d1df57c09762ecc2804a9fe11c42f085a174c2f0dc98be0bea24e3e20b1f88df0545f59bee80282b166861a43ca8273a6013f760fb2bef65c37789b1aaf02220dc155d153884a40359e511e9c23a6f2434916190a11fa75320d6945af461a921ed2ea3068cacc33822147e9b8cc59f4c958483039a50d145d5b7974136255185478587528697cc20f989a2912c6324ad4273690b34baee43c26dfcf01dcbc4dab41407bf246942dd41d1926b24150aad8892b58116895ef53bf281088439c8947189d00879e931192379b9633a1235452fa283718f692a7f566272575be6076a995ca80149841abbc43d7941d810b07687b0e1e9e6d2d439c1d1c8a47f486a41a2443e7d95962224af6562c23e6e5533c2a82009d241424daff48325aab87867924d0ed1b57166934afdaa52296ab097aa2181328f88995b4095519f7545518add8610e0aa5ad32776986fab0a9b83cd860f054318b1de8e366df454bc26d8672dc89b4aa268066067e2727469d32463253f0aae277bead7f9d1090d215e6b3a116268617766b75263c4ab6ec010918e566696a93dd2267d30321897e8507fb348511276df33497726bb4c1d4d38f0049a5cf4cb5841c61e96dec029218579b100539be5216891914606f1a97cfabc284167e8ccf1acde59d0c61542085a6ec490913500e488a389940a376d1d799b4332e470a44190ea2a435770feca6bb46ded13790206fccedca4192a77948eee594ce6e064f49f5e7bd85baa272a67db9a68a5d9b44ee0495fb434579bb9a2c6be16c79d1545b85226b469bb857e2115317bdc91c0c2333c1e7000f476c522685b52d98dacf7325241900f08ac60aa225f52ee134978617c78d68726d76ad7e27b7776c1827674d267a1f0551f503ee960b3e3a7aa19af0640e3cdc1381f74542a13b6629d337c2980f40ba664461a982c5e736ba4d841c248ec345b05f9b46669a44043903453f03dda48e236d6714bd4e7fa89912d991a1696e40bd82fc0669b7d883840d624a74ed7fd7d6b57a549c231a2a4c1fd5aad98699607be149d65244644656d93f0173c02f53cd1c79b62e80ecd82cf5774a69e05ae0ea7a1c02352d499821894e9286d4077af49e9441acfad4b21465dc0dd359b07fc4617cc316e1a4954b55542bf07d818efec0ea15abbd04e2e90230ac6f6dde24084238cdc56649f1209f0ea0e3611c2abf8d45710184f4a54a22202652ae4a5ee9f720b4a023fe4493c6d22971b693f0fb9a194a8c9a41789b1d7fd020faa3c936a91de323d0290c84ff978695b09643512f6205a1e1150d842521718c0544812a6855ba63cfe15cb2bfb16dd9aaa54b1ce8302f568062c14122d767082afaad9c3d85ad148e969a1b0ed8d19516427f297ab8eb1e719e81a2b6e6da0148a933e830fd16650c66a3b2d57b4c0269504c11121c4ad1a0c839b8650416850deda33fa31d35d7442fdac994daef5127b3eab1a1587034a5ebe7911ec46139ef3b4b8c8a9889ed2412172d3c8a163f413d1dadf51c3e60df100cfd2474730cc63aa221b863b2a2271b8b1109610d417f489ecbeed2362385c127625c0d50a0ebc3fda5a5d1e645e890924dd38044eb645887795a02b6b0ac48fe813f17a47c7b53e58d15176110fc9b16b503f297b4dc6b28fe1148e96ffbd408e41489d201c590b2285c0309832a3e22a7441c70501857f1ca0744a0e20910683bf023b6397485246600f161d927d0d9c34d7bfa59fc7326b450edd9ba45b621a3ce9315914c798d96a98d55544051536cf082674e13ea14d8b028bdbe99451d0774cc85354afa87f3648d36c9b8a657bd595e2ea80061b6a9059baf41a652961265aa42882d926fcd4b91860a229ec22561d596b26950976b08719ced1e8469536d43f9a8a69998ae4ebe435739b811474b1c48721bae7aa36d40655a9ea69a1a5894033953f0d6e488d1d62133a9c309c3d49e8c4cae0acba512519d11a0997e81215cf55ac0ccaa055d6deb039c672ea8ec81b34a175b45c9448d45a1479c84d95031216c0b8f30cc286859daff9a6a8e4d836d5ea33cc030532de579560846311e7b496a501bec2de3ba760d3f0e609659f4109f0fc1f6c70df56eb6122bc08082784748f375fa9859bb2b6207a9550bea67af4bbd141a5e591ea83d392af2675575ba4e19636bf6c1670a813414d08b5fc989e49d8840ecba24a6d192d63a11bb6167a610f786a769039c83d99d9f0fc6fa89ee21a475c7960918fe5e70dea2da3c5985aa63f6889886a4b8631eab5910b9f0578ac94c919a5c42167435be09c487e496465213bb5e9db5d8658abc2a6416c68e873a8a3e224c9c18bea9b8c983c53654e5df65e065205721dc199cc442440b6727b610822cc9f4d044511e7fd673f168cd26
+InA = 312dee62b48992a86afc71cfed062c85e5f76ce279f42a4e0561540685c1cf72fcde7f4720ef87581496c59d3cf0d14a745aa1f23292c56ca380c12045b184669164c73c3a2492af440a78453a1012fca13d290be6122cb832ba9de59019b8d0a40b6e2a8a99483931b5ee2b4971256cc31107c2cb14503e079d27570e37ac03c2aabce21990c0e4693c2a4c0eeded78361503d9023fd60edc742463daa39d32826ba8eb136dc02e6fcad62aaec67d9392a958ee094ba90b53b78c7496941644a04e7654ef51d18b66c80d4b55d9c3d5153760e8cb8495182e0a8ce50327142e286c27303ce56edaa6f74683cd8d10ef12d9970c30352574c06bde230f00d089214c6ad913333430a903f5253f13fcc4249b50efd5f0ad0c7b450713f84190e722c8b368b044744ee5c04172719d48a2919d3815c0c47a04848011c5843ea755007b9458a7c82340a243045d017946651ed32172980e353495df914ad64c2ad4ba925e4abd2b2fddb544386e4dd65feae8e2b0ccd0a2d2742c8666266762b4b6713b17240b5776278a6e1ad4c2d42ed64d32b14cbc66e7cc8844510a30faa9bfc179566034865ff0f7fc5510ca31e3093d39ca23c5c5d2e4b5b61b1c41be690b3822f6624cc99c2754710893f01105682c8685c11e36536114f07261e1e6a659f7e25c59824af93030a773450567a6c5a7f0150c7331cd4f60566c13a2320f2bcf6536e6b16ede24c3cb69f451de672451367969a6dd6d0afa58afc7daa9b6fc450d802ba879fc22207289783a79e614d3cd4f6ab0652a6a17bbb7f9659d4f14241a08382a549f4ac102ad0f8d8dd9706f0db4efa9c2dbbb9885b4e961289961ba8b8887d0b9dd20f5101e0890012d39a9e115c87a255001287b08b29ed9989b670b802e485813155bf1398c0b0409be7c1cba4b0a388014bf5bd5218199e63afc8d5a1548342fa14fa0e135ac7e05a5b9e1c475b6e7e30c1a75d630c05b43125b75410d055744f35805232183d57915a0e6a28eba865c61201baeb03cac68fb23fe6090f67f80cdb5039bc45638afa0a36520ac20c9ebd3a0d55d3c46d0ca48e52de52bbe70c3c911fceaf6b96a2e748a69b9d94bde44d5d5fda738226d3768a5d96a0e20b112af01ff59bbdf9c9bbbcea6af9ac22b74c2721222c07842296c5a1de44053eea0870b94ec94a1b0b1710e3dabfa3aab9c49ac1b3e019b712c8da748b1859b2aa5590ec4a7e78f1f1461f4b23015a5a9f5dd2e2624be2098580cf8de4b470a799a7e6c8753bb02b10c1dc1e70bc26e9c6d89039d282a8edd20274b5dbee6184327249664742e733a6d7d7e01100b638408b3d0479e80980d58c026a347fad6733de51b013f983455e257215adc3761624288cbfe8cda20459104bd18958415f2c120704cae55d2ff9637fb599835745869c127a4522e1e26fa0eb8f04c8a6cce41b09be1b1965c05a6551f74530986b6d7adfc53ff80bbb018b56e66665df1b0455b25d34c18b4b5b616051af4ca559010da68b8fdc6bf998b39f0def85c9fd9db86960d9ac5d99ae685bd2686546b6391c08426dfdeb133de4939689c67c569a2f7958ae70d31b5620db92963e0af8e2c25377258aee1051c9adc749a0d1e87d1b1bc0c9a5c13468b408172832cd893e025076b77d5a496b1776053fbac2a8251c5773632b91c7505bcabb57605ae2280e30b94131b63fca8caa8b6ed8477e60cb5005c48d91952b25caf5c2c8743be2e6754b712c0710d4f9f94317fa24a411271f8b4e8669241d6ba9cf65b7493fba1adcd0b4faaaca6bb2d8d79cb4e233d704a6725e5a4f19e1f498a96e783817b470140c0a25551650cd88ae4fd330b4212f6d848ae902ff662573a0ca7a6cc63898a6eaccfb97613456309e32e800fa039735a486962c9a58493afb7b9dc0c4bd9b12bff7e767b8f6f42f7bd53d0837a7574ddafd04cde42234a4919981cfb6d8841a3c063e03a52bf8598b0f12d6a28f82a4177a5ee7c3c2af1f0675685f8ab3c41cdec3046081b268f7999d9a17555826aa6052b8357d0b68b606a1d503d6627bbe608a4ccf94851502946390448779e9ffbc99a8d66874e988774b508ee66a03c5c94ca6224a618caa1ad9e69091ca4aaf840b856e2c1742a0ef0b067eca80849e7145ea574c093a12736bd207a51f51379bcb2ac2f08532e5097b6e0455516b0aa27c2af52f406b3f29cdaa7cc9609becf1821dd9c9839221b86f01c6c1c93169bc0fc6f0864adf9cfd1966e00cd52fad9a9f522ca821a2a2dab40fab8e199aaac12e2f1154032a49c5ea7a4ec2341051714136ab7e5193de862f12005881933b4601603daf7056e2c8582ce56b2a9aca49b5f3411cb182fd85f5e586bbc8124cac764eefe16242de424d5f89d1f5ace352829554c6cf10b488c5e7513dcf4a2685c904dc0727b040d14e7d92115ec256b590ff1a9b2295d4e7be92638b21fd55d8ad23165318d844b252523fca19961b9d60cd76597541ca04dd310080127a2ab8145fe9a8ba5a4
+InNoiseSP = c64a30f40c2146684b38004f9863741b2214bf060817d2d629f93e74cbc804336cc16adedf04d06e9d15a08426d15811a0a649cdd63ec59b4cafb7713b793d3c06f35b70a516eb932cb0086ebde5c3d7ab1f9017a10a0c382d3a7add8ea8195fc1436da06591293178f58ec70abb2e967ea9b6da0488995f593608c815a48c9c26b8035a33496efde470043b6cecb9f1c1c4b1eca56d572a382fe34df759cd15aa0465aa29e16e9fa71e673784662d534152db401db62bd0762864e84f392da410da063ca169646429fa5f361798e26fde806c9f268879669791adee4721d071b1ef4f7a6f64508e44e1b47e2c3bf0c12f77b4350cb2cd1f96d76415af453d016bbd638aafa1606d8e58eec8e1a0de86b466d6f7b7cf469d1d6e1847bc5c6874d78bd9b14a630be4c6db7b8529ef8fd18832084491635ad6c97e55b9a60bf0a4ea4899017481dd39a3420269417c71a520d7a2b3458d4f4e4a63777b14bb84ab31f2561c14005466c58a9e9a588d96c252e17d8e82cb3509d406c151f0521d9d774ad166675801a54ca6f0993dd12cf15f44d20da8b9fb052265bcc6524ac95221377834348cca46a23804874b12f9641418f6454b4612ecb7ab1ea664e4047fec42b2790cc6903b1205c8ab668a3596b3838ee958996f09d4be74ae0a18ae68ebf99c2d51df8ac3789cd2ee2521bbce27b4c718a6a4a210c124e54898d9ab04295e11e7ed01bb5b4d12cd9e341e0293b539a8ba619924db875d1f30959499d70186af9b64922099989596ea22f9399a0da0c2b049913bba52836a0b9cb0e6a0b225bcfd2c808e9292082977b7ecdca3b556bb354eaa2ab2a5bec6cd1d029b561789d28c523eea3822ab1f6468beb9b06878bb7ca69ebcc5e0c4ce9831ed2ed4e6ef4c01812e20054966b06a93e5896c2a054e14c90761793b3b8ea562dffd99a71b6854283833b590b5f03d7ca3f25534684491091e17dff72c9174474f4ad26ace5e51a5f78308716878d1ee07bf441f172b3472ec324cdda53bd04ac00faecac6a012a97a6fa22817ca217517e2b6c9dc74245a6a0b76260d4bfcc5d4a2de267815968c580d5dbeb2ad5ca39c0e979c184d39cac65cff1860f589c895bdde0dfbf45450361bfac39d8208df9d87f476c966d8daa8da7d1a5ff25a00d3a771706cce66a2e0e827fc9c55c2f442a831012df93b3035a51a4371049155cf154a96f5546d65c14e0136483bbfddfcc1aa2928b71010830a60191f9808840c3c894cefc2755ada5ce0a3dbb34eee0a0725979259425ac7678d834296039201cc4786ee974fa49497931461c95fbccb07555d0e60184664344992da6d42c9253c176deb548996a41be23e7a03e04badcbebf70dc6231a176aabb310438e25c379f4796d9d038cf7f8ac99aae2abc5639abd3f038e722465b8e45f01a2587534de24fa77d2b1ac5d882346a4422ae3211fb0f751a25c92393524619bbb014eb1564a245be8fbc55eed48356004e56d396f2f55a9daf9e0a35da47f23b7940caa0d2e26d4d68d88c3dc7a180637726da7336ea68fa4e5a8c124342c93e825a47419bc47e43b747e8c45558fba94e8ac0b5a0a5b51bc667b114c94064fb192b7182ab46908916a233fc959903e065b4e14991224c1a31424a18a0445e5c1ebad02ae87a88b72800d694c6bc940df3574f7501893835298b842c4d2b31063d91a1399e08a66a6886b59ba426f022d2317f5b298cd1dc1b1df3d8d4bcca913754a4b1946b39156357add4143948ac49c8644779b5ab1b7036193b7788d9c2ba55d74fe8d46c4840d7b328574320942f5f3e5150feb3079ce2c7abe5923e62c217e6f4e1f36b5796838c617e75f7921cb9a0043cfbd4da225f6f45492ba7f85dd51c62695f94bfee8d674b32b81de685530b7bde2825b000c3e2a8eb1f44c1a52cf23cea72fd517f36f4e587dde8161093f7801693e71e9f1d757f8532499a414a96aa16ac8b1409bad18205ec0646c5546b4047b06382101c521ba414d6c3b5f81c3b2c1898fe22538222cf825ce50a8b3dbad37e04db1f538d1701061ed41ba593acbcd3ee198442b5f1966914930129c8196e5cc422183ed2726b6fcba19c8d285ff0ab0908261d713856e12a5c198f9b2913fecfe95a0a4b4c5125eb87d640514961b5720582fa4d6ef87ee653a805570b4a326a6c2c2a46398fea5ed1e1fca0c857799de7a4b2258846adcae3282417e936bda359cd4893e118b363379125d13de48764a8cc2ae391745b263c0d55978900a7ff39902c5f6f85a8a254858dc529f4c6e2451ccbd140e82e9ab60f045efa83a12390e62060e920bb30eb09c289325597e0a819da13a0a555bdd8491599975a12c9f2aa7ffc660b75a2a0735749467ea7475131da2488427db46725242819dbb7bda96acef61c1367c62254f4868eb0d6de1082d70370849764b3bc02035af46dfa474791a82ca87e433d62174b6dca59532a59d0560d6b0779e7e3be36d9ad9723abd0e9bf8e9d56914e50140d8de2c
+InNoiseEP = 1084eda5639e2a95dd2c094281973c88e05852785c2d8e11822d4e257b8299449f751d69d084fac98c6a216e028ba52dba4015ead204e893ebd62d323cde8580a99f05b56676a441b1d636fe553143cc573e1855f24c667a9d8433efa38af3e0de544743e69769880796e95e6006919ef5ac9c9bb7d416719b2ad80de0812e11e3d3c541976e1f405662f27aa11707b8a858bee897caa5e0d06d9d92ca099c75a747e4dda9340a8b2c8d63ab767279e7669e7b66ca2718851bf0adc494906799c5b25e744c06c74445feb2e8ae88161079b46bec4cd920de6fc59de5d2d3f96f8463b4ba77ec7eb32fb3b0b1903661072bdb6018aeffa56125b09016e89a40817e38607eaa801191a493cf0e96207972a24561bdb40c3da2d78903957ff268f0e9dc3a3f3486fca5075a7cb832b2a08919e9366f1d4b2761a63dbec44fc5b5aed5b0742773e58d1a7cdb044204883d31b3a1d8634ab26f53846f7372587afbe4cf471fec7068e574e89d9c2e6ce65217d0cc6fe6620d1601e5b762d36a54eb6612d7ad663bad406111d2cc3618dd891d42ca66fe3944f38812392bbe8b9086e4f259be81b7953756532d741a51087377a8044013760a72806b108c055173dea0dd813f8a70349b9fad63b44f20a3b0418f4548316fd26cc740b6e9b324930b252822267b656fc1882ea0856301971d1a7e3fd1630a9590b96d16e7c71e1d808d00ab899f780809a612c2fa152fc4497e50622c37d69447c6ccfd0d355a10778cd1b88894c9d47ac12ac7a4b311d359863caef86aea8d7416576f161fd92bab081cb8e06d1d198d6e9b0895583a651a229b250778dc049710542594c79c45f338861e679cc554e6be3c2740a8733655e6c5aa5b8bae797f5b442a58599f321ae316e592bc380b879a87483eeb9d9761a550ae9ad46940056582d11ddd6870108b16a4d53b11896c6ce60ce1415e3f3c082a6a10413b354250b0d97561d4a0b9f36588137555c21824440b2f928aa6e3403a9061fa4b53cc73dda4cfa867449d5c65a090b16a87500df94b4a08882e11910bc51ea7fd06eda4a7a66640c6ca915ca89ee5cf322b57412d8c4d8d3385ad147241ea978f4282acc3dd10f3ba036be51646a3c63f3c578380b6687a816fd0c2dba86d9e8ba79940cc0b7c49e1034681227cddedf2ee6e638549141af0744d7d817730ea98aae4d0bdea72fa9506511714c64574da0e3221b1ee52d4deadd3bd9934752fb0c3a4f148f64f21a2815131b842ddb6680c49c21ae3a7c9dc4e5c405b8964728d67499fe48665ab7993b91a972e543699e7336dca6a889a8a3636a86cc7df9ef9234a1855629a01f592a6b8c6509bff789f2c446f81ae591b8458b5089f10984fdd8bbbf46259b91009174b4a8d2ee32fe1c190360d91d251638661b4c7e8ea623e6a2ac138f1aa8d9a2a2c5c87d83a972d4b36133b69416e8af142a5a612f0d7b80138b9750ddf813b7ac8204ad789bad2e166a5e3560589c14e9389a6932c743fbfc78cc047ca3a06da436baf8c0a651dcb74e356b9e9e7b7e3d92c88ab0920e54dae161491d1907159b7bad30e16db74547e061f3b732a819ec9d565cd769e915c8802a59528f05e2d70a04d991b6af9d4df6c122b6ffa15c62db8f6eedc120f7232a2e03a1b1442a67da1d6463af40d1ca8b2e2ccc5845c530036a6085b7f2969162c58aec6ed2ec71334583f93c47043e94c34d2cb2640f5b0884f1bc3ae9e2658e9d40b18c89540542c877e7252daebbdcb1c8d0c5ee5eb6ab46a3efa8ec02877362f562190614c65893a0240185ab1445727e5b400ed996184f0076a155134242de6923095fc65812a548d57de2882483c194f8a92d765d51119ac195ce56b785865c3837806f516c5566c5a32e5493e6da2f7959c7f8e2ca03a5b46b488629e463436956f2381f938a0311dc4950b3b56164598b2d71b1515492630449465bc888dc14b7bbe7e3cce4fa2f0861d52633f3689f068f19645525c4c09b01af422d95c9b480e1f0a08691ad98d29940a22260296e85436e47f891eb2f27261050464c7c1603c904b59c268c98490b42f4b7992c952d316c14a76928b6c0d3a19a93427ab6f8f503bc087bc4bc8227990378ec9a4c8bda8282f4aac76572519802d89e606a031209bec03b242ae73a6a1c839e513b50415d9684e58eb44e90a7c7957f4accdf87fe46ebf45eb12e8665395a5e357ae64284c841ec664bd9b1f2f9f53594d96bfa367e47fe6338804c6e03409aae54c9a3032702bb50fb3039bce16b0d00f1a6d747dd74d17054f2923f8e43316006c3b82e4b3b003b551ba534f1a8a45bdbf1729813f2005812edf29df358f629047ab933dafe59f998a854421621fcdc10726309122843347a07671c91f048dcd1d0b2369988ddc13616064838be1852765ec9a145a2dd6247afa521a42ef885cbb0e226fd84f8693d0f836daec92c75486a8434d9cc40436b9866c90600e000e3ade202446c145866931a138e66d96cd25a256219b
+InNoiseEPP = 00c0ff2b00fcbffe2f001c00fcbf00c00010000000040000200000c0fc6f0030000800ff2f002c00080000c00040000c000080001000fcbf04800030000800fdaf000000fcbf00b0ff1b00fcbf094000e0ff0a00030001000000c00580ff0b000000ff6fffdbff16000180ff0b00130002c0ff0b00f8bf00c0ffcbff0a00fe6f00b0ff1200fdefffebff02c0faefff1b0000000400fffbfffebffc2f00f0ff060001c0ff2b00fcbf0440013000fcbfffeffffbfff6bffd2fff1b00f8bffe2f002c000400040000acfffabfffafff1b00040000c0ff6b00f8bf0200002c0004000300002000f8bf0080000000efbffdafff1b000000ff6f001000000000f0fffbff06000580ff2b00fcbf0400ff2b00f4bf0400000c00ffbf0180ff0b0023000380005000fcbf030000e0ff02c00040001000f8bf0780ff2b000800fd2f002c00fcbf03c0004000fcbfff6f00f0fffebf0380ffdbff120000b0000000fcbf00f00010000c00fc6fff1b00f8bf00b0010000070000f000e0ff02c002c000200000c00030009cfffabf024000f0ff02c0030000000007000200002000040004800010001000040000e0ff02c00030ff0b00fbbf0080ffcbff02c00180ffcbff160003c0000000070001c0ff0b00f8bf0140ffdbfffebf010000f0ff02c0ff2f004c00fcbf044001b0ff0e0001c0001000f8bffbaf0010000400000000f0fffabf007000e0fffebf00f0005000f8bf04c0ff0b000c00fc2f00000010000480ff4b000c00feaf000000f7bf007001000004000030001c0008000600ffebff0e000000000c001700fe2f01000003c0fd2f01f0ff0e00ffefff1b00f0bfff2f00fcfff2bffcaf0020000c00feefff0b00e8bf0380ff2b000000fd6f00d0fff6bf0440ffdbff060003c0febbff0200ff2f002000f0bf0280ff1b0010000000ff3b00f0bf0030ff2b000400007000f0fffabffe6f0020000400feaf000000ffbf03400040001000fdefff7b00000000f0ff1b0000c000c000f0ff0600feaf0000000000ffaf0060000000ff2f00ecfff6bf0200001000f8bf00300000001300fd6fff0b00f0bffaaffffbff0200fc2f0110000800034000d0fff6bf0030000c00100000000010000c00010000dcff1a00fc2f000c00f8bfff2f00300008000500001c000800020000f0ff02c00070000000140000b0ffebff0600010000f0ff060000f0ff0b000700fe6fff0b0000000100003000f8bf01400020001000fd2f00dcff0600ff6f00400008000480000000f3bf0400003c0000c001c0000000070000300000000300ff6f01100000c008c0fffbff020001000000000f00054000c0ff02c0020000000003c00040ff0b00fbbf01c0003000f8bff82fff1b00fcbffd6f004000fcbf0100000c000b00ffef001000f8bf02400030000000fe2f000c00f8bf030000e0fffebf04c0ff1b0020000240ff0b000b00fdeffffbfff6bf07c0ff4b0018000180ff1b00fcbf00f0ff0b0003c000f0feebfffebfff6f0130000800058000100008000640fffbff1600fe6f010000efbf014000000008000000000000fcbf007000e0ff02c000f0fe0b00000005c0ff0b000000003000100008000100ff0b0003c0fe6f01c0fffabffb2f00ecff0a00030001d0ff0a00ffefff1b00f8bffd2f00ccff06000000001c000800ffafffabff0600010000acfffebf0300000000f3bf00b0ff2b00f4bf007000e0ff02c0014000f0ff0a00010000fcff0a00030000ecfffebf00800000000f0002400100001000feefff1b00080000b0fe0b00fcbf00700010000c00ff2f00f0ff160003400020001000ff2f00e0ff0e000030002c00f8bf0280ff3b000000020001c0ff160000b00000000700feefff6b0000c0018000f0ff1200feef01300000c0003000dcfffebf0100000c000400010000f0ff02c00000004c00fcbffe2fff0b0000c0feaf0100000800010000000010000080ff4b00f0bf007000f0ff0a000040fe3b00080000c000f0ff0a00038000f0ff0a00fb2f00c0ff1600fd2f003c0000c000000000000b00ffaf003000e4bf02c0ff4b00f8bffcefff0b000300060000fcff02c0feefff0b00000000f0002000ecbf034000f0ff02c00080ffebfffebf00b001d0fffebf054000000003c0ff6ffffbfffabffeefffdbff1600fc2f0000000c000000002c000c00fb6fff3b00080002800020000800004000f0ff02c0018000e0ff160001c00000000400000000acff0e0000f0ffcbff02000030002000100002c0000000070002800040000400fdef0010000400ff2f000c00fcbffc2f0030000400fd6f000000040003400040000000034000f0ff0e0004800010000c0001c0000000f4bf030000ecff02c000300110000000fe2f00e0ff06000680fe5b00f8bf0380001000f8bfffeffffbff0a000000001c001000010000000003c00100002000fcbf02400000001300fd2f00100000c000c0ff0b00f8bf0000ff0b00f0bffd2f0010000800fc2f01c0ff0200
+InRand = dcc79ac886c7ea2fb60721ed2c18a72a4684f1a2668c8bab4b7cd6de29e9834c
+OutPK = d2d75576a45915b2cfd75b4bf06b375114e4f74011e94172661f6644abce4f161ea0558ea13e358eb55f624a6191b25c6ae818f358443078ae43df8a800024254fd9191219b3ee6e2cea5fac0e0a0a5b8aff580b69972b592c311b65ea283267803a7407a663685e87419482505288759406c311ff79b69fd50923ba10120fd14849689471f3d74e74fbb17dd8a7c6e3315147b4d2b6e10b1d8e5fe5c0f9af15b7c80d2d165779a2ec26518bc9d8400def4707f2d8598e56f20501729f3fedd5fb136dba0e5539670a89906e9fab0327cd647d5a9c80e9dd5501469123deb9654d477b297cc4b4efa0f39aada4a37b54b94715a53f3b4bb2f2af109627504db876f505d020fa2103ee81862992a3be24b14749f52017460e83adf847a049108eca92294d117b1e6a146829a5b5699b73312d228a5808e1b11ff174484cf9920f20a016cb8aa461ad41ee13ada4f26d223d8e0678205a079e0de22b51a1265b86c015ab1132c19de6fb09650cb1a33f14eed944291b4629133a3c156e7bf85dfc0887a753a72a5930e8890bfb59fc1d5fe926fb30be72d520c8b6a5908cb5da4df7a34135b3862cb85c1162202dcea8a0a843ea441004d0d4a7ee90372174ba8a680b0137ec4887f44898e3c0a22e3696c33a7a76980b8f5c45ea126d769c6a337574384927e5c17090bf8a506edb6b60be7a9a7b5a32851aab83b2c4d8a66a44636261a6f0b5e72830c2edcc38069039701d58aa0f4730385f449cb3069e52b38d55f2d7ac981bfa15af4bad04200964b8e8aee47a7420f8e428ba9a5005ba89b323a8501fa3a5b0332895a865c408b24c7e8d8ae0f710880dbad5d0920bf676a1340c7e77b1fd2e890f3aa492ae2c2662bdb451f09e17623353d37eb0cd20a7c96abe0ffb2ffc42f88171374580e27b64a550ca636aed8e12758de313d2f22a6c6feec89dca4bd0cd69a5cb588b0a9f6d61a67d9ffd062627aba0653f5a5025385423a51bc5570afd0d88d196b2a8855ce606d2d5227cb1182a90b224ee39f52f5aa9d6b685210ec6db683caeaeddee41c30c26304464855b7562898482a361f4567d53c703559850d9436480c9d2923f1c4264721893798fe950b8dea6466eb51a045943faa88cf31c1e4dcac6a741ebad731a604ea3e04c558dcdbb82d361a1de843b59587c593f0c12a5b7c4acc325c41a8cc9271ba5d6763de51c34412aa3fc951bc4072c22feea35528d65a55eb554641d7ae6ce6086668e1d2758a8a7d50ddea987ad5bc2619e4be2cc8f49e10a13436225e08b7da09861207e2b7cfbd8c56d5b5dc7002fd6b3dae095189c591225153e237c703da222dac22b6897936d567222d66d2641b23037d0299b8a0e33e3c5839dc16a54e81499f2a13c305534283641e820e8363a17e62a86d49d7bb8eb85f5cfad9ea62dfc99374e0d75d5a1695bfd74b362ff561d41433a234b274c2dabdd5254561365b64968f105618aa8444daa44dae694766df7213fc4255fe4c3841ca975d10bc89b198e31531f7a14873cabfa048d00a53d8c3dca1cb1934d206ced70652fe0b592898ffa20244e23413f164ad90f7d43bf55ce346930efc89b1a4c02ccde523b408526c0970b4b6d8806510cb0d435ba7aada855c56ce66457ab562a124d591d9be210c4566bd54ce5091e39275cd2d49053b900518535a1d1c43b98a01ab99d8d41068a461831fc740a5c6a6a3bc25a16a7bfaadd80b5dd288058f341244b520b2ade65b6fd98dd197c14bd410e7b93eef102a45fc6d066610ff6af25414a7c96d9e625fbd28924bb9dd090f1f51f4b2de892ec0e536fa8c4eb80015136454c656566800d2871e4d5ce6a021db100c7296f2e0f066b336a880d24d6d5b7346cee9356f1f2426cc9d40100572a13eaa0f4d15ad5a4e24ecb94fbb2a85f0b06e9b2749758adcf88662836bfae9126f7ac9e941081288f944a84957ce3e5a9041f5ffee3990ca002596aa382ce515b27a171dc8c9cfea4ef282a25089aa99a84bd1d8e062631b7b6a00bb551f749466814f9a401b6b2a2b94986a618b98e1e076091144e628bd6619083bf8d33c36c2488be8194bcee7b95cd6480e097d6f6af604f864ff3275e02976995b7191b80b23f22cf60d11651775184f1c6088420edc352b5619f0badcc90f355575d2cbe5082e9775b01fe880c325ff688dc90e63c61acabaa1927fd89eecb7b99ce84b3ef0839887ad0bff75e3765e5ee2e09857106190e191e5437facc5a90798b442729f824cfadef839fe21daa64ba8a86ce72ce0e03e369c6b0e85aea721b9c534c900ef6db02773853eea69db49b80477efbc0e0ab92a37076a5314c181fb564affd4bfd011bc0e75a2357cc306796e0547951d0f771ec642dcc36b1e40ebfd51b06bb88a1bd7aa98d07ea217daa0ad9220d15bbaf460e30a7003a2f068e4783845230a3759ae509bbebe620a0be8807e28ceda71ed044354258f5461d42c76f510382da4f0140821527a23b220ad423126d3f6a1c18d725e55f
+OutRec = 00000030000000030000100008000000001000040003c0002000000002c00010000c000180003000080002000030000400014000200008000040000000040002400000000c0002c00030000000038000100000000140000000000000800000000c000180000000080000000010000800000000200008000380000000000003800000000400034000200004000040000000040001800020000400014000300004000180002000000002c0000000080000000020000c0001c0002000000002800020000c0002000030000c0002800030000c0001c000300000000200002000040001c000100000000040000000040002c000000004000140002000080003c0002000040002800030000c0002800020000000028000300004000180002000000000c00000000c00004000200000000340001000000001800000000c00000000100000000080001000080000c000200000000340000000000002000000000c0003000020000c000040001000040002800000000c0003400010000c0002c000100004000300002000040000000010000c0003800000000c000340003000040002000010000000030000200004000140000000000002c0000000080001c0000000000001800010000800018000200008000000000000040000c00010000c000040001000080003800020000c0003000010000000028000200008000100000000040001800030000c000000000000080000c0001000040003800010000c000300000000000002800000000c000040001000080000c000200000000300002000000002400010000c0003c000100008000280002000080001800000000400000000300004000200003000000000000020000000000000100004000100001000000002c00010000400000000300000000040000000000000c00000000400014000200004000300003000000003000030000c0001c0001000000000000030000c00010000300000000300002000080003c0001000000002c00010000400014000100000000040003000000003c000100008000200000000080003400010000c00038000100000000140001000000001800010000c00010000200008000180003000080000c000200000000280000000000003c00020000800038000300008000140000000040000400020000c0002800010000c0003c00000000c000340000000000000c0002000080000c0002000000003000020000c0000400020000000034000300004000000000000080002000000000000030000300004000100000000080003000010000c0001c000200004000340001000000001800030000c0000800000000c00010000200004000300001000040002400000000c00038000200004000280002000080003800000000c00034000000008000240003000080001000010000c0002000010000c00028000300000000100000000040001800000000400024000100000000000001000080003c0003000000001800020000c0002c000000004000280003000080001000020000c000080002000080002c00010000000000000300004000100002000040000000010000c0001800000000c0003000010000c0003c0001000080000400020000c0003800010000c0000800000000800030000200004000200002000000000c0002000080003c000300004000100001000080000400020000c00020000100000000200000000000002400000000c0002c0002000040002800010000c00030000200008000280002000040003800020000800018000100004000180002000080002000020000800028000200004000380002000000000c00000000800010000000004000180003000080003400010000c00038000100000000340002000040001c00010000c0002400000000c0001c00020000400010000200000000340003000040001400030000c000180001000000003c00020000800000000200004000180001000000000c0002000080003c000300000000040000000000003c000200004000140001000040001400000000c0000400030000c0000400020000400010000000008000100001000000000400030000800024000200000000180002000080001400000000c00038000300008000380002000000001400030000c0000000030000c000240002000000001c0000000080002800010000400018000200008000380000000000000c0000000080000c0002000080001c000300004000340003000080002c0002000040000400010000400014000300000000180000000080001400010000c0003c00020000000010000200004000000001000080003400030000000024000300000000280001000080000400020000c00024000200008000200003000040001000010000c000340000000000003000030000000034000300008000040002000040001000020000c0001800020000c0003c000200004000180002000000003000000000c0003c0002000000002800010000000
+Key = 4eba286d54cc289caf78c9964256be52db2f2cdc020ce12fb2c472f2e7913d0d
+
+InNoiseS = c1e9a276ceae5b944e79f8c57ab825a58ba9d01a23cedd5b2b2172a3f8ac35e80b5a3f84c034e226219e78e800453f3ab95329bfe0f4c17246ab6193db9dbe324b5f07f0998d6d83d24208d1b51298b5166c66258d26d86278843e3ddd13da7ebe0ed24902765149465113fee9461a84af1a68c8bf76769603e82a21a693fb0442bb70f599d8982076b9fc36a42c46b75db8b1699544e557fe21330ee6b53bd2310e6dee459b7a6fb55cd640ab1881334542aa920a8ac4e77c87c60ab1c98ae888f42134db67a7b809c69fc81194c487f24b61a011b086d058cb4556b582c54e4f047f50531416539ea7c1f04e7db95bacd3afb616812285354344167ee4745512601dfdae2a9afaf531b40e16d86569420b2805722ad890ed17308035c8943a0daad4e8c8325e8cd7d0263803879ebf420df2b761a86939b4e19ab161ae22bc045acd0af1985dca8230a752150191b20890d0788b9e8e299d08fbd7664e9645c43940c1b06d1c8251cf859d158fb5b515e40c0aaccd90b370020383b71298cdb335803d4b58fd3c8217435218b6b970d180a284d17b7f61ebeb9a46b8bc476bf321010f06128c02e171763dcd10b655aa2542213b6467800f134284da21622f6c20c522d1d05adf9bed5b7a6d63a3ab7236074e1f9b999138ac258900eeaf68a8328ed5084a23cf7cbd851ba7c222d1975363a0770cc446e7c4ef51e49457eaab2ef1fce02a1629c68b12d1aaa3a9bf041a765030d0e2a719ca712fec479ae3f5a4c2caba024ddc2c4c2c354bfb5c55b62daccb7a068adb03253437f87438643ee9d86929d5681b52b87664ace83a2672daae7c1f6c6aa2c486f9e3bb31c4f27b32d047a6af990e08d36e3a8fadb376cecf67989c4977d33d56db106107de6e89849646132a23858514a8931ebd4383d2635f90b2f17b7d92eae259e6ab4da034992a1b6ff215254e78a930fa6cf12283b7d23c73e08788a645b55268ca37e6c49227bb5f2f536caeab9344b7904519509990616250f127201bf5631ec28f5b9b7897870282b69bb46a8854bb5a66f626f9b5a394e062e4208c194cd1b963747216d8975f28a2480dc04a0f31462287d463ab14969827aa2f4fc4c30e977153e9e992688c8ad0b5c3efd17a4b95ec910881311649e223dd8d9348e11f0183560b345a4064c1205d4d41fa5b2b5c60e00dfdb2f31199d8897ea960fd78e6000b7bbb94720d275d9bbc819ca124dcf706a27615209cea60b952fb90455a2bbe3d311b9da08798491684a6291e915aa80b1983d6190610a094173575a7772587408338571e8e248a0b255c18a2cf4684040d215f88da53e9a6114903c3683d3eed814de857742e76a95282d87877289abbe54efdbc9d1961b1176cb5066d3f0bf7556be86106d1d6e9a8bfa8d5fbecf460095821989abd55b60261c8287a137feaedb0515e45694721081851957e88d105db0d974d5d5cd5a9386a8a037f315abe3b809b7f1b6656ac2d269452a39868e66b8e49543584f0667614a9f0aef09a7d956370a6a58353b70196498924bfa073ad687b1ee1a768ecabb7ab15f22fbc71579f7463429d69670d2ec605119f319574e572ee229f6241fab912addb1b83d71bd143149408abb1c15bde84ef93e6d2693c9423d99128832629e6d75b682e0e0181a0dcf442b4c27c32846431a3a6d8690f1c188a9a4274bf284bf12bf0a0dc9672d358b1b6243a631fdefa6464f9463c89f7e423ce03fcd5dd22fd606372296b024baa86c8c922071842a5084a799392ad39880a8b50d9386c7d60f3920db18c1feceda8d72e36e3db48858c00b0e921e35a09e1b16bc54428e0f119b7cd07466af576ec1908f489206e8fcb16580a8271d612ef272f8a5e18c947e10ff2263b08e46527b42d1c993774ed4139ccc0b39566adbacdd1aacb0eb2aceb6dacaa2cb1818b53e8e4b2995ddbc4f399f86d80e6644a2550d129f0a21e84f8950aed8cdd59fd1d09470ea43a19ca7f6a8de69422f0b3078a87a3129a8d819478a470d0624593620182087f57c62450c5f1121486c377648c3e5118e59659c56fd408dee705beae9b412467884904c1488cea3fc51696471ef154f9547ee6ee4636ae578f0611b4311c83e744f186ce2013e8eb00633a3a9223e39ea9107a13639a4dc0457116d20899da92e623b64240d090460a43d88476564c630f99a049f5ce5e34d645c8890e71099f16ebc72121aa044685fdf187e166155736bc1429c85cab2c808c0a1eda3bfbcc737395b4845031807b872407381212efa6856b69b145db0c4fa936ad6f05a824c10f500ad9e91cca8b7c0d57e38c3b82a8bc6d8132b6ae16381604ebfbfd8e8416177ca560e2983963fb1b25ae28d85071d251493e4c27a34319f04eb387a592e62c95b7e8b426dffe2b6d2ca89a71e091bb15c542ad9cb4211cd789b95c13972b9aea65e12051af44020f52971e61324245e9154d528879e559644ec8f7470e06a6d897cb84a13a656ecd55a69dad7234c79da3450a4d
+InPK = d2d75576a45915b2cfd75b4bf06b375114e4f74011e94172661f6644abce4f161ea0558ea13e358eb55f624a6191b25c6ae818f358443078ae43df8a800024254fd9191219b3ee6e2cea5fac0e0a0a5b8aff580b69972b592c311b65ea283267803a7407a663685e87419482505288759406c311ff79b69fd50923ba10120fd14849689471f3d74e74fbb17dd8a7c6e3315147b4d2b6e10b1d8e5fe5c0f9af15b7c80d2d165779a2ec26518bc9d8400def4707f2d8598e56f20501729f3fedd5fb136dba0e5539670a89906e9fab0327cd647d5a9c80e9dd5501469123deb9654d477b297cc4b4efa0f39aada4a37b54b94715a53f3b4bb2f2af109627504db876f505d020fa2103ee81862992a3be24b14749f52017460e83adf847a049108eca92294d117b1e6a146829a5b5699b73312d228a5808e1b11ff174484cf9920f20a016cb8aa461ad41ee13ada4f26d223d8e0678205a079e0de22b51a1265b86c015ab1132c19de6fb09650cb1a33f14eed944291b4629133a3c156e7bf85dfc0887a753a72a5930e8890bfb59fc1d5fe926fb30be72d520c8b6a5908cb5da4df7a34135b3862cb85c1162202dcea8a0a843ea441004d0d4a7ee90372174ba8a680b0137ec4887f44898e3c0a22e3696c33a7a76980b8f5c45ea126d769c6a337574384927e5c17090bf8a506edb6b60be7a9a7b5a32851aab83b2c4d8a66a44636261a6f0b5e72830c2edcc38069039701d58aa0f4730385f449cb3069e52b38d55f2d7ac981bfa15af4bad04200964b8e8aee47a7420f8e428ba9a5005ba89b323a8501fa3a5b0332895a865c408b24c7e8d8ae0f710880dbad5d0920bf676a1340c7e77b1fd2e890f3aa492ae2c2662bdb451f09e17623353d37eb0cd20a7c96abe0ffb2ffc42f88171374580e27b64a550ca636aed8e12758de313d2f22a6c6feec89dca4bd0cd69a5cb588b0a9f6d61a67d9ffd062627aba0653f5a5025385423a51bc5570afd0d88d196b2a8855ce606d2d5227cb1182a90b224ee39f52f5aa9d6b685210ec6db683caeaeddee41c30c26304464855b7562898482a361f4567d53c703559850d9436480c9d2923f1c4264721893798fe950b8dea6466eb51a045943faa88cf31c1e4dcac6a741ebad731a604ea3e04c558dcdbb82d361a1de843b59587c593f0c12a5b7c4acc325c41a8cc9271ba5d6763de51c34412aa3fc951bc4072c22feea35528d65a55eb554641d7ae6ce6086668e1d2758a8a7d50ddea987ad5bc2619e4be2cc8f49e10a13436225e08b7da09861207e2b7cfbd8c56d5b5dc7002fd6b3dae095189c591225153e237c703da222dac22b6897936d567222d66d2641b23037d0299b8a0e33e3c5839dc16a54e81499f2a13c305534283641e820e8363a17e62a86d49d7bb8eb85f5cfad9ea62dfc99374e0d75d5a1695bfd74b362ff561d41433a234b274c2dabdd5254561365b64968f105618aa8444daa44dae694766df7213fc4255fe4c3841ca975d10bc89b198e31531f7a14873cabfa048d00a53d8c3dca1cb1934d206ced70652fe0b592898ffa20244e23413f164ad90f7d43bf55ce346930efc89b1a4c02ccde523b408526c0970b4b6d8806510cb0d435ba7aada855c56ce66457ab562a124d591d9be210c4566bd54ce5091e39275cd2d49053b900518535a1d1c43b98a01ab99d8d41068a461831fc740a5c6a6a3bc25a16a7bfaadd80b5dd288058f341244b520b2ade65b6fd98dd197c14bd410e7b93eef102a45fc6d066610ff6af25414a7c96d9e625fbd28924bb9dd090f1f51f4b2de892ec0e536fa8c4eb80015136454c656566800d2871e4d5ce6a021db100c7296f2e0f066b336a880d24d6d5b7346cee9356f1f2426cc9d40100572a13eaa0f4d15ad5a4e24ecb94fbb2a85f0b06e9b2749758adcf88662836bfae9126f7ac9e941081288f944a84957ce3e5a9041f5ffee3990ca002596aa382ce515b27a171dc8c9cfea4ef282a25089aa99a84bd1d8e062631b7b6a00bb551f749466814f9a401b6b2a2b94986a618b98e1e076091144e628bd6619083bf8d33c36c2488be8194bcee7b95cd6480e097d6f6af604f864ff3275e02976995b7191b80b23f22cf60d11651775184f1c6088420edc352b5619f0badcc90f355575d2cbe5082e9775b01fe880c325ff688dc90e63c61acabaa1927fd89eecb7b99ce84b3ef0839887ad0bff75e3765e5ee2e09857106190e191e5437facc5a90798b442729f824cfadef839fe21daa64ba8a86ce72ce0e03e369c6b0e85aea721b9c534c900ef6db02773853eea69db49b80477efbc0e0ab92a37076a5314c181fb564affd4bfd011bc0e75a2357cc306796e0547951d0f771ec642dcc36b1e40ebfd51b06bb88a1bd7aa98d07ea217daa0ad9220d15bbaf460e30a7003a2f068e4783845230a3759ae509bbebe620a0be8807e28ceda71ed044354258f5461d42c76f510382da4f0140821527a23b220ad423126d3f6a1c18d725e55f
+InRec = 00000030000000030000100008000000001000040003c0002000000002c00010000c000180003000080002000030000400014000200008000040000000040002400000000c0002c00030000000038000100000000140000000000000800000000c000180000000080000000010000800000000200008000380000000000003800000000400034000200004000040000000040001800020000400014000300004000180002000000002c0000000080000000020000c0001c0002000000002800020000c0002000030000c0002800030000c0001c000300000000200002000040001c000100000000040000000040002c000000004000140002000080003c0002000040002800030000c0002800020000000028000300004000180002000000000c00000000c00004000200000000340001000000001800000000c00000000100000000080001000080000c000200000000340000000000002000000000c0003000020000c000040001000040002800000000c0003400010000c0002c000100004000300002000040000000010000c0003800000000c000340003000040002000010000000030000200004000140000000000002c0000000080001c0000000000001800010000800018000200008000000000000040000c00010000c000040001000080003800020000c0003000010000000028000200008000100000000040001800030000c000000000000080000c0001000040003800010000c000300000000000002800000000c000040001000080000c000200000000300002000000002400010000c0003c000100008000280002000080001800000000400000000300004000200003000000000000020000000000000100004000100001000000002c00010000400000000300000000040000000000000c00000000400014000200004000300003000000003000030000c0001c0001000000000000030000c00010000300000000300002000080003c0001000000002c00010000400014000100000000040003000000003c000100008000200000000080003400010000c00038000100000000140001000000001800010000c00010000200008000180003000080000c000200000000280000000000003c00020000800038000300008000140000000040000400020000c0002800010000c0003c00000000c000340000000000000c0002000080000c0002000000003000020000c0000400020000000034000300004000000000000080002000000000000030000300004000100000000080003000010000c0001c000200004000340001000000001800030000c0000800000000c00010000200004000300001000040002400000000c00038000200004000280002000080003800000000c00034000000008000240003000080001000010000c0002000010000c00028000300000000100000000040001800000000400024000100000000000001000080003c0003000000001800020000c0002c000000004000280003000080001000020000c000080002000080002c00010000000000000300004000100002000040000000010000c0001800000000c0003000010000c0003c0001000080000400020000c0003800010000c0000800000000800030000200004000200002000000000c0002000080003c000300004000100001000080000400020000c00020000100000000200000000000002400000000c0002c0002000040002800010000c00030000200008000280002000040003800020000800018000100004000180002000080002000020000800028000200004000380002000000000c00000000800010000000004000180003000080003400010000c00038000100000000340002000040001c00010000c0002400000000c0001c00020000400010000200000000340003000040001400030000c000180001000000003c00020000800000000200004000180001000000000c0002000080003c000300000000040000000000003c000200004000140001000040001400000000c0000400030000c0000400020000400010000000008000100001000000000400030000800024000200000000180002000080001400000000c00038000300008000380002000000001400030000c0000000030000c000240002000000001c0000000080002800010000400018000200008000380000000000000c0000000080000c0002000080001c000300004000340003000080002c0002000040000400010000400014000300000000180000000080001400010000c0003c00020000000010000200004000000001000080003400030000000024000300000000280001000080000400020000c00024000200008000200003000040001000010000c000340000000000003000030000000034000300008000040002000040001000020000c0001800020000c0003c000200004000180002000000003000000000c0003c0002000000002800010000000
+Key = 4eba286d54cc289caf78c9964256be52db2f2cdc020ce12fb2c472f2e7913d0d
+
+InRandA = 115dd662e4a18f069d8ef08e92843a45f73aecf6409390a45b46d41b5f92c6a85fe601c90487263afa39a28fa153054098a02fe501abb9abff56ac36378cb6cec3f2a962f6a8072601481922bde99367e2f0b4330ed70bd8c24295c31c9965b5917ed0ed48250f42468f22bb92ed3961b6e248848e2a2565def2a0657c8b49d027a5457d1f824fd23bfaa9a813eac634dc31025fe16bc067e640da864cf22621b422ee506a37343e41a23a56b2025d325d6129ecbd47f984fe0950c45c5d2a1bda0048b8fb91984b66d4930d667ad8f67d0ad2484ecabb3e4a6a4426d225846449457e21cb429bffe97c9510822a8bad238bde2a453e193b9a6b5d1dc8ab36d9ee36633298b6754e710b52afcf043ce9b9ccc2e902ffd6617442e902e4e529afccfa91b70984921c4809e39d9eee9d5be346988ee2da5cf9863864504fcda0ac8e9dea662555476647a8232564fd46ae420463137d947915d8d3c1207a6b5a0fdb9531a559169730a9fd7e6b70ce388673cd80586d10a4a7a08d1504cb4ad8ed3c3a14b667aaf477b4155c8afe75775299cd7388f57dcc590c0ae8cdbc0e95bdc9c9f5bf0e82dbc2726cb9a60be67395febcf3ec47802ad5b0eee7a1734d016fc41bba9056568cb5ae15c71a82acf6a6f9d53e643196ed6d680a4c8e5dea93cb80e03f6203c4f1e9ad1dd2e93968eb2959095d8c91c36c8e7e98a3ea23441f1a4b9a5a3ba24592a69d386bc8a516cb4cd0498905506ed6d26c68b7ba6291a584468b708f8731d13e8634dc2ea7663825aa6e7d27370866950ae18737049cd84f0763499223b2473ed72a5207b60aadeacc68a9d3934a55c8be32b2d44f253e0daf2c6cbf6a777e4784c34de26eb2ab1656210235813817a8793108317c05a569f1b74e2f47cccf691858b28c535d873f507e65a9b9e1a6da65532af12028ddabed18dc4bb8882f8c848c9bb23c7f99d893b9375e6b14dc71f834747cca9e081198c90e589d738895fd06eb1a9674b9b939b5e7b42a2c0d1167e13c13c8e27cec18c13506de7205917d59da589c04c1f45ab5c0b3a80120f86c7021dba9bf4a05c65ad1d27e153e2e44706caac82d99a8cf40e6c59cfeb7ec07e0db3ba0163e2ed5b05c60764562d60500a69a59831178a616b1f35ebd15876062f9437f8a8e78247d0cdc41f658672f4ea16a087c0a415402792838598eae4895ab79b1c4c69d5b144c4e82eabb748eec724454c3f6f0c935349a7d51d8e5a86a50ff5146e6a4c22ce0456f6d0ad50d0778d500326ad33bf7933d62cfd334316bf182ce109b51615679c02e0165d5f8ae54976cd837661324e4765792e4681e2ef7d134859424958ca5d6e1220fc00620df4295680b84574e985e1ba7e08b752805374332867659a273d91ed99dc5774ec798c06f8298ccab90d53bc950bbea2e25492e8c67deb3874bc4368b079d2a73499fc3c51c16c6b8b704967a71b795034d1e2da91cdcb246149c270095999e6be233d86538e0e572e3ef7190d58256a188f88628c81600337a563d4179c1d9a18744cea2279551af93aa278bb88a5ffe45e3e99a492ac86bd5c8957a7c018dcfb9ff56489084af406151658fde5f0b9ca6145098c9c1edfd08f7e0e3d4c162a58628a7d23009a4e4560723a694332fca49b902396b98d014bbabd262f21b780b4a056a878b55a8921293bedf45602eed1b4b4d80717492a9bcd9b8e99ef152bfe21c205b719a1d4d54a7df9579cfaa999404a13178efb236029d52e0a261a1973c5efd966b2219847b14065856272dac65c2d2614406740aa5f9145c859a7be9d6a48b8689b2ced1959b5c8d4b18f735268e70c65b4664481801916400d2b5d0739544bbd178d12cd2d718ea06f9649feee0850fb1584d1e18568e26833bc93d53261a488d261c295d2963b706d992e01eb2d78c5e548b2d483e410ccbf74ab5aad7d0e2637e0d3660fe3115cd5cea046f4778b426d5e079f9c7f09ac448a6d5bed819ec5b8bc525e504b8079650b10ca4036557b4f91c870fa56c200f220216125739e52ebac76f85abc64e1aeb5f3dbb250e50f69756a708cdac4aef845ae31c9a03091ff6d3123a65878e08dc1cb768a6f404ef9d52da0c2ce1f52431cde64e3432982b744710550c023d699b376054445df81699d411648e74cc7506b1506df3aceb7ba80aac6b21379062346c77d5cf68dbbc12e316f823ce2c33cc24c6e22afd7ed62134d744155cc9d007e010026c1e91121292a27efcc5d0213f1996458994b02e886966e97ff8a84d106c09f84aab516cb1d0f7ca443126c30dc0062598a3a21d32cb2fea35fe51a7a83892be55ca24971ac4863b0f4d557cd9a3420ea71b1f1a61de8912d2d6d59f23c425f9ac6077e86e50c333da23c7da73a5e47a804016819bf1c2a75f6c33522a505a1a9a5e313c901214cf33533ec8a6d2218900f2856b858b9bb49255236e090a90c49c84f32bc5f123d6072517e0ea091e6a04117c60639d2ada6f5d0bcd8d5729efa7394bfc85
+InNoiseS = b25e0026c0f1ac209932a42dac2b2a94f3d3a08078080b8ad39ddd85fe04106bad6c591655d7e6dc9936362a1442a112bfddef1594169d3b929b77663dae11971e713bb5d06882cc5933a4b55be9154f6b2da674e96cbc3ac56145875888931f64669d57c5637dbd469bd3b6504124227e5e86789b7403c7dcda60e2012bc20b28d116209cd9d26be498249ad7a933e63e587d4f8c8c728ef5a0e64fa532c8c56db5d629a803c451d0cabfa7fe185c559da2f73136b79418dd245cdd990fa948a7297591195b1fa8d6b953b3a4dc91692c84bada53c4ec8539394de26358102b509549a1dbaaa0ecd9a614b4e96f17d26ce3507c510d1798d11f218ce41a7900249e0ce70ca624560d0a74a23591f8fa553c1cda6b995c951ad4d965a8fea143523358b3147412422e629de92d64820fdb897a9ee22b5be0190e6ca889bf8b27914c61568bda84651b17a787d700aa1c8d0eed5b669d69b644b1283f61266f6d369a50f446e59c7bb911d1515023e484e7d949a9c6498368fd4291433629adfa93c993f5732e7e12a0cc3f79b94dbd84010f5711103f5d622fcbcbac55d511f8ba02ce47e00a4ec84d10af6684829275598c635defc620f59c5a1ce97399d12de74e9f84b8c25ccc87b4e4b7691d6cc595b40b6e7a2d0ea93773d60edb498ba0dc59906a930557d0529b4d975d68e1d0850f601b490f9a107847e909f8c8573c61927374d9a6bfac48f4ddedaeacc39c3037ecb7d251ebb98231bda7035ec9e2349ac3537496f609016d6a79d394ae43e951abe87fad7d7344148943fdb2b76b56c8e6316315a94eda5a3151a65e7608b80968442e33a7cfb1872ce5e2a1f462bd6d65c8d09a8023e944ccd88050a0c1d488843add51135b4ae73d90aef5143bf2016a668ccbfc6bc5d2275302ccb225a269dc08b26a83d96d16ab68e36eb19da009a87195e9200045d07172984ee427b983ec54af056df6caa32e24b2d579862ce60eac0a13a97da0312edf20d38cf94551a8fd61a78232b387a8b217f98ebb29737793d98a364c78a471dc04b0a3eb48cc9e43b6ae6d3875025d58e2aee7a95e69902f4c8bf34e73ce072572883aa930c1665055a07fec86c229dd9d5d4c8c80d227b278fadca1b00da0885b04c6959b96bedb6a5aeb5322a18cc116f29d3c1574cefd7513945479937a20040402011bacf9ddd010da0c7e19e8a65977d4bd96726951c18bd380c62e2fc861e338ab86587a69e49699c1587fc5737613405c50ca11a365b40ac58eb867f37d9aa61157621fb09737970451286e4e1e9d2cb01a1a0c1187bc491e2e1d75e08c02bcfe5cae870bd073ba05bf2b2f4be0d61a4b461970a5d930b5c9bf111b11252e61d3f4a7bd549ec44c0beff42a9c6273b03cad315907f490808144904388d4760e446e6bdadab21593a363f2db448987425f6963012e2803a4c50500ca9a1f22f9d8b64a4c59545bcba76813b7d41fa40d741ffa0d1ef60a040b4441951245c1b4aad9af707c1815959d0bd0bcceb80cce721b83ad1cdb9c1d5b45ae816403d63794cd285f169ec609791aa24f82d58e04436ec63d4a6086803ba584c83446519207c072d24a6ec7a696625e1cbff76c54468e458190e28e6848a4b6a52ab867fb9c0ec845bd26927d1d8b9f24f7afdc72402e65a1e0de44f45eec51585c594eebfee849f63ddc54ce073081837945a121f92e02f104c386df92b927ad02aba9ccbc2857f2557c7aae8eaf8524cae5620d86a2ebe43e40b108ea592b5450f10fcff13bf068771cc7440e7d6ae66c9af4a3340b6fcabee9ef459d8f8dd4b804717b3ec54ae2246abb7a2bd5647712a1694262eb4886befb8a11d4fd297f512e18b819121f4de1af51036a64fb97a111385d7a218ba794b9ddb7066fce7bb3f1b86590b7eb1b753a29d3bc584ecd300fdb33db715c5a15cc1bc3f2fa49a9abc52815c464af878781e85e15fee92788950005deae6822e084a4c9cbdae862c58f76a6fd25262a3a42004881a7160bf546e066f376163ee028b587014a2b2b269a19dea85c4a7690f3d2065dcb200af1e6714199d7498f3858e61d0d11e8bdaa85288c256cb8bab2982e038a084f459ba0697e7e9159ca0de7b2ecab32a8a0e2b3e26097e321868aedb9318c7972bf6e011e03db452ef8a07ce49d129d12b7e55818e9c4ada4dad00e8722764009ec09082a7870402abd180d050dab6cc5e110a290db641ae620ed5ec58a7f97821e07cb54de427454a5d90d28926af2008525d9f053487aea87972764023751e5cc959a793aa986230814082e8d0747d908027b0e0baf36e8768776a79a7056b438b8a7d3a134da4b698c8dfad12e418b2435f4aeda6cf0a6d4d4906e3d4845606947f87963c7238592e81aca8b03405365408383d120fc3178696d6599ca124fc6014ec6f2e93d274a8e28e3c64a395e433043283d81a91839d8984f642fa1c1043932596fade0cb561e08cffb08af0861535276d622b225d38c755b969c1971e24d600a9a5c
+InNoiseE = 410847f4c6bd1eed95a6d38272884feff2d3d58c25185437064cc584875e0901c0fe1d81e802e4efaa0e8654f95005f206854dc318e06a6bcb022923c26e521a6d98d8b15589e4efb1d5c3f57719dcabf362f9bfff4955b81759aad88856b08c3a08d661a50bf4e5a6ed00e4100bc0a483e460b138361c0806fdc791712a840dc500bbba42f60b87b52a963d15e6f4c7053d716d0ea5c27de87d2b00d4d60838760f56c570fd6942340dc0733f708493a99f78e81840da8fc4d94c914e01ce5cc4cc8183d6972ff4029537a18c756bc35a24588e3fe05abc340c6d593b68585293c04afbc18c179d8585c2a5f0aee36c0ae37ea8694fc79c51c5a87faf6126b766303a6963844b8538976752a363847064724018c939e1763c14a0b3667d841651f1b3753966d22c9bf76d2e0de9ab2091f1d439490fb796acdc55a34dbd02417d5914a55fc1271827c6d77862c330bac48c9ae334d20f499555c872716afdc9f6b219a18f7d47e608ebda1617c547903d6513cba84ed05132ab08272985778654bd1220534ab1134b5595b1880864224c316126547a9bde73001dc49e0b86516aa99951af2ab5e5417d2ba51032976d9449b58ab8d13d5e78a219beb77159072a27690842b134321f2a21508821c9810ed5bd4c1715d8bc02108538a01cd9517428a4cd4331f3a216474825ecd7607e3b2f5e6f08bb851e405b6995b11a5dbf2a72c4a0624446dac7c4e0d89eede099c9292567b318c81702268e1d9932b87ebebecb4ff258a428ab724993583f7e5123ccf2799e091d81a2e4723d9d71a8e40dcb29d8846dd910fa433436b005b624f16932d38321e14c6a41494ef3446c85b8f1d4607943868ddb9556ab50f1a6c10fe30055c699501a3c9525e60b7de7ca304a929b71eac5a903dea06f442882ef5594f453cd15c1be16b1cabdb200813c00e9cc0939349ba25643c968091de29e35d20015a3c89fe5c38f9c9e06402524eada65c7d344249a0c7c315b841bf5402c7241371718b22755ce4cc6d7b056031fc902ccd43f089db16b2b0e98fca82085ba4d8d8e1a00a4751c3b39d8956adb4154d42e100ae3916ae107ba130cb64a756666e4d9655f27d1e4f075a1170b24c873c919000222a413ba0d57a8cf2ca2d3313e3410be1369e06bdd4bab58d8843dda874d5420e458f32fb7c4e7d5b281a27aea3cf82a85d416c79b7a59cbd6ee2929c0307d13f0e8911430ce1b2f778481bc451da9a4677cb28858ab34f5983076c720871a9e1d0853af298369b6906cef6630c802ce4d868996e82d28c5583870e98d5695928abd709a2501b9c383b6022109223ba1b8a7d66358c37ef0518d484f7afb31199d1f4b0bb8509ad02fe8f52e3095f5088db3419081dcc4c66bc46558e8618e2ae52ca3bba1e2423824ad496046a3c72c4877c178478bc635061bcaa39fce6eada2cf50463c8023dafb634a5094179a208b18412a145aabf2f018a9fad81d941d529d46a534d8fa827525c363ea52463473e22ea27f3002c362f96a8e8284a9103db4b7328790dd537a6a387810e777b6c52c7cd989a208911a2d8d9e3e36adf4baed646b34fe397e1754981b4afa1d7917d11b6a623832113883c88d00766bcb044888bd76dda1b08cd47e0d6bf8a8e6c5675e9406682daab1a78cb736e22ea477c6b99091e53c4f41d278d37d9b6926488a54c93100698731a14927c4a9743980964fcb29f2641ed6534a0b21879776518711efd92635790ccefea8acdc73eeedecf345a1a92085f0bb3d34919e85cbd8c84a752ad9ccbb192911645c87677e3e1c61c556871ca9b09ae567c488d888088fb11130615dba6448c7b14d9b4b533ee1036451f3084714d8a2974c2448295e4479d76bf8e0bb4a4858a02924c49e7ce5c80111b4163139da0942aae538198d72d328d8bee651b85b11225a572f1c399d2e7309ef52770a085e241abb1969de0047574c46176a687a58de29b41a0ba02531586912397eda0e783dac53ffd9424b1172b0349ab3d16138079de655f95c9644640d4d5b8b82ab2b1ff8644d8485f461deb18579753b1ba189820226d7dad76627769e909bf6e6c10aad8c2e89db4b6d09481bc938223a46ded67842fa3c0d02abf02674bd147c022ce97fb67ccf827de700012c494223da7d6d60d86ef0c224714ac2858013e0690c48e75430c31689ee55240be39843bd6d75954dec140be06053073818374c08465d629ddbd6810966788e76e88cc4057024eceb2465200971d29d13d906d1584de81b5a4d19b78ec654202379a3780ada0937783fcc2fe582c5c92a04ef9223f9be72ee12f73b1d815863987cc07662450f41edc90e923c042d748559265e8bdffcf1e3a0220c2146417038565ee46dd5b9393dbb2c1a36a3a80fa04b91d623e89297e31979b70e4d53ee7472c5e69e18c2e62ad0fe7f51488df6b06e0ce96525d6862c322f40e069bf843ea6d511aabb92441a0d4ac7e2627c28e7ae654f12997babb4399ba84bd923d750791c9a
+OutPK = 7d49b21bf5e4a67ccde547f4783aa0000ca4174eb3e1557c33a9e934e0a29294662961ad6c55a4f301adf396d0ea8a7480291bf130682239040830034b247e2f5db7a8fba80689d9dca8b9403414ef2963cf600c2ca8b219606802fbcc691145cd38dde3330073c112658cb3f49d6d1a0a88f0b21114af5320a2b9273640d9131e78f60189122f26983c1a285ea26b6b23f0bb30e619a9dcda9dc3ebd885866271476a6ef088e26c4d1400c707d6455663944278347942858990c8597b38cad094e9118a3328cdd55a3a36a14e5594e0750c0316ee00b73e476e49dfc23ede180b621f0b4e294e045d6d40de291736192f93dc2996560561641a1ca94847d301a3982c06daa93a27ee1099659c866766599dc66d970ad48dfd92cdf611414910dc62e43f9192da51f3f62b9cb1639731082dfaad3a1851368620720f271aab645ea69aade694f3b1b8d556354aa25553d41fd9d6b1807fda9575fac5361c7c659eb487948046983a0b3a3c0d79edeac375e4179851eb20d029a49f55f3cab6ba07f1d9b8104bb11816a03dd700e2349eeb1ec5bec50b3fc32191fbccafdf90baeb5971b277c23e43d3205db85b5dd52f1d712a18c89bcb5416b9236e045de1b86754f3b24fa84cd82206218622ac2bdb90f9745d57fda12ab4b8466d7c86cbf57b65b103cf002199854925d38eea4a7e8b52def9049a41a6808481f4b514312797c6e22ea12740951fe06ce938dc249085aa31762225f9379250a4cf2b30e64b5a9bc04b3f2b69e505a9ca102765c9ae740daea6149db775e61f1b4a2db7a251b851eb394971d6320848dd1ede24d4c68b7139c40e5303fde09edbe6aa200802ac3d9d1411d0ce6ca3d8c793895a81cbe420719e2c45696a4ce8b9c0791cc9c999be0d22512b6c649dc24fe111ad97545a7f1cc72fe49d0c96d688fb0b8131b420cda989b5dc172922b11972dc1db5115483739888d7e5da77292534900cc2f2ae3dab61142bda269d20ef5414bb0fc9375e486158a5b41affe4862904f407bde90226c0308dc22bf63467fd02fa4696b1a2424061460b41feee968fd396b6cd12a3bfe067d831e541c8e29a9a2d724440acdc545b7ca593a5fc71f1fa069aca45cb28348eb450d1fbb0a55afd436feabc545c749c2f39065684e84013885c8452bc22a4ea411a93692bef741035bb5dd643c61a8822fa04a51751d8a005a91c36904a86172b11a52bfd18ab167741a27e82699763a8832ea73d5d3daa51a02b791ec062860440b029b3008e2e5c2846bf88388070b39e2156a1c28f1bd91846153c9a3449756b90810ac46a8c404af2bad14f71b636929a319ce7028a8556541fb2962995ab3561833a0e80629d8c9679fd5941dcc3972845f05e0f560870a12c29feeb104722f13410d7d9cb0c9a80518e0270883654d0e7446512ac3dc8563421eac4a5a50f33f84ee9afa82e451b9c469e26d862d7f2ee450c2ad7b050b9b76fdd5cc12f148517c8fd275a2da7a6a54eaa990893ad97b8234bb63340e2ada835bd051a6bc3eb9d7a5b1e5b89a2bce85fc541d5b542f054a2e495f4a5a07ea0a87522781c7312df0bf5c130927f1df0890e681bf3a986f63f500b9c4f8884873e12aa2c4c69b8982cd4530ddb0c914b6b1eb5e1bfc44f32d68e737f8e76aac22c51a76c8b1a83dba8ddedaa0b87e7d2dbda6ae667e2d3fc280defa6745a2a92b61941e3e83b2d053557f7fae24c907f9c6542805548f16664842e443c28c15b45fe5e2f7dd44485b120adab1445a55aa5a85025e52764213dab690a70319939ad971d81d5745d5fd4d03427b07d1b9d46859f3a67c6e556f5552a448ba312e61f4d32195fa2d8afd696ad2d5431c6a18ff02fd4281aa87d714350109d963f3e809cc4c9c51a3d6cd140274621af026df3663c1abad25a13092a9d42880dd2ce1e121c418f9b87c8b6bda67469d7b047e693c5ea3de27b272d30d39564082217c3aa294daf5de1428b3a1182e7dad9935e192d64c7f2ebb1357cb662ee6a67981f5ba73c8494c693d3280f47ae3ebf5fc6b9f52b044ec52bbaca15a82b169adfaa89c511df1be347829286846af2d797714bf866cd5aa44a557fa7f8cb40851fe39f3c468f8db78e867c917e0288625e271007a690f206cf443c7e52dc29710bfa4505912dc4930b7923d29bb304e13a26aa80e18403a4266c87e304b3a87a58a0f1864da113110236d371f63f4f9cb2724679bec457ed715f797ed6ab4c76de8da2ce6849858bed5d6c108b18ef2e75b5c22384286c8767c66f028cdd7b0043d6931eb12a0847ad660dfc030ded0e0acafd3d38214897c58cbfefefd8d1c07c18520082f9c63c45ff57aab3132caaaa5b94e289dc2b6f49e6d2d6a44bde58d6462424932d146d9aec4c30c0ac0e7ab0e986952f75e73e1e3d78e7e898c688a1f412a4c61f559fc8467f66bb5a7af8562e9415025dd8c70673d762bac81e4100a9b85d031a46d66df941f51c88468a820660170e032252811ce5625307e9a0
+
+InPK = 7d49b21bf5e4a67ccde547f4783aa0000ca4174eb3e1557c33a9e934e0a29294662961ad6c55a4f301adf396d0ea8a7480291bf130682239040830034b247e2f5db7a8fba80689d9dca8b9403414ef2963cf600c2ca8b219606802fbcc691145cd38dde3330073c112658cb3f49d6d1a0a88f0b21114af5320a2b9273640d9131e78f60189122f26983c1a285ea26b6b23f0bb30e619a9dcda9dc3ebd885866271476a6ef088e26c4d1400c707d6455663944278347942858990c8597b38cad094e9118a3328cdd55a3a36a14e5594e0750c0316ee00b73e476e49dfc23ede180b621f0b4e294e045d6d40de291736192f93dc2996560561641a1ca94847d301a3982c06daa93a27ee1099659c866766599dc66d970ad48dfd92cdf611414910dc62e43f9192da51f3f62b9cb1639731082dfaad3a1851368620720f271aab645ea69aade694f3b1b8d556354aa25553d41fd9d6b1807fda9575fac5361c7c659eb487948046983a0b3a3c0d79edeac375e4179851eb20d029a49f55f3cab6ba07f1d9b8104bb11816a03dd700e2349eeb1ec5bec50b3fc32191fbccafdf90baeb5971b277c23e43d3205db85b5dd52f1d712a18c89bcb5416b9236e045de1b86754f3b24fa84cd82206218622ac2bdb90f9745d57fda12ab4b8466d7c86cbf57b65b103cf002199854925d38eea4a7e8b52def9049a41a6808481f4b514312797c6e22ea12740951fe06ce938dc249085aa31762225f9379250a4cf2b30e64b5a9bc04b3f2b69e505a9ca102765c9ae740daea6149db775e61f1b4a2db7a251b851eb394971d6320848dd1ede24d4c68b7139c40e5303fde09edbe6aa200802ac3d9d1411d0ce6ca3d8c793895a81cbe420719e2c45696a4ce8b9c0791cc9c999be0d22512b6c649dc24fe111ad97545a7f1cc72fe49d0c96d688fb0b8131b420cda989b5dc172922b11972dc1db5115483739888d7e5da77292534900cc2f2ae3dab61142bda269d20ef5414bb0fc9375e486158a5b41affe4862904f407bde90226c0308dc22bf63467fd02fa4696b1a2424061460b41feee968fd396b6cd12a3bfe067d831e541c8e29a9a2d724440acdc545b7ca593a5fc71f1fa069aca45cb28348eb450d1fbb0a55afd436feabc545c749c2f39065684e84013885c8452bc22a4ea411a93692bef741035bb5dd643c61a8822fa04a51751d8a005a91c36904a86172b11a52bfd18ab167741a27e82699763a8832ea73d5d3daa51a02b791ec062860440b029b3008e2e5c2846bf88388070b39e2156a1c28f1bd91846153c9a3449756b90810ac46a8c404af2bad14f71b636929a319ce7028a8556541fb2962995ab3561833a0e80629d8c9679fd5941dcc3972845f05e0f560870a12c29feeb104722f13410d7d9cb0c9a80518e0270883654d0e7446512ac3dc8563421eac4a5a50f33f84ee9afa82e451b9c469e26d862d7f2ee450c2ad7b050b9b76fdd5cc12f148517c8fd275a2da7a6a54eaa990893ad97b8234bb63340e2ada835bd051a6bc3eb9d7a5b1e5b89a2bce85fc541d5b542f054a2e495f4a5a07ea0a87522781c7312df0bf5c130927f1df0890e681bf3a986f63f500b9c4f8884873e12aa2c4c69b8982cd4530ddb0c914b6b1eb5e1bfc44f32d68e737f8e76aac22c51a76c8b1a83dba8ddedaa0b87e7d2dbda6ae667e2d3fc280defa6745a2a92b61941e3e83b2d053557f7fae24c907f9c6542805548f16664842e443c28c15b45fe5e2f7dd44485b120adab1445a55aa5a85025e52764213dab690a70319939ad971d81d5745d5fd4d03427b07d1b9d46859f3a67c6e556f5552a448ba312e61f4d32195fa2d8afd696ad2d5431c6a18ff02fd4281aa87d714350109d963f3e809cc4c9c51a3d6cd140274621af026df3663c1abad25a13092a9d42880dd2ce1e121c418f9b87c8b6bda67469d7b047e693c5ea3de27b272d30d39564082217c3aa294daf5de1428b3a1182e7dad9935e192d64c7f2ebb1357cb662ee6a67981f5ba73c8494c693d3280f47ae3ebf5fc6b9f52b044ec52bbaca15a82b169adfaa89c511df1be347829286846af2d797714bf866cd5aa44a557fa7f8cb40851fe39f3c468f8db78e867c917e0288625e271007a690f206cf443c7e52dc29710bfa4505912dc4930b7923d29bb304e13a26aa80e18403a4266c87e304b3a87a58a0f1864da113110236d371f63f4f9cb2724679bec457ed715f797ed6ab4c76de8da2ce6849858bed5d6c108b18ef2e75b5c22384286c8767c66f028cdd7b0043d6931eb12a0847ad660dfc030ded0e0acafd3d38214897c58cbfefefd8d1c07c18520082f9c63c45ff57aab3132caaaa5b94e289dc2b6f49e6d2d6a44bde58d6462424932d146d9aec4c30c0ac0e7ab0e986952f75e73e1e3d78e7e898c688a1f412a4c61f559fc8467f66bb5a7af8562e9415025dd8c70673d762bac81e4100a9b85d031a46d66df941f51c88468a820660170e032252811ce5625307e9a0
+InA = 115dd662e4a18f069d8ef08e92843a45f73aecf6409390a45b46d41b5f92c6a85fe601c90487263afa39a28fa153054098a02fe501abb9abff56ac36378cb6cec3f2a962f6a8072601481922bde99367e2f0b4330ed70bd8c24295c31c9965b5917ed0ed48250f42468f22bb92ed3961b6e248848e2a2565def2a0657c8b49d027a5457d1f824fd23bfaa9a813eac634dc31025fe16bc067e640da864cf22621b422ee506a37343e41a23a56b2025d325d6129ecbd47f984fe0950c45c5d2a1bda0048b8fb91984b66d4930d667ad8f67d0ad2484ecabb3e4a6a4426d225846449457e21cb429bffe97c9510822a8bad238bde2a453e193b9a6b5d1dc8ab36d9ee36633298b6754e710b52afcf043ce9b9ccc2e902ffd6617442e902e4e529afccfa91b70984921c4809e39d9eee9d5be346988ee2da5cf9863864504fcda0ac8e9dea662555476647a8232564fd46ae420463137d947915d8d3c1207a6b5a0fdb9531a559169730a9fd7e6b70ce388673cd80586d10a4a7a08d1504cb4ad8ed3c3a14b667aaf477b4155c8afe75775299cd7388f57dcc590c0ae8cdbc0e95bdc9c9f5bf0e82dbc2726cb9a60be67395febcf3ec47802ad5b0eee7a1734d016fc41bba9056568cb5ae15c71a82acf6a6f9d53e643196ed6d680a4c8e5dea93cb80e03f6203c4f1e9ad1dd2e93968eb2959095d8c91c36c8e7e98a3ea23441f1a4b9a5a3ba24592a69d386bc8a516cb4cd0498905506ed6d26c68b7ba6291a584468b708f8731d13e8634dc2ea7663825aa6e7d27370866950ae18737049cd84f0763499223b2473ed72a5207b60aadeacc68a9d3934a55c8be32b2d44f253e0daf2c6cbf6a777e4784c34de26eb2ab1656210235813817a8793108317c05a569f1b74e2f47cccf691858b28c535d873f507e65a9b9e1a6da65532af12028ddabed18dc4bb8882f8c848c9bb23c7f99d893b9375e6b14dc71f834747cca9e081198c90e589d738895fd06eb1a9674b9b939b5e7b42a2c0d1167e13c13c8e27cec18c13506de7205917d59da589c04c1f45ab5c0b3a80120f86c7021dba9bf4a05c65ad1d27e153e2e44706caac82d99a8cf40e6c59cfeb7ec07e0db3ba0163e2ed5b05c60764562d60500a69a59831178a616b1f35ebd15876062f9437f8a8e78247d0cdc41f658672f4ea16a087c0a415402792838598eae4895ab79b1c4c69d5b144c4e82eabb748eec724454c3f6f0c935349a7d51d8e5a86a50ff5146e6a4c22ce0456f6d0ad50d0778d500326ad33bf7933d62cfd334316bf182ce109b51615679c02e0165d5f8ae54976cd837661324e4765792e4681e2ef7d134859424958ca5d6e1220fc00620df4295680b84574e985e1ba7e08b752805374332867659a273d91ed99dc5774ec798c06f8298ccab90d53bc950bbea2e25492e8c67deb3874bc4368b079d2a73499fc3c51c16c6b8b704967a71b795034d1e2da91cdcb246149c270095999e6be233d86538e0e572e3ef7190d58256a188f88628c81600337a563d4179c1d9a18744cea2279551af93aa278bb88a5ffe45e3e99a492ac86bd5c8957a7c018dcfb9ff56489084af406151658fde5f0b9ca6145098c9c1edfd08f7e0e3d4c162a58628a7d23009a4e4560723a694332fca49b902396b98d014bbabd262f21b780b4a056a878b55a8921293bedf45602eed1b4b4d80717492a9bcd9b8e99ef152bfe21c205b719a1d4d54a7df9579cfaa999404a13178efb236029d52e0a261a1973c5efd966b2219847b14065856272dac65c2d2614406740aa5f9145c859a7be9d6a48b8689b2ced1959b5c8d4b18f735268e70c65b4664481801916400d2b5d0739544bbd178d12cd2d718ea06f9649feee0850fb1584d1e18568e26833bc93d53261a488d261c295d2963b706d992e01eb2d78c5e548b2d483e410ccbf74ab5aad7d0e2637e0d3660fe3115cd5cea046f4778b426d5e079f9c7f09ac448a6d5bed819ec5b8bc525e504b8079650b10ca4036557b4f91c870fa56c200f220216125739e52ebac76f85abc64e1aeb5f3dbb250e50f69756a708cdac4aef845ae31c9a03091ff6d3123a65878e08dc1cb768a6f404ef9d52da0c2ce1f52431cde64e3432982b744710550c023d699b376054445df81699d411648e74cc7506b1506df3aceb7ba80aac6b21379062346c77d5cf68dbbc12e316f823ce2c33cc24c6e22afd7ed62134d744155cc9d007e010026c1e91121292a27efcc5d0213f1996458994b02e886966e97ff8a84d106c09f84aab516cb1d0f7ca443126c30dc0062598a3a21d32cb2fea35fe51a7a83892be55ca24971ac4863b0f4d557cd9a3420ea71b1f1a61de8912d2d6d59f23c425f9ac6077e86e50c333da23c7da73a5e47a804016819bf1c2a75f6c33522a505a1a9a5e313c901214cf33533ec8a6d2218900f2856b858b9bb49255236e090a90c49c84f32bc5f123d6072517e0ea091e6a04117c60639d2ada6f5d0bcd8d5729efa7394bfc85
+InNoiseSP = 55a7fa5b24024bb5e137b7da38998792e82320c91e6723ad06f209329f90c23707823be1ed092b16c44df82eded72c0819d42c484afa9575a11219e6a366a1eb9e6f659f458fb0432c888f6142be6f2f437ec4426b6d4f4103fe6428460e825d252b314fca0b32fd48d6afad55d842a0201aa9bb5ac664188ad119773d23f9cdce67850849cb42c76a2ac292a6dadcb60c5da1fd155419dedd9ef5d854cbd5910679ed5a51c5319f40dc5392de54b6a8d0ebd9b0c16ac8896d346572388c55c7fb9f3d6212eb51218b3c03644d6140a680270b51da06526c7ef4eb09c1043eb526a732e6509c0c0f6841da48467637ce94f88bf8adf841015aeeba5d979a783345f2652ae261d5fbf8957b0f20ab22f28d1edc65662adc042703deeb5d953855570937fdc226f76b444b05b85fdbaf615bcec839d0252021d7960923915d59a2ac6d1bcd8752c548aab3094fa27058bc5707bdc7a84488194c1c81e598bc2fd736eae2f945c3d07e6b9346203a48ebd7f79d4f8b172b74b79178f89bc766bcf63466571aa7548e66cf58ce2a0ec5a56dce10d006bd91c183e2a9ffe42f0e9496f713c905d0e4fe923cc8a2a85afb303a0d1bc429c68b209d9aa9a6aee3be4a8507e462b307ed443fcbb17a3172b4754a499a7384583a006897dc507589007bb20db84987d9d039b698af3392bf24b74e3ec59113f446cd972f4624465b81a5b6000dd89f88a694e941e7d2443f57137e78bdd66241801f8a90cca01148b3ab32dc057227f098936ea884a4b187889657cb9e81e1332caa24a806eacba46ade6022fbb82119f9d46b175c5a7493d59cf33bd5a4bdd0d1078e1c2348e4bde86b4071f6055f78c5109dd662c9fb9e98ad888e88a51e447b2f4a8ea5cbf8182083d7f2fbb93e248d39560e7a3e530ec72a4f8d4bd30fca930e4d7d4fc90ad4f5702bc9df4702521a2ae7a3dc701cf816bb5d24c0d17a56248a6ada95398d12ad80daee4806788c45017f500903c671b8305da3a5589ea5be3a5b6ce4435bc79215a82e23e2c4de860cc519701a94348eccbfc6473643d4093febd70e6fad8207f1367492e9de62b5e0722f76e914e4b670123c8ca5e61ac8a41e547dd22db952e4a71554fd304f1f45f841c71291c02054ea49b285360131d9914aa98cc3ed091ce0653aecd03653d6a4e393b190f1dc5d794214a294668415c99c5af27881acc54d6786aaa1bd2bb218c13a0d6c89a49689a983dae0a8655b6e64d66069b4b6c19623e34474b6bd0a020bde5a39314b5b91ead5852d9cc6e3bd45a4aa079f4199b293c9aaab8c41c1546c736b8f5b24b7a6a859410ea58f569e4edf3c953398bd490b32c9856c0b1891e17aa06e1c6788d6803496b50fd969b80f2152fb4263a1e3583d33e0aed9421d93c322c5869c341a4c109c092f7e2d5f544d344f688ddce65e3ad5a5bbccac709b963d02de9d8b6339923d0822eef1fff5b3a9957beb3a342c230c37b1e01938819bc2b70cacbebfe2493040969610a556711fac49dbe52cd71af4042a4431f574c43e846b1d7604c598d6632bd2962a3f48dd55da79956c1c4ca1c8ca8e79aaebc10723ed045b1c24249c36ab4cd0b6372ba9389769bc55f1c497ebd6b4ebf4e1b8528fde631ff4080d2eb3669d827c4864f7e96cad88b76cce3b02712bcf61d7194c31032b9a42018128bfa5af3d026146356f89987882e547d56301861f7c41574c984a0f5d637b0bd870205a2e3c1ae94605d5599650f50a9c8885db20c5273db062a1c3149826446d12d0d491ed95052c14433b7e1c52701ec8c2f555b79664e37550001148e241521af5b0d454e05100523ec28d8d57191c9e32c5365b6f7d8e750cd2c7aa461f8d97da4b75d94665a2c9566fc9a99064cbc6f012a04b8001a732f21ec5547160d37068005157f5d6696e16e198b1b1a1a450da9357a2f15baa12904695c4b202d5ecd8ab2990c7db893662ec6499461c043ae168b1dd1178cc78badd882aeba252229989de627954be86d685f567a459b624a9f3054553318b7ef7702656a8e13fe9a4feb50a91a15298908df8e89230f4c95b3f578710159007d49589e1428e1eef972f070b3c96efebfa87e0a942490a85131d5c4764968d0269cc6c6fceb5b897b2a2c7d9c9f8f4081bb1187da9db021dc8d8c87a02d45af155bb947fe6a381a9761641545e30539e92408170c7e5a5a3f3f0637a284d222988038e219aab72a036daabc785a7e57deb1360b789f0762acd555a5ab179970ccdf7483aa8d6681801f8524816ed00485e5e48a6a427f9368a60ca15da55b27d0c2c50bb4a312a1ac16dbc23c8e22fba9dd8d83bdc64d84dd2f7b8960feeede0c32fc59d442dfde25d1220898bddc2455ab1e10373e73c861efad11619d456152020e3653c56b275cf34f4775cbcf94047a4b9387ef3d8155af9303e868ec8926afa50418702c336c404a30d27062c4d31f8891022383e4951430a2bb1e99497ab54e1ba8871bf51b6c5eb208d88a437c5167929
+InNoiseEP = e1ead35290020eee908a1b102075c6c1e10b14684aef1e9591aa260b30d6e6d5fae61c8c2bb209e08ebc6de547c940657372687067629d50291347748fec50c4ee0793d4b8b6e515a20743580d856b42173784adc45101e4251e45b866423920191826cb512a87b5867b036e7962c0b842cb14188ec918194c5a68bfed117656752061202710141456c6acafb810bf0a0808beef8af48495e837509ee324e75191dd20b8e96bae2382daf1098f719090c15a46e55d1c8f2a4126e182881162d8529b60877ae1a2851b00330ec0d1062ead8f33d7188159d2741b6e5a71c7590353e7d293f204296fe050872c184f17eb1e682510633857cba3e1b57d21ca19867a9e18766601c434b1a74567c78767e57db9ddbe074db07f0d0ed00b68a26b2c6e2037b8e008b10db3d0145db460981d00aee53626ee575297901f780e4704b0ae258692c61805cd269a9fb5cb45fd8e864003975c05875ac08ff4dd34a51964ed366ccc4b58d60ebbd571600f5b2b3249508d77d96723fcfa90c30d19e04d51b9ff9332764e592595eb2a9bd8d4219a57ff803a6a04eba2c8e047896c82e24e3151b9b17def1f461d96529d58bdd456926b64165404faf20b461b7e9b3196b92042188144a9121414ef26395416725bd157c25e642b967e684116942fc1d59886ed30fb12f42b927e5e8a8a08d169301a08c794b9f29614062256f9ee300a1001ceb3e52291a98ab0487bc942510115706c9008735823d8a452af404ca1db9e4c72b6580e90351d639bd48e352c4d6e880dee2b45a11e9a0606da45751485d004e09c0e91e9951c3aefc9aed888f2a8db79acb117a3d81cfd812ec3c1f1f07c01e0a979c30b45b42ee7c979ab75b76816c38a19b581739cda62ca5e01344c0471c5c60d6be6dc22ec441add572d83940582842828b946b43857022f03c70425f169c825fdd24a9e11afdb75e6827216f7367a848d195d57761c106536d29f8a553055fba6b0c33d0198b05f52982bfc4e54205c4a56b69b5f4dec2594f18bafc89560ccb056ab2c5cd36f891cd0dfd0a9172dbd272f899934448a9cd32e8b4a483c84250c472f2e923cabd6a7a1cd73f41fe3640be880095afeea601c4b85e1d63ba4d5a6e88af2208c8c91e392f6b41aa1bea021f9845bea432b8d7440c4991a250e072a5ab50d2bd664a0af38967269f6173d1e8679840f064b4eba7f402a20462d44446bb093903482d506579459843b054e579986627803e1854ad5ed3de36e23d5dd14911c558255cfdd59c5e822113a248504e70537471a442dd4e2d11871aed58ee8060dac6073ef4f804cec2e7696be4155e1733c5ae969106455a2d02f02fbf06e4558eb33e3fa397562171862c55b4cad80080b86b0a98e6398dc1573699d5ef3bd369b8ca69178844c9ae7641951489506a1cfdec940fda8245fb2d83a19b105ef5079d8ce424a0cc2f964ca5b1aae8a5a7a7a647fd0d2279f8ebbb446d502346140ad14f7b5fce594f8d043b2968673af0f3e60543c783dc39157600120229b4f7259aa8d27080efae4d64aff5306d4eb02184b4ee30b36fa501f91ede3aca2483b0b62d4e6013e4fd47bc2bad8a02eedaa88b7bd2c4041168bff45092b27f8f8ceba2286cdacf5d6a55ebb2bd0d589a4a63e499719eda537a8ec0350afc27dad5c67d3de7d2f1497bf90f8e917424bc0b36a21647f1f507a38cd2435a7ab1aa14151c96ff40bb23065b322fb83464c79008055d24c6abf10d54c909995018992c3ebecde40c21ab7b8ea55b37fc57e11af58bdf2c5bfc071203d6daf4449de620a7148e2a9454c4537e86640e4dd4a44e4e2c049f9a19e68c8aa2322a6bc5df7606f727df98f9398099546011751ca49643ff3d4a6aaeab00702493a70dd345b72d6f459034e84041418348178bc710bd0e411107e5dcf4390deca0ebb081ab0c886117fa191388db4793f01ae4b8e0c8edc973a50621aa51d4f06e5f0c2a269eff52049300344d32f78e2029b7c1c3297d4984a180870c5b636954413e73bb6aebcbfc027375b4550faa37062969da41be13148bf8c08bd802ee5fd8963a847598522b977fb9c20db45905b840f6981a62403de15c5b7395999b450b967fdc124ea6f0ec840b488e51f68f9f53da25415be43ea864923ee3b40441a674721e435087e4b8ec108a2b7547f02089f718112b363a92f0207ed3d56c2b465e11d0f99a4c3d9d93463fa6beb4198547365d4d1429e5d81438ec8f316947ddba05bfb6c213871c4a2f101c04e9d81c531b89aa822ddb2c84f9c3b465130e2418e6069cb0698ae7954cac5498154402237d7d4908b587509664a549c458d5e564cf134e44235db3b60edec168585c638a78003c6ee44f67366b7476d8ae3dcd24389e51bc0354c8066ddd830971aa538929d7925ae6c83c65807309ca2628e159641dc669b1e652359801aa3257d2109aa35f825c55b274e362e0005b1b5b0799f53d01a46d57ca74d93696b0a23370a56282a3c2c51eaaaf80e5e22
+InNoiseEPP = 00b001600000c0fd2f001000000002c000100000c000c000f0ff02000100000c0008000040ffebff02c0feeffe1b000800ffefff0b00f8bf0100010000fcbf00f0ff0b0000c00380ffebff0a00fc6f0010000c00feaf000000f4bfff6f0000001300fe2f001c0000c0fb6f000000ffbf0140000000080002c0feebfffabf0030002000f4bf00f0fe1b00f4bf0070002000040000b0ff6b001000ff6f000000fbbf03c001500000c0014001300000c00200000c000700fe2f00fcff060000f0ff0b0004000200fffbff0e0003c00030000000feeffefbff060001c0ff3b00040007c0ffdbff0e0000f00110000c000240000000efbffc2f00ecff0e00014000e0ff0e00fd2f00f0ff12000240ff0b00ffbf0300010000fbbf0280fe0b0003c0020000ecff0a0000c000f0ff0a000040ffcbff0600ffafff3b0000000200001c000800fdefff0b000300ff6f003000fcbf0080ff5b0000c0ff6f0030000c00064000d0ff0a00ff6f0020000400feaf0010000000fa2f000c0007000030014000040003c000f0ff02c0ffef002000f8bf04c0002000f4bf030001e0ff0a0000c0ff8b0008000200000c000c0000b0004000fcbf01c0fffbfffebf00c0ff0b0004000030002c000400fe2f000c00fcbffe2f0000000c0001c00030000400fd2f000c0000000080ff3b00f8bf0480001000f4bfff6f00f0fffabf01400000000400ffafff3b0000c004c0ffebff1e0002c000000000c0ff2f0120000c00fb2f0020000400ff2f00d0ffeebffe2ffffbfffabf02c0ff0b000800010000100000000280000000030004c00000000c0005c0008000f4bf01c000000000000030000c00ffbf02c000e0ff020000c0ff0b000400040000d0ff0600064000400000000100fffbff0e00ffaffffbfffabf038000e0ff02c001c0ff0b0014000280ff2b000000fd2f001c000000ffef0000001b0002c0fffbff0200feaf00100008000040ff5b000000ffafff2b00f8bf0180001000f4bf048000e0ff02000030000000f4bf0500002000fcbf08c0ff0b000c0002800000000400fdef00200000c00380ff0b001300ff6f00d0fffebfff2f01e0fffebf007000300004000000000c000b00fbef01500008000140fffbfffebf0100ffcbff06000980ff9bfffabf00f0fffbff02c000400000000300fdef00a0ff02000480ff2b000000fdafff5b0000c00300001c000800010000e0ff060000b0006000080005c0fe2b0000000580ff1b000800ff2f004000fcbf0200000000e8bf01c000d0ff060004400100000400018000600000c00200005000100002c0000000ffbf0030000000fcbfffef000000fcbf00c0ff3b000400fb2f004c000c0005400060001800024000b0ff0200ff2f001c00fcbf000001f0ff0a0002000030000400fd2f00f0ff120000f0ff0b00f4bf0140000000fcbffeefff0b0000c0024000e0ff0a000070012000ecbffeaf0020000400fe2f000c000400ff6f003000000003c000000003000480ff0b00040000c0ff3b0000000070ff4b0000000040ff5b000800fbaf00d0fff2bf00b000200004000180ff1b00f8bf00c00000000300fe6fff2b000400018000200000000280ff1b0000c0fd6fff0b0000c0ff2f010000fcbf003000bcff02c0004000a0ff0a00ffef00f0ff02000180ff4b00f4bfffaf00f0ff120000b000c0fffebf0180fffbff02c0fe2f00300018000500001c000000fdafffdbfffabf00300010000400fdeffffbfffebffdaf0020000400fb2f00000000c00100000c000c000000000c00fcbf0080000000f4bf0400012000f8bf04c000000007000080000000f8bf0030ff2b000000fd2f00f0ff02c000b0fefbff0600064000300000000040005000fcbf04c0ffdbfff6bf024000b0ff02c0fdafff0b000400fd6f00000000c00100000000f7bffe6f00000003000180ffebff120002c0fedbfff6bf0340002000080000000000000800ff2f01100004000030006c000400020000300004000480000000f8bf03c0feebfffebf007000e0fff6bffcafff2b000c00fcefff4b000c000140000000040001c00020000800fe2f00fcff0a0000f0001000fcbffeefff5b00000000b000000018000030003c0000c000300020001000ff2f000c00000000000000000f000280014000000001c0ffebfff2bf02c0ff0b00100002400020000800fe2f002c0000c001c0ffcbff02c00500ff5b00000002800010000800003000300004000180010000ffbf0070000000030004c000f0ff060004c000a0ff06000040ffdbff12000240ff6b00080002c0ff7b000800024000b0fff6bffdaf0000002300090000fcff02c0000001e0ff1600000001500000c0fe2fffebfff2bf0700000000ffbf00c0ffdbff0e00ff6fff3b00fcbf02c0ffebfff6bf0180fffbfff2bf00b0ff0b00fcbf00300010000800fdefff3b0018000080fffbff0600003000100004000480ff3b001000034000f0ff0e000140ff3b00fcbfff6f0090fffebf
+InRand = 20435d4bcb09f5a9b8188f056742ae4a0dbca938870e3bff327efb7662656001
+OutPK = b5a0956984e94dcb5756f9ff394f581586c933aa95db66c5fbf68c15d5687bf954d27ba22042d62f8a6311571a81210da078cc70f7d411bf9c2e2c829c280e6ace7022f0de83c98cdf92a1f816a585080bb7fd5ace54adf4dd60b17fc35d3742beba77a10729f9c175954515474a1d7b1e0b06013cf2092d113461c99921ba2d84658c22713f530723f44642af1f8c87fb807a89d10c050635216259050061aa8f3c2d0e102e8e6d99024ac72120593f90d4982dbe5d130d004491ae8ae95afc12ba5059fe1d288a21f178854b50744a069617c70eca46447a189dfec5e7399dd90aac0a639485540bd060f96c877750aa13a118663f186b4a96e890d9d40cdaef268571012fd93fe26f689211a15eda78feafd1b97cc01590190589433d651cc73400bebe3b65aac4858d501e24a7535481ac5b996ad77a5ea814f16082705236299484b3d7dc8606de6e95445be4594e6030d945906b5660dc35fd753735a44a0874dead0ac44e23649c51f62daa013bfc33029ae994678da2ba46cac2a0bd283f4f48e7e9a619e9cc5214d2ea08e893c2e3cb9c11b287dc7835dc237a58c504139a9a49d11ff96c7d8215d3599abee62c54c407ebddde4f3c6b669ace8abaa61fe23b0ea98bae9e5599563c5263cd4125657c83f0d9a2c243158a7c2c6680a8a88add6bceb8e5e00f850394e69d3d47369dc9e1aa86b000d27f4a78c28c624506e8dcfe43a957497310711c54d3f8f22ce12e840a32d146715fc4c4039116a86ee7eb0af30db5adf7999c955a6a0067cc6c33fb8e3ab5124b18687464fc12177b69e66cae866fa291385b8ad872730294958e035a2a5fd9489acd5509a0005eab82dd177bb81af96c03b78d5e94692fb2357ff1bd2b663933b7d9646bc9eb4545fe970a886c54a9915a6c6083d47f42311d841874394963bf0459ebdb354785ae2babb696318ceceb28cd358ef9d389036cf5abfa814cb6abe1508261c9787dc44a9b4038b2a2585a125fb25bc46a179a8b47f1f841137b873101306a2556831bc110493d1c40c688227202c49ff290a0002ff0e56b859b3e3f46e0b34a2c44b19f17275a93257b7ad01640423c80431408813e3d6e5f94e7f18b1c22506c1c1bf4812a9b860b01b248805a03fd588ec54b1adb78a6c4f1af0c547c1b1f8257f6a28c11ea3972f860ff6a1ebd94202d1daaba1077512bf5f5ffb22c63dfbcf2ccba0d836c7042c330028b537364da743f5fec8b646c1974652e8e165c384da662acf28e51089a94857a024a5e6ea27f45abd0115b67d72460405e8ee1b00116ed26bf9c68092eaa8510c45f4015e920f6890a8b3a1aa64ddb820a2e5a6bee9eb399ca7d42a8e8ad79b9a1214e27f90b1f494c77a620f8158e0b6353999446c9b0401ef9910dce28ac6d6a6413fe8398c6dc7615ac85e4d470d1ed394d0bc1273b07f50bbfee2c136c2cbacf6e9e770fc02c9e96d9f39d601aa854e1b7f18a1b260f201055fc844d800af062b163ae176a5b72728acf030139c11d9e075f6cb0c362b00883fa9083f20649e28b75b7aead19e4b347a1e6111300da4487796df4dfdd16e242ac114d37f71485bbcd50f7047a92074265c450c78e016013ed25256a632b646a0840817083c5676182eabc595766d6f7b123c49acbdabbbe5ddb29fc83422432acc397241aeda878c6b6fab3210037d3b9f4a00d2e6753d5583961226bd16910590a7cc3993ff61156097f5bcffb4fae741f878572735296f904292bb9dd834a80fc0422bc002255f09377ce2dde000f23a4b1114de2aa9053a2495048cd9300b07ae6520ad9f2226ac813cbe77e8587d5436bba996042b41a6926a1e26019a34f88f8b285e2a2dc60061a45fb87d7892b745a4766f05a3eaa973e51fff6b7759aadea8254a94d12d7114ee265e96e108060c1fc82b0fea73ac320c9236d5768a979991d2f43b7d2bbe10f9361b959785958ead416b0433e90e757852865a292816d451a2a6a2dd8c87fd828f28de91f8a70cdf9164da8c74a939d6897db47449fe0b7bed448fbbd4d7a12444ae0e865b3f5af4ab8163db69a422c74f3ca71f8996c9758940e5edef168f9867a1f860c64e38508d0256b047c40181d4cd1f68fbdbbe44340fb944a67f310e15aeb8d6a3b168afa78ed81ca536d63b498a679556fa9fe5981c65c5b0566460009a557a7442da41e4cf5d7e1749ac929c84733ce73ca5e7393fd58bb07df14f861420a3aa3f6a1238d46b39742b490a54c8fa67cba2c26bbb655ecc2b2be47aad966b09b6580916f4a9ac3fe6d4e1bbb6161b81f0850bcaaf23c21a7239184b6f9198f9c16a1bd555165e25791e6951ec22acd97bcd10ded28ed67cac18a2f4164318c21088255bc3ad7612364cbaee41cfab0d8282033a8e0b18256c004eb0e6c5aec15854c456146591065664a928816fbfb213a5e4b4477148a2487aa5368b4dede4b54dad78566d42276558149302089bb23af8271e00090a33d29c090692da678a428442f35d8f0e6dbf40f
+OutRec = 00000000000000038000200000000380002000080003400020000c000140003000000000400020000c0003c000000004000300003000040002000030000c00014000300004000280003000080002c00030000800038000200004000240002000000002c000000000000300003000000001c000000000000300001000000000c0002000080002800030000c000200001000040001c00000000c0002000000000c0003400030000c0001c00030000c00010000100008000340000000000002c0000000080000000020000c0002000010000400004000200004000200002000040002400000000800018000100000000240003000080000000030000c000380001000000001c00000000c000200002000040000400020000c0002c000000004000240002000080001400020000400038000200004000200000000040002c000100000000380000000000000000030000400004000200000000180003000040002c00000000c000380003000040001800010000c0000c0002000040003000020000c000080001000000002c00010000c0003000020000000024000300004000300002000080001800010000c0001000000000c0000c00000000c000340002000080001000030000c0002c000100008000280002000040001800020000c0000400010000800020000100008000280000000080000800000000c00008000200000000340000000080002000030000c00014000000004000340000000000003c000200000000040003000080002800010000c0000c00000000c000280002000000001400030000c000080001000080003400030000c0000c00000000400018000300000000080001000080003400030000c00018000200008000280003000040000c0001000040001c000000008000280000000080002800000000c000080002000000000c0002000040002000030000c000280001000040002800030000c000080000000080003800010000c0000c0000000000003000030000c000280001000000000400010000000000000100000000300000000080000000000000c00038000000000000200001000080000c000200004000380002000080003000020000c0003c00020000400038000000004000300001000000000000030000c0001c0003000040003000010000400024000300000000340003000040003c0002000040001c0002000080003c0000000040002c0000000080002400020000c0000c0000000000001c00010000c000200002000040000800010000800038000300004000240002000040000400020000000038000100004000080003000000002c00010000400000000200000000380001000080003c0000000000003c00020000800014000300004000200001000000000000020000c0000c0001000000003000010000c0001c0001000040001400010000c000240003000000000c00010000000014000300008000240001000040001400010000c0003c0003000000000000000000c0002c000100000000280002000040002400000000c0002c0001000040003400030000c0003400000000c000140002000000000c00020000000004000200008000180000000080000c00020000000000000300004000340000000000002800020000c000100001000040002800020000c0003000020000400000000200004000000000000000001400000000c0003c0003000000003800020000c0003c000200000000380002000040001c0000000040003c00020000c0002c0001000080003c0000000000000c0002000000000c0002000000001c000200008000380003000000003400000000c000140003000040000c00030000800014000200004000240001000080000c00030000c000100003000040001400020000c000180002000040003400000000c0003c0000000080003c00010000c0002000020000000030000000004000300003000000001c00000000800004000200000000200000000040000400000000c00028000300008000140003000040003c00030000c000240003000000003c00010000c0000400030000c0002c000200004000040000000040003800000000c0003c00010000c0002c0003000040001c00020000c0001c0000000080002000020000c00030000300004000380002000000000400030000c000140000000040001c0002000040000400000000c0001000010000c0003000000000400018000200004000240002000000000800020000c000240001000040002400020000400028000100008000080001000080003c00020000c0003800010000c0003800020000800000000200008000340002000000003800020000c0000c000200000000040000000040000800030000c000340002000040000000000000c0003400030000000018000100000000140001000000001000030000c00000000200004000300000000000003000000000800020000200000000000003000080003000030000000
+Key = ad539b834982f525e844fbdf56fd496ca25cac45c6b5718de7f2417b7ff6e3b4
+
+InNoiseS = b25e0026c0f1ac209932a42dac2b2a94f3d3a08078080b8ad39ddd85fe04106bad6c591655d7e6dc9936362a1442a112bfddef1594169d3b929b77663dae11971e713bb5d06882cc5933a4b55be9154f6b2da674e96cbc3ac56145875888931f64669d57c5637dbd469bd3b6504124227e5e86789b7403c7dcda60e2012bc20b28d116209cd9d26be498249ad7a933e63e587d4f8c8c728ef5a0e64fa532c8c56db5d629a803c451d0cabfa7fe185c559da2f73136b79418dd245cdd990fa948a7297591195b1fa8d6b953b3a4dc91692c84bada53c4ec8539394de26358102b509549a1dbaaa0ecd9a614b4e96f17d26ce3507c510d1798d11f218ce41a7900249e0ce70ca624560d0a74a23591f8fa553c1cda6b995c951ad4d965a8fea143523358b3147412422e629de92d64820fdb897a9ee22b5be0190e6ca889bf8b27914c61568bda84651b17a787d700aa1c8d0eed5b669d69b644b1283f61266f6d369a50f446e59c7bb911d1515023e484e7d949a9c6498368fd4291433629adfa93c993f5732e7e12a0cc3f79b94dbd84010f5711103f5d622fcbcbac55d511f8ba02ce47e00a4ec84d10af6684829275598c635defc620f59c5a1ce97399d12de74e9f84b8c25ccc87b4e4b7691d6cc595b40b6e7a2d0ea93773d60edb498ba0dc59906a930557d0529b4d975d68e1d0850f601b490f9a107847e909f8c8573c61927374d9a6bfac48f4ddedaeacc39c3037ecb7d251ebb98231bda7035ec9e2349ac3537496f609016d6a79d394ae43e951abe87fad7d7344148943fdb2b76b56c8e6316315a94eda5a3151a65e7608b80968442e33a7cfb1872ce5e2a1f462bd6d65c8d09a8023e944ccd88050a0c1d488843add51135b4ae73d90aef5143bf2016a668ccbfc6bc5d2275302ccb225a269dc08b26a83d96d16ab68e36eb19da009a87195e9200045d07172984ee427b983ec54af056df6caa32e24b2d579862ce60eac0a13a97da0312edf20d38cf94551a8fd61a78232b387a8b217f98ebb29737793d98a364c78a471dc04b0a3eb48cc9e43b6ae6d3875025d58e2aee7a95e69902f4c8bf34e73ce072572883aa930c1665055a07fec86c229dd9d5d4c8c80d227b278fadca1b00da0885b04c6959b96bedb6a5aeb5322a18cc116f29d3c1574cefd7513945479937a20040402011bacf9ddd010da0c7e19e8a65977d4bd96726951c18bd380c62e2fc861e338ab86587a69e49699c1587fc5737613405c50ca11a365b40ac58eb867f37d9aa61157621fb09737970451286e4e1e9d2cb01a1a0c1187bc491e2e1d75e08c02bcfe5cae870bd073ba05bf2b2f4be0d61a4b461970a5d930b5c9bf111b11252e61d3f4a7bd549ec44c0beff42a9c6273b03cad315907f490808144904388d4760e446e6bdadab21593a363f2db448987425f6963012e2803a4c50500ca9a1f22f9d8b64a4c59545bcba76813b7d41fa40d741ffa0d1ef60a040b4441951245c1b4aad9af707c1815959d0bd0bcceb80cce721b83ad1cdb9c1d5b45ae816403d63794cd285f169ec609791aa24f82d58e04436ec63d4a6086803ba584c83446519207c072d24a6ec7a696625e1cbff76c54468e458190e28e6848a4b6a52ab867fb9c0ec845bd26927d1d8b9f24f7afdc72402e65a1e0de44f45eec51585c594eebfee849f63ddc54ce073081837945a121f92e02f104c386df92b927ad02aba9ccbc2857f2557c7aae8eaf8524cae5620d86a2ebe43e40b108ea592b5450f10fcff13bf068771cc7440e7d6ae66c9af4a3340b6fcabee9ef459d8f8dd4b804717b3ec54ae2246abb7a2bd5647712a1694262eb4886befb8a11d4fd297f512e18b819121f4de1af51036a64fb97a111385d7a218ba794b9ddb7066fce7bb3f1b86590b7eb1b753a29d3bc584ecd300fdb33db715c5a15cc1bc3f2fa49a9abc52815c464af878781e85e15fee92788950005deae6822e084a4c9cbdae862c58f76a6fd25262a3a42004881a7160bf546e066f376163ee028b587014a2b2b269a19dea85c4a7690f3d2065dcb200af1e6714199d7498f3858e61d0d11e8bdaa85288c256cb8bab2982e038a084f459ba0697e7e9159ca0de7b2ecab32a8a0e2b3e26097e321868aedb9318c7972bf6e011e03db452ef8a07ce49d129d12b7e55818e9c4ada4dad00e8722764009ec09082a7870402abd180d050dab6cc5e110a290db641ae620ed5ec58a7f97821e07cb54de427454a5d90d28926af2008525d9f053487aea87972764023751e5cc959a793aa986230814082e8d0747d908027b0e0baf36e8768776a79a7056b438b8a7d3a134da4b698c8dfad12e418b2435f4aeda6cf0a6d4d4906e3d4845606947f87963c7238592e81aca8b03405365408383d120fc3178696d6599ca124fc6014ec6f2e93d274a8e28e3c64a395e433043283d81a91839d8984f642fa1c1043932596fade0cb561e08cffb08af0861535276d622b225d38c755b969c1971e24d600a9a5c
+InPK = b5a0956984e94dcb5756f9ff394f581586c933aa95db66c5fbf68c15d5687bf954d27ba22042d62f8a6311571a81210da078cc70f7d411bf9c2e2c829c280e6ace7022f0de83c98cdf92a1f816a585080bb7fd5ace54adf4dd60b17fc35d3742beba77a10729f9c175954515474a1d7b1e0b06013cf2092d113461c99921ba2d84658c22713f530723f44642af1f8c87fb807a89d10c050635216259050061aa8f3c2d0e102e8e6d99024ac72120593f90d4982dbe5d130d004491ae8ae95afc12ba5059fe1d288a21f178854b50744a069617c70eca46447a189dfec5e7399dd90aac0a639485540bd060f96c877750aa13a118663f186b4a96e890d9d40cdaef268571012fd93fe26f689211a15eda78feafd1b97cc01590190589433d651cc73400bebe3b65aac4858d501e24a7535481ac5b996ad77a5ea814f16082705236299484b3d7dc8606de6e95445be4594e6030d945906b5660dc35fd753735a44a0874dead0ac44e23649c51f62daa013bfc33029ae994678da2ba46cac2a0bd283f4f48e7e9a619e9cc5214d2ea08e893c2e3cb9c11b287dc7835dc237a58c504139a9a49d11ff96c7d8215d3599abee62c54c407ebddde4f3c6b669ace8abaa61fe23b0ea98bae9e5599563c5263cd4125657c83f0d9a2c243158a7c2c6680a8a88add6bceb8e5e00f850394e69d3d47369dc9e1aa86b000d27f4a78c28c624506e8dcfe43a957497310711c54d3f8f22ce12e840a32d146715fc4c4039116a86ee7eb0af30db5adf7999c955a6a0067cc6c33fb8e3ab5124b18687464fc12177b69e66cae866fa291385b8ad872730294958e035a2a5fd9489acd5509a0005eab82dd177bb81af96c03b78d5e94692fb2357ff1bd2b663933b7d9646bc9eb4545fe970a886c54a9915a6c6083d47f42311d841874394963bf0459ebdb354785ae2babb696318ceceb28cd358ef9d389036cf5abfa814cb6abe1508261c9787dc44a9b4038b2a2585a125fb25bc46a179a8b47f1f841137b873101306a2556831bc110493d1c40c688227202c49ff290a0002ff0e56b859b3e3f46e0b34a2c44b19f17275a93257b7ad01640423c80431408813e3d6e5f94e7f18b1c22506c1c1bf4812a9b860b01b248805a03fd588ec54b1adb78a6c4f1af0c547c1b1f8257f6a28c11ea3972f860ff6a1ebd94202d1daaba1077512bf5f5ffb22c63dfbcf2ccba0d836c7042c330028b537364da743f5fec8b646c1974652e8e165c384da662acf28e51089a94857a024a5e6ea27f45abd0115b67d72460405e8ee1b00116ed26bf9c68092eaa8510c45f4015e920f6890a8b3a1aa64ddb820a2e5a6bee9eb399ca7d42a8e8ad79b9a1214e27f90b1f494c77a620f8158e0b6353999446c9b0401ef9910dce28ac6d6a6413fe8398c6dc7615ac85e4d470d1ed394d0bc1273b07f50bbfee2c136c2cbacf6e9e770fc02c9e96d9f39d601aa854e1b7f18a1b260f201055fc844d800af062b163ae176a5b72728acf030139c11d9e075f6cb0c362b00883fa9083f20649e28b75b7aead19e4b347a1e6111300da4487796df4dfdd16e242ac114d37f71485bbcd50f7047a92074265c450c78e016013ed25256a632b646a0840817083c5676182eabc595766d6f7b123c49acbdabbbe5ddb29fc83422432acc397241aeda878c6b6fab3210037d3b9f4a00d2e6753d5583961226bd16910590a7cc3993ff61156097f5bcffb4fae741f878572735296f904292bb9dd834a80fc0422bc002255f09377ce2dde000f23a4b1114de2aa9053a2495048cd9300b07ae6520ad9f2226ac813cbe77e8587d5436bba996042b41a6926a1e26019a34f88f8b285e2a2dc60061a45fb87d7892b745a4766f05a3eaa973e51fff6b7759aadea8254a94d12d7114ee265e96e108060c1fc82b0fea73ac320c9236d5768a979991d2f43b7d2bbe10f9361b959785958ead416b0433e90e757852865a292816d451a2a6a2dd8c87fd828f28de91f8a70cdf9164da8c74a939d6897db47449fe0b7bed448fbbd4d7a12444ae0e865b3f5af4ab8163db69a422c74f3ca71f8996c9758940e5edef168f9867a1f860c64e38508d0256b047c40181d4cd1f68fbdbbe44340fb944a67f310e15aeb8d6a3b168afa78ed81ca536d63b498a679556fa9fe5981c65c5b0566460009a557a7442da41e4cf5d7e1749ac929c84733ce73ca5e7393fd58bb07df14f861420a3aa3f6a1238d46b39742b490a54c8fa67cba2c26bbb655ecc2b2be47aad966b09b6580916f4a9ac3fe6d4e1bbb6161b81f0850bcaaf23c21a7239184b6f9198f9c16a1bd555165e25791e6951ec22acd97bcd10ded28ed67cac18a2f4164318c21088255bc3ad7612364cbaee41cfab0d8282033a8e0b18256c004eb0e6c5aec15854c456146591065664a928816fbfb213a5e4b4477148a2487aa5368b4dede4b54dad78566d42276558149302089bb23af8271e00090a33d29c090692da678a428442f35d8f0e6dbf40f
+InRec = 00000000000000038000200000000380002000080003400020000c000140003000000000400020000c0003c000000004000300003000040002000030000c00014000300004000280003000080002c00030000800038000200004000240002000000002c000000000000300003000000001c000000000000300001000000000c0002000080002800030000c000200001000040001c00000000c0002000000000c0003400030000c0001c00030000c00010000100008000340000000000002c0000000080000000020000c0002000010000400004000200004000200002000040002400000000800018000100000000240003000080000000030000c000380001000000001c00000000c000200002000040000400020000c0002c000000004000240002000080001400020000400038000200004000200000000040002c000100000000380000000000000000030000400004000200000000180003000040002c00000000c000380003000040001800010000c0000c0002000040003000020000c000080001000000002c00010000c0003000020000000024000300004000300002000080001800010000c0001000000000c0000c00000000c000340002000080001000030000c0002c000100008000280002000040001800020000c0000400010000800020000100008000280000000080000800000000c00008000200000000340000000080002000030000c00014000000004000340000000000003c000200000000040003000080002800010000c0000c00000000c000280002000000001400030000c000080001000080003400030000c0000c00000000400018000300000000080001000080003400030000c00018000200008000280003000040000c0001000040001c000000008000280000000080002800000000c000080002000000000c0002000040002000030000c000280001000040002800030000c000080000000080003800010000c0000c0000000000003000030000c000280001000000000400010000000000000100000000300000000080000000000000c00038000000000000200001000080000c000200004000380002000080003000020000c0003c00020000400038000000004000300001000000000000030000c0001c0003000040003000010000400024000300000000340003000040003c0002000040001c0002000080003c0000000040002c0000000080002400020000c0000c0000000000001c00010000c000200002000040000800010000800038000300004000240002000040000400020000000038000100004000080003000000002c00010000400000000200000000380001000080003c0000000000003c00020000800014000300004000200001000000000000020000c0000c0001000000003000010000c0001c0001000040001400010000c000240003000000000c00010000000014000300008000240001000040001400010000c0003c0003000000000000000000c0002c000100000000280002000040002400000000c0002c0001000040003400030000c0003400000000c000140002000000000c00020000000004000200008000180000000080000c00020000000000000300004000340000000000002800020000c000100001000040002800020000c0003000020000400000000200004000000000000000001400000000c0003c0003000000003800020000c0003c000200000000380002000040001c0000000040003c00020000c0002c0001000080003c0000000000000c0002000000000c0002000000001c000200008000380003000000003400000000c000140003000040000c00030000800014000200004000240001000080000c00030000c000100003000040001400020000c000180002000040003400000000c0003c0000000080003c00010000c0002000020000000030000000004000300003000000001c00000000800004000200000000200000000040000400000000c00028000300008000140003000040003c00030000c000240003000000003c00010000c0000400030000c0002c000200004000040000000040003800000000c0003c00010000c0002c0003000040001c00020000c0001c0000000080002000020000c00030000300004000380002000000000400030000c000140000000040001c0002000040000400000000c0001000010000c0003000000000400018000200004000240002000000000800020000c000240001000040002400020000400028000100008000080001000080003c00020000c0003800010000c0003800020000800000000200008000340002000000003800020000c0000c000200000000040000000040000800030000c000340002000040000000000000c0003400030000000018000100000000140001000000001000030000c00000000200004000300000000000003000000000800020000200000000000003000080003000030000000
+Key = ad539b834982f525e844fbdf56fd496ca25cac45c6b5718de7f2417b7ff6e3b4
+
+InRandA = c664383843e8befe514ab2bda15c5aad395931045b4b1c235b7bca75ad04216935f18f64dbf1d22c2e410c50e84468859fa80efbd78b1ab2cfcba7f235b471e5107e3337aa4de117333b3de593075f083a31f22e59964846dd454df9d992372561218a20d1f59a6628c65bf060d7a6956e0bc2e679c6b85b44ee1b07a13faedcde44724d4c98ef58516be8346ea4422008e96d68225fc9e0eebd5d8e149956cd1660c5eaab33387c6c17774073e9516009a007de75172991609901deb2808a3b93a15cae615e19852ab9a8fc415ce6f2ed203fc1f785ef6e77739d44eab1720ada4a7ad43cd96b99ad29b15c80b42f0566315841035e246e6b2358372c5257a4b97c3bf6dce693cf5c3f8acf468ac9ee2903a075eb829d9506e0b21504699f7cd7dbd72cbe0a36cc7e6b47f28a00e5e2a848bd95bbcaa9e14f9a72cc9edd253a61419e24dda294fe0de54df1fb14227b73d7cefad3bcbbcd41e74199797eab8089e7e56990f86eed4a3c8c7f39df1a70aaee6fd429d39854286e52d1bd8a0c2a8403ea58b010f0a175d0a974365a2558446b3522186cc2e0ff1b604caf2b211eb080f507ded619594de87d7f2655a2ea918dc384394a362a5a985c6bb935c14100acca189e84494ba27373ab1e955b228122807d78f1cb4a44b64459c90921308a448a83e14556129464459e9204cb2a90e3295833701d0bb6e700d9b3ed30f9599a31d6e00d871bfdf7e3e5a4e2a4317b233e4cded198074395092d9c9c513fd295e71cf4e0e85e2989eb4a31c752b5791c66842db51e4e8e150b23ad4c5724bff7a4f9061e5ae5c91a69615aa36fe6eb044b374fd2b88d5a532c608c8aacb091d08cea8a67a9028e620d7b41047d7a88d07b39050aaa67703101a492be1cc1f16224a91c9ce75b5e48ac5389aec2c7fd44b3521656a38e849b52d7c1dbd9138f868f78cb405c830a00a60f0e6a814efd8599726fe913b7b4fb36b2a94eacb7d938a1212d5f2aca551a2166f32ae45c2933ed945476014151448f649eca8b1b2b07c181e9153f4d7c78eea1b4ee00c4316fd073a1c9da8bbc2876f256e3d2218a180b2efc04fdfe61d2c417093e483bb0535a6892d52515ddbdeab4544b8b45e945650873f24025a6a65c3fc2202a244c695acd60f555f8b5ba196336daafd899ea09f1a8df918277889118383c12e5a8dda938ba5d0214148a16daaf196b6f12a20d17a6d1b57882b4437d9f0099cc483e731fabd2151e4febef2d55bb881f271a343306345096e8c4658a583cf2682d41ea924504ad0069c1764a5fc2c959a14d93ecadc18635e476b7d639d2bb008fb1e05ab6e454a30143f859f43477e7cc6253df152e2fa42958d67446dc9843c42e294b6196eb17c928811c0f686902d52cc24652e43344a6da135f6b2df84b4a802f703965274f8d5566469d9a146a65978d1d453f581881a52680f3eb9a89677563082bbd312bf53a569dc5c6f1c13279de627120fe804f6305a897fe479b1a5729836db61c9bf9c3cc96b9eb52a4836ce0608be6be33f1d2355bd45be2449d10e4012e3a92e420531056ea532039f8ca2daad8d0051d5b201b262db64e0c60901ae91d22126ce3390692a61b6e13d9a4b6ec44019a08e9241ca5e0d261baa092161eb58fed33f94e91a2bc18b7d1dfddc122de3c8d93bd6619945987c8af349714109a65b3a0f9a946b8843b1677d867aa8c5b38a1324d4a5cffb8d98e94e4d837b16c0a823f04ea17d4f470f7c46cb49d01ba23e66f966f111a525e662a0b69818801b8c4c7398f21954168551580766d4882b0f6586f4ace742d2c07b96dba61dfc8763aac92289e84afb1ae4afa784204e82f2c2461bc073da91c3615ca970f195e37b9e5a11143e1317336b320d349b6402979cc6fa1984a843cbf1435a519ca957fcf45658ddaaa8fc130e1bd3ebe5c8b4164fe6a0b76d6e3f252d170889572babe5085a68fb42bfbf45a9419372a7e926fc604faab4ce138d34a1e6438c649ad282d4077ed990b911656c6192cad9a079764f995179eb3225fc67fa71b008aa1a4821a991133497e28cfe02ca4a87cb087c412a8998d22fb4e807bb51ebfab53a6c9a6602e9cc54f1a8f9c53ef95c5f0879256b1d6fe2aacfd488943a49135d49fc54fd326e5963ccc451583030dadf30086128bee2b74902c58d9c0b4a10bce90a3848b75d4751038dd3ae5827f95a83476e060f38779d151a8deb0517b6a526415447b48f66ce28615a5e3c10f971397375a7c0ac5264266f4b930c34faba354d29f795c9aca392413586218e567d9bdb95209c94322a1d96c9a628f9e97abaaf6332e4e61ed0d904b119086ed021401be72abd6c460d50dd2a7d29ab890528d31070b7d781f2a6912074bd1fde427f60faab61b263c2d52cf6a4092b66e9080617554aeda564da0f5c9586c987541ec2551a7ca0d512bee052be4fef66f750b7c9bda78350ca4812394545041af7d550d7142e579db6d954489301dc4cd9b405f685d69470c325c490b
+InNoiseS = 8159e4d8f3901f0cec2355ebc6511fa4993a1576af5257b606f5b5317703e6b78b4053961048db1d4661b68e7bd70c8a00f758c257fbb81ed7cc2aba5fb098a4a0e8d5b5466ad209a639d99c0408eaef04895cae0cc75a18838a2d4517b927807d1e83ef9dd6f1cc1d42ca623b720581b804bee5b95ea47f8a7440db5073166fc595b314a519c178bb37b14b7b18cbe4d68027c45acb6760ed815f035b7b108c4193e470611f2e413d50e7d0596537cfa86cb93c4400c8240978a9d2325f0d30776de50e351662f2d97c8878468dfa5555618c0e25e237fe268658069153d90ee7552296b0853f2e2787853e2a72accf3dda02b203bca258b231b8b60f5fc0aa02b5680b15d6122e8d8bf5a7c474fb867d4f9840a47a198ba81e0d20b55692c528f0d296aa6ddb0a0e868fe41c00c01ba21900740a9cb3469e0948774fd769215a2b8ce940f37ed2b3e989c1883c548a220b88020dad389e55175989f916e62edf3bfdb9569ba33f8242a19e1c58141966be01e50c9514179644bfe6e2b0352d6d17eb637a498a5fb0d57181eb5400260ca0737e59038053a543cec243ee1da72263a0bd3669d4198b62855aaa315a7254603326e4a209116ba66bf9e7abfd34619adbf4086528fb24ab9780e54690695646eacdbb7e2f111782e11001464c22e74e52ddcba7a653bc822f6aec2ac0b694c9809d21de4e404e086cb67e7164b5018d29c3f64da96c1e7291949028ee6d279fa4314b26dc4515f95cd8436dc61a1c0dd429fe3652c8048c09392999b93b96de1be819e833d40b9f20440132d94b2cd13789473b5b87b41c75a3a5da6d8880013d8246ead4983d33c21e1ca7a6ac45e60c0e536ccd348821ce5bf59829bbc8a6357b5839cbe6d9a47bae4bec2963a023766b7d835f21d25c0bcf43b064400969a5ec08a50d245954e8c433bfc06347df623aaf988b17680fe0709012dbe9f3a071f92919de80f6825284a35929619732367a166b065ec83f9fe53510c0b84714db410b391ea1851d1313af396d8112b1c608300123d8d1c47df0bae78f97ca03f988d3ef3697aa76a11ba72e013d316a83edce235e680d8da0e6009dd019f6652ee8111419ed60586a116a637c9d2fb8ddea48384945337cc9720b63f6f7af590e4410d7a6be0c4bdce16776e0385ae3536a81104920c449298a8a0269c2d731a1b561a4e302358445cd1647abb5e54f96b07982e60a5d6200b9070949e6f974771cb9e3080d4bec507e3b462e8fe72228656201828f98d31b736e6dd0de704501dd3e069e7a070ae89c2e66ffbaae926426ae8d507f469b348f0996fa70274a90aeeb22ae51f11365123d7aa93ba0f309ea161f66cad5ca3795563fdcd0717d8650cfcf49821f5a600444b067f7d9a9619f2da086d1877dea143a77097e6999612155e9544a4c88a682e5014a8086c18a6e88942bc38254ca4c3021641b434623a046138b9166039e46e52bc2654f52cc367917fcaa77c7ddf798e6930f6cff97d8305c5f1323047f826279a115abf31470bb6868a4cc9a1f099246758a9801b769ccf145809e4b0d77abd4997d1bc88d90cd1a26ae6383fbd7d2aa3026ef860f9624ad092839b7d5753f1e266ac02614e1dc23052bf8171268aa8ae6c67105a38a08cfd93d7a0a35f5071104f7820632c760756ec263784676aaf708d6699fe09534dc1865cd11b1a58c190a20d93e33204475daa45f7c11e61900754ba3e93827fe2a2212a0f9839c22924ae69102f1ca4c1e1b8125df684cbd1839541b856d75825dd24a1a615810541348020f56952d89435c006d4aeb365ee11ac9a14709c8a894642265d03022243bcef2826f94227d02a1e6851c98c124162681a5113eddd24b3d889b58c0fe2a396a67b8a952b627c20ce5c0d8d66985261ad13b7658ad0b36ce4e24435809b928dc229dadbefccced1746a616d8d202037160442edde9e0f730542355d9cbe81433ef1e8714276dafb05671149c9a77e69195856e9e315820ab07cf35492a0b8009bb7c913ccf34ab5589ad0d6d7b6840b9673945ba16667a03cfcd70a70d14718c5b228566b54fa15fd1100a7e7406d72c6494e14643030d35a44d93325a07083cad85ac1f51d05542402eed5bf08e4e1046c3b4607ff864e4681581376db62ba977815e28203e066702c911593ead01d6ac4c4a69505e56ce6d59ae149631dcf19c2b0d8f05846a9a33901cf078fa35aa5d3f67d52649769daa605282581dd8f4c0f6156b2208841bd3c1573b42fab7c74db0aa0f4f5927e24765d83a307b644700704bc0bca665e1a8c240a9e4296d0873a6041d18f9633738402682fc23752931c611b3e526f2d43d95a346da7835e0662a68daf4de5e2c7561b1b9e2a836144be8841e157f62e22aa0293cb07183e0b9e4b6bfcf6b7baa91353264ad91795e2458125d441a4fb04ec0245282a18abbb39f6bd6c695b392d7ea22499eb22c5a795223191848d46f5691615b274ef72bf28d4226928947cbdcb02a0bd8e28ed45a
+InNoiseE = fbc6ff58a75dbc6e5cf3845afc27d2e024f3012cb691484ec86571bcd098636a008285835cfb3353942b9ba32e97ef3e1e17d72cb53cc5aaaad50235ee2ebe324a50b911963da9db2df069fa3a9905cdc54f0a8e5defcb69d08447df66b34244b4b879a6a577ff1a473c00b08b6eaabdddce9214d64628b053bd47633e215fc5f28a3bb10c115dabb2561d818b0147f5bfdab802decb987d7cb6c503a55104965b5fded9cb1d8c7faf557edac6c45acacf2f91d7debde409fd0b583060e581e7c50542b528099b192cbcb220254e17959933cdd481f944e99a8f9b0736dc9a661540f2e11c503f3614d873e4929b5668be71c9291f2f4da753747a23fa49c139127202ad96ce29e3a247cb638d97c40967cbd1b1a0e1ce6420135f8907a5485c505c73946046add0ca78491c934fa7851acb4e857110b4dabc1da28382ca03f59d69906941829b2d2d72ce99731f108f78cb3956096911cb5f98e8a8a5a109a2acb22bce952721a6d47844183e0f8ae14b5914de6c82a8b821a96243d9cbb7404308abac47904a0ce596f6250ad299fbe8a546482c7afcdbd745b942814e8d7b5087113d5885ceaab6c1893e166bb447f0079b1746ba97d95de7cfbb09c2f884be4927369cedbf8a4e0140d3e4409324cb5ae536356467bf09ac6e2f2a483451f406093a8943d56cb8302e9f898abeea41490b42b9b6e086d088362105a5bfb7605a22a77c5947ec2bb07cec320523899b3c29aa5e146b064f3e959340f1c51e380e1f94ce13f25c568865ae7a1dbdac6d526db2cfa44a732853a2dfb90df51bb0147e257557901a3474f863e6c100086d3034055b596ac2debc72a9f1376ff536facc099aa88cb2968c5beaa4f48bc099ccd6b5f8b33b047997689c6a1b9bd48a2e893c2c5cda755759840ca8e227f9224c74ab6e881a841528c7f0086bad9af2d82375aae2809cd5b4f665a445c4cd2daa50d146c983ecd2e19d8eaf85d24321163b921869807e255a4da5a5800b51a84a0f7cd447587fb66e3f94f7f08359233676ba7d8e44406e7a593549b2c5a72148256c3490c65af28846eca88c2529018c1d0517557aca9d9a4f35eb35a5345f2e3caa0ec9602ee97dc18c049d1045603543c404b82424dab739a2a42be4c8f4d83442c3ae80b91425d22a4113bee47a61dbe74bdece5d302dc2459be992c840d0d6398068d3c0ce578d997168d81d1302e86c7843d93419483d90e7da02d97536ad0ca827ffc8bc5ad761c4da16bfcd866b103faa4040196c383f11822bc865e6288d27e98759da788a46c827a2f3662a205f98be55422c172c4fc2eaca3a8fa911e7ab157284141365170ea02c0461c7d000c11f781175a54f92694e8716f2089aa85c1df74bf8a547bf991454c13ab7d81dbe02e2cc4ea953d7849d59a649120c1a630c4b57d4f5e67ff67560c93266453e12cf2234ab34a90531c4fd86764d847addbd6921be4ba167534390808d742dd282c88a926fc21ec6e8b059b65e3bc8c4dc738425ef9a0ba10e681b1ed8ffde75b04f955bd3358f741c5be06bd69b222d00615a05006def7e01ef5992bf93209945ae13d6ee6f44a1c16340181688724e357669d6b04f61bad76742268c389a36cebbe609294729e4e364147c6204d2e7f6b1954a92172a10cbca1f47e0dce19e356d4a0521830f504058c6d035b471bbfd9bd3db70a87f621b59ea115e5d1b028cbb66288b49cd48b567611602931697117c94c65f51a07e700bcfd60ed54ebe18ef0a72f2e9fc293da7f332c709996d66d8e4b785a2e6199c08368d2e028e023686a933f6dbbea656990886e8eb9931bcbc16da0950498c0dfb43655689ee3794013a69e0ca65c3a5e1c4923db71ce7b6693048a9fecd8895ca310fa1d93fcac2093169c7e458714a2eb1ae319241c88b491b75f4ac567f40211eb68dd6adca53a368ef2e6c0b89570821ba5d9805bcc1fd141a8385e7884e65af2852f9411f01105068fd41605572f0cac986688a42bfa5c7472fc17c220e594b7194698cc87b4788c831df1afab81952295a631449c7696b66aa35e82c34466a5625b1d3584492ac15a05cd2abe26fcd647c526a226743fa7aec6e5ed90255aff582be19b80730550fb8e3a8218d924c5dda52b5f7cd6ba049192244b43c01eb98f7650e3fb99581892b50601282c2b085ec858c1fc90b0c7eb1a72557bace0eb536a42f3310a29e08cd84b3993895decad42bc1701fe8629464de55037d60e2d3f0c57fb98dc1f5533ab708a950020bae7aba840d7a7cc1bea74c37da9d3e767951d4c9a405a1410f1334c3bc058ca75052c17110b2e025f7323a66add069f0539d0b9edbf548d7c110de42c4b4ee194dd76ddc2b2dd6a577437f927cd6a80e57acc6e752beb1c9e6f39529966397deeaa7e956f39f9de62ec00bd2129eb6bae6877824e11565bd6c8f0773796de4acab01ce8acce5a44ed9a74827088e8990cdaa56c264751581d37555befd6e2db56df5a43943ed285186161729dc14804082
+OutPK = 3821857b649a3bd42b7258662d639824e8b22c7661d9e7be58001824e56bf942c51a7aa4cf2e064a7e0938df4aa774554d9023d7887196425a41d0ca79b166690154c32dc59e580675dba22a63a76894a216f96241a7391a9a3db565e906077c040ee29297a2cac16159cf7e0822c097ce2c47556eb807e109fa6adf886b3222213a159507d209d494aa2042d2af1ac8933cb573e26819f05c36468e33f0eab26466c0fb0735cdb97f6270f80dce78721c73c4bb840cc6c8475b1c8d83792498dac8353c30eb41e5bc1419fb8a4f11384431e0c4ab597a3d68b6eed71ba66a21d8d714d77d7e4c7d1fd994ae407d38c3f631631a1ee7a3872b4da184cc02f5f947d2ae8d96740a1f2840eeabb1e0890e42828a0da52b15679de6a7f519b5b6d60e808b1819861c0cb87401a47d4f27475510d9b67be9de19814c0c6cedf2b254190147ee115b97454401de4a0621fe5f4e544a29f2962a814c2991099207042552388145837886ff93c9ca76cca1ecb05eac9a45cc5f4861909596ad55d9d5d627972cb35b1b9941e6281bf29cf9a9f1cc2298605914ad858daaada41a9a0dbd16985abc8b22c064690ca2ed022ed847bd1daa98a76876368277c82921ce15a1916d1ba1b05a86a8cf6600041567049d51a9c416a5314b13a8ce753eba167ff497d08209509bf4206cad3f852a03c54d31d5dd5e37d13e96666ba9f3ebdd8bd7c5e851f73cbac90258a90bb91bde8e7d003b0c2b2786c966d6706e4adb3a81e4b1803c99a00bd94d45cb0c4307ecb9a42f9dae935a226e84472ad76ac59fbc5dfd662c7e917000d7a901d427490bb0f0555d59e39c4864a0c62a2dee0dc2b6a856695c8e90a34981e38d2239da79a853c979e7bc5146fc23ce8b945e15290f525932f409cd97ee41d4a0ba6bca6485e95d476fabebb320ea2b639a16d8cbdc6a55d72557f7509f9a26ad3053165b7ae23a652796270fa783d417e07376d41966ec36102b6bb175c2cd20ea5abf92366468c74e0196afce0f23579bb4575c235651ff10ab3a4f38813bc200de7e262e11ca31e8854f85c858bbb98fc16f60e730d2b817489699768a7dff031036894c39ed99c2818cfc85ac51e1617b8e7bfd9f7540c0e938798bc539b1509a10e2bae74d0a5f998e2c83a53a3b8c94bf65b96c98c4eff216d1f93593654844b6f0af158d032bbe86196541d6d466c2887cc874d2cb75bc06a68585dd0a96d4de25c21ff64d7c0c20716032981a23acbbfc6980fb6a8b53475d644640efa7eaf65a830e95f97bb97ada61b2a14bfa13f7dc4c4a26b53541c53f51c9319f272e36e4b9d855bb09277aea1693c6e82c27bd85509751af4a21b0595c2ab164b79176d2269cf7903e996ccdd4724148a0ebc47531d04881ef562769420596891717778968107c9a63c86d491ac5dd885b672908e7820a419118633896d67a3274455f16acf436bc838a2cfcc5dd8503a982101488457d63043cf83bb273abdf0daafc5d966029fdc9235a9df74d024aebf08b4a9aee68f2b16185ceeb73a4394f015263771fda7979d947e84c616f380a87935ab90f0d9afcd79a6aad65efe6893ca21016915ef66b26aac818ba75a9985045d8ab749bd4a6ac8e2512febc2827e18965e37c9467982f0ab6a57cf70056981d4810f7e21158ada05fe354c5f3b1926802a7a3f88c411c2d01d9e56c2263bc64cf3805f0767b5f199b3d6535d3002b244ee2b0974acaebe9aa155ea9ee9b021d473f8cc545e45e227e8ebd5b4542b527ea5b4262a04f8169ba78586a830cc649d2b78e6f726da1b8e56db1f5e01a48bc3a379967a9772796450fe5f3863da94cef9671f4f56a3461239c3579ce7d2d6194cb84504a7a9cfe00f96e29d1ab69313bf95c021801f0507c1801081484682a15b241f8e7f345517ded639390958b448869ebb50087482f26fb8c7d7aca0f6720ae0d59f21e22e1ea66af51800fe717f444d9ea224216460a2e92f09aa3298879d388d8f2540dcfe5e617190e26fa6e87b9c91685a1131a5a14323bcde0be36d78510872b79a17745733311236875c827ca094f0ac6e5917d9bd6d0e3cd2194cf79e39be41b8dacf804447a44c6862571f0f496d9c8a8e549619b2b2f8af4d116a195cc1a34571a41a62fa09adec4744cdbe505f289047302a820a1a03ea9a2b6e9793d8a9b90b962b96e205d684161918194e1c085db26d812908ec429c199527d2b7d03e6b40fdf551cb70aa0a7a224b3c01bbe95762ce941d0ac72a1c0394acc994b1424985bbd6d64ec119cc535a00c229f37f7c21e32e92b9d71eeb88a118015b454ae4a0bc23bc8daf5b589628dd23dbca40966e0a7cc1463758abbd7ebb260da1dbe944df451fb5cd5f1437467d408509b5d5e726f265d93801155f282f73998f653e643c4493d70125f2c006b402eae4629efa69aac7ba8e8dc04b67009da88f6d8dbf148874cf4733845895ae13fa21746aa899b138b30b034d5e733380f66301dd129e030d43197c1b7f373d126
+
+InPK = 3821857b649a3bd42b7258662d639824e8b22c7661d9e7be58001824e56bf942c51a7aa4cf2e064a7e0938df4aa774554d9023d7887196425a41d0ca79b166690154c32dc59e580675dba22a63a76894a216f96241a7391a9a3db565e906077c040ee29297a2cac16159cf7e0822c097ce2c47556eb807e109fa6adf886b3222213a159507d209d494aa2042d2af1ac8933cb573e26819f05c36468e33f0eab26466c0fb0735cdb97f6270f80dce78721c73c4bb840cc6c8475b1c8d83792498dac8353c30eb41e5bc1419fb8a4f11384431e0c4ab597a3d68b6eed71ba66a21d8d714d77d7e4c7d1fd994ae407d38c3f631631a1ee7a3872b4da184cc02f5f947d2ae8d96740a1f2840eeabb1e0890e42828a0da52b15679de6a7f519b5b6d60e808b1819861c0cb87401a47d4f27475510d9b67be9de19814c0c6cedf2b254190147ee115b97454401de4a0621fe5f4e544a29f2962a814c2991099207042552388145837886ff93c9ca76cca1ecb05eac9a45cc5f4861909596ad55d9d5d627972cb35b1b9941e6281bf29cf9a9f1cc2298605914ad858daaada41a9a0dbd16985abc8b22c064690ca2ed022ed847bd1daa98a76876368277c82921ce15a1916d1ba1b05a86a8cf6600041567049d51a9c416a5314b13a8ce753eba167ff497d08209509bf4206cad3f852a03c54d31d5dd5e37d13e96666ba9f3ebdd8bd7c5e851f73cbac90258a90bb91bde8e7d003b0c2b2786c966d6706e4adb3a81e4b1803c99a00bd94d45cb0c4307ecb9a42f9dae935a226e84472ad76ac59fbc5dfd662c7e917000d7a901d427490bb0f0555d59e39c4864a0c62a2dee0dc2b6a856695c8e90a34981e38d2239da79a853c979e7bc5146fc23ce8b945e15290f525932f409cd97ee41d4a0ba6bca6485e95d476fabebb320ea2b639a16d8cbdc6a55d72557f7509f9a26ad3053165b7ae23a652796270fa783d417e07376d41966ec36102b6bb175c2cd20ea5abf92366468c74e0196afce0f23579bb4575c235651ff10ab3a4f38813bc200de7e262e11ca31e8854f85c858bbb98fc16f60e730d2b817489699768a7dff031036894c39ed99c2818cfc85ac51e1617b8e7bfd9f7540c0e938798bc539b1509a10e2bae74d0a5f998e2c83a53a3b8c94bf65b96c98c4eff216d1f93593654844b6f0af158d032bbe86196541d6d466c2887cc874d2cb75bc06a68585dd0a96d4de25c21ff64d7c0c20716032981a23acbbfc6980fb6a8b53475d644640efa7eaf65a830e95f97bb97ada61b2a14bfa13f7dc4c4a26b53541c53f51c9319f272e36e4b9d855bb09277aea1693c6e82c27bd85509751af4a21b0595c2ab164b79176d2269cf7903e996ccdd4724148a0ebc47531d04881ef562769420596891717778968107c9a63c86d491ac5dd885b672908e7820a419118633896d67a3274455f16acf436bc838a2cfcc5dd8503a982101488457d63043cf83bb273abdf0daafc5d966029fdc9235a9df74d024aebf08b4a9aee68f2b16185ceeb73a4394f015263771fda7979d947e84c616f380a87935ab90f0d9afcd79a6aad65efe6893ca21016915ef66b26aac818ba75a9985045d8ab749bd4a6ac8e2512febc2827e18965e37c9467982f0ab6a57cf70056981d4810f7e21158ada05fe354c5f3b1926802a7a3f88c411c2d01d9e56c2263bc64cf3805f0767b5f199b3d6535d3002b244ee2b0974acaebe9aa155ea9ee9b021d473f8cc545e45e227e8ebd5b4542b527ea5b4262a04f8169ba78586a830cc649d2b78e6f726da1b8e56db1f5e01a48bc3a379967a9772796450fe5f3863da94cef9671f4f56a3461239c3579ce7d2d6194cb84504a7a9cfe00f96e29d1ab69313bf95c021801f0507c1801081484682a15b241f8e7f345517ded639390958b448869ebb50087482f26fb8c7d7aca0f6720ae0d59f21e22e1ea66af51800fe717f444d9ea224216460a2e92f09aa3298879d388d8f2540dcfe5e617190e26fa6e87b9c91685a1131a5a14323bcde0be36d78510872b79a17745733311236875c827ca094f0ac6e5917d9bd6d0e3cd2194cf79e39be41b8dacf804447a44c6862571f0f496d9c8a8e549619b2b2f8af4d116a195cc1a34571a41a62fa09adec4744cdbe505f289047302a820a1a03ea9a2b6e9793d8a9b90b962b96e205d684161918194e1c085db26d812908ec429c199527d2b7d03e6b40fdf551cb70aa0a7a224b3c01bbe95762ce941d0ac72a1c0394acc994b1424985bbd6d64ec119cc535a00c229f37f7c21e32e92b9d71eeb88a118015b454ae4a0bc23bc8daf5b589628dd23dbca40966e0a7cc1463758abbd7ebb260da1dbe944df451fb5cd5f1437467d408509b5d5e726f265d93801155f282f73998f653e643c4493d70125f2c006b402eae4629efa69aac7ba8e8dc04b67009da88f6d8dbf148874cf4733845895ae13fa21746aa899b138b30b034d5e733380f66301dd129e030d43197c1b7f373d126
+InA = c664383843e8befe514ab2bda15c5aad395931045b4b1c235b7bca75ad04216935f18f64dbf1d22c2e410c50e84468859fa80efbd78b1ab2cfcba7f235b471e5107e3337aa4de117333b3de593075f083a31f22e59964846dd454df9d992372561218a20d1f59a6628c65bf060d7a6956e0bc2e679c6b85b44ee1b07a13faedcde44724d4c98ef58516be8346ea4422008e96d68225fc9e0eebd5d8e149956cd1660c5eaab33387c6c17774073e9516009a007de75172991609901deb2808a3b93a15cae615e19852ab9a8fc415ce6f2ed203fc1f785ef6e77739d44eab1720ada4a7ad43cd96b99ad29b15c80b42f0566315841035e246e6b2358372c5257a4b97c3bf6dce693cf5c3f8acf468ac9ee2903a075eb829d9506e0b21504699f7cd7dbd72cbe0a36cc7e6b47f28a00e5e2a848bd95bbcaa9e14f9a72cc9edd253a61419e24dda294fe0de54df1fb14227b73d7cefad3bcbbcd41e74199797eab8089e7e56990f86eed4a3c8c7f39df1a70aaee6fd429d39854286e52d1bd8a0c2a8403ea58b010f0a175d0a974365a2558446b3522186cc2e0ff1b604caf2b211eb080f507ded619594de87d7f2655a2ea918dc384394a362a5a985c6bb935c14100acca189e84494ba27373ab1e955b228122807d78f1cb4a44b64459c90921308a448a83e14556129464459e9204cb2a90e3295833701d0bb6e700d9b3ed30f9599a31d6e00d871bfdf7e3e5a4e2a4317b233e4cded198074395092d9c9c513fd295e71cf4e0e85e2989eb4a31c752b5791c66842db51e4e8e150b23ad4c5724bff7a4f9061e5ae5c91a69615aa36fe6eb044b374fd2b88d5a532c608c8aacb091d08cea8a67a9028e620d7b41047d7a88d07b39050aaa67703101a492be1cc1f16224a91c9ce75b5e48ac5389aec2c7fd44b3521656a38e849b52d7c1dbd9138f868f78cb405c830a00a60f0e6a814efd8599726fe913b7b4fb36b2a94eacb7d938a1212d5f2aca551a2166f32ae45c2933ed945476014151448f649eca8b1b2b07c181e9153f4d7c78eea1b4ee00c4316fd073a1c9da8bbc2876f256e3d2218a180b2efc04fdfe61d2c417093e483bb0535a6892d52515ddbdeab4544b8b45e945650873f24025a6a65c3fc2202a244c695acd60f555f8b5ba196336daafd899ea09f1a8df918277889118383c12e5a8dda938ba5d0214148a16daaf196b6f12a20d17a6d1b57882b4437d9f0099cc483e731fabd2151e4febef2d55bb881f271a343306345096e8c4658a583cf2682d41ea924504ad0069c1764a5fc2c959a14d93ecadc18635e476b7d639d2bb008fb1e05ab6e454a30143f859f43477e7cc6253df152e2fa42958d67446dc9843c42e294b6196eb17c928811c0f686902d52cc24652e43344a6da135f6b2df84b4a802f703965274f8d5566469d9a146a65978d1d453f581881a52680f3eb9a89677563082bbd312bf53a569dc5c6f1c13279de627120fe804f6305a897fe479b1a5729836db61c9bf9c3cc96b9eb52a4836ce0608be6be33f1d2355bd45be2449d10e4012e3a92e420531056ea532039f8ca2daad8d0051d5b201b262db64e0c60901ae91d22126ce3390692a61b6e13d9a4b6ec44019a08e9241ca5e0d261baa092161eb58fed33f94e91a2bc18b7d1dfddc122de3c8d93bd6619945987c8af349714109a65b3a0f9a946b8843b1677d867aa8c5b38a1324d4a5cffb8d98e94e4d837b16c0a823f04ea17d4f470f7c46cb49d01ba23e66f966f111a525e662a0b69818801b8c4c7398f21954168551580766d4882b0f6586f4ace742d2c07b96dba61dfc8763aac92289e84afb1ae4afa784204e82f2c2461bc073da91c3615ca970f195e37b9e5a11143e1317336b320d349b6402979cc6fa1984a843cbf1435a519ca957fcf45658ddaaa8fc130e1bd3ebe5c8b4164fe6a0b76d6e3f252d170889572babe5085a68fb42bfbf45a9419372a7e926fc604faab4ce138d34a1e6438c649ad282d4077ed990b911656c6192cad9a079764f995179eb3225fc67fa71b008aa1a4821a991133497e28cfe02ca4a87cb087c412a8998d22fb4e807bb51ebfab53a6c9a6602e9cc54f1a8f9c53ef95c5f0879256b1d6fe2aacfd488943a49135d49fc54fd326e5963ccc451583030dadf30086128bee2b74902c58d9c0b4a10bce90a3848b75d4751038dd3ae5827f95a83476e060f38779d151a8deb0517b6a526415447b48f66ce28615a5e3c10f971397375a7c0ac5264266f4b930c34faba354d29f795c9aca392413586218e567d9bdb95209c94322a1d96c9a628f9e97abaaf6332e4e61ed0d904b119086ed021401be72abd6c460d50dd2a7d29ab890528d31070b7d781f2a6912074bd1fde427f60faab61b263c2d52cf6a4092b66e9080617554aeda564da0f5c9586c987541ec2551a7ca0d512bee052be4fef66f750b7c9bda78350ca4812394545041af7d550d7142e579db6d954489301dc4cd9b405f685d69470c325c490b
+InNoiseSP = bf801ef9346a2d2160cff456a246c4c10e277bca9ded456ed94a385883620cd8f78430cf918cf9706c333cad91fbe1c05d81a06ac855224d03a613c2f1512478dc66c53b8a049a12cbe518224bfed226643c21155a5f28d9d97d78e70b0cc0af0622b3e8889bd8093442237a74f4dc1877a56594fdf081326fc3ab5b6a8fd0441f9331b64ed648688641198f2c84d16886c45f8856b5b04a245aff2a2e45cc095d9e24ca9922a6a4a28b507793dc8b7b84ebe0626eaec7e2f0c6a5c547e7938925cd1d373ea9979a3d2236a8e13ebb91d481955697157c76a2644081f7e96e587224ddd09fad2c3349ea6a6406155aa5425a88ce6199c78ac65e6a7d1a093ef0b27003e69df3a7094149cf4aeeb6e836b55a170437506a63090deb09cb4090252caf5701350c62eef2a4283287c644227903ee9626262da3ba6a35be090868fe580081de6a470458004e663d00169d71fd4b8ec0d6c603a094ec4524941f36027494310d5a585d30845dc22b0993b8b0fbea878d5e007343e980341c70d0f2553f0e2358d64872a9b91af5109c080fa05304406571856be3ec83d0181b030b7be53d869c1065156a10c5a4fc9bd07b63400dbb0c8568b5d84139e597060ce99f8962f356123e398e819d2881309a28a94faaf8caa79666a9943eb912b1473988a91564d79bb704006e2269201b68f91c00b3816d427b524e8d882da57b4193a954aca5c88438b82e575513700883c57cc5ce78b7bcddfed635718e1cd5b02545c532802054886d486ffddec2930110042a27420a0cce66d1dffaa1f7e47c0f53d3f4c8fe469410ea2831d9131f0049fb88d5016a691273eb9c9784e8ce08b23155b7c2a230c5e5a33f6f31e3c291219b993d6822cd5b822c9f506cd6398708e68339c49fa61ecae19cce241190bd54b2092ea8476e9637447f812a8de17b6a0e94df0a97a9ca83206e08c9aa05076823aa5be46e24cb05bc6aa11eb09a633b295aaa47e862e642b98e917e4e7ab5734e3b8063632b933c362e52b3e64f0020338cdf36fe1a173094ea5ac75e2086082a5b315d8f559e30598430ac27e6ac51b854079a8bc06bb5582e2ce348f1041845376f23d8a7b55441aa8c898ca60ebf57c097acd405df4f34b08a7439a9518d31dc78bc1c53be8b20d53b686b94717cdd76dace26bb25424eae6d47e7ae558be4488fd0b348bf4e42c4756a129bb62db6d7b25949df425653bc59a691db2a8bdc4e291aca98316bce06b0df63a0a6ed93c69b7a1510486318ad3dea55f44a4595a268b87a2ed4cdb00543a4bb6614bf4a54450921d2a9c474a0263885554924f119d7030a899859473a441276de02b71dd1f07b407d90ad27280b3fad4203656b466f5832724903e7db4c3a794e43a4f4416f7a9bbec811aa0f798952a4bc484e65222ca76c1471d1a36261b7dca89e5ab26415d1952568826ace34067713c2d15d991c1a5639139319a11d5ff2b6eea8229d6134b23ca6acd2569ea467b58fb58694c247d901c76c76f0c11a4b131336fb8bed2440cdb7a18d145b74aca0441f2d3151d09692e02c3fe06ad9e3bca57f3407513207b4436b4ffc795e0da3e75d78e13b295efbe0776b61ce1e3b95d130f3720cbd024a829410528c8066450bf47fec2b4b8116e067800c7753741175994e957082b52ac2a0f1570955a85fc608906291013a20eb7449769e6b267dd5553e1344dd46a700b60b0316ac1a6dfa4dbb64c449e5fd5e3a093c2570da1d9e4163b9cbd249180046221cae2d365725d7e2a8330641a4d0b7fa2d696aeed0c95416b0a3a274958c43155f2110463da5da99abc19ba40338e59f530c220d2867b0f69d4e41d6c63324c88805bacf3b2ab38209045561b3a79098bd8ea1e6e16cae5fef9ff4202e01030f68c517f93cd6c8128b84b68d8f9b74d2594e649f59f727709db60d52b16100c0349d841958fc38019918de3896484befe67181cc6627eccb7ea18710463d240a555f7c6be493bd2592653a4e8cdc47c8302ea9cc908257cc874c28a550fac6618b92985258614f0eac9c9443929d58e6a165e5c8837fe43646933cb04c9efd0407c97a2baf9d71bd9c7a5b4504f22c728056216a54f19419d8e72555e378b8db136ee0502c07c4a15ea72b1862f7a40230cc9a69cb6a34e6fd727393e8a9a85d88540f16a6c3f36d9d2aa647c9c10c745feb0e638fca46cc650974b91585decb5cd983e222ce109852dba42bd5dcffc7fda94f80d9147598d864a7e26e920608069bdf963a377499e4869fb151d07a5c0c8f388f3aaf6447540b92f9606cc62fb0e5b457820b2ad2644e99ad937799a4dc584ddab30a2db62b0f9cde26a78a739e629d43c3cd4ede87418a2348a8c64413e800e9ba3c45fa2642b6bc824cda7b0ffc6053a7b878516286adc754d05cde3e6526973390e8346fdf4a74d64575726e1172c6a89210958819b5464a1f0b01a8adbc4243a4a3999cc9b750949e38d84870cd9c93f88b2d167ec185796a6e19d042da81fcc42d
+InNoiseEP = e09827a03ea2aae6aa6f42fc006f2f530c4820199d449c5316776d8d511421d603bd6b3ed5476500e481226b0ad6176a77811e346bd57cbbc404b4107239ac64ee63b5e89c53b8193bd9af8075b20d2fd49da9af0c01e908575e14f7144ad4454852812da1e5503897690469baee995969095e858096afdfd54fa4ec2aa9a21ac9a7ee4c1d0207932ac7104f61886b94a8e1617757f487e040976959afd026768a8d4d734adb3d35422363268fe98756a6fff5c29d3e8d434845de66a9b2692bfb19ba7d49c50f078c789bbae5ebc3dea9920d5fef37462a3d194b8f07ff186870047b5bc9ca9f658494db39ed5bfa820836789203615f0a61412e079ec76b671f9a79738944bb466d982101b296cf6e158d46432003a69ad89fd4c23f727fbc40fc62a69041b66b124a9f2978d451120ad11d1a81996bf2c8363ea0670244fee51c5218e800ac8838588979ca380c94698ba210dee9226f1fd49663bc422f646b04bd12b0d82cd212ad281c819f61a1cf1ca44e1508c8b67d9e6f2275879bbd2060c6f611cf952939561091109e2cc781723be2dc7a2c064429f4d6234596149466e02839043a7068f0aba01ee4b4d49da084402826de309a5313567b78e6041ec0ffab92ae74af93a260bf824b6da2f560a36842d92979469e2c660b4298b86b264fb18165f36eb60f95a036e1c7ae93028b90f49ec00fccc3de4678c25558d14238a9dea4e4498af7ba82785756a5610f4c920f1a5235e4c00b635ac80567216d444683d214a597e59bc7e4827514a62fc30b18c97f325a04208d059c2f1283f3273cb2bda28f666cf009ecad95b3d76d6ab0acbc3a1fd8bc5a8bfd87829e21000ec3564379710e6d6c0bde5e7c89d977e6fc393323d1a2db32d68866c4e5545bb6463f9c47528de934ecd18995562e6a5f50649b5b1473225d87ab7e16bbb0c6e149611213269272c9f0f2a7681776da3c0e6a1285bd43d930ba9e9f77e7601a16185895fa9df01937c11ab210b222c288d994d2f23a681ec270f41110648e46b414ec9ea62fe3ba0969796e9122d34d8099c06991a444720ca3ef7fb034c452fb6fe520954d5d806705e84b706ba685f4e0d199af682220b3b5ca72d322b55371e4b17185b5b5abe913cf2521f90cc548acde5c39efbd428362bde206a44b46a9ac756f2e00954ec212098e8bfdcdcea08d393532220c4899a9631b815bfb94da8dce69ffb02ef4b4a61840c771dab530d479f6730e2a94cc52f12d9caddce3eb48eca0555628b6320ead812ddd4e28845d755169ba0548289780533fa6e8cc4396570af40e412f36930ea994e8b459c78be17a7caa4454dc5097fe6ee1e66587337240710e1d6058a4147de4a9e122e5ad84d7741a700472b6025d5911c28cb30989024b88a379193123fe25041edc933072c17da306d911c34ea31b485a85b62c9ccb948695c3795a35d50af9a926465212e76332104a04c468264ad679e6cb7924bd421eeb8c034987916696d5b345e69e24e59f9645a016039dc13f97be926f1b4ed25a5d4489ddce30f77df143846e6b66f2a2843b6f28d466a8026fa70db095095f1862c6a3042561a6671a16bbd6bd0e9651227d502ea5cf014a52fc6e22a0fe7af8b075d94cb5611aaeb97b6a51f42b782ff661d6646db15cdca511e2dfb0b76ba0acb77f209d42e1ace29b4eb1bd98b3d98b9c44c903261b480815ce0f4db8c7f0306adeeec79ebe4b331e3a116a91b8d6d26738c9d2b8864338b9837e536153fc482f958a208f4dd05c8ebe9d802434441a474acdb437a00d644e2509d6a00a23d4d259fb4ba220cc61506007285ec30ffb13465558ef8f1d24b62d317060ef05dc3e89efca5de506fd614dc4fe4593e5816ed4cf21e49a5892230b6b292673440c46f245066ec205b3e8528daa705939919d721537e330dbcdf5b2c347b6018c3a540258bbd781e134e10ece44e92d563faf542826b55f45d4b417254cba552b4e59d0a61ae12d8044e785268d6e9020c1095ce501e4370be80d2f92a274bbdd3d5459396a0c6815896cfc93bd3a55610882424c5632a722b6f4b26a2dde918ca20e385f4a27c2d97e75a6d752944a3598bba362f88b213e95cd08b412fd8c505956a8b1a37a0b99147534ffbe2a63a52d6234103af39081e72f1a113c8b4bdb36a0717600284b189237abe7b5145315329262fe596019be860182da0516575ae68a845d85a698ae584a5c846cf826c8a90fb20e74174592861c3a22a9c0873e3c6e4da84720fe0d537edc72cad841286fc21a43005c943fe6bec35484813bdc88455f7102869adb43195c9ee995d267a8ed58081d0a50f8746f6e0c3349427a1be61ab060c3d47a9a6d192036c10d0c538fe0268474f18550e41fad727a9b4b0016ed4f3ee04d02f4cd1d3f934c7b590566e7e849f37d329b7f5dd3abbd1a9dec5c90b415545ee1123693694438c46564a02082533c22c594191d04469b21c7316a9913893a861f2d4ff009fae3c2968ff8c82214d2ba4f
+InNoiseEPP = 024000700000c00300ff7b00f8bf003001b0ff0a00feefff2b0004000100000000ffbf04c0ffebff16000300010000fbbffcefff5b00fcbf01400000000400038000c0fff6bffeefff1b000c00fdaf00000008000000ff2b00f8bffd2fff2b0000000200000c00f0bf00c0ff4b0000c004400020000400feaffe1b00fcbfff2f001c00f8bfffaf00c0fffabf0040ff0b00ffbfff6fff0b0003000140ff6b000c0000b000c0ff0600fe2f01f0ffeebfff6ffffbff0a000600ff3b00fcbfffaffe0b000000feafff2b000800fd6f00f0fff6bf0340003000140000c0fefbfff6bf007000100010000040ff4b00f0bffe2f013000f0bf03c00000000c00ffaf002000fcbfff2f00bcff0a00ffef004000fcbf0000004000f8bffeefffdbff0200ffaf00300000c00300002c002000004001a0fffebf000000000008000240ff2b00fcbf02c000d0ff0200fd2fff0b00f4bf028000100004000000000000ebbffeefff0b000800ffaf00b0ff0a00fdeffe2b00f4bf01c0ffcbfff6bf00b0feebff16000140ffbbff1200004000000000c0fe6fffbbff0a00003000ecff02c0048000600000c0050000b0fffabf02400100000c0000f0ff3b0004000340014000f4bf0080005000f4bf0180004000f4bf030000ccff1200007000f0fffebffb2f00b0ff0a00fcef00e0fffebf000000e0ff0a00018000b0ff02c00030ff0b0004000080ffebff0600fdefff0b0000c0fe2f010000f0bf0440001000f4bffc6f001000180001000010000000fc2f00000008000040ffebff0a00ff6fff4b00f8bf00800010000c00003000f0fffebf000001000004000030001000f0bffdefff1b00fcbffaafff2b00fcbf00b000a0fff6bf0040ffebff0600028000100000c0fdeffe1b00e8bf000000ecff02c007c00000000400fe2f00fcfffebf00b0001000f4bf00f0ff0b000b0005c000000017000740003000fcbf00f0ff0b00f0bf04c0ff1b000c00010002f0ff020003400000000400ffaf0010001400ff2f01d0ff0e0004400010000000fe2f01500000000200000000f8bfff2f001c00100002c0ff0b001b00008000e0ff0e00ff2f02f0ff02c00030001c0000c00400000000fcbf0480000000f8bfffef0020001000024000e0ff020003c0ff3b00fcbf0030004000080000b0ffebfff6bf010000000007000400002000fcbf04c00010000800030000b0ff06000480ff2b000c00fdaf00d0ff0600fdef003000040001c000f0ff0e00fd2f00b0fffebf078000300000000180ff2b0008000580ff0b001300ffaf00e0ff02c0000000e0ff0a00fd2f0010001800fcef004000f0bf00c0fe1b000c000180006000fcbf0200000c00fbbffe6f010000fcbf0200002000fcbfffefff2b0000c002000000000700feef002000fcbf010000200008000100003000000003c000000017000380ff0b000800faefff0b000b000140ff0b0013000380ff0b00fbbf078000200004000180003000000005c0ff0b00ffbf030000ccff0200024000d0ff02c000b0fffbff0a000040003000fcbfffafff0b0003000280ff1b00f8bfffefff4b00040004400000001f00ffaf00f0ff02c00100000000f7bf018000f0ff0e00ff2f00fcff06000200005c000000fd6fff5b00f8bffc2f00e0fff6bffcaffe4b0000c00030001c000c00fdaf001000fcbf0180fe0b000000ffaf001000f8bf0200000c000400feefffebff0600fbefff4b000400ff6f0020000000010000ecfffebf0080ff0b00f3bf01000000001400fd2f00e0ffeebffdefff1b00000001400030001000fe2f00100000c002800020000c0000f000700004000240004000f4bf01c000100000000030000c00070001c0ff0b00ffbf010000fcff0600ffefff5b000000ff6f00000007000100002000f8bffeefffdbff1a00034000100000c000c0001000fcbf0030000c00fcbffe6f00f0ff02c00030001c00fcbf0000010000170000c0ff0b00ffbf0180ff3b000000ff2f000000ffbf0000000c00f0bffcef00e0fff6bf0380ffdbfffabffe2f006c001400014000000000c00040ff0b000c0000c0ff0b0000c0018000000000c0fcef004000fcbf030000f0ff0a0001800040000000ffaf0030001000fe6f00400000c000c000400000c00180000000070000800000001300fe2f010000e8bf024001300008000240ff3b00f8bf0040000000fbbffb2f010000f8bf0030001000f8bfff6f002000f0bf03000010000000fdaf00000000c0feafff5b0000c005c0ff0b0003c001400060000800ffef00000008000100004c0000000000003c000800fdaf001000fcbfff6fff1b000c00010000100000c0030000bcff0e00030000d0ff0600003000fcff1a00003000100000c000800000000000fd2f00e0ff0200ff6f001000f8bf0400011000f0bf0030010000f0bf03c000f0ff02c00080ff1b000c00ff2f003c00fcbffe2f00e0ff0a00007000f0ff0e00feaf002000000000b00030000000ff2f00300000c0
+InRand = ef9e8c91a774589ed24f16603ee706cf863ae430553ca47912e090bcc2dad2ad
+OutPK = 0868b7095909139920f60b50f0b56c14e0287116363521de40ce41b87cef52e34f4d15f1a4a7c4fe1681d3ea5094cd440f3c4749e928b212d8285b6545c60cb7ab1bcb591a8ad10f97c5f2c58d5ea8b5cb51fc4dbe14b6d12021b73581c697bac19d68129d09d10d310f4b09d4627544a06690161e7cb15da077898fe207225d4830c8657150a76bc1e9168b1fe0e929b77a7a91de7129b965a92f2d80c15f0074b4eaa8283bb5a7eda3c8a74a1aa396e629c02a8d98fe9fdd05f4a623d74e8211013241ae5f55a633aa65b6ed68c1fd41482262a856e75c75c81b7a271b191d47894d5987f86b23426b1368ae9c789cd298a6acb7cd4749f2a1fa3fa448db83e819976e6a9d99db028538a2234884d905099de876c108945c25780586319e1060d5f3986e00951017433599bd26cca7db8ec030bc1a565a59c61fc8a8c5f7ae087bab08c2e1222eac08d81ee84111153553abc5ae389bc9226e47854857395ed7920e8e01622ddf9393580a20877de6385c8d730ca612fe9889eae42067f97182dd2cd059b3f26c9d6384ea97603e01df8f172a5e2017956a81aae0272acbaed1efda1472a621f86c4e4133628293bdd603b20d64f251b649ff12766550a64377dc90c40d7c062d636550da144730060d4b185a1a75057cf6f2b159739306a20b6a5e4714ebb86248037216eeb3d1ac0440667330a0690bf8eb84f0f5fc5f8c2fa71427a42a225ae873cf3142c19b0350677e7106e4e8f7b8da96eb533a2afb565a33161aa66725a12f44d62bf5e17545a330596a357b65e06c51dd7150dbe9d85503b29a10e367911dd139bb65b62221893255cb6ea73f7067e3965207313d91f7a582b8fd9c84fdcdadb4b9111ce100b604ed3d88b1a86ec23b9c197d07ec69e2dc30756c2d95ef3d2e508d2991739cb5dca7759a4b8605c46a83464d86310c5ef6a6a240086c82ee1a8b1da31dc455d81ab8456e0916e9bc2a2668c10795e7206f2fcfda97387944f3a7c0a0c9c174d5892e7876943753c56cf951c8b8d11d223ae1ba55e3816d04795a95d81d1e92d0b8761f1443a6f25c2444987ed832fe4278e0fb81de4e03106e0b806dcd93190d00b92c2ca924ed230a6b7d23ca1f8dd8590c49ef050486da624dd42b49214a3a60098f934894d54eee870f820ad11d78834813d6fa2b69928b85a83e625e8a20a166cd40d85d8866980987d7002919d5111b5904837013c5795e1b3520cfc82940dd3f00e6d4538323760376a85fe44bfd5022d15646aeda06ae162743ae5a083d6403a917d783ccf9295890940599bc2faac9a4d468f9a0c6db7973d09525639cf0c1ae048a3a869be9316248728f7fb1c630424ccd7668daac8be6977f04069c034fa3c96a40c424648a4da0b808bb499435c4b3215c98d18ecbe09e201b9d1f473882343407b56605da6a1ec1745b45f1829f49eb80be284e589ab8b3df8d26528d8095895497bfdd0eb01a2ea4c59fd7fb2fa426f08ce8c252fc4875c38f8744a4385fc96cb1d8fcaa8ad26e217a92903865f259b5cc3840a95ff889656d031793528b9a2a46d7c58654d13a29c8fd99e38e7e81c1a0e926f8695d806eb6ad3866efa02046f2b00bade0d913ab1a8916da87d03d8a0dbd17f7b9d7692c6c5aecca2f05ac90a62b15497147181e1b1018d222ed4347d03bbd6f39d4b0caacf938632499d7c759b7eb6882467c4ea23e67624652ac414f92ea63295590b34930bb2b36744b0f54f434b863ceea67c171fd539616fee3471059c3d39f96c2ca04c5111c1870628a296fe66222ce84a2e69950961ca42ea8731230091db6492aa244f27729dc11c188753581cc8b25577e908d450df494febabf66c3885a7a159198c1010d569d0a952d494b4c729209b52a7020b1b6e06a81d8c43e9b216cc6c4291a7ced1c77313c423321bc20192c632a5f84e8819abc37848638f58a132122420ab2885d8742bbe2ece1795b1e5cb9cfd627e89256231cf185504619759a3e9ed5047d5bdc1208aa617af35c84a1272f986b9afa2331825ae107fa394a9a243039162e44014ca8d3c65b660cd51a73b4b217e97569b87836ba41d3da04b09f6e45ffa211122f266d43e8a0a66e41e1dd0082458261891d538094640080f9c60612a251d46cba88b8438ccc4228b6622ff81de322a3a20fb3d7179629a023d69c3a96cd5174818e037ab55e71bb1616e4412e5579d0dc941429a50c0fc37be6712a53e6010b5c8a94cc961604d05a847e8083703be17c0d133850c1f62ee765bd3ba64a0097223240a0dc7555d3db7274f65bc6a54b23477903f8a89d4a6ee534fb5af5783c381bb0a72ad76f25849b021d8871348d7d4fc9b61c68bc50c94e08562e165d4572482938656417d371568c6a3dca7007c26a5ef190e957df8e93f56c6be4da00b7a2e675a8a0094855188ae3ddee2bfb821673b389b8b32cfd83d88c986ae7e6f5f5b23e2dd62fc743e2063e8d3051862a54ef89ed823fdd14fbe3fce7182c27d90f981035d15f
+OutRec = 01c00020000c0002c00000000c0001800010000c0001800010000400010000000008000180000000080002800030000c0003000020000400024000200008000140002000000000c0001000040001c000000000000380001000040000800000000c0002800000000c00014000100000000380002000000003400020000000024000200008000200000000000001000030000c0000c00010000400018000000008000000000000040001c0002000040003000020000000000000100008000280001000040000800010000c000180000000040003400020000400024000200008000340000000000003c00030000800010000000004000200001000080003000000000c00008000000004000140003000080001400030000c000100001000000002000030000c0002000000000400014000300000000180003000040001c000300008000380003000080000c0001000000002c00030000c000040002000080001800000000c00028000000008000000000000000000400000000c000100000000000001400010000c0003c00000000400010000100000000240000000040000c00020000c0000c00000000c0000c0002000080003000010000800034000300008000040002000000000000010000c0001c000200000000380000000080003800030000c0003c000000008000380002000080002800010000800018000300000000080001000000002c000000000000200000000080002c0001000080000000000000c00020000100004000200002000040002800030000c0000000000000c0000c00000000c0001c0000000080002c000200000000300003000040002c0002000000000c00030000c0000400010000000000000100004000100000000080003800000000400010000300008000080002000080000800020000c0001800010000c0001000010000c0003000000000c0002c000200008000380002000080000c000300008000280002000040002400030000400030000100004000180003000000002800000000c000300001000000001800030000c0003c000300008000240003000000002800010000c0002800030000c00024000100004000080000000040002c0000000000002800030000c0001800030000000000000200008000040002000080003c00000000c0000c0001000080002c00020000c0001000000000800034000300008000200000000000000c000300004000080001000000001c00020000c000340002000040003c00030000800038000100000000140001000040003800030000c00010000300000000300000000080003000030000c0003000030000c0000c00010000c000200000000080003800010000c000180002000000001000030000000020000000000000180002000000002800000000800028000200004000180001000000000c0003000000002c0001000000000000020000000010000300000000140001000040002400000000c000300001000080003c000100004000140003000080000000030000400024000300008000040001000000001c00030000400024000100008000140003000040003800030000c000200002000040001c0002000080001000030000c000000003000040002400010000800018000100000000380002000080001000020000c00008000000000000380002000000001c0000000080003c0001000000003c0003000000000000010000400038000000000000280002000080001c0000000080003800000000c00030000100000000080003000000000c00030000400014000300004000200001000040000800000000c0001000000000400000000000004000100000000040000000020000c0000400030000c0003800030000c0002c0000000080001c000300000000240002000080001c0000000000000000030000c00028000200000000200003000040003800020000c0003800030000800038000300004000140000000040000c00010000c0002400010000000020000300004000080002000000003c0003000000002000010000c0003000000000000018000000004000240000000000001000010000c000080000000000000c00010000c00014000100004000200000000040000c0000000080003c000200000000200001000000001400000000400028000000008000340001000080000000010000c000040003000040001800000000c0001c00020000c0000400000000c0001c00030000c000140001000040002400020000c00000000000004000180001000000002800000000c000080002000040003000030000c000280000000080000800030000c0003c0001000080002c0002000080000c0002000040000800000000400008000000000000300000000080000400030000c0001400010000000014000200004000340002000040000c0002000000000c0003000000002000000000800008000300004000100001000080000c0002000000003000000000c00
+Key = 3c763fff910725780ae666ae0d91de15edb5faca0b8c2e22c318014401f91cff
+
+InNoiseS = 8159e4d8f3901f0cec2355ebc6511fa4993a1576af5257b606f5b5317703e6b78b4053961048db1d4661b68e7bd70c8a00f758c257fbb81ed7cc2aba5fb098a4a0e8d5b5466ad209a639d99c0408eaef04895cae0cc75a18838a2d4517b927807d1e83ef9dd6f1cc1d42ca623b720581b804bee5b95ea47f8a7440db5073166fc595b314a519c178bb37b14b7b18cbe4d68027c45acb6760ed815f035b7b108c4193e470611f2e413d50e7d0596537cfa86cb93c4400c8240978a9d2325f0d30776de50e351662f2d97c8878468dfa5555618c0e25e237fe268658069153d90ee7552296b0853f2e2787853e2a72accf3dda02b203bca258b231b8b60f5fc0aa02b5680b15d6122e8d8bf5a7c474fb867d4f9840a47a198ba81e0d20b55692c528f0d296aa6ddb0a0e868fe41c00c01ba21900740a9cb3469e0948774fd769215a2b8ce940f37ed2b3e989c1883c548a220b88020dad389e55175989f916e62edf3bfdb9569ba33f8242a19e1c58141966be01e50c9514179644bfe6e2b0352d6d17eb637a498a5fb0d57181eb5400260ca0737e59038053a543cec243ee1da72263a0bd3669d4198b62855aaa315a7254603326e4a209116ba66bf9e7abfd34619adbf4086528fb24ab9780e54690695646eacdbb7e2f111782e11001464c22e74e52ddcba7a653bc822f6aec2ac0b694c9809d21de4e404e086cb67e7164b5018d29c3f64da96c1e7291949028ee6d279fa4314b26dc4515f95cd8436dc61a1c0dd429fe3652c8048c09392999b93b96de1be819e833d40b9f20440132d94b2cd13789473b5b87b41c75a3a5da6d8880013d8246ead4983d33c21e1ca7a6ac45e60c0e536ccd348821ce5bf59829bbc8a6357b5839cbe6d9a47bae4bec2963a023766b7d835f21d25c0bcf43b064400969a5ec08a50d245954e8c433bfc06347df623aaf988b17680fe0709012dbe9f3a071f92919de80f6825284a35929619732367a166b065ec83f9fe53510c0b84714db410b391ea1851d1313af396d8112b1c608300123d8d1c47df0bae78f97ca03f988d3ef3697aa76a11ba72e013d316a83edce235e680d8da0e6009dd019f6652ee8111419ed60586a116a637c9d2fb8ddea48384945337cc9720b63f6f7af590e4410d7a6be0c4bdce16776e0385ae3536a81104920c449298a8a0269c2d731a1b561a4e302358445cd1647abb5e54f96b07982e60a5d6200b9070949e6f974771cb9e3080d4bec507e3b462e8fe72228656201828f98d31b736e6dd0de704501dd3e069e7a070ae89c2e66ffbaae926426ae8d507f469b348f0996fa70274a90aeeb22ae51f11365123d7aa93ba0f309ea161f66cad5ca3795563fdcd0717d8650cfcf49821f5a600444b067f7d9a9619f2da086d1877dea143a77097e6999612155e9544a4c88a682e5014a8086c18a6e88942bc38254ca4c3021641b434623a046138b9166039e46e52bc2654f52cc367917fcaa77c7ddf798e6930f6cff97d8305c5f1323047f826279a115abf31470bb6868a4cc9a1f099246758a9801b769ccf145809e4b0d77abd4997d1bc88d90cd1a26ae6383fbd7d2aa3026ef860f9624ad092839b7d5753f1e266ac02614e1dc23052bf8171268aa8ae6c67105a38a08cfd93d7a0a35f5071104f7820632c760756ec263784676aaf708d6699fe09534dc1865cd11b1a58c190a20d93e33204475daa45f7c11e61900754ba3e93827fe2a2212a0f9839c22924ae69102f1ca4c1e1b8125df684cbd1839541b856d75825dd24a1a615810541348020f56952d89435c006d4aeb365ee11ac9a14709c8a894642265d03022243bcef2826f94227d02a1e6851c98c124162681a5113eddd24b3d889b58c0fe2a396a67b8a952b627c20ce5c0d8d66985261ad13b7658ad0b36ce4e24435809b928dc229dadbefccced1746a616d8d202037160442edde9e0f730542355d9cbe81433ef1e8714276dafb05671149c9a77e69195856e9e315820ab07cf35492a0b8009bb7c913ccf34ab5589ad0d6d7b6840b9673945ba16667a03cfcd70a70d14718c5b228566b54fa15fd1100a7e7406d72c6494e14643030d35a44d93325a07083cad85ac1f51d05542402eed5bf08e4e1046c3b4607ff864e4681581376db62ba977815e28203e066702c911593ead01d6ac4c4a69505e56ce6d59ae149631dcf19c2b0d8f05846a9a33901cf078fa35aa5d3f67d52649769daa605282581dd8f4c0f6156b2208841bd3c1573b42fab7c74db0aa0f4f5927e24765d83a307b644700704bc0bca665e1a8c240a9e4296d0873a6041d18f9633738402682fc23752931c611b3e526f2d43d95a346da7835e0662a68daf4de5e2c7561b1b9e2a836144be8841e157f62e22aa0293cb07183e0b9e4b6bfcf6b7baa91353264ad91795e2458125d441a4fb04ec0245282a18abbb39f6bd6c695b392d7ea22499eb22c5a795223191848d46f5691615b274ef72bf28d4226928947cbdcb02a0bd8e28ed45a
+InPK = 0868b7095909139920f60b50f0b56c14e0287116363521de40ce41b87cef52e34f4d15f1a4a7c4fe1681d3ea5094cd440f3c4749e928b212d8285b6545c60cb7ab1bcb591a8ad10f97c5f2c58d5ea8b5cb51fc4dbe14b6d12021b73581c697bac19d68129d09d10d310f4b09d4627544a06690161e7cb15da077898fe207225d4830c8657150a76bc1e9168b1fe0e929b77a7a91de7129b965a92f2d80c15f0074b4eaa8283bb5a7eda3c8a74a1aa396e629c02a8d98fe9fdd05f4a623d74e8211013241ae5f55a633aa65b6ed68c1fd41482262a856e75c75c81b7a271b191d47894d5987f86b23426b1368ae9c789cd298a6acb7cd4749f2a1fa3fa448db83e819976e6a9d99db028538a2234884d905099de876c108945c25780586319e1060d5f3986e00951017433599bd26cca7db8ec030bc1a565a59c61fc8a8c5f7ae087bab08c2e1222eac08d81ee84111153553abc5ae389bc9226e47854857395ed7920e8e01622ddf9393580a20877de6385c8d730ca612fe9889eae42067f97182dd2cd059b3f26c9d6384ea97603e01df8f172a5e2017956a81aae0272acbaed1efda1472a621f86c4e4133628293bdd603b20d64f251b649ff12766550a64377dc90c40d7c062d636550da144730060d4b185a1a75057cf6f2b159739306a20b6a5e4714ebb86248037216eeb3d1ac0440667330a0690bf8eb84f0f5fc5f8c2fa71427a42a225ae873cf3142c19b0350677e7106e4e8f7b8da96eb533a2afb565a33161aa66725a12f44d62bf5e17545a330596a357b65e06c51dd7150dbe9d85503b29a10e367911dd139bb65b62221893255cb6ea73f7067e3965207313d91f7a582b8fd9c84fdcdadb4b9111ce100b604ed3d88b1a86ec23b9c197d07ec69e2dc30756c2d95ef3d2e508d2991739cb5dca7759a4b8605c46a83464d86310c5ef6a6a240086c82ee1a8b1da31dc455d81ab8456e0916e9bc2a2668c10795e7206f2fcfda97387944f3a7c0a0c9c174d5892e7876943753c56cf951c8b8d11d223ae1ba55e3816d04795a95d81d1e92d0b8761f1443a6f25c2444987ed832fe4278e0fb81de4e03106e0b806dcd93190d00b92c2ca924ed230a6b7d23ca1f8dd8590c49ef050486da624dd42b49214a3a60098f934894d54eee870f820ad11d78834813d6fa2b69928b85a83e625e8a20a166cd40d85d8866980987d7002919d5111b5904837013c5795e1b3520cfc82940dd3f00e6d4538323760376a85fe44bfd5022d15646aeda06ae162743ae5a083d6403a917d783ccf9295890940599bc2faac9a4d468f9a0c6db7973d09525639cf0c1ae048a3a869be9316248728f7fb1c630424ccd7668daac8be6977f04069c034fa3c96a40c424648a4da0b808bb499435c4b3215c98d18ecbe09e201b9d1f473882343407b56605da6a1ec1745b45f1829f49eb80be284e589ab8b3df8d26528d8095895497bfdd0eb01a2ea4c59fd7fb2fa426f08ce8c252fc4875c38f8744a4385fc96cb1d8fcaa8ad26e217a92903865f259b5cc3840a95ff889656d031793528b9a2a46d7c58654d13a29c8fd99e38e7e81c1a0e926f8695d806eb6ad3866efa02046f2b00bade0d913ab1a8916da87d03d8a0dbd17f7b9d7692c6c5aecca2f05ac90a62b15497147181e1b1018d222ed4347d03bbd6f39d4b0caacf938632499d7c759b7eb6882467c4ea23e67624652ac414f92ea63295590b34930bb2b36744b0f54f434b863ceea67c171fd539616fee3471059c3d39f96c2ca04c5111c1870628a296fe66222ce84a2e69950961ca42ea8731230091db6492aa244f27729dc11c188753581cc8b25577e908d450df494febabf66c3885a7a159198c1010d569d0a952d494b4c729209b52a7020b1b6e06a81d8c43e9b216cc6c4291a7ced1c77313c423321bc20192c632a5f84e8819abc37848638f58a132122420ab2885d8742bbe2ece1795b1e5cb9cfd627e89256231cf185504619759a3e9ed5047d5bdc1208aa617af35c84a1272f986b9afa2331825ae107fa394a9a243039162e44014ca8d3c65b660cd51a73b4b217e97569b87836ba41d3da04b09f6e45ffa211122f266d43e8a0a66e41e1dd0082458261891d538094640080f9c60612a251d46cba88b8438ccc4228b6622ff81de322a3a20fb3d7179629a023d69c3a96cd5174818e037ab55e71bb1616e4412e5579d0dc941429a50c0fc37be6712a53e6010b5c8a94cc961604d05a847e8083703be17c0d133850c1f62ee765bd3ba64a0097223240a0dc7555d3db7274f65bc6a54b23477903f8a89d4a6ee534fb5af5783c381bb0a72ad76f25849b021d8871348d7d4fc9b61c68bc50c94e08562e165d4572482938656417d371568c6a3dca7007c26a5ef190e957df8e93f56c6be4da00b7a2e675a8a0094855188ae3ddee2bfb821673b389b8b32cfd83d88c986ae7e6f5f5b23e2dd62fc743e2063e8d3051862a54ef89ed823fdd14fbe3fce7182c27d90f981035d15f
+InRec = 01c00020000c0002c00000000c0001800010000c0001800010000400010000000008000180000000080002800030000c0003000020000400024000200008000140002000000000c0001000040001c000000000000380001000040000800000000c0002800000000c00014000100000000380002000000003400020000000024000200008000200000000000001000030000c0000c00010000400018000000008000000000000040001c0002000040003000020000000000000100008000280001000040000800010000c000180000000040003400020000400024000200008000340000000000003c00030000800010000000004000200001000080003000000000c00008000000004000140003000080001400030000c000100001000000002000030000c0002000000000400014000300000000180003000040001c000300008000380003000080000c0001000000002c00030000c000040002000080001800000000c00028000000008000000000000000000400000000c000100000000000001400010000c0003c00000000400010000100000000240000000040000c00020000c0000c00000000c0000c0002000080003000010000800034000300008000040002000000000000010000c0001c000200000000380000000080003800030000c0003c000000008000380002000080002800010000800018000300000000080001000000002c000000000000200000000080002c0001000080000000000000c00020000100004000200002000040002800030000c0000000000000c0000c00000000c0001c0000000080002c000200000000300003000040002c0002000000000c00030000c0000400010000000000000100004000100000000080003800000000400010000300008000080002000080000800020000c0001800010000c0001000010000c0003000000000c0002c000200008000380002000080000c000300008000280002000040002400030000400030000100004000180003000000002800000000c000300001000000001800030000c0003c000300008000240003000000002800010000c0002800030000c00024000100004000080000000040002c0000000000002800030000c0001800030000000000000200008000040002000080003c00000000c0000c0001000080002c00020000c0001000000000800034000300008000200000000000000c000300004000080001000000001c00020000c000340002000040003c00030000800038000100000000140001000040003800030000c00010000300000000300000000080003000030000c0003000030000c0000c00010000c000200000000080003800010000c000180002000000001000030000000020000000000000180002000000002800000000800028000200004000180001000000000c0003000000002c0001000000000000020000000010000300000000140001000040002400000000c000300001000080003c000100004000140003000080000000030000400024000300008000040001000000001c00030000400024000100008000140003000040003800030000c000200002000040001c0002000080001000030000c000000003000040002400010000800018000100000000380002000080001000020000c00008000000000000380002000000001c0000000080003c0001000000003c0003000000000000010000400038000000000000280002000080001c0000000080003800000000c00030000100000000080003000000000c00030000400014000300004000200001000040000800000000c0001000000000400000000000004000100000000040000000020000c0000400030000c0003800030000c0002c0000000080001c000300000000240002000080001c0000000000000000030000c00028000200000000200003000040003800020000c0003800030000800038000300004000140000000040000c00010000c0002400010000000020000300004000080002000000003c0003000000002000010000c0003000000000000018000000004000240000000000001000010000c000080000000000000c00010000c00014000100004000200000000040000c0000000080003c000200000000200001000000001400000000400028000000008000340001000080000000010000c000040003000040001800000000c0001c00020000c0000400000000c0001c00030000c000140001000040002400020000c00000000000004000180001000000002800000000c000080002000040003000030000c000280000000080000800030000c0003c0001000080002c0002000080000c0002000040000800000000400008000000000000300000000080000400030000c0001400010000000014000200004000340002000040000c0002000000000c0003000000002000000000800008000300004000100001000080000c0002000000003000000000c00
+Key = 3c763fff910725780ae666ae0d91de15edb5faca0b8c2e22c318014401f91cff
+
+InRandA = 8f0774d3d5350bd8a9f1567b6408f044018892f845055d532885b240f813fb98007cb69e66716bc3e67f69d0331b21c613b367dc3263689b62a8b38b02846af41cfd8633f41b89aa2a7353c587b0d6b38a4ae8ad3ae2b279f340239296bea34b2d6a7048e1e38f98a6f3087ec2e24d9ff11a21e1f7b0a01e00e6b1a85c8e9c9fd986177153f76cc8b317ad0df744cf8498f01b7284038a91106217e511a0cf20ae7c5203e0ef196a552877585ad94c3b277e8b5edda7e2cef1455a066e09ef92365f19bc4c86044486498f6f4783667f72431283644708d03b534dda98dcae6692404fd49cad29b10115790de190f7eba815d93265deaf17f7d14651f8962e28394cae148d86181f7a81a941d1161198ab9d0fafa01525a043d6def1321ead41007fcafbd1243a1629d31e06776b1ba67a1bce2cd4cab1062b59877fda306afa8103adc95780c7f44b1b25ad03ff3d669d2ed2c42b46bb739ec5920d3e1f046469bb5c8d178c6caa73b82857ea5934fb87fa994c08a88291c2937129ade1e8f1a40899df5952ccbb2506b9e57796a26e999e2bdc966ec2aa89c4b8a85c15493a198472a857602f16cca5189ba0a303c6163a63d0ab94634512172c8d56a7917644937ab8a3a889f113a9738beea09f8fb2581e410689a626d38b2a3747d6873748b0a21040c8942e0e289f42dd812c298a23a5e7724f3d33cd619b82830e411d10fb9474dd95162587ab0d81a28d698e1a79e50b624f236b713a703bc46ff245387dab0a6bb77b0e0e885e7851aeac70e84b6d4a2e24bb6f9900d803d513b3ece9da5d495a18d09f61c3b50876967213f2cd4784044e5bdb3544fbacb01242e86ab0e4407bedd1ba31de696414b8a03ed07e227282602f9175a73e3698d696b54616b46b7caa419b870487f2e0869bb311398fd548897aba4a8a04f8d9b0152fb414c9a8333a48e1d7a19a7c864df42dde180148441b274beaeab25cd7cdaa5b3e369e0c16d1c8f20e2b8e5b1e70298e98651dd965a7a858a31f87c4da9a6c1dc20e025ad45f1f6b6372d99866b700d047d845b4b40563d039463bdd4e3e3150ec4aee0646b635aebf064ca1e9e7ee2483e46028a316989adf7483c160a08dafbec43aec6da81950a057fa20eb8046b9cccdb42c5e1938e7766c6f653948d1102cb399c5856fd91e1f667b27d205378f1aac0b83356cef589e5282300d8becfb547c7c297eef0c97335e1bc08869b78d46b6771f060b99b837dbee82b874a871cfe16937a4f07ed01815d7aec5664e13e755bd2c3df61f43f7c2b26e6610f5a9cc44a84c21015a06b0a72c22c68aa4493ea6d62f6258ad8e5ae1effa32c87f49431fd34c76995f85bccaa0e091231bafe3b614a0a881b1cb959427dbd3afcb9e4294c6e35d67902a908c1c42936aa258ca60953a9f4928f0820ac9f00d3c72c07bc11fc0954c0a72abbc3962a287da87ac994c1acd4aba4eda401c232c3a125814af2e2e031699bc0d600fa651f2484b1d7db75e22089492c574536e774a15c8fbb8d59164cda93b4066448da3fabbb7f52b8d6536cbea0474d6987f05c9e0296420c50a33ea26be27dc309b9201d5aa518586f58139136d7084585a3b2dc3c6b9895a0f5e468a4b00b0b52d98c147c641a2a334e45abc4289cc7f572324ba5be314e3e655b7a6ce63eb6ae217fb6f67cbb308350e91c48a88eaac9b24e8b35c05566d0e4cb2c1965b6a14593a1d245295aef119a57549fc4e86086badb512ac46d93ad0984fab1e8112a44a60a16e7051e00c630bf79042ad61a45147b1d7a531aa1c9c9bcd708ca12273daae848d990ecc46c228ad162e69302db52a008aea235a10af962b6b052c683b0d814fc74d4807076b8a0050789fa7569604a34d20b4e67aa5e6956e018b6e8696fe28f9649aa210a54d9c8c7c92b2be83a514a1a6f4e03bc721b180099cb14ccd66e812f97205a7310867f5348e6841309e8a7c2bc8fda8e336589d900813046aa96513a35086bd04745b4390ec2c7d981cf752df3578954751dab2265820ece73745903bb681cbe68f52a9f4cc7c30fab8380094df1296a1af88296b55b2a9b90dcf6a0aa8525f005706908b119727004570fb446a5a634ee44cd28e39cb53f707c9992baa7437f74d938e280a0bf29a40080da8d4798141d6a79c33d83e9b6fa01286d3920a1f5450b1c46241370533b1c5701e4f6a4ad720b208d7e567badc725c1e1364b597f03c4ddc1cc33d251d99a69ed744e04e5a2b8471c0a892fb67e0f75368b35f59c6aa6e9557f15b2cf78120a8575ffde653c968949254113406b4e5220833200c81c3013cea24983bffdeecb0f294041de340975c329b3dc9bda0a9562e436efc1b6c707c522a23c99e602bf103a01b5ea4029319f696a2919ab5c2c29a5caa59750c8ff424288e160cc02286f2ab68ac098ae8e59225c8b3579880486cab2da4e87d10348f5d97bdf20b791b60fb43d06bd88c3153c17819feef2c19df7d2cfbd4b74adcc61c370a16fa1521a2
+InNoiseS = ad9613f7d3f429e39015b40b84b0b0913ec1c4208c24d4573b1e0e5cafc5c2e3304c02271d1271721028f125e6974c6682ea15cea2cbe61cd1c03c601a708e42401ffa6cdd6bdfc925b9e520914a5902162f2db0a42b389894122e95cb5b12393642bee7c43bcd394449a938e73625985fdd9897355e13a453e073ad38438fe88738627c7ca3d39137a8e996630b1644a01c0cc5ad8c7ba79da067693c0080bdbdfdae94a5622587c4635fe319f439c7805e194b785fb65e1ce58d446e131206b025d98e60d10a1afd716e79103863382943964362c19c48a3aed93dc2aedaa4945a3d47a07ab585c3b7e377edaaaf8e4552ec3cb049c66ce1a7d9157dd552a63008a3ea6ff2026505788d18bc0152181b7b52489864aa4306eece17e366a9a822ad131059258665298515f1b8b691e490c9190ae668b2e6aaae8633a9f4b1d1a1015009c041b50e55d0d3d19066108e58c3ba80a67213c851687b6494a5235c7810718aafd10b7295810284592327f2b37ab9cd89eb80b3a81130e3a604796d95b3eede92df111d7264d21483851394002743f9fe13555f35250499421f189a1b35a92a2d2eec18e03183042e9ee7eaa15b9c11f17b4009a33960f9d628a225ab1c2557f8dca1dec00f82f80437c10a09f04fc52d3b8f95c19d86603bd6be368d427f274d3946d0221240cf76f4c4bc86b963f1e72fdeaa7eda6a382b41ba210eec4bd0a48b509dae0455a4381e6ec80226920a7fc67649fe4017b26407624bfa60da5c47559f248793eb4dd1216665201762d3b64c4782cf1175ff2eab9c6868b764d27a8f29e882beee78db130563114a1c8d91f125748ea0cfe56361aaa55b8d45a507754d332b8e9c252728b103aa48c1d5243c8e9e9a9879564f61cc2bb8cb3cbec982167859524f78cb374bb95056505acd22f0cd2890162931d4a200ba1e8490bbae0b521ff93bbaad8ed3ae62d7246205f92f8a7180492c398f76674a1a77d4278ee4117c11f001b016dc057c4d8665e7b4608e7726c727356e550a6974a4a0fa77b6677a40ff5683712a24d066d00ec14b2f926ea6b0b01b16f21a28b1ac2bdd05f4c162cfc844fb3ee4a4125e84e0876a77ee05457931550cc6c96673cf9d4526959719170815bbacdc97bd629924ea99731238be3f1c27a6594182f1944af3235ca8ab8ca067a1c6628401b4cbd665457e01c5fb6fed88191b24aa65e08c4bad30e5f9a00857aaaa0092302090ce66cbe192089896a524074c4a4e007e8a466a741417d7fb4f6d85e5c656c9540075258e3e1a0b1483ab482ffab6be449be33d0369c637cc526ee663395e092051e278e6aafc2e70f707017e85ab8dfb292a0d20eab39a773a429cce65a7f236612f633d79032c88b58af02651a1a05166032a446457fc2c8a548a60af745b8d762a1118feed7308af00023ea521d4a78a1e4d44cd266aac096985cea3f490989413b3e9cc047cd2c1e7599a5e3e1f081c647185bd819a9d7764a991e0a04db7a375102c5201527c9d23b242ac5ba5022ce8afcc78fd3a722bdc69119158898e405e68724889d6ee56831c1a2f39e507949a998e9fc3f2640c861841ac7e5ab261b563922109416ea2c4e071b4a1e46bc6c87e03b4e58bce9d7cf40a78407e1f44076f8166dc809a933e219e084126c1acf8a8e14e570383a454d0043c46b5e940540ff1f9de329321dcf7b179ca7adbc33693dab233d5d809332a5047839e50b1f20540d3d4a1908dfc64869937ab9b1a4bb21334826b449db24bc0a85a26183e870c39ce0e38372ca844aad89cec673713461468958b7e24fe3873670eea199eac685e9e64732e6070efe23ab892ce3e8b2053f0c1edbe5a46b1d6d839818047b0f2ae2150b909a3e6cc818c9819e3a156980fc2aebb172ac57a8ced24854550532249d827e798a83916bb4271aa841c5e76b49be014651b59f151092193cce682e1ad237818746724819862494633a96217581bba6a8e1652829ff0c128111d5d5d6b5bdc707ccf09e479e561aede184ac631cc7f19de60babf183cd6e6e3d3a80cbb398c58a147767da3d5e500c956083ced0699a850aada1f7b558c86778d9bc21b02ed4f6beee8a6267244a0e87687713161195d94f6dbf55adb0eb95967880a94c358579d945c521f19f361d68818a8cdf01f0a0f4a125e96f3a984d68c8a8a43cc8bd9c64a1231de791e2754928c088a519921888d460d7c5548e7c9f88e360c8da46e7616865897aa4ef14eaceb7753103103c343358398a4530d8fc86a851999f4e49b30e365044eea61a4e47524198d0f9600d8b10155ee33da006469ab55782c46416195f2a153c264ff1d7dbbb72ca01c26d11aeaa642fedadaf88a7478acca65515ab881719c8200d8559e3a63b96155016b625cb61a09209ab89cb08b444da5e6990f466e286047a72b1073c67d9e5cef88ea2e2c3713f6b1c1bababb9a1f2698e814c6ef0f4bd8aa72a7daeb41364c77831f06720b34574dc550b6b44a3550613c51db1823
+InNoiseE = 9869ddb12180ad1e6aa807a9709803867f57b8a8b7c9d6b2e6d3218f739e565a4064af20a14ea9914a36065df3804c15440d150c66588d6f3ed35828220d005ad2d8e630645a79142b3209fcb6431ffaa1ae85b26d4567abb2b44a096fae483f10173203f31ac4ce5faf521674f1065690a40af86e351e15c2f1f3640c3755cc8bf520548b0ad6b345ea8e0103a46b44c6ae053a82f998ff7c05bd09221793f90ed50d2f7328146755ab9e5943ad8b8f5d59723bb9911cd0734b5bb472bd84b43941cc04715aad31caf56c6e984c13783406fde0d5e00f7c4f1613f882a8bc4c4a145997798994920d20a350fc121051811888e25cca1a1439126008c967985956f59a7f039e68a0363b60113a559de89bfb1e68962a3887de89489b7b6d528b057e707a3da71a5aac31c372afecc9ee8bfc927648147d204b2c824fa36861029e41c9646ee30fe93a1357063045f997d09fa28bec090783def063cead9366d44ed6861537c2da5e28cf0a34024e4201738cb751c8595708a918f0aa79d6276e98c1608e89cf4e9b9a829b49c2341cd0cc81686bc551cb17133ae5185baf1abc2b37fc7cd4ab8cf04d562e29a18355521e1f126c75b625123f180791b65d94bc5f4696e5c06d1e7a49be544dd95e16c978c1ccd63f8aad341ba5b940bde106f49efea1a3e9ee481d0a163bc8b844eeb55eb7ceaf3162686aaa68d1c76b5a461adcb26af2ec714302bde25f203a20068dc3efc8158bab930559e56d4b0ed4d2a5fa6d1d677e262b9164ba9859a97e157ddc190a504f123d56907218a641840b6f55c1fa998693c1412671520a22c02690f9790d2d6c6b67f5e984da48b6e1e91e7affe38a765bd079b4d67a10da7a08ada86166a9aea80e43687a96003de5da1d1bb0018b9712f7b8a2c4af88617f449b4e3ae01f9006ded20f1142afe80f5d4c184d5989c6e24efe182c3258717e0204cd2893e043ffd1d34b59a2445fe56334e7fcb7709de3a41180be7026ab7a08b10179841aba0d34abc35ba1c0edd03e4e857c3a33956d77536718f5124c74814d0bb625a45e52b72336118a0fa382b608a6afcf8c12a8f0ea51a49ba947abbe7b0bef4a729d85364341dc20b46c7a4463cf3a22a928316f5137becc5f33ca2adae99664da189817093d3f58e55f18ddea199ece4fe21c0d8fba94ed76773d2ce5816c60b2e6b5815be238f54d838aecb992ece036de9dc5e74d892fad970a04cf5452fcd9a0c879a8254da8eac188e52dd48e2f983aec7284223139a30a7673d43cb9df86632f1b49bb2d462c20170d0957d52ae1d1a9f1261293492cfca0b671251e1f7977c72c8304090c70a61d7b01e493caa8e112ee4132a26cfa64c8aafe82061916640a69024c8d0da42b5627f8219dc74c537545e9747a9dac3ba160067aec5e45338a2a3e2e8b70d34d9fc596b3183dca4f0ca786d1483e9e17c59ff7f6d42ce8a94c45178d120ba8f5aa458e875b4434f0755985931d5835084478a8a8ed0184b14c5416ee76edb8a6b1822972092118f8c4c371c7ae318023dc536246315ce18d5abf3eb09eed7187bef9396683baf8238a22d1173dc7f2dc7fcd8cab87749c0dbcd1996415ce4fb055b9422c7c75d91aec088865935d235b2b679965839c24d85930499d274175e7954ccb6a69056714088798a2fbe6968ac3676433f50daef6d3ad46f3395d5d89ae455f0d36445b9577f40a9f26417812fdb80d10e1868b4d82225eaefb00081e3bd7d93019af46741b48c6ea1fa056fea89f43339580bc231db095a690e6c3823822d902df97603bcbec34da2e26b2426141ce1db0b9b8b4144a9244151d154683e9f222750e8049537c5262806ba0c41ac836bc13ed6b9c5350da5645994683a81a2fa4a18058d8a60a088cc8134b2809350650945d6478ad641a74db4e7f35ee0b0babd4247dd2b54a24d14a192cadcb898aa9d15672f9815609d2edb5f569b6295e6f17c0dd78bfe54538b7914a5f97ea71da80629311093499c4598d086d4c3471ae0f7d25bbd124653aea4c9be210a025db8d3753691502b0ea01e438b6aa041fc58a0c3c9d5c9819724e61b90cc74804be187555a59ae633e297ff507e96f96ca4c0421cc6b27454ad22859729dc7f4dc47fd132aa75b0d614a0defa674952c0308ad6b3479807f5afbc39ed451ee2b611441d4565a2b25cadd64e950552464775891e57db8842f9cc4a83b8bd526363bbb040fc61291886dbe8892fa71b20c6a29a1b159d8e695836ac8c97eed70448210e253b5a30651929108c1670f4afa10eb8d6252692566ea48a6e01b298c322d824cc59591d4813328da15447e90af6706a5ac42aead65931041c88b984697f11810d0365d0a6e42b2a617a0485b68da600811abe1d806fd975d13e5fe53a28f51250ba0606e3ab3dbdf49894c9c0310957d2819b08864a566866503a8db04f597be9cd721256c74ab736f0868548ad967eee6b0c4c19e03f66bf02d561071b399c54ec5e454664a5d12b2032121aab
+OutPK = a92b2c41ce706bed456c92ba9c5532a9e3d4105a9c5053f9db372c429e2a4f37f86976be5123d98b2803e72f8e68e0cc468ceb4ed04c500a900a8017417ea51ac97cf2bc1d4b11dad2836c7c0f2f12f0c2b3ee6b78e12a313c406f90420b32ffb4ac56cf9c4b83ec5848a3d289dc783983a0165585d20141cf3ab2ca4193c4c903c033ce7feac95ad34ec9815a4b0662087c97b78305e551ea630195d74b2bcd824908b843de40415c9d580445f009c98b6cb56f091343a7a18b2fccafb362730bf1f139a94012c7216c825899655b4002654e53444be1426d5f85e4410ee16861cc9787a34d3667c19af379aa657683af1691d22dd42e2bfb377e88992c68f1ed90bcbae6a0fbb8c13b9ce2e9830d414b67537ed737b6af1844a7d93d71000402935082f00d168dbd9966be19e128d01b61fe3e86c5d05b7b09a3de0afd7017942df88da1d551213eb36ec1fb97447789691d904786321300049bac6867d6db9dca622aaf1722f706b822a0470b1769efe5bb7ca755b1c29678bf5492d7556029ff5814e8bb10b56ace0fb075c47f1a600a40b8b1bb4d6c822048e50faa67fa152df251039e2f72da3180546ed88420889d63a58e498a18a79f9ae325f4da9f4a195c61e67c671c54b4121eaa3e75428c32c19980e329b978e32981c9a36413612cb50e0c95b31ba10826108db55c1d975f4269d41eb534e80af196630146192150a3af2d627ed05310a4b110bbc230c26735bb14e7328423ce25158813fbe84d82510a5ab536182e1b4d46d361613920e96397b5425a7de3342b80b0b34ece5aa63f79370d29f54203559ecacf3aa27f40a33a1b26462bfc3e621b7e903b3e04b1648fd6ae5881061e02c0ab610930e7b2a89ef22e3042b6168a647d17c49ef4eada957c136886fe4d1319611a7131eaadbfe6b420b999128f8998464e5627a0a288c3f3e5457ceedf656904984c2f043104b9822ee939884fa043da0e4aa8d81596151143993208a47318cae39eba6bffe5a5940536052e497695258820a2dd836a680d4ad550e49bea5c229a2736080a0ca2ad69bc94e66c016c51b1b906bea269c8b9523c94154992d6698894a06143dbb5adfc9c881010b7490178a3854e09aec566d35a71d4f920740149fc36564a028dc4d2985f2648a2990b699f0505ebd0a13a7c696960e542842db439cbe1ca2409dc605def6d7064f563f8e51f4270911ff8806273d9b2ac3549b0c638f99e60c5c9d8a20d294796bb147e6695af4be69331597ad656c0f4474e7a73cac1808e3c0552148474eb250e4cd87a463716173366ede98e0e6ff7514cd6cad20ad72b7cf9507d16f828d505da4103f3c8a94555e8bf18df0a3423ea1cd945f29373144b062f489877d84c0d9f0335bb1c8bdfc5f008c4366d8a2cc1a860715c4113fe48ca9e368d952a4496ada4096cf7b621793bfc2ea4a728b256ad0f2386cb5a0598250c510b8551ae5fe4cb9ed868a7eb3d4bd4cd686e64072a5852743816bd12eba1b7bca8fdd90b0633f302fc534cba923b469e854179a852835cf771cd3d23a5a0d5b4904e46ccbc1b39f6728da4f702a21638d46d566532395366211c3a88bc226acb54e1b8a936fd67cd94e6e620f5ec0e2abd2803a25f72106b7d84dfec6077a012371f0d66a2ec6e92e08f8407b41c95e3a7736887ee32e3ca43e4c9ee1f1c59b433768c01e58f22242ed5455ac8fb6522d262c9d26817f10a59b3cf32d2e57a539181d41778e41cd445a811876249448059536965b39c953dc737d632fe18a1cb2d2641e3dd0b67c6e40ec002f005dcfc0634698a818cb2bcfca6f2058b0a1c37e5083231fa9d3ce886306bfd9e2fe01a919c69ad0fa134b399ca86b4a93772d30e305d426819d7f984e10b05aa3fa49612c65e89f0310d4d60c5f67b8672ffea26c76f8a31639bf56360396e11c17cd192a01d7e579ef0b9b2797780efe1487e7bb66bd1f60bce073b212bb1429a246761366900eab92662ddc2fd99786a45a688db084118deca7586663dc50c45d8f6e88560a01cb5e55c289d5e3095d71a75b74975a3757d680092e29abcbc3d19454ff07bd5b92221b087c4154f21c39280acb0a5268345b541fda116ad9f87ecee717089802aa2ae6f0ae4371a08ae7bc2cf30309ece8659ee2c59fea41411c34c19340d05a89711d2776648a695e8e63ae20bb7e3eb4bf2047a3d8528f9baa9050b818ca2fdca1b5c035a87f7be3e34d5aec5d8363f0554fbe8aaad471c441a5346a5879bd968b6fbcd7cec07a133a00cbe5be0de2a213cb785a5f728ceeaa4b85d6fa8421c7539a0ec430a9982bc9554808162282543d2b6a5c9374c41b086eff61a5a05843a5cc884888b6475b0729193d5be8679f60ac14468381f5e41a7917d2628b0740f9934815b58195f6ff3c0bfd0013324b18a98796ada66d2457af69c51669fd9fa5e3d2180b0c915b4bedbd18de7fe04aac453d1e875ad83d325ed74a578857bd60758885193814092abf83088ea5ccc83753532
+
+InPK = a92b2c41ce706bed456c92ba9c5532a9e3d4105a9c5053f9db372c429e2a4f37f86976be5123d98b2803e72f8e68e0cc468ceb4ed04c500a900a8017417ea51ac97cf2bc1d4b11dad2836c7c0f2f12f0c2b3ee6b78e12a313c406f90420b32ffb4ac56cf9c4b83ec5848a3d289dc783983a0165585d20141cf3ab2ca4193c4c903c033ce7feac95ad34ec9815a4b0662087c97b78305e551ea630195d74b2bcd824908b843de40415c9d580445f009c98b6cb56f091343a7a18b2fccafb362730bf1f139a94012c7216c825899655b4002654e53444be1426d5f85e4410ee16861cc9787a34d3667c19af379aa657683af1691d22dd42e2bfb377e88992c68f1ed90bcbae6a0fbb8c13b9ce2e9830d414b67537ed737b6af1844a7d93d71000402935082f00d168dbd9966be19e128d01b61fe3e86c5d05b7b09a3de0afd7017942df88da1d551213eb36ec1fb97447789691d904786321300049bac6867d6db9dca622aaf1722f706b822a0470b1769efe5bb7ca755b1c29678bf5492d7556029ff5814e8bb10b56ace0fb075c47f1a600a40b8b1bb4d6c822048e50faa67fa152df251039e2f72da3180546ed88420889d63a58e498a18a79f9ae325f4da9f4a195c61e67c671c54b4121eaa3e75428c32c19980e329b978e32981c9a36413612cb50e0c95b31ba10826108db55c1d975f4269d41eb534e80af196630146192150a3af2d627ed05310a4b110bbc230c26735bb14e7328423ce25158813fbe84d82510a5ab536182e1b4d46d361613920e96397b5425a7de3342b80b0b34ece5aa63f79370d29f54203559ecacf3aa27f40a33a1b26462bfc3e621b7e903b3e04b1648fd6ae5881061e02c0ab610930e7b2a89ef22e3042b6168a647d17c49ef4eada957c136886fe4d1319611a7131eaadbfe6b420b999128f8998464e5627a0a288c3f3e5457ceedf656904984c2f043104b9822ee939884fa043da0e4aa8d81596151143993208a47318cae39eba6bffe5a5940536052e497695258820a2dd836a680d4ad550e49bea5c229a2736080a0ca2ad69bc94e66c016c51b1b906bea269c8b9523c94154992d6698894a06143dbb5adfc9c881010b7490178a3854e09aec566d35a71d4f920740149fc36564a028dc4d2985f2648a2990b699f0505ebd0a13a7c696960e542842db439cbe1ca2409dc605def6d7064f563f8e51f4270911ff8806273d9b2ac3549b0c638f99e60c5c9d8a20d294796bb147e6695af4be69331597ad656c0f4474e7a73cac1808e3c0552148474eb250e4cd87a463716173366ede98e0e6ff7514cd6cad20ad72b7cf9507d16f828d505da4103f3c8a94555e8bf18df0a3423ea1cd945f29373144b062f489877d84c0d9f0335bb1c8bdfc5f008c4366d8a2cc1a860715c4113fe48ca9e368d952a4496ada4096cf7b621793bfc2ea4a728b256ad0f2386cb5a0598250c510b8551ae5fe4cb9ed868a7eb3d4bd4cd686e64072a5852743816bd12eba1b7bca8fdd90b0633f302fc534cba923b469e854179a852835cf771cd3d23a5a0d5b4904e46ccbc1b39f6728da4f702a21638d46d566532395366211c3a88bc226acb54e1b8a936fd67cd94e6e620f5ec0e2abd2803a25f72106b7d84dfec6077a012371f0d66a2ec6e92e08f8407b41c95e3a7736887ee32e3ca43e4c9ee1f1c59b433768c01e58f22242ed5455ac8fb6522d262c9d26817f10a59b3cf32d2e57a539181d41778e41cd445a811876249448059536965b39c953dc737d632fe18a1cb2d2641e3dd0b67c6e40ec002f005dcfc0634698a818cb2bcfca6f2058b0a1c37e5083231fa9d3ce886306bfd9e2fe01a919c69ad0fa134b399ca86b4a93772d30e305d426819d7f984e10b05aa3fa49612c65e89f0310d4d60c5f67b8672ffea26c76f8a31639bf56360396e11c17cd192a01d7e579ef0b9b2797780efe1487e7bb66bd1f60bce073b212bb1429a246761366900eab92662ddc2fd99786a45a688db084118deca7586663dc50c45d8f6e88560a01cb5e55c289d5e3095d71a75b74975a3757d680092e29abcbc3d19454ff07bd5b92221b087c4154f21c39280acb0a5268345b541fda116ad9f87ecee717089802aa2ae6f0ae4371a08ae7bc2cf30309ece8659ee2c59fea41411c34c19340d05a89711d2776648a695e8e63ae20bb7e3eb4bf2047a3d8528f9baa9050b818ca2fdca1b5c035a87f7be3e34d5aec5d8363f0554fbe8aaad471c441a5346a5879bd968b6fbcd7cec07a133a00cbe5be0de2a213cb785a5f728ceeaa4b85d6fa8421c7539a0ec430a9982bc9554808162282543d2b6a5c9374c41b086eff61a5a05843a5cc884888b6475b0729193d5be8679f60ac14468381f5e41a7917d2628b0740f9934815b58195f6ff3c0bfd0013324b18a98796ada66d2457af69c51669fd9fa5e3d2180b0c915b4bedbd18de7fe04aac453d1e875ad83d325ed74a578857bd60758885193814092abf83088ea5ccc83753532
+InA = 8f0774d3d5350bd8a9f1567b6408f044018892f845055d532885b240f813fb98007cb69e66716bc3e67f69d0331b21c613b367dc3263689b62a8b38b02846af41cfd8633f41b89aa2a7353c587b0d6b38a4ae8ad3ae2b279f340239296bea34b2d6a7048e1e38f98a6f3087ec2e24d9ff11a21e1f7b0a01e00e6b1a85c8e9c9fd986177153f76cc8b317ad0df744cf8498f01b7284038a91106217e511a0cf20ae7c5203e0ef196a552877585ad94c3b277e8b5edda7e2cef1455a066e09ef92365f19bc4c86044486498f6f4783667f72431283644708d03b534dda98dcae6692404fd49cad29b10115790de190f7eba815d93265deaf17f7d14651f8962e28394cae148d86181f7a81a941d1161198ab9d0fafa01525a043d6def1321ead41007fcafbd1243a1629d31e06776b1ba67a1bce2cd4cab1062b59877fda306afa8103adc95780c7f44b1b25ad03ff3d669d2ed2c42b46bb739ec5920d3e1f046469bb5c8d178c6caa73b82857ea5934fb87fa994c08a88291c2937129ade1e8f1a40899df5952ccbb2506b9e57796a26e999e2bdc966ec2aa89c4b8a85c15493a198472a857602f16cca5189ba0a303c6163a63d0ab94634512172c8d56a7917644937ab8a3a889f113a9738beea09f8fb2581e410689a626d38b2a3747d6873748b0a21040c8942e0e289f42dd812c298a23a5e7724f3d33cd619b82830e411d10fb9474dd95162587ab0d81a28d698e1a79e50b624f236b713a703bc46ff245387dab0a6bb77b0e0e885e7851aeac70e84b6d4a2e24bb6f9900d803d513b3ece9da5d495a18d09f61c3b50876967213f2cd4784044e5bdb3544fbacb01242e86ab0e4407bedd1ba31de696414b8a03ed07e227282602f9175a73e3698d696b54616b46b7caa419b870487f2e0869bb311398fd548897aba4a8a04f8d9b0152fb414c9a8333a48e1d7a19a7c864df42dde180148441b274beaeab25cd7cdaa5b3e369e0c16d1c8f20e2b8e5b1e70298e98651dd965a7a858a31f87c4da9a6c1dc20e025ad45f1f6b6372d99866b700d047d845b4b40563d039463bdd4e3e3150ec4aee0646b635aebf064ca1e9e7ee2483e46028a316989adf7483c160a08dafbec43aec6da81950a057fa20eb8046b9cccdb42c5e1938e7766c6f653948d1102cb399c5856fd91e1f667b27d205378f1aac0b83356cef589e5282300d8becfb547c7c297eef0c97335e1bc08869b78d46b6771f060b99b837dbee82b874a871cfe16937a4f07ed01815d7aec5664e13e755bd2c3df61f43f7c2b26e6610f5a9cc44a84c21015a06b0a72c22c68aa4493ea6d62f6258ad8e5ae1effa32c87f49431fd34c76995f85bccaa0e091231bafe3b614a0a881b1cb959427dbd3afcb9e4294c6e35d67902a908c1c42936aa258ca60953a9f4928f0820ac9f00d3c72c07bc11fc0954c0a72abbc3962a287da87ac994c1acd4aba4eda401c232c3a125814af2e2e031699bc0d600fa651f2484b1d7db75e22089492c574536e774a15c8fbb8d59164cda93b4066448da3fabbb7f52b8d6536cbea0474d6987f05c9e0296420c50a33ea26be27dc309b9201d5aa518586f58139136d7084585a3b2dc3c6b9895a0f5e468a4b00b0b52d98c147c641a2a334e45abc4289cc7f572324ba5be314e3e655b7a6ce63eb6ae217fb6f67cbb308350e91c48a88eaac9b24e8b35c05566d0e4cb2c1965b6a14593a1d245295aef119a57549fc4e86086badb512ac46d93ad0984fab1e8112a44a60a16e7051e00c630bf79042ad61a45147b1d7a531aa1c9c9bcd708ca12273daae848d990ecc46c228ad162e69302db52a008aea235a10af962b6b052c683b0d814fc74d4807076b8a0050789fa7569604a34d20b4e67aa5e6956e018b6e8696fe28f9649aa210a54d9c8c7c92b2be83a514a1a6f4e03bc721b180099cb14ccd66e812f97205a7310867f5348e6841309e8a7c2bc8fda8e336589d900813046aa96513a35086bd04745b4390ec2c7d981cf752df3578954751dab2265820ece73745903bb681cbe68f52a9f4cc7c30fab8380094df1296a1af88296b55b2a9b90dcf6a0aa8525f005706908b119727004570fb446a5a634ee44cd28e39cb53f707c9992baa7437f74d938e280a0bf29a40080da8d4798141d6a79c33d83e9b6fa01286d3920a1f5450b1c46241370533b1c5701e4f6a4ad720b208d7e567badc725c1e1364b597f03c4ddc1cc33d251d99a69ed744e04e5a2b8471c0a892fb67e0f75368b35f59c6aa6e9557f15b2cf78120a8575ffde653c968949254113406b4e5220833200c81c3013cea24983bffdeecb0f294041de340975c329b3dc9bda0a9562e436efc1b6c707c522a23c99e602bf103a01b5ea4029319f696a2919ab5c2c29a5caa59750c8ff424288e160cc02286f2ab68ac098ae8e59225c8b3579880486cab2da4e87d10348f5d97bdf20b791b60fb43d06bd88c3153c17819feef2c19df7d2cfbd4b74adcc61c370a16fa1521a2
+InNoiseSP = 564eafbabe3db55e87c419bd7551d0e63228ed9c3ae2a107b7c02614350eec332d19a20f061f879a646868168999eaa9124a058f1565f8710c9669248a15abbe8b7631eb697ceb9b28a4d4359de12975c82ce417e389bde1f08a7960539e066d0288f8989d420a72040e44774bd64a3f0d0ed777e265520c1f75931eee184991718af619b1b62935f43e149068133458595e87e0a273a171714a1b9e8672fa8245fe8b430aa068ac93ef4da0ee1d88b65b3823f7721fca56771082dd0be86f4e811b7c4a838af224aae56534cacc3446d94450002f48ad0e7c4c543810677a937962ab26a2280f14548f7aff393e1a42ae25b56c941a4e7cb600d14dffe440a1d2de6a9027ed965521abd5dc26e25d729dc598e3c14924a29a2335e9fb3533de04e738edbd67096e0198635d3ca644a828753551c622a56acbe272ba06f4b409d922b68782d681d0501cca4f11351674cd6f2a2b06b116c994a123acc65e92e8c96406d8255f538768cb4e74af43a6e8db3da540da3c865a8d2c14e86852c3c97c26af554a609e184b1fe391861c73e4eda477288c1ca94043058236a668989d28a37629f18ce3754c5100a2ce34048e989e950ca7ab50c18e648a45d0e17a9ab49bd087fc46a8b597d32567a5013c58f4d826589c81c5464b29011e508e8b3ab65658105a5c8931deb5dea38e0190b62b6325523a59f287786fc6560421af46098cd686285103499b050729079154fc3a3250a6e859a1b3da1e291d86fc21db496df445d601c3b44a3346a1413280857ca1ff37d75aac5ddb99030a0998de562b4b580905b691f6f481d004be0bd233d28d36f253d1f65b05ab0e631fb661cd5fcc080e76a65160c02ddab089b6400dad4b2a8dc8763c15b9da59c640aaa31f168c657892e2e4816c5c51e80efef47f020991836306c40666e456c441548923ea44097171a19e199f8d2274887c4b54e4808ec5059ed786668245045e2baa1323927b5e5f8749fc668459a4daca0d8e81245b1eea482161dd8f488a6c8d71b88c2d23c0583fee4b3be04cfa344ced844afb41551013c73434fa739d4f0a82249080ed522f51663509585b6174905d5f0042635bfdc912a2e8f5a6efe99d67ea4d965c245507a560b3f2669817d4ee17019aa3d8171bd6304998531b0d706c1537cc2c1e0800e2b3558a12c7d019997a551009d3b12ac9dfb4b61aa2453609d787fb1a7f499db013b44089bbca19885602ae5c5d534aa1013e776b3bd76e9091fdcdc68bf15c65aaa284090dcd7ae9a634c8638a4d64688e7b144c2570858c17039d3b2d82c21714349bed5f1a5701511e79cae191e195a7b09a32999d2cb4291c4eda7c1da06d0985dad801a779613458756ebeaaa695f143d1a50da35e6b69b48f466cb479eed6154ca6ab5a5288932a8f8f62ab46238b97e0a14af0232144a0fa09444ac98b9700ebc819e86fc8b0092cbe5f2b0f60d6a1288f431d606c698d65c465850375634e01b6ab7b369d122874528136bdf8825ce63a621f056c12f00904a108400281da06824b8c5c1468f4931a2988db371620c7ebec23790c997beff4c90fa128459c8da6ddc802b10529b6305c6c41ca245abc65266e44bc4952e2adc7caa35607b20a8f1d0ee26c607e48224f22e36d68af19054115fc23741a28257a5d1ca88450867d7e752aea190357697beb4bcbc3f736924659d680681dac4d08cb8478ba76bdceb99a4864ad8b488b87d238bfd02c529834be431642371199d479b0c5f83b4f8196cc109d3a7292315fdb896992b52287cb61b8d28cadf1a44e58d0d25d5b0f084a3052408b4adf15acf6aacd47021431d9450c1dde8b98820fdd2c78aac94d0e36ef16328c3470552fa558c02693fe1c3135c4457e252f412a18ba0aec007a772de963762ce3a01b04bcf52e85b9cf121931c945ea126910001909f5e5e6b5c61aa7f456c5338a5999a33f216b1dafe3f0b74a74936274d9318906b56d609b295d0a73a10b05642272d954bc3370bd5a85a63962b551039bcbb4866b8e77e1dbb7fa336937eb9e18f6d5c0a5a927aea4b0bc7e736425e79772a0b90292f7495e48986f0543f5b97bca41b405a3fa47c8de3f2791adad8bdb4958da55351e91e6c4703d8d4f843435a9ce2d3dcb47278cc8826e567a314f94ab0a836570e7697d822857aa584818c822b858955e8aa0a51ae64a56865dce4e65032e76e0c0f610836d7d1752169bd59eba0fd206850ead8cb71afb671ad4304991b0f3e0640432e6b1251bfa9f5a9f71672d21790093d902c39d33081405d2156e1fd78ca1b3765c67d0c0e4aad4ad6731e7b6c79ea0456e6e7c1b8709405a21f0c9b5f83c405bf3d1631e8c6093b7591e71244b9212d980c4084ba73a4451f43089c8de175f344fb6691a06f54a5d2cc0b4d43321b0728b8e98bc5d0470104f06ad4819e1492fc922c42575a99ae6588e89c1ef6825e4582f4b6e548b1532236e10345b63e4743c078ec1c5ce0aca1125cb42841968654d9277c521
+InNoiseEP = 1a6aea83846d6c49937f55ec5c228e41f5b31ca182ebc7bc872b9a54c55b088a774624ffe5c5e8b635272509daa7d4a43d628154aa1d9c9c62e7b2d5762d1436ac97db5cbe8afc18bc34c77d0713e553420c5c9811cdfe131c66b9e0867b39ea85a45b420b533342a13d4b94d11aaa02c9596067e1b25ae6193224e5be04538787423996bc6b55c1232da1724ad9b8d6056070e64bf1fac64db54e0ba7532fcd62cd82260afba990b6a7b40b03949fc7ea51082b8143c9e1800893b24544419ca26b228c64690b3550a825e196d2b348fe6ed39c814a9bd67c51519b7905b28f69915d292ff8ae3aca98e85c466cac501e3b9be5478a6c29e3d7bcbb7626cce6e7b29296c727255d90389a9f8e86995142cf54104a60d1a7f46cddb342366e06ac308afbb9ab76a8ff2624725a9bac3f7808217547093a73f8e698834338330bbe06b3cc60621795573167e6eb0f7d38e85b34c73d96900c85b414598463051397b506c8afa6ac54126906265bedaf23654dbca883935b0ae2093b2a4579e01917ca8ddac676622a04a3a605ceadb8f8dad6c7c33e6c9ec5fa89f1ae7279056c4504a039cba1b1e1efc5506951be573131054a688fd80ab0186bdd53c98d2116d61a9eb85b6a03c34ca4265196762f0f82cb7504896aedfd4191b96ac2a8f372a14d820d644773c204799417f67b34f522a6228f562ab84262564e12c2f875d464d05757ba3058416d21bf06627e59b3e5339e45fb436ee8131e82314ef3e2ec7920dbca8ba0a8d249ea5ad75443792ea550f63068c551db89d007306155ea80b016e8342b23660e950671107fd2faa8fc91631eea713a79a017895a70161be146d2d0517091bc3c208a06eb4131b44eabfcb3cd2a1df482d2a81c896551815b11f38d420edbebf5335c25aadd4e552fed05135b2fb24c4655b76006d097dca7e545385a9f9096b64802b1ccb9ae515c7f7bc6385327d5fdd8a29595c1855387c60d1a920888656551b52e91a335ecfc5c3d4dda55270a0ead48aaf03092514f8ba4f6eae5a4c1d38287d235a9cb50cb24518a972eda50d29fb085b98c25f950741bdc6a3853792d27a5a389a1bdc65772832a43eddd12524db26136eaaf5c9aceb1a25993cd42e249e7644979c0afab6a08047766b365bc3e5af585d7241b125ca81aefd9c1ec9ead98b9f0634825590eb132fd10af74d386e227000006efc1b8951862d242205005f5513cca5e17acb614e282bde9ee4c0fd66c76a8cb0d68a9cb49276c9459696c1c230fc2b5d7dafa9789298981df45b1712675d46967f6f4c01fdec92702d3886ff58027fa6d32a99bdf1c86dbdc17945fac98e3c19beac43c959c3967295c0a7a0df1b2362be267623434749ba64abea437529876b7a27073fa1478a037d46b4c0f0b082bd4b1650099550d494d88658199bfe969acd45122731d9f2d4500372ae9183fa547ab22ba4cfdd70634d729a868d78642826e04551936c092c4194ad59ca070ca195c662dd7bef43141e09659dc7db71e1d15f07176b3a258efd331199ee0693645e4348785c55908df197aed0fa0a2d8b0aab351505afada2fc456fa7aa4c23ba6805e7439707ac0167bf61c017fc88866d334bc4259c014daddd423a6004291a9883d889187da474dad31552d1a82412fc2dac9246932b5cd4f2724db50aabbe5146388985156248e92ab9e9807d796d590b40ac3543035191c4597001fa8c1fa1d66a8be47126998b611bcf8298a9fa686c9e42b4407ff20002a97306ebf90f14bd294867425d5dae0c15cc1af3b86cc3057c4a2665634525a1b1753b2ebeda0f9d95052d02d05818d44f3fcf98508e9c40afa08ab4e453cb34991431219f6c2e8b5161acae5fa88497f414701b9f8f06ab8cb49db7a628c47af05215ef6b349cede61083ab3ec22184987547a085cc620cf086dc2dd3f2bf2484fd09af93ae304b06c274e839dbc5e23cb6fc23cdc4a021e9ba355006202e890e0d4d03b15e501969168a0e04fc87526bda835ac44f04875434fe8bf9b63c52fc15406d0a6fe466cc6fd640b5241bd91f8eba1c401745ff085393e09e4ae80b4e95d33f2ea5832bac91f135757b28e0267f283b71430216ca52c2793d776bfa89e5ad10cd808fb898bd90f6e21d36680e74b7a747653301a5f14a24b17abb120b28a9f5331c96c1e89bc1192e9786c336a2fe654be988080d4a1e5800053066bf260fa391a1def437243ce6be582bf022724152f41f5fa2eb53352a07aea4f8c4cb7a0d9f3d3215d6aa3b971ce846228d757f3933a30cae35f88c125a80bedea69b44940a59d1080c78285b1d73954a3b63403d4ad7649bcbbed067622eeaaac36937570fe15021cd893d7d6929adcc5f378bca09daf2b2de09d4a1f9f83d556f9122895628bc41d25bef96e7835ad21bbdae1bfc775821dc66e0494f6f86c5b6bd2317ec53533c238a4fcb81d33875530128192eb8fd63755d92b74d03da66ded0dd5c617050e2554fce83f3a492954ad2125837dba00
+InNoiseEPP = 000000ecff0600fd6fffcbff02c00300ff5b00f8bf058000000000c00180000000f8bf04c000e0fff6bf018000400000c0fcefff4b00040005c0ff0b000300010001400004000180001000080004800020000000fe6f00400000000100005c00f8bf0300fffbff0200fe6f0020000000feaf003000f4bf0000006000f8bf00000030000000ff6fff0b00ffbffe2f00500014000070ff1b00080001000010000000fe2f001c00f0bffdefff0b000000fc2f00e0ff0e00010001f0ff0e000070003000f8bffbefff0b000f00fe6f003000140003c0fe2b00f0bf0080fe1b00100002c0ff1b001400010000fcff0200ff6fff4b00fcbf00b0000000f4bf02400010000800feaf00100000c000f000300000000040000000f7bf014000f0fffebf0600010000f8bf007000e0ff02c0fdafff3b00f8bffe2f000000f8bf0100000c00f4bf05400170ff0a00010000f0ff0200003000000000c0ff2f003c00f4bf028001100000c00300001c000800064000f0ff0a0000f0ff2b00f8bfffef006000000001c0ff0b00f3bf034000f0fff6bf0000ff0b000f0002000000000b000200002c0000c000c0fe0b00000000b0000000fcbf0240ffebff0e0003c0ff3b0004000000000c000000fd6f003000fcbf03400020001000ffeffffbff0a00ff6f00f0ffeebf048000000000c003c0ff2b0000c00440004000fcbf0000002c0000000400002000040000300110000000ff6f000000ffbf0340001000fcbffb2f002c000000fe2f002c000400010000e0fff6bf03c0003000fcbf010000e0ffeebf030001000000000070ffebff0e0001000000000300007000e0ffeebf04c0ff1b000c0004400030000400ffefff0b000c00fd6f0000000c00038000200010000040ff0b00f0bffe6f00400010000100001c00f8bf0680ff0b000c0000400000000c00fe6f001000080003c0fe0b00ecbf01c0001000f8bffc2f00fcff02c000c0ffebff02c00240ff3b001000ff2f0020000400fb2f01d0ffeebf024000300000c001c0ff0b0003c00480fffbff020005c001400000c00600000c0003c0ffef0030000000fc6f00d0ff06000200000c0008000000001c00f8bf050000000003c0ff2f01e0fffabf0140ff1b0000c003c000000003c0f8afff3b000c0003c0002000000002c00030001000fe2f00500000c007c0001000040001c0ff1b000400ff2f000000f8bf0440fffbfffabf030001b0fffebffeef005000f0bf00f0ff1b00ecbf010000d0fff6bf000000ecff0a0000f0ff1b00f8bf0030000c00080005c000200000c0060001d0fffebf05c0ff0b000700fd2fff0b000b000440ff5b001800008000e0fffabf0280004000fcbf000000200000c00380fe2b0004000040fffbff0e00003001500004000340003000140002c0ff0b00ffbf01c0ff2b000400030000fcff020000c0fffbff02c0fd2f00ccff0200044000e0ff0a000180ff1b00000000400030001400fe2f01e0ff0e00fd2fff5b0004000180002000f4bf0380000000f4bf028000c0ff0a00008001f0ff0600fd2f002000000000c0ff0b0000c0003000fcff0600ff2f000c00080003400000000c000030fe0b001700ffafff0b0010000680003000040000b00000000300004001e0ff0a00fd6fff0b00ffbf00300020001800ffafff2b00f8bf0440011000080000b0003000f8bf00f000200008000300ff0b0003c001800010000c00004000400000c0f92f000c00fcbf0200000c00f8bf05c0ffcbff0a00fdef0010001000024000000003c0010000dcfffabf00c0ff0b0008000280004000f8bf068000e0ff0600fa2fff3b00fcbffe6f01f0ffeebf0070ff2b0000c00100001000fcbf014000f0fffebf0180ff5b000800018000f0fffabffc2f00200000c001c0001000fcbf0340ff3b00fcbfffaf00000003c0fe2f0050000400feafff1b00f8bf01800140000c00ffefff2b0000c000f0ffdbfffabf0280ff0b00140002c0fffbfff6bf05c0feebff0a000340ff1b0000c0ffefffbbff0200ff2f000c00fbbf008000100000c002c0ff0b0000c00200001000f8bffc2f000c000b00ff2f011000f0bf03c000300000c0fe6f00e0fffabf02400160000c00010000dcff12000240ff1b0000c0ffeffe9b00f0bff7ef00000000000500003000f8bf0040ff3b000400fc6f01e0ff020002c00000000000fdeffffbfff6bf02000100000b00024000100024000070001000fcbf003000400000c000b0000000f8bfff2f0000001000fe2f000000fbbff9efff0b0000c0ff2f00d0fff2bf007000f0ff12000040001000f8bf003000e0ff0600feefff4b00f0bf000001f0ff02c0ff6fffebff0e00fe2f000000080000b00000000000fe2f01c0ff0600038000f0ff0a00014000f0ff06000140ff0b0003c00200008000f4bf030000c0ff060002c0ff2b00f4bf0070ffbbfff6bf0100013000080002c000200004000300003c0000c0fe6f011000080000c000e0fffabfff2f003c00fcbf
+InRand = 3bec20e879d06c7784727a350e65ef4a75df10bcda185de1bb4e4a6cf8d8e450
+OutPK = e2637b35a9e43a2dd25333c125bb90407b7b1c0c62da269efb13008434d8a8f00d212f6198d693bff0062482ba182ce12bc16520d6928e1d6ea54a870adc94396e2f633e6a9b024f8878c64c8af86164fb6561717369db940d96a1844a7511105271785a8600fd062ec6e3f853a584ae238e7fc948ec1e3b2d1e24a679696eeb4a6a8e3d00f3d4428043b81ca050d3fbd03c036b400cfac70ab179eff09232c40f374991bb53d53f8c930e241105b31391fa9a65142d0c95b88b06c12c7c195296f91246e7687034eca81ad9ad1d47fb6c006e2245ebe8a179531c446976fe39028a06a1cb6451590f9c883095b9d543e36b26bd1506dff3f7eb9d79cad5fc62b106820f544e3688f09a386c07f0a7428892a80620f3da33bf19e595ac79af5d58cbb8b404862fd7b020e564a2551df746dc880b67098df5732eaf139adf20f41c8323c71e378f2e35544c12f446dd8536445a993f25a028cc3e106c9410dd5ed2f5f1acb1a02683e21c357153c056d2e755731f1aaab7dddd9a75cc159377ceb26404efd25e6676d946ec388a4268a1ee7317f209861adf78126f025363c9254839f465fa5e9e37098ebd8f633a16ee310a9d512fa922dd25dce24b364ba24388a72d40eaf13e4f535b61d8007690483f6aef6d4d07819744091a0e4d4a3ac85ae52f04d530a937aa0c81a858d7b38e7a4281ab20f186890d00bf89590650a5de283a37fcb2a4cf85c658f4148e24b478d8225f7e0ee0135c9e39568a6f8292261d856b9c3878741a11ac9d39aba68cb714292943e44aaf5d9d00385425d9407f99ba6a7743e9abd162c80895ea9585b611a205c90b9ad2188e6a903f5554c4a35996ce266a49371a4fecc68660be35055fe1f8797a5f6dce81e22414764c44d3ad981b2eaf415169855ebf5a4de3904227789c58d2a34a0c75e50668dfce4e4f2083a693a607370d5e9a79f943609f94663cf47c94e14d5708346b33ab51c2ba91729206356491cd57afd8ceaa0d3634d3257de0367110f05ab7253c2130989b9575887e0cdc6459f9e3b61d72416242e6c2b02a8ffdb98e5c5f6da8e7a13a7c7276ce47e4bfba1cdb000ce070a4bbed57413ac7e5110682fe86b0c5791644be6a7ce6169bca6bfab174b734918da1ce4a399a903be6e2621ca4a86f90e0bc4750819be2cc4603c4aef178c3865c9d858ce8a1f0519927fff327b906cc6e39a4238da0c7061fc4c8240388acd039ae8e7d68990fc78f5061362361c1e1869762ce6a066d24aa9ea4f8468112072fd16f8b314c5fb4c032725fb6729812fe9bdae138b81aba3abdee0ff740fd9a5ffa18205b3307e53607e90e7894767249ae95a436ab71798e1b5b48f4117cd56e3cf3a4912dae43bc63598a78f2ece536cbbd4320248df43cb845169a01981ffeaa2e9dfc17a8aea8675cecd86e7e9a544bddf12af07652cc4b2610a81871e66eb18e643fcd267f99b731ac72258ac4aa66a41a1cead40450876115119133449e2e5535b008957b7b6682e8271a9b0a4c0b4849fc1fc023ec529d2d6614d7e860587925b1eadb3311c90aa1597af55af1beb62dc01867dc0b932deac47adc91d7c1d93968041a1edeb5808a8883f65f7d11be85b8435d23482c081a9d6d3c5693a05aa66186620ed46a23118552673c96820a6f3bb3aa9e51c3a07b26d497c458ad219c5588f461311bc8bd702309f9b44aba430d81559989140f95982e871d502e02c3f161399a367910d526a2063b4892b507c0611d2d8d6d901e318e92eda13ac2c14ab3a9b13129552c00d529b975c1a8bfa0b55bc77488424af77b97d63fd78d9998158e51a297d286156a99fb6a5112ade63a1085228ba7de53c7c3f2d2131e510002ef92cf4c5a45570e07abc094ba294661e4cd96fcc3a7a1bfba84d1a2c8d0b2d550e20fd963d3100fa9d890540cacbc2babd97b6fc4052dc4d4abf77e6c5b8860219ed1276c9d5c566704a9d19e6f54d8ea63315079839a042ff0520797ce78b1489982c26aaa463b20a2e9ac710cb08473e79bd134416357e5216e3e644b71d7182a121dc0f1463e22aa44cc4f6246016cd1af2d119e82abbeae7b6b1ec05e38acee10fe422051c448a14a71a23a98594258d9525544fe697d752477c5e01922706d2ad10351262a32cf86859a180d7f2185bfe370663c9fe81b419ce52560d9552b95f013b31068eb447c528a48c53bff387575d61dda46a9499a0b0d59602591c31a7a20add950142d82719b08b460270b207e9a03ed91eee0e5d8203e5fa061f8e624195f05a4e4e9376e9dfba02d14325ec2beea8fc0b21e67e8b671d8a194e1f9367ada2c9a096c9a6d5c83ba9344d2d2026138ac89940a946090171fd868310fc29f2996b1046910a754243db02fbec676109fa25de969f3e626646209d38b9b3bf909c4d249e5ae2dbc119d779270aa3e332fa2124506a80f41c323a7e1a9486a0cf5002d1ae09f798670d981dfa07a313a254222a131163d596443ca8697e4990e0fd3c301e45874
+OutRec = 00c00020000400038000100004000300000000080000c000000008000080002000000001800020000800008000000000000040002000040003c00010000c000280002000000000c000000008000200003000080003000010000000020000000004000240002000040002c00020000c00018000100008000340001000040002400030000000034000000000000200002000080000c000000004000000000000080002000000000400034000300004000240003000000001400000000800030000100000000080003000080003c0003000040000c0002000040001c0001000040003400020000c000140003000040001000010000c000000002000040003c0001000000002c000000004000300001000040000c0003000080000c0000000080001800020000000030000100008000340001000040003c00000000c0003c0002000040000c0000000080003c0000000080002800020000400008000000000000300002000000001c0002000040002c00010000400024000300000000380000000040000c00010000c0002c000000000000300003000000000400020000c000040000000040002000000000c0001800010000c000040002000080003400010000c0002800020000c000080002000000002c00010000400018000300004000280000000080003c0003000040002800010000800030000100004000140003000080001000020000c0003c00020000c00020000000004000280000000040000c0000000000002400020000c0001c00020000c0001c0000000080001400010000c00008000000004000280000000040000000020000c0000c0001000040000000020000c0001c00010000000004000300004000280001000040002c00030000800038000000000000280000000080000000030000c000380002000000003400000000c0000c0002000040003800020000c000080002000080000c0002000040001c00010000c0000c00010000400014000300004000000001000080000400000000c0000c000000008000180001000000002000010000c0001c00020000000018000100004000080003000080003c0001000040001c0003000080003c00010000c000140002000040002c00000000800030000300000000000000000040003c000100004000040001000040003c00020000400028000200004000300002000000002c000100004000100003000080001000010000000024000300004000040001000000000c000100000000300001000080001400020000c0002800030000c0002c000000008000180000000080002c00010000c000380003000080003800020000c000040002000000000400030000c000240001000000003800000000c000180001000040000c0002000000000000020000800024000000008000140002000000002400010000400024000100008000180003000080003800000000400014000000000000100000000000001c0002000040003c00030000c000140001000040001800010000c00000000000000000300002000000000400030000c000080002000080003c00020000c000300000000080003c000000000000300003000040000000030000000004000100008000380002000000000c0002000040003800010000c00000000200004000080001000080000800020000c000040001000080003000030000c0002c00020000c0000800010000c000280000000000002c000000000000000001000000002c00020000c000140003000040003c000200008000200000000040000400020000c0001c0002000000003000010000400018000100008000080003000000000c00010000c0002000030000c000000001000080002400010000800000000300000000180002000080002800030000400008000100000000280001000080003000000000c0003000030000c00030000200004000380000000000001800000000c00004000300004000040002000080003c00020000c000040003000000000800000000800014000300000000180001000040002000020000c0002c0000000080000800000000800010000000000000100000000000003c00020000c00030000200000000140003000040001800000000c0002c000200000000040002000040001800030000c000340001000000000800030000400008000300004000340001000080000000030000c0000000030000c0000000030000c0000c000100008000040002000080003c000200004000140001000040002c0001000000000c0000000000003c000200008000280000000080002c0002000040001c00020000c000000003000040002400020000c000240002000000003c000300000000300003000040000000020000400018000100000000380001000000002c000000008000300003000040002c000300000000340001000080001c0001000000003800000000c0001c0002000040000c000100000000040002000080003000030000c00
+Key = 489c79a48135995c4c8cdeec1777a79cc68bfa7b167f21a25e92945b4004634f
+
+InNoiseS = ad9613f7d3f429e39015b40b84b0b0913ec1c4208c24d4573b1e0e5cafc5c2e3304c02271d1271721028f125e6974c6682ea15cea2cbe61cd1c03c601a708e42401ffa6cdd6bdfc925b9e520914a5902162f2db0a42b389894122e95cb5b12393642bee7c43bcd394449a938e73625985fdd9897355e13a453e073ad38438fe88738627c7ca3d39137a8e996630b1644a01c0cc5ad8c7ba79da067693c0080bdbdfdae94a5622587c4635fe319f439c7805e194b785fb65e1ce58d446e131206b025d98e60d10a1afd716e79103863382943964362c19c48a3aed93dc2aedaa4945a3d47a07ab585c3b7e377edaaaf8e4552ec3cb049c66ce1a7d9157dd552a63008a3ea6ff2026505788d18bc0152181b7b52489864aa4306eece17e366a9a822ad131059258665298515f1b8b691e490c9190ae668b2e6aaae8633a9f4b1d1a1015009c041b50e55d0d3d19066108e58c3ba80a67213c851687b6494a5235c7810718aafd10b7295810284592327f2b37ab9cd89eb80b3a81130e3a604796d95b3eede92df111d7264d21483851394002743f9fe13555f35250499421f189a1b35a92a2d2eec18e03183042e9ee7eaa15b9c11f17b4009a33960f9d628a225ab1c2557f8dca1dec00f82f80437c10a09f04fc52d3b8f95c19d86603bd6be368d427f274d3946d0221240cf76f4c4bc86b963f1e72fdeaa7eda6a382b41ba210eec4bd0a48b509dae0455a4381e6ec80226920a7fc67649fe4017b26407624bfa60da5c47559f248793eb4dd1216665201762d3b64c4782cf1175ff2eab9c6868b764d27a8f29e882beee78db130563114a1c8d91f125748ea0cfe56361aaa55b8d45a507754d332b8e9c252728b103aa48c1d5243c8e9e9a9879564f61cc2bb8cb3cbec982167859524f78cb374bb95056505acd22f0cd2890162931d4a200ba1e8490bbae0b521ff93bbaad8ed3ae62d7246205f92f8a7180492c398f76674a1a77d4278ee4117c11f001b016dc057c4d8665e7b4608e7726c727356e550a6974a4a0fa77b6677a40ff5683712a24d066d00ec14b2f926ea6b0b01b16f21a28b1ac2bdd05f4c162cfc844fb3ee4a4125e84e0876a77ee05457931550cc6c96673cf9d4526959719170815bbacdc97bd629924ea99731238be3f1c27a6594182f1944af3235ca8ab8ca067a1c6628401b4cbd665457e01c5fb6fed88191b24aa65e08c4bad30e5f9a00857aaaa0092302090ce66cbe192089896a524074c4a4e007e8a466a741417d7fb4f6d85e5c656c9540075258e3e1a0b1483ab482ffab6be449be33d0369c637cc526ee663395e092051e278e6aafc2e70f707017e85ab8dfb292a0d20eab39a773a429cce65a7f236612f633d79032c88b58af02651a1a05166032a446457fc2c8a548a60af745b8d762a1118feed7308af00023ea521d4a78a1e4d44cd266aac096985cea3f490989413b3e9cc047cd2c1e7599a5e3e1f081c647185bd819a9d7764a991e0a04db7a375102c5201527c9d23b242ac5ba5022ce8afcc78fd3a722bdc69119158898e405e68724889d6ee56831c1a2f39e507949a998e9fc3f2640c861841ac7e5ab261b563922109416ea2c4e071b4a1e46bc6c87e03b4e58bce9d7cf40a78407e1f44076f8166dc809a933e219e084126c1acf8a8e14e570383a454d0043c46b5e940540ff1f9de329321dcf7b179ca7adbc33693dab233d5d809332a5047839e50b1f20540d3d4a1908dfc64869937ab9b1a4bb21334826b449db24bc0a85a26183e870c39ce0e38372ca844aad89cec673713461468958b7e24fe3873670eea199eac685e9e64732e6070efe23ab892ce3e8b2053f0c1edbe5a46b1d6d839818047b0f2ae2150b909a3e6cc818c9819e3a156980fc2aebb172ac57a8ced24854550532249d827e798a83916bb4271aa841c5e76b49be014651b59f151092193cce682e1ad237818746724819862494633a96217581bba6a8e1652829ff0c128111d5d5d6b5bdc707ccf09e479e561aede184ac631cc7f19de60babf183cd6e6e3d3a80cbb398c58a147767da3d5e500c956083ced0699a850aada1f7b558c86778d9bc21b02ed4f6beee8a6267244a0e87687713161195d94f6dbf55adb0eb95967880a94c358579d945c521f19f361d68818a8cdf01f0a0f4a125e96f3a984d68c8a8a43cc8bd9c64a1231de791e2754928c088a519921888d460d7c5548e7c9f88e360c8da46e7616865897aa4ef14eaceb7753103103c343358398a4530d8fc86a851999f4e49b30e365044eea61a4e47524198d0f9600d8b10155ee33da006469ab55782c46416195f2a153c264ff1d7dbbb72ca01c26d11aeaa642fedadaf88a7478acca65515ab881719c8200d8559e3a63b96155016b625cb61a09209ab89cb08b444da5e6990f466e286047a72b1073c67d9e5cef88ea2e2c3713f6b1c1bababb9a1f2698e814c6ef0f4bd8aa72a7daeb41364c77831f06720b34574dc550b6b44a3550613c51db1823
+InPK = e2637b35a9e43a2dd25333c125bb90407b7b1c0c62da269efb13008434d8a8f00d212f6198d693bff0062482ba182ce12bc16520d6928e1d6ea54a870adc94396e2f633e6a9b024f8878c64c8af86164fb6561717369db940d96a1844a7511105271785a8600fd062ec6e3f853a584ae238e7fc948ec1e3b2d1e24a679696eeb4a6a8e3d00f3d4428043b81ca050d3fbd03c036b400cfac70ab179eff09232c40f374991bb53d53f8c930e241105b31391fa9a65142d0c95b88b06c12c7c195296f91246e7687034eca81ad9ad1d47fb6c006e2245ebe8a179531c446976fe39028a06a1cb6451590f9c883095b9d543e36b26bd1506dff3f7eb9d79cad5fc62b106820f544e3688f09a386c07f0a7428892a80620f3da33bf19e595ac79af5d58cbb8b404862fd7b020e564a2551df746dc880b67098df5732eaf139adf20f41c8323c71e378f2e35544c12f446dd8536445a993f25a028cc3e106c9410dd5ed2f5f1acb1a02683e21c357153c056d2e755731f1aaab7dddd9a75cc159377ceb26404efd25e6676d946ec388a4268a1ee7317f209861adf78126f025363c9254839f465fa5e9e37098ebd8f633a16ee310a9d512fa922dd25dce24b364ba24388a72d40eaf13e4f535b61d8007690483f6aef6d4d07819744091a0e4d4a3ac85ae52f04d530a937aa0c81a858d7b38e7a4281ab20f186890d00bf89590650a5de283a37fcb2a4cf85c658f4148e24b478d8225f7e0ee0135c9e39568a6f8292261d856b9c3878741a11ac9d39aba68cb714292943e44aaf5d9d00385425d9407f99ba6a7743e9abd162c80895ea9585b611a205c90b9ad2188e6a903f5554c4a35996ce266a49371a4fecc68660be35055fe1f8797a5f6dce81e22414764c44d3ad981b2eaf415169855ebf5a4de3904227789c58d2a34a0c75e50668dfce4e4f2083a693a607370d5e9a79f943609f94663cf47c94e14d5708346b33ab51c2ba91729206356491cd57afd8ceaa0d3634d3257de0367110f05ab7253c2130989b9575887e0cdc6459f9e3b61d72416242e6c2b02a8ffdb98e5c5f6da8e7a13a7c7276ce47e4bfba1cdb000ce070a4bbed57413ac7e5110682fe86b0c5791644be6a7ce6169bca6bfab174b734918da1ce4a399a903be6e2621ca4a86f90e0bc4750819be2cc4603c4aef178c3865c9d858ce8a1f0519927fff327b906cc6e39a4238da0c7061fc4c8240388acd039ae8e7d68990fc78f5061362361c1e1869762ce6a066d24aa9ea4f8468112072fd16f8b314c5fb4c032725fb6729812fe9bdae138b81aba3abdee0ff740fd9a5ffa18205b3307e53607e90e7894767249ae95a436ab71798e1b5b48f4117cd56e3cf3a4912dae43bc63598a78f2ece536cbbd4320248df43cb845169a01981ffeaa2e9dfc17a8aea8675cecd86e7e9a544bddf12af07652cc4b2610a81871e66eb18e643fcd267f99b731ac72258ac4aa66a41a1cead40450876115119133449e2e5535b008957b7b6682e8271a9b0a4c0b4849fc1fc023ec529d2d6614d7e860587925b1eadb3311c90aa1597af55af1beb62dc01867dc0b932deac47adc91d7c1d93968041a1edeb5808a8883f65f7d11be85b8435d23482c081a9d6d3c5693a05aa66186620ed46a23118552673c96820a6f3bb3aa9e51c3a07b26d497c458ad219c5588f461311bc8bd702309f9b44aba430d81559989140f95982e871d502e02c3f161399a367910d526a2063b4892b507c0611d2d8d6d901e318e92eda13ac2c14ab3a9b13129552c00d529b975c1a8bfa0b55bc77488424af77b97d63fd78d9998158e51a297d286156a99fb6a5112ade63a1085228ba7de53c7c3f2d2131e510002ef92cf4c5a45570e07abc094ba294661e4cd96fcc3a7a1bfba84d1a2c8d0b2d550e20fd963d3100fa9d890540cacbc2babd97b6fc4052dc4d4abf77e6c5b8860219ed1276c9d5c566704a9d19e6f54d8ea63315079839a042ff0520797ce78b1489982c26aaa463b20a2e9ac710cb08473e79bd134416357e5216e3e644b71d7182a121dc0f1463e22aa44cc4f6246016cd1af2d119e82abbeae7b6b1ec05e38acee10fe422051c448a14a71a23a98594258d9525544fe697d752477c5e01922706d2ad10351262a32cf86859a180d7f2185bfe370663c9fe81b419ce52560d9552b95f013b31068eb447c528a48c53bff387575d61dda46a9499a0b0d59602591c31a7a20add950142d82719b08b460270b207e9a03ed91eee0e5d8203e5fa061f8e624195f05a4e4e9376e9dfba02d14325ec2beea8fc0b21e67e8b671d8a194e1f9367ada2c9a096c9a6d5c83ba9344d2d2026138ac89940a946090171fd868310fc29f2996b1046910a754243db02fbec676109fa25de969f3e626646209d38b9b3bf909c4d249e5ae2dbc119d779270aa3e332fa2124506a80f41c323a7e1a9486a0cf5002d1ae09f798670d981dfa07a313a254222a131163d596443ca8697e4990e0fd3c301e45874
+InRec = 00c00020000400038000100004000300000000080000c000000008000080002000000001800020000800008000000000000040002000040003c00010000c000280002000000000c000000008000200003000080003000010000000020000000004000240002000040002c00020000c00018000100008000340001000040002400030000000034000000000000200002000080000c000000004000000000000080002000000000400034000300004000240003000000001400000000800030000100000000080003000080003c0003000040000c0002000040001c0001000040003400020000c000140003000040001000010000c000000002000040003c0001000000002c000000004000300001000040000c0003000080000c0000000080001800020000000030000100008000340001000040003c00000000c0003c0002000040000c0000000080003c0000000080002800020000400008000000000000300002000000001c0002000040002c00010000400024000300000000380000000040000c00010000c0002c000000000000300003000000000400020000c000040000000040002000000000c0001800010000c000040002000080003400010000c0002800020000c000080002000000002c00010000400018000300004000280000000080003c0003000040002800010000800030000100004000140003000080001000020000c0003c00020000c00020000000004000280000000040000c0000000000002400020000c0001c00020000c0001c0000000080001400010000c00008000000004000280000000040000000020000c0000c0001000040000000020000c0001c00010000000004000300004000280001000040002c00030000800038000000000000280000000080000000030000c000380002000000003400000000c0000c0002000040003800020000c000080002000080000c0002000040001c00010000c0000c00010000400014000300004000000001000080000400000000c0000c000000008000180001000000002000010000c0001c00020000000018000100004000080003000080003c0001000040001c0003000080003c00010000c000140002000040002c00000000800030000300000000000000000040003c000100004000040001000040003c00020000400028000200004000300002000000002c000100004000100003000080001000010000000024000300004000040001000000000c000100000000300001000080001400020000c0002800030000c0002c000000008000180000000080002c00010000c000380003000080003800020000c000040002000000000400030000c000240001000000003800000000c000180001000040000c0002000000000000020000800024000000008000140002000000002400010000400024000100008000180003000080003800000000400014000000000000100000000000001c0002000040003c00030000c000140001000040001800010000c00000000000000000300002000000000400030000c000080002000080003c00020000c000300000000080003c000000000000300003000040000000030000000004000100008000380002000000000c0002000040003800010000c00000000200004000080001000080000800020000c000040001000080003000030000c0002c00020000c0000800010000c000280000000000002c000000000000000001000000002c00020000c000140003000040003c000200008000200000000040000400020000c0001c0002000000003000010000400018000100008000080003000000000c00010000c0002000030000c000000001000080002400010000800000000300000000180002000080002800030000400008000100000000280001000080003000000000c0003000030000c00030000200004000380000000000001800000000c00004000300004000040002000080003c00020000c000040003000000000800000000800014000300000000180001000040002000020000c0002c0000000080000800000000800010000000000000100000000000003c00020000c00030000200000000140003000040001800000000c0002c000200000000040002000040001800030000c000340001000000000800030000400008000300004000340001000080000000030000c0000000030000c0000000030000c0000c000100008000040002000080003c000200004000140001000040002c0001000000000c0000000000003c000200008000280000000080002c0002000040001c00020000c000000003000040002400020000c000240002000000003c000300000000300003000040000000020000400018000100000000380001000000002c000000008000300003000040002c000300000000340001000080001c0001000000003800000000c0001c0002000040000c000100000000040002000080003000030000c00
+Key = 489c79a48135995c4c8cdeec1777a79cc68bfa7b167f21a25e92945b4004634f
+
+InRandA = ad8ebc02b5c27c85c559292964696c2e3fd406142102d74d8ae9168131abea968da1715a08c67bed550789ccc9254e404045d18a89d4a4696996a5c5cd3c87cfc3d6e92985973d6cce02ac765bec09fdda16a4776c9d92c75431121d1bd453b8f296dac1a5538555823b20f2999cc416e62eaa90a3a2788d877d03b69e399dd089c7778e4d70d831e48a9c371218478612a2ac8eae6c8278956b1aecb7874da681a14d5e5a95325400ec0341f5d58767d0a7798b56bd0882d35b1fee076529fa8a13d523a965093178959a169de1643611870f869069de2c1fd5cdc514dcf626d5da45e7a34c9ee648295890e01f222fd56089a99c6c1b9ca947da5ea7ca32c7a0faa26bcf6ec390ea439defe6a19daa689cc1a1467cfe75d9285931bbc42f2f21d802cea83fc1aa27500762242c6e624b396c499dda561aff040d6f265760ab4d38256352b682682f90c1f9aa1046838ceb916061a550370d3830c0317be41a8f8853406a8f86bda08f79b3e31f8c7746da1c62553ba706020ede82e632a9061de666a8b00bb10e5f44762a99e47ce09c68d080b931e5c34d4be3dd8a7b56cfd762f610c2a183293268258082873779f418d30c7f3517e192236ac6e208c994ec9acd82c52e85f4642c0626763484afe6160eec7f8e2fa317a1ad89ee65c7dbc18481fcc42a757f3d7b48a90cb211703f1ce112e4822057f385b497b0325d94594b66997e5dbf972b9a70b010da0363b79fad6841d4ba8513bcb728ae50e3bc7550630272a5e189715fc198b331de8931af19a0bbfc9e24947b97c0e2a751aca732389252ee53d1093bc175ec0035013ff2431e4fe3da60cc769c0bb515aed63601e824097e750c3587b0569b2897754676917c7e154aefb5f829b60e71c8beb534be1f39a0cf36520a727204339796bd24885dcae7c5e18ba40ea3c553e193a10f6255734a6bc6e171f9898969d8cac08721bea50ad906b4f8803c695e76c21a46b285a728d3f054bede0b1b72630a5eae82838714b26cf35fc0027fe685b1c7d4d422d606cd23bb68e3fa052b5504b243313892e4d1123dc6661a4bd899cf44584e975b14a8dd6bc4c6e1a7b0ba1ee7c6cef815e561abee2052462e6ce46c92b0bc1c717e0aabb1f09c21272df5f6ad650d0e0528f04c652a6a4b6ae784fabd51a3395622dc274d486c36b47d4be3dd454324e12fabed0f6761c9712d1ea6e9224653348202e4000013d4ea0300b6c9bf6a40ef32c1429c28a24a7b8d14b36a15c17896ea0ca047e7c6609177c2ead50053224a5ea12dfb23095b905fd88b422646e991d1049b9a358f88ba76ba3a24a4018594546c1bd5d4f5ab19daa88cc33f46c6194e3217b00b500290ca88c2200a3493ba935949a9cdab90c477b6717ea0df127097e73d4fb30e659b6722853d468261be609e085735fb15e075414cded0e0825ffaa99b0bcef49fded751d6ddd63d37a4f787b74094b356ffa3b5d920749990700a8c24ac573ac9e87d71d02fdf7362d830ac8080f7212a206754fa3bbd1ea21b5195d53ca67769ce53c4451020190b58c821aa5ab9909d69303419501ed9098fe11c048fa1c48d816334468370e5fc21a02b0bc94d158dbde43f9694f441da613252853c7f8010ca98720eaef82599dbf5a84b3a125eb42ee22af05a495077499d43ac084283d2813b6c0fc268e0b432d7ed59fa06187320ef49a7501aa648d1faa1b1a5e0ee2eca253629ba167a670d86587652fcca51482f704cfe71455a192bce7af801994885a34a3a5a063c79860cb0a846b75caf889ac9221e41d8828a783d9510d830a4a5ca7074ed5804e4d60f24eb90a609f07bbdda2df9f7fa5daddb1547582a6b5a41ed2350d0a4875dcc09c8f929e951f231626c3bb245f498c8899bfa9ea610522190b92ac091260e1489089bc244cd57c75b3813d35d84d48d120531ba07c9aefa76733a93c140a737223e7d58e57705425554b52be20ae22c4e69496e5364c906f78f3687c7f0840eaf70b233557bdea0f896b5ac60b9494fb370aeb69d2698f3aff06ebd85ca19fba82873a364b6671d887faf673586f551890b116bfb0541bb55da875cbcaa0751e05b73f20940a26036c1c2710283fe44bfa8b295528212a5b20b750e787465325adcc469189ec8200e866b6961ce8c8c985d18f6bca78540457bd3c12a4de82fca18dda3e6a1ea38336a0d9d5f52eb52e831afd7d7f23a2c06295cabd38bd558c30763669b89289c97d8dba5ac005fdc87534b32488eefeb5148262202db92989c543b2e82105159cda8f1948513b2a28b7fda1c78ae6c1269021a991b91a20ad698e3105cb58e2ecfab1a8d61a904e63244596acfc89f8b146d966915237bd0ad0e79e2cf029d8087d25056b94a699f6684cc83646257f4d033c7d3a6b565aae8626706a80fde6e595b7215dee1e689d7865f5b6b6fb5a3ac90d84584d15e862d2c0ea9ab60e642c76592e7dae26972dfe414e8e5873c6c6f504ec27f4a91b7b5c4aeb900e1b5e927ac57
+InNoiseS = a80b21a95b81047b96b9897ff01246dd9b46644d94e9eebb652d84bdd21a45815d7441a863e381121a78479f8a8b8ca9b3ecc170c8ac0630b1dfddba2f28a373471cd809001b36ea92e6291e26da1bbd469d526e734f45d78f2c6a840533b955fc36330f3dc865d5b7f9d6110b2b3d0eb92f34b9ae344ba06f04888b3202c111ad4749a2b923aa08528eb6a18a08719b06f4793b0dd2c958da1072628fb9a410bb7c5c2165806a718ba1ca0850c191230083928062776069b14562d513e843be94ad3e476b4c4239c1d52fbf900d2b00cd3725dd5111c238ba16a61314c59e706885aca57fc505fb9dfbe6ce6829bed6cc76e9e1b9af52805a737e4baf2f37ebde562ea01172fa29c27e4ed7244308aa253fe11481c90c9e762b11a880a6590d58ed1139f62ba60313f4afed1af24c4764d79c89fda62d06fcfc6258e88979f2559ca0612f845a5c3d6f6c5df309ac8701cdc21a648996f8d8ee97c8d894382b3994b3357afc5d06682e1095f25c1b59be76a316159cb623f04b494deb258f043f216eba710e6e9b0ee772432a45456602942a39f1912ad530b1d3d0b740e3f581cf368acd463a23d3960066d92de33b0a4a398ff673a719b52e15ac91b6a51aa8144826fd657bb517cb65e6e9782dd30a324022bbd7cd8995a5346b32970e0ae9be9aa79c91826b2c0e3c87c0030f72149ca9a77a53e946402e291097158db12aad04dd0c839aad8c220f207214cc87a07d057a81e37ba81956ab24554f657c124e10683af65fea15531d03f1190ebd0b0278089cbe01b019b194ae6ab8c9ef2c8b82e16ff1a4aad24060a62c5e89a3676d12fc1f1be3ee0e552c15808104919e64000a92d55800486af24632c4b02e631a5572d5751385aa95d4b5bbb71ebd56548a6f4a2cbcc33485803c90187b227ab2829e732b8ad15dddc3450317a966201f4ec3d70a3d04ec9a79a2c98ef2a3a693672ead1f0d20e42008726320f1ebfe162ba0c611b03a32a0c96260443ddeab0b04ff9381f14363a6a4e90b45a356907196cfb845c9e68c91d79d2e74510f5a2556605b0505142b0549416e3f8125c65afdad22a88620a05fe34a998a46ba57043488c2102e23da22f18e680be20702d326f8a86ae4bd36d4ed4e0f53fcd9d59c0cdf6a5cc80325730a513631991e420daa12b9f191af12c9b429298157754cb7ead1be85f8e826371954bb15946fa6620c8d63c235e37e7cad391829c258446522e30a60f0fa7a41c05eb0b2fc8faadad38ba6f66ec70fc62b2e9976a1d56bb2b4b26df54621f26b75af4f5030a668e211d58d36688e10a692c541648214a9e8037b86ec2009f2e6c5c0bb4c7e91db3123818441c8675d672c6e7cfde43d359d39280a974bc3e128407ca6e2883f21bc612777508f32202f2558b5b6224b6d4da3e83c9d3c582f7ab1bba82c904a1a75d6668ab0ef8893f4c24e305063e6d85471ced2d74a383451ab027613cdd094476538f9d03a55be9e4d0788099a3a4acebac42865ae436e55df2123a9425270cb113818640b614f8c487966904043d531b58c44b50571b1d45e04b56c4a0332a180f0006e3da108a08978159282670ea10b4e4e89155285bcd0a4d90827f845683b5fd708f0aa9541af9e304b2eb87c4b06f5d483789a621b5431384d7615cff8579ca2a44f157c6882ca6d15e213a9c8fd85015bf8d55cd21d274c442b66146d8dc456718599a68e8d57869e5a4ca4d00b17996c2bc483e476421205e6095594f5a8908ec8c6a28c118b9f2e7794c9920b928f4a5729ec983f2c5ae4846c91d50ddf2b90f6513949187900aa8ef828d4640012006dccfc7a225168165fb32b3a9d535de29310fa669aba94faf0c37d3a32463ec711a474e1cb20c15b36845ee4f6785d6d1a0eebc771d68d282ae2326933211fb91ea08b045113feef903bcaca3ffb6898f61815890b5a09cbe2413e5394f3d65a42250fae3930ddcd1d3d63bd26714640b8ae4cfaa3e57f0fc446ebc6e0822e6aeca4625252591568e1f80aa29a0679e65d9c6d19ea2f388c1a1a526db1f674f22ceba41412fa247b192eae509ff831be8fe55433a69570a7b3b24f1c8d5b443dcadd25a11f0cc432136c79bea5fb5a83de240c64d0717a7299ce499496e71e675c20428834445aa99db4124df4615865b68555c8ae0b021a824324a81ce0be995352b84490ad84413608c12dc2a00e4a53bfdbbb403a2847dde4616a38ed47cc8b04334cde0269ef0120fdfdaf795eec3b98924cce1a3924198e36dd6bc638faa01d76559942508e400c5f10573fb98187a562ca966dbe1b900043fcec5d826d17eb4a1e3790875d05baba956e6cb9d88b211bba112217d01ca67e83e3f6ae187e82e7c3398c127f894bedc489f15f6faad152f2364ebc8d63009e241d01c2db7bb9d6487de303a3915c4699c3e9857d8403671d2a774fe618d34b75560e78285f11938a343d8f5663a396c642b8dbe44aea56325af044979be3cd37b0e3b69436f45d5e95883a47e09d
+InNoiseE = e845be9491fc0c92163b96787e80bf0ed9e369841d76e3ba6a87548fb7999f66d78d96a7d296e777fe3db2c3033a11064940d950d84f01b3d0aa612119d18c200225f7d554a8f2c6c921c28e67efd92587a0f084578f5c36473500110ca8a7415c55750a75f004823d1be0cb09c6488918ea38c3778c212e2cd80081d95950c3fdc1cc61b24b5c8991069867d196189ae04c893be3fb51aa794abfe72b33e48ea2af932238e8747b37459854e30c84d223faf5cbf0707ae958483b3553b3a64aea4afc97eb296078007e2bb480c911795eb3b9954a83fad85d3e254f434c3d1075e9180b32fe7b2e083c0bf3469cb2e8ac6aa7c59645c9d0b3e2fc78ad19014546a545d7ad64d0ef2804eb9a8495c4805de8049c278ef24260019b0a1dd159055ac289067820e2c8cfa1cb7dae90e57072d0d14921ec2ed8ac2080011f004a95405c5167023b0e6e9ed2d0b15b9a0008a6aebd9677feb4cf0d6f904dc0bbea8ed11601c8bea66581c006e5a37ead62954e7ab810537f06e7d1210c80ff844fac9127c1b2005d6541dbe821e490e008524671a653709c249db99940567c4292166bb508984120ea44ae4180f62365d97b3c0153defc41099a5715a4f564d1454c172e3b8366a9a8b5415c99a9d60f6f1fe5a06dc58b7782dfe727f2a8932d45f5289e00ec07f6932d4a44f1e32bc446e9a69e611bc43b3015059f9093172583a0e2e18a2a557fe8690eb852cd1adbd1eee0e8ddbf9de930658830262e97ac30ec3893945485040d5caea90c3510b924a9ca842f281260217e2aa49a7155849c13b4963c708b71ddca47f9849f3347088519a8437462f348e7745aeb40d2eb36a2224617d85220f18f2c99d4c54ccc94a1dc1e47988d95470c925204014b201065b67c785d2a6f23289ad89df746ed90b1fc5a23c8be594a3943726d3c47efe0b087255413ceed195fc6bfb32fd8640b995f382e2d945645a05682ad74cf9ac2e3e9f13b958f89a541edb34558363bcea95315d9e7184dea7f45c081e1ed74869685685148164e4aac81747fe43be7d550a06885552416dabae41c23c89c4791e2110b07a3b4007e2a2d2d6dab709c384d09a92f91316225ccc46980c5ccbfc19bbc91f2d818f557f2f133780367a4954bd1fc8121e86ef57f1a59419d20162baa6b465d61231f5806dfcc373b8510b8d5cee65a09f932c54c71212c3570306baef65a6e8fc0e533b10e0abaea9105b3e5daabcfc82c92550c535c646e84aa4ea50ba7d8c78f419f61d4f6d39f1daf4deb0a48136c6a5d65f2f8db6612ec654795241c0543a1bcc69f8a65dfae5c76fbfd8c105a056b5a5d7e586087719301ab6804f2d5c1988a420b45f58a3e717725ec36e9c1877bd515c814da53822022763808907f4c56384131babc125b1562884a538cdff5e0c137e61b45a40de995c75929a8b1beaed8817ad64b15a823c1f6345d0924958310f0690c576a459d572b32496cdc53fa424cbed92b97a4214974ee10daa7c19d065299ac11151a4eeae4dc6771f642b0661c999ecc96ca58a0c7e80a621c6b32d1046c38ab9368269cc61a48e532171606213c5d5bf4ff6a19b4d36bf85b12b830903ca70576b276195356c03caba1cac6d67e923e2b498371985664cd0a15b46f1253822c3870927202f08dfee8d315255d09548ab2b698c8d19d9b2166a496c4431b5e99644620ac7663ba3cefad032bcafd77559d4fabdc71451c17f074ee12ad13443698a06c758c44afb28190245b221874073a7cef2d8ae46d5d2c2ce6b7fbd0c92978c1dd6a2bba3da1655bdb9cc09c0a24d1c4822c3ece61708414f996500ccbf0790e2f7f9fdd739c7aa7ae1d0be4ba4181910f9d339b6a1667c115b6b6884dc48642f551fc7822ae8ad55d6cbc32141762f1da6ff967720622daaea75455e6a999535763a17248426532511e33d21e00e784258a5079bdef43068acd352e7a43b269ceed99ec518db908ce55dad54c46277da381efd1a147854b492aa31b45f86f06476d6b2cb078cb8d137ab94c3d419dc5b67b6051286c9feb1a9a24d92d8ac781dc7c7b458e30bbce43a18ff2c4343560af9109cbdf69b49ed0ce24304015fb0adb88c2e18f0e50cb662f5635f6240ea0ed7598f4ef07da6d21ba975e9411e39968d5461977104c283ac14bba833cb5c112c699c25064bb22f0fb80e11cebcc0e70a90556e61399049e5880f2946e3425a4330d8ca8aae68d2a4160f1436d0a37aa91c3651bb4bef354f82404061884e6dd55ec591bea4a52b0e4096dd04514d4cbd891495da4d113381a756171d00e8d74d42d2a06001812fc63a10731918076ac892573fd17eb263dc0490615a0412bb38e793eaa146758b4c08af825936732f0bb8616151574c2294b51bb9a1bca28fbc7e29b30e5852c910f40c3d920feadca804e7569e827747ae976b6e5852a76bddea504cdc5bbdbaa06de2aa78686f0973845bb7563fc3c03eb6fa93162b40f56d50bab801068dfc3934c4e7a2c6708c9057e72
+OutPK = e092dbf9d91122e3c8c9b32888abf88fd30616761cccd9e4668c8224c749b688e8f27683d5ca9bac627d876c0ce8f16a872b190b69e839729d51b3a44742af8690498480044eea562de9fc9223254b1ee4c0047763914a21c93876e8e4a8650834774d4eef5b18207f114cbd124c158bae99d658a3718ad0dfd85504815a88808662264a90282e6fb9ca32863d5c789172ca65201704d2e94042aeef4e461ad19d9561abbbc09ca279aab71548b219dbe15199131c7eb9427ef9874297dcc51d83dc1d57d0a9260350a250f9d9db527e4e903605d1bbec04329288f081099218f715a8e808c9a222ea9582b6268a9909a357f4dc1d6d5504253adca14110e416f5aca00dc6ad747dda9ea34085854589062f557434adc9656b1357c550e972c86005e41bf08ac8817c4910813bb44ec3ea63a9b7acd1882695640fdcdcfb943baaa0d36a874b329c43d0dc82e7e6b1ae662abe23cd8eb1382c3241f2614894842a43e969805159846a38715cd98244260c604618eaefc89548648fc6d5f23f28246c033d5b3110267e0b25f6adf9432156bd6b9dc42bfec7d32b5b1abd80d19ebbf2388ad3af0a55e92da8a311434ba38a8b3d6252a7165596c7825e027ea95f619df33413619dfaabbc4b7119a9a8227044cd7827046b2e846ccc12bbe58af4d17d7957a50b6830c55898d220a3cf6500fb1d901380452209401837aa9c6c3403d71be9fdb43f5f64a5b866aeeb559833e604a463623dc9b5ad397ac8e3e7b0520ac610743a6e39a4a0a01006bcfd59e38bed07c7360f772c45d1dedcaf18e2593566d646292911bbdd7d632f57565712765fe90b0109ea3db99da61bb5422ea15767082184e221bbdb09e4094e58ecefff20560866c6eba6d1d7443180417ac8690223e9dd8c99a18e442e80cb4ba0e0746f644f34996200d8db57e6d7927485ae487166665880263cb1bcf28e1c4977864ec9a0b4089e5871be09e6a89879ee48aa415bc0a1d914a1faac0c91ae3889554e594842b696b293700651c0836e081dd250b00e5229a2ea113907b1a0a39b5a4555f66b4baa5dcd1bb02ff997c75d40c98a13474a1892ec463cd2eea565ea9c26bb987613c5aafed27dd42eaa212a09a01a322b80ff568f9d16c3ac70c5b958b7cf16fb9a17313858257133290a5873d34b6957da55b8a5bee2ff2a4ed363b12076c033746bc5b06a9e9c41dcb5780d0d29c0e73ad4fede7582256c1b3bfebc96245af8f97d6655c0606b1bf1bb8a27c719c41117402f9f93fea5bc0be6bdb14b96657de399a1c1206da328342b2d78aff767d7116690b16e0a9385b131a08e6230d0306c0bcb8e1685c1f857ab98d6f865080719058915beec43539640245cc6bd478719c39a691099c225b966ad7a838c4c08beb4033649288bae74978eeb06a6e36486ef1766955e3c31a525f377fc6abd050a52ea3e383ab792606827f276a8a736887a9cafb80314107e9c53d45be5ca85ba0c582683328839a2dfeb044abf56a32d22a4146b7aa7c7c926404b12645b10dc4013058dde023068f60501d9ecb8234a08992220d923110187f26b7b946c683b0d9c64f6ca397f019199ea72e9a13e5552b9b16c95e66eed44149e980c10a46b76c9451f8665f69a716d7bd5fe1858e677509a1c6ba3a8662aab81e42d7e39652d5c09141e8d3899c3c15a4c41bc1489d407ac1e949d37b1d359b58b6870c87e5c885880d8bbf2889b634ef21379f8b9f9a68344d74c4b9c5ea4cb7be919ae0354a189064c0a013c2b655264140c3dc43a812c762d00db994a5cb9a98a35cc582bfaca1c134636a76393ace07e46167aaf6ea22d783a6c8d0d891b5669b711ea92a701a660a2e7e1a368a1f65bd63a8cc2041fa30a09108c002d198d10cf5d821628a8cbf6ca45ebdd5a0018f8a832684fcb91b66f03c0bf56b9413c405457f563347f2928ef63bd3c6531e6ec412ba914ce9f2e576c913af8eabac93492ac2aae23233481afa0594a02cd6a3d7451eb67ebaa17972b6c749e765ebf9b1fc8953eb8b912ba2a6aed334726fe3b37741a26499f62928e0b460da43586923487e2648beb2c2ca59e64a987100590284ab2d25ca215c8ea765d31372d63547627221dfe697fd2db5e6226ac8ce52d0155604ad8c07c799a56e828bad21400421a92da4d455172c2ee099aa13f32a0fb02eac95487624c888eba13210434f52505bbd3672e83b2157cd2890a80e42475bd6e4c590ca9af555dad24e2694dd86d923a62fe313adc2757e195a2f7a8a268d1014a0bdc5bd4b6fd2c0a6a77468ea8bab7d0abb339ad9d186e172a2dc40d2b12cc631c0ab30017ac54f61ab239efdf257ac26ac6e3205ad84e5bc9876c284326430baab511444460dd08fbc5cd7c5ca2e14185c8148552aa1bbaa319b2cc937f17aef4711862e944f2a9360c5d5a96c6baa7f40bee36ee65119c243e78a08eba11e48c109f652844af9837056635649169f2bb3d9dc209543907a6ae6d837f68d670bc7b0626b86b0ab7
+
+InPK = e092dbf9d91122e3c8c9b32888abf88fd30616761cccd9e4668c8224c749b688e8f27683d5ca9bac627d876c0ce8f16a872b190b69e839729d51b3a44742af8690498480044eea562de9fc9223254b1ee4c0047763914a21c93876e8e4a8650834774d4eef5b18207f114cbd124c158bae99d658a3718ad0dfd85504815a88808662264a90282e6fb9ca32863d5c789172ca65201704d2e94042aeef4e461ad19d9561abbbc09ca279aab71548b219dbe15199131c7eb9427ef9874297dcc51d83dc1d57d0a9260350a250f9d9db527e4e903605d1bbec04329288f081099218f715a8e808c9a222ea9582b6268a9909a357f4dc1d6d5504253adca14110e416f5aca00dc6ad747dda9ea34085854589062f557434adc9656b1357c550e972c86005e41bf08ac8817c4910813bb44ec3ea63a9b7acd1882695640fdcdcfb943baaa0d36a874b329c43d0dc82e7e6b1ae662abe23cd8eb1382c3241f2614894842a43e969805159846a38715cd98244260c604618eaefc89548648fc6d5f23f28246c033d5b3110267e0b25f6adf9432156bd6b9dc42bfec7d32b5b1abd80d19ebbf2388ad3af0a55e92da8a311434ba38a8b3d6252a7165596c7825e027ea95f619df33413619dfaabbc4b7119a9a8227044cd7827046b2e846ccc12bbe58af4d17d7957a50b6830c55898d220a3cf6500fb1d901380452209401837aa9c6c3403d71be9fdb43f5f64a5b866aeeb559833e604a463623dc9b5ad397ac8e3e7b0520ac610743a6e39a4a0a01006bcfd59e38bed07c7360f772c45d1dedcaf18e2593566d646292911bbdd7d632f57565712765fe90b0109ea3db99da61bb5422ea15767082184e221bbdb09e4094e58ecefff20560866c6eba6d1d7443180417ac8690223e9dd8c99a18e442e80cb4ba0e0746f644f34996200d8db57e6d7927485ae487166665880263cb1bcf28e1c4977864ec9a0b4089e5871be09e6a89879ee48aa415bc0a1d914a1faac0c91ae3889554e594842b696b293700651c0836e081dd250b00e5229a2ea113907b1a0a39b5a4555f66b4baa5dcd1bb02ff997c75d40c98a13474a1892ec463cd2eea565ea9c26bb987613c5aafed27dd42eaa212a09a01a322b80ff568f9d16c3ac70c5b958b7cf16fb9a17313858257133290a5873d34b6957da55b8a5bee2ff2a4ed363b12076c033746bc5b06a9e9c41dcb5780d0d29c0e73ad4fede7582256c1b3bfebc96245af8f97d6655c0606b1bf1bb8a27c719c41117402f9f93fea5bc0be6bdb14b96657de399a1c1206da328342b2d78aff767d7116690b16e0a9385b131a08e6230d0306c0bcb8e1685c1f857ab98d6f865080719058915beec43539640245cc6bd478719c39a691099c225b966ad7a838c4c08beb4033649288bae74978eeb06a6e36486ef1766955e3c31a525f377fc6abd050a52ea3e383ab792606827f276a8a736887a9cafb80314107e9c53d45be5ca85ba0c582683328839a2dfeb044abf56a32d22a4146b7aa7c7c926404b12645b10dc4013058dde023068f60501d9ecb8234a08992220d923110187f26b7b946c683b0d9c64f6ca397f019199ea72e9a13e5552b9b16c95e66eed44149e980c10a46b76c9451f8665f69a716d7bd5fe1858e677509a1c6ba3a8662aab81e42d7e39652d5c09141e8d3899c3c15a4c41bc1489d407ac1e949d37b1d359b58b6870c87e5c885880d8bbf2889b634ef21379f8b9f9a68344d74c4b9c5ea4cb7be919ae0354a189064c0a013c2b655264140c3dc43a812c762d00db994a5cb9a98a35cc582bfaca1c134636a76393ace07e46167aaf6ea22d783a6c8d0d891b5669b711ea92a701a660a2e7e1a368a1f65bd63a8cc2041fa30a09108c002d198d10cf5d821628a8cbf6ca45ebdd5a0018f8a832684fcb91b66f03c0bf56b9413c405457f563347f2928ef63bd3c6531e6ec412ba914ce9f2e576c913af8eabac93492ac2aae23233481afa0594a02cd6a3d7451eb67ebaa17972b6c749e765ebf9b1fc8953eb8b912ba2a6aed334726fe3b37741a26499f62928e0b460da43586923487e2648beb2c2ca59e64a987100590284ab2d25ca215c8ea765d31372d63547627221dfe697fd2db5e6226ac8ce52d0155604ad8c07c799a56e828bad21400421a92da4d455172c2ee099aa13f32a0fb02eac95487624c888eba13210434f52505bbd3672e83b2157cd2890a80e42475bd6e4c590ca9af555dad24e2694dd86d923a62fe313adc2757e195a2f7a8a268d1014a0bdc5bd4b6fd2c0a6a77468ea8bab7d0abb339ad9d186e172a2dc40d2b12cc631c0ab30017ac54f61ab239efdf257ac26ac6e3205ad84e5bc9876c284326430baab511444460dd08fbc5cd7c5ca2e14185c8148552aa1bbaa319b2cc937f17aef4711862e944f2a9360c5d5a96c6baa7f40bee36ee65119c243e78a08eba11e48c109f652844af9837056635649169f2bb3d9dc209543907a6ae6d837f68d670bc7b0626b86b0ab7
+InA = ad8ebc02b5c27c85c559292964696c2e3fd406142102d74d8ae9168131abea968da1715a08c67bed550789ccc9254e404045d18a89d4a4696996a5c5cd3c87cfc3d6e92985973d6cce02ac765bec09fdda16a4776c9d92c75431121d1bd453b8f296dac1a5538555823b20f2999cc416e62eaa90a3a2788d877d03b69e399dd089c7778e4d70d831e48a9c371218478612a2ac8eae6c8278956b1aecb7874da681a14d5e5a95325400ec0341f5d58767d0a7798b56bd0882d35b1fee076529fa8a13d523a965093178959a169de1643611870f869069de2c1fd5cdc514dcf626d5da45e7a34c9ee648295890e01f222fd56089a99c6c1b9ca947da5ea7ca32c7a0faa26bcf6ec390ea439defe6a19daa689cc1a1467cfe75d9285931bbc42f2f21d802cea83fc1aa27500762242c6e624b396c499dda561aff040d6f265760ab4d38256352b682682f90c1f9aa1046838ceb916061a550370d3830c0317be41a8f8853406a8f86bda08f79b3e31f8c7746da1c62553ba706020ede82e632a9061de666a8b00bb10e5f44762a99e47ce09c68d080b931e5c34d4be3dd8a7b56cfd762f610c2a183293268258082873779f418d30c7f3517e192236ac6e208c994ec9acd82c52e85f4642c0626763484afe6160eec7f8e2fa317a1ad89ee65c7dbc18481fcc42a757f3d7b48a90cb211703f1ce112e4822057f385b497b0325d94594b66997e5dbf972b9a70b010da0363b79fad6841d4ba8513bcb728ae50e3bc7550630272a5e189715fc198b331de8931af19a0bbfc9e24947b97c0e2a751aca732389252ee53d1093bc175ec0035013ff2431e4fe3da60cc769c0bb515aed63601e824097e750c3587b0569b2897754676917c7e154aefb5f829b60e71c8beb534be1f39a0cf36520a727204339796bd24885dcae7c5e18ba40ea3c553e193a10f6255734a6bc6e171f9898969d8cac08721bea50ad906b4f8803c695e76c21a46b285a728d3f054bede0b1b72630a5eae82838714b26cf35fc0027fe685b1c7d4d422d606cd23bb68e3fa052b5504b243313892e4d1123dc6661a4bd899cf44584e975b14a8dd6bc4c6e1a7b0ba1ee7c6cef815e561abee2052462e6ce46c92b0bc1c717e0aabb1f09c21272df5f6ad650d0e0528f04c652a6a4b6ae784fabd51a3395622dc274d486c36b47d4be3dd454324e12fabed0f6761c9712d1ea6e9224653348202e4000013d4ea0300b6c9bf6a40ef32c1429c28a24a7b8d14b36a15c17896ea0ca047e7c6609177c2ead50053224a5ea12dfb23095b905fd88b422646e991d1049b9a358f88ba76ba3a24a4018594546c1bd5d4f5ab19daa88cc33f46c6194e3217b00b500290ca88c2200a3493ba935949a9cdab90c477b6717ea0df127097e73d4fb30e659b6722853d468261be609e085735fb15e075414cded0e0825ffaa99b0bcef49fded751d6ddd63d37a4f787b74094b356ffa3b5d920749990700a8c24ac573ac9e87d71d02fdf7362d830ac8080f7212a206754fa3bbd1ea21b5195d53ca67769ce53c4451020190b58c821aa5ab9909d69303419501ed9098fe11c048fa1c48d816334468370e5fc21a02b0bc94d158dbde43f9694f441da613252853c7f8010ca98720eaef82599dbf5a84b3a125eb42ee22af05a495077499d43ac084283d2813b6c0fc268e0b432d7ed59fa06187320ef49a7501aa648d1faa1b1a5e0ee2eca253629ba167a670d86587652fcca51482f704cfe71455a192bce7af801994885a34a3a5a063c79860cb0a846b75caf889ac9221e41d8828a783d9510d830a4a5ca7074ed5804e4d60f24eb90a609f07bbdda2df9f7fa5daddb1547582a6b5a41ed2350d0a4875dcc09c8f929e951f231626c3bb245f498c8899bfa9ea610522190b92ac091260e1489089bc244cd57c75b3813d35d84d48d120531ba07c9aefa76733a93c140a737223e7d58e57705425554b52be20ae22c4e69496e5364c906f78f3687c7f0840eaf70b233557bdea0f896b5ac60b9494fb370aeb69d2698f3aff06ebd85ca19fba82873a364b6671d887faf673586f551890b116bfb0541bb55da875cbcaa0751e05b73f20940a26036c1c2710283fe44bfa8b295528212a5b20b750e787465325adcc469189ec8200e866b6961ce8c8c985d18f6bca78540457bd3c12a4de82fca18dda3e6a1ea38336a0d9d5f52eb52e831afd7d7f23a2c06295cabd38bd558c30763669b89289c97d8dba5ac005fdc87534b32488eefeb5148262202db92989c543b2e82105159cda8f1948513b2a28b7fda1c78ae6c1269021a991b91a20ad698e3105cb58e2ecfab1a8d61a904e63244596acfc89f8b146d966915237bd0ad0e79e2cf029d8087d25056b94a699f6684cc83646257f4d033c7d3a6b565aae8626706a80fde6e595b7215dee1e689d7865f5b6b6fb5a3ac90d84584d15e862d2c0ea9ab60e642c76592e7dae26972dfe414e8e5873c6c6f504ec27f4a91b7b5c4aeb900e1b5e927ac57
+InNoiseSP = c64beb7608609174039c0966eabff18173e661d90f131e87d7ae8150e5c34773303d482a1d83f58ef58037e0ccf1aee263b3a8e0a6f4716019c3b735a4e5b4cc111c0b34623a65929394a9357224214776813e93fc1a03586de232a7a8327ad2be35a6542eb9adf031dd2a829662c2923fc25588de898075e4bd2b30921ccbd0f13280263a689fd4fb107aa35883f8212c858ff08aaabb6b0259154a0c479f40aca2a06d6319dd7ee75d6fc048f5ad6425c966cf1c6afd97108164c8828dcaf86a96264e85123180d4d97e4a43d620d9325b359a1788db6c5ce4cd08252d4c0f9d491132cd217da62ddea308ac8e992cbecb7a66bbe0909abbaff2a96f925b79f6516ec5c78ed3da0154030cbdc7ebe50286540ba84c54bdeb2b98f2693d69d9de9434a18529071a0ff96784288fd43550233ebeef51fef54e115ff5994b87072e2583806773d33969c8eb3bdba29a9012464278236159b542bd30aa8c6718ca3320ab6534455dbba143b937b24cd702c8d4963854bd819f9dabcc000005fdada7bed44a94263843ad6c08f7c05c09829c72510bc432411eff258c7d783e1676fbc7757321c6d845fbcd7ae609516427588cb4935438b76a64ea41f5f92ba167a25737748af281bb2b3646659e10db4896a4865013126cf70ac85098a305627a102cb4fb4d9d044498019604ef082f21393b588d81dd1a97a5640e171dad9dac6ded9874e52ad1eaaff519be29a35dc6cb60b044f5caca27eb9c96842758f2500592fe1f408be9381afbd95b557b3022b9ab00e2060498a00f5332802522ce41c6918a3a177b088d321b082b09eee19acd1986b9cd4f0802f6ba146e6c3859d0af7fd3a51a1d6c680717e3b1cf6e9b42e2a3c9094140f90289594e40a196112793e53a7a749fba7539061aef4518db2c9c981ee249d12f205e9f241949e18171e81c26700694bb3bcc474949f504ed98fcc827cc8e9b628b56ede94c3cca63e75c32aa9b41a5526c0160818c9c18ab484d49e015facce589c340ebe41d6c4f9ad66353f5ba6182d838cbf554a8ad4bb41b7396362d9dda2530a1411c15ba4a61cd473d0269e0d76e9c5aa8b3902c169269220c0076d215b61424237bbe46cad136d6c0dd220d42ab265402698b1d821a52512dc7c6ab0162b402ff8ab1b33da922abc61840ac76aa3505136789e07d461a08715acd713eaf3f42f40c46f848da48d15cbc2adeb705b29c33ebd330f8384501845eada58c80654a2cea07a3d558e4e80d81b8f943840b73a3272479132a2557efa6566b0688996f0e44ea171a52582a5abbd49fc12d35536bcc137283457de9d53a87295568cd5e6338a7b5b3664c26d18c99024b6143a5bd657f96e2320869305498864e34e9c046e6968705bbf530ddc73bb954817a0161b3ca898046b7eb97270ee48fb348a34b39d14933e18a47df80362ed4fc0227848fa448d061a11d97b62123f2985133d15a59f3d4dc83cb19cca11000320324c4a4bb008c965a2344237418ad00a5f2dfb609d89f89998e7e9470031bf0b06197198bdfdac9498f528ca7f817318e569816caab2944414113e3f89a08200e4921dd3ab85b5782b569d610b41f7a61d6ee2406e3e8e06429bc3329765592f04fe1403fc0fff88eb28f6587b2b6b1e5cc8cf1d44983c70e4de001500cb71807a8ea9a00f9cae380c8087fe8ef6ab157d90ccf234b206cee3823c3f775365c972422d0597bd01ae9e1596bdfde7c53617bb3964904c4897fb8f07515b525f3558715498168f12081b698a91e7b9ab7b80bcd2f1998a92255a4af3d4a169e73d3d255f2ec392c1a671aabd8be28c21207c636b12e49da9bf1978aa74723be73ca9872222e0ad439f681946e484867565f8ca48656e8f618bfda386209d9046a1c886b9414bd11e93178d0cc1944d84b987882884ce8271b5532332980c0d5ca8c629b8b81f65f62aa5545dba61e215249a7f2457c06965004db62e31e1344a7fe3557105580e6c181a184079090b535a7e15b04c434277b896cc98c7e56d2a8492b4f25a91c211d4a0bb219fb087453ede72402a17386c1c96770821f6fd4dfb97ce84ffe1d15133b765c7f6fc4b83d85b54704cb3bbd4a3221e990d3cd521874894993487a6fa25463645b89b8aa5aea272c9e2e0e2e14f010080f2e4f6fc6b771a7e7c377e91ce8896105e1e990714dba41a925479aa37bef79a963969bc16ce49888b8513e209820e3116dc786c39b8f5a4861ed4482f45e3c481fae6b6ce4a0fb9dffc76dd0b3b5046bcbaea678821655c434055106cdb3d2a88830d91345837bad1ac5cb230af6995aea644cd87e38a60393d024122d1a8ded1de4cff1050e98040866dda4c89278d02aa6bf5c4e31f442505e07a2889189c45994c5ced0de41b58baf44f2a7fc34259909fbc2f8b93356bf362086ac2493ff40ab3652fd9a890aad5c6c77a20052d5398649056cfbac185018cdb0c7779ab5898ce65b5af261921668d3b6b9186f6692db8c4658f29dc3050d7115
+InNoiseEP = 56580d3581e9b313853d989e7aa880543520dd4d79ba81873613024324416364673aa8eba9f6428ae800496d492547f1205d67af20d2c6bfa4029bcb560d421ac9ede485fc9ce525aa141fec013ad09b7b5ef14b24ce5761f2065850a6d9c7df2843d610a00b98e52ba54cffbaf24c0596609c3314d1823891ada417b425612df3ba99e287f65cb7e1727cb510c92932bd35511dcf81f9b4bc81bde3a2b98d7e3d7a847c64172c7f1fd6a5d214ceaeb955581613b6a9d28743569bbd711920a768a0bc31be652460497cbc8dea2eb7e54d09045b0f89f36c0d111c83c7b46406fd9e15f3aec966bf6fe6836d4e1c0f41ea729358621c2ed3078b26936096f73a67964af5e77ba41be07238d6a062c6582d01ca41ca6e8a75079d1497119466550d25d06e84a979adcf30ccfebb158482baa111026ad314fbed709f4f21d0700a2e82ca94837a314891dd573e64d53a8bc49a0d796fa1b4c7c640b9739c7d53518d74adba7f6c1428353bb628f79d1ca195f4aacf97a242ecc6336e0bcc89a29d133c55d9778be105e4cbef773495342a425858ac2a6094dcf4eb78f139bd0cf0918246b8e89281b9bf5949c452dbb45a199dfda959c369b2bdfb2221aa0f5d7f4fef8087c6d04bd56f34b8f98297c31feb281cd0b0bed525f32552079e274395f3a16fec6dfb16fb7558be4169bbfda64131e8e93318f69d974f841964d4278f53e910e7f29287073eb7d939217dae13b10be11f4ad27dbb505198a9c2402bf3649b95c06e78bda95e504a6a91b6ee77d7ef3a51d07552d692a920df1a5450a67839c39a8a636b89b14b6d7d8b6685343ad2539856bbd50a24b0134f56d5b6c28069efe7089d2085a799e7232a4c4e1785d58aed5d489b6ec2c49ecc2b5069ea29acb82d3bd61b77dedc67cfa2b1964d8080e850f47bd4a9052d043eca734487d526c2453c6d3722a01810a9a20c73903d9a4e51663683b17a44952dbe00185584a19f8a85ba56a0dc6f6c2eb21407de982ea6c24bb4ba99941cdf846c2822e51d88d7b88a6005c642d607c67eed65b63466b050e2810a2777de0cc055f100c69c7219cafe07936618f54f981414394387ad95b1adeda3d94edf6a2e4db35cd0b463b17aa7a1973f5a225226a4ec2fe6ba4c504aed32cb4abd79374ae045fe6a4c7bdbc0aac0b8bda624dc6099de66aa007c4938e0b4995466f8c3fe7cfc051c64a33d8c8f15eb7520dc0c35dafab4fc8c595859f000bf44717c9be42448eca6da25e0b702eebf6b272f41dab06106093fb0bb8e27b584e6c86df28616df637820f905b623503bd14523948545290c616fb30213e7da511965a2c81576f4a0786474a3c508a68fa92168b8847c6e6755c8fa8c5c9368381104545667d1221ab59a13dd9dbef2b0ed36736e90515c2175e408956a9085a3950b7da321668b97525580013970f415bde3225534b82f2549e0dc339e117bb1d9815683593bb18d2c70d387be2a723097ca6e30ebd3322d18d85c1241aa1e361828b7cf8c229ca177103d8c1c028bcc84b80a1013af478198dea250cd20f86d46b6e95f52b8e2b40eade14c7974a563d6a85e86dc69396629d58aa7b6110d6da33a7b80555ba543e25c987754522dc96db560e24b72e9dbb260522cf1e6da744c5faf989bf14e128647457ad26622d3aae638dfd49fe69938421e8a9d9f1ea0c8720d7e6a9da7893c7440fd920edabe4d06419598e2cb2e59606dedc006bcaa2acbac9a2ecd3065697b92059c299aace3f02cd51675049f820b4a4e7480026bc71e19e388df193a0ab98be36a353198a7ae0ccbf928e67eb427137bf6ce25fbec0be741fc4912a22c68875d37f2ac823008393461a684b643c0b39ac0f6eb35b9a2ae0953cbe1163a93e7a104acb035cbc00ab86ba09b8bc1738766602579e15ac21f94686095d0c82b945330834f633b655e54984948f7dc6e79a67e52c195726e2fe6d518e2615c9a43a3aa2e69ac2e8c67f1615db3070f671a08a0d2250c755cdc9b97901e6b36f68d9ce34526330a17f98bb2a12c9d09aa4846c0affea228a6705b5115667c231acb86e62541876d51e2622840181d18d99d8a7dea535aba4e62a8d432280db67ecdc4c5b997c079c2214718d0dd7e5fabfdb4ab9815340c66c0fada45c6041e4bea112db4627ce4a08a5b3e42e9ea8c390ee84636807b4d4b4759958951fe3cf64608d7b7799a42600a934c75b85843e436cb4a70440025a5ab594128190ff96c1c82d555bdf543b82d3bd88fd078b4b2c51b6171c3e90587169938535c48c5dbea13b6b187341f2f61d835b99e4fe3799e5a3af787cfa68f2a100c6f38c120ad73f36d95da3de1184103b0f192d80cce06b3d36b20acd5dd116a1ac2b383aa4f37876e107a4dc01842e12d2d6b819a8139bd7b9214b3e7dc44039652bb8acdb12f0fff23f7ac445804281959ac1529d63cab2ab6170c220c6983da677348ef13c3840835d6b14361798f598cc2ca4b16ac76affe8017a63e6225ed4a5cd05b
+InNoiseEPP = ffafff1b000c00008000f0fffebf00b0000000fcbf028000c0fffabffd2f011000fcbf0000002000f0bf00f001100000c0ffaf00e0ff0a00ff2f0100001000ff6fff1b00f8bf00b000d0fff2bf01c00130000400ff2f00f0fffebfff6f01000000c000000040000c000500ff1b0010000070011000ecbf0240ff2b000c00000000fcff0e0000000010000c00038000500000c00040001000e8bf00b0ff3b0004000040ff0b000b0001800010000400000001000000c0003001100000c00200001000000000f0ffdbff1600fdafff0b00040000c000f0ff02c000b000200000000080ff1b0008000340fffbff02c0ff6fffdbff0600ffefffdbff06000030ff2b00f8bf00c0ff0b00ecbf02c0006000f4bf01c0000000030001c000000004000480ffdbff020000f0002000f4bf014000f0ff020000f0ff3b000000fe6f0030000c000280ff0b000700fe6f0000000b000040ff1b00fcbf0180ff0b000700fd6f002000fcbf00c000a0fffebf0040fffbff0a00ff2f004c00f4bf01c0ff1b00e8bffc2fffdbff0600fe6f01f0ff0600ff6fff5b0000c0ffefff0b00f8bf00c000c0ff1a000100ff6b00fcbf0300005c00f8bffe2f00dcfffabf0040000000ecbf01c0fffbfffebf018000300008000280000000ffbffe6f00f0ff0200fcefff0b0000c00300004c00fcbf0180ffebff020000b000f0ff120002c00010000800ff6f000000030004c0ff2b0000000380ff4b0000c00030000000f0bf010000fcffeebf01800000000f00ff2f000c0000000030ff0b000f0000b0ffdbff120004c0ff1b00100003400010001000fe6f001000f4bf00b0000000fcbf058000b0fffabf003000b0ff1200028000f0ff160002800000000f000300000000ffbf014001c0fffabf0080003000fcbf0100ff1b0008000440ffebff1200ffefff5b00f0bf0400ff0b001300024000f0ff02c0040000dcfffebf0480ff0b000300feefffebff0a0001800030000400fe2f001c001400024000f0ff0a00028000000003c0024000e0ff02c0feefffebff2a00fdeffe1b000400000000d0fffebfff2f00fcff02c0014000000003c00380000000f4bf03c0ff3b000c00fe6f00e0ffeebf03c0001000080000b00010000400ff2f002c000000007000d0ff02c000b000e0ff02c0feaffffbff0600fd2fff2b000400feaf0000000f0000b0007000fcbf0200000c000b00040001200004000400000c00f8bffc2f002c000c00028000300000c0fe2f0130000c00fc2f0000000b000300005c00040002c0ff0b0004000030002000100000b0ffdbff06000200002c00f4bf04c0000000030002c000d0ff020002c000100000c000b0fe2b00000000300000000c0000f0ffcbff0e0004800020001c000180ff4b0000000100000c0000c0feeffe0b001300ff6f01000003c00480feebfff2bf050001200000c0ffaf00000003c0ffeffe5b00080005c0ffebff1600010000dcff02c0020000fcff0a000440ff2b000000fc6fff0b00f4bf03000030000400010000100000c004800000001700feefffebff020000c0ff0b001800feefffdbfff6bffe6f002000100000b000d0fff6bffe2f01300000c0028000d0ff0200014000100018000070ffcbfff2bf0140ff0b000f00ffaf00e0fffebf0080ffcbff02000030001000f8bf0040000000ffbf008000000000000240002000f0bffe2fff0b000300fd6f00000000c0064000000000c0fe6f012000fcbf03c0fffbfffebf0380001000fcbf0070fffbff02c0fe2f0000000c00fe6f00c0ff0a00fd2f0010000800fe6f000000ecbf010000f0ff0a0002c00030000c00fdaf00200018000780ff1b000400010000400000c0018000f0fffabf0030001c000c0000f0ff4b00ecbf0280002000f4bf00700050000c0000000000000700f72f006000f8bf008000f0ff020000f00010000c000040ff2b0000c001c0ff1b000000014001200004000240fffbff0a00024001f0ff0e00fe2f000000f8bf003000ecff1600008000f0ff1200ff2f002000fcbffe2f00d0ff020002000000000f0000300000000400ffef01200004000030003c0004000030015000f8bf05c000c0fffebf05c000f0ff0a00014000f0ff0a000400003000140000f0ff8b000400fcef00000004000030003c00040002c0ff0b00e8bf0100013000180004c0ff0b00100000000050000000fe6f01f0ff1a000540002000080001400100000b0002800010000000fd2f0020000c000000003c00f0bffe2f003c000c00ffafff3b00000000c0ff3b00000000400040000c000000000c00ffbf000001e0ff12000300016000f4bf038000100000000080ff6b000400024000e0ff0a00fdefff1b00f8bfff2f00d0ff02000100000000e4bf00400000000400fd2f00a0fff6bf00800030000400007001e0ff02c0000000000003000070ff5b000400feeffffbff0600fb2f002c000000003001e0fffabfff2f00f0ff0a000030003000100000b0008000fcbf
+InRand = 13d4f1b473932b85d8bbbdbd30713aa4a25482ae0f02e3351794769e68e70eec
+OutPK = 8b2d5c9aec7477f2e384b6a9ca064b029f6386ca3b760412859c647f78c364b158d8659c65d692b506bb4e56dc233189bdf703ed9134a47873cc14793f05aba55fc63ac34e9d02d3ef2a706e1a916a8816d8d07deacb2777e2b4a545e7e00575fd7a664b9d626bb05acda02a55e9a96afe54ecd6f95037edd2599089167b10e46d68f25258799ac46b166d9f9313d0e8f2d0a8a2a533b68ae1ac9c2c467071712f192bc809f2dc45b76e214a5d41222ec4b9d5a062a0b600beb70270aea1254cd8f79d4b034a357ba19527ea02bdd1a1ea09d04eabf568103cc4ca8be72e697a3e8ba131de02396c0a5b033742af982872ea3ade03f8a22059fad59fb21ee9529c544ccd9f7d64172c9d2515d6379b2e0df9903ec839e1b1db192a3a1ce5b1d94a17f748698a91cbf39306ad24e34ad329d3a8500cdf8bbbde0e2cc26b3d673e8a2159d0bbc0e5fd38f08e22063178b41a0d890b95761fec6bd5f64ebc260c6909008efa02f7477c199d32265e552f057606b13d84cab4de42094a94961226f58021cb1f34a95d1206a00ce286fea7c5aa40b1b93d9345ed1723b6747b1de69823ddb4409ba4391bbd24494011a4a590d20b151237a9e7a23b4be8865207514c666fec394406b367685880baa020eb5c6a556c614312aae258018d23b46f2c120cc43a8c9b082b755ab1fddd90b8eb4526eec8c43768255cac2c2d161a605ea90e2fa100a82448cbe04104e839ea617f93730064e0a963c3d9d60f4b214b29a1aa38380a5409e29878b788cad64db263449a69616d959bc8de606b40228dd38eef97797c80374b749a818a5ef40560a14701a4f4e45d1be415591ec47950aa9d6ca84af8986c9516a55be012a02d93a6a43604f9ed58a7dee509aab6576ed9a4217cd1bbf291864630723eb0d25c3ae7f123dbd12d92061a30de10a4e5a9dca35303e1379c0976295851f67e5237cae4e4566c8481382e2f212f580adfe4e18822d0a6bfd69a355eb670324e35559f95a9fe87222708d80a2b9269b075d660c020c2ba5c29acd809eacb71e266d627b7a322a9675203c4583e61a9b6c99ed6fd299e9992f60189be642d0b4bbb0e710153db50b4931c6849a4bc81608629a2ef850218f00d944be1ebe4f1520760c09119f47d751e85425eb89e309a45233fd290ae53f052074164b0cc35705f805b611aec389a209a122cb412d1d214f11314e427a931b5a82f49dcc4ac0ca5d347f49146bd6b35c62dac7689abd60be0399f045692484289491644ba9963510ef2c352a0e43c9589c6b52215c43ffde82ad868768c2da59727ffc45623eba8e3397995382471a60f4a82985987c110eab255cdf4319c88481e87f1fa80feac75eb0b626b71064d98a4c9324a7f9a58b023053c7849ee95ea7fe2510a8648b5894298d15776a49d35580122737a97968711ac9e98011c453b27f47b383e6ea46532678101374a2e6a8778e6b3f82212c240050a22cd40554aaea30b04eaf1b7748e7d51da4a1be83070eccab4c2f621fb93983b98940c9926b7d7f51a58ffa6d4a7350c0879546c4025013f952d9c410ecd7532d30b393b9a2bebac155468f48add16b6ca79e887bd5c7e12fafc71fbdda1cbbb8196b56dd3f168ce5e15dce5f0400030582e716056f85c5b10c2c5f4bd20cc6f64e2ccf179ee5f7864164c642d6356e6a89c17c91a0312f24859324b7d01f419691e03b4c198859a6b6b355964fc839c26f101ca88719b004492eed28a9d9c956519c053e0acc0350c2c3c82d4a438ec40033390fde66f2ab7672a16f8d7ae841d641754bde0466fa84b6822dca7766c7468205c12679594812d190153e54784665052961cdfc3fb3510084f44ea8bc47d00d8c7a0683a4178ab5e8725196334488ea9927448fae93ac72a548648d481122f166c8cc902161fadbb2325c2c4d89c79196a8648c49504b7036037337d85788b156865e674f6deed11965102ffe2041a7d9a55ddd53fe368828f6540fe79a4c4a1762dee08cb39524f89c0eb0a2a9246df1f85c1318c259f6dd6ae4dbcf39e91c9e3ba23f809bfd69d81bd749ddcb2bef679bfc6c118853e9736c9b5c808b4b31d254b444cd98c5ba104e6d368007c67e541ff42489d962c5462b5aa325f73e5e34c19998be96a705c78bb47a678f1a57819a887c2f3d64a37e997790f060f91c8b2760348802b1f854731003d21ab8f907c91861cc962804cb80c5cc26dd5802572c1594ce16cc57df24063289c582510cf5ff810ec43c2e0701b2a080d891992372c1979dd8420223cf04cbc401233d1a42fe646f8b2f2c98cd49cb813ab08b729a44f314c35884582d920e564659cef80aa61387029822713c2e868765a2917d8060c0115f5b6df3147548812216fd152ef4520c64e6a89de4a88946f7592dfc9ea20c61c8c1aaff83391fa71e6ce5e06f67e47e702663b137c275f5904e0c21c3b080723b75b492dcd03fc768ea633011ab3d3c4987cc5d96a92c22250b41ccf15beb885cca27352b4d9af
+OutRec = 00c0003000000002c00030000c0002c0003000000002000030000c000100002000040001400030000800008000200008000340002000080001800030000400004000300000000240003000000000c000300000000300001000040000000010000000004000000008000280000000040002000000000400024000200000000080002000080003c00000000800024000100004000080003000080002c00030000c0003800010000c0003c0001000080001c0002000040003c00030000c00010000300004000300001000000000800010000c000140003000080001400010000c0002000020000c0001400000000c00014000100004000100001000000003800010000000020000200004000380000000080003400000000000030000100000000140001000040000000010000400028000000008000100001000000001c0003000000001c0002000000002400020000c0001c0003000000001400020000c000080000000000000800030000800020000200004000240003000040003c0001000000002c00030000800000000200008000180002000000003c0003000040002800020000c00008000100000000200003000080000400020000c000380001000000001800010000c000180001000000000000000000c00000000200008000240003000080001400020000400010000300008000280001000000003000000000c0002000000000c0003c000000008000040001000080001c000000008000080002000000001c0003000040002c0001000040003000010000c0000c000000004000300002000080002c00020000c000200002000080000800000000c000180001000000003c000300000000340000000080000c00020000c000080001000040001c00010000c0000c0003000080003000030000c00034000000008000040000000000002800000000c0000000030000c0003c00000000c00018000100004000340002000040000c00000000c000000002000040003c00030000c0002c0002000040000c0003000040000c0000000040002c000200004000100003000080002c0001000080003400020000800014000300008000240002000000003800010000000038000000004000340001000000002000000000c000380001000080003000000000c0001c0003000040003400020000800028000000008000000003000080000800000000c000340002000080002800030000800020000200004000080000000040002000030000c000240003000040000c0001000040001400000000c0002c0003000000001c000000008000000001000080003800000000c00028000000008000100001000080000c00020000c0003c0003000000002000010000800020000300004000040001000080002c000300004000100001000040000c000200004000140003000080001c000200008000180000000040002c0002000040001c00020000c0002800010000000008000200004000100000000000002c000100004000340003000040001c0002000040003800000000000034000200008000140000000080001800000000c0000800010000c0000800020000c0000800010000c000340001000000002000000000800038000300008000040003000000003800030000800034000200008000180002000000002400000000c0002c0002000000001000030000800018000200000000200002000040000c0003000040002800020000c000080000000080000800010000c0001000010000c000200000000000001800000000c0001400010000c0003800000000800018000200000000100003000040000c0001000040002c0000000000001000010000c0001800000000c000300002000040003c00030000400020000000008000000000000000002c00030000c000200002000000001c000100000000240003000080000c00010000000028000100000000280003000080002c000100004000300000000040002800020000c00000000200004000100000000080001800030000400000000100004000240002000000000c0001000040001c0003000000002c0003000080001c0000000040003c00030000400034000200008000180000000040002800030000c0002800020000c0000800010000c00004000300000000380002000080001400020000800010000300004000200001000000002400030000c00008000200000000000000000000001800000000c0002c0002000040001c000200004000100002000000003c00030000c000380000000000000c00020000c0000800020000c0000400030000400038000100000000140001000040001c00020000800008000300004000080000000000003c0000000040003800020000c000040003000040002800030000c0001000010000c000100002000080002000030000c0003800020000c000340001000080002c0002000040002800030000400018000000008000000002000000000c00000000000
+Key = d5492977f04342e5c73557bce8b5f5c5a6c2e2acba0c8addcb834e797642aba6
+
+InNoiseS = a80b21a95b81047b96b9897ff01246dd9b46644d94e9eebb652d84bdd21a45815d7441a863e381121a78479f8a8b8ca9b3ecc170c8ac0630b1dfddba2f28a373471cd809001b36ea92e6291e26da1bbd469d526e734f45d78f2c6a840533b955fc36330f3dc865d5b7f9d6110b2b3d0eb92f34b9ae344ba06f04888b3202c111ad4749a2b923aa08528eb6a18a08719b06f4793b0dd2c958da1072628fb9a410bb7c5c2165806a718ba1ca0850c191230083928062776069b14562d513e843be94ad3e476b4c4239c1d52fbf900d2b00cd3725dd5111c238ba16a61314c59e706885aca57fc505fb9dfbe6ce6829bed6cc76e9e1b9af52805a737e4baf2f37ebde562ea01172fa29c27e4ed7244308aa253fe11481c90c9e762b11a880a6590d58ed1139f62ba60313f4afed1af24c4764d79c89fda62d06fcfc6258e88979f2559ca0612f845a5c3d6f6c5df309ac8701cdc21a648996f8d8ee97c8d894382b3994b3357afc5d06682e1095f25c1b59be76a316159cb623f04b494deb258f043f216eba710e6e9b0ee772432a45456602942a39f1912ad530b1d3d0b740e3f581cf368acd463a23d3960066d92de33b0a4a398ff673a719b52e15ac91b6a51aa8144826fd657bb517cb65e6e9782dd30a324022bbd7cd8995a5346b32970e0ae9be9aa79c91826b2c0e3c87c0030f72149ca9a77a53e946402e291097158db12aad04dd0c839aad8c220f207214cc87a07d057a81e37ba81956ab24554f657c124e10683af65fea15531d03f1190ebd0b0278089cbe01b019b194ae6ab8c9ef2c8b82e16ff1a4aad24060a62c5e89a3676d12fc1f1be3ee0e552c15808104919e64000a92d55800486af24632c4b02e631a5572d5751385aa95d4b5bbb71ebd56548a6f4a2cbcc33485803c90187b227ab2829e732b8ad15dddc3450317a966201f4ec3d70a3d04ec9a79a2c98ef2a3a693672ead1f0d20e42008726320f1ebfe162ba0c611b03a32a0c96260443ddeab0b04ff9381f14363a6a4e90b45a356907196cfb845c9e68c91d79d2e74510f5a2556605b0505142b0549416e3f8125c65afdad22a88620a05fe34a998a46ba57043488c2102e23da22f18e680be20702d326f8a86ae4bd36d4ed4e0f53fcd9d59c0cdf6a5cc80325730a513631991e420daa12b9f191af12c9b429298157754cb7ead1be85f8e826371954bb15946fa6620c8d63c235e37e7cad391829c258446522e30a60f0fa7a41c05eb0b2fc8faadad38ba6f66ec70fc62b2e9976a1d56bb2b4b26df54621f26b75af4f5030a668e211d58d36688e10a692c541648214a9e8037b86ec2009f2e6c5c0bb4c7e91db3123818441c8675d672c6e7cfde43d359d39280a974bc3e128407ca6e2883f21bc612777508f32202f2558b5b6224b6d4da3e83c9d3c582f7ab1bba82c904a1a75d6668ab0ef8893f4c24e305063e6d85471ced2d74a383451ab027613cdd094476538f9d03a55be9e4d0788099a3a4acebac42865ae436e55df2123a9425270cb113818640b614f8c487966904043d531b58c44b50571b1d45e04b56c4a0332a180f0006e3da108a08978159282670ea10b4e4e89155285bcd0a4d90827f845683b5fd708f0aa9541af9e304b2eb87c4b06f5d483789a621b5431384d7615cff8579ca2a44f157c6882ca6d15e213a9c8fd85015bf8d55cd21d274c442b66146d8dc456718599a68e8d57869e5a4ca4d00b17996c2bc483e476421205e6095594f5a8908ec8c6a28c118b9f2e7794c9920b928f4a5729ec983f2c5ae4846c91d50ddf2b90f6513949187900aa8ef828d4640012006dccfc7a225168165fb32b3a9d535de29310fa669aba94faf0c37d3a32463ec711a474e1cb20c15b36845ee4f6785d6d1a0eebc771d68d282ae2326933211fb91ea08b045113feef903bcaca3ffb6898f61815890b5a09cbe2413e5394f3d65a42250fae3930ddcd1d3d63bd26714640b8ae4cfaa3e57f0fc446ebc6e0822e6aeca4625252591568e1f80aa29a0679e65d9c6d19ea2f388c1a1a526db1f674f22ceba41412fa247b192eae509ff831be8fe55433a69570a7b3b24f1c8d5b443dcadd25a11f0cc432136c79bea5fb5a83de240c64d0717a7299ce499496e71e675c20428834445aa99db4124df4615865b68555c8ae0b021a824324a81ce0be995352b84490ad84413608c12dc2a00e4a53bfdbbb403a2847dde4616a38ed47cc8b04334cde0269ef0120fdfdaf795eec3b98924cce1a3924198e36dd6bc638faa01d76559942508e400c5f10573fb98187a562ca966dbe1b900043fcec5d826d17eb4a1e3790875d05baba956e6cb9d88b211bba112217d01ca67e83e3f6ae187e82e7c3398c127f894bedc489f15f6faad152f2364ebc8d63009e241d01c2db7bb9d6487de303a3915c4699c3e9857d8403671d2a774fe618d34b75560e78285f11938a343d8f5663a396c642b8dbe44aea56325af044979be3cd37b0e3b69436f45d5e95883a47e09d
+InPK = 8b2d5c9aec7477f2e384b6a9ca064b029f6386ca3b760412859c647f78c364b158d8659c65d692b506bb4e56dc233189bdf703ed9134a47873cc14793f05aba55fc63ac34e9d02d3ef2a706e1a916a8816d8d07deacb2777e2b4a545e7e00575fd7a664b9d626bb05acda02a55e9a96afe54ecd6f95037edd2599089167b10e46d68f25258799ac46b166d9f9313d0e8f2d0a8a2a533b68ae1ac9c2c467071712f192bc809f2dc45b76e214a5d41222ec4b9d5a062a0b600beb70270aea1254cd8f79d4b034a357ba19527ea02bdd1a1ea09d04eabf568103cc4ca8be72e697a3e8ba131de02396c0a5b033742af982872ea3ade03f8a22059fad59fb21ee9529c544ccd9f7d64172c9d2515d6379b2e0df9903ec839e1b1db192a3a1ce5b1d94a17f748698a91cbf39306ad24e34ad329d3a8500cdf8bbbde0e2cc26b3d673e8a2159d0bbc0e5fd38f08e22063178b41a0d890b95761fec6bd5f64ebc260c6909008efa02f7477c199d32265e552f057606b13d84cab4de42094a94961226f58021cb1f34a95d1206a00ce286fea7c5aa40b1b93d9345ed1723b6747b1de69823ddb4409ba4391bbd24494011a4a590d20b151237a9e7a23b4be8865207514c666fec394406b367685880baa020eb5c6a556c614312aae258018d23b46f2c120cc43a8c9b082b755ab1fddd90b8eb4526eec8c43768255cac2c2d161a605ea90e2fa100a82448cbe04104e839ea617f93730064e0a963c3d9d60f4b214b29a1aa38380a5409e29878b788cad64db263449a69616d959bc8de606b40228dd38eef97797c80374b749a818a5ef40560a14701a4f4e45d1be415591ec47950aa9d6ca84af8986c9516a55be012a02d93a6a43604f9ed58a7dee509aab6576ed9a4217cd1bbf291864630723eb0d25c3ae7f123dbd12d92061a30de10a4e5a9dca35303e1379c0976295851f67e5237cae4e4566c8481382e2f212f580adfe4e18822d0a6bfd69a355eb670324e35559f95a9fe87222708d80a2b9269b075d660c020c2ba5c29acd809eacb71e266d627b7a322a9675203c4583e61a9b6c99ed6fd299e9992f60189be642d0b4bbb0e710153db50b4931c6849a4bc81608629a2ef850218f00d944be1ebe4f1520760c09119f47d751e85425eb89e309a45233fd290ae53f052074164b0cc35705f805b611aec389a209a122cb412d1d214f11314e427a931b5a82f49dcc4ac0ca5d347f49146bd6b35c62dac7689abd60be0399f045692484289491644ba9963510ef2c352a0e43c9589c6b52215c43ffde82ad868768c2da59727ffc45623eba8e3397995382471a60f4a82985987c110eab255cdf4319c88481e87f1fa80feac75eb0b626b71064d98a4c9324a7f9a58b023053c7849ee95ea7fe2510a8648b5894298d15776a49d35580122737a97968711ac9e98011c453b27f47b383e6ea46532678101374a2e6a8778e6b3f82212c240050a22cd40554aaea30b04eaf1b7748e7d51da4a1be83070eccab4c2f621fb93983b98940c9926b7d7f51a58ffa6d4a7350c0879546c4025013f952d9c410ecd7532d30b393b9a2bebac155468f48add16b6ca79e887bd5c7e12fafc71fbdda1cbbb8196b56dd3f168ce5e15dce5f0400030582e716056f85c5b10c2c5f4bd20cc6f64e2ccf179ee5f7864164c642d6356e6a89c17c91a0312f24859324b7d01f419691e03b4c198859a6b6b355964fc839c26f101ca88719b004492eed28a9d9c956519c053e0acc0350c2c3c82d4a438ec40033390fde66f2ab7672a16f8d7ae841d641754bde0466fa84b6822dca7766c7468205c12679594812d190153e54784665052961cdfc3fb3510084f44ea8bc47d00d8c7a0683a4178ab5e8725196334488ea9927448fae93ac72a548648d481122f166c8cc902161fadbb2325c2c4d89c79196a8648c49504b7036037337d85788b156865e674f6deed11965102ffe2041a7d9a55ddd53fe368828f6540fe79a4c4a1762dee08cb39524f89c0eb0a2a9246df1f85c1318c259f6dd6ae4dbcf39e91c9e3ba23f809bfd69d81bd749ddcb2bef679bfc6c118853e9736c9b5c808b4b31d254b444cd98c5ba104e6d368007c67e541ff42489d962c5462b5aa325f73e5e34c19998be96a705c78bb47a678f1a57819a887c2f3d64a37e997790f060f91c8b2760348802b1f854731003d21ab8f907c91861cc962804cb80c5cc26dd5802572c1594ce16cc57df24063289c582510cf5ff810ec43c2e0701b2a080d891992372c1979dd8420223cf04cbc401233d1a42fe646f8b2f2c98cd49cb813ab08b729a44f314c35884582d920e564659cef80aa61387029822713c2e868765a2917d8060c0115f5b6df3147548812216fd152ef4520c64e6a89de4a88946f7592dfc9ea20c61c8c1aaff83391fa71e6ce5e06f67e47e702663b137c275f5904e0c21c3b080723b75b492dcd03fc768ea633011ab3d3c4987cc5d96a92c22250b41ccf15beb885cca27352b4d9af
+InRec = 00c0003000000002c00030000c0002c0003000000002000030000c000100002000040001400030000800008000200008000340002000080001800030000400004000300000000240003000000000c000300000000300001000040000000010000000004000000008000280000000040002000000000400024000200000000080002000080003c00000000800024000100004000080003000080002c00030000c0003800010000c0003c0001000080001c0002000040003c00030000c00010000300004000300001000000000800010000c000140003000080001400010000c0002000020000c0001400000000c00014000100004000100001000000003800010000000020000200004000380000000080003400000000000030000100000000140001000040000000010000400028000000008000100001000000001c0003000000001c0002000000002400020000c0001c0003000000001400020000c000080000000000000800030000800020000200004000240003000040003c0001000000002c00030000800000000200008000180002000000003c0003000040002800020000c00008000100000000200003000080000400020000c000380001000000001800010000c000180001000000000000000000c00000000200008000240003000080001400020000400010000300008000280001000000003000000000c0002000000000c0003c000000008000040001000080001c000000008000080002000000001c0003000040002c0001000040003000010000c0000c000000004000300002000080002c00020000c000200002000080000800000000c000180001000000003c000300000000340000000080000c00020000c000080001000040001c00010000c0000c0003000080003000030000c00034000000008000040000000000002800000000c0000000030000c0003c00000000c00018000100004000340002000040000c00000000c000000002000040003c00030000c0002c0002000040000c0003000040000c0000000040002c000200004000100003000080002c0001000080003400020000800014000300008000240002000000003800010000000038000000004000340001000000002000000000c000380001000080003000000000c0001c0003000040003400020000800028000000008000000003000080000800000000c000340002000080002800030000800020000200004000080000000040002000030000c000240003000040000c0001000040001400000000c0002c0003000000001c000000008000000001000080003800000000c00028000000008000100001000080000c00020000c0003c0003000000002000010000800020000300004000040001000080002c000300004000100001000040000c000200004000140003000080001c000200008000180000000040002c0002000040001c00020000c0002800010000000008000200004000100000000000002c000100004000340003000040001c0002000040003800000000000034000200008000140000000080001800000000c0000800010000c0000800020000c0000800010000c000340001000000002000000000800038000300008000040003000000003800030000800034000200008000180002000000002400000000c0002c0002000000001000030000800018000200000000200002000040000c0003000040002800020000c000080000000080000800010000c0001000010000c000200000000000001800000000c0001400010000c0003800000000800018000200000000100003000040000c0001000040002c0000000000001000010000c0001800000000c000300002000040003c00030000400020000000008000000000000000002c00030000c000200002000000001c000100000000240003000080000c00010000000028000100000000280003000080002c000100004000300000000040002800020000c00000000200004000100000000080001800030000400000000100004000240002000000000c0001000040001c0003000000002c0003000080001c0000000040003c00030000400034000200008000180000000040002800030000c0002800020000c0000800010000c00004000300000000380002000080001400020000800010000300004000200001000000002400030000c00008000200000000000000000000001800000000c0002c0002000040001c000200004000100002000000003c00030000c000380000000000000c00020000c0000800020000c0000400030000400038000100000000140001000040001c00020000800008000300004000080000000000003c0000000040003800020000c000040003000040002800030000c0001000010000c000100002000080002000030000c0003800020000c000340001000080002c0002000040002800030000400018000000008000000002000000000c00000000000
+Key = d5492977f04342e5c73557bce8b5f5c5a6c2e2acba0c8addcb834e797642aba6
+
+InRandA = 38cbf333053e5c9addf8537386b88da15212a3a81ae15340f63f194faf1e9f38addc51fbaa72470e210d2a97f8c3b988456389d8a0c6928cbaa2a752d3e2a12d23d2297ec417b003776169d5b5b1198ce1bc10206f9ecd915d680b71ab0f14a87560400c8927492278ce10d6e3470912ce1bb275cc098356dcd9a3eee19704825332c146bf7dea0e02b3ec22802fd706da3283bb2bb7aa58d17c09264bd8dba2776fa9ab08ceed27aed39091d4ca732cdb4880ad35b201d0ad8bacd61015d07fe1ad3c9b1865237a2f28afc16b19311d61b3ba2021a8cf1d733f61e3609986aa006ba6053d1023b1e5a0b797900cfa59a1d5b40ea466830170f5187a4cde089752f4467b9ed487ea85335b4f7b2a8400133867ada22db09d79d478d0c9a88977450154bf74201e020c2458b29ec3d25b94d0992e4f89cca758806aaadee52a592913358da200d006373458cda6dc399d2ee4c765771a6d7e69057345de1047611125a9a04df955e71b3a026a5d5dcda81035470227e5188090462e64a806b9d539c0a13eeb9635710d516a10219683c459cb397b467e0fee4bb4d4d060d001093b93297889499c3698428107aa58f76c012d0e95d046c2066b94211f005e22a3b5ce5968a8c47a3fa9ead41e925356820b85b12ca6d588525184ac72ed2de5aa24e2716e944dd20d3e22e0c10b163c007aba809f95c6e4a1e6ddf0f4515e1094ecf7426a747f1eaada64b6ed1df26ff3e474a1586a090247558e050d162e1583151cd9694cf650208d6d600663ddda518fd7438036064c925bf5a5398e4f18aa90193100ae980b3c2633f43da46f1cc8a19c4bbc6b4cc0c595aef60254cb96350e105100715b084c100a5553337d107cd78444b1865814968303aaf28ed9c2edd7effcb51ad73146bf4c8900a15ff60449a19566b8ca6b4a75a76432c397d81e2eabec411ac409118cfe53b25041d146a5f8e579bcd59978a5afce582a519331a325b4beee5b4361199bfac6362bc76506138ab9fb38b11e01d6b78a2266b2f00a329a84a1873bdf85fae39d29a714c0d891d9b31647d052cee828a902b268eb593aeac0c45a55cea69c429040c5a1763c0f52e394fea300108476968529c24cff510ce92b97a6d2620946bb3c8ffbb518da2bfeeb69e7cf41b1d39859b24824b3f792f8758fcd295f21c3d6e428281a42a740f67896454ce5d50d8e984c9e0309828d303bcb2117c31a10a6cc7917c8ba803c464d06a2ca146d6e9e666045b78dd385356be976bc0963528b7a4a42524942a63921245a7a089ef92aba50afdaa629ab470fab604ccc39869ec496ec2c2a102e1871a54c5378880f05c380304067392629d5a1f121674ae09870e082ff29a1269a22ee9316e889071f21199a36e522baa3bd43e81186d217b57a022045c98f2a6b9a32b9dc9ea276256900feab7ad036c53202297667fdb681e996cbaad03269a01bfafa74d00f6525f5534fd09800155f74cca1206ae6e6d0e058a0538c5d8480aeb1ef4c755b21222ec265de576316b63829ed37cca935e154f10580c05c1d8f51fae6d6643c43a9d546b07deb89afd9780c5e7adc0baa69383f6b235b11e87a3660531039e89e00496a9be8088609318e166a5d0272aa473617359840e79c95faf9cd9f08547780cfe594d1aff6352b7d6b1468148bff2c6c37d6660aeae9b482543337b6453f531e805b60526fdd59e5c1ccb83568d65db81c1dabf5afa573a7190cd42ca1e459c145a5430b61eab011e28f965befb658b8844ff7b056777bd80dd2097245120f8e5887750d386b28302a7279d700d3772eee28f3cb68e562328a3226437b55b9b2be81d1318f5413ef15de9a48fa50a344b6c51399afca6a82301cf6417213014a5a45bbcd90771ac2397e19e117d5a92d0b94c71965a001159feb9325b961ae725b0b14722aa3a906b6b076e9bea80d7af7c6211c28ee6a44bd4c2eb6cfa93a332489572968512818799687422122a59ed981f6a3bfcd928f9f0372bf64b4db4cd315597642d80c7683f85839fd57eaf80b1542f84383e04e313b91a6a8798a729e02a530a621b5912a1ccecbfe7da8e067a543526130e06537ca89a20399e775a2e34ea739eaf8e04180043f01d74a9a954a4a5b6b87cfd43fa4e1a9e36beca135e56c23f2756791cf1814d76537074575e18c09a5f68187c34d2223358f59c220b5229f69f948156e9f658d74d59292542ed226b8cd4e074ee6d0d0d1c64a6a9c1765e90c67f35bbbe342120d40826b174a2dbc4566309368500010d289e942d421bee3e7c5b90471ff8b9be754c168ccd5ef640e56bfb2d1628146dc0a752305f41316859ecd263052a90c149cf2003fdc791a1b4e555cdd163eec93346742b8199eb17ad1c66e342b991a1cf950225532e5ddfc8cb0e36d3b390d253a193b955a124e01606f51e14e20c0435a36924a2e79c5ddf12d126c73925a38c4f8109d09737459fc6826ef12653648a52665f80664b147ed544653d3ea09259b511be4c406
+InNoiseS = e5c40729d83a968c6b2ae550c89b6623e77579f20c14a6c8cb4a623b25da3973ebcc3ee5c92a34345957fe5d10827aa05da022a399332066a2679d11e83e00ac2be799dd3eb7a6a4c787e0b59fee900013ac050b77cbda453cfd06f0de51694b12433fdc32e37b16a8e60d2bb02b82101415850212b676144ba4145ef47731af3419fc8e406be62485d7da056868435a8d1c6a52823fd4ff3db975998aba564e7274525407c318a604a4dc1360c6629f9d425963019f2c9d05901e38abfe87ee51e4ea7c8591ed84c2f991669d6454d9a1b3b88e41e9309e94ae8fa797a91e27fe08f09a2c5e826b44b1626bc88098a4280428c05ffd8129939d450bd912784ae55e13c7044bc593e9406c1ec0c262ca59f225f60a812217471d1fe6af221c98a43135f6f6696441f17b698d92702f811702ce6b292e852723d21f996675c77070427be30a70f8fc8decd69c94c19c88949ac9b528261a26a77016952a7e91a17ea81be4bc4f2175d8b44835472e1606d0059a2e4d86c236cd9c8f27dbe9fb71800b5c335862f62acd0bafa1aa6821d585f7e6b4a5718a6020d4c53244b99d80718a09621766b7c158ec90cb0dee4bd630a9264a49db854e3af0126b17359842956ccca27e498df495c220ab9968000c021a7386464f958f8691a66c671186a26e484f04e5b29112e409ca5f366091d69ab4492f52e8f6abc7e561394ae89ce050bb776b7c3cb3c334f9e5da9fd3af1de2c68a2109ec683976a24cc4255139854c4a482fb8555e926c41a96db8f62e62f4ae6783bb48622a8e2373c7b0252dc40d52b1713fc48b0058b1f65a0fcdb3b8d07c3febd7eed55021773a58e9017aa90934c55f5799d53ee4aef2a8cb2209c01fafba6151be916bfdf15862204c52adcb0da5231408ebca29c02029cfda60baaa5aa09da3f3719495fa8de6107a6d175b030d8b84fe4e5b4f17032f447a20695f349ce8124d868eb7f2dab6820e6f78115c53514ab631f6fdbf3dda71b1be890d12e5bab273a9312d2afe739b6d75c6cb6446c445aa0198eb862748b55de2054acdf0b54bcd323ac6f27f4de55e197f7517210142e179d81afc501a88661d89be6c7e6aabac160704a5b6c1a2b829d9ce7486418fb92cfa23bd1ca3872a0b67b5ce4c62caf1a495bc442c11cdc87c06563d1a73941ae907d46ab77059166dcd11d12221582bb49ae411debc6cf36a9ed3c68643f7c18af0cf107e7dcabbb221cc201023a6156bdabde7e9b12bb3c64e0f0fb92a87ba2c59dcb8a5d48d97fce343ca0e69210b1c4d01897141ec4627e3a7ce05f848c4c558e0af50c36c053b100df69532935f46293a29c5c8e24ca3ade25bb427712f80263b736a6403cdd4c47b284d22ba4575d066d202d498e86b6ec23dba8abe87f63e375b0b6f41601c68fa1717e67b654ca21bfb428a0ca7ff5d2f51447e05a56e550a6790657cc3b0c736922fbd21b491694a64a11f45108b605f06d8610686f2912f504ff07f313edae07930cf8a4e838b0606a402625c494205fdfa764a5a9416853548364b0cd84ede3d3ae49af22f4d01ab127d31264eb8ace5d2554e55290a2d8979aaf88a761582f5c92a19f49ee4f573d54a61a638703e7535eb465bb6fa3a3dc1ab5cc452d826ef6e818a65aa842f1b60c57a50354fdaf1518f4d94c088ba049a5d963105f2a8e0819da6192361240474c5cebb328cdd907a2e04b0bda41c720c23c808a0918e68fb83dfe12684a4bb471eba7a0d48e75847a44042220ab85b412048da1981306d52fc659f34876d16ae89ccba803080b9268a8597bd57f00dcf79012cbb0528f9830864a129a5495879d228ef86fbc5bb39ac450b196a97200a1829323781d64fe981fac57b5228719adff3ee5e72c29af5a18d3e9635574cb65b4086e92fbb1ba62d36a823139955d186f65d05b6bc3915e5061416f548837d532a453aa50eb26848121a3a33aa5604c678249c676c8ec973c558f2e8ef88fb105998550da3cffa09838974403e8610370b2937bae154f488bf31c816890c83b878cacc577f2a3bb256687025c17cd595614fd2e803d1fa2891634772badad84549a71a5ae83e3b9418f6f9f6ca6d4a67d9c30459554bee4ce413091e1ca092a507d9685fd259d5f0b991d0645dc6d48a1fdf8171aa8e4c210c6cef97360155acdbe19b55f000012120e221240964cdf57b09900791e02f5168ddb798e3bdb1056298ef04d00a1bde9653e073e8899530db2d30961a4a58d604ae055ab56e5a0dcb77403a41e51b5d0895c675900c9e253d1851e9d87eabf235056bade602f0952ca1c8dbd5cd4a59324d5dfbc309518b5769926a4c7863c51db8a4249c6fce71c92b9c086c217f987a38569d923b01f58c3c3682a5a796223f89c7262160226cd8ef3730ec71a43d4e3053b2f15b855e3934501a90bfc6bdd9c3d6003ce2d86076215ce2db3e31bdd2266c8693e020129d63576617d3c68127608b7566b4be9dab7576b4167fa0cf610180153207d5ff9413488a
+InNoiseE = 4dc2a8f9bbe84e148d7f5389a5a28bd7162a43aa2e3e9415d944324e10c17885d0856af0495cd531401e6a970a82d439943b6ac520527c2afc2f3cbaf4d401178b9293111d76a14bb1407ad61e05284f6398020ed2db4ab42da6abeda9b9f631646ff2eb2300566814e225332580cc4c5068eb176509703d188e39354211a6944e125510006b972fd12f218efc8f231200c1062e91e2137931a125d2cb4b4e0d129a275cc766351d7961a589d0c254a19651073a456a80e6e59b28b00a5413eeb9e9e57bee93528388749cd2c08b89e5d1674a07e7247db53ea14b804413769be256ad01de518192c0310621a26bc3809313c6c877972eb9b9dfd91e27eb33468fcc99c14012f02ee67ee6479886fe208eb41b47d03d9d3ca3138cf08f2a8d9064a1c94e69ae5d8fcc5181bca3556bebe67c09ab47c7237532c03ebace244854b25160d455ab00b93bf3ae4822118c9c49aa42e149523a2c6badf8feed721ad8d6e56b26a0ae6836ca486e00a24c522a9544140701519b5cbc4392c72cf60b6c5e85d44ae4ec2077971640f98b361fd09e16252ff02dab937308995c8a9905674761b408a38c5fa6671583844bfcc5e0041088450940f37d5880999636a1fc8fba69264bc79482d7a4b2fa33467af8048924870e6e97d660b58d01b85d501f2566d5150aa74e8b7b0009a14449714d4e34de2fd7a87541033d1da5b7aba57081edc539837600239a870669f52c45de3585b0710f2a645d1807c1b9526df45445857f78018067f65d051a5fb96413e68792647b8a94664c5a2430f4b4e280898af079c1b95a456695d21ada7540af9490b109507d48b563bea1bd214988d7241a18af9f85901f4974b45afe7520ea31bf97c958bba2022012d755ce8cbb1701e7d730fd48396165309321bb2f5c45c9c8a153d22366849304277050dc31751d21db9fe6831c8506769eaa5a6bf4a1ab0adb72b5a003d75187d906e679b06dd63118a91b37a3748544c97eafd44fe5c90abec58acf93762471ed6b51a330082e624655d7846273aa9a78f667e47d4fef8c0981dd28896ad516288c85dc476493951a4cffdf8aa3ad706a4e6425b3870a5b27ce517afb1aa8808092bbd7161dea9048c9015ab10956f4c0b9e88b6c86325b5e6571df5d3c382dd94acc55ea65caf452bd1e3188c694b66924e793ccac23625cc7033cc2a05991d8bbc71e5c7c851871e2da8af241e198c3285946ad1603dc7990ac0f436a1bf2a8ee009c53c8e51eff9b3fe69ec4a5bc661a98a82074bf41df22362a32aa5318a800563bf40b413740dc1e3c0b20f160d804bb147ec55f5e09c8c834b78a8120e80c95aa84de5c0459f702257c6ccfdbfcb7a996970a0a3ed0e72ea11e09006a47a8424a494b383602ad9daad233befaa70598d717d52cb7e44be1b3ee4e948727cf071a8cb05e54a766f54e7935aaef25138db4d4468d627f9a090a689a7329718de61efa323645850685ac742e0e7c725ad006fb4a7209d2d1b7845e344b2ad9c29bf979bdea397a8d3097474a20c2fbea8071665942536a6e1f2c3bd7b54400259b3210147610c12047d705cc700e1f2d7879fd63fe69c554b64e02c76a4a1ba4c23b7f4e6fb000ce894598f27049f9ba0c257d5160e27b214ae151da0479f1069df0f4814b4b8636d84c0c963d2887a41cc867209c9fb219bc9847c10277f80d32ae40f88060f651739c77689f3640f1eba789a254b0cd191b61c82a48afaaeca4194031e8417cc0144d63c4643616dd2215a980236a02c60f8e67d7a42104949d4a1ee8d38cb88cc7a6b5674904984a894966e673578105ab3274bc3b015ea992bc6a70994e845669858b0062c0d1fa6defeb64c3d3e0a8a49e4de6892980c85a901295a479475438fa59b103dd1bd083d79c193a89db61d18c7d2d8410d5b63d3c04a85464713e8a856abb17aa1c935e5e2c791b0d5b2899bb2088127fe8907b7390f1bda841f48632561bbc2ddda6f2d01fac069629f63e1ef0821b388bf86966e178d82b3e9776a47bc011091c5e02dc12617c681be877584129617781a1d2a8b8a905e124a63620ad74cee68bc0d1a0cb4bda493f353c93200c533bfc6c94800e88895e045e09f6d4faf662468143955858768150746aed404d3e81a1f34ef9083761b1393b008ad524a789cf5da8862cb66b70a800f7a84e7aaef13456483d4ab8e8045659615237e6183f4be799583822b84bd397e7cc9af9865b70443679f52638910e7d3ff5c7497af2054e31927032e47d9b3a5fbae4613853061fecf8cc3d46a04aae5277021b0f2a4ca2cb6027b66d8d17d8089780a39794126d75744b7294775ca0675e3a32f7b62ff0ea6b033c0e3f77e39bea7e58b86ea0b973923295a7262b71657973f69133470da2565f4c4f3b24ec9bd5c309eab95db467a355e8cd385fd79fb766cd9d97a182438a56e11b08a3a57bf1aaad1a465d3557ba552a0168d4744d6020020b312eed92496e5a4502650c1529b5d549b98f59dd7831033e41
+OutPK = 41aa3310e40a5c72e000a825b951fb43b8145b3d240dc83aa705fd81a585a0b20894b09bc641244008319d5674e3dc916955877d153c3d9c04236e5513c67d535c704922ea0af16cb02423e0a8831104f6533c98264fce6a59d055ddc55e15a986667cc8c46397e6831850ed94d3416c320ea1502570936b9ae649d3c22a6fe104c30c15a6a915c6416ed891016435c8db948cf796a99189fa8c1601d1ca03b93bf80bd47591342c6dd9d976c77ea631e2b0d15eb569f2d9cee48d4a4e7de8c17a5f8046dc83f83916fd6ced61cbb6a2058ff22e685465e5ba97cab0312f5669d458f7d596f2171582afea02549766d1aa09aa39054080b174574875ad0579da369079565ba413a360198f92f1fb0a3d3ba467c3c5f1218bb6a9cb94373e1e0d0bddd53d24bd05c101db21b2b41a8b20822829bbfbdd3a93821c6facc547152f71771492a0c2c709aa541b5fb0a43a50d9ac5fa414509d09d448f4f271620c1159026768bc46ea9364e906571fab6976105d34ae22cf895fcc087461706936ee0a0ea4a8f9b73039cf18b874a7582ac3af68855e1e9d8928256158b801ca93178a16ac0f61c6d0234549abfe1dcbb9386084295d43a4324ca3015f575235285e6a97a125fb088706dd0bb7922194631cb0b46fb11e66c5a2f753aa3812d74c62519230019f6f27759dad24ee2365d3ec13809c920abe9c587f817d265e1d1c551fb917e85d53ded3e530afd648f72076aa0f396d41d824dbd46a79ed2e276b0025bc49e4b738cd166ee9134b1366558ed3a3f838b6c55f2bceaa6b6a55ac181d591a5c3d69cd4be59a7ea68de6e00ae238ee37475c0221c2f0785fa3deaad4eda01505480a171095206794330a004c37e9c0a9af38936bab9bcaaef2496eeac863f392295eeb6fd793f681c39a3b255f4e91228ad9d6831039da8b9948da25b830102b8468be17a5a317732bae56f407a575e8448084516202435c22d42b1e08e8b127498f3f50b99e08719e4595ebde9b54a76d7b8e145ec48002623580be54e99c4696bd4c47d28f96079596311f7ee7951513040a9449f2a806a04f20e4d5f25a23c84f40262ab0f144ee2956b66c7c8e2c38ff0c0a29df461080cea94c470f90ed1635340949280ab15e9189e9f054e5a39797a291c724162f64df6a4ad93b3a4f80845411124fdfd61320a4176c04cde3011a770add6870e36c0b8594083ad7d1246a22ba1611f88290138d79f6249fde82a920fe95a0c3d1ac017ebe55205eef41a8c01f5813c05a70c11908a37546e4101af12342c70cd05d03a1ec5404ada42a2d29a9fc8811805e5490a0317e1667dacb21a9a1d2489816cf1e2deaa2c708b5b03216cf2350546c062bc6e6e81b52a851826e9aef2e4ed55d18e99f8401c5db7709f659b808007c847e90754cdd7c55d850b0fb5077fb606867e3e00b9b109552a61cb187c6416e0729a5294f4e6ebf892be54ece31c74507237edc5884987237d5c270f52a86c429781648188479268e9e7eea00d12f6e321857d7948d388de52dc5d52d46b606848ac970c8ad49610ee8785470f71a10cbe3e48bdc497e5123890e1a93586089cd917a14fea4e4de89c885db8bafd2615a6855e1ca1a303443af75ef9d1239c3465bc9e0b2880b89b0d0140e11c147e894fa1096e75c4b863e69ef2f2c45c4087d40dd64130b58739e445bdb141a7f39d7d9a2032da8bbecca12d5aa1a718040834fec212f139d8aa4f50ee5159ff5102c2dad585ce19c8972b215f761e87d71d45174c4486a2c43a4435400b986cf8727c2e2009127405e39b85e1cea1e9841912567200bc6e5b2fc52ac0b895043228292adab063ba81ed049f5e1e0749d3e025ad16459b4ca18db00ce61a164d9d352043a6f44e8e7949c393a0aa56fa0bf8d065e531cf570a09e1f21b6c7ee507d6e803999296576bd243f3410e42adbab7e19a3098ad75967c248dc0359cc68a5d6ac1c6c81fdc1c1f6a00f530aa2facc51b0ab9cf8f408afdd2967dacb586b721a54f7363d87f1af0ed354d017b567ae0b2440279f4c5e237360018194a8e38bba66316d7634f1002d5d245e5019ad08090a35b732e84aae82ef9bb329286661f9e5218da95a6deb6ab7416b551361444ed890866a8cbb70ea59b20c05a64fbc94efed92f72faca2584d779476d41c5427d9119ebd6d94af6ef9306637cc4590f705dc5f28007568c7748d49248483cca2accc1a6bf008668878c853a1d09c247e0c3854dbf55647ae9ba2194c4a111c99e032f830b69b9ef8c45a864c23876343ee870290ff33b8241a4a95808a0fd17217af5803d5f83e676d29914290ad98addc43f77a85fa6623b0a254af2a87ae677c18029049a225681da84ccd9d37ddd50b8a205c7b9f2e140256d278c4c858ffc9fcb5d7c2aa302abeb15c6c227f5a4508dd0579164264fb953487f5a077d9a4ed2fac17dfe22012a327ae89a1e6b99133ef6415ef953056117f9b476d58d6865f577d65576559a03660a912789870fbd42520
+
+InPK = 41aa3310e40a5c72e000a825b951fb43b8145b3d240dc83aa705fd81a585a0b20894b09bc641244008319d5674e3dc916955877d153c3d9c04236e5513c67d535c704922ea0af16cb02423e0a8831104f6533c98264fce6a59d055ddc55e15a986667cc8c46397e6831850ed94d3416c320ea1502570936b9ae649d3c22a6fe104c30c15a6a915c6416ed891016435c8db948cf796a99189fa8c1601d1ca03b93bf80bd47591342c6dd9d976c77ea631e2b0d15eb569f2d9cee48d4a4e7de8c17a5f8046dc83f83916fd6ced61cbb6a2058ff22e685465e5ba97cab0312f5669d458f7d596f2171582afea02549766d1aa09aa39054080b174574875ad0579da369079565ba413a360198f92f1fb0a3d3ba467c3c5f1218bb6a9cb94373e1e0d0bddd53d24bd05c101db21b2b41a8b20822829bbfbdd3a93821c6facc547152f71771492a0c2c709aa541b5fb0a43a50d9ac5fa414509d09d448f4f271620c1159026768bc46ea9364e906571fab6976105d34ae22cf895fcc087461706936ee0a0ea4a8f9b73039cf18b874a7582ac3af68855e1e9d8928256158b801ca93178a16ac0f61c6d0234549abfe1dcbb9386084295d43a4324ca3015f575235285e6a97a125fb088706dd0bb7922194631cb0b46fb11e66c5a2f753aa3812d74c62519230019f6f27759dad24ee2365d3ec13809c920abe9c587f817d265e1d1c551fb917e85d53ded3e530afd648f72076aa0f396d41d824dbd46a79ed2e276b0025bc49e4b738cd166ee9134b1366558ed3a3f838b6c55f2bceaa6b6a55ac181d591a5c3d69cd4be59a7ea68de6e00ae238ee37475c0221c2f0785fa3deaad4eda01505480a171095206794330a004c37e9c0a9af38936bab9bcaaef2496eeac863f392295eeb6fd793f681c39a3b255f4e91228ad9d6831039da8b9948da25b830102b8468be17a5a317732bae56f407a575e8448084516202435c22d42b1e08e8b127498f3f50b99e08719e4595ebde9b54a76d7b8e145ec48002623580be54e99c4696bd4c47d28f96079596311f7ee7951513040a9449f2a806a04f20e4d5f25a23c84f40262ab0f144ee2956b66c7c8e2c38ff0c0a29df461080cea94c470f90ed1635340949280ab15e9189e9f054e5a39797a291c724162f64df6a4ad93b3a4f80845411124fdfd61320a4176c04cde3011a770add6870e36c0b8594083ad7d1246a22ba1611f88290138d79f6249fde82a920fe95a0c3d1ac017ebe55205eef41a8c01f5813c05a70c11908a37546e4101af12342c70cd05d03a1ec5404ada42a2d29a9fc8811805e5490a0317e1667dacb21a9a1d2489816cf1e2deaa2c708b5b03216cf2350546c062bc6e6e81b52a851826e9aef2e4ed55d18e99f8401c5db7709f659b808007c847e90754cdd7c55d850b0fb5077fb606867e3e00b9b109552a61cb187c6416e0729a5294f4e6ebf892be54ece31c74507237edc5884987237d5c270f52a86c429781648188479268e9e7eea00d12f6e321857d7948d388de52dc5d52d46b606848ac970c8ad49610ee8785470f71a10cbe3e48bdc497e5123890e1a93586089cd917a14fea4e4de89c885db8bafd2615a6855e1ca1a303443af75ef9d1239c3465bc9e0b2880b89b0d0140e11c147e894fa1096e75c4b863e69ef2f2c45c4087d40dd64130b58739e445bdb141a7f39d7d9a2032da8bbecca12d5aa1a718040834fec212f139d8aa4f50ee5159ff5102c2dad585ce19c8972b215f761e87d71d45174c4486a2c43a4435400b986cf8727c2e2009127405e39b85e1cea1e9841912567200bc6e5b2fc52ac0b895043228292adab063ba81ed049f5e1e0749d3e025ad16459b4ca18db00ce61a164d9d352043a6f44e8e7949c393a0aa56fa0bf8d065e531cf570a09e1f21b6c7ee507d6e803999296576bd243f3410e42adbab7e19a3098ad75967c248dc0359cc68a5d6ac1c6c81fdc1c1f6a00f530aa2facc51b0ab9cf8f408afdd2967dacb586b721a54f7363d87f1af0ed354d017b567ae0b2440279f4c5e237360018194a8e38bba66316d7634f1002d5d245e5019ad08090a35b732e84aae82ef9bb329286661f9e5218da95a6deb6ab7416b551361444ed890866a8cbb70ea59b20c05a64fbc94efed92f72faca2584d779476d41c5427d9119ebd6d94af6ef9306637cc4590f705dc5f28007568c7748d49248483cca2accc1a6bf008668878c853a1d09c247e0c3854dbf55647ae9ba2194c4a111c99e032f830b69b9ef8c45a864c23876343ee870290ff33b8241a4a95808a0fd17217af5803d5f83e676d29914290ad98addc43f77a85fa6623b0a254af2a87ae677c18029049a225681da84ccd9d37ddd50b8a205c7b9f2e140256d278c4c858ffc9fcb5d7c2aa302abeb15c6c227f5a4508dd0579164264fb953487f5a077d9a4ed2fac17dfe22012a327ae89a1e6b99133ef6415ef953056117f9b476d58d6865f577d65576559a03660a912789870fbd42520
+InA = 38cbf333053e5c9addf8537386b88da15212a3a81ae15340f63f194faf1e9f38addc51fbaa72470e210d2a97f8c3b988456389d8a0c6928cbaa2a752d3e2a12d23d2297ec417b003776169d5b5b1198ce1bc10206f9ecd915d680b71ab0f14a87560400c8927492278ce10d6e3470912ce1bb275cc098356dcd9a3eee19704825332c146bf7dea0e02b3ec22802fd706da3283bb2bb7aa58d17c09264bd8dba2776fa9ab08ceed27aed39091d4ca732cdb4880ad35b201d0ad8bacd61015d07fe1ad3c9b1865237a2f28afc16b19311d61b3ba2021a8cf1d733f61e3609986aa006ba6053d1023b1e5a0b797900cfa59a1d5b40ea466830170f5187a4cde089752f4467b9ed487ea85335b4f7b2a8400133867ada22db09d79d478d0c9a88977450154bf74201e020c2458b29ec3d25b94d0992e4f89cca758806aaadee52a592913358da200d006373458cda6dc399d2ee4c765771a6d7e69057345de1047611125a9a04df955e71b3a026a5d5dcda81035470227e5188090462e64a806b9d539c0a13eeb9635710d516a10219683c459cb397b467e0fee4bb4d4d060d001093b93297889499c3698428107aa58f76c012d0e95d046c2066b94211f005e22a3b5ce5968a8c47a3fa9ead41e925356820b85b12ca6d588525184ac72ed2de5aa24e2716e944dd20d3e22e0c10b163c007aba809f95c6e4a1e6ddf0f4515e1094ecf7426a747f1eaada64b6ed1df26ff3e474a1586a090247558e050d162e1583151cd9694cf650208d6d600663ddda518fd7438036064c925bf5a5398e4f18aa90193100ae980b3c2633f43da46f1cc8a19c4bbc6b4cc0c595aef60254cb96350e105100715b084c100a5553337d107cd78444b1865814968303aaf28ed9c2edd7effcb51ad73146bf4c8900a15ff60449a19566b8ca6b4a75a76432c397d81e2eabec411ac409118cfe53b25041d146a5f8e579bcd59978a5afce582a519331a325b4beee5b4361199bfac6362bc76506138ab9fb38b11e01d6b78a2266b2f00a329a84a1873bdf85fae39d29a714c0d891d9b31647d052cee828a902b268eb593aeac0c45a55cea69c429040c5a1763c0f52e394fea300108476968529c24cff510ce92b97a6d2620946bb3c8ffbb518da2bfeeb69e7cf41b1d39859b24824b3f792f8758fcd295f21c3d6e428281a42a740f67896454ce5d50d8e984c9e0309828d303bcb2117c31a10a6cc7917c8ba803c464d06a2ca146d6e9e666045b78dd385356be976bc0963528b7a4a42524942a63921245a7a089ef92aba50afdaa629ab470fab604ccc39869ec496ec2c2a102e1871a54c5378880f05c380304067392629d5a1f121674ae09870e082ff29a1269a22ee9316e889071f21199a36e522baa3bd43e81186d217b57a022045c98f2a6b9a32b9dc9ea276256900feab7ad036c53202297667fdb681e996cbaad03269a01bfafa74d00f6525f5534fd09800155f74cca1206ae6e6d0e058a0538c5d8480aeb1ef4c755b21222ec265de576316b63829ed37cca935e154f10580c05c1d8f51fae6d6643c43a9d546b07deb89afd9780c5e7adc0baa69383f6b235b11e87a3660531039e89e00496a9be8088609318e166a5d0272aa473617359840e79c95faf9cd9f08547780cfe594d1aff6352b7d6b1468148bff2c6c37d6660aeae9b482543337b6453f531e805b60526fdd59e5c1ccb83568d65db81c1dabf5afa573a7190cd42ca1e459c145a5430b61eab011e28f965befb658b8844ff7b056777bd80dd2097245120f8e5887750d386b28302a7279d700d3772eee28f3cb68e562328a3226437b55b9b2be81d1318f5413ef15de9a48fa50a344b6c51399afca6a82301cf6417213014a5a45bbcd90771ac2397e19e117d5a92d0b94c71965a001159feb9325b961ae725b0b14722aa3a906b6b076e9bea80d7af7c6211c28ee6a44bd4c2eb6cfa93a332489572968512818799687422122a59ed981f6a3bfcd928f9f0372bf64b4db4cd315597642d80c7683f85839fd57eaf80b1542f84383e04e313b91a6a8798a729e02a530a621b5912a1ccecbfe7da8e067a543526130e06537ca89a20399e775a2e34ea739eaf8e04180043f01d74a9a954a4a5b6b87cfd43fa4e1a9e36beca135e56c23f2756791cf1814d76537074575e18c09a5f68187c34d2223358f59c220b5229f69f948156e9f658d74d59292542ed226b8cd4e074ee6d0d0d1c64a6a9c1765e90c67f35bbbe342120d40826b174a2dbc4566309368500010d289e942d421bee3e7c5b90471ff8b9be754c168ccd5ef640e56bfb2d1628146dc0a752305f41316859ecd263052a90c149cf2003fdc791a1b4e555cdd163eec93346742b8199eb17ad1c66e342b991a1cf950225532e5ddfc8cb0e36d3b390d253a193b955a124e01606f51e14e20c0435a36924a2e79c5ddf12d126c73925a38c4f8109d09737459fc6826ef12653648a52665f80664b147ed544653d3ea09259b511be4c406
+InNoiseSP = b1854163d7624f012383189759bdcd5ccb464ded5d1cd229a2c4fd610eeb3a568e2900ed165616cea24d09853c0ab8658ced40e7751bf1b34ae4c9896ab621992aef37b9041446a9a3495cd942ff266a04c5b9039b5f18420f51b976a1b4d9a81095f00d4cb4e87144284df1a470c25637ed724b21da34206369bb7a5624e341449421da69a3464451c53c3893919533443594761c30da94ec8295807b78e8ac8e80d05e745375a37f9027691b2a309e85d255bf7c06178ac212b90d1c3d262d9bf6096c5d806e39ada889afd21db68d6192a318a2fb09288c6180c7c4843129e0eb9db966aa317d127d4318f9a677e95294283452f8612635294a9fa31cb08bca6d4dc0a3e2239c753301080c4a142d08502fe898b288bd6c4230046c103103aa3cf84a65860951a0fbb990394aa03035b6d49342a57a86cf687860ae0f70544aa6f2020ee558e5911161b793d1764fc55aa2098de4bd9a6749ebf2298c9941de469b94891004ae06d944a7902f02093b404b684f5c6bb0b000bb608ff2b7a904f7a266aba00d04e30fb915d40893d411b91a0785a037477f344aa02a57e81ef7b88d49f6c0b589af5152cd16492b5c16a3cf4da893452ea4986347b22cbe8ef48945026ef68f822af9f6e18ca0fe403e12a1ba187412f2e6c4e59f2f0ece65fc4d45ecc7f47a058a5a55e503cb5a485e23573de071388365a81e76f98eb6ec4203f346e0b670d29464974249045239e119f545ed6a6f57c5e80ab15266c2a87d15418ab3588c218477ceb65679020f0a96d9c74be12fc064b999f5ce7a24e36d89b6714d3dd52af3145849689dadf603f2bd7ba3e3127a4c03ff2a90f7f1cc1a4388a05a1b6098a6236b32069c0f5baeb8b2be20125d80e9f3576c5b114968e1d9c43159a281a9c70c87291f6646f3e2a28796898132218890a62cd799fd1bb14b979a0758665c11b7a690dd05dd2e59b68eaaa98ee1fdc6aa111fdd2a11fa1150b99b10ad47ecdd6b2481dd63704c56cfad7ce0e7bc64ea169bf25f799a279bb12969683fe493069b7422bcefa49b12c964700a66dda50e525ba04d4f0be93aabb7e0b1335888a5de0e9c431c4592fb6d2384322c26f005a7a3134ebd48a5b299a94d6d7ae4d37438d55f69101b457a7198cbded8ba2f5d85360b70fb1476bc80281c77f4cc5b9521aa52e01443f09e30a0929a8aa804e9f0f5b52b1fa0c805d604989ed3d9cbb1c66ea8a7e160e9b01d0d642ecae2b91548023e41125e5b96ddccf5f35a89b4c0c79a7259614921b9862b6a91674d49a8353c63f89ad3eae1ea5040d176e28632209f5dd2d37182035d0b34b2d2fd49ab1b3885d55180691ca7c93bca936dd9f7b71c741b7eabcd71eba93b6cc8ed29de343e00a6a7a74ee6913b160bfb8ea4897fa97e2b8f2d27456bf945c121b29ce9e8c4749d14161f65d2dd3db0ca1f2f853975191e48aae5b7e684fc5ab599ed11b83b61cebba59e4ffec46830ea1cb11e2b5075f0ee4b58538048c62241f2d73baa39fc8223268f818660bb9b96fbd42ea50f7e0199760ff07254e913530a112f7c2b35a7177aae3c9f60d8a62238979d2d81988d084045abf10790beba42ee8b07a006098bdb42cac11dea20f5e2981880dadf42f59bce784f130da97c645c2f661b8167f1435ad8eea3e004459e0d5628bca93a390a530b70148fb51ca130dac87f96559146d66010d54820f525d469622cf13a5a8a79f09a1088178e39e794ec756ee15a351651f6fbcc4cb786f6d60e1a53cdc5251631f84e6d6cdbc9e9dd41165e4872f6ee35c0d8b6db7dc48d6384a9287f65461044d08be3c29f2708a57496fe966a659db13d496ce16c39c34aad76ab80a330726078a0a8f9429ddd7e9c91c2b3b1594044a658e3f46e3a079a98222a9a5074883095a6717ab807a4b2b77a4894c5c6e0dfae62abeaaed26ece6b29553413df7448fc4e40b7311e3bb556716ab2c921d36b1ee7e65111c6224c300e466a259309c39de94a7d5a32764c4259add929900845829c91a677fd39355e2d3392d0c547875a43f05f3819c1ed74a86a890cbfa8255645916b62a1dbeaaa5d94e80f54d831240ed266e07bafa0780f92fbb147109e2a65ba6536d01154cee3e577ae2afb8a3a761d9169b5afcd322f85558bd0a762be2821a1290af2c50c194a2a7a85aaaa1d68c11642de8a3c1a22674481782f8847b8330ee4091a281e9bd3e4a5925bcf54f062bc4aa20780497200e61e4bd537e0515fda23246c04943d0d3b59205c501610118ac73c2f33e5b15b3c49123e9e1be9b6b8984b13146497b53b48574b85c376565c5cf8e82d0049f3d591e652947fa027b011fd008042ae6cdb7c6e3e55833ba0b0a00cc1248405b9d90a17cbd022fcb049c0cb6f0516c2a566eb776be7194df155e3ba46f10ec3272f879dc1186d2b8851b938119656c563b95d7977eefb73a1929991c0f413b99049269597796688020ca0a6e401263ab5691934a3d971aac2ce626b811c7c1394237f3c91
+InNoiseEP = f3add13126a14ead16967a55997c47a25801efca5d3a8633f38ca2bacc15aea13b784a90c920c0ffe1519e275f8051fe6133ca42b6184899c44057c686c24b85e2341017714d72231f95105209269c6f5a6b1c6b1fdf0e82048d9b5b8ec355996aab3fdf5ed55e44b64a48d0421dcd69464568827a3206f41aa0f444b2b197025d03b9dea0c442ac07137e85854239248d080f3e9f4aa8ca86039d519d45b2d424e5928ab6b39a6658e65bc119006672daa2cb0c54783e455456c43862d10b050a2d1611144d2b5b21d6668129ade5ef1165ba58e0769c2d31fbd19ad144cc38566e243b83362d51c8d72937e54d10db9e4428f4aea5ab7c22d22d07079698d671a8b7b58edfc181d53fafd1a2c0034d8c2382807b85f82f9a025320ea7d768da0cd03aff8b7eeac270883cd27dc664976e301524aa8eec82da0163cd6b8b456881af113349915c5ae9515156bdb820018c6b895c2357e93e2e1b04acc54c75fae61ce1882666ad3a95f7d10b32c73f2c3f97d215c34a36391059742b597e0c26a30103b8824311500dc416a33c68328266394f16a57b684c21b2b785f77eed6e7c5ad1f7967b6095912455c48cd96b6a2629a82ce277c3a0c2b01bda0e02d6c201b2f249e6d4ecc910fa38c6d703b868a637f050da4c831390bba28b65f39d48824bbe88402c6794a2c4f0b63b713f09c69592cc79b7e5e5b224fb8a38c9c2581e7602e5039b64ca7f468e99e1f6bef7878842d5ba1cbe54c5dae6ca7c360ea8488681bf48850b805bc82a1d07bf630d90188aa68cd1edfc22df57bf1abed5a10f230f1089a40c531a841a15e094615c732a42a4005c3815d2d272711079124400f23e9a7d0f112c5db8f02b958621ce6c7d6010c35249fc5c06e2c505565de5708a6448707c9a5ff0943b709c046fb2d00c5e2b4b356f15bd0ac0d2af0d237134acc6b2ae5b2d9436870aebe62f26415966695a42011bf301775340f52c7567924b9d4e977b8d03121afe7b5f111d9a5a6235f054e8a98078d74d4ac3a6b7d4b5b555e6d870c032b8b4d451898abef511add7a235c6aa3d62e2b40e757b876c6ab7addbee704cd39beaf3164495a95de5083d4a26833f3a75e397c58598a5e484be40544ff1def8329806948c94238f5ae0f38d4f287748ea04e1c74e7b9f45ca426cdc8aeda5c940d7c3940e68926d4523a5c4ab89fefe9109876064fd710bbbb18b24a9f149a8752a28d4284346bf1b76382ca69f000a6d8052200ad202464d44072820c3f012d280b310951d2593624b80485504bdc25749e166d929824057869a763f9849671a349267b8ae75a7fb1274b53f02d3f8f98e822ad1461d35faa83433a1f2e0eb3598ef23f0aa765b6f96506fe50be77dfac62ef0f74d0db752d0ba8a0586eb51d14a83e69ce197318c08562b3727597ceb25b48fc395211c262f618590d834c602b4c6e81c93fe3f8558272e25dc6b184a01f8cb5e5b7d66c102c7a47fe55535067690440b2895bc96b5b73ea2fcca448e9dd389b725e91c379f296e313d6e44c40b575aed932fe628341c066f36dd8053d81776973448191a3f2b5cd8c52e3a3a7416bb234a59ddf2567ae92839e1a7a71aa0d175f0503729a1b6f5fac31ba5552ad481ce0ce8208ea98ea3a33c1acdce0c31a45f06c8c10cd4127f24edc116a13db464a7fa00ee7f92629918db067ed9e4830ccb830a95840971a492a838217dca136c9149c2f245cda65f58c4996d12639049a648ec6845518488e1ae8f4d23c14102b9d90b38b6a1b47d44cc7fb458a230e59c4d42e366414b6577bd567c7ec70d779ed277ea4d3e7107a1fd20d9ff85289bc7d626264544aa8b24dee58a94e12871b23ab97945f630a6125037087924399a8a60c8a66599f82c1c496078ddfa400e0be15a41849d940a8941d10a322d951b98522cb30426092c5419882e06fa0cc41119b3e540e240c506d2898305b5ed2c9324310c530d67a7072870269aa338db4a26551122f62abe129fcb8f0163975cb8636360ca331d966902b9d28dcc016549942310209a7c64f261e998f6421c074007adee784c4beba5fc2f1c5a9a6a40907dea8dde52c3c99b330cede97e06a4421bea9a073808d351d2d411d63d1ca113939ada555263e455c7e19a1d8c9c271fe402191dced3d0c01718607185a329e42216de02d9857da9936f2b2bc47076b6bc92672e831d66060a5bed6b077abe2301a60376418a125e9216888f5e151858c3ee799794ba347f5b26c18608c93f2b09d0e87d8ad03521c1100181581e617a23466ae3496878cadfe5922250226403c0706204161ab546ff9875c910b694c69f0d3c08a901fd3e8f79e052feb55d1010c58d590b8295ec6b09f586577ba1e2f900ed856140020aaa1f8e25945bd91add9b0109a38f75fc886ab422a37e673206c8612861e9093d2f20293c7a42346b05e32d14f177f8586c74492e0f27e04376f88c61f6c27c302f5c5866d96a36c53d709b63aa94e14ba4fc43e5c8edb93cf08a1
+InNoiseEPP = 00b000000003c0ffefffdbff0600038000000000c0ff2f0000000c00010000e0ff0a00038000000000000040ff0b00ecbfff2f012000f0bf000000e0ff12000680ff1b0008000200005c0010000180ff3b0000c0008000c0fffebf01c00060000000fd6f004000080000c0ff0b00fbbf05c0002000080000c0ffdbff0200ffafff2b00000000f0ffcbff06000280ff1b00f4bf00f0ffebff02c0000001d0ff0a0001000050000c0002c0ffebff0e00fe6f0010001800feafff5b0000c002400020000000003000200000c0fb6f0000000f00020000e0fffabf04c0ff1b00f8bf00c0ff1b0000c001c0ff4b000800fdeffffbfffabffdefff1b000c000000013000f0bf0080fffbff0e0000f000e0fffebf0480ff1b00f8bfffaf003000f8bf06c0ffcbfffabfff6fff0b00fcbffc2f00400000c000000130000400020000dcff120001c0ff0b00040002c0011000fcbffbef000000f7bf01c0fffbff0200fd2f000000f7bf03c000e0fffebf0300003c00fcbf003000100000c0fe2f0040000800ffef00f0ff12000200000c0010000240014000080000c0ff1b00f8bf0140ff0b0000c000c0ff2b000c00000000fcff0e000140003000fcbf004000e0ffeebffbeffe0b00ffbffbef000000fcbffe2f00000000c001000140000000fe2f00fcff060001c0ff0b00f8bf0440001000fcbffe6f0030000800003000000007000140001000fcbf028000000000c0010000fcff120001400020000800ffefff0b0007000180ff1b00080004800030000c000580ff2b001000003000fcffe6bf00000030000400ffaf0060000c0000b0ff0b000700020000000000c0048000000008000000000c0003c00240023000f0bf01c0ff0b0000c0ff2f00000017000440ff0b000000014001b0fff6bfffafff0b000800fc2f000c0003c0010000e0fffebf0240ff1b00f8bf028000e0fffebf030000fcff02c003c0ff0b00f3bf0240ff2b001800ffaf00600000c003c0000000fcbf034000d0ff02000080ff0b0003c0fe2f0000000700010001200000c0014001d0ff02c0004000f0ff060000b0ffebff0e00fd6f0040000c00007000000004000030000c0003c0ff6f000000130003000010000400fe2f0100000400004000500000c0fc2f002c0000c00040fe3b00f8bfff2f01f0fff6bf030000dcffeebffe2f00fcff02c000000020000800fd2f000c000f0000f0003000fcbffdef01f0ff02c001c000f0fffebf0540014000040000f0ff1b0004000300002c00fcbffeaf000000070001c0fe4b000c0004c0ff0b0018000100003c0000c00100000c00030000c0ffcbff02000140000000080001c0ffebff02c0034001f0ff1200ff2f003c002000fd6f0000000300fe2f00dcff02c000b00000000400020000c0ff0e00014001100008000030003000100000f0fe0b000400054000f0ff120000b00010000000004000100014000380ff0b00ffbffeafff0b0007000040002000f8bf00b00030001c000340ff4b00000001c0ff4b000c00fd6fff2b001000fd2f00e0ff0a0000c000700000c00000010000ffbfffefffebfff6bf01400040000000fc2f0030000400ff2f000c00ffbf00b000f0fff6bffeefffdbff0a00ffeffe1b0000c0ffafff3b001000fbef0100000f000200ff0b0003c00340002000f4bf0040012000f8bffe6f0000000c000440002000fcbf010000300008000400fffbff0600feaf001000f8bf00400000000c00ffef000000130003400000000f000280fe0b00f8bf060000300000c0034000e0ff0200fc2f000000ebbf00f0000000f7bffeafffbbfffebf06800030000c000040000000fcbf003000400000c0010000f0fffabf007000f0ff1200fc2f000c000700fb2f01100000c0007000d0ff0a000180ff0b0003c0fdaf005000f4bfff2f000c000700fe2f00fcfffabf01c0ff2b000c00ffaf00e0fffebf0240002000080000c000f0ff1a00003001a0fffebffe6f0000001b00fc2f0000000400fdefff2b00000002000110000c000200000c000300fd2f00dcff0e000400ff1b00f4bf0070002000040004c00000000700ffef001000140004c000d0fff6bf01000200000400fd2f002c000400feefff0b00fcbffcefff0b00f8bffe2f006c0008000040ff3b000c00054001e0fffabf0200001c000400ffafff0b0008000070ff0b000f0006c0ff0b0000c0020001d0fffabf0440ff0b0000c000c0ff3b00f0bffbaf00000017000480ffdbff1e0001c000e0fffebf04c0ff0b00ffbffd2f001c00ecbf0000001c0018000300006000fcbf02800050001000feafff8b0000c0ff2f0080000400ffef00000004000380fffbff02c0ff2f00e0fffebffeefff0b001300fcaf00a0ff1a0000800040000c00003001000003c0fdefffebff060002c00010000c00050000f0ff1200007000800000000600001c001000007001000004000600ff1b00040000c0003000080001000000000f00007000100004000000001000f4bf
+InRand = 452a15b4d9006730f0a433be2d84ea6706f03119ad2410292922375e0f7d2c3a
+OutPK = 5696358110206fb1cced54bffe3e0fa80884f17ab7572dfdcb8b290fd99c29c74d007d68410e52899001aa27e511076d11acda1ee6ae52b3489831c4ccb89b331bef19c5beb666d2f331fabc0e96d4bdf5815d394ac99bb410a83e29c731e06c5403b0075cf15ef20edf09ea6a012aaf589a1f670cd6adf8920f177155aa0fd094c101c5487c682f0054152fa2676800673843820172f8cf5c5a64d47a881fd69327cc4885295a5be6c2805acbc8ae6cd8c6512d9e94f84baec76f419e03a272132c3884840610f58fd6bf6893da49d4549d5c0e87d28a417097daa1917c691b08076564d1c6683a139792e6da65d66115026755730d9a61b9f09ab158cece142fcaaf42d56397affd9a7ba6f8c40c7e5cfcd48b81a9b6819ed631c709f28329823c4a64947a3bcd47920dfc949b56eef44c9a256ed225da70d8245c444f98a2c49e3ca97b4632d8155d14aa35c7cc6051c57aab4ca84a24180d3adb15051a49afb9b6982a1a2ce99137297eebe64103fd51646cd6dda0f612268607e1f6aa213adb97a595ec6d9ae20730f6d12da5e6d6273178a294030cc3a4427eb2a1ea9d3a262079eee0165732a8460116d76ad5695dde58dba1edeaad26643a67b3c815970911caa9189244558e20083d1783d7c85aad881bc3cf6194cd8a46a7560c74d1a81df1c84832c91d2e3ad98669b709757d08b534b356b5f0948572bb9023dfdebd5b3650bfa995a4965e3d45e84c06e7f15d731264eebb01c10dd3a7381661cc9491ac3e76efa0ada251c9f79790549f2c9af179b91b44533cc8b2f67f7d6f587bb3c50ab14634ba8d8e41cf4a58a728f55c2b87fe67d7580e8aa3ed249284244f97a693e35d67ac1a00888ee63482107386ccd2023d9465bb7671b3341636a856b8b90aa38b78f25e434c6d8e6b0b20633de72e63750d834ed714e46f7dbc5d14046692850a9846e28518ec0cb78e4fb15bbe3738e852a6d84876fe279266621a5fb2c65453e33e9eaccc95265a668266a6c0ab15bd1a70c525e18f6d0dde6fcb4b23e5b8a8a715e05060209d1f89fa07b1816181f740ded8271e059018408e5a2044df41f81db0376aa2aae69dab1b6e88675aa578f8d5d243e838a231859364cb409fa21042196721a0af53d1a98d82886ade64b64d316204e4d6c7a5389424aafbb787823d87e1f379d5a6622b870e852f7d8db69f14ab905a153dceaf291034841ddadd53129d010b6ff232aca879c11e45c02095394cecc045a70d8ff5c57ad14df16b0c15009476986ffb93abc8848d79801ced33e3f03e37811a545b6808e9461f7a2752afadd6db15e316a599c8979a05c849d54345f83dad8ad8d10bd1f9152dd11884bb981273af1e4ae5386eb33e8f2b7800267eb78f71ab0cbaa05d8fc13be72c5aaa46bf089b5e150b967b17bd242be86df331e7c911a9cefb9b16fc5379c1bb0b8481b3f0ec7ec3fa3a956ac47e1ba69db083055e56c32941e1efd032bd9e413b63737bb99130ec99b1035509ac4611fa27afa265f9e52238e7211e62d5e1faffca7e8c4552967bdca8c32de81545767b5f033a21d1b07131e5ce85f3718f4bd00518f08946854b2e667f7e49291196a5400450ef446eb76ae05f7e1e52f56c49725bc087a3c7288e931d4d87a8ca8e651e7f2ab0b008c56f68a01fceaed626ee5666722603247f6bb2e05038e93c70e1cda82fc2edc3ae5ca6b622ff4af401b7f4c09ca4e9084ceb2812b8ba36435dd1cf55b896250824351149445d6fdce499c6ec94f19bb6abefb2b6fecdb7c90985b93d8c068373210d1ca87d09dc9e78d81b9d2659f939ab1e59b1a58009f468ff887c489fcd4fe3392749554024995aaeed8d57846ce261c0776d540647e8484de8c780e02725a37540f3e216456cc40c5d14e3b412cf5167937bdda6d809727ae5483f715acfd9d422488a1c0bb553ed8a83cedce18e427905c58bb998fdae6fc377f155185d085f83a71364430d275949afa59f4294e7718b56b24a67b114ee7d5c945741c710aa191b202e43ba894917a21fb39266a1995e8e0017007f281bf8781b02918e4b27f6f36d75ddc0c767349a31d35c3af3d8b52c5bdc2e01a29566f1cf94f256206e1d8afdd3f7c20a6a6d98c46b8101fd648484b5fc2f038dd4d8c410a0f3976ad0499873bee69c131d0daaca531a853fb661798967ca011d7251a234d6c94e326217fbc72e364fd02f3f4336e5afe5dd6ee6ad9a411805dec8a2253f778d89d29c2a5d76a544f30818b32d8c5710224090f32a28bac4b2b04920cabb12514ce5d34de66b627ae1a524974c55990a92bd4a01bd0fd7c8fa527b7236421d99b1df396912895da67132bd48158ca540a69c962c222019a1157dc90639743522db4e4a656e307817aa52632add1b026ce82709e50057d81c5bcd3080806ea630a1740bff4cc938b434475028cd1084ea6b2595f77a165a86b327e9c9f2dc0e480934fbaf86951269c5a6c1e9873a16e38033555be2dc4063144d5244e8f3fab06442
+OutRec = 02c00030000c00000000300008000000002000080001000020000c0000c000300000000240001000000003c00030000c00020000300004000000003000000000000020000c000340002000000003400020000c00014000300004000240001000000000c00000000c0001c00030000c000280000000000000400030000800028000000000000300003000080002c0000000040003c00000000c000380002000000000800030000c0000800020000400008000300004000040000000040002c0002000040002000000000c0001c00000000800000000300000000300001000080002c0003000080000800010000000004000000000000000000000040002800010000000020000200008000200003000000003400010000800008000300008000080000000000001800010000c000340003000080000000030000c0002800000000c0003c000100008000300002000080001c00020000c00010000000000000100000000080002400000000c0001000000000c0002c00000000c0003c0001000080003400020000400030000200004000100003000000000c00020000c000380003000040001c0003000080003800010000400028000100000000080000000000003000020000c0000c00030000000000000100008000380002000040002400000000400018000100000000180002000080002c0002000040003000020000c0000c00000000c0000000020000c0001800000000c000300001000000002800030000000038000000004000040000000000002000030000c0003c0003000080001800010000c0002000010000000010000300004000040003000080003000020000c000340001000080003c00030000400014000300008000080000000000001400020000000004000100000000340003000080003000030000800030000300000000140001000040001800000000400008000000008000380003000040000000010000400038000200008000280002000080003800000000c00020000200000000000002000040001c0003000000000c00010000c000180002000040000800010000c000000000000040003c00010000400004000200004000200002000080001c00010000000018000000000000000003000000003c0001000000003c00000000c00008000100004000240002000080002c0003000080003c000100000000080000000000002000020000c00024000300008000180001000000002c00010000800020000300000000040000000040001800010000c000040001000040001c00010000800038000300000000200001000080003c00020000400010000200008000000001000000000400030000c0001c00010000c0000c0002000000002c0001000040001400010000c000240001000040002400010000c0000c0003000000002400010000c0003400030000c00008000000000000000003000000002c00020000000010000300008000200000000040001c00010000c000340000000040003800020000c000380003000080000000000000c000280003000000003c000200008000000002000040001c000300000000040003000040000800000000000024000000000000100002000000003c0001000000002400020000c000180002000000003c0002000000001c00030000800038000000008000240003000000003400000000c0000c0001000000002c00030000c0000400030000c0003000000000c0001c0002000080003c0000000080001000030000000020000100008000300003000000002400030000c000200001000000000000020000c00020000000008000180000000000000c00010000c0000400000000c0003000010000c0000400020000800000000300004000300003000000001800010000c0002c0002000080002800030000400008000100008000080000000000003800010000c0000400010000c0000800000000c0003400030000000000000300000000240001000080002c0002000000002c0001000000001c000000000000240001000080000400000000c0000400030000c0001000020000c00000000100004000280002000000000000020000c000380001000080000000030000000020000300004000080003000000001c0001000080001c00010000c0002c00000000c0003400010000800020000200008000080001000000000c000300000000340002000080003c0001000000003c0003000000003800020000c0001800020000c0001c00000000c0002000030000c0001800000000800014000300000000180002000080002c000300008000040001000040001c00030000c000140003000000003c00020000c000240000000040003c00010000800014000200000000240001000080002c0000000040000800020000c000240003000080002c0002000080002000000000c0002c00020000c0003800010000c00018000000004000080002000040001c00030000c0002800020000c00
+Key = e99667992da3a284dc25fbf5e0856d5877938a2b7e96172e49f5b6cae78afb8a
+
+InNoiseS = e5c40729d83a968c6b2ae550c89b6623e77579f20c14a6c8cb4a623b25da3973ebcc3ee5c92a34345957fe5d10827aa05da022a399332066a2679d11e83e00ac2be799dd3eb7a6a4c787e0b59fee900013ac050b77cbda453cfd06f0de51694b12433fdc32e37b16a8e60d2bb02b82101415850212b676144ba4145ef47731af3419fc8e406be62485d7da056868435a8d1c6a52823fd4ff3db975998aba564e7274525407c318a604a4dc1360c6629f9d425963019f2c9d05901e38abfe87ee51e4ea7c8591ed84c2f991669d6454d9a1b3b88e41e9309e94ae8fa797a91e27fe08f09a2c5e826b44b1626bc88098a4280428c05ffd8129939d450bd912784ae55e13c7044bc593e9406c1ec0c262ca59f225f60a812217471d1fe6af221c98a43135f6f6696441f17b698d92702f811702ce6b292e852723d21f996675c77070427be30a70f8fc8decd69c94c19c88949ac9b528261a26a77016952a7e91a17ea81be4bc4f2175d8b44835472e1606d0059a2e4d86c236cd9c8f27dbe9fb71800b5c335862f62acd0bafa1aa6821d585f7e6b4a5718a6020d4c53244b99d80718a09621766b7c158ec90cb0dee4bd630a9264a49db854e3af0126b17359842956ccca27e498df495c220ab9968000c021a7386464f958f8691a66c671186a26e484f04e5b29112e409ca5f366091d69ab4492f52e8f6abc7e561394ae89ce050bb776b7c3cb3c334f9e5da9fd3af1de2c68a2109ec683976a24cc4255139854c4a482fb8555e926c41a96db8f62e62f4ae6783bb48622a8e2373c7b0252dc40d52b1713fc48b0058b1f65a0fcdb3b8d07c3febd7eed55021773a58e9017aa90934c55f5799d53ee4aef2a8cb2209c01fafba6151be916bfdf15862204c52adcb0da5231408ebca29c02029cfda60baaa5aa09da3f3719495fa8de6107a6d175b030d8b84fe4e5b4f17032f447a20695f349ce8124d868eb7f2dab6820e6f78115c53514ab631f6fdbf3dda71b1be890d12e5bab273a9312d2afe739b6d75c6cb6446c445aa0198eb862748b55de2054acdf0b54bcd323ac6f27f4de55e197f7517210142e179d81afc501a88661d89be6c7e6aabac160704a5b6c1a2b829d9ce7486418fb92cfa23bd1ca3872a0b67b5ce4c62caf1a495bc442c11cdc87c06563d1a73941ae907d46ab77059166dcd11d12221582bb49ae411debc6cf36a9ed3c68643f7c18af0cf107e7dcabbb221cc201023a6156bdabde7e9b12bb3c64e0f0fb92a87ba2c59dcb8a5d48d97fce343ca0e69210b1c4d01897141ec4627e3a7ce05f848c4c558e0af50c36c053b100df69532935f46293a29c5c8e24ca3ade25bb427712f80263b736a6403cdd4c47b284d22ba4575d066d202d498e86b6ec23dba8abe87f63e375b0b6f41601c68fa1717e67b654ca21bfb428a0ca7ff5d2f51447e05a56e550a6790657cc3b0c736922fbd21b491694a64a11f45108b605f06d8610686f2912f504ff07f313edae07930cf8a4e838b0606a402625c494205fdfa764a5a9416853548364b0cd84ede3d3ae49af22f4d01ab127d31264eb8ace5d2554e55290a2d8979aaf88a761582f5c92a19f49ee4f573d54a61a638703e7535eb465bb6fa3a3dc1ab5cc452d826ef6e818a65aa842f1b60c57a50354fdaf1518f4d94c088ba049a5d963105f2a8e0819da6192361240474c5cebb328cdd907a2e04b0bda41c720c23c808a0918e68fb83dfe12684a4bb471eba7a0d48e75847a44042220ab85b412048da1981306d52fc659f34876d16ae89ccba803080b9268a8597bd57f00dcf79012cbb0528f9830864a129a5495879d228ef86fbc5bb39ac450b196a97200a1829323781d64fe981fac57b5228719adff3ee5e72c29af5a18d3e9635574cb65b4086e92fbb1ba62d36a823139955d186f65d05b6bc3915e5061416f548837d532a453aa50eb26848121a3a33aa5604c678249c676c8ec973c558f2e8ef88fb105998550da3cffa09838974403e8610370b2937bae154f488bf31c816890c83b878cacc577f2a3bb256687025c17cd595614fd2e803d1fa2891634772badad84549a71a5ae83e3b9418f6f9f6ca6d4a67d9c30459554bee4ce413091e1ca092a507d9685fd259d5f0b991d0645dc6d48a1fdf8171aa8e4c210c6cef97360155acdbe19b55f000012120e221240964cdf57b09900791e02f5168ddb798e3bdb1056298ef04d00a1bde9653e073e8899530db2d30961a4a58d604ae055ab56e5a0dcb77403a41e51b5d0895c675900c9e253d1851e9d87eabf235056bade602f0952ca1c8dbd5cd4a59324d5dfbc309518b5769926a4c7863c51db8a4249c6fce71c92b9c086c217f987a38569d923b01f58c3c3682a5a796223f89c7262160226cd8ef3730ec71a43d4e3053b2f15b855e3934501a90bfc6bdd9c3d6003ce2d86076215ce2db3e31bdd2266c8693e020129d63576617d3c68127608b7566b4be9dab7576b4167fa0cf610180153207d5ff9413488a
+InPK = 5696358110206fb1cced54bffe3e0fa80884f17ab7572dfdcb8b290fd99c29c74d007d68410e52899001aa27e511076d11acda1ee6ae52b3489831c4ccb89b331bef19c5beb666d2f331fabc0e96d4bdf5815d394ac99bb410a83e29c731e06c5403b0075cf15ef20edf09ea6a012aaf589a1f670cd6adf8920f177155aa0fd094c101c5487c682f0054152fa2676800673843820172f8cf5c5a64d47a881fd69327cc4885295a5be6c2805acbc8ae6cd8c6512d9e94f84baec76f419e03a272132c3884840610f58fd6bf6893da49d4549d5c0e87d28a417097daa1917c691b08076564d1c6683a139792e6da65d66115026755730d9a61b9f09ab158cece142fcaaf42d56397affd9a7ba6f8c40c7e5cfcd48b81a9b6819ed631c709f28329823c4a64947a3bcd47920dfc949b56eef44c9a256ed225da70d8245c444f98a2c49e3ca97b4632d8155d14aa35c7cc6051c57aab4ca84a24180d3adb15051a49afb9b6982a1a2ce99137297eebe64103fd51646cd6dda0f612268607e1f6aa213adb97a595ec6d9ae20730f6d12da5e6d6273178a294030cc3a4427eb2a1ea9d3a262079eee0165732a8460116d76ad5695dde58dba1edeaad26643a67b3c815970911caa9189244558e20083d1783d7c85aad881bc3cf6194cd8a46a7560c74d1a81df1c84832c91d2e3ad98669b709757d08b534b356b5f0948572bb9023dfdebd5b3650bfa995a4965e3d45e84c06e7f15d731264eebb01c10dd3a7381661cc9491ac3e76efa0ada251c9f79790549f2c9af179b91b44533cc8b2f67f7d6f587bb3c50ab14634ba8d8e41cf4a58a728f55c2b87fe67d7580e8aa3ed249284244f97a693e35d67ac1a00888ee63482107386ccd2023d9465bb7671b3341636a856b8b90aa38b78f25e434c6d8e6b0b20633de72e63750d834ed714e46f7dbc5d14046692850a9846e28518ec0cb78e4fb15bbe3738e852a6d84876fe279266621a5fb2c65453e33e9eaccc95265a668266a6c0ab15bd1a70c525e18f6d0dde6fcb4b23e5b8a8a715e05060209d1f89fa07b1816181f740ded8271e059018408e5a2044df41f81db0376aa2aae69dab1b6e88675aa578f8d5d243e838a231859364cb409fa21042196721a0af53d1a98d82886ade64b64d316204e4d6c7a5389424aafbb787823d87e1f379d5a6622b870e852f7d8db69f14ab905a153dceaf291034841ddadd53129d010b6ff232aca879c11e45c02095394cecc045a70d8ff5c57ad14df16b0c15009476986ffb93abc8848d79801ced33e3f03e37811a545b6808e9461f7a2752afadd6db15e316a599c8979a05c849d54345f83dad8ad8d10bd1f9152dd11884bb981273af1e4ae5386eb33e8f2b7800267eb78f71ab0cbaa05d8fc13be72c5aaa46bf089b5e150b967b17bd242be86df331e7c911a9cefb9b16fc5379c1bb0b8481b3f0ec7ec3fa3a956ac47e1ba69db083055e56c32941e1efd032bd9e413b63737bb99130ec99b1035509ac4611fa27afa265f9e52238e7211e62d5e1faffca7e8c4552967bdca8c32de81545767b5f033a21d1b07131e5ce85f3718f4bd00518f08946854b2e667f7e49291196a5400450ef446eb76ae05f7e1e52f56c49725bc087a3c7288e931d4d87a8ca8e651e7f2ab0b008c56f68a01fceaed626ee5666722603247f6bb2e05038e93c70e1cda82fc2edc3ae5ca6b622ff4af401b7f4c09ca4e9084ceb2812b8ba36435dd1cf55b896250824351149445d6fdce499c6ec94f19bb6abefb2b6fecdb7c90985b93d8c068373210d1ca87d09dc9e78d81b9d2659f939ab1e59b1a58009f468ff887c489fcd4fe3392749554024995aaeed8d57846ce261c0776d540647e8484de8c780e02725a37540f3e216456cc40c5d14e3b412cf5167937bdda6d809727ae5483f715acfd9d422488a1c0bb553ed8a83cedce18e427905c58bb998fdae6fc377f155185d085f83a71364430d275949afa59f4294e7718b56b24a67b114ee7d5c945741c710aa191b202e43ba894917a21fb39266a1995e8e0017007f281bf8781b02918e4b27f6f36d75ddc0c767349a31d35c3af3d8b52c5bdc2e01a29566f1cf94f256206e1d8afdd3f7c20a6a6d98c46b8101fd648484b5fc2f038dd4d8c410a0f3976ad0499873bee69c131d0daaca531a853fb661798967ca011d7251a234d6c94e326217fbc72e364fd02f3f4336e5afe5dd6ee6ad9a411805dec8a2253f778d89d29c2a5d76a544f30818b32d8c5710224090f32a28bac4b2b04920cabb12514ce5d34de66b627ae1a524974c55990a92bd4a01bd0fd7c8fa527b7236421d99b1df396912895da67132bd48158ca540a69c962c222019a1157dc90639743522db4e4a656e307817aa52632add1b026ce82709e50057d81c5bcd3080806ea630a1740bff4cc938b434475028cd1084ea6b2595f77a165a86b327e9c9f2dc0e480934fbaf86951269c5a6c1e9873a16e38033555be2dc4063144d5244e8f3fab06442
+InRec = 02c00030000c00000000300008000000002000080001000020000c0000c000300000000240001000000003c00030000c00020000300004000000003000000000000020000c000340002000000003400020000c00014000300004000240001000000000c00000000c0001c00030000c000280000000000000400030000800028000000000000300003000080002c0000000040003c00000000c000380002000000000800030000c0000800020000400008000300004000040000000040002c0002000040002000000000c0001c00000000800000000300000000300001000080002c0003000080000800010000000004000000000000000000000040002800010000000020000200008000200003000000003400010000800008000300008000080000000000001800010000c000340003000080000000030000c0002800000000c0003c000100008000300002000080001c00020000c00010000000000000100000000080002400000000c0001000000000c0002c00000000c0003c0001000080003400020000400030000200004000100003000000000c00020000c000380003000040001c0003000080003800010000400028000100000000080000000000003000020000c0000c00030000000000000100008000380002000040002400000000400018000100000000180002000080002c0002000040003000020000c0000c00000000c0000000020000c0001800000000c000300001000000002800030000000038000000004000040000000000002000030000c0003c0003000080001800010000c0002000010000000010000300004000040003000080003000020000c000340001000080003c00030000400014000300008000080000000000001400020000000004000100000000340003000080003000030000800030000300000000140001000040001800000000400008000000008000380003000040000000010000400038000200008000280002000080003800000000c00020000200000000000002000040001c0003000000000c00010000c000180002000040000800010000c000000000000040003c00010000400004000200004000200002000080001c00010000000018000000000000000003000000003c0001000000003c00000000c00008000100004000240002000080002c0003000080003c000100000000080000000000002000020000c00024000300008000180001000000002c00010000800020000300000000040000000040001800010000c000040001000040001c00010000800038000300000000200001000080003c00020000400010000200008000000001000000000400030000c0001c00010000c0000c0002000000002c0001000040001400010000c000240001000040002400010000c0000c0003000000002400010000c0003400030000c00008000000000000000003000000002c00020000000010000300008000200000000040001c00010000c000340000000040003800020000c000380003000080000000000000c000280003000000003c000200008000000002000040001c000300000000040003000040000800000000000024000000000000100002000000003c0001000000002400020000c000180002000000003c0002000000001c00030000800038000000008000240003000000003400000000c0000c0001000000002c00030000c0000400030000c0003000000000c0001c0002000080003c0000000080001000030000000020000100008000300003000000002400030000c000200001000000000000020000c00020000000008000180000000000000c00010000c0000400000000c0003000010000c0000400020000800000000300004000300003000000001800010000c0002c0002000080002800030000400008000100008000080000000000003800010000c0000400010000c0000800000000c0003400030000000000000300000000240001000080002c0002000000002c0001000000001c000000000000240001000080000400000000c0000400030000c0001000020000c00000000100004000280002000000000000020000c000380001000080000000030000000020000300004000080003000000001c0001000080001c00010000c0002c00000000c0003400010000800020000200008000080001000000000c000300000000340002000080003c0001000000003c0003000000003800020000c0001800020000c0001c00000000c0002000030000c0001800000000800014000300000000180002000080002c000300008000040001000040001c00030000c000140003000000003c00020000c000240000000040003c00010000800014000200000000240001000080002c0000000040000800020000c000240003000080002c0002000080002000000000c0002c00020000c0003800010000c00018000000004000080002000040001c00030000c0002800020000c00
+Key = e99667992da3a284dc25fbf5e0856d5877938a2b7e96172e49f5b6cae78afb8a
+
+InRandA = 466e66f041312a755f555a949a661f8966f440cc2d3a4cfc08ad7aa8f018a681444247d0dd37b2ea61a2496ad9880bdda2c2c41895f83180f79cda5ba1f202f19896aa9ba51443ab58f7349c1fdecef93b444a9996a13d716e709efd1c08e2e2768daf974c78dce6a18b5eb9ba8db402ad955609740425aa21457adfe5802991075b62dd62ee55135b4040a3b32147748e9980e0958736c66c24262cbf55c782646c255712e4665ff80576774d420f4e13892016e6530001df93fab40ed9d48ec5d2d44726cfd0dab47094b8dbf0da6da5b4f7534e680166788daeb2a7bbfa2f746fbab1346d3f3d8f82d859f973661c3c6bb624bc0ed2de274789275110fe50b9e18ca5196040006e9dc78be2bbf1214e6e47e305f54e7d1b51450781123ae01ba6774ca51a7745f2a68aa44e37a8d6444fc03aca490fd4a1aa02908a51e1df4cbc1d0804d70f9d94859b01264cea842da37d86fdf97f5cad10b03aee627545aa02c3d67f07de5f63624e45615308a8e81d55698851ba625188624b032aa52cbbda9c80f715897fc86d300b527d303aeb03b8b18440b21e2b0a682da5740dc9c6863a5a1606ba784e2e47a4ca2fb09bbe641346d533e82c221d6fbbd29a2cba99d71fc153959c62985bb092de06c2253a032ecea0f6d8bb041ac2236a98f51a7220a73c52f4498d153ad99774883f85680410944030fe28204db6ba2a454a0928b10af2b920b3658e92c3bdbcf4681c7993f2aea59c419a979687a3ac2180f94c8e50c293b627c0216f5c0ffa2c310b7d49ccbafa14875e8a94b3ef1e3ad7926db6eafa0e87cf04a8f5101a8407f0d7e731ae31ee23f14c09609c29e254dc781588648e89abe662fc5a79e30cd8559bae7db123b96f4dd878526374311b681c45ddad6d96a520a13d6860e967e3f7daa8718f86f5c4cca4309f5caa4646b2ab5787033553b4149de6d63aa4593a70e6486b0c3d4d02dce897d0e14bfa6bca6b261176ead285e7007905672a76754c8d66414d99781eca5f9e83fe7bc3066c139eb909d3156d79d1860a2650149683e34578f272bd185a93b0418e50844fc04b253504e8e2f7a60a50c1ddeb747c357f249164d437e0bf53a8df2a01a836fa69d85893ea895c449fcb7e6d7c9f24565848b97f529e376885a219640774898a96aaf7c1260b871246949f6874c23e28e2adc98b3d6e4fdf8fc091a45e75ae6503f535f4b1ec20f66b61152f63dd8e3bc512305a0cfe9bd09a5c65910586123a246cd8188764c5895d278ba01f91196f4c68599cf1b3b800c37bd3f813a5ce326b0d9952ac4b6b96bf2468de4837157451177dab8ccb5d90591f5c81f5d8f14855a22ca4e89522fb4ff333756021f4c3b5245738293d8c81d4b0dc7ed618ac14c712350ed97d1685388ec2e14317a2295710418889fc3e214d2d225869509b068ca5032af80db7587b759b4c073069a4c4fe9a8be40f39d500667dc720b90a2ee17785644a6a3be55f51260736ad6525d7e121f413165bb38142621191b7f21feddbb8a658cd013187b246051ccc0cf952f574148317571a6643666d9fdbd4fd7ed343519b791c131c68ee85850595339c962335351744db3738569cb5bd42becb2e3c0c2be214592d1aa3f1d3cefb6b364896cb12096b2491df4381d50ace9f766cf140fb289a5b6415f0fa72548ba6e54a5da261bd2606150ff6003c87af1a687512645cfcd2cb555962d59c5affec340c9460218541228c99df057601824715f38ba0a27f945125fa1322a02c4b0e3388866cb349f4d0a1e423cf20d41055a46be20e0a43d70183de531537c9ec0229a65168027494f19a4ce8ace666298bdbe3db10bafb4661d7c9f8b70ca955d7054a25dbcc6575a18979ce4d42118039a739811429d0e26f4f6b842890e47c6d5178d5f2ccac590157f9b35aa0746b9c9353181a546ecfc92131ba556c1638a9529c6688f037ebf8879e15ebaae9f881c9db1143d7509b2b8ca242ecd245dc0898f847b96bdc4c273908a2149817eb2bb0aa9963e54007767ea0afc0d9508f0e5039cfa257f19cb57898c52737f16958e30101d289a484e7e460643409126c6610a15570648a40a0233cbdf863cd1384299f6cd5b8a88c700bff8faf80bf35874a024db6164195bde038e2f61c4d9e6994643ef0923f6c795a8f2a9d24a2bc391b4046b8cf4bfb40287893254c493a70434b12af36c64d645ccd6e4bd8c003674bf315e512bc9d21b6121ad11a790197bbf5b453f8443449012544e02c5045705c908a89f2d1faf0309d0aae891efc1717aa3f32ce3645138c13125db68d06effa6436359783c4d863702e6b2b4f7eea76a4504a8d01d39ab252d66a64f3b19186fc5918f19d4a36d2415aa943d267cb5d4673990e74fb8ed8484af02df782cd23e302574069aba1a631959be32831c3a27b35a3ff909de8a1fb2a6c852fd05affdff5fa11ce353ba7a3b1e1920bb62c497acdea0243431d8ae65459e867aa8082d44a5ac8fee3bd3d1653dcd0d209a62c
+InNoiseS = 55d10f4b48067ba8ef2308defa0285cec13987c82d528761f851ce55ef4f40659ebd2f0b6deae54a28ad4dcdcff387b99a8e4639c0cf354127186a92f6c0b1735f6d34d89596800646533332b2e5dab016a3d5129f8702223a94003c03774bb2061d322a86d3b7727904414df6c1c03c1a680863a43a09a862e6a0a0921eeb4431188c4c7b79edd293f24c3a1496763936b23d599d922b82663fe59836743d843046d5ac7493a95e36d16b770b7a47bf5b958355fc289c653e4637dda5ea68d40253440eb96f5976ad7a6248a138e760352792267249e91239050d4cf24406a57b2d98025bf104e587632aa7c52f65e781561b0e71c5ce16f371fe50da1f6008f2824828523fd3e2a201050b17a2b474491d49a0b36c8c34eea3adf9339c20a651d6eaa5205f406d933113816e1b5e587ad49a09de8e6e6630f60ed96163833a8560385c1b2124f165ece2ec52af9a9b612f9dc03a81190e5f46eaeda60faa0b7fb79c047207cc4e48078a46a0c49cd1132e9c9a00f85a193551a8cb4b99ec1d6c07491c114969b652935a82bba252326dab5440cca66fe24c37fae468a32b22d21540862f062c148fbda0f0a320ca12ca1ddadc661b19b45c461a38171ad57da96b89c01aba52ce596ebb325a22016e2070d5420284e4a319bf521480181ac4294d28ee037016f03149ad538e632f3c274a162e93b982079fa85aeadabe3cc58671e4bc0a2604243037ae98211789dce0b5a59dd89cfd5b13c56c97d520d73a4c373501f604c3316ce255df320b9494d10d9415faed012ac6b53400bc6d47e3307852697a142c4a9bd28a16b11cf93af3914d31e020ebf4ce8dd41aae69e8885ba641b47352212e69c03f932c5c4d54687a3503288ef5c3d6ab83fcaf2059e9098b59a898c7801683d636e45cbbabd1d8268606c3764111666fc3d57845891126dcd9faa5191a8bdae12466d62cffca274b10129b5d1d5caba36c15bf1e7de911b471a3c7a82ac6ea2374122e2770f8237c0d48e4e25c112b2f6659582567088482c9e9e0789191d226353878202120448980a6b7069bc71bde617452fd2317ed4e989f771032c46ba99724806f5998c8e8fe940b7ea24e6291ea5e550e7e5e2088dcdc6c60dee55496f22c870ca597357d728a9e45c4a8a44c984f48a62281a994098558f77eb70d2b690601a92c8327ea246355744ad97d912ca63d84eab3e0cfa521ce800699989a79269d10fb9285826da751db0dee4c716eeb946b59bf312226e7b95171915ea15615a1bb1c59a749cfb12761edd989e08a79079af4a781dc4f5d6056a91a0661742e5d54673a6c1cec1013739c2e71df299942769ef25da2e5daba26f9addc5155a8608aecbf53254c2d27a588b0823aa54d0bc24a2131b7d842edb3f9666a798f3e86abfe279d86259165bd93e8e7f913ab7d14a94f40cb44062a3d2728e9029ebaa6865be89d7d052c049e7389ca866022c267a3392f689d7ae627fa3b58141ab762d10be4e6d8752edd88cfa3985bfc723023dc380398ee9d9b9b9153a5a06eb295858397fd7719400f80e38aa18fd1eba6c324b15726f4907b84897aa3ff347578a13f1b905a148db1ffe55813c17831f54ab7eb52b44545427a25c17481d0851b590c4e1ea2682139c421108dd2bda3fdbe90549a7548e1463cf0a51e4abe1c171f4866191cba036d270248635c48848fdcb690a0bae3240029cbd688a4d6f150d08d6a0b4e62e2714e57806aad69420c71a72788c996b19b5fd5870506262b878e354056ed2dc4cc6bf00e59acd15ef776d1ee75970799c95a5a32814f8e790d459d32d4ccd807117acf2d2ff290a57342e9b439fbc6163c268953fcc0444d5afd040dc035a3aaa54884c09b4d60f2c0cf2c1e91cb1dd5573e26f3ca8609d3d582c926d429005891c02699e5d3c40eb203a8641fb8bc5dc13a04e832b954cc0003988ab691495e5662e21afb22ba667836bb7f177301005ba3124e4f947f851e5de9b8042b5da3476cbee91e588626da672217be58d146a2f3eb590be8832595455972b5531a87b1e63c20ec19bb9ee925ed1d5c7765b19c199769920d8c4ee6d7eaa3973995011e9e77c6de17662beb49ee169dcda4c6d7091459794277a0418c55926bbbc83a320cc38de4126612a3bd8a55ebfaa897c9e17082319d71b2c964ca7471721e96c69bf84d2ce9149069e119b3f40617d20dc20404dd587aef66972f14369056e2673c5cc54877f69bf8e0ada3527c58c9d8c408ce218c04858e5b94c4ba2e2da592b4c0bfb2c9e0a894e614e7a21baad239149743d1e4b3b068c5c324e1080c09eeca22487b2d807620ff20f64eb1ce404ff82f3926c0673b4341c6a6a1005b08e1fd27578ed1373af6879be3159b2cad27a29eb0c9fab2358258d0a946b1396e6d007995c291cbee1837b4454a13c84aa7b4da799bdebe33b9d2879d11f02008c82a7f9d48c33e5c57a74f731496b62a180db690406a9d8828c13550093aa1a29309ffb96adb68cda1a1089a
+InNoiseE = 121aa624d30404040175048b103de50d947082212327e5c6d7208da2728f9ea5ef151880c98011516e525785943af3824676c562531144a82704add92ba0079da53dc88ed59d32822781a41949f60ee8a8b35822bf8bfbd3ffa47b0a6b46a16926ab810de79289c15659261bb4c91600975658b4239a00406233211799177811256b0f7597ab4b169bb0424a900f76759682b3d542d341e60066ceead0b319e40edf5333177f712c4a9788c11d701f2e1a214aa7d87210a1df861de92d676999e4c68e0ddb41de716c0c569c5e8bc62ece83ebc14266c819573edd33f5c52c286d65dccb8a3444d228800b1dee5d88430fba5a708637abfce060c57cb926dda157092959e01b455e754065dfb97092c965b0e861fb7dd150f811e5c3f77d41c7dc5356f0f497c0e7185702398a8dc5d311c58c02d00d18155e1901ff0afdba08724a5883e7b2a66a4dd2d85cab4e2d8c87856cb93af91cac1337c828565d8950fae2582177bb40c3da5e5034e9478b2789d163d720229b7be153d5575c86cfe58129eb1435cd8e4a816e76e94411077d9d9837463884452e5dc8471c71b5c9fdb859d25734295fe0be0c551fa901a6fc4515e7554cd3bdb87bdfd9f17a41a13396d806751c1138e81995ab879d59aa89df001fd882f5138df1bf62ad4d96ef641c3577e04ea5e372ca3a47d7b8c8829d0f9da89c25a394a0921f4eab11ad0e17e931c1ae1e89ff0c59e025bca569823017f9cd007605d156a2ce6ecadba763dba289f6805261b0d23cd8aa9ae759f066c0130e675ec52f0797e278b0eea94a6ca80729459acb40cf19af581184590eb70b8c1566534de4f5dea35c61a9f62fdc307f282fb33d84ad5718459287853f769ce497d25c3fd55192468524293aa906a6b1f11524804375f8b8324d084f639e5506bd55ab5732669df1159c70b3ae32ee63cb06317e645d241c123a787402491c31afed53e0228dc0e2462e86e70b8afcb0065f13fa8193be55a29a59327788518ec8ff3b15d290366bb93698f82c2bc7d0a2e9c50f042708b403982dad02ac976d9aad53a2a8195b6844da8475772ab8a322ae12c7b81ca7401d5942c8763c00c503e6650a95108ab596b1814c4f919213722a4a36d7045b9f801ad9a872b3913e41ea46d01434f9b90ce4b751e01821bcd883a63a2d9837121ba23b2d72bd8a07e22b14bdb3c616a832940100541936aff634965b5c0b9c9051dda6fd7593f43e266e56469c0a90c0ae5e57f781780b111bdbf2c9667542ac025f6697cec7a215cb765016ec07224b4d58f18350b2aa764368a69ec4913a3534c455f9f2c6a10d6172d61c8a950d8fa6f5c6a5b8885de6a227b5a8708d868a51315ab6c61a16e9786e08cf3c857c415662e32ef97b8e24c5166c9821c02f8be965d890d154f01f5eda8136713607740a122eb26c0910040ae879bc935798da8413538e2ea9568ebdc9504c202f9a8e79098ce92e1e6115c507a06ebc055e64094711c5388695b84858989cc2eb96900a48129198324af985281ce6ea74d0c2a4dd6515a23bf488808344f00f3023905de32185a915fddd9901c0f5724eadc850439e2de4e166a5814c3e40d36686c5115ed5c13d7146c1031182e3175de04cdb54add2ac990600878f858ee4970a89286ab7e04587cfd879a8ca8e2a2dfef6ec088090dd20e0d2624ce5edb6f57f46aed3ec8039196e9c7bcd353acde58e65c26b01a6dc7f03eb1de5c97d8c9c97cf9b5062341800e7fbe0de48686645b79c257feed2253a1ae5a29ea0ba1479da61130159b8494663f56d465b91026cb7ee7a56867688575c0268f0ad053151716b37a9b9dd6fc4e6738132f4e4dbab3ad61ca24bbe49897958bba0d0db6276100c2fce04e04e392cecdd6799126f8f179494f1563eca6a2c930acd95f169b4308e1e62689c14b8e3f27be3c1a772948a77e4d38990a9983a744400bb0aec769b21db0ae10963d80e65619a7a39eb6bf614b64811bc452f67a60d595c6230c802f252cbdc008afb351cc4268137f48031d32ac71b997d9f6eda00f5efe28078a31bc2ca0e77304191f6d7aab3e561a7577aa218a18eba60257a8bddeabdc61164a8111886d89000478f9c1bd005198e5be5ed27078e096fd56030c51c04cc673f09055d3de26119834e668192d045a03cbe054768d05be3a8895205e4713a8e826bdbd6660bac715125f928839981ee898fb4e89d196b213f38643a3b9008d9c8cf4a2f5d43e232d70582c9e9c0767d64068ea447256d9e1ddf9e0e3b831a702acda0d110b522ef157ce9674d119ca14dcaec20371301c89263e42f57d15999165d0f44d11a54564a083059f5633cb9bc4e825f6bef346985ee571b8f1c45ec8a42b9cbf4abf214ce904e4d5e41636f57243a0e7ba4a52aff900cc25eda444e814c9f253fe34532a198dcab228ba12f2b576784f7847a8596fce7caae95eaaba06b74b67c90def7db4fc10d645b28d3bcb40c0606cdbb63a48284405053da8d2d67d68bd3b1aa0a
+OutPK = 9b9c71049e319792e1110bea4da03eda4dd5220d01ddc3c921022e5d3bcf8b70c1218b77d576d564c08f95d6fb271fd09c6c546e764e2d8b36a72e852de90d89683e9b54598fd7dff269431685381ff842643813944c2d502a582162ab35125938acde5ea3b2644c16dfca13360efd8c0dc02284750c8e8255aba28d2411591463186d4c5b63caf21a9972560c848c01d650b256a0b2f312850de681720a35012ad22a1fcb89d491768f9524e74453370075d5a60d6e470cc348f1e20afcddb41bf44c73428f41dbc50e27248f7f11683e0abf5e1bc4e1e1255fe2b22b1bec643389d453a8e58be11205237d8e9578ca9b822c18856f6e2434d39286dfcf2b6280d84f6ee2e1c3fc007394240e448a8429bdac9dd659edab45adc3608b1050c7c521aa19e056599b8c820e740f22dc6e15b520a8f4933f53adec2e9d270100389991eb00f6f6f21676699d72f95ae838dda9f5e43bfc985c554532801122e86527aa690c4567af3eb755f540abc6abf744ce8ae69f83111a4c9a618373c5cbb61ab2a91b028338b1242e7f170196331e0883c66f784c6edbbe8b0aad15572a9116fb3d50759a3695e38d4ae7c61888a15e056ec2057269f5600424256435bc2321ea102a333531a96ddda6584dbd3d171109b2b533d00720754d99b4d7ceecf891823b2a95be9bbf960a2626281b7402a1555ad5933c793757abc611e9ae555e882257a4125882438134c89d17948cdd4174a28178cb0242a55571dcaab8cae3494578ab84124ace3edf82645ac1386c12595debb108951e4d32567fda2e12cdadd810ea61166dc2a83e6d9c4a578c212df229cd0b8ae52e89584b2729359f912a6e6fde14b1e22a78191bb26259912be8ef71edd98d85484e647461ba9c5ac332d8959a42c5088990ba08cc877b0acfc964b31de2e8411a5cd6d94f769c605c8a5a2b25c2e66f42983281e41143c489ce29887e1f7898a4606071bee156bef0d49a455b21f5ca7beaab014fe597ef3d9d514d56110d21b532a5f0401419663d215b81ef7d7f28df3f1b2d401df4d8659381ed4ff8db80e964aa1b7297f0632d2c8b2b822678e1b861ffa9bdb03e013e916a392895c91e890c60d65c3650b1cb8d4adbd014f45ef50617b48a2353db272160a8d48728c2565c6a0511b934a3050a246a200b6e296d694c324376a9569f0df0c525d24ccd9b1a779da422591cefb952dc72f16859a1e6b84db768233b03581853ec7a40bbf98980411ebb5a396352d492b6accc79129b964417e94871c480a08e867c2069d5e03b994084e4c5f3d8c499054c2903d1c0913864b92734008bc396448340b91c5157c325e1a107774dc1779352164508fc721d268393442c7212e8a9da833c851b224ce7975e621dad0a191575571e6d505b91c7423884bb9a464a64e6a40e566a70c8c74940768fca4b62d03023c430826005b7bf9dc6f863f51e98aa713b781d8aa1aa65f73de019be459852850684f963502a82c9619867026064f9543a13dd7af9bd77eeeb25d2566cb2326b2d50805602dc270655d8eca27320d5302bca56ef5eccd4046066a4d9778675e15a01d17363d0c5076f43de1084f551674a6b02a990ae164284e467dc300b5c619bc0a45e411b8e5b15121d1e62668850d4a45ec7a56113e213dd291a40d80d33be8c0cc3fdee08e0a94182b63c4d8de78c1aabd5ab6cd90b18de9e7e5684f8b497a1751867af4218c20ca949fc8506a837fe9e1843b4da6dd690c9cab2e00880089bf0af4914c1ab01241c5e9816efe9275138230327e23a6ef42ce810c088feaa8b2a5d120837bca64b54a57618228b5bad1c02d33591d71790027780113804dc60757991c1150580398a45c1620bb17c620db8ec78d04770b2295086a6a6ea36ab0f44e13f70364a890532f08a8f9a11557093a27ab8ebd5a0bc9dba17a972c4db39aa6580c6b1a4a1208e5af6cb6d246ec44fb463cae807f668eb27c3390a60ad3cb3ca021e06d295ba7bf07483076f73ba44ba81609259aa0d7b48a975b56aad075c06002696da667bd23ccb26045bfadb6121dd810ea05b77195dc66cc5c68de68df80cdd2ea6a699c451c2d6d033c6c4915c8408009494029fa3782442f83d0fa2e8ea536d1a8f4f146344a639609753810a512539eed3673fb60ce58dc07b97d80369021f6738c92ea445c038e0cc89d8596e6268641b2604b3a6635d594b9348e73a6a448840623966fc5497d1cb252714b993ef45a27b3d36f01da8cbface615dc349b0d8d168b1aed283bd38302fc181984734231660e076f7dd56eaa839f398d18c00cf4a418961231a506ec185b862d4c442b2820053831abcb609e13956d9440150e50da9850f95ea8a93bf54984b0c000bc299a721a35ab9882e5c9b7da11265cc36115071a6381145b22246a0d3e851d2d901b79b1b7bb2b8d659bd5b9aeb9288582b69b124e189a914a9645056603db6649cd5ace453c80fbd592a06779567e41532ac0318cf3eb8d3fa154d6197216326aa
+
+InPK = 9b9c71049e319792e1110bea4da03eda4dd5220d01ddc3c921022e5d3bcf8b70c1218b77d576d564c08f95d6fb271fd09c6c546e764e2d8b36a72e852de90d89683e9b54598fd7dff269431685381ff842643813944c2d502a582162ab35125938acde5ea3b2644c16dfca13360efd8c0dc02284750c8e8255aba28d2411591463186d4c5b63caf21a9972560c848c01d650b256a0b2f312850de681720a35012ad22a1fcb89d491768f9524e74453370075d5a60d6e470cc348f1e20afcddb41bf44c73428f41dbc50e27248f7f11683e0abf5e1bc4e1e1255fe2b22b1bec643389d453a8e58be11205237d8e9578ca9b822c18856f6e2434d39286dfcf2b6280d84f6ee2e1c3fc007394240e448a8429bdac9dd659edab45adc3608b1050c7c521aa19e056599b8c820e740f22dc6e15b520a8f4933f53adec2e9d270100389991eb00f6f6f21676699d72f95ae838dda9f5e43bfc985c554532801122e86527aa690c4567af3eb755f540abc6abf744ce8ae69f83111a4c9a618373c5cbb61ab2a91b028338b1242e7f170196331e0883c66f784c6edbbe8b0aad15572a9116fb3d50759a3695e38d4ae7c61888a15e056ec2057269f5600424256435bc2321ea102a333531a96ddda6584dbd3d171109b2b533d00720754d99b4d7ceecf891823b2a95be9bbf960a2626281b7402a1555ad5933c793757abc611e9ae555e882257a4125882438134c89d17948cdd4174a28178cb0242a55571dcaab8cae3494578ab84124ace3edf82645ac1386c12595debb108951e4d32567fda2e12cdadd810ea61166dc2a83e6d9c4a578c212df229cd0b8ae52e89584b2729359f912a6e6fde14b1e22a78191bb26259912be8ef71edd98d85484e647461ba9c5ac332d8959a42c5088990ba08cc877b0acfc964b31de2e8411a5cd6d94f769c605c8a5a2b25c2e66f42983281e41143c489ce29887e1f7898a4606071bee156bef0d49a455b21f5ca7beaab014fe597ef3d9d514d56110d21b532a5f0401419663d215b81ef7d7f28df3f1b2d401df4d8659381ed4ff8db80e964aa1b7297f0632d2c8b2b822678e1b861ffa9bdb03e013e916a392895c91e890c60d65c3650b1cb8d4adbd014f45ef50617b48a2353db272160a8d48728c2565c6a0511b934a3050a246a200b6e296d694c324376a9569f0df0c525d24ccd9b1a779da422591cefb952dc72f16859a1e6b84db768233b03581853ec7a40bbf98980411ebb5a396352d492b6accc79129b964417e94871c480a08e867c2069d5e03b994084e4c5f3d8c499054c2903d1c0913864b92734008bc396448340b91c5157c325e1a107774dc1779352164508fc721d268393442c7212e8a9da833c851b224ce7975e621dad0a191575571e6d505b91c7423884bb9a464a64e6a40e566a70c8c74940768fca4b62d03023c430826005b7bf9dc6f863f51e98aa713b781d8aa1aa65f73de019be459852850684f963502a82c9619867026064f9543a13dd7af9bd77eeeb25d2566cb2326b2d50805602dc270655d8eca27320d5302bca56ef5eccd4046066a4d9778675e15a01d17363d0c5076f43de1084f551674a6b02a990ae164284e467dc300b5c619bc0a45e411b8e5b15121d1e62668850d4a45ec7a56113e213dd291a40d80d33be8c0cc3fdee08e0a94182b63c4d8de78c1aabd5ab6cd90b18de9e7e5684f8b497a1751867af4218c20ca949fc8506a837fe9e1843b4da6dd690c9cab2e00880089bf0af4914c1ab01241c5e9816efe9275138230327e23a6ef42ce810c088feaa8b2a5d120837bca64b54a57618228b5bad1c02d33591d71790027780113804dc60757991c1150580398a45c1620bb17c620db8ec78d04770b2295086a6a6ea36ab0f44e13f70364a890532f08a8f9a11557093a27ab8ebd5a0bc9dba17a972c4db39aa6580c6b1a4a1208e5af6cb6d246ec44fb463cae807f668eb27c3390a60ad3cb3ca021e06d295ba7bf07483076f73ba44ba81609259aa0d7b48a975b56aad075c06002696da667bd23ccb26045bfadb6121dd810ea05b77195dc66cc5c68de68df80cdd2ea6a699c451c2d6d033c6c4915c8408009494029fa3782442f83d0fa2e8ea536d1a8f4f146344a639609753810a512539eed3673fb60ce58dc07b97d80369021f6738c92ea445c038e0cc89d8596e6268641b2604b3a6635d594b9348e73a6a448840623966fc5497d1cb252714b993ef45a27b3d36f01da8cbface615dc349b0d8d168b1aed283bd38302fc181984734231660e076f7dd56eaa839f398d18c00cf4a418961231a506ec185b862d4c442b2820053831abcb609e13956d9440150e50da9850f95ea8a93bf54984b0c000bc299a721a35ab9882e5c9b7da11265cc36115071a6381145b22246a0d3e851d2d901b79b1b7bb2b8d659bd5b9aeb9288582b69b124e189a914a9645056603db6649cd5ace453c80fbd592a06779567e41532ac0318cf3eb8d3fa154d6197216326aa
+InA = 466e66f041312a755f555a949a661f8966f440cc2d3a4cfc08ad7aa8f018a681444247d0dd37b2ea61a2496ad9880bdda2c2c41895f83180f79cda5ba1f202f19896aa9ba51443ab58f7349c1fdecef93b444a9996a13d716e709efd1c08e2e2768daf974c78dce6a18b5eb9ba8db402ad955609740425aa21457adfe5802991075b62dd62ee55135b4040a3b32147748e9980e0958736c66c24262cbf55c782646c255712e4665ff80576774d420f4e13892016e6530001df93fab40ed9d48ec5d2d44726cfd0dab47094b8dbf0da6da5b4f7534e680166788daeb2a7bbfa2f746fbab1346d3f3d8f82d859f973661c3c6bb624bc0ed2de274789275110fe50b9e18ca5196040006e9dc78be2bbf1214e6e47e305f54e7d1b51450781123ae01ba6774ca51a7745f2a68aa44e37a8d6444fc03aca490fd4a1aa02908a51e1df4cbc1d0804d70f9d94859b01264cea842da37d86fdf97f5cad10b03aee627545aa02c3d67f07de5f63624e45615308a8e81d55698851ba625188624b032aa52cbbda9c80f715897fc86d300b527d303aeb03b8b18440b21e2b0a682da5740dc9c6863a5a1606ba784e2e47a4ca2fb09bbe641346d533e82c221d6fbbd29a2cba99d71fc153959c62985bb092de06c2253a032ecea0f6d8bb041ac2236a98f51a7220a73c52f4498d153ad99774883f85680410944030fe28204db6ba2a454a0928b10af2b920b3658e92c3bdbcf4681c7993f2aea59c419a979687a3ac2180f94c8e50c293b627c0216f5c0ffa2c310b7d49ccbafa14875e8a94b3ef1e3ad7926db6eafa0e87cf04a8f5101a8407f0d7e731ae31ee23f14c09609c29e254dc781588648e89abe662fc5a79e30cd8559bae7db123b96f4dd878526374311b681c45ddad6d96a520a13d6860e967e3f7daa8718f86f5c4cca4309f5caa4646b2ab5787033553b4149de6d63aa4593a70e6486b0c3d4d02dce897d0e14bfa6bca6b261176ead285e7007905672a76754c8d66414d99781eca5f9e83fe7bc3066c139eb909d3156d79d1860a2650149683e34578f272bd185a93b0418e50844fc04b253504e8e2f7a60a50c1ddeb747c357f249164d437e0bf53a8df2a01a836fa69d85893ea895c449fcb7e6d7c9f24565848b97f529e376885a219640774898a96aaf7c1260b871246949f6874c23e28e2adc98b3d6e4fdf8fc091a45e75ae6503f535f4b1ec20f66b61152f63dd8e3bc512305a0cfe9bd09a5c65910586123a246cd8188764c5895d278ba01f91196f4c68599cf1b3b800c37bd3f813a5ce326b0d9952ac4b6b96bf2468de4837157451177dab8ccb5d90591f5c81f5d8f14855a22ca4e89522fb4ff333756021f4c3b5245738293d8c81d4b0dc7ed618ac14c712350ed97d1685388ec2e14317a2295710418889fc3e214d2d225869509b068ca5032af80db7587b759b4c073069a4c4fe9a8be40f39d500667dc720b90a2ee17785644a6a3be55f51260736ad6525d7e121f413165bb38142621191b7f21feddbb8a658cd013187b246051ccc0cf952f574148317571a6643666d9fdbd4fd7ed343519b791c131c68ee85850595339c962335351744db3738569cb5bd42becb2e3c0c2be214592d1aa3f1d3cefb6b364896cb12096b2491df4381d50ace9f766cf140fb289a5b6415f0fa72548ba6e54a5da261bd2606150ff6003c87af1a687512645cfcd2cb555962d59c5affec340c9460218541228c99df057601824715f38ba0a27f945125fa1322a02c4b0e3388866cb349f4d0a1e423cf20d41055a46be20e0a43d70183de531537c9ec0229a65168027494f19a4ce8ace666298bdbe3db10bafb4661d7c9f8b70ca955d7054a25dbcc6575a18979ce4d42118039a739811429d0e26f4f6b842890e47c6d5178d5f2ccac590157f9b35aa0746b9c9353181a546ecfc92131ba556c1638a9529c6688f037ebf8879e15ebaae9f881c9db1143d7509b2b8ca242ecd245dc0898f847b96bdc4c273908a2149817eb2bb0aa9963e54007767ea0afc0d9508f0e5039cfa257f19cb57898c52737f16958e30101d289a484e7e460643409126c6610a15570648a40a0233cbdf863cd1384299f6cd5b8a88c700bff8faf80bf35874a024db6164195bde038e2f61c4d9e6994643ef0923f6c795a8f2a9d24a2bc391b4046b8cf4bfb40287893254c493a70434b12af36c64d645ccd6e4bd8c003674bf315e512bc9d21b6121ad11a790197bbf5b453f8443449012544e02c5045705c908a89f2d1faf0309d0aae891efc1717aa3f32ce3645138c13125db68d06effa6436359783c4d863702e6b2b4f7eea76a4504a8d01d39ab252d66a64f3b19186fc5918f19d4a36d2415aa943d267cb5d4673990e74fb8ed8484af02df782cd23e302574069aba1a631959be32831c3a27b35a3ff909de8a1fb2a6c852fd05affdff5fa11ce353ba7a3b1e1920bb62c497acdea0243431d8ae65459e867aa8082d44a5ac8fee3bd3d1653dcd0d209a62c
+InNoiseSP = 6b8addd536524101c8fa265801addd950fd2d7b19fe4a590e175300c2ce7532a467165019fd7d1485a779105b51720b68eccc12c95622861c18d5f3679a2a11466ef66aa258e61cd0f26b2eda7f1400703868030296c41c241cc5fa7aac5212c6e52a8c20013d9017ab951af7513c82d1f8531abb4214cfcd5cd72377563db181ab084f6afca162a866a941a899cad20cc1156078a71c6f6f8662e6424f87b8e84aee1ce925bf273969256645e648ff6286677915257c2d49210a1b04e7b29eaf030ca2dcf8c0d3375096d41a904c36b2d1e9e466c73d319ba3cdd79b8081e1d7c6ee100ce0e7a40496be1f70e338edd9aa2e1ec869c859f1817456ee14fa8118f7832f50ae0e5a73a8964527d421b76678fe346d8f31511576e2c84ea6415d1061ec46455017fe70910d36c76cd131f272ba180ba12a3cb23ae6079892c058a8a0d01a54b398579b1ecc6a1f3960092d114343027695b87eff62bd35691251b935ab332aa00068a89fcf25b14d6e9084044959d830d686fb92ba222d7bb712c0572c8fb99eb4285fec5dbe5d7b83f8582c49928d65466c479831d116482cae805037ebc2200fbdb1519555c125db380ecb068df5efbd33a7df5c257462c3215ae29bf316d72bc7c4834a55332995ec99882efd9666be73afa6f8e0a3f877e9290a89bfe47110284b8299727c05a38b20807a93d17e4c55595e8a392deb58cdc568796b9f6bfd0d34b3af9318ff9955da956b5a555a023f6a68455a794e6d3c86a6c46a70591e598074eebfc87f348bdbb2b21399b3d35b360d429f341238d4ce695a8699f4c6a41a6d865a9475879a1fd9a0ae62808ab242920bcc8011611dc677aa938564b38b3911ae2721f02aa9e8701b686ac17984190ea11ecbd090e2a4b4f11821daf62f570150ba8ee08e0493e33fa0b108a9ba2a897859cc94a6545c34329462df93f84c3b35923cc0fac9442025cb028fc9519b70dde566d2c3f2899690cbf4b6656e979571fd0aa5af21123c753f1d4a4fc24db4ea19623ec2ae5cfb428d9a054c00eb53068bd37baaac8eb18723917ad7737e819a189928e8149ec83f7da1807fb21b5a644c3b4c77479529e4cd112451384275d869be843ce9479723d8a074cc66be5054197b9e0fcb0c2260e7219ce86c79e0f4ecac526ff5a716059e4a9a1f6501bacbf905a3c99af11e7e242de820b82795407da6ab558bbc4d5567e44d24bb8561557f49a675357893dc8d5e873dec55b62dc0fc77bd469274cc425c1a174c54ad6e6f649b38a8b6749101623bb5b2e38d1eaac041ccefa6c1569adca16843b059fc35f9ac600ca1a911940ab15de9c4c144a21e6e452899c9ee173113fdc2d90950ce26d38827c21c83c1e63e61a7a3d3a06e8171660467595b1671829ac485503164894bcf240d2a05576f20a78869a7899ab682c5fcdd067da91a099a64266ea34a513666e89a292bf1fac7ea8377e5b51e398e48ec92622597d03c4054cc94593175a28a1f981990509eabef568e4e65e99437a2b8291a2c60a6f69cfe8c82aad1759fafb716d63675040859821ab1c9be1b36c2265ac80360afa196e22c4a1d945585f4e2996b4e91866cc28ab21555954844d9e714d96a6145778a9e6603abd4ca802778ea5748a4799b7faa04345eff917ca729dd1a1e5bf88b8ddaa7a33aafa6e5eec53c7173222d4ea96a1446a512b6e12564c0048df48fb88549a37d2065904cf88b3804cc20136f98aa69cbca686115f9daed1a622746ee9993fea934ab3d991e2b2081202085e3ff568a098a39e81145a7a15bc48c26a47ae28f0691f33fcf8515345ebe88a09656544f3a17f5d41dfa4926815ecbc10424a9219e62a83584382fa38bdb00623ba0f20379691e17479fc8ebd12607bf3e4adf559e51a1a1d8788d32269187532c29982899e5a83b7c6d929584c91dc5769fa5b1489499b4fc4d5a479ce12d4b4b2067628c37205d19d00874d3181a0981718816202f6ad6c8de8fcdbe270a30bc6f1899c2e8886a1cecbf68e2542a7040abf2c0540a9f823997db447149503f4764706615db6655c0978e31dab5b256995a08f7110086602ac6f204b55799bc8f68616010c86c4a090cbc55b1385f3d231aab8988ee810249c4dc82bb1a96485afd3093976b54588b145a3e4f426bb80c32da5d7099100c54df1360d8001cee5b9d89c19d501fd6b9e7596b20969330a117b5c2d492950841acfec61e20bd8b55222389624716fe859aa2bd21043082b0b8be3991bf7cf8843f4322a6e167b24941e7ede5b5d0442c166d6a00a745d1c8cbcaa56889fccabe0ec2048cf6d30a98e64c5e152676f04b6b50d85ba068ef0c2a148731b0132f50f6e869022c446bad8ac219fb3c96e754092e6b7f64e608bfd0e72e7015dbb3c1f210254745e135bbfe8c46488a05065f7d97a90b61bfe24232aac498494f0f89d1e0293ecc78fec02c78c30a636bcaeb86de704b10cb411292b84027c1ff3460016b4cca36c6bb2fb32e040050b5c368082b9
+InNoiseEP = 3bc5cf207e017b682a21a47b75503aef0fe96bf80d73a0cbe9daf58eabed30e0c9d0a1fa88bb7a42761bb598d4c37bb61386a63344aa8c42a39b13cb87d902a112e264c4fc286e6703a6cf506e8fea14a1b4a4a03ae998b995909d2fca5196d80c176b1a3f351e3d7a56d08f8a235daf03c80a9501c08756ebf040190eb76e8d740223a43f2853f251432825485f97497090b3b9d7191925a28a70d32646b1486743cea5d364c248d3e474e27e8c173218428af32eb5780c4ff9c47c2c455d0b83f01089b3652cb921560f7c646c27e670a359537731cd9e149323df20c199b40b66c06642a256d016b4c56cba3de19be9853a30a39b2959cb215d2eac56d5d4dfb06a4f82da34cf108804d754587ab450f06327b2cd88550feadabb8e9d1404526cf74ea4125a5eb5c790ca16594739d54e946779abb3012689b6066aa2fb7d925b9893e1f067d5512190a349785c58db4c9fd265148d3344f5c1b3aa18928899b33aee55050451fb167811ae8a5c50b9f40400a4c28bba64096f088af54fe4885197b814c2be2dead7c2e7f335916aefd94297b89a384451b7dba87b01cbbc36c37c9bb09661a4f8389043253331e2cd6a41c948d6309284579dbb3648e86f9cde470b8400089a966888663117e9dc21580889bbe9ca2517bdb9b58d5740f0c16a8dbee0a3b1569c8d219808a9a7289b94268a23f1c958d2652877172d917da3d305757d098986f6e2e1e460a3cf4b0094d8a050e998a6b4885ad106f0c98b102b58c5c4b63b5e1d442974bad2f06c9feb0d01219e652e90db2338fe4b4041b665668c5a00a24530b3a181d2089bb6a4b599d2294d2036562f5047d8938715213f90630a58014e174f906ad0a20821a539775efda2b4e25abb4fd0090ddac2774db411ee4d43339c081aba8f62f0e291351b1fb84a3e28191714bf94b3a94aa529eac8b0aab51945d185ffacb823e163b379fda4de57d23046618180e0728367b262ed6da3629fd91e2baf7cb9d4d401d219221527da00a0a0c778621aa7bfa73a2677dc10ec81a1db301884b86e5b0ba0928e4d29e10b11243fd39990a25a416d3ea6d214620645969be0e634544df6c48e1643964e68a338d5633e4b085f2f36d234959b69b309f2f20015dbf9f71bda678b85f186d75999ec1c3da0b6128f1304976b381c3f2c118312af521b0f810ac1d190876c5499aa1e0a0c5e8b9d7975c92d31014177bb310c2a282be0740297629c54f5d1ae79361cc77650c0a6206fca4441a52e780bc22b71dd1dd12f4f5886449a1702cdf04c114c628e0d7975110e85cf045bb820bafa99432033de0408e1b81a12ee4f8a6f043a1d115d145d729b15e63db3d4e5926f76bca550785be6ca3e7b640f77e82c145e8b9717f2b61ba223248202b68772c9de72fdaa4bbcdf4ac433187a85ec03f8588530dfdd3bbbe5a0490294c5900f8080ba647bf3b8c0a6b624da805f4ab6f04981d550f29219eba6051058ba1a87e80839a572f76320a31731002184843259f656904f5dfae05c91c8df4350f425bde08b2b2651feb012df0ae777c842a44103db2c861b45658fe1413c256ae47ba944ca2f139338c44fa80e59445b88cf6156bfed02166df2b3970fa2daf1c9832de4f5a3b3b199108a0d2af2d237751e868a234a5ac36f8959cbda135e63ac98a91884ca6c62c9930507559a7d51ab52bf3da1a95b545cadc34afe4b1add66fe24b531380811a31d9716972c2e2e261b805c0a1ac70d956720902eec010c78c6bab20a2936522f75bb5dc361f494e289ef5ad6c8964d6dc8e883a1b0e036920a5e011c8416e881de84b809854ca0ec128681ba989db383a1827bdf8c61d997196ff8809f68c651aa6c27f0b825ea227ccd9972efc8a79d80a4a5fa0a23f9035298703208be84b5463a703356a7039563c627841786d0417579e69f495510fa6d6ba2e6e5d5de05de899f53d3f9256ce94079722c6d9bd16d220a3e6d399bff03088e38e3db2ac9d8f44fe426d3f5968539392845cbe00d8f6452d5f1c87d9a4745391338127996d52e49b809354fde1bf189297865aa2d712f80ac4ecdfde7c58d51e89cea5bd36690276b056b4569257ea78acbde485924026ed86d741356ad5c575aaa6200a5e18b81cd99332723133dc5a00595cd9a7cce957164b3e6adaca3f6ea7d687e444ef39269e65ec81320c5cd283fa250bf4bc246e5595600568440f73a0ca8a30da4e6ac8af4ccd0705ac62f3865f676ddcd9a85c38757f628bf0655ebfb941897fc62e5007bd145fd66fd78b5ad4bcd1392b826554f0a2c1702b45865fde2e1e7f4fe0f4355cbb20b4a16dd9fc0e88e7c57eaa8a7d56d21b89ee79edad6e82b950066f9c06050689b4505e396530c05940a92cc87d79531169c566960802de5b278168563d05908061df9dcbd31268e4429e008eb9e3a4628a194023d1412334975b4ac35a1e4ebf6197e6150b60ca4370a2e3fa9c897554e5a9fa3cfa5a647695c6ca865e402bc5536c2bd65e9112a
+InNoiseEPP = 00f0003000f4bf0100fffbff0600ff2f003c000000fbaf00d0ff02000440003000fcbf034002000008000180ff2b000400000000ecfffebffd2fffcbff0200048001000000c0fdaf00b0fffabffd2f00dcff02c0020001e0ff0a00010000fcfffebf0040ff0b0000000400003000fcbf0280004000f8bffcef011000fcbf0000000000fbbfff2f00d0ff060000f0ffebff02c000c0ff0b00000002800000001c00034000a0ff0a000100005c00fcbf01c0000000ebbf01c00000000800ffafffcbff02c0010000f0ff02c002c0ff0b00f4bf0480010000fbbf0200001000fcbf020001e0ff12000200000c00ffbf01c0ff2b00f8bf010000c0ffe6bf007000f0fff2bfff6ffe0b00fcbf00700000000b000280ff2b00100002400000000700fcafffebffeabf03400000000c000030002c001400fa2f000c00f4bf04c0ffebff0600fdefff0b0007000540ff4b00f8bf034000000003c00080fefbff020000f00000000700004001f0ff0600fd6f00300000c0fd6f010000ffbf038000000000c0feafff0b0008000030005000fcbf02000000001300fe2f0000000b00040000d0ff0e00014001100008000000ff2b00f4bf0280ff3b00000002000000000400ff6f002000000001c0ff0b0004000200000c0018000300000000f7bf044000c0ff0a00f9ef00f0ff020000c0ffebfffebfffaf000000f3bfff6f00600000000030001c00f0bf0100000c00f4bffb6f0000000b0002c0ffcbff0e000070ffbbff060000f0ff3b0000c0003000000007000240ffebff120005400000000b00fcef000000ffbf01400000000000fe6f000000130001c000f0fff2bf0100001000f8bffc6fff2b00f0bfffefff0b000400ff6f01400000000030000c00fcbf03c0ff0b00f8bfffef003000f4bf000000f0fff6bf0300000000f4bfffefffbbfffebf000001e0ff1e00fd2f000000f8bf0280fffbff060000f000f0fffebf0280003000f4bf01400000000400fd2f00f0fff2bf03c0ff0b000000000000200004000140ff0b00100001400020000400008000d0ff02c002c0ff1b000400f96fff0b0013000180000000fcbffcef002000080004c0ff0b0003c0fe2f000c0008000680ff3b00fcbf0200feabff0e00fc6f00000003c0faef001000040002c0fe0b000f000340000000fcbf03c000f0ff0600014000e0ff0a000240ff0b000b000200003000fcbffd6f00f0fffabf00b000e0ff12000000ffebfff6bf0140000000fbbf003000acff0a0000400060001400020000f0ff160001c0fffbff02c0fcaf0000000b00003000fcfffebffbefff2b0000c0020000f0fff2bf0480ff0b0000c00100000000030002c0fffbff0e000080000000040000b000100000c000c0ffebff06000380ffebff02c00030ff1b000400008000500000c000c000e0ff0e00f96f01d0ff0a00010000e0ff0e00018000f0ff0200040000000007000180ff0b0000c0ff2f0110001c00f9afff0b000c00010000ecfffebf03c000f0ff02c0ff2f00000007000280ff0b000800003000d0fffabf0480ff1b00f0bfffafff1b00fcbf008000b0ff0e0000c0ff0b0007000070ff1b00fcbf0000001c00ecbf0300ff4b0004000070000000fbbf0240003000f8bf0000000c001c0000c0ff0b00fcbf0640ff0b000c00feef00f0ff1a0004c0ffebff0e000070ff0b0004000240000000070000300010000400fceffffbff0600030000dcff0200054001f0ffeebf0280fe2b00fcbf0680001000f4bf004000e0ff02c004c0ff0b0000000300002000f0bffcaf00f0fff6bf050000f0fff6bf0200fffbfff2bf03000000001b000070000000fbbffeeffe4b000400038001d0ff22000000005c001400003000d0fffabf00f000f0ff0a00020000ecfffabf010000f0ffeebf01400120000800ff6f00100014000180fffbff02c000300010000400fdafff2b000000fe2f00ecff0200feaf0020000c000000003c001800003000200000c001400040000800fcef0020000000000000e0ff02000100ffdbfffabfff2f000000fbbf03c0010000fbbf0200013000fcbf020002f0fff6bf0580001000fcbffd2f00bcff160000c000400010000180fffbff0e00ff2f015000fcbf00c0fd2b00f0bffeefffbbfffebf0070ff3b0000000030004c000000fcef004000ecbf00b00000000400038000a0fff6bffcafffdbff1200feaf002000080003000050000c00fe6fff4b0018000180ff4b00080001c000000004000180ffcbff0a000070001000080002800000000700fc2fffcbff0a00fd2f00f0ff06000380000000fcbf0070005000ecbffe2f00dcff1600003000f0ff02c0054000200000c00500000c000b00020000dcff02000300000000000000c000500004000300004c0000c0feaf00100008000540ff1b00f4bf00c0ff2b000c00020001f0fff6bf010001100010000030fefbfffabf00b000f0ff02c003c0ff1b00fcbf00800090ff06000000001c0000c0028000f0ff1600
+InRand = d7e1e1191de63a93fd94e7106466467856449206e281c17eddfe5597c5ba7e7f
+OutPK = 73ae7fcb7366049e5c2060340422d555213529f573740c28c3f7e11191d2ff660c2c9789d31cc5cfc91227e48ec3c9593df0524f9998904f8d04d3a82de231ac4760a3097911c216159909a08c42195a7661ee825a93108560d582792bb5566f900ff301118ae6607d8282bfc340de1ea6463cab4734ad43e15dea831c599fea681947790c8b1ae4f24ed2460b68d371b24c80474ce5a551418bfed86f0349695f6adf26da3e9a65d3913e29f96eb9ad94452847d43b0aae7401d46aa384108de8ef5a906299744b19ed4f62ae99a6bd18580b6d736ac04a5c450901b8c61843470c23d37b964a200863097bce54f9588db1ca487107eed30630b013774770f881e9375e99ab44a978663d1a22b0bc3e38e19e4f1042e07fb8c3340873b60def9f9cd605eeaae4609742139517ce5f4080ca3a2e6b189b4bd26a6700d6bb7bac648774962aa27ec4a9c5c89c9b264d0757497b88825859cfa682db002a9665864b5a1d9154456a1872321e6f596b87a810aa3cc326070a06be443d5894e981bc4552abf2faadbc37a356f8e5f0655847a6d7aa8e8dad54442ce0154546f784609855b677986523c111b54221dc88e7a2519500da5cc2e9b0ab31db066aff6e3c1de5de84f8893ac361f494130943c724dd563070a23c0f7601ee0077f46b38033f2d493d29c27062953d7594f5c2381e5500ed684550b40959ce1a8327b474288e0fb052a0466a11239574f9ad38467541aa1276cee8aee57b3ea1f20d8cb40f74925415e8099c896e6fcefbd8574a47496028db135433d888690a701118bec07ed04150956586ef56a4321aa18a5197553aa37d1ab9a8d4905f4ece940b7442447f21048b562e75e490e46313a21866ae6be3951e3b9d8c56c940a46746d18b285e1c5409e5c6007b8214d8976e101c161e1e9aef577614b08b1db9d4ebcc2c568598e5d35a45394233254a651dd543db9081ee320207e173732e3c3f19707a0db288e2635029be6e7266d37332994c52e3d445573aa088abcb5faaa5de1dc801112649ed8f4e95190091e00482024a96d96e1a0b14d7c3374c2df96689e53409239f03d9e576c9a3da4725d4dbc58aab1f36a4ce346102923a9052f95703ece5208e9cb6580c9006fab2520549ec5ad3ea5ffdd7eca486a016cea353e89918a8aaee98fab66493c5e8ebb6e7b90da7ef7a812ea497541065098b265200ec25c6d4ba175b6b26e3b03c550668bed246ba5d178f260693858897969608116250652146d3819a5535efc598ab217ea94587042c15711590b3c0e746286a8c521806d99329a8f424c9046336578e85ab3e17ab40657a86b6b4dae8de63bb0573280417c7dfda172320613122592ed64572d38d94864884642553190af01aaf4a5439499883ded55a7a2e3e6b7fa06e909b225e48513cc82fcbdb9c497cba02c06eacc707d5b4825ffad9ca16589fe2c7a365de96b7e2d1a3b7a54ccad5f0f0777834a41ef870ae4560158d35e7e12902b26325d5e52d3efdca6290e3b601f581454236c89d1d9ba978760eaa1018fef4482a6111eb871024d81429915ce552852bfb561ed55bf14eae24ddbaa024935aad9523dc8e7b5dc72b933404ae6dcfd97a8cfe27865774966d74b8cf53df557f8d9b8203fc3824dd44658c23e3e39da6d0c9d007960469768352c42a6d8e34940d93582559494ef581b7b2a45c294de684718ea09009aa1778925818d86b0ee8a76bee470246e480b76716497aac21a9173d1657488a24ac57824174372e89e8f369586ee4545a06c2f960ccab7e21237d9b0a44243082201c57d7e69be972b5f899438a54d490e9c255c222f64ebc4165a95822964242cce9773968271d15081e821931ce05f265441a226d8435ac0a163849c945ad9a3e29c64fc4ff8d298f46d683ca240f0fed020189a9835c592d67777e3b0f559be8dbfd377594a28a55a85fa8d415e190616eb0e2a4039f8cb9c6a5c8251709b4fa9992f576fdba9355dd283d6646b90a80b2e7c54d4f69c97366f884571c5548cc7c5671d76ca5664abbf75bcec6ce22554a68c023b98d1387090f91f0318d5092c667e2124da5540aaa5c4e2dd6638d7751940dea57df2726e151e5a2332bd5d608e169ded8e4f2adb9cabe03afa2be4641879a36e40054dc2f5be00405b71ddba7774991678b6e39cd2c7215ce06e1bedc8b004af437b579273303f8637840487002ff38d176274c156617ddf1173653a9967df61a144b61942b6093d18e0a631ab58539824a70b7b181d36339169d3d44f903fea37818983d663baae9401d3edd00e3ed6d704784d2208d584c5d486e723e11691b4ec8cb164c78c4208e24f0d81a33d178a4eae516a0130c499cb56a4ca4d5b1e54c73e28c70394db17539a958a036123157e97612caad06011c57c5e0be2484d17ee7304824845aa2c0142280e5aae956264e71865958c671652c4f440583cc4e9df15235d90b2c8d5298bb9551de2c14cbfa90cbd283d6a4057661582b55da53e2d37134
+OutRec = 0300002000040000c0001000000002c00000000c0002400000000400000000100000000300000000040002000000000c0001c000000004000080001000080002400000000400004000300004000200000000040001c00020000000018000100000000280000000040003c00010000c0001c00000000400038000200004000300002000040000c00000000c000140002000040002000020000c000200002000000002c000300008000040000000080002c00000000c000080001000040000800000000c000140000000080003000000000c00004000000004000140001000040000800000000c0001c00030000c0000c0000000000003000010000400000000300000000080002000080000800000000c0003800010000c0002c0002000000003c0000000080003c00030000400038000000004000300001000080001400000000000024000300008000240002000080002c00030000c00030000000004000000001000040002c0002000000002400010000000030000100008000300002000080000400030000c0003400000000c000100002000000001800020000c000000001000000001c0003000000003c00010000c00028000200000000340000000040000400020000c00018000100004000100000000000001c000200008000240002000040003400010000c0000800010000400018000300004000100002000080000800030000c0000c0003000080000c000200008000300003000000002400020000800014000100008000200000000080003c00010000c000000003000040000c00000000c000200001000080000800030000400010000200004000300000000000000c0000000080000400010000c00030000000004000040001000000003c0003000080003800000000c0003400020000c0001400000000c0000000000000c00030000200004000240000000080003c000300000000300002000040003000010000c0001400010000400020000300000000280000000040000000000000000008000100008000100002000040002c00000000c0003800020000400030000300004000280000000080003000010000c000380003000080000000030000c0002c000300000000080002000000001400020000800034000300008000340001000000000800010000c0001800030000c0002c0001000040003400010000c00018000000008000140002000000000800000000c00010000300008000040002000000002400010000000038000000008000280003000080000000030000c000080001000000002800020000c000380003000040001c0003000080001400020000c00028000100004000380002000040001c0002000080003400020000c000240000000040001400030000000008000100004000100000000080000000010000400020000100004000280000000080001c0000000080002c000200008000140002000040003400000000c00028000300000000000001000000002c00030000c000240001000040003000020000800018000300008000000001000080001400000000c0001400010000c000180003000040000800030000c0000000010000800024000000004000280002000080000800020000c000280001000080000c0002000080000c000000004000280003000000000c00020000400018000300008000380000000040001800030000800004000000008000000002000040002c000100004000240003000080002400030000c0000c0001000040001c0003000080000000000000c000380002000000002c00000000c0001c0000000040003800010000c0002c0000000040002400030000c0002000020000800008000300004000340000000040002c0001000000001000000000c0003000000000c00030000200008000140002000080003400030000c0000000000000400014000000008000380001000080002000030000400014000000004000080002000000002c0002000080003c0000000000000000010000c0003800010000c000040002000040000800010000c00014000200008000080001000040001c00000000c000000002000040002000030000c0003800030000c000380001000000000c000000000000000002000040001000000000400004000300008000140001000040000800020000c0002000010000000010000300008000280003000040003c0002000000000000010000c0003000020000c0000c0001000040000800000000400018000100000000380001000000000c0002000000000c00000000c000140001000080002400000000c0001c000200008000000001000000000c0001000000003c000000008000040001000080000800010000c0001000020000000038000200004000040002000040003c0000000000002800010000c000000002000080003c0003000000000800000000c00010000100008000080003000000002400020000c0002800010000c0000000030000400
+Key = 8b02bb704b579798db6aa226b731347518155ce79f24d9005c79f17d5baa5b1d
+
+InNoiseS = 55d10f4b48067ba8ef2308defa0285cec13987c82d528761f851ce55ef4f40659ebd2f0b6deae54a28ad4dcdcff387b99a8e4639c0cf354127186a92f6c0b1735f6d34d89596800646533332b2e5dab016a3d5129f8702223a94003c03774bb2061d322a86d3b7727904414df6c1c03c1a680863a43a09a862e6a0a0921eeb4431188c4c7b79edd293f24c3a1496763936b23d599d922b82663fe59836743d843046d5ac7493a95e36d16b770b7a47bf5b958355fc289c653e4637dda5ea68d40253440eb96f5976ad7a6248a138e760352792267249e91239050d4cf24406a57b2d98025bf104e587632aa7c52f65e781561b0e71c5ce16f371fe50da1f6008f2824828523fd3e2a201050b17a2b474491d49a0b36c8c34eea3adf9339c20a651d6eaa5205f406d933113816e1b5e587ad49a09de8e6e6630f60ed96163833a8560385c1b2124f165ece2ec52af9a9b612f9dc03a81190e5f46eaeda60faa0b7fb79c047207cc4e48078a46a0c49cd1132e9c9a00f85a193551a8cb4b99ec1d6c07491c114969b652935a82bba252326dab5440cca66fe24c37fae468a32b22d21540862f062c148fbda0f0a320ca12ca1ddadc661b19b45c461a38171ad57da96b89c01aba52ce596ebb325a22016e2070d5420284e4a319bf521480181ac4294d28ee037016f03149ad538e632f3c274a162e93b982079fa85aeadabe3cc58671e4bc0a2604243037ae98211789dce0b5a59dd89cfd5b13c56c97d520d73a4c373501f604c3316ce255df320b9494d10d9415faed012ac6b53400bc6d47e3307852697a142c4a9bd28a16b11cf93af3914d31e020ebf4ce8dd41aae69e8885ba641b47352212e69c03f932c5c4d54687a3503288ef5c3d6ab83fcaf2059e9098b59a898c7801683d636e45cbbabd1d8268606c3764111666fc3d57845891126dcd9faa5191a8bdae12466d62cffca274b10129b5d1d5caba36c15bf1e7de911b471a3c7a82ac6ea2374122e2770f8237c0d48e4e25c112b2f6659582567088482c9e9e0789191d226353878202120448980a6b7069bc71bde617452fd2317ed4e989f771032c46ba99724806f5998c8e8fe940b7ea24e6291ea5e550e7e5e2088dcdc6c60dee55496f22c870ca597357d728a9e45c4a8a44c984f48a62281a994098558f77eb70d2b690601a92c8327ea246355744ad97d912ca63d84eab3e0cfa521ce800699989a79269d10fb9285826da751db0dee4c716eeb946b59bf312226e7b95171915ea15615a1bb1c59a749cfb12761edd989e08a79079af4a781dc4f5d6056a91a0661742e5d54673a6c1cec1013739c2e71df299942769ef25da2e5daba26f9addc5155a8608aecbf53254c2d27a588b0823aa54d0bc24a2131b7d842edb3f9666a798f3e86abfe279d86259165bd93e8e7f913ab7d14a94f40cb44062a3d2728e9029ebaa6865be89d7d052c049e7389ca866022c267a3392f689d7ae627fa3b58141ab762d10be4e6d8752edd88cfa3985bfc723023dc380398ee9d9b9b9153a5a06eb295858397fd7719400f80e38aa18fd1eba6c324b15726f4907b84897aa3ff347578a13f1b905a148db1ffe55813c17831f54ab7eb52b44545427a25c17481d0851b590c4e1ea2682139c421108dd2bda3fdbe90549a7548e1463cf0a51e4abe1c171f4866191cba036d270248635c48848fdcb690a0bae3240029cbd688a4d6f150d08d6a0b4e62e2714e57806aad69420c71a72788c996b19b5fd5870506262b878e354056ed2dc4cc6bf00e59acd15ef776d1ee75970799c95a5a32814f8e790d459d32d4ccd807117acf2d2ff290a57342e9b439fbc6163c268953fcc0444d5afd040dc035a3aaa54884c09b4d60f2c0cf2c1e91cb1dd5573e26f3ca8609d3d582c926d429005891c02699e5d3c40eb203a8641fb8bc5dc13a04e832b954cc0003988ab691495e5662e21afb22ba667836bb7f177301005ba3124e4f947f851e5de9b8042b5da3476cbee91e588626da672217be58d146a2f3eb590be8832595455972b5531a87b1e63c20ec19bb9ee925ed1d5c7765b19c199769920d8c4ee6d7eaa3973995011e9e77c6de17662beb49ee169dcda4c6d7091459794277a0418c55926bbbc83a320cc38de4126612a3bd8a55ebfaa897c9e17082319d71b2c964ca7471721e96c69bf84d2ce9149069e119b3f40617d20dc20404dd587aef66972f14369056e2673c5cc54877f69bf8e0ada3527c58c9d8c408ce218c04858e5b94c4ba2e2da592b4c0bfb2c9e0a894e614e7a21baad239149743d1e4b3b068c5c324e1080c09eeca22487b2d807620ff20f64eb1ce404ff82f3926c0673b4341c6a6a1005b08e1fd27578ed1373af6879be3159b2cad27a29eb0c9fab2358258d0a946b1396e6d007995c291cbee1837b4454a13c84aa7b4da799bdebe33b9d2879d11f02008c82a7f9d48c33e5c57a74f731496b62a180db690406a9d8828c13550093aa1a29309ffb96adb68cda1a1089a
+InPK = 73ae7fcb7366049e5c2060340422d555213529f573740c28c3f7e11191d2ff660c2c9789d31cc5cfc91227e48ec3c9593df0524f9998904f8d04d3a82de231ac4760a3097911c216159909a08c42195a7661ee825a93108560d582792bb5566f900ff301118ae6607d8282bfc340de1ea6463cab4734ad43e15dea831c599fea681947790c8b1ae4f24ed2460b68d371b24c80474ce5a551418bfed86f0349695f6adf26da3e9a65d3913e29f96eb9ad94452847d43b0aae7401d46aa384108de8ef5a906299744b19ed4f62ae99a6bd18580b6d736ac04a5c450901b8c61843470c23d37b964a200863097bce54f9588db1ca487107eed30630b013774770f881e9375e99ab44a978663d1a22b0bc3e38e19e4f1042e07fb8c3340873b60def9f9cd605eeaae4609742139517ce5f4080ca3a2e6b189b4bd26a6700d6bb7bac648774962aa27ec4a9c5c89c9b264d0757497b88825859cfa682db002a9665864b5a1d9154456a1872321e6f596b87a810aa3cc326070a06be443d5894e981bc4552abf2faadbc37a356f8e5f0655847a6d7aa8e8dad54442ce0154546f784609855b677986523c111b54221dc88e7a2519500da5cc2e9b0ab31db066aff6e3c1de5de84f8893ac361f494130943c724dd563070a23c0f7601ee0077f46b38033f2d493d29c27062953d7594f5c2381e5500ed684550b40959ce1a8327b474288e0fb052a0466a11239574f9ad38467541aa1276cee8aee57b3ea1f20d8cb40f74925415e8099c896e6fcefbd8574a47496028db135433d888690a701118bec07ed04150956586ef56a4321aa18a5197553aa37d1ab9a8d4905f4ece940b7442447f21048b562e75e490e46313a21866ae6be3951e3b9d8c56c940a46746d18b285e1c5409e5c6007b8214d8976e101c161e1e9aef577614b08b1db9d4ebcc2c568598e5d35a45394233254a651dd543db9081ee320207e173732e3c3f19707a0db288e2635029be6e7266d37332994c52e3d445573aa088abcb5faaa5de1dc801112649ed8f4e95190091e00482024a96d96e1a0b14d7c3374c2df96689e53409239f03d9e576c9a3da4725d4dbc58aab1f36a4ce346102923a9052f95703ece5208e9cb6580c9006fab2520549ec5ad3ea5ffdd7eca486a016cea353e89918a8aaee98fab66493c5e8ebb6e7b90da7ef7a812ea497541065098b265200ec25c6d4ba175b6b26e3b03c550668bed246ba5d178f260693858897969608116250652146d3819a5535efc598ab217ea94587042c15711590b3c0e746286a8c521806d99329a8f424c9046336578e85ab3e17ab40657a86b6b4dae8de63bb0573280417c7dfda172320613122592ed64572d38d94864884642553190af01aaf4a5439499883ded55a7a2e3e6b7fa06e909b225e48513cc82fcbdb9c497cba02c06eacc707d5b4825ffad9ca16589fe2c7a365de96b7e2d1a3b7a54ccad5f0f0777834a41ef870ae4560158d35e7e12902b26325d5e52d3efdca6290e3b601f581454236c89d1d9ba978760eaa1018fef4482a6111eb871024d81429915ce552852bfb561ed55bf14eae24ddbaa024935aad9523dc8e7b5dc72b933404ae6dcfd97a8cfe27865774966d74b8cf53df557f8d9b8203fc3824dd44658c23e3e39da6d0c9d007960469768352c42a6d8e34940d93582559494ef581b7b2a45c294de684718ea09009aa1778925818d86b0ee8a76bee470246e480b76716497aac21a9173d1657488a24ac57824174372e89e8f369586ee4545a06c2f960ccab7e21237d9b0a44243082201c57d7e69be972b5f899438a54d490e9c255c222f64ebc4165a95822964242cce9773968271d15081e821931ce05f265441a226d8435ac0a163849c945ad9a3e29c64fc4ff8d298f46d683ca240f0fed020189a9835c592d67777e3b0f559be8dbfd377594a28a55a85fa8d415e190616eb0e2a4039f8cb9c6a5c8251709b4fa9992f576fdba9355dd283d6646b90a80b2e7c54d4f69c97366f884571c5548cc7c5671d76ca5664abbf75bcec6ce22554a68c023b98d1387090f91f0318d5092c667e2124da5540aaa5c4e2dd6638d7751940dea57df2726e151e5a2332bd5d608e169ded8e4f2adb9cabe03afa2be4641879a36e40054dc2f5be00405b71ddba7774991678b6e39cd2c7215ce06e1bedc8b004af437b579273303f8637840487002ff38d176274c156617ddf1173653a9967df61a144b61942b6093d18e0a631ab58539824a70b7b181d36339169d3d44f903fea37818983d663baae9401d3edd00e3ed6d704784d2208d584c5d486e723e11691b4ec8cb164c78c4208e24f0d81a33d178a4eae516a0130c499cb56a4ca4d5b1e54c73e28c70394db17539a958a036123157e97612caad06011c57c5e0be2484d17ee7304824845aa2c0142280e5aae956264e71865958c671652c4f440583cc4e9df15235d90b2c8d5298bb9551de2c14cbfa90cbd283d6a4057661582b55da53e2d37134
+InRec = 0300002000040000c0001000000002c00000000c0002400000000400000000100000000300000000040002000000000c0001c000000004000080001000080002400000000400004000300004000200000000040001c00020000000018000100000000280000000040003c00010000c0001c00000000400038000200004000300002000040000c00000000c000140002000040002000020000c000200002000000002c000300008000040000000080002c00000000c000080001000040000800000000c000140000000080003000000000c00004000000004000140001000040000800000000c0001c00030000c0000c0000000000003000010000400000000300000000080002000080000800000000c0003800010000c0002c0002000000003c0000000080003c00030000400038000000004000300001000080001400000000000024000300008000240002000080002c00030000c00030000000004000000001000040002c0002000000002400010000000030000100008000300002000080000400030000c0003400000000c000100002000000001800020000c000000001000000001c0003000000003c00010000c00028000200000000340000000040000400020000c00018000100004000100000000000001c000200008000240002000040003400010000c0000800010000400018000300004000100002000080000800030000c0000c0003000080000c000200008000300003000000002400020000800014000100008000200000000080003c00010000c000000003000040000c00000000c000200001000080000800030000400010000200004000300000000000000c0000000080000400010000c00030000000004000040001000000003c0003000080003800000000c0003400020000c0001400000000c0000000000000c00030000200004000240000000080003c000300000000300002000040003000010000c0001400010000400020000300000000280000000040000000000000000008000100008000100002000040002c00000000c0003800020000400030000300004000280000000080003000010000c000380003000080000000030000c0002c000300000000080002000000001400020000800034000300008000340001000000000800010000c0001800030000c0002c0001000040003400010000c00018000000008000140002000000000800000000c00010000300008000040002000000002400010000000038000000008000280003000080000000030000c000080001000000002800020000c000380003000040001c0003000080001400020000c00028000100004000380002000040001c0002000080003400020000c000240000000040001400030000000008000100004000100000000080000000010000400020000100004000280000000080001c0000000080002c000200008000140002000040003400000000c00028000300000000000001000000002c00030000c000240001000040003000020000800018000300008000000001000080001400000000c0001400010000c000180003000040000800030000c0000000010000800024000000004000280002000080000800020000c000280001000080000c0002000080000c000000004000280003000000000c00020000400018000300008000380000000040001800030000800004000000008000000002000040002c000100004000240003000080002400030000c0000c0001000040001c0003000080000000000000c000380002000000002c00000000c0001c0000000040003800010000c0002c0000000040002400030000c0002000020000800008000300004000340000000040002c0001000000001000000000c0003000000000c00030000200008000140002000080003400030000c0000000000000400014000000008000380001000080002000030000400014000000004000080002000000002c0002000080003c0000000000000000010000c0003800010000c000040002000040000800010000c00014000200008000080001000040001c00000000c000000002000040002000030000c0003800030000c000380001000000000c000000000000000002000040001000000000400004000300008000140001000040000800020000c0002000010000000010000300008000280003000040003c0002000000000000010000c0003000020000c0000c0001000040000800000000400018000100000000380001000000000c0002000000000c00000000c000140001000080002400000000c0001c000200008000000001000000000c0001000000003c000000008000040001000080000800010000c0001000020000000038000200004000040002000040003c0000000000002800010000c000000002000080003c0003000000000800000000c00010000100008000080003000000002400020000c0002800010000c0000000030000400
+Key = 8b02bb704b579798db6aa226b731347518155ce79f24d9005c79f17d5baa5b1d
+
+InRandA = 711d61a7cc0a64ee994d801efabd24af23056beeacddc2a453dbb25eaf9b22d6f8aa0cf11781712ea06ffeeb5adb4a20669ceb8e8a6f7867c55dc376d941a1300e68b06110738e1fdad3c68ab12bafb8d1ed723eb898ee9631304bd843dcd69c6a3d7659a872f74529ad5ab697b285361702dad750299cdd0d3f10cc680b94134898200463ee1d45e688520118cc162872fe87aa6707c57e291d490e6ea92f624f1218212ba4d08818960676831c2d21939bd680be8c0face78192423b97a37f4aad65ab00d24fa7aa8a13ef6987716ce45a2bddea183c5c37a6a64faa3c1a345f0ab811b768454c1b9335c5cd8db96e657a0cd635a20dec30ef425e18957053f28174f9514613a7685fe662c007f61a309959b8a09b22b341630c86f04870af4c57c64e6181f0047d955a2516b546fda3799e8ec3472982a57d249f29e88bb26064541da9a8867975acaf7861ecac944b2e37b8f7194a725342505e9855334d5dc6c7d8ad864856bbcf50490f23fe86e452b04e0134f6665295c26da31211890b9c5ce243713904415f8e71f42c0955e723815f7cad3726fc2a3ca861e7095f7277ceacd9a88f93c71eb70a9bfc600d7d959ad6171be74c29ca4d980676120c59879bb1de4c4369223e15c6f43d8b1e4e94344636f8496cea5f8d696f1414e3c5a20d239c75d0d21289615c2ad12c9654c623b24ae0008a342d8994c0ecaeb211c5079fc81d7ec6b0407d6ab042961d0962b21e23e09f11a39459095e58b8fc30b93618797954e1b87a0c7f42b5e28591c7cdd2a58e6f039a4ad3b054a328dfc0daf276b586dcb4c426c4406aa528f5f4fc497483312b7d3825b30cdfc6756852404c148bd751be30d2143a2ff2383d4fc3419c417c2093766355e938fd43263bfaedbeec42bab1d9f6ad8e90aa58d03c033720aa30d679085b4029a2cc048ae8545b791a253efea4464ad8d6b44b561395679c418e6a6c67cc7147218ebcb4dadd1d5f8d0dabbd79538d81b4d22151550dc8bf729cf63338ea5c4a950e2b50e2cec5a25187ad10a12729ad62806a92035eb49cf04e8fe35f1c40811a9987e0d06145a1eaab26d14a7e0e15bb7d4533e42dd2d430de6faccf2a25e3c132579e1a5103ae457a420b25392687a0d813e1caba3b1e11635198cd672eae29a1cd9d97478e2c6189b50b49ed4e68809d0d15035cfaf6943a378d107044f6674f9d811acad9757be85df6e52c082ada6d2688f2a6e12e4760f24abb3ba8f1d9d9456c94c20b3711dd01349fe70b16711f7209f1921e5d81ba25b3ea9af2bb51ed71215dd41a096bccc14ac4476e8e7702f9fd5d19e40bfb2e5164435534f1d48263afa708469b340d0aae57b1020988fae64c662e017ec68a4f7aa5d1b1ec82edf365b62d130e8ff28f6d511f97b166d1bc607b127f4a612e9bc5445f6055e9192529e528be112757a0abf2bf72544199806944e04b53d8e45a08fd96c9939b9874e9803e56bb16608a47cae265fa023d799646e0775c5c0518825000b872b7d65653424b050905e02ee6a732717f5a12b1117923376d9b8a728c3a24828123903426c0c27f9bbba84c94e18259bf2e0010244df8edf6a938ed1787796c32f4d26878e1cd7b520197c8838144f82c5c3a2e5837a89dcd95f6d29dab9d72ea63d41c9e072b67c61a1f182c2368c4a22fd46699e4a5d6a804eb6e974c8642f5ce9aea803522e66f81b21bc0323ae9410673a43683cdf61befa5b19496758ac456155103a38924f613215271c18892ad96dceb7a32b10a8e1e86d9588c7a5ed9690154f4629909e1d45b545f74a14480de196fe58b332a13acb353cad15bb85d87fb458d6b4f225524d3ad87d0985a049572a0f16ca1f81b5f550a4127cf9c9e9b5e39552042e624ebdc96f35f48647a5c5231889db3ba0ab8835aafd76719892990b2b75931568b9213b96d6da5c01455d5407534ca64f7d0a55a47c44f85e221489e42932d80e5d261d39159176dda667b2d2f8173798ae841e7d92b6c3f450ba9172ed635dace2592ccbc477cd72c2661513701262d84d9bc6611da3c26085d6978000f322d80374f6cef19100625972fd08610cc1810d147b6b7700872a4898718a2919d82d3e9f9d8064069d41301f060321e9b19f7851cb36b0f298e9d5cb4104feb8aca16f096390ada458cf0026fe6c74299e35f97b682d82311eda63b640991e651a940c5be02e74b2f74fe4953d61d09278be62956dff441b45434035ab0c9eb05543d8c6a2a480c0fa419b9e999844f5a5f73d4627104de298e80787542730d57d7ed35236be32271f1d034562b8484bfa101926cbb5098fa18f09a1ad54b0d1556598d9178f602b4deda672ea147e8c4e8a5029003f11a1df1cb6e6f17a24010630c908096a3712ba2b94717448374389aeb08c783adfd9491aaea0746481a6a24757712ed94992aa6e6b715974356d061c1449b1bd11cc64eed6b5c24f86b26a872a49936db6b9487c0cef621fe16a248921386c9dc49bb08c1c15d2061
+InNoiseS = 4ca10ae48258b14d83e48384f858eae4c130e49055a044c78590f0a74f1a19e8edd427300659bb38647c032c5722a6ac4b05413b4a0dc870ac1b16f25099428b9beb83af39887340a1c4bd986241429eb8eec081442a418b10ac60be94b3e34374a63c5582274aba579a03202666b16f3066985a26b96dd8993e242ccd6a3d9a2d287fdc82da9091830d0886b80bf3419ae968c615521160e85676c96af65dd92ea10e2c520bca4b882326b7b2c131d22d922827c5b41f2f33b281b50e8b64d92ac48a9bc4516a39272018ef5b707223b59bc2e07dd6831015b610b04638aa9d949cb7444c7d3162cf3a088b628f73c93d66375540330ac2d871d4b0405421caa142a0a2effcaacfe5173862deb228da286993d7605db54efd98f122b1949be7a15481fbd23d97d588b7bce9bf4da31481296149138c1b5753caaa9428b6d5f3be48c69979d351525c61532bf5535aa7d72850c294021d1614fda36c781f2ddbf10a4f723e578a596092ec312827ae456cac024c5a44bb68e5175025ce6876aeb1951d022426faab5a0db9d0cf369324a153533fb50b5a5866c77c00524265020b769517d7970918f5d2bc5a6e874332186d5f9e7a3a03aa28a39de5078002c0845c9eb74791088a81b185958e014f95d1219d702d2ec39a772fa82a3c91fc873a991d54c3c0babb64a7bdd15e78232d3b71a1c08bd60e68fc2f5e46348c8b948c1f93860eab88d24b736c785f2a4564a6754492c9c988c786166708d2b240d3da4c3280bd5616c0aff7a81a9a560809766df9b27e014c6c8aa45b38a6416046ba4b560804a90b54c3f5b6a2abaa7149968c8567c0ed07f2ee99218ed52b88bd98624c1c91b9ae1b082b6d07c8697eccc6a953cec576a25cdf548866a1cb03ded4fb26a1afa6c9287050459de64af1aac1572b1509643c6407f5d4a944904856c42f770717adbc701ff3c9f44aae6bea40c50bdd9f1f9368b667286732023d89581e7f872639f19766b65305b07babe9003e631b6a32511e690a864a18d45263c9436a0f1245db4405b31e1d9a6598922ae6f09a61975b3ac27225baa60e1bf6f01b8a0c07988dc9167648e9b1891c3e01a5031260cd52d08cce39498835b9122ef5d4f24f34c7623448294c4da985b5904583bd6f7e301bb911abaf1c778ee1567e8f4df0e05479cf1b5854e0cc7083a4463a96f2aa4d28944147464d249057b13c3eb8e0e93466a70194309f3339ef597459e9ffb5b15a1cf080c34713b819f6051d2baa142b9602460ac3451161913bd960202f68092c456b6ab71c638877f008862904b3fa62b815414e745b2309629d4691e894282c37e70ab15a82a7b055157b481552c6ee3ef7510a9d9420216b7f2275ef64dab95cc86b3e8ffbcaf508bafa0251c4755d287041290b4f6675f22d3ff9c31808c29d8281f2aaa7c7dede72a42592c10b20a35cee60b31b9d67f5ea6adaa33fb3dd911816aa142975551ebd40569bb1fd904a504b7ac811234029921b6b06b28a1df7c2a2ed59a4ad3541f8852e815b08c09444809decfd2904a62d991cc3c6659d6d4c6906d482bc03cce05cbb9ae142264aeda128148084c5b93b831458b061dd99e94e60a1ef51199f550156047901792628c6d5ff316c20be6d5ea59030d6abb624f8909e12a02dcf69f039ad45ffda6113f2f6aa9be6bb934122ae2de84b7a0add8488c052aaf50d0e098d58c7be3c80fe946c566c00b4739fd59aa2de006885b0cb9c65231f5fa760af69a929443aa3252aa16497dcb2c1180f42cca1310b99278a956a07cf540561dc0bb9e8b6b2ea25e57ae52d636b6297a2afbcb6d014942a33ce4869829de6f1ba761b60b6b93f993938884076c1e4976848f8bb6c4486daddaae7fb8073749a70f0eec61ff2c9687184c09bd15f849108700efe8a01b72c9c97d40957b4e3d64533411887541a5de6518ab756994bb5ed9f7af8da0bbe6959c57e4a2f346884a6716a847015c5545d69770d56d44500097f83ee4b736df867029d979848b64a2c281b2ac3d140ed854f12fd946b770754139e0e320223dac9823a14c28cbae29dc4af992ced62ab7255f265c533cb54b75f48a8321e7aa8f7939c468d26645c57b4abf0569260229a40611920af1add758474b8d026f41785559ad04faa501a649e44abee8607fc4eb21376552ba48931156485c7916d4d63247a757d4f92cf34322202b94acdc3276d99a2a899d3471475bb268ef9ea9976a949437e30e168301d027518aeec04ffc4294a00a2649b271b334f3cbdf88678b8b8c583f62c0815937667aede6ae53aec271e5d885a84b58d348449aa06649d6a635bd7d392885a0ae60218d8a085a509f5e5ad12e24c4d36b04600c0011623d4a4bd2206fce8d5003234405db3ad7e3d4dd6aa790abc6b1e49e8b26436ae6c9f1010b1e052158639c1582d641d8b3ed0a9c289aa5eae66e66a43048876b14cf4a69489224564c4932adaaf83e2b15e0b2248425d71198849f534d801b24cccb2aa434829
+InNoiseE = 349b8309537882c618c642ab2d78d380e2401039ac30ec4fd00536ad1d6297b1a4cc7dad96c8385cf90ce6e5f6995dfd317a510bcabc18a58ea4959286c491ae000ca949f92137c851e143c574b66e510b66b05ec661bcf0d32a401450af69e8a8943cd8b807ecc8be785a0ce5b840200fdc4c41c7a48fe2625853a59d807452ae647f3d139a97cb66aaf2b4988095d52ecc17e6a9ec41ee8821fbeec2d03d7a2466a0af2a211e718bded74735ac8e6a63cf3b18f16ae61619263bfc065e9c2197b9ca9b48e2ae35ab3c0500684e86c6e55e34a4d37415864578484180f53c500a16b601232987cdd02994ef560a8cc37f205ee27712e4a39104c23ec69e03c98c5c403cd7fc2b3f22aaab0c8dc50e6557995468564c100e37d009228b7a71fc98abe828810d4ec0a208103c1e5068029a86a8abc4e0516a96807de96a38ba7c16bd1e2dcf85d7ec192e9fd9a4822207640d6681b45c4f0d1b1ba2739ea684676278a5259e8166357aa6b90a1cccb8001e7e3aac2eb6c713a9705daf156015ccab64c49509760d4b464462ba92ce812aa10bd195c27e70a6254208929bcf85f5f23f583e1ec4b60123aa3d9217f37a33b19bd120aff2e13ab15a534d669701a9cb650a58958c5900a02938a7fd321cc4d07a0f4dbae65d00d44724377aa3ddd4a37d368995cc85fe5672d68f3c453b286fa5cc0b3322ca8d3eae302b982e732fa369c89ada8d45213ba560797a81d54f437a1e8708856781dbe5a5e013676bdfbebb758d41a500f466aad9ce997fd566a143dd299a5a51494de7aad82a820cc966901b9e0f326bfc01e77e7b78285c60fa0064c0e0cdd5e54112e51667323c9c4f842628c20128489ce13cdbc4366c7ee94791d936adad0c9a290e78931a2adab935664ab195e998108c50490bab1ad28a77f5a6b296dcf51e1b5850d2b9ea41ca1f45d96a1660ba055d1b441cb0702a8460dc1eab7642ee35f352bffd638be7148dae22cb8300e435364fe6481052506a9529426803b236ba6d8497214529a6ca9935ed79bdab27ddf330c20ba1d5b1959e487a206bd6706fd51ae3ecac0a7029485d13c9a84d1a1e0d9446a46d7c046ddef9bb50a5ada49a6f50612906b2423a4a7d30b837e39640b196a6a98175f05ea02c624c57186489be678f7981d5918c8a59ef3618245f45d5182b33ea6f7fa2f92004b043ffc9a4b88bd2b319c5f3a6a1f93511ef5ac6e9c2773beee23533b175cc67b6879840bb002bd6b45055a5f2acb6e8e3ad5cba250510c6758ff59e8257b051a06d8dab789d856165eae7c057c22e6ca3fee36a20052ac6f5f583ce2c1e48b172ca815bf84d263bbeae1d88679df8681661fb0650a48cea4ad15c78355429048a91a847d3c45c72e964db630073049a6ab35a9e1cc15aa979e05e81f8ee5945b289648025f6b86a489bb75023eb0c2a035cd211e5a88a3daa479c53098184359ed6e85a3c3d29e6f6e66e1595b3aa78abccb5485d67a741e211436513dd5ac5047068aa03ab59890bb148d809cd9cbe152996b5e8d266689276105c887b5268ecab7f2e68e045aea8082c0a535f3773ff614527616fc145e8228d2d467144a06077dfeda7ef2284b46dbb7861ba904f19429a15422dd79f4ab4ff912cc8ac83635e611ca79581f487b56c44a2f5f0f84d80f00918802571072e591cf8c81e1b831431117f30ac7e9ae6067f410e03d580231c86141e0ee1a6767a1085c3a1391ede006fdd47d5ea252bd1a723a92abab5a21ea0392f812235c40d7b2930405e2a8278b3e885ed41cb29834d09c7013d06596834bd465856f3e407600c29544380acfaeef9127af55fc150a08b8381a3450913dbc33d5f1591cc27cfa41ed705e8aa8bf872c0a31268fb329a3d14121898d213bca41d43d99c4c37eb0f454e4e8e889f35d12d1818c750ce16adb47eb6e1c006402992490158ba67b87b6cd6d5d787fc953fd66796fb8d1cd6e67d13403c7275d2ec56ce16a0792429f2b374b608ec3cd17a740055c0ef2162cd151d0025b23d6db53249f15409563e49595b26dc3970a8ef890280c64b56de24941208366558d1f601e921335c880af02d52e5ade6757a6019c6648a2a77ba634f802edb4cd0b6cf0f8b4bfbea2cf68b80f4b6f47e070eb87479b1996d1681298ec5445be5ff4761baa0f9a586e4ac2170d75311322c1a30301ee5275bca731052d4688f71774e5a1509f60d163c56fa403aa810f1804cc682cc3b112522917c51613d4fad32f401a02ba0b059c4b1136d07164bf935a3bc14ca8640d597dce54316616a38a41ef7fa54e0178c2111084742bef21667b6d031a5c5a962a23d3229715be995f18438f75168d7a69dac1c8f10b480841c001dbc6997003d0ae87d4424aa3a918b81c17894b16f4697559b2a0ef3ac68e61ea9a788407324235951e2ef01b0a260993c03aad0f00a433c2b40a90518a11eaea4756af408da6181c288fa82bb4c3b625b98096a62d6c15449234a609958e1955dcd40c4d9cb8d14
+OutPK = 5455f1b09dc660942d60b9e13ab27b43086b595a47099a78b526a4bff2e3ed7addf47fc796c09adf480b8a091d09111d0999d632d910c03dc1ea867aa458a99b2c9a4795393bb6a417085fcc776a6c49f32a8185e24c7662ef62bbbb184db4e73670a16279b1c0245d8aeb3c6aa93c6eb588f84bc89847e312c8b419fd8305ea392a32a297c449ccf51ba56ee566a6e91c9cb46417a927bd688bd0223232db5c5f62d85bf3bbbe2ff0021dbace3c8f3a6fd3991e70a277c2390a64b64c43907154d83e779e0358426e090fba1a3676c94652e20a40f3dae5bf08952265706a9fc942991a3cdd56265f48768096287598c820953d90728c57b0fd352be0db8e677824a7f92b6ce9bf68721b2251547f392200c5c2625448b11a8dc7a0bce8b6f0202a24b65d63a6d7479b474543d2d6c42508c8724996c335134553a6df4d88d5ac44560023a009d5561bd0a5d0d65859ffde9070bb2c72b616ea62b1647a0263d1ca4f3e7d35267e00831eb1dbc2f9a7a7793d1d6d575b77e6686b429cb771fa928fd55b0b48d4266f557b49800083f6425f9653f84763dafb03c8dea5aede1f86e69d37148da13afa4d9ffa4a435a23a93aaa1175224ff2667524ec7a8af29c518784e6f43c657fc4a023a2da2773ea7d19cae499cd5f244473aeae2865b92bfc248212e843c73b6879f769f9b5a8757e1fc4f61ba801613e8c004a61516774e159e14ba972b3cd3d77e3f6b4f093aad5906d91f6c4b9f19cb158e05a652135bc11e89735f4b6bc2fbac84ab8c849644d1678522e3109e8ee32d3a1c407e993d311b0baaaba5aeac6ed11a904092044e8028964044b01ef56663b908aa3cb2a5fdb23121aa12d80ced256d5501a57f1c99ca0a69848859b8ee4484dac685a02c2c37a7baa0a0b7029d1190e89dff2e44d2afd5461c2f05a040a0be2e0652e4e9c041e3405112fa12e869069e1081666c509c60186b512b822274d27c9c78f413fcdb48097692115a461daa70688fc093ed22d9663818e238a25a0b2413176e1687f20320c8efa9d2666a2444d88d452717e0608c98c91fab266143bdf5698b8ac22de8576c672da2993cf0bd6c2c638f19ca672603da4355226a71e8465bc51cc96ac7c34a0e91a777962249a6429a6810405828093709d9cbe465c446371188ce0c4caaaf1849210cc5ec084fe2de62773191e3d9c7290caa4952c0a5b2ad4c4b6907c616a55a8c7768d1b9b45b8872819a4e44b47a3c92f86411c14530db4d82a83c0678e22834408d342117fbb414d8979718499231f43a960281ca12974a6b08f2258a7879a3c67d0afaa6451c9167a4c79d04c909fff62d2ab71e116ea58dd41057487db414bea87b925e5ca33c88852a71a104d3600942fac9119a7512054b32d7b57e23554a026d7510996738d844792050519d5a0226812ba5a1998098213008d08d91f14a2b8088b5ccf2a5e003bb84bdaf9e25c4d1692420400c19f21d675f686290df3295ff814de1e3c09d74504696e0ea29d357e76b813d2339880f293419098851b665fab0dee933352274157f944701459b9da26c745fe73729e7757f46c03066e9ab8e1a863a8e1a430ab719c3b0e342617d80859c200b787996abc02b00232728741cb34c4478644846acfda8f393789e259abf7fd67a188c3382c0d8c0c4d427b5e2e8650d440177ea64e3720e6e8a4864c7cacdd65f25c2817c5b2832be22ba31bff60e540318449f9f55451aa04db2215846d9b794b949b09e66f59e84f70f278bce0aaae026e79132c8be008ae6db23869e58b2c9695149bdef339753759043463628c2690d6aa352c1410f0e99ae326fa9b678add542c9e2a44d1a3815aa06c5cd6f5b2c7023db2ad0b6773c4121ced854a27ed579189a014f5fa43d38cddd1b412a8ca6410a32e553d70e5d4d90a84986cd0abcaab4e73f0cdc68b6d7d710d5e9b83ff482f37a8237289255001801aea39a5641da06a21b3ea2dcf057f27c210acd300750a06c991e7633942204897101182fa9f2049286143ba79666f18905719c0e879d7d442e4c7a537c713597308b54f261963f7e8bd82725e5e8837e23253667427753d78db5f22e5891eaf9b459ed8f86516769a44c03a528d45ca13067056225b430bab658496220edbe3a70c5e2daf0736da80076ec85ea08cc259a40f412296861d37af6f38610624291e7f410abaa56edb34c20ecd2bc8c2e4315b3850bae021906498497912a70266259824976aa9eb88049c4b08f6876063dca72331c5a9ba0e2f8e21e0668db8d1c105566e39c51910268e551dbb146a9aacd8a457a91e49022e8eb318d216dcf086454d0a88a5ea27364a27d3b585757ce194255d857d9b12e648661659c4c16a9b954216bda445863828ab799d45b61184b8fad5613199eca1cb59a5c69c4843d8a8dd0ab9c149f6035dc26cd4bdb59fa3b6ee699781cf3b06977d22ae472155bb5e64c96b1241f5e67aaa2b73335032aa34da0ee50a0145e92ad0f2011e57151a3f1a01ee5b
+
+InPK = 5455f1b09dc660942d60b9e13ab27b43086b595a47099a78b526a4bff2e3ed7addf47fc796c09adf480b8a091d09111d0999d632d910c03dc1ea867aa458a99b2c9a4795393bb6a417085fcc776a6c49f32a8185e24c7662ef62bbbb184db4e73670a16279b1c0245d8aeb3c6aa93c6eb588f84bc89847e312c8b419fd8305ea392a32a297c449ccf51ba56ee566a6e91c9cb46417a927bd688bd0223232db5c5f62d85bf3bbbe2ff0021dbace3c8f3a6fd3991e70a277c2390a64b64c43907154d83e779e0358426e090fba1a3676c94652e20a40f3dae5bf08952265706a9fc942991a3cdd56265f48768096287598c820953d90728c57b0fd352be0db8e677824a7f92b6ce9bf68721b2251547f392200c5c2625448b11a8dc7a0bce8b6f0202a24b65d63a6d7479b474543d2d6c42508c8724996c335134553a6df4d88d5ac44560023a009d5561bd0a5d0d65859ffde9070bb2c72b616ea62b1647a0263d1ca4f3e7d35267e00831eb1dbc2f9a7a7793d1d6d575b77e6686b429cb771fa928fd55b0b48d4266f557b49800083f6425f9653f84763dafb03c8dea5aede1f86e69d37148da13afa4d9ffa4a435a23a93aaa1175224ff2667524ec7a8af29c518784e6f43c657fc4a023a2da2773ea7d19cae499cd5f244473aeae2865b92bfc248212e843c73b6879f769f9b5a8757e1fc4f61ba801613e8c004a61516774e159e14ba972b3cd3d77e3f6b4f093aad5906d91f6c4b9f19cb158e05a652135bc11e89735f4b6bc2fbac84ab8c849644d1678522e3109e8ee32d3a1c407e993d311b0baaaba5aeac6ed11a904092044e8028964044b01ef56663b908aa3cb2a5fdb23121aa12d80ced256d5501a57f1c99ca0a69848859b8ee4484dac685a02c2c37a7baa0a0b7029d1190e89dff2e44d2afd5461c2f05a040a0be2e0652e4e9c041e3405112fa12e869069e1081666c509c60186b512b822274d27c9c78f413fcdb48097692115a461daa70688fc093ed22d9663818e238a25a0b2413176e1687f20320c8efa9d2666a2444d88d452717e0608c98c91fab266143bdf5698b8ac22de8576c672da2993cf0bd6c2c638f19ca672603da4355226a71e8465bc51cc96ac7c34a0e91a777962249a6429a6810405828093709d9cbe465c446371188ce0c4caaaf1849210cc5ec084fe2de62773191e3d9c7290caa4952c0a5b2ad4c4b6907c616a55a8c7768d1b9b45b8872819a4e44b47a3c92f86411c14530db4d82a83c0678e22834408d342117fbb414d8979718499231f43a960281ca12974a6b08f2258a7879a3c67d0afaa6451c9167a4c79d04c909fff62d2ab71e116ea58dd41057487db414bea87b925e5ca33c88852a71a104d3600942fac9119a7512054b32d7b57e23554a026d7510996738d844792050519d5a0226812ba5a1998098213008d08d91f14a2b8088b5ccf2a5e003bb84bdaf9e25c4d1692420400c19f21d675f686290df3295ff814de1e3c09d74504696e0ea29d357e76b813d2339880f293419098851b665fab0dee933352274157f944701459b9da26c745fe73729e7757f46c03066e9ab8e1a863a8e1a430ab719c3b0e342617d80859c200b787996abc02b00232728741cb34c4478644846acfda8f393789e259abf7fd67a188c3382c0d8c0c4d427b5e2e8650d440177ea64e3720e6e8a4864c7cacdd65f25c2817c5b2832be22ba31bff60e540318449f9f55451aa04db2215846d9b794b949b09e66f59e84f70f278bce0aaae026e79132c8be008ae6db23869e58b2c9695149bdef339753759043463628c2690d6aa352c1410f0e99ae326fa9b678add542c9e2a44d1a3815aa06c5cd6f5b2c7023db2ad0b6773c4121ced854a27ed579189a014f5fa43d38cddd1b412a8ca6410a32e553d70e5d4d90a84986cd0abcaab4e73f0cdc68b6d7d710d5e9b83ff482f37a8237289255001801aea39a5641da06a21b3ea2dcf057f27c210acd300750a06c991e7633942204897101182fa9f2049286143ba79666f18905719c0e879d7d442e4c7a537c713597308b54f261963f7e8bd82725e5e8837e23253667427753d78db5f22e5891eaf9b459ed8f86516769a44c03a528d45ca13067056225b430bab658496220edbe3a70c5e2daf0736da80076ec85ea08cc259a40f412296861d37af6f38610624291e7f410abaa56edb34c20ecd2bc8c2e4315b3850bae021906498497912a70266259824976aa9eb88049c4b08f6876063dca72331c5a9ba0e2f8e21e0668db8d1c105566e39c51910268e551dbb146a9aacd8a457a91e49022e8eb318d216dcf086454d0a88a5ea27364a27d3b585757ce194255d857d9b12e648661659c4c16a9b954216bda445863828ab799d45b61184b8fad5613199eca1cb59a5c69c4843d8a8dd0ab9c149f6035dc26cd4bdb59fa3b6ee699781cf3b06977d22ae472155bb5e64c96b1241f5e67aaa2b73335032aa34da0ee50a0145e92ad0f2011e57151a3f1a01ee5b
+InA = 711d61a7cc0a64ee994d801efabd24af23056beeacddc2a453dbb25eaf9b22d6f8aa0cf11781712ea06ffeeb5adb4a20669ceb8e8a6f7867c55dc376d941a1300e68b06110738e1fdad3c68ab12bafb8d1ed723eb898ee9631304bd843dcd69c6a3d7659a872f74529ad5ab697b285361702dad750299cdd0d3f10cc680b94134898200463ee1d45e688520118cc162872fe87aa6707c57e291d490e6ea92f624f1218212ba4d08818960676831c2d21939bd680be8c0face78192423b97a37f4aad65ab00d24fa7aa8a13ef6987716ce45a2bddea183c5c37a6a64faa3c1a345f0ab811b768454c1b9335c5cd8db96e657a0cd635a20dec30ef425e18957053f28174f9514613a7685fe662c007f61a309959b8a09b22b341630c86f04870af4c57c64e6181f0047d955a2516b546fda3799e8ec3472982a57d249f29e88bb26064541da9a8867975acaf7861ecac944b2e37b8f7194a725342505e9855334d5dc6c7d8ad864856bbcf50490f23fe86e452b04e0134f6665295c26da31211890b9c5ce243713904415f8e71f42c0955e723815f7cad3726fc2a3ca861e7095f7277ceacd9a88f93c71eb70a9bfc600d7d959ad6171be74c29ca4d980676120c59879bb1de4c4369223e15c6f43d8b1e4e94344636f8496cea5f8d696f1414e3c5a20d239c75d0d21289615c2ad12c9654c623b24ae0008a342d8994c0ecaeb211c5079fc81d7ec6b0407d6ab042961d0962b21e23e09f11a39459095e58b8fc30b93618797954e1b87a0c7f42b5e28591c7cdd2a58e6f039a4ad3b054a328dfc0daf276b586dcb4c426c4406aa528f5f4fc497483312b7d3825b30cdfc6756852404c148bd751be30d2143a2ff2383d4fc3419c417c2093766355e938fd43263bfaedbeec42bab1d9f6ad8e90aa58d03c033720aa30d679085b4029a2cc048ae8545b791a253efea4464ad8d6b44b561395679c418e6a6c67cc7147218ebcb4dadd1d5f8d0dabbd79538d81b4d22151550dc8bf729cf63338ea5c4a950e2b50e2cec5a25187ad10a12729ad62806a92035eb49cf04e8fe35f1c40811a9987e0d06145a1eaab26d14a7e0e15bb7d4533e42dd2d430de6faccf2a25e3c132579e1a5103ae457a420b25392687a0d813e1caba3b1e11635198cd672eae29a1cd9d97478e2c6189b50b49ed4e68809d0d15035cfaf6943a378d107044f6674f9d811acad9757be85df6e52c082ada6d2688f2a6e12e4760f24abb3ba8f1d9d9456c94c20b3711dd01349fe70b16711f7209f1921e5d81ba25b3ea9af2bb51ed71215dd41a096bccc14ac4476e8e7702f9fd5d19e40bfb2e5164435534f1d48263afa708469b340d0aae57b1020988fae64c662e017ec68a4f7aa5d1b1ec82edf365b62d130e8ff28f6d511f97b166d1bc607b127f4a612e9bc5445f6055e9192529e528be112757a0abf2bf72544199806944e04b53d8e45a08fd96c9939b9874e9803e56bb16608a47cae265fa023d799646e0775c5c0518825000b872b7d65653424b050905e02ee6a732717f5a12b1117923376d9b8a728c3a24828123903426c0c27f9bbba84c94e18259bf2e0010244df8edf6a938ed1787796c32f4d26878e1cd7b520197c8838144f82c5c3a2e5837a89dcd95f6d29dab9d72ea63d41c9e072b67c61a1f182c2368c4a22fd46699e4a5d6a804eb6e974c8642f5ce9aea803522e66f81b21bc0323ae9410673a43683cdf61befa5b19496758ac456155103a38924f613215271c18892ad96dceb7a32b10a8e1e86d9588c7a5ed9690154f4629909e1d45b545f74a14480de196fe58b332a13acb353cad15bb85d87fb458d6b4f225524d3ad87d0985a049572a0f16ca1f81b5f550a4127cf9c9e9b5e39552042e624ebdc96f35f48647a5c5231889db3ba0ab8835aafd76719892990b2b75931568b9213b96d6da5c01455d5407534ca64f7d0a55a47c44f85e221489e42932d80e5d261d39159176dda667b2d2f8173798ae841e7d92b6c3f450ba9172ed635dace2592ccbc477cd72c2661513701262d84d9bc6611da3c26085d6978000f322d80374f6cef19100625972fd08610cc1810d147b6b7700872a4898718a2919d82d3e9f9d8064069d41301f060321e9b19f7851cb36b0f298e9d5cb4104feb8aca16f096390ada458cf0026fe6c74299e35f97b682d82311eda63b640991e651a940c5be02e74b2f74fe4953d61d09278be62956dff441b45434035ab0c9eb05543d8c6a2a480c0fa419b9e999844f5a5f73d4627104de298e80787542730d57d7ed35236be32271f1d034562b8484bfa101926cbb5098fa18f09a1ad54b0d1556598d9178f602b4deda672ea147e8c4e8a5029003f11a1df1cb6e6f17a24010630c908096a3712ba2b94717448374389aeb08c783adfd9491aaea0746481a6a24757712ed94992aa6e6b715974356d061c1449b1bd11cc64eed6b5c24f86b26a872a49936db6b9487c0cef621fe16a248921386c9dc49bb08c1c15d2061
+InNoiseSP = ee8182d96f319477ec31a90e7e466e1fe90abbc0abd2e68e952c659794cfdf901eb0a0c481c3f11a46118f4b9a288f1827fadab55868d020e0818994bab98bfc0db557bdfe3fd4a1295a831258e76af1a85c019da0eb2fc25a5e2c9ba98448e865723e41f7f8a802aeb9a66b40ec249a225848777e05b27e8db160d43d43e847c339342db6fd648020f7a4421fed95b1b84868c6acbc953922173c41b0608cfd7b650d2f13c4b91aaf6600910d2a7d87ed8cb8a54c140c6aad638ff58d79046bca4f38b51801f6f6eafc94420dbc35bf019bebdfeda27d580d439505ba08ea976bc0f68112781399635e14d73622d469af175e7e2eef887575b112744683c3c9f37e78974cb7674104277d9e8fb9af78138c01e96af2105de9001f06e2295aa7a24847384ebad216ff597d787624240df403613d7922a7c68dbe6894cf60b669f8a18a0e84846e05303f68c8a9595c7a1c2e6b82fa14b00a2da0b369660286c1a7a86554a39905b01965665acf1f1a7200297b7382e3eb227dad0de70b30b32c9b495450d83b2072daa1d61b699d1d0166246b6efeb266cbd6729b3540fe14d3b272f1152d29fb405b4c2f2f96adb3e90e51ade8656ac8551054d10f05d51155b796d8dabfa4a35ec06dc325c92ed94a7bf28ed0974d54e8c4d9658f7ea4b7150d14716602e28755ce81a9a197379e25a5fccf49969754ad632f803592055c829ace64fef68ef324100bf61c714d82a9246e09bca1431833a3f0a3ecd4f2609488b172128127c12d6e9818e27a45f5918411c339e92c1dd829555afa4a1bc9d80292b7920400d75128ba54461bc3e5687455501fda0db5e990a6cd8e03a1b8ec54238197c22a017986d5a17722c605c42e493b4260676a9af43a6c5964c71ddd975bd8b49b1de569cc6c89b667ad5334ca7bfd1c0b5ae8c85ecbca5c59e9d84b949b31f2a1594eea92436715dca746435c554b386e2a6265a198b50ffc5c6c460f093ea12fa13718fa445dc0e4161ea6ae71673282905d302aa22d9587d10411d577117e947cca55b344f21141a92acd69296ab9b0583968f959365ca7b9f318c2180489e060e8bda8709bfb10ba75924e803d3466d23e7ee20efa1b964da2823a37fc8660900dc287488d1e918b8df40d0e4c3f059a91c00071ddc81b4836ba143fc22159802a655ddb52c7dc6e6f25aec2e48ea69bc7aacc94e7d00af08d09a0556c0a73d06ef464422c47ac23e0060a07b59ca109c54a8bdc094bc380de51908eb0b4314e1d9b8d3e87e8a621a1e7454445b6a23bd0d391d2fe3677aef161cb40129ca9422a379a379b693ae2b49175a71d758b79ca19ebdc8ee0b926a325e8bef852c96811ab1516fc294459de763b950aa4ba1f11b69789b529db2047ab541364c32dca3dbe29a1244cf56b6e8ebd19373acbe80d8cab9ea7889e3cea625df9d05e5f54e7d098dce2ba89ac7ea8fed87ccfd18d0165d53545405a51525ea325c19f4781f885d5a11ad7868876365e8f403451740a06896b558d593a5c46fb7e29b89c8beef2b0baab2595f611809e97535c90766239a287dc031012a44730a0664a195e225b53e9ab1f4882754dc5293e64328acde9901d7e96d3c32254e28d1c7dcda48564762eee27cf66a1c6813fe6237300e24b719d1d928bf979a4a5b0eb570960396c3c925701496c2e9896d3ccb2ce603c36d052bf3819cf19ac825975ea27a15cd48f2b117a2a37705f081ce6f069c577c4457d2054346acfd66650fa1c4f0547fc9ab1d0742769d44aaf6427cd8c689aa14497bc0b2c3a91fdb07560bd31feaa9a2e09bcdbd529afc7e2ab289a28290c07a273f45c7a10e3559a530876a6cfc1374a7183bf172574cb891e278b2541f2a111abcaa3f09e7cbb24ddc9ca99c555d600aee2592e45c148b2eaf1b5ae562988130f090e301f3f09714834d94cfb57defa53bde222c8cfdc6d7de54e67283a9c9387033147ec77844e9f538fd973639b632280411144ea53930d914e649b6048f22860f3d38f466e38301dedb309e64c5b2cc4e8c35d2e8e932290b9b33d4ced0bf87b8d2a558296c92664c0028c2ddaf499800f9c894283630e9694ad26381e5c92b5c860a279c403e602c929f7323aa4689f5244a8545f53187ab5a239b30167932c2e36c72d12ba671864b9c83d68c04a18ba622fa4654abda3e0f1d11f586e6080d6524bd9783f4a3b78a9992eb6972d95cfb14182448ce89aeda8a399a77abaf8bf56d49a6b294e158d19e8f3716211fa19cb0a2f2655f8ce24e4a101a35c68d5aaaa34bc2fcd4ec3354e2fbcc5a9b8d75d559bdabf02807a59c62fa3e960de7e460baaa4bfcd7a0ca088979bb124fbe5beaa28e42230943526a8fe48e5ad8d5132766415ca2f562a6654c3e1c2f3290c83276db375302267ac09fbf9a3f17ffc010c3367018c7b1b72c6fc6a02bf2d04db3e9a0cac601cca96f44104dfccb7024e44f09c0cd4b2e52666ee4e23f74618ac0b84f24f015f38cdfefbefd6567396ee7593f56f
+InNoiseEP = 5a9a43219eac7517ad1b9abd5ca888e84c953f48773e0cec94d4322f4cea9ddb830c1c3de76ea5564a5b3b2ec5476414ac2f4ca4b2b0de57cda2ffa9aaa58feadbeb403f057810881f56b5e60eaca35551eca91f36554610c8cc8cf26b75e939a84803d8ae1584890cd80aa728caad06a12c6f29560c8adda597e43a5d00a2c261fb8a9a37fb816c04331176c48d4670d7085adb9fc3077ed49172a81006448c3bf229724bee26b657eb11957008a653d9156ad76597e4138c866e310d285718a6e3a9bdc6af88b260cc24e9a7dd452fb81f099a464946caa2a4ca2e9b27dc48a2980db3ae7098f55d95d8eb0e19d380f6544119ae0f1430f82dea7490ac46b77cfdae116c4096d0de15c1a3c0fb861011821e80709fcca262a8e4f038c9555f4c17a278881f1e867c9761ea909c9e5aa3769a7e5748b0bb46bd782d212062744243239f1847ad5d9f449b9b80a934b5b702c758ed9a5efe5202caf6192e47aa49686eb612f01944715352b6e7c759802992b3248f7ec4a0d973829131c16a65ac97cca9b731757587a38776ce987d2f5f61f024993e3ae2bd95c7be68a723e590040c14e84ba7518ed54855dab19948f4945fe5771923ea97d0492902b139737a5181b9173a17742e27e626ae6475989bc68aa048339a80a3300879b72a0af0f4ca5f688cc6a6902a790a228356a9f576bcd07de18b583276e4977aa80d60a1acb0e88974a3775f31b76ffc4bcdae32e73f892f7ea1d9c6f21a073dda31a5def64d1e516a4af52c09095d21756dae530c53df12ae9d10916ca672a322893b69389464c0452186bd88897029818d0250df314d2e2efbd803353f431fea4b092854ff6fc5d9444129c49d0313c49e9be0516e414c8420fb2a1c28548d4a0293fce5452d6ff1da977a34a92711ce10480e0581f80fb0609458958f15bf7486447672905552dfce91976a0f261e94bc1eafad76fe7d6547105d0ac5d89d670464367ba27defa406c6f32c0e21166c605ab8ab0f5bf211b78190e9dffb8508f2aeaba52980eec98c3863b8b4fd81b67529132675992c272eb615794156e80a091772442f884d4630aa6e344359fd5694c910faabf198027e1ef5481ecba91245c1ed936a5416ab706796547878703c4126d5267596354fbdc518f95e7396b795de3c7996150a295d82056712e4288f99743c8b740703cd57ca668ad2bd5c50349e438522bd5ba84821a320410b27062fb5f196432955db86a6a88b306d0b71149c9b7d8204ab7cb6bc4299fe5598c490a79d53abd8ce6d71e0948b5dc41f8654f983350c739b1e3cc697a11e5306ca097b75a980d0f37b9044a6c3209570d09ca4cf8a3de989d11bad8abfd9a5254093d4d8482bae4e7125f2a6d27c49ef68aea073a505d86609040cac20029971d33e5c96e76e812114ce83234b56a89f5d8bbbd6a1e4e49a0cd08ee4fb354a6e568bff89d3b234d7e01543de4e60660dbd5b88d9073943e9f3f16aa5da91ad30819d59b94326da3909aaf0e7667394444ffdef93193daa21ed03847771ce981c40438a2ee8b472e494a9307d53254dc7c534dab0bb401a0ba434268022d8a7155e654c14e5709632bc9c2fd507027258edaefe73fd482be81d77b4955d22728819a35d26745edd9672c8a5615c510495abf2bacf93b358c0aa1e13cb6048be4082b95b3cb96015442fcc338677b204f6cacc907f5e8194994dd83b16a592defc349190532fa616ca1f763ddd6a575858f8885351c72aa2857ad30447c0f6564064187387820d3209e7d38329503ff89f54793300489dec9092007940ff8372222b3e1819c7996a13458f69068855b9f63dec8f9501ab0c799b6190e42edd417740d5a40684bb74946a64c3fe0c1e2f9674f6260e200d7b4913647ebedc75c20d023be90ec8d1eea1a9946143c249e572b5eb6119fa9a2ace5c46f281f9760f8f1769e8104c2441b4da0a5971ff22dd6343591977eb524235e4959804c00a39a43bb31a30024ac801a707c1f8e8983cd5e677b62d9e9ff4e0eaca214a5babda03690229ae91209964242d1acfea5416bc19743dd30c9111a660e3ac4627c4718cfa94c737af2468c52f8e47d9055399c52369b2c550ff62af79b75cb8dba1f538b61d72c5dee5a5ccb44a2f8b70190795942c64602482ec6cf8d74f75cadc921f4050c3e7e52b80cfbc6a29d5024e1de18be732b7c3a1d1eabac8603a8019e378f9a3b5128f8890047363d80be37b9464a213dd61202e7160037f57bb991ef214eb163d796957980177bda87897478e3a4d3094ef2e9a587c991fa4055540ef51a66983aeb2857215af46ea6b3a6d580099434bab327fb680d9097e3072a1637233d0559546e09853f8a6b448e814e7ca6a51482bb2958744692e55b43b8bcd9a5ca487589aaa848e955924169c13d0e95e9348c20c982e0d697a9a5b114708463ebd3b48c5dc7502c1bd3c69bfc97da18c60e1c7b4a4a29528a95bf4b258800208cca3c530a3c05eceb838d61cd56c40e4b41c08
+InNoiseEPP = 0080ff1b00fcbf0180000000f8bfffaf00b0ff0a0000300090ff0600ff2f012000f4bf00c0fffbff02000000ffdbff0200ffefffebff0a00ffafff1b00040001c0ff2b00000000400000001400f8effe0b0004000300ff1b00f8bf06c000d0ff0600000000100000c0010000ecfff2bffdef00e0ff02c0fd2f001000f8bf0180ff9b00fcbf0700003000fcbf054000000004000400001c0000c0048000000000000640003000000007400040001000007000f0ff0600ff6fffcbff1200008000200000c00300000c00f3bf07c000100000c0fdef0030000400010000ccff06000030000c00070002c0fffbfffabf0140ff0b000400020000fcffeebfff2f000c00fcbf0300002c00f4bffd6f00b0ff0a00074000c0ff0a0002c0fe0b00f7bf0240001000fcbf00c00020000400030000e0ff0200ff2f00400000c000000100000000020000dcff0e000500000000fcbffc6fff1b000000ff2f0000000c00034000e0ff0e000300ff2b0000000100003c0000000580fe2b0010000380005000f8bf02800000000c00feef00e0ff0e0002c0ff2b000800fd2f0120000400fcefffdbff1200ff2f01e0ff0a000000003c00f8bf0280ffdbff02c0024000f0fffabf0080ff1b000c000100003000fcbf014000d0ff0200003000f0ff0a0000f0ffebff06000240fffbff0200ff2f001000f4bffe2f00ecff06000080ff2b00fcbffbef00e0ffeabf0030000000030000300000000700fe6f0000000300070000f0fffebf040000d0fffebf0000000c000400ff2f00acfff6bf00400100000300feafff0b000400fe6fff3b0014000280000000f4bf0180ff1b000c000300001c00f4bffe6f00d0ff0200fe2f00f0ff02c00240002000040000f000e0fffabffbefff3b0000c0018000000000c00540fffbff0a000400ff2b00080008800010000c00048000100004000340000000f0bf0480002000f4bfffeffe0b000000fcef000000fcbf0000000000080001c0ffdbff060003400010001c00007000e0ff02c00280ff0b000000060000dcfffebf0080fffbff0a00ff2f004000140000300010000400010000bcff0200fe6f003000fcbf0200ff1b00f8bf00b00040000400ff2f000c00180000f00020000800014000000004000180ff0b00fcbffe2f0120001800f76f004000fcbf0100011000100002000100000700fe2f00f0fff2bf018000f0ff0200ffef001000ecbffe2f000000040001c00010001000038000f0ff0e00014000300004000080ff0b0000c00070ff0b0003000180ff0b0004000030003c00e8bf0280ff3b0000c00100010000f3bf00c000200000c00070000000fbbfff2f00bcff0a00004000d0ff06000030000c00f8bf030000300004000030003000080002c0001000000003c0ff0b000000ff6f011000f0bfffafff0b000400004000c0ff0200014001400008000100003c000400fb2f00f0fffebf0100001c0008000500000000f7bf00c0ffcbff0e000400000c00000005c0ff5b0008000100000c00f4bf020000ecfffabf01c0000000fcbffaaf00d0ff02c001000000000700fe2ffe2b00f8bf04c00020000800fdaf0050001400ff6f0000000f0004800000001000000000d0ff02c0fdaf00f0ff0200007000d0fffebf064001e0ff0a0001c0fffbfffebffd2f002c001400fe2f001c0000000600ffebff060004c0ff3b001400fd6f0020000800fe6fff0b000700fb2fff0b00fcbffd2f00f0ff0e0004000110000c0000f000f0ff0200034000100000000140ff3b00fcbf00300100000f00054000d0ff0e000100ff3b00fcbf038000e0fffabf00c0002000fcbffb6f012000fcbf0200000c0003000340ff0b000b00003000ecff0200ff2fff3b0000000080002000f8bffdef00d0fff6bf010000ecff02c00100001c00fcbf01800090000800000000ecfffebffc2f003c00080001c001f0fffebffdaf0000000300feefff0b00f8bf0070001000f4bfff2f00ccfffabfff6f003000000001000110000c00ff2f003c00040001c0ff7b001000034000200000c0ff2f00e0ff1600fc2f00300000c000b0003000180000400150000800fcaf0050000800010000b0ff0e00feef00900000c0fc2f00f0ff02000000002c00080000700000000800007000c0ff06000400000c000b000080fffbff0e000100001c001400fe6f00000007000030000c000f0005c000200000000100005c000800ffaf0030000400ff2f001000f4bf003001500000c000b0ff4b00f4bf0080ff1b00f4bf0300000c00030000b0ffcbfffabf0080ffebff02c003c0fffbff1a00008000000003c0fdef00200000c00040ffbbffeebffdaf010000f4bfff2f002c000000feaf000000fcbffcaf001000040004c0ff0b000b0000800000001300ff2f01100004000100000000ffbf028000d0ff0200feeffedbff0a00fbafffebff020003c0ffebff02c001800060000800fe2f0100000400014001500000c0ff2f01e0ff0200ffef005000f0bf
+InRand = 869e8bb1806d746f8978d27fead08f551a3825d1ce8cb7e0f07476ae742b8f82
+OutPK = 39d9341741d840b49a1ea42aaa9722c7dee138dd713741b43288ba177ce3c8e5aa59bedf4b449964e0a285205af18e087405025e068f8c0a0393eccaf4cc03081fc982bd9d5e6ca138020b9eb351d787104e9c58bf89f4f2bdbd4c65649308cc3d77eec7b1535d2635596a81b0da909fa26ac5254a6d09bd0d4edb5a797589194d94b3d65022a76e04766e934e91704b98e8b758d0b6f962915d302a7405f9ee58540cbac0b97940f1a3979080b876962a5b113779a60164a42bdfa64f36522516425e285d2fd55af31e0cf29e6e73ae5c991d922811d2d60bf89467458e18b7409e2dd354962123de0804b92a7951ca8ef8c1bdabc4ab0cf118f174af0721200d6241399d4ab35de597e56ba39b0b01215ba6a180467800e02dbe09b2e05760c714085c266ca540f6d872750103cf72918ea6baef8320f8199a2f975484576fd615895d66e4b37697a04e71b79fe92f745013872421ad346d8e5aa5e0548d451d7a0d92a3086f4d52849c84cd8a50ca7199411d91310b17a24523dd274541ea37fc48ab3771b110d76bc10a6fe22060459295a4699c11a0b832c29c3d844e8ab5f3226f04e826005bd0bbac50e7339c51a54a989d204ca1671e15d9531022729f541404840d7ebe90f9e1283e6561d3ed2bb4882a94e5112624e205d0d5eab574e003f24665d3e5b12e2debc982896a00bb6501e79dc887f3ae8352a7262f3fd33543c5f1a1126cbea35beeb09503c927a1de5e131ef644ec508872e143f7f51e47ddeb61105ebda015ef5573e0490c0d887cb676b0816c13c3061ad6a48d6fb3526dc03977a25ba445cd47442b9330f2e92f59efe62560cd6eaf408783a6b2b5744c507b575665bc8a0b80c6d42bbc237b8585a133b5eba767fac0783463c341c6267d082a986410e8a85387f5c48aa415dfd65921ed993ca46bd779219a678f423333d98a4d2f083260ef080b1a87281a6d5c984a59c1d85bb08a5b80af4243b00169c1f59265469f57d603b215f29f2f6dff032e551e0ddf73a6424db8ec1d4d84f48c332895a87be5c18a30629d6045900478db6942878680895223a2bca8195da9fc97e6e08e1a029b5654656a279709890294045beca301eb527625ad22968938235dad6df25de662ee6d687af6f559b809c63bcde4a4a20bedc5bce97264d69c14c462751c9fa4fa4c26054fe0f09a430431c4d63cc787100ac142741849219f0a8a0231fe2070ab87fc95b9596f354acc252ce0b4a00a53fb3e1191f50cabe214bd1ae618e2e83a32308d64ee02475e8b8d8530001804525017f8a9d1c197c903ed14eaf5b76c6418c8395972831be313056ca4759c11e4f9902febad2d2806c6300a6e7664512d68d9543c1090091f2edcd9c65f010313c3e18af7d15745ce168663d094dd6d45750c7094cd5cb6b57289af8c69fe1685840da00e5af305a477ddc150f3799cacb1c34297dc9d64ee255265dc254377220cd410089da86707d48c70b06785a7f113be123887b78af2fa7d9c8c6b292f0a4a0bd7c5a7982c6b3bd638b285300ecce36023dc2c329916b3596db2bbdcec5c8ae5ea1be382bc1520950f9260edc81c58be801574a33769520b2b09d329015e8618f95984c519931c2289ee4e949b29c9460d963c15d2dc488cc864a516f40ba5fab00e154e82054e4dccc3cfc73224589d6fade0f41e63021c9a5b85be53b325a7a311edbc559f565781d0909186dcf6be5869635ef36b110d5e7685ddc33372843fe425ebf5f990d2635280fb01a8bc007057af0c6f995e5d30e316a7ccc4d59243d8760cc930733e7a3972a467f15adaa37e476fd3497a50c905e261fbfa863edce31bf7f95eb5009ac796791e0ed0df86af317cbd6891d939647bfc2c815606ba465658e768fd1e1e5101ef1315481a5ce238885a98b7c2ad689785108fe59f2935328212aa83cac332c93fcb11a1621efa0b0c6d59418e1e460e1af0e3f7198fac9f7c4157c05806906e9a5cea7554255d22af04a631dd85643411b7a5a3ded243b1b3b1a334887a2241f001bf6403a5bdc569858649696a12618444aef605f5df1c13d2da470c513442e4f6b877ca0d163e2981d18c731263a40697d381709a8a25e445ea4b266a84efab42653fc09e246d8ce1acc40fcc0a6ababd28af2a141be523bc713dd7c4c333e9b55f0005c533556b5b07fef3fbce365423ffc3e398638ba10dc30a08ba9301e3cbffd929945e45fae3b41d69e1dde5a59c879f91a9946029b9761f2b641c5c393a95f814cfd806c009a6dbb0e6882c103497fef03e5a1aa152f7c816fd8aaec60b845177e421c510706d40d13a256035294cc0ab0be31e11d5af22235b9187d25964f77ff18ab6e91a3b8bb8731be50d610859020266b065392037db58b77947fe8048656ed0f49665a654a9d1dd681cc94f54d3999951add67369aab6afa00b4e76cfcd5a262b420bd19d189a87c0b8d7c154b5212ed36dcd01b70f540b7b08286ccd4e7a1802ae77115ae829fc7fc0469ce0671c2c
+OutRec = 01c000300000000140003000080000000020000c000080000000040001000000000800014000300008000200001000000003c0001000040000c0001000000002c00030000c0003400000000000018000200004000080002000080001c0000000080000c000100000000180000000080001c00020000c000200002000080000c00020000c000340001000080002c0000000040000000000000400014000300000000280000000080000800020000000024000300000000180000000040003c000000004000340001000000002000020000c0001000010000c0000000010000c0000400030000c00014000200000000280002000000002c00020000c0002c000000000000040003000080003c0003000080000c0001000040001c000000004000100002000080003800000000400034000300008000340000000000000000030000800014000000004000380003000000001c0001000000003c000200000000140003000040002c0003000000000000000000c000100003000040003000030000c0002400000000c0000c00000000c0001c0002000080000c000000008000000000000040001800030000000024000200004000140000000040001800030000800024000300000000180000000080003c0002000000000400020000000030000100004000040002000040001c000000008000200001000040000000010000000028000100004000180003000040003c00030000c000080002000000003c00030000c00034000000004000100001000080000c0002000080001000010000c0000c00020000000018000200008000140002000000001c0003000000000c00010000c000000001000040000c0001000040002800010000c00018000100000000140002000080000400020000c0001400020000c0001000000000400020000300000000200001000040000400020000c0001c000200008000140000000000002400000000c000000001000040000c00030000c0002c00010000c000340002000000001800020000000030000200004000080002000080002400030000c000300002000040000c00030000c00028000000000000040003000080001000020000c0002800000000c000240003000080000400030000c000100001000040001400000000800038000300004000180000000000002400020000800014000000004000180001000080002400000000c00038000100004000040001000040003000030000400024000200000000000001000040001800020000c000080001000080003400000000c0000c0000000080002c00010000c0002800020000400014000100004000000000000080000000010000c0002c00030000c00010000100000000000000000040000800020000c0002000000000c0003c00030000c0000400000000c000200001000000001000020000000000000200000000140002000040003c0001000080002c000300000000280000000080001400030000c0001c000100004000380000000000001000010000c0001000000000800038000300008000380003000000003400000000c00020000100008000340000000040000000010000c0002c00030000000024000100004000300000000080000800000000c0003800010000c00014000300004000180002000000000c00020000c000280003000080000c0001000040001c000100000000200003000040001c0003000040003000020000c000000001000080003c0001000040002800000000c00000000000000000200003000080002c00000000c00030000000008000280001000080002c00020000400028000100004000200001000080000c0002000040000c000300004000200001000080003c000200000000000003000000001400030000c000100001000000003000000000c0001800030000000018000100000000000000000080001c0000000080002400010000c00018000200000000000003000040003c0003000000003800000000c000240002000040001000030000c000240002000040003c000200008000000003000040003c0002000000001c0000000000002c0003000040003c0003000040001c00030000000038000200008000340002000080003000000000800030000000008000280000000040000800010000c00008000100000000080003000040001400010000c0000800030000c000300002000040002c0001000000000c0002000040000800020000c000180002000000002c000100008000340003000040002400010000800014000300000000340000000000000400000000c000080002000040002c00000000c000100003000080002c0003000000002800000000000000000100008000300001000040003400000000800004000000000000000001000040002c0003000040000000020000800020000300008000180000000040003c000300004000100001000040002800010000c000140000000080000400020000800
+Key = 76f2c93a81a15cc9e46a714d5ede343d56b2e08761c7c8df10b13e08db01ec06
+
+InNoiseS = 4ca10ae48258b14d83e48384f858eae4c130e49055a044c78590f0a74f1a19e8edd427300659bb38647c032c5722a6ac4b05413b4a0dc870ac1b16f25099428b9beb83af39887340a1c4bd986241429eb8eec081442a418b10ac60be94b3e34374a63c5582274aba579a03202666b16f3066985a26b96dd8993e242ccd6a3d9a2d287fdc82da9091830d0886b80bf3419ae968c615521160e85676c96af65dd92ea10e2c520bca4b882326b7b2c131d22d922827c5b41f2f33b281b50e8b64d92ac48a9bc4516a39272018ef5b707223b59bc2e07dd6831015b610b04638aa9d949cb7444c7d3162cf3a088b628f73c93d66375540330ac2d871d4b0405421caa142a0a2effcaacfe5173862deb228da286993d7605db54efd98f122b1949be7a15481fbd23d97d588b7bce9bf4da31481296149138c1b5753caaa9428b6d5f3be48c69979d351525c61532bf5535aa7d72850c294021d1614fda36c781f2ddbf10a4f723e578a596092ec312827ae456cac024c5a44bb68e5175025ce6876aeb1951d022426faab5a0db9d0cf369324a153533fb50b5a5866c77c00524265020b769517d7970918f5d2bc5a6e874332186d5f9e7a3a03aa28a39de5078002c0845c9eb74791088a81b185958e014f95d1219d702d2ec39a772fa82a3c91fc873a991d54c3c0babb64a7bdd15e78232d3b71a1c08bd60e68fc2f5e46348c8b948c1f93860eab88d24b736c785f2a4564a6754492c9c988c786166708d2b240d3da4c3280bd5616c0aff7a81a9a560809766df9b27e014c6c8aa45b38a6416046ba4b560804a90b54c3f5b6a2abaa7149968c8567c0ed07f2ee99218ed52b88bd98624c1c91b9ae1b082b6d07c8697eccc6a953cec576a25cdf548866a1cb03ded4fb26a1afa6c9287050459de64af1aac1572b1509643c6407f5d4a944904856c42f770717adbc701ff3c9f44aae6bea40c50bdd9f1f9368b667286732023d89581e7f872639f19766b65305b07babe9003e631b6a32511e690a864a18d45263c9436a0f1245db4405b31e1d9a6598922ae6f09a61975b3ac27225baa60e1bf6f01b8a0c07988dc9167648e9b1891c3e01a5031260cd52d08cce39498835b9122ef5d4f24f34c7623448294c4da985b5904583bd6f7e301bb911abaf1c778ee1567e8f4df0e05479cf1b5854e0cc7083a4463a96f2aa4d28944147464d249057b13c3eb8e0e93466a70194309f3339ef597459e9ffb5b15a1cf080c34713b819f6051d2baa142b9602460ac3451161913bd960202f68092c456b6ab71c638877f008862904b3fa62b815414e745b2309629d4691e894282c37e70ab15a82a7b055157b481552c6ee3ef7510a9d9420216b7f2275ef64dab95cc86b3e8ffbcaf508bafa0251c4755d287041290b4f6675f22d3ff9c31808c29d8281f2aaa7c7dede72a42592c10b20a35cee60b31b9d67f5ea6adaa33fb3dd911816aa142975551ebd40569bb1fd904a504b7ac811234029921b6b06b28a1df7c2a2ed59a4ad3541f8852e815b08c09444809decfd2904a62d991cc3c6659d6d4c6906d482bc03cce05cbb9ae142264aeda128148084c5b93b831458b061dd99e94e60a1ef51199f550156047901792628c6d5ff316c20be6d5ea59030d6abb624f8909e12a02dcf69f039ad45ffda6113f2f6aa9be6bb934122ae2de84b7a0add8488c052aaf50d0e098d58c7be3c80fe946c566c00b4739fd59aa2de006885b0cb9c65231f5fa760af69a929443aa3252aa16497dcb2c1180f42cca1310b99278a956a07cf540561dc0bb9e8b6b2ea25e57ae52d636b6297a2afbcb6d014942a33ce4869829de6f1ba761b60b6b93f993938884076c1e4976848f8bb6c4486daddaae7fb8073749a70f0eec61ff2c9687184c09bd15f849108700efe8a01b72c9c97d40957b4e3d64533411887541a5de6518ab756994bb5ed9f7af8da0bbe6959c57e4a2f346884a6716a847015c5545d69770d56d44500097f83ee4b736df867029d979848b64a2c281b2ac3d140ed854f12fd946b770754139e0e320223dac9823a14c28cbae29dc4af992ced62ab7255f265c533cb54b75f48a8321e7aa8f7939c468d26645c57b4abf0569260229a40611920af1add758474b8d026f41785559ad04faa501a649e44abee8607fc4eb21376552ba48931156485c7916d4d63247a757d4f92cf34322202b94acdc3276d99a2a899d3471475bb268ef9ea9976a949437e30e168301d027518aeec04ffc4294a00a2649b271b334f3cbdf88678b8b8c583f62c0815937667aede6ae53aec271e5d885a84b58d348449aa06649d6a635bd7d392885a0ae60218d8a085a509f5e5ad12e24c4d36b04600c0011623d4a4bd2206fce8d5003234405db3ad7e3d4dd6aa790abc6b1e49e8b26436ae6c9f1010b1e052158639c1582d641d8b3ed0a9c289aa5eae66e66a43048876b14cf4a69489224564c4932adaaf83e2b15e0b2248425d71198849f534d801b24cccb2aa434829
+InPK = 39d9341741d840b49a1ea42aaa9722c7dee138dd713741b43288ba177ce3c8e5aa59bedf4b449964e0a285205af18e087405025e068f8c0a0393eccaf4cc03081fc982bd9d5e6ca138020b9eb351d787104e9c58bf89f4f2bdbd4c65649308cc3d77eec7b1535d2635596a81b0da909fa26ac5254a6d09bd0d4edb5a797589194d94b3d65022a76e04766e934e91704b98e8b758d0b6f962915d302a7405f9ee58540cbac0b97940f1a3979080b876962a5b113779a60164a42bdfa64f36522516425e285d2fd55af31e0cf29e6e73ae5c991d922811d2d60bf89467458e18b7409e2dd354962123de0804b92a7951ca8ef8c1bdabc4ab0cf118f174af0721200d6241399d4ab35de597e56ba39b0b01215ba6a180467800e02dbe09b2e05760c714085c266ca540f6d872750103cf72918ea6baef8320f8199a2f975484576fd615895d66e4b37697a04e71b79fe92f745013872421ad346d8e5aa5e0548d451d7a0d92a3086f4d52849c84cd8a50ca7199411d91310b17a24523dd274541ea37fc48ab3771b110d76bc10a6fe22060459295a4699c11a0b832c29c3d844e8ab5f3226f04e826005bd0bbac50e7339c51a54a989d204ca1671e15d9531022729f541404840d7ebe90f9e1283e6561d3ed2bb4882a94e5112624e205d0d5eab574e003f24665d3e5b12e2debc982896a00bb6501e79dc887f3ae8352a7262f3fd33543c5f1a1126cbea35beeb09503c927a1de5e131ef644ec508872e143f7f51e47ddeb61105ebda015ef5573e0490c0d887cb676b0816c13c3061ad6a48d6fb3526dc03977a25ba445cd47442b9330f2e92f59efe62560cd6eaf408783a6b2b5744c507b575665bc8a0b80c6d42bbc237b8585a133b5eba767fac0783463c341c6267d082a986410e8a85387f5c48aa415dfd65921ed993ca46bd779219a678f423333d98a4d2f083260ef080b1a87281a6d5c984a59c1d85bb08a5b80af4243b00169c1f59265469f57d603b215f29f2f6dff032e551e0ddf73a6424db8ec1d4d84f48c332895a87be5c18a30629d6045900478db6942878680895223a2bca8195da9fc97e6e08e1a029b5654656a279709890294045beca301eb527625ad22968938235dad6df25de662ee6d687af6f559b809c63bcde4a4a20bedc5bce97264d69c14c462751c9fa4fa4c26054fe0f09a430431c4d63cc787100ac142741849219f0a8a0231fe2070ab87fc95b9596f354acc252ce0b4a00a53fb3e1191f50cabe214bd1ae618e2e83a32308d64ee02475e8b8d8530001804525017f8a9d1c197c903ed14eaf5b76c6418c8395972831be313056ca4759c11e4f9902febad2d2806c6300a6e7664512d68d9543c1090091f2edcd9c65f010313c3e18af7d15745ce168663d094dd6d45750c7094cd5cb6b57289af8c69fe1685840da00e5af305a477ddc150f3799cacb1c34297dc9d64ee255265dc254377220cd410089da86707d48c70b06785a7f113be123887b78af2fa7d9c8c6b292f0a4a0bd7c5a7982c6b3bd638b285300ecce36023dc2c329916b3596db2bbdcec5c8ae5ea1be382bc1520950f9260edc81c58be801574a33769520b2b09d329015e8618f95984c519931c2289ee4e949b29c9460d963c15d2dc488cc864a516f40ba5fab00e154e82054e4dccc3cfc73224589d6fade0f41e63021c9a5b85be53b325a7a311edbc559f565781d0909186dcf6be5869635ef36b110d5e7685ddc33372843fe425ebf5f990d2635280fb01a8bc007057af0c6f995e5d30e316a7ccc4d59243d8760cc930733e7a3972a467f15adaa37e476fd3497a50c905e261fbfa863edce31bf7f95eb5009ac796791e0ed0df86af317cbd6891d939647bfc2c815606ba465658e768fd1e1e5101ef1315481a5ce238885a98b7c2ad689785108fe59f2935328212aa83cac332c93fcb11a1621efa0b0c6d59418e1e460e1af0e3f7198fac9f7c4157c05806906e9a5cea7554255d22af04a631dd85643411b7a5a3ded243b1b3b1a334887a2241f001bf6403a5bdc569858649696a12618444aef605f5df1c13d2da470c513442e4f6b877ca0d163e2981d18c731263a40697d381709a8a25e445ea4b266a84efab42653fc09e246d8ce1acc40fcc0a6ababd28af2a141be523bc713dd7c4c333e9b55f0005c533556b5b07fef3fbce365423ffc3e398638ba10dc30a08ba9301e3cbffd929945e45fae3b41d69e1dde5a59c879f91a9946029b9761f2b641c5c393a95f814cfd806c009a6dbb0e6882c103497fef03e5a1aa152f7c816fd8aaec60b845177e421c510706d40d13a256035294cc0ab0be31e11d5af22235b9187d25964f77ff18ab6e91a3b8bb8731be50d610859020266b065392037db58b77947fe8048656ed0f49665a654a9d1dd681cc94f54d3999951add67369aab6afa00b4e76cfcd5a262b420bd19d189a87c0b8d7c154b5212ed36dcd01b70f540b7b08286ccd4e7a1802ae77115ae829fc7fc0469ce0671c2c
+InRec = 01c000300000000140003000080000000020000c000080000000040001000000000800014000300008000200001000000003c0001000040000c0001000000002c00030000c0003400000000000018000200004000080002000080001c0000000080000c000100000000180000000080001c00020000c000200002000080000c00020000c000340001000080002c0000000040000000000000400014000300000000280000000080000800020000000024000300000000180000000040003c000000004000340001000000002000020000c0001000010000c0000000010000c0000400030000c00014000200000000280002000000002c00020000c0002c000000000000040003000080003c0003000080000c0001000040001c000000004000100002000080003800000000400034000300008000340000000000000000030000800014000000004000380003000000001c0001000000003c000200000000140003000040002c0003000000000000000000c000100003000040003000030000c0002400000000c0000c00000000c0001c0002000080000c000000008000000000000040001800030000000024000200004000140000000040001800030000800024000300000000180000000080003c0002000000000400020000000030000100004000040002000040001c000000008000200001000040000000010000000028000100004000180003000040003c00030000c000080002000000003c00030000c00034000000004000100001000080000c0002000080001000010000c0000c00020000000018000200008000140002000000001c0003000000000c00010000c000000001000040000c0001000040002800010000c00018000100000000140002000080000400020000c0001400020000c0001000000000400020000300000000200001000040000400020000c0001c000200008000140000000000002400000000c000000001000040000c00030000c0002c00010000c000340002000000001800020000000030000200004000080002000080002400030000c000300002000040000c00030000c00028000000000000040003000080001000020000c0002800000000c000240003000080000400030000c000100001000040001400000000800038000300004000180000000000002400020000800014000000004000180001000080002400000000c00038000100004000040001000040003000030000400024000200000000000001000040001800020000c000080001000080003400000000c0000c0000000080002c00010000c0002800020000400014000100004000000000000080000000010000c0002c00030000c00010000100000000000000000040000800020000c0002000000000c0003c00030000c0000400000000c000200001000000001000020000000000000200000000140002000040003c0001000080002c000300000000280000000080001400030000c0001c000100004000380000000000001000010000c0001000000000800038000300008000380003000000003400000000c00020000100008000340000000040000000010000c0002c00030000000024000100004000300000000080000800000000c0003800010000c00014000300004000180002000000000c00020000c000280003000080000c0001000040001c000100000000200003000040001c0003000040003000020000c000000001000080003c0001000040002800000000c00000000000000000200003000080002c00000000c00030000000008000280001000080002c00020000400028000100004000200001000080000c0002000040000c000300004000200001000080003c000200000000000003000000001400030000c000100001000000003000000000c0001800030000000018000100000000000000000080001c0000000080002400010000c00018000200000000000003000040003c0003000000003800000000c000240002000040001000030000c000240002000040003c000200008000000003000040003c0002000000001c0000000000002c0003000040003c0003000040001c00030000000038000200008000340002000080003000000000800030000000008000280000000040000800010000c00008000100000000080003000040001400010000c0000800030000c000300002000040002c0001000000000c0002000040000800020000c000180002000000002c000100008000340003000040002400010000800014000300000000340000000000000400000000c000080002000040002c00000000c000100003000080002c0003000000002800000000000000000100008000300001000040003400000000800004000000000000000001000040002c0003000040000000020000800020000300008000180000000040003c000300004000100001000040002800010000c000140000000080000400020000800
+Key = 76f2c93a81a15cc9e46a714d5ede343d56b2e08761c7c8df10b13e08db01ec06
+
diff --git a/crypto/newhope/newhope_vectors_test.cc b/crypto/newhope/newhope_vectors_test.cc
new file mode 100644
index 00000000..fe84cd4b
--- /dev/null
+++ b/crypto/newhope/newhope_vectors_test.cc
@@ -0,0 +1,122 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+
+#include "../test/file_test.h"
+#include "../test/scoped_types.h"
+#include "internal.h"
+
+
+static bool TestNewhope(FileTest *t, void *arg) {
+ ScopedNEWHOPE_POLY a(NEWHOPE_POLY_new());
+ ScopedNEWHOPE_POLY s(NEWHOPE_POLY_new()), sp(NEWHOPE_POLY_new());
+ ScopedNEWHOPE_POLY e(NEWHOPE_POLY_new()), ep(NEWHOPE_POLY_new()),
+ epp(NEWHOPE_POLY_new());
+ ScopedNEWHOPE_POLY in_pk(NEWHOPE_POLY_new());
+ ScopedNEWHOPE_POLY in_rec(NEWHOPE_POLY_new());
+
+ if (t->GetType() == "InRandA") {
+ std::vector<uint8_t> a_bytes, s_bytes, e_bytes, expected_pk;
+ if (!t->GetBytes(&a_bytes, "InRandA") ||
+ !t->GetBytes(&s_bytes, "InNoiseS") ||
+ !t->GetBytes(&e_bytes, "InNoiseE") ||
+ !t->GetBytes(&expected_pk, "OutPK")) {
+ return false;
+ }
+ NEWHOPE_POLY_frombytes(a.get(), a_bytes.data());
+ NEWHOPE_POLY_frombytes(s.get(), s_bytes.data());
+ NEWHOPE_POLY_frombytes(e.get(), e_bytes.data());
+
+ NEWHOPE_POLY pk;
+ NEWHOPE_offer_computation(&pk, s.get(), e.get(), a.get());
+
+ uint8_t pk_bytes[NEWHOPE_POLY_LENGTH];
+ NEWHOPE_POLY_tobytes(pk_bytes, &pk);
+ return t->ExpectBytesEqual(expected_pk.data(), expected_pk.size(),
+ pk_bytes, NEWHOPE_POLY_LENGTH);
+ } else if (t->GetType() == "InPK") {
+ std::vector<uint8_t> rand, in_pk_bytes, a_bytes, sp_bytes, ep_bytes,
+ epp_bytes, expected_pk, expected_rec, expected_key;
+ if (!t->GetBytes(&in_pk_bytes, "InPK") ||
+ !t->GetBytes(&rand, "InRand") ||
+ !t->GetBytes(&a_bytes, "InA") ||
+ !t->GetBytes(&sp_bytes, "InNoiseSP") ||
+ !t->GetBytes(&ep_bytes, "InNoiseEP") ||
+ !t->GetBytes(&epp_bytes, "InNoiseEPP") ||
+ !t->GetBytes(&expected_pk, "OutPK") ||
+ !t->GetBytes(&expected_rec, "OutRec") ||
+ !t->GetBytes(&expected_key, "Key")) {
+ return false;
+ }
+ NEWHOPE_POLY_frombytes(in_pk.get(), in_pk_bytes.data());
+ NEWHOPE_POLY_frombytes(a.get(), a_bytes.data());
+ NEWHOPE_POLY_frombytes(sp.get(), sp_bytes.data());
+ NEWHOPE_POLY_frombytes(ep.get(), ep_bytes.data());
+ NEWHOPE_POLY_frombytes(epp.get(), epp_bytes.data());
+
+ uint8_t key[NEWHOPE_KEY_LENGTH];
+ NEWHOPE_POLY pk, rec;
+ NEWHOPE_accept_computation(key, &pk, &rec,
+ sp.get(), ep.get(), epp.get(),
+ rand.data(), in_pk.get(), a.get());
+
+ uint8_t pk_bytes[NEWHOPE_POLY_LENGTH], rec_bytes[NEWHOPE_POLY_LENGTH];
+ NEWHOPE_POLY_tobytes(pk_bytes, &pk);
+ NEWHOPE_POLY_tobytes(rec_bytes, &rec);
+ return
+ t->ExpectBytesEqual(expected_key.data(), expected_key.size(),
+ key, NEWHOPE_KEY_LENGTH) &&
+ t->ExpectBytesEqual(expected_pk.data(), expected_pk.size(),
+ pk_bytes, NEWHOPE_POLY_LENGTH) &&
+ t->ExpectBytesEqual(expected_rec.data(), expected_rec.size(),
+ rec_bytes, NEWHOPE_POLY_LENGTH);
+ } else if (t->GetType() == "InNoiseS") {
+ std::vector<uint8_t> s_bytes, in_pk_bytes, in_rec_bytes, expected_key;
+ if (!t->GetBytes(&s_bytes, "InNoiseS") ||
+ !t->GetBytes(&in_pk_bytes, "InPK") ||
+ !t->GetBytes(&in_rec_bytes, "InRec") ||
+ !t->GetBytes(&expected_key, "Key")) {
+ return false;
+ }
+ NEWHOPE_POLY_frombytes(s.get(), s_bytes.data());
+ NEWHOPE_POLY_frombytes(in_pk.get(), in_pk_bytes.data());
+ NEWHOPE_POLY_frombytes(in_rec.get(), in_rec_bytes.data());
+
+ uint8_t key[NEWHOPE_KEY_LENGTH];
+ NEWHOPE_finish_computation(key, s.get(), in_pk.get(), in_rec.get());
+
+ return t->ExpectBytesEqual(expected_key.data(), expected_key.size(), key,
+ NEWHOPE_KEY_LENGTH);
+ } else {
+ t->PrintLine("Unknown test '%s'", t->GetType().c_str());
+ return false;
+ }
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ if (argc != 2) {
+ fprintf(stderr, "%s <test file>\n", argv[0]);
+ return 1;
+ }
+
+ return FileTestMain(TestNewhope, nullptr, argv[1]);
+}
diff --git a/crypto/newhope/ntt.c b/crypto/newhope/ntt.c
new file mode 100644
index 00000000..163a9d1a
--- /dev/null
+++ b/crypto/newhope/ntt.c
@@ -0,0 +1,148 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+
+static uint16_t bitrev_table[1024] = {
+ 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704,
+ 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864,
+ 224, 736, 480, 992, 16, 528, 272, 784, 144, 656, 400, 912, 80, 592,
+ 336, 848, 208, 720, 464, 976, 48, 560, 304, 816, 176, 688, 432, 944,
+ 112, 624, 368, 880, 240, 752, 496, 1008, 8, 520, 264, 776, 136, 648,
+ 392, 904, 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808,
+ 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, 24, 536,
+ 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, 216, 728, 472, 984,
+ 56, 568, 312, 824, 184, 696, 440, 952, 120, 632, 376, 888, 248, 760,
+ 504, 1016, 4, 516, 260, 772, 132, 644, 388, 900, 68, 580, 324, 836,
+ 196, 708, 452, 964, 36, 548, 292, 804, 164, 676, 420, 932, 100, 612,
+ 356, 868, 228, 740, 484, 996, 20, 532, 276, 788, 148, 660, 404, 916,
+ 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, 180, 692,
+ 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, 12, 524, 268, 780,
+ 140, 652, 396, 908, 76, 588, 332, 844, 204, 716, 460, 972, 44, 556,
+ 300, 812, 172, 684, 428, 940, 108, 620, 364, 876, 236, 748, 492, 1004,
+ 28, 540, 284, 796, 156, 668, 412, 924, 92, 604, 348, 860, 220, 732,
+ 476, 988, 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892,
+ 252, 764, 508, 1020, 2, 514, 258, 770, 130, 642, 386, 898, 66, 578,
+ 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, 162, 674, 418, 930,
+ 98, 610, 354, 866, 226, 738, 482, 994, 18, 530, 274, 786, 146, 658,
+ 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50, 562, 306, 818,
+ 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498, 1010, 10, 522,
+ 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970,
+ 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, 234, 746,
+ 490, 1002, 26, 538, 282, 794, 154, 666, 410, 922, 90, 602, 346, 858,
+ 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442, 954, 122, 634,
+ 378, 890, 250, 762, 506, 1018, 6, 518, 262, 774, 134, 646, 390, 902,
+ 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806, 166, 678,
+ 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, 22, 534, 278, 790,
+ 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54, 566,
+ 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502, 1014,
+ 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206, 718,
+ 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366, 878,
+ 238, 750, 494, 1006, 30, 542, 286, 798, 158, 670, 414, 926, 94, 606,
+ 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958,
+ 126, 638, 382, 894, 254, 766, 510, 1022, 1, 513, 257, 769, 129, 641,
+ 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801,
+ 161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, 17, 529,
+ 273, 785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977,
+ 49, 561, 305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753,
+ 497, 1009, 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841,
+ 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617,
+ 361, 873, 233, 745, 489, 1001, 25, 537, 281, 793, 153, 665, 409, 921,
+ 89, 601, 345, 857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697,
+ 441, 953, 121, 633, 377, 889, 249, 761, 505, 1017, 5, 517, 261, 773,
+ 133, 645, 389, 901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549,
+ 293, 805, 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997,
+ 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, 213, 725,
+ 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, 117, 629, 373, 885,
+ 245, 757, 501, 1013, 13, 525, 269, 781, 141, 653, 397, 909, 77, 589,
+ 333, 845, 205, 717, 461, 973, 45, 557, 301, 813, 173, 685, 429, 941,
+ 109, 621, 365, 877, 237, 749, 493, 1005, 29, 541, 285, 797, 157, 669,
+ 413, 925, 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829,
+ 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, 3, 515,
+ 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, 195, 707, 451, 963,
+ 35, 547, 291, 803, 163, 675, 419, 931, 99, 611, 355, 867, 227, 739,
+ 483, 995, 19, 531, 275, 787, 147, 659, 403, 915, 83, 595, 339, 851,
+ 211, 723, 467, 979, 51, 563, 307, 819, 179, 691, 435, 947, 115, 627,
+ 371, 883, 243, 755, 499, 1011, 11, 523, 267, 779, 139, 651, 395, 907,
+ 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, 171, 683,
+ 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, 27, 539, 283, 795,
+ 155, 667, 411, 923, 91, 603, 347, 859, 219, 731, 475, 987, 59, 571,
+ 315, 827, 187, 699, 443, 955, 123, 635, 379, 891, 251, 763, 507, 1019,
+ 7, 519, 263, 775, 135, 647, 391, 903, 71, 583, 327, 839, 199, 711,
+ 455, 967, 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871,
+ 231, 743, 487, 999, 23, 535, 279, 791, 151, 663, 407, 919, 87, 599,
+ 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183, 695, 439, 951,
+ 119, 631, 375, 887, 247, 759, 503, 1015, 15, 527, 271, 783, 143, 655,
+ 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559, 303, 815,
+ 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007, 31, 543,
+ 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991,
+ 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255, 767,
+ 511, 1023};
+
+void newhope_bitrev_vector(uint16_t* poly) {
+ unsigned int i, r;
+ uint16_t tmp;
+
+ for (i = 0; i < PARAM_N; i++) {
+ r = bitrev_table[i];
+ if (i < r) {
+ tmp = poly[i];
+ poly[i] = poly[r];
+ poly[r] = tmp;
+ }
+ }
+}
+
+void newhope_mul_coefficients(uint16_t* poly, const uint16_t* factors) {
+ unsigned int i;
+
+ for (i = 0; i < PARAM_N; i++) {
+ poly[i] = newhope_montgomery_reduce((poly[i] * factors[i]));
+ }
+}
+
+/* GS_bo_to_no; omegas need to be in Montgomery domain */
+void newhope_ntt(uint16_t* a, const uint16_t* omega) {
+ int i, start, j, jTwiddle, distance;
+ uint16_t temp, W;
+
+ for (i = 0; i < 10; i += 2) {
+ /* Even level */
+ distance = (1 << i);
+ for (start = 0; start < distance; start++) {
+ jTwiddle = 0;
+ for (j = start; j < PARAM_N - 1; j += 2 * distance) {
+ W = omega[jTwiddle++];
+ temp = a[j];
+ a[j] = (temp + a[j + distance]); /* Omit reduction (be lazy) */
+ a[j + distance] = newhope_montgomery_reduce(
+ (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance])));
+ }
+ }
+
+ /* Odd level */
+ distance <<= 1;
+ for (start = 0; start < distance; start++) {
+ jTwiddle = 0;
+ for (j = start; j < PARAM_N - 1; j += 2 * distance) {
+ W = omega[jTwiddle++];
+ temp = a[j];
+ a[j] = newhope_barrett_reduce((temp + a[j + distance]));
+ a[j + distance] = newhope_montgomery_reduce(
+ (W * ((uint32_t)temp + 3 * PARAM_Q - a[j + distance])));
+ }
+ }
+ }
+}
diff --git a/crypto/newhope/poly.c b/crypto/newhope/poly.c
new file mode 100644
index 00000000..44cd3839
--- /dev/null
+++ b/crypto/newhope/poly.c
@@ -0,0 +1,189 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/aes.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+
+
+extern uint16_t newhope_omegas_montgomery[];
+extern uint16_t newhope_omegas_inv_montgomery[];
+
+extern uint16_t newhope_psis_bitrev_montgomery[];
+extern uint16_t newhope_psis_inv_montgomery[];
+
+void NEWHOPE_POLY_frombytes(NEWHOPE_POLY* r, const uint8_t* a) {
+ int i;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ r->coeffs[4 * i + 0] =
+ a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8);
+ r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) |
+ (((uint16_t)a[7 * i + 2]) << 2) |
+ (((uint16_t)a[7 * i + 3] & 0x0f) << 10);
+ r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) |
+ (((uint16_t)a[7 * i + 4]) << 4) |
+ (((uint16_t)a[7 * i + 5] & 0x03) << 12);
+ r->coeffs[4 * i + 3] =
+ (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6);
+ }
+}
+
+void NEWHOPE_POLY_tobytes(uint8_t* r, const NEWHOPE_POLY* p) {
+ int i;
+ uint16_t t0, t1, t2, t3, m;
+ int16_t c;
+ for (i = 0; i < PARAM_N / 4; i++) {
+ t0 = newhope_barrett_reduce(
+ p->coeffs[4 * i + 0]); /* Make sure that coefficients
+ have only 14 bits */
+ t1 = newhope_barrett_reduce(p->coeffs[4 * i + 1]);
+ t2 = newhope_barrett_reduce(p->coeffs[4 * i + 2]);
+ t3 = newhope_barrett_reduce(p->coeffs[4 * i + 3]);
+
+ m = t0 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t0 = m ^ ((t0 ^ m) & c); /* Make sure that coefficients are in [0,q] */
+
+ m = t1 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t1 = m ^ ((t1 ^ m) & c); /* <Make sure that coefficients are in [0,q] */
+
+ m = t2 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t2 = m ^ ((t2 ^ m) & c); /* <Make sure that coefficients are in [0,q] */
+
+ m = t3 - PARAM_Q;
+ c = m;
+ c >>= 15;
+ t3 = m ^ ((t3 ^ m) & c); /* Make sure that coefficients are in [0,q] */
+
+ r[7 * i + 0] = t0 & 0xff;
+ r[7 * i + 1] = (t0 >> 8) | (t1 << 6);
+ r[7 * i + 2] = (t1 >> 2);
+ r[7 * i + 3] = (t1 >> 10) | (t2 << 4);
+ r[7 * i + 4] = (t2 >> 4);
+ r[7 * i + 5] = (t2 >> 12) | (t3 << 2);
+ r[7 * i + 6] = (t3 >> 6);
+ }
+}
+
+void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed) {
+/* The reference implementation uses SHAKE-128 here; this implementation uses
+ * AES-CTR. Use half the seed for the initialization vector and half for the
+ * key. */
+#if SEED_LENGTH != 2 * AES_BLOCK_SIZE
+#error "2 * seed length != AES_BLOCK_SIZE"
+#endif
+ uint8_t ivec[AES_BLOCK_SIZE];
+ memcpy(ivec, &seed[SEED_LENGTH / 2], SEED_LENGTH / 2);
+ AES_KEY key;
+ AES_set_encrypt_key(seed, 8 * SEED_LENGTH / 2, &key);
+
+ /* AES state. */
+ uint8_t ecount[AES_BLOCK_SIZE];
+ memset(ecount, 0, AES_BLOCK_SIZE);
+
+ /* Encrypt a block of zeros just to get the random bytes. With luck, 2688
+ * bytes is enough. */
+ uint8_t buf[AES_BLOCK_SIZE * 168];
+ memset(buf, 0, sizeof(buf));
+
+ unsigned int block_num = 0;
+ AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num);
+
+ size_t pos = 0, coeff_num = 0;
+ while (coeff_num < PARAM_N) {
+ /* Specialized for q = 12889 */
+ uint16_t val = (buf[pos] | ((uint16_t)buf[pos + 1] << 8)) & 0x3fff;
+ if (val < PARAM_Q) {
+ a->coeffs[coeff_num++] = val;
+ }
+
+ pos += 2;
+ if (pos > sizeof(buf) - 2) {
+ memset(buf, 0, sizeof(buf));
+ AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num);
+ pos = 0;
+ }
+ }
+}
+
+void NEWHOPE_POLY_noise(NEWHOPE_POLY* r) {
+#if PARAM_K != 16
+#error "poly_getnoise in poly.c only supports k=16"
+#endif
+
+ uint32_t tp[PARAM_N];
+
+ /* The reference implementation calls ChaCha20 here. */
+ RAND_bytes((uint8_t *) tp, sizeof(tp));
+
+ size_t i;
+ for (i = 0; i < PARAM_N; i++) {
+ const uint32_t t = tp[i];
+
+ size_t j;
+ uint32_t d = 0;
+ for (j = 0; j < 8; j++) {
+ d += (t >> j) & 0x01010101;
+ }
+
+ const uint32_t a = ((d >> 8) & 0xff) + (d & 0xff);
+ const uint32_t b = (d >> 24) + ((d >> 16) & 0xff);
+ r->coeffs[i] = a + PARAM_Q - b;
+ }
+}
+
+void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b) {
+ size_t i;
+ for (i = 0; i < PARAM_N; i++) {
+ uint16_t t = newhope_montgomery_reduce(3186 * b->coeffs[i]);
+ /* t is now in Montgomery domain */
+ r->coeffs[i] = newhope_montgomery_reduce(a->coeffs[i] * t);
+ /* r->coeffs[i] is back in normal domain */
+ }
+}
+
+void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
+ const NEWHOPE_POLY* b) {
+ size_t i;
+ for (i = 0; i < PARAM_N; i++) {
+ r->coeffs[i] = newhope_barrett_reduce(a->coeffs[i] + b->coeffs[i]);
+ }
+}
+
+void NEWHOPE_POLY_noise_ntt(NEWHOPE_POLY* r) {
+ NEWHOPE_POLY_noise(r);
+ /* Forward NTT transformation. Because we're operating on a noise polynomial,
+ * we can regard the bits as already reversed and skip the bit-reversal
+ * step:
+ *
+ * newhope_bitrev_vector(r->coeffs); */
+ newhope_mul_coefficients(r->coeffs, newhope_psis_bitrev_montgomery);
+ newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_montgomery);
+}
+
+void newhope_poly_invntt(NEWHOPE_POLY* r) {
+ newhope_bitrev_vector(r->coeffs);
+ newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_inv_montgomery);
+ newhope_mul_coefficients(r->coeffs, newhope_psis_inv_montgomery);
+}
diff --git a/crypto/newhope/precomp.c b/crypto/newhope/precomp.c
new file mode 100644
index 00000000..d0c478ee
--- /dev/null
+++ b/crypto/newhope/precomp.c
@@ -0,0 +1,306 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+
+uint16_t newhope_omegas_montgomery[PARAM_N / 2] = {
+ 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041,
+ 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118,
+ 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973,
+ 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930,
+ 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643,
+ 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605,
+ 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080,
+ 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142,
+ 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968,
+ 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821,
+ 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874,
+ 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281,
+ 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453,
+ 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030,
+ 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939,
+ 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706,
+ 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634,
+ 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459,
+ 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065,
+ 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922,
+ 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948,
+ 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992,
+ 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106,
+ 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969,
+ 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553,
+ 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088,
+ 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479,
+ 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961,
+ 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744,
+ 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374,
+ 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011,
+ 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791,
+ 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755,
+ 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637,
+ 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207,
+ 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952,
+ 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302,
+ 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045,
+ 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516,
+ 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714,
+ 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618,
+ 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730,
+ 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686,
+ 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863,
+ 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852,
+ 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364,
+ 3271, 4057, 4414, 9442, 7917, 2174};
+
+uint16_t newhope_omegas_inv_montgomery[PARAM_N / 2] = {
+ 4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278,
+ 9945, 3514, 11248, 11271, 5925, 147, 8500, 7840, 6833, 5537, 4749,
+ 4467, 7500, 11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, 9090,
+ 12233, 5529, 5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427,
+ 7341, 6152, 10561, 400, 8410, 1922, 2033, 8291, 1359, 6854, 11035,
+ 973, 8579, 6093, 6950, 5446, 11821, 8301, 11907, 316, 52, 3174,
+ 10966, 9523, 6055, 8953, 11612, 6415, 2505, 5906, 10710, 11858, 8332,
+ 9450, 10162, 151, 3482, 787, 5468, 1010, 4169, 9162, 5241, 9369,
+ 7509, 8844, 7232, 4698, 192, 1321, 10240, 4912, 885, 6281, 10333,
+ 7280, 8757, 11286, 58, 12048, 12147, 11184, 8812, 6608, 2844, 3438,
+ 4212, 11314, 8687, 6068, 421, 8209, 3600, 3263, 7665, 6077, 7507,
+ 5886, 3029, 6695, 4213, 504, 11684, 2302, 1962, 1594, 6328, 7183,
+ 168, 2692, 8960, 4298, 5184, 11089, 6122, 9734, 10929, 3956, 5297,
+ 6170, 3762, 9370, 4016, 4077, 6523, 652, 11994, 6099, 1146, 11341,
+ 11964, 10885, 6299, 1159, 8240, 8561, 11177, 2078, 10331, 4322, 11367,
+ 441, 4079, 11231, 3150, 1319, 8243, 709, 8049, 8719, 11454, 6224,
+ 3054, 6803, 3123, 10542, 4433, 6370, 7032, 3834, 8633, 12225, 9830,
+ 683, 1566, 5782, 9786, 9341, 12115, 723, 3009, 1693, 5735, 2655,
+ 2738, 6421, 11942, 2925, 1975, 8532, 3315, 11863, 4754, 1858, 1583,
+ 6347, 2500, 10800, 6374, 1483, 12240, 1263, 1815, 5383, 10777, 350,
+ 6920, 10232, 4493, 9087, 8855, 8760, 9381, 218, 9928, 10446, 9259,
+ 4115, 6147, 9842, 8326, 576, 10335, 10238, 10484, 9407, 6381, 11836,
+ 8517, 418, 6860, 7515, 1293, 7552, 2767, 156, 8298, 8320, 10008,
+ 5876, 5333, 10258, 10115, 4372, 2847, 7875, 8232, 9018, 8925, 1689,
+ 8236, 2645, 5042, 9984, 7094, 9509, 1484, 7394, 3, 4437, 160,
+ 3149, 113, 7370, 10123, 3915, 6998, 2704, 8653, 4938, 1426, 7635,
+ 10512, 1663, 6957, 3510, 2370, 2865, 3978, 9320, 3247, 9603, 6882,
+ 3186, 10659, 10163, 1153, 9405, 8241, 10040, 2178, 1544, 5559, 420,
+ 8304, 4905, 476, 3531, 5191, 9153, 2399, 8889, 3000, 671, 243,
+ 3016, 3763, 10849, 12262, 9223, 10657, 7205, 11272, 7404, 7575, 8146,
+ 10752, 242, 2678, 3704, 11744, 5019, 3833, 3778, 11899, 773, 5101,
+ 11222, 9888, 442, 2912, 5698, 11935, 4861, 7277, 9808, 11244, 2859,
+ 3780, 11414, 4976, 10682, 7201, 8005, 11287, 5011, 6267, 2987, 2437,
+ 3646, 2566, 10102, 9867, 6250, 5444, 2381, 11796, 8193, 4337, 11854,
+ 1912, 1378, 404, 7644, 1065, 2143, 11121, 5277, 3248, 11082, 2548,
+ 8058, 8907, 11934, 1759, 8582, 3694, 7110, 12144, 6747, 8652, 3459,
+ 2731, 8357, 6378, 7399, 10861, 1696, 9863, 334, 7657, 6534, 11029,
+ 4388, 11560, 3241, 10276, 9000, 9408, 3284, 10200, 7197, 6498, 544,
+ 2468, 339, 11267, 9, 2842, 480, 5331, 7300, 1673, 4278, 4177,
+ 8705, 9764, 1381, 7837, 2396, 8340, 8993, 4354, 130, 6915, 2837,
+ 11462, 5767, 953, 8541, 9813, 118, 7222, 2197, 3006, 9545, 563,
+ 9314, 2625, 11340, 4821, 2639, 7266, 5828, 6561, 7698, 3328, 6512,
+ 1351, 7311, 6553, 8155, 1305, 722, 5146, 4043, 12288, 10810, 2545,
+ 3621, 8747, 8785, 1646, 1212, 5860, 3195, 7203, 10963, 3201, 3014,
+ 955, 11499, 9970, 11119, 3135, 3712, 7443, 9542, 7484, 8736, 9995,
+ 11227, 1635, 9521, 1177, 8034, 140, 10436, 11563, 7678, 4320, 11289,
+ 9198, 12208, 2963, 7393, 2366, 9238};
+
+uint16_t newhope_psis_bitrev_montgomery[PARAM_N] = {
+ 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041,
+ 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118,
+ 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973,
+ 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930,
+ 3998, 10256, 10367, 3879, 11889, 1728, 6137, 4948, 5862, 6136, 3643,
+ 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, 9987, 605,
+ 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080,
+ 11868, 6221, 3602, 975, 8077, 8851, 9445, 5681, 3477, 1105, 142,
+ 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, 7377, 2049, 10968,
+ 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821,
+ 11502, 8807, 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874,
+ 677, 3336, 6234, 2766, 1323, 9115, 12237, 2031, 6956, 6413, 2281,
+ 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453,
+ 5908, 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030,
+ 1843, 2361, 12071, 2908, 3529, 3434, 3202, 7796, 2057, 5369, 11939,
+ 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706,
+ 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634,
+ 6554, 10596, 9280, 11566, 174, 2948, 2503, 6507, 10723, 11606, 2459,
+ 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, 6065,
+ 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922,
+ 7967, 1958, 10211, 1112, 3728, 4049, 11130, 5990, 1404, 325, 948,
+ 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, 6119, 6992,
+ 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106,
+ 5961, 10695, 10327, 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969,
+ 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, 1062, 2294, 3553,
+ 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088,
+ 1326, 5086, 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479,
+ 1, 8246, 7143, 11567, 10984, 4134, 5736, 4978, 10938, 5777, 8961,
+ 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744,
+ 9283, 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374,
+ 12159, 7935, 3296, 3949, 9893, 4452, 10908, 2525, 3584, 8112, 8011,
+ 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791,
+ 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755,
+ 4632, 11955, 2426, 10593, 1428, 4890, 5911, 3932, 9558, 8830, 3637,
+ 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, 1207,
+ 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952,
+ 4096, 493, 9908, 6845, 6039, 2422, 2187, 9723, 8643, 9852, 9302,
+ 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, 9430, 1045,
+ 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516,
+ 390, 8511, 8456, 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714,
+ 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, 9273, 12046, 11618,
+ 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730,
+ 10745, 10111, 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686,
+ 9042, 2969, 8311, 9424, 9919, 8779, 5332, 10626, 1777, 4654, 10863,
+ 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852,
+ 12286, 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364,
+ 3271, 4057, 4414, 9442, 7917, 2174, 3947, 11951, 2455, 6599, 10545,
+ 10975, 3654, 2894, 7681, 7126, 7287, 12269, 4119, 3343, 2151, 1522,
+ 7174, 7350, 11041, 2442, 2148, 5959, 6492, 8330, 8945, 5598, 3624,
+ 10397, 1325, 6565, 1945, 11260, 10077, 2674, 3338, 3276, 11034, 506,
+ 6505, 1392, 5478, 8778, 1178, 2776, 3408, 10347, 11124, 2575, 9489,
+ 12096, 6092, 10058, 4167, 6085, 923, 11251, 11912, 4578, 10669, 11914,
+ 425, 10453, 392, 10104, 8464, 4235, 8761, 7376, 2291, 3375, 7954,
+ 8896, 6617, 7790, 1737, 11667, 3982, 9342, 6680, 636, 6825, 7383,
+ 512, 4670, 2900, 12050, 7735, 994, 1687, 11883, 7021, 146, 10485,
+ 1403, 5189, 6094, 2483, 2054, 3042, 10945, 3981, 10821, 11826, 8882,
+ 8151, 180, 9600, 7684, 5219, 10880, 6780, 204, 11232, 2600, 7584,
+ 3121, 3017, 11053, 7814, 7043, 4251, 4739, 11063, 6771, 7073, 9261,
+ 2360, 11925, 1928, 11825, 8024, 3678, 3205, 3359, 11197, 5209, 8581,
+ 3238, 8840, 1136, 9363, 1826, 3171, 4489, 7885, 346, 2068, 1389,
+ 8257, 3163, 4840, 6127, 8062, 8921, 612, 4238, 10763, 8067, 125,
+ 11749, 10125, 5416, 2110, 716, 9839, 10584, 11475, 11873, 3448, 343,
+ 1908, 4538, 10423, 7078, 4727, 1208, 11572, 3589, 2982, 1373, 1721,
+ 10753, 4103, 2429, 4209, 5412, 5993, 9011, 438, 3515, 7228, 1218,
+ 8347, 5232, 8682, 1327, 7508, 4924, 448, 1014, 10029, 12221, 4566,
+ 5836, 12229, 2717, 1535, 3200, 5588, 5845, 412, 5102, 7326, 3744,
+ 3056, 2528, 7406, 8314, 9202, 6454, 6613, 1417, 10032, 7784, 1518,
+ 3765, 4176, 5063, 9828, 2275, 6636, 4267, 6463, 2065, 7725, 3495,
+ 8328, 8755, 8144, 10533, 5966, 12077, 9175, 9520, 5596, 6302, 8400,
+ 579, 6781, 11014, 5734, 11113, 11164, 4860, 1131, 10844, 9068, 8016,
+ 9694, 3837, 567, 9348, 7000, 6627, 7699, 5082, 682, 11309, 5207,
+ 4050, 7087, 844, 7434, 3769, 293, 9057, 6940, 9344, 10883, 2633,
+ 8190, 3944, 5530, 5604, 3480, 2171, 9282, 11024, 2213, 8136, 3805,
+ 767, 12239, 216, 11520, 6763, 10353, 7, 8566, 845, 7235, 3154,
+ 4360, 3285, 10268, 2832, 3572, 1282, 7559, 3229, 8360, 10583, 6105,
+ 3120, 6643, 6203, 8536, 8348, 6919, 3536, 9199, 10891, 11463, 5043,
+ 1658, 5618, 8787, 5789, 4719, 751, 11379, 6389, 10783, 3065, 7806,
+ 6586, 2622, 5386, 510, 7628, 6921, 578, 10345, 11839, 8929, 4684,
+ 12226, 7154, 9916, 7302, 8481, 3670, 11066, 2334, 1590, 7878, 10734,
+ 1802, 1891, 5103, 6151, 8820, 3418, 7846, 9951, 4693, 417, 9996,
+ 9652, 4510, 2946, 5461, 365, 881, 1927, 1015, 11675, 11009, 1371,
+ 12265, 2485, 11385, 5039, 6742, 8449, 1842, 12217, 8176, 9577, 4834,
+ 7937, 9461, 2643, 11194, 3045, 6508, 4094, 3451, 7911, 11048, 5406,
+ 4665, 3020, 6616, 11345, 7519, 3669, 5287, 1790, 7014, 5410, 11038,
+ 11249, 2035, 6125, 10407, 4565, 7315, 5078, 10506, 2840, 2478, 9270,
+ 4194, 9195, 4518, 7469, 1160, 6878, 2730, 10421, 10036, 1734, 3815,
+ 10939, 5832, 10595, 10759, 4423, 8420, 9617, 7119, 11010, 11424, 9173,
+ 189, 10080, 10526, 3466, 10588, 7592, 3578, 11511, 7785, 9663, 530,
+ 12150, 8957, 2532, 3317, 9349, 10243, 1481, 9332, 3454, 3758, 7899,
+ 4218, 2593, 11410, 2276, 982, 6513, 1849, 8494, 9021, 4523, 7988,
+ 8, 457, 648, 150, 8000, 2307, 2301, 874, 5650, 170, 9462,
+ 2873, 9855, 11498, 2535, 11169, 5808, 12268, 9687, 1901, 7171, 11787,
+ 3846, 1573, 6063, 3793, 466, 11259, 10608, 3821, 6320, 4649, 6263,
+ 2929};
+
+uint16_t newhope_psis_inv_montgomery[PARAM_N] = {
+ 256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000,
+ 2327, 2088, 5565, 795, 10647, 1521, 5484, 2539, 7385, 1055, 7173,
+ 8047, 11683, 1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, 10525,
+ 12037, 12253, 3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207,
+ 5582, 2553, 7387, 6322, 9681, 1383, 10731, 1533, 219, 5298, 4268,
+ 7632, 6357, 9686, 8406, 4712, 9451, 10128, 4958, 5975, 11387, 8649,
+ 11769, 6948, 11526, 12180, 1740, 10782, 6807, 2728, 7412, 4570, 4164,
+ 4106, 11120, 12122, 8754, 11784, 3439, 5758, 11356, 6889, 9762, 11928,
+ 1704, 1999, 10819, 12079, 12259, 7018, 11536, 1648, 1991, 2040, 2047,
+ 2048, 10826, 12080, 8748, 8272, 8204, 1172, 1923, 7297, 2798, 7422,
+ 6327, 4415, 7653, 6360, 11442, 12168, 7005, 8023, 9924, 8440, 8228,
+ 2931, 7441, 1063, 3663, 5790, 9605, 10150, 1450, 8985, 11817, 10466,
+ 10273, 12001, 3470, 7518, 1074, 1909, 7295, 9820, 4914, 702, 5367,
+ 7789, 8135, 9940, 1420, 3714, 11064, 12114, 12264, 1752, 5517, 9566,
+ 11900, 1700, 3754, 5803, 829, 1874, 7290, 2797, 10933, 5073, 7747,
+ 8129, 6428, 6185, 11417, 1631, 233, 5300, 9535, 10140, 11982, 8734,
+ 8270, 2937, 10953, 8587, 8249, 2934, 9197, 4825, 5956, 4362, 9401,
+ 1343, 3703, 529, 10609, 12049, 6988, 6265, 895, 3639, 4031, 4087,
+ 4095, 585, 10617, 8539, 4731, 4187, 9376, 3095, 9220, 10095, 10220,
+ 1460, 10742, 12068, 1724, 5513, 11321, 6884, 2739, 5658, 6075, 4379,
+ 11159, 10372, 8504, 4726, 9453, 3106, 7466, 11600, 10435, 8513, 9994,
+ 8450, 9985, 3182, 10988, 8592, 2983, 9204, 4826, 2445, 5616, 6069,
+ 867, 3635, 5786, 11360, 5134, 2489, 10889, 12089, 1727, 7269, 2794,
+ 9177, 1311, 5454, 9557, 6632, 2703, 9164, 10087, 1441, 3717, 531,
+ 3587, 2268, 324, 5313, 759, 1864, 5533, 2546, 7386, 9833, 8427,
+ 4715, 11207, 1601, 7251, 4547, 11183, 12131, 1733, 10781, 10318, 1474,
+ 10744, 5046, 4232, 11138, 10369, 6748, 964, 7160, 4534, 7670, 8118,
+ 8182, 4680, 11202, 6867, 981, 8918, 1274, 182, 26, 7026, 8026,
+ 11680, 12202, 10521, 1503, 7237, 4545, 5916, 9623, 8397, 11733, 10454,
+ 3249, 9242, 6587, 941, 1890, 270, 10572, 6777, 9746, 6659, 6218,
+ 6155, 6146, 878, 1881, 7291, 11575, 12187, 1741, 7271, 8061, 11685,
+ 6936, 4502, 9421, 4857, 4205, 7623, 1089, 10689, 1527, 8996, 10063,
+ 11971, 10488, 6765, 2722, 3900, 9335, 11867, 6962, 11528, 5158, 4248,
+ 4118, 5855, 2592, 5637, 6072, 2623, 7397, 8079, 9932, 4930, 5971,
+ 853, 3633, 519, 8852, 11798, 3441, 11025, 1575, 225, 8810, 11792,
+ 12218, 3501, 9278, 3081, 9218, 4828, 7712, 8124, 11694, 12204, 3499,
+ 4011, 573, 3593, 5780, 7848, 9899, 10192, 1456, 208, 7052, 2763,
+ 7417, 11593, 10434, 12024, 8740, 11782, 10461, 3250, 5731, 7841, 9898,
+ 1414, 202, 3540, 7528, 2831, 2160, 10842, 5060, 4234, 4116, 588,
+ 84, 12, 7024, 2759, 9172, 6577, 11473, 1639, 9012, 3043, 7457,
+ 6332, 11438, 1634, 1989, 9062, 11828, 8712, 11778, 12216, 10523, 6770,
+ 9745, 10170, 4964, 9487, 6622, 946, 8913, 6540, 6201, 4397, 9406,
+ 8366, 9973, 8447, 8229, 11709, 8695, 10020, 3187, 5722, 2573, 10901,
+ 6824, 4486, 4152, 9371, 8361, 2950, 2177, 311, 1800, 9035, 8313,
+ 11721, 3430, 490, 70, 10, 1757, 251, 3547, 7529, 11609, 3414,
+ 7510, 4584, 4166, 9373, 1339, 5458, 7802, 11648, 1664, 7260, 9815,
+ 10180, 6721, 9738, 10169, 8475, 8233, 9954, 1422, 8981, 1283, 5450,
+ 11312, 1616, 3742, 11068, 10359, 4991, 713, 3613, 9294, 8350, 4704,
+ 672, 96, 7036, 9783, 11931, 3460, 5761, 823, 10651, 12055, 10500,
+ 1500, 5481, 783, 3623, 11051, 8601, 8251, 8201, 11705, 10450, 5004,
+ 4226, 7626, 2845, 2162, 3820, 7568, 9859, 3164, 452, 10598, 1514,
+ 5483, 6050, 6131, 4387, 7649, 8115, 6426, 918, 8909, 8295, 1185,
+ 5436, 11310, 8638, 1234, 5443, 11311, 5127, 2488, 2111, 10835, 5059,
+ 7745, 2862, 3920, 560, 80, 1767, 2008, 3798, 11076, 6849, 2734,
+ 10924, 12094, 8750, 1250, 10712, 6797, 971, 7161, 1023, 8924, 4786,
+ 7706, 4612, 4170, 7618, 6355, 4419, 5898, 11376, 10403, 10264, 6733,
+ 4473, 639, 5358, 2521, 9138, 3061, 5704, 4326, 618, 5355, 765,
+ 5376, 768, 7132, 4530, 9425, 3102, 9221, 6584, 11474, 10417, 10266,
+ 12000, 6981, 6264, 4406, 2385, 7363, 4563, 4163, 7617, 9866, 3165,
+ 9230, 11852, 10471, 5007, 5982, 11388, 5138, 734, 3616, 11050, 12112,
+ 6997, 11533, 12181, 10518, 12036, 3475, 2252, 7344, 9827, 4915, 9480,
+ 6621, 4457, 7659, 9872, 6677, 4465, 4149, 7615, 4599, 657, 3605,
+ 515, 10607, 6782, 4480, 640, 1847, 3775, 5806, 2585, 5636, 9583,
+ 1369, 10729, 8555, 10000, 11962, 5220, 7768, 8132, 8184, 9947, 1421,
+ 203, 29, 8782, 11788, 1684, 10774, 10317, 4985, 9490, 8378, 4708,
+ 11206, 5112, 5997, 7879, 11659, 12199, 8765, 10030, 4944, 5973, 6120,
+ 6141, 6144, 7900, 11662, 1666, 238, 34, 3516, 5769, 9602, 8394,
+ 9977, 6692, 956, 10670, 6791, 9748, 11926, 8726, 11780, 5194, 742,
+ 106, 8793, 10034, 3189, 10989, 5081, 4237, 5872, 4350, 2377, 10873,
+ 6820, 6241, 11425, 10410, 10265, 3222, 5727, 9596, 4882, 2453, 2106,
+ 3812, 11078, 12116, 5242, 4260, 11142, 8614, 11764, 12214, 5256, 4262,
+ 4120, 11122, 5100, 11262, 5120, 2487, 5622, 9581, 8391, 8221, 2930,
+ 10952, 12098, 6995, 6266, 9673, 4893, 699, 3611, 4027, 5842, 11368,
+ 1624, 232, 8811, 8281, 1183, 169, 8802, 3013, 2186, 5579, 797,
+ 3625, 4029, 11109, 1587, 7249, 11569, 8675, 6506, 2685, 10917, 12093,
+ 12261, 12285, 1755, 7273, 1039, 1904, 272, 3550, 9285, 3082, 5707,
+ 6082, 4380, 7648, 11626, 5172, 4250, 9385, 8363, 8217, 4685, 5936,
+ 848, 8899, 6538, 934, 1889, 3781, 9318, 10109, 10222, 6727, 961,
+ 5404, 772, 5377, 9546, 8386, 1198, 8949, 3034, 2189, 7335, 4559,
+ 5918, 2601, 10905, 5069, 9502, 3113, 7467, 8089, 11689, 5181, 9518,
+ 8382, 2953, 3933, 4073, 4093, 7607, 8109, 2914, 5683, 4323, 11151,
+ 1593, 10761, 6804, 972, 3650, 2277, 5592, 4310, 7638, 9869, 4921,
+ 703, 1856, 9043, 4803, 9464, 1352, 8971, 11815, 5199, 7765, 6376,
+ 4422, 7654, 2849, 407, 8836, 6529, 7955, 2892, 9191, 1313, 10721,
+ 12065, 12257, 1751, 9028, 8312, 2943, 2176, 3822, 546, 78, 8789,
+ 11789, 10462, 12028, 6985, 4509, 9422, 1346, 5459, 4291, 613, 10621,
+ 6784, 9747, 3148, 7472, 2823, 5670, 810, 7138, 8042, 4660, 7688,
+ 6365, 6176, 6149, 2634, 5643, 9584, 10147, 11983, 5223, 9524, 11894,
+ 10477, 8519, 1217, 3685, 2282, 326, 10580, 3267, 7489, 4581, 2410,
+ 5611, 11335, 6886, 8006, 8166, 11700, 3427, 11023, 8597, 10006, 3185,
+ 455, 65, 5276, 7776, 4622, 5927, 7869, 9902, 11948, 5218, 2501,
+ 5624, 2559, 10899, 1557, 1978, 10816, 10323, 8497, 4725, 675, 1852,
+ 10798, 12076, 10503, 3256, 9243, 3076, 2195, 10847, 12083, 10504, 12034,
+ 10497};
diff --git a/crypto/newhope/reduce.c b/crypto/newhope/reduce.c
new file mode 100644
index 00000000..e7f13649
--- /dev/null
+++ b/crypto/newhope/reduce.c
@@ -0,0 +1,42 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+
+/* Incomplete-reduction routines; for details on allowed input ranges
+ * and produced output ranges, see the description in the paper:
+ * https://cryptojedi.org/papers/#newhope */
+
+static const uint32_t kQInv = 12287; /* -inverse_mod(p,2^18) */
+static const uint32_t kRLog = 18;
+
+uint16_t newhope_montgomery_reduce(uint32_t a) {
+ uint32_t u;
+
+ u = (a * kQInv);
+ u &= ((1 << kRLog) - 1);
+ u *= PARAM_Q;
+ a = a + u;
+ return a >> 18;
+}
+
+uint16_t newhope_barrett_reduce(uint16_t a) {
+ uint32_t u;
+
+ u = ((uint32_t)a * 5) >> 16;
+ u *= PARAM_Q;
+ a -= u;
+ return a;
+}
diff --git a/crypto/obj/CMakeLists.txt b/crypto/obj/CMakeLists.txt
index b8a4ef37..46b7918d 100644
--- a/crypto/obj/CMakeLists.txt
+++ b/crypto/obj/CMakeLists.txt
@@ -8,3 +8,16 @@ add_library(
obj.c
obj_xref.c
)
+
+if(ENABLE_TESTS)
+add_executable(
+ obj_test
+
+ obj_test.cc
+
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(obj_test crypto)
+add_dependencies(all_tests obj_test)
+endif() \ No newline at end of file
diff --git a/crypto/obj/README b/crypto/obj/README
index 8826e598..6199fb4b 100644
--- a/crypto/obj/README
+++ b/crypto/obj/README
@@ -1,17 +1,17 @@
OID information is generated via a series of perl scripts. In order, the full
list of commands to run are:
- perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h
- perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h
+ perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h
+ perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h
perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h
objects.txt contains the list of all built-in OIDs. It is processed by
-objects.pl to output obj_mac.num and obj_mac.h. obj_mac.num is the list of NID
+objects.pl to output obj_mac.num and nid.h. obj_mac.num is the list of NID
values for each OID. This is an input/output parameter so NID values are stable
-across regenerations. obj_mac.h is the header which defines macros for all the
+across regenerations. nid.h is the header which defines macros for all the
built-in OIDs in C.
-obj_mac.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the
+nid.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the
ASN1_OBJECTs corresponding to built-in OIDs themselves along with lookup tables
for search by short name, OID, etc.
@@ -28,7 +28,7 @@ Dependency graph:
[objects.pl] <--+
/ \ |
V V |
- obj_mac.h obj_mac.num obj_xref.txt
+ nid.h obj_mac.num obj_xref.txt
| \ /
V V V
[obj_dat.pl] [obj_xref.pl]
diff --git a/crypto/obj/obj.c b/crypto/obj/obj.c
index 94f739ce..16d964c5 100644
--- a/crypto/obj/obj.c
+++ b/crypto/obj/obj.c
@@ -87,7 +87,7 @@ static int obj_next_nid(void) {
CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
ret = global_next_nid++;
- CRYPTO_STATIC_MUTEX_unlock(&global_next_nid_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock);
return ret;
}
@@ -200,11 +200,11 @@ int OBJ_obj2nid(const ASN1_OBJECT *obj) {
match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
if (match != NULL) {
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
return match->nid;
}
}
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
if (nid_ptr == NULL) {
@@ -243,11 +243,11 @@ int OBJ_sn2nid(const char *short_name) {
template.sn = short_name;
match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
if (match != NULL) {
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
return match->nid;
}
}
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
if (nid_ptr == NULL) {
@@ -277,11 +277,11 @@ int OBJ_ln2nid(const char *long_name) {
template.ln = long_name;
match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
if (match != NULL) {
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
return match->nid;
}
}
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
if (nid_ptr == NULL) {
@@ -330,11 +330,11 @@ const ASN1_OBJECT *OBJ_nid2obj(int nid) {
template.nid = nid;
match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
if (match != NULL) {
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
return match;
}
}
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
err:
OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
@@ -618,7 +618,7 @@ static int obj_add_object(ASN1_OBJECT *obj) {
if (obj->ln != NULL) {
ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
}
- CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&global_added_lock);
return ok;
}
diff --git a/crypto/obj/obj_dat.h b/crypto/obj/obj_dat.h
index bf44c6d9..1d779de6 100644
--- a/crypto/obj/obj_dat.h
+++ b/crypto/obj/obj_dat.h
@@ -1,6 +1,6 @@
/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
* following command:
- * perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
+ * perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
@@ -61,7 +61,7 @@
#define NUM_NID 949
#define NUM_SN 941
#define NUM_LN 941
-#define NUM_OBJ 882
+#define NUM_OBJ 876
static const unsigned char lvalues[6176]={
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
@@ -2482,7 +2482,7 @@ static const ASN1_OBJECT kObjects[NUM_NID]={
NID_dhSinglePass_cofactorDH_sha512kdf_scheme,6,&(lvalues[6169]),0},
{"dh-std-kdf","dh-std-kdf",NID_dh_std_kdf,0,NULL,0},
{"dh-cofactor-kdf","dh-cofactor-kdf",NID_dh_cofactor_kdf,0,NULL,0},
-{"X25519","x25519",NID_x25519,0,NULL,0},
+{"X25519","X25519",NID_X25519,0,NULL,0},
};
static const unsigned int kNIDsInShortNameOrder[NUM_SN]={
@@ -3538,6 +3538,7 @@ static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
129, /* "TLS Web Server Authentication" */
133, /* "Time Stamping" */
375, /* "Trust Root" */
+948, /* "X25519" */
12, /* "X509" */
402, /* "X509v3 AC Targeting" */
746, /* "X509v3 Any Policy" */
@@ -4366,7 +4367,6 @@ static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
742, /* "wap-wsg-idm-ecid-wtls9" */
804, /* "whirlpool" */
868, /* "x121Address" */
-948, /* "x25519" */
503, /* "x500UniqueIdentifier" */
158, /* "x509Certificate" */
160, /* "x509Crl" */
@@ -4374,12 +4374,6 @@ static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
};
static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={
- 0, /* OBJ_undef 0 */
-181, /* OBJ_iso 1 */
-393, /* OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t */
-404, /* OBJ_ccitt OBJ_itu_t */
-645, /* OBJ_itu_t 0 */
-646, /* OBJ_joint_iso_itu_t 2 */
434, /* OBJ_data 0 9 */
182, /* OBJ_member_body 1 2 */
379, /* OBJ_org 1 3 */
diff --git a/crypto/obj/obj_dat.pl b/crypto/obj/obj_dat.pl
index 201ec722..036ded54 100644
--- a/crypto/obj/obj_dat.pl
+++ b/crypto/obj/obj_dat.pl
@@ -6,7 +6,7 @@ use integer;
if (scalar @ARGV != 2)
{
- print "Usage: perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h\n";
+ print "Usage: perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h\n";
exit 1;
}
@@ -163,7 +163,7 @@ foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a)
push(@ln,sprintf("%2d,\t/* \"$ln{$nid{$_}}\" */\n",$_));
}
-@a=grep(defined($obj{$nid{$_}}),0 .. $n);
+@a=grep(defined($obj{$nid{$_}}) && $objd{$obj{$nid{$_}}} =~ /,/,0 .. $n);
foreach (sort obj_cmp @a)
{
$m=$obj{$nid{$_}};
@@ -176,7 +176,7 @@ foreach (sort obj_cmp @a)
print OUT <<'EOF';
/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
* following command:
- * perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
+ * perl obj_dat.pl ../../include/openssl/nid.h obj_dat.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
diff --git a/crypto/obj/obj_mac.num b/crypto/obj/obj_mac.num
index a0e09b80..3a7844cd 100644
--- a/crypto/obj/obj_mac.num
+++ b/crypto/obj/obj_mac.num
@@ -945,4 +945,5 @@ dhSinglePass_cofactorDH_sha384kdf_scheme 944
dhSinglePass_cofactorDH_sha512kdf_scheme 945
dh_std_kdf 946
dh_cofactor_kdf 947
-x25519 948
+X25519 948
+cecpq1 949
diff --git a/crypto/obj/obj_test.cc b/crypto/obj/obj_test.cc
new file mode 100644
index 00000000..2948941a
--- /dev/null
+++ b/crypto/obj/obj_test.cc
@@ -0,0 +1,106 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/obj.h>
+
+
+static bool TestBasic() {
+ static const int kNID = NID_sha256WithRSAEncryption;
+ static const char kShortName[] = "RSA-SHA256";
+ static const char kLongName[] = "sha256WithRSAEncryption";
+ static const char kText[] = "1.2.840.113549.1.1.11";
+ static const uint8_t kDER[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ };
+
+ CBS cbs;
+ CBS_init(&cbs, kDER, sizeof(kDER));
+ if (OBJ_cbs2nid(&cbs) != kNID ||
+ OBJ_sn2nid(kShortName) != kNID ||
+ OBJ_ln2nid(kLongName) != kNID ||
+ OBJ_txt2nid(kShortName) != kNID ||
+ OBJ_txt2nid(kLongName) != kNID ||
+ OBJ_txt2nid(kText) != kNID) {
+ return false;
+ }
+
+ if (strcmp(kShortName, OBJ_nid2sn(kNID)) != 0 ||
+ strcmp(kLongName, OBJ_nid2ln(kNID)) != 0) {
+ return false;
+ }
+
+ if (OBJ_sn2nid("this is not an OID") != NID_undef ||
+ OBJ_ln2nid("this is not an OID") != NID_undef ||
+ OBJ_txt2nid("this is not an OID") != NID_undef) {
+ return false;
+ }
+
+ CBS_init(&cbs, NULL, 0);
+ if (OBJ_cbs2nid(&cbs) != NID_undef) {
+ return false;
+ }
+
+ // 1.2.840.113554.4.1.72585.2 (https://davidben.net/oid).
+ static const uint8_t kUnknownDER[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02,
+ };
+ CBS_init(&cbs, kUnknownDER, sizeof(kUnknownDER));
+ if (OBJ_cbs2nid(&cbs) != NID_undef) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestSignatureAlgorithms() {
+ int digest_nid, pkey_nid;
+ if (!OBJ_find_sigid_algs(NID_sha256WithRSAEncryption, &digest_nid,
+ &pkey_nid) ||
+ digest_nid != NID_sha256 || pkey_nid != NID_rsaEncryption) {
+ return false;
+ }
+
+ if (OBJ_find_sigid_algs(NID_sha256, &digest_nid, &pkey_nid)) {
+ return false;
+ }
+
+ int sign_nid;
+ if (!OBJ_find_sigid_by_algs(&sign_nid, NID_sha256, NID_rsaEncryption) ||
+ sign_nid != NID_sha256WithRSAEncryption) {
+ return false;
+ }
+
+ if (OBJ_find_sigid_by_algs(&sign_nid, NID_dsa, NID_rsaEncryption)) {
+ return false;
+ }
+
+ return true;
+}
+
+int main() {
+ CRYPTO_library_init();
+
+ if (!TestBasic() ||
+ !TestSignatureAlgorithms()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/crypto/obj/objects.pl b/crypto/obj/objects.pl
index 7073e855..165429b4 100644
--- a/crypto/obj/objects.pl
+++ b/crypto/obj/objects.pl
@@ -2,7 +2,7 @@
if (scalar @ARGV != 3)
{
- print "Usage: perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h\n";
+ print "Usage: perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h\n";
exit 1;
}
@@ -127,7 +127,7 @@ open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]";
print OUT <<'EOF';
/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
* following command:
- * perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h */
+ * perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
@@ -186,23 +186,43 @@ print OUT <<'EOF';
* [including the GNU Public Licence.]
*/
-#define SN_undef "UNDEF"
-#define LN_undef "undefined"
-#define NID_undef 0
-#define OBJ_undef 0L
+#ifndef OPENSSL_HEADER_NID_H
+#define OPENSSL_HEADER_NID_H
+
+
+/* The nid library provides numbered values for ASN.1 object identifiers and
+ * other symbols. These values are used by other libraries to identify
+ * cryptographic primitives.
+ *
+ * A separate objects library, obj.h, provides functions for converting between
+ * nids and object identifiers. However it depends on large internal tables with
+ * the encodings of every nid defind. Consumers concerned with binary size
+ * should instead embed the encodings of the few consumed OIDs and compare
+ * against those.
+ *
+ * These values should not be used outside of a single process; they are not
+ * stable identifiers. */
+
+
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
EOF
foreach (sort { $a <=> $b } keys %ordern)
{
$Cname=$ordern{$_};
- print OUT "#define SN_",$Cname,"\t\t\"",$sn{$Cname},"\"\n" if $sn{$Cname} ne "";
- print OUT "#define LN_",$Cname,"\t\t\"",$ln{$Cname},"\"\n" if $ln{$Cname} ne "";
- print OUT "#define NID_",$Cname,"\t\t",$nid{$Cname},"\n" if $nid{$Cname} ne "";
- print OUT "#define OBJ_",$Cname,"\t\t",$obj{$Cname},"\n" if $obj{$Cname} ne "";
+ print OUT "#define SN_",$Cname," \"",$sn{$Cname},"\"\n" if $sn{$Cname} ne "";
+ print OUT "#define LN_",$Cname," \"",$ln{$Cname},"\"\n" if $ln{$Cname} ne "";
+ print OUT "#define NID_",$Cname," ",$nid{$Cname},"\n" if $nid{$Cname} ne "";
+ print OUT "#define OBJ_",$Cname," ",$obj{$Cname},"\n" if $obj{$Cname} ne "";
print OUT "\n";
}
+print OUT "\n#endif /* OPENSSL_HEADER_NID_H */\n";
+
close OUT;
sub process_oid
diff --git a/crypto/obj/objects.txt b/crypto/obj/objects.txt
index 93cf53aa..75f2cbf9 100644
--- a/crypto/obj/objects.txt
+++ b/crypto/obj/objects.txt
@@ -1332,4 +1332,7 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
: dh-cofactor-kdf
# NID for X25519 (no corresponding OID).
- : X25519 : x25519
+ : X25519
+
+# NID for CECPQ1 (no corresponding OID)
+ : cecpq1
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index deaf26ab..e53abf86 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -71,13 +71,10 @@
#include <openssl/rand.h>
#include <openssl/x509.h>
-#include "../evp/internal.h"
-
#define MIN_LENGTH 4
static int load_iv(char **fromp, unsigned char *to, int num);
static int check_pem(const char *nm, const char *name);
-int pem_check_suffix(const char *pem_str, const char *suffix);
void PEM_proc_type(char *buf, int type)
{
@@ -144,23 +141,11 @@ static int check_pem(const char *nm, const char *name)
/* Make PEM_STRING_EVP_PKEY match any private key */
if (!strcmp(name, PEM_STRING_EVP_PKEY)) {
- int slen;
- const EVP_PKEY_ASN1_METHOD *ameth;
- if (!strcmp(nm, PEM_STRING_PKCS8))
- return 1;
- if (!strcmp(nm, PEM_STRING_PKCS8INF))
- return 1;
- slen = pem_check_suffix(nm, "PRIVATE KEY");
- if (slen > 0) {
- /*
- * NB: ENGINE implementations wont contain a deprecated old
- * private key decode function so don't look for them.
- */
- ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
- if (ameth && ameth->old_priv_decode)
- return 1;
- }
- return 0;
+ return !strcmp(nm, PEM_STRING_PKCS8) ||
+ !strcmp(nm, PEM_STRING_PKCS8INF) ||
+ !strcmp(nm, PEM_STRING_RSA) ||
+ !strcmp(nm, PEM_STRING_EC) ||
+ !strcmp(nm, PEM_STRING_DSA);
}
/* Permit older strings */
@@ -277,7 +262,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
if (enc != NULL) {
objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
- if (objstr == NULL) {
+ if (objstr == NULL || EVP_CIPHER_iv_length(enc) == 0) {
OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
goto err;
}
@@ -779,28 +764,6 @@ int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
return (0);
}
-/*
- * Check pem string and return prefix length. If for example the pem_str ==
- * "RSA PRIVATE KEY" and suffix = "PRIVATE KEY" the return value is 3 for the
- * string "RSA".
- */
-
-int pem_check_suffix(const char *pem_str, const char *suffix)
-{
- int pem_len = strlen(pem_str);
- int suffix_len = strlen(suffix);
- const char *p;
- if (suffix_len + 1 >= pem_len)
- return 0;
- p = pem_str + pem_len - suffix_len;
- if (strcmp(p, suffix))
- return 0;
- p--;
- if (*p != ' ')
- return 0;
- return p - pem_str;
-}
-
int PEM_def_callback(char *buf, int size, int rwflag, void *userdata)
{
if (!buf || !userdata) {
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index 4cac7c28..058c0311 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -69,10 +69,6 @@
#include <openssl/rand.h>
#include <openssl/x509.h>
-#include "../evp/internal.h"
-
-int pem_check_suffix(const char *pem_str, const char *suffix);
-
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
void *u)
{
@@ -80,7 +76,6 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
const unsigned char *p = NULL;
unsigned char *data = NULL;
long len;
- int slen;
EVP_PKEY *ret = NULL;
if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
@@ -128,12 +123,15 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
*x = ret;
}
PKCS8_PRIV_KEY_INFO_free(p8inf);
- } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) {
- const EVP_PKEY_ASN1_METHOD *ameth;
- ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
- if (!ameth || !ameth->old_priv_decode)
- goto p8err;
- ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len);
+ } else if (strcmp(nm, PEM_STRING_RSA) == 0) {
+ /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the
+ * standalone format. This and the cases below probably should not
+ * accept PKCS#8. */
+ ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len);
+ } else if (strcmp(nm, PEM_STRING_EC) == 0) {
+ ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len);
+ } else if (strcmp(nm, PEM_STRING_DSA) == 0) {
+ ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len);
}
p8err:
if (ret == NULL)
@@ -150,14 +148,7 @@ int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- char pem_str[80];
- if (!x->ameth || x->ameth->priv_encode)
- return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
- (char *)kstr, klen, cb, u);
-
- BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
- pem_str, bp, x, enc, kstr, klen, cb, u);
+ return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u);
}
#ifndef OPENSSL_NO_FP_API
diff --git a/crypto/perlasm/x86_64-xlate.pl b/crypto/perlasm/x86_64-xlate.pl
index 3ebb0184..4965985d 100755
--- a/crypto/perlasm/x86_64-xlate.pl
+++ b/crypto/perlasm/x86_64-xlate.pl
@@ -190,14 +190,17 @@ my %globals;
sub out {
my $self = shift;
+ $self->{value} =~ s/\b(0b[0-1]+)/oct($1)/eig;
if ($gas) {
# Solaris /usr/ccs/bin/as can't handle multiplications
# in $self->{value}
- $self->{value} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
- $self->{value} =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg;
+ my $value = $self->{value};
+ $value =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
+ if ($value =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg) {
+ $self->{value} = $value;
+ }
sprintf "\$%s",$self->{value};
} else {
- $self->{value} =~ s/(0b[0-1]+)/oct($1)/eig;
$self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm);
sprintf "%s",$self->{value};
}
diff --git a/crypto/perlasm/x86gas.pl b/crypto/perlasm/x86gas.pl
index 99d7c1bd..55d09d8b 100644
--- a/crypto/perlasm/x86gas.pl
+++ b/crypto/perlasm/x86gas.pl
@@ -17,7 +17,7 @@ sub opsize()
{ my $reg=shift;
if ($reg =~ m/^%e/o) { "l"; }
elsif ($reg =~ m/^%[a-d][hl]$/o) { "b"; }
- elsif ($reg =~ m/^%[xm]/o) { undef; }
+ elsif ($reg =~ m/^%[yxm]/o) { undef; }
else { "w"; }
}
diff --git a/crypto/pkcs8/CMakeLists.txt b/crypto/pkcs8/CMakeLists.txt
index 329e02b2..8f674f91 100644
--- a/crypto/pkcs8/CMakeLists.txt
+++ b/crypto/pkcs8/CMakeLists.txt
@@ -1,7 +1,7 @@
include_directories(../../include)
add_library(
- pkcs8
+ pkcs8_lib
OBJECT
diff --git a/crypto/pkcs8/p5_pbe.c b/crypto/pkcs8/p5_pbe.c
index 653cabf3..8e56d41b 100644
--- a/crypto/pkcs8/p5_pbe.c
+++ b/crypto/pkcs8/p5_pbe.c
@@ -57,6 +57,7 @@
#include <openssl/asn1t.h>
#include <openssl/err.h>
+#include <openssl/obj.h>
#include <openssl/pkcs8.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
diff --git a/crypto/pkcs8/p5_pbev2.c b/crypto/pkcs8/p5_pbev2.c
index fec0d86d..3799b39b 100644
--- a/crypto/pkcs8/p5_pbev2.c
+++ b/crypto/pkcs8/p5_pbev2.c
@@ -61,6 +61,7 @@
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+#include <openssl/obj.h>
#include <openssl/pkcs8.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
diff --git a/crypto/pkcs8/pkcs12_test.cc b/crypto/pkcs8/pkcs12_test.cc
index f1a1fcd2..17bcd273 100644
--- a/crypto/pkcs8/pkcs12_test.cc
+++ b/crypto/pkcs8/pkcs12_test.cc
@@ -708,7 +708,7 @@ static bool Test(const char *name, const uint8_t *der, size_t der_len) {
}
static bool TestCompat(const uint8_t *der, size_t der_len) {
- ScopedBIO bio(BIO_new_mem_buf((void*) der, der_len));
+ ScopedBIO bio(BIO_new_mem_buf(der, der_len));
if (!bio) {
return false;
}
diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c
index 85af2063..0ca0f2ec 100644
--- a/crypto/pkcs8/pkcs8.c
+++ b/crypto/pkcs8/pkcs8.c
@@ -60,7 +60,6 @@
#include <string.h>
#include <openssl/asn1.h>
-#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/bytestring.h>
#include <openssl/cipher.h>
@@ -68,6 +67,7 @@
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/mem.h>
+#include <openssl/obj.h>
#include <openssl/x509.h>
#include "internal.h"
@@ -112,112 +112,122 @@ static int ascii_to_ucs2(const char *ascii, size_t ascii_len,
static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len,
const uint8_t *salt, size_t salt_len,
- int id, int iterations,
+ uint8_t id, int iterations,
size_t out_len, uint8_t *out,
- const EVP_MD *md_type) {
- uint8_t *B, *D, *I, *p, *Ai;
- int Slen, Plen, Ilen, Ijlen;
- int i, j, v;
- size_t u;
- int ret = 0;
- BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */
- EVP_MD_CTX ctx;
+ const EVP_MD *md) {
+ /* See https://tools.ietf.org/html/rfc7292#appendix-B. Quoted parts of the
+ * specification have errata applied and other typos fixed. */
- EVP_MD_CTX_init(&ctx);
- v = EVP_MD_block_size(md_type);
- u = EVP_MD_size(md_type);
- D = OPENSSL_malloc(v);
- Ai = OPENSSL_malloc(u);
- B = OPENSSL_malloc(v + 1);
- Slen = v * ((salt_len + v - 1) / v);
- if (pass_raw_len) {
- Plen = v * ((pass_raw_len + v - 1) / v);
- } else {
- Plen = 0;
+ if (iterations < 1) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
+ return 0;
}
- Ilen = Slen + Plen;
- I = OPENSSL_malloc(Ilen);
- Ij = BN_new();
- Bpl1 = BN_new();
- if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
- goto err;
+
+ /* In the spec, |block_size| is called "v", but measured in bits. */
+ size_t block_size = EVP_MD_block_size(md);
+
+ /* 1. Construct a string, D (the "diversifier"), by concatenating v/8 copies
+ * of ID. */
+ uint8_t D[EVP_MAX_MD_BLOCK_SIZE];
+ memset(D, id, block_size);
+
+ /* 2. Concatenate copies of the salt together to create a string S of length
+ * v(ceiling(s/v)) bits (the final copy of the salt may be truncated to
+ * create S). Note that if the salt is the empty string, then so is S.
+ *
+ * 3. Concatenate copies of the password together to create a string P of
+ * length v(ceiling(p/v)) bits (the final copy of the password may be
+ * truncated to create P). Note that if the password is the empty string,
+ * then so is P.
+ *
+ * 4. Set I=S||P to be the concatenation of S and P. */
+ if (salt_len + block_size - 1 < salt_len ||
+ pass_raw_len + block_size - 1 < pass_raw_len) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
+ return 0;
}
- for (i = 0; i < v; i++) {
- D[i] = id;
+ size_t S_len = block_size * ((salt_len + block_size - 1) / block_size);
+ size_t P_len = block_size * ((pass_raw_len + block_size - 1) / block_size);
+ size_t I_len = S_len + P_len;
+ if (I_len < S_len) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
+ return 0;
}
- p = I;
- for (i = 0; i < Slen; i++) {
- *p++ = salt[i % salt_len];
+
+ uint8_t *I = OPENSSL_malloc(I_len);
+ if (I_len != 0 && I == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+ return 0;
}
- for (i = 0; i < Plen; i++) {
- *p++ = pass_raw[i % pass_raw_len];
+
+ size_t i;
+ for (i = 0; i < S_len; i++) {
+ I[i] = salt[i % salt_len];
}
- for (;;) {
- if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
- !EVP_DigestUpdate(&ctx, D, v) ||
- !EVP_DigestUpdate(&ctx, I, Ilen) ||
- !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ for (i = 0; i < P_len; i++) {
+ I[i + S_len] = pass_raw[i % pass_raw_len];
+ }
+
+ int ret = 0;
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+
+ while (out_len != 0) {
+ /* A. Set A_i=H^r(D||I). (i.e., the r-th hash of D||I,
+ * H(H(H(... H(D||I)))) */
+ uint8_t A[EVP_MAX_MD_SIZE];
+ unsigned A_len;
+ if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
+ !EVP_DigestUpdate(&ctx, D, block_size) ||
+ !EVP_DigestUpdate(&ctx, I, I_len) ||
+ !EVP_DigestFinal_ex(&ctx, A, &A_len)) {
goto err;
}
- for (j = 1; j < iterations; j++) {
- if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
- !EVP_DigestUpdate(&ctx, Ai, u) ||
- !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ int iter;
+ for (iter = 1; iter < iterations; iter++) {
+ if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
+ !EVP_DigestUpdate(&ctx, A, A_len) ||
+ !EVP_DigestFinal_ex(&ctx, A, &A_len)) {
goto err;
}
}
- memcpy(out, Ai, out_len < u ? out_len : u);
- if (u >= out_len) {
- ret = 1;
- goto end;
- }
- out_len -= u;
- out += u;
- for (j = 0; j < v; j++) {
- B[j] = Ai[j % u];
+
+ size_t todo = out_len < A_len ? out_len : A_len;
+ memcpy(out, A, todo);
+ out += todo;
+ out_len -= todo;
+ if (out_len == 0) {
+ break;
}
- /* Work out B + 1 first then can use B as tmp space */
- if (!BN_bin2bn(B, v, Bpl1) ||
- !BN_add_word(Bpl1, 1)) {
- goto err;
+
+ /* B. Concatenate copies of A_i to create a string B of length v bits (the
+ * final copy of A_i may be truncated to create B). */
+ uint8_t B[EVP_MAX_MD_BLOCK_SIZE];
+ for (i = 0; i < block_size; i++) {
+ B[i] = A[i % A_len];
}
- for (j = 0; j < Ilen; j += v) {
- if (!BN_bin2bn(I + j, v, Ij) ||
- !BN_add(Ij, Ij, Bpl1) ||
- !BN_bn2bin(Ij, B)) {
- goto err;
- }
- Ijlen = BN_num_bytes(Ij);
- /* If more than 2^(v*8) - 1 cut off MSB */
- if (Ijlen > v) {
- if (!BN_bn2bin(Ij, B)) {
- goto err;
- }
- memcpy(I + j, B + 1, v);
- /* If less than v bytes pad with zeroes */
- } else if (Ijlen < v) {
- memset(I + j, 0, v - Ijlen);
- if (!BN_bn2bin(Ij, I + j + v - Ijlen)) {
- goto err;
- }
- } else if (!BN_bn2bin(Ij, I + j)) {
- goto err;
+
+ /* C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit blocks,
+ * where k=ceiling(s/v)+ceiling(p/v), modify I by setting I_j=(I_j+B+1) mod
+ * 2^v for each j. */
+ assert(I_len % block_size == 0);
+ for (i = 0; i < I_len; i += block_size) {
+ unsigned carry = 1;
+ size_t j;
+ for (j = block_size - 1; j < block_size; j--) {
+ carry += I[i + j] + B[j];
+ I[i + j] = (uint8_t)carry;
+ carry >>= 8;
}
}
}
-err:
- OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+ ret = 1;
-end:
- OPENSSL_free(Ai);
- OPENSSL_free(B);
- OPENSSL_free(D);
+err:
+ OPENSSL_cleanse(I, I_len);
OPENSSL_free(I);
- BN_free(Ij);
- BN_free(Bpl1);
EVP_MD_CTX_cleanup(&ctx);
-
return ret;
}
diff --git a/crypto/poly1305/asm/poly1305-armv4.pl b/crypto/poly1305/asm/poly1305-armv4.pl
new file mode 100755
index 00000000..9b765cec
--- /dev/null
+++ b/crypto/poly1305/asm/poly1305-armv4.pl
@@ -0,0 +1,1216 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# IALU(*)/gcc-4.4 NEON
+#
+# ARM11xx(ARMv6) 7.78/+100% -
+# Cortex-A5 6.30/+130% 2.96
+# Cortex-A8 6.25/+115% 2.36
+# Cortex-A9 5.10/+95% 2.55
+# Cortex-A15 3.79/+85% 1.25(**)
+# Snapdragon S4 5.70/+100% 1.48(**)
+#
+# (*) this is for -march=armv6, i.e. with bunch of ldrb loading data;
+# (**) these are trade-off results, they can be improved by ~8% but at
+# the cost of 15/12% regression on Cortex-A5/A7, it's even possible
+# to improve Cortex-A9 result, but then A5/A7 loose more than 20%;
+
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
+
+($ctx,$inp,$len,$padbit)=map("r$_",(0..3));
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+#if defined(__thumb2__)
+.syntax unified
+.thumb
+#else
+.code 32
+#endif
+
+.globl poly1305_emit
+.globl poly1305_blocks
+.globl poly1305_init
+.type poly1305_init,%function
+.align 5
+poly1305_init:
+.Lpoly1305_init:
+ stmdb sp!,{r4-r11}
+
+ eor r3,r3,r3
+ cmp $inp,#0
+ str r3,[$ctx,#0] @ zero hash value
+ str r3,[$ctx,#4]
+ str r3,[$ctx,#8]
+ str r3,[$ctx,#12]
+ str r3,[$ctx,#16]
+ str r3,[$ctx,#36] @ is_base2_26
+ add $ctx,$ctx,#20
+
+#ifdef __thumb2__
+ it eq
+#endif
+ moveq r0,#0
+ beq .Lno_key
+
+#if __ARM_MAX_ARCH__>=7
+ adr r11,.Lpoly1305_init
+ ldr r12,.LOPENSSL_armcap
+#endif
+ ldrb r4,[$inp,#0]
+ mov r10,#0x0fffffff
+ ldrb r5,[$inp,#1]
+ and r3,r10,#-4 @ 0x0ffffffc
+ ldrb r6,[$inp,#2]
+ ldrb r7,[$inp,#3]
+ orr r4,r4,r5,lsl#8
+ ldrb r5,[$inp,#4]
+ orr r4,r4,r6,lsl#16
+ ldrb r6,[$inp,#5]
+ orr r4,r4,r7,lsl#24
+ ldrb r7,[$inp,#6]
+ and r4,r4,r10
+
+#if __ARM_MAX_ARCH__>=7
+ ldr r12,[r11,r12] @ OPENSSL_armcap_P
+# ifdef __APPLE__
+ ldr r12,[r12]
+# endif
+#endif
+ ldrb r8,[$inp,#7]
+ orr r5,r5,r6,lsl#8
+ ldrb r6,[$inp,#8]
+ orr r5,r5,r7,lsl#16
+ ldrb r7,[$inp,#9]
+ orr r5,r5,r8,lsl#24
+ ldrb r8,[$inp,#10]
+ and r5,r5,r3
+
+#if __ARM_MAX_ARCH__>=7
+ tst r12,#ARMV7_NEON @ check for NEON
+# ifdef __APPLE__
+ adr r9,poly1305_blocks_neon
+ adr r11,poly1305_blocks
+# ifdef __thumb2__
+ it ne
+# endif
+ movne r11,r9
+ adr r12,poly1305_emit
+ adr r10,poly1305_emit_neon
+# ifdef __thumb2__
+ it ne
+# endif
+ movne r12,r10
+# else
+# ifdef __thumb2__
+ itete eq
+# endif
+ addeq r12,r11,#(poly1305_emit-.Lpoly1305_init)
+ addne r12,r11,#(poly1305_emit_neon-.Lpoly1305_init)
+ addeq r11,r11,#(poly1305_blocks-.Lpoly1305_init)
+ addne r11,r11,#(poly1305_blocks_neon-.Lpoly1305_init)
+# endif
+# ifdef __thumb2__
+ orr r12,r12,#1 @ thumb-ify address
+ orr r11,r11,#1
+# endif
+#endif
+ ldrb r9,[$inp,#11]
+ orr r6,r6,r7,lsl#8
+ ldrb r7,[$inp,#12]
+ orr r6,r6,r8,lsl#16
+ ldrb r8,[$inp,#13]
+ orr r6,r6,r9,lsl#24
+ ldrb r9,[$inp,#14]
+ and r6,r6,r3
+
+ ldrb r10,[$inp,#15]
+ orr r7,r7,r8,lsl#8
+ str r4,[$ctx,#0]
+ orr r7,r7,r9,lsl#16
+ str r5,[$ctx,#4]
+ orr r7,r7,r10,lsl#24
+ str r6,[$ctx,#8]
+ and r7,r7,r3
+ str r7,[$ctx,#12]
+#if __ARM_MAX_ARCH__>=7
+ stmia r2,{r11,r12} @ fill functions table
+ mov r0,#1
+#else
+ mov r0,#0
+#endif
+.Lno_key:
+ ldmia sp!,{r4-r11}
+#if __ARM_ARCH__>=5
+ ret @ bx lr
+#else
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size poly1305_init,.-poly1305_init
+___
+{
+my ($h0,$h1,$h2,$h3,$h4,$r0,$r1,$r2,$r3)=map("r$_",(4..12));
+my ($s1,$s2,$s3)=($r1,$r2,$r3);
+
+$code.=<<___;
+.type poly1305_blocks,%function
+.align 5
+poly1305_blocks:
+ stmdb sp!,{r3-r11,lr}
+
+ ands $len,$len,#-16
+ beq .Lno_data
+
+ cmp $padbit,#0
+ add $len,$len,$inp @ end pointer
+ sub sp,sp,#32
+
+ ldmia $ctx,{$h0-$r3} @ load context
+
+ str $ctx,[sp,#12] @ offload stuff
+ mov lr,$inp
+ str $len,[sp,#16]
+ str $r1,[sp,#20]
+ str $r2,[sp,#24]
+ str $r3,[sp,#28]
+ b .Loop
+
+.Loop:
+#if __ARM_ARCH__<7
+ ldrb r0,[lr],#16 @ load input
+# ifdef __thumb2__
+ it hi
+# endif
+ addhi $h4,$h4,#1 @ 1<<128
+ ldrb r1,[lr,#-15]
+ ldrb r2,[lr,#-14]
+ ldrb r3,[lr,#-13]
+ orr r1,r0,r1,lsl#8
+ ldrb r0,[lr,#-12]
+ orr r2,r1,r2,lsl#16
+ ldrb r1,[lr,#-11]
+ orr r3,r2,r3,lsl#24
+ ldrb r2,[lr,#-10]
+ adds $h0,$h0,r3 @ accumulate input
+
+ ldrb r3,[lr,#-9]
+ orr r1,r0,r1,lsl#8
+ ldrb r0,[lr,#-8]
+ orr r2,r1,r2,lsl#16
+ ldrb r1,[lr,#-7]
+ orr r3,r2,r3,lsl#24
+ ldrb r2,[lr,#-6]
+ adcs $h1,$h1,r3
+
+ ldrb r3,[lr,#-5]
+ orr r1,r0,r1,lsl#8
+ ldrb r0,[lr,#-4]
+ orr r2,r1,r2,lsl#16
+ ldrb r1,[lr,#-3]
+ orr r3,r2,r3,lsl#24
+ ldrb r2,[lr,#-2]
+ adcs $h2,$h2,r3
+
+ ldrb r3,[lr,#-1]
+ orr r1,r0,r1,lsl#8
+ str lr,[sp,#8] @ offload input pointer
+ orr r2,r1,r2,lsl#16
+ add $s1,$r1,$r1,lsr#2
+ orr r3,r2,r3,lsl#24
+#else
+ ldr r0,[lr],#16 @ load input
+# ifdef __thumb2__
+ it hi
+# endif
+ addhi $h4,$h4,#1 @ padbit
+ ldr r1,[lr,#-12]
+ ldr r2,[lr,#-8]
+ ldr r3,[lr,#-4]
+# ifdef __ARMEB__
+ rev r0,r0
+ rev r1,r1
+ rev r2,r2
+ rev r3,r3
+# endif
+ adds $h0,$h0,r0 @ accumulate input
+ str lr,[sp,#8] @ offload input pointer
+ adcs $h1,$h1,r1
+ add $s1,$r1,$r1,lsr#2
+ adcs $h2,$h2,r2
+#endif
+ add $s2,$r2,$r2,lsr#2
+ adcs $h3,$h3,r3
+ add $s3,$r3,$r3,lsr#2
+
+ umull r2,r3,$h1,$r0
+ adc $h4,$h4,#0
+ umull r0,r1,$h0,$r0
+ umlal r2,r3,$h4,$s1
+ umlal r0,r1,$h3,$s1
+ ldr $r1,[sp,#20] @ reload $r1
+ umlal r2,r3,$h2,$s3
+ umlal r0,r1,$h1,$s3
+ umlal r2,r3,$h3,$s2
+ umlal r0,r1,$h2,$s2
+ umlal r2,r3,$h0,$r1
+ str r0,[sp,#0] @ future $h0
+ mul r0,$s2,$h4
+ ldr $r2,[sp,#24] @ reload $r2
+ adds r2,r2,r1 @ d1+=d0>>32
+ eor r1,r1,r1
+ adc lr,r3,#0 @ future $h2
+ str r2,[sp,#4] @ future $h1
+
+ mul r2,$s3,$h4
+ eor r3,r3,r3
+ umlal r0,r1,$h3,$s3
+ ldr $r3,[sp,#28] @ reload $r3
+ umlal r2,r3,$h3,$r0
+ umlal r0,r1,$h2,$r0
+ umlal r2,r3,$h2,$r1
+ umlal r0,r1,$h1,$r1
+ umlal r2,r3,$h1,$r2
+ umlal r0,r1,$h0,$r2
+ umlal r2,r3,$h0,$r3
+ ldr $h0,[sp,#0]
+ mul $h4,$r0,$h4
+ ldr $h1,[sp,#4]
+
+ adds $h2,lr,r0 @ d2+=d1>>32
+ ldr lr,[sp,#8] @ reload input pointer
+ adc r1,r1,#0
+ adds $h3,r2,r1 @ d3+=d2>>32
+ ldr r0,[sp,#16] @ reload end pointer
+ adc r3,r3,#0
+ add $h4,$h4,r3 @ h4+=d3>>32
+
+ and r1,$h4,#-4
+ and $h4,$h4,#3
+ add r1,r1,r1,lsr#2 @ *=5
+ adds $h0,$h0,r1
+ adcs $h1,$h1,#0
+ adcs $h2,$h2,#0
+ adc $h3,$h3,#0
+
+ cmp r0,lr @ done yet?
+ bhi .Loop
+
+ ldr $ctx,[sp,#12]
+ add sp,sp,#32
+ stmia $ctx,{$h0-$h4} @ store the result
+
+.Lno_data:
+#if __ARM_ARCH__>=5
+ ldmia sp!,{r3-r11,pc}
+#else
+ ldmia sp!,{r3-r11,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size poly1305_blocks,.-poly1305_blocks
+___
+}
+{
+my ($ctx,$mac,$nonce)=map("r$_",(0..2));
+my ($h0,$h1,$h2,$h3,$h4,$g0,$g1,$g2,$g3)=map("r$_",(3..11));
+my $g4=$h4;
+
+$code.=<<___;
+.type poly1305_emit,%function
+.align 5
+poly1305_emit:
+ stmdb sp!,{r4-r11}
+.Lpoly1305_emit_enter:
+
+ ldmia $ctx,{$h0-$h4}
+ adds $g0,$h0,#5 @ compare to modulus
+ adcs $g1,$h1,#0
+ adcs $g2,$h2,#0
+ adcs $g3,$h3,#0
+ adc $g4,$h4,#0
+ tst $g4,#4 @ did it carry/borrow?
+
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h0,$g0
+ ldr $g0,[$nonce,#0]
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h1,$g1
+ ldr $g1,[$nonce,#4]
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h2,$g2
+ ldr $g2,[$nonce,#8]
+#ifdef __thumb2__
+ it ne
+#endif
+ movne $h3,$g3
+ ldr $g3,[$nonce,#12]
+
+ adds $h0,$h0,$g0
+ adcs $h1,$h1,$g1
+ adcs $h2,$h2,$g2
+ adc $h3,$h3,$g3
+
+#if __ARM_ARCH__>=7
+# ifdef __ARMEB__
+ rev $h0,$h0
+ rev $h1,$h1
+ rev $h2,$h2
+ rev $h3,$h3
+# endif
+ str $h0,[$mac,#0]
+ str $h1,[$mac,#4]
+ str $h2,[$mac,#8]
+ str $h3,[$mac,#12]
+#else
+ strb $h0,[$mac,#0]
+ mov $h0,$h0,lsr#8
+ strb $h1,[$mac,#4]
+ mov $h1,$h1,lsr#8
+ strb $h2,[$mac,#8]
+ mov $h2,$h2,lsr#8
+ strb $h3,[$mac,#12]
+ mov $h3,$h3,lsr#8
+
+ strb $h0,[$mac,#1]
+ mov $h0,$h0,lsr#8
+ strb $h1,[$mac,#5]
+ mov $h1,$h1,lsr#8
+ strb $h2,[$mac,#9]
+ mov $h2,$h2,lsr#8
+ strb $h3,[$mac,#13]
+ mov $h3,$h3,lsr#8
+
+ strb $h0,[$mac,#2]
+ mov $h0,$h0,lsr#8
+ strb $h1,[$mac,#6]
+ mov $h1,$h1,lsr#8
+ strb $h2,[$mac,#10]
+ mov $h2,$h2,lsr#8
+ strb $h3,[$mac,#14]
+ mov $h3,$h3,lsr#8
+
+ strb $h0,[$mac,#3]
+ strb $h1,[$mac,#7]
+ strb $h2,[$mac,#11]
+ strb $h3,[$mac,#15]
+#endif
+ ldmia sp!,{r4-r11}
+#if __ARM_ARCH__>=5
+ ret @ bx lr
+#else
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size poly1305_emit,.-poly1305_emit
+___
+{
+my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("d$_",(0..9));
+my ($D0,$D1,$D2,$D3,$D4, $H0,$H1,$H2,$H3,$H4) = map("q$_",(5..14));
+my ($T0,$T1,$MASK) = map("q$_",(15,4,0));
+
+my ($in2,$zeros,$tbl0,$tbl1) = map("r$_",(4..7));
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.fpu neon
+
+.type poly1305_init_neon,%function
+.align 5
+poly1305_init_neon:
+ ldr r4,[$ctx,#20] @ load key base 2^32
+ ldr r5,[$ctx,#24]
+ ldr r6,[$ctx,#28]
+ ldr r7,[$ctx,#32]
+
+ and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26
+ mov r3,r4,lsr#26
+ mov r4,r5,lsr#20
+ orr r3,r3,r5,lsl#6
+ mov r5,r6,lsr#14
+ orr r4,r4,r6,lsl#12
+ mov r6,r7,lsr#8
+ orr r5,r5,r7,lsl#18
+ and r3,r3,#0x03ffffff
+ and r4,r4,#0x03ffffff
+ and r5,r5,#0x03ffffff
+
+ vdup.32 $R0,r2 @ r^1 in both lanes
+ add r2,r3,r3,lsl#2 @ *5
+ vdup.32 $R1,r3
+ add r3,r4,r4,lsl#2
+ vdup.32 $S1,r2
+ vdup.32 $R2,r4
+ add r4,r5,r5,lsl#2
+ vdup.32 $S2,r3
+ vdup.32 $R3,r5
+ add r5,r6,r6,lsl#2
+ vdup.32 $S3,r4
+ vdup.32 $R4,r6
+ vdup.32 $S4,r5
+
+ mov $zeros,#2 @ counter
+
+.Lsquare_neon:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+ @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+
+ vmull.u32 $D0,$R0,${R0}[1]
+ vmull.u32 $D1,$R1,${R0}[1]
+ vmull.u32 $D2,$R2,${R0}[1]
+ vmull.u32 $D3,$R3,${R0}[1]
+ vmull.u32 $D4,$R4,${R0}[1]
+
+ vmlal.u32 $D0,$R4,${S1}[1]
+ vmlal.u32 $D1,$R0,${R1}[1]
+ vmlal.u32 $D2,$R1,${R1}[1]
+ vmlal.u32 $D3,$R2,${R1}[1]
+ vmlal.u32 $D4,$R3,${R1}[1]
+
+ vmlal.u32 $D0,$R3,${S2}[1]
+ vmlal.u32 $D1,$R4,${S2}[1]
+ vmlal.u32 $D3,$R1,${R2}[1]
+ vmlal.u32 $D2,$R0,${R2}[1]
+ vmlal.u32 $D4,$R2,${R2}[1]
+
+ vmlal.u32 $D0,$R2,${S3}[1]
+ vmlal.u32 $D3,$R0,${R3}[1]
+ vmlal.u32 $D1,$R3,${S3}[1]
+ vmlal.u32 $D2,$R4,${S3}[1]
+ vmlal.u32 $D4,$R1,${R3}[1]
+
+ vmlal.u32 $D3,$R4,${S4}[1]
+ vmlal.u32 $D0,$R1,${S4}[1]
+ vmlal.u32 $D1,$R2,${S4}[1]
+ vmlal.u32 $D2,$R3,${S4}[1]
+ vmlal.u32 $D4,$R0,${R4}[1]
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ @ and P. Schwabe
+
+ vshr.u64 $T0,$D3,#26
+ vmovn.i64 $D3#lo,$D3
+ vshr.u64 $T1,$D0,#26
+ vmovn.i64 $D0#lo,$D0
+ vadd.i64 $D4,$D4,$T0 @ h3 -> h4
+ vbic.i32 $D3#lo,#0xfc000000 @ &=0x03ffffff
+ vadd.i64 $D1,$D1,$T1 @ h0 -> h1
+ vbic.i32 $D0#lo,#0xfc000000
+
+ vshrn.u64 $T0#lo,$D4,#26
+ vmovn.i64 $D4#lo,$D4
+ vshr.u64 $T1,$D1,#26
+ vmovn.i64 $D1#lo,$D1
+ vadd.i64 $D2,$D2,$T1 @ h1 -> h2
+ vbic.i32 $D4#lo,#0xfc000000
+ vbic.i32 $D1#lo,#0xfc000000
+
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo
+ vshl.u32 $T0#lo,$T0#lo,#2
+ vshrn.u64 $T1#lo,$D2,#26
+ vmovn.i64 $D2#lo,$D2
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0
+ vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3
+ vbic.i32 $D2#lo,#0xfc000000
+
+ vshr.u32 $T0#lo,$D0#lo,#26
+ vbic.i32 $D0#lo,#0xfc000000
+ vshr.u32 $T1#lo,$D3#lo,#26
+ vbic.i32 $D3#lo,#0xfc000000
+ vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1
+ vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4
+
+ subs $zeros,$zeros,#1
+ beq .Lsquare_break_neon
+
+ add $tbl0,$ctx,#(48+0*9*4)
+ add $tbl1,$ctx,#(48+1*9*4)
+
+ vtrn.32 $R0,$D0#lo @ r^2:r^1
+ vtrn.32 $R2,$D2#lo
+ vtrn.32 $R3,$D3#lo
+ vtrn.32 $R1,$D1#lo
+ vtrn.32 $R4,$D4#lo
+
+ vshl.u32 $S2,$R2,#2 @ *5
+ vshl.u32 $S3,$R3,#2
+ vshl.u32 $S1,$R1,#2
+ vshl.u32 $S4,$R4,#2
+ vadd.i32 $S2,$S2,$R2
+ vadd.i32 $S1,$S1,$R1
+ vadd.i32 $S3,$S3,$R3
+ vadd.i32 $S4,$S4,$R4
+
+ vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]!
+ vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]!
+ vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vst1.32 {${S4}[0]},[$tbl0,:32]
+ vst1.32 {${S4}[1]},[$tbl1,:32]
+
+ b .Lsquare_neon
+
+.align 4
+.Lsquare_break_neon:
+ add $tbl0,$ctx,#(48+2*4*9)
+ add $tbl1,$ctx,#(48+3*4*9)
+
+ vmov $R0,$D0#lo @ r^4:r^3
+ vshl.u32 $S1,$D1#lo,#2 @ *5
+ vmov $R1,$D1#lo
+ vshl.u32 $S2,$D2#lo,#2
+ vmov $R2,$D2#lo
+ vshl.u32 $S3,$D3#lo,#2
+ vmov $R3,$D3#lo
+ vshl.u32 $S4,$D4#lo,#2
+ vmov $R4,$D4#lo
+ vadd.i32 $S1,$S1,$D1#lo
+ vadd.i32 $S2,$S2,$D2#lo
+ vadd.i32 $S3,$S3,$D3#lo
+ vadd.i32 $S4,$S4,$D4#lo
+
+ vst4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]!
+ vst4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]!
+ vst4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vst4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vst1.32 {${S4}[0]},[$tbl0]
+ vst1.32 {${S4}[1]},[$tbl1]
+
+ ret @ bx lr
+.size poly1305_init_neon,.-poly1305_init_neon
+
+.type poly1305_blocks_neon,%function
+.align 5
+poly1305_blocks_neon:
+ ldr ip,[$ctx,#36] @ is_base2_26
+ ands $len,$len,#-16
+ beq .Lno_data_neon
+
+ cmp $len,#64
+ bhs .Lenter_neon
+ tst ip,ip @ is_base2_26?
+ beq poly1305_blocks
+
+.Lenter_neon:
+ stmdb sp!,{r4-r7}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+
+ tst ip,ip @ is_base2_26?
+ bne .Lbase2_26_neon
+
+ stmdb sp!,{r1-r3,lr}
+ bl poly1305_init_neon
+
+ ldr r4,[$ctx,#0] @ load hash value base 2^32
+ ldr r5,[$ctx,#4]
+ ldr r6,[$ctx,#8]
+ ldr r7,[$ctx,#12]
+ ldr ip,[$ctx,#16]
+
+ and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26
+ mov r3,r4,lsr#26
+ veor $D0#lo,$D0#lo,$D0#lo
+ mov r4,r5,lsr#20
+ orr r3,r3,r5,lsl#6
+ veor $D1#lo,$D1#lo,$D1#lo
+ mov r5,r6,lsr#14
+ orr r4,r4,r6,lsl#12
+ veor $D2#lo,$D2#lo,$D2#lo
+ mov r6,r7,lsr#8
+ orr r5,r5,r7,lsl#18
+ veor $D3#lo,$D3#lo,$D3#lo
+ and r3,r3,#0x03ffffff
+ orr r6,r6,ip,lsl#24
+ veor $D4#lo,$D4#lo,$D4#lo
+ and r4,r4,#0x03ffffff
+ mov r1,#1
+ and r5,r5,#0x03ffffff
+ str r1,[$ctx,#36] @ is_base2_26
+
+ vmov.32 $D0#lo[0],r2
+ vmov.32 $D1#lo[0],r3
+ vmov.32 $D2#lo[0],r4
+ vmov.32 $D3#lo[0],r5
+ vmov.32 $D4#lo[0],r6
+ adr $zeros,.Lzeros
+
+ ldmia sp!,{r1-r3,lr}
+ b .Lbase2_32_neon
+
+.align 4
+.Lbase2_26_neon:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ load hash value
+
+ veor $D0#lo,$D0#lo,$D0#lo
+ veor $D1#lo,$D1#lo,$D1#lo
+ veor $D2#lo,$D2#lo,$D2#lo
+ veor $D3#lo,$D3#lo,$D3#lo
+ veor $D4#lo,$D4#lo,$D4#lo
+ vld4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]!
+ adr $zeros,.Lzeros
+ vld1.32 {$D4#lo[0]},[$ctx]
+ sub $ctx,$ctx,#16 @ rewind
+
+.Lbase2_32_neon:
+ add $in2,$inp,#32
+ mov $padbit,$padbit,lsl#24
+ tst $len,#31
+ beq .Leven
+
+ vld4.32 {$H0#lo[0],$H1#lo[0],$H2#lo[0],$H3#lo[0]},[$inp]!
+ vmov.32 $H4#lo[0],$padbit
+ sub $len,$len,#16
+ add $in2,$inp,#32
+
+# ifdef __ARMEB__
+ vrev32.8 $H0,$H0
+ vrev32.8 $H3,$H3
+ vrev32.8 $H1,$H1
+ vrev32.8 $H2,$H2
+# endif
+ vsri.u32 $H4#lo,$H3#lo,#8 @ base 2^32 -> base 2^26
+ vshl.u32 $H3#lo,$H3#lo,#18
+
+ vsri.u32 $H3#lo,$H2#lo,#14
+ vshl.u32 $H2#lo,$H2#lo,#12
+ vadd.i32 $H4#hi,$H4#lo,$D4#lo @ add hash value and move to #hi
+
+ vbic.i32 $H3#lo,#0xfc000000
+ vsri.u32 $H2#lo,$H1#lo,#20
+ vshl.u32 $H1#lo,$H1#lo,#6
+
+ vbic.i32 $H2#lo,#0xfc000000
+ vsri.u32 $H1#lo,$H0#lo,#26
+ vadd.i32 $H3#hi,$H3#lo,$D3#lo
+
+ vbic.i32 $H0#lo,#0xfc000000
+ vbic.i32 $H1#lo,#0xfc000000
+ vadd.i32 $H2#hi,$H2#lo,$D2#lo
+
+ vadd.i32 $H0#hi,$H0#lo,$D0#lo
+ vadd.i32 $H1#hi,$H1#lo,$D1#lo
+
+ mov $tbl1,$zeros
+ add $tbl0,$ctx,#48
+
+ cmp $len,$len
+ b .Long_tail
+
+.align 4
+.Leven:
+ subs $len,$len,#64
+# ifdef __thumb2__
+ it lo
+# endif
+ movlo $in2,$zeros
+
+ vmov.i32 $H4,#1<<24 @ padbit, yes, always
+ vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1]
+ add $inp,$inp,#64
+ vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0)
+ add $in2,$in2,#64
+# ifdef __thumb2__
+ itt hi
+# endif
+ addhi $tbl1,$ctx,#(48+1*9*4)
+ addhi $tbl0,$ctx,#(48+3*9*4)
+
+# ifdef __ARMEB__
+ vrev32.8 $H0,$H0
+ vrev32.8 $H3,$H3
+ vrev32.8 $H1,$H1
+ vrev32.8 $H2,$H2
+# endif
+ vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26
+ vshl.u32 $H3,$H3,#18
+
+ vsri.u32 $H3,$H2,#14
+ vshl.u32 $H2,$H2,#12
+
+ vbic.i32 $H3,#0xfc000000
+ vsri.u32 $H2,$H1,#20
+ vshl.u32 $H1,$H1,#6
+
+ vbic.i32 $H2,#0xfc000000
+ vsri.u32 $H1,$H0,#26
+
+ vbic.i32 $H0,#0xfc000000
+ vbic.i32 $H1,#0xfc000000
+
+ bls .Lskip_loop
+
+ vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^2
+ vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4
+ vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ b .Loop_neon
+
+.align 5
+.Loop_neon:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ @ \___________________/
+ @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ @ \___________________/ \____________________/
+ @
+ @ Note that we start with inp[2:3]*r^2. This is because it
+ @ doesn't depend on reduction in previous iteration.
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ inp[2:3]*r^2
+
+ vadd.i32 $H2#lo,$H2#lo,$D2#lo @ accumulate inp[0:1]
+ vmull.u32 $D2,$H2#hi,${R0}[1]
+ vadd.i32 $H0#lo,$H0#lo,$D0#lo
+ vmull.u32 $D0,$H0#hi,${R0}[1]
+ vadd.i32 $H3#lo,$H3#lo,$D3#lo
+ vmull.u32 $D3,$H3#hi,${R0}[1]
+ vmlal.u32 $D2,$H1#hi,${R1}[1]
+ vadd.i32 $H1#lo,$H1#lo,$D1#lo
+ vmull.u32 $D1,$H1#hi,${R0}[1]
+
+ vadd.i32 $H4#lo,$H4#lo,$D4#lo
+ vmull.u32 $D4,$H4#hi,${R0}[1]
+ subs $len,$len,#64
+ vmlal.u32 $D0,$H4#hi,${S1}[1]
+# ifdef __thumb2__
+ it lo
+# endif
+ movlo $in2,$zeros
+ vmlal.u32 $D3,$H2#hi,${R1}[1]
+ vld1.32 ${S4}[1],[$tbl1,:32]
+ vmlal.u32 $D1,$H0#hi,${R1}[1]
+ vmlal.u32 $D4,$H3#hi,${R1}[1]
+
+ vmlal.u32 $D0,$H3#hi,${S2}[1]
+ vmlal.u32 $D3,$H1#hi,${R2}[1]
+ vmlal.u32 $D4,$H2#hi,${R2}[1]
+ vmlal.u32 $D1,$H4#hi,${S2}[1]
+ vmlal.u32 $D2,$H0#hi,${R2}[1]
+
+ vmlal.u32 $D3,$H0#hi,${R3}[1]
+ vmlal.u32 $D0,$H2#hi,${S3}[1]
+ vmlal.u32 $D4,$H1#hi,${R3}[1]
+ vmlal.u32 $D1,$H3#hi,${S3}[1]
+ vmlal.u32 $D2,$H4#hi,${S3}[1]
+
+ vmlal.u32 $D3,$H4#hi,${S4}[1]
+ vmlal.u32 $D0,$H1#hi,${S4}[1]
+ vmlal.u32 $D4,$H0#hi,${R4}[1]
+ vmlal.u32 $D1,$H2#hi,${S4}[1]
+ vmlal.u32 $D2,$H3#hi,${S4}[1]
+
+ vld4.32 {$H0#hi,$H1#hi,$H2#hi,$H3#hi},[$in2] @ inp[2:3] (or 0)
+ add $in2,$in2,#64
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ (hash+inp[0:1])*r^4 and accumulate
+
+ vmlal.u32 $D3,$H3#lo,${R0}[0]
+ vmlal.u32 $D0,$H0#lo,${R0}[0]
+ vmlal.u32 $D4,$H4#lo,${R0}[0]
+ vmlal.u32 $D1,$H1#lo,${R0}[0]
+ vmlal.u32 $D2,$H2#lo,${R0}[0]
+ vld1.32 ${S4}[0],[$tbl0,:32]
+
+ vmlal.u32 $D3,$H2#lo,${R1}[0]
+ vmlal.u32 $D0,$H4#lo,${S1}[0]
+ vmlal.u32 $D4,$H3#lo,${R1}[0]
+ vmlal.u32 $D1,$H0#lo,${R1}[0]
+ vmlal.u32 $D2,$H1#lo,${R1}[0]
+
+ vmlal.u32 $D3,$H1#lo,${R2}[0]
+ vmlal.u32 $D0,$H3#lo,${S2}[0]
+ vmlal.u32 $D4,$H2#lo,${R2}[0]
+ vmlal.u32 $D1,$H4#lo,${S2}[0]
+ vmlal.u32 $D2,$H0#lo,${R2}[0]
+
+ vmlal.u32 $D3,$H0#lo,${R3}[0]
+ vmlal.u32 $D0,$H2#lo,${S3}[0]
+ vmlal.u32 $D4,$H1#lo,${R3}[0]
+ vmlal.u32 $D1,$H3#lo,${S3}[0]
+ vmlal.u32 $D3,$H4#lo,${S4}[0]
+
+ vmlal.u32 $D2,$H4#lo,${S3}[0]
+ vmlal.u32 $D0,$H1#lo,${S4}[0]
+ vmlal.u32 $D4,$H0#lo,${R4}[0]
+ vmov.i32 $H4,#1<<24 @ padbit, yes, always
+ vmlal.u32 $D1,$H2#lo,${S4}[0]
+ vmlal.u32 $D2,$H3#lo,${S4}[0]
+
+ vld4.32 {$H0#lo,$H1#lo,$H2#lo,$H3#lo},[$inp] @ inp[0:1]
+ add $inp,$inp,#64
+# ifdef __ARMEB__
+ vrev32.8 $H0,$H0
+ vrev32.8 $H1,$H1
+ vrev32.8 $H2,$H2
+ vrev32.8 $H3,$H3
+# endif
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ lazy reduction interleaved with base 2^32 -> base 2^26
+
+ vshr.u64 $T0,$D3,#26
+ vmovn.i64 $D3#lo,$D3
+ vshr.u64 $T1,$D0,#26
+ vmovn.i64 $D0#lo,$D0
+ vadd.i64 $D4,$D4,$T0 @ h3 -> h4
+ vbic.i32 $D3#lo,#0xfc000000
+ vsri.u32 $H4,$H3,#8 @ base 2^32 -> base 2^26
+ vadd.i64 $D1,$D1,$T1 @ h0 -> h1
+ vshl.u32 $H3,$H3,#18
+ vbic.i32 $D0#lo,#0xfc000000
+
+ vshrn.u64 $T0#lo,$D4,#26
+ vmovn.i64 $D4#lo,$D4
+ vshr.u64 $T1,$D1,#26
+ vmovn.i64 $D1#lo,$D1
+ vadd.i64 $D2,$D2,$T1 @ h1 -> h2
+ vsri.u32 $H3,$H2,#14
+ vbic.i32 $D4#lo,#0xfc000000
+ vshl.u32 $H2,$H2,#12
+ vbic.i32 $D1#lo,#0xfc000000
+
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo
+ vshl.u32 $T0#lo,$T0#lo,#2
+ vbic.i32 $H3,#0xfc000000
+ vshrn.u64 $T1#lo,$D2,#26
+ vmovn.i64 $D2#lo,$D2
+ vadd.i32 $D0#lo,$D0#lo,$T0#lo @ h4 -> h0
+ vsri.u32 $H2,$H1,#20
+ vadd.i32 $D3#lo,$D3#lo,$T1#lo @ h2 -> h3
+ vshl.u32 $H1,$H1,#6
+ vbic.i32 $D2#lo,#0xfc000000
+ vbic.i32 $H2,#0xfc000000
+
+ vshr.u32 $T0#lo,$D0#lo,#26
+ vbic.i32 $D0#lo,#0xfc000000
+ vsri.u32 $H1,$H0,#26
+ vbic.i32 $H0,#0xfc000000
+ vshr.u32 $T1#lo,$D3#lo,#26
+ vbic.i32 $D3#lo,#0xfc000000
+ vadd.i32 $D1#lo,$D1#lo,$T0#lo @ h0 -> h1
+ vadd.i32 $D4#lo,$D4#lo,$T1#lo @ h3 -> h4
+ vbic.i32 $H1,#0xfc000000
+
+ bhi .Loop_neon
+
+.Lskip_loop:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ add $tbl1,$ctx,#(48+0*9*4)
+ add $tbl0,$ctx,#(48+1*9*4)
+ adds $len,$len,#32
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $len,#0
+ bne .Long_tail
+
+ vadd.i32 $H2#hi,$H2#lo,$D2#lo @ add hash value and move to #hi
+ vadd.i32 $H0#hi,$H0#lo,$D0#lo
+ vadd.i32 $H3#hi,$H3#lo,$D3#lo
+ vadd.i32 $H1#hi,$H1#lo,$D1#lo
+ vadd.i32 $H4#hi,$H4#lo,$D4#lo
+
+.Long_tail:
+ vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^1
+ vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^2
+
+ vadd.i32 $H2#lo,$H2#lo,$D2#lo @ can be redundant
+ vmull.u32 $D2,$H2#hi,$R0
+ vadd.i32 $H0#lo,$H0#lo,$D0#lo
+ vmull.u32 $D0,$H0#hi,$R0
+ vadd.i32 $H3#lo,$H3#lo,$D3#lo
+ vmull.u32 $D3,$H3#hi,$R0
+ vadd.i32 $H1#lo,$H1#lo,$D1#lo
+ vmull.u32 $D1,$H1#hi,$R0
+ vadd.i32 $H4#lo,$H4#lo,$D4#lo
+ vmull.u32 $D4,$H4#hi,$R0
+
+ vmlal.u32 $D0,$H4#hi,$S1
+ vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vmlal.u32 $D3,$H2#hi,$R1
+ vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vmlal.u32 $D1,$H0#hi,$R1
+ vmlal.u32 $D4,$H3#hi,$R1
+ vmlal.u32 $D2,$H1#hi,$R1
+
+ vmlal.u32 $D3,$H1#hi,$R2
+ vld1.32 ${S4}[1],[$tbl1,:32]
+ vmlal.u32 $D0,$H3#hi,$S2
+ vld1.32 ${S4}[0],[$tbl0,:32]
+ vmlal.u32 $D4,$H2#hi,$R2
+ vmlal.u32 $D1,$H4#hi,$S2
+ vmlal.u32 $D2,$H0#hi,$R2
+
+ vmlal.u32 $D3,$H0#hi,$R3
+# ifdef __thumb2__
+ it ne
+# endif
+ addne $tbl1,$ctx,#(48+2*9*4)
+ vmlal.u32 $D0,$H2#hi,$S3
+# ifdef __thumb2__
+ it ne
+# endif
+ addne $tbl0,$ctx,#(48+3*9*4)
+ vmlal.u32 $D4,$H1#hi,$R3
+ vmlal.u32 $D1,$H3#hi,$S3
+ vmlal.u32 $D2,$H4#hi,$S3
+
+ vmlal.u32 $D3,$H4#hi,$S4
+ vorn $MASK,$MASK,$MASK @ all-ones, can be redundant
+ vmlal.u32 $D0,$H1#hi,$S4
+ vshr.u64 $MASK,$MASK,#38
+ vmlal.u32 $D4,$H0#hi,$R4
+ vmlal.u32 $D1,$H2#hi,$S4
+ vmlal.u32 $D2,$H3#hi,$S4
+
+ beq .Lshort_tail
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ (hash+inp[0:1])*r^4:r^3 and accumulate
+
+ vld4.32 {${R0}[1],${R1}[1],${S1}[1],${R2}[1]},[$tbl1]! @ load r^3
+ vld4.32 {${R0}[0],${R1}[0],${S1}[0],${R2}[0]},[$tbl0]! @ load r^4
+
+ vmlal.u32 $D2,$H2#lo,$R0
+ vmlal.u32 $D0,$H0#lo,$R0
+ vmlal.u32 $D3,$H3#lo,$R0
+ vmlal.u32 $D1,$H1#lo,$R0
+ vmlal.u32 $D4,$H4#lo,$R0
+
+ vmlal.u32 $D0,$H4#lo,$S1
+ vld4.32 {${S2}[1],${R3}[1],${S3}[1],${R4}[1]},[$tbl1]!
+ vmlal.u32 $D3,$H2#lo,$R1
+ vld4.32 {${S2}[0],${R3}[0],${S3}[0],${R4}[0]},[$tbl0]!
+ vmlal.u32 $D1,$H0#lo,$R1
+ vmlal.u32 $D4,$H3#lo,$R1
+ vmlal.u32 $D2,$H1#lo,$R1
+
+ vmlal.u32 $D3,$H1#lo,$R2
+ vld1.32 ${S4}[1],[$tbl1,:32]
+ vmlal.u32 $D0,$H3#lo,$S2
+ vld1.32 ${S4}[0],[$tbl0,:32]
+ vmlal.u32 $D4,$H2#lo,$R2
+ vmlal.u32 $D1,$H4#lo,$S2
+ vmlal.u32 $D2,$H0#lo,$R2
+
+ vmlal.u32 $D3,$H0#lo,$R3
+ vmlal.u32 $D0,$H2#lo,$S3
+ vmlal.u32 $D4,$H1#lo,$R3
+ vmlal.u32 $D1,$H3#lo,$S3
+ vmlal.u32 $D2,$H4#lo,$S3
+
+ vmlal.u32 $D3,$H4#lo,$S4
+ vorn $MASK,$MASK,$MASK @ all-ones
+ vmlal.u32 $D0,$H1#lo,$S4
+ vshr.u64 $MASK,$MASK,#38
+ vmlal.u32 $D4,$H0#lo,$R4
+ vmlal.u32 $D1,$H2#lo,$S4
+ vmlal.u32 $D2,$H3#lo,$S4
+
+.Lshort_tail:
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ horizontal addition
+
+ vadd.i64 $D3#lo,$D3#lo,$D3#hi
+ vadd.i64 $D0#lo,$D0#lo,$D0#hi
+ vadd.i64 $D4#lo,$D4#lo,$D4#hi
+ vadd.i64 $D1#lo,$D1#lo,$D1#hi
+ vadd.i64 $D2#lo,$D2#lo,$D2#hi
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ lazy reduction, but without narrowing
+
+ vshr.u64 $T0,$D3,#26
+ vand.i64 $D3,$D3,$MASK
+ vshr.u64 $T1,$D0,#26
+ vand.i64 $D0,$D0,$MASK
+ vadd.i64 $D4,$D4,$T0 @ h3 -> h4
+ vadd.i64 $D1,$D1,$T1 @ h0 -> h1
+
+ vshr.u64 $T0,$D4,#26
+ vand.i64 $D4,$D4,$MASK
+ vshr.u64 $T1,$D1,#26
+ vand.i64 $D1,$D1,$MASK
+ vadd.i64 $D2,$D2,$T1 @ h1 -> h2
+
+ vadd.i64 $D0,$D0,$T0
+ vshl.u64 $T0,$T0,#2
+ vshr.u64 $T1,$D2,#26
+ vand.i64 $D2,$D2,$MASK
+ vadd.i64 $D0,$D0,$T0 @ h4 -> h0
+ vadd.i64 $D3,$D3,$T1 @ h2 -> h3
+
+ vshr.u64 $T0,$D0,#26
+ vand.i64 $D0,$D0,$MASK
+ vshr.u64 $T1,$D3,#26
+ vand.i64 $D3,$D3,$MASK
+ vadd.i64 $D1,$D1,$T0 @ h0 -> h1
+ vadd.i64 $D4,$D4,$T1 @ h3 -> h4
+
+ cmp $len,#0
+ bne .Leven
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ store hash value
+
+ vst4.32 {$D0#lo[0],$D1#lo[0],$D2#lo[0],$D3#lo[0]},[$ctx]!
+ vst1.32 {$D4#lo[0]},[$ctx]
+
+ vldmia sp!,{d8-d15} @ epilogue
+ ldmia sp!,{r4-r7}
+.Lno_data_neon:
+ ret @ bx lr
+.size poly1305_blocks_neon,.-poly1305_blocks_neon
+
+.type poly1305_emit_neon,%function
+.align 5
+poly1305_emit_neon:
+ ldr ip,[$ctx,#36] @ is_base2_26
+
+ stmdb sp!,{r4-r11}
+
+ tst ip,ip
+ beq .Lpoly1305_emit_enter
+
+ ldmia $ctx,{$h0-$h4}
+ eor $g0,$g0,$g0
+
+ adds $h0,$h0,$h1,lsl#26 @ base 2^26 -> base 2^32
+ mov $h1,$h1,lsr#6
+ adcs $h1,$h1,$h2,lsl#20
+ mov $h2,$h2,lsr#12
+ adcs $h2,$h2,$h3,lsl#14
+ mov $h3,$h3,lsr#18
+ adcs $h3,$h3,$h4,lsl#8
+ adc $h4,$g0,$h4,lsr#24 @ can be partially reduced ...
+
+ and $g0,$h4,#-4 @ ... so reduce
+ and $h4,$h3,#3
+ add $g0,$g0,$g0,lsr#2 @ *= 5
+ adds $h0,$h0,$g0
+ adcs $h1,$h1,#0
+ adcs $h2,$h2,#0
+ adc $h3,$h3,#0
+
+ adds $g0,$h0,#5 @ compare to modulus
+ adcs $g1,$h1,#0
+ adcs $g2,$h2,#0
+ adcs $g3,$h3,#0
+ adc $g4,$h4,#0
+ tst $g4,#4 @ did it carry/borrow?
+
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h0,$g0
+ ldr $g0,[$nonce,#0]
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h1,$g1
+ ldr $g1,[$nonce,#4]
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h2,$g2
+ ldr $g2,[$nonce,#8]
+# ifdef __thumb2__
+ it ne
+# endif
+ movne $h3,$g3
+ ldr $g3,[$nonce,#12]
+
+ adds $h0,$h0,$g0 @ accumulate nonce
+ adcs $h1,$h1,$g1
+ adcs $h2,$h2,$g2
+ adc $h3,$h3,$g3
+
+# ifdef __ARMEB__
+ rev $h0,$h0
+ rev $h1,$h1
+ rev $h2,$h2
+ rev $h3,$h3
+# endif
+ str $h0,[$mac,#0] @ store the result
+ str $h1,[$mac,#4]
+ str $h2,[$mac,#8]
+ str $h3,[$mac,#12]
+
+ ldmia sp!,{r4-r11}
+ ret @ bx lr
+.size poly1305_emit_neon,.-poly1305_emit_neon
+
+.align 5
+.Lzeros:
+.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-.Lpoly1305_init
+#endif
+___
+} }
+$code.=<<___;
+.asciz "Poly1305 for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
+ s/\bret\b/bx lr/go or
+ s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4
+
+ print $_,"\n";
+}
+close STDOUT; # enforce flush
diff --git a/crypto/poly1305/asm/poly1305-armv8.pl b/crypto/poly1305/asm/poly1305-armv8.pl
new file mode 100755
index 00000000..1d9a81b8
--- /dev/null
+++ b/crypto/poly1305/asm/poly1305-armv8.pl
@@ -0,0 +1,925 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# This module implements Poly1305 hash for ARMv8.
+#
+# June 2015
+#
+# Numbers are cycles per processed byte with poly1305_blocks alone.
+#
+# IALU/gcc-4.9 NEON
+#
+# Apple A7 1.86/+5% 0.72
+# Cortex-A53 2.63/+58% 1.47
+# Cortex-A57 2.70/+7% 1.14
+# Denver 1.39/+50% 1.18(*)
+# X-Gene 2.00/+68% 2.19
+#
+# (*) estimate based on resources availability is less than 1.0,
+# i.e. measured result is worse than expected, presumably binary
+# translator is not almighty;
+
+$flavour=shift;
+$output=shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my ($ctx,$inp,$len,$padbit) = map("x$_",(0..3));
+my ($mac,$nonce)=($inp,$len);
+
+my ($h0,$h1,$h2,$r0,$r1,$s1,$t0,$t1,$d0,$d1,$d2) = map("x$_",(4..14));
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+
+// forward "declarations" are required for Apple
+.extern OPENSSL_armcap_P
+.globl poly1305_blocks
+.globl poly1305_emit
+
+.globl poly1305_init
+.type poly1305_init,%function
+.align 5
+poly1305_init:
+ cmp $inp,xzr
+ stp xzr,xzr,[$ctx] // zero hash value
+ stp xzr,xzr,[$ctx,#16] // [along with is_base2_26]
+
+ csel x0,xzr,x0,eq
+ b.eq .Lno_key
+
+#ifdef __ILP32__
+ ldrsw $t1,.LOPENSSL_armcap_P
+#else
+ ldr $t1,.LOPENSSL_armcap_P
+#endif
+ adr $t0,.LOPENSSL_armcap_P
+
+ ldp $r0,$r1,[$inp] // load key
+ mov $s1,#0xfffffffc0fffffff
+ movk $s1,#0x0fff,lsl#48
+ ldr w17,[$t0,$t1]
+#ifdef __ARMEB__
+ rev $r0,$r0 // flip bytes
+ rev $r1,$r1
+#endif
+ and $r0,$r0,$s1 // &=0ffffffc0fffffff
+ and $s1,$s1,#-4
+ and $r1,$r1,$s1 // &=0ffffffc0ffffffc
+ stp $r0,$r1,[$ctx,#32] // save key value
+
+ tst w17,#ARMV7_NEON
+
+ adr $d0,poly1305_blocks
+ adr $r0,poly1305_blocks_neon
+ adr $d1,poly1305_emit
+ adr $r1,poly1305_emit_neon
+
+ csel $d0,$d0,$r0,eq
+ csel $d1,$d1,$r1,eq
+
+ stp $d0,$d1,[$len]
+
+ mov x0,#1
+.Lno_key:
+ ret
+.size poly1305_init,.-poly1305_init
+
+.type poly1305_blocks,%function
+.align 5
+poly1305_blocks:
+ ands $len,$len,#-16
+ b.eq .Lno_data
+
+ ldp $h0,$h1,[$ctx] // load hash value
+ ldp $r0,$r1,[$ctx,#32] // load key value
+ ldr $h2,[$ctx,#16]
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+ b .Loop
+
+.align 5
+.Loop:
+ ldp $t0,$t1,[$inp],#16 // load input
+ sub $len,$len,#16
+#ifdef __ARMEB__
+ rev $t0,$t0
+ rev $t1,$t1
+#endif
+ adds $h0,$h0,$t0 // accumulate input
+ adcs $h1,$h1,$t1
+
+ mul $d0,$h0,$r0 // h0*r0
+ adc $h2,$h2,$padbit
+ umulh $d1,$h0,$r0
+
+ mul $t0,$h1,$s1 // h1*5*r1
+ umulh $t1,$h1,$s1
+
+ adds $d0,$d0,$t0
+ mul $t0,$h0,$r1 // h0*r1
+ adc $d1,$d1,$t1
+ umulh $d2,$h0,$r1
+
+ adds $d1,$d1,$t0
+ mul $t0,$h1,$r0 // h1*r0
+ adc $d2,$d2,xzr
+ umulh $t1,$h1,$r0
+
+ adds $d1,$d1,$t0
+ mul $t0,$h2,$s1 // h2*5*r1
+ adc $d2,$d2,$t1
+ mul $t1,$h2,$r0 // h2*r0
+
+ adds $d1,$d1,$t0
+ adc $d2,$d2,$t1
+
+ and $t0,$d2,#-4 // final reduction
+ and $h2,$d2,#3
+ add $t0,$t0,$d2,lsr#2
+ adds $h0,$d0,$t0
+ adc $h1,$d1,xzr
+
+ cbnz $len,.Loop
+
+ stp $h0,$h1,[$ctx] // store hash value
+ str $h2,[$ctx,#16]
+
+.Lno_data:
+ ret
+.size poly1305_blocks,.-poly1305_blocks
+
+.type poly1305_emit,%function
+.align 5
+poly1305_emit:
+ ldp $h0,$h1,[$ctx] // load hash base 2^64
+ ldr $h2,[$ctx,#16]
+ ldp $t0,$t1,[$nonce] // load nonce
+
+ adds $d0,$h0,#5 // compare to modulus
+ adcs $d1,$h1,xzr
+ adc $d2,$h2,xzr
+
+ tst $d2,#-4 // see if it's carried/borrowed
+
+ csel $h0,$h0,$d0,eq
+ csel $h1,$h1,$d1,eq
+
+#ifdef __ARMEB__
+ ror $t0,$t0,#32 // flip nonce words
+ ror $t1,$t1,#32
+#endif
+ adds $h0,$h0,$t0 // accumulate nonce
+ adc $h1,$h1,$t1
+#ifdef __ARMEB__
+ rev $h0,$h0 // flip output bytes
+ rev $h1,$h1
+#endif
+ stp $h0,$h1,[$mac] // write result
+
+ ret
+.size poly1305_emit,.-poly1305_emit
+___
+my ($R0,$R1,$S1,$R2,$S2,$R3,$S3,$R4,$S4) = map("v$_.4s",(0..8));
+my ($IN01_0,$IN01_1,$IN01_2,$IN01_3,$IN01_4) = map("v$_.2s",(9..13));
+my ($IN23_0,$IN23_1,$IN23_2,$IN23_3,$IN23_4) = map("v$_.2s",(14..18));
+my ($ACC0,$ACC1,$ACC2,$ACC3,$ACC4) = map("v$_.2d",(19..23));
+my ($H0,$H1,$H2,$H3,$H4) = map("v$_.2s",(24..28));
+my ($T0,$T1,$MASK) = map("v$_",(29..31));
+
+my ($in2,$zeros)=("x16","x17");
+my $is_base2_26 = $zeros; # borrow
+
+$code.=<<___;
+.type poly1305_mult,%function
+.align 5
+poly1305_mult:
+ mul $d0,$h0,$r0 // h0*r0
+ umulh $d1,$h0,$r0
+
+ mul $t0,$h1,$s1 // h1*5*r1
+ umulh $t1,$h1,$s1
+
+ adds $d0,$d0,$t0
+ mul $t0,$h0,$r1 // h0*r1
+ adc $d1,$d1,$t1
+ umulh $d2,$h0,$r1
+
+ adds $d1,$d1,$t0
+ mul $t0,$h1,$r0 // h1*r0
+ adc $d2,$d2,xzr
+ umulh $t1,$h1,$r0
+
+ adds $d1,$d1,$t0
+ mul $t0,$h2,$s1 // h2*5*r1
+ adc $d2,$d2,$t1
+ mul $t1,$h2,$r0 // h2*r0
+
+ adds $d1,$d1,$t0
+ adc $d2,$d2,$t1
+
+ and $t0,$d2,#-4 // final reduction
+ and $h2,$d2,#3
+ add $t0,$t0,$d2,lsr#2
+ adds $h0,$d0,$t0
+ adc $h1,$d1,xzr
+
+ ret
+.size poly1305_mult,.-poly1305_mult
+
+.type poly1305_splat,%function
+.align 5
+poly1305_splat:
+ and x12,$h0,#0x03ffffff // base 2^64 -> base 2^26
+ ubfx x13,$h0,#26,#26
+ extr x14,$h1,$h0,#52
+ and x14,x14,#0x03ffffff
+ ubfx x15,$h1,#14,#26
+ extr x16,$h2,$h1,#40
+
+ str w12,[$ctx,#16*0] // r0
+ add w12,w13,w13,lsl#2 // r1*5
+ str w13,[$ctx,#16*1] // r1
+ add w13,w14,w14,lsl#2 // r2*5
+ str w12,[$ctx,#16*2] // s1
+ str w14,[$ctx,#16*3] // r2
+ add w14,w15,w15,lsl#2 // r3*5
+ str w13,[$ctx,#16*4] // s2
+ str w15,[$ctx,#16*5] // r3
+ add w15,w16,w16,lsl#2 // r4*5
+ str w14,[$ctx,#16*6] // s3
+ str w16,[$ctx,#16*7] // r4
+ str w15,[$ctx,#16*8] // s4
+
+ ret
+.size poly1305_splat,.-poly1305_splat
+
+.type poly1305_blocks_neon,%function
+.align 5
+poly1305_blocks_neon:
+ ldr $is_base2_26,[$ctx,#24]
+ cmp $len,#128
+ b.hs .Lblocks_neon
+ cbz $is_base2_26,poly1305_blocks
+
+.Lblocks_neon:
+ stp x29,x30,[sp,#-80]!
+ add x29,sp,#0
+
+ ands $len,$len,#-16
+ b.eq .Lno_data_neon
+
+ cbz $is_base2_26,.Lbase2_64_neon
+
+ ldp w10,w11,[$ctx] // load hash value base 2^26
+ ldp w12,w13,[$ctx,#8]
+ ldr w14,[$ctx,#16]
+
+ tst $len,#31
+ b.eq .Leven_neon
+
+ ldp $r0,$r1,[$ctx,#32] // load key value
+
+ add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64
+ lsr $h1,x12,#12
+ adds $h0,$h0,x12,lsl#52
+ add $h1,$h1,x13,lsl#14
+ adc $h1,$h1,xzr
+ lsr $h2,x14,#24
+ adds $h1,$h1,x14,lsl#40
+ adc $d2,$h2,xzr // can be partially reduced...
+
+ ldp $d0,$d1,[$inp],#16 // load input
+ sub $len,$len,#16
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+
+ and $t0,$d2,#-4 // ... so reduce
+ and $h2,$d2,#3
+ add $t0,$t0,$d2,lsr#2
+ adds $h0,$h0,$t0
+ adc $h1,$h1,xzr
+
+#ifdef __ARMEB__
+ rev $d0,$d0
+ rev $d1,$d1
+#endif
+ adds $h0,$h0,$d0 // accumulate input
+ adcs $h1,$h1,$d1
+ adc $h2,$h2,$padbit
+
+ bl poly1305_mult
+ ldr x30,[sp,#8]
+
+ cbz $padbit,.Lstore_base2_64_neon
+
+ and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26
+ ubfx x11,$h0,#26,#26
+ extr x12,$h1,$h0,#52
+ and x12,x12,#0x03ffffff
+ ubfx x13,$h1,#14,#26
+ extr x14,$h2,$h1,#40
+
+ cbnz $len,.Leven_neon
+
+ stp w10,w11,[$ctx] // store hash value base 2^26
+ stp w12,w13,[$ctx,#8]
+ str w14,[$ctx,#16]
+ b .Lno_data_neon
+
+.align 4
+.Lstore_base2_64_neon:
+ stp $h0,$h1,[$ctx] // store hash value base 2^64
+ stp $h2,xzr,[$ctx,#16] // note that is_base2_26 is zeroed
+ b .Lno_data_neon
+
+.align 4
+.Lbase2_64_neon:
+ ldp $r0,$r1,[$ctx,#32] // load key value
+
+ ldp $h0,$h1,[$ctx] // load hash value base 2^64
+ ldr $h2,[$ctx,#16]
+
+ tst $len,#31
+ b.eq .Linit_neon
+
+ ldp $d0,$d1,[$inp],#16 // load input
+ sub $len,$len,#16
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+#ifdef __ARMEB__
+ rev $d0,$d0
+ rev $d1,$d1
+#endif
+ adds $h0,$h0,$d0 // accumulate input
+ adcs $h1,$h1,$d1
+ adc $h2,$h2,$padbit
+
+ bl poly1305_mult
+
+.Linit_neon:
+ and x10,$h0,#0x03ffffff // base 2^64 -> base 2^26
+ ubfx x11,$h0,#26,#26
+ extr x12,$h1,$h0,#52
+ and x12,x12,#0x03ffffff
+ ubfx x13,$h1,#14,#26
+ extr x14,$h2,$h1,#40
+
+ stp d8,d9,[sp,#16] // meet ABI requirements
+ stp d10,d11,[sp,#32]
+ stp d12,d13,[sp,#48]
+ stp d14,d15,[sp,#64]
+
+ fmov ${H0},x10
+ fmov ${H1},x11
+ fmov ${H2},x12
+ fmov ${H3},x13
+ fmov ${H4},x14
+
+ ////////////////////////////////// initialize r^n table
+ mov $h0,$r0 // r^1
+ add $s1,$r1,$r1,lsr#2 // s1 = r1 + (r1 >> 2)
+ mov $h1,$r1
+ mov $h2,xzr
+ add $ctx,$ctx,#48+12
+ bl poly1305_splat
+
+ bl poly1305_mult // r^2
+ sub $ctx,$ctx,#4
+ bl poly1305_splat
+
+ bl poly1305_mult // r^3
+ sub $ctx,$ctx,#4
+ bl poly1305_splat
+
+ bl poly1305_mult // r^4
+ sub $ctx,$ctx,#4
+ bl poly1305_splat
+ ldr x30,[sp,#8]
+
+ add $in2,$inp,#32
+ adr $zeros,.Lzeros
+ subs $len,$len,#64
+ csel $in2,$zeros,$in2,lo
+
+ mov x4,#1
+ str x4,[$ctx,#-24] // set is_base2_26
+ sub $ctx,$ctx,#48 // restore original $ctx
+ b .Ldo_neon
+
+.align 4
+.Leven_neon:
+ add $in2,$inp,#32
+ adr $zeros,.Lzeros
+ subs $len,$len,#64
+ csel $in2,$zeros,$in2,lo
+
+ stp d8,d9,[sp,#16] // meet ABI requirements
+ stp d10,d11,[sp,#32]
+ stp d12,d13,[sp,#48]
+ stp d14,d15,[sp,#64]
+
+ fmov ${H0},x10
+ fmov ${H1},x11
+ fmov ${H2},x12
+ fmov ${H3},x13
+ fmov ${H4},x14
+
+.Ldo_neon:
+ ldp x8,x12,[$in2],#16 // inp[2:3] (or zero)
+ ldp x9,x13,[$in2],#48
+
+ lsl $padbit,$padbit,#24
+ add x15,$ctx,#48
+
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ and x5,x9,#0x03ffffff
+ ubfx x6,x8,#26,#26
+ ubfx x7,x9,#26,#26
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+ extr x8,x12,x8,#52
+ extr x9,x13,x9,#52
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ fmov $IN23_0,x4
+ and x8,x8,#0x03ffffff
+ and x9,x9,#0x03ffffff
+ ubfx x10,x12,#14,#26
+ ubfx x11,x13,#14,#26
+ add x12,$padbit,x12,lsr#40
+ add x13,$padbit,x13,lsr#40
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ fmov $IN23_1,x6
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ fmov $IN23_2,x8
+ fmov $IN23_3,x10
+ fmov $IN23_4,x12
+
+ ldp x8,x12,[$inp],#16 // inp[0:1]
+ ldp x9,x13,[$inp],#48
+
+ ld1 {$R0,$R1,$S1,$R2},[x15],#64
+ ld1 {$S2,$R3,$S3,$R4},[x15],#64
+ ld1 {$S4},[x15]
+
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ and x5,x9,#0x03ffffff
+ ubfx x6,x8,#26,#26
+ ubfx x7,x9,#26,#26
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+ extr x8,x12,x8,#52
+ extr x9,x13,x9,#52
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ fmov $IN01_0,x4
+ and x8,x8,#0x03ffffff
+ and x9,x9,#0x03ffffff
+ ubfx x10,x12,#14,#26
+ ubfx x11,x13,#14,#26
+ add x12,$padbit,x12,lsr#40
+ add x13,$padbit,x13,lsr#40
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ fmov $IN01_1,x6
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ fmov $IN01_2,x8
+ fmov $IN01_3,x10
+ fmov $IN01_4,x12
+
+ b.ls .Lskip_loop
+
+.align 4
+.Loop_neon:
+ ////////////////////////////////////////////////////////////////
+ // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ // \___________________/
+ // ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ // ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ // \___________________/ \____________________/
+ //
+ // Note that we start with inp[2:3]*r^2. This is because it
+ // doesn't depend on reduction in previous iteration.
+ ////////////////////////////////////////////////////////////////
+ // d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0
+ // d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*5*r4
+ // d2 = h0*r2 + h1*r1 + h2*r0 + h3*5*r4 + h4*5*r3
+ // d1 = h0*r1 + h1*r0 + h2*5*r4 + h3*5*r3 + h4*5*r2
+ // d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1
+
+ subs $len,$len,#64
+ umull $ACC4,$IN23_0,${R4}[2]
+ csel $in2,$zeros,$in2,lo
+ umull $ACC3,$IN23_0,${R3}[2]
+ umull $ACC2,$IN23_0,${R2}[2]
+ ldp x8,x12,[$in2],#16 // inp[2:3] (or zero)
+ umull $ACC1,$IN23_0,${R1}[2]
+ ldp x9,x13,[$in2],#48
+ umull $ACC0,$IN23_0,${R0}[2]
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+
+ umlal $ACC4,$IN23_1,${R3}[2]
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ umlal $ACC3,$IN23_1,${R2}[2]
+ and x5,x9,#0x03ffffff
+ umlal $ACC2,$IN23_1,${R1}[2]
+ ubfx x6,x8,#26,#26
+ umlal $ACC1,$IN23_1,${R0}[2]
+ ubfx x7,x9,#26,#26
+ umlal $ACC0,$IN23_1,${S4}[2]
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+
+ umlal $ACC4,$IN23_2,${R2}[2]
+ extr x8,x12,x8,#52
+ umlal $ACC3,$IN23_2,${R1}[2]
+ extr x9,x13,x9,#52
+ umlal $ACC2,$IN23_2,${R0}[2]
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ umlal $ACC1,$IN23_2,${S4}[2]
+ fmov $IN23_0,x4
+ umlal $ACC0,$IN23_2,${S3}[2]
+ and x8,x8,#0x03ffffff
+
+ umlal $ACC4,$IN23_3,${R1}[2]
+ and x9,x9,#0x03ffffff
+ umlal $ACC3,$IN23_3,${R0}[2]
+ ubfx x10,x12,#14,#26
+ umlal $ACC2,$IN23_3,${S4}[2]
+ ubfx x11,x13,#14,#26
+ umlal $ACC1,$IN23_3,${S3}[2]
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ umlal $ACC0,$IN23_3,${S2}[2]
+ fmov $IN23_1,x6
+
+ add $IN01_2,$IN01_2,$H2
+ add x12,$padbit,x12,lsr#40
+ umlal $ACC4,$IN23_4,${R0}[2]
+ add x13,$padbit,x13,lsr#40
+ umlal $ACC3,$IN23_4,${S4}[2]
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ umlal $ACC2,$IN23_4,${S3}[2]
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ umlal $ACC1,$IN23_4,${S2}[2]
+ fmov $IN23_2,x8
+ umlal $ACC0,$IN23_4,${S1}[2]
+ fmov $IN23_3,x10
+
+ ////////////////////////////////////////////////////////////////
+ // (hash+inp[0:1])*r^4 and accumulate
+
+ add $IN01_0,$IN01_0,$H0
+ fmov $IN23_4,x12
+ umlal $ACC3,$IN01_2,${R1}[0]
+ ldp x8,x12,[$inp],#16 // inp[0:1]
+ umlal $ACC0,$IN01_2,${S3}[0]
+ ldp x9,x13,[$inp],#48
+ umlal $ACC4,$IN01_2,${R2}[0]
+ umlal $ACC1,$IN01_2,${S4}[0]
+ umlal $ACC2,$IN01_2,${R0}[0]
+#ifdef __ARMEB__
+ rev x8,x8
+ rev x12,x12
+ rev x9,x9
+ rev x13,x13
+#endif
+
+ add $IN01_1,$IN01_1,$H1
+ umlal $ACC3,$IN01_0,${R3}[0]
+ umlal $ACC4,$IN01_0,${R4}[0]
+ and x4,x8,#0x03ffffff // base 2^64 -> base 2^26
+ umlal $ACC2,$IN01_0,${R2}[0]
+ and x5,x9,#0x03ffffff
+ umlal $ACC0,$IN01_0,${R0}[0]
+ ubfx x6,x8,#26,#26
+ umlal $ACC1,$IN01_0,${R1}[0]
+ ubfx x7,x9,#26,#26
+
+ add $IN01_3,$IN01_3,$H3
+ add x4,x4,x5,lsl#32 // bfi x4,x5,#32,#32
+ umlal $ACC3,$IN01_1,${R2}[0]
+ extr x8,x12,x8,#52
+ umlal $ACC4,$IN01_1,${R3}[0]
+ extr x9,x13,x9,#52
+ umlal $ACC0,$IN01_1,${S4}[0]
+ add x6,x6,x7,lsl#32 // bfi x6,x7,#32,#32
+ umlal $ACC2,$IN01_1,${R1}[0]
+ fmov $IN01_0,x4
+ umlal $ACC1,$IN01_1,${R0}[0]
+ and x8,x8,#0x03ffffff
+
+ add $IN01_4,$IN01_4,$H4
+ and x9,x9,#0x03ffffff
+ umlal $ACC3,$IN01_3,${R0}[0]
+ ubfx x10,x12,#14,#26
+ umlal $ACC0,$IN01_3,${S2}[0]
+ ubfx x11,x13,#14,#26
+ umlal $ACC4,$IN01_3,${R1}[0]
+ add x8,x8,x9,lsl#32 // bfi x8,x9,#32,#32
+ umlal $ACC1,$IN01_3,${S3}[0]
+ fmov $IN01_1,x6
+ umlal $ACC2,$IN01_3,${S4}[0]
+ add x12,$padbit,x12,lsr#40
+
+ umlal $ACC3,$IN01_4,${S4}[0]
+ add x13,$padbit,x13,lsr#40
+ umlal $ACC0,$IN01_4,${S1}[0]
+ add x10,x10,x11,lsl#32 // bfi x10,x11,#32,#32
+ umlal $ACC4,$IN01_4,${R0}[0]
+ add x12,x12,x13,lsl#32 // bfi x12,x13,#32,#32
+ umlal $ACC1,$IN01_4,${S2}[0]
+ fmov $IN01_2,x8
+ umlal $ACC2,$IN01_4,${S3}[0]
+ fmov $IN01_3,x10
+
+ /////////////////////////////////////////////////////////////////
+ // lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ // and P. Schwabe
+
+ ushr $T0.2d,$ACC3,#26
+ fmov $IN01_4,x12
+ xtn $H3,$ACC3
+ ushr $T1.2d,$ACC0,#26
+ xtn $H0,$ACC0
+ add $ACC4,$ACC4,$T0.2d // h3 -> h4
+ bic $H3,#0xfc,lsl#24 // &=0x03ffffff
+ add $ACC1,$ACC1,$T1.2d // h0 -> h1
+ bic $H0,#0xfc,lsl#24
+
+ shrn $T0.2s,$ACC4,#26
+ xtn $H4,$ACC4
+ ushr $T1.2d,$ACC1,#26
+ xtn $H1,$ACC1
+ add $ACC2,$ACC2,$T1.2d // h1 -> h2
+ bic $H4,#0xfc,lsl#24
+ bic $H1,#0xfc,lsl#24
+
+ add $H0,$H0,$T0.2s
+ shl $T0.2s,$T0.2s,#2
+ shrn $T1.2s,$ACC2,#26
+ xtn $H2,$ACC2
+ add $H0,$H0,$T0.2s // h4 -> h0
+ add $H3,$H3,$T1.2s // h2 -> h3
+ bic $H2,#0xfc,lsl#24
+
+ ushr $T0.2s,$H0,#26
+ bic $H0,#0xfc,lsl#24
+ ushr $T1.2s,$H3,#26
+ bic $H3,#0xfc,lsl#24
+ add $H1,$H1,$T0.2s // h0 -> h1
+ add $H4,$H4,$T1.2s // h3 -> h4
+
+ b.hi .Loop_neon
+
+.Lskip_loop:
+ dup $IN23_2,${IN23_2}[0]
+ movi $MASK.2d,#-1
+ add $IN01_2,$IN01_2,$H2
+ ushr $MASK.2d,$MASK.2d,#38
+
+ ////////////////////////////////////////////////////////////////
+ // multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ adds $len,$len,#32
+ b.ne .Long_tail
+
+ dup $IN23_2,${IN01_2}[0]
+ add $IN23_0,$IN01_0,$H0
+ add $IN23_3,$IN01_3,$H3
+ add $IN23_1,$IN01_1,$H1
+ add $IN23_4,$IN01_4,$H4
+
+.Long_tail:
+ dup $IN23_0,${IN23_0}[0]
+ umull2 $ACC0,$IN23_2,${S3}
+ umull2 $ACC3,$IN23_2,${R1}
+ umull2 $ACC4,$IN23_2,${R2}
+ umull2 $ACC2,$IN23_2,${R0}
+ umull2 $ACC1,$IN23_2,${S4}
+
+ dup $IN23_1,${IN23_1}[0]
+ umlal2 $ACC0,$IN23_0,${R0}
+ umlal2 $ACC2,$IN23_0,${R2}
+ umlal2 $ACC3,$IN23_0,${R3}
+ umlal2 $ACC4,$IN23_0,${R4}
+ umlal2 $ACC1,$IN23_0,${R1}
+
+ dup $IN23_3,${IN23_3}[0]
+ umlal2 $ACC0,$IN23_1,${S4}
+ umlal2 $ACC3,$IN23_1,${R2}
+ umlal2 $ACC2,$IN23_1,${R1}
+ umlal2 $ACC4,$IN23_1,${R3}
+ umlal2 $ACC1,$IN23_1,${R0}
+
+ dup $IN23_4,${IN23_4}[0]
+ umlal2 $ACC3,$IN23_3,${R0}
+ umlal2 $ACC4,$IN23_3,${R1}
+ umlal2 $ACC0,$IN23_3,${S2}
+ umlal2 $ACC1,$IN23_3,${S3}
+ umlal2 $ACC2,$IN23_3,${S4}
+
+ umlal2 $ACC3,$IN23_4,${S4}
+ umlal2 $ACC0,$IN23_4,${S1}
+ umlal2 $ACC4,$IN23_4,${R0}
+ umlal2 $ACC1,$IN23_4,${S2}
+ umlal2 $ACC2,$IN23_4,${S3}
+
+ b.eq .Lshort_tail
+
+ ////////////////////////////////////////////////////////////////
+ // (hash+inp[0:1])*r^4:r^3 and accumulate
+
+ add $IN01_0,$IN01_0,$H0
+ umlal $ACC3,$IN01_2,${R1}
+ umlal $ACC0,$IN01_2,${S3}
+ umlal $ACC4,$IN01_2,${R2}
+ umlal $ACC1,$IN01_2,${S4}
+ umlal $ACC2,$IN01_2,${R0}
+
+ add $IN01_1,$IN01_1,$H1
+ umlal $ACC3,$IN01_0,${R3}
+ umlal $ACC0,$IN01_0,${R0}
+ umlal $ACC4,$IN01_0,${R4}
+ umlal $ACC1,$IN01_0,${R1}
+ umlal $ACC2,$IN01_0,${R2}
+
+ add $IN01_3,$IN01_3,$H3
+ umlal $ACC3,$IN01_1,${R2}
+ umlal $ACC0,$IN01_1,${S4}
+ umlal $ACC4,$IN01_1,${R3}
+ umlal $ACC1,$IN01_1,${R0}
+ umlal $ACC2,$IN01_1,${R1}
+
+ add $IN01_4,$IN01_4,$H4
+ umlal $ACC3,$IN01_3,${R0}
+ umlal $ACC0,$IN01_3,${S2}
+ umlal $ACC4,$IN01_3,${R1}
+ umlal $ACC1,$IN01_3,${S3}
+ umlal $ACC2,$IN01_3,${S4}
+
+ umlal $ACC3,$IN01_4,${S4}
+ umlal $ACC0,$IN01_4,${S1}
+ umlal $ACC4,$IN01_4,${R0}
+ umlal $ACC1,$IN01_4,${S2}
+ umlal $ACC2,$IN01_4,${S3}
+
+.Lshort_tail:
+ ////////////////////////////////////////////////////////////////
+ // horizontal add
+
+ addp $ACC3,$ACC3,$ACC3
+ ldp d8,d9,[sp,#16] // meet ABI requirements
+ addp $ACC0,$ACC0,$ACC0
+ ldp d10,d11,[sp,#32]
+ addp $ACC4,$ACC4,$ACC4
+ ldp d12,d13,[sp,#48]
+ addp $ACC1,$ACC1,$ACC1
+ ldp d14,d15,[sp,#64]
+ addp $ACC2,$ACC2,$ACC2
+
+ ////////////////////////////////////////////////////////////////
+ // lazy reduction, but without narrowing
+
+ ushr $T0.2d,$ACC3,#26
+ and $ACC3,$ACC3,$MASK.2d
+ ushr $T1.2d,$ACC0,#26
+ and $ACC0,$ACC0,$MASK.2d
+
+ add $ACC4,$ACC4,$T0.2d // h3 -> h4
+ add $ACC1,$ACC1,$T1.2d // h0 -> h1
+
+ ushr $T0.2d,$ACC4,#26
+ and $ACC4,$ACC4,$MASK.2d
+ ushr $T1.2d,$ACC1,#26
+ and $ACC1,$ACC1,$MASK.2d
+ add $ACC2,$ACC2,$T1.2d // h1 -> h2
+
+ add $ACC0,$ACC0,$T0.2d
+ shl $T0.2d,$T0.2d,#2
+ ushr $T1.2d,$ACC2,#26
+ and $ACC2,$ACC2,$MASK.2d
+ add $ACC0,$ACC0,$T0.2d // h4 -> h0
+ add $ACC3,$ACC3,$T1.2d // h2 -> h3
+
+ ushr $T0.2d,$ACC0,#26
+ and $ACC0,$ACC0,$MASK.2d
+ ushr $T1.2d,$ACC3,#26
+ and $ACC3,$ACC3,$MASK.2d
+ add $ACC1,$ACC1,$T0.2d // h0 -> h1
+ add $ACC4,$ACC4,$T1.2d // h3 -> h4
+
+ ////////////////////////////////////////////////////////////////
+ // write the result, can be partially reduced
+
+ st4 {$ACC0,$ACC1,$ACC2,$ACC3}[0],[$ctx],#16
+ st1 {$ACC4}[0],[$ctx]
+
+.Lno_data_neon:
+ ldr x29,[sp],#80
+ ret
+.size poly1305_blocks_neon,.-poly1305_blocks_neon
+
+.type poly1305_emit_neon,%function
+.align 5
+poly1305_emit_neon:
+ ldr $is_base2_26,[$ctx,#24]
+ cbz $is_base2_26,poly1305_emit
+
+ ldp w10,w11,[$ctx] // load hash value base 2^26
+ ldp w12,w13,[$ctx,#8]
+ ldr w14,[$ctx,#16]
+
+ add $h0,x10,x11,lsl#26 // base 2^26 -> base 2^64
+ lsr $h1,x12,#12
+ adds $h0,$h0,x12,lsl#52
+ add $h1,$h1,x13,lsl#14
+ adc $h1,$h1,xzr
+ lsr $h2,x14,#24
+ adds $h1,$h1,x14,lsl#40
+ adc $h2,$h2,xzr // can be partially reduced...
+
+ ldp $t0,$t1,[$nonce] // load nonce
+
+ and $d0,$h2,#-4 // ... so reduce
+ add $d0,$d0,$h2,lsr#2
+ and $h2,$h2,#3
+ adds $h0,$h0,$d0
+ adc $h1,$h1,xzr
+
+ adds $d0,$h0,#5 // compare to modulus
+ adcs $d1,$h1,xzr
+ adc $d2,$h2,xzr
+
+ tst $d2,#-4 // see if it's carried/borrowed
+
+ csel $h0,$h0,$d0,eq
+ csel $h1,$h1,$d1,eq
+
+#ifdef __ARMEB__
+ ror $t0,$t0,#32 // flip nonce words
+ ror $t1,$t1,#32
+#endif
+ adds $h0,$h0,$t0 // accumulate nonce
+ adc $h1,$h1,$t1
+#ifdef __ARMEB__
+ rev $h0,$h0 // flip output bytes
+ rev $h1,$h1
+#endif
+ stp $h0,$h1,[$mac] // write result
+
+ ret
+.size poly1305_emit_neon,.-poly1305_emit_neon
+
+.align 5
+.Lzeros:
+.long 0,0,0,0,0,0,0,0
+.LOPENSSL_armcap_P:
+#ifdef __ILP32__
+.long OPENSSL_armcap_P-.
+#else
+.quad OPENSSL_armcap_P-.
+#endif
+.asciz "Poly1305 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+___
+
+foreach (split("\n",$code)) {
+ s/\b(shrn\s+v[0-9]+)\.[24]d/$1.2s/ or
+ s/\b(fmov\s+)v([0-9]+)[^,]*,\s*x([0-9]+)/$1d$2,x$3/ or
+ (m/\bdup\b/ and (s/\.[24]s/.2d/g or 1)) or
+ (m/\b(eor|and)/ and (s/\.[248][sdh]/.16b/g or 1)) or
+ (m/\bum(ul|la)l\b/ and (s/\.4s/.2s/g or 1)) or
+ (m/\bum(ul|la)l2\b/ and (s/\.2s/.4s/g or 1)) or
+ (m/\bst[1-4]\s+{[^}]+}\[/ and (s/\.[24]d/.s/g or 1));
+
+ s/\.[124]([sd])\[/.$1\[/;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/crypto/poly1305/asm/poly1305-x86.pl b/crypto/poly1305/asm/poly1305-x86.pl
new file mode 100755
index 00000000..4ad2289e
--- /dev/null
+++ b/crypto/poly1305/asm/poly1305-x86.pl
@@ -0,0 +1,1788 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# This module implements Poly1305 hash for x86.
+#
+# April 2015
+#
+# Numbers are cycles per processed byte with poly1305_blocks alone,
+# measured with rdtsc at fixed clock frequency.
+#
+# IALU/gcc-3.4(*) SSE2(**) AVX2
+# Pentium 15.7/+80% -
+# PIII 6.21/+90% -
+# P4 19.8/+40% 3.24
+# Core 2 4.85/+90% 1.80
+# Westmere 4.58/+100% 1.43
+# Sandy Bridge 3.90/+100% 1.36
+# Haswell 3.88/+70% 1.18 0.72
+# Silvermont 11.0/+40% 4.80
+# VIA Nano 6.71/+90% 2.47
+# Sledgehammer 3.51/+180% 4.27
+# Bulldozer 4.53/+140% 1.31
+#
+# (*) gcc 4.8 for some reason generated worse code;
+# (**) besides SSE2 there are floating-point and AVX options; FP
+# is deemed unnecessary, because pre-SSE2 processor are too
+# old to care about, while it's not the fastest option on
+# SSE2-capable ones; AVX is omitted, because it doesn't give
+# a lot of improvement, 5-10% depending on processor;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"poly1305-x86.pl",$ARGV[$#ARGV] eq "386");
+
+$sse2=$avx=0;
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+if ($sse2) {
+ &static_label("const_sse2");
+ &static_label("enter_blocks");
+ &static_label("enter_emit");
+ &external_label("OPENSSL_ia32cap_P");
+
+ # This may be set to 2, but valgrind can't do AVX2 on 32-bit. Without a
+ # way to verify test coverage, keep it disabled.
+ $avx = 0;
+}
+
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int32 h[5]; # current hash value base 2^32
+# unsigned __int32 pad; # is_base2_26 in vector context
+# unsigned __int32 r[4]; # key value base 2^32
+
+&align(64);
+&function_begin("poly1305_init");
+ &mov ("edi",&wparam(0)); # context
+ &mov ("esi",&wparam(1)); # key
+ &mov ("ebp",&wparam(2)); # function table
+
+ &xor ("eax","eax");
+ &mov (&DWP(4*0,"edi"),"eax"); # zero hash value
+ &mov (&DWP(4*1,"edi"),"eax");
+ &mov (&DWP(4*2,"edi"),"eax");
+ &mov (&DWP(4*3,"edi"),"eax");
+ &mov (&DWP(4*4,"edi"),"eax");
+ &mov (&DWP(4*5,"edi"),"eax"); # is_base2_26
+
+ &cmp ("esi",0);
+ &je (&label("nokey"));
+
+ if ($sse2) {
+ &call (&label("pic_point"));
+ &set_label("pic_point");
+ &blindpop("ebx");
+
+ &lea ("eax",&DWP("poly1305_blocks-".&label("pic_point"),"ebx"));
+ &lea ("edx",&DWP("poly1305_emit-".&label("pic_point"),"ebx"));
+
+ &picmeup("edi","OPENSSL_ia32cap_P","ebx",&label("pic_point"));
+ &mov ("ecx",&DWP(0,"edi"));
+ &and ("ecx",1<<26|1<<24);
+ &cmp ("ecx",1<<26|1<<24); # SSE2 and XMM?
+ &jne (&label("no_sse2"));
+
+ &lea ("eax",&DWP("_poly1305_blocks_sse2-".&label("pic_point"),"ebx"));
+ &lea ("edx",&DWP("_poly1305_emit_sse2-".&label("pic_point"),"ebx"));
+
+ if ($avx>1) {
+ &mov ("ecx",&DWP(8,"edi"));
+ &test ("ecx",1<<5); # AVX2?
+ &jz (&label("no_sse2"));
+
+ &lea ("eax",&DWP("_poly1305_blocks_avx2-".&label("pic_point"),"ebx"));
+ }
+ &set_label("no_sse2");
+ &mov ("edi",&wparam(0)); # reload context
+ &mov (&DWP(0,"ebp"),"eax"); # fill function table
+ &mov (&DWP(4,"ebp"),"edx");
+ }
+
+ &mov ("eax",&DWP(4*0,"esi")); # load input key
+ &mov ("ebx",&DWP(4*1,"esi"));
+ &mov ("ecx",&DWP(4*2,"esi"));
+ &mov ("edx",&DWP(4*3,"esi"));
+ &and ("eax",0x0fffffff);
+ &and ("ebx",0x0ffffffc);
+ &and ("ecx",0x0ffffffc);
+ &and ("edx",0x0ffffffc);
+ &mov (&DWP(4*6,"edi"),"eax");
+ &mov (&DWP(4*7,"edi"),"ebx");
+ &mov (&DWP(4*8,"edi"),"ecx");
+ &mov (&DWP(4*9,"edi"),"edx");
+
+ &mov ("eax",$sse2);
+&set_label("nokey");
+&function_end("poly1305_init");
+
+($h0,$h1,$h2,$h3,$h4,
+ $d0,$d1,$d2,$d3,
+ $r0,$r1,$r2,$r3,
+ $s1,$s2,$s3)=map(4*$_,(0..15));
+
+&function_begin("poly1305_blocks");
+ &mov ("edi",&wparam(0)); # ctx
+ &mov ("esi",&wparam(1)); # inp
+ &mov ("ecx",&wparam(2)); # len
+&set_label("enter_blocks");
+ &and ("ecx",-15);
+ &jz (&label("nodata"));
+
+ &stack_push(16);
+ &mov ("eax",&DWP(4*6,"edi")); # r0
+ &mov ("ebx",&DWP(4*7,"edi")); # r1
+ &lea ("ebp",&DWP(0,"esi","ecx")); # end of input
+ &mov ("ecx",&DWP(4*8,"edi")); # r2
+ &mov ("edx",&DWP(4*9,"edi")); # r3
+
+ &mov (&wparam(2),"ebp");
+ &mov ("ebp","esi");
+
+ &mov (&DWP($r0,"esp"),"eax"); # r0
+ &mov ("eax","ebx");
+ &shr ("eax",2);
+ &mov (&DWP($r1,"esp"),"ebx"); # r1
+ &add ("eax","ebx"); # s1
+ &mov ("ebx","ecx");
+ &shr ("ebx",2);
+ &mov (&DWP($r2,"esp"),"ecx"); # r2
+ &add ("ebx","ecx"); # s2
+ &mov ("ecx","edx");
+ &shr ("ecx",2);
+ &mov (&DWP($r3,"esp"),"edx"); # r3
+ &add ("ecx","edx"); # s3
+ &mov (&DWP($s1,"esp"),"eax"); # s1
+ &mov (&DWP($s2,"esp"),"ebx"); # s2
+ &mov (&DWP($s3,"esp"),"ecx"); # s3
+
+ &mov ("eax",&DWP(4*0,"edi")); # load hash value
+ &mov ("ebx",&DWP(4*1,"edi"));
+ &mov ("ecx",&DWP(4*2,"edi"));
+ &mov ("esi",&DWP(4*3,"edi"));
+ &mov ("edi",&DWP(4*4,"edi"));
+ &jmp (&label("loop"));
+
+&set_label("loop",32);
+ &add ("eax",&DWP(4*0,"ebp")); # accumulate input
+ &adc ("ebx",&DWP(4*1,"ebp"));
+ &adc ("ecx",&DWP(4*2,"ebp"));
+ &adc ("esi",&DWP(4*3,"ebp"));
+ &lea ("ebp",&DWP(4*4,"ebp"));
+ &adc ("edi",&wparam(3)); # padbit
+
+ &mov (&DWP($h0,"esp"),"eax"); # put aside hash[+inp]
+ &mov (&DWP($h3,"esp"),"esi");
+
+ &mul (&DWP($r0,"esp")); # h0*r0
+ &mov (&DWP($h4,"esp"),"edi");
+ &mov ("edi","eax");
+ &mov ("eax","ebx"); # h1
+ &mov ("esi","edx");
+ &mul (&DWP($s3,"esp")); # h1*s3
+ &add ("edi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("esi","edx");
+ &mul (&DWP($s2,"esp")); # h2*s2
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("esi","edx");
+ &mul (&DWP($s1,"esp")); # h3*s1
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h0,"esp"));
+ &adc ("esi","edx");
+
+ &mul (&DWP($r1,"esp")); # h0*r1
+ &mov (&DWP($d0,"esp"),"edi");
+ &xor ("edi","edi");
+ &add ("esi","eax");
+ &mov ("eax","ebx"); # h1
+ &adc ("edi","edx");
+ &mul (&DWP($r0,"esp")); # h1*r0
+ &add ("esi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("edi","edx");
+ &mul (&DWP($s3,"esp")); # h2*s3
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("edi","edx");
+ &mul (&DWP($s2,"esp")); # h3*s2
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h4,"esp"));
+ &adc ("edi","edx");
+ &imul ("eax",&DWP($s1,"esp")); # h4*s1
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h0,"esp"));
+ &adc ("edi",0);
+
+ &mul (&DWP($r2,"esp")); # h0*r2
+ &mov (&DWP($d1,"esp"),"esi");
+ &xor ("esi","esi");
+ &add ("edi","eax");
+ &mov ("eax","ebx"); # h1
+ &adc ("esi","edx");
+ &mul (&DWP($r1,"esp")); # h1*r1
+ &add ("edi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("esi","edx");
+ &mul (&DWP($r0,"esp")); # h2*r0
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("esi","edx");
+ &mul (&DWP($s3,"esp")); # h3*s3
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h4,"esp"));
+ &adc ("esi","edx");
+ &imul ("eax",&DWP($s2,"esp")); # h4*s2
+ &add ("edi","eax");
+ &mov ("eax",&DWP($h0,"esp"));
+ &adc ("esi",0);
+
+ &mul (&DWP($r3,"esp")); # h0*r3
+ &mov (&DWP($d2,"esp"),"edi");
+ &xor ("edi","edi");
+ &add ("esi","eax");
+ &mov ("eax","ebx"); # h1
+ &adc ("edi","edx");
+ &mul (&DWP($r2,"esp")); # h1*r2
+ &add ("esi","eax");
+ &mov ("eax","ecx"); # h2
+ &adc ("edi","edx");
+ &mul (&DWP($r1,"esp")); # h2*r1
+ &add ("esi","eax");
+ &mov ("eax",&DWP($h3,"esp"));
+ &adc ("edi","edx");
+ &mul (&DWP($r0,"esp")); # h3*r0
+ &add ("esi","eax");
+ &mov ("ecx",&DWP($h4,"esp"));
+ &adc ("edi","edx");
+
+ &mov ("edx","ecx");
+ &imul ("ecx",&DWP($s3,"esp")); # h4*s3
+ &add ("esi","ecx");
+ &mov ("eax",&DWP($d0,"esp"));
+ &adc ("edi",0);
+
+ &imul ("edx",&DWP($r0,"esp")); # h4*r0
+ &add ("edx","edi");
+
+ &mov ("ebx",&DWP($d1,"esp"));
+ &mov ("ecx",&DWP($d2,"esp"));
+
+ &mov ("edi","edx"); # last reduction step
+ &shr ("edx",2);
+ &and ("edi",3);
+ &lea ("edx",&DWP(0,"edx","edx",4)); # *5
+ &add ("eax","edx");
+ &adc ("ebx",0);
+ &adc ("ecx",0);
+ &adc ("esi",0);
+
+ &cmp ("ebp",&wparam(2)); # done yet?
+ &jne (&label("loop"));
+
+ &mov ("edx",&wparam(0)); # ctx
+ &stack_pop(16);
+ &mov (&DWP(4*0,"edx"),"eax"); # store hash value
+ &mov (&DWP(4*1,"edx"),"ebx");
+ &mov (&DWP(4*2,"edx"),"ecx");
+ &mov (&DWP(4*3,"edx"),"esi");
+ &mov (&DWP(4*4,"edx"),"edi");
+&set_label("nodata");
+&function_end("poly1305_blocks");
+
+&function_begin("poly1305_emit");
+ &mov ("ebp",&wparam(0)); # context
+&set_label("enter_emit");
+ &mov ("edi",&wparam(1)); # output
+ &mov ("eax",&DWP(4*0,"ebp")); # load hash value
+ &mov ("ebx",&DWP(4*1,"ebp"));
+ &mov ("ecx",&DWP(4*2,"ebp"));
+ &mov ("edx",&DWP(4*3,"ebp"));
+ &mov ("esi",&DWP(4*4,"ebp"));
+
+ &add ("eax",5); # compare to modulus
+ &adc ("ebx",0);
+ &adc ("ecx",0);
+ &adc ("edx",0);
+ &adc ("esi",0);
+ &shr ("esi",2); # did it carry/borrow?
+ &neg ("esi"); # do we choose hash-modulus?
+
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &and ("ecx","esi");
+ &and ("edx","esi");
+ &mov (&DWP(4*0,"edi"),"eax");
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &mov (&DWP(4*3,"edi"),"edx");
+
+ &not ("esi"); # or original hash value?
+ &mov ("eax",&DWP(4*0,"ebp"));
+ &mov ("ebx",&DWP(4*1,"ebp"));
+ &mov ("ecx",&DWP(4*2,"ebp"));
+ &mov ("edx",&DWP(4*3,"ebp"));
+ &mov ("ebp",&wparam(2));
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &and ("ecx","esi");
+ &and ("edx","esi");
+ &or ("eax",&DWP(4*0,"edi"));
+ &or ("ebx",&DWP(4*1,"edi"));
+ &or ("ecx",&DWP(4*2,"edi"));
+ &or ("edx",&DWP(4*3,"edi"));
+
+ &add ("eax",&DWP(4*0,"ebp")); # accumulate key
+ &adc ("ebx",&DWP(4*1,"ebp"));
+ &adc ("ecx",&DWP(4*2,"ebp"));
+ &adc ("edx",&DWP(4*3,"ebp"));
+
+ &mov (&DWP(4*0,"edi"),"eax");
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &mov (&DWP(4*3,"edi"),"edx");
+&function_end("poly1305_emit");
+
+if ($sse2) {
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int32 h[5]; # current hash value base 2^26
+# unsigned __int32 is_base2_26;
+# unsigned __int32 r[4]; # key value base 2^32
+# unsigned __int32 pad[2];
+# struct { unsigned __int32 r^4, r^3, r^2, r^1; } r[9];
+#
+# where r^n are base 2^26 digits of degrees of multiplier key. There are
+# 5 digits, but last four are interleaved with multiples of 5, totalling
+# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4.
+
+my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("xmm$_",(0..7));
+my $MASK=$T2; # borrow and keep in mind
+
+&align (32);
+&function_begin_B("_poly1305_init_sse2");
+ &movdqu ($D4,&QWP(4*6,"edi")); # key base 2^32
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &mov ("ebp","esp");
+ &sub ("esp",16*(9+5));
+ &and ("esp",-16);
+
+ #&pand ($D4,&QWP(96,"ebx")); # magic mask
+ &movq ($MASK,&QWP(64,"ebx"));
+
+ &movdqa ($D0,$D4);
+ &movdqa ($D1,$D4);
+ &movdqa ($D2,$D4);
+
+ &pand ($D0,$MASK); # -> base 2^26
+ &psrlq ($D1,26);
+ &psrldq ($D2,6);
+ &pand ($D1,$MASK);
+ &movdqa ($D3,$D2);
+ &psrlq ($D2,4)
+ &psrlq ($D3,30);
+ &pand ($D2,$MASK);
+ &pand ($D3,$MASK);
+ &psrldq ($D4,13);
+
+ &lea ("edx",&DWP(16*9,"esp")); # size optimization
+ &mov ("ecx",2);
+&set_label("square");
+ &movdqa (&QWP(16*0,"esp"),$D0);
+ &movdqa (&QWP(16*1,"esp"),$D1);
+ &movdqa (&QWP(16*2,"esp"),$D2);
+ &movdqa (&QWP(16*3,"esp"),$D3);
+ &movdqa (&QWP(16*4,"esp"),$D4);
+
+ &movdqa ($T1,$D1);
+ &movdqa ($T0,$D2);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D1); # *5
+ &paddd ($T0,$D2); # *5
+ &movdqa (&QWP(16*5,"esp"),$T1);
+ &movdqa (&QWP(16*6,"esp"),$T0);
+ &movdqa ($T1,$D3);
+ &movdqa ($T0,$D4);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D3); # *5
+ &paddd ($T0,$D4); # *5
+ &movdqa (&QWP(16*7,"esp"),$T1);
+ &movdqa (&QWP(16*8,"esp"),$T0);
+
+ &pshufd ($T1,$D0,0b01000100);
+ &movdqa ($T0,$D1);
+ &pshufd ($D1,$D1,0b01000100);
+ &pshufd ($D2,$D2,0b01000100);
+ &pshufd ($D3,$D3,0b01000100);
+ &pshufd ($D4,$D4,0b01000100);
+ &movdqa (&QWP(16*0,"edx"),$T1);
+ &movdqa (&QWP(16*1,"edx"),$D1);
+ &movdqa (&QWP(16*2,"edx"),$D2);
+ &movdqa (&QWP(16*3,"edx"),$D3);
+ &movdqa (&QWP(16*4,"edx"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &pmuludq ($D4,$D0); # h4*r0
+ &pmuludq ($D3,$D0); # h3*r0
+ &pmuludq ($D2,$D0); # h2*r0
+ &pmuludq ($D1,$D0); # h1*r0
+ &pmuludq ($D0,$T1); # h0*r0
+
+sub pmuladd {
+my $load = shift;
+my $base = shift; $base = "esp" if (!defined($base));
+
+ ################################################################
+ # As for choice to "rotate" $T0-$T2 in order to move paddq
+ # past next multiplication. While it makes code harder to read
+ # and doesn't have significant effect on most processors, it
+ # makes a lot of difference on Atom, up to 30% improvement.
+
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*3,$base)); # r1*h3
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*2,$base)); # r1*h2
+ &paddq ($D4,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*1,$base)); # r1*h1
+ &paddq ($D3,$T1);
+ &$load ($T1,5); # s1
+ &pmuludq ($T0,&QWP(16*0,$base)); # r1*h0
+ &paddq ($D2,$T2);
+ &pmuludq ($T1,&QWP(16*4,$base)); # s1*h4
+ &$load ($T2,2); # r2^n
+ &paddq ($D1,$T0);
+
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*2,$base)); # r2*h2
+ &paddq ($D0,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*1,$base)); # r2*h1
+ &paddq ($D4,$T2);
+ &$load ($T2,6); # s2^n
+ &pmuludq ($T1,&QWP(16*0,$base)); # r2*h0
+ &paddq ($D3,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*4,$base)); # s2*h4
+ &paddq ($D2,$T1);
+ &pmuludq ($T0,&QWP(16*3,$base)); # s2*h3
+ &$load ($T1,3); # r3^n
+ &paddq ($D1,$T2);
+
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*1,$base)); # r3*h1
+ &paddq ($D0,$T0);
+ &$load ($T0,7); # s3^n
+ &pmuludq ($T2,&QWP(16*0,$base)); # r3*h0
+ &paddq ($D4,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*4,$base)); # s3*h4
+ &paddq ($D3,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*3,$base)); # s3*h3
+ &paddq ($D2,$T0);
+ &pmuludq ($T2,&QWP(16*2,$base)); # s3*h2
+ &$load ($T0,4); # r4^n
+ &paddq ($D1,$T1);
+
+ &$load ($T1,8); # s4^n
+ &pmuludq ($T0,&QWP(16*0,$base)); # r4*h0
+ &paddq ($D0,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&QWP(16*4,$base)); # s4*h4
+ &paddq ($D4,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&QWP(16*1,$base)); # s4*h1
+ &paddq ($D3,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&QWP(16*2,$base)); # s4*h2
+ &paddq ($D0,$T2);
+ &pmuludq ($T1,&QWP(16*3,$base)); # s4*h3
+ &movdqa ($MASK,&QWP(64,"ebx"));
+ &paddq ($D1,$T0);
+ &paddq ($D2,$T1);
+}
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &movdqa ($reg,&QWP(16*$i,"esp"));
+ },"edx");
+
+sub lazy_reduction {
+my $extra = shift;
+my $paddx = defined($extra) ? paddq : paddd;
+
+ ################################################################
+ # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ # and P. Schwabe
+
+ &movdqa ($T0,$D3);
+ &pand ($D3,$MASK);
+ &psrlq ($T0,26);
+ &$extra () if (defined($extra));
+ &paddq ($T0,$D4); # h3 -> h4
+ &movdqa ($T1,$D0);
+ &pand ($D0,$MASK);
+ &psrlq ($T1,26);
+ &movdqa ($D4,$T0);
+ &paddq ($T1,$D1); # h0 -> h1
+ &psrlq ($T0,26);
+ &pand ($D4,$MASK);
+ &movdqa ($D1,$T1);
+ &psrlq ($T1,26);
+ &paddd ($D0,$T0); # favour paddd when
+ # possible, because
+ # paddq is "broken"
+ # on Atom
+ &psllq ($T0,2);
+ &paddq ($T1,$D2); # h1 -> h2
+ &$paddx ($T0,$D0); # h4 -> h0
+ &pand ($D1,$MASK);
+ &movdqa ($D2,$T1);
+ &psrlq ($T1,26);
+ &pand ($D2,$MASK);
+ &paddd ($T1,$D3); # h2 -> h3
+ &movdqa ($D0,$T0);
+ &psrlq ($T0,26);
+ &movdqa ($D3,$T1);
+ &psrlq ($T1,26);
+ &pand ($D0,$MASK);
+ &paddd ($D1,$T0); # h0 -> h1
+ &pand ($D3,$MASK);
+ &paddd ($D4,$T1); # h3 -> h4
+}
+ &lazy_reduction ();
+
+ &dec ("ecx");
+ &jz (&label("square_break"));
+
+ &punpcklqdq ($D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2
+ &punpcklqdq ($D1,&QWP(16*1,"esp"));
+ &punpcklqdq ($D2,&QWP(16*2,"esp"));
+ &punpcklqdq ($D3,&QWP(16*3,"esp"));
+ &punpcklqdq ($D4,&QWP(16*4,"esp"));
+ &jmp (&label("square"));
+
+&set_label("square_break");
+ &psllq ($D0,32); # -> r^3:0:r^4:0
+ &psllq ($D1,32);
+ &psllq ($D2,32);
+ &psllq ($D3,32);
+ &psllq ($D4,32);
+ &por ($D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2
+ &por ($D1,&QWP(16*1,"esp"));
+ &por ($D2,&QWP(16*2,"esp"));
+ &por ($D3,&QWP(16*3,"esp"));
+ &por ($D4,&QWP(16*4,"esp"));
+
+ &pshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4
+ &pshufd ($D1,$D1,0b10001101);
+ &pshufd ($D2,$D2,0b10001101);
+ &pshufd ($D3,$D3,0b10001101);
+ &pshufd ($D4,$D4,0b10001101);
+
+ &movdqu (&QWP(16*0,"edi"),$D0); # save the table
+ &movdqu (&QWP(16*1,"edi"),$D1);
+ &movdqu (&QWP(16*2,"edi"),$D2);
+ &movdqu (&QWP(16*3,"edi"),$D3);
+ &movdqu (&QWP(16*4,"edi"),$D4);
+
+ &movdqa ($T1,$D1);
+ &movdqa ($T0,$D2);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D1); # *5
+ &paddd ($T0,$D2); # *5
+ &movdqu (&QWP(16*5,"edi"),$T1);
+ &movdqu (&QWP(16*6,"edi"),$T0);
+ &movdqa ($T1,$D3);
+ &movdqa ($T0,$D4);
+ &pslld ($T1,2);
+ &pslld ($T0,2);
+ &paddd ($T1,$D3); # *5
+ &paddd ($T0,$D4); # *5
+ &movdqu (&QWP(16*7,"edi"),$T1);
+ &movdqu (&QWP(16*8,"edi"),$T0);
+
+ &mov ("esp","ebp");
+ &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization
+ &ret ();
+&function_end_B("_poly1305_init_sse2");
+
+&align (32);
+&function_begin("_poly1305_blocks_sse2");
+ &mov ("edi",&wparam(0)); # ctx
+ &mov ("esi",&wparam(1)); # inp
+ &mov ("ecx",&wparam(2)); # len
+
+ &mov ("eax",&DWP(4*5,"edi")); # is_base2_26
+ &and ("ecx",-16);
+ &jz (&label("nodata"));
+ &cmp ("ecx",64);
+ &jae (&label("enter_sse2"));
+ &test ("eax","eax"); # is_base2_26?
+ &jz (&label("enter_blocks"));
+
+&set_label("enter_sse2",16);
+ &call (&label("pic_point"));
+&set_label("pic_point");
+ &blindpop("ebx");
+ &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx"));
+
+ &test ("eax","eax"); # is_base2_26?
+ &jnz (&label("base2_26"));
+
+ &call ("_poly1305_init_sse2");
+
+ ################################################# base 2^32 -> base 2^26
+ &mov ("eax",&DWP(0,"edi"));
+ &mov ("ecx",&DWP(3,"edi"));
+ &mov ("edx",&DWP(6,"edi"));
+ &mov ("esi",&DWP(9,"edi"));
+ &mov ("ebp",&DWP(13,"edi"));
+ &mov (&DWP(4*5,"edi"),1); # is_base2_26
+
+ &shr ("ecx",2);
+ &and ("eax",0x3ffffff);
+ &shr ("edx",4);
+ &and ("ecx",0x3ffffff);
+ &shr ("esi",6);
+ &and ("edx",0x3ffffff);
+
+ &movd ($D0,"eax");
+ &movd ($D1,"ecx");
+ &movd ($D2,"edx");
+ &movd ($D3,"esi");
+ &movd ($D4,"ebp");
+
+ &mov ("esi",&wparam(1)); # [reload] inp
+ &mov ("ecx",&wparam(2)); # [reload] len
+ &jmp (&label("base2_32"));
+
+&set_label("base2_26",16);
+ &movd ($D0,&DWP(4*0,"edi")); # load hash value
+ &movd ($D1,&DWP(4*1,"edi"));
+ &movd ($D2,&DWP(4*2,"edi"));
+ &movd ($D3,&DWP(4*3,"edi"));
+ &movd ($D4,&DWP(4*4,"edi"));
+ &movdqa ($MASK,&QWP(64,"ebx"));
+
+&set_label("base2_32");
+ &mov ("eax",&wparam(3)); # padbit
+ &mov ("ebp","esp");
+
+ &sub ("esp",16*(5+5+5+9+9));
+ &and ("esp",-16);
+
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &shl ("eax",24); # padbit
+
+ &test ("ecx",31);
+ &jz (&label("even"));
+
+ ################################################################
+ # process single block, with SSE2, because it's still faster
+ # even though half of result is discarded
+
+ &movdqu ($T1,&QWP(0,"esi")); # input
+ &lea ("esi",&DWP(16,"esi"));
+
+ &movdqa ($T0,$T1); # -> base 2^26 ...
+ &pand ($T1,$MASK);
+ &paddd ($D0,$T1); # ... and accumuate
+
+ &movdqa ($T1,$T0);
+ &psrlq ($T0,26);
+ &psrldq ($T1,6);
+ &pand ($T0,$MASK);
+ &paddd ($D1,$T0);
+
+ &movdqa ($T0,$T1);
+ &psrlq ($T1,4);
+ &pand ($T1,$MASK);
+ &paddd ($D2,$T1);
+
+ &movdqa ($T1,$T0);
+ &psrlq ($T0,30);
+ &pand ($T0,$MASK);
+ &psrldq ($T1,7);
+ &paddd ($D3,$T0);
+
+ &movd ($T0,"eax"); # padbit
+ &paddd ($D4,$T1);
+ &movd ($T1,&DWP(16*0+12,"edi")); # r0
+ &paddd ($D4,$T0);
+
+ &movdqa (&QWP(16*0,"esp"),$D0);
+ &movdqa (&QWP(16*1,"esp"),$D1);
+ &movdqa (&QWP(16*2,"esp"),$D2);
+ &movdqa (&QWP(16*3,"esp"),$D3);
+ &movdqa (&QWP(16*4,"esp"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &pmuludq ($D0,$T1); # h4*r0
+ &pmuludq ($D1,$T1); # h3*r0
+ &pmuludq ($D2,$T1); # h2*r0
+ &movd ($T0,&DWP(16*1+12,"edi")); # r1
+ &pmuludq ($D3,$T1); # h1*r0
+ &pmuludq ($D4,$T1); # h0*r0
+
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &movd ($reg,&DWP(16*$i+12,"edi"));
+ });
+
+ &lazy_reduction ();
+
+ &sub ("ecx",16);
+ &jz (&label("done"));
+
+&set_label("even");
+ &lea ("edx",&DWP(16*(5+5+5+9),"esp"));# size optimization
+ &lea ("eax",&DWP(-16*2,"esi"));
+ &sub ("ecx",64);
+
+ ################################################################
+ # expand and copy pre-calculated table to stack
+
+ &movdqu ($T0,&QWP(16*0,"edi")); # r^1:r^2:r^3:r^4
+ &pshufd ($T1,$T0,0b01000100); # duplicate r^3:r^4
+ &cmovb ("esi","eax");
+ &pshufd ($T0,$T0,0b11101110); # duplicate r^1:r^2
+ &movdqa (&QWP(16*0,"edx"),$T1);
+ &lea ("eax",&DWP(16*10,"esp"));
+ &movdqu ($T1,&QWP(16*1,"edi"));
+ &movdqa (&QWP(16*(0-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*1,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*2,"edi"));
+ &movdqa (&QWP(16*(1-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*2,"edx"),$T1);
+ &movdqu ($T1,&QWP(16*3,"edi"));
+ &movdqa (&QWP(16*(2-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*3,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*4,"edi"));
+ &movdqa (&QWP(16*(3-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*4,"edx"),$T1);
+ &movdqu ($T1,&QWP(16*5,"edi"));
+ &movdqa (&QWP(16*(4-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*5,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*6,"edi"));
+ &movdqa (&QWP(16*(5-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*6,"edx"),$T1);
+ &movdqu ($T1,&QWP(16*7,"edi"));
+ &movdqa (&QWP(16*(6-9),"edx"),$T0);
+ &pshufd ($T0,$T1,0b01000100);
+ &pshufd ($T1,$T1,0b11101110);
+ &movdqa (&QWP(16*7,"edx"),$T0);
+ &movdqu ($T0,&QWP(16*8,"edi"));
+ &movdqa (&QWP(16*(7-9),"edx"),$T1);
+ &pshufd ($T1,$T0,0b01000100);
+ &pshufd ($T0,$T0,0b11101110);
+ &movdqa (&QWP(16*8,"edx"),$T1);
+ &movdqa (&QWP(16*(8-9),"edx"),$T0);
+
+sub load_input {
+my ($inpbase,$offbase)=@_;
+
+ &movdqu ($T0,&QWP($inpbase+0,"esi")); # load input
+ &movdqu ($T1,&QWP($inpbase+16,"esi"));
+ &lea ("esi",&DWP(16*2,"esi"));
+
+ &movdqa (&QWP($offbase+16*2,"esp"),$D2);
+ &movdqa (&QWP($offbase+16*3,"esp"),$D3);
+ &movdqa (&QWP($offbase+16*4,"esp"),$D4);
+
+ &movdqa ($D2,$T0); # splat input
+ &movdqa ($D3,$T1);
+ &psrldq ($D2,6);
+ &psrldq ($D3,6);
+ &movdqa ($D4,$T0);
+ &punpcklqdq ($D2,$D3); # 2:3
+ &punpckhqdq ($D4,$T1); # 4
+ &punpcklqdq ($T0,$T1); # 0:1
+
+ &movdqa ($D3,$D2);
+ &psrlq ($D2,4);
+ &psrlq ($D3,30);
+ &movdqa ($T1,$T0);
+ &psrlq ($D4,40); # 4
+ &psrlq ($T1,26);
+ &pand ($T0,$MASK); # 0
+ &pand ($T1,$MASK); # 1
+ &pand ($D2,$MASK); # 2
+ &pand ($D3,$MASK); # 3
+ &por ($D4,&QWP(0,"ebx")); # padbit, yes, always
+
+ &movdqa (&QWP($offbase+16*0,"esp"),$D0) if ($offbase);
+ &movdqa (&QWP($offbase+16*1,"esp"),$D1) if ($offbase);
+}
+ &load_input (16*2,16*5);
+
+ &jbe (&label("skip_loop"));
+ &jmp (&label("loop"));
+
+&set_label("loop",32);
+ ################################################################
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ # \___________________/
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ # \___________________/ \____________________/
+ ################################################################
+
+ &movdqa ($T2,&QWP(16*(0-9),"edx")); # r0^2
+ &movdqa (&QWP(16*1,"eax"),$T1);
+ &movdqa (&QWP(16*2,"eax"),$D2);
+ &movdqa (&QWP(16*3,"eax"),$D3);
+ &movdqa (&QWP(16*4,"eax"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1
+ # d3 = h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4
+ # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3
+ # d1 = h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2
+ # d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1
+
+ &movdqa ($D1,$T0);
+ &pmuludq ($T0,$T2); # h0*r0
+ &movdqa ($D0,$T1);
+ &pmuludq ($T1,$T2); # h1*r0
+ &pmuludq ($D2,$T2); # h2*r0
+ &pmuludq ($D3,$T2); # h3*r0
+ &pmuludq ($D4,$T2); # h4*r0
+
+sub pmuladd_alt {
+my $addr = shift;
+
+ &pmuludq ($D0,&$addr(8)); # h1*s4
+ &movdqa ($T2,$D1);
+ &pmuludq ($D1,&$addr(1)); # h0*r1
+ &paddq ($D0,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(2)); # h0*r2
+ &paddq ($D1,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(3)); # h0*r3
+ &paddq ($D2,$T2);
+ &movdqa ($T2,&QWP(16*1,"eax")); # pull h1
+ &pmuludq ($T1,&$addr(4)); # h0*r4
+ &paddq ($D3,$T0);
+
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(1)); # h1*r1
+ &paddq ($D4,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(2)); # h1*r2
+ &paddq ($D2,$T2);
+ &movdqa ($T2,&QWP(16*2,"eax")); # pull h2
+ &pmuludq ($T1,&$addr(3)); # h1*r3
+ &paddq ($D3,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(7)); # h2*s3
+ &paddq ($D4,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(8)); # h2*s4
+ &paddq ($D0,$T2);
+
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&$addr(1)); # h2*r1
+ &paddq ($D1,$T0);
+ &movdqa ($T0,&QWP(16*3,"eax")); # pull h3
+ &pmuludq ($T2,&$addr(2)); # h2*r2
+ &paddq ($D3,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(6)); # h3*s2
+ &paddq ($D4,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&$addr(7)); # h3*s3
+ &paddq ($D0,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(8)); # h3*s4
+ &paddq ($D1,$T1);
+
+ &movdqa ($T1,&QWP(16*4,"eax")); # pull h4
+ &pmuludq ($T0,&$addr(1)); # h3*r1
+ &paddq ($D2,$T2);
+ &movdqa ($T2,$T1);
+ &pmuludq ($T1,&$addr(8)); # h4*s4
+ &paddq ($D4,$T0);
+ &movdqa ($T0,$T2);
+ &pmuludq ($T2,&$addr(5)); # h4*s1
+ &paddq ($D3,$T1);
+ &movdqa ($T1,$T0);
+ &pmuludq ($T0,&$addr(6)); # h4*s2
+ &paddq ($D0,$T2);
+ &movdqa ($MASK,&QWP(64,"ebx"));
+ &pmuludq ($T1,&$addr(7)); # h4*s3
+ &paddq ($D1,$T0);
+ &paddq ($D2,$T1);
+}
+ &pmuladd_alt (sub { my $i=shift; &QWP(16*($i-9),"edx"); });
+
+ &load_input (-16*2,0);
+ &lea ("eax",&DWP(-16*2,"esi"));
+ &sub ("ecx",64);
+
+ &paddd ($T0,&QWP(16*(5+0),"esp")); # add hash value
+ &paddd ($T1,&QWP(16*(5+1),"esp"));
+ &paddd ($D2,&QWP(16*(5+2),"esp"));
+ &paddd ($D3,&QWP(16*(5+3),"esp"));
+ &paddd ($D4,&QWP(16*(5+4),"esp"));
+
+ &cmovb ("esi","eax");
+ &lea ("eax",&DWP(16*10,"esp"));
+
+ &movdqa ($T2,&QWP(16*0,"edx")); # r0^4
+ &movdqa (&QWP(16*1,"esp"),$D1);
+ &movdqa (&QWP(16*1,"eax"),$T1);
+ &movdqa (&QWP(16*2,"eax"),$D2);
+ &movdqa (&QWP(16*3,"eax"),$D3);
+ &movdqa (&QWP(16*4,"eax"),$D4);
+
+ ################################################################
+ # d4 += h4*r0 + h0*r4 + h1*r3 + h2*r2 + h3*r1
+ # d3 += h3*r0 + h0*r3 + h1*r2 + h2*r1 + h4*5*r4
+ # d2 += h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3
+ # d1 += h1*r0 + h0*r1 + h2*5*r4 + h3*5*r3 + h4*5*r2
+ # d0 += h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1
+
+ &movdqa ($D1,$T0);
+ &pmuludq ($T0,$T2); # h0*r0
+ &paddq ($T0,$D0);
+ &movdqa ($D0,$T1);
+ &pmuludq ($T1,$T2); # h1*r0
+ &pmuludq ($D2,$T2); # h2*r0
+ &pmuludq ($D3,$T2); # h3*r0
+ &pmuludq ($D4,$T2); # h4*r0
+
+ &paddq ($T1,&QWP(16*1,"esp"));
+ &paddq ($D2,&QWP(16*2,"esp"));
+ &paddq ($D3,&QWP(16*3,"esp"));
+ &paddq ($D4,&QWP(16*4,"esp"));
+
+ &pmuladd_alt (sub { my $i=shift; &QWP(16*$i,"edx"); });
+
+ &lazy_reduction ();
+
+ &load_input (16*2,16*5);
+
+ &ja (&label("loop"));
+
+&set_label("skip_loop");
+ ################################################################
+ # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ &pshufd ($T2,&QWP(16*(0-9),"edx"),0x10);# r0^n
+ &add ("ecx",32);
+ &jnz (&label("long_tail"));
+
+ &paddd ($T0,$D0); # add hash value
+ &paddd ($T1,$D1);
+ &paddd ($D2,&QWP(16*7,"esp"));
+ &paddd ($D3,&QWP(16*8,"esp"));
+ &paddd ($D4,&QWP(16*9,"esp"));
+
+&set_label("long_tail");
+
+ &movdqa (&QWP(16*0,"eax"),$T0);
+ &movdqa (&QWP(16*1,"eax"),$T1);
+ &movdqa (&QWP(16*2,"eax"),$D2);
+ &movdqa (&QWP(16*3,"eax"),$D3);
+ &movdqa (&QWP(16*4,"eax"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &pmuludq ($T0,$T2); # h0*r0
+ &pmuludq ($T1,$T2); # h1*r0
+ &pmuludq ($D2,$T2); # h2*r0
+ &movdqa ($D0,$T0);
+ &pshufd ($T0,&QWP(16*(1-9),"edx"),0x10);# r1^n
+ &pmuludq ($D3,$T2); # h3*r0
+ &movdqa ($D1,$T1);
+ &pmuludq ($D4,$T2); # h4*r0
+
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &pshufd ($reg,&QWP(16*($i-9),"edx"),0x10);
+ },"eax");
+
+ &jz (&label("short_tail"));
+
+ &load_input (-16*2,0);
+
+ &pshufd ($T2,&QWP(16*0,"edx"),0x10); # r0^n
+ &paddd ($T0,&QWP(16*5,"esp")); # add hash value
+ &paddd ($T1,&QWP(16*6,"esp"));
+ &paddd ($D2,&QWP(16*7,"esp"));
+ &paddd ($D3,&QWP(16*8,"esp"));
+ &paddd ($D4,&QWP(16*9,"esp"));
+
+ ################################################################
+ # multiply inp[0:1] by r^4:r^3 and accumulate
+
+ &movdqa (&QWP(16*0,"esp"),$T0);
+ &pmuludq ($T0,$T2); # h0*r0
+ &movdqa (&QWP(16*1,"esp"),$T1);
+ &pmuludq ($T1,$T2); # h1*r0
+ &paddq ($D0,$T0);
+ &movdqa ($T0,$D2);
+ &pmuludq ($D2,$T2); # h2*r0
+ &paddq ($D1,$T1);
+ &movdqa ($T1,$D3);
+ &pmuludq ($D3,$T2); # h3*r0
+ &paddq ($D2,&QWP(16*2,"esp"));
+ &movdqa (&QWP(16*2,"esp"),$T0);
+ &pshufd ($T0,&QWP(16*1,"edx"),0x10); # r1^n
+ &paddq ($D3,&QWP(16*3,"esp"));
+ &movdqa (&QWP(16*3,"esp"),$T1);
+ &movdqa ($T1,$D4);
+ &pmuludq ($D4,$T2); # h4*r0
+ &paddq ($D4,&QWP(16*4,"esp"));
+ &movdqa (&QWP(16*4,"esp"),$T1);
+
+ &pmuladd (sub { my ($reg,$i)=@_;
+ &pshufd ($reg,&QWP(16*$i,"edx"),0x10);
+ });
+
+&set_label("short_tail");
+
+ ################################################################
+ # horizontal addition
+
+ &pshufd ($T1,$D4,0b01001110);
+ &pshufd ($T0,$D3,0b01001110);
+ &paddq ($D4,$T1);
+ &paddq ($D3,$T0);
+ &pshufd ($T1,$D0,0b01001110);
+ &pshufd ($T0,$D1,0b01001110);
+ &paddq ($D0,$T1);
+ &paddq ($D1,$T0);
+ &pshufd ($T1,$D2,0b01001110);
+ #&paddq ($D2,$T1);
+
+ &lazy_reduction (sub { &paddq ($D2,$T1) });
+
+&set_label("done");
+ &movd (&DWP(-16*3+4*0,"edi"),$D0); # store hash value
+ &movd (&DWP(-16*3+4*1,"edi"),$D1);
+ &movd (&DWP(-16*3+4*2,"edi"),$D2);
+ &movd (&DWP(-16*3+4*3,"edi"),$D3);
+ &movd (&DWP(-16*3+4*4,"edi"),$D4);
+ &mov ("esp","ebp");
+&set_label("nodata");
+&function_end("_poly1305_blocks_sse2");
+
+&align (32);
+&function_begin("_poly1305_emit_sse2");
+ &mov ("ebp",&wparam(0)); # context
+
+ &cmp (&DWP(4*5,"ebp"),0); # is_base2_26?
+ &je (&label("enter_emit"));
+
+ &mov ("eax",&DWP(4*0,"ebp")); # load hash value
+ &mov ("edi",&DWP(4*1,"ebp"));
+ &mov ("ecx",&DWP(4*2,"ebp"));
+ &mov ("edx",&DWP(4*3,"ebp"));
+ &mov ("esi",&DWP(4*4,"ebp"));
+
+ &mov ("ebx","edi"); # base 2^26 -> base 2^32
+ &shl ("edi",26);
+ &shr ("ebx",6);
+ &add ("eax","edi");
+ &mov ("edi","ecx");
+ &adc ("ebx",0);
+
+ &shl ("edi",20);
+ &shr ("ecx",12);
+ &add ("ebx","edi");
+ &mov ("edi","edx");
+ &adc ("ecx",0);
+
+ &shl ("edi",14);
+ &shr ("edx",18);
+ &add ("ecx","edi");
+ &mov ("edi","esi");
+ &adc ("edx",0);
+
+ &shl ("edi",8);
+ &shr ("esi",24);
+ &add ("edx","edi");
+ &adc ("esi",0); # can be partially reduced
+
+ &mov ("edi","esi"); # final reduction
+ &and ("esi",3);
+ &shr ("edi",2);
+ &lea ("ebp",&DWP(0,"edi","edi",4)); # *5
+ &mov ("edi",&wparam(1)); # output
+ add ("eax","ebp");
+ &mov ("ebp",&wparam(2)); # key
+ adc ("ebx",0);
+ adc ("ecx",0);
+ adc ("edx",0);
+
+ &movd ($D0,"eax"); # offload original hash value
+ &add ("eax",5); # compare to modulus
+ &movd ($D1,"ebx");
+ &adc ("ebx",0);
+ &movd ($D2,"ecx");
+ &adc ("ecx",0);
+ &movd ($D3,"edx");
+ &adc ("edx",0);
+ &adc ("esi",0);
+ &shr ("esi",2); # did it carry/borrow?
+
+ &neg ("esi"); # do we choose (hash-modulus) ...
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &and ("ecx","esi");
+ &and ("edx","esi");
+ &mov (&DWP(4*0,"edi"),"eax");
+ &movd ("eax",$D0);
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &movd ("ebx",$D1);
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &movd ("ecx",$D2);
+ &mov (&DWP(4*3,"edi"),"edx");
+ &movd ("edx",$D3);
+
+ &not ("esi"); # ... or original hash value?
+ &and ("eax","esi");
+ &and ("ebx","esi");
+ &or ("eax",&DWP(4*0,"edi"));
+ &and ("ecx","esi");
+ &or ("ebx",&DWP(4*1,"edi"));
+ &and ("edx","esi");
+ &or ("ecx",&DWP(4*2,"edi"));
+ &or ("edx",&DWP(4*3,"edi"));
+
+ &add ("eax",&DWP(4*0,"ebp")); # accumulate key
+ &adc ("ebx",&DWP(4*1,"ebp"));
+ &mov (&DWP(4*0,"edi"),"eax");
+ &adc ("ecx",&DWP(4*2,"ebp"));
+ &mov (&DWP(4*1,"edi"),"ebx");
+ &adc ("edx",&DWP(4*3,"ebp"));
+ &mov (&DWP(4*2,"edi"),"ecx");
+ &mov (&DWP(4*3,"edi"),"edx");
+&function_end("_poly1305_emit_sse2");
+
+if ($avx>1) {
+########################################################################
+# Note that poly1305_init_avx2 operates on %xmm, I could have used
+# poly1305_init_sse2...
+
+&align (32);
+&function_begin_B("_poly1305_init_avx2");
+ &vmovdqu ($D4,&QWP(4*6,"edi")); # key base 2^32
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &mov ("ebp","esp");
+ &sub ("esp",16*(9+5));
+ &and ("esp",-16);
+
+ #&vpand ($D4,$D4,&QWP(96,"ebx")); # magic mask
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+
+ &vpand ($D0,$D4,$MASK); # -> base 2^26
+ &vpsrlq ($D1,$D4,26);
+ &vpsrldq ($D3,$D4,6);
+ &vpand ($D1,$D1,$MASK);
+ &vpsrlq ($D2,$D3,4)
+ &vpsrlq ($D3,$D3,30);
+ &vpand ($D2,$D2,$MASK);
+ &vpand ($D3,$D3,$MASK);
+ &vpsrldq ($D4,$D4,13);
+
+ &lea ("edx",&DWP(16*9,"esp")); # size optimization
+ &mov ("ecx",2);
+&set_label("square");
+ &vmovdqa (&QWP(16*0,"esp"),$D0);
+ &vmovdqa (&QWP(16*1,"esp"),$D1);
+ &vmovdqa (&QWP(16*2,"esp"),$D2);
+ &vmovdqa (&QWP(16*3,"esp"),$D3);
+ &vmovdqa (&QWP(16*4,"esp"),$D4);
+
+ &vpslld ($T1,$D1,2);
+ &vpslld ($T0,$D2,2);
+ &vpaddd ($T1,$T1,$D1); # *5
+ &vpaddd ($T0,$T0,$D2); # *5
+ &vmovdqa (&QWP(16*5,"esp"),$T1);
+ &vmovdqa (&QWP(16*6,"esp"),$T0);
+ &vpslld ($T1,$D3,2);
+ &vpslld ($T0,$D4,2);
+ &vpaddd ($T1,$T1,$D3); # *5
+ &vpaddd ($T0,$T0,$D4); # *5
+ &vmovdqa (&QWP(16*7,"esp"),$T1);
+ &vmovdqa (&QWP(16*8,"esp"),$T0);
+
+ &vpshufd ($T0,$D0,0b01000100);
+ &vmovdqa ($T1,$D1);
+ &vpshufd ($D1,$D1,0b01000100);
+ &vpshufd ($D2,$D2,0b01000100);
+ &vpshufd ($D3,$D3,0b01000100);
+ &vpshufd ($D4,$D4,0b01000100);
+ &vmovdqa (&QWP(16*0,"edx"),$T0);
+ &vmovdqa (&QWP(16*1,"edx"),$D1);
+ &vmovdqa (&QWP(16*2,"edx"),$D2);
+ &vmovdqa (&QWP(16*3,"edx"),$D3);
+ &vmovdqa (&QWP(16*4,"edx"),$D4);
+
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ &vpmuludq ($D4,$D4,$D0); # h4*r0
+ &vpmuludq ($D3,$D3,$D0); # h3*r0
+ &vpmuludq ($D2,$D2,$D0); # h2*r0
+ &vpmuludq ($D1,$D1,$D0); # h1*r0
+ &vpmuludq ($D0,$T0,$D0); # h0*r0
+
+ &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # r1*h3
+ &vpaddq ($D4,$D4,$T0);
+ &vpmuludq ($T2,$T1,&QWP(16*2,"edx")); # r1*h2
+ &vpaddq ($D3,$D3,$T2);
+ &vpmuludq ($T0,$T1,&QWP(16*1,"edx")); # r1*h1
+ &vpaddq ($D2,$D2,$T0);
+ &vmovdqa ($T2,&QWP(16*5,"esp")); # s1
+ &vpmuludq ($T1,$T1,&QWP(16*0,"edx")); # r1*h0
+ &vpaddq ($D1,$D1,$T1);
+ &vmovdqa ($T0,&QWP(16*2,"esp")); # r2
+ &vpmuludq ($T2,$T2,&QWP(16*4,"edx")); # s1*h4
+ &vpaddq ($D0,$D0,$T2);
+
+ &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # r2*h2
+ &vpaddq ($D4,$D4,$T1);
+ &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r2*h1
+ &vpaddq ($D3,$D3,$T2);
+ &vmovdqa ($T1,&QWP(16*6,"esp")); # s2
+ &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r2*h0
+ &vpaddq ($D2,$D2,$T0);
+ &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s2*h4
+ &vpaddq ($D1,$D1,$T2);
+ &vmovdqa ($T0,&QWP(16*3,"esp")); # r3
+ &vpmuludq ($T1,$T1,&QWP(16*3,"edx")); # s2*h3
+ &vpaddq ($D0,$D0,$T1);
+
+ &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # r3*h1
+ &vpaddq ($D4,$D4,$T2);
+ &vmovdqa ($T1,&QWP(16*7,"esp")); # s3
+ &vpmuludq ($T0,$T0,&QWP(16*0,"edx")); # r3*h0
+ &vpaddq ($D3,$D3,$T0);
+ &vpmuludq ($T2,$T1,&QWP(16*4,"edx")); # s3*h4
+ &vpaddq ($D2,$D2,$T2);
+ &vpmuludq ($T0,$T1,&QWP(16*3,"edx")); # s3*h3
+ &vpaddq ($D1,$D1,$T0);
+ &vmovdqa ($T2,&QWP(16*4,"esp")); # r4
+ &vpmuludq ($T1,$T1,&QWP(16*2,"edx")); # s3*h2
+ &vpaddq ($D0,$D0,$T1);
+
+ &vmovdqa ($T0,&QWP(16*8,"esp")); # s4
+ &vpmuludq ($T2,$T2,&QWP(16*0,"edx")); # r4*h0
+ &vpaddq ($D4,$D4,$T2);
+ &vpmuludq ($T1,$T0,&QWP(16*4,"edx")); # s4*h4
+ &vpaddq ($D3,$D3,$T1);
+ &vpmuludq ($T2,$T0,&QWP(16*1,"edx")); # s4*h1
+ &vpaddq ($D0,$D0,$T2);
+ &vpmuludq ($T1,$T0,&QWP(16*2,"edx")); # s4*h2
+ &vpaddq ($D1,$D1,$T1);
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+ &vpmuludq ($T0,$T0,&QWP(16*3,"edx")); # s4*h3
+ &vpaddq ($D2,$D2,$T0);
+
+ ################################################################
+ # lazy reduction
+ &vpsrlq ($T0,$D3,26);
+ &vpand ($D3,$D3,$MASK);
+ &vpsrlq ($T1,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpaddq ($D4,$D4,$T0); # h3 -> h4
+ &vpaddq ($D1,$D1,$T1); # h0 -> h1
+ &vpsrlq ($T0,$D4,26);
+ &vpand ($D4,$D4,$MASK);
+ &vpsrlq ($T1,$D1,26);
+ &vpand ($D1,$D1,$MASK);
+ &vpaddq ($D2,$D2,$T1); # h1 -> h2
+ &vpaddd ($D0,$D0,$T0);
+ &vpsllq ($T0,$T0,2);
+ &vpsrlq ($T1,$D2,26);
+ &vpand ($D2,$D2,$MASK);
+ &vpaddd ($D0,$D0,$T0); # h4 -> h0
+ &vpaddd ($D3,$D3,$T1); # h2 -> h3
+ &vpsrlq ($T1,$D3,26);
+ &vpsrlq ($T0,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpand ($D3,$D3,$MASK);
+ &vpaddd ($D1,$D1,$T0); # h0 -> h1
+ &vpaddd ($D4,$D4,$T1); # h3 -> h4
+
+ &dec ("ecx");
+ &jz (&label("square_break"));
+
+ &vpunpcklqdq ($D0,$D0,&QWP(16*0,"esp")); # 0:r^1:0:r^2
+ &vpunpcklqdq ($D1,$D1,&QWP(16*1,"esp"));
+ &vpunpcklqdq ($D2,$D2,&QWP(16*2,"esp"));
+ &vpunpcklqdq ($D3,$D3,&QWP(16*3,"esp"));
+ &vpunpcklqdq ($D4,$D4,&QWP(16*4,"esp"));
+ &jmp (&label("square"));
+
+&set_label("square_break");
+ &vpsllq ($D0,$D0,32); # -> r^3:0:r^4:0
+ &vpsllq ($D1,$D1,32);
+ &vpsllq ($D2,$D2,32);
+ &vpsllq ($D3,$D3,32);
+ &vpsllq ($D4,$D4,32);
+ &vpor ($D0,$D0,&QWP(16*0,"esp")); # r^3:r^1:r^4:r^2
+ &vpor ($D1,$D1,&QWP(16*1,"esp"));
+ &vpor ($D2,$D2,&QWP(16*2,"esp"));
+ &vpor ($D3,$D3,&QWP(16*3,"esp"));
+ &vpor ($D4,$D4,&QWP(16*4,"esp"));
+
+ &vpshufd ($D0,$D0,0b10001101); # -> r^1:r^2:r^3:r^4
+ &vpshufd ($D1,$D1,0b10001101);
+ &vpshufd ($D2,$D2,0b10001101);
+ &vpshufd ($D3,$D3,0b10001101);
+ &vpshufd ($D4,$D4,0b10001101);
+
+ &vmovdqu (&QWP(16*0,"edi"),$D0); # save the table
+ &vmovdqu (&QWP(16*1,"edi"),$D1);
+ &vmovdqu (&QWP(16*2,"edi"),$D2);
+ &vmovdqu (&QWP(16*3,"edi"),$D3);
+ &vmovdqu (&QWP(16*4,"edi"),$D4);
+
+ &vpslld ($T1,$D1,2);
+ &vpslld ($T0,$D2,2);
+ &vpaddd ($T1,$T1,$D1); # *5
+ &vpaddd ($T0,$T0,$D2); # *5
+ &vmovdqu (&QWP(16*5,"edi"),$T1);
+ &vmovdqu (&QWP(16*6,"edi"),$T0);
+ &vpslld ($T1,$D3,2);
+ &vpslld ($T0,$D4,2);
+ &vpaddd ($T1,$T1,$D3); # *5
+ &vpaddd ($T0,$T0,$D4); # *5
+ &vmovdqu (&QWP(16*7,"edi"),$T1);
+ &vmovdqu (&QWP(16*8,"edi"),$T0);
+
+ &mov ("esp","ebp");
+ &lea ("edi",&DWP(-16*3,"edi")); # size de-optimization
+ &ret ();
+&function_end_B("_poly1305_init_avx2");
+
+########################################################################
+# now it's time to switch to %ymm
+
+my ($D0,$D1,$D2,$D3,$D4,$T0,$T1,$T2)=map("ymm$_",(0..7));
+my $MASK=$T2;
+
+sub X { my $reg=shift; $reg=~s/^ymm/xmm/; $reg; }
+
+&align (32);
+&function_begin("_poly1305_blocks_avx2");
+ &mov ("edi",&wparam(0)); # ctx
+ &mov ("esi",&wparam(1)); # inp
+ &mov ("ecx",&wparam(2)); # len
+
+ &mov ("eax",&DWP(4*5,"edi")); # is_base2_26
+ &and ("ecx",-16);
+ &jz (&label("nodata"));
+ &cmp ("ecx",64);
+ &jae (&label("enter_avx2"));
+ &test ("eax","eax"); # is_base2_26?
+ &jz (&label("enter_blocks"));
+
+&set_label("enter_avx2");
+ &vzeroupper ();
+
+ &call (&label("pic_point"));
+&set_label("pic_point");
+ &blindpop("ebx");
+ &lea ("ebx",&DWP(&label("const_sse2")."-".&label("pic_point"),"ebx"));
+
+ &test ("eax","eax"); # is_base2_26?
+ &jnz (&label("base2_26"));
+
+ &call ("_poly1305_init_avx2");
+
+ ################################################# base 2^32 -> base 2^26
+ &mov ("eax",&DWP(0,"edi"));
+ &mov ("ecx",&DWP(3,"edi"));
+ &mov ("edx",&DWP(6,"edi"));
+ &mov ("esi",&DWP(9,"edi"));
+ &mov ("ebp",&DWP(13,"edi"));
+
+ &shr ("ecx",2);
+ &and ("eax",0x3ffffff);
+ &shr ("edx",4);
+ &and ("ecx",0x3ffffff);
+ &shr ("esi",6);
+ &and ("edx",0x3ffffff);
+
+ &mov (&DWP(4*0,"edi"),"eax");
+ &mov (&DWP(4*1,"edi"),"ecx");
+ &mov (&DWP(4*2,"edi"),"edx");
+ &mov (&DWP(4*3,"edi"),"esi");
+ &mov (&DWP(4*4,"edi"),"ebp");
+ &mov (&DWP(4*5,"edi"),1); # is_base2_26
+
+ &mov ("esi",&wparam(1)); # [reload] inp
+ &mov ("ecx",&wparam(2)); # [reload] len
+
+&set_label("base2_26");
+ &mov ("eax",&wparam(3)); # padbit
+ &mov ("ebp","esp");
+
+ &sub ("esp",32*(5+9));
+ &and ("esp",-512); # ensure that frame
+ # doesn't cross page
+ # boundary, which is
+ # essential for
+ # misaligned 32-byte
+ # loads
+
+ ################################################################
+ # expand and copy pre-calculated table to stack
+
+ &vmovdqu (&X($D0),&QWP(16*(3+0),"edi"));
+ &lea ("edx",&DWP(32*5+128,"esp")); # +128 size optimization
+ &vmovdqu (&X($D1),&QWP(16*(3+1),"edi"));
+ &vmovdqu (&X($D2),&QWP(16*(3+2),"edi"));
+ &vmovdqu (&X($D3),&QWP(16*(3+3),"edi"));
+ &vmovdqu (&X($D4),&QWP(16*(3+4),"edi"));
+ &lea ("edi",&DWP(16*3,"edi")); # size optimization
+ &vpermq ($D0,$D0,0b01000000); # 00001234 -> 12343434
+ &vpermq ($D1,$D1,0b01000000);
+ &vpermq ($D2,$D2,0b01000000);
+ &vpermq ($D3,$D3,0b01000000);
+ &vpermq ($D4,$D4,0b01000000);
+ &vpshufd ($D0,$D0,0b11001000); # 12343434 -> 14243444
+ &vpshufd ($D1,$D1,0b11001000);
+ &vpshufd ($D2,$D2,0b11001000);
+ &vpshufd ($D3,$D3,0b11001000);
+ &vpshufd ($D4,$D4,0b11001000);
+ &vmovdqa (&QWP(32*0-128,"edx"),$D0);
+ &vmovdqu (&X($D0),&QWP(16*5,"edi"));
+ &vmovdqa (&QWP(32*1-128,"edx"),$D1);
+ &vmovdqu (&X($D1),&QWP(16*6,"edi"));
+ &vmovdqa (&QWP(32*2-128,"edx"),$D2);
+ &vmovdqu (&X($D2),&QWP(16*7,"edi"));
+ &vmovdqa (&QWP(32*3-128,"edx"),$D3);
+ &vmovdqu (&X($D3),&QWP(16*8,"edi"));
+ &vmovdqa (&QWP(32*4-128,"edx"),$D4);
+ &vpermq ($D0,$D0,0b01000000);
+ &vpermq ($D1,$D1,0b01000000);
+ &vpermq ($D2,$D2,0b01000000);
+ &vpermq ($D3,$D3,0b01000000);
+ &vpshufd ($D0,$D0,0b11001000);
+ &vpshufd ($D1,$D1,0b11001000);
+ &vpshufd ($D2,$D2,0b11001000);
+ &vpshufd ($D3,$D3,0b11001000);
+ &vmovdqa (&QWP(32*5-128,"edx"),$D0);
+ &vmovd (&X($D0),&DWP(-16*3+4*0,"edi"));# load hash value
+ &vmovdqa (&QWP(32*6-128,"edx"),$D1);
+ &vmovd (&X($D1),&DWP(-16*3+4*1,"edi"));
+ &vmovdqa (&QWP(32*7-128,"edx"),$D2);
+ &vmovd (&X($D2),&DWP(-16*3+4*2,"edi"));
+ &vmovdqa (&QWP(32*8-128,"edx"),$D3);
+ &vmovd (&X($D3),&DWP(-16*3+4*3,"edi"));
+ &vmovd (&X($D4),&DWP(-16*3+4*4,"edi"));
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+ &neg ("eax"); # padbit
+
+ &test ("ecx",63);
+ &jz (&label("even"));
+
+ &mov ("edx","ecx");
+ &and ("ecx",-64);
+ &and ("edx",63);
+
+ &vmovdqu (&X($T0),&QWP(16*0,"esi"));
+ &cmp ("edx",32);
+ &jb (&label("one"));
+
+ &vmovdqu (&X($T1),&QWP(16*1,"esi"));
+ &je (&label("two"));
+
+ &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1);
+ &lea ("esi",&DWP(16*3,"esi"));
+ &lea ("ebx",&DWP(8,"ebx")); # three padbits
+ &lea ("edx",&DWP(32*5+128+8,"esp")); # --:r^1:r^2:r^3 (*)
+ &jmp (&label("tail"));
+
+&set_label("two");
+ &lea ("esi",&DWP(16*2,"esi"));
+ &lea ("ebx",&DWP(16,"ebx")); # two padbits
+ &lea ("edx",&DWP(32*5+128+16,"esp"));# --:--:r^1:r^2 (*)
+ &jmp (&label("tail"));
+
+&set_label("one");
+ &lea ("esi",&DWP(16*1,"esi"));
+ &vpxor ($T1,$T1,$T1);
+ &lea ("ebx",&DWP(32,"ebx","eax",8)); # one or no padbits
+ &lea ("edx",&DWP(32*5+128+24,"esp"));# --:--:--:r^1 (*)
+ &jmp (&label("tail"));
+
+# (*) spots marked with '--' are data from next table entry, but they
+# are multiplied by 0 and therefore rendered insignificant
+
+&set_label("even",32);
+ &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input
+ &vmovdqu (&X($T1),&QWP(16*1,"esi"));
+ &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1);
+ &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1);
+ &lea ("esi",&DWP(16*4,"esi"));
+ &sub ("ecx",64);
+ &jz (&label("tail"));
+
+&set_label("loop");
+ ################################################################
+ # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4
+ # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3
+ # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2
+ # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1
+ # \________/ \_______/
+ ################################################################
+
+sub vsplat_input {
+ &vmovdqa (&QWP(32*2,"esp"),$D2);
+ &vpsrldq ($D2,$T0,6); # splat input
+ &vmovdqa (&QWP(32*0,"esp"),$D0);
+ &vpsrldq ($D0,$T1,6);
+ &vmovdqa (&QWP(32*1,"esp"),$D1);
+ &vpunpckhqdq ($D1,$T0,$T1); # 4
+ &vpunpcklqdq ($T0,$T0,$T1); # 0:1
+ &vpunpcklqdq ($D2,$D2,$D0); # 2:3
+
+ &vpsrlq ($D0,$D2,30);
+ &vpsrlq ($D2,$D2,4);
+ &vpsrlq ($T1,$T0,26);
+ &vpsrlq ($D1,$D1,40); # 4
+ &vpand ($D2,$D2,$MASK); # 2
+ &vpand ($T0,$T0,$MASK); # 0
+ &vpand ($T1,$T1,$MASK); # 1
+ &vpand ($D0,$D0,$MASK); # 3 (*)
+ &vpor ($D1,$D1,&QWP(0,"ebx")); # padbit, yes, always
+
+ # (*) note that output is counterintuitive, inp[3:4] is
+ # returned in $D1-2, while $D3-4 are preserved;
+}
+ &vsplat_input ();
+
+sub vpmuladd {
+my $addr = shift;
+
+ &vpaddq ($D2,$D2,&QWP(32*2,"esp")); # add hash value
+ &vpaddq ($T0,$T0,&QWP(32*0,"esp"));
+ &vpaddq ($T1,$T1,&QWP(32*1,"esp"));
+ &vpaddq ($D0,$D0,$D3);
+ &vpaddq ($D1,$D1,$D4);
+
+ ################################################################
+ # d3 = h2*r1 + h0*r3 + h1*r2 + h3*r0 + h4*5*r4
+ # d4 = h2*r2 + h0*r4 + h1*r3 + h3*r1 + h4*r0
+ # d0 = h2*5*r3 + h0*r0 + h1*5*r4 + h3*5*r2 + h4*5*r1
+ # d1 = h2*5*r4 + h0*r1 + h1*r0 + h3*5*r3 + h4*5*r2
+ # d2 = h2*r0 + h0*r2 + h1*r1 + h3*5*r4 + h4*5*r3
+
+ &vpmuludq ($D3,$D2,&$addr(1)); # d3 = h2*r1
+ &vmovdqa (QWP(32*1,"esp"),$T1);
+ &vpmuludq ($D4,$D2,&$addr(2)); # d4 = h2*r2
+ &vmovdqa (QWP(32*3,"esp"),$D0);
+ &vpmuludq ($D0,$D2,&$addr(7)); # d0 = h2*s3
+ &vmovdqa (QWP(32*4,"esp"),$D1);
+ &vpmuludq ($D1,$D2,&$addr(8)); # d1 = h2*s4
+ &vpmuludq ($D2,$D2,&$addr(0)); # d2 = h2*r0
+
+ &vpmuludq ($T2,$T0,&$addr(3)); # h0*r3
+ &vpaddq ($D3,$D3,$T2); # d3 += h0*r3
+ &vpmuludq ($T1,$T0,&$addr(4)); # h0*r4
+ &vpaddq ($D4,$D4,$T1); # d4 + h0*r4
+ &vpmuludq ($T2,$T0,&$addr(0)); # h0*r0
+ &vpaddq ($D0,$D0,$T2); # d0 + h0*r0
+ &vmovdqa ($T2,&QWP(32*1,"esp")); # h1
+ &vpmuludq ($T1,$T0,&$addr(1)); # h0*r1
+ &vpaddq ($D1,$D1,$T1); # d1 += h0*r1
+ &vpmuludq ($T0,$T0,&$addr(2)); # h0*r2
+ &vpaddq ($D2,$D2,$T0); # d2 += h0*r2
+
+ &vpmuludq ($T1,$T2,&$addr(2)); # h1*r2
+ &vpaddq ($D3,$D3,$T1); # d3 += h1*r2
+ &vpmuludq ($T0,$T2,&$addr(3)); # h1*r3
+ &vpaddq ($D4,$D4,$T0); # d4 += h1*r3
+ &vpmuludq ($T1,$T2,&$addr(8)); # h1*s4
+ &vpaddq ($D0,$D0,$T1); # d0 += h1*s4
+ &vmovdqa ($T1,&QWP(32*3,"esp")); # h3
+ &vpmuludq ($T0,$T2,&$addr(0)); # h1*r0
+ &vpaddq ($D1,$D1,$T0); # d1 += h1*r0
+ &vpmuludq ($T2,$T2,&$addr(1)); # h1*r1
+ &vpaddq ($D2,$D2,$T2); # d2 += h1*r1
+
+ &vpmuludq ($T0,$T1,&$addr(0)); # h3*r0
+ &vpaddq ($D3,$D3,$T0); # d3 += h3*r0
+ &vpmuludq ($T2,$T1,&$addr(1)); # h3*r1
+ &vpaddq ($D4,$D4,$T2); # d4 += h3*r1
+ &vpmuludq ($T0,$T1,&$addr(6)); # h3*s2
+ &vpaddq ($D0,$D0,$T0); # d0 += h3*s2
+ &vmovdqa ($T0,&QWP(32*4,"esp")); # h4
+ &vpmuludq ($T2,$T1,&$addr(7)); # h3*s3
+ &vpaddq ($D1,$D1,$T2); # d1+= h3*s3
+ &vpmuludq ($T1,$T1,&$addr(8)); # h3*s4
+ &vpaddq ($D2,$D2,$T1); # d2 += h3*s4
+
+ &vpmuludq ($T2,$T0,&$addr(8)); # h4*s4
+ &vpaddq ($D3,$D3,$T2); # d3 += h4*s4
+ &vpmuludq ($T1,$T0,&$addr(5)); # h4*s1
+ &vpaddq ($D0,$D0,$T1); # d0 += h4*s1
+ &vpmuludq ($T2,$T0,&$addr(0)); # h4*r0
+ &vpaddq ($D4,$D4,$T2); # d4 += h4*r0
+ &vmovdqa ($MASK,&QWP(64,"ebx"));
+ &vpmuludq ($T1,$T0,&$addr(6)); # h4*s2
+ &vpaddq ($D1,$D1,$T1); # d1 += h4*s2
+ &vpmuludq ($T0,$T0,&$addr(7)); # h4*s3
+ &vpaddq ($D2,$D2,$T0); # d2 += h4*s3
+}
+ &vpmuladd (sub { my $i=shift; &QWP(32*$i-128,"edx"); });
+
+sub vlazy_reduction {
+ ################################################################
+ # lazy reduction
+
+ &vpsrlq ($T0,$D3,26);
+ &vpand ($D3,$D3,$MASK);
+ &vpsrlq ($T1,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpaddq ($D4,$D4,$T0); # h3 -> h4
+ &vpaddq ($D1,$D1,$T1); # h0 -> h1
+ &vpsrlq ($T0,$D4,26);
+ &vpand ($D4,$D4,$MASK);
+ &vpsrlq ($T1,$D1,26);
+ &vpand ($D1,$D1,$MASK);
+ &vpaddq ($D2,$D2,$T1); # h1 -> h2
+ &vpaddq ($D0,$D0,$T0);
+ &vpsllq ($T0,$T0,2);
+ &vpsrlq ($T1,$D2,26);
+ &vpand ($D2,$D2,$MASK);
+ &vpaddq ($D0,$D0,$T0); # h4 -> h0
+ &vpaddq ($D3,$D3,$T1); # h2 -> h3
+ &vpsrlq ($T1,$D3,26);
+ &vpsrlq ($T0,$D0,26);
+ &vpand ($D0,$D0,$MASK);
+ &vpand ($D3,$D3,$MASK);
+ &vpaddq ($D1,$D1,$T0); # h0 -> h1
+ &vpaddq ($D4,$D4,$T1); # h3 -> h4
+}
+ &vlazy_reduction();
+
+ &vmovdqu (&X($T0),&QWP(16*0,"esi")); # load input
+ &vmovdqu (&X($T1),&QWP(16*1,"esi"));
+ &vinserti128 ($T0,$T0,&QWP(16*2,"esi"),1);
+ &vinserti128 ($T1,$T1,&QWP(16*3,"esi"),1);
+ &lea ("esi",&DWP(16*4,"esi"));
+ &sub ("ecx",64);
+ &jnz (&label("loop"));
+
+&set_label("tail");
+ &vsplat_input ();
+ &and ("ebx",-64); # restore pointer
+
+ &vpmuladd (sub { my $i=shift; &QWP(4+32*$i-128,"edx"); });
+
+ ################################################################
+ # horizontal addition
+
+ &vpsrldq ($T0,$D4,8);
+ &vpsrldq ($T1,$D3,8);
+ &vpaddq ($D4,$D4,$T0);
+ &vpsrldq ($T0,$D0,8);
+ &vpaddq ($D3,$D3,$T1);
+ &vpsrldq ($T1,$D1,8);
+ &vpaddq ($D0,$D0,$T0);
+ &vpsrldq ($T0,$D2,8);
+ &vpaddq ($D1,$D1,$T1);
+ &vpermq ($T1,$D4,2); # keep folding
+ &vpaddq ($D2,$D2,$T0);
+ &vpermq ($T0,$D3,2);
+ &vpaddq ($D4,$D4,$T1);
+ &vpermq ($T1,$D0,2);
+ &vpaddq ($D3,$D3,$T0);
+ &vpermq ($T0,$D1,2);
+ &vpaddq ($D0,$D0,$T1);
+ &vpermq ($T1,$D2,2);
+ &vpaddq ($D1,$D1,$T0);
+ &vpaddq ($D2,$D2,$T1);
+
+ &vlazy_reduction();
+
+ &cmp ("ecx",0);
+ &je (&label("done"));
+
+ ################################################################
+ # clear all but single word
+
+ &vpshufd (&X($D0),&X($D0),0b11111100);
+ &lea ("edx",&DWP(32*5+128,"esp")); # restore pointer
+ &vpshufd (&X($D1),&X($D1),0b11111100);
+ &vpshufd (&X($D2),&X($D2),0b11111100);
+ &vpshufd (&X($D3),&X($D3),0b11111100);
+ &vpshufd (&X($D4),&X($D4),0b11111100);
+ &jmp (&label("even"));
+
+&set_label("done",16);
+ &vmovd (&DWP(-16*3+4*0,"edi"),&X($D0));# store hash value
+ &vmovd (&DWP(-16*3+4*1,"edi"),&X($D1));
+ &vmovd (&DWP(-16*3+4*2,"edi"),&X($D2));
+ &vmovd (&DWP(-16*3+4*3,"edi"),&X($D3));
+ &vmovd (&DWP(-16*3+4*4,"edi"),&X($D4));
+ &vzeroupper ();
+ &mov ("esp","ebp");
+&set_label("nodata");
+&function_end("_poly1305_blocks_avx2");
+}
+&set_label("const_sse2",64);
+ &data_word(1<<24,0, 1<<24,0, 1<<24,0, 1<<24,0);
+ &data_word(0,0, 0,0, 0,0, 0,0);
+ &data_word(0x03ffffff,0,0x03ffffff,0, 0x03ffffff,0, 0x03ffffff,0);
+ &data_word(0x0fffffff,0x0ffffffc,0x0ffffffc,0x0ffffffc);
+}
+&asciz ("Poly1305 for x86, CRYPTOGAMS by <appro\@openssl.org>");
+&align (4);
+
+&asm_finish();
diff --git a/crypto/poly1305/asm/poly1305-x86_64.pl b/crypto/poly1305/asm/poly1305-x86_64.pl
new file mode 100755
index 00000000..3c810c5a
--- /dev/null
+++ b/crypto/poly1305/asm/poly1305-x86_64.pl
@@ -0,0 +1,2235 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# This module implements Poly1305 hash for x86_64.
+#
+# March 2015
+#
+# Numbers are cycles per processed byte with poly1305_blocks alone,
+# measured with rdtsc at fixed clock frequency.
+#
+# IALU/gcc-4.8(*) AVX(**) AVX2
+# P4 4.90/+120% -
+# Core 2 2.39/+90% -
+# Westmere 1.86/+120% -
+# Sandy Bridge 1.39/+140% 1.10
+# Haswell 1.10/+175% 1.11 0.65
+# Skylake 1.12/+120% 0.96 0.51
+# Silvermont 2.83/+95% -
+# VIA Nano 1.82/+150% -
+# Sledgehammer 1.38/+160% -
+# Bulldozer 2.21/+130% 0.97
+#
+# (*) improvement coefficients relative to clang are more modest and
+# are ~50% on most processors, in both cases we are comparing to
+# __int128 code;
+# (**) SSE2 implementation was attempted, but among non-AVX processors
+# it was faster than integer-only code only on older Intel P4 and
+# Core processors, 50-30%, less newer processor is, but slower on
+# contemporary ones, for example almost 2x slower on Atom, and as
+# former are naturally disappearing, SSE2 is deemed unnecessary;
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+$avx = 2;
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my ($ctx,$inp,$len,$padbit)=("%rdi","%rsi","%rdx","%rcx");
+my ($mac,$nonce)=($inp,$len); # *_emit arguments
+my ($d1,$d2,$d3, $r0,$r1,$s1)=map("%r$_",(8..13));
+my ($h0,$h1,$h2)=("%r14","%rbx","%rbp");
+
+sub poly1305_iteration {
+# input: copy of $r1 in %rax, $h0-$h2, $r0-$r1
+# output: $h0-$h2 *= $r0-$r1
+$code.=<<___;
+ mulq $h0 # h0*r1
+ mov %rax,$d2
+ mov $r0,%rax
+ mov %rdx,$d3
+
+ mulq $h0 # h0*r0
+ mov %rax,$h0 # future $h0
+ mov $r0,%rax
+ mov %rdx,$d1
+
+ mulq $h1 # h1*r0
+ add %rax,$d2
+ mov $s1,%rax
+ adc %rdx,$d3
+
+ mulq $h1 # h1*s1
+ mov $h2,$h1 # borrow $h1
+ add %rax,$h0
+ adc %rdx,$d1
+
+ imulq $s1,$h1 # h2*s1
+ add $h1,$d2
+ mov $d1,$h1
+ adc \$0,$d3
+
+ imulq $r0,$h2 # h2*r0
+ add $d2,$h1
+ mov \$-4,%rax # mask value
+ adc $h2,$d3
+
+ and $d3,%rax # last reduction step
+ mov $d3,$h2
+ shr \$2,$d3
+ and \$3,$h2
+ add $d3,%rax
+ add %rax,$h0
+ adc \$0,$h1
+___
+}
+
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int64 h[3]; # current hash value base 2^64
+# unsigned __int64 r[2]; # key value base 2^64
+
+$code.=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.globl poly1305_init
+.globl poly1305_blocks
+.globl poly1305_emit
+.type poly1305_init,\@function,3
+.align 32
+poly1305_init:
+ xor %rax,%rax
+ mov %rax,0($ctx) # initialize hash value
+ mov %rax,8($ctx)
+ mov %rax,16($ctx)
+
+ cmp \$0,$inp
+ je .Lno_key
+
+ lea poly1305_blocks(%rip),%r10
+ lea poly1305_emit(%rip),%r11
+___
+$code.=<<___ if ($avx);
+ mov OPENSSL_ia32cap_P+4(%rip),%r9
+ lea poly1305_blocks_avx(%rip),%rax
+ lea poly1305_emit_avx(%rip),%rcx
+ bt \$`60-32`,%r9 # AVX?
+ cmovc %rax,%r10
+ cmovc %rcx,%r11
+___
+$code.=<<___ if ($avx>1);
+ lea poly1305_blocks_avx2(%rip),%rax
+ bt \$`5+32`,%r9 # AVX2?
+ cmovc %rax,%r10
+___
+$code.=<<___;
+ mov \$0x0ffffffc0fffffff,%rax
+ mov \$0x0ffffffc0ffffffc,%rcx
+ and 0($inp),%rax
+ and 8($inp),%rcx
+ mov %rax,24($ctx)
+ mov %rcx,32($ctx)
+___
+$code.=<<___ if ($flavour !~ /elf32/);
+ mov %r10,0(%rdx)
+ mov %r11,8(%rdx)
+___
+$code.=<<___ if ($flavour =~ /elf32/);
+ mov %r10d,0(%rdx)
+ mov %r11d,4(%rdx)
+___
+$code.=<<___;
+ mov \$1,%eax
+.Lno_key:
+ ret
+.size poly1305_init,.-poly1305_init
+
+.type poly1305_blocks,\@function,4
+.align 32
+poly1305_blocks:
+.Lblocks:
+ sub \$16,$len # too short?
+ jc .Lno_data
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lblocks_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ mov 0($ctx),$h0 # load hash value
+ mov 8($ctx),$h1
+ mov 16($ctx),$h2
+
+ mov $s1,$r1
+ shr \$2,$s1
+ mov $r1,%rax
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+ jmp .Loop
+
+.align 32
+.Loop:
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+___
+ &poly1305_iteration();
+$code.=<<___;
+ mov $r1,%rax
+ sub \$16,%r15 # len-=16
+ jnc .Loop
+
+ mov $h0,0($ctx) # store hash value
+ mov $h1,8($ctx)
+ mov $h2,16($ctx)
+
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rsp
+.Lno_data:
+.Lblocks_epilogue:
+ ret
+.size poly1305_blocks,.-poly1305_blocks
+
+.type poly1305_emit,\@function,3
+.align 32
+poly1305_emit:
+.Lemit:
+ mov 0($ctx),%r8 # load hash value
+ mov 8($ctx),%r9
+ mov 16($ctx),%r10
+
+ mov %r8,%rax
+ add \$5,%r8 # compare to modulus
+ mov %r9,%rcx
+ adc \$0,%r9
+ adc \$0,%r10
+ shr \$2,%r10 # did 130-bit value overfow?
+ cmovnz %r8,%rax
+ cmovnz %r9,%rcx
+
+ add 0($nonce),%rax # accumulate nonce
+ adc 8($nonce),%rcx
+ mov %rax,0($mac) # write result
+ mov %rcx,8($mac)
+
+ ret
+.size poly1305_emit,.-poly1305_emit
+___
+if ($avx) {
+
+########################################################################
+# Layout of opaque area is following.
+#
+# unsigned __int32 h[5]; # current hash value base 2^26
+# unsigned __int32 is_base2_26;
+# unsigned __int64 r[2]; # key value base 2^64
+# unsigned __int64 pad;
+# struct { unsigned __int32 r^2, r^1, r^4, r^3; } r[9];
+#
+# where r^n are base 2^26 digits of degrees of multiplier key. There are
+# 5 digits, but last four are interleaved with multiples of 5, totalling
+# in 9 elements: r0, r1, 5*r1, r2, 5*r2, r3, 5*r3, r4, 5*r4.
+
+my ($H0,$H1,$H2,$H3,$H4, $T0,$T1,$T2,$T3,$T4, $D0,$D1,$D2,$D3,$D4, $MASK) =
+ map("%xmm$_",(0..15));
+
+$code.=<<___;
+.type __poly1305_block,\@abi-omnipotent
+.align 32
+__poly1305_block:
+___
+ &poly1305_iteration();
+$code.=<<___;
+ ret
+.size __poly1305_block,.-__poly1305_block
+
+.type __poly1305_init_avx,\@abi-omnipotent
+.align 32
+__poly1305_init_avx:
+ mov $r0,$h0
+ mov $r1,$h1
+ xor $h2,$h2
+
+ lea 48+64($ctx),$ctx # size optimization
+
+ mov $r1,%rax
+ call __poly1305_block # r^2
+
+ mov \$0x3ffffff,%eax # save interleaved r^2 and r base 2^26
+ mov \$0x3ffffff,%edx
+ mov $h0,$d1
+ and $h0#d,%eax
+ mov $r0,$d2
+ and $r0#d,%edx
+ mov %eax,`16*0+0-64`($ctx)
+ shr \$26,$d1
+ mov %edx,`16*0+4-64`($ctx)
+ shr \$26,$d2
+
+ mov \$0x3ffffff,%eax
+ mov \$0x3ffffff,%edx
+ and $d1#d,%eax
+ and $d2#d,%edx
+ mov %eax,`16*1+0-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov %edx,`16*1+4-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ mov %eax,`16*2+0-64`($ctx)
+ shr \$26,$d1
+ mov %edx,`16*2+4-64`($ctx)
+ shr \$26,$d2
+
+ mov $h1,%rax
+ mov $r1,%rdx
+ shl \$12,%rax
+ shl \$12,%rdx
+ or $d1,%rax
+ or $d2,%rdx
+ and \$0x3ffffff,%eax
+ and \$0x3ffffff,%edx
+ mov %eax,`16*3+0-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov %edx,`16*3+4-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ mov %eax,`16*4+0-64`($ctx)
+ mov $h1,$d1
+ mov %edx,`16*4+4-64`($ctx)
+ mov $r1,$d2
+
+ mov \$0x3ffffff,%eax
+ mov \$0x3ffffff,%edx
+ shr \$14,$d1
+ shr \$14,$d2
+ and $d1#d,%eax
+ and $d2#d,%edx
+ mov %eax,`16*5+0-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov %edx,`16*5+4-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ mov %eax,`16*6+0-64`($ctx)
+ shr \$26,$d1
+ mov %edx,`16*6+4-64`($ctx)
+ shr \$26,$d2
+
+ mov $h2,%rax
+ shl \$24,%rax
+ or %rax,$d1
+ mov $d1#d,`16*7+0-64`($ctx)
+ lea ($d1,$d1,4),$d1 # *5
+ mov $d2#d,`16*7+4-64`($ctx)
+ lea ($d2,$d2,4),$d2 # *5
+ mov $d1#d,`16*8+0-64`($ctx)
+ mov $d2#d,`16*8+4-64`($ctx)
+
+ mov $r1,%rax
+ call __poly1305_block # r^3
+
+ mov \$0x3ffffff,%eax # save r^3 base 2^26
+ mov $h0,$d1
+ and $h0#d,%eax
+ shr \$26,$d1
+ mov %eax,`16*0+12-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ and $d1#d,%edx
+ mov %edx,`16*1+12-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*2+12-64`($ctx)
+
+ mov $h1,%rax
+ shl \$12,%rax
+ or $d1,%rax
+ and \$0x3ffffff,%eax
+ mov %eax,`16*3+12-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov $h1,$d1
+ mov %eax,`16*4+12-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ shr \$14,$d1
+ and $d1#d,%edx
+ mov %edx,`16*5+12-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*6+12-64`($ctx)
+
+ mov $h2,%rax
+ shl \$24,%rax
+ or %rax,$d1
+ mov $d1#d,`16*7+12-64`($ctx)
+ lea ($d1,$d1,4),$d1 # *5
+ mov $d1#d,`16*8+12-64`($ctx)
+
+ mov $r1,%rax
+ call __poly1305_block # r^4
+
+ mov \$0x3ffffff,%eax # save r^4 base 2^26
+ mov $h0,$d1
+ and $h0#d,%eax
+ shr \$26,$d1
+ mov %eax,`16*0+8-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ and $d1#d,%edx
+ mov %edx,`16*1+8-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*2+8-64`($ctx)
+
+ mov $h1,%rax
+ shl \$12,%rax
+ or $d1,%rax
+ and \$0x3ffffff,%eax
+ mov %eax,`16*3+8-64`($ctx)
+ lea (%rax,%rax,4),%eax # *5
+ mov $h1,$d1
+ mov %eax,`16*4+8-64`($ctx)
+
+ mov \$0x3ffffff,%edx
+ shr \$14,$d1
+ and $d1#d,%edx
+ mov %edx,`16*5+8-64`($ctx)
+ lea (%rdx,%rdx,4),%edx # *5
+ shr \$26,$d1
+ mov %edx,`16*6+8-64`($ctx)
+
+ mov $h2,%rax
+ shl \$24,%rax
+ or %rax,$d1
+ mov $d1#d,`16*7+8-64`($ctx)
+ lea ($d1,$d1,4),$d1 # *5
+ mov $d1#d,`16*8+8-64`($ctx)
+
+ lea -48-64($ctx),$ctx # size [de-]optimization
+ ret
+.size __poly1305_init_avx,.-__poly1305_init_avx
+
+.type poly1305_blocks_avx,\@function,4
+.align 32
+poly1305_blocks_avx:
+ mov 20($ctx),%r8d # is_base2_26
+ cmp \$128,$len
+ jae .Lblocks_avx
+ test %r8d,%r8d
+ jz .Lblocks
+
+.Lblocks_avx:
+ and \$-16,$len
+ jz .Lno_data_avx
+
+ vzeroupper
+
+ test %r8d,%r8d
+ jz .Lbase2_64_avx
+
+ test \$31,$len
+ jz .Leven_avx
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lblocks_avx_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 0($ctx),$d1 # load hash value
+ mov 8($ctx),$d2
+ mov 16($ctx),$h2#d
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ ################################# base 2^26 -> base 2^64
+ mov $d1#d,$h0#d
+ and \$-1<<31,$d1
+ mov $d2,$r1 # borrow $r1
+ mov $d2#d,$h1#d
+ and \$-1<<31,$d2
+
+ shr \$6,$d1
+ shl \$52,$r1
+ add $d1,$h0
+ shr \$12,$h1
+ shr \$18,$d2
+ add $r1,$h0
+ adc $d2,$h1
+
+ mov $h2,$d1
+ shl \$40,$d1
+ shr \$24,$h2
+ add $d1,$h1
+ adc \$0,$h2 # can be partially reduced...
+
+ mov \$-4,$d2 # ... so reduce
+ mov $h2,$d1
+ and $h2,$d2
+ shr \$2,$d1
+ and \$3,$h2
+ add $d2,$d1 # =*5
+ add $d1,$h0
+ adc \$0,$h1
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+
+ call __poly1305_block
+
+ test $padbit,$padbit # if $padbit is zero,
+ jz .Lstore_base2_64_avx # store hash in base 2^64 format
+
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$r0
+ mov $h1,$r1
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$r0
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $r0,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$r1
+ and \$0x3ffffff,$h1 # h[3]
+ or $r1,$h2 # h[4]
+
+ sub \$16,%r15
+ jz .Lstore_base2_26_avx
+
+ vmovd %rax#d,$H0
+ vmovd %rdx#d,$H1
+ vmovd $h0#d,$H2
+ vmovd $h1#d,$H3
+ vmovd $h2#d,$H4
+ jmp .Lproceed_avx
+
+.align 32
+.Lstore_base2_64_avx:
+ mov $h0,0($ctx)
+ mov $h1,8($ctx)
+ mov $h2,16($ctx) # note that is_base2_26 is zeroed
+ jmp .Ldone_avx
+
+.align 16
+.Lstore_base2_26_avx:
+ mov %rax#d,0($ctx) # store hash value base 2^26
+ mov %rdx#d,4($ctx)
+ mov $h0#d,8($ctx)
+ mov $h1#d,12($ctx)
+ mov $h2#d,16($ctx)
+.align 16
+.Ldone_avx:
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rsp
+.Lno_data_avx:
+.Lblocks_avx_epilogue:
+ ret
+
+.align 32
+.Lbase2_64_avx:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lbase2_64_avx_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ mov 0($ctx),$h0 # load hash value
+ mov 8($ctx),$h1
+ mov 16($ctx),$h2#d
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+ test \$31,$len
+ jz .Linit_avx
+
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+ sub \$16,%r15
+
+ call __poly1305_block
+
+.Linit_avx:
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$d1
+ mov $h1,$d2
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$d1
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $d1,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$d2
+ and \$0x3ffffff,$h1 # h[3]
+ or $d2,$h2 # h[4]
+
+ vmovd %rax#d,$H0
+ vmovd %rdx#d,$H1
+ vmovd $h0#d,$H2
+ vmovd $h1#d,$H3
+ vmovd $h2#d,$H4
+ movl \$1,20($ctx) # set is_base2_26
+
+ call __poly1305_init_avx
+
+.Lproceed_avx:
+ mov %r15,$len
+
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rax
+ lea 48(%rsp),%rsp
+.Lbase2_64_avx_epilogue:
+ jmp .Ldo_avx
+
+.align 32
+.Leven_avx:
+ vmovd 4*0($ctx),$H0 # load hash value
+ vmovd 4*1($ctx),$H1
+ vmovd 4*2($ctx),$H2
+ vmovd 4*3($ctx),$H3
+ vmovd 4*4($ctx),$H4
+
+.Ldo_avx:
+___
+$code.=<<___ if (!$win64);
+ lea -0x58(%rsp),%r11
+ sub \$0x178,%rsp
+___
+$code.=<<___ if ($win64);
+ lea -0xf8(%rsp),%r11
+ sub \$0x218,%rsp
+ vmovdqa %xmm6,0x50(%r11)
+ vmovdqa %xmm7,0x60(%r11)
+ vmovdqa %xmm8,0x70(%r11)
+ vmovdqa %xmm9,0x80(%r11)
+ vmovdqa %xmm10,0x90(%r11)
+ vmovdqa %xmm11,0xa0(%r11)
+ vmovdqa %xmm12,0xb0(%r11)
+ vmovdqa %xmm13,0xc0(%r11)
+ vmovdqa %xmm14,0xd0(%r11)
+ vmovdqa %xmm15,0xe0(%r11)
+.Ldo_avx_body:
+___
+$code.=<<___;
+ sub \$64,$len
+ lea -32($inp),%rax
+ cmovc %rax,$inp
+
+ vmovdqu `16*3`($ctx),$D4 # preload r0^2
+ lea `16*3+64`($ctx),$ctx # size optimization
+ lea .Lconst(%rip),%rcx
+
+ ################################################################
+ # load input
+ vmovdqu 16*2($inp),$T0
+ vmovdqu 16*3($inp),$T1
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpsrldq \$6,$T1,$T3
+ vpunpckhqdq $T1,$T0,$T4 # 4
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+ vpunpcklqdq $T3,$T2,$T3 # 2:3
+
+ vpsrlq \$40,$T4,$T4 # 4
+ vpsrlq \$26,$T0,$T1
+ vpand $MASK,$T0,$T0 # 0
+ vpsrlq \$4,$T3,$T2
+ vpand $MASK,$T1,$T1 # 1
+ vpsrlq \$30,$T3,$T3
+ vpand $MASK,$T2,$T2 # 2
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ jbe .Lskip_loop_avx
+
+ # expand and copy pre-calculated table to stack
+ vmovdqu `16*1-64`($ctx),$D1
+ vmovdqu `16*2-64`($ctx),$D2
+ vpshufd \$0xEE,$D4,$D3 # 34xx -> 3434
+ vpshufd \$0x44,$D4,$D0 # xx12 -> 1212
+ vmovdqa $D3,-0x90(%r11)
+ vmovdqa $D0,0x00(%rsp)
+ vpshufd \$0xEE,$D1,$D4
+ vmovdqu `16*3-64`($ctx),$D0
+ vpshufd \$0x44,$D1,$D1
+ vmovdqa $D4,-0x80(%r11)
+ vmovdqa $D1,0x10(%rsp)
+ vpshufd \$0xEE,$D2,$D3
+ vmovdqu `16*4-64`($ctx),$D1
+ vpshufd \$0x44,$D2,$D2
+ vmovdqa $D3,-0x70(%r11)
+ vmovdqa $D2,0x20(%rsp)
+ vpshufd \$0xEE,$D0,$D4
+ vmovdqu `16*5-64`($ctx),$D2
+ vpshufd \$0x44,$D0,$D0
+ vmovdqa $D4,-0x60(%r11)
+ vmovdqa $D0,0x30(%rsp)
+ vpshufd \$0xEE,$D1,$D3
+ vmovdqu `16*6-64`($ctx),$D0
+ vpshufd \$0x44,$D1,$D1
+ vmovdqa $D3,-0x50(%r11)
+ vmovdqa $D1,0x40(%rsp)
+ vpshufd \$0xEE,$D2,$D4
+ vmovdqu `16*7-64`($ctx),$D1
+ vpshufd \$0x44,$D2,$D2
+ vmovdqa $D4,-0x40(%r11)
+ vmovdqa $D2,0x50(%rsp)
+ vpshufd \$0xEE,$D0,$D3
+ vmovdqu `16*8-64`($ctx),$D2
+ vpshufd \$0x44,$D0,$D0
+ vmovdqa $D3,-0x30(%r11)
+ vmovdqa $D0,0x60(%rsp)
+ vpshufd \$0xEE,$D1,$D4
+ vpshufd \$0x44,$D1,$D1
+ vmovdqa $D4,-0x20(%r11)
+ vmovdqa $D1,0x70(%rsp)
+ vpshufd \$0xEE,$D2,$D3
+ vmovdqa 0x00(%rsp),$D4 # preload r0^2
+ vpshufd \$0x44,$D2,$D2
+ vmovdqa $D3,-0x10(%r11)
+ vmovdqa $D2,0x80(%rsp)
+
+ jmp .Loop_avx
+
+.align 32
+.Loop_avx:
+ ################################################################
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
+ # \___________________/
+ # ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
+ # ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
+ # \___________________/ \____________________/
+ #
+ # Note that we start with inp[2:3]*r^2. This is because it
+ # doesn't depend on reduction in previous iteration.
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+ #
+ # though note that $Tx and $Hx are "reversed" in this section,
+ # and $D4 is preloaded with r0^2...
+
+ vpmuludq $T0,$D4,$D0 # d0 = h0*r0
+ vpmuludq $T1,$D4,$D1 # d1 = h1*r0
+ vmovdqa $H2,0x20(%r11) # offload hash
+ vpmuludq $T2,$D4,$D2 # d3 = h2*r0
+ vmovdqa 0x10(%rsp),$H2 # r1^2
+ vpmuludq $T3,$D4,$D3 # d3 = h3*r0
+ vpmuludq $T4,$D4,$D4 # d4 = h4*r0
+
+ vmovdqa $H0,0x00(%r11) #
+ vpmuludq 0x20(%rsp),$T4,$H0 # h4*s1
+ vmovdqa $H1,0x10(%r11) #
+ vpmuludq $T3,$H2,$H1 # h3*r1
+ vpaddq $H0,$D0,$D0 # d0 += h4*s1
+ vpaddq $H1,$D4,$D4 # d4 += h3*r1
+ vmovdqa $H3,0x30(%r11) #
+ vpmuludq $T2,$H2,$H0 # h2*r1
+ vpmuludq $T1,$H2,$H1 # h1*r1
+ vpaddq $H0,$D3,$D3 # d3 += h2*r1
+ vmovdqa 0x30(%rsp),$H3 # r2^2
+ vpaddq $H1,$D2,$D2 # d2 += h1*r1
+ vmovdqa $H4,0x40(%r11) #
+ vpmuludq $T0,$H2,$H2 # h0*r1
+ vpmuludq $T2,$H3,$H0 # h2*r2
+ vpaddq $H2,$D1,$D1 # d1 += h0*r1
+
+ vmovdqa 0x40(%rsp),$H4 # s2^2
+ vpaddq $H0,$D4,$D4 # d4 += h2*r2
+ vpmuludq $T1,$H3,$H1 # h1*r2
+ vpmuludq $T0,$H3,$H3 # h0*r2
+ vpaddq $H1,$D3,$D3 # d3 += h1*r2
+ vmovdqa 0x50(%rsp),$H2 # r3^2
+ vpaddq $H3,$D2,$D2 # d2 += h0*r2
+ vpmuludq $T4,$H4,$H0 # h4*s2
+ vpmuludq $T3,$H4,$H4 # h3*s2
+ vpaddq $H0,$D1,$D1 # d1 += h4*s2
+ vmovdqa 0x60(%rsp),$H3 # s3^2
+ vpaddq $H4,$D0,$D0 # d0 += h3*s2
+
+ vmovdqa 0x80(%rsp),$H4 # s4^2
+ vpmuludq $T1,$H2,$H1 # h1*r3
+ vpmuludq $T0,$H2,$H2 # h0*r3
+ vpaddq $H1,$D4,$D4 # d4 += h1*r3
+ vpaddq $H2,$D3,$D3 # d3 += h0*r3
+ vpmuludq $T4,$H3,$H0 # h4*s3
+ vpmuludq $T3,$H3,$H1 # h3*s3
+ vpaddq $H0,$D2,$D2 # d2 += h4*s3
+ vmovdqu 16*0($inp),$H0 # load input
+ vpaddq $H1,$D1,$D1 # d1 += h3*s3
+ vpmuludq $T2,$H3,$H3 # h2*s3
+ vpmuludq $T2,$H4,$T2 # h2*s4
+ vpaddq $H3,$D0,$D0 # d0 += h2*s3
+
+ vmovdqu 16*1($inp),$H1 #
+ vpaddq $T2,$D1,$D1 # d1 += h2*s4
+ vpmuludq $T3,$H4,$T3 # h3*s4
+ vpmuludq $T4,$H4,$T4 # h4*s4
+ vpsrldq \$6,$H0,$H2 # splat input
+ vpaddq $T3,$D2,$D2 # d2 += h3*s4
+ vpaddq $T4,$D3,$D3 # d3 += h4*s4
+ vpsrldq \$6,$H1,$H3 #
+ vpmuludq 0x70(%rsp),$T0,$T4 # h0*r4
+ vpmuludq $T1,$H4,$T0 # h1*s4
+ vpunpckhqdq $H1,$H0,$H4 # 4
+ vpaddq $T4,$D4,$D4 # d4 += h0*r4
+ vmovdqa -0x90(%r11),$T4 # r0^4
+ vpaddq $T0,$D0,$D0 # d0 += h1*s4
+
+ vpunpcklqdq $H1,$H0,$H0 # 0:1
+ vpunpcklqdq $H3,$H2,$H3 # 2:3
+
+ #vpsrlq \$40,$H4,$H4 # 4
+ vpsrldq \$`40/8`,$H4,$H4 # 4
+ vpsrlq \$26,$H0,$H1
+ vpand $MASK,$H0,$H0 # 0
+ vpsrlq \$4,$H3,$H2
+ vpand $MASK,$H1,$H1 # 1
+ vpand 0(%rcx),$H4,$H4 # .Lmask24
+ vpsrlq \$30,$H3,$H3
+ vpand $MASK,$H2,$H2 # 2
+ vpand $MASK,$H3,$H3 # 3
+ vpor 32(%rcx),$H4,$H4 # padbit, yes, always
+
+ vpaddq 0x00(%r11),$H0,$H0 # add hash value
+ vpaddq 0x10(%r11),$H1,$H1
+ vpaddq 0x20(%r11),$H2,$H2
+ vpaddq 0x30(%r11),$H3,$H3
+ vpaddq 0x40(%r11),$H4,$H4
+
+ lea 16*2($inp),%rax
+ lea 16*4($inp),$inp
+ sub \$64,$len
+ cmovc %rax,$inp
+
+ ################################################################
+ # Now we accumulate (inp[0:1]+hash)*r^4
+ ################################################################
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ vpmuludq $H0,$T4,$T0 # h0*r0
+ vpmuludq $H1,$T4,$T1 # h1*r0
+ vpaddq $T0,$D0,$D0
+ vpaddq $T1,$D1,$D1
+ vmovdqa -0x80(%r11),$T2 # r1^4
+ vpmuludq $H2,$T4,$T0 # h2*r0
+ vpmuludq $H3,$T4,$T1 # h3*r0
+ vpaddq $T0,$D2,$D2
+ vpaddq $T1,$D3,$D3
+ vpmuludq $H4,$T4,$T4 # h4*r0
+ vpmuludq -0x70(%r11),$H4,$T0 # h4*s1
+ vpaddq $T4,$D4,$D4
+
+ vpaddq $T0,$D0,$D0 # d0 += h4*s1
+ vpmuludq $H2,$T2,$T1 # h2*r1
+ vpmuludq $H3,$T2,$T0 # h3*r1
+ vpaddq $T1,$D3,$D3 # d3 += h2*r1
+ vmovdqa -0x60(%r11),$T3 # r2^4
+ vpaddq $T0,$D4,$D4 # d4 += h3*r1
+ vpmuludq $H1,$T2,$T1 # h1*r1
+ vpmuludq $H0,$T2,$T2 # h0*r1
+ vpaddq $T1,$D2,$D2 # d2 += h1*r1
+ vpaddq $T2,$D1,$D1 # d1 += h0*r1
+
+ vmovdqa -0x50(%r11),$T4 # s2^4
+ vpmuludq $H2,$T3,$T0 # h2*r2
+ vpmuludq $H1,$T3,$T1 # h1*r2
+ vpaddq $T0,$D4,$D4 # d4 += h2*r2
+ vpaddq $T1,$D3,$D3 # d3 += h1*r2
+ vmovdqa -0x40(%r11),$T2 # r3^4
+ vpmuludq $H0,$T3,$T3 # h0*r2
+ vpmuludq $H4,$T4,$T0 # h4*s2
+ vpaddq $T3,$D2,$D2 # d2 += h0*r2
+ vpaddq $T0,$D1,$D1 # d1 += h4*s2
+ vmovdqa -0x30(%r11),$T3 # s3^4
+ vpmuludq $H3,$T4,$T4 # h3*s2
+ vpmuludq $H1,$T2,$T1 # h1*r3
+ vpaddq $T4,$D0,$D0 # d0 += h3*s2
+
+ vmovdqa -0x10(%r11),$T4 # s4^4
+ vpaddq $T1,$D4,$D4 # d4 += h1*r3
+ vpmuludq $H0,$T2,$T2 # h0*r3
+ vpmuludq $H4,$T3,$T0 # h4*s3
+ vpaddq $T2,$D3,$D3 # d3 += h0*r3
+ vpaddq $T0,$D2,$D2 # d2 += h4*s3
+ vmovdqu 16*2($inp),$T0 # load input
+ vpmuludq $H3,$T3,$T2 # h3*s3
+ vpmuludq $H2,$T3,$T3 # h2*s3
+ vpaddq $T2,$D1,$D1 # d1 += h3*s3
+ vmovdqu 16*3($inp),$T1 #
+ vpaddq $T3,$D0,$D0 # d0 += h2*s3
+
+ vpmuludq $H2,$T4,$H2 # h2*s4
+ vpmuludq $H3,$T4,$H3 # h3*s4
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpaddq $H2,$D1,$D1 # d1 += h2*s4
+ vpmuludq $H4,$T4,$H4 # h4*s4
+ vpsrldq \$6,$T1,$T3 #
+ vpaddq $H3,$D2,$H2 # h2 = d2 + h3*s4
+ vpaddq $H4,$D3,$H3 # h3 = d3 + h4*s4
+ vpmuludq -0x20(%r11),$H0,$H4 # h0*r4
+ vpmuludq $H1,$T4,$H0
+ vpunpckhqdq $T1,$T0,$T4 # 4
+ vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4
+ vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4
+
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+ vpunpcklqdq $T3,$T2,$T3 # 2:3
+
+ #vpsrlq \$40,$T4,$T4 # 4
+ vpsrldq \$`40/8`,$T4,$T4 # 4
+ vpsrlq \$26,$T0,$T1
+ vmovdqa 0x00(%rsp),$D4 # preload r0^2
+ vpand $MASK,$T0,$T0 # 0
+ vpsrlq \$4,$T3,$T2
+ vpand $MASK,$T1,$T1 # 1
+ vpand 0(%rcx),$T4,$T4 # .Lmask24
+ vpsrlq \$30,$T3,$T3
+ vpand $MASK,$T2,$T2 # 2
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ ################################################################
+ # lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
+ # and P. Schwabe
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$D1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H4,$D0
+ vpand $MASK,$H4,$H4
+
+ vpsrlq \$26,$H1,$D1
+ vpand $MASK,$H1,$H1
+ vpaddq $D1,$H2,$H2 # h1 -> h2
+
+ vpaddq $D0,$H0,$H0
+ vpsllq \$2,$D0,$D0
+ vpaddq $D0,$H0,$H0 # h4 -> h0
+
+ vpsrlq \$26,$H2,$D2
+ vpand $MASK,$H2,$H2
+ vpaddq $D2,$H3,$H3 # h2 -> h3
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$H1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ ja .Loop_avx
+
+.Lskip_loop_avx:
+ ################################################################
+ # multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
+
+ vpshufd \$0x10,$D4,$D4 # r0^n, xx12 -> x1x2
+ add \$32,$len
+ jnz .Long_tail_avx
+
+ vpaddq $H2,$T2,$T2
+ vpaddq $H0,$T0,$T0
+ vpaddq $H1,$T1,$T1
+ vpaddq $H3,$T3,$T3
+ vpaddq $H4,$T4,$T4
+
+.Long_tail_avx:
+ vmovdqa $H2,0x20(%r11)
+ vmovdqa $H0,0x00(%r11)
+ vmovdqa $H1,0x10(%r11)
+ vmovdqa $H3,0x30(%r11)
+ vmovdqa $H4,0x40(%r11)
+
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+
+ vpmuludq $T2,$D4,$D2 # d2 = h2*r0
+ vpmuludq $T0,$D4,$D0 # d0 = h0*r0
+ vpshufd \$0x10,`16*1-64`($ctx),$H2 # r1^n
+ vpmuludq $T1,$D4,$D1 # d1 = h1*r0
+ vpmuludq $T3,$D4,$D3 # d3 = h3*r0
+ vpmuludq $T4,$D4,$D4 # d4 = h4*r0
+
+ vpmuludq $T3,$H2,$H0 # h3*r1
+ vpaddq $H0,$D4,$D4 # d4 += h3*r1
+ vpshufd \$0x10,`16*2-64`($ctx),$H3 # s1^n
+ vpmuludq $T2,$H2,$H1 # h2*r1
+ vpaddq $H1,$D3,$D3 # d3 += h2*r1
+ vpshufd \$0x10,`16*3-64`($ctx),$H4 # r2^n
+ vpmuludq $T1,$H2,$H0 # h1*r1
+ vpaddq $H0,$D2,$D2 # d2 += h1*r1
+ vpmuludq $T0,$H2,$H2 # h0*r1
+ vpaddq $H2,$D1,$D1 # d1 += h0*r1
+ vpmuludq $T4,$H3,$H3 # h4*s1
+ vpaddq $H3,$D0,$D0 # d0 += h4*s1
+
+ vpshufd \$0x10,`16*4-64`($ctx),$H2 # s2^n
+ vpmuludq $T2,$H4,$H1 # h2*r2
+ vpaddq $H1,$D4,$D4 # d4 += h2*r2
+ vpmuludq $T1,$H4,$H0 # h1*r2
+ vpaddq $H0,$D3,$D3 # d3 += h1*r2
+ vpshufd \$0x10,`16*5-64`($ctx),$H3 # r3^n
+ vpmuludq $T0,$H4,$H4 # h0*r2
+ vpaddq $H4,$D2,$D2 # d2 += h0*r2
+ vpmuludq $T4,$H2,$H1 # h4*s2
+ vpaddq $H1,$D1,$D1 # d1 += h4*s2
+ vpshufd \$0x10,`16*6-64`($ctx),$H4 # s3^n
+ vpmuludq $T3,$H2,$H2 # h3*s2
+ vpaddq $H2,$D0,$D0 # d0 += h3*s2
+
+ vpmuludq $T1,$H3,$H0 # h1*r3
+ vpaddq $H0,$D4,$D4 # d4 += h1*r3
+ vpmuludq $T0,$H3,$H3 # h0*r3
+ vpaddq $H3,$D3,$D3 # d3 += h0*r3
+ vpshufd \$0x10,`16*7-64`($ctx),$H2 # r4^n
+ vpmuludq $T4,$H4,$H1 # h4*s3
+ vpaddq $H1,$D2,$D2 # d2 += h4*s3
+ vpshufd \$0x10,`16*8-64`($ctx),$H3 # s4^n
+ vpmuludq $T3,$H4,$H0 # h3*s3
+ vpaddq $H0,$D1,$D1 # d1 += h3*s3
+ vpmuludq $T2,$H4,$H4 # h2*s3
+ vpaddq $H4,$D0,$D0 # d0 += h2*s3
+
+ vpmuludq $T0,$H2,$H2 # h0*r4
+ vpaddq $H2,$D4,$D4 # h4 = d4 + h0*r4
+ vpmuludq $T4,$H3,$H1 # h4*s4
+ vpaddq $H1,$D3,$D3 # h3 = d3 + h4*s4
+ vpmuludq $T3,$H3,$H0 # h3*s4
+ vpaddq $H0,$D2,$D2 # h2 = d2 + h3*s4
+ vpmuludq $T2,$H3,$H1 # h2*s4
+ vpaddq $H1,$D1,$D1 # h1 = d1 + h2*s4
+ vpmuludq $T1,$H3,$H3 # h1*s4
+ vpaddq $H3,$D0,$D0 # h0 = d0 + h1*s4
+
+ jz .Lshort_tail_avx
+
+ vmovdqu 16*0($inp),$H0 # load input
+ vmovdqu 16*1($inp),$H1
+
+ vpsrldq \$6,$H0,$H2 # splat input
+ vpsrldq \$6,$H1,$H3
+ vpunpckhqdq $H1,$H0,$H4 # 4
+ vpunpcklqdq $H1,$H0,$H0 # 0:1
+ vpunpcklqdq $H3,$H2,$H3 # 2:3
+
+ vpsrlq \$40,$H4,$H4 # 4
+ vpsrlq \$26,$H0,$H1
+ vpand $MASK,$H0,$H0 # 0
+ vpsrlq \$4,$H3,$H2
+ vpand $MASK,$H1,$H1 # 1
+ vpsrlq \$30,$H3,$H3
+ vpand $MASK,$H2,$H2 # 2
+ vpand $MASK,$H3,$H3 # 3
+ vpor 32(%rcx),$H4,$H4 # padbit, yes, always
+
+ vpshufd \$0x32,`16*0-64`($ctx),$T4 # r0^n, 34xx -> x3x4
+ vpaddq 0x00(%r11),$H0,$H0
+ vpaddq 0x10(%r11),$H1,$H1
+ vpaddq 0x20(%r11),$H2,$H2
+ vpaddq 0x30(%r11),$H3,$H3
+ vpaddq 0x40(%r11),$H4,$H4
+
+ ################################################################
+ # multiply (inp[0:1]+hash) by r^4:r^3 and accumulate
+
+ vpmuludq $H0,$T4,$T0 # h0*r0
+ vpaddq $T0,$D0,$D0 # d0 += h0*r0
+ vpmuludq $H1,$T4,$T1 # h1*r0
+ vpaddq $T1,$D1,$D1 # d1 += h1*r0
+ vpmuludq $H2,$T4,$T0 # h2*r0
+ vpaddq $T0,$D2,$D2 # d2 += h2*r0
+ vpshufd \$0x32,`16*1-64`($ctx),$T2 # r1^n
+ vpmuludq $H3,$T4,$T1 # h3*r0
+ vpaddq $T1,$D3,$D3 # d3 += h3*r0
+ vpmuludq $H4,$T4,$T4 # h4*r0
+ vpaddq $T4,$D4,$D4 # d4 += h4*r0
+
+ vpmuludq $H3,$T2,$T0 # h3*r1
+ vpaddq $T0,$D4,$D4 # d4 += h3*r1
+ vpshufd \$0x32,`16*2-64`($ctx),$T3 # s1
+ vpmuludq $H2,$T2,$T1 # h2*r1
+ vpaddq $T1,$D3,$D3 # d3 += h2*r1
+ vpshufd \$0x32,`16*3-64`($ctx),$T4 # r2
+ vpmuludq $H1,$T2,$T0 # h1*r1
+ vpaddq $T0,$D2,$D2 # d2 += h1*r1
+ vpmuludq $H0,$T2,$T2 # h0*r1
+ vpaddq $T2,$D1,$D1 # d1 += h0*r1
+ vpmuludq $H4,$T3,$T3 # h4*s1
+ vpaddq $T3,$D0,$D0 # d0 += h4*s1
+
+ vpshufd \$0x32,`16*4-64`($ctx),$T2 # s2
+ vpmuludq $H2,$T4,$T1 # h2*r2
+ vpaddq $T1,$D4,$D4 # d4 += h2*r2
+ vpmuludq $H1,$T4,$T0 # h1*r2
+ vpaddq $T0,$D3,$D3 # d3 += h1*r2
+ vpshufd \$0x32,`16*5-64`($ctx),$T3 # r3
+ vpmuludq $H0,$T4,$T4 # h0*r2
+ vpaddq $T4,$D2,$D2 # d2 += h0*r2
+ vpmuludq $H4,$T2,$T1 # h4*s2
+ vpaddq $T1,$D1,$D1 # d1 += h4*s2
+ vpshufd \$0x32,`16*6-64`($ctx),$T4 # s3
+ vpmuludq $H3,$T2,$T2 # h3*s2
+ vpaddq $T2,$D0,$D0 # d0 += h3*s2
+
+ vpmuludq $H1,$T3,$T0 # h1*r3
+ vpaddq $T0,$D4,$D4 # d4 += h1*r3
+ vpmuludq $H0,$T3,$T3 # h0*r3
+ vpaddq $T3,$D3,$D3 # d3 += h0*r3
+ vpshufd \$0x32,`16*7-64`($ctx),$T2 # r4
+ vpmuludq $H4,$T4,$T1 # h4*s3
+ vpaddq $T1,$D2,$D2 # d2 += h4*s3
+ vpshufd \$0x32,`16*8-64`($ctx),$T3 # s4
+ vpmuludq $H3,$T4,$T0 # h3*s3
+ vpaddq $T0,$D1,$D1 # d1 += h3*s3
+ vpmuludq $H2,$T4,$T4 # h2*s3
+ vpaddq $T4,$D0,$D0 # d0 += h2*s3
+
+ vpmuludq $H0,$T2,$T2 # h0*r4
+ vpaddq $T2,$D4,$D4 # d4 += h0*r4
+ vpmuludq $H4,$T3,$T1 # h4*s4
+ vpaddq $T1,$D3,$D3 # d3 += h4*s4
+ vpmuludq $H3,$T3,$T0 # h3*s4
+ vpaddq $T0,$D2,$D2 # d2 += h3*s4
+ vpmuludq $H2,$T3,$T1 # h2*s4
+ vpaddq $T1,$D1,$D1 # d1 += h2*s4
+ vpmuludq $H1,$T3,$T3 # h1*s4
+ vpaddq $T3,$D0,$D0 # d0 += h1*s4
+
+.Lshort_tail_avx:
+ ################################################################
+ # horizontal addition
+
+ vpsrldq \$8,$D4,$T4
+ vpsrldq \$8,$D3,$T3
+ vpsrldq \$8,$D1,$T1
+ vpsrldq \$8,$D0,$T0
+ vpsrldq \$8,$D2,$T2
+ vpaddq $T3,$D3,$D3
+ vpaddq $T4,$D4,$D4
+ vpaddq $T0,$D0,$D0
+ vpaddq $T1,$D1,$D1
+ vpaddq $T2,$D2,$D2
+
+ ################################################################
+ # lazy reduction
+
+ vpsrlq \$26,$D3,$H3
+ vpand $MASK,$D3,$D3
+ vpaddq $H3,$D4,$D4 # h3 -> h4
+
+ vpsrlq \$26,$D0,$H0
+ vpand $MASK,$D0,$D0
+ vpaddq $H0,$D1,$D1 # h0 -> h1
+
+ vpsrlq \$26,$D4,$H4
+ vpand $MASK,$D4,$D4
+
+ vpsrlq \$26,$D1,$H1
+ vpand $MASK,$D1,$D1
+ vpaddq $H1,$D2,$D2 # h1 -> h2
+
+ vpaddq $H4,$D0,$D0
+ vpsllq \$2,$H4,$H4
+ vpaddq $H4,$D0,$D0 # h4 -> h0
+
+ vpsrlq \$26,$D2,$H2
+ vpand $MASK,$D2,$D2
+ vpaddq $H2,$D3,$D3 # h2 -> h3
+
+ vpsrlq \$26,$D0,$H0
+ vpand $MASK,$D0,$D0
+ vpaddq $H0,$D1,$D1 # h0 -> h1
+
+ vpsrlq \$26,$D3,$H3
+ vpand $MASK,$D3,$D3
+ vpaddq $H3,$D4,$D4 # h3 -> h4
+
+ vmovd $D0,`4*0-48-64`($ctx) # save partially reduced
+ vmovd $D1,`4*1-48-64`($ctx)
+ vmovd $D2,`4*2-48-64`($ctx)
+ vmovd $D3,`4*3-48-64`($ctx)
+ vmovd $D4,`4*4-48-64`($ctx)
+___
+$code.=<<___ if ($win64);
+ vmovdqa 0x50(%r11),%xmm6
+ vmovdqa 0x60(%r11),%xmm7
+ vmovdqa 0x70(%r11),%xmm8
+ vmovdqa 0x80(%r11),%xmm9
+ vmovdqa 0x90(%r11),%xmm10
+ vmovdqa 0xa0(%r11),%xmm11
+ vmovdqa 0xb0(%r11),%xmm12
+ vmovdqa 0xc0(%r11),%xmm13
+ vmovdqa 0xd0(%r11),%xmm14
+ vmovdqa 0xe0(%r11),%xmm15
+ lea 0xf8(%r11),%rsp
+.Ldo_avx_epilogue:
+___
+$code.=<<___ if (!$win64);
+ lea 0x58(%r11),%rsp
+___
+$code.=<<___;
+ vzeroupper
+ ret
+.size poly1305_blocks_avx,.-poly1305_blocks_avx
+
+.type poly1305_emit_avx,\@function,3
+.align 32
+poly1305_emit_avx:
+ cmpl \$0,20($ctx) # is_base2_26?
+ je .Lemit
+
+ mov 0($ctx),%eax # load hash value base 2^26
+ mov 4($ctx),%ecx
+ mov 8($ctx),%r8d
+ mov 12($ctx),%r11d
+ mov 16($ctx),%r10d
+
+ shl \$26,%rcx # base 2^26 -> base 2^64
+ mov %r8,%r9
+ shl \$52,%r8
+ add %rcx,%rax
+ shr \$12,%r9
+ add %rax,%r8 # h0
+ adc \$0,%r9
+
+ shl \$14,%r11
+ mov %r10,%rax
+ shr \$24,%r10
+ add %r11,%r9
+ shl \$40,%rax
+ add %rax,%r9 # h1
+ adc \$0,%r10 # h2
+
+ mov %r10,%rax # could be partially reduced, so reduce
+ mov %r10,%rcx
+ and \$3,%r10
+ shr \$2,%rax
+ and \$-4,%rcx
+ add %rcx,%rax
+ add %rax,%r8
+ adc \$0,%r9
+
+ mov %r8,%rax
+ add \$5,%r8 # compare to modulus
+ mov %r9,%rcx
+ adc \$0,%r9
+ adc \$0,%r10
+ shr \$2,%r10 # did 130-bit value overfow?
+ cmovnz %r8,%rax
+ cmovnz %r9,%rcx
+
+ add 0($nonce),%rax # accumulate nonce
+ adc 8($nonce),%rcx
+ mov %rax,0($mac) # write result
+ mov %rcx,8($mac)
+
+ ret
+.size poly1305_emit_avx,.-poly1305_emit_avx
+___
+
+if ($avx>1) {
+my ($H0,$H1,$H2,$H3,$H4, $MASK, $T4,$T0,$T1,$T2,$T3, $D0,$D1,$D2,$D3,$D4) =
+ map("%ymm$_",(0..15));
+my $S4=$MASK;
+
+$code.=<<___;
+.type poly1305_blocks_avx2,\@function,4
+.align 32
+poly1305_blocks_avx2:
+ mov 20($ctx),%r8d # is_base2_26
+ cmp \$128,$len
+ jae .Lblocks_avx2
+ test %r8d,%r8d
+ jz .Lblocks
+
+.Lblocks_avx2:
+ and \$-16,$len
+ jz .Lno_data_avx2
+
+ vzeroupper
+
+ test %r8d,%r8d
+ jz .Lbase2_64_avx2
+
+ test \$63,$len
+ jz .Leven_avx2
+
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lblocks_avx2_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 0($ctx),$d1 # load hash value
+ mov 8($ctx),$d2
+ mov 16($ctx),$h2#d
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ ################################# base 2^26 -> base 2^64
+ mov $d1#d,$h0#d
+ and \$-1<<31,$d1
+ mov $d2,$r1 # borrow $r1
+ mov $d2#d,$h1#d
+ and \$-1<<31,$d2
+
+ shr \$6,$d1
+ shl \$52,$r1
+ add $d1,$h0
+ shr \$12,$h1
+ shr \$18,$d2
+ add $r1,$h0
+ adc $d2,$h1
+
+ mov $h2,$d1
+ shl \$40,$d1
+ shr \$24,$h2
+ add $d1,$h1
+ adc \$0,$h2 # can be partially reduced...
+
+ mov \$-4,$d2 # ... so reduce
+ mov $h2,$d1
+ and $h2,$d2
+ shr \$2,$d1
+ and \$3,$h2
+ add $d2,$d1 # =*5
+ add $d1,$h0
+ adc \$0,$h1
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+.Lbase2_26_pre_avx2:
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+ sub \$16,%r15
+
+ call __poly1305_block
+ mov $r1,%rax
+
+ test \$63,%r15
+ jnz .Lbase2_26_pre_avx2
+
+ test $padbit,$padbit # if $padbit is zero,
+ jz .Lstore_base2_64_avx2 # store hash in base 2^64 format
+
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$r0
+ mov $h1,$r1
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$r0
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $r0,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$r1
+ and \$0x3ffffff,$h1 # h[3]
+ or $r1,$h2 # h[4]
+
+ test %r15,%r15
+ jz .Lstore_base2_26_avx2
+
+ vmovd %rax#d,%x#$H0
+ vmovd %rdx#d,%x#$H1
+ vmovd $h0#d,%x#$H2
+ vmovd $h1#d,%x#$H3
+ vmovd $h2#d,%x#$H4
+ jmp .Lproceed_avx2
+
+.align 32
+.Lstore_base2_64_avx2:
+ mov $h0,0($ctx)
+ mov $h1,8($ctx)
+ mov $h2,16($ctx) # note that is_base2_26 is zeroed
+ jmp .Ldone_avx2
+
+.align 16
+.Lstore_base2_26_avx2:
+ mov %rax#d,0($ctx) # store hash value base 2^26
+ mov %rdx#d,4($ctx)
+ mov $h0#d,8($ctx)
+ mov $h1#d,12($ctx)
+ mov $h2#d,16($ctx)
+.align 16
+.Ldone_avx2:
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rsp
+.Lno_data_avx2:
+.Lblocks_avx2_epilogue:
+ ret
+
+.align 32
+.Lbase2_64_avx2:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lbase2_64_avx2_body:
+
+ mov $len,%r15 # reassign $len
+
+ mov 24($ctx),$r0 # load r
+ mov 32($ctx),$s1
+
+ mov 0($ctx),$h0 # load hash value
+ mov 8($ctx),$h1
+ mov 16($ctx),$h2#d
+
+ mov $s1,$r1
+ mov $s1,%rax
+ shr \$2,$s1
+ add $r1,$s1 # s1 = r1 + (r1 >> 2)
+
+ test \$63,$len
+ jz .Linit_avx2
+
+.Lbase2_64_pre_avx2:
+ add 0($inp),$h0 # accumulate input
+ adc 8($inp),$h1
+ lea 16($inp),$inp
+ adc $padbit,$h2
+ sub \$16,%r15
+
+ call __poly1305_block
+ mov $r1,%rax
+
+ test \$63,%r15
+ jnz .Lbase2_64_pre_avx2
+
+.Linit_avx2:
+ ################################# base 2^64 -> base 2^26
+ mov $h0,%rax
+ mov $h0,%rdx
+ shr \$52,$h0
+ mov $h1,$d1
+ mov $h1,$d2
+ shr \$26,%rdx
+ and \$0x3ffffff,%rax # h[0]
+ shl \$12,$d1
+ and \$0x3ffffff,%rdx # h[1]
+ shr \$14,$h1
+ or $d1,$h0
+ shl \$24,$h2
+ and \$0x3ffffff,$h0 # h[2]
+ shr \$40,$d2
+ and \$0x3ffffff,$h1 # h[3]
+ or $d2,$h2 # h[4]
+
+ vmovd %rax#d,%x#$H0
+ vmovd %rdx#d,%x#$H1
+ vmovd $h0#d,%x#$H2
+ vmovd $h1#d,%x#$H3
+ vmovd $h2#d,%x#$H4
+ movl \$1,20($ctx) # set is_base2_26
+
+ call __poly1305_init_avx
+
+.Lproceed_avx2:
+ mov %r15,$len
+
+ mov 0(%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r13
+ mov 24(%rsp),%r12
+ mov 32(%rsp),%rbp
+ mov 40(%rsp),%rbx
+ lea 48(%rsp),%rax
+ lea 48(%rsp),%rsp
+.Lbase2_64_avx2_epilogue:
+ jmp .Ldo_avx2
+
+.align 32
+.Leven_avx2:
+ vmovd 4*0($ctx),%x#$H0 # load hash value base 2^26
+ vmovd 4*1($ctx),%x#$H1
+ vmovd 4*2($ctx),%x#$H2
+ vmovd 4*3($ctx),%x#$H3
+ vmovd 4*4($ctx),%x#$H4
+
+.Ldo_avx2:
+___
+$code.=<<___ if (!$win64);
+ lea -8(%rsp),%r11
+ sub \$0x128,%rsp
+___
+$code.=<<___ if ($win64);
+ lea -0xf8(%rsp),%r11
+ sub \$0x1c8,%rsp
+ vmovdqa %xmm6,0x50(%r11)
+ vmovdqa %xmm7,0x60(%r11)
+ vmovdqa %xmm8,0x70(%r11)
+ vmovdqa %xmm9,0x80(%r11)
+ vmovdqa %xmm10,0x90(%r11)
+ vmovdqa %xmm11,0xa0(%r11)
+ vmovdqa %xmm12,0xb0(%r11)
+ vmovdqa %xmm13,0xc0(%r11)
+ vmovdqa %xmm14,0xd0(%r11)
+ vmovdqa %xmm15,0xe0(%r11)
+.Ldo_avx2_body:
+___
+$code.=<<___;
+ lea 48+64($ctx),$ctx # size optimization
+ lea .Lconst(%rip),%rcx
+
+ # expand and copy pre-calculated table to stack
+ vmovdqu `16*0-64`($ctx),%x#$T2
+ and \$-512,%rsp
+ vmovdqu `16*1-64`($ctx),%x#$T3
+ vmovdqu `16*2-64`($ctx),%x#$T4
+ vmovdqu `16*3-64`($ctx),%x#$D0
+ vmovdqu `16*4-64`($ctx),%x#$D1
+ vmovdqu `16*5-64`($ctx),%x#$D2
+ vmovdqu `16*6-64`($ctx),%x#$D3
+ vpermq \$0x15,$T2,$T2 # 00003412 -> 12343434
+ vmovdqu `16*7-64`($ctx),%x#$D4
+ vpermq \$0x15,$T3,$T3
+ vpshufd \$0xc8,$T2,$T2 # 12343434 -> 14243444
+ vmovdqu `16*8-64`($ctx),%x#$MASK
+ vpermq \$0x15,$T4,$T4
+ vpshufd \$0xc8,$T3,$T3
+ vmovdqa $T2,0x00(%rsp)
+ vpermq \$0x15,$D0,$D0
+ vpshufd \$0xc8,$T4,$T4
+ vmovdqa $T3,0x20(%rsp)
+ vpermq \$0x15,$D1,$D1
+ vpshufd \$0xc8,$D0,$D0
+ vmovdqa $T4,0x40(%rsp)
+ vpermq \$0x15,$D2,$D2
+ vpshufd \$0xc8,$D1,$D1
+ vmovdqa $D0,0x60(%rsp)
+ vpermq \$0x15,$D3,$D3
+ vpshufd \$0xc8,$D2,$D2
+ vmovdqa $D1,0x80(%rsp)
+ vpermq \$0x15,$D4,$D4
+ vpshufd \$0xc8,$D3,$D3
+ vmovdqa $D2,0xa0(%rsp)
+ vpermq \$0x15,$MASK,$MASK
+ vpshufd \$0xc8,$D4,$D4
+ vmovdqa $D3,0xc0(%rsp)
+ vpshufd \$0xc8,$MASK,$MASK
+ vmovdqa $D4,0xe0(%rsp)
+ vmovdqa $MASK,0x100(%rsp)
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+
+ ################################################################
+ # load input
+ vmovdqu 16*0($inp),%x#$T0
+ vmovdqu 16*1($inp),%x#$T1
+ vinserti128 \$1,16*2($inp),$T0,$T0
+ vinserti128 \$1,16*3($inp),$T1,$T1
+ lea 16*4($inp),$inp
+
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpsrldq \$6,$T1,$T3
+ vpunpckhqdq $T1,$T0,$T4 # 4
+ vpunpcklqdq $T3,$T2,$T2 # 2:3
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+
+ vpsrlq \$30,$T2,$T3
+ vpsrlq \$4,$T2,$T2
+ vpsrlq \$26,$T0,$T1
+ vpsrlq \$40,$T4,$T4 # 4
+ vpand $MASK,$T2,$T2 # 2
+ vpand $MASK,$T0,$T0 # 0
+ vpand $MASK,$T1,$T1 # 1
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ lea 0x90(%rsp),%rax # size optimization
+ vpaddq $H2,$T2,$H2 # accumulate input
+ sub \$64,$len
+ jz .Ltail_avx2
+ jmp .Loop_avx2
+
+.align 32
+.Loop_avx2:
+ ################################################################
+ # ((inp[0]*r^4+r[4])*r^4+r[8])*r^4
+ # ((inp[1]*r^4+r[5])*r^4+r[9])*r^3
+ # ((inp[2]*r^4+r[6])*r^4+r[10])*r^2
+ # ((inp[3]*r^4+r[7])*r^4+r[11])*r^1
+ # \________/\________/
+ ################################################################
+ #vpaddq $H2,$T2,$H2 # accumulate input
+ vpaddq $H0,$T0,$H0
+ vmovdqa `32*0`(%rsp),$T0 # r0^4
+ vpaddq $H1,$T1,$H1
+ vmovdqa `32*1`(%rsp),$T1 # r1^4
+ vpaddq $H3,$T3,$H3
+ vmovdqa `32*3`(%rsp),$T2 # r2^4
+ vpaddq $H4,$T4,$H4
+ vmovdqa `32*6-0x90`(%rax),$T3 # s3^4
+ vmovdqa `32*8-0x90`(%rax),$S4 # s4^4
+
+ # d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
+ # d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
+ # d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
+ #
+ # however, as h2 is "chronologically" first one available pull
+ # corresponding operations up, so it's
+ #
+ # d4 = h2*r2 + h4*r0 + h3*r1 + h1*r3 + h0*r4
+ # d3 = h2*r1 + h3*r0 + h1*r2 + h0*r3 + h4*5*r4
+ # d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
+ # d1 = h2*5*r4 + h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3
+ # d0 = h2*5*r3 + h0*r0 + h4*5*r1 + h3*5*r2 + h1*5*r4
+
+ vpmuludq $H2,$T0,$D2 # d2 = h2*r0
+ vpmuludq $H2,$T1,$D3 # d3 = h2*r1
+ vpmuludq $H2,$T2,$D4 # d4 = h2*r2
+ vpmuludq $H2,$T3,$D0 # d0 = h2*s3
+ vpmuludq $H2,$S4,$D1 # d1 = h2*s4
+
+ vpmuludq $H0,$T1,$T4 # h0*r1
+ vpmuludq $H1,$T1,$H2 # h1*r1, borrow $H2 as temp
+ vpaddq $T4,$D1,$D1 # d1 += h0*r1
+ vpaddq $H2,$D2,$D2 # d2 += h1*r1
+ vpmuludq $H3,$T1,$T4 # h3*r1
+ vpmuludq `32*2`(%rsp),$H4,$H2 # h4*s1
+ vpaddq $T4,$D4,$D4 # d4 += h3*r1
+ vpaddq $H2,$D0,$D0 # d0 += h4*s1
+ vmovdqa `32*4-0x90`(%rax),$T1 # s2
+
+ vpmuludq $H0,$T0,$T4 # h0*r0
+ vpmuludq $H1,$T0,$H2 # h1*r0
+ vpaddq $T4,$D0,$D0 # d0 += h0*r0
+ vpaddq $H2,$D1,$D1 # d1 += h1*r0
+ vpmuludq $H3,$T0,$T4 # h3*r0
+ vpmuludq $H4,$T0,$H2 # h4*r0
+ vmovdqu 16*0($inp),%x#$T0 # load input
+ vpaddq $T4,$D3,$D3 # d3 += h3*r0
+ vpaddq $H2,$D4,$D4 # d4 += h4*r0
+ vinserti128 \$1,16*2($inp),$T0,$T0
+
+ vpmuludq $H3,$T1,$T4 # h3*s2
+ vpmuludq $H4,$T1,$H2 # h4*s2
+ vmovdqu 16*1($inp),%x#$T1
+ vpaddq $T4,$D0,$D0 # d0 += h3*s2
+ vpaddq $H2,$D1,$D1 # d1 += h4*s2
+ vmovdqa `32*5-0x90`(%rax),$H2 # r3
+ vpmuludq $H1,$T2,$T4 # h1*r2
+ vpmuludq $H0,$T2,$T2 # h0*r2
+ vpaddq $T4,$D3,$D3 # d3 += h1*r2
+ vpaddq $T2,$D2,$D2 # d2 += h0*r2
+ vinserti128 \$1,16*3($inp),$T1,$T1
+ lea 16*4($inp),$inp
+
+ vpmuludq $H1,$H2,$T4 # h1*r3
+ vpmuludq $H0,$H2,$H2 # h0*r3
+ vpsrldq \$6,$T0,$T2 # splat input
+ vpaddq $T4,$D4,$D4 # d4 += h1*r3
+ vpaddq $H2,$D3,$D3 # d3 += h0*r3
+ vpmuludq $H3,$T3,$T4 # h3*s3
+ vpmuludq $H4,$T3,$H2 # h4*s3
+ vpsrldq \$6,$T1,$T3
+ vpaddq $T4,$D1,$D1 # d1 += h3*s3
+ vpaddq $H2,$D2,$D2 # d2 += h4*s3
+ vpunpckhqdq $T1,$T0,$T4 # 4
+
+ vpmuludq $H3,$S4,$H3 # h3*s4
+ vpmuludq $H4,$S4,$H4 # h4*s4
+ vpunpcklqdq $T1,$T0,$T0 # 0:1
+ vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4
+ vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4
+ vpunpcklqdq $T3,$T2,$T3 # 2:3
+ vpmuludq `32*7-0x90`(%rax),$H0,$H4 # h0*r4
+ vpmuludq $H1,$S4,$H0 # h1*s4
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+ vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4
+ vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4
+
+ ################################################################
+ # lazy reduction (interleaved with tail of input splat)
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$D1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H4,$D4
+ vpand $MASK,$H4,$H4
+
+ vpsrlq \$4,$T3,$T2
+
+ vpsrlq \$26,$H1,$D1
+ vpand $MASK,$H1,$H1
+ vpaddq $D1,$H2,$H2 # h1 -> h2
+
+ vpaddq $D4,$H0,$H0
+ vpsllq \$2,$D4,$D4
+ vpaddq $D4,$H0,$H0 # h4 -> h0
+
+ vpand $MASK,$T2,$T2 # 2
+ vpsrlq \$26,$T0,$T1
+
+ vpsrlq \$26,$H2,$D2
+ vpand $MASK,$H2,$H2
+ vpaddq $D2,$H3,$H3 # h2 -> h3
+
+ vpaddq $T2,$H2,$H2 # modulo-scheduled
+ vpsrlq \$30,$T3,$T3
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$H1,$H1 # h0 -> h1
+
+ vpsrlq \$40,$T4,$T4 # 4
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpand $MASK,$T0,$T0 # 0
+ vpand $MASK,$T1,$T1 # 1
+ vpand $MASK,$T3,$T3 # 3
+ vpor 32(%rcx),$T4,$T4 # padbit, yes, always
+
+ sub \$64,$len
+ jnz .Loop_avx2
+
+ .byte 0x66,0x90
+.Ltail_avx2:
+ ################################################################
+ # while above multiplications were by r^4 in all lanes, in last
+ # iteration we multiply least significant lane by r^4 and most
+ # significant one by r, so copy of above except that references
+ # to the precomputed table are displaced by 4...
+
+ #vpaddq $H2,$T2,$H2 # accumulate input
+ vpaddq $H0,$T0,$H0
+ vmovdqu `32*0+4`(%rsp),$T0 # r0^4
+ vpaddq $H1,$T1,$H1
+ vmovdqu `32*1+4`(%rsp),$T1 # r1^4
+ vpaddq $H3,$T3,$H3
+ vmovdqu `32*3+4`(%rsp),$T2 # r2^4
+ vpaddq $H4,$T4,$H4
+ vmovdqu `32*6+4-0x90`(%rax),$T3 # s3^4
+ vmovdqu `32*8+4-0x90`(%rax),$S4 # s4^4
+
+ vpmuludq $H2,$T0,$D2 # d2 = h2*r0
+ vpmuludq $H2,$T1,$D3 # d3 = h2*r1
+ vpmuludq $H2,$T2,$D4 # d4 = h2*r2
+ vpmuludq $H2,$T3,$D0 # d0 = h2*s3
+ vpmuludq $H2,$S4,$D1 # d1 = h2*s4
+
+ vpmuludq $H0,$T1,$T4 # h0*r1
+ vpmuludq $H1,$T1,$H2 # h1*r1
+ vpaddq $T4,$D1,$D1 # d1 += h0*r1
+ vpaddq $H2,$D2,$D2 # d2 += h1*r1
+ vpmuludq $H3,$T1,$T4 # h3*r1
+ vpmuludq `32*2+4`(%rsp),$H4,$H2 # h4*s1
+ vpaddq $T4,$D4,$D4 # d4 += h3*r1
+ vpaddq $H2,$D0,$D0 # d0 += h4*s1
+
+ vpmuludq $H0,$T0,$T4 # h0*r0
+ vpmuludq $H1,$T0,$H2 # h1*r0
+ vpaddq $T4,$D0,$D0 # d0 += h0*r0
+ vmovdqu `32*4+4-0x90`(%rax),$T1 # s2
+ vpaddq $H2,$D1,$D1 # d1 += h1*r0
+ vpmuludq $H3,$T0,$T4 # h3*r0
+ vpmuludq $H4,$T0,$H2 # h4*r0
+ vpaddq $T4,$D3,$D3 # d3 += h3*r0
+ vpaddq $H2,$D4,$D4 # d4 += h4*r0
+
+ vpmuludq $H3,$T1,$T4 # h3*s2
+ vpmuludq $H4,$T1,$H2 # h4*s2
+ vpaddq $T4,$D0,$D0 # d0 += h3*s2
+ vpaddq $H2,$D1,$D1 # d1 += h4*s2
+ vmovdqu `32*5+4-0x90`(%rax),$H2 # r3
+ vpmuludq $H1,$T2,$T4 # h1*r2
+ vpmuludq $H0,$T2,$T2 # h0*r2
+ vpaddq $T4,$D3,$D3 # d3 += h1*r2
+ vpaddq $T2,$D2,$D2 # d2 += h0*r2
+
+ vpmuludq $H1,$H2,$T4 # h1*r3
+ vpmuludq $H0,$H2,$H2 # h0*r3
+ vpaddq $T4,$D4,$D4 # d4 += h1*r3
+ vpaddq $H2,$D3,$D3 # d3 += h0*r3
+ vpmuludq $H3,$T3,$T4 # h3*s3
+ vpmuludq $H4,$T3,$H2 # h4*s3
+ vpaddq $T4,$D1,$D1 # d1 += h3*s3
+ vpaddq $H2,$D2,$D2 # d2 += h4*s3
+
+ vpmuludq $H3,$S4,$H3 # h3*s4
+ vpmuludq $H4,$S4,$H4 # h4*s4
+ vpaddq $H3,$D2,$H2 # h2 = d2 + h3*r4
+ vpaddq $H4,$D3,$H3 # h3 = d3 + h4*r4
+ vpmuludq `32*7+4-0x90`(%rax),$H0,$H4 # h0*r4
+ vpmuludq $H1,$S4,$H0 # h1*s4
+ vmovdqa 64(%rcx),$MASK # .Lmask26
+ vpaddq $H4,$D4,$H4 # h4 = d4 + h0*r4
+ vpaddq $H0,$D0,$H0 # h0 = d0 + h1*s4
+
+ ################################################################
+ # horizontal addition
+
+ vpsrldq \$8,$D1,$T1
+ vpsrldq \$8,$H2,$T2
+ vpsrldq \$8,$H3,$T3
+ vpsrldq \$8,$H4,$T4
+ vpsrldq \$8,$H0,$T0
+ vpaddq $T1,$D1,$D1
+ vpaddq $T2,$H2,$H2
+ vpaddq $T3,$H3,$H3
+ vpaddq $T4,$H4,$H4
+ vpaddq $T0,$H0,$H0
+
+ vpermq \$0x2,$H3,$T3
+ vpermq \$0x2,$H4,$T4
+ vpermq \$0x2,$H0,$T0
+ vpermq \$0x2,$D1,$T1
+ vpermq \$0x2,$H2,$T2
+ vpaddq $T3,$H3,$H3
+ vpaddq $T4,$H4,$H4
+ vpaddq $T0,$H0,$H0
+ vpaddq $T1,$D1,$D1
+ vpaddq $T2,$H2,$H2
+
+ ################################################################
+ # lazy reduction
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$D1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H4,$D4
+ vpand $MASK,$H4,$H4
+
+ vpsrlq \$26,$H1,$D1
+ vpand $MASK,$H1,$H1
+ vpaddq $D1,$H2,$H2 # h1 -> h2
+
+ vpaddq $D4,$H0,$H0
+ vpsllq \$2,$D4,$D4
+ vpaddq $D4,$H0,$H0 # h4 -> h0
+
+ vpsrlq \$26,$H2,$D2
+ vpand $MASK,$H2,$H2
+ vpaddq $D2,$H3,$H3 # h2 -> h3
+
+ vpsrlq \$26,$H0,$D0
+ vpand $MASK,$H0,$H0
+ vpaddq $D0,$H1,$H1 # h0 -> h1
+
+ vpsrlq \$26,$H3,$D3
+ vpand $MASK,$H3,$H3
+ vpaddq $D3,$H4,$H4 # h3 -> h4
+
+ vmovd %x#$H0,`4*0-48-64`($ctx)# save partially reduced
+ vmovd %x#$H1,`4*1-48-64`($ctx)
+ vmovd %x#$H2,`4*2-48-64`($ctx)
+ vmovd %x#$H3,`4*3-48-64`($ctx)
+ vmovd %x#$H4,`4*4-48-64`($ctx)
+___
+$code.=<<___ if ($win64);
+ vmovdqa 0x50(%r11),%xmm6
+ vmovdqa 0x60(%r11),%xmm7
+ vmovdqa 0x70(%r11),%xmm8
+ vmovdqa 0x80(%r11),%xmm9
+ vmovdqa 0x90(%r11),%xmm10
+ vmovdqa 0xa0(%r11),%xmm11
+ vmovdqa 0xb0(%r11),%xmm12
+ vmovdqa 0xc0(%r11),%xmm13
+ vmovdqa 0xd0(%r11),%xmm14
+ vmovdqa 0xe0(%r11),%xmm15
+ lea 0xf8(%r11),%rsp
+.Ldo_avx2_epilogue:
+___
+$code.=<<___ if (!$win64);
+ lea 8(%r11),%rsp
+___
+$code.=<<___;
+ vzeroupper
+ ret
+.size poly1305_blocks_avx2,.-poly1305_blocks_avx2
+___
+}
+$code.=<<___;
+.align 64
+.Lconst:
+.Lmask24:
+.long 0x0ffffff,0,0x0ffffff,0,0x0ffffff,0,0x0ffffff,0
+.L129:
+.long 1<<24,0,1<<24,0,1<<24,0,1<<24,0
+.Lmask26:
+.long 0x3ffffff,0,0x3ffffff,0,0x3ffffff,0,0x3ffffff,0
+.Lfive:
+.long 5,0,5,0,5,0,5,0
+___
+}
+
+$code.=<<___;
+.asciz "Poly1305 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 16
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<.Lprologue
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lcommon_seh_tail
+
+ lea 48(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R14
+
+ jmp .Lcommon_seh_tail
+.size se_handler,.-se_handler
+
+.type avx_handler,\@abi-omnipotent
+.align 16
+avx_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ mov 208($context),%rax # pull context->R11
+
+ lea 0x50(%rax),%rsi
+ lea 0xf8(%rax),%rax
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$20,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size avx_handler,.-avx_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_poly1305_init
+ .rva .LSEH_end_poly1305_init
+ .rva .LSEH_info_poly1305_init
+
+ .rva .LSEH_begin_poly1305_blocks
+ .rva .LSEH_end_poly1305_blocks
+ .rva .LSEH_info_poly1305_blocks
+
+ .rva .LSEH_begin_poly1305_emit
+ .rva .LSEH_end_poly1305_emit
+ .rva .LSEH_info_poly1305_emit
+___
+$code.=<<___ if ($avx);
+ .rva .LSEH_begin_poly1305_blocks_avx
+ .rva .Lbase2_64_avx
+ .rva .LSEH_info_poly1305_blocks_avx_1
+
+ .rva .Lbase2_64_avx
+ .rva .Leven_avx
+ .rva .LSEH_info_poly1305_blocks_avx_2
+
+ .rva .Leven_avx
+ .rva .LSEH_end_poly1305_blocks_avx
+ .rva .LSEH_info_poly1305_blocks_avx_3
+
+ .rva .LSEH_begin_poly1305_emit_avx
+ .rva .LSEH_end_poly1305_emit_avx
+ .rva .LSEH_info_poly1305_emit_avx
+___
+$code.=<<___ if ($avx>1);
+ .rva .LSEH_begin_poly1305_blocks_avx2
+ .rva .Lbase2_64_avx2
+ .rva .LSEH_info_poly1305_blocks_avx2_1
+
+ .rva .Lbase2_64_avx2
+ .rva .Leven_avx2
+ .rva .LSEH_info_poly1305_blocks_avx2_2
+
+ .rva .Leven_avx2
+ .rva .LSEH_end_poly1305_blocks_avx2
+ .rva .LSEH_info_poly1305_blocks_avx2_3
+___
+$code.=<<___;
+.section .xdata
+.align 8
+.LSEH_info_poly1305_init:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .LSEH_begin_poly1305_init,.LSEH_begin_poly1305_init
+
+.LSEH_info_poly1305_blocks:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lblocks_body,.Lblocks_epilogue
+
+.LSEH_info_poly1305_emit:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .LSEH_begin_poly1305_emit,.LSEH_begin_poly1305_emit
+___
+$code.=<<___ if ($avx);
+.LSEH_info_poly1305_blocks_avx_1:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lblocks_avx_body,.Lblocks_avx_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx_2:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lbase2_64_avx_body,.Lbase2_64_avx_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx_3:
+ .byte 9,0,0,0
+ .rva avx_handler
+ .rva .Ldo_avx_body,.Ldo_avx_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_emit_avx:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .LSEH_begin_poly1305_emit_avx,.LSEH_begin_poly1305_emit_avx
+___
+$code.=<<___ if ($avx>1);
+.LSEH_info_poly1305_blocks_avx2_1:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lblocks_avx2_body,.Lblocks_avx2_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx2_2:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lbase2_64_avx2_body,.Lbase2_64_avx2_epilogue # HandlerData[]
+
+.LSEH_info_poly1305_blocks_avx2_3:
+ .byte 9,0,0,0
+ .rva avx_handler
+ .rva .Ldo_avx2_body,.Ldo_avx2_epilogue # HandlerData[]
+___
+}
+
+foreach (split('\n',$code)) {
+ s/\`([^\`]*)\`/eval($1)/ge;
+ s/%r([a-z]+)#d/%e$1/g;
+ s/%r([0-9]+)#d/%r$1d/g;
+ s/%x#%y/%x/g;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/crypto/poly1305/internal.h b/crypto/poly1305/internal.h
new file mode 100644
index 00000000..df6769ea
--- /dev/null
+++ b/crypto/poly1305/internal.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_POLY1305_INTERNAL_H
+#define OPENSSL_HEADER_POLY1305_INTERNAL_H
+
+#include <openssl/base.h>
+#include <openssl/poly1305.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
+
+void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
+ size_t in_len);
+
+void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]);
+#endif
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_POLY1305_INTERNAL_H */
diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c
index 5a49e2df..dc2d6a68 100644
--- a/crypto/poly1305/poly1305.c
+++ b/crypto/poly1305/poly1305.c
@@ -22,6 +22,8 @@
#include <openssl/cpu.h>
+#include "internal.h"
+
#if defined(OPENSSL_WINDOWS) || !defined(OPENSSL_X86_64)
@@ -48,15 +50,6 @@ static void U32TO8_LE(uint8_t *m, uint32_t v) {
}
#endif
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
-
-void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
- size_t in_len);
-
-void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]);
-#endif
-
static uint64_t mul32x32_64(uint32_t a, uint32_t b) { return (uint64_t)a * b; }
struct poly1305_state_st {
@@ -170,7 +163,7 @@ void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) {
uint32_t t0, t1, t2, t3;
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_functional()) {
+ if (CRYPTO_is_NEON_capable()) {
CRYPTO_poly1305_init_neon(statep, key);
return;
}
@@ -217,7 +210,7 @@ void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_functional()) {
+ if (CRYPTO_is_NEON_capable()) {
CRYPTO_poly1305_update_neon(statep, in, in_len);
return;
}
@@ -263,7 +256,7 @@ void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
uint32_t b, nb;
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
- if (CRYPTO_is_NEON_functional()) {
+ if (CRYPTO_is_NEON_capable()) {
CRYPTO_poly1305_finish_neon(statep, mac);
return;
}
diff --git a/crypto/poly1305/poly1305_arm.c b/crypto/poly1305/poly1305_arm.c
index 82876e18..de31d6b2 100644
--- a/crypto/poly1305/poly1305_arm.c
+++ b/crypto/poly1305/poly1305_arm.c
@@ -22,6 +22,7 @@
#include <string.h>
#include "../internal.h"
+#include "internal.h"
typedef struct {
diff --git a/crypto/poly1305/poly1305_test.cc b/crypto/poly1305/poly1305_test.cc
index cae30a42..2c25e93b 100644
--- a/crypto/poly1305/poly1305_test.cc
+++ b/crypto/poly1305/poly1305_test.cc
@@ -24,6 +24,54 @@
#include "../test/file_test.h"
+static bool TestSIMD(FileTest *t, unsigned excess,
+ const std::vector<uint8_t> &key,
+ const std::vector<uint8_t> &in,
+ const std::vector<uint8_t> &mac) {
+ poly1305_state state;
+ CRYPTO_poly1305_init(&state, key.data());
+
+ size_t done = 0;
+
+ // Feed 16 bytes in. Some implementations begin in non-SIMD mode and upgrade
+ // on-demand. Stress the upgrade path.
+ size_t todo = 16;
+ if (todo > in.size()) {
+ todo = in.size();
+ }
+ CRYPTO_poly1305_update(&state, in.data(), todo);
+ done += todo;
+
+ for (;;) {
+ // Feed 128 + |excess| bytes to test SIMD mode.
+ if (done + 128 + excess > in.size()) {
+ break;
+ }
+ CRYPTO_poly1305_update(&state, in.data() + done, 128 + excess);
+ done += 128 + excess;
+
+ // Feed |excess| bytes to ensure SIMD mode can handle short inputs.
+ if (done + excess > in.size()) {
+ break;
+ }
+ CRYPTO_poly1305_update(&state, in.data() + done, excess);
+ done += excess;
+ }
+
+ // Consume the remainder and finish.
+ CRYPTO_poly1305_update(&state, in.data() + done, in.size() - done);
+
+ // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
+ alignas(16) uint8_t out[16];
+ CRYPTO_poly1305_finish(&state, out);
+ if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
+ t->PrintLine("SIMD pattern %u failed.", excess);
+ return false;
+ }
+
+ return true;
+}
+
static bool TestPoly1305(FileTest *t, void *arg) {
std::vector<uint8_t> key, in, mac;
if (!t->GetBytes(&key, "Key") ||
@@ -54,11 +102,20 @@ static bool TestPoly1305(FileTest *t, void *arg) {
CRYPTO_poly1305_update(&state, &in[i], 1);
}
CRYPTO_poly1305_finish(&state, out);
- if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) {
+ if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
t->PrintLine("Streaming Poly1305 failed.");
return false;
}
+ // Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of
+ // four blocks, so test up to three blocks of excess.
+ if (!TestSIMD(t, 0, key, in, mac) ||
+ !TestSIMD(t, 16, key, in, mac) ||
+ !TestSIMD(t, 32, key, in, mac) ||
+ !TestSIMD(t, 48, key, in, mac)) {
+ return false;
+ }
+
return true;
}
diff --git a/crypto/poly1305/poly1305_test.txt b/crypto/poly1305/poly1305_test.txt
deleted file mode 100644
index ad40699e..00000000
--- a/crypto/poly1305/poly1305_test.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-# RFC 7539, section 2.5.2.
-
-Key = 85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b
-Input = "Cryptographic Forum Research Group"
-MAC = a8061dc1305136c6c22b8baf0c0127a9
-
-
-# RFC 7539, section A.3.
-
-Key = 0000000000000000000000000000000000000000000000000000000000000000
-Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-MAC = 00000000000000000000000000000000
-
-Key = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e
-Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
-MAC = 36e5f6b5c5e06070f0efca96227a863e
-
-Key = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000
-Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
-MAC = f3477e7cd95417af89a6b8794c310cf0
-
-Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
-Input = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
-MAC = 4541669a7eaaee61e708dc7cbcc5eb62
-
-Key = 0200000000000000000000000000000000000000000000000000000000000000
-Input = ffffffffffffffffffffffffffffffff
-MAC = 03000000000000000000000000000000
-
-Key = 02000000000000000000000000000000ffffffffffffffffffffffffffffffff
-Input = 02000000000000000000000000000000
-MAC = 03000000000000000000000000000000
-
-Key = 0100000000000000000000000000000000000000000000000000000000000000
-Input = fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000
-MAC = 05000000000000000000000000000000
-
-Key = 0100000000000000000000000000000000000000000000000000000000000000
-Input = fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101
-MAC = 00000000000000000000000000000000
-
-Key = 0200000000000000000000000000000000000000000000000000000000000000
-Input = fdffffffffffffffffffffffffffffff
-MAC = faffffffffffffffffffffffffffffff
-
-Key = 0100000000000000040000000000000000000000000000000000000000000000
-Input = e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000
-MAC = 14000000000000005500000000000000
-
-Key = 0100000000000000040000000000000000000000000000000000000000000000
-Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000
-MAC = 13000000000000000000000000000000
diff --git a/crypto/poly1305/poly1305_tests.txt b/crypto/poly1305/poly1305_tests.txt
new file mode 100644
index 00000000..611007a0
--- /dev/null
+++ b/crypto/poly1305/poly1305_tests.txt
@@ -0,0 +1,159 @@
+# RFC 7539, section 2.5.2.
+
+Key = 85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b
+Input = "Cryptographic Forum Research Group"
+MAC = a8061dc1305136c6c22b8baf0c0127a9
+
+
+# RFC 7539, section A.3.
+
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+MAC = 00000000000000000000000000000000
+
+Key = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e
+Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+MAC = 36e5f6b5c5e06070f0efca96227a863e
+
+Key = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000
+Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+MAC = f3477e7cd95417af89a6b8794c310cf0
+
+Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
+Input = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
+MAC = 4541669a7eaaee61e708dc7cbcc5eb62
+
+Key = 0200000000000000000000000000000000000000000000000000000000000000
+Input = ffffffffffffffffffffffffffffffff
+MAC = 03000000000000000000000000000000
+
+Key = 02000000000000000000000000000000ffffffffffffffffffffffffffffffff
+Input = 02000000000000000000000000000000
+MAC = 03000000000000000000000000000000
+
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+Input = fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000
+MAC = 05000000000000000000000000000000
+
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+Input = fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101
+MAC = 00000000000000000000000000000000
+
+Key = 0200000000000000000000000000000000000000000000000000000000000000
+Input = fdffffffffffffffffffffffffffffff
+MAC = faffffffffffffffffffffffffffffff
+
+Key = 0100000000000000040000000000000000000000000000000000000000000000
+Input = e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000
+MAC = 14000000000000005500000000000000
+
+Key = 0100000000000000040000000000000000000000000000000000000000000000
+Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000
+MAC = 13000000000000000000000000000000
+
+
+# Additional test vectors that are long enough to ensure OpenSSL's SIMD
+# assembly is fully tested.
+
+# Length 2048.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfed
+MAC = 69d28f73dd09d39a92aa179da354b7ea
+
+# Length 2049.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc8
+MAC = d6a26654b88572e875d9661c83471c1b
+
+# Length 2050.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852
+MAC = 9fbbb7f7adcd0cd5b46a4a520b22499a
+
+# Length 2051.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f5
+MAC = eb7cdceb97ade2a07622f8f5a4b1ce15
+
+# Length 2052.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f590
+MAC = d41c310927cd92e14784ea78b85503db
+
+# Length 2053.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073
+MAC = 16af133c423f783a14c49d9f526384cf
+
+# Length 2054.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4
+MAC = 00c75db8f0636b22f195645b03091f5f
+
+# Length 2055.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f434
+MAC = 4a532bc740f581555831345f3b75bf33
+
+# Length 2056.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a
+MAC = 698c7d32c5923871d124a2479e521706
+
+# Length 2057.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c
+MAC = a677187dbf3c927aeeafb9ebce0f61dc
+
+# Length 2058.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a
+MAC = 201fed7eee981b31d2cc42ff6c38141a
+
+# Length 2059.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28
+MAC = 0c3d3d01a37f347c4f7c5826bcafb3e1
+
+# Length 2060.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c9
+MAC = 33a4e0e0bed7c84c5cc5dd4784410f07
+
+# Length 2061.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e
+MAC = 8e41c40a2f8ec58fe594f3a3a2de4ae1
+
+# Length 2062.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21
+MAC = c6e5d1810fd878ac6b844c66cef36a22
+
+# Length 2063.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21df
+MAC = f6eaae369c3cb5c05748e8d919178e00
+
+# Regression test for https://rt.openssl.org/Ticket/Display.html?id=4439
+Key = 2d773be37adb1e4d683bf0075e79c4ee037918535a7f99ccb7040fb5f5f43aea
+Input = 89dab80b7717c1db5db437860a3f70218e93e1b8f461fb677f16f35f6f87e2a91c99bc3a47ace47640cc95c345be5ecca5a3523c35cc01893af0b64a620334270372ec12482d1b1e363561698a578b359803495bb4e2ef1930b17a5190b580f141300df30adbeca28f6427a8bc1a999fd51c554a017d095d8c3e3127daf9f595
+MAC = c85d15ed44c378d6b00e23064c7bcd51
+
+# Regression tests for https://rt.openssl.org/Ticket/Display.html?id=4483
+
+Key = 7f1b02640000000000000000000000000000000000000000cccccccccccccccc
+Input = cccccccccccccccccccccccccccccccccccccccccccccccccc80ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccceccccccccccccccccccccccccccccccccccccc5cccccccccccccccccccccccccccccccccccccccccce3ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaccccccccccccccccccccce6cccccccccc000000afccccccccccccccccccfffffff5000000000000000000000000000000000000000000000000000000ffffffe70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000719205a8521dfc
+MAC = 8559b876eceed66eb37798c0457baff9
+
+Key = e00016000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+Input = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000000000000000800264
+MAC = 00bd1258978e205444c9aaaa82006fed
+
+Key = 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+Input = 02fc
+MAC = 06120c0c0c0c0c0c0c0c0c0c0c0c0c0c
+
+Key = 00ff000000000000000000000000000000000000001e00000000000000007b7b
+Input = 7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b007b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff0009000000000000000000000000100000000009000000640000000000000000000000001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff00090000000000000000007a000010000000000900000064000000000000000000000000000000000000000000000000fc
+MAC = 33205bbf9e9f8f7212ab9e2ab9b7e4a5
diff --git a/crypto/poly1305/poly1305_vec.c b/crypto/poly1305/poly1305_vec.c
index 59aab199..3045a2f1 100644
--- a/crypto/poly1305/poly1305_vec.c
+++ b/crypto/poly1305/poly1305_vec.c
@@ -701,9 +701,9 @@ static size_t poly1305_combine(poly1305_state_internal *st, const uint8_t *m,
t0 &= 0x3ffffff;
t1 = t1 + c;
- st->HH[0] = ((t0) | (t1 << 26)) & 0xfffffffffffull;
- st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & 0xfffffffffffull;
- st->HH[2] = ((t3 >> 10) | (t4 << 16)) & 0x3ffffffffffull;
+ st->HH[0] = ((t0) | (t1 << 26)) & UINT64_C(0xfffffffffff);
+ st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & UINT64_C(0xfffffffffff);
+ st->HH[2] = ((t3 >> 10) | (t4 << 16)) & UINT64_C(0x3ffffffffff);
return consumed;
}
diff --git a/crypto/rand/CMakeLists.txt b/crypto/rand/CMakeLists.txt
index eedf81b8..c66d2eeb 100644
--- a/crypto/rand/CMakeLists.txt
+++ b/crypto/rand/CMakeLists.txt
@@ -13,6 +13,7 @@ add_library(
OBJECT
+ deterministic.c
rand.c
urandom.c
windows.c
diff --git a/crypto/rand/deterministic.c b/crypto/rand/deterministic.c
new file mode 100644
index 00000000..e6b7bb7e
--- /dev/null
+++ b/crypto/rand/deterministic.c
@@ -0,0 +1,49 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/rand.h>
+
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+
+#include <string.h>
+
+#include <openssl/chacha.h>
+
+#include "internal.h"
+
+
+/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occured.
+ *
+ * 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.) */
+static uint64_t g_num_calls = 0;
+
+void RAND_cleanup(void) {}
+
+void RAND_reset_for_fuzzing(void) { g_num_calls = 0; }
+
+void CRYPTO_sysrand(uint8_t *out, size_t requested) {
+ static const uint8_t kZeroKey[32];
+
+ uint8_t nonce[12];
+ memset(nonce, 0, sizeof(nonce));
+ memcpy(nonce, &g_num_calls, sizeof(g_num_calls));
+
+ memset(out, 0, requested);
+ CRYPTO_chacha_20(out, out, requested, kZeroKey, nonce, 0);
+ g_num_calls++;
+}
+
+#endif /* BORINGSSL_UNSAFE_FUZZER_MODE */
diff --git a/crypto/rand/rand.c b/crypto/rand/rand.c
index 82087ba2..5a1bec2e 100644
--- a/crypto/rand/rand.c
+++ b/crypto/rand/rand.c
@@ -72,7 +72,8 @@ static void rand_thread_state_free(void *state) {
OPENSSL_free(state);
}
-#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
+#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
+ !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
/* These functions are defined in asm/rdrand-x86_64.pl */
extern int CRYPTO_rdrand(uint8_t out[8]);
diff --git a/crypto/rand/urandom.c b/crypto/rand/urandom.c
index 5bf5c739..434fe431 100644
--- a/crypto/rand/urandom.c
+++ b/crypto/rand/urandom.c
@@ -14,7 +14,7 @@
#include <openssl/rand.h>
-#if !defined(OPENSSL_WINDOWS)
+#if !defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
#include <assert.h>
#include <errno.h>
@@ -69,7 +69,7 @@ static void init_once(void) {
CRYPTO_STATIC_MUTEX_lock_read(&requested_lock);
urandom_buffering = urandom_buffering_requested;
int fd = urandom_fd_requested;
- CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock);
if (fd == -2) {
do {
@@ -106,7 +106,7 @@ void RAND_set_urandom_fd(int fd) {
CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
urandom_fd_requested = fd;
- CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
CRYPTO_once(&once, init_once);
if (urandom_fd != fd) {
@@ -127,7 +127,7 @@ void RAND_enable_fork_unsafe_buffering(int fd) {
CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
urandom_buffering_requested = 1;
urandom_fd_requested = fd;
- CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
CRYPTO_once(&once, init_once);
if (urandom_buffering != 1 || (fd >= 0 && urandom_fd != fd)) {
@@ -220,4 +220,4 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
}
}
-#endif /* !OPENSSL_WINDOWS */
+#endif /* !OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */
diff --git a/crypto/rand/windows.c b/crypto/rand/windows.c
index 1a0cb8b0..5a9a96b4 100644
--- a/crypto/rand/windows.c
+++ b/crypto/rand/windows.c
@@ -14,12 +14,12 @@
#include <openssl/rand.h>
-#if defined(OPENSSL_WINDOWS)
+#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
#include <limits.h>
#include <stdlib.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
@@ -30,7 +30,7 @@
#include <ntsecapi.h>
#undef SystemFunction036
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#include "internal.h"
@@ -53,4 +53,4 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
return;
}
-#endif /* OPENSSL_WINDOWS */
+#endif /* OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_FUZZER_MODE */
diff --git a/crypto/rc4/asm/rc4-586.pl b/crypto/rc4/asm/rc4-586.pl
index fc860ae2..8d3ccb72 100644
--- a/crypto/rc4/asm/rc4-586.pl
+++ b/crypto/rc4/asm/rc4-586.pl
@@ -384,31 +384,5 @@ $idx="edx";
&mov (&DWP(-4,$out),"eax"); # key->y=0;
&function_end("asm_RC4_set_key");
-# const char *RC4_options(void);
-&function_begin_B("RC4_options");
- &call (&label("pic_point"));
-&set_label("pic_point");
- &blindpop("eax");
- &lea ("eax",&DWP(&label("opts")."-".&label("pic_point"),"eax"));
- &picmeup("edx","OPENSSL_ia32cap_P");
- &mov ("edx",&DWP(0,"edx"));
- &bt ("edx",20);
- &jc (&label("1xchar"));
- &bt ("edx",26);
- &jnc (&label("ret"));
- &add ("eax",25);
- &ret ();
-&set_label("1xchar");
- &add ("eax",12);
-&set_label("ret");
- &ret ();
-&set_label("opts",64);
-&asciz ("rc4(4x,int)");
-&asciz ("rc4(1x,char)");
-&asciz ("rc4(8x,mmx)");
-&asciz ("RC4 for x86, CRYPTOGAMS by <appro\@openssl.org>");
-&align (64);
-&function_end_B("RC4_options");
-
&asm_finish();
diff --git a/crypto/refcount_lock.c b/crypto/refcount_lock.c
index bb8ef86b..ea6a06d3 100644
--- a/crypto/refcount_lock.c
+++ b/crypto/refcount_lock.c
@@ -31,7 +31,7 @@ void CRYPTO_refcount_inc(CRYPTO_refcount_t *count) {
if (*count < CRYPTO_REFCOUNT_MAX) {
(*count)++;
}
- CRYPTO_STATIC_MUTEX_unlock(&g_refcount_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock);
}
int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count) {
@@ -45,7 +45,7 @@ int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count) {
(*count)--;
}
ret = (*count == 0);
- CRYPTO_STATIC_MUTEX_unlock(&g_refcount_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock);
return ret;
}
diff --git a/crypto/rsa/blinding.c b/crypto/rsa/blinding.c
index e6b987d9..d9d90c2b 100644
--- a/crypto/rsa/blinding.c
+++ b/crypto/rsa/blinding.c
@@ -120,53 +120,35 @@
#define BN_BLINDING_COUNTER 32
struct bn_blinding_st {
- BIGNUM *A;
- BIGNUM *Ai;
- BIGNUM *e;
- BIGNUM *mod;
- int counter;
- /* mont is the Montgomery context used for this |BN_BLINDING|. It is not
- * owned and must outlive this structure. */
- const BN_MONT_CTX *mont;
- int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont);
+ BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */
+ BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */
+ unsigned counter;
};
-BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) {
- BN_BLINDING *ret = NULL;
+static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx);
- ret = (BN_BLINDING*) OPENSSL_malloc(sizeof(BN_BLINDING));
+BN_BLINDING *BN_BLINDING_new(void) {
+ BN_BLINDING *ret = OPENSSL_malloc(sizeof(BN_BLINDING));
if (ret == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
return NULL;
}
memset(ret, 0, sizeof(BN_BLINDING));
- if (A != NULL) {
- ret->A = BN_dup(A);
- if (ret->A == NULL) {
- goto err;
- }
- }
- if (Ai != NULL) {
- ret->Ai = BN_dup(Ai);
- if (ret->Ai == NULL) {
- goto err;
- }
- }
- /* save a copy of mod in the BN_BLINDING structure */
- ret->mod = BN_dup(mod);
- if (ret->mod == NULL) {
+ ret->A = BN_new();
+ if (ret->A == NULL) {
goto err;
}
- if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) {
- BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
+
+ ret->Ai = BN_new();
+ if (ret->Ai == NULL) {
+ goto err;
}
- /* Set the counter to the special value -1
- * to indicate that this is never-used fresh blinding
- * that does not need updating before first use. */
- ret->counter = -1;
+ /* The blinding values need to be created before this blinding can be used. */
+ ret->counter = BN_BLINDING_COUNTER - 1;
+
return ret;
err:
@@ -181,242 +163,105 @@ void BN_BLINDING_free(BN_BLINDING *r) {
BN_free(r->A);
BN_free(r->Ai);
- BN_free(r->e);
- BN_free(r->mod);
OPENSSL_free(r);
}
-int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) {
- int ret = 0;
-
- if (b->A == NULL || b->Ai == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
- goto err;
- }
-
- if (b->counter == -1) {
- b->counter = 0;
- }
-
- if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL) {
+static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ if (++b->counter == BN_BLINDING_COUNTER) {
/* re-create blinding parameters */
- if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) {
+ if (!bn_blinding_create_param(b, e, mont, ctx)) {
goto err;
}
+ b->counter = 0;
} else {
- if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) {
- goto err;
- }
- if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx)) {
+ if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) ||
+ !BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) {
goto err;
}
}
- ret = 1;
+ return 1;
err:
- if (b->counter == BN_BLINDING_COUNTER) {
- b->counter = 0;
- }
- return ret;
-}
-
-int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) {
- int ret = 1;
+ /* |A| and |Ai| may be in an inconsistent state so they both need to be
+ * replaced the next time this blinding is used. Note that this is only
+ * sufficient because support for |BN_BLINDING_NO_UPDATE| and
+ * |BN_BLINDING_NO_RECREATE| was previously dropped. */
+ b->counter = BN_BLINDING_COUNTER - 1;
- if (b->A == NULL || b->Ai == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
- return 0;
- }
+ return 0;
+}
- if (b->counter == -1) {
- /* Fresh blinding, doesn't need updating. */
- b->counter = 0;
- } else if (!BN_BLINDING_update(b, ctx)) {
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
+ * cancels one Montgomery factor, so the resulting value of |n| is unencoded.
+ */
+ if (!bn_blinding_update(b, e, mont, ctx) ||
+ !BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) {
return 0;
}
- if (!BN_mod_mul(n, n, b->A, b->mod, ctx)) {
- ret = 0;
- }
-
- return ret;
+ return 1;
}
-int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_CTX *ctx) {
- if (b->Ai == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
- return 0;
- }
- return BN_mod_mul(n, n, b->Ai, b->mod, ctx);
+int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont,
+ BN_CTX *ctx) {
+ /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
+ * cancels one Montgomery factor, so the resulting value of |n| is unencoded.
+ */
+ return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx);
}
-BN_BLINDING *BN_BLINDING_create_param(
- BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
- int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont),
- const BN_MONT_CTX *mont) {
+static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ BIGNUM mont_N_consttime;
+ BN_init(&mont_N_consttime);
+ BN_with_flags(&mont_N_consttime, &mont->N, BN_FLG_CONSTTIME);
int retry_counter = 32;
- BN_BLINDING *ret = NULL;
-
- if (b == NULL) {
- ret = BN_BLINDING_new(NULL, NULL, m);
- } else {
- ret = b;
- }
-
- if (ret == NULL) {
- goto err;
- }
-
- if (ret->A == NULL && (ret->A = BN_new()) == NULL) {
- goto err;
- }
- if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) {
- goto err;
- }
-
- if (e != NULL) {
- BN_free(ret->e);
- ret->e = BN_dup(e);
- }
- if (ret->e == NULL) {
- goto err;
- }
-
- if (bn_mod_exp != NULL) {
- ret->bn_mod_exp = bn_mod_exp;
- }
- if (mont != NULL) {
- ret->mont = mont;
- }
do {
- if (!BN_rand_range(ret->A, ret->mod)) {
- goto err;
+ if (!BN_rand_range(b->A, &mont->N)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* |BN_from_montgomery| + |BN_mod_inverse_no_branch| is equivalent to, but
+ * more efficient than, |BN_mod_inverse_no_branch| + |BN_to_montgomery|. */
+ if (!BN_from_montgomery(b->Ai, b->A, mont, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
int no_inverse;
- if (BN_mod_inverse_ex(ret->Ai, &no_inverse, ret->A, ret->mod, ctx) == NULL) {
+ if (BN_mod_inverse_ex(b->Ai, &no_inverse, b->Ai, &mont_N_consttime, ctx) ==
+ NULL) {
/* this should almost never happen for good RSA keys */
if (no_inverse) {
if (retry_counter-- == 0) {
OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS);
- goto err;
+ return 0;
}
ERR_clear_error();
} else {
- goto err;
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
} else {
break;
}
} while (1);
- if (ret->bn_mod_exp != NULL && ret->mont != NULL) {
- if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->mont)) {
- goto err;
- }
- } else {
- if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) {
- goto err;
- }
- }
-
- return ret;
-
-err:
- if (b == NULL) {
- BN_BLINDING_free(ret);
- ret = NULL;
- }
-
- return ret;
-}
-
-static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
- const BIGNUM *q, BN_CTX *ctx) {
- BIGNUM *ret = NULL, *r0, *r1, *r2;
-
- if (d == NULL || p == NULL || q == NULL) {
- return NULL;
- }
-
- BN_CTX_start(ctx);
- r0 = BN_CTX_get(ctx);
- r1 = BN_CTX_get(ctx);
- r2 = BN_CTX_get(ctx);
- if (r2 == NULL) {
- goto err;
- }
-
- if (!BN_sub(r1, p, BN_value_one())) {
- goto err;
- }
- if (!BN_sub(r2, q, BN_value_one())) {
- goto err;
- }
- if (!BN_mul(r0, r1, r2, ctx)) {
- goto err;
- }
-
- ret = BN_mod_inverse(NULL, d, r0, ctx);
-
-err:
- BN_CTX_end(ctx);
- return ret;
-}
-
-BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx) {
- BIGNUM local_n;
- BIGNUM *e, *n;
- BN_CTX *ctx;
- BN_BLINDING *ret = NULL;
- BN_MONT_CTX *mont_ctx = NULL;
-
- if (in_ctx == NULL) {
- ctx = BN_CTX_new();
- if (ctx == NULL) {
- return 0;
- }
- } else {
- ctx = in_ctx;
- }
-
- if (rsa->e == NULL) {
- e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
- if (e == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
- goto err;
- }
- } else {
- e = rsa->e;
- }
-
- n = &local_n;
- BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
-
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- mont_ctx = BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx);
- if (mont_ctx == NULL) {
- goto err;
- }
- }
-
- ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp,
- mont_ctx);
- if (ret == NULL) {
- OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
- goto err;
+ if (!BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
-err:
- if (in_ctx == NULL) {
- BN_CTX_free(ctx);
- }
- if (rsa->e == NULL) {
- BN_free(e);
+ if (!BN_to_montgomery(b->A, b->A, mont, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- return ret;
+ return 1;
}
diff --git a/crypto/rsa/internal.h b/crypto/rsa/internal.h
index 4d27344e..c6ea97f0 100644
--- a/crypto/rsa/internal.h
+++ b/crypto/rsa/internal.h
@@ -77,9 +77,6 @@ int rsa_default_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out,
int padding);
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);
-int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
- size_t max_out, const uint8_t *in, size_t in_len,
- int padding);
int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
size_t len);
int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
@@ -90,17 +87,12 @@ int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
#define RSA_PKCS1_PADDING_SIZE 11
-BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
+BN_BLINDING *BN_BLINDING_new(void);
void BN_BLINDING_free(BN_BLINDING *b);
-int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx);
-int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
-int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_CTX *ctx);
-BN_BLINDING *BN_BLINDING_create_param(
- BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
- int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont),
- const BN_MONT_CTX *mont);
-BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
+ const BN_MONT_CTX *mont_ctx, BN_CTX *ctx);
+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,
diff --git a/crypto/rsa/padding.c b/crypto/rsa/padding.c
index 128950ae..12147ea4 100644
--- a/crypto/rsa/padding.c
+++ b/crypto/rsa/padding.c
@@ -59,6 +59,7 @@
#include <limits.h>
#include <string.h>
+#include <openssl/bn.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -73,7 +74,6 @@
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
unsigned j;
- uint8_t *p;
if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
@@ -85,7 +85,7 @@ int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
return 0;
}
- p = (uint8_t *)to;
+ uint8_t *p = to;
*(p++) = 0;
*(p++) = 1; /* Private Key BT (Block Type) */
@@ -154,7 +154,6 @@ int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
const uint8_t *from, unsigned from_len) {
unsigned i, j;
- uint8_t *p;
if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
@@ -166,7 +165,7 @@ int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
return 0;
}
- p = (unsigned char *)to;
+ uint8_t *p = to;
*(p++) = 0;
*(p++) = 2; /* Public Key BT (Block Type) */
@@ -275,8 +274,8 @@ int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
return 1;
}
-int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed,
- unsigned seedlen, const EVP_MD *dgst) {
+static int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed,
+ unsigned seedlen, const EVP_MD *dgst) {
unsigned outlen = 0;
uint32_t i;
uint8_t cnt[4];
@@ -357,7 +356,7 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
seed = to + 1;
db = to + mdlen + 1;
- if (!EVP_Digest((void *)param, param_len, db, NULL, md, NULL)) {
+ if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) {
return 0;
}
memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1);
@@ -443,7 +442,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
db[i] ^= maskeddb[i];
}
- if (!EVP_Digest((void *)param, param_len, phash, NULL, md, NULL)) {
+ if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
goto err;
}
diff --git a/crypto/rsa/rsa.c b/crypto/rsa/rsa.c
index 9ffea1f2..e5f98916 100644
--- a/crypto/rsa/rsa.c
+++ b/crypto/rsa/rsa.c
@@ -64,7 +64,7 @@
#include <openssl/err.h>
#include <openssl/ex_data.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/thread.h>
#include "internal.h"
@@ -258,16 +258,6 @@ int RSA_private_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
return out_len;
}
-int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
- const uint8_t *in, size_t in_len, int padding) {
- if (rsa->meth->verify_raw) {
- return rsa->meth->verify_raw(rsa, out_len, out, max_out, in, in_len, padding);
- }
-
- return rsa_default_verify_raw(rsa, out_len, out, max_out, in, in_len,
- padding);
-}
-
int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
int padding) {
size_t out_len;
@@ -473,6 +463,11 @@ finish:
int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
const uint8_t *sig, size_t sig_len, RSA *rsa) {
+ if (rsa->n == NULL || rsa->e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
+ return 0;
+ }
+
const size_t rsa_size = RSA_size(rsa);
uint8_t *buf = NULL;
int ret = 0;
@@ -480,15 +475,6 @@ int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
size_t signed_msg_len, len;
int signed_msg_is_alloced = 0;
- if (rsa->meth->verify) {
- return rsa->meth->verify(hash_nid, msg, msg_len, sig, sig_len, rsa);
- }
-
- if (sig_len != rsa_size) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_WRONG_SIGNATURE_LENGTH);
- return 0;
- }
-
if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) {
OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
return 0;
@@ -510,7 +496,7 @@ int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
goto out;
}
- if (len != signed_msg_len || CRYPTO_memcmp(buf, signed_msg, len) != 0) {
+ if (len != signed_msg_len || memcmp(buf, signed_msg, len) != 0) {
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE);
goto out;
}
diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c
index 1f3d6a24..d14ecaee 100644
--- a/crypto/rsa/rsa_asn1.c
+++ b/crypto/rsa/rsa_asn1.c
@@ -59,8 +59,6 @@
#include <limits.h>
#include <string.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
@@ -390,6 +388,7 @@ int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!RSA_marshal_public_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
@@ -417,20 +416,12 @@ int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 0) ||
!RSA_marshal_private_key(&cbb, in)) {
+ CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
}
-ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
- ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
- ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
- ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
- ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
-} ASN1_SEQUENCE_END(RSA_PSS_PARAMS);
-
-IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS);
-
RSA *RSAPublicKey_dup(const RSA *rsa) {
uint8_t *der;
size_t der_len;
diff --git a/crypto/rsa/rsa_impl.c b/crypto/rsa/rsa_impl.c
index ba310739..af44a3d5 100644
--- a/crypto/rsa/rsa_impl.c
+++ b/crypto/rsa/rsa_impl.c
@@ -56,6 +56,7 @@
#include <openssl/rsa.h>
+#include <assert.h>
#include <string.h>
#include <openssl/bn.h>
@@ -69,21 +70,37 @@
static int check_modulus_and_exponent_sizes(const RSA *rsa) {
unsigned rsa_bits = BN_num_bits(rsa->n);
+
if (rsa_bits > 16 * 1024) {
OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
return 0;
}
- if (BN_ucmp(rsa->n, rsa->e) <= 0) {
+ /* Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as
+ * the limit based on the recommendations in [1] and [2]. Windows CryptoAPI
+ * doesn't support values larger than 32 bits [3], so it is unlikely that
+ * exponents larger than 32 bits are being used for anything Windows commonly
+ * does.
+ *
+ * [1] https://www.imperialviolet.org/2012/03/16/rsae.html
+ * [2] https://www.imperialviolet.org/2012/03/17/rsados.html
+ * [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx */
+ static const unsigned kMaxExponentBits = 33;
+
+ if (BN_num_bits(rsa->e) > kMaxExponentBits) {
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
return 0;
}
- /* For large moduli only, enforce exponent limit. */
- if (rsa_bits > 3072 && BN_num_bits(rsa->e) > 64) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+ /* Verify |n > e|. Comparing |rsa_bits| to |kMaxExponentBits| is a small
+ * shortcut to comparing |n| and |e| directly. In reality, |kMaxExponentBits|
+ * is much smaller than the minimum RSA key size that any application should
+ * accept. */
+ if (rsa_bits <= kMaxExponentBits) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
+ assert(BN_ucmp(rsa->n, rsa->e) > 0);
return 1;
}
@@ -154,13 +171,8 @@ int rsa_default_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
goto err;
}
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
- goto err;
- }
- }
-
- if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+ !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
goto err;
}
@@ -201,6 +213,9 @@ err:
* |*index_used| and must be passed to |rsa_blinding_release| when finished. */
static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
BN_CTX *ctx) {
+ assert(ctx != NULL);
+ assert(rsa->mont_n != NULL);
+
BN_BLINDING *ret = NULL;
BN_BLINDING **new_blindings;
uint8_t *new_blindings_inuse;
@@ -219,7 +234,7 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
}
if (ret != NULL) {
- CRYPTO_MUTEX_unlock(&rsa->lock);
+ CRYPTO_MUTEX_unlock_write(&rsa->lock);
return ret;
}
@@ -228,8 +243,8 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
/* We didn't find a free BN_BLINDING to use so increase the length of
* the arrays by one and use the newly created element. */
- CRYPTO_MUTEX_unlock(&rsa->lock);
- ret = rsa_setup_blinding(rsa, ctx);
+ CRYPTO_MUTEX_unlock_write(&rsa->lock);
+ ret = BN_BLINDING_new();
if (ret == NULL) {
return NULL;
}
@@ -266,14 +281,14 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
rsa->blindings_inuse = new_blindings_inuse;
rsa->num_blindings++;
- CRYPTO_MUTEX_unlock(&rsa->lock);
+ CRYPTO_MUTEX_unlock_write(&rsa->lock);
return ret;
err2:
OPENSSL_free(new_blindings);
err1:
- CRYPTO_MUTEX_unlock(&rsa->lock);
+ CRYPTO_MUTEX_unlock_write(&rsa->lock);
BN_BLINDING_free(ret);
return NULL;
}
@@ -290,7 +305,7 @@ static void rsa_blinding_release(RSA *rsa, BN_BLINDING *blinding,
CRYPTO_MUTEX_lock_write(&rsa->lock);
rsa->blindings_inuse[blinding_index] = 0;
- CRYPTO_MUTEX_unlock(&rsa->lock);
+ CRYPTO_MUTEX_unlock_write(&rsa->lock);
}
/* signing */
@@ -409,33 +424,49 @@ err:
return ret;
}
-int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
- size_t max_out, const uint8_t *in, size_t in_len,
- int padding) {
+static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+
+int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ if (rsa->n == NULL || rsa->e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
+ return 0;
+ }
+
const unsigned rsa_size = RSA_size(rsa);
BIGNUM *f, *result;
- int ret = 0;
int r = -1;
- uint8_t *buf = NULL;
- BN_CTX *ctx = NULL;
if (max_out < rsa_size) {
OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
+ if (in_len != rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
+ return 0;
+ }
+
if (!check_modulus_and_exponent_sizes(rsa)) {
return 0;
}
- ctx = BN_CTX_new();
+ BN_CTX *ctx = BN_CTX_new();
if (ctx == NULL) {
- goto err;
+ return 0;
}
+ int ret = 0;
+ uint8_t *buf = NULL;
+
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
result = BN_CTX_get(ctx);
+ if (f == NULL || result == NULL) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
if (padding == RSA_NO_PADDING) {
buf = out;
} else {
@@ -446,15 +477,6 @@ int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
goto err;
}
}
- if (!f || !result) {
- OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (in_len != rsa_size) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
- goto err;
- }
if (BN_bin2bn(in, in_len, f) == NULL) {
goto err;
@@ -465,13 +487,8 @@ int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
goto err;
}
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
- goto err;
- }
- }
-
- if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+ !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
goto err;
}
@@ -500,12 +517,9 @@ int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
}
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
- if (padding != RSA_NO_PADDING && buf != NULL) {
- OPENSSL_cleanse(buf, rsa_size);
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ if (buf != out) {
OPENSSL_free(buf);
}
return ret;
@@ -542,21 +556,38 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
goto err;
}
- if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* We cannot do blinding or verification without |e|, and continuing without
+ * those countermeasures is dangerous. However, the Java/Android RSA API
+ * requires support for keys where only |d| and |n| (and not |e|) are known.
+ * The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. */
+ int disable_security = (rsa->flags & RSA_FLAG_NO_BLINDING) && rsa->e == NULL;
+
+ if (!disable_security) {
+ /* Keys without public exponents must have blinding explicitly disabled to
+ * be used. */
+ if (rsa->e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
+ goto err;
+ }
+
blinding = rsa_blinding_get(rsa, &blinding_index, ctx);
if (blinding == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
- if (!BN_BLINDING_convert(f, blinding, ctx)) {
+ if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) {
goto err;
}
}
- if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
- ((rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) &&
- (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
- if (!rsa->meth->mod_exp(result, f, rsa, ctx)) {
+ if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL &&
+ rsa->dmq1 != NULL && rsa->iqmp != NULL) {
+ if (!mod_exp(result, f, rsa, ctx)) {
goto err;
}
} else {
@@ -567,20 +598,30 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
d = &local_d;
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ==
- NULL) {
- goto err;
- }
+ if (!BN_mod_exp_mont_consttime(result, f, d, rsa->n, ctx, rsa->mont_n)) {
+ goto err;
}
+ }
- if (!rsa->meth->bn_mod_exp(result, f, d, rsa->n, ctx, rsa->mont_n)) {
+ /* Verify the result to protect against fault attacks as described in the
+ * 1997 paper "On the Importance of Checking Cryptographic Protocols for
+ * Faults" by Dan Boneh, Richard A. DeMillo, and Richard J. Lipton. Some
+ * implementations do this only when the CRT is used, but we do it in all
+ * cases. Section 6 of the aforementioned paper describes an attack that
+ * works when the CRT isn't used. That attack is much less likely to succeed
+ * than the CRT attack, but there have likely been improvements since 1997.
+ *
+ * This check is cheap assuming |e| is small; it almost always is. */
+ if (!disable_security) {
+ BIGNUM *vrfy = BN_CTX_get(ctx);
+ if (vrfy == NULL ||
+ !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) ||
+ !BN_equal_consttime(vrfy, f)) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
- }
- if (blinding) {
- if (!BN_BLINDING_invert(result, blinding, ctx)) {
+ if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) {
goto err;
}
}
@@ -605,6 +646,17 @@ err:
}
static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
+ assert(ctx != NULL);
+
+ assert(rsa->n != NULL);
+ assert(rsa->e != NULL);
+ assert(rsa->d != NULL);
+ assert(rsa->p != NULL);
+ assert(rsa->q != NULL);
+ assert(rsa->dmp1 != NULL);
+ assert(rsa->dmq1 != NULL);
+ assert(rsa->iqmp != NULL);
+
BIGNUM *r1, *m1, *vrfy;
BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
BIGNUM *dmp1, *dmq1, *c, *pr1;
@@ -619,6 +671,11 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
r1 = BN_CTX_get(ctx);
m1 = BN_CTX_get(ctx);
vrfy = BN_CTX_get(ctx);
+ if (r1 == NULL ||
+ m1 == NULL ||
+ vrfy == NULL) {
+ goto err;
+ }
{
BIGNUM local_p, local_q;
@@ -634,20 +691,14 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
q = &local_q;
BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
- if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) == NULL) {
- goto err;
- }
- if (BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx) == NULL) {
- goto err;
- }
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) ||
+ !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx)) {
+ goto err;
}
}
- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
- goto err;
- }
+ if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
+ goto err;
}
/* compute I mod q */
@@ -660,7 +711,7 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
/* compute r1^dmq1 mod q */
dmq1 = &local_dmq1;
BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
- if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) {
+ if (!BN_mod_exp_mont_consttime(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) {
goto err;
}
@@ -674,7 +725,7 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
/* compute r1^dmp1 mod p */
dmp1 = &local_dmp1;
BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
- if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) {
+ if (!BN_mod_exp_mont_consttime(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) {
goto err;
}
@@ -734,12 +785,8 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
goto err;
}
- if ((rsa->flags & RSA_FLAG_CACHE_PRIVATE) &&
- !BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx)) {
- goto err;
- }
-
- if (!rsa->meth->bn_mod_exp(m1, r1, exp, prime, ctx, ap->mont)) {
+ if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx) ||
+ !BN_mod_exp_mont_consttime(m1, r1, exp, prime, ctx, ap->mont)) {
goto err;
}
@@ -755,40 +802,6 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
}
}
- if (rsa->e && rsa->n) {
- if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, rsa->mont_n)) {
- goto err;
- }
- /* If 'I' was greater than (or equal to) rsa->n, the operation
- * will be equivalent to using 'I mod n'. However, the result of
- * the verify will *always* be less than 'n' so we don't check
- * for absolute equality, just congruency. */
- if (!BN_sub(vrfy, vrfy, I)) {
- goto err;
- }
- if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) {
- goto err;
- }
- if (BN_is_negative(vrfy)) {
- if (!BN_add(vrfy, vrfy, rsa->n)) {
- goto err;
- }
- }
- if (!BN_is_zero(vrfy)) {
- /* 'I' and 'vrfy' aren't congruent mod n. Don't leak
- * miscalculated CRT output, just do a raw (slower)
- * mod_exp and return that instead. */
-
- BIGNUM local_d;
- BIGNUM *d = NULL;
-
- d = &local_d;
- BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
- if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, rsa->mont_n)) {
- goto err;
- }
- }
- }
ret = 1;
err:
@@ -1090,9 +1103,9 @@ int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
cb);
}
-/* Many of these methods are NULL to more easily drop unused functions. The
- * wrapper functions will select the appropriate |rsa_default_*| for all
- * methods. */
+/* All of the methods are NULL to make it easier for the compiler/linker to drop
+ * unused functions. The wrapper functions will select the appropriate
+ * |rsa_default_*| implementation. */
const RSA_METHOD RSA_default_method = {
{
0 /* references */,
@@ -1115,8 +1128,8 @@ const RSA_METHOD RSA_default_method = {
NULL /* private_transform (defaults to rsa_default_private_transform) */,
- mod_exp,
- BN_mod_exp_mont /* bn_mod_exp */,
+ NULL /* mod_exp (ignored) */,
+ NULL /* bn_mod_exp (ignored) */,
RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE,
diff --git a/crypto/rsa/rsa_test.cc b/crypto/rsa/rsa_test.cc
index 5545161c..62177a4c 100644
--- a/crypto/rsa/rsa_test.cc
+++ b/crypto/rsa/rsa_test.cc
@@ -63,7 +63,7 @@
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "../test/scoped_types.h"
@@ -593,6 +593,7 @@ static bool TestRSA(const uint8_t *der, size_t der_len,
fprintf(stderr, "Corrupt data decrypted!\n");
return false;
}
+ ERR_clear_error();
ciphertext[i] ^= 1;
}
@@ -603,6 +604,7 @@ static bool TestRSA(const uint8_t *der, size_t der_len,
fprintf(stderr, "Corrupt data decrypted!\n");
return false;
}
+ ERR_clear_error();
}
return true;
@@ -693,25 +695,27 @@ static bool TestBadKey() {
}
static bool TestOnlyDGiven() {
+ static const char kN[] =
+ "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd09ac42b2662"
+ "1cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e5808c659";
+ static const char kE[] = "010001";
+ static const char kD[] =
+ "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea316eaeca21a"
+ "73ac365e58713195f2ae9849348525ca855386b6d028e437a9495a01";
+
uint8_t buf[64];
unsigned buf_len = sizeof(buf);
ScopedRSA key(RSA_new());
if (!key ||
- !BN_hex2bn(&key->n,
- "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd"
- "09ac42b26621cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e"
- "5808c659") ||
- !BN_hex2bn(&key->e, "010001") ||
- !BN_hex2bn(&key->d,
- "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea"
- "316eaeca21a73ac365e58713195f2ae9849348525ca855386b6d028e437a9"
- "495a01") ||
+ !BN_hex2bn(&key->n, kN) ||
+ !BN_hex2bn(&key->e, kE) ||
+ !BN_hex2bn(&key->d, kD) ||
RSA_size(key.get()) > sizeof(buf)) {
return false;
}
if (!RSA_check_key(key.get())) {
- fprintf(stderr, "RSA_check_key failed with only d given.\n");
+ fprintf(stderr, "RSA_check_key failed with only n, d, and e given.\n");
ERR_print_errors_fp(stderr);
return false;
}
@@ -720,14 +724,46 @@ static bool TestOnlyDGiven() {
if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
key.get())) {
- fprintf(stderr, "RSA_sign failed with only d given.\n");
+ fprintf(stderr, "RSA_sign failed with only n, d, and e given.\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
+ key.get())) {
+ fprintf(stderr, "RSA_verify failed with only n, d, and e given.\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ // Keys without the public exponent must continue to work when blinding is
+ // disabled to support Java's RSAPrivateKeySpec API. See
+ // https://bugs.chromium.org/p/boringssl/issues/detail?id=12.
+ ScopedRSA key2(RSA_new());
+ if (!key2 ||
+ !BN_hex2bn(&key2->n, kN) ||
+ !BN_hex2bn(&key2->d, kD)) {
+ return false;
+ }
+ key2->flags |= RSA_FLAG_NO_BLINDING;
+
+ if (RSA_size(key2.get()) > sizeof(buf)) {
+ return false;
+ }
+
+ if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
+ key2.get())) {
+ fprintf(stderr, "RSA_sign failed with only n and d given.\n");
ERR_print_errors_fp(stderr);
return false;
}
+ // Verify the signature with |key|. |key2| has no public exponent.
if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
key.get())) {
- fprintf(stderr, "RSA_verify failed with only d given.\n");
+ fprintf(stderr,
+ "Could not verify signature produced from key with only n and d "
+ "given.\n");
ERR_print_errors_fp(stderr);
return false;
}
diff --git a/crypto/sha/asm/sha512-armv4.pl b/crypto/sha/asm/sha512-armv4.pl
index cd3662a5..15d50f28 100644
--- a/crypto/sha/asm/sha512-armv4.pl
+++ b/crypto/sha/asm/sha512-armv4.pl
@@ -291,7 +291,7 @@ sha512_block_data_order:
#ifdef __APPLE__
ldr r12,[r12]
#endif
- tst r12,#1
+ tst r12,#ARMV7_NEON
bne .LNEON
#endif
add $len,$inp,$len,lsl#7 @ len to point at the end of inp
diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c
index 0ddacbad..58f7c42c 100644
--- a/crypto/sha/sha256.c
+++ b/crypto/sha/sha256.c
@@ -104,8 +104,8 @@ uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
out = buf;
}
SHA224_Init(&ctx);
- SHA256_Update(&ctx, data, len);
- SHA256_Final(out, &ctx);
+ SHA224_Update(&ctx, data, len);
+ SHA224_Final(out, &ctx);
OPENSSL_cleanse(&ctx, sizeof(ctx));
return out;
}
diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c
index 6ad8d40c..f4730463 100644
--- a/crypto/sha/sha512.c
+++ b/crypto/sha/sha512.c
@@ -129,8 +129,8 @@ uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
}
SHA384_Init(&ctx);
- SHA512_Update(&ctx, data, len);
- SHA512_Final(out, &ctx);
+ SHA384_Update(&ctx, data, len);
+ SHA384_Final(out, &ctx);
OPENSSL_cleanse(&ctx, sizeof(ctx));
return out;
}
diff --git a/crypto/stack/make_macros.sh b/crypto/stack/make_macros.sh
index 4837e449..3c3691b3 100644
--- a/crypto/stack/make_macros.sh
+++ b/crypto/stack/make_macros.sh
@@ -36,13 +36,13 @@ output_stack () {
((STACK_OF(${type})*) sk_new_null())
#define sk_${type}_num(sk)\\
- sk_num(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))
+ sk_num(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk))
#define sk_${type}_zero(sk)\\
sk_zero(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk));
#define sk_${type}_value(sk, i)\\
- ((${ptrtype}) sk_value(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk), (i)))
+ ((${ptrtype}) sk_value(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), (i)))
#define sk_${type}_set(sk, i, p)\\
((${ptrtype}) sk_set(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (i), CHECKED_CAST(void*, ${ptrtype}, p)))
@@ -75,13 +75,13 @@ output_stack () {
((${ptrtype}) sk_pop(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk)))
#define sk_${type}_dup(sk)\\
- ((STACK_OF(${type})*) sk_dup(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk)))
+ ((STACK_OF(${type})*) sk_dup(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk)))
#define sk_${type}_sort(sk)\\
sk_sort(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))
#define sk_${type}_is_sorted(sk)\\
- sk_is_sorted(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk))
#define sk_${type}_set_cmp_func(sk, comp)\\
((int (*) (const ${type} **a, const ${type} **b)) sk_set_cmp_func(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(stack_cmp_func, int (*) (const ${type} **a, const ${type} **b), comp)))
@@ -89,7 +89,6 @@ output_stack () {
#define sk_${type}_deep_copy(sk, copy_func, free_func)\\
((STACK_OF(${type})*) sk_deep_copy(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), CHECKED_CAST(void* (*) (void*), ${ptrtype} (*) (${ptrtype}), copy_func), CHECKED_CAST(void (*) (void*), void (*) (${ptrtype}), free_func)))
-
EOF
}
diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c
index c5845159..e8932217 100644
--- a/crypto/stack/stack.c
+++ b/crypto/stack/stack.c
@@ -329,7 +329,7 @@ err:
void sk_sort(_STACK *sk) {
int (*comp_func)(const void *,const void *);
- if (sk == NULL || sk->sorted) {
+ if (sk == NULL || sk->comp == NULL || sk->sorted) {
return;
}
diff --git a/crypto/test/file_test.cc b/crypto/test/file_test.cc
index d0447c34..d684aa09 100644
--- a/crypto/test/file_test.cc
+++ b/crypto/test/file_test.cc
@@ -14,6 +14,8 @@
#include "file_test.h"
+#include <memory>
+
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
@@ -73,10 +75,12 @@ FileTest::ReadResult FileTest::ReadNext() {
ClearTest();
+ static const size_t kBufLen = 64 + 8192*2;
+ std::unique_ptr<char[]> buf(new char[kBufLen]);
+
while (true) {
// Read the next line.
- char buf[4096];
- if (fgets(buf, sizeof(buf), file_) == nullptr) {
+ if (fgets(buf.get(), kBufLen, file_) == nullptr) {
if (feof(file_)) {
// EOF is a valid terminator for a test.
return start_line_ > 0 ? kReadSuccess : kReadEOF;
@@ -86,7 +90,7 @@ FileTest::ReadResult FileTest::ReadNext() {
}
line_++;
- size_t len = strlen(buf);
+ size_t len = strlen(buf.get());
// Check for truncation.
if (len > 0 && buf[len - 1] != '\n' && !feof(file_)) {
fprintf(stderr, "Line %u too long.\n", line_);
@@ -100,14 +104,14 @@ FileTest::ReadResult FileTest::ReadNext() {
}
} else if (buf[0] != '#') { // Comment lines are ignored.
// Parse the line as an attribute.
- const char *delimiter = FindDelimiter(buf);
+ const char *delimiter = FindDelimiter(buf.get());
if (delimiter == nullptr) {
fprintf(stderr, "Line %u: Could not parse attribute.\n", line_);
return kReadError;
}
- std::string key = StripSpace(buf, delimiter - buf);
+ std::string key = StripSpace(buf.get(), delimiter - buf.get());
std::string value = StripSpace(delimiter + 1,
- buf + len - delimiter - 1);
+ buf.get() + len - delimiter - 1);
unused_attributes_.insert(key);
attributes_[key] = value;
diff --git a/crypto/test/file_test.h b/crypto/test/file_test.h
index e90cc86a..a8591277 100644
--- a/crypto/test/file_test.h
+++ b/crypto/test/file_test.h
@@ -20,19 +20,15 @@
#include <stdint.h>
#include <stdio.h>
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable: 4702)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(push))
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
#include <string>
#include <map>
#include <set>
#include <vector>
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(pop))
// File-based test framework.
//
diff --git a/crypto/test/scoped_types.h b/crypto/test/scoped_types.h
index b5ae324d..2a2c3713 100644
--- a/crypto/test/scoped_types.h
+++ b/crypto/test/scoped_types.h
@@ -24,14 +24,17 @@
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/cmac.h>
+#include <openssl/curve25519.h>
#include <openssl/dh.h>
+#include <openssl/ecdsa.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
-#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/mem.h>
+#include <openssl/newhope.h>
#include <openssl/pkcs8.h>
#include <openssl/rsa.h>
#include <openssl/stack.h>
@@ -109,9 +112,11 @@ using ScopedEC_KEY = ScopedOpenSSLType<EC_KEY, EC_KEY_free>;
using ScopedEC_POINT = ScopedOpenSSLType<EC_POINT, EC_POINT_free>;
using ScopedEVP_PKEY = ScopedOpenSSLType<EVP_PKEY, EVP_PKEY_free>;
using ScopedEVP_PKEY_CTX = ScopedOpenSSLType<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
+using ScopedNEWHOPE_POLY = ScopedOpenSSLType<NEWHOPE_POLY, NEWHOPE_POLY_free>;
using ScopedPKCS8_PRIV_KEY_INFO = ScopedOpenSSLType<PKCS8_PRIV_KEY_INFO,
PKCS8_PRIV_KEY_INFO_free>;
using ScopedPKCS12 = ScopedOpenSSLType<PKCS12, PKCS12_free>;
+using ScopedSPAKE2_CTX = ScopedOpenSSLType<SPAKE2_CTX, SPAKE2_CTX_free>;
using ScopedRSA = ScopedOpenSSLType<RSA, RSA_free>;
using ScopedX509 = ScopedOpenSSLType<X509, X509_free>;
using ScopedX509_ALGOR = ScopedOpenSSLType<X509_ALGOR, X509_ALGOR_free>;
diff --git a/crypto/thread.c b/crypto/thread.c
index 88371159..373f8dbc 100644
--- a/crypto/thread.c
+++ b/crypto/thread.c
@@ -61,9 +61,9 @@
#if !defined(OPENSSL_WINDOWS)
#include <errno.h>
#else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/mem.h>
@@ -74,6 +74,11 @@ int CRYPTO_num_locks(void) { return 1; }
void CRYPTO_set_locking_callback(void (*func)(int mode, int lock_num,
const char *file, int line)) {}
+void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
+ const char *file, int line) {
+ return NULL;
+}
+
void CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int lock_num,
const char *file, int line)) {}
@@ -99,3 +104,19 @@ void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(
void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(
struct CRYPTO_dynlock_value *l, const char *file, int line)) {}
+
+struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))(
+ const char *file, int line) {
+ return NULL;
+}
+
+void (*CRYPTO_get_dynlock_lock_callback(void))(int mode,
+ struct CRYPTO_dynlock_value *l,
+ const char *file, int line) {
+ return NULL;
+}
+
+void (*CRYPTO_get_dynlock_destroy_callback(void))(
+ struct CRYPTO_dynlock_value *l, const char *file, int line) {
+ return NULL;
+}
diff --git a/crypto/thread_none.c b/crypto/thread_none.c
index cf4e85a7..85768b4b 100644
--- a/crypto/thread_none.c
+++ b/crypto/thread_none.c
@@ -22,7 +22,9 @@ void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {}
void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {}
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {}
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {}
void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {}
@@ -30,7 +32,9 @@ void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {}
void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {}
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {}
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {}
void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
if (*once) {
diff --git a/crypto/thread_pthread.c b/crypto/thread_pthread.c
index 68aaab5b..2baa2b4d 100644
--- a/crypto/thread_pthread.c
+++ b/crypto/thread_pthread.c
@@ -17,7 +17,6 @@
#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS)
#include <pthread.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -46,7 +45,13 @@ void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {
}
}
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {
+ if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {
if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) {
abort();
}
@@ -68,7 +73,13 @@ void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {
}
}
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+ if (pthread_rwlock_unlock(&lock->lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {
if (pthread_rwlock_unlock(&lock->lock) != 0) {
abort();
}
@@ -76,8 +87,6 @@ void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
if (pthread_once(once, init) != 0) {
- fprintf(stderr,
- "pthread_once failed. Did you link against a threading library?\n");
abort();
}
}
diff --git a/crypto/thread_test.c b/crypto/thread_test.c
index e028b1be..12ca2ec0 100644
--- a/crypto/thread_test.c
+++ b/crypto/thread_test.c
@@ -21,9 +21,9 @@
#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
typedef HANDLE thread_t;
@@ -53,6 +53,8 @@ static int wait_for_thread(thread_t thread) {
#else
#include <pthread.h>
+#include <string.h>
+#include <time.h>
typedef pthread_t thread_t;
@@ -77,6 +79,17 @@ static unsigned g_once_init_called = 0;
static void once_init(void) {
g_once_init_called++;
+
+ /* Sleep briefly so one |call_once_thread| instance will call |CRYPTO_once|
+ * while the other is running this function. */
+#if defined(OPENSSL_WINDOWS)
+ Sleep(1 /* milliseconds */);
+#else
+ struct timespec req;
+ memset(&req, 0, sizeof(req));
+ req.tv_nsec = 1000000;
+ nanosleep(&req, NULL);
+#endif
}
static CRYPTO_once_t g_test_once = CRYPTO_ONCE_INIT;
@@ -91,9 +104,11 @@ static int test_once(void) {
return 0;
}
- thread_t thread;
- if (!run_thread(&thread, call_once_thread) ||
- !wait_for_thread(thread)) {
+ thread_t thread1, thread2;
+ if (!run_thread(&thread1, call_once_thread) ||
+ !run_thread(&thread2, call_once_thread) ||
+ !wait_for_thread(thread1) ||
+ !wait_for_thread(thread2)) {
fprintf(stderr, "thread failed.\n");
return 0;
}
diff --git a/crypto/thread_win.c b/crypto/thread_win.c
index e48ab5f5..c7a90f7e 100644
--- a/crypto/thread_win.c
+++ b/crypto/thread_win.c
@@ -16,11 +16,10 @@
#if defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -28,110 +27,59 @@
#include <openssl/type_check.h>
-OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(CRITICAL_SECTION),
+OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(SRWLOCK),
CRYPTO_MUTEX_too_small);
-union run_once_arg_t {
- void (*func)(void);
- void *data;
-};
-
-static void run_once(CRYPTO_once_t *once, void (*init)(union run_once_arg_t),
- union run_once_arg_t arg) {
- /* Values must be aligned. */
- assert((((uintptr_t) once) & 3) == 0);
-
- /* This assumes that reading *once has acquire semantics. This should be true
- * on x86 and x86-64, where we expect Windows to run. */
-#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
-#error "Windows once code may not work on other platforms." \
- "You can use InitOnceBeginInitialize on >=Vista"
-#endif
- if (*once == 1) {
- return;
- }
-
- for (;;) {
- switch (InterlockedCompareExchange(once, 2, 0)) {
- case 0:
- /* The value was zero so we are the first thread to call |CRYPTO_once|
- * on it. */
- init(arg);
- /* Write one to indicate that initialisation is complete. */
- InterlockedExchange(once, 1);
- return;
-
- case 1:
- /* Another thread completed initialisation between our fast-path check
- * and |InterlockedCompareExchange|. */
- return;
-
- case 2:
- /* Another thread is running the initialisation. Switch to it then try
- * again. */
- SwitchToThread();
- break;
-
- default:
- abort();
- }
- }
-}
-
-static void call_once_init(union run_once_arg_t arg) {
- arg.func();
+static BOOL CALLBACK call_once_init(INIT_ONCE *once, void *arg, void **out) {
+ void (**init)(void) = (void (**)(void))arg;
+ (**init)();
+ return TRUE;
}
-void CRYPTO_once(CRYPTO_once_t *in_once, void (*init)(void)) {
- union run_once_arg_t arg;
- arg.func = init;
- run_once(in_once, call_once_init, arg);
+void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
+ if (!InitOnceExecuteOnce(once, call_once_init, &init, NULL)) {
+ abort();
+ }
}
void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {
- if (!InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION *) lock, 0x400)) {
- abort();
- }
+ InitializeSRWLock((SRWLOCK *) lock);
}
void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {
- /* Since we have to support Windows XP, read locks are actually exclusive. */
- EnterCriticalSection((CRITICAL_SECTION *) lock);
+ AcquireSRWLockShared((SRWLOCK *) lock);
}
void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {
- EnterCriticalSection((CRITICAL_SECTION *) lock);
+ AcquireSRWLockExclusive((SRWLOCK *) lock);
}
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
- LeaveCriticalSection((CRITICAL_SECTION *) lock);
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {
+ ReleaseSRWLockShared((SRWLOCK *) lock);
}
-void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {
- DeleteCriticalSection((CRITICAL_SECTION *) lock);
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {
+ ReleaseSRWLockExclusive((SRWLOCK *) lock);
}
-static void static_lock_init(union run_once_arg_t arg) {
- struct CRYPTO_STATIC_MUTEX *lock = arg.data;
- if (!InitializeCriticalSectionAndSpinCount(&lock->lock, 0x400)) {
- abort();
- }
+void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {
+ /* SRWLOCKs require no cleanup. */
}
void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {
- union run_once_arg_t arg;
- arg.data = lock;
- /* Since we have to support Windows XP, read locks are actually exclusive. */
- run_once(&lock->once, static_lock_init, arg);
- EnterCriticalSection(&lock->lock);
+ AcquireSRWLockShared(&lock->lock);
}
void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {
- CRYPTO_STATIC_MUTEX_lock_read(lock);
+ AcquireSRWLockExclusive(&lock->lock);
+}
+
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+ ReleaseSRWLockShared(&lock->lock);
}
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
- LeaveCriticalSection(&lock->lock);
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {
+ ReleaseSRWLockExclusive(&lock->lock);
}
static CRITICAL_SECTION g_destructors_lock;
@@ -150,9 +98,14 @@ static void thread_local_init(void) {
g_thread_local_failed = (g_thread_local_key == TLS_OUT_OF_INDEXES);
}
-static void NTAPI thread_local_destructor(PVOID module,
- DWORD reason, PVOID reserved) {
- if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason) {
+static void NTAPI thread_local_destructor(PVOID module, DWORD reason,
+ PVOID reserved) {
+ /* Only free memory on |DLL_THREAD_DETACH|, not |DLL_PROCESS_DETACH|. In
+ * VS2015's debug runtime, the C runtime has been unloaded by the time
+ * |DLL_PROCESS_DETACH| runs. See https://crbug.com/575795. This is consistent
+ * with |pthread_key_create| which does not call destructors on process exit,
+ * only thread exit. */
+ if (reason != DLL_THREAD_DETACH) {
return;
}
diff --git a/crypto/x509/CMakeLists.txt b/crypto/x509/CMakeLists.txt
index de98eedf..bc867860 100644
--- a/crypto/x509/CMakeLists.txt
+++ b/crypto/x509/CMakeLists.txt
@@ -9,11 +9,13 @@ add_library(
a_sign.c
a_strex.c
a_verify.c
+ algorithm.c
asn1_gen.c
by_dir.c
by_file.c
i2d_pr.c
pkcs7.c
+ rsa_pss.c
t_crl.c
t_req.c
t_x509.c
diff --git a/crypto/x509/a_sign.c b/crypto/x509/a_sign.c
index 74f23438..13a3ac25 100644
--- a/crypto/x509/a_sign.c
+++ b/crypto/x509/a_sign.c
@@ -62,7 +62,7 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
-#include "../evp/internal.h"
+#include "internal.h"
int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
@@ -88,10 +88,10 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
/* Write out the requested copies of the AlgorithmIdentifier. */
- if (algor1 && !EVP_DigestSignAlgorithm(ctx, algor1)) {
+ if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) {
goto err;
}
- if (algor2 && !EVP_DigestSignAlgorithm(ctx, algor2)) {
+ if (algor2 && !x509_digest_sign_algorithm(ctx, algor2)) {
goto err;
}
diff --git a/crypto/x509/a_verify.c b/crypto/x509/a_verify.c
index 969591c0..5a9adb65 100644
--- a/crypto/x509/a_verify.c
+++ b/crypto/x509/a_verify.c
@@ -68,7 +68,7 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
-#include "../evp/internal.h"
+#include "internal.h"
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
@@ -89,7 +89,7 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
EVP_MD_CTX_init(&ctx);
- if (!EVP_DigestVerifyInitFromAlgorithm(&ctx, a, pkey)) {
+ if (!x509_digest_verify_init(&ctx, a, pkey)) {
goto err;
}
diff --git a/crypto/x509/algorithm.c b/crypto/x509/algorithm.c
new file mode 100644
index 00000000..78ae882b
--- /dev/null
+++ b/crypto/x509/algorithm.c
@@ -0,0 +1,137 @@
+/* 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/x509.h>
+
+#include <openssl/asn1.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+ const EVP_MD *digest = EVP_MD_CTX_md(ctx);
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+ if (digest == NULL || pkey == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
+ return 0;
+ }
+
+ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
+ int pad_mode;
+ if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) {
+ return 0;
+ }
+ /* RSA-PSS has special signature algorithm logic. */
+ if (pad_mode == RSA_PKCS1_PSS_PADDING) {
+ return x509_rsa_ctx_to_pss(ctx, algor);
+ }
+ }
+
+ /* Default behavior: look up the OID for the algorithm/hash pair and encode
+ * that. */
+ int sign_nid;
+ if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
+ EVP_PKEY_id(pkey))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+ return 0;
+ }
+
+ /* RSA signature algorithms include an explicit NULL parameter. Others omit
+ * it. */
+ int paramtype =
+ (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF;
+ X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
+ return 1;
+}
+
+int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
+ EVP_PKEY *pkey) {
+ /* Convert the signature OID into digest and public key OIDs. */
+ int sigalg_nid = OBJ_obj2nid(sigalg->algorithm);
+ int digest_nid, pkey_nid;
+ if (!OBJ_find_sigid_algs(sigalg_nid, &digest_nid, &pkey_nid)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ return 0;
+ }
+
+ /* Check the public key OID matches the public key type. */
+ if (pkey_nid != EVP_PKEY_id(pkey)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+ return 0;
+ }
+
+ /* NID_undef signals that there are custom parameters to set. */
+ if (digest_nid == NID_undef) {
+ if (sigalg_nid != NID_rsassaPss) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ return 0;
+ }
+ return x509_rsa_pss_to_ctx(ctx, sigalg, pkey);
+ }
+
+ /* Otherwise, initialize with the digest from the OID. */
+ const EVP_MD *digest = EVP_get_digestbynid(digest_nid);
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+ return 0;
+ }
+
+ return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey);
+}
diff --git a/crypto/x509/asn1_gen.c b/crypto/x509/asn1_gen.c
index 0660840f..03a0ab9f 100644
--- a/crypto/x509/asn1_gen.c
+++ b/crypto/x509/asn1_gen.c
@@ -142,7 +142,6 @@ ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
}
ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
ASN1_TYPE *ret;
tag_exp_arg asn1_tags;
@@ -155,7 +154,7 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
unsigned char *p;
const unsigned char *cp;
int cpy_len;
- long hdr_len;
+ long hdr_len = 0;
int hdr_constructed = 0, hdr_tag, hdr_class;
int r;
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 4f0a49e2..4445b058 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -327,7 +327,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
hent = NULL;
k = 0;
}
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&g_ent_hashes_lock);
} else {
k = 0;
hent = NULL;
@@ -392,7 +392,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx);
}
- CRYPTO_MUTEX_unlock(&xl->store_ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock);
/*
* If a CRL, update the last file suffix added for this
@@ -412,14 +412,14 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
if (!hent) {
hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
if (hent == NULL) {
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
ok = 0;
goto finish;
}
hent->hash = h;
hent->suffix = k;
if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
OPENSSL_free(hent);
ok = 0;
goto finish;
@@ -427,7 +427,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
} else if (hent->suffix < k)
hent->suffix = k;
- CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
}
if (tmp != NULL) {
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h
new file mode 100644
index 00000000..4957c1e1
--- /dev/null
+++ b/crypto/x509/internal.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_X509_INTERNAL_H
+#define OPENSSL_HEADER_X509_INTERNAL_H
+
+#include <openssl/base.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* RSA-PSS functions. */
+
+/* x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on
+ * signature algorithm parameters in |sigalg| (which must have type
+ * |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on
+ * error. */
+int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey);
+
+/* x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for
+ * |ctx|, which must have been configured for an RSA-PSS signing operation. It
+ * returns one on success and zero on error. */
+int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
+/* x509_print_rsa_pss_params prints a human-readable representation of RSA-PSS
+ * parameters in |sigalg| to |bp|. It returns one on success and zero on
+ * error. */
+int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
+ ASN1_PCTX *pctx);
+
+
+/* Signature algorithm functions. */
+
+/* x509_digest_sign_algorithm encodes the signing parameters of |ctx| as an
+ * AlgorithmIdentifer and saves the result in |algor|. It returns one on
+ * success, or zero on error. */
+int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
+/* x509_digest_verify_init sets up |ctx| for a signature verification operation
+ * with public key |pkey| and parameters from |algor|. The |ctx| argument must
+ * have been initialised with |EVP_MD_CTX_init|. It returns one on success, or
+ * zero on error. */
+int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
+ EVP_PKEY *pkey);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_X509_INTERNAL_H */
diff --git a/crypto/x509/pkcs7_test.c b/crypto/x509/pkcs7_test.c
index 38beb3e8..bebcbd95 100644
--- a/crypto/x509/pkcs7_test.c
+++ b/crypto/x509/pkcs7_test.c
@@ -22,6 +22,8 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
+#include "../test/test_util.h"
+
/* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
* using the Chrome UI. */
@@ -504,7 +506,7 @@ static int test_cert_reparse(const uint8_t *der_bytes, size_t der_len) {
X509 *b = sk_X509_value(certs2, i);
if (X509_cmp(a, b) != 0) {
- fprintf(stderr, "Certificate %u differs.\n", (unsigned) i);
+ fprintf(stderr, "Certificate %zu differs.\n", i);
return 0;
}
}
@@ -568,7 +570,7 @@ static int test_crl_reparse(const uint8_t *der_bytes, size_t der_len) {
X509_CRL *b = sk_X509_CRL_value(crls2, i);
if (X509_CRL_cmp(a, b) != 0) {
- fprintf(stderr, "CRL %u differs.\n", (unsigned) i);
+ fprintf(stderr, "CRL %zu differs.\n", i);
return 0;
}
}
@@ -596,7 +598,7 @@ static int test_crl_reparse(const uint8_t *der_bytes, size_t der_len) {
}
static int test_pem_certs(const char *pem) {
- BIO *bio = BIO_new_mem_buf((char *) pem, strlen(pem));
+ BIO *bio = BIO_new_mem_buf(pem, strlen(pem));
STACK_OF(X509) *certs = sk_X509_new_null();
if (!PKCS7_get_PEM_certificates(certs, bio)) {
@@ -606,8 +608,8 @@ static int test_pem_certs(const char *pem) {
if (sk_X509_num(certs) != 1) {
fprintf(stderr,
- "Bad number of certificates from PKCS7_get_PEM_certificates: %u\n",
- (unsigned)sk_X509_num(certs));
+ "Bad number of certificates from PKCS7_get_PEM_certificates: %zu\n",
+ sk_X509_num(certs));
return 0;
}
@@ -618,7 +620,7 @@ static int test_pem_certs(const char *pem) {
}
static int test_pem_crls(const char *pem) {
- BIO *bio = BIO_new_mem_buf((char *) pem, strlen(pem));
+ BIO *bio = BIO_new_mem_buf(pem, strlen(pem));
STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null();
if (!PKCS7_get_PEM_CRLs(crls, bio)) {
@@ -627,9 +629,8 @@ static int test_pem_crls(const char *pem) {
}
if (sk_X509_CRL_num(crls) != 1) {
- fprintf(stderr,
- "Bad number of CRLs from PKCS7_get_PEM_CRLs: %u\n",
- (unsigned)sk_X509_CRL_num(crls));
+ fprintf(stderr, "Bad number of CRLs from PKCS7_get_PEM_CRLs: %zu\n",
+ sk_X509_CRL_num(crls));
return 0;
}
@@ -653,4 +654,3 @@ int main(void) {
printf("PASS\n");
return 0;
}
-
diff --git a/crypto/x509/rsa_pss.c b/crypto/x509/rsa_pss.c
new file mode 100644
index 00000000..1ae01a3d
--- /dev/null
+++ b/crypto/x509/rsa_pss.c
@@ -0,0 +1,385 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 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/x509.h>
+
+#include <assert.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
+} ASN1_SEQUENCE_END(RSA_PSS_PARAMS);
+
+IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS);
+
+
+/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
+static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
+ if (alg == NULL || alg->parameter == NULL ||
+ OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
+ alg->parameter->type != V_ASN1_SEQUENCE) {
+ return NULL;
+ }
+
+ const uint8_t *p = alg->parameter->value.sequence->data;
+ int plen = alg->parameter->value.sequence->length;
+ return d2i_X509_ALGOR(NULL, &p, plen);
+}
+
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
+ X509_ALGOR **pmaskHash) {
+ *pmaskHash = NULL;
+
+ if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) {
+ return NULL;
+ }
+
+ const uint8_t *p = alg->parameter->value.sequence->data;
+ int plen = alg->parameter->value.sequence->length;
+ RSA_PSS_PARAMS *pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
+ if (pss == NULL) {
+ return NULL;
+ }
+
+ *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+ return pss;
+}
+
+/* allocate and set algorithm ID from EVP_MD, default SHA1 */
+static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
+ if (EVP_MD_type(md) == NID_sha1) {
+ return 1;
+ }
+ *palg = X509_ALGOR_new();
+ if (*palg == NULL) {
+ return 0;
+ }
+ X509_ALGOR_set_md(*palg, md);
+ return 1;
+}
+
+/* Allocate and set MGF1 algorithm ID from EVP_MD */
+static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
+ X509_ALGOR *algtmp = NULL;
+ ASN1_STRING *stmp = NULL;
+ *palg = NULL;
+
+ if (EVP_MD_type(mgf1md) == NID_sha1) {
+ return 1;
+ }
+ /* need to embed algorithm ID inside another */
+ if (!rsa_md_to_algor(&algtmp, mgf1md) ||
+ !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
+ goto err;
+ }
+ *palg = X509_ALGOR_new();
+ if (!*palg) {
+ goto err;
+ }
+ X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
+ stmp = NULL;
+
+err:
+ ASN1_STRING_free(stmp);
+ X509_ALGOR_free(algtmp);
+ if (*palg) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* convert algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
+ const EVP_MD *md;
+ if (!alg) {
+ return EVP_sha1();
+ }
+ md = EVP_get_digestbyobj(alg->algorithm);
+ if (md == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ }
+ return md;
+}
+
+/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
+ const EVP_MD *md;
+ if (!alg) {
+ return EVP_sha1();
+ }
+ /* Check mask and lookup mask hash algorithm */
+ if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
+ maskHash == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ return NULL;
+ }
+ md = EVP_get_digestbyobj(maskHash->algorithm);
+ if (md == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ return NULL;
+ }
+ return md;
+}
+
+int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+ const EVP_MD *sigmd, *mgf1md;
+ int saltlen;
+ if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) ||
+ !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) ||
+ !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) {
+ return 0;
+ }
+
+ EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+ if (saltlen == -1) {
+ saltlen = EVP_MD_size(sigmd);
+ } else if (saltlen == -2) {
+ saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
+ if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
+ saltlen--;
+ }
+ } else {
+ return 0;
+ }
+
+ int ret = 0;
+ ASN1_STRING *os = NULL;
+ RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new();
+ if (!pss) {
+ goto err;
+ }
+
+ if (saltlen != 20) {
+ pss->saltLength = ASN1_INTEGER_new();
+ if (!pss->saltLength ||
+ !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
+ goto err;
+ }
+ }
+
+ if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
+ !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
+ goto err;
+ }
+
+ /* Finally create string with pss parameter encoding. */
+ if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
+ goto err;
+ }
+
+ X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os);
+ os = NULL;
+ ret = 1;
+
+err:
+ RSA_PSS_PARAMS_free(pss);
+ ASN1_STRING_free(os);
+ return ret;
+}
+
+int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
+ assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
+
+ /* Decode PSS parameters */
+ int ret = 0;
+ X509_ALGOR *maskHash;
+ RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
+ if (pss == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+
+ const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
+ const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm);
+ if (mgf1md == NULL || md == NULL) {
+ goto err;
+ }
+
+ int saltlen = 20;
+ if (pss->saltLength != NULL) {
+ saltlen = ASN1_INTEGER_get(pss->saltLength);
+
+ /* Could perform more salt length sanity checks but the main
+ * RSA routines will trap other invalid values anyway. */
+ if (saltlen < 0) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+ }
+
+ /* low-level routines support only trailer field 0xbc (value 1)
+ * and PKCS#1 says we should reject any other value anyway. */
+ if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) {
+ OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+
+ EVP_PKEY_CTX *pkctx;
+ if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
+ !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
+ !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ RSA_PSS_PARAMS_free(pss);
+ X509_ALGOR_free(maskHash);
+ return ret;
+}
+
+int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
+ ASN1_PCTX *pctx) {
+ assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
+
+ int rv = 0;
+ X509_ALGOR *maskHash;
+ RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
+ if (!pss) {
+ if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
+ goto err;
+ }
+ rv = 1;
+ goto err;
+ }
+
+ if (BIO_puts(bp, "\n") <= 0 ||
+ !BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Hash Algorithm: ") <= 0) {
+ goto err;
+ }
+
+ if (pss->hashAlgorithm) {
+ if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
+ goto err;
+ }
+
+ if (BIO_puts(bp, "\n") <= 0 ||
+ !BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Mask Algorithm: ") <= 0) {
+ goto err;
+ }
+
+ if (pss->maskGenAlgorithm) {
+ if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
+ BIO_puts(bp, " with ") <= 0) {
+ goto err;
+ }
+
+ if (maskHash) {
+ if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "INVALID") <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
+ goto err;
+ }
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Salt Length: 0x") <= 0) {
+ goto err;
+ }
+
+ if (pss->saltLength) {
+ if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "14 (default)") <= 0) {
+ goto err;
+ }
+ BIO_puts(bp, "\n");
+
+ if (!BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Trailer Field: 0x") <= 0) {
+ goto err;
+ }
+
+ if (pss->trailerField) {
+ if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
+ goto err;
+ }
+ } else if (BIO_puts(bp, "BC (default)") <= 0) {
+ goto err;
+ }
+ BIO_puts(bp, "\n");
+
+ rv = 1;
+
+err:
+ RSA_PSS_PARAMS_free(pss);
+ X509_ALGOR_free(maskHash);
+ return rv;
+}
diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c
index 1afcf601..1fba9b43 100644
--- a/crypto/x509/t_x509.c
+++ b/crypto/x509/t_x509.c
@@ -64,7 +64,8 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-#include "../evp/internal.h"
+#include "internal.h"
+
#ifndef OPENSSL_NO_FP_API
int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
@@ -132,7 +133,8 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
goto err;
bs = X509_get_serialNumber(x);
- if (bs->length <= (int)sizeof(long)) {
+ if (bs->length < (int)sizeof(long)
+ || (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) {
l = ASN1_INTEGER_get(bs);
if (bs->type == V_ASN1_NEG_INTEGER) {
l = -l;
@@ -298,22 +300,18 @@ int X509_ocspid_print(BIO *bp, X509 *x)
int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
{
- int sig_nid;
if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
return 0;
if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
return 0;
- sig_nid = OBJ_obj2nid(sigalg->algorithm);
- if (sig_nid != NID_undef) {
- int pkey_nid, dig_nid;
- const EVP_PKEY_ASN1_METHOD *ameth;
- if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
- ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
- if (ameth && ameth->sig_print)
- return ameth->sig_print(bp, sigalg, sig, 9, 0);
- }
+ /* RSA-PSS signatures have parameters to print. */
+ int sig_nid = OBJ_obj2nid(sigalg->algorithm);
+ if (sig_nid == NID_rsassaPss &&
+ !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) {
+ return 0;
}
+
if (sig)
return X509_signature_dump(bp, sig, 9);
else if (BIO_puts(bp, "\n") <= 0)
diff --git a/crypto/x509/x509.c b/crypto/x509/x509.c
index 31f9e1eb..188fd496 100644
--- a/crypto/x509/x509.c
+++ b/crypto/x509/x509.c
@@ -57,9 +57,14 @@
#include <openssl/x509.h>
#include <openssl/bio.h>
+#include <openssl/err.h>
#include <openssl/mem.h>
+/* |X509_R_UNSUPPORTED_ALGORITHM| is no longer emitted, but continue to define
+ * it to avoid downstream churn. */
+OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM)
+
int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
int ptype, void *pval, uint8_t *penc, int penclen) {
uint8_t **ppenc = NULL;
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index bfe6b11b..9f427dea 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -130,18 +130,18 @@ int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
- return X509_LU_FAIL;
+ return 0;
if (ctx->skip)
return 0;
- return ctx->method->get_by_subject(ctx, type, name, ret);
+ return ctx->method->get_by_subject(ctx, type, name, ret) > 0;
}
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
ASN1_INTEGER *serial, X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
- return X509_LU_FAIL;
- return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
+ return 0;
+ return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0;
}
int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
@@ -149,16 +149,16 @@ int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
- return X509_LU_FAIL;
- return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
+ return 0;
+ return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0;
}
int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
- return X509_LU_FAIL;
- return ctx->method->get_by_alias(ctx, type, str, len, ret);
+ return 0;
+ return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0;
}
static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
@@ -217,6 +217,11 @@ X509_STORE *X509_STORE_new(void)
return NULL;
}
+void X509_STORE_up_ref(X509_STORE *store)
+{
+ CRYPTO_refcount_inc(&store->references);
+}
+
static void cleanup(X509_OBJECT *a)
{
if (a == NULL) {
@@ -296,26 +301,20 @@ int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
X509_STORE *ctx = vs->ctx;
X509_LOOKUP *lu;
X509_OBJECT stmp, *tmp;
- int i, j;
+ int i;
CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
- CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
if (tmp == NULL || type == X509_LU_CRL) {
- for (i = vs->current_method;
- i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
+ for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
- j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
- if (j < 0) {
- vs->current_method = j;
- return j;
- } else if (j) {
+ if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) {
tmp = &stmp;
break;
}
}
- vs->current_method = 0;
if (tmp == NULL)
return 0;
}
@@ -359,7 +358,7 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
} else
sk_X509_OBJECT_push(ctx->objs, obj);
- CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
return ret;
}
@@ -391,7 +390,7 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
} else
sk_X509_OBJECT_push(ctx->objs, obj);
- CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
return ret;
}
@@ -499,7 +498,7 @@ STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
* cache
*/
X509_OBJECT xobj;
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
sk_X509_free(sk);
return NULL;
@@ -508,7 +507,7 @@ STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
sk_X509_free(sk);
return NULL;
}
@@ -517,13 +516,13 @@ STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
x = obj->data.x509;
if (!sk_X509_push(sk, X509_up_ref(x))) {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
X509_free(x);
sk_X509_pop_free(sk, X509_free);
return NULL;
}
}
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
return sk;
}
@@ -547,7 +546,7 @@ STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
if (idx < 0) {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
sk_X509_CRL_free(sk);
return NULL;
}
@@ -557,13 +556,13 @@ STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
x = obj->data.crl;
X509_CRL_up_ref(x);
if (!sk_X509_CRL_push(sk, x)) {
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
X509_CRL_free(x);
sk_X509_CRL_pop_free(sk, X509_CRL_free);
return NULL;
}
}
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
return sk;
}
@@ -606,22 +605,11 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
X509_NAME *xn;
X509_OBJECT obj, *pobj;
- int ok, idx, ret;
+ int idx, ret;
size_t i;
xn = X509_get_issuer_name(x);
- ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj);
- if (ok != X509_LU_X509) {
- if (ok == X509_LU_RETRY) {
- X509_OBJECT_free_contents(&obj);
- OPENSSL_PUT_ERROR(X509, X509_R_SHOULD_RETRY);
- return -1;
- } else if (ok != X509_LU_FAIL) {
- X509_OBJECT_free_contents(&obj);
- /* not good :-(, break anyway */
- return -1;
- }
+ if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj))
return 0;
- }
/* If certificate matches all OK */
if (ctx->check_issued(ctx, x, obj.data.x509)) {
*issuer = obj.data.x509;
@@ -651,7 +639,7 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
}
}
}
- CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
return ret;
}
diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c
index 641e308d..a7f31e03 100644
--- a/crypto/x509/x509_obj.c
+++ b/crypto/x509/x509_obj.c
@@ -64,6 +64,13 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
+/*
+ * Limit to ensure we don't overflow: much greater than
+ * anything enountered in practice.
+ */
+
+#define NAME_ONELINE_MAX (1024 * 1024)
+
char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
{
X509_NAME_ENTRY *ne;
@@ -84,6 +91,8 @@ char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
goto err;
b->data[0] = '\0';
len = 200;
+ } else if (len <= 0) {
+ return NULL;
}
if (a == NULL) {
if (b) {
@@ -108,6 +117,10 @@ char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
type = ne->value->type;
num = ne->value->length;
+ if (num > NAME_ONELINE_MAX) {
+ OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG);
+ goto end;
+ }
q = ne->value->data;
if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) {
@@ -135,6 +148,10 @@ char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
lold = l;
l += 1 + l1 + 1 + l2;
+ if (l > NAME_ONELINE_MAX) {
+ OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG);
+ goto end;
+ }
if (b != NULL) {
if (!BUF_MEM_grow(b, l + 1))
goto err;
@@ -174,7 +191,7 @@ char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
return (p);
err:
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
- if (b != NULL)
- BUF_MEM_free(b);
+ end:
+ BUF_MEM_free(b);
return (NULL);
}
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index 486fc4c4..650163a8 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -17,8 +17,12 @@
#include <assert.h>
#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
#include <openssl/err.h>
+#include <openssl/evp.h>
#include <openssl/pem.h>
+#include <openssl/x509.h>
#include "../test/scoped_types.h"
@@ -159,18 +163,89 @@ static const char kForgeryPEM[] =
"4UZAXPttuJXpn74IY1tuouaM06B3vXKZR+/ityKmfJvSwxacmFcK+2ziAg==\n"
"-----END CERTIFICATE-----\n";
+// kExamplePSSCert is an example RSA-PSS self-signed certificate, signed with
+// the default hash functions.
+static const char kExamplePSSCert[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIICYjCCAcagAwIBAgIJAI3qUyT6SIfzMBIGCSqGSIb3DQEBCjAFogMCAWowRTEL\n"
+"MAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVy\n"
+"bmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDEwMDkxOTA5NTVaFw0xNTEwMDkxOTA5\n"
+"NTVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQK\n"
+"DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A\n"
+"MIGJAoGBAPi4bIO0vNmoV8CltFl2jFQdeesiUgR+0zfrQf2D+fCmhRU0dXFahKg8\n"
+"0u9aTtPel4rd/7vPCqqGkr64UOTNb4AzMHYTj8p73OxaymPHAyXvqIqDWHYg+hZ3\n"
+"13mSYwFIGth7Z/FSVUlO1m5KXNd6NzYM3t2PROjCpywrta9kS2EHAgMBAAGjUDBO\n"
+"MB0GA1UdDgQWBBTQQfuJQR6nrVrsNF1JEflVgXgfEzAfBgNVHSMEGDAWgBTQQfuJ\n"
+"QR6nrVrsNF1JEflVgXgfEzAMBgNVHRMEBTADAQH/MBIGCSqGSIb3DQEBCjAFogMC\n"
+"AWoDgYEASUy2RZcgNbNQZA0/7F+V1YTLEXwD16bm+iSVnzGwtexmQVEYIZG74K/w\n"
+"xbdZQdTbpNJkp1QPjPfh0zsatw6dmt5QoZ8K8No0DjR9dgf+Wvv5WJvJUIQBoAVN\n"
+"Z0IL+OQFz6+LcTHxD27JJCebrATXZA0wThGTQDm7crL+a+SujBY=\n"
+"-----END CERTIFICATE-----\n";
+
+// kBadPSSCertPEM is a self-signed RSA-PSS certificate with bad parameters.
+static const char kBadPSSCertPEM[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDdjCCAjqgAwIBAgIJANcwZLyfEv7DMD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n"
+"AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3jAnMSUwIwYD\n"
+"VQQDDBxUZXN0IEludmFsaWQgUFNTIGNlcnRpZmljYXRlMB4XDTE1MTEwNDE2MDIz\n"
+"NVoXDTE1MTIwNDE2MDIzNVowJzElMCMGA1UEAwwcVGVzdCBJbnZhbGlkIFBTUyBj\n"
+"ZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTaM7WH\n"
+"qVCAGAIA+zL1KWvvASTrhlq+1ePdO7wsrWX2KiYoTYrJYTnxhLnn0wrHqApt79nL\n"
+"IBG7cfShyZqFHOY/IzlYPMVt+gPo293gw96Fds5JBsjhjkyGnOyr9OUntFqvxDbT\n"
+"IIFU7o9IdxD4edaqjRv+fegVE+B79pDk4s0ujsk6dULtCg9Rst0ucGFo19mr+b7k\n"
+"dbfn8pZ72ZNDJPueVdrUAWw9oll61UcYfk75XdrLk6JlL41GrYHc8KlfXf43gGQq\n"
+"QfrpHkg4Ih2cI6Wt2nhFGAzrlcorzLliQIUJRIhM8h4IgDfpBpaPdVQLqS2pFbXa\n"
+"5eQjqiyJwak2vJ8CAwEAAaNQME4wHQYDVR0OBBYEFCt180N4oGUt5LbzBwQ4Ia+2\n"
+"4V97MB8GA1UdIwQYMBaAFCt180N4oGUt5LbzBwQ4Ia+24V97MAwGA1UdEwQFMAMB\n"
+"Af8wMQYJKoZIhvcNAQEKMCSgDTALBglghkgBZQMEAgGhDTALBgkqhkiG9w0BAQii\n"
+"BAICAN4DggEBAAjBtm90lGxgddjc4Xu/nbXXFHVs2zVcHv/mqOZoQkGB9r/BVgLb\n"
+"xhHrFZ2pHGElbUYPfifdS9ztB73e1d4J+P29o0yBqfd4/wGAc/JA8qgn6AAEO/Xn\n"
+"plhFeTRJQtLZVl75CkHXgUGUd3h+ADvKtcBuW9dSUncaUrgNKR8u/h/2sMG38RWY\n"
+"DzBddC/66YTa3r7KkVUfW7yqRQfELiGKdcm+bjlTEMsvS+EhHup9CzbpoCx2Fx9p\n"
+"NPtFY3yEObQhmL1JyoCRWqBE75GzFPbRaiux5UpEkns+i3trkGssZzsOuVqHNTNZ\n"
+"lC9+9hPHIoc9UMmAQNo1vGIW3NWVoeGbaJ8=\n"
+"-----END CERTIFICATE-----\n";
-// CertFromPEM parses the given, NUL-terminated PEM block and returns an
+static const char kRSAKey[] =
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
+"kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
+"KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
+"AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
+"i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
+"WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
+"m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
+"QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
+"aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
+"LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
+"104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
+"tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
+"moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
+"-----END RSA PRIVATE KEY-----\n";
+
+
+// CertFromPEM parses the given, NUL-terminated pem block and returns an
// |X509*|.
-static X509* CertFromPEM(const char *pem) {
- ScopedBIO bio(BIO_new_mem_buf(const_cast<char*>(pem), strlen(pem)));
- return PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr);
+static ScopedX509 CertFromPEM(const char *pem) {
+ ScopedBIO bio(BIO_new_mem_buf(pem, strlen(pem)));
+ return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+}
+
+// PrivateKeyFromPEM parses the given, NUL-terminated pem block and returns an
+// |EVP_PKEY*|.
+static ScopedEVP_PKEY PrivateKeyFromPEM(const char *pem) {
+ ScopedBIO bio(BIO_new_mem_buf(const_cast<char *>(pem), strlen(pem)));
+ return ScopedEVP_PKEY(
+ PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
}
// CertsToStack converts a vector of |X509*| to an OpenSSL STACK_OF(X509*),
// bumping the reference counts for each certificate in question.
static STACK_OF(X509)* CertsToStack(const std::vector<X509*> &certs) {
ScopedX509Stack stack(sk_X509_new_null());
+ if (!stack) {
+ return nullptr;
+ }
for (auto cert : certs) {
if (!sk_X509_push(stack.get(), cert)) {
return nullptr;
@@ -217,7 +292,7 @@ static bool Verify(X509 *leaf, const std::vector<X509 *> &roots,
return X509_verify_cert(ctx.get()) == 1;
}
-int main(int argc, char **argv) {
+static bool TestVerify() {
ScopedX509 cross_signing_root(CertFromPEM(kCrossSigningRootPEM));
ScopedX509 root(CertFromPEM(kRootCAPEM));
ScopedX509 root_cross_signed(CertFromPEM(kRootCrossSignedPEM));
@@ -236,38 +311,38 @@ int main(int argc, char **argv) {
!leaf_no_key_usage ||
!forgery) {
fprintf(stderr, "Failed to parse certificates\n");
- return 1;
+ return false;
}
std::vector<X509*> empty;
if (Verify(leaf.get(), empty, empty)) {
fprintf(stderr, "Leaf verified with no roots!\n");
- return 1;
+ return false;
}
if (Verify(leaf.get(), empty, {intermediate.get()})) {
fprintf(stderr, "Leaf verified with no roots!\n");
- return 1;
+ return false;
}
if (!Verify(leaf.get(), {root.get()}, {intermediate.get()})) {
ERR_print_errors_fp(stderr);
fprintf(stderr, "Basic chain didn't verify.\n");
- return 1;
+ return false;
}
if (!Verify(leaf.get(), {cross_signing_root.get()},
{intermediate.get(), root_cross_signed.get()})) {
ERR_print_errors_fp(stderr);
fprintf(stderr, "Cross-signed chain didn't verify.\n");
- return 1;
+ return false;
}
if (!Verify(leaf.get(), {cross_signing_root.get(), root.get()},
{intermediate.get(), root_cross_signed.get()})) {
ERR_print_errors_fp(stderr);
fprintf(stderr, "Cross-signed chain with root didn't verify.\n");
- return 1;
+ return false;
}
/* This is the “altchains” test – we remove the cross-signing CA but include
@@ -276,20 +351,20 @@ int main(int argc, char **argv) {
{intermediate.get(), root_cross_signed.get()})) {
ERR_print_errors_fp(stderr);
fprintf(stderr, "Chain with cross-sign didn't backtrack to find root.\n");
- return 1;
+ return false;
}
if (Verify(leaf.get(), {root.get()},
{intermediate.get(), root_cross_signed.get()},
X509_V_FLAG_NO_ALT_CHAINS)) {
fprintf(stderr, "Altchains test still passed when disabled.\n");
- return 1;
+ return false;
}
if (Verify(forgery.get(), {intermediate_self_signed.get()},
{leaf_no_key_usage.get()})) {
fprintf(stderr, "Basic constraints weren't checked.\n");
- return 1;
+ return false;
}
/* Test that one cannot skip Basic Constraints checking with a contorted set
@@ -298,6 +373,97 @@ int main(int argc, char **argv) {
{intermediate_self_signed.get(), root_cross_signed.get()},
{leaf_no_key_usage.get(), intermediate.get()})) {
fprintf(stderr, "Basic constraints weren't checked.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestPSS() {
+ ScopedX509 cert(CertFromPEM(kExamplePSSCert));
+ if (!cert) {
+ return false;
+ }
+
+ ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get()));
+ if (!pkey) {
+ return false;
+ }
+
+ if (!X509_verify(cert.get(), pkey.get())) {
+ fprintf(stderr, "Could not verify certificate.\n");
+ return false;
+ }
+ return true;
+}
+
+static bool TestBadPSSParameters() {
+ ScopedX509 cert(CertFromPEM(kBadPSSCertPEM));
+ if (!cert) {
+ return false;
+ }
+
+ ScopedEVP_PKEY pkey(X509_get_pubkey(cert.get()));
+ if (!pkey) {
+ return false;
+ }
+
+ if (X509_verify(cert.get(), pkey.get())) {
+ fprintf(stderr, "Unexpectedly verified bad certificate.\n");
+ return false;
+ }
+ ERR_clear_error();
+ return true;
+}
+
+static bool SignatureRoundTrips(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
+ // Make a certificate like signed with |md_ctx|'s settings.'
+ ScopedX509 cert(CertFromPEM(kLeafPEM));
+ if (!cert || !X509_sign_ctx(cert.get(), md_ctx)) {
+ return false;
+ }
+
+ // Ensure that |pkey| may still be used to verify the resulting signature. All
+ // settings in |md_ctx| must have been serialized appropriately.
+ return !!X509_verify(cert.get(), pkey);
+}
+
+static bool TestSignCtx() {
+ ScopedEVP_PKEY pkey(PrivateKeyFromPEM(kRSAKey));
+ if (!pkey) {
+ return false;
+ }
+
+ // Test PKCS#1 v1.5.
+ ScopedEVP_MD_CTX md_ctx;
+ if (!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
+ !SignatureRoundTrips(md_ctx.get(), pkey.get())) {
+ fprintf(stderr, "RSA PKCS#1 with SHA-256 failed\n");
+ return false;
+ }
+
+ // Test RSA-PSS with custom parameters.
+ md_ctx.Reset();
+ EVP_PKEY_CTX *pkey_ctx;
+ if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
+ pkey.get()) ||
+ !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) ||
+ !SignatureRoundTrips(md_ctx.get(), pkey.get())) {
+ fprintf(stderr, "RSA-PSS failed\n");
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ if (!TestVerify() ||
+ !TestPSS() ||
+ !TestBadPSSParameters() ||
+ !TestSignCtx()) {
return 1;
}
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index 86af3fec..17e6cdb9 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -199,6 +199,11 @@ const char *X509_verify_cert_error_string(long n)
case X509_V_ERR_IP_ADDRESS_MISMATCH:
return ("IP address mismatch");
+ case X509_V_ERR_INVALID_CALL:
+ return ("Invalid certificate verification context");
+ case X509_V_ERR_STORE_LOOKUP:
+ return ("Issuer certificate lookup error");
+
default:
BIO_snprintf(buf, sizeof buf, "error number %ld", n);
return (buf);
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 602c8fbc..520408fe 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -193,11 +193,12 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
int bad_chain = 0;
X509_VERIFY_PARAM *param = ctx->param;
int depth, i, ok = 0;
- int num, j, retry;
+ int num, j, retry, trust;
int (*cb) (int xok, X509_STORE_CTX *xctx);
STACK_OF(X509) *sktmp = NULL;
if (ctx->cert == NULL) {
OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
+ ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
if (ctx->chain != NULL) {
@@ -206,6 +207,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
* cannot do another one.
*/
OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
@@ -218,6 +220,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
ctx->chain = sk_X509_new_null();
if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
goto end;
}
X509_up_ref(ctx->cert);
@@ -227,6 +230,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (ctx->untrusted != NULL
&& (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
goto end;
}
@@ -250,8 +254,10 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
*/
if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
ok = ctx->get_issuer(&xtmp, ctx, x);
- if (ok < 0)
+ if (ok < 0) {
+ ctx->error = X509_V_ERR_STORE_LOOKUP;
goto end;
+ }
/*
* If successful for now free up cert so it will be picked up
* again later.
@@ -268,6 +274,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (xtmp != NULL) {
if (!sk_X509_push(ctx->chain, xtmp)) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ ok = 0;
goto end;
}
X509_up_ref(xtmp);
@@ -348,14 +356,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
break;
ok = ctx->get_issuer(&xtmp, ctx, x);
- if (ok < 0)
+ if (ok < 0) {
+ ctx->error = X509_V_ERR_STORE_LOOKUP;
goto end;
+ }
if (ok == 0)
break;
x = xtmp;
if (!sk_X509_push(ctx->chain, x)) {
X509_free(xtmp);
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
ok = 0;
goto end;
}
@@ -363,11 +374,13 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
}
/* we now have our chain, lets check it... */
- i = check_trust(ctx);
+ trust = check_trust(ctx);
/* If explicitly rejected error */
- if (i == X509_TRUST_REJECTED)
+ if (trust == X509_TRUST_REJECTED) {
+ ok = 0;
goto end;
+ }
/*
* If it's not explicitly trusted then check if there is an alternative
* chain that could be used. We only do this if we haven't already
@@ -375,7 +388,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
* chain checking
*/
retry = 0;
- if (i != X509_TRUST_TRUSTED
+ if (trust != X509_TRUST_TRUSTED
&& !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
&& !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
while (j-- > 1) {
@@ -412,7 +425,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
* self signed certificate in which case we've indicated an error already
* and set bad_chain == 1
*/
- if (i != X509_TRUST_TRUSTED && !bad_chain) {
+ if (trust != X509_TRUST_TRUSTED && !bad_chain) {
if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) {
if (ctx->last_untrusted >= num)
ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
@@ -463,10 +476,10 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (!ok)
goto end;
- i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
- ctx->param->flags);
- if (i != X509_V_OK) {
- ctx->error = i;
+ int err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
+ ctx->param->flags);
+ if (err != X509_V_OK) {
+ ctx->error = err;
ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
ok = cb(0, ctx);
if (!ok)
@@ -490,6 +503,10 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
sk_X509_free(sktmp);
if (chain_ss != NULL)
X509_free(chain_ss);
+
+ /* Safety net, error returns must set ctx->error */
+ if (ok <= 0 && ctx->error == X509_V_OK)
+ ctx->error = X509_V_ERR_UNSPECIFIED;
return ok;
}
@@ -706,12 +723,19 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
if (nc) {
rv = NAME_CONSTRAINTS_check(x, nc);
- if (rv != X509_V_OK) {
+ switch (rv) {
+ case X509_V_OK:
+ continue;
+ case X509_V_ERR_OUT_OF_MEM:
+ ctx->error = rv;
+ return 0;
+ default:
ctx->error = rv;
ctx->error_depth = i;
ctx->current_cert = x;
if (!ctx->verify_cb(0, ctx))
return 0;
+ break;
}
}
}
@@ -841,11 +865,10 @@ static int check_revocation(X509_STORE_CTX *ctx)
}
static int check_cert(X509_STORE_CTX *ctx)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
X509_CRL *crl = NULL, *dcrl = NULL;
X509 *x;
- int ok, cnum;
+ int ok = 0, cnum;
unsigned int last_reasons;
cnum = ctx->error_depth;
x = sk_X509_value(ctx->chain, cnum);
@@ -1603,6 +1626,7 @@ static int check_policy(X509_STORE_CTX *ctx)
ctx->param->policies, ctx->param->flags);
if (ret == 0) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
/* Invalid or inconsistent extensions */
@@ -1631,7 +1655,12 @@ static int check_policy(X509_STORE_CTX *ctx)
if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
ctx->current_cert = NULL;
- ctx->error = X509_V_OK;
+ /*
+ * Verification errors need to be "sticky", a callback may have allowed
+ * an SSL handshake to continue despite an error, and we must then
+ * remain in an error state. Therefore, we MUST NOT clear earlier
+ * verification errors by setting the error to X509_V_OK.
+ */
if (!ctx->verify_cb(2, ctx))
return 0;
}
diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index cd648901..934571dd 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -460,14 +460,14 @@ static int def_crl_lookup(X509_CRL *crl,
CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock);
const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
- CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&g_crl_sort_lock);
if (!is_sorted) {
CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock);
if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
sk_X509_REVOKED_sort(crl->crl->revoked);
}
- CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_crl_sort_lock);
}
if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c
index 226e76dc..d7dbf804 100644
--- a/crypto/x509/x_name.c
+++ b/crypto/x509/x_name.c
@@ -71,6 +71,13 @@
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
+/*
+ * Maximum length of X509_NAME: much larger than anything we should
+ * ever see in practice.
+ */
+
+#define X509_NAME_MAX (1024 * 1024)
+
static int x509_name_ex_d2i(ASN1_VALUE **val,
const unsigned char **in, long len,
const ASN1_ITEM *it,
@@ -87,10 +94,6 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname,
unsigned char **in);
-static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
- int indent,
- const char *fname, const ASN1_PCTX *pctx);
-
ASN1_SEQUENCE(X509_NAME_ENTRY) = {
ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
@@ -126,7 +129,7 @@ static const ASN1_EXTERN_FUNCS x509_name_ff = {
0, /* Default clear behaviour is OK */
x509_name_ex_d2i,
x509_name_ex_i2d,
- x509_name_ex_print
+ NULL,
};
IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
@@ -208,6 +211,10 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
int ret;
STACK_OF(X509_NAME_ENTRY) *entries;
X509_NAME_ENTRY *entry;
+ /* Bound the size of an X509_NAME we are willing to parse. */
+ if (len > X509_NAME_MAX) {
+ len = X509_NAME_MAX;
+ }
q = p;
/* Get internal representation of Name */
@@ -323,16 +330,6 @@ static int x509_name_encode(X509_NAME *a)
return -1;
}
-static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
- int indent,
- const char *fname, const ASN1_PCTX *pctx)
-{
- if (X509_NAME_print_ex(out, (X509_NAME *)*pval,
- indent, pctx->nm_flags) <= 0)
- return 0;
- return 2;
-}
-
/*
* This function generates the canonical encoding of the Name structure. In
* it all strings are converted to UTF8, leading, trailing and multiple
@@ -453,10 +450,10 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
len--;
}
- to = from + len - 1;
+ to = from + len;
/* Ignore trailing spaces */
- while ((len > 0) && !(*to & 0x80) && isspace(*to)) {
+ while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) {
to--;
len--;
}
diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c
index 47f256c7..23534b2b 100644
--- a/crypto/x509/x_pubkey.c
+++ b/crypto/x509/x_pubkey.c
@@ -54,6 +54,8 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
+#include <openssl/x509.h>
+
#include <limits.h>
#include <openssl/asn1.h>
@@ -64,7 +66,6 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/thread.h>
-#include <openssl/x509.h>
#include "../internal.h"
@@ -139,10 +140,10 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock);
if (key->pkey != NULL) {
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock);
return EVP_PKEY_up_ref(key->pkey);
}
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock);
/* Re-encode the |X509_PUBKEY| to DER and parse it. */
int spki_len = i2d_X509_PUBKEY(key, &spki);
@@ -160,12 +161,12 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
/* Check to see if another thread set key->pkey first */
CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
if (key->pkey) {
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock);
EVP_PKEY_free(ret);
ret = key->pkey;
} else {
key->pkey = ret;
- CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock);
}
OPENSSL_free(spki);
diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c
index 1ae37c4b..e21258d4 100644
--- a/crypto/x509/x_x509.c
+++ b/crypto/x509/x_x509.c
@@ -55,6 +55,7 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
+#include <assert.h>
#include <stdio.h>
#include <openssl/asn1t.h>
@@ -204,12 +205,73 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
return NULL;
}
+/*
+ * Serialize trusted certificate to *pp or just return the required buffer
+ * length if pp == NULL. We ultimately want to avoid modifying *pp in the
+ * error path, but that depends on similar hygiene in lower-level functions.
+ * Here we avoid compounding the problem.
+ */
+static int i2d_x509_aux_internal(X509 *a, unsigned char **pp)
+{
+ int length, tmplen;
+ unsigned char *start = pp != NULL ? *pp : NULL;
+
+ assert(pp == NULL || *pp != NULL);
+
+ /*
+ * This might perturb *pp on error, but fixing that belongs in i2d_X509()
+ * not here. It should be that if a == NULL length is zero, but we check
+ * both just in case.
+ */
+ length = i2d_X509(a, pp);
+ if (length <= 0 || a == NULL) {
+ return length;
+ }
+
+ tmplen = i2d_X509_CERT_AUX(a->aux, pp);
+ if (tmplen < 0) {
+ if (start != NULL)
+ *pp = start;
+ return tmplen;
+ }
+ length += tmplen;
+
+ return length;
+}
+
+/*
+ * Serialize trusted certificate to *pp, or just return the required buffer
+ * length if pp == NULL.
+ *
+ * When pp is not NULL, but *pp == NULL, we allocate the buffer, but since
+ * we're writing two ASN.1 objects back to back, we can't have i2d_X509() do
+ * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the
+ * allocated buffer.
+ */
int i2d_X509_AUX(X509 *a, unsigned char **pp)
{
int length;
- length = i2d_X509(a, pp);
- if (a)
- length += i2d_X509_CERT_AUX(a->aux, pp);
+ unsigned char *tmp;
+
+ /* Buffer provided by caller */
+ if (pp == NULL || *pp != NULL)
+ return i2d_x509_aux_internal(a, pp);
+
+ /* Obtain the combined length */
+ if ((length = i2d_x509_aux_internal(a, NULL)) <= 0)
+ return length;
+
+ /* Allocate requisite combined storage */
+ *pp = tmp = OPENSSL_malloc(length);
+ if (tmp == NULL)
+ return -1; /* Push error onto error stack? */
+
+ /* Encode, but keep *pp at the originally malloced pointer */
+ length = i2d_x509_aux_internal(a, &tmp);
+ if (length <= 0) {
+ OPENSSL_free(*pp);
+ *pp = NULL;
+ }
return length;
}
diff --git a/crypto/x509v3/pcy_cache.c b/crypto/x509v3/pcy_cache.c
index f1e512ea..b8a4be27 100644
--- a/crypto/x509v3/pcy_cache.c
+++ b/crypto/x509v3/pcy_cache.c
@@ -241,7 +241,7 @@ const X509_POLICY_CACHE *policy_cache_set(X509 *x)
CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
cache = x->policy_cache;
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+ CRYPTO_STATIC_MUTEX_unlock_read(&g_x509_policy_cache_lock);
if (cache != NULL)
return cache;
@@ -250,7 +250,7 @@ const X509_POLICY_CACHE *policy_cache_set(X509 *x)
if (x->policy_cache == NULL)
policy_cache_new(x);
cache = x->policy_cache;
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_policy_cache_lock);
return cache;
}
diff --git a/crypto/x509v3/tab_test.c b/crypto/x509v3/tab_test.c
index 7994043b..19005474 100644
--- a/crypto/x509v3/tab_test.c
+++ b/crypto/x509v3/tab_test.c
@@ -66,6 +66,7 @@
#include <openssl/base.h>
#include <openssl/crypto.h>
+#include <openssl/obj.h>
#include <openssl/x509v3.h>
#if !defined(BORINGSSL_SHARED_LIBRARY)
diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c
index 7405e1e4..66abca4e 100644
--- a/crypto/x509v3/v3_conf.c
+++ b/crypto/x509v3/v3_conf.c
@@ -263,10 +263,9 @@ static int v3_check_generic(char **value)
static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
int crit, int gen_type,
X509V3_CTX *ctx)
- OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
unsigned char *ext_der = NULL;
- long ext_len;
+ long ext_len = 0;
ASN1_OBJECT *obj = NULL;
ASN1_OCTET_STRING *oct = NULL;
X509_EXTENSION *extension = NULL;
diff --git a/crypto/x509v3/v3_cpols.c b/crypto/x509v3/v3_cpols.c
index 4d086ab5..d67dcb08 100644
--- a/crypto/x509v3/v3_cpols.c
+++ b/crypto/x509v3/v3_cpols.c
@@ -190,6 +190,11 @@ static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
goto err;
}
pol = POLICYINFO_new();
+ if (pol == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ ASN1_OBJECT_free(pobj);
+ goto err;
+ }
pol->policyid = pobj;
}
if (!sk_POLICYINFO_push(pols, pol)) {
diff --git a/crypto/x509v3/v3_prn.c b/crypto/x509v3/v3_prn.c
index 5015efcc..2f5efcff 100644
--- a/crypto/x509v3/v3_prn.c
+++ b/crypto/x509v3/v3_prn.c
@@ -207,9 +207,6 @@ static int unknown_ext_print(BIO *out, X509_EXTENSION *ext,
return 1;
case X509V3_EXT_PARSE_UNKNOWN:
- return ASN1_parse_dump(out,
- ext->value->data, ext->value->length, indent,
- -1);
case X509V3_EXT_DUMP_UNKNOWN:
return BIO_hexdump(out, ext->value->data, ext->value->length, indent);
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index 85bc15b7..f9324d4e 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -431,7 +431,7 @@ static void x509v3_cache_extensions(X509 *x)
CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock);
if (x->ex_flags & EXFLAG_SET) {
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock);
return;
}
@@ -564,7 +564,7 @@ static void x509v3_cache_extensions(X509 *x)
}
x->ex_flags |= EXFLAG_SET;
- CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock);
}
/*
diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c
index 6b6a6f88..a238a20e 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509v3/v3_utl.c
@@ -852,7 +852,8 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
state = LABEL_START;
++dots;
} else if (p[i] == '-') {
- if (state & LABEL_HYPHEN)
+ /* no domain/subdomain starts with '-' */
+ if ((state & LABEL_START) != 0)
return NULL;
state |= LABEL_HYPHEN;
} else
diff --git a/crypto/x509v3/v3name_test.c b/crypto/x509v3/v3name_test.c
index 0979583f..dadf488f 100644
--- a/crypto/x509v3/v3name_test.c
+++ b/crypto/x509v3/v3name_test.c
@@ -65,12 +65,16 @@
static const char *const names[] = {
"a", "b", ".", "*", "@",
".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
+ "-example.com", "example-.com",
"@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
"*@example.com", "test@*.example.com", "example.com", "www.example.com",
"test.www.example.com", "*.example.com", "*.www.example.com",
"test.*.example.com", "www.*.com",
".www.example.com", "*www.example.com",
"example.net", "xn--rger-koa.example.com",
+ "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
+ "*.good--example.com", "www.good--example.com",
+ "*.xn--bar.com", "xn--foo.xn--bar.com",
"a.example.com", "b.example.com",
"postmaster@example.com", "Postmaster@example.com",
"postmaster@EXAMPLE.COM",
@@ -86,6 +90,9 @@ static const char *const exceptions[] = {
"set CN: host: [*.www.example.com] matches [.www.example.com]",
"set CN: host: [*www.example.com] matches [www.example.com]",
"set CN: host: [test.www.example.com] matches [.www.example.com]",
+ "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+ "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+ "set CN: host: [*.good--example.com] matches [www.good--example.com]",
"set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
"set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
"set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
@@ -102,6 +109,9 @@ static const char *const exceptions[] = {
"set dnsName: host: [*.www.example.com] matches [.www.example.com]",
"set dnsName: host: [*www.example.com] matches [www.example.com]",
"set dnsName: host: [test.www.example.com] matches [.www.example.com]",
+ "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+ "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+ "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
"set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
"set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
"set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
diff --git a/decrepit/CMakeLists.txt b/decrepit/CMakeLists.txt
index a7677d0a..6a5462c2 100644
--- a/decrepit/CMakeLists.txt
+++ b/decrepit/CMakeLists.txt
@@ -2,8 +2,15 @@ add_subdirectory(bio)
add_subdirectory(blowfish)
add_subdirectory(cast)
add_subdirectory(des)
+add_subdirectory(dh)
+add_subdirectory(dsa)
add_subdirectory(evp)
+add_subdirectory(obj)
+add_subdirectory(rc4)
+add_subdirectory(ripemd)
add_subdirectory(rsa)
+add_subdirectory(ssl)
+add_subdirectory(x509)
add_subdirectory(xts)
add_library(
@@ -13,9 +20,16 @@ add_library(
$<TARGET_OBJECTS:blowfish>
$<TARGET_OBJECTS:cast>
$<TARGET_OBJECTS:des_decrepit>
+ $<TARGET_OBJECTS:dh_decrepit>
+ $<TARGET_OBJECTS:dsa_decrepit>
$<TARGET_OBJECTS:evp_decrepit>
+ $<TARGET_OBJECTS:obj_decrepit>
+ $<TARGET_OBJECTS:rc4_decrepit>
+ $<TARGET_OBJECTS:ripemd_decrepit>
$<TARGET_OBJECTS:rsa_decrepit>
+ $<TARGET_OBJECTS:ssl_decrepit>
+ $<TARGET_OBJECTS:x509_decrepit>
$<TARGET_OBJECTS:xts>
)
-target_link_libraries(decrepit crypto)
+target_link_libraries(decrepit crypto ssl)
diff --git a/decrepit/bio/base64_bio.c b/decrepit/bio/base64_bio.c
index 2056138f..8415bfed 100644
--- a/decrepit/bio/base64_bio.c
+++ b/decrepit/bio/base64_bio.c
@@ -452,7 +452,7 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) {
case BIO_CTRL_WPENDING: /* More to write in buffer */
assert(ctx->buf_len >= ctx->buf_off);
ret = ctx->buf_len - ctx->buf_off;
- if ((ret == 0) && (ctx->encode != B64_NONE) && (ctx->base64.num != 0)) {
+ if ((ret == 0) && (ctx->encode != B64_NONE) && (ctx->base64.data_used != 0)) {
ret = 1;
} else if (ret <= 0) {
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
@@ -484,7 +484,7 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) {
ctx->tmp_len = 0;
goto again;
}
- } else if (ctx->encode != B64_NONE && ctx->base64.num != 0) {
+ } else if (ctx->encode != B64_NONE && ctx->base64.data_used != 0) {
ctx->buf_off = 0;
EVP_EncodeFinal(&(ctx->base64), (uint8_t *)ctx->buf, &(ctx->buf_len));
/* push out the bytes */
diff --git a/decrepit/cast/cast.c b/decrepit/cast/cast.c
index 94b07106..75ea6567 100644
--- a/decrepit/cast/cast.c
+++ b/decrepit/cast/cast.c
@@ -57,9 +57,9 @@
#include <openssl/cast.h>
#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <intrin.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include "internal.h"
diff --git a/decrepit/dh/CMakeLists.txt b/decrepit/dh/CMakeLists.txt
new file mode 100644
index 00000000..fb862b51
--- /dev/null
+++ b/decrepit/dh/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+ dh_decrepit
+
+ OBJECT
+
+ dh_decrepit.c
+)
diff --git a/decrepit/dh/dh_decrepit.c b/decrepit/dh/dh_decrepit.c
new file mode 100644
index 00000000..1d38c12e
--- /dev/null
+++ b/decrepit/dh/dh_decrepit.c
@@ -0,0 +1,103 @@
+/* ====================================================================
+ * Copyright (c) 1998-2002 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
+ * openssl-core@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/bn.h>
+#include <openssl/dh.h>
+
+
+struct wrapped_callback {
+ void (*callback)(int, int, void *);
+ void *arg;
+};
+
+/* callback_wrapper converts an “old” style generation callback to the newer
+ * |BN_GENCB| form. */
+static int callback_wrapper(int event, int n, BN_GENCB *gencb) {
+ struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg;
+ wrapped->callback(event, n, wrapped->arg);
+ return 1;
+}
+
+DH *DH_generate_parameters(int prime_len, int generator,
+ void (*callback)(int, int, void *), void *cb_arg) {
+ if (prime_len < 0 || generator < 0) {
+ return NULL;
+ }
+
+ DH *ret = DH_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ BN_GENCB gencb_storage;
+ BN_GENCB *cb = NULL;
+
+ struct wrapped_callback wrapped;
+
+ if (callback != NULL) {
+ wrapped.callback = callback;
+ wrapped.arg = cb_arg;
+
+ cb = &gencb_storage;
+ BN_GENCB_set(cb, callback_wrapper, &wrapped);
+ }
+
+ if (!DH_generate_parameters_ex(ret, prime_len, generator, cb)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ DH_free(ret);
+ return NULL;
+}
diff --git a/decrepit/dsa/CMakeLists.txt b/decrepit/dsa/CMakeLists.txt
new file mode 100644
index 00000000..cc64b604
--- /dev/null
+++ b/decrepit/dsa/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+ dsa_decrepit
+
+ OBJECT
+
+ dsa_decrepit.c
+)
diff --git a/decrepit/dsa/dsa_decrepit.c b/decrepit/dsa/dsa_decrepit.c
new file mode 100644
index 00000000..aef8056b
--- /dev/null
+++ b/decrepit/dsa/dsa_decrepit.c
@@ -0,0 +1,105 @@
+/* ====================================================================
+ * Copyright (c) 1998-2002 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
+ * openssl-core@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/bn.h>
+#include <openssl/dsa.h>
+
+
+struct wrapped_callback {
+ void (*callback)(int, int, void *);
+ void *arg;
+};
+
+/* callback_wrapper converts an “old” style generation callback to the newer
+ * |BN_GENCB| form. */
+static int callback_wrapper(int event, int n, BN_GENCB *gencb) {
+ struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg;
+ wrapped->callback(event, n, wrapped->arg);
+ return 1;
+}
+
+DSA *DSA_generate_parameters(int bits, uint8_t *seed_in, int seed_len,
+ int *counter_ret, unsigned long *h_ret,
+ void (*callback)(int, int, void *), void *cb_arg) {
+ if (bits < 0 || seed_len < 0) {
+ return NULL;
+ }
+
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ BN_GENCB gencb_storage;
+ BN_GENCB *cb = NULL;
+
+ struct wrapped_callback wrapped;
+
+ if (callback != NULL) {
+ wrapped.callback = callback;
+ wrapped.arg = cb_arg;
+
+ cb = &gencb_storage;
+ BN_GENCB_set(cb, callback_wrapper, &wrapped);
+ }
+
+ if (!DSA_generate_parameters_ex(ret, bits, seed_in, seed_len, counter_ret,
+ h_ret, cb)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ DSA_free(ret);
+ return NULL;
+}
diff --git a/decrepit/evp/CMakeLists.txt b/decrepit/evp/CMakeLists.txt
index ee3bf33b..e631a9a9 100644
--- a/decrepit/evp/CMakeLists.txt
+++ b/decrepit/evp/CMakeLists.txt
@@ -5,5 +5,6 @@ add_library(
OBJECT
+ dss1.c
evp_do_all.c
)
diff --git a/decrepit/evp/dss1.c b/decrepit/evp/dss1.c
new file mode 100644
index 00000000..9c370acb
--- /dev/null
+++ b/decrepit/evp/dss1.c
@@ -0,0 +1,20 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/digest.h>
+
+
+const EVP_MD *EVP_dss1(void) {
+ return EVP_sha1();
+}
diff --git a/decrepit/obj/CMakeLists.txt b/decrepit/obj/CMakeLists.txt
new file mode 100644
index 00000000..caaecd32
--- /dev/null
+++ b/decrepit/obj/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+ obj_decrepit
+
+ OBJECT
+
+ obj_decrepit.c
+)
diff --git a/decrepit/obj/obj_decrepit.c b/decrepit/obj/obj_decrepit.c
new file mode 100644
index 00000000..06051f11
--- /dev/null
+++ b/decrepit/obj/obj_decrepit.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/obj.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+
+
+struct wrapped_callback {
+ void (*callback)(const OBJ_NAME *, void *arg);
+ void *arg;
+};
+
+static void cipher_callback(const EVP_CIPHER *cipher, const char *name,
+ const char *unused, void *arg) {
+ const struct wrapped_callback *wrapped = (struct wrapped_callback *)arg;
+ OBJ_NAME obj_name;
+
+ memset(&obj_name, 0, sizeof(obj_name));
+ obj_name.type = OBJ_NAME_TYPE_CIPHER_METH;
+ obj_name.name = name;
+
+ wrapped->callback(&obj_name, wrapped->arg);
+}
+
+static void md_callback(const EVP_MD *md, const char *name, const char *unused,
+ void *arg) {
+ const struct wrapped_callback *wrapped = (struct wrapped_callback*) arg;
+ OBJ_NAME obj_name;
+
+ memset(&obj_name, 0, sizeof(obj_name));
+ obj_name.type = OBJ_NAME_TYPE_MD_METH;
+ obj_name.name = name;
+
+ wrapped->callback(&obj_name, wrapped->arg);
+}
+
+void OBJ_NAME_do_all_sorted(int type,
+ void (*callback)(const OBJ_NAME *, void *arg),
+ void *arg) {
+ struct wrapped_callback wrapped;
+ wrapped.callback = callback;
+ wrapped.arg = arg;
+
+ if (type == OBJ_NAME_TYPE_CIPHER_METH) {
+ EVP_CIPHER_do_all_sorted(cipher_callback, &wrapped);
+ } else if (type == OBJ_NAME_TYPE_MD_METH) {
+ EVP_MD_do_all_sorted(md_callback, &wrapped);
+ } else {
+ assert(0);
+ }
+}
+
+void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *, void *arg),
+ void *arg) {
+ OBJ_NAME_do_all_sorted(type, callback, arg);
+}
diff --git a/decrepit/rc4/CMakeLists.txt b/decrepit/rc4/CMakeLists.txt
new file mode 100644
index 00000000..459b24e2
--- /dev/null
+++ b/decrepit/rc4/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+ rc4_decrepit
+
+ OBJECT
+
+ rc4_decrepit.c
+)
diff --git a/decrepit/rc4/rc4_decrepit.c b/decrepit/rc4/rc4_decrepit.c
new file mode 100644
index 00000000..140e15d6
--- /dev/null
+++ b/decrepit/rc4/rc4_decrepit.c
@@ -0,0 +1,62 @@
+/* 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/rc4.h>
+
+
+const char *RC4_options(void) {
+ return "rc4(ptr,int)";
+}
diff --git a/decrepit/ripemd/CMakeLists.txt b/decrepit/ripemd/CMakeLists.txt
new file mode 100644
index 00000000..b913e5b8
--- /dev/null
+++ b/decrepit/ripemd/CMakeLists.txt
@@ -0,0 +1,23 @@
+include_directories(../../include)
+
+add_library(
+ ripemd_decrepit
+
+ OBJECT
+
+ ripemd.c
+)
+
+if(ENABLE_TESTS)
+add_executable(
+ ripemd_test
+
+ ripemd_test.cc
+
+ $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(ripemd_test crypto)
+target_link_libraries(ripemd_test decrepit)
+add_dependencies(all_tests ripemd_test)
+endif()
diff --git a/decrepit/ripemd/internal.h b/decrepit/ripemd/internal.h
new file mode 100644
index 00000000..c4db4b23
--- /dev/null
+++ b/decrepit/ripemd/internal.h
@@ -0,0 +1,493 @@
+/* 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.] */
+
+#ifndef OPENSSL_HEADER_BN_INTERNAL_H
+#define OPENSSL_HEADER_BN_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data,
+ size_t num);
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG uint32_t
+#define HASH_CTX RIPEMD160_CTX
+#define HASH_CBLOCK RIPEMD160_CBLOCK
+#define HASH_UPDATE RIPEMD160_Update
+#define HASH_TRANSFORM RIPEMD160_Transform
+#define HASH_FINAL RIPEMD160_Final
+#define HASH_MAKE_STRING(c, s) \
+ do { \
+ unsigned long ll; \
+ ll = (c)->h[0]; \
+ (void)HOST_l2c(ll, (s)); \
+ ll = (c)->h[1]; \
+ (void)HOST_l2c(ll, (s)); \
+ ll = (c)->h[2]; \
+ (void)HOST_l2c(ll, (s)); \
+ ll = (c)->h[3]; \
+ (void)HOST_l2c(ll, (s)); \
+ ll = (c)->h[4]; \
+ (void)HOST_l2c(ll, (s)); \
+ } while (0)
+#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order
+
+#include "../../crypto/digest/md32_common.h"
+
+/* Transformed F2 and F4 are courtesy of Wei Dai <weidai@eskimo.com> */
+#define F1(x, y, z) ((x) ^ (y) ^ (z))
+#define F2(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
+#define F3(x, y, z) (((~(y)) | (x)) ^ (z))
+#define F4(x, y, z) ((((x) ^ (y)) & (z)) ^ (y))
+#define F5(x, y, z) (((~(z)) | (y)) ^ (x))
+
+#define RIPEMD160_A 0x67452301L
+#define RIPEMD160_B 0xEFCDAB89L
+#define RIPEMD160_C 0x98BADCFEL
+#define RIPEMD160_D 0x10325476L
+#define RIPEMD160_E 0xC3D2E1F0L
+
+#define ROTATE(a, n) (((a) << (n)) | (((a)&0xffffffff) >> (32 - (n))))
+
+#define RIP1(a, b, c, d, e, w, s) \
+ { \
+ a += F1(b, c, d) + X(w); \
+ a = ROTATE(a, s) + e; \
+ c = ROTATE(c, 10); \
+ }
+
+#define RIP2(a, b, c, d, e, w, s, K) \
+ { \
+ a += F2(b, c, d) + X(w) + K; \
+ a = ROTATE(a, s) + e; \
+ c = ROTATE(c, 10); \
+ }
+
+#define RIP3(a, b, c, d, e, w, s, K) \
+ { \
+ a += F3(b, c, d) + X(w) + K; \
+ a = ROTATE(a, s) + e; \
+ c = ROTATE(c, 10); \
+ }
+
+#define RIP4(a, b, c, d, e, w, s, K) \
+ { \
+ a += F4(b, c, d) + X(w) + K; \
+ a = ROTATE(a, s) + e; \
+ c = ROTATE(c, 10); \
+ }
+
+#define RIP5(a, b, c, d, e, w, s, K) \
+ { \
+ a += F5(b, c, d) + X(w) + K; \
+ a = ROTATE(a, s) + e; \
+ c = ROTATE(c, 10); \
+ }
+
+#define KL0 0x00000000L
+#define KL1 0x5A827999L
+#define KL2 0x6ED9EBA1L
+#define KL3 0x8F1BBCDCL
+#define KL4 0xA953FD4EL
+
+#define KR0 0x50A28BE6L
+#define KR1 0x5C4DD124L
+#define KR2 0x6D703EF3L
+#define KR3 0x7A6D76E9L
+#define KR4 0x00000000L
+
+#define WL00 0
+#define SL00 11
+#define WL01 1
+#define SL01 14
+#define WL02 2
+#define SL02 15
+#define WL03 3
+#define SL03 12
+#define WL04 4
+#define SL04 5
+#define WL05 5
+#define SL05 8
+#define WL06 6
+#define SL06 7
+#define WL07 7
+#define SL07 9
+#define WL08 8
+#define SL08 11
+#define WL09 9
+#define SL09 13
+#define WL10 10
+#define SL10 14
+#define WL11 11
+#define SL11 15
+#define WL12 12
+#define SL12 6
+#define WL13 13
+#define SL13 7
+#define WL14 14
+#define SL14 9
+#define WL15 15
+#define SL15 8
+
+#define WL16 7
+#define SL16 7
+#define WL17 4
+#define SL17 6
+#define WL18 13
+#define SL18 8
+#define WL19 1
+#define SL19 13
+#define WL20 10
+#define SL20 11
+#define WL21 6
+#define SL21 9
+#define WL22 15
+#define SL22 7
+#define WL23 3
+#define SL23 15
+#define WL24 12
+#define SL24 7
+#define WL25 0
+#define SL25 12
+#define WL26 9
+#define SL26 15
+#define WL27 5
+#define SL27 9
+#define WL28 2
+#define SL28 11
+#define WL29 14
+#define SL29 7
+#define WL30 11
+#define SL30 13
+#define WL31 8
+#define SL31 12
+
+#define WL32 3
+#define SL32 11
+#define WL33 10
+#define SL33 13
+#define WL34 14
+#define SL34 6
+#define WL35 4
+#define SL35 7
+#define WL36 9
+#define SL36 14
+#define WL37 15
+#define SL37 9
+#define WL38 8
+#define SL38 13
+#define WL39 1
+#define SL39 15
+#define WL40 2
+#define SL40 14
+#define WL41 7
+#define SL41 8
+#define WL42 0
+#define SL42 13
+#define WL43 6
+#define SL43 6
+#define WL44 13
+#define SL44 5
+#define WL45 11
+#define SL45 12
+#define WL46 5
+#define SL46 7
+#define WL47 12
+#define SL47 5
+
+#define WL48 1
+#define SL48 11
+#define WL49 9
+#define SL49 12
+#define WL50 11
+#define SL50 14
+#define WL51 10
+#define SL51 15
+#define WL52 0
+#define SL52 14
+#define WL53 8
+#define SL53 15
+#define WL54 12
+#define SL54 9
+#define WL55 4
+#define SL55 8
+#define WL56 13
+#define SL56 9
+#define WL57 3
+#define SL57 14
+#define WL58 7
+#define SL58 5
+#define WL59 15
+#define SL59 6
+#define WL60 14
+#define SL60 8
+#define WL61 5
+#define SL61 6
+#define WL62 6
+#define SL62 5
+#define WL63 2
+#define SL63 12
+
+#define WL64 4
+#define SL64 9
+#define WL65 0
+#define SL65 15
+#define WL66 5
+#define SL66 5
+#define WL67 9
+#define SL67 11
+#define WL68 7
+#define SL68 6
+#define WL69 12
+#define SL69 8
+#define WL70 2
+#define SL70 13
+#define WL71 10
+#define SL71 12
+#define WL72 14
+#define SL72 5
+#define WL73 1
+#define SL73 12
+#define WL74 3
+#define SL74 13
+#define WL75 8
+#define SL75 14
+#define WL76 11
+#define SL76 11
+#define WL77 6
+#define SL77 8
+#define WL78 15
+#define SL78 5
+#define WL79 13
+#define SL79 6
+
+#define WR00 5
+#define SR00 8
+#define WR01 14
+#define SR01 9
+#define WR02 7
+#define SR02 9
+#define WR03 0
+#define SR03 11
+#define WR04 9
+#define SR04 13
+#define WR05 2
+#define SR05 15
+#define WR06 11
+#define SR06 15
+#define WR07 4
+#define SR07 5
+#define WR08 13
+#define SR08 7
+#define WR09 6
+#define SR09 7
+#define WR10 15
+#define SR10 8
+#define WR11 8
+#define SR11 11
+#define WR12 1
+#define SR12 14
+#define WR13 10
+#define SR13 14
+#define WR14 3
+#define SR14 12
+#define WR15 12
+#define SR15 6
+
+#define WR16 6
+#define SR16 9
+#define WR17 11
+#define SR17 13
+#define WR18 3
+#define SR18 15
+#define WR19 7
+#define SR19 7
+#define WR20 0
+#define SR20 12
+#define WR21 13
+#define SR21 8
+#define WR22 5
+#define SR22 9
+#define WR23 10
+#define SR23 11
+#define WR24 14
+#define SR24 7
+#define WR25 15
+#define SR25 7
+#define WR26 8
+#define SR26 12
+#define WR27 12
+#define SR27 7
+#define WR28 4
+#define SR28 6
+#define WR29 9
+#define SR29 15
+#define WR30 1
+#define SR30 13
+#define WR31 2
+#define SR31 11
+
+#define WR32 15
+#define SR32 9
+#define WR33 5
+#define SR33 7
+#define WR34 1
+#define SR34 15
+#define WR35 3
+#define SR35 11
+#define WR36 7
+#define SR36 8
+#define WR37 14
+#define SR37 6
+#define WR38 6
+#define SR38 6
+#define WR39 9
+#define SR39 14
+#define WR40 11
+#define SR40 12
+#define WR41 8
+#define SR41 13
+#define WR42 12
+#define SR42 5
+#define WR43 2
+#define SR43 14
+#define WR44 10
+#define SR44 13
+#define WR45 0
+#define SR45 13
+#define WR46 4
+#define SR46 7
+#define WR47 13
+#define SR47 5
+
+#define WR48 8
+#define SR48 15
+#define WR49 6
+#define SR49 5
+#define WR50 4
+#define SR50 8
+#define WR51 1
+#define SR51 11
+#define WR52 3
+#define SR52 14
+#define WR53 11
+#define SR53 14
+#define WR54 15
+#define SR54 6
+#define WR55 0
+#define SR55 14
+#define WR56 5
+#define SR56 6
+#define WR57 12
+#define SR57 9
+#define WR58 2
+#define SR58 12
+#define WR59 13
+#define SR59 9
+#define WR60 9
+#define SR60 12
+#define WR61 7
+#define SR61 5
+#define WR62 10
+#define SR62 15
+#define WR63 14
+#define SR63 8
+
+#define WR64 12
+#define SR64 8
+#define WR65 15
+#define SR65 5
+#define WR66 10
+#define SR66 12
+#define WR67 4
+#define SR67 9
+#define WR68 1
+#define SR68 12
+#define WR69 5
+#define SR69 5
+#define WR70 8
+#define SR70 14
+#define WR71 7
+#define SR71 6
+#define WR72 6
+#define SR72 8
+#define WR73 2
+#define SR73 13
+#define WR74 13
+#define SR74 6
+#define WR75 14
+#define SR75 5
+#define WR76 0
+#define SR76 15
+#define WR77 3
+#define SR77 13
+#define WR78 9
+#define SR78 11
+#define WR79 11
+#define SR79 11
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BN_INTERNAL_H */
diff --git a/decrepit/ripemd/ripemd.c b/decrepit/ripemd/ripemd.c
new file mode 100644
index 00000000..6ed7816c
--- /dev/null
+++ b/decrepit/ripemd/ripemd.c
@@ -0,0 +1,324 @@
+/* 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/ripemd.h>
+
+#include <string.h>
+
+#include "internal.h"
+
+
+int RIPEMD160_Init(RIPEMD160_CTX *ctx) {
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->h[0] = RIPEMD160_A;
+ ctx->h[1] = RIPEMD160_B;
+ ctx->h[2] = RIPEMD160_C;
+ ctx->h[3] = RIPEMD160_D;
+ ctx->h[4] = RIPEMD160_E;
+ return 1;
+}
+
+static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data,
+ size_t num) {
+ uint32_t A, B, C, D, E;
+ uint32_t a, b, c, d, e, l;
+ uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12,
+ XX13, XX14, XX15;
+#define X(i) XX##i
+
+ for (; num--;) {
+ A = h[0];
+ B = h[1];
+ C = h[2];
+ D = h[3];
+ E = h[4];
+
+ (void)HOST_c2l(data, l);
+ X(0) = l;
+ (void)HOST_c2l(data, l);
+ X(1) = l;
+ RIP1(A, B, C, D, E, WL00, SL00);
+ (void)HOST_c2l(data, l);
+ X(2) = l;
+ RIP1(E, A, B, C, D, WL01, SL01);
+ (void)HOST_c2l(data, l);
+ X(3) = l;
+ RIP1(D, E, A, B, C, WL02, SL02);
+ (void)HOST_c2l(data, l);
+ X(4) = l;
+ RIP1(C, D, E, A, B, WL03, SL03);
+ (void)HOST_c2l(data, l);
+ X(5) = l;
+ RIP1(B, C, D, E, A, WL04, SL04);
+ (void)HOST_c2l(data, l);
+ X(6) = l;
+ RIP1(A, B, C, D, E, WL05, SL05);
+ (void)HOST_c2l(data, l);
+ X(7) = l;
+ RIP1(E, A, B, C, D, WL06, SL06);
+ (void)HOST_c2l(data, l);
+ X(8) = l;
+ RIP1(D, E, A, B, C, WL07, SL07);
+ (void)HOST_c2l(data, l);
+ X(9) = l;
+ RIP1(C, D, E, A, B, WL08, SL08);
+ (void)HOST_c2l(data, l);
+ X(10) = l;
+ RIP1(B, C, D, E, A, WL09, SL09);
+ (void)HOST_c2l(data, l);
+ X(11) = l;
+ RIP1(A, B, C, D, E, WL10, SL10);
+ (void)HOST_c2l(data, l);
+ X(12) = l;
+ RIP1(E, A, B, C, D, WL11, SL11);
+ (void)HOST_c2l(data, l);
+ X(13) = l;
+ RIP1(D, E, A, B, C, WL12, SL12);
+ (void)HOST_c2l(data, l);
+ X(14) = l;
+ RIP1(C, D, E, A, B, WL13, SL13);
+ (void)HOST_c2l(data, l);
+ X(15) = l;
+ RIP1(B, C, D, E, A, WL14, SL14);
+ RIP1(A, B, C, D, E, WL15, SL15);
+
+ RIP2(E, A, B, C, D, WL16, SL16, KL1);
+ RIP2(D, E, A, B, C, WL17, SL17, KL1);
+ RIP2(C, D, E, A, B, WL18, SL18, KL1);
+ RIP2(B, C, D, E, A, WL19, SL19, KL1);
+ RIP2(A, B, C, D, E, WL20, SL20, KL1);
+ RIP2(E, A, B, C, D, WL21, SL21, KL1);
+ RIP2(D, E, A, B, C, WL22, SL22, KL1);
+ RIP2(C, D, E, A, B, WL23, SL23, KL1);
+ RIP2(B, C, D, E, A, WL24, SL24, KL1);
+ RIP2(A, B, C, D, E, WL25, SL25, KL1);
+ RIP2(E, A, B, C, D, WL26, SL26, KL1);
+ RIP2(D, E, A, B, C, WL27, SL27, KL1);
+ RIP2(C, D, E, A, B, WL28, SL28, KL1);
+ RIP2(B, C, D, E, A, WL29, SL29, KL1);
+ RIP2(A, B, C, D, E, WL30, SL30, KL1);
+ RIP2(E, A, B, C, D, WL31, SL31, KL1);
+
+ RIP3(D, E, A, B, C, WL32, SL32, KL2);
+ RIP3(C, D, E, A, B, WL33, SL33, KL2);
+ RIP3(B, C, D, E, A, WL34, SL34, KL2);
+ RIP3(A, B, C, D, E, WL35, SL35, KL2);
+ RIP3(E, A, B, C, D, WL36, SL36, KL2);
+ RIP3(D, E, A, B, C, WL37, SL37, KL2);
+ RIP3(C, D, E, A, B, WL38, SL38, KL2);
+ RIP3(B, C, D, E, A, WL39, SL39, KL2);
+ RIP3(A, B, C, D, E, WL40, SL40, KL2);
+ RIP3(E, A, B, C, D, WL41, SL41, KL2);
+ RIP3(D, E, A, B, C, WL42, SL42, KL2);
+ RIP3(C, D, E, A, B, WL43, SL43, KL2);
+ RIP3(B, C, D, E, A, WL44, SL44, KL2);
+ RIP3(A, B, C, D, E, WL45, SL45, KL2);
+ RIP3(E, A, B, C, D, WL46, SL46, KL2);
+ RIP3(D, E, A, B, C, WL47, SL47, KL2);
+
+ RIP4(C, D, E, A, B, WL48, SL48, KL3);
+ RIP4(B, C, D, E, A, WL49, SL49, KL3);
+ RIP4(A, B, C, D, E, WL50, SL50, KL3);
+ RIP4(E, A, B, C, D, WL51, SL51, KL3);
+ RIP4(D, E, A, B, C, WL52, SL52, KL3);
+ RIP4(C, D, E, A, B, WL53, SL53, KL3);
+ RIP4(B, C, D, E, A, WL54, SL54, KL3);
+ RIP4(A, B, C, D, E, WL55, SL55, KL3);
+ RIP4(E, A, B, C, D, WL56, SL56, KL3);
+ RIP4(D, E, A, B, C, WL57, SL57, KL3);
+ RIP4(C, D, E, A, B, WL58, SL58, KL3);
+ RIP4(B, C, D, E, A, WL59, SL59, KL3);
+ RIP4(A, B, C, D, E, WL60, SL60, KL3);
+ RIP4(E, A, B, C, D, WL61, SL61, KL3);
+ RIP4(D, E, A, B, C, WL62, SL62, KL3);
+ RIP4(C, D, E, A, B, WL63, SL63, KL3);
+
+ RIP5(B, C, D, E, A, WL64, SL64, KL4);
+ RIP5(A, B, C, D, E, WL65, SL65, KL4);
+ RIP5(E, A, B, C, D, WL66, SL66, KL4);
+ RIP5(D, E, A, B, C, WL67, SL67, KL4);
+ RIP5(C, D, E, A, B, WL68, SL68, KL4);
+ RIP5(B, C, D, E, A, WL69, SL69, KL4);
+ RIP5(A, B, C, D, E, WL70, SL70, KL4);
+ RIP5(E, A, B, C, D, WL71, SL71, KL4);
+ RIP5(D, E, A, B, C, WL72, SL72, KL4);
+ RIP5(C, D, E, A, B, WL73, SL73, KL4);
+ RIP5(B, C, D, E, A, WL74, SL74, KL4);
+ RIP5(A, B, C, D, E, WL75, SL75, KL4);
+ RIP5(E, A, B, C, D, WL76, SL76, KL4);
+ RIP5(D, E, A, B, C, WL77, SL77, KL4);
+ RIP5(C, D, E, A, B, WL78, SL78, KL4);
+ RIP5(B, C, D, E, A, WL79, SL79, KL4);
+
+ a = A;
+ b = B;
+ c = C;
+ d = D;
+ e = E;
+ /* Do other half */
+ A = h[0];
+ B = h[1];
+ C = h[2];
+ D = h[3];
+ E = h[4];
+
+ RIP5(A, B, C, D, E, WR00, SR00, KR0);
+ RIP5(E, A, B, C, D, WR01, SR01, KR0);
+ RIP5(D, E, A, B, C, WR02, SR02, KR0);
+ RIP5(C, D, E, A, B, WR03, SR03, KR0);
+ RIP5(B, C, D, E, A, WR04, SR04, KR0);
+ RIP5(A, B, C, D, E, WR05, SR05, KR0);
+ RIP5(E, A, B, C, D, WR06, SR06, KR0);
+ RIP5(D, E, A, B, C, WR07, SR07, KR0);
+ RIP5(C, D, E, A, B, WR08, SR08, KR0);
+ RIP5(B, C, D, E, A, WR09, SR09, KR0);
+ RIP5(A, B, C, D, E, WR10, SR10, KR0);
+ RIP5(E, A, B, C, D, WR11, SR11, KR0);
+ RIP5(D, E, A, B, C, WR12, SR12, KR0);
+ RIP5(C, D, E, A, B, WR13, SR13, KR0);
+ RIP5(B, C, D, E, A, WR14, SR14, KR0);
+ RIP5(A, B, C, D, E, WR15, SR15, KR0);
+
+ RIP4(E, A, B, C, D, WR16, SR16, KR1);
+ RIP4(D, E, A, B, C, WR17, SR17, KR1);
+ RIP4(C, D, E, A, B, WR18, SR18, KR1);
+ RIP4(B, C, D, E, A, WR19, SR19, KR1);
+ RIP4(A, B, C, D, E, WR20, SR20, KR1);
+ RIP4(E, A, B, C, D, WR21, SR21, KR1);
+ RIP4(D, E, A, B, C, WR22, SR22, KR1);
+ RIP4(C, D, E, A, B, WR23, SR23, KR1);
+ RIP4(B, C, D, E, A, WR24, SR24, KR1);
+ RIP4(A, B, C, D, E, WR25, SR25, KR1);
+ RIP4(E, A, B, C, D, WR26, SR26, KR1);
+ RIP4(D, E, A, B, C, WR27, SR27, KR1);
+ RIP4(C, D, E, A, B, WR28, SR28, KR1);
+ RIP4(B, C, D, E, A, WR29, SR29, KR1);
+ RIP4(A, B, C, D, E, WR30, SR30, KR1);
+ RIP4(E, A, B, C, D, WR31, SR31, KR1);
+
+ RIP3(D, E, A, B, C, WR32, SR32, KR2);
+ RIP3(C, D, E, A, B, WR33, SR33, KR2);
+ RIP3(B, C, D, E, A, WR34, SR34, KR2);
+ RIP3(A, B, C, D, E, WR35, SR35, KR2);
+ RIP3(E, A, B, C, D, WR36, SR36, KR2);
+ RIP3(D, E, A, B, C, WR37, SR37, KR2);
+ RIP3(C, D, E, A, B, WR38, SR38, KR2);
+ RIP3(B, C, D, E, A, WR39, SR39, KR2);
+ RIP3(A, B, C, D, E, WR40, SR40, KR2);
+ RIP3(E, A, B, C, D, WR41, SR41, KR2);
+ RIP3(D, E, A, B, C, WR42, SR42, KR2);
+ RIP3(C, D, E, A, B, WR43, SR43, KR2);
+ RIP3(B, C, D, E, A, WR44, SR44, KR2);
+ RIP3(A, B, C, D, E, WR45, SR45, KR2);
+ RIP3(E, A, B, C, D, WR46, SR46, KR2);
+ RIP3(D, E, A, B, C, WR47, SR47, KR2);
+
+ RIP2(C, D, E, A, B, WR48, SR48, KR3);
+ RIP2(B, C, D, E, A, WR49, SR49, KR3);
+ RIP2(A, B, C, D, E, WR50, SR50, KR3);
+ RIP2(E, A, B, C, D, WR51, SR51, KR3);
+ RIP2(D, E, A, B, C, WR52, SR52, KR3);
+ RIP2(C, D, E, A, B, WR53, SR53, KR3);
+ RIP2(B, C, D, E, A, WR54, SR54, KR3);
+ RIP2(A, B, C, D, E, WR55, SR55, KR3);
+ RIP2(E, A, B, C, D, WR56, SR56, KR3);
+ RIP2(D, E, A, B, C, WR57, SR57, KR3);
+ RIP2(C, D, E, A, B, WR58, SR58, KR3);
+ RIP2(B, C, D, E, A, WR59, SR59, KR3);
+ RIP2(A, B, C, D, E, WR60, SR60, KR3);
+ RIP2(E, A, B, C, D, WR61, SR61, KR3);
+ RIP2(D, E, A, B, C, WR62, SR62, KR3);
+ RIP2(C, D, E, A, B, WR63, SR63, KR3);
+
+ RIP1(B, C, D, E, A, WR64, SR64);
+ RIP1(A, B, C, D, E, WR65, SR65);
+ RIP1(E, A, B, C, D, WR66, SR66);
+ RIP1(D, E, A, B, C, WR67, SR67);
+ RIP1(C, D, E, A, B, WR68, SR68);
+ RIP1(B, C, D, E, A, WR69, SR69);
+ RIP1(A, B, C, D, E, WR70, SR70);
+ RIP1(E, A, B, C, D, WR71, SR71);
+ RIP1(D, E, A, B, C, WR72, SR72);
+ RIP1(C, D, E, A, B, WR73, SR73);
+ RIP1(B, C, D, E, A, WR74, SR74);
+ RIP1(A, B, C, D, E, WR75, SR75);
+ RIP1(E, A, B, C, D, WR76, SR76);
+ RIP1(D, E, A, B, C, WR77, SR77);
+ RIP1(C, D, E, A, B, WR78, SR78);
+ RIP1(B, C, D, E, A, WR79, SR79);
+
+ D = h[1] + c + D;
+ h[1] = h[2] + d + E;
+ h[2] = h[3] + e + A;
+ h[3] = h[4] + a + B;
+ h[4] = h[0] + b + C;
+ h[0] = D;
+ }
+
+#undef X
+}
+
+uint8_t *RIPEMD160(const uint8_t *data, size_t len, unsigned char *out) {
+ RIPEMD160_CTX ctx;
+
+ if (!RIPEMD160_Init(&ctx)) {
+ return NULL;
+ }
+
+ RIPEMD160_Update(&ctx, data, len);
+ RIPEMD160_Final(out, &ctx);
+ return out;
+}
diff --git a/decrepit/ripemd/ripemd_test.cc b/decrepit/ripemd/ripemd_test.cc
new file mode 100644
index 00000000..ebcabdfb
--- /dev/null
+++ b/decrepit/ripemd/ripemd_test.cc
@@ -0,0 +1,119 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ripemd.h>
+
+#include <memory>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../../crypto/test/test_util.h"
+
+
+struct RIPEMDTestCase {
+ const char *input;
+ uint8_t expected[RIPEMD160_DIGEST_LENGTH];
+};
+
+static const RIPEMDTestCase kRIPEMDTestCases[] = {
+ {"", {0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
+ 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31}},
+ {"a", {0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
+ 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe}},
+ {"abc", {0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
+ 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc}},
+ {"message digest",
+ {0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
+ 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36}},
+ {"abcdefghijklmnopqrstuvwxyz",
+ {0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
+ 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc}},
+ {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ {0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
+ 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b}},
+ {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ {0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,
+ 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89}},
+ {"1234567890123456789012345678901234567890123456789012345678901234567890123"
+ "4567890",
+ {0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,
+ 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb}},
+};
+
+int main(void) {
+ unsigned test_num = 0;
+ int ok = 1;
+
+ for (const auto &test : kRIPEMDTestCases) {
+ test_num++;
+
+ const size_t input_len = strlen(test.input);
+
+ for (size_t stride = 0; stride <= input_len; stride++) {
+ uint8_t digest[RIPEMD160_DIGEST_LENGTH];
+
+ if (stride == 0) {
+ RIPEMD160(reinterpret_cast<const uint8_t *>(test.input), input_len,
+ digest);
+ } else {
+ RIPEMD160_CTX ctx;
+ RIPEMD160_Init(&ctx);
+
+ for (size_t done = 0; done < input_len;) {
+ const size_t remaining = input_len - done;
+ size_t todo = stride;
+ if (todo > remaining) {
+ todo = remaining;
+ }
+
+ RIPEMD160_Update(&ctx, &test.input[done], todo);
+ done += todo;
+ }
+
+ RIPEMD160_Final(digest, &ctx);
+ }
+
+ if (memcmp(digest, test.expected, sizeof(digest)) != 0) {
+ fprintf(stderr, "#%u: bad result with stride %u: ", test_num,
+ static_cast<unsigned>(stride));
+ hexdump(stderr, "", digest, sizeof(digest));
+ ok = 0;
+ }
+ }
+ }
+
+ static const size_t kLargeBufSize = 1000000;
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[kLargeBufSize]);
+ memset(buf.get(), 'a', kLargeBufSize);
+ uint8_t digest[RIPEMD160_DIGEST_LENGTH];
+ RIPEMD160(buf.get(), kLargeBufSize, digest);
+
+ static const uint8_t kMillionADigest[RIPEMD160_DIGEST_LENGTH] = {
+ 0x52, 0x78, 0x32, 0x43, 0xc1, 0x69, 0x7b, 0xdb, 0xe1, 0x6d,
+ 0x37, 0xf9, 0x7f, 0x68, 0xf0, 0x83, 0x25, 0xdc, 0x15, 0x28};
+
+ if (memcmp(digest, kMillionADigest, sizeof(digest)) != 0) {
+ fprintf(stderr, "Digest incorrect for “million a's” test: ");
+ hexdump(stderr, "", digest, sizeof(digest));
+ ok = 0;
+ }
+
+ if (!ok) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/decrepit/rsa/rsa_decrepit.c b/decrepit/rsa/rsa_decrepit.c
index c238f468..0d7c5f66 100644
--- a/decrepit/rsa/rsa_decrepit.c
+++ b/decrepit/rsa/rsa_decrepit.c
@@ -84,3 +84,20 @@ err:
RSA_free(rsa);
return NULL;
}
+
+int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM, const uint8_t *mHash,
+ const EVP_MD *Hash, int sLen) {
+ return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
+}
+
+int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, const EVP_MD *Hash,
+ const uint8_t *EM, int sLen) {
+ 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) {
+ return RSA_padding_add_PKCS1_OAEP_mgf1(to, to_len, from, from_len, param,
+ param_len, NULL, NULL);
+}
diff --git a/decrepit/ssl/CMakeLists.txt b/decrepit/ssl/CMakeLists.txt
new file mode 100644
index 00000000..fba0234d
--- /dev/null
+++ b/decrepit/ssl/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+ ssl_decrepit
+
+ OBJECT
+
+ ssl_decrepit.c
+)
diff --git a/decrepit/ssl/ssl_decrepit.c b/decrepit/ssl/ssl_decrepit.c
new file mode 100644
index 00000000..e25cbf31
--- /dev/null
+++ b/decrepit/ssl/ssl_decrepit.c
@@ -0,0 +1,225 @@
+/* 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.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 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
+ * openssl-core@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/ssl.h>
+
+#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_PNACL)
+
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+typedef struct {
+ DIR *dir;
+ struct dirent dirent;
+} OPENSSL_DIR_CTX;
+
+static const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx,
+ const char *directory) {
+ struct dirent *dirent;
+
+ if (ctx == NULL || directory == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ errno = 0;
+ if (*ctx == NULL) {
+ *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
+ if (*ctx == NULL) {
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
+
+ (*ctx)->dir = opendir(directory);
+ if ((*ctx)->dir == NULL) {
+ int save_errno = errno; /* Probably not needed, but I'm paranoid */
+ free(*ctx);
+ *ctx = NULL;
+ errno = save_errno;
+ return 0;
+ }
+ }
+
+ if (readdir_r((*ctx)->dir, &(*ctx)->dirent, &dirent) != 0 ||
+ dirent == NULL) {
+ return 0;
+ }
+
+ return (*ctx)->dirent.d_name;
+}
+
+static int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
+ if (ctx != NULL && *ctx != NULL) {
+ int r = closedir((*ctx)->dir);
+ free(*ctx);
+ *ctx = NULL;
+ return r == 0;
+ }
+
+ errno = EINVAL;
+ return 0;
+}
+
+
+/* Add a directory of certs to a stack.
+ *
+ * \param stack the stack to append to.
+ * \param dir the directory to append from. All files in this directory will be
+ * examined as potential certs. Any that are acceptable to
+ * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will
+ * be included.
+ * \return 1 for success, 0 for failure. Note that in the case of failure some
+ * certs may have been added to \c stack. */
+int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+ const char *dir) {
+ OPENSSL_DIR_CTX *d = NULL;
+ const char *filename;
+ int ret = 0;
+
+ /* Note that a side effect is that the CAs will be sorted by name */
+ while ((filename = OPENSSL_DIR_read(&d, dir))) {
+ char buf[1024];
+ int r;
+
+ if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PATH_TOO_LONG);
+ goto err;
+ }
+
+ r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename);
+ if (r <= 0 || r >= (int)sizeof(buf) ||
+ !SSL_add_file_cert_subjects_to_stack(stack, buf)) {
+ goto err;
+ }
+ }
+
+ if (errno) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
+ ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ if (d) {
+ OPENSSL_DIR_end(&d);
+ }
+ return ret;
+}
+
+#endif /* !WINDOWS && !PNACL */
diff --git a/decrepit/x509/CMakeLists.txt b/decrepit/x509/CMakeLists.txt
new file mode 100644
index 00000000..930912d1
--- /dev/null
+++ b/decrepit/x509/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+ x509_decrepit
+
+ OBJECT
+
+ x509_decrepit.c
+)
diff --git a/decrepit/x509/x509_decrepit.c b/decrepit/x509/x509_decrepit.c
new file mode 100644
index 00000000..5714b40a
--- /dev/null
+++ b/decrepit/x509/x509_decrepit.c
@@ -0,0 +1,42 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+
+
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
+ X509V3_CTX *ctx, int ext_nid, char *value) {
+ CONF *nconf = NULL;
+ LHASH_OF(CONF_VALUE) *orig_data = NULL;
+
+ if (conf != NULL) {
+ nconf = NCONF_new(NULL /* no method */);
+ if (nconf == NULL) {
+ return NULL;
+ }
+
+ orig_data = nconf->data;
+ nconf->data = conf;
+ }
+
+ X509_EXTENSION *ret = X509V3_EXT_nconf_nid(nconf, ctx, ext_nid, value);
+
+ if (nconf != NULL) {
+ nconf->data = orig_data;
+ NCONF_free(nconf);
+ }
+
+ return ret;
+}
diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt
index 0453e7c5..5bef3ae9 100644
--- a/fuzz/CMakeLists.txt
+++ b/fuzz/CMakeLists.txt
@@ -19,6 +19,24 @@ target_link_libraries(cert Fuzzer)
target_link_libraries(cert crypto)
add_executable(
+ spki
+
+ spki.cc
+)
+
+target_link_libraries(spki Fuzzer)
+target_link_libraries(spki crypto)
+
+add_executable(
+ pkcs8
+
+ pkcs8.cc
+)
+
+target_link_libraries(pkcs8 Fuzzer)
+target_link_libraries(pkcs8 crypto)
+
+add_executable(
server
server.cc
@@ -37,3 +55,12 @@ add_executable(
target_link_libraries(client Fuzzer)
target_link_libraries(client crypto)
target_link_libraries(client ssl)
+
+add_executable(
+ read_pem
+
+ read_pem.cc
+)
+
+target_link_libraries(read_pem Fuzzer)
+target_link_libraries(read_pem crypto)
diff --git a/fuzz/cert.cc b/fuzz/cert.cc
index 4078c0ec..b8815a5a 100644
--- a/fuzz/cert.cc
+++ b/fuzz/cert.cc
@@ -1,11 +1,31 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/mem.h>
#include <openssl/x509.h>
extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
const uint8_t *bufp = buf;
X509 *x509 = d2i_X509(NULL, &bufp, len);
if (x509 != NULL) {
- /* Also extract the public key. */
+ /* Extract the public key. */
EVP_PKEY_free(X509_get_pubkey(x509));
+
+ /* Reserialize the structure. */
+ uint8_t *der = NULL;
+ i2d_X509(x509, &der);
+ OPENSSL_free(der);
}
X509_free(x509);
return 0;
diff --git a/fuzz/cert_corpus/003c6f57b1e485b75bdb524b7c141350a2f86ec2 b/fuzz/cert_corpus/003c6f57b1e485b75bdb524b7c141350a2f86ec2
deleted file mode 100644
index d6d19d12..00000000
--- a/fuzz/cert_corpus/003c6f57b1e485b75bdb524b7c141350a2f86ec2
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/00591f1dde4cf571e013dcd11f40e2944cfc8715 b/fuzz/cert_corpus/00591f1dde4cf571e013dcd11f40e2944cfc8715
deleted file mode 100644
index eefab745..00000000
--- a/fuzz/cert_corpus/00591f1dde4cf571e013dcd11f40e2944cfc8715
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be b/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be
new file mode 100644
index 00000000..25e3980a
--- /dev/null
+++ b/fuzz/cert_corpus/00c85e80891f1b88e11ee5a2502e0f682f0e60be
Binary files differ
diff --git a/fuzz/cert_corpus/01705fb53f7cc35f64e5796c78dad8abc6cf25ce b/fuzz/cert_corpus/01705fb53f7cc35f64e5796c78dad8abc6cf25ce
deleted file mode 100644
index b7da84ee..00000000
--- a/fuzz/cert_corpus/01705fb53f7cc35f64e5796c78dad8abc6cf25ce
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f b/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f
new file mode 100644
index 00000000..ed974654
--- /dev/null
+++ b/fuzz/cert_corpus/02e0dfed35539f2a8fe487237de3cf6ba4ebb54f
Binary files differ
diff --git a/fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408 b/fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408
new file mode 100644
index 00000000..3073da2c
--- /dev/null
+++ b/fuzz/cert_corpus/039d65de40da4745433e149f9fb5ae66f8c90408
Binary files differ
diff --git a/fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fde b/fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fde
new file mode 100644
index 00000000..132c9243
--- /dev/null
+++ b/fuzz/cert_corpus/03b547e325434d1454dfdd34d4819f5b1e234fde
Binary files differ
diff --git a/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41 b/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41
new file mode 100644
index 00000000..2e749572
--- /dev/null
+++ b/fuzz/cert_corpus/054cb963aaf9b554874b32275f44520641a11d41
Binary files differ
diff --git a/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3 b/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3
new file mode 100644
index 00000000..bce3ec11
--- /dev/null
+++ b/fuzz/cert_corpus/08464c9f40426e219bdd673525af22a89b62c4d3
Binary files differ
diff --git a/fuzz/cert_corpus/0853174f70d58b195813fbdc716c1a4f4b227ed2 b/fuzz/cert_corpus/0853174f70d58b195813fbdc716c1a4f4b227ed2
deleted file mode 100644
index 2b1aea28..00000000
--- a/fuzz/cert_corpus/0853174f70d58b195813fbdc716c1a4f4b227ed2
+++ /dev/null
@@ -1 +0,0 @@
-00(;1hA0 \ No newline at end of file
diff --git a/fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704 b/fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704
new file mode 100644
index 00000000..877a49b5
--- /dev/null
+++ b/fuzz/cert_corpus/09406b74a5fd8ad9a82052a835c24dc3194d9704
Binary files differ
diff --git a/fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144 b/fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144
new file mode 100644
index 00000000..44d087c0
--- /dev/null
+++ b/fuzz/cert_corpus/095554da7da9b4234670b7f47cf9663c9c60c144
Binary files differ
diff --git a/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5 b/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5
new file mode 100644
index 00000000..902db253
--- /dev/null
+++ b/fuzz/cert_corpus/0969cd6815249cf0c66b302b20e71ef677b1c3e5
Binary files differ
diff --git a/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e b/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e
new file mode 100644
index 00000000..220384f7
--- /dev/null
+++ b/fuzz/cert_corpus/0ba8e2a62b579b857e560bf1201fad463318c73e
Binary files differ
diff --git a/fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627 b/fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627
new file mode 100644
index 00000000..c063caef
--- /dev/null
+++ b/fuzz/cert_corpus/0bacf5f9ce89ed83a29bf8b01109f1ebd5b1a627
Binary files differ
diff --git a/fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59 b/fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59
new file mode 100644
index 00000000..2fea51cc
--- /dev/null
+++ b/fuzz/cert_corpus/0be05d072f2f3828875fdfc55b04ff0f0ae9fc59
Binary files differ
diff --git a/fuzz/cert_corpus/0d538ac33c112193da6c78e9039027f3325e9990 b/fuzz/cert_corpus/0d538ac33c112193da6c78e9039027f3325e9990
deleted file mode 100644
index 0f38c6f8..00000000
--- a/fuzz/cert_corpus/0d538ac33c112193da6c78e9039027f3325e9990
+++ /dev/null
@@ -1 +0,0 @@
-0 \ No newline at end of file
diff --git a/fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3c b/fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3c
new file mode 100644
index 00000000..74a03643
--- /dev/null
+++ b/fuzz/cert_corpus/0d8ec36263c4e32e25e4ef1f01baed35b6227d3c
Binary files differ
diff --git a/fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f b/fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f
new file mode 100644
index 00000000..d1650249
--- /dev/null
+++ b/fuzz/cert_corpus/0db7a0d1afb99cd01fafa18b2961c6623f5b1d8f
Binary files differ
diff --git a/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de b/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de
new file mode 100644
index 00000000..266f737e
--- /dev/null
+++ b/fuzz/cert_corpus/0e29ba7cbd357efa6d2619ea98ef275e0b13a1de
Binary files differ
diff --git a/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad b/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad
new file mode 100644
index 00000000..3b2ca66c
--- /dev/null
+++ b/fuzz/cert_corpus/0fa9626b934e330a7cc18c118e31aad5639f2dad
Binary files differ
diff --git a/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1 b/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1
new file mode 100644
index 00000000..a342e7e4
--- /dev/null
+++ b/fuzz/cert_corpus/0ff9646573d3cbb8cfad86755ff52cad4788fcb1
Binary files differ
diff --git a/fuzz/cert_corpus/11cf2fd91b0edc11a509859032ebbfe89675c0c4 b/fuzz/cert_corpus/11cf2fd91b0edc11a509859032ebbfe89675c0c4
deleted file mode 100644
index 065d35be..00000000
--- a/fuzz/cert_corpus/11cf2fd91b0edc11a509859032ebbfe89675c0c4
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/1233d3b329be1220bff82db29a9497a7000e4b33 b/fuzz/cert_corpus/1233d3b329be1220bff82db29a9497a7000e4b33
deleted file mode 100644
index 587b264f..00000000
--- a/fuzz/cert_corpus/1233d3b329be1220bff82db29a9497a7000e4b33
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92 b/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92
new file mode 100644
index 00000000..dab73403
--- /dev/null
+++ b/fuzz/cert_corpus/1288e7bc9178d23aa6662dc5348b8010e6b4ec92
Binary files differ
diff --git a/fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900 b/fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900
new file mode 100644
index 00000000..63be22dc
--- /dev/null
+++ b/fuzz/cert_corpus/1293428367413052338e0b8b9e2660fea076f900
Binary files differ
diff --git a/fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bc b/fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bc
new file mode 100644
index 00000000..64b57dfe
--- /dev/null
+++ b/fuzz/cert_corpus/1400c7baa454c64e5e1bc6454bfbef3700c881bc
Binary files differ
diff --git a/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb b/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb
new file mode 100644
index 00000000..d435368e
--- /dev/null
+++ b/fuzz/cert_corpus/159cc124352f0c0ac1cef2399c5c25614e29c6eb
Binary files differ
diff --git a/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac b/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac
new file mode 100644
index 00000000..4e5cc3b3
--- /dev/null
+++ b/fuzz/cert_corpus/15c89fc35e674fcd2fca3563669cc3c02db164ac
Binary files differ
diff --git a/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a b/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a
new file mode 100644
index 00000000..df739fc0
--- /dev/null
+++ b/fuzz/cert_corpus/163fd7d62de6042f6353f383cdc0b700e0980f8a
Binary files differ
diff --git a/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938 b/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938
new file mode 100644
index 00000000..4595890a
--- /dev/null
+++ b/fuzz/cert_corpus/173db5dac0923eaaf0516593ec62ff48d07aa938
Binary files differ
diff --git a/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90 b/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90
new file mode 100644
index 00000000..21662148
--- /dev/null
+++ b/fuzz/cert_corpus/183c776a51a73466cf9f32b5d22f05cf1348fa90
Binary files differ
diff --git a/fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94e b/fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94e
new file mode 100644
index 00000000..2005ec54
--- /dev/null
+++ b/fuzz/cert_corpus/1894a7ef9741425a741189996181a7b85773a94e
Binary files differ
diff --git a/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea b/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea
new file mode 100644
index 00000000..1c50fb0d
--- /dev/null
+++ b/fuzz/cert_corpus/1950704c247d49ee53fde32fcdff958b44bdd2ea
Binary files differ
diff --git a/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7 b/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7
new file mode 100644
index 00000000..fe6520c7
--- /dev/null
+++ b/fuzz/cert_corpus/19a0a17b14c3a849d626f6b61219959343a575d7
Binary files differ
diff --git a/fuzz/cert_corpus/1a1cb7c7bc8bbd96a752a6dde3129a9839a0a56d b/fuzz/cert_corpus/1a1cb7c7bc8bbd96a752a6dde3129a9839a0a56d
deleted file mode 100644
index a8978874..00000000
--- a/fuzz/cert_corpus/1a1cb7c7bc8bbd96a752a6dde3129a9839a0a56d
+++ /dev/null
@@ -1 +0,0 @@
-00h)1h|%0 \ No newline at end of file
diff --git a/fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875 b/fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875
new file mode 100644
index 00000000..310216fb
--- /dev/null
+++ b/fuzz/cert_corpus/1a6654c8844f6eb41d34508e4330111cc14a4875
Binary files differ
diff --git a/fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8 b/fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8
new file mode 100644
index 00000000..b52e4ddf
--- /dev/null
+++ b/fuzz/cert_corpus/1b4aac6123267d5f6258899bb6ccd01747a87ba8
Binary files differ
diff --git a/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7 b/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7
new file mode 100644
index 00000000..362abb37
--- /dev/null
+++ b/fuzz/cert_corpus/1ba101e147f4453f2c709c037ae506cd79b6d7c7
Binary files differ
diff --git a/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2 b/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2
new file mode 100644
index 00000000..8b0fbf38
--- /dev/null
+++ b/fuzz/cert_corpus/1ced169e5e3c017b015637eeb88afcd7d48bafc2
@@ -0,0 +1 @@
+00(00h1hA!1h|0%0  *000 \ No newline at end of file
diff --git a/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0 b/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0
new file mode 100644
index 00000000..88e4e80f
--- /dev/null
+++ b/fuzz/cert_corpus/1d61ed4eb67ed64942174bea48a77523a805a3e0
Binary files differ
diff --git a/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575 b/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575
new file mode 100644
index 00000000..27a2a39a
--- /dev/null
+++ b/fuzz/cert_corpus/1d6b1f58a8be854b7667c019b5c470f3d325d575
Binary files differ
diff --git a/fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01 b/fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01
new file mode 100644
index 00000000..79023b11
--- /dev/null
+++ b/fuzz/cert_corpus/1d752734c8ecb0ffb7d98801159f9cfbd97e0d01
Binary files differ
diff --git a/fuzz/cert_corpus/1dc3882d4bcccb325751803b817489c3715db4cc b/fuzz/cert_corpus/1dc3882d4bcccb325751803b817489c3715db4cc
deleted file mode 100644
index 6d0b7ebd..00000000
--- a/fuzz/cert_corpus/1dc3882d4bcccb325751803b817489c3715db4cc
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/fuzz/cert_corpus/1e177827da539595862d41ee1f470e3654a77d04 b/fuzz/cert_corpus/1e177827da539595862d41ee1f470e3654a77d04
deleted file mode 100644
index 8972c28f..00000000
--- a/fuzz/cert_corpus/1e177827da539595862d41ee1f470e3654a77d04
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/208db41327b2152bd0b3cdb3392358dcc72951f8 b/fuzz/cert_corpus/208db41327b2152bd0b3cdb3392358dcc72951f8
deleted file mode 100644
index efb4f9bc..00000000
--- a/fuzz/cert_corpus/208db41327b2152bd0b3cdb3392358dcc72951f8
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca b/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca
new file mode 100644
index 00000000..51396035
--- /dev/null
+++ b/fuzz/cert_corpus/2172996f7233ccd5607b6414058e64ac7c9bcdca
Binary files differ
diff --git a/fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189 b/fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189
new file mode 100644
index 00000000..731b90c4
--- /dev/null
+++ b/fuzz/cert_corpus/2199b815cfe8b39732b8eb2847f6b5008a75d189
Binary files differ
diff --git a/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132 b/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132
new file mode 100644
index 00000000..532aae11
--- /dev/null
+++ b/fuzz/cert_corpus/21a4835c0fe0b0a69bab262724f6356f7c008132
Binary files differ
diff --git a/fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304 b/fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304
new file mode 100644
index 00000000..61cdabad
--- /dev/null
+++ b/fuzz/cert_corpus/2357c3ad0b6adfa54a5fe88b7f99b1c21416d304
Binary files differ
diff --git a/fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02 b/fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02
new file mode 100644
index 00000000..39e6d6be
--- /dev/null
+++ b/fuzz/cert_corpus/23da98cdc1af6ef01ca8fad38ac021910832fe02
Binary files differ
diff --git a/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed b/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed
new file mode 100644
index 00000000..4b58072a
--- /dev/null
+++ b/fuzz/cert_corpus/245c09cd01ac5a3a74dc5c2c2d11921978ebc4ed
Binary files differ
diff --git a/fuzz/cert_corpus/2569acd835ecb6dfd61f6ce4459ba5f94df685a9 b/fuzz/cert_corpus/2569acd835ecb6dfd61f6ce4459ba5f94df685a9
deleted file mode 100644
index 62442ace..00000000
--- a/fuzz/cert_corpus/2569acd835ecb6dfd61f6ce4459ba5f94df685a9
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69e b/fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69e
new file mode 100644
index 00000000..318611cc
--- /dev/null
+++ b/fuzz/cert_corpus/25e586f9292916959c71561431fecfc188dcf69e
Binary files differ
diff --git a/fuzz/cert_corpus/266bb871295b34d3bf47110dd8d6c69de7733db0 b/fuzz/cert_corpus/266bb871295b34d3bf47110dd8d6c69de7733db0
deleted file mode 100644
index 87ebdebd..00000000
--- a/fuzz/cert_corpus/266bb871295b34d3bf47110dd8d6c69de7733db0
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4 b/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4
new file mode 100644
index 00000000..f3bdb763
--- /dev/null
+++ b/fuzz/cert_corpus/272ed7d95717a523c65e5cbf1849f89041cb58a4
Binary files differ
diff --git a/fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1 b/fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1
new file mode 100644
index 00000000..750eb09d
--- /dev/null
+++ b/fuzz/cert_corpus/277042c5f5018c9e4ead5db206baf143f0a1a9a1
Binary files differ
diff --git a/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4 b/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4
new file mode 100644
index 00000000..24181ca6
--- /dev/null
+++ b/fuzz/cert_corpus/29164dbd53e8108c324376573091e4c4213d5bf4
Binary files differ
diff --git a/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8 b/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8
new file mode 100644
index 00000000..dcd4a2c4
--- /dev/null
+++ b/fuzz/cert_corpus/29e05bbfa0e8cb0a9b3bd679b0572bf5229c26c8
Binary files differ
diff --git a/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1 b/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1
new file mode 100644
index 00000000..51a8f090
--- /dev/null
+++ b/fuzz/cert_corpus/29f8bb7ef38d13bff66e3c52ba2f20376731c2c1
Binary files differ
diff --git a/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8 b/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8
new file mode 100644
index 00000000..3553e97f
--- /dev/null
+++ b/fuzz/cert_corpus/2a0d8199c1117a1cee556ce8e13fdce6c00529f8
Binary files differ
diff --git a/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2 b/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2
new file mode 100644
index 00000000..01423b80
--- /dev/null
+++ b/fuzz/cert_corpus/2ab7a88a553b5b82b4346b4ed2abb832bf9ac6c2
Binary files differ
diff --git a/fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f0 b/fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f0
new file mode 100644
index 00000000..6a7b6527
--- /dev/null
+++ b/fuzz/cert_corpus/2adda7db83a6e20697612ee835c58415072899f0
@@ -0,0 +1 @@
+Ȇ!: \ No newline at end of file
diff --git a/fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571 b/fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571
new file mode 100644
index 00000000..02e39153
--- /dev/null
+++ b/fuzz/cert_corpus/2c3743ad90044cc189240b7874e6e4df3ce69571
Binary files differ
diff --git a/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79 b/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79
new file mode 100644
index 00000000..21d883a6
--- /dev/null
+++ b/fuzz/cert_corpus/2cd91be7451b6016cee440fb86e06c7afd157e79
Binary files differ
diff --git a/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1 b/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1
new file mode 100644
index 00000000..b941ede8
--- /dev/null
+++ b/fuzz/cert_corpus/2d0c5affedc4d6a45b59a45abd71cf4b59efb5f1
Binary files differ
diff --git a/fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879 b/fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879
new file mode 100644
index 00000000..63777aa2
--- /dev/null
+++ b/fuzz/cert_corpus/2e1f157c8c157903e5e862dcb34fb3b7be376879
Binary files differ
diff --git a/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436 b/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436
new file mode 100644
index 00000000..229d9e1b
--- /dev/null
+++ b/fuzz/cert_corpus/2e375a900fedc57b49326e77554e6550fdc1e436
Binary files differ
diff --git a/fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42 b/fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42
new file mode 100644
index 00000000..15e70080
--- /dev/null
+++ b/fuzz/cert_corpus/2ef6c305d2b8478403c470bfc09807d3cfedcd42
Binary files differ
diff --git a/fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572 b/fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572
new file mode 100644
index 00000000..caea8d8b
--- /dev/null
+++ b/fuzz/cert_corpus/301c5e78f8b0334ee078e8e89eba2d9ea545d572
Binary files differ
diff --git a/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad b/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad
new file mode 100644
index 00000000..ccb22758
--- /dev/null
+++ b/fuzz/cert_corpus/301f44ea637ab6dbc97d15ace5a3250215c999ad
Binary files differ
diff --git a/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b b/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b
new file mode 100644
index 00000000..15d763e7
--- /dev/null
+++ b/fuzz/cert_corpus/312cbcea0df790d023073e9dc5de165190f86b5b
Binary files differ
diff --git a/fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1 b/fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1
new file mode 100644
index 00000000..6bcd137c
--- /dev/null
+++ b/fuzz/cert_corpus/31dad1d547e55649e2ca06f479081d5418d212b1
Binary files differ
diff --git a/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b b/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b
new file mode 100644
index 00000000..550f4c90
--- /dev/null
+++ b/fuzz/cert_corpus/3256b480f1212007bcb0e53ef124ead78ec30b9b
Binary files differ
diff --git a/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd b/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd
new file mode 100644
index 00000000..de773a6b
--- /dev/null
+++ b/fuzz/cert_corpus/340cd6562eb74d264b8a8123b49fc3babb6033bd
Binary files differ
diff --git a/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06 b/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06
new file mode 100644
index 00000000..0c30057b
--- /dev/null
+++ b/fuzz/cert_corpus/3607fbd5d18f5f196e2ad467b39c31d80c136f06
Binary files differ
diff --git a/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91 b/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91
new file mode 100644
index 00000000..16dbc90c
--- /dev/null
+++ b/fuzz/cert_corpus/360e330b02ff481851b528cdb2fdc952d21afa91
Binary files differ
diff --git a/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9 b/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9
new file mode 100644
index 00000000..07673247
--- /dev/null
+++ b/fuzz/cert_corpus/3666ba893cec5a069376d0b91532ab4317b720a9
Binary files differ
diff --git a/fuzz/cert_corpus/36827665da414f5d36db7850ae76975eb7d616e9 b/fuzz/cert_corpus/36827665da414f5d36db7850ae76975eb7d616e9
deleted file mode 100644
index a09315ad..00000000
--- a/fuzz/cert_corpus/36827665da414f5d36db7850ae76975eb7d616e9
+++ /dev/null
@@ -1 +0,0 @@
-(; \ No newline at end of file
diff --git a/fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17f b/fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17f
new file mode 100644
index 00000000..ac2a24f5
--- /dev/null
+++ b/fuzz/cert_corpus/370522e931da2c14602da88ac1a9b781f0d7a17f
Binary files differ
diff --git a/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0 b/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0
new file mode 100644
index 00000000..8fa5ff7f
--- /dev/null
+++ b/fuzz/cert_corpus/375a68f804031aaaf103a54625036bf419656cb0
Binary files differ
diff --git a/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7 b/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7
new file mode 100644
index 00000000..03d905b8
--- /dev/null
+++ b/fuzz/cert_corpus/37ea6223d496dd2bb8d317b752010198d1fc14c7
Binary files differ
diff --git a/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c b/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c
new file mode 100644
index 00000000..1cab2138
--- /dev/null
+++ b/fuzz/cert_corpus/3834b376516fd4984fc5dc3b8f42a1fabd74664c
Binary files differ
diff --git a/fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6 b/fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6
new file mode 100644
index 00000000..8cd3819b
--- /dev/null
+++ b/fuzz/cert_corpus/38d7a3a0edc77172b1663880ceda8d1ab373a0d6
Binary files differ
diff --git a/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4 b/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4
new file mode 100644
index 00000000..5c0b7925
--- /dev/null
+++ b/fuzz/cert_corpus/3922605043f42c4868f47dd2463d2858fadfe0c4
Binary files differ
diff --git a/fuzz/cert_corpus/39b894e9f4745142150a62b7688ac4dfac65375d b/fuzz/cert_corpus/39b894e9f4745142150a62b7688ac4dfac65375d
deleted file mode 100644
index 7efb04cd..00000000
--- a/fuzz/cert_corpus/39b894e9f4745142150a62b7688ac4dfac65375d
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee b/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee
new file mode 100644
index 00000000..d3bd31da
--- /dev/null
+++ b/fuzz/cert_corpus/39fe902954bf3c1e0a033d33528e090c8c7835ee
Binary files differ
diff --git a/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33 b/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33
new file mode 100644
index 00000000..82ceb520
--- /dev/null
+++ b/fuzz/cert_corpus/3b7f75154dca9e79b5662226dc6c939b8aa7ac33
Binary files differ
diff --git a/fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541 b/fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541
new file mode 100644
index 00000000..5534c4b5
--- /dev/null
+++ b/fuzz/cert_corpus/3bac41829e17f9dc2f349d90283030f97e9c6541
Binary files differ
diff --git a/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151 b/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151
new file mode 100644
index 00000000..ef62d9eb
--- /dev/null
+++ b/fuzz/cert_corpus/3c2763aa2e94dc845be54417f2ca9c1386720151
Binary files differ
diff --git a/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537 b/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537
new file mode 100644
index 00000000..40ad5df1
--- /dev/null
+++ b/fuzz/cert_corpus/3d1dc5780b01d8d4e3381d534b36ac875d2e8537
Binary files differ
diff --git a/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d b/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d
new file mode 100644
index 00000000..f65e28b8
--- /dev/null
+++ b/fuzz/cert_corpus/3decf06ce7e54513145619feedb9ad5ba96e898d
Binary files differ
diff --git a/fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137 b/fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137
new file mode 100644
index 00000000..2ec21a4b
--- /dev/null
+++ b/fuzz/cert_corpus/3e5d5a9ba52db7de52d2aa3a08f95c35ae9b9137
Binary files differ
diff --git a/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645 b/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645
new file mode 100644
index 00000000..8e669738
--- /dev/null
+++ b/fuzz/cert_corpus/3eace4afa12afe234d6ded7d08130217fc2c9645
Binary files differ
diff --git a/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a b/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a
new file mode 100644
index 00000000..c8dbfdba
--- /dev/null
+++ b/fuzz/cert_corpus/3f1f7551d55ebb535cb54aa24037a83275b0c89a
Binary files differ
diff --git a/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934 b/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934
new file mode 100644
index 00000000..83452a81
--- /dev/null
+++ b/fuzz/cert_corpus/3fa31bd76bae27f66b61c63a4abfc461bd371934
Binary files differ
diff --git a/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab b/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab
new file mode 100644
index 00000000..bcd14d28
--- /dev/null
+++ b/fuzz/cert_corpus/40ac31d214a40326d74fdf7814ca312288360fab
Binary files differ
diff --git a/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c b/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c
new file mode 100644
index 00000000..e6153bae
--- /dev/null
+++ b/fuzz/cert_corpus/4225f4d93f8b87431acc7167a7e6ca27fe7d119c
Binary files differ
diff --git a/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619 b/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619
new file mode 100644
index 00000000..8c66eca1
--- /dev/null
+++ b/fuzz/cert_corpus/4298a95b560d773b41276414f4f7e991126fe619
Binary files differ
diff --git a/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6 b/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6
new file mode 100644
index 00000000..b82296b1
--- /dev/null
+++ b/fuzz/cert_corpus/4306c7e25b8389c7d3f402887a4077655ace41c6
Binary files differ
diff --git a/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3 b/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3
new file mode 100644
index 00000000..fed22995
--- /dev/null
+++ b/fuzz/cert_corpus/4439d387e849de35ea6711c3819463345004b2e3
Binary files differ
diff --git a/fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866 b/fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866
new file mode 100644
index 00000000..999fdc09
--- /dev/null
+++ b/fuzz/cert_corpus/44d2f5537df291966ab6205ee71a809a8a56e866
Binary files differ
diff --git a/fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbb b/fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbb
new file mode 100644
index 00000000..a15499a8
--- /dev/null
+++ b/fuzz/cert_corpus/45bec5a0ca33be77b2363ab59fb821aa44c55cbb
Binary files differ
diff --git a/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c b/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c
new file mode 100644
index 00000000..2d0a3841
--- /dev/null
+++ b/fuzz/cert_corpus/4685dd4dae8033acdb72a6fb3a0ce71f1299a92c
Binary files differ
diff --git a/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b b/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b
new file mode 100644
index 00000000..fbaa9603
--- /dev/null
+++ b/fuzz/cert_corpus/46904f9ce32352458c5e294c368797ae0e48991b
Binary files differ
diff --git a/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf b/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf
new file mode 100644
index 00000000..a798b2ed
--- /dev/null
+++ b/fuzz/cert_corpus/471e13c4ef32ffa3867034fe360e142cd7699faf
Binary files differ
diff --git a/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2 b/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2
new file mode 100644
index 00000000..dd35e586
--- /dev/null
+++ b/fuzz/cert_corpus/47c5db7df8938b05eb5344148af2ba4e6a6ebec2
Binary files differ
diff --git a/fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693ad b/fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693ad
new file mode 100644
index 00000000..5c22df75
--- /dev/null
+++ b/fuzz/cert_corpus/47f69c07723fe0f12f8f81d3a622f0ca09d693ad
Binary files differ
diff --git a/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc b/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc
new file mode 100644
index 00000000..0164a8dc
--- /dev/null
+++ b/fuzz/cert_corpus/4843ed9fc33451381b6f97311b8c6e254937f2bc
Binary files differ
diff --git a/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90 b/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90
new file mode 100644
index 00000000..9f71dd3e
--- /dev/null
+++ b/fuzz/cert_corpus/4938a5264e0e29b97f1a10e1a51a0e7de8334a90
Binary files differ
diff --git a/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd b/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd
new file mode 100644
index 00000000..8ef0accb
--- /dev/null
+++ b/fuzz/cert_corpus/4b32eb728bdaa1e1ce8f75344c9113f01addd7dd
Binary files differ
diff --git a/fuzz/cert_corpus/4b3fff8f4209aec529055a64cb7b38b89513c725 b/fuzz/cert_corpus/4b3fff8f4209aec529055a64cb7b38b89513c725
deleted file mode 100644
index 1130e04c..00000000
--- a/fuzz/cert_corpus/4b3fff8f4209aec529055a64cb7b38b89513c725
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5 b/fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5
new file mode 100644
index 00000000..ed665737
--- /dev/null
+++ b/fuzz/cert_corpus/4b5b5c5fafa6bd96ffc447488f2b283ef76287a5
Binary files differ
diff --git a/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0 b/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0
new file mode 100644
index 00000000..b6595073
--- /dev/null
+++ b/fuzz/cert_corpus/4b67f91302b63e6de6ffa81a57b38e12f1ee88b0
Binary files differ
diff --git a/fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5 b/fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5
new file mode 100644
index 00000000..242ece82
--- /dev/null
+++ b/fuzz/cert_corpus/4bb850171e9fc5a8a480876eb1f7331ffd2fc7b5
@@ -0,0 +1 @@
+00(00h1hA1h|0%0  *000 \ No newline at end of file
diff --git a/fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6 b/fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6
new file mode 100644
index 00000000..24ab6ebb
--- /dev/null
+++ b/fuzz/cert_corpus/4c1470de173adf77388fd8be8206e5f987d468e6
Binary files differ
diff --git a/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84 b/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84
new file mode 100644
index 00000000..cd94bb28
--- /dev/null
+++ b/fuzz/cert_corpus/4c1bb06706cb5a80f1c7ea2a738b129360823a84
Binary files differ
diff --git a/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2 b/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2
new file mode 100644
index 00000000..2111d2d4
--- /dev/null
+++ b/fuzz/cert_corpus/4c3c8a3a7e4d8ed30d8f37924503f1d643aab3c2
Binary files differ
diff --git a/fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057 b/fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057
new file mode 100644
index 00000000..83f61616
--- /dev/null
+++ b/fuzz/cert_corpus/4cf5cbf6eff378231f206e345fe96ce8b8ce5057
Binary files differ
diff --git a/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90 b/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90
new file mode 100644
index 00000000..d6d1eed8
--- /dev/null
+++ b/fuzz/cert_corpus/4d19ff9e4518157c69e1a03d87d00f2eaa932a90
Binary files differ
diff --git a/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c b/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c
new file mode 100644
index 00000000..2f28f2fc
--- /dev/null
+++ b/fuzz/cert_corpus/4e433c8a70e56cfa46a1ae7be617a9609540e59c
Binary files differ
diff --git a/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a b/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a
new file mode 100644
index 00000000..202ee12c
--- /dev/null
+++ b/fuzz/cert_corpus/4f131a48839d15feb0fb9fc92e3cafb76975632a
@@ -0,0 +1 @@
+001hA0 \ No newline at end of file
diff --git a/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0 b/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0
new file mode 100644
index 00000000..47c240d4
--- /dev/null
+++ b/fuzz/cert_corpus/51f89a8688c1b0fcdd806578ca485c7e4037f3c0
Binary files differ
diff --git a/fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854 b/fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854
new file mode 100644
index 00000000..abf6dbe3
--- /dev/null
+++ b/fuzz/cert_corpus/5222e890a092812b05c20232eca33516d61e6854
Binary files differ
diff --git a/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833 b/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833
new file mode 100644
index 00000000..cb767023
--- /dev/null
+++ b/fuzz/cert_corpus/5357bd89f226463ea66378f1872f2f3dcc45c833
Binary files differ
diff --git a/fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2f b/fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2f
new file mode 100644
index 00000000..02bdd1d0
--- /dev/null
+++ b/fuzz/cert_corpus/545e53e61cfc711f2faf4556040d09fc8d8aaf2f
Binary files differ
diff --git a/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23 b/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23
new file mode 100644
index 00000000..6aabed04
--- /dev/null
+++ b/fuzz/cert_corpus/54e8f165765c879ddb14f19d76b6e040a8269e23
Binary files differ
diff --git a/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92 b/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92
new file mode 100644
index 00000000..b5badb0c
--- /dev/null
+++ b/fuzz/cert_corpus/55a82b305fab4b2ab0bee8d3c70e8f41e8fedc92
Binary files differ
diff --git a/fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77caf b/fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77caf
new file mode 100644
index 00000000..e6b619f2
--- /dev/null
+++ b/fuzz/cert_corpus/5616542c0240af6572786b4088b07a3d6da77caf
Binary files differ
diff --git a/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b b/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b
new file mode 100644
index 00000000..cfc78b45
--- /dev/null
+++ b/fuzz/cert_corpus/56e4a5c9a93b5a414e2d14ea6eabd787dd0ffe7b
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8 b/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8
new file mode 100644
index 00000000..55d28fee
--- /dev/null
+++ b/fuzz/cert_corpus/5873ef5ad329e0bb4d788f1e8ea965fe2da858b8
Binary files differ
diff --git a/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5 b/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5
new file mode 100644
index 00000000..dd27b81f
--- /dev/null
+++ b/fuzz/cert_corpus/5aa3c8afa0c89038c509026d2a48d790521f92a5
Binary files differ
diff --git a/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422 b/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422
new file mode 100644
index 00000000..c7c90d20
--- /dev/null
+++ b/fuzz/cert_corpus/5b20a5b709ca2a262ba0e6a89c4a7f3bd9098422
Binary files differ
diff --git a/fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132b b/fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132b
new file mode 100644
index 00000000..d5473337
--- /dev/null
+++ b/fuzz/cert_corpus/5d00700f69a1db5a65201dc8d56aa917c6e6132b
Binary files differ
diff --git a/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8 b/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8
new file mode 100644
index 00000000..88bebfb5
--- /dev/null
+++ b/fuzz/cert_corpus/5d26b3013f6c3210b1e1b0e837bc577bb491e1b8
Binary files differ
diff --git a/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf b/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf
new file mode 100644
index 00000000..15f124b4
--- /dev/null
+++ b/fuzz/cert_corpus/5d5680962803669e9a931bc79eb421002bb6abdf
Binary files differ
diff --git a/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224 b/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224
new file mode 100644
index 00000000..1a757ff8
--- /dev/null
+++ b/fuzz/cert_corpus/5d6ffff8423a44c92868994adb23e851b6932224
Binary files differ
diff --git a/fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb b/fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb
new file mode 100644
index 00000000..cebe87c2
--- /dev/null
+++ b/fuzz/cert_corpus/5f7cc578c2516d3b9465841482354b609fee62fb
@@ -0,0 +1 @@
+00(00h1hA1h|0%0  *000 \ No newline at end of file
diff --git a/fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31 b/fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31
new file mode 100644
index 00000000..d69f231a
--- /dev/null
+++ b/fuzz/cert_corpus/5fd4775f8a1b947387c3fbd5f8d5e794e21eaa31
Binary files differ
diff --git a/fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5b b/fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5b
new file mode 100644
index 00000000..0322804b
--- /dev/null
+++ b/fuzz/cert_corpus/5fe171e9917a45ecee64fd75cdc3726a0dc65a5b
Binary files differ
diff --git a/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4 b/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4
new file mode 100644
index 00000000..7d999fee
--- /dev/null
+++ b/fuzz/cert_corpus/6030d8a8d1d58b4e2efa13c04a1da538bac6c2c4
Binary files differ
diff --git a/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9 b/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9
new file mode 100644
index 00000000..227dc492
--- /dev/null
+++ b/fuzz/cert_corpus/60c070cf2975070c6def7c702abd7d7d941ae0e9
Binary files differ
diff --git a/fuzz/cert_corpus/60c9a5ce074daf266315dfa2093b014b43baedd6 b/fuzz/cert_corpus/60c9a5ce074daf266315dfa2093b014b43baedd6
deleted file mode 100644
index fd26e4f8..00000000
--- a/fuzz/cert_corpus/60c9a5ce074daf266315dfa2093b014b43baedd6
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/60fe312a17b6d5a46ca05116fbc5cfd23977bab4 b/fuzz/cert_corpus/60fe312a17b6d5a46ca05116fbc5cfd23977bab4
deleted file mode 100644
index 50324631..00000000
--- a/fuzz/cert_corpus/60fe312a17b6d5a46ca05116fbc5cfd23977bab4
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337 b/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337
new file mode 100644
index 00000000..0464b038
--- /dev/null
+++ b/fuzz/cert_corpus/6461be4247a144f92150a896c56f9561f2169337
Binary files differ
diff --git a/fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715 b/fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715
new file mode 100644
index 00000000..f6d312a9
--- /dev/null
+++ b/fuzz/cert_corpus/64f00e208a2077bce3a031aa41a2dd696d012715
Binary files differ
diff --git a/fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719b b/fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719b
new file mode 100644
index 00000000..fa42c20a
--- /dev/null
+++ b/fuzz/cert_corpus/65459fb5f394db61715e19187239b7aa90b1719b
Binary files differ
diff --git a/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33 b/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33
new file mode 100644
index 00000000..f7e437ab
--- /dev/null
+++ b/fuzz/cert_corpus/667d0776ef5074ba6525d5a56fbf3ff140108a33
Binary files differ
diff --git a/fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148 b/fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148
new file mode 100644
index 00000000..fc15793c
--- /dev/null
+++ b/fuzz/cert_corpus/6b6697d8bf086fa6e9fc7d5dfb27a5fee7a3a148
Binary files differ
diff --git a/fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1 b/fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1
new file mode 100644
index 00000000..11f1f3fb
--- /dev/null
+++ b/fuzz/cert_corpus/6e58bd8357c877fe7e3ca75af4b9959831ee44b1
Binary files differ
diff --git a/fuzz/cert_corpus/6fcf556855dd7013e57ae7a729f43bc9d76d41f1 b/fuzz/cert_corpus/6fcf556855dd7013e57ae7a729f43bc9d76d41f1
deleted file mode 100644
index a2fd3124..00000000
--- a/fuzz/cert_corpus/6fcf556855dd7013e57ae7a729f43bc9d76d41f1
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06 b/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06
new file mode 100644
index 00000000..781008a6
--- /dev/null
+++ b/fuzz/cert_corpus/6fe20105baf3a79f9c69ff4dde501c4542118d06
Binary files differ
diff --git a/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d b/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d
new file mode 100644
index 00000000..1eb88833
--- /dev/null
+++ b/fuzz/cert_corpus/70be2630942a6f72e66f3f7189ad014acc45bb7d
Binary files differ
diff --git a/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd b/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd
new file mode 100644
index 00000000..5d1a0fee
--- /dev/null
+++ b/fuzz/cert_corpus/70f2004db5c4ddfa9bd91d0db596867b4403d9cd
Binary files differ
diff --git a/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06 b/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06
new file mode 100644
index 00000000..31cd9410
--- /dev/null
+++ b/fuzz/cert_corpus/71123779ed3db9713684829f9a2ed309c9d96f06
@@ -0,0 +1 @@
+00(00h1hA!1h|0%0  *0' \ No newline at end of file
diff --git a/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744 b/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744
new file mode 100644
index 00000000..67bd8406
--- /dev/null
+++ b/fuzz/cert_corpus/719702d86cd0fc94ad0b193398112815f3308744
Binary files differ
diff --git a/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3 b/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3
new file mode 100644
index 00000000..f5f7646e
--- /dev/null
+++ b/fuzz/cert_corpus/71b0adb1b0c1fccff4150b015220e74e549d24d3
Binary files differ
diff --git a/fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330 b/fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330
new file mode 100644
index 00000000..628d517d
--- /dev/null
+++ b/fuzz/cert_corpus/72273c2fa36dbb9b39a69e65f59b616c706f3330
Binary files differ
diff --git a/fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5d b/fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5d
new file mode 100644
index 00000000..98502362
--- /dev/null
+++ b/fuzz/cert_corpus/72b8b2c9ae429de1590b68fd125892a3832abc5d
Binary files differ
diff --git a/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18 b/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18
new file mode 100644
index 00000000..5a91ba11
--- /dev/null
+++ b/fuzz/cert_corpus/72c6ba776c93cce6f82c1acaf9ccd95adfd22a18
Binary files differ
diff --git a/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5 b/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5
new file mode 100644
index 00000000..b88f3942
--- /dev/null
+++ b/fuzz/cert_corpus/72d95d75d6a1c5e6f8c0e488f71d30bdd01b52d5
Binary files differ
diff --git a/fuzz/cert_corpus/7359755c6df9a0abc3060bce369564c8ec4542a3 b/fuzz/cert_corpus/7359755c6df9a0abc3060bce369564c8ec4542a3
deleted file mode 100644
index 82e50046..00000000
--- a/fuzz/cert_corpus/7359755c6df9a0abc3060bce369564c8ec4542a3
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224 b/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224
new file mode 100644
index 00000000..65c09fa5
--- /dev/null
+++ b/fuzz/cert_corpus/73c845434d7055e1cff670fe85edb1b7581ee224
Binary files differ
diff --git a/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c b/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c
new file mode 100644
index 00000000..8c6be702
--- /dev/null
+++ b/fuzz/cert_corpus/73fa79cca934a2c5c13f7d41b0162e611d6e4f5c
Binary files differ
diff --git a/fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd b/fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd
new file mode 100644
index 00000000..f69814f2
--- /dev/null
+++ b/fuzz/cert_corpus/74a907e9d20fab94e34c3e46d73f7aa2d4f1dccd
Binary files differ
diff --git a/fuzz/cert_corpus/74ea68736ec375b226f0ca86464d2d43baac3574 b/fuzz/cert_corpus/74ea68736ec375b226f0ca86464d2d43baac3574
deleted file mode 100644
index a043e433..00000000
--- a/fuzz/cert_corpus/74ea68736ec375b226f0ca86464d2d43baac3574
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75 b/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75
new file mode 100644
index 00000000..32e7bc84
--- /dev/null
+++ b/fuzz/cert_corpus/77818abcde8b135fcc987e61388553e697d32d75
@@ -0,0 +1 @@
+10 \ No newline at end of file
diff --git a/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9 b/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9
new file mode 100644
index 00000000..ec01b39f
--- /dev/null
+++ b/fuzz/cert_corpus/785389bce6d1f4c8f2cec6062ecacb1d49a784f9
Binary files differ
diff --git a/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876 b/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876
new file mode 100644
index 00000000..31cf9849
--- /dev/null
+++ b/fuzz/cert_corpus/795b50e9f9bc6f1a3be9b158a9fa287a5bba6876
Binary files differ
diff --git a/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1 b/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1
new file mode 100644
index 00000000..51b0e63f
--- /dev/null
+++ b/fuzz/cert_corpus/7a37f6614fd5c0dda82eceb3d171090c7581f0c1
Binary files differ
diff --git a/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144 b/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144
new file mode 100644
index 00000000..598723ce
--- /dev/null
+++ b/fuzz/cert_corpus/7adda79c5f85db9577eac0cf60e0cad63c74e144
Binary files differ
diff --git a/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847 b/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847
new file mode 100644
index 00000000..90c60101
--- /dev/null
+++ b/fuzz/cert_corpus/7d8eed80cfd58de130245bea2880f3b042225847
Binary files differ
diff --git a/fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5f b/fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5f
new file mode 100644
index 00000000..7f953764
--- /dev/null
+++ b/fuzz/cert_corpus/808871bc380bc3221c7ce683031bb6d85293ee5f
Binary files differ
diff --git a/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb b/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb
new file mode 100644
index 00000000..a9b39dff
--- /dev/null
+++ b/fuzz/cert_corpus/808882216e9afcc5257f494435c2d9757dc785eb
Binary files differ
diff --git a/fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6 b/fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6
new file mode 100644
index 00000000..62145006
--- /dev/null
+++ b/fuzz/cert_corpus/808bf82ca615b1d70ef5b1c2d2afc19d25e3dbb6
Binary files differ
diff --git a/fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988b b/fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988b
new file mode 100644
index 00000000..91539014
--- /dev/null
+++ b/fuzz/cert_corpus/8210a65e177303f8b801f73c663806236584988b
Binary files differ
diff --git a/fuzz/cert_corpus/8275aabe75b73bb398933bf9a106fde4b198d1b1 b/fuzz/cert_corpus/8275aabe75b73bb398933bf9a106fde4b198d1b1
deleted file mode 100644
index a3e76e6f..00000000
--- a/fuzz/cert_corpus/8275aabe75b73bb398933bf9a106fde4b198d1b1
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1 b/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1
new file mode 100644
index 00000000..4463be12
--- /dev/null
+++ b/fuzz/cert_corpus/8369ebff6d1524579c2bcd10b5ab2df186cba6c1
Binary files differ
diff --git a/fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48 b/fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48
new file mode 100644
index 00000000..888308ad
--- /dev/null
+++ b/fuzz/cert_corpus/83a5535a9a577453d218f897017e59a996439c48
Binary files differ
diff --git a/fuzz/cert_corpus/840007514cd63aca9bd6d65fe5d1eb4c58600106 b/fuzz/cert_corpus/840007514cd63aca9bd6d65fe5d1eb4c58600106
deleted file mode 100644
index 8d066328..00000000
--- a/fuzz/cert_corpus/840007514cd63aca9bd6d65fe5d1eb4c58600106
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264def b/fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264def
new file mode 100644
index 00000000..530b4805
--- /dev/null
+++ b/fuzz/cert_corpus/848f69b34380f7554ab3074737d72ca8b0264def
Binary files differ
diff --git a/fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85 b/fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85
new file mode 100644
index 00000000..afae567c
--- /dev/null
+++ b/fuzz/cert_corpus/85e7763d7b35b96c1fd9f3462f02f4ddd9fb9e85
Binary files differ
diff --git a/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6 b/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6
new file mode 100644
index 00000000..54e26203
--- /dev/null
+++ b/fuzz/cert_corpus/86c40f29670fbf2e1eed17d3a99aa2a6b90cecf6
Binary files differ
diff --git a/fuzz/cert_corpus/87555b600217d444d85e8a7afece3239a566c6a0 b/fuzz/cert_corpus/87555b600217d444d85e8a7afece3239a566c6a0
deleted file mode 100644
index 0385a72a..00000000
--- a/fuzz/cert_corpus/87555b600217d444d85e8a7afece3239a566c6a0
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57f b/fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57f
new file mode 100644
index 00000000..b7539dbb
--- /dev/null
+++ b/fuzz/cert_corpus/8786dd7aa2d0ea06461fc1d4751c9c00e234e57f
Binary files differ
diff --git a/fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668 b/fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668
new file mode 100644
index 00000000..351ca6ed
--- /dev/null
+++ b/fuzz/cert_corpus/8816b6afa44700585efccf15d9b4b0ebdaa57668
Binary files differ
diff --git a/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35 b/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35
new file mode 100644
index 00000000..51c9b6da
--- /dev/null
+++ b/fuzz/cert_corpus/883b4622778cad8346c050139607cac3ff967b35
Binary files differ
diff --git a/fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050ead b/fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050ead
new file mode 100644
index 00000000..940f722f
--- /dev/null
+++ b/fuzz/cert_corpus/888fe58059dfa918cfa17edfeb3746c709050ead
Binary files differ
diff --git a/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d b/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d
new file mode 100644
index 00000000..677607b7
--- /dev/null
+++ b/fuzz/cert_corpus/88bc068b97b79216220812a038ebb2810b26886d
Binary files differ
diff --git a/fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8f b/fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8f
new file mode 100644
index 00000000..056b81d0
--- /dev/null
+++ b/fuzz/cert_corpus/88fd1e4a65f306244552395b6ca6534a20982b8f
Binary files differ
diff --git a/fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fade b/fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fade
new file mode 100644
index 00000000..e8810237
--- /dev/null
+++ b/fuzz/cert_corpus/8a27963ce5bb499fea5f1fc3a2876e4f5a21fade
Binary files differ
diff --git a/fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665 b/fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665
new file mode 100644
index 00000000..85039f89
--- /dev/null
+++ b/fuzz/cert_corpus/8a677dfa5510949833db9b79ae63bd4a5d882665
Binary files differ
diff --git a/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431 b/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431
new file mode 100644
index 00000000..4ce4a75c
--- /dev/null
+++ b/fuzz/cert_corpus/8abde7f7cab98c1b02729fcd665090c8b0934431
Binary files differ
diff --git a/fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4d b/fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4d
new file mode 100644
index 00000000..e5759761
--- /dev/null
+++ b/fuzz/cert_corpus/8ce5aebbe8c9d1562a2ae1b996669f1843692c4d
Binary files differ
diff --git a/fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3 b/fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3
new file mode 100644
index 00000000..3e6a37d1
--- /dev/null
+++ b/fuzz/cert_corpus/8d181c10f73a5574cbf445593200e71a16584ec3
Binary files differ
diff --git a/fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538 b/fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538
new file mode 100644
index 00000000..a0c7acc9
--- /dev/null
+++ b/fuzz/cert_corpus/8dbbc76831fa9eaff21b8a04f5ce41c1a0468538
Binary files differ
diff --git a/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00 b/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00
new file mode 100644
index 00000000..4e1df5da
--- /dev/null
+++ b/fuzz/cert_corpus/8f5cdec4e18527ddbc930a7bfe710ac015527f00
Binary files differ
diff --git a/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a b/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a
new file mode 100644
index 00000000..75117a52
--- /dev/null
+++ b/fuzz/cert_corpus/92e6a50ac9f8a75d43d93b85873adf8f0ffb9d0a
Binary files differ
diff --git a/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad b/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad
new file mode 100644
index 00000000..60705583
--- /dev/null
+++ b/fuzz/cert_corpus/94b7796d627b110ff66c1bd9dc1a7c2f87a723ad
Binary files differ
diff --git a/fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394 b/fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394
new file mode 100644
index 00000000..1ed9eac0
--- /dev/null
+++ b/fuzz/cert_corpus/94d777c0eae1377aa35069f15e75954792406394
Binary files differ
diff --git a/fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6 b/fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6
new file mode 100644
index 00000000..11296bfc
--- /dev/null
+++ b/fuzz/cert_corpus/96516b3b33c6faa0224d198d549b6a167416a4f6
Binary files differ
diff --git a/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae b/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae
new file mode 100644
index 00000000..5d40be85
--- /dev/null
+++ b/fuzz/cert_corpus/96aa3fabebccf825b9cc06ec34e605a450b49eae
Binary files differ
diff --git a/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93 b/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93
new file mode 100644
index 00000000..034fc2bb
--- /dev/null
+++ b/fuzz/cert_corpus/96ce1cb3ca0061f2865d1348f3e147000a3b1a93
@@ -0,0 +1 @@
+)(; \ No newline at end of file
diff --git a/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd b/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd
new file mode 100644
index 00000000..7cd7165d
--- /dev/null
+++ b/fuzz/cert_corpus/9716858fbfa71a1c8bc855f2a09dece8df15e5bd
Binary files differ
diff --git a/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad b/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad
new file mode 100644
index 00000000..d8d6fc10
--- /dev/null
+++ b/fuzz/cert_corpus/97335aacabe616a3b92c25187ef3ccc58dc09fad
Binary files differ
diff --git a/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db b/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db
new file mode 100644
index 00000000..1552adb5
--- /dev/null
+++ b/fuzz/cert_corpus/9827e8a5ab0f09782c75a948175d723ea6fc54db
Binary files differ
diff --git a/fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc631 b/fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc631
new file mode 100644
index 00000000..b112929b
--- /dev/null
+++ b/fuzz/cert_corpus/990a8dcc9aadd0b161023f0d16e6556e30ddc631
@@ -0,0 +1 @@
+0:;0 \ No newline at end of file
diff --git a/fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9 b/fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9
new file mode 100644
index 00000000..fd85e93a
--- /dev/null
+++ b/fuzz/cert_corpus/9948b60fcf547feec8bdd433a1dde37e2cd34de9
Binary files differ
diff --git a/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079 b/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079
new file mode 100644
index 00000000..901fe6ff
--- /dev/null
+++ b/fuzz/cert_corpus/999f2f88a8b6510ca0253005f3a6cc06840a8079
Binary files differ
diff --git a/fuzz/cert_corpus/9a5618d71d29f45a7dbe3f2b98d66702427faaaf b/fuzz/cert_corpus/9a5618d71d29f45a7dbe3f2b98d66702427faaaf
deleted file mode 100644
index fd56394b..00000000
--- a/fuzz/cert_corpus/9a5618d71d29f45a7dbe3f2b98d66702427faaaf
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3 b/fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3
new file mode 100644
index 00000000..5c254e7e
--- /dev/null
+++ b/fuzz/cert_corpus/9afae58a2080ea211e3e5b25f4c35c0aa3c341a3
Binary files differ
diff --git a/fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7d b/fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7d
new file mode 100644
index 00000000..8267cd15
--- /dev/null
+++ b/fuzz/cert_corpus/9c719bffb73cc4fa6a3bba4acd487049eb781a7d
Binary files differ
diff --git a/fuzz/cert_corpus/9d1eb7853324fba4aa29f65e2213c54c44d988a6 b/fuzz/cert_corpus/9d1eb7853324fba4aa29f65e2213c54c44d988a6
deleted file mode 100644
index 8265f1c9..00000000
--- a/fuzz/cert_corpus/9d1eb7853324fba4aa29f65e2213c54c44d988a6
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd b/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd
new file mode 100644
index 00000000..41b10c20
--- /dev/null
+++ b/fuzz/cert_corpus/9d20961e30091256f8211c2837a35db60411dffd
Binary files differ
diff --git a/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155 b/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155
new file mode 100644
index 00000000..5fbfacb1
--- /dev/null
+++ b/fuzz/cert_corpus/9dc938dc1db7f1b8f8f21a3550f1f3de5729d155
@@ -0,0 +1 @@
+(; \ No newline at end of file
diff --git a/fuzz/cert_corpus/9df5fabe0c5cdf7cf5c427be02ed3cee33b2a0e9 b/fuzz/cert_corpus/9df5fabe0c5cdf7cf5c427be02ed3cee33b2a0e9
deleted file mode 100644
index 44deb494..00000000
--- a/fuzz/cert_corpus/9df5fabe0c5cdf7cf5c427be02ed3cee33b2a0e9
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/9fad61f53d1256a653b0f9351b6624793089f50c b/fuzz/cert_corpus/9fad61f53d1256a653b0f9351b6624793089f50c
deleted file mode 100644
index 6f80978d..00000000
--- a/fuzz/cert_corpus/9fad61f53d1256a653b0f9351b6624793089f50c
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3 b/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3
new file mode 100644
index 00000000..a2ab64c5
--- /dev/null
+++ b/fuzz/cert_corpus/a0666bf912f161ed73664e328cdd57d59118e3a3
Binary files differ
diff --git a/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff b/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff
new file mode 100644
index 00000000..4a375c33
--- /dev/null
+++ b/fuzz/cert_corpus/a15fa9644e1be0193331158823bf88ff51593bff
Binary files differ
diff --git a/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420 b/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420
new file mode 100644
index 00000000..09c2b624
--- /dev/null
+++ b/fuzz/cert_corpus/a19ed2ca60eddf4a56e318b33c4767194efdd420
Binary files differ
diff --git a/fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9 b/fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9
new file mode 100644
index 00000000..994fc86e
--- /dev/null
+++ b/fuzz/cert_corpus/a29b87920a4c706f69a58c61e7d22aaa26a781a9
Binary files differ
diff --git a/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029 b/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029
new file mode 100644
index 00000000..b12aa104
--- /dev/null
+++ b/fuzz/cert_corpus/a330339d9f71af3b1ef51f62aacf3e5a18233029
Binary files differ
diff --git a/fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f b/fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f
new file mode 100644
index 00000000..a31a79b0
--- /dev/null
+++ b/fuzz/cert_corpus/a3332f9638dc9ec85e9c2166128bf7eb8ebb005f
@@ -0,0 +1 @@
+( \ No newline at end of file
diff --git a/fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681 b/fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681
new file mode 100644
index 00000000..8b4d7f2f
--- /dev/null
+++ b/fuzz/cert_corpus/a36107992ae6b6dca220e831495ba60a4e817681
Binary files differ
diff --git a/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83 b/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83
new file mode 100644
index 00000000..be16f72a
--- /dev/null
+++ b/fuzz/cert_corpus/a5061c9bd9b94e35318ca968a7f933147ca56e83
@@ -0,0 +1 @@
+?',; \ No newline at end of file
diff --git a/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4 b/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4
new file mode 100644
index 00000000..ea357ce0
--- /dev/null
+++ b/fuzz/cert_corpus/a5dbab7e4f4c13f0ae62a3df935501484fecc8d4
@@ -0,0 +1 @@
+00&0 \ No newline at end of file
diff --git a/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a b/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a
new file mode 100644
index 00000000..523423a9
--- /dev/null
+++ b/fuzz/cert_corpus/a63ee3d25f38c1cca2b1498b548396d900e8741a
Binary files differ
diff --git a/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d b/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d
new file mode 100644
index 00000000..f1505650
--- /dev/null
+++ b/fuzz/cert_corpus/a6e50bf5f58ab1b4d2f034f924ef88ab3255e88d
Binary files differ
diff --git a/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a b/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a
new file mode 100644
index 00000000..6b428010
--- /dev/null
+++ b/fuzz/cert_corpus/a758736dfeb57d7bb7f31793d81bab116942d31a
Binary files differ
diff --git a/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb b/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb
new file mode 100644
index 00000000..9529ae15
--- /dev/null
+++ b/fuzz/cert_corpus/a83ca2374044aa6547ce0cd931cea82f34bcfbeb
Binary files differ
diff --git a/fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcd b/fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcd
new file mode 100644
index 00000000..095fe4c7
--- /dev/null
+++ b/fuzz/cert_corpus/a897327b805c8b342ef8ad32adc92e904ee16bcd
Binary files differ
diff --git a/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457 b/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457
new file mode 100644
index 00000000..8ec9696c
--- /dev/null
+++ b/fuzz/cert_corpus/a8be778f7892a8d914e7d742529143c57959e457
Binary files differ
diff --git a/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7 b/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7
new file mode 100644
index 00000000..b7a36331
--- /dev/null
+++ b/fuzz/cert_corpus/aa94e8277aa662cf0a17f930b9724e0c39699db7
Binary files differ
diff --git a/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a b/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a
new file mode 100644
index 00000000..40a633e6
--- /dev/null
+++ b/fuzz/cert_corpus/ac7ce7801f5c13864f06b098b137bcca98c9dd4a
Binary files differ
diff --git a/fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0a b/fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0a
new file mode 100644
index 00000000..137e123d
--- /dev/null
+++ b/fuzz/cert_corpus/ad520c064da535365c2cf4262dc960cc03011a0a
Binary files differ
diff --git a/fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2 b/fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2
new file mode 100644
index 00000000..701d60b2
--- /dev/null
+++ b/fuzz/cert_corpus/ad6d7bb7923133cf1bd53c824cd8f400359430e2
Binary files differ
diff --git a/fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9 b/fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9
new file mode 100644
index 00000000..f6d620a6
--- /dev/null
+++ b/fuzz/cert_corpus/ad987767605d380e8465acbca66ea6b74158e4f9
Binary files differ
diff --git a/fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746 b/fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746
new file mode 100644
index 00000000..2136ac82
--- /dev/null
+++ b/fuzz/cert_corpus/ae096884e1100954f53c3e6c79845e94d4d9a746
Binary files differ
diff --git a/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b b/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b
new file mode 100644
index 00000000..9aff0ede
--- /dev/null
+++ b/fuzz/cert_corpus/ae6c9f7732c5b28312dbfdd0d2708050e056f85b
Binary files differ
diff --git a/fuzz/cert_corpus/ae820c47ddc20ff0be7109c331f04b7d5ddd623a b/fuzz/cert_corpus/ae820c47ddc20ff0be7109c331f04b7d5ddd623a
deleted file mode 100644
index 3b249dc3..00000000
--- a/fuzz/cert_corpus/ae820c47ddc20ff0be7109c331f04b7d5ddd623a
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb b/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb
new file mode 100644
index 00000000..fa9b8831
--- /dev/null
+++ b/fuzz/cert_corpus/af72aeeb36675d40d33838d25bad17ebe69e95eb
Binary files differ
diff --git a/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a b/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a
new file mode 100644
index 00000000..92621d97
--- /dev/null
+++ b/fuzz/cert_corpus/afebf1b47d59c6c659856c5858596d646d42048a
Binary files differ
diff --git a/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542 b/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542
new file mode 100644
index 00000000..cfb4fcef
--- /dev/null
+++ b/fuzz/cert_corpus/b240ee6879847aa20ae97315c6062da51a223542
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63 b/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63
new file mode 100644
index 00000000..0e302167
--- /dev/null
+++ b/fuzz/cert_corpus/b2617f1a96f347b9d3d08f52e2459de63daaae63
Binary files differ
diff --git a/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99 b/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99
new file mode 100644
index 00000000..456fba1d
--- /dev/null
+++ b/fuzz/cert_corpus/b27f0261d700798b8499047d9d3e5a4330ff1b99
@@ -0,0 +1 @@
+); \ No newline at end of file
diff --git a/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810 b/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810
new file mode 100644
index 00000000..a571c87c
--- /dev/null
+++ b/fuzz/cert_corpus/b2bce56f2d1a5dcd77cc5373fcb6c6fd2bf0d810
Binary files differ
diff --git a/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024 b/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024
new file mode 100644
index 00000000..d434d195
--- /dev/null
+++ b/fuzz/cert_corpus/b33bee76673e45a532c82df4459d8f0efca9b024
Binary files differ
diff --git a/fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8 b/fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8
new file mode 100644
index 00000000..3bfb4662
--- /dev/null
+++ b/fuzz/cert_corpus/b496b414ddd42dd3d1633921131dab70ee93f9e8
Binary files differ
diff --git a/fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74 b/fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74
new file mode 100644
index 00000000..257ea3fb
--- /dev/null
+++ b/fuzz/cert_corpus/b5442281d01a098f07aa150dc8c8ebc432922b74
Binary files differ
diff --git a/fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902 b/fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902
new file mode 100644
index 00000000..1ea877c5
--- /dev/null
+++ b/fuzz/cert_corpus/b569b141740c0b32d4f8f8d77fe603287cf4d902
Binary files differ
diff --git a/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29 b/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29
new file mode 100644
index 00000000..c7d4fda7
--- /dev/null
+++ b/fuzz/cert_corpus/b612998fc4201e2955aec046387e95254b25ba29
@@ -0,0 +1 @@
+0}00 \ No newline at end of file
diff --git a/fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84 b/fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84
new file mode 100644
index 00000000..d849e7cd
--- /dev/null
+++ b/fuzz/cert_corpus/b6934c620f93440e12cf5861f588ab3574da9a84
Binary files differ
diff --git a/fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fda b/fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fda
new file mode 100644
index 00000000..479ca266
--- /dev/null
+++ b/fuzz/cert_corpus/b6b89469619a6e0194005e993cf053cae6ff9fda
Binary files differ
diff --git a/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac b/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac
new file mode 100644
index 00000000..d01d05e8
--- /dev/null
+++ b/fuzz/cert_corpus/b732cd2e2227deff1529a431a16b3166bd66f0ac
Binary files differ
diff --git a/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7 b/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7
new file mode 100644
index 00000000..2b91c143
--- /dev/null
+++ b/fuzz/cert_corpus/b7a53770b23d0ac54b006ea0509bcc5bd27ce1d7
Binary files differ
diff --git a/fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2 b/fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2
new file mode 100644
index 00000000..a3332f24
--- /dev/null
+++ b/fuzz/cert_corpus/b8f244f0d4a928ec6e532af4c7c633c99de03ee2
Binary files differ
diff --git a/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399 b/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399
new file mode 100644
index 00000000..89f479aa
--- /dev/null
+++ b/fuzz/cert_corpus/ba485873c6de244c1d036607fd57107bf3d54399
Binary files differ
diff --git a/fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0 b/fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0
new file mode 100644
index 00000000..48242a3e
--- /dev/null
+++ b/fuzz/cert_corpus/ba8ffb341293741fb442ad7817290bf57acc87f0
Binary files differ
diff --git a/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e b/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e
new file mode 100644
index 00000000..f4e18e08
--- /dev/null
+++ b/fuzz/cert_corpus/bae9b0825a33ac52cd413665dd38a17837174a7e
Binary files differ
diff --git a/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068 b/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068
new file mode 100644
index 00000000..f0bbba61
--- /dev/null
+++ b/fuzz/cert_corpus/bb1fb206c56745bf992220e6c7de0e2fc94cf068
Binary files differ
diff --git a/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92 b/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92
new file mode 100644
index 00000000..8a708456
--- /dev/null
+++ b/fuzz/cert_corpus/bc01d9510d91bcf2ba747842a572140801564b92
Binary files differ
diff --git a/fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767c b/fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767c
new file mode 100644
index 00000000..b41960e7
--- /dev/null
+++ b/fuzz/cert_corpus/bd351dbed468c58280ee4735c6fe101813bb767c
Binary files differ
diff --git a/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def b/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def
new file mode 100644
index 00000000..583b1229
--- /dev/null
+++ b/fuzz/cert_corpus/bd49114ebfcb9795f8231b482ad700f1dd092def
Binary files differ
diff --git a/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf b/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf
new file mode 100644
index 00000000..f5762866
--- /dev/null
+++ b/fuzz/cert_corpus/bd72b9ca5d91970e5b77e97a67781e3e70810edf
Binary files differ
diff --git a/fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2 b/fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2
new file mode 100644
index 00000000..682eebf8
--- /dev/null
+++ b/fuzz/cert_corpus/bf89b0f5278535c052386adea67874b12668fca2
Binary files differ
diff --git a/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28 b/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28
new file mode 100644
index 00000000..90503330
--- /dev/null
+++ b/fuzz/cert_corpus/bfa6177702f7b3d35d431d805af1216b3ace3a28
Binary files differ
diff --git a/fuzz/cert_corpus/c0bc4e081e8de875ffd9f4e4f611351d790c3316 b/fuzz/cert_corpus/c0bc4e081e8de875ffd9f4e4f611351d790c3316
deleted file mode 100644
index eac0fc86..00000000
--- a/fuzz/cert_corpus/c0bc4e081e8de875ffd9f4e4f611351d790c3316
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851b b/fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851b
new file mode 100644
index 00000000..60554075
--- /dev/null
+++ b/fuzz/cert_corpus/c10def6097a072cd11a89161c49c76f4cd9b851b
Binary files differ
diff --git a/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea b/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea
new file mode 100644
index 00000000..cdce1db3
--- /dev/null
+++ b/fuzz/cert_corpus/c218be470382eb7b9cf45659c58d66bb000f4eea
@@ -0,0 +1 @@
+90 \ No newline at end of file
diff --git a/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6 b/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6
new file mode 100644
index 00000000..473c58d5
--- /dev/null
+++ b/fuzz/cert_corpus/c2b238783ccd5d9a8ab37f45e12001e2d32634b6
Binary files differ
diff --git a/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b b/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b
new file mode 100644
index 00000000..a4c5ee24
--- /dev/null
+++ b/fuzz/cert_corpus/c4437538c745e35381b74aba56778cfa6379180b
Binary files differ
diff --git a/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4 b/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4
new file mode 100644
index 00000000..620119d8
--- /dev/null
+++ b/fuzz/cert_corpus/c452d11f12a4eafb8d61aefd5354e5f5d51c18d4
Binary files differ
diff --git a/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3 b/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3
new file mode 100644
index 00000000..fac8866a
--- /dev/null
+++ b/fuzz/cert_corpus/c45c2dd1094d4b93f18f081c0b576bae60bb27d3
Binary files differ
diff --git a/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd b/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd
new file mode 100644
index 00000000..8d81d375
--- /dev/null
+++ b/fuzz/cert_corpus/c4f3c6cfbef081bf63b3b5972c9137635d445fdd
Binary files differ
diff --git a/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008 b/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008
new file mode 100644
index 00000000..42c6db63
--- /dev/null
+++ b/fuzz/cert_corpus/c4f605ca070c95dc5d1fd59124a12d35e8c76008
Binary files differ
diff --git a/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040 b/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040
new file mode 100644
index 00000000..dcc743f4
--- /dev/null
+++ b/fuzz/cert_corpus/c549b74782b8ee587cea2d773c76f736774a1040
Binary files differ
diff --git a/fuzz/cert_corpus/c5ed379b9f6794810a09862f48297a9e576014ad b/fuzz/cert_corpus/c5ed379b9f6794810a09862f48297a9e576014ad
deleted file mode 100644
index b767b2aa..00000000
--- a/fuzz/cert_corpus/c5ed379b9f6794810a09862f48297a9e576014ad
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92 b/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92
new file mode 100644
index 00000000..eea04152
--- /dev/null
+++ b/fuzz/cert_corpus/c613a74f7c25acd72e426aae6b6f8aca4230de92
@@ -0,0 +1 @@
+: \ No newline at end of file
diff --git a/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744 b/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744
new file mode 100644
index 00000000..7f767fde
--- /dev/null
+++ b/fuzz/cert_corpus/c6b5b66f8a56110cef76c49e0f128584ff9ae744
Binary files differ
diff --git a/fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fb b/fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fb
new file mode 100644
index 00000000..f760e5ed
--- /dev/null
+++ b/fuzz/cert_corpus/c885c076019c097c788823b5c242789315ce18fb
Binary files differ
diff --git a/fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54 b/fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54
new file mode 100644
index 00000000..5091a202
--- /dev/null
+++ b/fuzz/cert_corpus/c8fe6b745e1bed025f2948444e1372cf89bf2f54
Binary files differ
diff --git a/fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8 b/fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8
new file mode 100644
index 00000000..c50621aa
--- /dev/null
+++ b/fuzz/cert_corpus/ca5f6f2655ef6d5737e61519eddd94cecbd9aec8
Binary files differ
diff --git a/fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644 b/fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644
new file mode 100644
index 00000000..1ff4122b
--- /dev/null
+++ b/fuzz/cert_corpus/cca7bdb3e8b8c03d754aedbb5f781644305d3644
Binary files differ
diff --git a/fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18ca b/fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18ca
new file mode 100644
index 00000000..8ecbb726
--- /dev/null
+++ b/fuzz/cert_corpus/ccea62417883c07b37d5f8120602b78e96cf18ca
Binary files differ
diff --git a/fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9a b/fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9a
new file mode 100644
index 00000000..bc694027
--- /dev/null
+++ b/fuzz/cert_corpus/ccf05090692d99c4c28dc2e104896819ed3fdd9a
Binary files differ
diff --git a/fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1ca b/fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1ca
new file mode 100644
index 00000000..636066d8
--- /dev/null
+++ b/fuzz/cert_corpus/ce1b40306ee7b3df129aa772c11103f7237aa1ca
Binary files differ
diff --git a/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f b/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f
new file mode 100644
index 00000000..3873f4b7
--- /dev/null
+++ b/fuzz/cert_corpus/ce80fcf5a7c0dcfbdb2739c27c38a4d4a764d66f
Binary files differ
diff --git a/fuzz/cert_corpus/d0ff24cb960cd6b725466290c98faec196340ad3 b/fuzz/cert_corpus/d0ff24cb960cd6b725466290c98faec196340ad3
deleted file mode 100644
index 1edf7107..00000000
--- a/fuzz/cert_corpus/d0ff24cb960cd6b725466290c98faec196340ad3
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0d b/fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0d
new file mode 100644
index 00000000..e18ba566
--- /dev/null
+++ b/fuzz/cert_corpus/d16735101a64c74e14692a65c2ca06abb8d9cb0d
Binary files differ
diff --git a/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c b/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c
new file mode 100644
index 00000000..bf18fc9c
--- /dev/null
+++ b/fuzz/cert_corpus/d16b443aec52814ed1678cb3b02ee561b6f1889c
Binary files differ
diff --git a/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61 b/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61
new file mode 100644
index 00000000..c439807e
--- /dev/null
+++ b/fuzz/cert_corpus/d3c601c2ca8db7dbeddb254cda2d91cadc036e61
Binary files differ
diff --git a/fuzz/cert_corpus/d5d316b2ae6ca106895ecfc4d77cab5ee403b624 b/fuzz/cert_corpus/d5d316b2ae6ca106895ecfc4d77cab5ee403b624
deleted file mode 100644
index 06143ba9..00000000
--- a/fuzz/cert_corpus/d5d316b2ae6ca106895ecfc4d77cab5ee403b624
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15 b/fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15
new file mode 100644
index 00000000..0533d26d
--- /dev/null
+++ b/fuzz/cert_corpus/d60f11bfbd2a0b5de6ca765d4059f994ec6e9c15
Binary files differ
diff --git a/fuzz/cert_corpus/d642d2788c9378b41858bfd84d8f493df5a6ed90 b/fuzz/cert_corpus/d642d2788c9378b41858bfd84d8f493df5a6ed90
deleted file mode 100644
index 53045724..00000000
--- a/fuzz/cert_corpus/d642d2788c9378b41858bfd84d8f493df5a6ed90
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d b/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d
new file mode 100644
index 00000000..ed27ac74
--- /dev/null
+++ b/fuzz/cert_corpus/d665df68474dfd7f768ac8f202455cebf498724d
Binary files differ
diff --git a/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d b/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d
new file mode 100644
index 00000000..7c91980a
--- /dev/null
+++ b/fuzz/cert_corpus/d74eeb9a616344007edfa077561a95bd1874152d
Binary files differ
diff --git a/fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796 b/fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796
new file mode 100644
index 00000000..b945a254
--- /dev/null
+++ b/fuzz/cert_corpus/d88ae7db4ae813bab4769563be5290808a004796
Binary files differ
diff --git a/fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1 b/fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1
new file mode 100644
index 00000000..8e3f12c8
--- /dev/null
+++ b/fuzz/cert_corpus/d93f2f96d294071ed098a03d86ed46d71919e7a1
Binary files differ
diff --git a/fuzz/cert_corpus/d9f35e97892b69a6b1f7053907b45bec9aaf878b b/fuzz/cert_corpus/d9f35e97892b69a6b1f7053907b45bec9aaf878b
deleted file mode 100644
index a53b38ed..00000000
--- a/fuzz/cert_corpus/d9f35e97892b69a6b1f7053907b45bec9aaf878b
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/daaf3e94dde553128327f392e512eed23d939a06 b/fuzz/cert_corpus/daaf3e94dde553128327f392e512eed23d939a06
deleted file mode 100644
index 8a36975f..00000000
--- a/fuzz/cert_corpus/daaf3e94dde553128327f392e512eed23d939a06
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/dc0186c5badd988d5ee4dd4c3013311d301d3104 b/fuzz/cert_corpus/dc0186c5badd988d5ee4dd4c3013311d301d3104
deleted file mode 100644
index 7d580565..00000000
--- a/fuzz/cert_corpus/dc0186c5badd988d5ee4dd4c3013311d301d3104
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee b/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee
new file mode 100644
index 00000000..513eabb4
--- /dev/null
+++ b/fuzz/cert_corpus/dc999ae9538c03dc88825fb62c92d98a8d8e48ee
Binary files differ
diff --git a/fuzz/cert_corpus/dce902110210d2f6bb76f2dba03e7144897f1111 b/fuzz/cert_corpus/dce902110210d2f6bb76f2dba03e7144897f1111
deleted file mode 100644
index c15d884f..00000000
--- a/fuzz/cert_corpus/dce902110210d2f6bb76f2dba03e7144897f1111
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674 b/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674
new file mode 100644
index 00000000..2f9537c0
--- /dev/null
+++ b/fuzz/cert_corpus/de0df75a8e629a16586e75477510bb7f0093f674
Binary files differ
diff --git a/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e b/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e
new file mode 100644
index 00000000..8363e7d9
--- /dev/null
+++ b/fuzz/cert_corpus/dfab8ecb3664b5c7e32ef43d24f964fd2d7aad4e
Binary files differ
diff --git a/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79 b/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79
new file mode 100644
index 00000000..af531320
--- /dev/null
+++ b/fuzz/cert_corpus/e1749e1d3e67cc947379ece199ded471a5e55c79
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945 b/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945
new file mode 100644
index 00000000..1fe7694e
--- /dev/null
+++ b/fuzz/cert_corpus/e350aef7327491a094f8a8bc3ca01ce636e9b945
Binary files differ
diff --git a/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25 b/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25
new file mode 100644
index 00000000..46ac641d
--- /dev/null
+++ b/fuzz/cert_corpus/e4c5cfd43a153699610e5456b0b58984bdc36b25
@@ -0,0 +1 @@
+00(00h1hA1h|0%0  (0*00 \ No newline at end of file
diff --git a/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3 b/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3
new file mode 100644
index 00000000..93353a7a
--- /dev/null
+++ b/fuzz/cert_corpus/e8d362075baf5e7ffa283a1f685ecfe270b756e3
Binary files differ
diff --git a/fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419 b/fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419
new file mode 100644
index 00000000..51bfe733
--- /dev/null
+++ b/fuzz/cert_corpus/ea796fb39b55459c01da8f1aa538c91b9a3e0419
Binary files differ
diff --git a/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229 b/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229
new file mode 100644
index 00000000..a6b757b1
--- /dev/null
+++ b/fuzz/cert_corpus/eb0f13db27c5f72eef417ac98c8d5b326f40d229
Binary files differ
diff --git a/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf b/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf
new file mode 100644
index 00000000..8ab90f42
--- /dev/null
+++ b/fuzz/cert_corpus/ebf19e8523e49eabc87277ada0e355d096d5cddf
Binary files differ
diff --git a/fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794 b/fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794
new file mode 100644
index 00000000..33ce1592
--- /dev/null
+++ b/fuzz/cert_corpus/ec19b8e77fa86a2aa5602a6a45a8a6df7b334794
Binary files differ
diff --git a/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22 b/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22
new file mode 100644
index 00000000..dbc33b6f
--- /dev/null
+++ b/fuzz/cert_corpus/ec32acf8f685b186fcfe11250167c70174cbea22
Binary files differ
diff --git a/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2 b/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2
new file mode 100644
index 00000000..ca67e3cc
--- /dev/null
+++ b/fuzz/cert_corpus/ec32f05544e071fea1ec748e9a5692e85a490cc2
Binary files differ
diff --git a/fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cd b/fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cd
new file mode 100644
index 00000000..71bfc737
--- /dev/null
+++ b/fuzz/cert_corpus/ec755a11cd589bdd907bbb67b83f41e3b49f42cd
Binary files differ
diff --git a/fuzz/cert_corpus/ec7f5fea97ac8cca5a49f7833769e026b55916b9 b/fuzz/cert_corpus/ec7f5fea97ac8cca5a49f7833769e026b55916b9
deleted file mode 100644
index f1233cda..00000000
--- a/fuzz/cert_corpus/ec7f5fea97ac8cca5a49f7833769e026b55916b9
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/eca7916b3e759ecd116bd761c7df90adda331bc5 b/fuzz/cert_corpus/eca7916b3e759ecd116bd761c7df90adda331bc5
deleted file mode 100644
index f9a04c2a..00000000
--- a/fuzz/cert_corpus/eca7916b3e759ecd116bd761c7df90adda331bc5
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/eccdca719eadb11048cfea5e48e5fd9fa44be622 b/fuzz/cert_corpus/eccdca719eadb11048cfea5e48e5fd9fa44be622
deleted file mode 100644
index 03ac92d4..00000000
--- a/fuzz/cert_corpus/eccdca719eadb11048cfea5e48e5fd9fa44be622
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53 b/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53
new file mode 100644
index 00000000..cda1d18c
--- /dev/null
+++ b/fuzz/cert_corpus/ed5c5806eb26764f7aa87b897ab67a1df82dbf53
Binary files differ
diff --git a/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100 b/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100
new file mode 100644
index 00000000..3e1f3783
--- /dev/null
+++ b/fuzz/cert_corpus/edf23858b6ac5eb22f6e573f9d6edae229b9c100
Binary files differ
diff --git a/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95 b/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95
new file mode 100644
index 00000000..14f5dc75
--- /dev/null
+++ b/fuzz/cert_corpus/ee895bc6274dd27e4a6f18e26d598846f4b15e95
Binary files differ
diff --git a/fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93 b/fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93
new file mode 100644
index 00000000..b6dfdc41
--- /dev/null
+++ b/fuzz/cert_corpus/efbda51a6d24e19451c4445f985b85fe04b87a93
Binary files differ
diff --git a/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44 b/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44
new file mode 100644
index 00000000..0b71f42c
--- /dev/null
+++ b/fuzz/cert_corpus/f00aedcbd7394eb866d433f49f04f6d252d3fe44
Binary files differ
diff --git a/fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987c b/fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987c
new file mode 100644
index 00000000..97bd8c94
--- /dev/null
+++ b/fuzz/cert_corpus/f00bfbc36ddb3d9cf089414ff7dcfc973927987c
Binary files differ
diff --git a/fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119 b/fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119
new file mode 100644
index 00000000..5f7013c4
--- /dev/null
+++ b/fuzz/cert_corpus/f02539e797ce16b7842fe95cfba87c44fbf92119
Binary files differ
diff --git a/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741 b/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741
new file mode 100644
index 00000000..c3a681d4
--- /dev/null
+++ b/fuzz/cert_corpus/f0cf1c8a091014b0ddd88edb3e9567370cb5d741
Binary files differ
diff --git a/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8 b/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8
new file mode 100644
index 00000000..a84f9e28
--- /dev/null
+++ b/fuzz/cert_corpus/f167e20b679ab2689a5723e39c19c33fc3b4c9e8
Binary files differ
diff --git a/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1 b/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1
new file mode 100644
index 00000000..d8bd910a
--- /dev/null
+++ b/fuzz/cert_corpus/f44630078d74ae4e135a62d7477847b24b399bf1
Binary files differ
diff --git a/fuzz/cert_corpus/f50d7ea12daaf659dc71a82e17daa9cad454be8b b/fuzz/cert_corpus/f50d7ea12daaf659dc71a82e17daa9cad454be8b
deleted file mode 100644
index d42ec512..00000000
--- a/fuzz/cert_corpus/f50d7ea12daaf659dc71a82e17daa9cad454be8b
+++ /dev/null
@@ -1 +0,0 @@
-00(00h1hAPh|0%0 (*)010 \ No newline at end of file
diff --git a/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b b/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b
new file mode 100644
index 00000000..304f5b3e
--- /dev/null
+++ b/fuzz/cert_corpus/f588df591762aeb4f9cef3e2d63ab34cbab3567b
Binary files differ
diff --git a/fuzz/cert_corpus/fb7209d187e6c93f840abfded54439ea031fe0de b/fuzz/cert_corpus/fb7209d187e6c93f840abfded54439ea031fe0de
deleted file mode 100644
index 25162473..00000000
--- a/fuzz/cert_corpus/fb7209d187e6c93f840abfded54439ea031fe0de
+++ /dev/null
Binary files differ
diff --git a/fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0 b/fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0
new file mode 100644
index 00000000..9ebce354
--- /dev/null
+++ b/fuzz/cert_corpus/fbd5fda7debfed22a821cd1c796f2ecf459a14a0
Binary files differ
diff --git a/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac b/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac
new file mode 100644
index 00000000..2d3b0ce0
--- /dev/null
+++ b/fuzz/cert_corpus/fd7e619a4b12bc64f5275b6afde1c2c1ccb8e4ac
Binary files differ
diff --git a/fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547 b/fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547
new file mode 100644
index 00000000..4bc86a27
--- /dev/null
+++ b/fuzz/cert_corpus/feba41538668e8c9eb82132ca606c0fd7f812547
Binary files differ
diff --git a/fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2 b/fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2
new file mode 100644
index 00000000..fb4165c6
--- /dev/null
+++ b/fuzz/cert_corpus/feefb266829c616c907a1d4accab0287ef47c2c2
Binary files differ
diff --git a/fuzz/client.cc b/fuzz/client.cc
index 7cf41fca..a90a8960 100644
--- a/fuzz/client.cc
+++ b/fuzz/client.cc
@@ -1,5 +1,20 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
#include <assert.h>
+#include <openssl/rand.h>
#include <openssl/ssl.h>
struct GlobalState {
@@ -15,15 +30,25 @@ struct GlobalState {
static GlobalState g_state;
extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
- // This only fuzzes the initial flow from the server so far.
+ RAND_reset_for_fuzzing();
+
SSL *client = SSL_new(g_state.ctx);
BIO *in = BIO_new(BIO_s_mem());
BIO *out = BIO_new(BIO_s_mem());
SSL_set_bio(client, in, out);
SSL_set_connect_state(client);
+ SSL_set_renegotiate_mode(client, ssl_renegotiate_freely);
BIO_write(in, buf, len);
- SSL_do_handshake(client);
+ if (SSL_do_handshake(client) == 1) {
+ // Keep reading application data until error or EOF.
+ uint8_t tmp[1024];
+ for (;;) {
+ if (SSL_read(client, tmp, sizeof(tmp)) <= 0) {
+ break;
+ }
+ }
+ }
SSL_free(client);
return 0;
diff --git a/fuzz/client_corpus/0045429528cdad90f2fea4a05a6a35311af246d8 b/fuzz/client_corpus/0045429528cdad90f2fea4a05a6a35311af246d8
deleted file mode 100644
index 7e8c0cbe..00000000
--- a/fuzz/client_corpus/0045429528cdad90f2fea4a05a6a35311af246d8
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c b/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c
new file mode 100644
index 00000000..4a6fe546
--- /dev/null
+++ b/fuzz/client_corpus/008ffccde65bd0671279ec86741c59a52e0dd87c
Binary files differ
diff --git a/fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86 b/fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86
new file mode 100644
index 00000000..d5bf92f1
--- /dev/null
+++ b/fuzz/client_corpus/00a98becb30742ad93ddeb7c851dd34f369d8e86
Binary files differ
diff --git a/fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801dee b/fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801dee
new file mode 100644
index 00000000..5400898c
--- /dev/null
+++ b/fuzz/client_corpus/02551a10425ba3ad2afdbefb411ff64aba801dee
Binary files differ
diff --git a/fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678 b/fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678
new file mode 100644
index 00000000..55cafe35
--- /dev/null
+++ b/fuzz/client_corpus/02c7b35834a45ac78a329ee5ed00bb55b2885678
Binary files differ
diff --git a/fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16 b/fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16
new file mode 100644
index 00000000..fe7e1a82
--- /dev/null
+++ b/fuzz/client_corpus/030f1cffd7e368013256e33ac467b978fbb60d16
Binary files differ
diff --git a/fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2 b/fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2
new file mode 100644
index 00000000..ed7b708f
--- /dev/null
+++ b/fuzz/client_corpus/031b3b89e72498be49f6cf81c83993686097fba2
Binary files differ
diff --git a/fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05 b/fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05
new file mode 100644
index 00000000..c77b13d6
--- /dev/null
+++ b/fuzz/client_corpus/03b58ffa513cd4ada2eab899bf1399530dd1bf05
Binary files differ
diff --git a/fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45 b/fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45
new file mode 100644
index 00000000..521b7329
--- /dev/null
+++ b/fuzz/client_corpus/03e3208240d13bdbe7f9c85e49c2059c69b35c45
Binary files differ
diff --git a/fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5 b/fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5
new file mode 100644
index 00000000..a8b3a5f7
--- /dev/null
+++ b/fuzz/client_corpus/03e6058b6fad092499130b6651f3cdf2a937eec5
Binary files differ
diff --git a/fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263 b/fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263
new file mode 100644
index 00000000..6135044c
--- /dev/null
+++ b/fuzz/client_corpus/03f8d3cd1b55f1b7ef8f9aa635a0890edbd7c263
Binary files differ
diff --git a/fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865 b/fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865
new file mode 100644
index 00000000..edd1c0c1
--- /dev/null
+++ b/fuzz/client_corpus/0513ed635daf437c5a28ca633f74646a61ca6865
Binary files differ
diff --git a/fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083 b/fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083
new file mode 100644
index 00000000..f103d21a
--- /dev/null
+++ b/fuzz/client_corpus/051cb5c1e3b99a50ff1a9b76944011402b738083
Binary files differ
diff --git a/fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078 b/fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078
new file mode 100644
index 00000000..be9f2495
--- /dev/null
+++ b/fuzz/client_corpus/052085640421d4472a5597cc6b4f86104a8c9078
Binary files differ
diff --git a/fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520 b/fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520
new file mode 100644
index 00000000..4951427b
--- /dev/null
+++ b/fuzz/client_corpus/0526966b0ebf7fe77e4dee7c39fe7f0741730520
Binary files differ
diff --git a/fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8 b/fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8
new file mode 100644
index 00000000..c6971e1a
--- /dev/null
+++ b/fuzz/client_corpus/05eb6bb7db04c88f052471a36c9937431f2e51a8
Binary files differ
diff --git a/fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343 b/fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343
new file mode 100644
index 00000000..51d53383
--- /dev/null
+++ b/fuzz/client_corpus/063c1c4256bb77dcd3abaac0dbe28071bd749343
Binary files differ
diff --git a/fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6 b/fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6
new file mode 100644
index 00000000..8a1f12b9
--- /dev/null
+++ b/fuzz/client_corpus/06e7df8edebe9b55ffe0279cc19b46b88ae76aa6
Binary files differ
diff --git a/fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3 b/fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3
new file mode 100644
index 00000000..647756f3
--- /dev/null
+++ b/fuzz/client_corpus/06fa70728c05d229e2dfa67ff3f0172feae65ff3
Binary files differ
diff --git a/fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0d b/fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0d
new file mode 100644
index 00000000..aa41f661
--- /dev/null
+++ b/fuzz/client_corpus/07559907aedb2924c0084232c2a50ce815443f0d
Binary files differ
diff --git a/fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968f b/fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968f
new file mode 100644
index 00000000..24be586d
--- /dev/null
+++ b/fuzz/client_corpus/075c12272d2e7c3b9dacac07ea89f69c76d8968f
Binary files differ
diff --git a/fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85 b/fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85
new file mode 100644
index 00000000..f5fb6cc4
--- /dev/null
+++ b/fuzz/client_corpus/07e4a83c3949fcf90947bdcb7b9f97b0d09cfc85
Binary files differ
diff --git a/fuzz/client_corpus/08166819b9de009808ba8aeeb2e11eb6d1b1bba8 b/fuzz/client_corpus/08166819b9de009808ba8aeeb2e11eb6d1b1bba8
deleted file mode 100644
index 7d3a4aed..00000000
--- a/fuzz/client_corpus/08166819b9de009808ba8aeeb2e11eb6d1b1bba8
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0a b/fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0a
new file mode 100644
index 00000000..864cb3e3
--- /dev/null
+++ b/fuzz/client_corpus/083018618734196e3979d96b571e627909d8be0a
Binary files differ
diff --git a/fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35 b/fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35
new file mode 100644
index 00000000..6fe60e8f
--- /dev/null
+++ b/fuzz/client_corpus/08310c6bd2fd887cf1f5933965c9321bc3a96b35
Binary files differ
diff --git a/fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740 b/fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740
new file mode 100644
index 00000000..64f5a9c5
--- /dev/null
+++ b/fuzz/client_corpus/08719b765365d265aae6a3ca7e5cc45e92e4c740
Binary files differ
diff --git a/fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903 b/fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903
new file mode 100644
index 00000000..5e3ca114
--- /dev/null
+++ b/fuzz/client_corpus/089063763289688a92b523abe0b21dde1dcb5903
Binary files differ
diff --git a/fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145 b/fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145
new file mode 100644
index 00000000..50b56d3d
--- /dev/null
+++ b/fuzz/client_corpus/09a8967150d2ecb7b2adb5cfacf86e754274a145
Binary files differ
diff --git a/fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099 b/fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099
new file mode 100644
index 00000000..53a2c26f
--- /dev/null
+++ b/fuzz/client_corpus/09ea428e385f7cedefdd33c6e46ded0c26eca099
Binary files differ
diff --git a/fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5 b/fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5
new file mode 100644
index 00000000..acf76c66
--- /dev/null
+++ b/fuzz/client_corpus/0a3cb64ca50c3eddeb4f38d82bb300896ce258d5
Binary files differ
diff --git a/fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103 b/fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103
new file mode 100644
index 00000000..b0bc2c56
--- /dev/null
+++ b/fuzz/client_corpus/0a44610c64874e172780e8e51b10031b0a2a4103
Binary files differ
diff --git a/fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0 b/fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0
new file mode 100644
index 00000000..7eb67c19
--- /dev/null
+++ b/fuzz/client_corpus/0a7fc3b19f7aa0892008f89d2540cfd652d924a0
Binary files differ
diff --git a/fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192 b/fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192
new file mode 100644
index 00000000..970edff3
--- /dev/null
+++ b/fuzz/client_corpus/0b1614426dcada7c22eae8bde20c9ea1955af192
Binary files differ
diff --git a/fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2 b/fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2
new file mode 100644
index 00000000..a290f8a1
--- /dev/null
+++ b/fuzz/client_corpus/0b393412092142d934bd3021e9ab95fa9c433de2
Binary files differ
diff --git a/fuzz/client_corpus/0c79672c66964d7747dbf2f2321a2e204a35f68f b/fuzz/client_corpus/0c79672c66964d7747dbf2f2321a2e204a35f68f
deleted file mode 100644
index fe8dcca2..00000000
--- a/fuzz/client_corpus/0c79672c66964d7747dbf2f2321a2e204a35f68f
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629d b/fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629d
new file mode 100644
index 00000000..d109fdd5
--- /dev/null
+++ b/fuzz/client_corpus/0ca74dfc9546ed626a103ffece16d214b0b4629d
Binary files differ
diff --git a/fuzz/client_corpus/0d5c745716044febd8eeac90ae421efc7fc52530 b/fuzz/client_corpus/0d5c745716044febd8eeac90ae421efc7fc52530
deleted file mode 100644
index f75dc5b9..00000000
--- a/fuzz/client_corpus/0d5c745716044febd8eeac90ae421efc7fc52530
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929 b/fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929
new file mode 100644
index 00000000..0060faa8
--- /dev/null
+++ b/fuzz/client_corpus/0d860a629f778931860041c502a048b562c5b929
Binary files differ
diff --git a/fuzz/client_corpus/0e8233cf1731cca3af17ab71677c477d877ac384 b/fuzz/client_corpus/0e8233cf1731cca3af17ab71677c477d877ac384
deleted file mode 100644
index f657b388..00000000
--- a/fuzz/client_corpus/0e8233cf1731cca3af17ab71677c477d877ac384
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/0ecdd5fd1d9a04965be08daa6a8df1450eb2535d b/fuzz/client_corpus/0ecdd5fd1d9a04965be08daa6a8df1450eb2535d
deleted file mode 100644
index 8780739d..00000000
--- a/fuzz/client_corpus/0ecdd5fd1d9a04965be08daa6a8df1450eb2535d
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51d b/fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51d
new file mode 100644
index 00000000..2de58f60
--- /dev/null
+++ b/fuzz/client_corpus/0ee7921127cd9571a51441816b048a4f340ac51d
Binary files differ
diff --git a/fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28 b/fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28
new file mode 100644
index 00000000..c75297db
--- /dev/null
+++ b/fuzz/client_corpus/0f14ae60b90b40bee0fec50ab06886127a245c28
Binary files differ
diff --git a/fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9f b/fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9f
new file mode 100644
index 00000000..33907868
--- /dev/null
+++ b/fuzz/client_corpus/0f7df9d0bc3a0978204d37dc4c74034e32438d9f
Binary files differ
diff --git a/fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04ad b/fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04ad
new file mode 100644
index 00000000..ced45d0b
--- /dev/null
+++ b/fuzz/client_corpus/0fd8481bfc9ea37bbd7fc33dce344bca965b04ad
Binary files differ
diff --git a/fuzz/client_corpus/0ff674842ef580cca7a5a6422808d7b698027131 b/fuzz/client_corpus/0ff674842ef580cca7a5a6422808d7b698027131
deleted file mode 100644
index c641e55c..00000000
--- a/fuzz/client_corpus/0ff674842ef580cca7a5a6422808d7b698027131
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538 b/fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538
new file mode 100644
index 00000000..0b10f635
--- /dev/null
+++ b/fuzz/client_corpus/1018b39874ea33fd123605bffa8986270e6ba538
Binary files differ
diff --git a/fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370 b/fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370
new file mode 100644
index 00000000..75defd2f
--- /dev/null
+++ b/fuzz/client_corpus/10b4b91e0940fcfaa7a4f0959f2079ed70ae7370
Binary files differ
diff --git a/fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720 b/fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720
new file mode 100644
index 00000000..4be2e154
--- /dev/null
+++ b/fuzz/client_corpus/117e20e32c26799a3228a2b1fa2cbe39c8440720
Binary files differ
diff --git a/fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8f b/fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8f
new file mode 100644
index 00000000..51b2dd8b
--- /dev/null
+++ b/fuzz/client_corpus/11a132d5dd71f67c2386cd2f6a5a256572423c8f
Binary files differ
diff --git a/fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8 b/fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8
new file mode 100644
index 00000000..d9c9522e
--- /dev/null
+++ b/fuzz/client_corpus/11d92649d0dd312e6328dd34231e4bc56ee7cfb8
Binary files differ
diff --git a/fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4a b/fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4a
new file mode 100644
index 00000000..6ae89b13
--- /dev/null
+++ b/fuzz/client_corpus/11da8204a79299f2855dbeddff540442ac33ed4a
Binary files differ
diff --git a/fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1b b/fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1b
new file mode 100644
index 00000000..f076b108
--- /dev/null
+++ b/fuzz/client_corpus/125a95886e4a7240566a17221a4453078a659d1b
Binary files differ
diff --git a/fuzz/client_corpus/1263ef52964f6480ecfb0703593b43f62ad6e0f0 b/fuzz/client_corpus/1263ef52964f6480ecfb0703593b43f62ad6e0f0
deleted file mode 100644
index 3ee72293..00000000
--- a/fuzz/client_corpus/1263ef52964f6480ecfb0703593b43f62ad6e0f0
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5e b/fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5e
new file mode 100644
index 00000000..f1b28e0c
--- /dev/null
+++ b/fuzz/client_corpus/12852dc6e23d0eb6dffa19470b4d44f0105d6a5e
Binary files differ
diff --git a/fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbb b/fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbb
new file mode 100644
index 00000000..47db6941
--- /dev/null
+++ b/fuzz/client_corpus/12a16512ec0e3937654b4d283d70c7506cbeffbb
Binary files differ
diff --git a/fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526 b/fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526
new file mode 100644
index 00000000..128abcce
--- /dev/null
+++ b/fuzz/client_corpus/1364b4aa04c2515df069617f9de27a1311e5b526
Binary files differ
diff --git a/fuzz/client_corpus/1387b2abb0baff44aa00f822361ac1627f59b0ab b/fuzz/client_corpus/1387b2abb0baff44aa00f822361ac1627f59b0ab
deleted file mode 100644
index 625e3b47..00000000
--- a/fuzz/client_corpus/1387b2abb0baff44aa00f822361ac1627f59b0ab
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49 b/fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49
new file mode 100644
index 00000000..85c35f80
--- /dev/null
+++ b/fuzz/client_corpus/13e9182cb5db0720afec91acafe85fe3bac18d49
Binary files differ
diff --git a/fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36 b/fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36
new file mode 100644
index 00000000..a0a999f7
--- /dev/null
+++ b/fuzz/client_corpus/1413c7537c6e54d1c9e36d5559eee4c6f4bebe36
Binary files differ
diff --git a/fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95e b/fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95e
new file mode 100644
index 00000000..e72dd64e
--- /dev/null
+++ b/fuzz/client_corpus/143cce6709b4f9760b89dc6920b427e2628db95e
Binary files differ
diff --git a/fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063b b/fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063b
new file mode 100644
index 00000000..2ccc8c2c
--- /dev/null
+++ b/fuzz/client_corpus/14c3e63325718a0374c028dcd127d952bd5e063b
Binary files differ
diff --git a/fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6 b/fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6
new file mode 100644
index 00000000..f7daa4e5
--- /dev/null
+++ b/fuzz/client_corpus/15bbaf9e1cd7992a03fb9e365ef92f02c0d17bb6
Binary files differ
diff --git a/fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9 b/fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9
new file mode 100644
index 00000000..d39abf05
--- /dev/null
+++ b/fuzz/client_corpus/1617afc9570c0c60a70fc6c93313203df55e35f9
Binary files differ
diff --git a/fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bf b/fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bf
new file mode 100644
index 00000000..d8682782
--- /dev/null
+++ b/fuzz/client_corpus/1635f341671bca1a04ff2a13c8c3c54f914288bf
Binary files differ
diff --git a/fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0d b/fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0d
new file mode 100644
index 00000000..07dfc9cf
--- /dev/null
+++ b/fuzz/client_corpus/16673ecbbfa4b6a7e0246386e0ee2785515ecf0d
Binary files differ
diff --git a/fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644 b/fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644
new file mode 100644
index 00000000..9292a8c2
--- /dev/null
+++ b/fuzz/client_corpus/169f2b81de0de2a0d403d21ca7f9ed0da77eb644
Binary files differ
diff --git a/fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7 b/fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7
new file mode 100644
index 00000000..2aa9ea7c
--- /dev/null
+++ b/fuzz/client_corpus/1701cb50412ff3dd90f63cc9380bdf9421a9b8c7
Binary files differ
diff --git a/fuzz/client_corpus/170cc10f660a715bbde0e00ad2d20f2c518a9716 b/fuzz/client_corpus/170cc10f660a715bbde0e00ad2d20f2c518a9716
deleted file mode 100644
index af95fa5a..00000000
--- a/fuzz/client_corpus/170cc10f660a715bbde0e00ad2d20f2c518a9716
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a b/fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a
new file mode 100644
index 00000000..2690f7dc
--- /dev/null
+++ b/fuzz/client_corpus/1731d4b7ac9ea64d9e0f7852ca94e7a6382a7f5a
Binary files differ
diff --git a/fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801 b/fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801
new file mode 100644
index 00000000..f027ddce
--- /dev/null
+++ b/fuzz/client_corpus/1737b38dda86f8045b2ec419664c9cba31d02801
Binary files differ
diff --git a/fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6dec b/fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6dec
new file mode 100644
index 00000000..cc798dea
--- /dev/null
+++ b/fuzz/client_corpus/175b59e886da4e09ecac6c84b39a6f30b37c6dec
Binary files differ
diff --git a/fuzz/client_corpus/17f8d2b61c40dd352a6fb9f72e8ab6824a992f3a b/fuzz/client_corpus/17f8d2b61c40dd352a6fb9f72e8ab6824a992f3a
deleted file mode 100644
index 0ffce93e..00000000
--- a/fuzz/client_corpus/17f8d2b61c40dd352a6fb9f72e8ab6824a992f3a
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4ae b/fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4ae
new file mode 100644
index 00000000..611f0d97
--- /dev/null
+++ b/fuzz/client_corpus/1825f52717650a3fac3cd62f5250255a83b9f4ae
Binary files differ
diff --git a/fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6d b/fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6d
new file mode 100644
index 00000000..cf4af918
--- /dev/null
+++ b/fuzz/client_corpus/1856b18ba40b75802c03e5216393950a32cdbc6d
Binary files differ
diff --git a/fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1d b/fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1d
new file mode 100644
index 00000000..de83ccce
--- /dev/null
+++ b/fuzz/client_corpus/185e35d9e0d325e70f58efa24fbee9f4edce6c1d
Binary files differ
diff --git a/fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924 b/fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924
new file mode 100644
index 00000000..672f9490
--- /dev/null
+++ b/fuzz/client_corpus/193183a77f39a2ee7a54d2cd86191fcbde1c5924
Binary files differ
diff --git a/fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7f b/fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7f
new file mode 100644
index 00000000..6712ba92
--- /dev/null
+++ b/fuzz/client_corpus/19d0710b2aeacf4904cebbc1b304cbf02bad0d7f
Binary files differ
diff --git a/fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956 b/fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956
new file mode 100644
index 00000000..0fc9d66f
--- /dev/null
+++ b/fuzz/client_corpus/1a024dc9c5d74085b76f8cad6600f4edc350b956
Binary files differ
diff --git a/fuzz/client_corpus/1acd222a42da3a075dffa389d6afb2f42b6e143b b/fuzz/client_corpus/1acd222a42da3a075dffa389d6afb2f42b6e143b
deleted file mode 100644
index b0348d4e..00000000
--- a/fuzz/client_corpus/1acd222a42da3a075dffa389d6afb2f42b6e143b
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2 b/fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2
new file mode 100644
index 00000000..d409c039
--- /dev/null
+++ b/fuzz/client_corpus/1b21a6e6a2f9b34a8ce85f0adea54578b58d48b2
Binary files differ
diff --git a/fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38 b/fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38
new file mode 100644
index 00000000..abe97d0b
--- /dev/null
+++ b/fuzz/client_corpus/1b2437add9137fd1392126d2535573a016628d38
Binary files differ
diff --git a/fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00b b/fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00b
new file mode 100644
index 00000000..0da10a93
--- /dev/null
+++ b/fuzz/client_corpus/1cac14fadaa7ae3640dd3916f3c78e3544afd00b
Binary files differ
diff --git a/fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6 b/fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6
new file mode 100644
index 00000000..c2e4bdee
--- /dev/null
+++ b/fuzz/client_corpus/1ce3af082176f17eae5a3987ea9a131c74da45e6
Binary files differ
diff --git a/fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069 b/fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069
new file mode 100644
index 00000000..6f5d62dc
--- /dev/null
+++ b/fuzz/client_corpus/1d103883a36101f8f67fd0eda2273177bd979069
Binary files differ
diff --git a/fuzz/client_corpus/1d79993946951d8c5e37daccdd793c73f8c8b7a4 b/fuzz/client_corpus/1d79993946951d8c5e37daccdd793c73f8c8b7a4
deleted file mode 100644
index a6fe745c..00000000
--- a/fuzz/client_corpus/1d79993946951d8c5e37daccdd793c73f8c8b7a4
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2 b/fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2
new file mode 100644
index 00000000..991584eb
--- /dev/null
+++ b/fuzz/client_corpus/1dba9107853637cddf377a6a07ca87c1e4cd18f2
Binary files differ
diff --git a/fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507 b/fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507
new file mode 100644
index 00000000..640ac65d
--- /dev/null
+++ b/fuzz/client_corpus/1e58390b95aa6e729013cd5ec6f67fd9410fe507
Binary files differ
diff --git a/fuzz/client_corpus/1eb2aba2bb11920007b64d8c9a2dd5f54c398591 b/fuzz/client_corpus/1eb2aba2bb11920007b64d8c9a2dd5f54c398591
deleted file mode 100644
index d898954c..00000000
--- a/fuzz/client_corpus/1eb2aba2bb11920007b64d8c9a2dd5f54c398591
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7 b/fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7
new file mode 100644
index 00000000..2300c5f1
--- /dev/null
+++ b/fuzz/client_corpus/1eeae24b70a330001a18cb1d7b3e6358b34fddd7
Binary files differ
diff --git a/fuzz/client_corpus/1f0ba9f8642a13aab05da4fb0add5257cfa0622e b/fuzz/client_corpus/1f0ba9f8642a13aab05da4fb0add5257cfa0622e
deleted file mode 100644
index d3cbd2a2..00000000
--- a/fuzz/client_corpus/1f0ba9f8642a13aab05da4fb0add5257cfa0622e
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92 b/fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92
new file mode 100644
index 00000000..f5b701c8
--- /dev/null
+++ b/fuzz/client_corpus/1f93a5e95e85c6a649ca7ed71d349ca6e04a6d92
Binary files differ
diff --git a/fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55da b/fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55da
new file mode 100644
index 00000000..4bd5216b
--- /dev/null
+++ b/fuzz/client_corpus/207778a53046b0f733160d96fc0e0a5f9d9f55da
Binary files differ
diff --git a/fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ff b/fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ff
new file mode 100644
index 00000000..4b37c8b4
--- /dev/null
+++ b/fuzz/client_corpus/209164c30c53ba6c97e2bf6f767310e540f335ff
Binary files differ
diff --git a/fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94 b/fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94
new file mode 100644
index 00000000..0abb5e71
--- /dev/null
+++ b/fuzz/client_corpus/20f99df931bffe2e70b4114d50250cfa8c32ff94
Binary files differ
diff --git a/fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b b/fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b
new file mode 100644
index 00000000..36cbefd8
--- /dev/null
+++ b/fuzz/client_corpus/212a56ac6a79d534cdf75292a9e9cd4b7c98ff9b
Binary files differ
diff --git a/fuzz/client_corpus/2188751539674238828d645bbde78b4cef2fa39c b/fuzz/client_corpus/2188751539674238828d645bbde78b4cef2fa39c
deleted file mode 100644
index e7142121..00000000
--- a/fuzz/client_corpus/2188751539674238828d645bbde78b4cef2fa39c
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73a b/fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73a
new file mode 100644
index 00000000..37070b92
--- /dev/null
+++ b/fuzz/client_corpus/21928dcf456992eb55399cd77f741a332978d73a
Binary files differ
diff --git a/fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819 b/fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819
new file mode 100644
index 00000000..5c16ae22
--- /dev/null
+++ b/fuzz/client_corpus/22363c659b583272354f371c4d0107a0d2aff819
Binary files differ
diff --git a/fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647d b/fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647d
new file mode 100644
index 00000000..1975f774
--- /dev/null
+++ b/fuzz/client_corpus/223d182dd2661a4ce650c9cff7f0dea8582b647d
Binary files differ
diff --git a/fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7 b/fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7
new file mode 100644
index 00000000..c704d4d1
--- /dev/null
+++ b/fuzz/client_corpus/2254a23660bd2a0ff02c837c37a270e59a460de7
Binary files differ
diff --git a/fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89 b/fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89
new file mode 100644
index 00000000..55cd68d3
--- /dev/null
+++ b/fuzz/client_corpus/22721e338dad9836a391790ee54b4de0cbe00c89
Binary files differ
diff --git a/fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92 b/fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92
new file mode 100644
index 00000000..c90db251
--- /dev/null
+++ b/fuzz/client_corpus/227d4ae9ca9f113f16b84ab497ca26db8fc5ce92
Binary files differ
diff --git a/fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625 b/fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625
new file mode 100644
index 00000000..6ffed455
--- /dev/null
+++ b/fuzz/client_corpus/234ff4cbcd44f84d9dc948795ee60452a0693625
Binary files differ
diff --git a/fuzz/client_corpus/236017193c5b7a862bc69756b856028eef0f10af b/fuzz/client_corpus/236017193c5b7a862bc69756b856028eef0f10af
deleted file mode 100644
index 9a475423..00000000
--- a/fuzz/client_corpus/236017193c5b7a862bc69756b856028eef0f10af
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560 b/fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560
new file mode 100644
index 00000000..2119201a
--- /dev/null
+++ b/fuzz/client_corpus/237565819ea32ff3cbad0947bbf63311e1b9a560
Binary files differ
diff --git a/fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0b b/fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0b
new file mode 100644
index 00000000..8fa6aa37
--- /dev/null
+++ b/fuzz/client_corpus/23af7fe04a1105a294ba962383a1a90895f23e0b
Binary files differ
diff --git a/fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dc b/fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dc
new file mode 100644
index 00000000..23c0f16f
--- /dev/null
+++ b/fuzz/client_corpus/2465ecbfe1070f98fd88ca6158eb3014a19e01dc
Binary files differ
diff --git a/fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740 b/fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740
new file mode 100644
index 00000000..6d4a24e8
--- /dev/null
+++ b/fuzz/client_corpus/24f2ed7e40f94ef359aa05060ee1d13ca5a26740
Binary files differ
diff --git a/fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4 b/fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4
new file mode 100644
index 00000000..d20ae105
--- /dev/null
+++ b/fuzz/client_corpus/252954f3b81c2bf8a67fcfe0e3c1647f60993be4
Binary files differ
diff --git a/fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79 b/fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79
new file mode 100644
index 00000000..65d93c03
--- /dev/null
+++ b/fuzz/client_corpus/252a34182e0b4b0f44f41e82de867242bdccea79
Binary files differ
diff --git a/fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873da b/fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873da
new file mode 100644
index 00000000..15f23cd6
--- /dev/null
+++ b/fuzz/client_corpus/259e1c5b762116d55e5369ac45c611ee06f873da
Binary files differ
diff --git a/fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129e b/fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129e
new file mode 100644
index 00000000..9d63d2f4
--- /dev/null
+++ b/fuzz/client_corpus/265cf9b5e8b582233ee53de117a953ec586a129e
Binary files differ
diff --git a/fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bb b/fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bb
new file mode 100644
index 00000000..d1440b27
--- /dev/null
+++ b/fuzz/client_corpus/2751bd28914df3bc80eabdf0a1722c01a9d9a0bb
Binary files differ
diff --git a/fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296d b/fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296d
new file mode 100644
index 00000000..8981ff13
--- /dev/null
+++ b/fuzz/client_corpus/28459cfb1e5a27160fc0a2337bae96c1c7c0296d
Binary files differ
diff --git a/fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2 b/fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2
new file mode 100644
index 00000000..7d95076e
--- /dev/null
+++ b/fuzz/client_corpus/28a6cbd11ae657e98ef2536fbdd66a5ba44ecdc2
Binary files differ
diff --git a/fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1 b/fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1
new file mode 100644
index 00000000..4ecead8a
--- /dev/null
+++ b/fuzz/client_corpus/28bb46d65faf3a8d3e112d25e7937e15571277e1
Binary files differ
diff --git a/fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7 b/fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7
new file mode 100644
index 00000000..e90ae327
--- /dev/null
+++ b/fuzz/client_corpus/294892eee3e322937e5c48a692c1a80f512f86a7
Binary files differ
diff --git a/fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807 b/fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807
new file mode 100644
index 00000000..a2aab819
--- /dev/null
+++ b/fuzz/client_corpus/296b4a799ffd5949e625d993de20aaf47045b807
Binary files differ
diff --git a/fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857f b/fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857f
new file mode 100644
index 00000000..52888481
--- /dev/null
+++ b/fuzz/client_corpus/2a74dc354366c2490747f436c3a9ece14330857f
Binary files differ
diff --git a/fuzz/client_corpus/2ac1d35580c355bdab0b951f07b1983b4bd6b981 b/fuzz/client_corpus/2ac1d35580c355bdab0b951f07b1983b4bd6b981
deleted file mode 100644
index 2e622635..00000000
--- a/fuzz/client_corpus/2ac1d35580c355bdab0b951f07b1983b4bd6b981
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9c b/fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9c
new file mode 100644
index 00000000..771e023d
--- /dev/null
+++ b/fuzz/client_corpus/2afe68d42826fa1cdad90848708c07a710658e9c
Binary files differ
diff --git a/fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8a b/fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8a
new file mode 100644
index 00000000..4300d129
--- /dev/null
+++ b/fuzz/client_corpus/2b298d34dea054df52fbec818faef171c34e1c8a
Binary files differ
diff --git a/fuzz/client_corpus/2b2b7b4cc764d2141319668022a3a220864f421e b/fuzz/client_corpus/2b2b7b4cc764d2141319668022a3a220864f421e
deleted file mode 100644
index fc533a17..00000000
--- a/fuzz/client_corpus/2b2b7b4cc764d2141319668022a3a220864f421e
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205 b/fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205
new file mode 100644
index 00000000..a2bac371
--- /dev/null
+++ b/fuzz/client_corpus/2b448ff1e24aa4da10783f03e86b58f5f8446205
Binary files differ
diff --git a/fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6 b/fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6
new file mode 100644
index 00000000..f86cdd26
--- /dev/null
+++ b/fuzz/client_corpus/2b86a76cf1318e021a59f231a72bc64b410dbea6
Binary files differ
diff --git a/fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552 b/fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552
new file mode 100644
index 00000000..9a2e4075
--- /dev/null
+++ b/fuzz/client_corpus/2c25c12a76c3fa337df33fb8523855fef69a3552
Binary files differ
diff --git a/fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8 b/fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8
new file mode 100644
index 00000000..1c2f3754
--- /dev/null
+++ b/fuzz/client_corpus/2c29b94d94502d8f305aad65c532f0e4ef6400a8
Binary files differ
diff --git a/fuzz/client_corpus/2c593c598bad54c9ec436a543910f18adfe1e40f b/fuzz/client_corpus/2c593c598bad54c9ec436a543910f18adfe1e40f
deleted file mode 100644
index ed09fe37..00000000
--- a/fuzz/client_corpus/2c593c598bad54c9ec436a543910f18adfe1e40f
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020 b/fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020
new file mode 100644
index 00000000..f148ed23
--- /dev/null
+++ b/fuzz/client_corpus/2c673d0a67080d78b85738d7494270f4e9932020
Binary files differ
diff --git a/fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aa b/fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aa
new file mode 100644
index 00000000..32b5940d
--- /dev/null
+++ b/fuzz/client_corpus/2db4737507ab67ea548413e232fb8c5edfe907aa
Binary files differ
diff --git a/fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9 b/fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9
new file mode 100644
index 00000000..5a3c2b36
--- /dev/null
+++ b/fuzz/client_corpus/2dcef28430b5fefc918a951bf28bbf996dce68e9
Binary files differ
diff --git a/fuzz/client_corpus/2e113fb2084dbb3623caaa1bc9240417eb1745e7 b/fuzz/client_corpus/2e113fb2084dbb3623caaa1bc9240417eb1745e7
deleted file mode 100644
index 1ba51f03..00000000
--- a/fuzz/client_corpus/2e113fb2084dbb3623caaa1bc9240417eb1745e7
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5 b/fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5
new file mode 100644
index 00000000..c9498f7e
--- /dev/null
+++ b/fuzz/client_corpus/2e271373d7ea8184987d5d9cb61e0dab7b8af8e5
Binary files differ
diff --git a/fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40e b/fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40e
new file mode 100644
index 00000000..9c39e12f
--- /dev/null
+++ b/fuzz/client_corpus/2e3b6c6ae461d3aaad63e918019874edd57bd40e
Binary files differ
diff --git a/fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248 b/fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248
new file mode 100644
index 00000000..b5f0b73f
--- /dev/null
+++ b/fuzz/client_corpus/2ec2f6f5530b0daf769c3a5b608d95132283c248
Binary files differ
diff --git a/fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a b/fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a
new file mode 100644
index 00000000..545c52d0
--- /dev/null
+++ b/fuzz/client_corpus/2f0549f7d7779c00cd1aaf4a69f14f96b6b0a85a
Binary files differ
diff --git a/fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66e b/fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66e
new file mode 100644
index 00000000..4abc8497
--- /dev/null
+++ b/fuzz/client_corpus/2f0c291ff5daa13064c5c7ff4a95d6785e78f66e
Binary files differ
diff --git a/fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825 b/fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825
new file mode 100644
index 00000000..deab891c
--- /dev/null
+++ b/fuzz/client_corpus/2feba4853e4f4d64baeba180780940cdf8ff1825
Binary files differ
diff --git a/fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224 b/fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224
new file mode 100644
index 00000000..a382da5c
--- /dev/null
+++ b/fuzz/client_corpus/304eea2da2a6032172159e9f43ddb21397a08224
Binary files differ
diff --git a/fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6a b/fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6a
new file mode 100644
index 00000000..f3337e21
--- /dev/null
+++ b/fuzz/client_corpus/30763ce17b7ec3d80954cf5a461743cf04238c6a
Binary files differ
diff --git a/fuzz/client_corpus/31070a7503de09885b27548828871cd7095deae6 b/fuzz/client_corpus/31070a7503de09885b27548828871cd7095deae6
deleted file mode 100644
index 2568adfd..00000000
--- a/fuzz/client_corpus/31070a7503de09885b27548828871cd7095deae6
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3 b/fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3
new file mode 100644
index 00000000..4b3568cf
--- /dev/null
+++ b/fuzz/client_corpus/318fb04e83191ad61d152cc68f6d84d0a24a66d3
Binary files differ
diff --git a/fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8 b/fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8
new file mode 100644
index 00000000..6a0d6467
--- /dev/null
+++ b/fuzz/client_corpus/31f779223bc6f44ef7a9a464fe11b31ca5abd5e8
Binary files differ
diff --git a/fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501 b/fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501
new file mode 100644
index 00000000..2ada7901
--- /dev/null
+++ b/fuzz/client_corpus/3286a72e23cd5f583a25bb5c489f12c60427d501
Binary files differ
diff --git a/fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39 b/fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39
new file mode 100644
index 00000000..25d31a9c
--- /dev/null
+++ b/fuzz/client_corpus/32e6b85afd36cbafcb3149b16da3783c5bbd8c39
Binary files differ
diff --git a/fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7c b/fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7c
new file mode 100644
index 00000000..6ea294ec
--- /dev/null
+++ b/fuzz/client_corpus/32fcabb3daaba21acf21bad494ef03b3f81f7f7c
Binary files differ
diff --git a/fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02 b/fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02
new file mode 100644
index 00000000..9a6dda01
--- /dev/null
+++ b/fuzz/client_corpus/334532c6a6e2d134c489dfa4d80989fb06172d02
Binary files differ
diff --git a/fuzz/client_corpus/3368ce768ff26ebc4e4e7b3bd1f1574afc71435f b/fuzz/client_corpus/3368ce768ff26ebc4e4e7b3bd1f1574afc71435f
deleted file mode 100644
index e23862bb..00000000
--- a/fuzz/client_corpus/3368ce768ff26ebc4e4e7b3bd1f1574afc71435f
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31 b/fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31
new file mode 100644
index 00000000..e1f29c76
--- /dev/null
+++ b/fuzz/client_corpus/34bd03730328037405744586b88c57c81992cd31
Binary files differ
diff --git a/fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9d b/fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9d
new file mode 100644
index 00000000..d1ec7b0a
--- /dev/null
+++ b/fuzz/client_corpus/34d566d2f53d0b428cd37a9a775992bc41763d9d
Binary files differ
diff --git a/fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203 b/fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203
new file mode 100644
index 00000000..6a8dd19c
--- /dev/null
+++ b/fuzz/client_corpus/361bcd77ea202443741a8c6abe135f3d430c6203
Binary files differ
diff --git a/fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbe b/fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbe
new file mode 100644
index 00000000..0000ed5c
--- /dev/null
+++ b/fuzz/client_corpus/36cc750fd326bb566cd107ddd157a6e7e191fcbe
Binary files differ
diff --git a/fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725b b/fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725b
new file mode 100644
index 00000000..e603e145
--- /dev/null
+++ b/fuzz/client_corpus/36d0151313a6b5053cb75bae03d3860dd48c725b
Binary files differ
diff --git a/fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f b/fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f
new file mode 100644
index 00000000..cb278f11
--- /dev/null
+++ b/fuzz/client_corpus/37d11e4a9d0dc08dd725a6909f4b3ccc0d904e0f
Binary files differ
diff --git a/fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8 b/fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8
new file mode 100644
index 00000000..70eb35b8
--- /dev/null
+++ b/fuzz/client_corpus/37ecd40aaea21c8d39d36ded147feb60af7a58c8
Binary files differ
diff --git a/fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14 b/fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14
new file mode 100644
index 00000000..9d0d3e4b
--- /dev/null
+++ b/fuzz/client_corpus/388e0215db4ce5142a628644b3cd431c515a1f14
Binary files differ
diff --git a/fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12 b/fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12
new file mode 100644
index 00000000..1e5ee59c
--- /dev/null
+++ b/fuzz/client_corpus/389938579b67a293b6b5176c16e7199edcd75a12
Binary files differ
diff --git a/fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5 b/fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5
new file mode 100644
index 00000000..878a30bb
--- /dev/null
+++ b/fuzz/client_corpus/38d4760261ec36cb13967bed3bd2f1914082ade5
Binary files differ
diff --git a/fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6d b/fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6d
new file mode 100644
index 00000000..204f8588
--- /dev/null
+++ b/fuzz/client_corpus/38f482657361ba8058abba483509cec9b2ba7f6d
Binary files differ
diff --git a/fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308 b/fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308
new file mode 100644
index 00000000..1f6da9c5
--- /dev/null
+++ b/fuzz/client_corpus/38fedaee7cc66c4cec5cb9c0618b6f6bfaf04308
Binary files differ
diff --git a/fuzz/client_corpus/3940f0ddcaac3b00c6ddb06c29483958214a8d08 b/fuzz/client_corpus/3940f0ddcaac3b00c6ddb06c29483958214a8d08
deleted file mode 100644
index b565129a..00000000
--- a/fuzz/client_corpus/3940f0ddcaac3b00c6ddb06c29483958214a8d08
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4 b/fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4
new file mode 100644
index 00000000..e14a8375
--- /dev/null
+++ b/fuzz/client_corpus/3965ca28906687da44123bbaf6a6c589021a80b4
Binary files differ
diff --git a/fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656 b/fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656
new file mode 100644
index 00000000..cad8ed30
--- /dev/null
+++ b/fuzz/client_corpus/3981b84969aeaa457545577ff22b6fa973c21656
Binary files differ
diff --git a/fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8 b/fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8
new file mode 100644
index 00000000..6841412d
--- /dev/null
+++ b/fuzz/client_corpus/39a56836c3a816e0e4930846af629bdbd139e8a8
Binary files differ
diff --git a/fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809 b/fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809
new file mode 100644
index 00000000..3c383519
--- /dev/null
+++ b/fuzz/client_corpus/39ab33714bd7e79f1905c2471643371bbd22b809
Binary files differ
diff --git a/fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afb b/fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afb
new file mode 100644
index 00000000..a8a32edf
--- /dev/null
+++ b/fuzz/client_corpus/3a077a02dab98581d00d2f679def27b8818b9afb
Binary files differ
diff --git a/fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491 b/fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491
new file mode 100644
index 00000000..386bfe61
--- /dev/null
+++ b/fuzz/client_corpus/3a7353d5a43ca223422a827a480d3c7faf69c491
Binary files differ
diff --git a/fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438c b/fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438c
new file mode 100644
index 00000000..40fd0a0f
--- /dev/null
+++ b/fuzz/client_corpus/3aa50d20cca6074a98c77480f27d62ef3675438c
Binary files differ
diff --git a/fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37c b/fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37c
new file mode 100644
index 00000000..102e21b5
--- /dev/null
+++ b/fuzz/client_corpus/3acf8c1831d6f97bdc31ff541fe1da11e558c37c
Binary files differ
diff --git a/fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834c b/fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834c
new file mode 100644
index 00000000..f866eac2
--- /dev/null
+++ b/fuzz/client_corpus/3b085660a48ed6743ab50e4cf21ba181487e834c
Binary files differ
diff --git a/fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990 b/fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990
new file mode 100644
index 00000000..98ea5dda
--- /dev/null
+++ b/fuzz/client_corpus/3b240f61c01265600a3a37d2be9e1ba0d9e31990
Binary files differ
diff --git a/fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba b/fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba
new file mode 100644
index 00000000..5fe2d11b
--- /dev/null
+++ b/fuzz/client_corpus/3b7b4ca1d3fd9f71d35dfeef5df35d231c9cebba
Binary files differ
diff --git a/fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512a b/fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512a
new file mode 100644
index 00000000..05f7c017
--- /dev/null
+++ b/fuzz/client_corpus/3be80948934b8980f9f6a509062820245c51512a
Binary files differ
diff --git a/fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5af b/fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5af
new file mode 100644
index 00000000..bae2b233
--- /dev/null
+++ b/fuzz/client_corpus/3c185ac9221ffa389695a41ea1cd5d6edba6f5af
Binary files differ
diff --git a/fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495 b/fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495
new file mode 100644
index 00000000..464c532d
--- /dev/null
+++ b/fuzz/client_corpus/3c3226c37487c643f0c392730627c0aef3ba1495
Binary files differ
diff --git a/fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5 b/fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5
new file mode 100644
index 00000000..daa63e18
--- /dev/null
+++ b/fuzz/client_corpus/3c32698e2d5af52bd2011d3924058834f0a34ed5
Binary files differ
diff --git a/fuzz/client_corpus/3c4871d7a5c1819913394d6997693857c117cb24 b/fuzz/client_corpus/3c4871d7a5c1819913394d6997693857c117cb24
deleted file mode 100644
index b8c600f3..00000000
--- a/fuzz/client_corpus/3c4871d7a5c1819913394d6997693857c117cb24
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353 b/fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353
new file mode 100644
index 00000000..c597f225
--- /dev/null
+++ b/fuzz/client_corpus/3c6f5c00bc1086d604ae1a50eef96cf721c62353
Binary files differ
diff --git a/fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988c b/fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988c
new file mode 100644
index 00000000..71953a95
--- /dev/null
+++ b/fuzz/client_corpus/3c72b62ed35afc086b83c81e71053a0f4ef3988c
Binary files differ
diff --git a/fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13 b/fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13
new file mode 100644
index 00000000..50ad4def
--- /dev/null
+++ b/fuzz/client_corpus/3cd1dd085b1ab7bea2586e5aaf0807d22dde5c13
Binary files differ
diff --git a/fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3beb b/fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3beb
new file mode 100644
index 00000000..b423fb98
--- /dev/null
+++ b/fuzz/client_corpus/3cffa14e490c092657bbb33af7c14a33768b3beb
Binary files differ
diff --git a/fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80 b/fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80
new file mode 100644
index 00000000..93638fea
--- /dev/null
+++ b/fuzz/client_corpus/3d63cf90bd396f0824b290f576997daf16884f80
Binary files differ
diff --git a/fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0 b/fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0
new file mode 100644
index 00000000..a1be5d88
--- /dev/null
+++ b/fuzz/client_corpus/3ed7d737427f45bd3f824c31aaa6c0b2d72c5df0
Binary files differ
diff --git a/fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6f b/fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6f
new file mode 100644
index 00000000..b96224ec
--- /dev/null
+++ b/fuzz/client_corpus/3f67156ac8c46e96a0cf59c6b7f64af25316db6f
Binary files differ
diff --git a/fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5b b/fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5b
new file mode 100644
index 00000000..02703a20
--- /dev/null
+++ b/fuzz/client_corpus/4073b68ca8908512aa7a9f71fad9866321690c5b
Binary files differ
diff --git a/fuzz/client_corpus/4105f3698152311e9e23ebec179197475c8910d4 b/fuzz/client_corpus/4105f3698152311e9e23ebec179197475c8910d4
deleted file mode 100644
index bdf45e5f..00000000
--- a/fuzz/client_corpus/4105f3698152311e9e23ebec179197475c8910d4
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5 b/fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5
new file mode 100644
index 00000000..86c55cc6
--- /dev/null
+++ b/fuzz/client_corpus/420326169b2a6c801a90fa1a414a17a461e81de5
Binary files differ
diff --git a/fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182 b/fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182
new file mode 100644
index 00000000..e55728b2
--- /dev/null
+++ b/fuzz/client_corpus/4207635e571247e374c3bac2d5cfe6d279b3c182
Binary files differ
diff --git a/fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5a b/fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5a
new file mode 100644
index 00000000..2b058751
--- /dev/null
+++ b/fuzz/client_corpus/42ec8d96c8304cc2f4a98d1670752862ea967a5a
Binary files differ
diff --git a/fuzz/client_corpus/43288d61a185406eeef5c10298a898755dd108dc b/fuzz/client_corpus/43288d61a185406eeef5c10298a898755dd108dc
deleted file mode 100644
index 451f05dd..00000000
--- a/fuzz/client_corpus/43288d61a185406eeef5c10298a898755dd108dc
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fb b/fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fb
new file mode 100644
index 00000000..7c570377
--- /dev/null
+++ b/fuzz/client_corpus/433c4b6fa77655178d8d2782e9ac59fa527ec4fb
Binary files differ
diff --git a/fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bd b/fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bd
new file mode 100644
index 00000000..72496064
--- /dev/null
+++ b/fuzz/client_corpus/43f38755fd9aeab3ac4f842c87379ea2e7c087bd
Binary files differ
diff --git a/fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8 b/fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8
new file mode 100644
index 00000000..9633d8e1
--- /dev/null
+++ b/fuzz/client_corpus/4405b79401b4338ea26a7b0f2cc43f4cf4c5c4b8
Binary files differ
diff --git a/fuzz/client_corpus/447ab5b3ef953688fc388dd37555497ce1213a4a b/fuzz/client_corpus/447ab5b3ef953688fc388dd37555497ce1213a4a
deleted file mode 100644
index 56232760..00000000
--- a/fuzz/client_corpus/447ab5b3ef953688fc388dd37555497ce1213a4a
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5 b/fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5
new file mode 100644
index 00000000..4e563408
--- /dev/null
+++ b/fuzz/client_corpus/44e7f1eae0a0e729bb6f990eceb544ba1cfde7d5
Binary files differ
diff --git a/fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872b b/fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872b
new file mode 100644
index 00000000..52dea25e
--- /dev/null
+++ b/fuzz/client_corpus/453340dfa05d4c218067a9c01d12d0c0dc05872b
Binary files differ
diff --git a/fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64 b/fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64
new file mode 100644
index 00000000..3c1d7e5f
--- /dev/null
+++ b/fuzz/client_corpus/45add649d95c14b12c577e21ae2af7f9050aaf64
Binary files differ
diff --git a/fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8 b/fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8
new file mode 100644
index 00000000..a1014550
--- /dev/null
+++ b/fuzz/client_corpus/45c53453a35ecd0c755c03936c68103b0dff17b8
Binary files differ
diff --git a/fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252 b/fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252
new file mode 100644
index 00000000..1d3933f3
--- /dev/null
+++ b/fuzz/client_corpus/45e5a626f981cca5c160850cf0a7054d6dcb7252
Binary files differ
diff --git a/fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4 b/fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4
new file mode 100644
index 00000000..82afe1b6
--- /dev/null
+++ b/fuzz/client_corpus/45f83321ca27fbb48c856bf051c5ac1b3293f5d4
Binary files differ
diff --git a/fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1 b/fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1
new file mode 100644
index 00000000..9dcc4554
--- /dev/null
+++ b/fuzz/client_corpus/461ec2d1f3724eba0fc12a620a1a3b441bde50f1
Binary files differ
diff --git a/fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cb b/fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cb
new file mode 100644
index 00000000..6c5c29d4
--- /dev/null
+++ b/fuzz/client_corpus/465d2a8214142a177aaacafc8e7da3642b7410cb
Binary files differ
diff --git a/fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8 b/fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8
new file mode 100644
index 00000000..5c2b04df
--- /dev/null
+++ b/fuzz/client_corpus/468dc35f968efd4dac4fa31bbe1f5e69bf1c7dd8
Binary files differ
diff --git a/fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552c b/fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552c
new file mode 100644
index 00000000..9beba514
--- /dev/null
+++ b/fuzz/client_corpus/470813fb2b87e90fd61f1a3e3a7046afe1ca552c
Binary files differ
diff --git a/fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418 b/fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418
new file mode 100644
index 00000000..1a1803c4
--- /dev/null
+++ b/fuzz/client_corpus/47a72fd0a7615521d4ced25c6df549288dc45418
Binary files differ
diff --git a/fuzz/client_corpus/480fa3d3cf83d7a161f4a3d863cc5b256c95b0cb b/fuzz/client_corpus/480fa3d3cf83d7a161f4a3d863cc5b256c95b0cb
deleted file mode 100644
index 5c03364c..00000000
--- a/fuzz/client_corpus/480fa3d3cf83d7a161f4a3d863cc5b256c95b0cb
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54 b/fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54
new file mode 100644
index 00000000..47553be8
--- /dev/null
+++ b/fuzz/client_corpus/48396ed7c8f8d7cb48705c22d157a43841e3bf54
Binary files differ
diff --git a/fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01d b/fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01d
new file mode 100644
index 00000000..cfc87606
--- /dev/null
+++ b/fuzz/client_corpus/48d0e70401c0f5124e8ee35ce51453c4648ea01d
Binary files differ
diff --git a/fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77 b/fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77
new file mode 100644
index 00000000..b77aff7b
--- /dev/null
+++ b/fuzz/client_corpus/48dbfc59064af6b303eaa6c6b39b92047b6e9a77
Binary files differ
diff --git a/fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4e b/fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4e
new file mode 100644
index 00000000..27eae100
--- /dev/null
+++ b/fuzz/client_corpus/4976325a6b3d9d258b512743adf4dd7ef037ae4e
Binary files differ
diff --git a/fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80 b/fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80
new file mode 100644
index 00000000..560466b0
--- /dev/null
+++ b/fuzz/client_corpus/49a3fc41e9dc84a4e693056bdfc96139d9f25f80
Binary files differ
diff --git a/fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35e b/fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35e
new file mode 100644
index 00000000..d0d8b889
--- /dev/null
+++ b/fuzz/client_corpus/49c7e584495621defd79963151fb33ebf79bc35e
Binary files differ
diff --git a/fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfd b/fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfd
new file mode 100644
index 00000000..ede296fb
--- /dev/null
+++ b/fuzz/client_corpus/4a0a0cb71589d083291ea86ebc858f8a49868cfd
Binary files differ
diff --git a/fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0 b/fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0
new file mode 100644
index 00000000..060c4a02
--- /dev/null
+++ b/fuzz/client_corpus/4a0b77fa110185719de6c967c6030acab1ba82b0
Binary files differ
diff --git a/fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8a b/fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8a
new file mode 100644
index 00000000..4b0e6965
--- /dev/null
+++ b/fuzz/client_corpus/4aa9b19fc0c44229c97649e98566b23235876c8a
Binary files differ
diff --git a/fuzz/client_corpus/4ad82ef07c3ced7fa615073827bc04a3e4969a3d b/fuzz/client_corpus/4ad82ef07c3ced7fa615073827bc04a3e4969a3d
deleted file mode 100644
index 323eb7aa..00000000
--- a/fuzz/client_corpus/4ad82ef07c3ced7fa615073827bc04a3e4969a3d
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432 b/fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432
new file mode 100644
index 00000000..db083542
--- /dev/null
+++ b/fuzz/client_corpus/4afce9787aecf1f3bfccaf89fdf65cabb504b432
Binary files differ
diff --git a/fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714 b/fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714
new file mode 100644
index 00000000..857434b2
--- /dev/null
+++ b/fuzz/client_corpus/4b2b4eef9cb2f51ba3b06799c5dd384c7373f714
Binary files differ
diff --git a/fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35 b/fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35
new file mode 100644
index 00000000..700779ad
--- /dev/null
+++ b/fuzz/client_corpus/4b9f7e74269a66abf0332cef8d0754617fdbbd35
Binary files differ
diff --git a/fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412 b/fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412
new file mode 100644
index 00000000..1f4d3ef7
--- /dev/null
+++ b/fuzz/client_corpus/4bd18d873361567417de32972a3672d54102d412
Binary files differ
diff --git a/fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178 b/fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178
new file mode 100644
index 00000000..f6583d4c
--- /dev/null
+++ b/fuzz/client_corpus/4bd886ceae40aefd8e370a126f0c9eb914fd5178
Binary files differ
diff --git a/fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42 b/fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42
new file mode 100644
index 00000000..ca65fe88
--- /dev/null
+++ b/fuzz/client_corpus/4c2e48c4b70f93db36c76fde74b5a858f90eef42
Binary files differ
diff --git a/fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc b/fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc
new file mode 100644
index 00000000..f8492631
--- /dev/null
+++ b/fuzz/client_corpus/4c2f5c72d1c9b71d6673feec2f4b3fd7b02b89dc
Binary files differ
diff --git a/fuzz/client_corpus/4c72c8bec7ac46b94757c9043197afa1b13eaa27 b/fuzz/client_corpus/4c72c8bec7ac46b94757c9043197afa1b13eaa27
deleted file mode 100644
index 7ac9309c..00000000
--- a/fuzz/client_corpus/4c72c8bec7ac46b94757c9043197afa1b13eaa27
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/4c8d920b2b9c2c43b50561b90e9c6a03689e7171 b/fuzz/client_corpus/4c8d920b2b9c2c43b50561b90e9c6a03689e7171
deleted file mode 100644
index 2c213097..00000000
--- a/fuzz/client_corpus/4c8d920b2b9c2c43b50561b90e9c6a03689e7171
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479 b/fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479
new file mode 100644
index 00000000..e3ca838a
--- /dev/null
+++ b/fuzz/client_corpus/4cb2db6b2178c7548d37ca9d2b6c1216ed0aa479
Binary files differ
diff --git a/fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866e b/fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866e
new file mode 100644
index 00000000..e69148ec
--- /dev/null
+++ b/fuzz/client_corpus/4cdf29aab0710302590f972ae90c76ab98d4866e
Binary files differ
diff --git a/fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cf b/fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cf
new file mode 100644
index 00000000..0ce3a262
--- /dev/null
+++ b/fuzz/client_corpus/4ce91349ad2d273a481bcc859277322cfe3ca2cf
Binary files differ
diff --git a/fuzz/client_corpus/4d6fed1b6f36945060b1b4f73ca29e20cf76744d b/fuzz/client_corpus/4d6fed1b6f36945060b1b4f73ca29e20cf76744d
deleted file mode 100644
index 9e0dc963..00000000
--- a/fuzz/client_corpus/4d6fed1b6f36945060b1b4f73ca29e20cf76744d
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/4dbe7996ef1b6fc26351aec25483eebfefb0c678 b/fuzz/client_corpus/4dbe7996ef1b6fc26351aec25483eebfefb0c678
deleted file mode 100644
index 27ec1e63..00000000
--- a/fuzz/client_corpus/4dbe7996ef1b6fc26351aec25483eebfefb0c678
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbe b/fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbe
new file mode 100644
index 00000000..a7122315
--- /dev/null
+++ b/fuzz/client_corpus/4dc96e80aeb3cfb40d59716db7316357a787ddbe
Binary files differ
diff --git a/fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32 b/fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32
new file mode 100644
index 00000000..50249d59
--- /dev/null
+++ b/fuzz/client_corpus/4dedc9b74663d27cb122c6dc4d1f9de031bfba32
Binary files differ
diff --git a/fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019 b/fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019
new file mode 100644
index 00000000..8ee5d90e
--- /dev/null
+++ b/fuzz/client_corpus/4dfb9236bb2c945b7f38ca2ddf80ebeb206ef019
Binary files differ
diff --git a/fuzz/client_corpus/4e53d29f05655cd0f1a746b3ddabd86e479486ff b/fuzz/client_corpus/4e53d29f05655cd0f1a746b3ddabd86e479486ff
deleted file mode 100644
index 5a70281f..00000000
--- a/fuzz/client_corpus/4e53d29f05655cd0f1a746b3ddabd86e479486ff
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249b b/fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249b
new file mode 100644
index 00000000..5607116c
--- /dev/null
+++ b/fuzz/client_corpus/4e5ca638af464b9c18f96cf68ef346a1c7f4249b
Binary files differ
diff --git a/fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13 b/fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13
new file mode 100644
index 00000000..147c292d
--- /dev/null
+++ b/fuzz/client_corpus/4f04ca4460744c01566bd82d52cc7aad444d3e13
Binary files differ
diff --git a/fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71 b/fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71
new file mode 100644
index 00000000..afa96cb6
--- /dev/null
+++ b/fuzz/client_corpus/4f4d94f986e0ef2a67b2dda1d93dfbfe95194c71
Binary files differ
diff --git a/fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9 b/fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9
new file mode 100644
index 00000000..4a750d4a
--- /dev/null
+++ b/fuzz/client_corpus/4f79b4289be8ebc7a2524bb2ac9f29098d4b73a9
Binary files differ
diff --git a/fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261d b/fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261d
new file mode 100644
index 00000000..16a5a565
--- /dev/null
+++ b/fuzz/client_corpus/4f9252d70faee72c6708fce7f5c744248fe3261d
Binary files differ
diff --git a/fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55 b/fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55
new file mode 100644
index 00000000..e9f7aa24
--- /dev/null
+++ b/fuzz/client_corpus/501d6d76ac062c912f5896543a7983bcf4253c55
Binary files differ
diff --git a/fuzz/client_corpus/505c17e142df143ed7c625dbb2a03999d335c2c4 b/fuzz/client_corpus/505c17e142df143ed7c625dbb2a03999d335c2c4
deleted file mode 100644
index 1c8b1286..00000000
--- a/fuzz/client_corpus/505c17e142df143ed7c625dbb2a03999d335c2c4
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1 b/fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1
new file mode 100644
index 00000000..df21df47
--- /dev/null
+++ b/fuzz/client_corpus/5093bef091d961c4db1461031506e734374120f1
Binary files differ
diff --git a/fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebc b/fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebc
new file mode 100644
index 00000000..f9a987ed
--- /dev/null
+++ b/fuzz/client_corpus/50ef30b0dff70dae8632b17cd493971d63a65ebc
Binary files differ
diff --git a/fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183 b/fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183
new file mode 100644
index 00000000..c326a29c
--- /dev/null
+++ b/fuzz/client_corpus/51aa8cac7aa64345016927d1f2d694926244a183
Binary files differ
diff --git a/fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78 b/fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78
new file mode 100644
index 00000000..42a236e5
--- /dev/null
+++ b/fuzz/client_corpus/51c860e1ee8f6b577aace2da887d1357df130b78
Binary files differ
diff --git a/fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3 b/fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3
new file mode 100644
index 00000000..fcc855f6
--- /dev/null
+++ b/fuzz/client_corpus/525b787309e65a8a02fd26b313f06598052a4ae3
Binary files differ
diff --git a/fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9 b/fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9
new file mode 100644
index 00000000..7bd32213
--- /dev/null
+++ b/fuzz/client_corpus/52a4a908684553c648cecb1bc85476f72aec44e9
Binary files differ
diff --git a/fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14 b/fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14
new file mode 100644
index 00000000..c020bc6d
--- /dev/null
+++ b/fuzz/client_corpus/52d54569aef7040df77bb0d484e929b927968c14
Binary files differ
diff --git a/fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350 b/fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350
new file mode 100644
index 00000000..93ad1d11
--- /dev/null
+++ b/fuzz/client_corpus/53fdf746a1ff4ca6004a67122c6667292ee01350
Binary files differ
diff --git a/fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97 b/fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97
new file mode 100644
index 00000000..eda584c1
--- /dev/null
+++ b/fuzz/client_corpus/54097c70512fcb14a736ef5049279161b86b0a97
Binary files differ
diff --git a/fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1 b/fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1
new file mode 100644
index 00000000..ab15ac21
--- /dev/null
+++ b/fuzz/client_corpus/54be5dc0bfab143c982bf41b88d21f0cbb4969e1
Binary files differ
diff --git a/fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306 b/fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306
new file mode 100644
index 00000000..14cb1ad5
--- /dev/null
+++ b/fuzz/client_corpus/5598d89f542fdc4bc2bae890b3cacc9f41373306
Binary files differ
diff --git a/fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608a b/fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608a
new file mode 100644
index 00000000..f8f6c708
--- /dev/null
+++ b/fuzz/client_corpus/55dc2b5c70c3456c6ec3806f94d960d92488608a
Binary files differ
diff --git a/fuzz/client_corpus/55e200ec05782651e9fb7034708fc21048a63cb1 b/fuzz/client_corpus/55e200ec05782651e9fb7034708fc21048a63cb1
deleted file mode 100644
index eea095d9..00000000
--- a/fuzz/client_corpus/55e200ec05782651e9fb7034708fc21048a63cb1
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44 b/fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44
new file mode 100644
index 00000000..c61a8836
--- /dev/null
+++ b/fuzz/client_corpus/56484d61a742afd778d2f6c3d515aeebe632cf44
Binary files differ
diff --git a/fuzz/client_corpus/5668dabb85cbf4c3021307c59f8aef76cf7c2cf8 b/fuzz/client_corpus/5668dabb85cbf4c3021307c59f8aef76cf7c2cf8
deleted file mode 100644
index e2b854d1..00000000
--- a/fuzz/client_corpus/5668dabb85cbf4c3021307c59f8aef76cf7c2cf8
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9c b/fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9c
new file mode 100644
index 00000000..86c8a3f9
--- /dev/null
+++ b/fuzz/client_corpus/572e7a6444bf5587b2162daa9a72f1c8f5d51e9c
Binary files differ
diff --git a/fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374a b/fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374a
new file mode 100644
index 00000000..9c51b7f8
--- /dev/null
+++ b/fuzz/client_corpus/574b435b4ef7de4bcd68e660cb470bbdc66e374a
Binary files differ
diff --git a/fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0 b/fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0
new file mode 100644
index 00000000..e83502d1
--- /dev/null
+++ b/fuzz/client_corpus/5754da205d9819c7ea49216be19802eee8e753a0
Binary files differ
diff --git a/fuzz/client_corpus/578c44a3c147de923df010f2fc2ab66509a46efb b/fuzz/client_corpus/578c44a3c147de923df010f2fc2ab66509a46efb
deleted file mode 100644
index 838d3fbb..00000000
--- a/fuzz/client_corpus/578c44a3c147de923df010f2fc2ab66509a46efb
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449 b/fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449
new file mode 100644
index 00000000..f4d35f2a
--- /dev/null
+++ b/fuzz/client_corpus/57a964488d1e20c8533345f23beb1c5c9e01d449
Binary files differ
diff --git a/fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9 b/fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9
new file mode 100644
index 00000000..1d3d292c
--- /dev/null
+++ b/fuzz/client_corpus/57bb13e7806ca27917172cc30594672f9ba207b9
Binary files differ
diff --git a/fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2 b/fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2
new file mode 100644
index 00000000..c8cfb3bc
--- /dev/null
+++ b/fuzz/client_corpus/57c5d916bf10fdd126c0e96c1069369905b58cf2
Binary files differ
diff --git a/fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4c b/fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4c
new file mode 100644
index 00000000..23eac38f
--- /dev/null
+++ b/fuzz/client_corpus/583bba681bfd0c4f7716a1ce2d20c32dfe564d4c
Binary files differ
diff --git a/fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87a b/fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87a
new file mode 100644
index 00000000..b3ea299d
--- /dev/null
+++ b/fuzz/client_corpus/596704f5b04744871e34207f99222293839ff87a
Binary files differ
diff --git a/fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47a b/fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47a
new file mode 100644
index 00000000..833ae210
--- /dev/null
+++ b/fuzz/client_corpus/5a20733c310f3909b5a809efb0f46a8b5feae47a
Binary files differ
diff --git a/fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5 b/fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5
new file mode 100644
index 00000000..1f792c6d
--- /dev/null
+++ b/fuzz/client_corpus/5a48db5a7daaf524abc694cd705d254a67422dd5
Binary files differ
diff --git a/fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fa b/fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fa
new file mode 100644
index 00000000..25b740a1
--- /dev/null
+++ b/fuzz/client_corpus/5a82000383e9b7b54a845b59252c45b3d5e033fa
Binary files differ
diff --git a/fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2 b/fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2
new file mode 100644
index 00000000..4dd8b7c6
--- /dev/null
+++ b/fuzz/client_corpus/5aeb1c91ca68e775203bad56f26fd8674dc99fd2
Binary files differ
diff --git a/fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6f b/fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6f
new file mode 100644
index 00000000..b2f3d054
--- /dev/null
+++ b/fuzz/client_corpus/5b74d4da2178f677bcbd74fff58b81d340f92e6f
Binary files differ
diff --git a/fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0 b/fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0
new file mode 100644
index 00000000..d99c7d7f
--- /dev/null
+++ b/fuzz/client_corpus/5b86351af3b24a2417c722402ebb541f59f737d0
Binary files differ
diff --git a/fuzz/client_corpus/5c3eff78d2ab5b4cabbbccedb3bde8c213b6e764 b/fuzz/client_corpus/5c3eff78d2ab5b4cabbbccedb3bde8c213b6e764
deleted file mode 100644
index b88fe33f..00000000
--- a/fuzz/client_corpus/5c3eff78d2ab5b4cabbbccedb3bde8c213b6e764
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635 b/fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635
new file mode 100644
index 00000000..2858a1a0
--- /dev/null
+++ b/fuzz/client_corpus/5c4163db4fc5f3a4ad2a9af3d2fb451c4e74c635
Binary files differ
diff --git a/fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77b b/fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77b
new file mode 100644
index 00000000..6e606ca8
--- /dev/null
+++ b/fuzz/client_corpus/5c4fa075408244af7dd819c116c275fb3bfbb77b
Binary files differ
diff --git a/fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebae b/fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebae
new file mode 100644
index 00000000..8a6d25c2
--- /dev/null
+++ b/fuzz/client_corpus/5c94616c033d0ffca7d4d5a9a21ee506af3aebae
Binary files differ
diff --git a/fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7 b/fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7
new file mode 100644
index 00000000..1a5d4474
--- /dev/null
+++ b/fuzz/client_corpus/5d7c621d353957c1f30ff0551bf103e0533ec5d7
Binary files differ
diff --git a/fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5b b/fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5b
new file mode 100644
index 00000000..0f2a1a2a
--- /dev/null
+++ b/fuzz/client_corpus/5d88975282d86be1605186c9f9390f2a97856f5b
Binary files differ
diff --git a/fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3a b/fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3a
new file mode 100644
index 00000000..d618dcb6
--- /dev/null
+++ b/fuzz/client_corpus/5dcf69ec2d27aa65a270aa75b893bfa843379c3a
Binary files differ
diff --git a/fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6 b/fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6
new file mode 100644
index 00000000..a3ce2152
--- /dev/null
+++ b/fuzz/client_corpus/5e541fdc01b0b57e4f642af19a8dcada95fc7af6
Binary files differ
diff --git a/fuzz/client_corpus/5e5aac66a37640a8f570abd028adfdd9b50ba75a b/fuzz/client_corpus/5e5aac66a37640a8f570abd028adfdd9b50ba75a
deleted file mode 100644
index dea3c653..00000000
--- a/fuzz/client_corpus/5e5aac66a37640a8f570abd028adfdd9b50ba75a
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331 b/fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331
new file mode 100644
index 00000000..8bd49e6b
--- /dev/null
+++ b/fuzz/client_corpus/5e84e44562a78a2ac27ff90e26bcc5a33835e331
Binary files differ
diff --git a/fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28 b/fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28
new file mode 100644
index 00000000..a720c7aa
--- /dev/null
+++ b/fuzz/client_corpus/5ecd7fa21205cd75112a2182955dc33dc1befd28
Binary files differ
diff --git a/fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925 b/fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925
new file mode 100644
index 00000000..512e6e66
--- /dev/null
+++ b/fuzz/client_corpus/5f2456ab7aa81a53b89e0af7455db660c54ac925
Binary files differ
diff --git a/fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5 b/fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5
new file mode 100644
index 00000000..95774804
--- /dev/null
+++ b/fuzz/client_corpus/5f3f171c9d7370fc11a2d31925bfec08286dbaf5
Binary files differ
diff --git a/fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabe b/fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabe
new file mode 100644
index 00000000..aa3ca396
--- /dev/null
+++ b/fuzz/client_corpus/5fd69dd2daac7ec11fa9bc6789263ab658a5eabe
Binary files differ
diff --git a/fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34b b/fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34b
new file mode 100644
index 00000000..282fce40
--- /dev/null
+++ b/fuzz/client_corpus/6163978844f3de0ffe06c5da0d2ac19d93a1a34b
Binary files differ
diff --git a/fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4b b/fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4b
new file mode 100644
index 00000000..f7404244
--- /dev/null
+++ b/fuzz/client_corpus/6173cc33be71450af930872b0029d42f7f9a9e4b
Binary files differ
diff --git a/fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c b/fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c
new file mode 100644
index 00000000..c392c86f
--- /dev/null
+++ b/fuzz/client_corpus/624cdac358ae1bfd8fe7ee1c42c7ac79a549d78c
Binary files differ
diff --git a/fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03 b/fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03
new file mode 100644
index 00000000..429ab1e4
--- /dev/null
+++ b/fuzz/client_corpus/624e7bf21953e5ad0f95669086842161f2f86e03
Binary files differ
diff --git a/fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418 b/fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418
new file mode 100644
index 00000000..9d367a8a
--- /dev/null
+++ b/fuzz/client_corpus/6264654e1126813ba22fb14a3be0752b488fd418
Binary files differ
diff --git a/fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08 b/fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08
new file mode 100644
index 00000000..e02b353f
--- /dev/null
+++ b/fuzz/client_corpus/6276b4e7495a620b384250f61dd5264698cc0a08
Binary files differ
diff --git a/fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343 b/fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343
new file mode 100644
index 00000000..1ee9c459
--- /dev/null
+++ b/fuzz/client_corpus/62a932027da8c0b8ab694b888aa2050de3883343
Binary files differ
diff --git a/fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56 b/fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56
new file mode 100644
index 00000000..ea091552
--- /dev/null
+++ b/fuzz/client_corpus/62ac547e0a1d58293db58e3f3c23505b08029e56
Binary files differ
diff --git a/fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a b/fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a
new file mode 100644
index 00000000..396d0be2
--- /dev/null
+++ b/fuzz/client_corpus/63d2f2cd51b3851f6e2f115a717b5da3bed6dc5a
Binary files differ
diff --git a/fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6 b/fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6
new file mode 100644
index 00000000..d89447b2
--- /dev/null
+++ b/fuzz/client_corpus/64382d709a4f6a87cb58fcccc0ad716207d409b6
Binary files differ
diff --git a/fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6 b/fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6
new file mode 100644
index 00000000..397a811f
--- /dev/null
+++ b/fuzz/client_corpus/64a109fad628c758f34cb85efb00dca77826b9f6
Binary files differ
diff --git a/fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9 b/fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9
new file mode 100644
index 00000000..c72a093a
--- /dev/null
+++ b/fuzz/client_corpus/64d2d203ec77b22c80b0587a19bd157f609408b9
Binary files differ
diff --git a/fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341a b/fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341a
new file mode 100644
index 00000000..24d03e82
--- /dev/null
+++ b/fuzz/client_corpus/65232590b25ceebb4287ca8108142578ff4e341a
Binary files differ
diff --git a/fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7d b/fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7d
new file mode 100644
index 00000000..565c28c5
--- /dev/null
+++ b/fuzz/client_corpus/6539b554ad60eeffa97fa4024d2ee8dac1800a7d
Binary files differ
diff --git a/fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caa b/fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caa
new file mode 100644
index 00000000..f337ba06
--- /dev/null
+++ b/fuzz/client_corpus/65b1680687a0ba3ba4d53917b4a07a22f2b45caa
Binary files differ
diff --git a/fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561 b/fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561
new file mode 100644
index 00000000..157cff56
--- /dev/null
+++ b/fuzz/client_corpus/65d29e0e9f26b5a95f68c3c8bb7d52b7baad2561
Binary files differ
diff --git a/fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851a b/fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851a
new file mode 100644
index 00000000..3fa3f288
--- /dev/null
+++ b/fuzz/client_corpus/665c6dc07ff4414425a77a786be26280af20851a
Binary files differ
diff --git a/fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153a b/fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153a
new file mode 100644
index 00000000..57d4ee33
--- /dev/null
+++ b/fuzz/client_corpus/6682e09c97ef156e808ad63e3a5dd9030146153a
Binary files differ
diff --git a/fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6b b/fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6b
new file mode 100644
index 00000000..ed970902
--- /dev/null
+++ b/fuzz/client_corpus/669dfafe89414c0056ffa214d4ef4c1405d01c6b
Binary files differ
diff --git a/fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613 b/fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613
new file mode 100644
index 00000000..569ccf81
--- /dev/null
+++ b/fuzz/client_corpus/67201a0dcd94ff51530eaf8d43982203d8cc3613
Binary files differ
diff --git a/fuzz/client_corpus/674253e9d5eacc5c0133fe872f32c2e8a2ea4cf7 b/fuzz/client_corpus/674253e9d5eacc5c0133fe872f32c2e8a2ea4cf7
deleted file mode 100644
index 3c47eb7e..00000000
--- a/fuzz/client_corpus/674253e9d5eacc5c0133fe872f32c2e8a2ea4cf7
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2 b/fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2
new file mode 100644
index 00000000..92195afa
--- /dev/null
+++ b/fuzz/client_corpus/67740cc59121af29e2b57f491c6dfaf9e54a16f2
Binary files differ
diff --git a/fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545 b/fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545
new file mode 100644
index 00000000..1f82642b
--- /dev/null
+++ b/fuzz/client_corpus/67c56ee635a2f54a05120f7f741b6de3b8416545
Binary files differ
diff --git a/fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12 b/fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12
new file mode 100644
index 00000000..03fb0d03
--- /dev/null
+++ b/fuzz/client_corpus/67ec3a092c013c1901c6056982c4b3c2d4345b12
Binary files differ
diff --git a/fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80 b/fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80
new file mode 100644
index 00000000..d17b0978
--- /dev/null
+++ b/fuzz/client_corpus/681a06e9ae918b77088a6c41e2084a7065fb4a80
Binary files differ
diff --git a/fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11b b/fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11b
new file mode 100644
index 00000000..5b40dfce
--- /dev/null
+++ b/fuzz/client_corpus/68d08ed34adbab401519c4a6b457edf839a8e11b
Binary files differ
diff --git a/fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62 b/fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62
new file mode 100644
index 00000000..a378c89b
--- /dev/null
+++ b/fuzz/client_corpus/692e389e27b91478ee30ab6966720c8e42198b62
Binary files differ
diff --git a/fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277 b/fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277
new file mode 100644
index 00000000..dc78ff9e
--- /dev/null
+++ b/fuzz/client_corpus/69301c0fab85b8afd0c235a97125acb36f259277
Binary files differ
diff --git a/fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262 b/fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262
new file mode 100644
index 00000000..c153fc46
--- /dev/null
+++ b/fuzz/client_corpus/693212f1a1e378e4020ee13126b4ee8df4ce9262
Binary files differ
diff --git a/fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbd b/fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbd
new file mode 100644
index 00000000..86e8e6e6
--- /dev/null
+++ b/fuzz/client_corpus/693a6ddbf67b0835d90ca231b9d68d9f2cccffbd
Binary files differ
diff --git a/fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960a b/fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960a
new file mode 100644
index 00000000..f843b13f
--- /dev/null
+++ b/fuzz/client_corpus/69a10fd0965617fda08b1ff2bf80999a51b8960a
Binary files differ
diff --git a/fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045 b/fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045
new file mode 100644
index 00000000..10c32239
--- /dev/null
+++ b/fuzz/client_corpus/6a09a081020b1d5bdad5c981af10066d4ed4b045
Binary files differ
diff --git a/fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecf b/fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecf
new file mode 100644
index 00000000..88ddabdf
--- /dev/null
+++ b/fuzz/client_corpus/6a4404e833ba7eef96eec09b54978858661acecf
Binary files differ
diff --git a/fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822 b/fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822
new file mode 100644
index 00000000..a3b3cbe6
--- /dev/null
+++ b/fuzz/client_corpus/6a5e936ffd7eba1efe6b7aa54b5beff373272822
Binary files differ
diff --git a/fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312 b/fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312
new file mode 100644
index 00000000..c8adab10
--- /dev/null
+++ b/fuzz/client_corpus/6a75638c3215e638e82bbc28c3fc523bda75f312
Binary files differ
diff --git a/fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2e b/fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2e
new file mode 100644
index 00000000..d8eae636
--- /dev/null
+++ b/fuzz/client_corpus/6bbd392cd841bb74dbba1190cab5066d5ecd9b2e
Binary files differ
diff --git a/fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463b b/fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463b
new file mode 100644
index 00000000..fdb0dd9c
--- /dev/null
+++ b/fuzz/client_corpus/6bdc8def26589304a945125ceb8bcb15b55d463b
Binary files differ
diff --git a/fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363df b/fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363df
new file mode 100644
index 00000000..30776e99
--- /dev/null
+++ b/fuzz/client_corpus/6cbd0fd179a77260e246c45f424a769b951363df
Binary files differ
diff --git a/fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5a b/fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5a
new file mode 100644
index 00000000..b6dbf0ff
--- /dev/null
+++ b/fuzz/client_corpus/6cdbc5f074be9de313240590e337c7733f3bcb5a
Binary files differ
diff --git a/fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcad b/fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcad
new file mode 100644
index 00000000..d7fa9cfe
--- /dev/null
+++ b/fuzz/client_corpus/6d7de8f65158095884723fb0b1a4dd9bb1e4bcad
Binary files differ
diff --git a/fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eec b/fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eec
new file mode 100644
index 00000000..431a77b8
--- /dev/null
+++ b/fuzz/client_corpus/6ed3b3793181c3319bacd290bc05190cfd944eec
Binary files differ
diff --git a/fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771 b/fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771
new file mode 100644
index 00000000..013cadca
--- /dev/null
+++ b/fuzz/client_corpus/6efd3899822aa131578394f89fb5c8fd17d14771
Binary files differ
diff --git a/fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7 b/fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7
new file mode 100644
index 00000000..41b11c3f
--- /dev/null
+++ b/fuzz/client_corpus/6f2c69f7cc2c99cb694c37710c7b46104906aff7
Binary files differ
diff --git a/fuzz/client_corpus/6fca24aa17c9d63a109d89bf05f7cf847fd3de7e b/fuzz/client_corpus/6fca24aa17c9d63a109d89bf05f7cf847fd3de7e
deleted file mode 100644
index 70cf4ac0..00000000
--- a/fuzz/client_corpus/6fca24aa17c9d63a109d89bf05f7cf847fd3de7e
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/700a646ead0f82d584b5bc69901ea3a4d6dbee52 b/fuzz/client_corpus/700a646ead0f82d584b5bc69901ea3a4d6dbee52
deleted file mode 100644
index c65edc08..00000000
--- a/fuzz/client_corpus/700a646ead0f82d584b5bc69901ea3a4d6dbee52
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/7072ff5269664a33f709ca3fc6bb158667c3c421 b/fuzz/client_corpus/7072ff5269664a33f709ca3fc6bb158667c3c421
deleted file mode 100644
index a70def5f..00000000
--- a/fuzz/client_corpus/7072ff5269664a33f709ca3fc6bb158667c3c421
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5 b/fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5
new file mode 100644
index 00000000..bf764558
--- /dev/null
+++ b/fuzz/client_corpus/709b1199449d8138c4936b95179ba12fbb9a68d5
Binary files differ
diff --git a/fuzz/client_corpus/71050f1658866c73590296856c498f54087519cc b/fuzz/client_corpus/71050f1658866c73590296856c498f54087519cc
new file mode 100644
index 00000000..227a07b2
--- /dev/null
+++ b/fuzz/client_corpus/71050f1658866c73590296856c498f54087519cc
Binary files differ
diff --git a/fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864 b/fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864
new file mode 100644
index 00000000..a26d494f
--- /dev/null
+++ b/fuzz/client_corpus/71432178fa30339f80d4fe0b95ca40886ea4b864
Binary files differ
diff --git a/fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4a b/fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4a
new file mode 100644
index 00000000..8f10bcc2
--- /dev/null
+++ b/fuzz/client_corpus/715f569f1599e0fec12773fec26c7cc3cddbec4a
Binary files differ
diff --git a/fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388 b/fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388
new file mode 100644
index 00000000..12442072
--- /dev/null
+++ b/fuzz/client_corpus/7166e8b36a98dc10904f0a92bee9c729ef454388
Binary files differ
diff --git a/fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1 b/fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1
new file mode 100644
index 00000000..ca083559
--- /dev/null
+++ b/fuzz/client_corpus/716737b5ca18f7589bdc492806e84bafbf7822e1
Binary files differ
diff --git a/fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7 b/fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7
new file mode 100644
index 00000000..b942cd14
--- /dev/null
+++ b/fuzz/client_corpus/71983e3b061a3211f83e36cccaf8be3d61e3ade7
Binary files differ
diff --git a/fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066 b/fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066
new file mode 100644
index 00000000..a62786d4
--- /dev/null
+++ b/fuzz/client_corpus/725174c7260ca145c5513b1f8277581ad80d8066
Binary files differ
diff --git a/fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2 b/fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2
new file mode 100644
index 00000000..723da2ba
--- /dev/null
+++ b/fuzz/client_corpus/7268bdfc00cc1a2c768d4c9c13cca51538d3f6e2
Binary files differ
diff --git a/fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4 b/fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4
new file mode 100644
index 00000000..301ae4be
--- /dev/null
+++ b/fuzz/client_corpus/7312c2e60d9d48602429f06752f2c1856b2484a4
Binary files differ
diff --git a/fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14b b/fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14b
new file mode 100644
index 00000000..3af5fc4b
--- /dev/null
+++ b/fuzz/client_corpus/73641c2c728554997a9a97544e207a235111d14b
Binary files differ
diff --git a/fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5 b/fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5
new file mode 100644
index 00000000..c140b5ef
--- /dev/null
+++ b/fuzz/client_corpus/73786b6e81d47e740623eb11e031c685c239d8e5
Binary files differ
diff --git a/fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0 b/fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0
new file mode 100644
index 00000000..5ee48c8a
--- /dev/null
+++ b/fuzz/client_corpus/7454f672d5cea5dade5e712090b552ca39a3cbe0
Binary files differ
diff --git a/fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6c b/fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6c
new file mode 100644
index 00000000..40bc2119
--- /dev/null
+++ b/fuzz/client_corpus/745e5941c0812aa48b525e64969d6960c3f86d6c
Binary files differ
diff --git a/fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43 b/fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43
new file mode 100644
index 00000000..51bca855
--- /dev/null
+++ b/fuzz/client_corpus/7460a3a91f807e0c47725fe6d856219c9b1a3f43
Binary files differ
diff --git a/fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4 b/fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4
new file mode 100644
index 00000000..936f18e6
--- /dev/null
+++ b/fuzz/client_corpus/74f4656ef6630ddae9353e0989f10d9c8f37edb4
Binary files differ
diff --git a/fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20 b/fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20
new file mode 100644
index 00000000..5281f5a5
--- /dev/null
+++ b/fuzz/client_corpus/750e5dd452c8bc44976eae6b99463b951cf3ed20
Binary files differ
diff --git a/fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24 b/fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24
new file mode 100644
index 00000000..c90c9241
--- /dev/null
+++ b/fuzz/client_corpus/75629895fd19a7ff9492e93a6d2aae0de33b6a24
Binary files differ
diff --git a/fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186cc b/fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186cc
new file mode 100644
index 00000000..5b85fe59
--- /dev/null
+++ b/fuzz/client_corpus/75a37a2cdee4ac71d0996720b3c9adf50da186cc
Binary files differ
diff --git a/fuzz/client_corpus/75d5755e499a739b66987b12149f914e04227fda b/fuzz/client_corpus/75d5755e499a739b66987b12149f914e04227fda
deleted file mode 100644
index becf8648..00000000
--- a/fuzz/client_corpus/75d5755e499a739b66987b12149f914e04227fda
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7 b/fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7
new file mode 100644
index 00000000..ac6e7b2c
--- /dev/null
+++ b/fuzz/client_corpus/7643869fe4d74ef2e262015d55ea60dc08f072b7
Binary files differ
diff --git a/fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769 b/fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769
new file mode 100644
index 00000000..46e86850
--- /dev/null
+++ b/fuzz/client_corpus/76ad1888b6ab0433924386fc74ec9668f08d3769
Binary files differ
diff --git a/fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254 b/fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254
new file mode 100644
index 00000000..b03996b4
--- /dev/null
+++ b/fuzz/client_corpus/76b77a87e73f5fd403af0cb73ad2b8bbcd572254
Binary files differ
diff --git a/fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4 b/fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4
new file mode 100644
index 00000000..efc7bfd8
--- /dev/null
+++ b/fuzz/client_corpus/76f0e061914c0fe572963f0cc404d49121ec57a4
Binary files differ
diff --git a/fuzz/client_corpus/7753dbbdf3391950f08197d3158ee144b58ae9d4 b/fuzz/client_corpus/7753dbbdf3391950f08197d3158ee144b58ae9d4
deleted file mode 100644
index 12d2ded5..00000000
--- a/fuzz/client_corpus/7753dbbdf3391950f08197d3158ee144b58ae9d4
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29 b/fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29
new file mode 100644
index 00000000..9974766d
--- /dev/null
+++ b/fuzz/client_corpus/7757a4fcd5642fb0ac1f0230ced865a8546a9c29
Binary files differ
diff --git a/fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9 b/fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9
new file mode 100644
index 00000000..21c06f6c
--- /dev/null
+++ b/fuzz/client_corpus/77a1114a47681f3f3cf0f65aa2f4645214b5c7c9
Binary files differ
diff --git a/fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6 b/fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6
new file mode 100644
index 00000000..7a1a684a
--- /dev/null
+++ b/fuzz/client_corpus/77aa55183550820d02557f4a09c688cfe6c2b5f6
Binary files differ
diff --git a/fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088 b/fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088
new file mode 100644
index 00000000..785e71e9
--- /dev/null
+++ b/fuzz/client_corpus/78623435559dd4f83050c3a5743c0652d2b47088
Binary files differ
diff --git a/fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef b/fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef
new file mode 100644
index 00000000..8871626f
--- /dev/null
+++ b/fuzz/client_corpus/789d5b07e2685ea9b9dec86f6d4026ac3edaf4ef
Binary files differ
diff --git a/fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3 b/fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3
new file mode 100644
index 00000000..81f1adc1
--- /dev/null
+++ b/fuzz/client_corpus/78d330c46e50c13cae9560065fa4cc7bcac8dcb3
Binary files differ
diff --git a/fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210b b/fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210b
new file mode 100644
index 00000000..ff3a16aa
--- /dev/null
+++ b/fuzz/client_corpus/790ffe47b5b84c76762f6b95eb51467844ef210b
Binary files differ
diff --git a/fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40 b/fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40
new file mode 100644
index 00000000..870a7e9f
--- /dev/null
+++ b/fuzz/client_corpus/79153550be1dc1365a10a08792f49b02a9c56c40
Binary files differ
diff --git a/fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35 b/fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35
new file mode 100644
index 00000000..87b443e2
--- /dev/null
+++ b/fuzz/client_corpus/79f2cafab7df9ff93fbd71edd2049f431f478a35
Binary files differ
diff --git a/fuzz/client_corpus/79ff7a233e149ae13d67905eda9e5af4ed27fbe0 b/fuzz/client_corpus/79ff7a233e149ae13d67905eda9e5af4ed27fbe0
deleted file mode 100644
index 9a8a5114..00000000
--- a/fuzz/client_corpus/79ff7a233e149ae13d67905eda9e5af4ed27fbe0
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913 b/fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913
new file mode 100644
index 00000000..1215f8ed
--- /dev/null
+++ b/fuzz/client_corpus/7a13e0426d9dbdfeb38d83eb5a51d48e5de38913
Binary files differ
diff --git a/fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0 b/fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0
new file mode 100644
index 00000000..43c16870
--- /dev/null
+++ b/fuzz/client_corpus/7a5e12eb4b25a0c9687e38e614f062a5e74ff7d0
Binary files differ
diff --git a/fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853b b/fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853b
new file mode 100644
index 00000000..49a6534d
--- /dev/null
+++ b/fuzz/client_corpus/7a7c19fbe0835087aaa22bc29bc713d825a4853b
Binary files differ
diff --git a/fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578 b/fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578
new file mode 100644
index 00000000..a6e06f42
--- /dev/null
+++ b/fuzz/client_corpus/7b1989a53e27b944b1f3a71ba37b95bf65502578
Binary files differ
diff --git a/fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5d b/fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5d
new file mode 100644
index 00000000..ddd0b6c8
--- /dev/null
+++ b/fuzz/client_corpus/7b1fb1cf0c4afa24743bc18c43d810383ff35b5d
Binary files differ
diff --git a/fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0 b/fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0
new file mode 100644
index 00000000..33c6c3f3
--- /dev/null
+++ b/fuzz/client_corpus/7ba00c13f3af17b2f767423f969827ed237674f0
Binary files differ
diff --git a/fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256 b/fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256
new file mode 100644
index 00000000..452c868e
--- /dev/null
+++ b/fuzz/client_corpus/7baeee7bae72e0d0df2d314544e7476afffd9256
Binary files differ
diff --git a/fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01e b/fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01e
new file mode 100644
index 00000000..bbe73a0b
--- /dev/null
+++ b/fuzz/client_corpus/7c833d2738d69dd0303fd774e425c0da8da5b01e
Binary files differ
diff --git a/fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320d b/fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320d
new file mode 100644
index 00000000..629a978b
--- /dev/null
+++ b/fuzz/client_corpus/7cc04676ba336d7e15e837b9c7648e804b1b320d
Binary files differ
diff --git a/fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053 b/fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053
new file mode 100644
index 00000000..8e15f2e7
--- /dev/null
+++ b/fuzz/client_corpus/7cd0efd7b6d2fb98673ad3cf4b663bcefda82053
Binary files differ
diff --git a/fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26 b/fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26
new file mode 100644
index 00000000..8d20715c
--- /dev/null
+++ b/fuzz/client_corpus/7d13671b71b0f71496a2e17bdc503826bd4d0c26
Binary files differ
diff --git a/fuzz/client_corpus/7d3b5ce72e5374d1771f33b19dbc5ed20f423aeb b/fuzz/client_corpus/7d3b5ce72e5374d1771f33b19dbc5ed20f423aeb
deleted file mode 100644
index ed069ac1..00000000
--- a/fuzz/client_corpus/7d3b5ce72e5374d1771f33b19dbc5ed20f423aeb
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63 b/fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63
new file mode 100644
index 00000000..02e8ff55
--- /dev/null
+++ b/fuzz/client_corpus/7d7637cadd57353b459108088ad62bd7746fca63
Binary files differ
diff --git a/fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0 b/fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0
new file mode 100644
index 00000000..584dec85
--- /dev/null
+++ b/fuzz/client_corpus/7d82bcecfa30a487dd52bd4dd8461304d7d499e0
Binary files differ
diff --git a/fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87ba b/fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87ba
new file mode 100644
index 00000000..f29cd226
--- /dev/null
+++ b/fuzz/client_corpus/7d8bfe2499bea27ee16d1dbeb1707037b99a87ba
Binary files differ
diff --git a/fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044d b/fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044d
new file mode 100644
index 00000000..4c37ee56
--- /dev/null
+++ b/fuzz/client_corpus/7db2e5e257d7891667d78cb272ca3ec3b6dc044d
Binary files differ
diff --git a/fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817b b/fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817b
new file mode 100644
index 00000000..5449d261
--- /dev/null
+++ b/fuzz/client_corpus/7dbb31067130270f15c56b92f50d21818e4e817b
Binary files differ
diff --git a/fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1ea b/fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1ea
new file mode 100644
index 00000000..b29adf3d
--- /dev/null
+++ b/fuzz/client_corpus/7e1e374599e9ff2d515754b718b3e959966ac1ea
Binary files differ
diff --git a/fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa b/fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa
new file mode 100644
index 00000000..a2fc83a0
--- /dev/null
+++ b/fuzz/client_corpus/7ea89e4a96e2deadf8b9ca3e81d0f886dabdebfa
Binary files differ
diff --git a/fuzz/client_corpus/7f080ab49b7b5feb09319aa348413686b20b8394 b/fuzz/client_corpus/7f080ab49b7b5feb09319aa348413686b20b8394
deleted file mode 100644
index e6b01c0b..00000000
--- a/fuzz/client_corpus/7f080ab49b7b5feb09319aa348413686b20b8394
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca b/fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca
new file mode 100644
index 00000000..b27f1fa1
--- /dev/null
+++ b/fuzz/client_corpus/7f0f43b60dbb78b847fc67e352f7ce8d0eac57ca
Binary files differ
diff --git a/fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86 b/fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86
new file mode 100644
index 00000000..cf2d7971
--- /dev/null
+++ b/fuzz/client_corpus/7f6ab5401afb02d08c34b835ce95d4f886c50a86
Binary files differ
diff --git a/fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205 b/fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205
new file mode 100644
index 00000000..1578b008
--- /dev/null
+++ b/fuzz/client_corpus/7fd3e12d7776e72ea2a347d1a546f4e17275e205
Binary files differ
diff --git a/fuzz/client_corpus/7fd9affa725bf314f60d28ae06bcc038b7dc3dd0 b/fuzz/client_corpus/7fd9affa725bf314f60d28ae06bcc038b7dc3dd0
deleted file mode 100644
index b865a8b1..00000000
--- a/fuzz/client_corpus/7fd9affa725bf314f60d28ae06bcc038b7dc3dd0
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6 b/fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6
new file mode 100644
index 00000000..f4fc7c21
--- /dev/null
+++ b/fuzz/client_corpus/80003831f114e372c44f168f26e192100b8bc4c6
Binary files differ
diff --git a/fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571 b/fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571
new file mode 100644
index 00000000..9f1f4327
--- /dev/null
+++ b/fuzz/client_corpus/809b64143ccfb187a639440e8a49dc061733c571
Binary files differ
diff --git a/fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727 b/fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727
new file mode 100644
index 00000000..39b05ac9
--- /dev/null
+++ b/fuzz/client_corpus/81860583db2f2f8e3492dbe683063e2bc7c6a727
Binary files differ
diff --git a/fuzz/client_corpus/819b64ad6fe9da24271678ecf337427fe17e95b2 b/fuzz/client_corpus/819b64ad6fe9da24271678ecf337427fe17e95b2
deleted file mode 100644
index 868b4539..00000000
--- a/fuzz/client_corpus/819b64ad6fe9da24271678ecf337427fe17e95b2
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270 b/fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270
new file mode 100644
index 00000000..6ddbde5e
--- /dev/null
+++ b/fuzz/client_corpus/81b11d6d83e00df6595eed84463b910f30d77270
Binary files differ
diff --git a/fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62 b/fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62
new file mode 100644
index 00000000..4e4acbe8
--- /dev/null
+++ b/fuzz/client_corpus/81d289fdfa9a0ae60dcbe3b67db2b33db6159a62
Binary files differ
diff --git a/fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182d b/fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182d
new file mode 100644
index 00000000..3878eb46
--- /dev/null
+++ b/fuzz/client_corpus/81df12ca53a2432e288b18c6c00af52b8769182d
Binary files differ
diff --git a/fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8 b/fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8
new file mode 100644
index 00000000..037f23db
--- /dev/null
+++ b/fuzz/client_corpus/821820b20f0fbbe3a958e4b9ab2a13e958a7e3e8
Binary files differ
diff --git a/fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116 b/fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116
new file mode 100644
index 00000000..b668fe63
--- /dev/null
+++ b/fuzz/client_corpus/8259b1524f55bc4cb4f365ab450cbe984e494116
Binary files differ
diff --git a/fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741c b/fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741c
new file mode 100644
index 00000000..1c10e574
--- /dev/null
+++ b/fuzz/client_corpus/82a1464e8df650fa1f2e4943d31904f6c266741c
Binary files differ
diff --git a/fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3 b/fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3
new file mode 100644
index 00000000..a87e7858
--- /dev/null
+++ b/fuzz/client_corpus/8305e70211c7966e15cc56bd12625ecb5f156ce3
Binary files differ
diff --git a/fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1a b/fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1a
new file mode 100644
index 00000000..5c0c37aa
--- /dev/null
+++ b/fuzz/client_corpus/8368d8b0cdaaba63b4183434b0a42567b4baca1a
Binary files differ
diff --git a/fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0 b/fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0
new file mode 100644
index 00000000..f7142e18
--- /dev/null
+++ b/fuzz/client_corpus/83cf3abf757469e3f081bf0714766a1d603dc2d0
Binary files differ
diff --git a/fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86b b/fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86b
new file mode 100644
index 00000000..0f4e55da
--- /dev/null
+++ b/fuzz/client_corpus/83edd983c9817e0bd1a5613acab9ee0329bff86b
Binary files differ
diff --git a/fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1d b/fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1d
new file mode 100644
index 00000000..4f130bc2
--- /dev/null
+++ b/fuzz/client_corpus/84f9f1c8cf176949f562f077a36b81adbf8a2a1d
Binary files differ
diff --git a/fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206 b/fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206
new file mode 100644
index 00000000..ea3401c5
--- /dev/null
+++ b/fuzz/client_corpus/8537957625c6fbe222a7aa318210d21a146ef206
Binary files differ
diff --git a/fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5 b/fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5
new file mode 100644
index 00000000..8cf9e3a9
--- /dev/null
+++ b/fuzz/client_corpus/860e128954a5d8933886313be553fb2bf872e6f5
Binary files differ
diff --git a/fuzz/client_corpus/862c1aa11fe288ba4d472f1b5e2776a4c68517e6 b/fuzz/client_corpus/862c1aa11fe288ba4d472f1b5e2776a4c68517e6
deleted file mode 100644
index 9cc03d6a..00000000
--- a/fuzz/client_corpus/862c1aa11fe288ba4d472f1b5e2776a4c68517e6
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658 b/fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658
new file mode 100644
index 00000000..220cf804
--- /dev/null
+++ b/fuzz/client_corpus/86674fe6d9cef4e7dc6f810214161701fc266658
Binary files differ
diff --git a/fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3f b/fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3f
new file mode 100644
index 00000000..3737f855
--- /dev/null
+++ b/fuzz/client_corpus/8689c5a7abc8bab0ca468f15671d770331fa9a3f
Binary files differ
diff --git a/fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3e b/fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3e
new file mode 100644
index 00000000..ccea4c22
--- /dev/null
+++ b/fuzz/client_corpus/873fdc25def6c4c6fbed6a548d23f268c393be3e
Binary files differ
diff --git a/fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3d b/fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3d
new file mode 100644
index 00000000..721b5e5a
--- /dev/null
+++ b/fuzz/client_corpus/877637beb6b6884b7fdf7d01b07b5c950de56a3d
Binary files differ
diff --git a/fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624 b/fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624
new file mode 100644
index 00000000..85298291
--- /dev/null
+++ b/fuzz/client_corpus/87af0b01920985b125c1a5482d6cc9039887f624
Binary files differ
diff --git a/fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832 b/fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832
new file mode 100644
index 00000000..b4fea7dd
--- /dev/null
+++ b/fuzz/client_corpus/881a7c422abdfd0dc71278d126ac94f22ae61832
Binary files differ
diff --git a/fuzz/client_corpus/88b816c47071b8c82dc0a24b98529c4623317ef7 b/fuzz/client_corpus/88b816c47071b8c82dc0a24b98529c4623317ef7
deleted file mode 100644
index 07467089..00000000
--- a/fuzz/client_corpus/88b816c47071b8c82dc0a24b98529c4623317ef7
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5 b/fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5
new file mode 100644
index 00000000..e0e05ca0
--- /dev/null
+++ b/fuzz/client_corpus/89355b9199fa689195eeca48631ac8effaaeabb5
Binary files differ
diff --git a/fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1e b/fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1e
new file mode 100644
index 00000000..a3f84ed4
--- /dev/null
+++ b/fuzz/client_corpus/8958860f8aae77703cc14b0ca88fa902319d4f1e
Binary files differ
diff --git a/fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8 b/fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8
new file mode 100644
index 00000000..e3dd7366
--- /dev/null
+++ b/fuzz/client_corpus/89cbaec2af2c891586062633c097e9c4e9762cf8
Binary files differ
diff --git a/fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078 b/fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078
new file mode 100644
index 00000000..3ced36bd
--- /dev/null
+++ b/fuzz/client_corpus/89defbb1150e0cb3520e7510f0e7e06bf8973078
Binary files differ
diff --git a/fuzz/client_corpus/8a6f7e1fbb6295fb0a5dacf44d914658beb1e9d1 b/fuzz/client_corpus/8a6f7e1fbb6295fb0a5dacf44d914658beb1e9d1
deleted file mode 100644
index b2ea3fe5..00000000
--- a/fuzz/client_corpus/8a6f7e1fbb6295fb0a5dacf44d914658beb1e9d1
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4 b/fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4
new file mode 100644
index 00000000..100699dd
--- /dev/null
+++ b/fuzz/client_corpus/8b055ee2fc887c0d42c013c861a790b199cccfa4
Binary files differ
diff --git a/fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22 b/fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22
new file mode 100644
index 00000000..7be01ae8
--- /dev/null
+++ b/fuzz/client_corpus/8b57c39fadcde2215b64ce3925654fba85c5ea22
Binary files differ
diff --git a/fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6 b/fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6
new file mode 100644
index 00000000..c1f19b09
--- /dev/null
+++ b/fuzz/client_corpus/8b9f236c2d33624817a2e03bcc8a3c78c4e756c6
Binary files differ
diff --git a/fuzz/client_corpus/8bc268d09be3e8eb8b75e600a65857ad93c50b6f b/fuzz/client_corpus/8bc268d09be3e8eb8b75e600a65857ad93c50b6f
deleted file mode 100644
index 455ee60d..00000000
--- a/fuzz/client_corpus/8bc268d09be3e8eb8b75e600a65857ad93c50b6f
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93beb b/fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93beb
new file mode 100644
index 00000000..012821c1
--- /dev/null
+++ b/fuzz/client_corpus/8bdf4c52b4671f30500f90e08445da26adf93beb
Binary files differ
diff --git a/fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3 b/fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3
new file mode 100644
index 00000000..240dfc6d
--- /dev/null
+++ b/fuzz/client_corpus/8c71832b8b6a2cd633d1dab36191392e08af24b3
Binary files differ
diff --git a/fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57 b/fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57
new file mode 100644
index 00000000..315aeb6c
--- /dev/null
+++ b/fuzz/client_corpus/8ce6863d4a91451041f82fb30a6bb6bcfe04bd57
Binary files differ
diff --git a/fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20 b/fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20
new file mode 100644
index 00000000..c065474b
--- /dev/null
+++ b/fuzz/client_corpus/8d5185ae5f4f9ec9753a995ca97c16f937508e20
Binary files differ
diff --git a/fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4d b/fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4d
new file mode 100644
index 00000000..64f55564
--- /dev/null
+++ b/fuzz/client_corpus/8d66c97ec703bad66d714f8f76eaf3d80f4fec4d
Binary files differ
diff --git a/fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3 b/fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3
new file mode 100644
index 00000000..83b98691
--- /dev/null
+++ b/fuzz/client_corpus/8d7451a7ce24c4ff1a684228fede21c6a27090e3
Binary files differ
diff --git a/fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8 b/fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8
new file mode 100644
index 00000000..efa16f5d
--- /dev/null
+++ b/fuzz/client_corpus/8da2fcb023ba27413d3e034b552e576cb348e6b8
Binary files differ
diff --git a/fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708f b/fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708f
new file mode 100644
index 00000000..35075b5e
--- /dev/null
+++ b/fuzz/client_corpus/8dc032fd415972bf4ff2c700e875f05bf4c6708f
Binary files differ
diff --git a/fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05 b/fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05
new file mode 100644
index 00000000..63ec2fca
--- /dev/null
+++ b/fuzz/client_corpus/8e7191d8482bccdf5b7b9ad2ae98bb56f976ea05
Binary files differ
diff --git a/fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400 b/fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400
new file mode 100644
index 00000000..aa7b59f1
--- /dev/null
+++ b/fuzz/client_corpus/8ea73c00f324ec5a252b47857dd59f9828ccd400
Binary files differ
diff --git a/fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6 b/fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6
new file mode 100644
index 00000000..77c5c3c5
--- /dev/null
+++ b/fuzz/client_corpus/8ed53379924ea04ec7917a8625bd8d42153516e6
Binary files differ
diff --git a/fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59 b/fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59
new file mode 100644
index 00000000..341b274d
--- /dev/null
+++ b/fuzz/client_corpus/8f555d98707e74734b2d9f175fecd508d9e73f59
Binary files differ
diff --git a/fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8b b/fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8b
new file mode 100644
index 00000000..236f52a3
--- /dev/null
+++ b/fuzz/client_corpus/8f57cb63093021e5617344387a6ef9b472514e8b
Binary files differ
diff --git a/fuzz/client_corpus/8f8643720d03bae58facfb7876166a5d5d7b5fbf b/fuzz/client_corpus/8f8643720d03bae58facfb7876166a5d5d7b5fbf
deleted file mode 100644
index df4a4258..00000000
--- a/fuzz/client_corpus/8f8643720d03bae58facfb7876166a5d5d7b5fbf
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9018d7e0774e15a88c894b02d9d9ebd5a713deea b/fuzz/client_corpus/9018d7e0774e15a88c894b02d9d9ebd5a713deea
deleted file mode 100644
index 594753ab..00000000
--- a/fuzz/client_corpus/9018d7e0774e15a88c894b02d9d9ebd5a713deea
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760 b/fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760
new file mode 100644
index 00000000..f00f62c2
--- /dev/null
+++ b/fuzz/client_corpus/90d49e05c95e7e73df106cae3a0391439736a760
Binary files differ
diff --git a/fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73 b/fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73
new file mode 100644
index 00000000..08c4de31
--- /dev/null
+++ b/fuzz/client_corpus/912f1e539eefdc5b24e0d1ea4733314c4a45dd73
Binary files differ
diff --git a/fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3 b/fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3
new file mode 100644
index 00000000..f860aaf0
--- /dev/null
+++ b/fuzz/client_corpus/91c6bb92bd906e6bda8bbdc81e811f6374f0ecc3
Binary files differ
diff --git a/fuzz/client_corpus/91c7d49741905d07a691350e0b5ab9baacfc6273 b/fuzz/client_corpus/91c7d49741905d07a691350e0b5ab9baacfc6273
deleted file mode 100644
index fab6322a..00000000
--- a/fuzz/client_corpus/91c7d49741905d07a691350e0b5ab9baacfc6273
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674 b/fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674
new file mode 100644
index 00000000..97d4bdda
--- /dev/null
+++ b/fuzz/client_corpus/9200f3939411cb47950bbc4578bbb8e061f17674
Binary files differ
diff --git a/fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92 b/fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92
new file mode 100644
index 00000000..aa6af6bd
--- /dev/null
+++ b/fuzz/client_corpus/92f58505d1c1904cb7f5c0f38abf62432a380c92
Binary files differ
diff --git a/fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783c b/fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783c
new file mode 100644
index 00000000..5549e5bf
--- /dev/null
+++ b/fuzz/client_corpus/92fcc5e47daf5fc36a817aebef83191add2c783c
Binary files differ
diff --git a/fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141 b/fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141
new file mode 100644
index 00000000..89628552
--- /dev/null
+++ b/fuzz/client_corpus/93416d9bae039bfbcd8a847cee630d6253b1c141
Binary files differ
diff --git a/fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488 b/fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488
new file mode 100644
index 00000000..6b34c0c9
--- /dev/null
+++ b/fuzz/client_corpus/9379b70637beee45fa31d3e016363eefb5834488
Binary files differ
diff --git a/fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc b/fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc
new file mode 100644
index 00000000..36042218
--- /dev/null
+++ b/fuzz/client_corpus/938b5f50bb8bdf2e2ba3ff9f56e1a06f4a11cbcc
Binary files differ
diff --git a/fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d b/fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d
new file mode 100644
index 00000000..cfc8be4d
--- /dev/null
+++ b/fuzz/client_corpus/93ff7a343798cbe2c42e02d8bc85b7a63d5ecc2d
Binary files differ
diff --git a/fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3a b/fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3a
new file mode 100644
index 00000000..cb81c3dc
--- /dev/null
+++ b/fuzz/client_corpus/9458125f964837130e97064c97abb83f9646aa3a
Binary files differ
diff --git a/fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253 b/fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253
new file mode 100644
index 00000000..45558cb1
--- /dev/null
+++ b/fuzz/client_corpus/948632bab2c87e14a502f6515527b4ce924f7253
Binary files differ
diff --git a/fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2c b/fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2c
new file mode 100644
index 00000000..c046a4aa
--- /dev/null
+++ b/fuzz/client_corpus/94ea697bb35e030154ca5c901a1e3b3f39d36e2c
Binary files differ
diff --git a/fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90d b/fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90d
new file mode 100644
index 00000000..2639e1c0
--- /dev/null
+++ b/fuzz/client_corpus/952698e57a900fd6dfd60cac5161b4acdb16b90d
Binary files differ
diff --git a/fuzz/client_corpus/9532c89ac942ba20c7fdd32231364b18ec54f430 b/fuzz/client_corpus/9532c89ac942ba20c7fdd32231364b18ec54f430
deleted file mode 100644
index a12a52c3..00000000
--- a/fuzz/client_corpus/9532c89ac942ba20c7fdd32231364b18ec54f430
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4b b/fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4b
new file mode 100644
index 00000000..6bcf2a1b
--- /dev/null
+++ b/fuzz/client_corpus/9546e93d1ebee30df46b3946a6739ffb52624e4b
Binary files differ
diff --git a/fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510b b/fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510b
new file mode 100644
index 00000000..269c6fec
--- /dev/null
+++ b/fuzz/client_corpus/9626102a12051d367f2cbc10d134766302a2510b
Binary files differ
diff --git a/fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76 b/fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76
new file mode 100644
index 00000000..deb5c7c6
--- /dev/null
+++ b/fuzz/client_corpus/96528c570cfaaea1ed945bba352f194fc4e9dd76
Binary files differ
diff --git a/fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71 b/fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71
new file mode 100644
index 00000000..fc345647
--- /dev/null
+++ b/fuzz/client_corpus/9671b1c78f584a5de5029ae5d2cbd807c4b9ff71
Binary files differ
diff --git a/fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7 b/fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7
new file mode 100644
index 00000000..a76a8729
--- /dev/null
+++ b/fuzz/client_corpus/96e04588af90d18412bed0fe821ee8609f1445f7
Binary files differ
diff --git a/fuzz/client_corpus/989c8c11e9167d64d6a4d5572da373d35ed1fdff b/fuzz/client_corpus/989c8c11e9167d64d6a4d5572da373d35ed1fdff
deleted file mode 100644
index c16a93dd..00000000
--- a/fuzz/client_corpus/989c8c11e9167d64d6a4d5572da373d35ed1fdff
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731 b/fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731
new file mode 100644
index 00000000..04c2bfe8
--- /dev/null
+++ b/fuzz/client_corpus/98a585cedac8d4736c292421597537dba155e731
Binary files differ
diff --git a/fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25d b/fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25d
new file mode 100644
index 00000000..2017c7f7
--- /dev/null
+++ b/fuzz/client_corpus/99582e8bb92c8a66cd106db899de002e38a3f25d
Binary files differ
diff --git a/fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0 b/fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0
new file mode 100644
index 00000000..a717924a
--- /dev/null
+++ b/fuzz/client_corpus/997fc5a88d3784c7ca294afa083e0c803f801fb0
Binary files differ
diff --git a/fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cf b/fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cf
new file mode 100644
index 00000000..e2690d50
--- /dev/null
+++ b/fuzz/client_corpus/99b8f9912e5eb8b7305ebe14d09c80f21faf05cf
Binary files differ
diff --git a/fuzz/client_corpus/99dc5a5424282f707e4253be228175472a21586a b/fuzz/client_corpus/99dc5a5424282f707e4253be228175472a21586a
deleted file mode 100644
index 541b2efb..00000000
--- a/fuzz/client_corpus/99dc5a5424282f707e4253be228175472a21586a
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634 b/fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634
new file mode 100644
index 00000000..2c5f68c1
--- /dev/null
+++ b/fuzz/client_corpus/9a2ecde2abf1b187b05d042840236f29c658f634
Binary files differ
diff --git a/fuzz/client_corpus/9a51f0205f7ce5211db0255cc82b16b5d70bcff8 b/fuzz/client_corpus/9a51f0205f7ce5211db0255cc82b16b5d70bcff8
deleted file mode 100644
index b8336f23..00000000
--- a/fuzz/client_corpus/9a51f0205f7ce5211db0255cc82b16b5d70bcff8
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9c7600ab81633b7f346a4fa2a6f51ea19eedaf30 b/fuzz/client_corpus/9c7600ab81633b7f346a4fa2a6f51ea19eedaf30
deleted file mode 100644
index 9ce4e1b6..00000000
--- a/fuzz/client_corpus/9c7600ab81633b7f346a4fa2a6f51ea19eedaf30
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9cc204eb7db5b083a0fa390a97ae3399cca42dbb b/fuzz/client_corpus/9cc204eb7db5b083a0fa390a97ae3399cca42dbb
deleted file mode 100644
index 453791bd..00000000
--- a/fuzz/client_corpus/9cc204eb7db5b083a0fa390a97ae3399cca42dbb
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3 b/fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3
new file mode 100644
index 00000000..7e0d4fcd
--- /dev/null
+++ b/fuzz/client_corpus/9cea539fa3ed5e1cb0b22afd9b0ae7c2fc400fa3
Binary files differ
diff --git a/fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98d b/fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98d
new file mode 100644
index 00000000..dd35cdc1
--- /dev/null
+++ b/fuzz/client_corpus/9d5097026b59a1f6608991d745c001707134c98d
Binary files differ
diff --git a/fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2 b/fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2
new file mode 100644
index 00000000..b90787e2
--- /dev/null
+++ b/fuzz/client_corpus/9d9923ec92568c981b160f715358aa70d8e079b2
Binary files differ
diff --git a/fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22 b/fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22
new file mode 100644
index 00000000..42c9e768
--- /dev/null
+++ b/fuzz/client_corpus/9de75429028831dca2fd372a81cdd9a3ec343f22
Binary files differ
diff --git a/fuzz/client_corpus/9f1e488eb682d3e24920c040e815e9a7c22f1d5c b/fuzz/client_corpus/9f1e488eb682d3e24920c040e815e9a7c22f1d5c
deleted file mode 100644
index 77994893..00000000
--- a/fuzz/client_corpus/9f1e488eb682d3e24920c040e815e9a7c22f1d5c
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98d b/fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98d
new file mode 100644
index 00000000..d53e90fd
--- /dev/null
+++ b/fuzz/client_corpus/9f3c5c4568790eb1583d02d285d1a6bfc209e98d
Binary files differ
diff --git a/fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834 b/fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834
new file mode 100644
index 00000000..a7958bd6
--- /dev/null
+++ b/fuzz/client_corpus/9f6f8fb110096b920fa6a3e65564ae0a0cca4834
Binary files differ
diff --git a/fuzz/client_corpus/9f98a4a0fda63a672bd66ce7e2f16c50c9af1ac4 b/fuzz/client_corpus/9f98a4a0fda63a672bd66ce7e2f16c50c9af1ac4
deleted file mode 100644
index 8b933a4f..00000000
--- a/fuzz/client_corpus/9f98a4a0fda63a672bd66ce7e2f16c50c9af1ac4
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdc b/fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdc
new file mode 100644
index 00000000..57c2ba3f
--- /dev/null
+++ b/fuzz/client_corpus/9fc364fc3f2a6522f904ac7afa35f74853ff6cdc
Binary files differ
diff --git a/fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229 b/fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229
new file mode 100644
index 00000000..442a197b
--- /dev/null
+++ b/fuzz/client_corpus/a0235e7a5ff466220a742084c5c254c1ddbe9229
Binary files differ
diff --git a/fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0 b/fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0
new file mode 100644
index 00000000..2fce9076
--- /dev/null
+++ b/fuzz/client_corpus/a0753eaf3cf2571e61efa16bbd8ff494d1d746f0
Binary files differ
diff --git a/fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1 b/fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1
new file mode 100644
index 00000000..f32b434c
--- /dev/null
+++ b/fuzz/client_corpus/a07942a046ea947ee7fa432c44f2dfe8369ad3b1
Binary files differ
diff --git a/fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9 b/fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9
new file mode 100644
index 00000000..79fd173d
--- /dev/null
+++ b/fuzz/client_corpus/a0e018264482fdad568e31e3698ae48d09f5ede9
Binary files differ
diff --git a/fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179 b/fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179
new file mode 100644
index 00000000..dbbbb28e
--- /dev/null
+++ b/fuzz/client_corpus/a0ed1be09750824c2f10f1e47249cea3210bf179
Binary files differ
diff --git a/fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862daf b/fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862daf
new file mode 100644
index 00000000..92e3ed34
--- /dev/null
+++ b/fuzz/client_corpus/a130fb854ed6720458b564902ad8356882862daf
Binary files differ
diff --git a/fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0 b/fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0
new file mode 100644
index 00000000..12e631b9
--- /dev/null
+++ b/fuzz/client_corpus/a172350dffb276e420877c300b37260c243ef2d0
Binary files differ
diff --git a/fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486 b/fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486
new file mode 100644
index 00000000..c9da3a0d
--- /dev/null
+++ b/fuzz/client_corpus/a19081ccc4eee7a72caf54666e34706bd6ccb486
Binary files differ
diff --git a/fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261ad b/fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261ad
new file mode 100644
index 00000000..6a6eaddb
--- /dev/null
+++ b/fuzz/client_corpus/a1ff1dc066ae44ba884fa5fba82543577a5261ad
Binary files differ
diff --git a/fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552 b/fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552
new file mode 100644
index 00000000..3286296b
--- /dev/null
+++ b/fuzz/client_corpus/a2158aa067898aba1b75e977192e03f13de20552
Binary files differ
diff --git a/fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3 b/fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3
new file mode 100644
index 00000000..cdbda666
--- /dev/null
+++ b/fuzz/client_corpus/a22efd143aa1cf004a7ace6ba056dffdf1bed8f3
Binary files differ
diff --git a/fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bb b/fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bb
new file mode 100644
index 00000000..f7aa3af1
--- /dev/null
+++ b/fuzz/client_corpus/a294bec7193e517c3d48201cd5ce2200a8c482bb
Binary files differ
diff --git a/fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605b b/fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605b
new file mode 100644
index 00000000..f24fadc4
--- /dev/null
+++ b/fuzz/client_corpus/a2f974cccbf5442bf1a8c55477afccf39168605b
Binary files differ
diff --git a/fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104 b/fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104
new file mode 100644
index 00000000..0c4f719b
--- /dev/null
+++ b/fuzz/client_corpus/a417315ebb027548f50a52b1e274fc5f8f6b0104
Binary files differ
diff --git a/fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928 b/fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928
new file mode 100644
index 00000000..7186fd44
--- /dev/null
+++ b/fuzz/client_corpus/a51278e710ef32f80c76a25419ded9f378f73928
Binary files differ
diff --git a/fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20 b/fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20
new file mode 100644
index 00000000..71a50263
--- /dev/null
+++ b/fuzz/client_corpus/a52b559cb5576d2d78315121b141ab72adb7bf20
Binary files differ
diff --git a/fuzz/client_corpus/a554b83ba6c67a8a9df612b8885ec028fb525c11 b/fuzz/client_corpus/a554b83ba6c67a8a9df612b8885ec028fb525c11
deleted file mode 100644
index 36aa5a49..00000000
--- a/fuzz/client_corpus/a554b83ba6c67a8a9df612b8885ec028fb525c11
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3b b/fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3b
new file mode 100644
index 00000000..a919857f
--- /dev/null
+++ b/fuzz/client_corpus/a55b4c066a0ade77b7d681e47b7341c479d68c3b
Binary files differ
diff --git a/fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401d b/fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401d
new file mode 100644
index 00000000..ec54ec3c
--- /dev/null
+++ b/fuzz/client_corpus/a5b5d110779c03c88043f20cb31a443402cf401d
Binary files differ
diff --git a/fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821a b/fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821a
new file mode 100644
index 00000000..8b61e7f4
--- /dev/null
+++ b/fuzz/client_corpus/a5ccd3683d69f1699f62d1b25bb72bfe804c821a
Binary files differ
diff --git a/fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290 b/fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290
new file mode 100644
index 00000000..5cc479c4
--- /dev/null
+++ b/fuzz/client_corpus/a647ad0e3689d42850d0dc5211b63ed3bbd51290
Binary files differ
diff --git a/fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdef b/fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdef
new file mode 100644
index 00000000..f95a7bd1
--- /dev/null
+++ b/fuzz/client_corpus/a679b20b95835cea68864e84d9d5271dc148cdef
Binary files differ
diff --git a/fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826 b/fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826
new file mode 100644
index 00000000..5f8cf8ad
--- /dev/null
+++ b/fuzz/client_corpus/a6a0b7158098709725de5a40691cf476af9fa826
Binary files differ
diff --git a/fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305 b/fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305
new file mode 100644
index 00000000..10c900d0
--- /dev/null
+++ b/fuzz/client_corpus/a6c3e91a3a28655fce34b777ffc83112591a5305
Binary files differ
diff --git a/fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769 b/fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769
new file mode 100644
index 00000000..532023b4
--- /dev/null
+++ b/fuzz/client_corpus/a72e9c8f8a5898128d15f8db799805fb0af08769
Binary files differ
diff --git a/fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94 b/fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94
new file mode 100644
index 00000000..fc1e4c30
--- /dev/null
+++ b/fuzz/client_corpus/a778a560be38a3bd5a3ea923c350f804d1dece94
Binary files differ
diff --git a/fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28 b/fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28
new file mode 100644
index 00000000..73b31374
--- /dev/null
+++ b/fuzz/client_corpus/a7816bfa7527e483e56adb8c69bab7b1e8e9bd28
Binary files differ
diff --git a/fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42e b/fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42e
new file mode 100644
index 00000000..62235a86
--- /dev/null
+++ b/fuzz/client_corpus/a7960ebdd7568141959f4174078a227b67b6a42e
Binary files differ
diff --git a/fuzz/client_corpus/a7bff22ed83e686e0c57edac5be3cb1a5ed4116f b/fuzz/client_corpus/a7bff22ed83e686e0c57edac5be3cb1a5ed4116f
deleted file mode 100644
index b934c423..00000000
--- a/fuzz/client_corpus/a7bff22ed83e686e0c57edac5be3cb1a5ed4116f
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641 b/fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641
new file mode 100644
index 00000000..d2ed50b7
--- /dev/null
+++ b/fuzz/client_corpus/a7f7698acb1a785bc16f01a9996a0b552feb9641
Binary files differ
diff --git a/fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98 b/fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98
new file mode 100644
index 00000000..1e780ad4
--- /dev/null
+++ b/fuzz/client_corpus/a8f7d1273ef6222a7d75652c9692146d1285fe98
Binary files differ
diff --git a/fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973 b/fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973
new file mode 100644
index 00000000..19b26c1c
--- /dev/null
+++ b/fuzz/client_corpus/a93092c6332f5da16c6445e9901c751967377973
Binary files differ
diff --git a/fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53 b/fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53
new file mode 100644
index 00000000..ac8bf191
--- /dev/null
+++ b/fuzz/client_corpus/a948c8df25bd48a0c09ec5a4c9414d75b92f9f53
Binary files differ
diff --git a/fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7 b/fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7
new file mode 100644
index 00000000..fd0d5703
--- /dev/null
+++ b/fuzz/client_corpus/a95561be75e63a4cbc50dc98ce9522df464cb9f7
Binary files differ
diff --git a/fuzz/client_corpus/a9658c0476840377572405c1932c87ed66cda245 b/fuzz/client_corpus/a9658c0476840377572405c1932c87ed66cda245
deleted file mode 100644
index 3e8d772a..00000000
--- a/fuzz/client_corpus/a9658c0476840377572405c1932c87ed66cda245
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/a992d16f1ba3c69f27780a4052836292fdbc0510 b/fuzz/client_corpus/a992d16f1ba3c69f27780a4052836292fdbc0510
deleted file mode 100644
index 4616fac4..00000000
--- a/fuzz/client_corpus/a992d16f1ba3c69f27780a4052836292fdbc0510
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6 b/fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6
new file mode 100644
index 00000000..5ea2fe6b
--- /dev/null
+++ b/fuzz/client_corpus/a9c923edd522f91856371fb45fa87d4e432286c6
Binary files differ
diff --git a/fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585 b/fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585
new file mode 100644
index 00000000..dcc07208
--- /dev/null
+++ b/fuzz/client_corpus/a9ffba3c720e1215a0e65c0952ddfda9664b2585
Binary files differ
diff --git a/fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6 b/fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6
new file mode 100644
index 00000000..962b81b0
--- /dev/null
+++ b/fuzz/client_corpus/aa45f50d4ad0419c89f03c11032fefb7f27f09c6
Binary files differ
diff --git a/fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71 b/fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71
new file mode 100644
index 00000000..f26c474c
--- /dev/null
+++ b/fuzz/client_corpus/aac5de1115c0934b3e4a4fa1bff4e10fa1e61d71
Binary files differ
diff --git a/fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508 b/fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508
new file mode 100644
index 00000000..9b1a0946
--- /dev/null
+++ b/fuzz/client_corpus/ac7e3ccc463eb9334528b256bb2fa05b58274508
Binary files differ
diff --git a/fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5 b/fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5
new file mode 100644
index 00000000..df778e2a
--- /dev/null
+++ b/fuzz/client_corpus/ac9900e115b00f2e3955371c512a5048cb9126e5
Binary files differ
diff --git a/fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60 b/fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60
new file mode 100644
index 00000000..5b2f9ec9
--- /dev/null
+++ b/fuzz/client_corpus/ac9c3021b430c86c30300143099b6f313a25ef60
Binary files differ
diff --git a/fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872 b/fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872
new file mode 100644
index 00000000..498e7a78
--- /dev/null
+++ b/fuzz/client_corpus/acc7c0d52ef2f9477aa67e3aefc8c05d89c8e872
Binary files differ
diff --git a/fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5 b/fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5
new file mode 100644
index 00000000..5485f0bb
--- /dev/null
+++ b/fuzz/client_corpus/acd6f322d20bdd2325a0927aa307fdd4a57b1ce5
Binary files differ
diff --git a/fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807f b/fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807f
new file mode 100644
index 00000000..e7bf5d30
--- /dev/null
+++ b/fuzz/client_corpus/ace9bdbbb130491029271f8a781605b940eb807f
Binary files differ
diff --git a/fuzz/client_corpus/ad1c259b96a734170ba88187ac864f61c763ced9 b/fuzz/client_corpus/ad1c259b96a734170ba88187ac864f61c763ced9
deleted file mode 100644
index 12d1e15e..00000000
--- a/fuzz/client_corpus/ad1c259b96a734170ba88187ac864f61c763ced9
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683a b/fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683a
new file mode 100644
index 00000000..7db1bef3
--- /dev/null
+++ b/fuzz/client_corpus/ad8e168bbba36c52740aa3bbb41d8f503715683a
Binary files differ
diff --git a/fuzz/client_corpus/add4ed5e0dafec5bfbe7060139c9ae444a5fd422 b/fuzz/client_corpus/add4ed5e0dafec5bfbe7060139c9ae444a5fd422
deleted file mode 100644
index 80720f7e..00000000
--- a/fuzz/client_corpus/add4ed5e0dafec5bfbe7060139c9ae444a5fd422
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445 b/fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445
new file mode 100644
index 00000000..24f20c13
--- /dev/null
+++ b/fuzz/client_corpus/ae2a77d41b7fac3e56af9e15139c2fb667387445
Binary files differ
diff --git a/fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055 b/fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055
new file mode 100644
index 00000000..db9f830b
--- /dev/null
+++ b/fuzz/client_corpus/ae9abebb13aafcead7dbd2a3b309be9bbc2ee055
Binary files differ
diff --git a/fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970 b/fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970
new file mode 100644
index 00000000..2a4f6249
--- /dev/null
+++ b/fuzz/client_corpus/af5ad09d790177794ac60e2e8cd54be03c7df970
Binary files differ
diff --git a/fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6 b/fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6
new file mode 100644
index 00000000..a1db8f47
--- /dev/null
+++ b/fuzz/client_corpus/b02387538c10d919e45118d91ebb52d3fdfb74e6
Binary files differ
diff --git a/fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9 b/fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9
new file mode 100644
index 00000000..3d974907
--- /dev/null
+++ b/fuzz/client_corpus/b0b2cece76492218026f90503c4394daaa0d95d9
Binary files differ
diff --git a/fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84 b/fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84
new file mode 100644
index 00000000..5bae12b7
--- /dev/null
+++ b/fuzz/client_corpus/b1511eff332f93d93d5990f9d49014fbb8fc1a84
Binary files differ
diff --git a/fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6 b/fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6
new file mode 100644
index 00000000..1f3ff03d
--- /dev/null
+++ b/fuzz/client_corpus/b174c062d7b5df9f7e88d3f2b4b107e8f582e6e6
Binary files differ
diff --git a/fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817 b/fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817
new file mode 100644
index 00000000..8df81c52
--- /dev/null
+++ b/fuzz/client_corpus/b1850b14ae80f8be2fd166838e994eb536d9a817
Binary files differ
diff --git a/fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52 b/fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52
new file mode 100644
index 00000000..708c1f14
--- /dev/null
+++ b/fuzz/client_corpus/b1bc8ccbf4ca18d4fc67cc4298bdfbf2f8a48a52
Binary files differ
diff --git a/fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8a b/fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8a
new file mode 100644
index 00000000..f2f88222
--- /dev/null
+++ b/fuzz/client_corpus/b215c683e8544dc16c0285029b72f8ef8e4bdf8a
Binary files differ
diff --git a/fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79 b/fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79
new file mode 100644
index 00000000..aaa85d41
--- /dev/null
+++ b/fuzz/client_corpus/b25fcfa7688e490ff503af7a1fe277c4ccae0e79
Binary files differ
diff --git a/fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564 b/fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564
new file mode 100644
index 00000000..f984bb45
--- /dev/null
+++ b/fuzz/client_corpus/b27898123afcd9087d724486b032b67f38f3b564
Binary files differ
diff --git a/fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811 b/fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811
new file mode 100644
index 00000000..dcfb17a9
--- /dev/null
+++ b/fuzz/client_corpus/b3450111f5d3ccdbcf6e08ffda25a7e0e5c53811
Binary files differ
diff --git a/fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18 b/fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18
new file mode 100644
index 00000000..c0858d60
--- /dev/null
+++ b/fuzz/client_corpus/b34dcdb2702d8fc829ddcc8908c227db8ab39f18
Binary files differ
diff --git a/fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6 b/fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6
new file mode 100644
index 00000000..457af3da
--- /dev/null
+++ b/fuzz/client_corpus/b38d66292459ad2fae16464f561aa199812b7ec6
Binary files differ
diff --git a/fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8 b/fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8
new file mode 100644
index 00000000..32b699d7
--- /dev/null
+++ b/fuzz/client_corpus/b3a58509fdd22e3f6a77d4718b3933c2144e8be8
Binary files differ
diff --git a/fuzz/client_corpus/b4742350fd9936eeec364b2cf2d7a9a9432b4bb4 b/fuzz/client_corpus/b4742350fd9936eeec364b2cf2d7a9a9432b4bb4
deleted file mode 100644
index dc3848cc..00000000
--- a/fuzz/client_corpus/b4742350fd9936eeec364b2cf2d7a9a9432b4bb4
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648 b/fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648
new file mode 100644
index 00000000..3d47a95c
--- /dev/null
+++ b/fuzz/client_corpus/b4768e27463348cdc83824f609bcc0bc4c064648
Binary files differ
diff --git a/fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74f b/fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74f
new file mode 100644
index 00000000..d4003277
--- /dev/null
+++ b/fuzz/client_corpus/b47b7e03177dc00879c0c5eaa1046e289e8cc74f
Binary files differ
diff --git a/fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713be b/fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713be
new file mode 100644
index 00000000..b923b55f
--- /dev/null
+++ b/fuzz/client_corpus/b4b6b38c2edab3fd1396696ab437c144603713be
Binary files differ
diff --git a/fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27d b/fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27d
new file mode 100644
index 00000000..9187998e
--- /dev/null
+++ b/fuzz/client_corpus/b51cc11a839138e0a972e1c13b2da0d86e67a27d
Binary files differ
diff --git a/fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226 b/fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226
new file mode 100644
index 00000000..2640f7a9
--- /dev/null
+++ b/fuzz/client_corpus/b524627a5d86fca25217970da5f8cb4c6119d226
Binary files differ
diff --git a/fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621 b/fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621
new file mode 100644
index 00000000..b7d48efd
--- /dev/null
+++ b/fuzz/client_corpus/b5ceea502c4b27e709a4baa0e2992cc942b57621
Binary files differ
diff --git a/fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18 b/fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18
new file mode 100644
index 00000000..b970ef71
--- /dev/null
+++ b/fuzz/client_corpus/b5e84dfe2ad6dec21fe39b8a158022db050b7f18
Binary files differ
diff --git a/fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941a b/fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941a
new file mode 100644
index 00000000..2beb7922
--- /dev/null
+++ b/fuzz/client_corpus/b5f0a0ed4afb8db0be1385bbb58df0e39637941a
Binary files differ
diff --git a/fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1 b/fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1
new file mode 100644
index 00000000..f3a5df37
--- /dev/null
+++ b/fuzz/client_corpus/b601dcb412a63b13ef14d9ae6c041acf7a7716a1
Binary files differ
diff --git a/fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfde b/fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfde
new file mode 100644
index 00000000..611a07a9
--- /dev/null
+++ b/fuzz/client_corpus/b672eb91f36cce66d8e000551c6bef6d0215bfde
Binary files differ
diff --git a/fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9 b/fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9
new file mode 100644
index 00000000..b9cc663e
--- /dev/null
+++ b/fuzz/client_corpus/b6b132f06663996cf8c976cb44be9cfafbef83d9
Binary files differ
diff --git a/fuzz/client_corpus/b6f0bc18a3ba91cfd6d1bfab7d93b114a58a29af b/fuzz/client_corpus/b6f0bc18a3ba91cfd6d1bfab7d93b114a58a29af
deleted file mode 100644
index 30087c77..00000000
--- a/fuzz/client_corpus/b6f0bc18a3ba91cfd6d1bfab7d93b114a58a29af
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43b b/fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43b
new file mode 100644
index 00000000..f0a876ed
--- /dev/null
+++ b/fuzz/client_corpus/b70773f3b09ea80a6adf9641ed753f364a1cb43b
Binary files differ
diff --git a/fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fc b/fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fc
new file mode 100644
index 00000000..1653e726
--- /dev/null
+++ b/fuzz/client_corpus/b711730ee7cf094e22dfed3d9bbdafe6537945fc
Binary files differ
diff --git a/fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683ae b/fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683ae
new file mode 100644
index 00000000..8a98e95b
--- /dev/null
+++ b/fuzz/client_corpus/b72f792402e28cf94c28bc8e33e785989e5683ae
Binary files differ
diff --git a/fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07a b/fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07a
new file mode 100644
index 00000000..a4626b3b
--- /dev/null
+++ b/fuzz/client_corpus/b748db1e3357fde15527e79c66dd5dcc3b96a07a
Binary files differ
diff --git a/fuzz/client_corpus/b7653eb906619065dee11e795efe3ce8ad464072 b/fuzz/client_corpus/b7653eb906619065dee11e795efe3ce8ad464072
deleted file mode 100644
index 317d3348..00000000
--- a/fuzz/client_corpus/b7653eb906619065dee11e795efe3ce8ad464072
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9b b/fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9b
new file mode 100644
index 00000000..50468fc3
--- /dev/null
+++ b/fuzz/client_corpus/b80c7961e196c01be618d2b46c9c3497f7f32c9b
Binary files differ
diff --git a/fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2 b/fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2
new file mode 100644
index 00000000..4d9949c7
--- /dev/null
+++ b/fuzz/client_corpus/b85c172c80e31de442f8af7d1c182e0a88d4cef2
Binary files differ
diff --git a/fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251b b/fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251b
new file mode 100644
index 00000000..ee3030b4
--- /dev/null
+++ b/fuzz/client_corpus/b93163f45f4e7d49ee5721e5865aa2e7a394251b
Binary files differ
diff --git a/fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5 b/fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5
new file mode 100644
index 00000000..12100778
--- /dev/null
+++ b/fuzz/client_corpus/b9abeb89a255b98c7dcf1c740f6a352dfd6ef0a5
Binary files differ
diff --git a/fuzz/client_corpus/ba2b35cd92fd6d0ee105dfe86441c4999409b417 b/fuzz/client_corpus/ba2b35cd92fd6d0ee105dfe86441c4999409b417
deleted file mode 100644
index e75b7c20..00000000
--- a/fuzz/client_corpus/ba2b35cd92fd6d0ee105dfe86441c4999409b417
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828 b/fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828
new file mode 100644
index 00000000..97494ba6
--- /dev/null
+++ b/fuzz/client_corpus/baadac1b80a15dbf1db8ba42c4f439cbcd911828
Binary files differ
diff --git a/fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6 b/fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6
new file mode 100644
index 00000000..01b8f4f2
--- /dev/null
+++ b/fuzz/client_corpus/baf11ce608a902568d00f98bca4ff7a819bb60b6
Binary files differ
diff --git a/fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7 b/fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7
new file mode 100644
index 00000000..5d99a7c8
--- /dev/null
+++ b/fuzz/client_corpus/bb0a8f58a539f9ad9ae76ca78dee870fe4fe63f7
Binary files differ
diff --git a/fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c b/fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c
new file mode 100644
index 00000000..944e1763
--- /dev/null
+++ b/fuzz/client_corpus/bb4436d1ef9495c9e28cca2f036cb9542d6e9a5c
Binary files differ
diff --git a/fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246 b/fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246
new file mode 100644
index 00000000..a08cc691
--- /dev/null
+++ b/fuzz/client_corpus/bb6db7d33c7d284a648fa1ec3b063027b85e4246
Binary files differ
diff --git a/fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55 b/fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55
new file mode 100644
index 00000000..60aecbec
--- /dev/null
+++ b/fuzz/client_corpus/bb9c2f7c0e7e527e32ee0f76f7115c1a69894c55
Binary files differ
diff --git a/fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4 b/fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4
new file mode 100644
index 00000000..db54f255
--- /dev/null
+++ b/fuzz/client_corpus/bc6b78c3b0976d705b9e1ac3e72f5a9f0d5fc4f4
Binary files differ
diff --git a/fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29 b/fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29
new file mode 100644
index 00000000..7211dbac
--- /dev/null
+++ b/fuzz/client_corpus/bc72c2884450288e4b04aa3a04e632259ba7bb29
Binary files differ
diff --git a/fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730 b/fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730
new file mode 100644
index 00000000..f2e65061
--- /dev/null
+++ b/fuzz/client_corpus/bc82b67ead0462d088b02bc7bd2fc9916f522730
Binary files differ
diff --git a/fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4 b/fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4
new file mode 100644
index 00000000..a0a003bd
--- /dev/null
+++ b/fuzz/client_corpus/bcc2c2490f36613db8fd45ff4bdd3bc4b52cb2e4
Binary files differ
diff --git a/fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0 b/fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0
new file mode 100644
index 00000000..72aadda8
--- /dev/null
+++ b/fuzz/client_corpus/bd466cc2cf72548409171797d3825e499c74a8d0
Binary files differ
diff --git a/fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c b/fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c
new file mode 100644
index 00000000..0d8683e8
--- /dev/null
+++ b/fuzz/client_corpus/bdb1831c86d75d7dbfc9350ca5cc1aaf81ef0c7c
Binary files differ
diff --git a/fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0ed b/fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0ed
new file mode 100644
index 00000000..3c505f62
--- /dev/null
+++ b/fuzz/client_corpus/be295faf55c0b0d81ae1ad6725c19e8910e3a0ed
Binary files differ
diff --git a/fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0 b/fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0
new file mode 100644
index 00000000..9ccb37f5
--- /dev/null
+++ b/fuzz/client_corpus/bf329543f2b0cd6f4ed335035294caef4853baf0
Binary files differ
diff --git a/fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98ea b/fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98ea
new file mode 100644
index 00000000..ad6e1c25
--- /dev/null
+++ b/fuzz/client_corpus/bf3afcd912f6bb94259c0892591fa1c90fab98ea
Binary files differ
diff --git a/fuzz/client_corpus/bf9de6b11863f9b35c33ccac6029000515a06e40 b/fuzz/client_corpus/bf9de6b11863f9b35c33ccac6029000515a06e40
deleted file mode 100644
index 89c454b5..00000000
--- a/fuzz/client_corpus/bf9de6b11863f9b35c33ccac6029000515a06e40
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583 b/fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583
new file mode 100644
index 00000000..edd88664
--- /dev/null
+++ b/fuzz/client_corpus/c01dc2df8abf8fa0da256c42671eb3ccef2c7583
Binary files differ
diff --git a/fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8c b/fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8c
new file mode 100644
index 00000000..7e36aea1
--- /dev/null
+++ b/fuzz/client_corpus/c12fd34002a04bef3844ea9baaa3afafc0b68f8c
Binary files differ
diff --git a/fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4d b/fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4d
new file mode 100644
index 00000000..ac533ee7
--- /dev/null
+++ b/fuzz/client_corpus/c1ec31d151af62da3c866eb4399bae3ea8fc9d4d
Binary files differ
diff --git a/fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8 b/fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8
new file mode 100644
index 00000000..2a8c3f7a
--- /dev/null
+++ b/fuzz/client_corpus/c1f877b95dfe5d06ebfb3e7a7d7b16e24985b8e8
Binary files differ
diff --git a/fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427e b/fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427e
new file mode 100644
index 00000000..8086922f
--- /dev/null
+++ b/fuzz/client_corpus/c262943ec79d2929acb8beab22686d0687c4427e
Binary files differ
diff --git a/fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86 b/fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86
new file mode 100644
index 00000000..f9aeeaa0
--- /dev/null
+++ b/fuzz/client_corpus/c2707301c99a3b7447cbc72f5bf9f2d133c66e86
Binary files differ
diff --git a/fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8d b/fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8d
new file mode 100644
index 00000000..50972078
--- /dev/null
+++ b/fuzz/client_corpus/c27785bdba6f5e27bf38a51a58058998fe3edf8d
Binary files differ
diff --git a/fuzz/client_corpus/c2acfea4afeebc8548ca57e7b406b733fdc7efd0 b/fuzz/client_corpus/c2acfea4afeebc8548ca57e7b406b733fdc7efd0
deleted file mode 100644
index c4548474..00000000
--- a/fuzz/client_corpus/c2acfea4afeebc8548ca57e7b406b733fdc7efd0
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523 b/fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523
new file mode 100644
index 00000000..24a3c7bf
--- /dev/null
+++ b/fuzz/client_corpus/c3324216917872b674aff6cdcb6f4aef27045523
Binary files differ
diff --git a/fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419 b/fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419
new file mode 100644
index 00000000..9dbc3ebb
--- /dev/null
+++ b/fuzz/client_corpus/c4146e5fc9388f70a690f71722d86e7a38caa419
Binary files differ
diff --git a/fuzz/client_corpus/c43bc9792aae5572f7718bd39efb25418b6a29e3 b/fuzz/client_corpus/c43bc9792aae5572f7718bd39efb25418b6a29e3
deleted file mode 100644
index 55293b7a..00000000
--- a/fuzz/client_corpus/c43bc9792aae5572f7718bd39efb25418b6a29e3
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9 b/fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9
new file mode 100644
index 00000000..f0e8454e
--- /dev/null
+++ b/fuzz/client_corpus/c49fb6353471694f0c78891efa2faf9f093c98d9
Binary files differ
diff --git a/fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224 b/fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224
new file mode 100644
index 00000000..81d8a4b6
--- /dev/null
+++ b/fuzz/client_corpus/c504bcfb34d2cb10820c049d5437e9a9744b9224
Binary files differ
diff --git a/fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862 b/fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862
new file mode 100644
index 00000000..ff34cd82
--- /dev/null
+++ b/fuzz/client_corpus/c55fd6f979e9fe13ce89b4e236f40c4bd1bed862
Binary files differ
diff --git a/fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117 b/fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117
new file mode 100644
index 00000000..86aae327
--- /dev/null
+++ b/fuzz/client_corpus/c58f346547bdcb658ad1cb70fff078b8701dd117
Binary files differ
diff --git a/fuzz/client_corpus/c64059ad0a8b3d4b6e953c4d5e35e7c088f6b072 b/fuzz/client_corpus/c64059ad0a8b3d4b6e953c4d5e35e7c088f6b072
deleted file mode 100644
index eae15d9d..00000000
--- a/fuzz/client_corpus/c64059ad0a8b3d4b6e953c4d5e35e7c088f6b072
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8 b/fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8
new file mode 100644
index 00000000..1100e024
--- /dev/null
+++ b/fuzz/client_corpus/c676b7ee163f0a21bb6577d2649aa5d5cab305d8
Binary files differ
diff --git a/fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7 b/fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7
new file mode 100644
index 00000000..a1dc9e76
--- /dev/null
+++ b/fuzz/client_corpus/c705dcc86039ee3a05d5cd15ab00cc2356d9aab7
Binary files differ
diff --git a/fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cb b/fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cb
new file mode 100644
index 00000000..2b9a6326
--- /dev/null
+++ b/fuzz/client_corpus/c788bb2baf4eaccebbdbbd865fd36688103057cb
Binary files differ
diff --git a/fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7 b/fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7
new file mode 100644
index 00000000..dfba4e97
--- /dev/null
+++ b/fuzz/client_corpus/c78e5014d7ea4b8fcd106de5d889cec13d3d68e7
Binary files differ
diff --git a/fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490b b/fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490b
new file mode 100644
index 00000000..c460cd2a
--- /dev/null
+++ b/fuzz/client_corpus/c78ece72bae26caf43d6739f97a17ed5dda5490b
Binary files differ
diff --git a/fuzz/client_corpus/c84a90953124137637e9ab5b77a44e174556b9ea b/fuzz/client_corpus/c84a90953124137637e9ab5b77a44e174556b9ea
deleted file mode 100644
index 3e8ed968..00000000
--- a/fuzz/client_corpus/c84a90953124137637e9ab5b77a44e174556b9ea
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89 b/fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89
new file mode 100644
index 00000000..dfc62bcc
--- /dev/null
+++ b/fuzz/client_corpus/c8664ec4a19b06e1d468cb8ba5d87447f1e4aa89
Binary files differ
diff --git a/fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0 b/fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0
new file mode 100644
index 00000000..58259ec0
--- /dev/null
+++ b/fuzz/client_corpus/c992a79f1c3f1f793885df808cb830ea934099a0
Binary files differ
diff --git a/fuzz/client_corpus/c9d3a1db96c2c8567c4a0ad352b67bc79b864d1e b/fuzz/client_corpus/c9d3a1db96c2c8567c4a0ad352b67bc79b864d1e
deleted file mode 100644
index a4c609ac..00000000
--- a/fuzz/client_corpus/c9d3a1db96c2c8567c4a0ad352b67bc79b864d1e
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/c9de70d1d9ec6220bd9139da63e87fa0ba2bf02b b/fuzz/client_corpus/c9de70d1d9ec6220bd9139da63e87fa0ba2bf02b
deleted file mode 100644
index d7d154e5..00000000
--- a/fuzz/client_corpus/c9de70d1d9ec6220bd9139da63e87fa0ba2bf02b
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7 b/fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7
new file mode 100644
index 00000000..de136f1e
--- /dev/null
+++ b/fuzz/client_corpus/c9ffc718c34d14f22de37b5b4f23747ea9c1c1c7
Binary files differ
diff --git a/fuzz/client_corpus/ca70b7405469638eba2d87352235cb91c327b3b7 b/fuzz/client_corpus/ca70b7405469638eba2d87352235cb91c327b3b7
deleted file mode 100644
index f7cde81b..00000000
--- a/fuzz/client_corpus/ca70b7405469638eba2d87352235cb91c327b3b7
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152 b/fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152
new file mode 100644
index 00000000..df7c99c7
--- /dev/null
+++ b/fuzz/client_corpus/cac2b2aad6911e529198d2255be8f5fd47192152
Binary files differ
diff --git a/fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5c b/fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5c
new file mode 100644
index 00000000..fb280cb8
--- /dev/null
+++ b/fuzz/client_corpus/cad08942d1b38a26085b2550c66de32fef4faa5c
Binary files differ
diff --git a/fuzz/client_corpus/caff3955e5a402b64c513cf89f6c6178d32f91ca b/fuzz/client_corpus/caff3955e5a402b64c513cf89f6c6178d32f91ca
deleted file mode 100644
index c5861330..00000000
--- a/fuzz/client_corpus/caff3955e5a402b64c513cf89f6c6178d32f91ca
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48 b/fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48
new file mode 100644
index 00000000..fa640700
--- /dev/null
+++ b/fuzz/client_corpus/ccd0c03acdc4430cbc759f3d672ff530c1d3ad48
Binary files differ
diff --git a/fuzz/client_corpus/cd61d1f2d30352c129043a805a48fc77e91bdd6f b/fuzz/client_corpus/cd61d1f2d30352c129043a805a48fc77e91bdd6f
deleted file mode 100644
index d7530e8d..00000000
--- a/fuzz/client_corpus/cd61d1f2d30352c129043a805a48fc77e91bdd6f
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81 b/fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81
new file mode 100644
index 00000000..86571246
--- /dev/null
+++ b/fuzz/client_corpus/cd89f3d76d270f94df4e98676711f9afddcd0a81
Binary files differ
diff --git a/fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2 b/fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2
new file mode 100644
index 00000000..50331c17
--- /dev/null
+++ b/fuzz/client_corpus/cddf422981522324fdb5b0b1a7cfe9ac0305e5b2
Binary files differ
diff --git a/fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984 b/fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984
new file mode 100644
index 00000000..ef0769f9
--- /dev/null
+++ b/fuzz/client_corpus/cde1c623e7095e180c3a485bc8333cf8bee2e984
Binary files differ
diff --git a/fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41 b/fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41
new file mode 100644
index 00000000..9108f179
--- /dev/null
+++ b/fuzz/client_corpus/ce6c351af3d3912d66db41de4a2c71fa812e8d41
Binary files differ
diff --git a/fuzz/client_corpus/ce87aa069c66ce66a19031e66737ad2c8ba230a3 b/fuzz/client_corpus/ce87aa069c66ce66a19031e66737ad2c8ba230a3
deleted file mode 100644
index 9c045d21..00000000
--- a/fuzz/client_corpus/ce87aa069c66ce66a19031e66737ad2c8ba230a3
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565d b/fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565d
new file mode 100644
index 00000000..4547363a
--- /dev/null
+++ b/fuzz/client_corpus/ce93d2a149cdc6695256b062cfd1225092ba565d
Binary files differ
diff --git a/fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41 b/fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41
new file mode 100644
index 00000000..864361fa
--- /dev/null
+++ b/fuzz/client_corpus/ced8a723d0468a850f5aa93642f934e547928f41
Binary files differ
diff --git a/fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60 b/fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60
new file mode 100644
index 00000000..d9ddb7b8
--- /dev/null
+++ b/fuzz/client_corpus/d0288bf062576db0058deb80e6a475d6b1fdbc60
Binary files differ
diff --git a/fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824b b/fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824b
new file mode 100644
index 00000000..d6f34ede
--- /dev/null
+++ b/fuzz/client_corpus/d032befc9c75ee26197c43f1d189c231d9aa824b
Binary files differ
diff --git a/fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84 b/fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84
new file mode 100644
index 00000000..2bf136e9
--- /dev/null
+++ b/fuzz/client_corpus/d03537cd5fde0747d593075d6a6f595f6a425a84
Binary files differ
diff --git a/fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290 b/fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290
new file mode 100644
index 00000000..5d23763c
--- /dev/null
+++ b/fuzz/client_corpus/d03a3bf8b4d1976030d1584960ac3dea63e06290
Binary files differ
diff --git a/fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00f b/fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00f
new file mode 100644
index 00000000..a2ed9df3
--- /dev/null
+++ b/fuzz/client_corpus/d058010606ec0a6c48817aa0d93a48e455e8c00f
Binary files differ
diff --git a/fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344 b/fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344
new file mode 100644
index 00000000..eee82946
--- /dev/null
+++ b/fuzz/client_corpus/d12a59b71ab1c96bada47b4a2ec2a6376699e344
Binary files differ
diff --git a/fuzz/client_corpus/d153ecdd0aecb6560ceb29ac482ac648f3c91b3c b/fuzz/client_corpus/d153ecdd0aecb6560ceb29ac482ac648f3c91b3c
deleted file mode 100644
index 33a10b3d..00000000
--- a/fuzz/client_corpus/d153ecdd0aecb6560ceb29ac482ac648f3c91b3c
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04 b/fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04
new file mode 100644
index 00000000..47834725
--- /dev/null
+++ b/fuzz/client_corpus/d1788576205c4adf09461c7961a29a2b41fa9f04
Binary files differ
diff --git a/fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90 b/fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90
new file mode 100644
index 00000000..abd2edbc
--- /dev/null
+++ b/fuzz/client_corpus/d17b3b5c53b857d35787caf5a547e58e5a326f90
Binary files differ
diff --git a/fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6 b/fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6
new file mode 100644
index 00000000..e4ae2cd0
--- /dev/null
+++ b/fuzz/client_corpus/d1b04032c449ccfdb320500ce922e905a9b746f6
Binary files differ
diff --git a/fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6d b/fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6d
new file mode 100644
index 00000000..689d3b01
--- /dev/null
+++ b/fuzz/client_corpus/d2c608fc637a44b7ab58dfbd2adfc919857c9a6d
Binary files differ
diff --git a/fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024 b/fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024
new file mode 100644
index 00000000..38d69d75
--- /dev/null
+++ b/fuzz/client_corpus/d2dc18b5d34852e1a4e1c9956d729259af11c024
Binary files differ
diff --git a/fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032 b/fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032
new file mode 100644
index 00000000..13c311a6
--- /dev/null
+++ b/fuzz/client_corpus/d35b83a8f3a1503d9d8682d2e123127c42852032
Binary files differ
diff --git a/fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19 b/fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19
new file mode 100644
index 00000000..77c13c41
--- /dev/null
+++ b/fuzz/client_corpus/d44d74d1e715b1eff600cf9025ccf7980cdbeb19
Binary files differ
diff --git a/fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005 b/fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005
new file mode 100644
index 00000000..95884640
--- /dev/null
+++ b/fuzz/client_corpus/d4826144f817a4419086d0c3e6eaf326843ab005
Binary files differ
diff --git a/fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603 b/fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603
new file mode 100644
index 00000000..1bdedc18
--- /dev/null
+++ b/fuzz/client_corpus/d49261c056a68e3789b2aa041c9a8372f9342603
Binary files differ
diff --git a/fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69 b/fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69
new file mode 100644
index 00000000..003a7458
--- /dev/null
+++ b/fuzz/client_corpus/d4ddfce77cf7f1e9b50618c636f9a811dbc64e69
Binary files differ
diff --git a/fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694 b/fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694
new file mode 100644
index 00000000..e5efee86
--- /dev/null
+++ b/fuzz/client_corpus/d4e7f76de93312778f03a167ef99b93e8a277694
Binary files differ
diff --git a/fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317a b/fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317a
new file mode 100644
index 00000000..147853c8
--- /dev/null
+++ b/fuzz/client_corpus/d50e0da5bd72f68d49bbe8b080dfe16587f9317a
Binary files differ
diff --git a/fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7 b/fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7
new file mode 100644
index 00000000..8deb82af
--- /dev/null
+++ b/fuzz/client_corpus/d5278057d56703a1526dae2e78a40392f9d1a0d7
Binary files differ
diff --git a/fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52 b/fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52
new file mode 100644
index 00000000..9410f6b3
--- /dev/null
+++ b/fuzz/client_corpus/d531f5874372bc6af0e744859bca3eeb101e0d52
Binary files differ
diff --git a/fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57c b/fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57c
new file mode 100644
index 00000000..4f9459f9
--- /dev/null
+++ b/fuzz/client_corpus/d54b651c80434d4c87f0ffc1a94a8934bfcbe57c
Binary files differ
diff --git a/fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7 b/fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7
new file mode 100644
index 00000000..45e4dd22
--- /dev/null
+++ b/fuzz/client_corpus/d5a14089cae100bd2a22abd28263798e146743e7
Binary files differ
diff --git a/fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01 b/fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01
new file mode 100644
index 00000000..93c24c24
--- /dev/null
+++ b/fuzz/client_corpus/d5c17cf9f504aa2b8013d4a70e9f197c5ec1ee01
Binary files differ
diff --git a/fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0 b/fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0
new file mode 100644
index 00000000..606094c6
--- /dev/null
+++ b/fuzz/client_corpus/d5ed598cfe5995c9f93d9141181d629b5122efd0
Binary files differ
diff --git a/fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278 b/fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278
new file mode 100644
index 00000000..f8786fd2
--- /dev/null
+++ b/fuzz/client_corpus/d60a9a78b49e24cffcf407fe5fd50bb9365b4278
Binary files differ
diff --git a/fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02 b/fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02
new file mode 100644
index 00000000..bbc61cd6
--- /dev/null
+++ b/fuzz/client_corpus/d60b4797ac2c7cc376e670dd97ded488a75d7a02
Binary files differ
diff --git a/fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4 b/fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4
new file mode 100644
index 00000000..d7a6442a
--- /dev/null
+++ b/fuzz/client_corpus/d62572b25b3b2f5d91a46757a7b98b5823d601a4
Binary files differ
diff --git a/fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399 b/fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399
new file mode 100644
index 00000000..ab0d67ce
--- /dev/null
+++ b/fuzz/client_corpus/d62c0e1927c0518813dc457bf4b9798096758399
Binary files differ
diff --git a/fuzz/client_corpus/d6d2b5c6f73c3d83547b1cf3a4ef71aaaa19eb56 b/fuzz/client_corpus/d6d2b5c6f73c3d83547b1cf3a4ef71aaaa19eb56
deleted file mode 100644
index 8fe88187..00000000
--- a/fuzz/client_corpus/d6d2b5c6f73c3d83547b1cf3a4ef71aaaa19eb56
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/d6d7771c49302badd8825680a2a1f95bc265707e b/fuzz/client_corpus/d6d7771c49302badd8825680a2a1f95bc265707e
deleted file mode 100644
index 88430ab4..00000000
--- a/fuzz/client_corpus/d6d7771c49302badd8825680a2a1f95bc265707e
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/d7975db1a9687110ecbe1a90c604313557dcc3b3 b/fuzz/client_corpus/d7975db1a9687110ecbe1a90c604313557dcc3b3
deleted file mode 100644
index 11b2e190..00000000
--- a/fuzz/client_corpus/d7975db1a9687110ecbe1a90c604313557dcc3b3
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10 b/fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10
new file mode 100644
index 00000000..4cab30e5
--- /dev/null
+++ b/fuzz/client_corpus/d799d28eea5dc9ec1b00e18d9bb650a069304d10
Binary files differ
diff --git a/fuzz/client_corpus/d7a895d52691c31e12ea463089d855cc6466fd61 b/fuzz/client_corpus/d7a895d52691c31e12ea463089d855cc6466fd61
deleted file mode 100644
index 7241df1e..00000000
--- a/fuzz/client_corpus/d7a895d52691c31e12ea463089d855cc6466fd61
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318 b/fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318
new file mode 100644
index 00000000..10173556
--- /dev/null
+++ b/fuzz/client_corpus/d7b49428ad8ba32ff3ed0de60bb2454517ad4318
Binary files differ
diff --git a/fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3b b/fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3b
new file mode 100644
index 00000000..07c1ebec
--- /dev/null
+++ b/fuzz/client_corpus/d80d720514be9459653d2eb637ea5b76c6982d3b
Binary files differ
diff --git a/fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b b/fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b
new file mode 100644
index 00000000..52857397
--- /dev/null
+++ b/fuzz/client_corpus/d94dc3e2729f9aba19d5ac15ee1cdd14edc4f58b
Binary files differ
diff --git a/fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5 b/fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5
new file mode 100644
index 00000000..bd9c75d5
--- /dev/null
+++ b/fuzz/client_corpus/d9533ed23666d92676c97620061e21a33d6d1bc5
Binary files differ
diff --git a/fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4e b/fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4e
new file mode 100644
index 00000000..ab390ad1
--- /dev/null
+++ b/fuzz/client_corpus/d9d1d1a511c5a753ad80a380f28a4e405e73ca4e
Binary files differ
diff --git a/fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559d b/fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559d
new file mode 100644
index 00000000..a25e83f3
--- /dev/null
+++ b/fuzz/client_corpus/da8789ba323501ec7ca492232eb9a0ab1fff559d
Binary files differ
diff --git a/fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93d b/fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93d
new file mode 100644
index 00000000..f58beb37
--- /dev/null
+++ b/fuzz/client_corpus/db1a0fcfb08514ca415b2009b06d4d03fa85d93d
Binary files differ
diff --git a/fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bd b/fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bd
new file mode 100644
index 00000000..fd5c1176
--- /dev/null
+++ b/fuzz/client_corpus/dbe1c29786bcb974e23eeeb948a094b8b60ed6bd
Binary files differ
diff --git a/fuzz/client_corpus/dc7efdf6cb7e95e7c257c3f850e58e504949e9a8 b/fuzz/client_corpus/dc7efdf6cb7e95e7c257c3f850e58e504949e9a8
deleted file mode 100644
index f61aa7e8..00000000
--- a/fuzz/client_corpus/dc7efdf6cb7e95e7c257c3f850e58e504949e9a8
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9 b/fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9
new file mode 100644
index 00000000..ec9378a0
--- /dev/null
+++ b/fuzz/client_corpus/dc9fd88d1bef7f495ea968bc451988098eff8ee9
Binary files differ
diff --git a/fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0 b/fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0
new file mode 100644
index 00000000..38d3203a
--- /dev/null
+++ b/fuzz/client_corpus/dd0b7faae253e3f2d0251266ce65752648ecf3e0
Binary files differ
diff --git a/fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575f b/fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575f
new file mode 100644
index 00000000..e2f8f465
--- /dev/null
+++ b/fuzz/client_corpus/dd0d01989ca202ed57067269b166148bc2c5575f
Binary files differ
diff --git a/fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d b/fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d
new file mode 100644
index 00000000..78eec5aa
--- /dev/null
+++ b/fuzz/client_corpus/dd7ce1ad6b11303be4937c29f4724c24e6b5ea2d
Binary files differ
diff --git a/fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30 b/fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30
new file mode 100644
index 00000000..fbf79852
--- /dev/null
+++ b/fuzz/client_corpus/dd8287ebeb79534ebe090d6085806f3b44fdfe30
Binary files differ
diff --git a/fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9 b/fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9
new file mode 100644
index 00000000..2cb8af31
--- /dev/null
+++ b/fuzz/client_corpus/dd8cf6b21f54ae0083050f5458e54b1dbc3180c9
Binary files differ
diff --git a/fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177aba b/fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177aba
new file mode 100644
index 00000000..46f629b1
--- /dev/null
+++ b/fuzz/client_corpus/de0335436dd87366e3be8c7d728943a7c6177aba
Binary files differ
diff --git a/fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856a b/fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856a
new file mode 100644
index 00000000..fe5590ba
--- /dev/null
+++ b/fuzz/client_corpus/de66c31a968bf35553dff76e45831ecf1000856a
Binary files differ
diff --git a/fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01 b/fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01
new file mode 100644
index 00000000..21ee3664
--- /dev/null
+++ b/fuzz/client_corpus/de98b3137af7eab1edef6958a79ff8d731056f01
Binary files differ
diff --git a/fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303 b/fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303
new file mode 100644
index 00000000..36c6a2ed
--- /dev/null
+++ b/fuzz/client_corpus/dedfa96557b62d4a8df63694dad15e0b0f491303
Binary files differ
diff --git a/fuzz/client_corpus/df19fb0f0752cebfa3e221eca2396ce74e568c71 b/fuzz/client_corpus/df19fb0f0752cebfa3e221eca2396ce74e568c71
deleted file mode 100644
index c7cebd42..00000000
--- a/fuzz/client_corpus/df19fb0f0752cebfa3e221eca2396ce74e568c71
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294 b/fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294
new file mode 100644
index 00000000..e0b56c4f
--- /dev/null
+++ b/fuzz/client_corpus/df2d4210d382ad94c550c3d560c607c8febd8294
Binary files differ
diff --git a/fuzz/client_corpus/df3af56fc7423b564ed2c18258e934796f574b2e b/fuzz/client_corpus/df3af56fc7423b564ed2c18258e934796f574b2e
deleted file mode 100644
index 71782e20..00000000
--- a/fuzz/client_corpus/df3af56fc7423b564ed2c18258e934796f574b2e
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0 b/fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0
new file mode 100644
index 00000000..652cf27b
--- /dev/null
+++ b/fuzz/client_corpus/df58f2b01e1583f71599e1e98f5c8cb50fee4cf0
Binary files differ
diff --git a/fuzz/client_corpus/df811b530178666cc79c5ca440c9f2aca9fae5be b/fuzz/client_corpus/df811b530178666cc79c5ca440c9f2aca9fae5be
deleted file mode 100644
index 3be34162..00000000
--- a/fuzz/client_corpus/df811b530178666cc79c5ca440c9f2aca9fae5be
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0 b/fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0
new file mode 100644
index 00000000..29850a77
--- /dev/null
+++ b/fuzz/client_corpus/df8361ab66b111e870d66da944074034a8b9aff0
Binary files differ
diff --git a/fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099 b/fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099
new file mode 100644
index 00000000..afc902a9
--- /dev/null
+++ b/fuzz/client_corpus/dfa5eae13138c3035d5be8ee38d14437664b8099
Binary files differ
diff --git a/fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679 b/fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679
new file mode 100644
index 00000000..32c1d1d1
--- /dev/null
+++ b/fuzz/client_corpus/dfa62f0edaf6b90d9fa8d58b3792abf1937db679
Binary files differ
diff --git a/fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998 b/fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998
new file mode 100644
index 00000000..b12fae6e
--- /dev/null
+++ b/fuzz/client_corpus/dfcb7073dea2e606dc7b1877577bbaac9c020998
Binary files differ
diff --git a/fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074 b/fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074
new file mode 100644
index 00000000..75239b30
--- /dev/null
+++ b/fuzz/client_corpus/dfcf39ec02f1f05132f8cb28c9ad62fc2b6fe074
Binary files differ
diff --git a/fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7d b/fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7d
new file mode 100644
index 00000000..3e153ec8
--- /dev/null
+++ b/fuzz/client_corpus/dff8677490e8b612a3fa1aafea7db76a57531a7d
Binary files differ
diff --git a/fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6 b/fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6
new file mode 100644
index 00000000..457e25ab
--- /dev/null
+++ b/fuzz/client_corpus/e00c632f0217269fce83f0baac055b2e9dc522d6
Binary files differ
diff --git a/fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8 b/fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8
new file mode 100644
index 00000000..c377d01d
--- /dev/null
+++ b/fuzz/client_corpus/e04df2a864a3be5065d25603a6f79090c8f70ef8
Binary files differ
diff --git a/fuzz/client_corpus/e108931e2f35aa964740a5d2d769b9ed09e1d3ba b/fuzz/client_corpus/e108931e2f35aa964740a5d2d769b9ed09e1d3ba
deleted file mode 100644
index 30ff14bf..00000000
--- a/fuzz/client_corpus/e108931e2f35aa964740a5d2d769b9ed09e1d3ba
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/e250493d1912990f1c388651fa7436bd61b43cf0 b/fuzz/client_corpus/e250493d1912990f1c388651fa7436bd61b43cf0
deleted file mode 100644
index 11923d6a..00000000
--- a/fuzz/client_corpus/e250493d1912990f1c388651fa7436bd61b43cf0
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305 b/fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305
new file mode 100644
index 00000000..e329c770
--- /dev/null
+++ b/fuzz/client_corpus/e25a7b9befe26a89d379fecf190f4b9aad7c2305
Binary files differ
diff --git a/fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897 b/fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897
new file mode 100644
index 00000000..ddc86fe8
--- /dev/null
+++ b/fuzz/client_corpus/e2d7108a4559fe36b7ff8854d7cf96549deb8897
Binary files differ
diff --git a/fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ec b/fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ec
new file mode 100644
index 00000000..9ba32c48
--- /dev/null
+++ b/fuzz/client_corpus/e33830dba87718ca367a275cf4c7a59ccd4927ec
Binary files differ
diff --git a/fuzz/client_corpus/e422ebbe19856f99bf12daa91dfa9374110cc1ae b/fuzz/client_corpus/e422ebbe19856f99bf12daa91dfa9374110cc1ae
deleted file mode 100644
index e59dbe4f..00000000
--- a/fuzz/client_corpus/e422ebbe19856f99bf12daa91dfa9374110cc1ae
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/e44a2a205da5934fe88f471db4bff606b7b32910 b/fuzz/client_corpus/e44a2a205da5934fe88f471db4bff606b7b32910
deleted file mode 100644
index 9ee349df..00000000
--- a/fuzz/client_corpus/e44a2a205da5934fe88f471db4bff606b7b32910
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4e b/fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4e
new file mode 100644
index 00000000..a768f314
--- /dev/null
+++ b/fuzz/client_corpus/e46cf6de573e5e07b5e2429ddca6277e5dad9b4e
Binary files differ
diff --git a/fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0 b/fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0
new file mode 100644
index 00000000..ccf58d07
--- /dev/null
+++ b/fuzz/client_corpus/e478fba23e6bec21363045d0d1de05237a0dcfe0
Binary files differ
diff --git a/fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8 b/fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8
new file mode 100644
index 00000000..7e401f26
--- /dev/null
+++ b/fuzz/client_corpus/e4d71e3a91460379358500d9b998a911e04f0bd8
Binary files differ
diff --git a/fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501 b/fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501
new file mode 100644
index 00000000..285989a3
--- /dev/null
+++ b/fuzz/client_corpus/e4eec0bbadced0366353f387512000ec8504f501
Binary files differ
diff --git a/fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eeb b/fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eeb
new file mode 100644
index 00000000..2b8015be
--- /dev/null
+++ b/fuzz/client_corpus/e51409d12b954c9e7478e79b1393b76c3dea5eeb
Binary files differ
diff --git a/fuzz/client_corpus/e53fb23dfe5472f0f6e04906425108118361c485 b/fuzz/client_corpus/e53fb23dfe5472f0f6e04906425108118361c485
deleted file mode 100644
index 34ae6cd4..00000000
--- a/fuzz/client_corpus/e53fb23dfe5472f0f6e04906425108118361c485
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111 b/fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111
new file mode 100644
index 00000000..afd971f4
--- /dev/null
+++ b/fuzz/client_corpus/e567be3c710068e4b985312b5c342e78ac177111
Binary files differ
diff --git a/fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07d b/fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07d
new file mode 100644
index 00000000..68b3ebfa
--- /dev/null
+++ b/fuzz/client_corpus/e5a85219718efd390ce1cffbe60cbb8fbe7bd07d
Binary files differ
diff --git a/fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444 b/fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444
new file mode 100644
index 00000000..790ca6e1
--- /dev/null
+++ b/fuzz/client_corpus/e734d584122a869a16a10dd58fd90b82e8c9f444
Binary files differ
diff --git a/fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6a b/fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6a
new file mode 100644
index 00000000..2e37e076
--- /dev/null
+++ b/fuzz/client_corpus/e74c6de58f2b27059af669fadc1c6e65fc5c2c6a
Binary files differ
diff --git a/fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875 b/fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875
new file mode 100644
index 00000000..4c42849f
--- /dev/null
+++ b/fuzz/client_corpus/e764ee13b2cbee6650ac9a43e30059748be94875
Binary files differ
diff --git a/fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0fea b/fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0fea
new file mode 100644
index 00000000..2752fc13
--- /dev/null
+++ b/fuzz/client_corpus/e78589cd285cd5f51be25c22e99ee6d5b3dd0fea
Binary files differ
diff --git a/fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966ac b/fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966ac
new file mode 100644
index 00000000..4bef09b5
--- /dev/null
+++ b/fuzz/client_corpus/e793e02598daa45d72386d500fadc7b8847966ac
Binary files differ
diff --git a/fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478 b/fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478
new file mode 100644
index 00000000..f782f873
--- /dev/null
+++ b/fuzz/client_corpus/e7b94d5f17cb2bda3a289528baa04e66b5ef5478
Binary files differ
diff --git a/fuzz/client_corpus/e856a78f2e32bd8f0d60a4fe693b36c83c0a8356 b/fuzz/client_corpus/e856a78f2e32bd8f0d60a4fe693b36c83c0a8356
deleted file mode 100644
index a742b88b..00000000
--- a/fuzz/client_corpus/e856a78f2e32bd8f0d60a4fe693b36c83c0a8356
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/e88ec440a42915f80706afbc0cc7bf1111db4936 b/fuzz/client_corpus/e88ec440a42915f80706afbc0cc7bf1111db4936
deleted file mode 100644
index 199b74be..00000000
--- a/fuzz/client_corpus/e88ec440a42915f80706afbc0cc7bf1111db4936
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26b b/fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26b
new file mode 100644
index 00000000..23f88637
--- /dev/null
+++ b/fuzz/client_corpus/e8baf78fba26327aeea9353f4160469133c9e26b
Binary files differ
diff --git a/fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90ad b/fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90ad
new file mode 100644
index 00000000..3d6c6ebe
--- /dev/null
+++ b/fuzz/client_corpus/eac3471325184b407218efb4fbf9ed18502b90ad
Binary files differ
diff --git a/fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670 b/fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670
new file mode 100644
index 00000000..8f22276f
--- /dev/null
+++ b/fuzz/client_corpus/eb0614a6bcbfbf345c2760bc22ca0061c5d6e670
Binary files differ
diff --git a/fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884 b/fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884
new file mode 100644
index 00000000..93e7edff
--- /dev/null
+++ b/fuzz/client_corpus/ebd0214511a49a39219400618c3d355021157884
Binary files differ
diff --git a/fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1 b/fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1
new file mode 100644
index 00000000..ff1a0e0a
--- /dev/null
+++ b/fuzz/client_corpus/ec6ed05526c37da3cb8f5f13c4af297999ac86b1
Binary files differ
diff --git a/fuzz/client_corpus/ecccd730722b03678c74bdf87163035af5d70ecb b/fuzz/client_corpus/ecccd730722b03678c74bdf87163035af5d70ecb
deleted file mode 100644
index c53b4606..00000000
--- a/fuzz/client_corpus/ecccd730722b03678c74bdf87163035af5d70ecb
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/ecd22a9f8c1f5017f89d6c2288979c96433b3d0c b/fuzz/client_corpus/ecd22a9f8c1f5017f89d6c2288979c96433b3d0c
deleted file mode 100644
index 5d9a4263..00000000
--- a/fuzz/client_corpus/ecd22a9f8c1f5017f89d6c2288979c96433b3d0c
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84 b/fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84
new file mode 100644
index 00000000..6bd2c49c
--- /dev/null
+++ b/fuzz/client_corpus/ed12741b6e328f435f5859366b7307de25191d84
Binary files differ
diff --git a/fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2 b/fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2
new file mode 100644
index 00000000..50fd4c48
--- /dev/null
+++ b/fuzz/client_corpus/ed762b2b7148ee7ed1759bc6dc3d898238f3c4a2
Binary files differ
diff --git a/fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6 b/fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6
new file mode 100644
index 00000000..753949c5
--- /dev/null
+++ b/fuzz/client_corpus/edb8eb2806f70ced44e984d5b6ba736e2bfc87a6
Binary files differ
diff --git a/fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190 b/fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190
new file mode 100644
index 00000000..5b3183cc
--- /dev/null
+++ b/fuzz/client_corpus/ee4553a19b0f86ef2b74c1d2821b9be12bf19190
Binary files differ
diff --git a/fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59 b/fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59
new file mode 100644
index 00000000..d16d3f51
--- /dev/null
+++ b/fuzz/client_corpus/ee9397fa6666c21dcfde633a790ae8c928e34f59
Binary files differ
diff --git a/fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265ca b/fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265ca
new file mode 100644
index 00000000..ef3ee606
--- /dev/null
+++ b/fuzz/client_corpus/eef3168490e70c8b410a8595d440d05ebb3265ca
Binary files differ
diff --git a/fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2f b/fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2f
new file mode 100644
index 00000000..38eb62b4
--- /dev/null
+++ b/fuzz/client_corpus/ef08605ec2c45ae9d761fc90ea46e73328c81b2f
Binary files differ
diff --git a/fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786 b/fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786
new file mode 100644
index 00000000..f9473930
--- /dev/null
+++ b/fuzz/client_corpus/ef10ddcdd49df604183649b612ffe27ea1473786
Binary files differ
diff --git a/fuzz/client_corpus/ef7bb7e9656aa4b23d6f4a78ea0b6a12acfc5edb b/fuzz/client_corpus/ef7bb7e9656aa4b23d6f4a78ea0b6a12acfc5edb
deleted file mode 100644
index d005016c..00000000
--- a/fuzz/client_corpus/ef7bb7e9656aa4b23d6f4a78ea0b6a12acfc5edb
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1 b/fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1
new file mode 100644
index 00000000..4fbd9f20
--- /dev/null
+++ b/fuzz/client_corpus/f030612c62ffda07dfd3f71da34a355f810351c1
Binary files differ
diff --git a/fuzz/client_corpus/f05f5c9edbc997d109efedb280f5df56d91e3f30 b/fuzz/client_corpus/f05f5c9edbc997d109efedb280f5df56d91e3f30
deleted file mode 100644
index 310f6a5f..00000000
--- a/fuzz/client_corpus/f05f5c9edbc997d109efedb280f5df56d91e3f30
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5 b/fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5
new file mode 100644
index 00000000..9c20c2a1
--- /dev/null
+++ b/fuzz/client_corpus/f16469af68d82405182616d57cb88e79a8f84fa5
Binary files differ
diff --git a/fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35 b/fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35
new file mode 100644
index 00000000..5ff2dfd1
--- /dev/null
+++ b/fuzz/client_corpus/f20d61a351628b54d7acc53df3fa9a8b89d23a35
Binary files differ
diff --git a/fuzz/client_corpus/f221430334f4351262a86cfa0bb3dced4fb50b2f b/fuzz/client_corpus/f221430334f4351262a86cfa0bb3dced4fb50b2f
deleted file mode 100644
index 81da21cd..00000000
--- a/fuzz/client_corpus/f221430334f4351262a86cfa0bb3dced4fb50b2f
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/f2443da1130f34d948c2897195681f324e1eb14d b/fuzz/client_corpus/f2443da1130f34d948c2897195681f324e1eb14d
deleted file mode 100644
index f5e989fd..00000000
--- a/fuzz/client_corpus/f2443da1130f34d948c2897195681f324e1eb14d
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1 b/fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1
new file mode 100644
index 00000000..5babb581
--- /dev/null
+++ b/fuzz/client_corpus/f279591cee3d393edab74b64f5bff2783f7896e1
Binary files differ
diff --git a/fuzz/client_corpus/f2982b479f4d0426f25b71b7e4ef7199542fba6c b/fuzz/client_corpus/f2982b479f4d0426f25b71b7e4ef7199542fba6c
deleted file mode 100644
index 0be81eb3..00000000
--- a/fuzz/client_corpus/f2982b479f4d0426f25b71b7e4ef7199542fba6c
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3 b/fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3
new file mode 100644
index 00000000..3234a33e
--- /dev/null
+++ b/fuzz/client_corpus/f2be10d2e0ede8e502a5ad6d7327c0c57b7510e3
Binary files differ
diff --git a/fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0 b/fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0
new file mode 100644
index 00000000..be999faf
--- /dev/null
+++ b/fuzz/client_corpus/f2fcc44bdba89769aef1a58d9067e5e43918e9c0
Binary files differ
diff --git a/fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16 b/fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16
new file mode 100644
index 00000000..a54e8b6d
--- /dev/null
+++ b/fuzz/client_corpus/f32305c1d36de1b0fb6d285af73faf95c35dbd16
Binary files differ
diff --git a/fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2 b/fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2
new file mode 100644
index 00000000..834d321d
--- /dev/null
+++ b/fuzz/client_corpus/f35d6f2a1afc32377a077202b533490fa53ef4e2
Binary files differ
diff --git a/fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0 b/fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0
new file mode 100644
index 00000000..819e6d8f
--- /dev/null
+++ b/fuzz/client_corpus/f45c5268333bc7bb0b7cca415d591d825e42ceb0
Binary files differ
diff --git a/fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286 b/fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286
new file mode 100644
index 00000000..ef2d2302
--- /dev/null
+++ b/fuzz/client_corpus/f46c909f402c6c9388a03588a3259caa870ab286
Binary files differ
diff --git a/fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2 b/fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2
new file mode 100644
index 00000000..1a8e4e64
--- /dev/null
+++ b/fuzz/client_corpus/f490ddb2112392be3524baf6a9232090865665e2
Binary files differ
diff --git a/fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9 b/fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9
new file mode 100644
index 00000000..b1815b7c
--- /dev/null
+++ b/fuzz/client_corpus/f4bad3d51cdf7d01881e91f8a490cea8d1e54ea9
Binary files differ
diff --git a/fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8e b/fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8e
new file mode 100644
index 00000000..705272b5
--- /dev/null
+++ b/fuzz/client_corpus/f4f2510033775e469a30abcfbc0a32fe6d515f8e
Binary files differ
diff --git a/fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097a b/fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097a
new file mode 100644
index 00000000..d9cd5a7e
--- /dev/null
+++ b/fuzz/client_corpus/f4fd47fe28b86db86a6924d755b21e4de999097a
Binary files differ
diff --git a/fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8 b/fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8
new file mode 100644
index 00000000..db25df95
--- /dev/null
+++ b/fuzz/client_corpus/f56b7a7c163e45f1bcb7f770f1dedae14f6118d8
Binary files differ
diff --git a/fuzz/client_corpus/f5df7fc246fc8d4b89c1cd46c9ef1140ec57ffae b/fuzz/client_corpus/f5df7fc246fc8d4b89c1cd46c9ef1140ec57ffae
deleted file mode 100644
index 55963577..00000000
--- a/fuzz/client_corpus/f5df7fc246fc8d4b89c1cd46c9ef1140ec57ffae
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944a b/fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944a
new file mode 100644
index 00000000..964a4cd9
--- /dev/null
+++ b/fuzz/client_corpus/f5dfbb265362ba53aba22dba5f1ea72fd6e5944a
Binary files differ
diff --git a/fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae b/fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae
new file mode 100644
index 00000000..f7a46403
--- /dev/null
+++ b/fuzz/client_corpus/f68b9f23a79a62e1d6175d0c88e9c1f68d27cbae
Binary files differ
diff --git a/fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4b b/fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4b
new file mode 100644
index 00000000..e560f951
--- /dev/null
+++ b/fuzz/client_corpus/f6913522dd421f05632968344bd38c06d1954d4b
Binary files differ
diff --git a/fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84fe b/fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84fe
new file mode 100644
index 00000000..cbac193f
--- /dev/null
+++ b/fuzz/client_corpus/f6c8c28942664fd860f1105fc6a734f94a6f84fe
Binary files differ
diff --git a/fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3 b/fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3
new file mode 100644
index 00000000..e4a2d3d4
--- /dev/null
+++ b/fuzz/client_corpus/f734fc3f014d55431bcdd133b58da2b1a96380d3
Binary files differ
diff --git a/fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9 b/fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9
new file mode 100644
index 00000000..e1a07e5d
--- /dev/null
+++ b/fuzz/client_corpus/f7993bc9d744a6cd696b1a3c3ddcfcf783670dd9
Binary files differ
diff --git a/fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060a b/fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060a
new file mode 100644
index 00000000..9232d490
--- /dev/null
+++ b/fuzz/client_corpus/f855d4851bf113baf924a3694e3256fa084b060a
Binary files differ
diff --git a/fuzz/client_corpus/f8eb6c08a85e0474abf60cd5e222093cfbdd95f8 b/fuzz/client_corpus/f8eb6c08a85e0474abf60cd5e222093cfbdd95f8
deleted file mode 100644
index f793cf40..00000000
--- a/fuzz/client_corpus/f8eb6c08a85e0474abf60cd5e222093cfbdd95f8
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/f978108e734598b126868ee1dfba52a2f03f2af7 b/fuzz/client_corpus/f978108e734598b126868ee1dfba52a2f03f2af7
deleted file mode 100644
index 25c2b84e..00000000
--- a/fuzz/client_corpus/f978108e734598b126868ee1dfba52a2f03f2af7
+++ /dev/null
Binary files differ
diff --git a/fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090 b/fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090
new file mode 100644
index 00000000..1f6077cf
--- /dev/null
+++ b/fuzz/client_corpus/fa3a1b5f04942ab0eccd31075514dc93e542e090
Binary files differ
diff --git a/fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21 b/fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21
new file mode 100644
index 00000000..384becd2
--- /dev/null
+++ b/fuzz/client_corpus/fab4991ad6fa8f169113266acab7a163ad17fe21
Binary files differ
diff --git a/fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502a b/fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502a
new file mode 100644
index 00000000..c7abe5e8
--- /dev/null
+++ b/fuzz/client_corpus/fab7c6b18d19dd33b24adc9cf45d53e385ae502a
Binary files differ
diff --git a/fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31 b/fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31
new file mode 100644
index 00000000..211e50c9
--- /dev/null
+++ b/fuzz/client_corpus/fb0317a7ce975c9dfa03675f67ca79aa488e3c31
Binary files differ
diff --git a/fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08 b/fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08
new file mode 100644
index 00000000..853de8a8
--- /dev/null
+++ b/fuzz/client_corpus/fb9480b786a21506a1ec7934c939acf52c7bbe08
Binary files differ
diff --git a/fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80b b/fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80b
new file mode 100644
index 00000000..bd74d9bb
--- /dev/null
+++ b/fuzz/client_corpus/fb99ad4d6f7a231d56480050b364e0e37e91f80b
Binary files differ
diff --git a/fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afb b/fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afb
new file mode 100644
index 00000000..668c6fa9
--- /dev/null
+++ b/fuzz/client_corpus/fd86260d8b505b81449a6c72f4c86ae869366afb
Binary files differ
diff --git a/fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5a b/fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5a
new file mode 100644
index 00000000..3a01319b
--- /dev/null
+++ b/fuzz/client_corpus/fdad067c8148822fffbbf2e8ec8b0021ea597b5a
Binary files differ
diff --git a/fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579 b/fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579
new file mode 100644
index 00000000..73dee12c
--- /dev/null
+++ b/fuzz/client_corpus/fe9abe3ee8ab25893f43f213496ba1c01f9d8579
Binary files differ
diff --git a/fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60 b/fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60
new file mode 100644
index 00000000..d23f09e4
--- /dev/null
+++ b/fuzz/client_corpus/feb7e9ac7b76f28911465a514c2c8ec273e2ba60
Binary files differ
diff --git a/fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749 b/fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749
new file mode 100644
index 00000000..7b6062b4
--- /dev/null
+++ b/fuzz/client_corpus/ff7f5fcbaf508db2e56ff22d5f38446f03837749
Binary files differ
diff --git a/fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561 b/fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561
new file mode 100644
index 00000000..68136af0
--- /dev/null
+++ b/fuzz/client_corpus/ffc9310b8efa4d9644324dc9c79b0024aa28c561
Binary files differ
diff --git a/fuzz/minimise_corpuses.sh b/fuzz/minimise_corpuses.sh
index 6a0b7aa6..7c45ef66 100644
--- a/fuzz/minimise_corpuses.sh
+++ b/fuzz/minimise_corpuses.sh
@@ -1,6 +1,27 @@
+# Copyright (c) 2016, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+set -e
+
+buildDir=../build
+if [ $# -gt 0 ]; then
+ buildDir=$1
+fi
+
for testSource in $(ls -1 *.cc); do
test=$(echo $testSource | sed -e 's/\.cc$//')
- if [ ! -x ../build/fuzz/$test ] ; then
+ if [ ! -x $buildDir/fuzz/$test ] ; then
echo "Failed to find binary for $test"
exit 1
fi
@@ -16,8 +37,8 @@ done
for testSource in $(ls -1 *.cc); do
test=$(echo $testSource | sed -e 's/\.cc$//')
- mv ${test}_corpus ${test}_corpus_old && \
- mkdir ${test}_corpus
- ../build/fuzz/$test -max_len=50000 -runs=0 -save_minimized_corpus=1 ${test}_corpus ${test}_corpus_old &&
- rm -Rf ${test}_corpus_old
+ mv ${test}_corpus ${test}_corpus_old
+ mkdir ${test}_corpus
+ $buildDir/fuzz/$test -max_len=50000 -merge=1 ${test}_corpus ${test}_corpus_old
+ rm -Rf ${test}_corpus_old
done
diff --git a/fuzz/pkcs8.cc b/fuzz/pkcs8.cc
new file mode 100644
index 00000000..55d38930
--- /dev/null
+++ b/fuzz/pkcs8.cc
@@ -0,0 +1,38 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/bytestring.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
+ CBS cbs;
+ CBS_init(&cbs, buf, len);
+ EVP_PKEY *pkey = EVP_parse_private_key(&cbs);
+ if (pkey == NULL) {
+ return 0;
+ }
+
+ uint8_t *der;
+ size_t der_len;
+ CBB cbb;
+ if (CBB_init(&cbb, 0) &&
+ EVP_marshal_private_key(&cbb, pkey) &&
+ CBB_finish(&cbb, &der, &der_len)) {
+ OPENSSL_free(der);
+ }
+ CBB_cleanup(&cbb);
+ EVP_PKEY_free(pkey);
+ return 0;
+}
diff --git a/fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63 b/fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63
new file mode 100644
index 00000000..3221600e
--- /dev/null
+++ b/fuzz/pkcs8_corpus/129ebe4bf8b167a37741c9c470fd7c4a0359ad63
Binary files differ
diff --git a/fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350b b/fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350b
new file mode 100644
index 00000000..05800eef
--- /dev/null
+++ b/fuzz/pkcs8_corpus/1bf03b5d9f129cd80513b820a55c9568eb1d350b
Binary files differ
diff --git a/fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3f b/fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3f
new file mode 100644
index 00000000..df3b06bf
--- /dev/null
+++ b/fuzz/pkcs8_corpus/225df81ad5fc9783575b57e20207645e55a8fa3f
Binary files differ
diff --git a/fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53 b/fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53
new file mode 100644
index 00000000..a13699c4
--- /dev/null
+++ b/fuzz/pkcs8_corpus/3033b336d833baef80981f40394c281c20677f53
Binary files differ
diff --git a/fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7 b/fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7
new file mode 100644
index 00000000..96f304e7
--- /dev/null
+++ b/fuzz/pkcs8_corpus/31aa87887801ac3f6eaab0bade714e56fcb5fab7
Binary files differ
diff --git a/fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348 b/fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348
new file mode 100644
index 00000000..ab5dc9e0
--- /dev/null
+++ b/fuzz/pkcs8_corpus/3f7e0b4378403f44de34874789bce582790a1348
Binary files differ
diff --git a/fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046 b/fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046
new file mode 100644
index 00000000..05020c93
--- /dev/null
+++ b/fuzz/pkcs8_corpus/40d5a9f71cacb2389b58a8a24cfa52d6b51bf046
Binary files differ
diff --git a/fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125ab b/fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125ab
new file mode 100644
index 00000000..4d4de1c8
--- /dev/null
+++ b/fuzz/pkcs8_corpus/57e8e625f2f2313f2ec174a3209972e9bc5125ab
Binary files differ
diff --git a/fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75 b/fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75
new file mode 100644
index 00000000..7e8322c0
--- /dev/null
+++ b/fuzz/pkcs8_corpus/89db3807a0d30e36007b74c8ee4aac912fe3fd75
Binary files differ
diff --git a/fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08 b/fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08
new file mode 100644
index 00000000..fe360394
--- /dev/null
+++ b/fuzz/pkcs8_corpus/d38e79992de4ffaf585a6450ba2e6f21188fdd08
Binary files differ
diff --git a/fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36b b/fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36b
new file mode 100644
index 00000000..f45bac55
--- /dev/null
+++ b/fuzz/pkcs8_corpus/d9206dbdd26c06ee8de4e587553e72b3bb22d36b
Binary files differ
diff --git a/fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41fe b/fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41fe
new file mode 100644
index 00000000..4047d7e4
--- /dev/null
+++ b/fuzz/pkcs8_corpus/e0a0b34deb64510a36919a13258bd2c8725e41fe
Binary files differ
diff --git a/fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7 b/fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7
new file mode 100644
index 00000000..477a3da1
--- /dev/null
+++ b/fuzz/pkcs8_corpus/e5cfb9f3e23eda47731b1cf3414df1bd408179b7
Binary files differ
diff --git a/fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648 b/fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648
new file mode 100644
index 00000000..d9a28d42
--- /dev/null
+++ b/fuzz/pkcs8_corpus/efb2c016e9375355e04a5d99e2a17415c9d4f648
Binary files differ
diff --git a/fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18e b/fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18e
new file mode 100644
index 00000000..cac230a5
--- /dev/null
+++ b/fuzz/pkcs8_corpus/fc0fad9f9fb142dee99a03a50a64d10767f9f18e
Binary files differ
diff --git a/fuzz/privkey.cc b/fuzz/privkey.cc
index 094d438f..a7cd1b7b 100644
--- a/fuzz/privkey.cc
+++ b/fuzz/privkey.cc
@@ -1,3 +1,17 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
#include <openssl/evp.h>
extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
diff --git a/fuzz/privkey_corpus/0011b315985d69eb7e3e2eb946d7b17b2ba124d8 b/fuzz/privkey_corpus/0011b315985d69eb7e3e2eb946d7b17b2ba124d8
deleted file mode 100644
index 3e4af813..00000000
--- a/fuzz/privkey_corpus/0011b315985d69eb7e3e2eb946d7b17b2ba124d8
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3 b/fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3
new file mode 100644
index 00000000..2b0fd294
--- /dev/null
+++ b/fuzz/privkey_corpus/00c42569d947a510cf9797c6f57e072aa0ca5bb3
Binary files differ
diff --git a/fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104 b/fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104
new file mode 100644
index 00000000..f56d6bbc
--- /dev/null
+++ b/fuzz/privkey_corpus/015681c081de9b2950dcfe212a3ce6a12cae5104
Binary files differ
diff --git a/fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9 b/fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9
new file mode 100644
index 00000000..38c74b90
--- /dev/null
+++ b/fuzz/privkey_corpus/019773b072a48b8cf7e0aa11b1d9a37898dc70f9
Binary files differ
diff --git a/fuzz/privkey_corpus/04d89eb4c7cb4e6dc1e26b1104ee2f78c77e573f b/fuzz/privkey_corpus/04d89eb4c7cb4e6dc1e26b1104ee2f78c77e573f
deleted file mode 100644
index deb48b5f..00000000
--- a/fuzz/privkey_corpus/04d89eb4c7cb4e6dc1e26b1104ee2f78c77e573f
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67 b/fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67
new file mode 100644
index 00000000..02928978
--- /dev/null
+++ b/fuzz/privkey_corpus/05025c1927ae0e2827a85a34c295f2aa08e58b67
Binary files differ
diff --git a/fuzz/privkey_corpus/0553b1378ca822d924b1ea95c6654e3508faa8bf b/fuzz/privkey_corpus/0553b1378ca822d924b1ea95c6654e3508faa8bf
deleted file mode 100644
index 28130ae9..00000000
--- a/fuzz/privkey_corpus/0553b1378ca822d924b1ea95c6654e3508faa8bf
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/0555561f448567b597875a17041f0cfc6dd30527 b/fuzz/privkey_corpus/0555561f448567b597875a17041f0cfc6dd30527
deleted file mode 100644
index 443eaa40..00000000
--- a/fuzz/privkey_corpus/0555561f448567b597875a17041f0cfc6dd30527
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4 b/fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4
new file mode 100644
index 00000000..b3e6ac04
--- /dev/null
+++ b/fuzz/privkey_corpus/05a573fb3bb39c31923a303fc2792e72eff61cc4
Binary files differ
diff --git a/fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35 b/fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35
new file mode 100644
index 00000000..d16e08b6
--- /dev/null
+++ b/fuzz/privkey_corpus/061a18d5264822fc83ec032231ebaf117ffb6b35
Binary files differ
diff --git a/fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2 b/fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2
new file mode 100644
index 00000000..aa55da67
--- /dev/null
+++ b/fuzz/privkey_corpus/0769477785fe09940b3003c2d57ae2510be249d2
Binary files differ
diff --git a/fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60b b/fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60b
new file mode 100644
index 00000000..09641d1f
--- /dev/null
+++ b/fuzz/privkey_corpus/077658aca2047636d0a66aff776af558a960e60b
Binary files differ
diff --git a/fuzz/privkey_corpus/078f4cb1e10cc91428b751c97f543eaba2303b6f b/fuzz/privkey_corpus/078f4cb1e10cc91428b751c97f543eaba2303b6f
deleted file mode 100644
index d8edb6f4..00000000
--- a/fuzz/privkey_corpus/078f4cb1e10cc91428b751c97f543eaba2303b6f
+++ /dev/null
@@ -1 +0,0 @@
-00% 0 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92f b/fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92f
new file mode 100644
index 00000000..4bb2e46f
--- /dev/null
+++ b/fuzz/privkey_corpus/09db9192b630c602121231a0de852de7888af92f
Binary files differ
diff --git a/fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4f b/fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4f
new file mode 100644
index 00000000..3b2e9522
--- /dev/null
+++ b/fuzz/privkey_corpus/0a6ff602ee335dd5e91e1ce4e4807f9830108e4f
Binary files differ
diff --git a/fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346 b/fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346
new file mode 100644
index 00000000..6f955481
--- /dev/null
+++ b/fuzz/privkey_corpus/0b274245377b1f87f39f76dbc876d43192ec7346
Binary files differ
diff --git a/fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5 b/fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5
new file mode 100644
index 00000000..b6efb3d5
--- /dev/null
+++ b/fuzz/privkey_corpus/0b85f3e44876a3d970e21d829336e33faa9d36d5
Binary files differ
diff --git a/fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961 b/fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961
new file mode 100644
index 00000000..bcc6e0ee
--- /dev/null
+++ b/fuzz/privkey_corpus/0c49b71767b49200648c3672ba14308d8a525961
Binary files differ
diff --git a/fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95e b/fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95e
new file mode 100644
index 00000000..8b9d315e
--- /dev/null
+++ b/fuzz/privkey_corpus/0e33f8a77a50c72a6a6d72a539badee3bb8cf95e
Binary files differ
diff --git a/fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2f b/fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2f
new file mode 100644
index 00000000..530056a6
--- /dev/null
+++ b/fuzz/privkey_corpus/0e371858c1ec53ce2327b9067fb0f663b3951f2f
Binary files differ
diff --git a/fuzz/privkey_corpus/0e490fa7001442785c829645692993a1f55c9653 b/fuzz/privkey_corpus/0e490fa7001442785c829645692993a1f55c9653
deleted file mode 100644
index d65345e2..00000000
--- a/fuzz/privkey_corpus/0e490fa7001442785c829645692993a1f55c9653
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0 b/fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0
new file mode 100644
index 00000000..01982fbd
--- /dev/null
+++ b/fuzz/privkey_corpus/0fe7d2c6759892ccb8117dee4427b01230c32ac0
Binary files differ
diff --git a/fuzz/privkey_corpus/103201e00ff234028e8795585d722409ba8b85c3 b/fuzz/privkey_corpus/103201e00ff234028e8795585d722409ba8b85c3
deleted file mode 100644
index caee37f6..00000000
--- a/fuzz/privkey_corpus/103201e00ff234028e8795585d722409ba8b85c3
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/1074eb39d16c92b2d4ae77245a32f63353739780 b/fuzz/privkey_corpus/1074eb39d16c92b2d4ae77245a32f63353739780
deleted file mode 100644
index 87d7d770..00000000
--- a/fuzz/privkey_corpus/1074eb39d16c92b2d4ae77245a32f63353739780
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673 b/fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673
new file mode 100644
index 00000000..98b0eb30
--- /dev/null
+++ b/fuzz/privkey_corpus/111513715bade1f0f1a1bcd76defc32853664673
Binary files differ
diff --git a/fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4 b/fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4
new file mode 100644
index 00000000..d06ba8b2
--- /dev/null
+++ b/fuzz/privkey_corpus/1116b7d25a60b231dcb7f6b244cfae6ebc272bc4
Binary files differ
diff --git a/fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7 b/fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7
new file mode 100644
index 00000000..bf9ea3aa
--- /dev/null
+++ b/fuzz/privkey_corpus/144955d4b56923a5003f4778a724aaae45e133a7
Binary files differ
diff --git a/fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794 b/fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794
new file mode 100644
index 00000000..6bd56465
--- /dev/null
+++ b/fuzz/privkey_corpus/159042d0b44248e2218fde21764132a20b29f794
Binary files differ
diff --git a/fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1 b/fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1
new file mode 100644
index 00000000..38874749
--- /dev/null
+++ b/fuzz/privkey_corpus/1716744626b9a81aafcd612d6802ba6d968533b1
Binary files differ
diff --git a/fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1 b/fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1
new file mode 100644
index 00000000..648100e8
--- /dev/null
+++ b/fuzz/privkey_corpus/171735592c8f147c39aa928c10b3a2fb101eadb1
Binary files differ
diff --git a/fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4 b/fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4
new file mode 100644
index 00000000..2e03c880
--- /dev/null
+++ b/fuzz/privkey_corpus/1786f7578e40c0526ef27e9d14276f2e30cf1fa4
Binary files differ
diff --git a/fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574 b/fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574
new file mode 100644
index 00000000..26c288af
--- /dev/null
+++ b/fuzz/privkey_corpus/17960a325cbc94a0d43d005a00f7243b44403574
Binary files differ
diff --git a/fuzz/privkey_corpus/1898789ee447b3c8fe5731fdf02c603aba33ca4e b/fuzz/privkey_corpus/1898789ee447b3c8fe5731fdf02c603aba33ca4e
deleted file mode 100644
index e5d63b8d..00000000
--- a/fuzz/privkey_corpus/1898789ee447b3c8fe5731fdf02c603aba33ca4e
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301b b/fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301b
new file mode 100644
index 00000000..bd998c56
--- /dev/null
+++ b/fuzz/privkey_corpus/19793a06cf885b10b04e38a23649bd7f1e31301b
Binary files differ
diff --git a/fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489d b/fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489d
new file mode 100644
index 00000000..09e29bc1
--- /dev/null
+++ b/fuzz/privkey_corpus/1a23c272e3bef73eb0bbd4f74122a1c99d86489d
Binary files differ
diff --git a/fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fd b/fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fd
new file mode 100644
index 00000000..c12613f7
--- /dev/null
+++ b/fuzz/privkey_corpus/1b2547c6637c3b54fe2c243a56ebc2b778e574fd
Binary files differ
diff --git a/fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b b/fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b
new file mode 100644
index 00000000..127ef66b
--- /dev/null
+++ b/fuzz/privkey_corpus/1e5f0ef4e8fedbd7d8712b9b65accaa4257c6e1b
Binary files differ
diff --git a/fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018 b/fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018
new file mode 100644
index 00000000..9d1ee6b7
--- /dev/null
+++ b/fuzz/privkey_corpus/1fbe5e5f1e017d5624f50ce4fe90f4e2aef10018
Binary files differ
diff --git a/fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01 b/fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01
new file mode 100644
index 00000000..d1a75470
--- /dev/null
+++ b/fuzz/privkey_corpus/21390a583c6914c6217e3e7a6f0f500565c3db01
Binary files differ
diff --git a/fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73ef b/fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73ef
new file mode 100644
index 00000000..dc8f4e43
--- /dev/null
+++ b/fuzz/privkey_corpus/25c8eb80d13e90627aeaeb6041ec5c9c80db73ef
Binary files differ
diff --git a/fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904 b/fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904
new file mode 100644
index 00000000..3eb536e4
--- /dev/null
+++ b/fuzz/privkey_corpus/2658121eaf30eacfa090bbfb248068dde890a904
Binary files differ
diff --git a/fuzz/privkey_corpus/272ef5b501f038eccbae4084d7cd476f69c9baa8 b/fuzz/privkey_corpus/272ef5b501f038eccbae4084d7cd476f69c9baa8
deleted file mode 100644
index 2f2a95e1..00000000
--- a/fuzz/privkey_corpus/272ef5b501f038eccbae4084d7cd476f69c9baa8
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/27ca11aae0b2385e458770be3a4cc8ca2c7d7eb5 b/fuzz/privkey_corpus/27ca11aae0b2385e458770be3a4cc8ca2c7d7eb5
deleted file mode 100644
index 54c0aba5..00000000
--- a/fuzz/privkey_corpus/27ca11aae0b2385e458770be3a4cc8ca2c7d7eb5
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/288788112f0df06a025c8020b3783aa5de18727b b/fuzz/privkey_corpus/288788112f0df06a025c8020b3783aa5de18727b
deleted file mode 100644
index 3f99355a..00000000
--- a/fuzz/privkey_corpus/288788112f0df06a025c8020b3783aa5de18727b
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423b b/fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423b
new file mode 100644
index 00000000..9f05553c
--- /dev/null
+++ b/fuzz/privkey_corpus/290126ecf71a6a446667ef8d55e533330409423b
Binary files differ
diff --git a/fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8 b/fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8
new file mode 100644
index 00000000..a6f9ba1e
--- /dev/null
+++ b/fuzz/privkey_corpus/2909caee653dbeefc20c7071a91eae9f4cfa35b8
Binary files differ
diff --git a/fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4 b/fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4
new file mode 100644
index 00000000..3e4f31bc
--- /dev/null
+++ b/fuzz/privkey_corpus/290a2847a0a316567c9c292d1655934b092196b4
Binary files differ
diff --git a/fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9 b/fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9
new file mode 100644
index 00000000..278f2da5
--- /dev/null
+++ b/fuzz/privkey_corpus/29c333dee5bb24eebdd3a69e2f384115b62f5da9
Binary files differ
diff --git a/fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183e b/fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183e
new file mode 100644
index 00000000..83d13653
--- /dev/null
+++ b/fuzz/privkey_corpus/2acf5bdf834aaad09ced02a2f9b17c6b84ee183e
Binary files differ
diff --git a/fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0 b/fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0
new file mode 100644
index 00000000..4eb5cb00
--- /dev/null
+++ b/fuzz/privkey_corpus/2b3a1c22ead8fc7d963fc8b09d733529970a1ed0
Binary files differ
diff --git a/fuzz/privkey_corpus/2bd1d090ed0b879a80e200d18199361abdb583c6 b/fuzz/privkey_corpus/2bd1d090ed0b879a80e200d18199361abdb583c6
deleted file mode 100644
index 323c98b0..00000000
--- a/fuzz/privkey_corpus/2bd1d090ed0b879a80e200d18199361abdb583c6
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/2cc2eb036512e3407569cb670d99d53b77708ffd b/fuzz/privkey_corpus/2cc2eb036512e3407569cb670d99d53b77708ffd
deleted file mode 100644
index 3b71d74b..00000000
--- a/fuzz/privkey_corpus/2cc2eb036512e3407569cb670d99d53b77708ffd
+++ /dev/null
@@ -1 +0,0 @@
-0)'00*00);;;00'0)B*0!L''0 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696 b/fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696
new file mode 100644
index 00000000..00ab22d8
--- /dev/null
+++ b/fuzz/privkey_corpus/2d91275a1b8cfa0d6d96bf496b71f39ee061f696
Binary files differ
diff --git a/fuzz/privkey_corpus/2ddcac6ee1d95669aba11a7960f9b3d2f23801e2 b/fuzz/privkey_corpus/2ddcac6ee1d95669aba11a7960f9b3d2f23801e2
deleted file mode 100644
index f903ac1a..00000000
--- a/fuzz/privkey_corpus/2ddcac6ee1d95669aba11a7960f9b3d2f23801e2
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9 b/fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9
new file mode 100644
index 00000000..b9b5d975
--- /dev/null
+++ b/fuzz/privkey_corpus/2eb06460c0ce9f89df1b7b71d59ffe29007b24b9
Binary files differ
diff --git a/fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274 b/fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274
new file mode 100644
index 00000000..51cc7f75
--- /dev/null
+++ b/fuzz/privkey_corpus/2f180fb11e42c282af2cce12419433c3edc37274
Binary files differ
diff --git a/fuzz/privkey_corpus/2f224b103dee345266651abd8ca972e8e0d5515a b/fuzz/privkey_corpus/2f224b103dee345266651abd8ca972e8e0d5515a
deleted file mode 100644
index fda07e61..00000000
--- a/fuzz/privkey_corpus/2f224b103dee345266651abd8ca972e8e0d5515a
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9 b/fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9
new file mode 100644
index 00000000..353c7548
--- /dev/null
+++ b/fuzz/privkey_corpus/2f8e198fa3cd2d59a1bbe2ac182de095368689f9
Binary files differ
diff --git a/fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164 b/fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164
new file mode 100644
index 00000000..8196de39
--- /dev/null
+++ b/fuzz/privkey_corpus/30cdd0dffab35c6e1fa833a06956f29de0540164
Binary files differ
diff --git a/fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4 b/fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4
new file mode 100644
index 00000000..3a82476d
--- /dev/null
+++ b/fuzz/privkey_corpus/30d35fe2026932f96aa4254f12fba48d42ddabe4
Binary files differ
diff --git a/fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068 b/fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068
new file mode 100644
index 00000000..10971e67
--- /dev/null
+++ b/fuzz/privkey_corpus/312b84ddde85711337fe7e38f9e66c67d53af068
Binary files differ
diff --git a/fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29 b/fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29
new file mode 100644
index 00000000..dc4a1595
--- /dev/null
+++ b/fuzz/privkey_corpus/32e6213837aac65804f3b3c57a9a58b3dd751e29
Binary files differ
diff --git a/fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0 b/fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0
new file mode 100644
index 00000000..360bc456
--- /dev/null
+++ b/fuzz/privkey_corpus/339e070bfd090281e546cefa960412b76bcaafb0
Binary files differ
diff --git a/fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32af b/fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32af
new file mode 100644
index 00000000..e701803e
--- /dev/null
+++ b/fuzz/privkey_corpus/346b0e49695097dec5bc9f39616b744e825c32af
Binary files differ
diff --git a/fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39 b/fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39
new file mode 100644
index 00000000..548f7750
--- /dev/null
+++ b/fuzz/privkey_corpus/3485d5bced3fb725b0d5db9a9a5ededd07b84b39
Binary files differ
diff --git a/fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75 b/fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75
new file mode 100644
index 00000000..35cb9a6f
--- /dev/null
+++ b/fuzz/privkey_corpus/3499daeee13c1a1f32021dd6666834b3f57eaf75
Binary files differ
diff --git a/fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19ef b/fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19ef
new file mode 100644
index 00000000..176b6833
--- /dev/null
+++ b/fuzz/privkey_corpus/35191613835734a77f62636d0e5ca55656df19ef
Binary files differ
diff --git a/fuzz/privkey_corpus/359d4453699f8fc738128afd76853e637d453f22 b/fuzz/privkey_corpus/359d4453699f8fc738128afd76853e637d453f22
deleted file mode 100644
index a52bdf31..00000000
--- a/fuzz/privkey_corpus/359d4453699f8fc738128afd76853e637d453f22
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adf b/fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adf
new file mode 100644
index 00000000..ee5af358
--- /dev/null
+++ b/fuzz/privkey_corpus/35d56dec4d0b9eee7bc3f7116694b78bd3e14adf
Binary files differ
diff --git a/fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735 b/fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735
new file mode 100644
index 00000000..1d89360f
--- /dev/null
+++ b/fuzz/privkey_corpus/35ec32a0302aff2dd46b92744dd0e0aad643a735
Binary files differ
diff --git a/fuzz/privkey_corpus/378d3cdaaeab3bbeeca778259c1fcf1b916c0936 b/fuzz/privkey_corpus/378d3cdaaeab3bbeeca778259c1fcf1b916c0936
deleted file mode 100644
index 2787163c..00000000
--- a/fuzz/privkey_corpus/378d3cdaaeab3bbeeca778259c1fcf1b916c0936
+++ /dev/null
@@ -1 +0,0 @@
-' \ No newline at end of file
diff --git a/fuzz/privkey_corpus/38fd17896ebaa4c75cd71d1255f3194ddc1f8829 b/fuzz/privkey_corpus/38fd17896ebaa4c75cd71d1255f3194ddc1f8829
deleted file mode 100644
index b5ab4582..00000000
--- a/fuzz/privkey_corpus/38fd17896ebaa4c75cd71d1255f3194ddc1f8829
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85 b/fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85
new file mode 100644
index 00000000..3a386e55
--- /dev/null
+++ b/fuzz/privkey_corpus/390356980b48356de3bb28ddbc5cf107ec4f7a85
Binary files differ
diff --git a/fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4 b/fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4
new file mode 100644
index 00000000..25c92d18
--- /dev/null
+++ b/fuzz/privkey_corpus/3a37605591ee36af41d000670302ff871c78a9e4
Binary files differ
diff --git a/fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7 b/fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7
new file mode 100644
index 00000000..d44126ad
--- /dev/null
+++ b/fuzz/privkey_corpus/3b99bd1bf571734f599661c6e3032034c1c397a7
Binary files differ
diff --git a/fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512 b/fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512
new file mode 100644
index 00000000..ba908232
--- /dev/null
+++ b/fuzz/privkey_corpus/3c0fd6b8973aecbc8515b7659c611b1f43fc9512
Binary files differ
diff --git a/fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754 b/fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754
new file mode 100644
index 00000000..50b260a9
--- /dev/null
+++ b/fuzz/privkey_corpus/3d70c8546bd266eb21f3ad3410ce40ce0f11c754
Binary files differ
diff --git a/fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193 b/fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193
new file mode 100644
index 00000000..e81eaf03
--- /dev/null
+++ b/fuzz/privkey_corpus/3da8eb8c3fad53453fe6be874706f011290cc193
Binary files differ
diff --git a/fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31 b/fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31
new file mode 100644
index 00000000..a4d6d0ef
--- /dev/null
+++ b/fuzz/privkey_corpus/3fa9a81502da9188dc226556ca3ebedf247b2a31
Binary files differ
diff --git a/fuzz/privkey_corpus/3fdb71ab5aec32080dbc60867a754e57cabc90de b/fuzz/privkey_corpus/3fdb71ab5aec32080dbc60867a754e57cabc90de
deleted file mode 100644
index 7fb4c510..00000000
--- a/fuzz/privkey_corpus/3fdb71ab5aec32080dbc60867a754e57cabc90de
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574b b/fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574b
new file mode 100644
index 00000000..50847fa7
--- /dev/null
+++ b/fuzz/privkey_corpus/401ae4a9be451bec291b1ea4d2a3326b9b40574b
Binary files differ
diff --git a/fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10 b/fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10
new file mode 100644
index 00000000..da2802b2
--- /dev/null
+++ b/fuzz/privkey_corpus/4084d7b10c7f3c7e5312e49c478ba7f01545fc10
Binary files differ
diff --git a/fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217 b/fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217
new file mode 100644
index 00000000..dc9de300
--- /dev/null
+++ b/fuzz/privkey_corpus/41180009eff3da207f5fab3a1e03764aaabff217
Binary files differ
diff --git a/fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5 b/fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5
new file mode 100644
index 00000000..dc2e774e
--- /dev/null
+++ b/fuzz/privkey_corpus/4225b400b9e45f5b3a9bea9b4b1ded8c400a1be5
Binary files differ
diff --git a/fuzz/privkey_corpus/429f95d3029b0242e7ae1c668f64317196d5a442 b/fuzz/privkey_corpus/429f95d3029b0242e7ae1c668f64317196d5a442
deleted file mode 100644
index ff3633ed..00000000
--- a/fuzz/privkey_corpus/429f95d3029b0242e7ae1c668f64317196d5a442
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/476758eb3f59a8dfa8effeeca7f610d795a69701 b/fuzz/privkey_corpus/476758eb3f59a8dfa8effeeca7f610d795a69701
deleted file mode 100644
index aa2b49cc..00000000
--- a/fuzz/privkey_corpus/476758eb3f59a8dfa8effeeca7f610d795a69701
+++ /dev/null
@@ -1 +0,0 @@
-: \ No newline at end of file
diff --git a/fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0 b/fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0
new file mode 100644
index 00000000..0e7ae5f0
--- /dev/null
+++ b/fuzz/privkey_corpus/48832cec638db3098a957580a1da162535ae25a0
Binary files differ
diff --git a/fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412 b/fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412
new file mode 100644
index 00000000..c80a11ac
--- /dev/null
+++ b/fuzz/privkey_corpus/4af1489b0c9ee9d122721c257dbcc71076950412
Binary files differ
diff --git a/fuzz/privkey_corpus/4b68c5924a60f7c907987c79af7d972644c5c990 b/fuzz/privkey_corpus/4b68c5924a60f7c907987c79af7d972644c5c990
deleted file mode 100644
index b4298d0d..00000000
--- a/fuzz/privkey_corpus/4b68c5924a60f7c907987c79af7d972644c5c990
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/4c19e7a0b01f37323b6f19b2e5ef3217de6b350a b/fuzz/privkey_corpus/4c19e7a0b01f37323b6f19b2e5ef3217de6b350a
deleted file mode 100644
index f6f011a2..00000000
--- a/fuzz/privkey_corpus/4c19e7a0b01f37323b6f19b2e5ef3217de6b350a
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/4f653e0b8a3b198d0b2deadec8a6e23635f27032 b/fuzz/privkey_corpus/4f653e0b8a3b198d0b2deadec8a6e23635f27032
deleted file mode 100644
index f65b94bd..00000000
--- a/fuzz/privkey_corpus/4f653e0b8a3b198d0b2deadec8a6e23635f27032
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db b/fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db
new file mode 100644
index 00000000..98ab1e7a
--- /dev/null
+++ b/fuzz/privkey_corpus/4fe79bebd0cc1d75bc6c6f3f35f9792f1dbfe1db
Binary files differ
diff --git a/fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04 b/fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04
new file mode 100644
index 00000000..893471f7
--- /dev/null
+++ b/fuzz/privkey_corpus/502f53c70c4a0cdc28ec7d4e5e663d71628eba04
Binary files differ
diff --git a/fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28 b/fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28
new file mode 100644
index 00000000..f5fc5121
--- /dev/null
+++ b/fuzz/privkey_corpus/50bc50a6a7b81c4f8056973b0c54bdae838c2e28
Binary files differ
diff --git a/fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647 b/fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647
new file mode 100644
index 00000000..b2c494a6
--- /dev/null
+++ b/fuzz/privkey_corpus/516282abddff3db5f7806bb9540c4ffb3da5a647
Binary files differ
diff --git a/fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4e b/fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4e
new file mode 100644
index 00000000..54cb5b8e
--- /dev/null
+++ b/fuzz/privkey_corpus/51911d8d5529737e78a8c07f7835add996096e4e
Binary files differ
diff --git a/fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8 b/fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8
new file mode 100644
index 00000000..3b236f1c
--- /dev/null
+++ b/fuzz/privkey_corpus/528fc66881a989e0be226cb9681f25fe8f8639e8
Binary files differ
diff --git a/fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13e b/fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13e
new file mode 100644
index 00000000..8cd6fdc0
--- /dev/null
+++ b/fuzz/privkey_corpus/5519002b1f0f5920ced3f7db347bb2a9a803f13e
Binary files differ
diff --git a/fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040 b/fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040
new file mode 100644
index 00000000..8e0d23c8
--- /dev/null
+++ b/fuzz/privkey_corpus/552b2592e9e09483334a9e43fb11cf4c60c9a040
Binary files differ
diff --git a/fuzz/privkey_corpus/573829cd6df068f7ac72bfe6f17d79f8b5006aa8 b/fuzz/privkey_corpus/573829cd6df068f7ac72bfe6f17d79f8b5006aa8
deleted file mode 100644
index d626db8d..00000000
--- a/fuzz/privkey_corpus/573829cd6df068f7ac72bfe6f17d79f8b5006aa8
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0 b/fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0
new file mode 100644
index 00000000..9f20287e
--- /dev/null
+++ b/fuzz/privkey_corpus/57e60fab45178a0597b816ff92a5f72d6c789da0
Binary files differ
diff --git a/fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6c b/fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6c
new file mode 100644
index 00000000..e00b2207
--- /dev/null
+++ b/fuzz/privkey_corpus/586d7d93d8c2a3f43248c6b437e743de6dc0ac6c
Binary files differ
diff --git a/fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9 b/fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9
new file mode 100644
index 00000000..34f2f8ad
--- /dev/null
+++ b/fuzz/privkey_corpus/59685ccee38382c2b951f3f147a930aca6157cc9
Binary files differ
diff --git a/fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287 b/fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287
new file mode 100644
index 00000000..f633bcba
--- /dev/null
+++ b/fuzz/privkey_corpus/596f5f7d381c904a2f4bd12ec6e061b8e9656287
Binary files differ
diff --git a/fuzz/privkey_corpus/59b889ce764f1da0bbfb4e90c1856b48fc9f1565 b/fuzz/privkey_corpus/59b889ce764f1da0bbfb4e90c1856b48fc9f1565
deleted file mode 100644
index 034cac7e..00000000
--- a/fuzz/privkey_corpus/59b889ce764f1da0bbfb4e90c1856b48fc9f1565
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87 b/fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87
new file mode 100644
index 00000000..c5906ae7
--- /dev/null
+++ b/fuzz/privkey_corpus/59f333ce69d71f603fe0864944d9b5da92b4cf87
Binary files differ
diff --git a/fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36 b/fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36
new file mode 100644
index 00000000..2cfe629c
--- /dev/null
+++ b/fuzz/privkey_corpus/5aec6cb701b322ad16c4cd6b35e2ba07b09f0f36
Binary files differ
diff --git a/fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9 b/fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9
new file mode 100644
index 00000000..c06289de
--- /dev/null
+++ b/fuzz/privkey_corpus/5b1101cb6a5041a87b29734f0a9e5db654781ad9
Binary files differ
diff --git a/fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217 b/fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217
new file mode 100644
index 00000000..6578bc99
--- /dev/null
+++ b/fuzz/privkey_corpus/5b31b569e17276924adb39d7c501f8146eb40217
Binary files differ
diff --git a/fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692d b/fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692d
new file mode 100644
index 00000000..ee831939
--- /dev/null
+++ b/fuzz/privkey_corpus/5bacad39834b363e5a1c70862881bf1bd6cd692d
Binary files differ
diff --git a/fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e b/fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e
new file mode 100644
index 00000000..0f1c7cb9
--- /dev/null
+++ b/fuzz/privkey_corpus/5c6c100ff72c9e74d3dbf16d7fc29752cf983f0e
Binary files differ
diff --git a/fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e b/fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e
new file mode 100644
index 00000000..05282a1d
--- /dev/null
+++ b/fuzz/privkey_corpus/5c755df2a1f4c2672ff31c9d7d58d6e003a5f42e
Binary files differ
diff --git a/fuzz/privkey_corpus/5c99d308d575a71a5b4ccbd13280bb13ac79894f b/fuzz/privkey_corpus/5c99d308d575a71a5b4ccbd13280bb13ac79894f
deleted file mode 100644
index c6d19bb6..00000000
--- a/fuzz/privkey_corpus/5c99d308d575a71a5b4ccbd13280bb13ac79894f
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841 b/fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841
new file mode 100644
index 00000000..e724e6d9
--- /dev/null
+++ b/fuzz/privkey_corpus/5d50b7105a65869ceb68ad2a8d6dbadc184d0841
Binary files differ
diff --git a/fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaa b/fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaa
new file mode 100644
index 00000000..a4d62667
--- /dev/null
+++ b/fuzz/privkey_corpus/5e89654d60cffb7a5a715535a4aaf4828269cfaa
Binary files differ
diff --git a/fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050b b/fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050b
new file mode 100644
index 00000000..6c8d07c8
--- /dev/null
+++ b/fuzz/privkey_corpus/5ecdfa9f5c5f4052646bc85523a3d66f606f050b
Binary files differ
diff --git a/fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60bec b/fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60bec
new file mode 100644
index 00000000..f5b51e12
--- /dev/null
+++ b/fuzz/privkey_corpus/600e8914f660c5e8d5d403313e6d50c022e60bec
Binary files differ
diff --git a/fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c b/fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c
new file mode 100644
index 00000000..43653a75
--- /dev/null
+++ b/fuzz/privkey_corpus/6099440734ee930046e454c92ff576aafe33023c
@@ -0,0 +1 @@
+0))0000)00)000 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/616d00f4518e24cbf78f5c7898fae159b97de6b5 b/fuzz/privkey_corpus/616d00f4518e24cbf78f5c7898fae159b97de6b5
deleted file mode 100644
index b9e1477f..00000000
--- a/fuzz/privkey_corpus/616d00f4518e24cbf78f5c7898fae159b97de6b5
+++ /dev/null
@@ -1 +0,0 @@
-007 000 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8 b/fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8
new file mode 100644
index 00000000..460566f7
--- /dev/null
+++ b/fuzz/privkey_corpus/61db53da0168c52fbe159f9490f899d40babe9b8
Binary files differ
diff --git a/fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cb b/fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cb
new file mode 100644
index 00000000..8e1c6c8f
--- /dev/null
+++ b/fuzz/privkey_corpus/63a1c254ef76396040a8a11c9715f0d7435ca3cb
Binary files differ
diff --git a/fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9 b/fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9
new file mode 100644
index 00000000..538b5f60
--- /dev/null
+++ b/fuzz/privkey_corpus/63c16bcb66f7e1bf859ddb2652033d08322e1ef9
Binary files differ
diff --git a/fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9b b/fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9b
new file mode 100644
index 00000000..b4a2c650
--- /dev/null
+++ b/fuzz/privkey_corpus/63d06cb1068c254e3dd462b434e985ae8fb10e9b
Binary files differ
diff --git a/fuzz/privkey_corpus/63d9ecea3f2f5141b1bc4c4ada40381999d2ae78 b/fuzz/privkey_corpus/63d9ecea3f2f5141b1bc4c4ada40381999d2ae78
deleted file mode 100644
index d7a6cd8a..00000000
--- a/fuzz/privkey_corpus/63d9ecea3f2f5141b1bc4c4ada40381999d2ae78
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/64213f486e58ce1cc0bea2a6f145e6769dbcb93e b/fuzz/privkey_corpus/64213f486e58ce1cc0bea2a6f145e6769dbcb93e
deleted file mode 100644
index 4be4a5cd..00000000
--- a/fuzz/privkey_corpus/64213f486e58ce1cc0bea2a6f145e6769dbcb93e
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658 b/fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658
new file mode 100644
index 00000000..b83b3ebf
--- /dev/null
+++ b/fuzz/privkey_corpus/6457f1ad199e3535c56189326f5785071ca45658
Binary files differ
diff --git a/fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3 b/fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3
new file mode 100644
index 00000000..a8e09864
--- /dev/null
+++ b/fuzz/privkey_corpus/64d5fbd143dd252a45201c7ca8a9d5df6503fca3
Binary files differ
diff --git a/fuzz/privkey_corpus/6531424fdad457866089d58c9279bd5fe8719ca0 b/fuzz/privkey_corpus/6531424fdad457866089d58c9279bd5fe8719ca0
deleted file mode 100644
index 5e87dec1..00000000
--- a/fuzz/privkey_corpus/6531424fdad457866089d58c9279bd5fe8719ca0
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67 b/fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67
new file mode 100644
index 00000000..973b0ad7
--- /dev/null
+++ b/fuzz/privkey_corpus/6564b23ca877f7b46600c0628d9ecc503888cc67
Binary files differ
diff --git a/fuzz/privkey_corpus/66725ca0c9d2a7fbb3f6660180b7f9d172dd8c64 b/fuzz/privkey_corpus/66725ca0c9d2a7fbb3f6660180b7f9d172dd8c64
deleted file mode 100644
index a61fe7b4..00000000
--- a/fuzz/privkey_corpus/66725ca0c9d2a7fbb3f6660180b7f9d172dd8c64
+++ /dev/null
@@ -1 +0,0 @@
-00l00B)*'00 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/6778469c6519b69b3741a62e8df40a1091aeffd3 b/fuzz/privkey_corpus/6778469c6519b69b3741a62e8df40a1091aeffd3
deleted file mode 100644
index 76e9ae6b..00000000
--- a/fuzz/privkey_corpus/6778469c6519b69b3741a62e8df40a1091aeffd3
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965 b/fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965
new file mode 100644
index 00000000..419f9c27
--- /dev/null
+++ b/fuzz/privkey_corpus/69568bdb90b3dfaa1537da561b1fd3da443c4965
Binary files differ
diff --git a/fuzz/privkey_corpus/695f506c23c31450f3698f15f5d5dcd0a00e2292 b/fuzz/privkey_corpus/695f506c23c31450f3698f15f5d5dcd0a00e2292
deleted file mode 100644
index ac6be3ee..00000000
--- a/fuzz/privkey_corpus/695f506c23c31450f3698f15f5d5dcd0a00e2292
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308 b/fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308
new file mode 100644
index 00000000..5904dcc5
--- /dev/null
+++ b/fuzz/privkey_corpus/6a291a3d2db8f217bbf4778ff04b7f09c8fb5308
Binary files differ
diff --git a/fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884b b/fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884b
new file mode 100644
index 00000000..123df83b
--- /dev/null
+++ b/fuzz/privkey_corpus/6a3f0dff7e9cb30114ba47d280dc228074a3884b
Binary files differ
diff --git a/fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1 b/fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1
new file mode 100644
index 00000000..7f7337cb
--- /dev/null
+++ b/fuzz/privkey_corpus/6b470afcebd759c96b6c15f6936f8d3068eb79f1
Binary files differ
diff --git a/fuzz/privkey_corpus/6e846663b4af1ecf73ba93611d1f9b39f63803e5 b/fuzz/privkey_corpus/6e846663b4af1ecf73ba93611d1f9b39f63803e5
deleted file mode 100644
index 7cf58228..00000000
--- a/fuzz/privkey_corpus/6e846663b4af1ecf73ba93611d1f9b39f63803e5
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/6f12c3d548d85deae6946b279d85e03491787077 b/fuzz/privkey_corpus/6f12c3d548d85deae6946b279d85e03491787077
deleted file mode 100644
index 9950b2e7..00000000
--- a/fuzz/privkey_corpus/6f12c3d548d85deae6946b279d85e03491787077
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/6f2f15721e6c0b664759fa65e307c9a8cd20c464 b/fuzz/privkey_corpus/6f2f15721e6c0b664759fa65e307c9a8cd20c464
deleted file mode 100644
index 13fc8993..00000000
--- a/fuzz/privkey_corpus/6f2f15721e6c0b664759fa65e307c9a8cd20c464
+++ /dev/null
@@ -1 +0,0 @@
-0)00)00)00)000 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606d b/fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606d
new file mode 100644
index 00000000..aad3b414
--- /dev/null
+++ b/fuzz/privkey_corpus/6fd9b893b202e88165bd8b4b0e55b2879667606d
Binary files differ
diff --git a/fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0b b/fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0b
new file mode 100644
index 00000000..cfee2217
--- /dev/null
+++ b/fuzz/privkey_corpus/6fdabfc555764f5a61263c6c213e57f93fb12a0b
Binary files differ
diff --git a/fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9b b/fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9b
new file mode 100644
index 00000000..afe6753e
--- /dev/null
+++ b/fuzz/privkey_corpus/7019dcba7ca33cc061327b124fb24709299a3e9b
Binary files differ
diff --git a/fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ec b/fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ec
new file mode 100644
index 00000000..94265502
--- /dev/null
+++ b/fuzz/privkey_corpus/704cc64f5ba905eeb3f4cb8049231ee97c34e4ec
Binary files differ
diff --git a/fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0b b/fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0b
new file mode 100644
index 00000000..076f00ce
--- /dev/null
+++ b/fuzz/privkey_corpus/7115008ca4af946a5e2cec6166c8cf2bfacf6f0b
Binary files differ
diff --git a/fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14 b/fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14
new file mode 100644
index 00000000..653b3b78
--- /dev/null
+++ b/fuzz/privkey_corpus/715d34e2a6215569029969826e0bf2b78534fc14
Binary files differ
diff --git a/fuzz/privkey_corpus/71b67011b691dbde02d398dc730efc2d5205c837 b/fuzz/privkey_corpus/71b67011b691dbde02d398dc730efc2d5205c837
deleted file mode 100644
index 5a746325..00000000
--- a/fuzz/privkey_corpus/71b67011b691dbde02d398dc730efc2d5205c837
+++ /dev/null
@@ -1 +0,0 @@
-0)00) 0)00)00)0) \ No newline at end of file
diff --git a/fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3 b/fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3
new file mode 100644
index 00000000..aea9b499
--- /dev/null
+++ b/fuzz/privkey_corpus/723b16d087e14eab86b59cdd487a264f91cfc4e3
Binary files differ
diff --git a/fuzz/privkey_corpus/74306f8ce43c5b77c55b94ec37204d8be7c7a220 b/fuzz/privkey_corpus/74306f8ce43c5b77c55b94ec37204d8be7c7a220
deleted file mode 100644
index 5f3bb693..00000000
--- a/fuzz/privkey_corpus/74306f8ce43c5b77c55b94ec37204d8be7c7a220
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10 b/fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10
new file mode 100644
index 00000000..7bb6836e
--- /dev/null
+++ b/fuzz/privkey_corpus/7469a2e7bd870f04ad21e12c6547f4c5e3c2ee10
Binary files differ
diff --git a/fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7 b/fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7
new file mode 100644
index 00000000..85d81e72
--- /dev/null
+++ b/fuzz/privkey_corpus/74de715f42ee6e07b7b86bbe56d488227e0e30a7
Binary files differ
diff --git a/fuzz/privkey_corpus/761cde476b5b3f9af80a15150a8cbeb0992a3446 b/fuzz/privkey_corpus/761cde476b5b3f9af80a15150a8cbeb0992a3446
deleted file mode 100644
index 120f115f..00000000
--- a/fuzz/privkey_corpus/761cde476b5b3f9af80a15150a8cbeb0992a3446
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72ea b/fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72ea
new file mode 100644
index 00000000..bedfdfa3
--- /dev/null
+++ b/fuzz/privkey_corpus/767184473ade3f29a1a06a6498f9acf4aead72ea
Binary files differ
diff --git a/fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ec b/fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ec
new file mode 100644
index 00000000..68c3c31b
--- /dev/null
+++ b/fuzz/privkey_corpus/775f54fa88dc085283d4363426a4c408771545ec
Binary files differ
diff --git a/fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2f b/fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2f
new file mode 100644
index 00000000..4a03969e
--- /dev/null
+++ b/fuzz/privkey_corpus/7898b0d86f7cc71b934347a20e134169ef076d2f
Binary files differ
diff --git a/fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86 b/fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86
new file mode 100644
index 00000000..92c7c57c
--- /dev/null
+++ b/fuzz/privkey_corpus/79959ffbd0c540e1769f94f6381bbd2c28736a86
Binary files differ
diff --git a/fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26b b/fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26b
new file mode 100644
index 00000000..1b2f880a
--- /dev/null
+++ b/fuzz/privkey_corpus/7997306479d844e94a2b8cd0c33bd928bfaaf26b
Binary files differ
diff --git a/fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70 b/fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70
new file mode 100644
index 00000000..011f0dc5
--- /dev/null
+++ b/fuzz/privkey_corpus/7ad800c3d44252093ad9ad6030f08a48fcd72f70
Binary files differ
diff --git a/fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462e b/fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462e
new file mode 100644
index 00000000..e5e9ffbd
--- /dev/null
+++ b/fuzz/privkey_corpus/7b1d3464ee005c28e177b4f65f7f71a1cd50462e
Binary files differ
diff --git a/fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bdd b/fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bdd
new file mode 100644
index 00000000..f75a9bb2
--- /dev/null
+++ b/fuzz/privkey_corpus/7b4202b35800a1c6fbfde9de8dd7c06704353bdd
Binary files differ
diff --git a/fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158 b/fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158
new file mode 100644
index 00000000..14ce22db
--- /dev/null
+++ b/fuzz/privkey_corpus/7baa95845eeabd342bfec6eacfa14a623c59e158
Binary files differ
diff --git a/fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018 b/fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018
new file mode 100644
index 00000000..b17041b9
--- /dev/null
+++ b/fuzz/privkey_corpus/7c418f677717e6525bc27159e3af3a5858b15018
Binary files differ
diff --git a/fuzz/privkey_corpus/7dad0c94279194dcb34901efc1bfe47e19ace379 b/fuzz/privkey_corpus/7dad0c94279194dcb34901efc1bfe47e19ace379
deleted file mode 100644
index 1957351c..00000000
--- a/fuzz/privkey_corpus/7dad0c94279194dcb34901efc1bfe47e19ace379
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/7de3b5459637fb5839105f571da68411f7b9a4e2 b/fuzz/privkey_corpus/7de3b5459637fb5839105f571da68411f7b9a4e2
deleted file mode 100644
index 5545d892..00000000
--- a/fuzz/privkey_corpus/7de3b5459637fb5839105f571da68411f7b9a4e2
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90 b/fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90
new file mode 100644
index 00000000..b83b1dc7
--- /dev/null
+++ b/fuzz/privkey_corpus/7dfd158e7e1d8c6737ece7d1ea5d67820c671c90
Binary files differ
diff --git a/fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856 b/fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856
new file mode 100644
index 00000000..246e0e8d
--- /dev/null
+++ b/fuzz/privkey_corpus/7f52cc7f25c0899099277f4057fdac6351907856
Binary files differ
diff --git a/fuzz/privkey_corpus/7fbcab532053a01781fdcdf1c8c9c5707479fbda b/fuzz/privkey_corpus/7fbcab532053a01781fdcdf1c8c9c5707479fbda
deleted file mode 100644
index fc60afd8..00000000
--- a/fuzz/privkey_corpus/7fbcab532053a01781fdcdf1c8c9c5707479fbda
+++ /dev/null
@@ -1 +0,0 @@
-0 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270 b/fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270
new file mode 100644
index 00000000..a1ae8086
--- /dev/null
+++ b/fuzz/privkey_corpus/7ff996c54474adad856bc3db017ddc9959784270
Binary files differ
diff --git a/fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892 b/fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892
new file mode 100644
index 00000000..30e7b5e5
--- /dev/null
+++ b/fuzz/privkey_corpus/81107eec8b4507243f1c673f820a72ea80c18892
Binary files differ
diff --git a/fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491b b/fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491b
new file mode 100644
index 00000000..3d838ed5
--- /dev/null
+++ b/fuzz/privkey_corpus/8134651d726deed781cdf0d3283af116cea8491b
Binary files differ
diff --git a/fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fc b/fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fc
new file mode 100644
index 00000000..eb5dbc7c
--- /dev/null
+++ b/fuzz/privkey_corpus/815c2fb64bab0f77580b953f7c2d7fd0621996fc
Binary files differ
diff --git a/fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bb b/fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bb
new file mode 100644
index 00000000..5bcfd750
--- /dev/null
+++ b/fuzz/privkey_corpus/81bbb1193d24b3cf1e462f898f47a2e819e293bb
Binary files differ
diff --git a/fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eef b/fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eef
new file mode 100644
index 00000000..bf06ec21
--- /dev/null
+++ b/fuzz/privkey_corpus/820362d206b0835f12b35ff4aa7a813799be8eef
Binary files differ
diff --git a/fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688 b/fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688
new file mode 100644
index 00000000..b0920263
--- /dev/null
+++ b/fuzz/privkey_corpus/825915611b3cd3ba1ae6a9c178fe27bbc7dd3688
Binary files differ
diff --git a/fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0 b/fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0
new file mode 100644
index 00000000..05441402
--- /dev/null
+++ b/fuzz/privkey_corpus/827761890aafb4a26f4da0eb6232a59420c1ecb0
Binary files differ
diff --git a/fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009 b/fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009
new file mode 100644
index 00000000..10dacc6e
--- /dev/null
+++ b/fuzz/privkey_corpus/82e9c1cb3f406331f68205bcf9a96691dd463009
Binary files differ
diff --git a/fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99d b/fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99d
new file mode 100644
index 00000000..6a74b9c8
--- /dev/null
+++ b/fuzz/privkey_corpus/83a952b25c76484e160a04f5f2c0263cc07cc99d
Binary files differ
diff --git a/fuzz/privkey_corpus/83ce66bb0c9c3bec32b125c66b724522a293989b b/fuzz/privkey_corpus/83ce66bb0c9c3bec32b125c66b724522a293989b
deleted file mode 100644
index 16a083d5..00000000
--- a/fuzz/privkey_corpus/83ce66bb0c9c3bec32b125c66b724522a293989b
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876c b/fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876c
new file mode 100644
index 00000000..54688dfa
--- /dev/null
+++ b/fuzz/privkey_corpus/8526e62eff355f6b808a1f8682ffbbb99efc876c
Binary files differ
diff --git a/fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5 b/fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5
new file mode 100644
index 00000000..fb719df0
--- /dev/null
+++ b/fuzz/privkey_corpus/85b4691cf62b04e12af3d914153b2f92bda218f5
Binary files differ
diff --git a/fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9 b/fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9
new file mode 100644
index 00000000..7a9fcbe3
--- /dev/null
+++ b/fuzz/privkey_corpus/864e3b9ea0ec966bcf1d1dc827c5b5d32dfe5bd9
Binary files differ
diff --git a/fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2c b/fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2c
new file mode 100644
index 00000000..abb7a097
--- /dev/null
+++ b/fuzz/privkey_corpus/8718dc82bbda78b01bef7fa736f36fdd7db61a2c
Binary files differ
diff --git a/fuzz/privkey_corpus/872f45b8c5fcebb9e7d8e26f3b41e4d42af2a824 b/fuzz/privkey_corpus/872f45b8c5fcebb9e7d8e26f3b41e4d42af2a824
deleted file mode 100644
index 3a144a6e..00000000
--- a/fuzz/privkey_corpus/872f45b8c5fcebb9e7d8e26f3b41e4d42af2a824
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0 b/fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0
new file mode 100644
index 00000000..3ce04de8
--- /dev/null
+++ b/fuzz/privkey_corpus/879102898920f7b123cb3bf2d3bce4eab71c38e0
Binary files differ
diff --git a/fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365 b/fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365
new file mode 100644
index 00000000..8575eb1d
--- /dev/null
+++ b/fuzz/privkey_corpus/87b0269cf7ebd7a44757d8f9a45ef60484904365
Binary files differ
diff --git a/fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088 b/fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088
new file mode 100644
index 00000000..c74a127d
--- /dev/null
+++ b/fuzz/privkey_corpus/8930a6e954f28a8c0e4e70c9f41df099a931a088
Binary files differ
diff --git a/fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3 b/fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3
new file mode 100644
index 00000000..bacf4a89
--- /dev/null
+++ b/fuzz/privkey_corpus/89333d13b767e6b4af04246afb58e77b5e2d7be3
Binary files differ
diff --git a/fuzz/privkey_corpus/897d7068f38f4c9f9d127901f7da58ebbbbe989a b/fuzz/privkey_corpus/897d7068f38f4c9f9d127901f7da58ebbbbe989a
deleted file mode 100644
index 0ffc9738..00000000
--- a/fuzz/privkey_corpus/897d7068f38f4c9f9d127901f7da58ebbbbe989a
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/89af3687b8bb5fa6ed225799fd97cbc79f6678ef b/fuzz/privkey_corpus/89af3687b8bb5fa6ed225799fd97cbc79f6678ef
deleted file mode 100644
index a75f41d1..00000000
--- a/fuzz/privkey_corpus/89af3687b8bb5fa6ed225799fd97cbc79f6678ef
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347d b/fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347d
new file mode 100644
index 00000000..1935c27b
--- /dev/null
+++ b/fuzz/privkey_corpus/8af7ff3e32e33166427356e04d98401ded9a347d
Binary files differ
diff --git a/fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14c b/fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14c
new file mode 100644
index 00000000..34502ecb
--- /dev/null
+++ b/fuzz/privkey_corpus/8b6fd2ab1d0d7fefe124696065e074b2d161c14c
Binary files differ
diff --git a/fuzz/privkey_corpus/8e7daf81d667f41e4310a12a560b69400b97d85d b/fuzz/privkey_corpus/8e7daf81d667f41e4310a12a560b69400b97d85d
deleted file mode 100644
index 01281ee4..00000000
--- a/fuzz/privkey_corpus/8e7daf81d667f41e4310a12a560b69400b97d85d
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206 b/fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206
new file mode 100644
index 00000000..13a1bd6c
--- /dev/null
+++ b/fuzz/privkey_corpus/8f108bc5c869083074bfe9d08f9f9e905e56a206
Binary files differ
diff --git a/fuzz/privkey_corpus/8fe2bfb00afe3d66f36bdb951df47f28e4bc60f1 b/fuzz/privkey_corpus/8fe2bfb00afe3d66f36bdb951df47f28e4bc60f1
deleted file mode 100644
index c0206842..00000000
--- a/fuzz/privkey_corpus/8fe2bfb00afe3d66f36bdb951df47f28e4bc60f1
+++ /dev/null
@@ -1 +0,0 @@
-0)0!00 *0H 0000 *00)0 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1e b/fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1e
new file mode 100644
index 00000000..201d6fdd
--- /dev/null
+++ b/fuzz/privkey_corpus/906e954acb728d2e7ed6fb8630672667f09b1f1e
Binary files differ
diff --git a/fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4 b/fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4
new file mode 100644
index 00000000..e9230755
--- /dev/null
+++ b/fuzz/privkey_corpus/91583ca2b096602157ea1e68c7d6b2adff9378e4
Binary files differ
diff --git a/fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15 b/fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15
new file mode 100644
index 00000000..03cc3733
--- /dev/null
+++ b/fuzz/privkey_corpus/91946201829018208daad41691f4aaa7e2c3eb15
Binary files differ
diff --git a/fuzz/privkey_corpus/9270672e3b3b0c6dd04c2001646900d392a8f0cd b/fuzz/privkey_corpus/9270672e3b3b0c6dd04c2001646900d392a8f0cd
deleted file mode 100644
index b25b4494..00000000
--- a/fuzz/privkey_corpus/9270672e3b3b0c6dd04c2001646900d392a8f0cd
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afa b/fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afa
new file mode 100644
index 00000000..40a111bc
--- /dev/null
+++ b/fuzz/privkey_corpus/92ba02b6268e6c21133447c6518a896157d68afa
Binary files differ
diff --git a/fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3 b/fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3
new file mode 100644
index 00000000..fd29f40b
--- /dev/null
+++ b/fuzz/privkey_corpus/946bfe147670f490b65da4929129a05ba4fe3eb3
Binary files differ
diff --git a/fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594 b/fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594
new file mode 100644
index 00000000..13014bad
--- /dev/null
+++ b/fuzz/privkey_corpus/94a53c59e935429397267a33a6d19fb5bd90c594
Binary files differ
diff --git a/fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354 b/fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354
new file mode 100644
index 00000000..8f8ec04d
--- /dev/null
+++ b/fuzz/privkey_corpus/94af57e79c33b555ed3d577d7d7278776e2e3354
Binary files differ
diff --git a/fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23 b/fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23
new file mode 100644
index 00000000..b683ebd3
--- /dev/null
+++ b/fuzz/privkey_corpus/94d32ba71497e04e729fed8a7b0eb4bbdd44be23
Binary files differ
diff --git a/fuzz/privkey_corpus/957768c9faad66620a63f5f529546ae973203c0c b/fuzz/privkey_corpus/957768c9faad66620a63f5f529546ae973203c0c
deleted file mode 100644
index a425cb83..00000000
--- a/fuzz/privkey_corpus/957768c9faad66620a63f5f529546ae973203c0c
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88 b/fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88
new file mode 100644
index 00000000..9f5a5ffe
--- /dev/null
+++ b/fuzz/privkey_corpus/96ca3c3159a62867cd0f67e00cdc29592777fa88
Binary files differ
diff --git a/fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9 b/fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9
new file mode 100644
index 00000000..8899be37
--- /dev/null
+++ b/fuzz/privkey_corpus/97d88e10db105ca8aff02affa4df9105fcf6c0c9
Binary files differ
diff --git a/fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931f b/fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931f
new file mode 100644
index 00000000..b529b0b4
--- /dev/null
+++ b/fuzz/privkey_corpus/97dccd2f5301d606ef218ead83374e2dbf23931f
Binary files differ
diff --git a/fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49 b/fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49
new file mode 100644
index 00000000..35c51bdf
--- /dev/null
+++ b/fuzz/privkey_corpus/987113dad3aecd5a8bc478cc94e11708f3e23b49
Binary files differ
diff --git a/fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02 b/fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02
new file mode 100644
index 00000000..416b6777
--- /dev/null
+++ b/fuzz/privkey_corpus/98ac3859a7ffb3851d4269b8fbc1b408eb36da02
Binary files differ
diff --git a/fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6ca b/fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6ca
new file mode 100644
index 00000000..f71a19d7
--- /dev/null
+++ b/fuzz/privkey_corpus/98d8745802ae439a6bd8b6cb20b35ba6c942f6ca
Binary files differ
diff --git a/fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631 b/fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631
new file mode 100644
index 00000000..a164e007
--- /dev/null
+++ b/fuzz/privkey_corpus/996a0120ca7d868a8a8da7141ed352e18ada4631
Binary files differ
diff --git a/fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cf b/fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cf
new file mode 100644
index 00000000..b8d7e5bc
--- /dev/null
+++ b/fuzz/privkey_corpus/99925faf1244b710b84a12cb1b602dae69f795cf
Binary files differ
diff --git a/fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dac b/fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dac
new file mode 100644
index 00000000..c02e8e80
--- /dev/null
+++ b/fuzz/privkey_corpus/99af875391c1e7c13743893fdd8c3d354e034dac
Binary files differ
diff --git a/fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0c b/fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0c
new file mode 100644
index 00000000..964d8209
--- /dev/null
+++ b/fuzz/privkey_corpus/9b1bb094b817690bf3f92ed11eaa10371ad3cb0c
Binary files differ
diff --git a/fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546 b/fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546
new file mode 100644
index 00000000..187ad6e5
--- /dev/null
+++ b/fuzz/privkey_corpus/9d23cb41145d5d0643f52b7376b75f5628f95546
Binary files differ
diff --git a/fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4 b/fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4
new file mode 100644
index 00000000..7776a832
--- /dev/null
+++ b/fuzz/privkey_corpus/9d93a1a13ef025beb36b2d0c3fda83177c0dd1b4
Binary files differ
diff --git a/fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12c b/fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12c
new file mode 100644
index 00000000..7fc8b6e1
--- /dev/null
+++ b/fuzz/privkey_corpus/9daaa6a59373116fdafd6a88ae78a66f82d3b12c
Binary files differ
diff --git a/fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425 b/fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425
new file mode 100644
index 00000000..f5697194
--- /dev/null
+++ b/fuzz/privkey_corpus/9e68ef050c944e5ad80ecb7b4e5023520e190425
Binary files differ
diff --git a/fuzz/privkey_corpus/9ed81784ce2583f8be38e859dce5e95b495a6f5e b/fuzz/privkey_corpus/9ed81784ce2583f8be38e859dce5e95b495a6f5e
deleted file mode 100644
index 591f2fed..00000000
--- a/fuzz/privkey_corpus/9ed81784ce2583f8be38e859dce5e95b495a6f5e
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766ed b/fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766ed
new file mode 100644
index 00000000..e2ac5c62
--- /dev/null
+++ b/fuzz/privkey_corpus/9f3c56915a0a55918fb711cddc3c72039d2766ed
Binary files differ
diff --git a/fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7 b/fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7
new file mode 100644
index 00000000..42d2dbb0
--- /dev/null
+++ b/fuzz/privkey_corpus/a148911d708b9ce5e436a45f9ade17782afc86b7
Binary files differ
diff --git a/fuzz/privkey_corpus/a3f0a9ff5a9ec60daa274d60cfeecdd579401ece b/fuzz/privkey_corpus/a3f0a9ff5a9ec60daa274d60cfeecdd579401ece
deleted file mode 100644
index d6fcaece..00000000
--- a/fuzz/privkey_corpus/a3f0a9ff5a9ec60daa274d60cfeecdd579401ece
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/a463eb1757724d37c64e0f34e7b8c2f214bf9db2 b/fuzz/privkey_corpus/a463eb1757724d37c64e0f34e7b8c2f214bf9db2
deleted file mode 100644
index 7f585f49..00000000
--- a/fuzz/privkey_corpus/a463eb1757724d37c64e0f34e7b8c2f214bf9db2
+++ /dev/null
@@ -1 +0,0 @@
-00v&(00'V0 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/a4c7ddac15ef72f597bcf6c3e6f287ede7de6119 b/fuzz/privkey_corpus/a4c7ddac15ef72f597bcf6c3e6f287ede7de6119
deleted file mode 100644
index 53c1da04..00000000
--- a/fuzz/privkey_corpus/a4c7ddac15ef72f597bcf6c3e6f287ede7de6119
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0df b/fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0df
new file mode 100644
index 00000000..1cd09f45
--- /dev/null
+++ b/fuzz/privkey_corpus/a4d958b6af098740bdd7bdbc670d9d5ff33af0df
Binary files differ
diff --git a/fuzz/privkey_corpus/a547b12cbdf4c9ad8002e735e5276674a0dc48d1 b/fuzz/privkey_corpus/a547b12cbdf4c9ad8002e735e5276674a0dc48d1
deleted file mode 100644
index 022298bf..00000000
--- a/fuzz/privkey_corpus/a547b12cbdf4c9ad8002e735e5276674a0dc48d1
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfb b/fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfb
new file mode 100644
index 00000000..8557eb81
--- /dev/null
+++ b/fuzz/privkey_corpus/a5481eb2b17062606e626ae7cb9156851f314cfb
Binary files differ
diff --git a/fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966bee b/fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966bee
new file mode 100644
index 00000000..e0c424a7
--- /dev/null
+++ b/fuzz/privkey_corpus/a57da87205e925a5088c9136d5013928ea966bee
Binary files differ
diff --git a/fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555 b/fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555
new file mode 100644
index 00000000..edc9a33d
--- /dev/null
+++ b/fuzz/privkey_corpus/a5bbdddaabff03f981ac4812c9f78744fb59d555
Binary files differ
diff --git a/fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2d b/fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2d
new file mode 100644
index 00000000..29c9a4ae
--- /dev/null
+++ b/fuzz/privkey_corpus/a786d0dd572029971ee468ceea31c153df41bd2d
Binary files differ
diff --git a/fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5 b/fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5
new file mode 100644
index 00000000..d35f31ad
--- /dev/null
+++ b/fuzz/privkey_corpus/a7d0b5428d0fee536cad87e3243a8668061164c5
Binary files differ
diff --git a/fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078 b/fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078
new file mode 100644
index 00000000..c4f9c9fd
--- /dev/null
+++ b/fuzz/privkey_corpus/a876f0286bdaf5715d37f5446196924288318078
Binary files differ
diff --git a/fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43a b/fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43a
new file mode 100644
index 00000000..84eb4c73
--- /dev/null
+++ b/fuzz/privkey_corpus/a89172016f91c2d90eae0ec282965f2b980cd43a
Binary files differ
diff --git a/fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042 b/fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042
new file mode 100644
index 00000000..b51d35c4
--- /dev/null
+++ b/fuzz/privkey_corpus/a8bdd4f4f781cc89e87621188db36b8490046042
Binary files differ
diff --git a/fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6 b/fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6
new file mode 100644
index 00000000..3c4d88a3
--- /dev/null
+++ b/fuzz/privkey_corpus/a9d62074bf9e1200cd0a3dea12c106925b58e6e6
Binary files differ
diff --git a/fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fad b/fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fad
new file mode 100644
index 00000000..8d6852f3
--- /dev/null
+++ b/fuzz/privkey_corpus/aa0505ea0b3d4c360a5200a50a010b4a55849fad
Binary files differ
diff --git a/fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4d b/fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4d
new file mode 100644
index 00000000..265ef556
--- /dev/null
+++ b/fuzz/privkey_corpus/aa3a41b9a808b2028bb83d5279ba42371c8dca4d
Binary files differ
diff --git a/fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82 b/fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82
new file mode 100644
index 00000000..74007711
--- /dev/null
+++ b/fuzz/privkey_corpus/aabc600f07af79ddb976e2c101f0625f991f2c82
Binary files differ
diff --git a/fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544 b/fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544
new file mode 100644
index 00000000..82a5caea
--- /dev/null
+++ b/fuzz/privkey_corpus/aafac2d9b5d50385e892a1c9792bbf9f31530544
Binary files differ
diff --git a/fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908 b/fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908
new file mode 100644
index 00000000..684d61c9
--- /dev/null
+++ b/fuzz/privkey_corpus/ab5f3c4a4181cfaec1fbd6949a96cde343cfa908
Binary files differ
diff --git a/fuzz/privkey_corpus/ac4c5ab934f6f54f4337c1fd1194a979bffec24d b/fuzz/privkey_corpus/ac4c5ab934f6f54f4337c1fd1194a979bffec24d
deleted file mode 100644
index a98dc21e..00000000
--- a/fuzz/privkey_corpus/ac4c5ab934f6f54f4337c1fd1194a979bffec24d
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ac74cf6269b94ccb419933a32bd7d8c9452dce2e b/fuzz/privkey_corpus/ac74cf6269b94ccb419933a32bd7d8c9452dce2e
deleted file mode 100644
index 3076859a..00000000
--- a/fuzz/privkey_corpus/ac74cf6269b94ccb419933a32bd7d8c9452dce2e
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ad691a66d0a57b9737701d8b431e48a9a9b98a5a b/fuzz/privkey_corpus/ad691a66d0a57b9737701d8b431e48a9a9b98a5a
deleted file mode 100644
index 26f205db..00000000
--- a/fuzz/privkey_corpus/ad691a66d0a57b9737701d8b431e48a9a9b98a5a
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534e b/fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534e
new file mode 100644
index 00000000..b9384e91
--- /dev/null
+++ b/fuzz/privkey_corpus/adc6e9d3be69a83a22a8e9579d721139fdef534e
Binary files differ
diff --git a/fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4 b/fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4
new file mode 100644
index 00000000..d37482fa
--- /dev/null
+++ b/fuzz/privkey_corpus/ae4960ecdce376a9bbd26afbc481619ba303f4e4
Binary files differ
diff --git a/fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bf b/fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bf
new file mode 100644
index 00000000..e3dc371c
--- /dev/null
+++ b/fuzz/privkey_corpus/ae97c55d39f8c51a81fe559e278110d90a8095bf
Binary files differ
diff --git a/fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451 b/fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451
new file mode 100644
index 00000000..705931c4
--- /dev/null
+++ b/fuzz/privkey_corpus/aecd29853dcf0d6429665efa95349bca6672d451
Binary files differ
diff --git a/fuzz/privkey_corpus/b0af7aec354da869abfb72e1ac8586c079101d78 b/fuzz/privkey_corpus/b0af7aec354da869abfb72e1ac8586c079101d78
deleted file mode 100644
index 735a0e17..00000000
--- a/fuzz/privkey_corpus/b0af7aec354da869abfb72e1ac8586c079101d78
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d b/fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d
new file mode 100644
index 00000000..74f1528e
--- /dev/null
+++ b/fuzz/privkey_corpus/b199b6e6200bcbc9b8972d8e5fd5bae8a379f57d
Binary files differ
diff --git a/fuzz/privkey_corpus/b2c7dc902172c6beea66a96df921d559acce2e1d b/fuzz/privkey_corpus/b2c7dc902172c6beea66a96df921d559acce2e1d
deleted file mode 100644
index bde51c09..00000000
--- a/fuzz/privkey_corpus/b2c7dc902172c6beea66a96df921d559acce2e1d
+++ /dev/null
@@ -1 +0,0 @@
-0)00)00)00)00);00! \ No newline at end of file
diff --git a/fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238 b/fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238
new file mode 100644
index 00000000..fac39b43
--- /dev/null
+++ b/fuzz/privkey_corpus/b3f8287d91c8ae6d29b8db61b5d4b757a9c4c238
Binary files differ
diff --git a/fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321 b/fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321
new file mode 100644
index 00000000..59c38276
--- /dev/null
+++ b/fuzz/privkey_corpus/b56d41d9a951ef3ed52a55a640c9741d7d171321
Binary files differ
diff --git a/fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898c b/fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898c
new file mode 100644
index 00000000..cf952880
--- /dev/null
+++ b/fuzz/privkey_corpus/b626fd67fd56e710f1ab83f25cd9355de125898c
Binary files differ
diff --git a/fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636 b/fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636
new file mode 100644
index 00000000..ed9bf8d2
--- /dev/null
+++ b/fuzz/privkey_corpus/b6b36ce62527c806633c581bd83928ca658c5636
Binary files differ
diff --git a/fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185 b/fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185
new file mode 100644
index 00000000..1b95c6b6
--- /dev/null
+++ b/fuzz/privkey_corpus/b73ec5775410255daf79b77df66d8bc3844ac185
Binary files differ
diff --git a/fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6 b/fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6
new file mode 100644
index 00000000..33efbfb0
--- /dev/null
+++ b/fuzz/privkey_corpus/b82de94562e200e03ce3082d5618fb95d1f61ab6
Binary files differ
diff --git a/fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4 b/fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4
new file mode 100644
index 00000000..05d0017d
--- /dev/null
+++ b/fuzz/privkey_corpus/b83ad977325da3e287251f214e5f076700df66c4
Binary files differ
diff --git a/fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4 b/fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4
new file mode 100644
index 00000000..313bba86
--- /dev/null
+++ b/fuzz/privkey_corpus/b8e3f3d19adcbb244d85b968264adf4bc34bbba4
Binary files differ
diff --git a/fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3 b/fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3
new file mode 100644
index 00000000..c136bf93
--- /dev/null
+++ b/fuzz/privkey_corpus/b9260c758df1d058735482a8b9b540612b9d2ae3
Binary files differ
diff --git a/fuzz/privkey_corpus/b92cebe5be4c47d05ae4ea152c198b4d5978f22f b/fuzz/privkey_corpus/b92cebe5be4c47d05ae4ea152c198b4d5978f22f
deleted file mode 100644
index cbcc948f..00000000
--- a/fuzz/privkey_corpus/b92cebe5be4c47d05ae4ea152c198b4d5978f22f
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfca b/fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfca
new file mode 100644
index 00000000..c1d2aa69
--- /dev/null
+++ b/fuzz/privkey_corpus/b9924406c46a4a954895fdb416f6ef4f9fbecfca
Binary files differ
diff --git a/fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369 b/fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369
new file mode 100644
index 00000000..6b3745f5
--- /dev/null
+++ b/fuzz/privkey_corpus/ba0e5fccc5b9b1a3c009ef5ab6b616be07aea369
Binary files differ
diff --git a/fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711e b/fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711e
new file mode 100644
index 00000000..32576ed0
--- /dev/null
+++ b/fuzz/privkey_corpus/baa2017f3f816ea489150c2753fcf2acceed711e
Binary files differ
diff --git a/fuzz/privkey_corpus/bb27d0460c1351c8fc37f87f26db293fbe57f0a8 b/fuzz/privkey_corpus/bb27d0460c1351c8fc37f87f26db293fbe57f0a8
deleted file mode 100644
index d580adb8..00000000
--- a/fuzz/privkey_corpus/bb27d0460c1351c8fc37f87f26db293fbe57f0a8
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/bc30b3e987eff679901a24d19a205048f2ca54ba b/fuzz/privkey_corpus/bc30b3e987eff679901a24d19a205048f2ca54ba
deleted file mode 100644
index 80bfab0b..00000000
--- a/fuzz/privkey_corpus/bc30b3e987eff679901a24d19a205048f2ca54ba
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/bdc3b30e8d1a278f81ebe78c4b5e44aaef55c4e1 b/fuzz/privkey_corpus/bdc3b30e8d1a278f81ebe78c4b5e44aaef55c4e1
deleted file mode 100644
index 69f94819..00000000
--- a/fuzz/privkey_corpus/bdc3b30e8d1a278f81ebe78c4b5e44aaef55c4e1
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273 b/fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273
new file mode 100644
index 00000000..89f12f2d
--- /dev/null
+++ b/fuzz/privkey_corpus/be34aad9e27b0e5fbeea5acbdefe813dff55c273
Binary files differ
diff --git a/fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064f b/fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064f
new file mode 100644
index 00000000..ad4d5c14
--- /dev/null
+++ b/fuzz/privkey_corpus/be998be251e63a0d855a269dec3abd974edf064f
Binary files differ
diff --git a/fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591ee b/fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591ee
new file mode 100644
index 00000000..040c66a8
--- /dev/null
+++ b/fuzz/privkey_corpus/bf44fcd5fb4037ca361643ead75091cd7d7591ee
Binary files differ
diff --git a/fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188f b/fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188f
new file mode 100644
index 00000000..ee8636f7
--- /dev/null
+++ b/fuzz/privkey_corpus/c09c79dd6953ac6766586c288673bbf07717188f
Binary files differ
diff --git a/fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b b/fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b
new file mode 100644
index 00000000..371cbb6b
--- /dev/null
+++ b/fuzz/privkey_corpus/c0fb9c7ea154ea9bd8d69b07054aef25a7c7122b
@@ -0,0 +1 @@
+0)00)00)00)000 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caece b/fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caece
new file mode 100644
index 00000000..2ccd946e
--- /dev/null
+++ b/fuzz/privkey_corpus/c3658e11896a6c7a16d3f40160d91c6e281caece
Binary files differ
diff --git a/fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216 b/fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216
new file mode 100644
index 00000000..a81026f6
--- /dev/null
+++ b/fuzz/privkey_corpus/c540b77632fe86d68bd3caa3c3ffb92473e38216
Binary files differ
diff --git a/fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050 b/fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050
new file mode 100644
index 00000000..1ed257aa
--- /dev/null
+++ b/fuzz/privkey_corpus/c5964a09ff096f10007be24c483697813e641050
Binary files differ
diff --git a/fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3 b/fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3
new file mode 100644
index 00000000..d21cb87e
--- /dev/null
+++ b/fuzz/privkey_corpus/c5be586cbc10f9982b132505e84eed971e375fd3
Binary files differ
diff --git a/fuzz/privkey_corpus/c638138e56beeacb40af3cd20050b8a3f5036992 b/fuzz/privkey_corpus/c638138e56beeacb40af3cd20050b8a3f5036992
deleted file mode 100644
index cc74a9bb..00000000
--- a/fuzz/privkey_corpus/c638138e56beeacb40af3cd20050b8a3f5036992
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71 b/fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71
new file mode 100644
index 00000000..bfb51734
--- /dev/null
+++ b/fuzz/privkey_corpus/c63c2f2c72fa6788f4e229f4021c3f9001d9ae71
Binary files differ
diff --git a/fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75 b/fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75
new file mode 100644
index 00000000..7dc22bc1
--- /dev/null
+++ b/fuzz/privkey_corpus/c7add8dd1a26be2f8429baad24c10726c5e62a75
Binary files differ
diff --git a/fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7b b/fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7b
new file mode 100644
index 00000000..a3e7397e
--- /dev/null
+++ b/fuzz/privkey_corpus/c8f478aa35ec77a762c0289f59baeb61fc4bbb7b
Binary files differ
diff --git a/fuzz/privkey_corpus/ca03fe7c55904c73f9ff1eadf2e192e0eb411e0c b/fuzz/privkey_corpus/ca03fe7c55904c73f9ff1eadf2e192e0eb411e0c
deleted file mode 100644
index 503c43ae..00000000
--- a/fuzz/privkey_corpus/ca03fe7c55904c73f9ff1eadf2e192e0eb411e0c
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ca6887f6d21cf4ecdebe7ac1900c1c49ee16c6b2 b/fuzz/privkey_corpus/ca6887f6d21cf4ecdebe7ac1900c1c49ee16c6b2
deleted file mode 100644
index dbb14ef7..00000000
--- a/fuzz/privkey_corpus/ca6887f6d21cf4ecdebe7ac1900c1c49ee16c6b2
+++ /dev/null
@@ -1 +0,0 @@
-01 l00*0!)00 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/cab3b9db9caea2b6998acc6755d0bcaa20a2ba48 b/fuzz/privkey_corpus/cab3b9db9caea2b6998acc6755d0bcaa20a2ba48
deleted file mode 100644
index 8ec90d1f..00000000
--- a/fuzz/privkey_corpus/cab3b9db9caea2b6998acc6755d0bcaa20a2ba48
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2b b/fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2b
new file mode 100644
index 00000000..bd126a98
--- /dev/null
+++ b/fuzz/privkey_corpus/cb0a918db754c106d0ba72f50c03eb4b2a434e2b
Binary files differ
diff --git a/fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19 b/fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19
new file mode 100644
index 00000000..cd1fa9d2
--- /dev/null
+++ b/fuzz/privkey_corpus/cbebcaa181e9397a660ad6e6f48e91c1c92c4c19
Binary files differ
diff --git a/fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acf b/fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acf
new file mode 100644
index 00000000..a2ef00ef
--- /dev/null
+++ b/fuzz/privkey_corpus/cc28f7a74f73a3429ef1268030fff5ee64e09acf
Binary files differ
diff --git a/fuzz/privkey_corpus/cc719b2377a9c7bf6b598fd1a0385a128be673dc b/fuzz/privkey_corpus/cc719b2377a9c7bf6b598fd1a0385a128be673dc
deleted file mode 100644
index 642475d3..00000000
--- a/fuzz/privkey_corpus/cc719b2377a9c7bf6b598fd1a0385a128be673dc
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21 b/fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21
new file mode 100644
index 00000000..857af6d1
--- /dev/null
+++ b/fuzz/privkey_corpus/cd54bf63ab01d994be8c966cb92ef919530afc21
Binary files differ
diff --git a/fuzz/privkey_corpus/cd7337d143156288c8f0236cc15ce647b652e739 b/fuzz/privkey_corpus/cd7337d143156288c8f0236cc15ce647b652e739
deleted file mode 100644
index dec6f9f7..00000000
--- a/fuzz/privkey_corpus/cd7337d143156288c8f0236cc15ce647b652e739
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016 b/fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016
new file mode 100644
index 00000000..66cc449b
--- /dev/null
+++ b/fuzz/privkey_corpus/ce25fe172d2513459fb070d62778e3b7aa865016
Binary files differ
diff --git a/fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62 b/fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62
new file mode 100644
index 00000000..3ec8f233
--- /dev/null
+++ b/fuzz/privkey_corpus/ce3d342f48dc9d4602f9ec0b63d665fc54a06f62
Binary files differ
diff --git a/fuzz/privkey_corpus/ce70afddf822af8cf9e69bffb31e1fc24e636be1 b/fuzz/privkey_corpus/ce70afddf822af8cf9e69bffb31e1fc24e636be1
deleted file mode 100644
index f1739fa0..00000000
--- a/fuzz/privkey_corpus/ce70afddf822af8cf9e69bffb31e1fc24e636be1
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643 b/fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643
new file mode 100644
index 00000000..d1428ae1
--- /dev/null
+++ b/fuzz/privkey_corpus/ce8427301dda48d954972a123a2d93a501761643
Binary files differ
diff --git a/fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99 b/fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99
new file mode 100644
index 00000000..3013814e
--- /dev/null
+++ b/fuzz/privkey_corpus/d0b3bfe45b283df4ba481c7e64ec2400dc16ae99
Binary files differ
diff --git a/fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5 b/fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5
new file mode 100644
index 00000000..6441dd87
--- /dev/null
+++ b/fuzz/privkey_corpus/d1187b0b6682c51b58021364a766c43108691cc5
Binary files differ
diff --git a/fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1 b/fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1
new file mode 100644
index 00000000..f372111d
--- /dev/null
+++ b/fuzz/privkey_corpus/d124af93bea4a34e7faf20d4c2d81b93c2d8e7c1
Binary files differ
diff --git a/fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedb b/fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedb
new file mode 100644
index 00000000..62f8bfcd
--- /dev/null
+++ b/fuzz/privkey_corpus/d23dd357f27569aa18f9ca99bedc31267977eedb
Binary files differ
diff --git a/fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2b b/fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2b
new file mode 100644
index 00000000..9730d548
--- /dev/null
+++ b/fuzz/privkey_corpus/d36420fc5040deaf0c097779c63ad45c5dc40a2b
Binary files differ
diff --git a/fuzz/privkey_corpus/d3b57fed5ac21ef3efb48176f09412eb8c042c0c b/fuzz/privkey_corpus/d3b57fed5ac21ef3efb48176f09412eb8c042c0c
deleted file mode 100644
index 4debf426..00000000
--- a/fuzz/privkey_corpus/d3b57fed5ac21ef3efb48176f09412eb8c042c0c
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32 b/fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32
new file mode 100644
index 00000000..68c6bdf9
--- /dev/null
+++ b/fuzz/privkey_corpus/d3c7a122c93a36b2e2ddd3576ea446e0cb39fc32
Binary files differ
diff --git a/fuzz/privkey_corpus/d512a5050e4f5f699c7388a740671286aa571c6e b/fuzz/privkey_corpus/d512a5050e4f5f699c7388a740671286aa571c6e
deleted file mode 100644
index 273b8f50..00000000
--- a/fuzz/privkey_corpus/d512a5050e4f5f699c7388a740671286aa571c6e
+++ /dev/null
@@ -1 +0,0 @@
-0 !00 \ No newline at end of file
diff --git a/fuzz/privkey_corpus/d5908176a8cf6c8fa4d500ab81e0fc66a927b74a b/fuzz/privkey_corpus/d5908176a8cf6c8fa4d500ab81e0fc66a927b74a
deleted file mode 100644
index 36b6830c..00000000
--- a/fuzz/privkey_corpus/d5908176a8cf6c8fa4d500ab81e0fc66a927b74a
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec b/fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec
new file mode 100644
index 00000000..f2ee4e41
--- /dev/null
+++ b/fuzz/privkey_corpus/d70ddef2d9af1c0b3bca27e5e1fd28508151c3ec
Binary files differ
diff --git a/fuzz/privkey_corpus/d77a9ea971ce9b7fb6c73339ab715c1e7475c735 b/fuzz/privkey_corpus/d77a9ea971ce9b7fb6c73339ab715c1e7475c735
deleted file mode 100644
index 0bbe5c23..00000000
--- a/fuzz/privkey_corpus/d77a9ea971ce9b7fb6c73339ab715c1e7475c735
+++ /dev/null
@@ -1 +0,0 @@
-000^0 )*H  \ No newline at end of file
diff --git a/fuzz/privkey_corpus/d86de6972bc8bd6f0df835199ab0aae303f3f8d4 b/fuzz/privkey_corpus/d86de6972bc8bd6f0df835199ab0aae303f3f8d4
deleted file mode 100644
index e78c74dc..00000000
--- a/fuzz/privkey_corpus/d86de6972bc8bd6f0df835199ab0aae303f3f8d4
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35 b/fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35
new file mode 100644
index 00000000..750df24a
--- /dev/null
+++ b/fuzz/privkey_corpus/d87db84d6d07adc1eaf599cd5c648b12dd27ac35
Binary files differ
diff --git a/fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0 b/fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0
new file mode 100644
index 00000000..404213d4
--- /dev/null
+++ b/fuzz/privkey_corpus/d91f6aa49d402a9e5af29198f642f5362e768ff0
Binary files differ
diff --git a/fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28 b/fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28
new file mode 100644
index 00000000..1ae825ba
--- /dev/null
+++ b/fuzz/privkey_corpus/d9438c6b463eb1d6ad4b3927379bab36bbc83a28
Binary files differ
diff --git a/fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375 b/fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375
new file mode 100644
index 00000000..30787329
--- /dev/null
+++ b/fuzz/privkey_corpus/d95b5a0a0e5f4899ec2810205fa188eaec863375
Binary files differ
diff --git a/fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44 b/fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44
new file mode 100644
index 00000000..2f694f0e
--- /dev/null
+++ b/fuzz/privkey_corpus/da5cb65f5a4b18e5667b7fa2e9dd0217f738da44
Binary files differ
diff --git a/fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112 b/fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112
new file mode 100644
index 00000000..9b533c26
--- /dev/null
+++ b/fuzz/privkey_corpus/daa4d5092473a26fa51d907baf58b62001574112
Binary files differ
diff --git a/fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7 b/fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7
new file mode 100644
index 00000000..dba943b1
--- /dev/null
+++ b/fuzz/privkey_corpus/db0897cfd10616880044b4ecd103a9b342bebdb7
Binary files differ
diff --git a/fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2 b/fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2
new file mode 100644
index 00000000..c6de154b
--- /dev/null
+++ b/fuzz/privkey_corpus/db168d324c7afabbd41281dea38fb921b26127a2
Binary files differ
diff --git a/fuzz/privkey_corpus/db6c91a81049a4c819e086b54513d20446691ab9 b/fuzz/privkey_corpus/db6c91a81049a4c819e086b54513d20446691ab9
deleted file mode 100644
index 598e5514..00000000
--- a/fuzz/privkey_corpus/db6c91a81049a4c819e086b54513d20446691ab9
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fd b/fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fd
new file mode 100644
index 00000000..38c7903a
--- /dev/null
+++ b/fuzz/privkey_corpus/ddbc813e2d2bd98f212f672d957c4435ec2d44fd
Binary files differ
diff --git a/fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151 b/fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151
new file mode 100644
index 00000000..41689c31
--- /dev/null
+++ b/fuzz/privkey_corpus/de5041627e235f218681ba95d19f2e9173e63151
Binary files differ
diff --git a/fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041 b/fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041
new file mode 100644
index 00000000..29c82cc9
--- /dev/null
+++ b/fuzz/privkey_corpus/dec155c4b108bd455f1b4ef2aa7c126d99c8d041
Binary files differ
diff --git a/fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7 b/fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7
new file mode 100644
index 00000000..82fab30c
--- /dev/null
+++ b/fuzz/privkey_corpus/dedafeddf2d532a8e4c2659d81e774539df6d1e7
Binary files differ
diff --git a/fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091 b/fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091
new file mode 100644
index 00000000..ab88371c
--- /dev/null
+++ b/fuzz/privkey_corpus/dfabe7f053a84772adcd20f73f28c4b7d4360091
Binary files differ
diff --git a/fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798d b/fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798d
new file mode 100644
index 00000000..b2dc58aa
--- /dev/null
+++ b/fuzz/privkey_corpus/e0c41dfc764c3a0343dbb9bc55109dc45f88798d
Binary files differ
diff --git a/fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54 b/fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54
new file mode 100644
index 00000000..a671525d
--- /dev/null
+++ b/fuzz/privkey_corpus/e2e3d56e07f5c7c4a496c232fad04406eefedf54
Binary files differ
diff --git a/fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10 b/fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10
new file mode 100644
index 00000000..dba55f6e
--- /dev/null
+++ b/fuzz/privkey_corpus/e59134a28131083c665bb210e95ec94903f65b10
Binary files differ
diff --git a/fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36d b/fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36d
new file mode 100644
index 00000000..b4611b05
--- /dev/null
+++ b/fuzz/privkey_corpus/e5b4fb31f24d7177673bd17da10fcc23bc5fc36d
Binary files differ
diff --git a/fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5 b/fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5
new file mode 100644
index 00000000..2963c6a7
--- /dev/null
+++ b/fuzz/privkey_corpus/e5e988ac8dd0269554bc8c0d636c6c5f1ab306c5
Binary files differ
diff --git a/fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660c b/fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660c
new file mode 100644
index 00000000..76d8ccd0
--- /dev/null
+++ b/fuzz/privkey_corpus/e8570727b0bdb9794368ce4e52702cc6fa91660c
Binary files differ
diff --git a/fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0ad b/fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0ad
new file mode 100644
index 00000000..bf71f0af
--- /dev/null
+++ b/fuzz/privkey_corpus/e877fa4f35693b4629b43b5e0a464f9239a8a0ad
Binary files differ
diff --git a/fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464 b/fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464
new file mode 100644
index 00000000..b0b92798
--- /dev/null
+++ b/fuzz/privkey_corpus/e8c30442040d5df46c96fcf09e200565851fd464
Binary files differ
diff --git a/fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dc b/fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dc
new file mode 100644
index 00000000..ddd36e7b
--- /dev/null
+++ b/fuzz/privkey_corpus/e9734e0052649aab1e22f6638d4e4070fd7675dc
Binary files differ
diff --git a/fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7 b/fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7
new file mode 100644
index 00000000..15fcbfb1
--- /dev/null
+++ b/fuzz/privkey_corpus/e97a189be7a813919db5a4b277d0978d762e6db7
Binary files differ
diff --git a/fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41 b/fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41
new file mode 100644
index 00000000..ec04dac5
--- /dev/null
+++ b/fuzz/privkey_corpus/ea1fb604e956587f84c7af5ab9b2d0c39549be41
Binary files differ
diff --git a/fuzz/privkey_corpus/ea36122710fd32c98c091a6d3851b347d9dce5a5 b/fuzz/privkey_corpus/ea36122710fd32c98c091a6d3851b347d9dce5a5
deleted file mode 100644
index 07f51a02..00000000
--- a/fuzz/privkey_corpus/ea36122710fd32c98c091a6d3851b347d9dce5a5
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477 b/fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477
new file mode 100644
index 00000000..084c5593
--- /dev/null
+++ b/fuzz/privkey_corpus/ebc358fc77925b5da9feec9b06a12724f7416477
Binary files differ
diff --git a/fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94 b/fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94
new file mode 100644
index 00000000..7bf2aaef
--- /dev/null
+++ b/fuzz/privkey_corpus/ec8c496dd5407c982d19a0814c282bed0bc8ba94
Binary files differ
diff --git a/fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424 b/fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424
new file mode 100644
index 00000000..07ec62fc
--- /dev/null
+++ b/fuzz/privkey_corpus/ec91f82481fda2b90261e991ea8a9bc210ca8424
Binary files differ
diff --git a/fuzz/privkey_corpus/ec97391303bce6e2ce9f61eaf52fd06fef0ab82b b/fuzz/privkey_corpus/ec97391303bce6e2ce9f61eaf52fd06fef0ab82b
deleted file mode 100644
index 80b80cf5..00000000
--- a/fuzz/privkey_corpus/ec97391303bce6e2ce9f61eaf52fd06fef0ab82b
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7 b/fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7
new file mode 100644
index 00000000..00997d3e
--- /dev/null
+++ b/fuzz/privkey_corpus/ecb6d9c45861c603a32054d8543fa740598751e7
Binary files differ
diff --git a/fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400d b/fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400d
new file mode 100644
index 00000000..bf86cb0a
--- /dev/null
+++ b/fuzz/privkey_corpus/ee988717ae3fbaecc5463e174a397c35afcb400d
Binary files differ
diff --git a/fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96 b/fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96
new file mode 100644
index 00000000..3a67b04b
--- /dev/null
+++ b/fuzz/privkey_corpus/ef7b58b485fa43fe4db625066556e21c53d74c96
Binary files differ
diff --git a/fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8 b/fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8
new file mode 100644
index 00000000..377e3b31
--- /dev/null
+++ b/fuzz/privkey_corpus/f02080cd564a6b1a46ceff085f2a44ac015af1b8
Binary files differ
diff --git a/fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9ed b/fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9ed
new file mode 100644
index 00000000..fc452d7b
--- /dev/null
+++ b/fuzz/privkey_corpus/f0c2ec4a959d10612cd67742f319075d172da9ed
Binary files differ
diff --git a/fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61d b/fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61d
new file mode 100644
index 00000000..bc8d8684
--- /dev/null
+++ b/fuzz/privkey_corpus/f2672bb54f6a49d0c5b14c4da7ca3f790955c61d
Binary files differ
diff --git a/fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076b b/fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076b
new file mode 100644
index 00000000..9deb8688
--- /dev/null
+++ b/fuzz/privkey_corpus/f2b919fbae73d9d89c6afbd7352a6d6271db076b
Binary files differ
diff --git a/fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162d b/fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162d
new file mode 100644
index 00000000..ef400c08
--- /dev/null
+++ b/fuzz/privkey_corpus/f3494677a550ceb7644ca41d74f5358389eb162d
Binary files differ
diff --git a/fuzz/privkey_corpus/f34aa93e1616ffaf490c9c24826fcc5c637655f4 b/fuzz/privkey_corpus/f34aa93e1616ffaf490c9c24826fcc5c637655f4
deleted file mode 100644
index b7a93dbc..00000000
--- a/fuzz/privkey_corpus/f34aa93e1616ffaf490c9c24826fcc5c637655f4
+++ /dev/null
@@ -1 +0,0 @@
-' \ No newline at end of file
diff --git a/fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985e b/fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985e
new file mode 100644
index 00000000..fb96ad0e
--- /dev/null
+++ b/fuzz/privkey_corpus/f3b6ac34b1e0de8b6a8bc0092af2546f17db985e
Binary files differ
diff --git a/fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34b b/fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34b
new file mode 100644
index 00000000..d23b05af
--- /dev/null
+++ b/fuzz/privkey_corpus/f510a4e3243a5214e171c388d4de68dbb074e34b
Binary files differ
diff --git a/fuzz/privkey_corpus/f56e3afd3eece26c160ae0b80b545edbbaa35a7b b/fuzz/privkey_corpus/f56e3afd3eece26c160ae0b80b545edbbaa35a7b
deleted file mode 100644
index 6b698d88..00000000
--- a/fuzz/privkey_corpus/f56e3afd3eece26c160ae0b80b545edbbaa35a7b
+++ /dev/null
Binary files differ
diff --git a/fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bd b/fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bd
new file mode 100644
index 00000000..31cdac40
--- /dev/null
+++ b/fuzz/privkey_corpus/f63885f363b05455c24d547a378d98578529e6bd
Binary files differ
diff --git a/fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bd b/fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bd
new file mode 100644
index 00000000..854c083f
--- /dev/null
+++ b/fuzz/privkey_corpus/f67021300689c16cff95fac4d33565f788e820bd
Binary files differ
diff --git a/fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7 b/fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7
new file mode 100644
index 00000000..b1fa88cc
--- /dev/null
+++ b/fuzz/privkey_corpus/f686aef722cf896abde5defa3dfc6d6533189eb7
Binary files differ
diff --git a/fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634e b/fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634e
new file mode 100644
index 00000000..31a64ed3
--- /dev/null
+++ b/fuzz/privkey_corpus/f69f0bcbf3c1afcd32f0506afca7b37db449634e
Binary files differ
diff --git a/fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e b/fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e
new file mode 100644
index 00000000..6cf47b4b
--- /dev/null
+++ b/fuzz/privkey_corpus/f6bf878f2c1a1f523e8b1cff0a2a3cfadb492c1e
Binary files differ
diff --git a/fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848a b/fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848a
new file mode 100644
index 00000000..ac608367
--- /dev/null
+++ b/fuzz/privkey_corpus/f84e4fd02339fdc0d688342523e803b1a786848a
Binary files differ
diff --git a/fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7ce b/fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7ce
new file mode 100644
index 00000000..f5092aa2
--- /dev/null
+++ b/fuzz/privkey_corpus/f99bca591409d3bab5f99232c5af1d7bf871e7ce
Binary files differ
diff --git a/fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420d b/fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420d
new file mode 100644
index 00000000..506ad566
--- /dev/null
+++ b/fuzz/privkey_corpus/fa21edf3b4aac56ad7c2e224d31b269b099f420d
Binary files differ
diff --git a/fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5e b/fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5e
new file mode 100644
index 00000000..295d55aa
--- /dev/null
+++ b/fuzz/privkey_corpus/fd0faf38df5b04f9a26ecd3084af7e669eb23a5e
Binary files differ
diff --git a/fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208 b/fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208
new file mode 100644
index 00000000..a33319c4
--- /dev/null
+++ b/fuzz/privkey_corpus/fd3d7ba8e7ced0692c56beb9150b0bbbb546f208
Binary files differ
diff --git a/fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4 b/fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4
new file mode 100644
index 00000000..8941f7f5
--- /dev/null
+++ b/fuzz/privkey_corpus/fe4c7ca0cd95cef2dca804ce88c3ee1e076197d4
Binary files differ
diff --git a/fuzz/privkey_corpus/fe7d7ae7b073e7076b8dd729ff7627431162b5c3 b/fuzz/privkey_corpus/fe7d7ae7b073e7076b8dd729ff7627431162b5c3
deleted file mode 100644
index 550582b2..00000000
--- a/fuzz/privkey_corpus/fe7d7ae7b073e7076b8dd729ff7627431162b5c3
+++ /dev/null
Binary files differ
diff --git a/fuzz/read_pem.cc b/fuzz/read_pem.cc
new file mode 100644
index 00000000..511c4ee0
--- /dev/null
+++ b/fuzz/read_pem.cc
@@ -0,0 +1,36 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/crypto.h>
+#include <openssl/mem.h>
+#include <openssl/pem.h>
+
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
+ char *name, *header;
+ uint8_t *pem_data;
+ long pem_len;
+
+ BIO *bio = BIO_new_mem_buf(buf, len);
+
+ if (PEM_read_bio(bio, &name, &header, &pem_data, &pem_len) == 1) {
+ OPENSSL_free(name);
+ OPENSSL_free(header);
+ OPENSSL_free(pem_data);
+ }
+
+ BIO_free(bio);
+
+ return 0;
+}
diff --git a/fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e2 b/fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e2
new file mode 100644
index 00000000..7709f4a3
--- /dev/null
+++ b/fuzz/read_pem_corpus/01270d57eecae64f59b9b27cc06e3f9eaf2304e2
@@ -0,0 +1 @@
+-----BEGIN O-------- \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d b/fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d
new file mode 100644
index 00000000..74e0f12e
--- /dev/null
+++ b/fuzz/read_pem_corpus/0ab8318acaf6e678dd02e2b5c343ed41111b393d
@@ -0,0 +1 @@
+! \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3 b/fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3
new file mode 100644
index 00000000..80ece3cf
--- /dev/null
+++ b/fuzz/read_pem_corpus/0b08765ad46bb11ac55348755ad5c8e4386bd2f3
Binary files differ
diff --git a/fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e b/fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e
new file mode 100644
index 00000000..6f429701
--- /dev/null
+++ b/fuzz/read_pem_corpus/0bdb9660f74f82a5471210026fdee0b674f1114e
@@ -0,0 +1,33 @@
+-G
+----BEGIN O-----
+----(END /!----G
+(
+ 7--
+--BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN :4'-----
+G
+UU--
+--BEGIN :4'-----
+G
+UU -----BEGIN 24'/----
+----BEGIN :4'-----
+G
+UU qG
+wFUG
+ fbwFUU QG
+wFU QG
+wFUG
+ fbwFUU QG
+wFU fbwFUUU G
+bwFU f
+bwFU U fbwFUU f
+bwFU U fbU fbwF fUG
+ fbwFU f fTwFTU fbwFUf(
+FUU f
+bwFU U fbwFUU;!(;)-----EN /O!:---
+---BE- NI-GO---
+---*
+ f
+bwFU U fbU fbw-----BEG-F fU \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0 b/fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0
new file mode 100644
index 00000000..0bcf00c1
--- /dev/null
+++ b/fuzz/read_pem_corpus/0c4287915a432e6b50e1c2eb0f4ca037b1730aa0
Binary files differ
diff --git a/fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f4 b/fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f4
new file mode 100644
index 00000000..8782df57
--- /dev/null
+++ b/fuzz/read_pem_corpus/0d583f2aee2e15a7dc7eb93af1ecf44203b537f4
@@ -0,0 +1,3 @@
+------BEG-*
+----BEGIN N )(!a!*)(a':':--!;'---BEGIN )a':'!;'R):u ;qrR)M
+* \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a b/fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a
new file mode 100644
index 00000000..77d030eb
--- /dev/null
+++ b/fuzz/read_pem_corpus/0e3deb2e809b535f39efded20697314a29c8335a
@@ -0,0 +1,7 @@
+-
+---BEGIN O-----
+----(END--=--END /!-----BE-----END GI 5;!(;)-----END /!---
+
+-
+6(-
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237d b/fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237d
new file mode 100644
index 00000000..c8e019d1
--- /dev/null
+++ b/fuzz/read_pem_corpus/0f29362dfb076a14a103e8bc2c9681fac93c237d
Binary files differ
diff --git a/fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f b/fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f
new file mode 100644
index 00000000..61da76b9
--- /dev/null
+++ b/fuzz/read_pem_corpus/1078e6b183abbe50aa19cffd741db1cb30e5cf4f
@@ -0,0 +1,8 @@
+-----BEGIN O!:'U('((/!;!;O!:'U('((/!;!;6();':('H('G)MG'yO )O(*-----
+-----BEGIN :(*:!:O!:'U('(:(/!;!;6();-----BEGIN (/!;!;6();':('H('G)':('H('G)MG-----BEGIN O!:'U('((/!;!;O!:'U('((/!;!;3();':('H('G)MG'yO )O(*-----
+-----BEGIN :(*:!:O!O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*;:)
+
+*:!------
+----BEIN *;:)
+N O!:'U('((!;!;6();''yO )o(*(*;:)*:!::(';'(;)(!:):"PZw;:P:('H(%G; ) \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e1 b/fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e1
new file mode 100644
index 00000000..71c2bae5
--- /dev/null
+++ b/fuzz/read_pem_corpus/149b4073e8ee2d37455c0d7867c7cffdecf0f8e1
@@ -0,0 +1,17 @@
+O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*---------
+;:)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('G)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(';)MG'yO )o(*(*-----
+O*;:)
+
+----B--E-6-BG \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc32 b/fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc32
new file mode 100644
index 00000000..592aee1a
--- /dev/null
+++ b/fuzz/read_pem_corpus/15dd914fbdc4335ebc69caa9afe37681dd75cc32
@@ -0,0 +1,17 @@
+------
+-----
+----BEGIN 6(
+
+----N!(ED /-----BEGI 6;!(;)--'-8-END -
+---BEGIN O-----
+----(END--=--END -----BEGIN O-----
+----(END /!-----BEGIN 6;!(;)-----END //!-----!;BE-----END GI 5;!(;)-----END -----
+/!---
+
+-
+6/!--!-----
+6(-
+
+-
+6((-
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e8 b/fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e8
new file mode 100644
index 00000000..8cb5a8c8
--- /dev/null
+++ b/fuzz/read_pem_corpus/18810634408061267ccb64d68fb85b4ed93515e8
@@ -0,0 +1,45 @@
+-----BEGIN O-*---
+-(
+-(END /!----G
+(
+ (--
+(
+BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN :4'-----
+G
+UU--
+--BEGIN :4'G
+-----
+G
+UU -----BEGIN 24'/----
+-----BEGIN :4'---=-
+G
+UU-----BEGIN O-----
+-(
+-(END /!----G
+(
+ (--
+(
+BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN QG
+wF:4'-----
+G
+UU--
+--BEGIN :4'G
+-----
+G
+UU -----BEGIN 24'/----
+-----BGIN :4'-----
+G
+UU QG
+wFUG
+ fbwFUU QG
+wFU UQG
+wFUG
+ fbwFUU QG
+wFU fG
+ b \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5 b/fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5
new file mode 100644
index 00000000..089c7892
--- /dev/null
+++ b/fuzz/read_pem_corpus/1f68f0ee67566b2954a4e2d2c31f6abb60cdaed5
@@ -0,0 +1,4 @@
+-*
+-----BEG--)--BEGIN N )a':':--!;'*
+---BEGIN )a':':!;'R):u::rR)M'
+* \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67 b/fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67
new file mode 100644
index 00000000..d3be1807
--- /dev/null
+++ b/fuzz/read_pem_corpus/20a000f3932e041a634b759b7cef8138b5b40f67
Binary files differ
diff --git a/fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4 b/fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4
new file mode 100644
index 00000000..e2d9d4c5
--- /dev/null
+++ b/fuzz/read_pem_corpus/20d3859cd71d9b215f55983a5ac9cce7c0a36cc4
Binary files differ
diff --git a/fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe52789 b/fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe52789
new file mode 100644
index 00000000..b66cf6b8
--- /dev/null
+++ b/fuzz/read_pem_corpus/217d0e120e43e1899a8ab51009de55038fe52789
@@ -0,0 +1,15 @@
+-----BEGIN :T!(!*!*z:'*:Ͱ:!m*O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*-------END :)
+O*;:)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('1)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(';)MG'yO )o(*(*-----
+-----END O*;;)''D;:f(;w:;;V*H \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8 b/fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8
new file mode 100644
index 00000000..08dee539
--- /dev/null
+++ b/fuzz/read_pem_corpus/2493849afd1697d00f4c2f36af4522e6a9ba46b8
Binary files differ
diff --git a/fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933 b/fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933
new file mode 100644
index 00000000..ffa04113
--- /dev/null
+++ b/fuzz/read_pem_corpus/27c891aa76f51487ada28b1fc69ac13c7315c933
Binary files differ
diff --git a/fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3 b/fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3
new file mode 100644
index 00000000..db3ca3cc
--- /dev/null
+++ b/fuzz/read_pem_corpus/27ec8c0bf073ec4ea4f5ee15fbaca4fb32f728b3
@@ -0,0 +1 @@
+O!:'U('((/!;!;6();'8('H('G)MG'yO )o(*(*;:)O!:'U(*:!::(';'(;'(:(/))(-----BEGIN (/!;!;6();':('!;!;H('G)MG'yO*o( )(*;:)*:!::(';'(6;)(!:):"PZw;:P; :'::7!))vǾ:kqU;|:؎8*:;s(f!;;)j*:: \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f b/fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f
new file mode 100644
index 00000000..0e95e43b
--- /dev/null
+++ b/fuzz/read_pem_corpus/2904f9b6f6cb0ddf9248537b4fb4b2170174b74f
@@ -0,0 +1,3 @@
+-----BEGIN x:*****f(~'!5 ) );'*E---------------
+
+-----E::T***f(~'!5); C'*E;:;h0G;G('!*'l*)!:!:;'4C*3:)((#(':(''u*!!!;!;) \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeed b/fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeed
new file mode 100644
index 00000000..e07812af
--- /dev/null
+++ b/fuzz/read_pem_corpus/2a7b8759f3267d3ddca22e936df0b21eabb1aeed
Binary files differ
diff --git a/fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c111 b/fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c111
new file mode 100644
index 00000000..08e697b6
--- /dev/null
+++ b/fuzz/read_pem_corpus/2aaf881c96d0758e5ac244a74deccb7e6363c111
@@ -0,0 +1,14 @@
+-----BEGIN O-----
+----(END /!-----BEGI 7;!(;)-----END /O!:---
+-----END O-----
+----(END /!---'U('(:(!/;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!-
+:(';'(;)-
+(!:):"PZg;:; :'::7!))v*Ǿ:--BEGIN 6;!(;)--
+----END /!-----
+-
+kqU;!:O'U|:؎9*:;s(f!;;)------
+----BEGIN O-----
+----(END /!-----BEGIN 6
+j-
+;!(;)-----END 6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f b/fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f
new file mode 100644
index 00000000..5ed63dd8
--- /dev/null
+++ b/fuzz/read_pem_corpus/2ef2666e807e55481eb81bd2bd8369a4422dfc6f
@@ -0,0 +1,5 @@
+-----BEGIN --+---'---+-------
+
+-----BEGIN :T!(!*!*z:H_t);~*N?!:m*;*'---+--------
+GIN '-----
+:T!(!-c:>:;}!;*:!;'y 'x'`)*a;:!E!*)(*)()''*:E*:1***!*z:H:*'*$'F';'*T!):- \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0 b/fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0
new file mode 100644
index 00000000..36b11260
--- /dev/null
+++ b/fuzz/read_pem_corpus/318bcf81a2b6fa0ce680ec82cf11e8a6e4bd93f0
@@ -0,0 +1,4 @@
+-----BEGIN O-----
+----(END /!-----BEGI 2;!(;)-----ED/ !---
+
+-6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f13121 b/fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f13121
new file mode 100644
index 00000000..be1427a1
--- /dev/null
+++ b/fuzz/read_pem_corpus/358ff4aeb6903affa5d080c317c3270ac4f13121
@@ -0,0 +1 @@
+- \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a b/fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a
new file mode 100644
index 00000000..654203b5
--- /dev/null
+++ b/fuzz/read_pem_corpus/35bae979e092abdc6b31f8b3c52ddcafa4722a9a
@@ -0,0 +1,11 @@
+-----BEGIN O----
+----N!(ED /-----BEGI 6;!(;)----8-END -
+---BEGIN O-----
+----(END--=--END /!-----BE-----END GI 5;!(;)-----END /!---
+
+-
+6/!---
+
+-
+6((-
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef25 b/fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef25
new file mode 100644
index 00000000..1ddb5fd9
--- /dev/null
+++ b/fuzz/read_pem_corpus/38fccbaee723a06ca137a952843b58d32d35ef25
@@ -0,0 +1,2 @@
+-----BEGIN --+-----
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181 b/fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181
new file mode 100644
index 00000000..de6ff53b
--- /dev/null
+++ b/fuzz/read_pem_corpus/3aaa3cdd4444fad7e59ba1ac2c0cbe6b60ea1181
@@ -0,0 +1 @@
+-----BEGIN \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d798 b/fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d798
new file mode 100644
index 00000000..9f35df06
--- /dev/null
+++ b/fuzz/read_pem_corpus/3b981c1e4697103278b32ee4e29e3a7b5225d798
@@ -0,0 +1,14 @@
+O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*-------END :)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('1)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(';)MG'yO )o(*(*-----
+-----END O*;;)''D;:f(;w:; ,=*'4>;9:(;'5*i)T;:) \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2 b/fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2
new file mode 100644
index 00000000..c998e40a
--- /dev/null
+++ b/fuzz/read_pem_corpus/3bff6c9ef0381ea1080fdfb5b4f9c02e95f549b2
Binary files differ
diff --git a/fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18 b/fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18
new file mode 100644
index 00000000..60180841
--- /dev/null
+++ b/fuzz/read_pem_corpus/3cdb51f7ffc8ef0bd03265c3a414069815821d18
Binary files differ
diff --git a/fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64 b/fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64
new file mode 100644
index 00000000..a082d7ca
--- /dev/null
+++ b/fuzz/read_pem_corpus/3f46a93da1448c00d2a9f3a62117bd522ce8de64
Binary files differ
diff --git a/fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb b/fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb
new file mode 100644
index 00000000..cc885607
--- /dev/null
+++ b/fuzz/read_pem_corpus/411752e433e18c27f83b9728256082c2ffb77ebb
@@ -0,0 +1,15 @@
+O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*-------END :)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('1)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(';)MG'yO )o(*(*-----
+-----END O*;;)''D;:f(;w:; ,=*'4>;9:(;'5*i)T;:G
+) \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d b/fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d
new file mode 100644
index 00000000..bc4db0e6
--- /dev/null
+++ b/fuzz/read_pem_corpus/42650de48dbf62d86a91ede484061f834214915d
@@ -0,0 +1,2 @@
+-----BEGIN O-----
+----(END------B /!----BEGIN 6;!(;)-----END EGIN ---/!;!6(-BEGIN O \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588 b/fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588
new file mode 100644
index 00000000..ec5064dc
--- /dev/null
+++ b/fuzz/read_pem_corpus/488ae502baabc6506f8722dcdc5294940fa5d588
Binary files differ
diff --git a/fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e b/fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e
new file mode 100644
index 00000000..8935731f
--- /dev/null
+++ b/fuzz/read_pem_corpus/4aa25eda7560bbd746d9a69b63965c0de21bb53e
@@ -0,0 +1,34 @@
+-----BEGIN O-----
+-(
+-(END /!----G
+(
+ (--
+(
+BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN :4'-----
+G
+UU--
+--BEGIN :4'G
+-----
+G
+UU -----BEGIN 24'/----
+-----BEGIN :4'-----
+G
+UU QG
+wFUG
+ fbwFUU QG
+wFU QG
+wFUG
+ fbwFUU QG
+wFU fbwFUUU G
+bwFU f
+bwFU U f fbwFUU f
+bwFU U fbU fbwF fUG
+ fbwFU f fTwFTU fbwFUfbwFUU f
+bwFU U fbwFUU;!(;)-----EN /O!:---
+---BE- NI-GO---
+---*
+ f
+bwFU U fbU fbw-----BEG-F fU \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d45596 b/fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d45596
new file mode 100644
index 00000000..0240c224
--- /dev/null
+++ b/fuzz/read_pem_corpus/4b32aa9edbd17b2d63390a41cc98739be7d45596
@@ -0,0 +1,7 @@
+-----BEGIN :4'-----
+ f uf f -
+;3;w: ,=*'3>;9:5;('*i)T'fi'(;n*;;*?;-----
+-----END :4'-----
+:$;(:!@;L)J))':Z:!:.6'y:*'*aYXX;:()*!;S------BEGIN :f(;w:; ,=*'3>;9:(;i'(;
+E=BEGI(N-----)GIԂ')*::!!;!>:r*>!oT#!>;):)) :pэ*;e' *(%y*';*'(d'!;Տ;N 'i'(;
+%i;;)''D;:;;)j':';;ki!'!''D;m!!('4!$!0* \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18 b/fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18
new file mode 100644
index 00000000..23ab556b
--- /dev/null
+++ b/fuzz/read_pem_corpus/4d43fa4e63042871afdb387b75a8845d47b46d18
Binary files differ
diff --git a/fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2 b/fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2
new file mode 100644
index 00000000..a6b3eb0c
--- /dev/null
+++ b/fuzz/read_pem_corpus/548649f5502df5e77b9d332d3f1e29dedd7afdb2
Binary files differ
diff --git a/fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208c b/fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208c
new file mode 100644
index 00000000..dbf27e96
--- /dev/null
+++ b/fuzz/read_pem_corpus/55885a3f94688b36e34fac8ce1fd7fcc7bb7208c
Binary files differ
diff --git a/fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e8 b/fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e8
new file mode 100644
index 00000000..fe314319
--- /dev/null
+++ b/fuzz/read_pem_corpus/5891dd7c6715eca7f427ed9267de9da72b8e82e8
@@ -0,0 +1,15 @@
+-----BEGIN :T!(!*!*z:'*:Ͱ:!m*O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*-------END :)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('1)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(';)MG'yO )o(*(*-----
+-----END O*;;)''D;:f(;w:;;*H-----
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55 b/fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55
new file mode 100644
index 00000000..2a9c6c51
--- /dev/null
+++ b/fuzz/read_pem_corpus/58bdb0aea139a2790c2e1a3b25e302892a6c4b55
Binary files differ
diff --git a/fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96 b/fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96
new file mode 100644
index 00000000..32ddacab
--- /dev/null
+++ b/fuzz/read_pem_corpus/5c720dc0326e4ffa322f706337df9bc87f42fd96
Binary files differ
diff --git a/fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e b/fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e
new file mode 100644
index 00000000..e0f7f035
--- /dev/null
+++ b/fuzz/read_pem_corpus/667da9df1cde33d635bbde1986827573ed686a7e
@@ -0,0 +1,6 @@
+O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*-----
+O*;:)
+
+----BEGIN O!:'U('O*;:)
+-----BEGIN :(/!(( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f4760 b/fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f4760
new file mode 100644
index 00000000..1a3eaae4
--- /dev/null
+++ b/fuzz/read_pem_corpus/66f8b696c46c10a6db20b690e4431b72745f4760
@@ -0,0 +1,7 @@
+-----BEGIN !:T(!*!*z:H-----
+F'*T!:m*;*c:>:;}!;*Z:!;'y 'x'`)*a;:!E!*)('---+----
+*)()''*:E*:1**';)*(;*-----vBEGIN --+---'---+------/
+
+-----BEGIN --+---'---+-------
+
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb68 b/fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb68
new file mode 100644
index 00000000..3e36ec28
--- /dev/null
+++ b/fuzz/read_pem_corpus/699044ddfe4887d6081ce2a36c1302814294eb68
@@ -0,0 +1,15 @@
+--*
+--*
+BEGIN -*
+a!*)(-----BE-*
+
+----BEGIN N --*
+--*
+BEGIN -*
+a!*)(-----BE-*
+
+----BEGIN N )(!a!*)(a':':--!9'---BEGIN )a'-*
+a!*)(--:'!;'R):w (;Rrq)---B)(!a!*)(a':'E-*
+
+----BEGIN N :--!9'---BEGIN )a')(!-*
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d907 b/fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d907
new file mode 100644
index 00000000..3c91ae44
--- /dev/null
+++ b/fuzz/read_pem_corpus/6d1d12ef00c585b4c859479bfa2522f4a447d907
@@ -0,0 +1,5 @@
+-----BEGIN --+---'------BEGIN --+---'---+-------
+
+-----BEGIN :T!(!**z:H_t);~*N?!:m*;*'----+------/
+
+- \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c b/fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c
new file mode 100644
index 00000000..50119ec3
--- /dev/null
+++ b/fuzz/read_pem_corpus/6d67bafd83bed7aadd641417671e6864dc87073c
@@ -0,0 +1,16 @@
+O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*-------END :)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('G)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(';)MG'yO )o(*(*-----
+-----END O*;:)Ĺ
+
+----B--E-6-BG \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2 b/fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2
new file mode 100644
index 00000000..2090fe20
--- /dev/null
+++ b/fuzz/read_pem_corpus/6dcb7976d9af4a72b3667926f1fe7642c75685b2
Binary files differ
diff --git a/fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b80 b/fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b80
new file mode 100644
index 00000000..7ad3f5c3
--- /dev/null
+++ b/fuzz/read_pem_corpus/6e6aa5ec1653a57a37c043255ab834f6b2228b80
@@ -0,0 +1,2 @@
+-----BEGIN O!:'U('((/!;!;O!:'U('((/!;!;3();':('H('GO*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*)MG'----- \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e6 b/fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e6
new file mode 100644
index 00000000..6f386229
--- /dev/null
+++ b/fuzz/read_pem_corpus/729be2837328d9f25597b1d605188bc724c632e6
@@ -0,0 +1,6 @@
+O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('G)MG'O*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(----BEGIN ;(j-/!;!;6();':('; \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa915 b/fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa915
new file mode 100644
index 00000000..a88821da
--- /dev/null
+++ b/fuzz/read_pem_corpus/74a4f38726a49f3a8c06763d58d8fc229b2aa915
@@ -0,0 +1,3 @@
+-----BEGIN --+---'---+-------
+
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567 b/fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567
new file mode 100644
index 00000000..fc048fe4
--- /dev/null
+++ b/fuzz/read_pem_corpus/74b9536c60def2f9cb8e83512b80ff8406d12567
Binary files differ
diff --git a/fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda b/fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda
new file mode 100644
index 00000000..16ea15dd
--- /dev/null
+++ b/fuzz/read_pem_corpus/74b97735df0ee03d5a912734de93772093826bda
@@ -0,0 +1,33 @@
+-6(
+
+-----
+----BEGIN 6(
+
+----N!(ED /-----BEGI 5;!()--'-8-END -
+---BEGIN O-----
+----(END--=--E------
+-----
+----ND -----BEGIN O-----
+----(END /!-----BEGIN 6;!(;)-----END //!-----!;BE-----END GI 5;!(;)-----END /!---
+
+-
+6BEGIN 6(
+
+----N!(ED /-----BEGI 6;!(;)--'-8-END -
+---BEGIN O-----
+---;(END--=--END -----BEGIN O-
+---
+----(END /!-----BEGIN 6;!(;)-----END //!-----!;BE-----END GI 5/!--!-----
+6(-;!(;)-----END /!---
+
+-
+6/!--
+
+-
+6((-
+!-----
+6(-
+
+-
+6((-
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b21126 b/fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b21126
new file mode 100644
index 00000000..59ae4f47
--- /dev/null
+++ b/fuzz/read_pem_corpus/7539289d67a0974d16f0ed01ded0a58a02b21126
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70b b/fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70b
new file mode 100644
index 00000000..7eeef2a9
--- /dev/null
+++ b/fuzz/read_pem_corpus/78c435e1927ec196afab938edced0b9ee267e70b
Binary files differ
diff --git a/fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e848121 b/fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e848121
new file mode 100644
index 00000000..890697e6
--- /dev/null
+++ b/fuzz/read_pem_corpus/78e4c8a5d73cf074f243ef12a3669fef1e848121
@@ -0,0 +1,10 @@
+-----BEGIN O-----
+----(END /!-----BEGI 7;!(;)-----END /O!:-----BEGIN O-----
+----(END /!---'U('(:(/!;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!::(';'(;)(!:):"PZg;:; :'::7!))vǾ:--BEGIN 6;!(;)--
+----END /!-----
+-
+kqU;O!:'U|:؎8*:;s(f!;;)--*----
+----BEGIN O-----
+----(END /!-----BEGIN 6-
+j*:;!(;)-----END 6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f b/fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f
new file mode 100644
index 00000000..84f5797c
--- /dev/null
+++ b/fuzz/read_pem_corpus/7a582440bd4712ab88a3e745f928202707585e6f
@@ -0,0 +1,33 @@
+-----BEGIN O-----
+-(
+-(END /!----G
+(
+ 7--
+(
+BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN :4'-----
+G
+UU--
+--BEGIN :4'-----
+G
+UU -----BEGIN 24'/----
+-----BEGIN :4'-----
+G
+UU QG
+wFUG
+ fbwFUU QG
+wFU QG
+wFUG
+ fbwFUU QG
+wFU fbwFUUU G
+bwFU f
+bwFU U f fbwFUU f
+bwFU U fbU fbwF fUG
+ fbwFU f fTwFTU fbwFUfbwFUU f
+bwFU U fbwFUU;!(;)-----EN /O!:---
+---BE- NI-GO---
+---*
+ f
+bwFU U fbU fbw-----BEG-F fU \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd b/fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd
new file mode 100644
index 00000000..7e27d284
--- /dev/null
+++ b/fuzz/read_pem_corpus/7b8e2a5dfa03cc13b70eb5f77d61222c108ab6bd
Binary files differ
diff --git a/fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232fe b/fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232fe
new file mode 100644
index 00000000..7a8b3f88
--- /dev/null
+++ b/fuzz/read_pem_corpus/824b6dd27deb9ed157fdc80485f104268f7232fe
Binary files differ
diff --git a/fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c b/fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c
new file mode 100644
index 00000000..a92ec4f4
--- /dev/null
+++ b/fuzz/read_pem_corpus/825edbf21bc40ec23225772635ea6390e6d9fb4c
@@ -0,0 +1,3 @@
+-----BEGIN --+---'---+------/
+
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5db b/fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5db
new file mode 100644
index 00000000..a0629275
--- /dev/null
+++ b/fuzz/read_pem_corpus/8347c4366b5d668b467fb589c3090f201eacb5db
Binary files differ
diff --git a/fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b b/fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b
new file mode 100644
index 00000000..a11db388
--- /dev/null
+++ b/fuzz/read_pem_corpus/874ed5d633d245b10fdda52c49627b43b3f2e25b
@@ -0,0 +1,14 @@
+-----BEGIN :T!(!*!*z:'*:Ͱ:!m*O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*-------END :)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('1)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(';)MG'yO )o(*(*-----
+-----END O*;;)''D;:f(;w:;;*H--- \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f37 b/fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f37
new file mode 100644
index 00000000..66f9ba82
--- /dev/null
+++ b/fuzz/read_pem_corpus/88581ebac8ffbea71bb83f704e14d789dbc33f37
@@ -0,0 +1,17 @@
+-----BEGIN O-----
+----(END /!----6(
+ 7;!(;)-----END /O!:---
+---BEGIN O-----
+----(END /!---'U('(:(!/;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!-
+:(';'(;)-
+(!:):"PZg:; :'::0!))v*Ǿ:--BEGIN 6;!(;)--
+----END /!-----
+-
+kqU;!:O'U|:؎8*:;s(f!;;)--*----
+----BEGIN O-----
+----(END /!-----BEGIN 6
+j-
+;!(;)--
+----EN-
+6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad b/fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad
new file mode 100644
index 00000000..fa326656
--- /dev/null
+++ b/fuzz/read_pem_corpus/892155ce92d4c3293f48e6fc2097336ba882a0ad
@@ -0,0 +1,8 @@
+-:($X:
+m---BEGIN )a':':!;'R):u ;:rM'**;)=*;:)O(h!;:;'*0'!:;:((:;*()'(!E(:*t;;::;:!:(''`'O:!*:(&((')V`;'m\:!(@!(*:']A *:a!*)((;!2'):::)**g*!r;S()(;(*(;)*:(;c(!)!':)a':':!;'R):u ;:rM'**;)=*;::5;*j(';*(X) -x
+-----BEGIN )'*;'))!':-----
+ 8x
+x
+ =
+-----END )'*;'))!':-----
+---BEGIN )a':':!;'R):u ;:rM'**;)=*;:)O(h!;:;'*0'!:ˏ(:;:;(*()'(!E(:*t;;::;:!:(''`'O:!*:(&((')V`;'m\:!(@!(*:']A *:a!*)((;!0'):*::)*g*!r;S()( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d3491 b/fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d3491
new file mode 100644
index 00000000..3c9e422e
--- /dev/null
+++ b/fuzz/read_pem_corpus/894e092b7fd9f4e0a5911ca106e097d3833d3491
@@ -0,0 +1,3 @@
+Nh'):!X;*:):;!)l;'O2)+'*:):($X:
+-----BEGIN !*!((4!ΰ)ϫ((D:(!(W;:w:*S;((':*:((`:(6 !; *(:'3@;2!(J`!:(() )'9:(B)J m!Y(!;)T!);*P)Nh'):!X;*:):;!)l;'O2Nh'):!X;*:)k*!*D'a[!ʬ*#'&:;!)l;)+*;Nh''*:):($X:
+-----BEGIN !*!'O2)+'*:) \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f b/fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f
new file mode 100644
index 00000000..1322c288
--- /dev/null
+++ b/fuzz/read_pem_corpus/8c07d6299f33fee89ab0c82e92e06cd558ade60f
@@ -0,0 +1,14 @@
+-----BEGIN :T!(!*!*z:'*:Ͱ:!m*O*;:)
+O*;:)
+ :(/!;!;7();':['H 'G)MG'yO )o(*(*-------END :)
+-----BEGINO*;:)
+
+
+ :(/!;!;O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('1)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-7();';['H('G/!;!;6();':(;)MG'yO )o(*(*-----
+-----END O*;;)''D;:f(;w:; \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e b/fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e
new file mode 100644
index 00000000..715ec1cc
--- /dev/null
+++ b/fuzz/read_pem_corpus/8e07fb01e0cfa23caddb6b0280c03d0ae2bac57e
Binary files differ
diff --git a/fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e785 b/fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e785
new file mode 100644
index 00000000..e5afad41
--- /dev/null
+++ b/fuzz/read_pem_corpus/92207925db84106af0167e887696d936aa41e785
@@ -0,0 +1,5 @@
+-----BEGIN O-----
+----(END /!-----BEGI 6;!(;)-----END /!---
+
+
+6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1 b/fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1
new file mode 100644
index 00000000..66aec936
--- /dev/null
+++ b/fuzz/read_pem_corpus/94514c5c092afe2f8295dc193d506f16c6ea82c1
Binary files differ
diff --git a/fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33f b/fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33f
new file mode 100644
index 00000000..eb4f5951
--- /dev/null
+++ b/fuzz/read_pem_corpus/956c8cf1db9220ac8004eb9a75e3ebc1df33a33f
Binary files differ
diff --git a/fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6 b/fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6
new file mode 100644
index 00000000..eabac816
--- /dev/null
+++ b/fuzz/read_pem_corpus/97c5565f723c0e49787fdec9ed15354760fcb1e6
Binary files differ
diff --git a/fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f3 b/fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f3
new file mode 100644
index 00000000..033a2723
--- /dev/null
+++ b/fuzz/read_pem_corpus/9832fea1fe1c8b575790f59f98404fb61672a3f3
@@ -0,0 +1,5 @@
+-----BEGIN O-----
+----(END /!-----BE-----END GI 6;!(;)-----END /!---
+
+-
+6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae711 b/fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae711
new file mode 100644
index 00000000..009adb9f
--- /dev/null
+++ b/fuzz/read_pem_corpus/9940bd2f440a8c1e07dba6476c219349afeae711
@@ -0,0 +1,12 @@
+-----BEGIN O-----
+----(END /!-----BEGI 7;!(;)-----END /O!:---
+---BEGIN O-----
+----(END /!---'U('(:(!/;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!::(';'(;)(!:):"PZg;:; :'::7!))vǾ:--BEGIN 6;!(;)--
+----END /!-----
+-
+kqU;O!:'U|:؎8*:;s(f!;;)--*----
+----BEGIN O-----
+----(END /!-----BEGIN 6
+j-
+;!(;)-----END 6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5 b/fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5
new file mode 100644
index 00000000..44917bba
--- /dev/null
+++ b/fuzz/read_pem_corpus/9d1e6ed2fc4b095a2ccb4e695241c91d4b194be5
Binary files differ
diff --git a/fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158af b/fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158af
new file mode 100644
index 00000000..e0e223d0
--- /dev/null
+++ b/fuzz/read_pem_corpus/a2bc14d4be3bb4f4deb93ddaa77224db305158af
Binary files differ
diff --git a/fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca b/fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca
new file mode 100644
index 00000000..d10f2f60
--- /dev/null
+++ b/fuzz/read_pem_corpus/a75abe0b4dd03dc232f9192666d6adb369beffca
@@ -0,0 +1,5 @@
+-----vBEGIN --+---'---+------/
+
+-----BEGIN --+---'---+-------
+
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46 b/fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46
new file mode 100644
index 00000000..23a50387
--- /dev/null
+++ b/fuzz/read_pem_corpus/a92c58dfadb8195fbd90c70b4dc576986dbb7c46
Binary files differ
diff --git a/fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c b/fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c
new file mode 100644
index 00000000..d84db471
--- /dev/null
+++ b/fuzz/read_pem_corpus/aa82ef4cf1c3c2d7dd7811803227cc87d2429b3c
Binary files differ
diff --git a/fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad b/fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad
new file mode 100644
index 00000000..99dd9ff6
--- /dev/null
+++ b/fuzz/read_pem_corpus/ad49ff8fb9ff95a8f110b15702f8209df64f8fad
@@ -0,0 +1,14 @@
+-----BEGIN O-----
+----(END /!-----BEGI 7;!(;)-----END /O!:---
+-----END O-=---
+----(END /!---'U('(:(!/;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!-
+:(';'(;)-
+(!:):"PZg;:; :'::7!))v*Ǿ:--BEGIN 6;!(;)--
+----END /!-----
+-
+kqU;!:O'U|:؎9*:;s(f!;;)------
+----BEGIN O-----
+----(END /!-----BEGIN 6
+j-
+;!(;)-----END 6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b b/fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b
new file mode 100644
index 00000000..45332baf
--- /dev/null
+++ b/fuzz/read_pem_corpus/af9207c320f7400ba18dea62fd4af98330ba260b
@@ -0,0 +1,3 @@
+-----BEGIN x:*****f(~'!5 ) );'*E-----B-----
+-----END f(~'!5 ) C;'*E;:;h0G;G('!*l*)!:!:;'4C*ֈ3:)((#(':(''u*!!x
+;!;) \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009ce b/fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009ce
new file mode 100644
index 00000000..eb258897
--- /dev/null
+++ b/fuzz/read_pem_corpus/b034864020154378b78a11122c8f61f81e8009ce
Binary files differ
diff --git a/fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b9 b/fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b9
new file mode 100644
index 00000000..b66e0af3
--- /dev/null
+++ b/fuzz/read_pem_corpus/b178eadb35af688d045ba6bc400396ae0fc7c9b9
@@ -0,0 +1,6 @@
+-----BEGIN O!:'U('((/!;!;O!:'U('((/!;!;3();':('H('G)MG'yO )O(*-----
+-----BEGIN :(*:!:O!O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*-----
+*:!------
+----BEIN *;:)
+N O!:'U('((!;!;6();':('H(%G)MG'yO :)o(*(*;:):'U('O!:'U(*:!::(';'(;'(:(/)(!;!;(:(/!;!;6();-6();O!-: \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c3990385 b/fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c3990385
new file mode 100644
index 00000000..6c2f8068
--- /dev/null
+++ b/fuzz/read_pem_corpus/b709f3412c5fb9a0b38a69eee59620a5c3990385
@@ -0,0 +1,8 @@
+-:($X:
+----BEGIN )a':':!;'R):u ;:rM'**;)=*;:)O(h!;:;'*0'!:;:((:;*()'(!E(:*t;;::;:!:(''`'O:!*:(&((')V`;'m\:!(@!(*:']A *:a!*)((;!2'):::)**g*!r;S()(;(*(;)*:(;c(!)!':)a':':!;'R):u ;:rM'**;)=*;::5;*j(';*(X) -x
+-----BEGIN )'*;'))!':-----
+ x
+x
+ x
+-----END )'*;'))!':-----
+---BEGIN )a':':!;'R):u ;:rM'**;)=*;:)O(h!;:;'*0'!:ˏ(:;(:;*()'(!E(:*t;;::;:!:(''`'O:!*:(&((')V`;'m\:!(@!(*:']A *:a!*)((;!0'):*::)*g*!r;S()( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa513 b/fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa513
new file mode 100644
index 00000000..5393ba08
--- /dev/null
+++ b/fuzz/read_pem_corpus/b92f0f72b6839f6c7ac10f4c663765b89e1fa513
@@ -0,0 +1,2 @@
+-----BEGIN O-----
+'U('(:(/!-----BEGIN 6;!(;)'U('(:(/!;!;;':(6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5c b/fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5c
new file mode 100644
index 00000000..0fa1d3d7
--- /dev/null
+++ b/fuzz/read_pem_corpus/bc205ed015bb01de66b5a6b5a631d167c8077a5c
Binary files differ
diff --git a/fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b9 b/fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b9
new file mode 100644
index 00000000..4471d0e6
--- /dev/null
+++ b/fuzz/read_pem_corpus/c0348b5dd7aaf73888372a5a6abef82bd0df97b9
@@ -0,0 +1,18 @@
+-----BEGIN O-----
+----(END /!--
+---6(
+ 7;!(;)-----END /O!:---
+---BEGIN O-----
+----(END /!---'U('(:(!/;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!-
+:(';'(;)-
+(!:):"PZg:; :'::0!))v*Ǿ:--BEGIN 6;!(;)--
+----END /!-----
+-
+kqU;!:O'U|:؎8*:;s(f!;;)--*----
+----BEGIN O-----
+----(END /!-----BEGIN 6
+j-
+;!(;)--
+----EN-
+6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf0 b/fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf0
new file mode 100644
index 00000000..15883583
--- /dev/null
+++ b/fuzz/read_pem_corpus/c0596e573f43d2bd5a5d038bf4bd7d073141ddf0
@@ -0,0 +1,16 @@
+------
+-----
+----BEGIN 6(
+
+----N!(ED /-----BEGI 6;!(;)--'-8-END -
+---BEGIN O-----
+----(END--=--END -----BEGIN O-----
+----(END /!-----BEGIN 6;!(;)-----END //!-----!;BE-----END GI 5;!(;)-----END /!---
+
+-
+6/!--!-----
+6(-
+
+-
+6((-
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b71205 b/fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b71205
new file mode 100644
index 00000000..887d05d1
--- /dev/null
+++ b/fuzz/read_pem_corpus/c45f49452fcdf531f2bcfd100645c535e5b71205
@@ -0,0 +1 @@
+O \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf347929 b/fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf347929
new file mode 100644
index 00000000..e5a9f051
--- /dev/null
+++ b/fuzz/read_pem_corpus/c504659b0454be5eef0594da6a952f8daf347929
@@ -0,0 +1 @@
+-----B-EGIN f( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1 b/fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1
new file mode 100644
index 00000000..4b26afa7
--- /dev/null
+++ b/fuzz/read_pem_corpus/c7e4b7f4c3bbc7c6ed4e3366d1d4c16ed44952f1
Binary files differ
diff --git a/fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26a b/fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26a
new file mode 100644
index 00000000..b30a845e
--- /dev/null
+++ b/fuzz/read_pem_corpus/caf489bb8f6f48e35b95032b2824ca0ffc77d26a
Binary files differ
diff --git a/fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e1 b/fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e1
new file mode 100644
index 00000000..fe47159b
--- /dev/null
+++ b/fuzz/read_pem_corpus/cc8ceeebb230ca237479e0c3dacafbb5524222e1
@@ -0,0 +1,20 @@
+-6(
+
+-----
+----BEGI) 6(
+
+----N!(ED /-----BEGI 6;!(;)--'-8-END -
+---BEGIN O-----
+----(END--=--END -----BEGIN O-----
+----(END /!---GB-E-IN 3;!(;)-----END //!-----!;BE-----END GI 5;!(;)-----END ----------BEGIN O---------BEGIN O-----
+----
+'U('(:(
+/!---
+
+-
+7/!--!-----
+6/!---O!:'U('(-
+
+(:(/!;!;6();':(-
+6((-
+'H'G)MG'yO )o(*(*;:)*;!::(';'(; )(!:):"PZw;:P; :'::7!))vǾ:kqU;|:8*a;s(f! \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e0 b/fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e0
new file mode 100644
index 00000000..b7c794be
--- /dev/null
+++ b/fuzz/read_pem_corpus/cf1b3d1ed204deed6c62f41d0e706ee47bc802e0
@@ -0,0 +1,7 @@
+O*;:)
+-----BEGIN :(/!;!;6();':['H('G)MG'yO )o(*(*-----
+O*;:)
+
+----BEGIN O!:'U('((/!;!;6();'8('H('G)MG'O!*;:)
+:(-/!;!;6();':('H('G)MG'yO-----BEGIN----::(O*;:)
+;(j-/!;!;6();':('; \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c b/fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c
new file mode 100644
index 00000000..f9941660
--- /dev/null
+++ b/fuzz/read_pem_corpus/cfc3b1348ca73b8c02d9aed715d1e0681326888c
@@ -0,0 +1 @@
+O!:'U('((/!;!;6();'8('H('G)MG'yO )o(*(*;O!:'U('((/!;!;6();'8('H('G)MG'yO )o:)O!:'U(*:!::(';'(;'(:(/))(-----BEGIN (/!;!;6();':('!;!;H('G)MG'yO*o( )(*;:()**(*;:)O!:'U(*:!::(';'(;'(:(:!::(';'/))(-----BEGIN (/!;!;6();':('!;!;H('G)MG(6;)(!:):'yO*o( )(*;:)*:!::(';'(6;)(!:):"PZw;:P; :'::7!))vǾ:kqU;|:؎8"PZw;:P; :'*:;s(f!;;)j:*:::7!))vǾ:kqU;|:؎8*:;s(f!; \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89 b/fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89
new file mode 100644
index 00000000..cc15e7f4
--- /dev/null
+++ b/fuzz/read_pem_corpus/d4f0a19ece82b78c82c81eae5b49dc662c6f4a89
Binary files differ
diff --git a/fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5 b/fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5
new file mode 100644
index 00000000..cae86a1d
--- /dev/null
+++ b/fuzz/read_pem_corpus/d959c647c6a5ea641fec147b0de36187a9d2f8c5
Binary files differ
diff --git a/fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214d b/fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214d
new file mode 100644
index 00000000..10df3f62
--- /dev/null
+++ b/fuzz/read_pem_corpus/de2fb44503aca3f82d5466a9489c0735324b214d
Binary files differ
diff --git a/fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a421 b/fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a421
new file mode 100644
index 00000000..f5951adb
--- /dev/null
+++ b/fuzz/read_pem_corpus/df9fe7d51a89ee267034a2834025f71505d4a421
@@ -0,0 +1,7 @@
+-----BEGIN )a':':!;'R):u ;:rM-----
+--*
+(!a!*)(-)--BEGIN N )a':':--*
+*
+(!a!*)(-)--BEGIN N )!;'*
+---BEGIN )a':':!;'R):u::rR)M')a':':!a':':--!;'*
+---BEGIN )a':':!;'R):u::rR)M')a':':!;'R):u ;;'R):u:rM' *;:rM'* \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e b/fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e
new file mode 100644
index 00000000..2afaa7ce
--- /dev/null
+++ b/fuzz/read_pem_corpus/e1a6c4096b145ced5362ede6ffedbc49d16ba57e
@@ -0,0 +1,4 @@
+-----BEGIN O-----
+----(END /!-----BEGIN 6;!(;)-----END /!-----
+-
+6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695 b/fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695
new file mode 100644
index 00000000..f45de5f6
--- /dev/null
+++ b/fuzz/read_pem_corpus/e207960b1761ba95e7544b9d924459c56e2c4695
Binary files differ
diff --git a/fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce743 b/fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce743
new file mode 100644
index 00000000..4e5586e5
--- /dev/null
+++ b/fuzz/read_pem_corpus/e3344ef8d734471ef90b16c719cb0f11af2ce743
@@ -0,0 +1,3 @@
+-----BEGIN )a':':!;'R):u ;:rM-----
+--*
+(!a!*)(-)--BEGIN N )--a \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c b/fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c
new file mode 100644
index 00000000..349cbf19
--- /dev/null
+++ b/fuzz/read_pem_corpus/e45a6df435a1cecae6547f6dcde626a7e706434c
@@ -0,0 +1,8 @@
+-:($X:
+----BEGIN )a':':!;'R):u ;:rM'**;)=*;:)O(h!;:;'*0'!:;:((:;*()'(!E(:*t;;::;:!:(''`'O:!*:(&((')V`;'m\:!(@!(*:']A *:a!*)((;!2'):::)**g*!r;S()(;(*(;)*:(;c(!)!':)a':':!;'R):u ;:rM'**;)=*;::5;*j(';*(X) -x
+-----BEGIN )'*;'))!':-----
+ 8x
+x
+ x
+-----END )'*;'))!':-----
+---BEGIN )a':':!;'R):u ;:rM'**;)=*;:)O(h!;:;'*0'!:ˏ(:;(:;*()'(!E(:*t;;::;:!:(''`'O:!*:(&((')V`;'m\:!(@!(*:']A *:a!*)((;!0'):*::)*g*!r;S()( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678f b/fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678f
new file mode 100644
index 00000000..78850833
--- /dev/null
+++ b/fuzz/read_pem_corpus/e7ef91e03a3aa8bd53b2466a2207a5028185678f
Binary files differ
diff --git a/fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2c b/fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2c
new file mode 100644
index 00000000..dc16e558
--- /dev/null
+++ b/fuzz/read_pem_corpus/ebcae74985ccc7905a3800c0db2723392cfd2f2c
Binary files differ
diff --git a/fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb b/fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb
new file mode 100644
index 00000000..0a71a8ea
--- /dev/null
+++ b/fuzz/read_pem_corpus/ed31baee70d3b705762e808e494b4debf604c5fb
@@ -0,0 +1,31 @@
+-----BEGIN O-----
+----(END /!----G
+(
+ 7--
+--BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN :4'-----
+G
+UU--
+--BEGIN :4'-----
+G
+UU -----BEGIN 24'/----
+-----BEGIN :4'-----
+G
+UU QG
+wFUG
+ fbwFUU QG
+wFU QG
+wFUG
+ fbwFUU QG
+wFU fbwFUUU G
+bwFU f
+bwFU U fbwFUU f
+bwFU U fbU fbwF fUG
+ fbwFU f fTwFTU fbwFUfbwFUU f
+bwFU U fbwFUU;!(;)-----EN /O!:---
+---BE- NI-GO---
+---*
+ f
+bwFU U fbU fbw-----BEG-F fU \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb b/fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb
new file mode 100644
index 00000000..cc7aeba8
--- /dev/null
+++ b/fuzz/read_pem_corpus/ee06965764fdf6769657e744a61efe7d60d085fb
@@ -0,0 +1 @@
+O! \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f8 b/fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f8
new file mode 100644
index 00000000..e530a127
--- /dev/null
+++ b/fuzz/read_pem_corpus/f123c08d0a46b72fa8989296e82e7aa25ebf16f8
@@ -0,0 +1,7 @@
+-----BEGIN --+---'-----vBEGIN --+---'---+------/
+
+-----+---------BEGIN --+---'----
+
++-------
+
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6aca b/fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6aca
new file mode 100644
index 00000000..fe29dff6
--- /dev/null
+++ b/fuzz/read_pem_corpus/f18ebc593b87baa03b5e003b7540577001ba6aca
Binary files differ
diff --git a/fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd5 b/fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd5
new file mode 100644
index 00000000..628e2676
--- /dev/null
+++ b/fuzz/read_pem_corpus/f1903c6e205ba7b902e53b07e08890ec8179cbd5
@@ -0,0 +1 @@
+'*:'*:-'----BEGIN*:'*: \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e b/fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e
new file mode 100644
index 00000000..47ebb5b4
--- /dev/null
+++ b/fuzz/read_pem_corpus/f3f2959361766dbfafbb2f99a4f60c920001386e
@@ -0,0 +1,6 @@
+------
+----BEGIN O---------
+----BEGIN O-----
+----(END /!-----BEGIN 6;!(;)-------
+--END --(END /!-----BEGIN 6;!(;)--/!-----
+-- \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d058 b/fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d058
new file mode 100644
index 00000000..ce9b7f8e
--- /dev/null
+++ b/fuzz/read_pem_corpus/f72115838630c70a067e89b98615357fcf19d058
@@ -0,0 +1,45 @@
+-----BEGIN O-----
+-(
+-(END /!----G
+(
+ (--
+(
+BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN :4'-----
+G
+UU--
+--BEGIN :4'G
+-----
+G
+UU -----BEGIN 24'/----
+-----BEGIN :4'-----
+G
+UU-----BEGIN O-----
+-(
+-(END /!----G
+(
+ (--
+(
+BEGIN :4'-----
+G
+UU -----BEGIN :4'/----
+-----BEIN QG
+wF:4'-----
+G
+UU--
+--BEGIN :4'G
+-----
+G
+UU -----BEGIN 24'/----
+-----BEGIN :4'-----
+G
+UU QG
+wFUG
+ fbwFUU QG
+wFU UQG
+wFUG
+ fbwFUU QG
+wFU fG
+ b \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fc b/fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fc
new file mode 100644
index 00000000..7643d8eb
--- /dev/null
+++ b/fuzz/read_pem_corpus/f9f61f03681250b015a00df3010b89d2d776d8fc
Binary files differ
diff --git a/fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e b/fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e
new file mode 100644
index 00000000..a6b2ddb6
--- /dev/null
+++ b/fuzz/read_pem_corpus/fad7e4071afc1e4f441e2cb65cf9b0da37dcd74e
@@ -0,0 +1,2 @@
+'---+-----
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5 b/fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5
new file mode 100644
index 00000000..56195cbd
--- /dev/null
+++ b/fuzz/read_pem_corpus/fb36b0ce1600b9399d552eab916600c239be5ad5
Binary files differ
diff --git a/fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f b/fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f
new file mode 100644
index 00000000..00294ef9
--- /dev/null
+++ b/fuzz/read_pem_corpus/fb64fef6ea2f835804b69ae3d21fb2cac7e4973f
@@ -0,0 +1,9 @@
+-----BEGIN O-----
+----(END /!-----BEGI 7;!(;)-----END /O!:-----BEGIN O-----
+----(END /!---'U('(:(/!;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!::(';'(;)(!:):"PZg;:P; :'::7!))vǾ:--BEGIN 6;!(;)-----END /!-----
+-
+kqU;O!:'U|:؎8*:;s(f!;;)------
+----BEGIN O-----
+----(END /!-----BEGIN 6-
+j*:;!(;)-----END 6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f b/fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f
new file mode 100644
index 00000000..cc3cbef2
--- /dev/null
+++ b/fuzz/read_pem_corpus/fb6d4702bcb98df173527a5f08d5ac829adb2f9f
@@ -0,0 +1,15 @@
+-----BEGIN O-----
+----(END /!----6(
+ 7;!(;)-----END /O!:---
+---BEGIN O-----
+----(END /!---'U('(:(!/;!;6();':('H('G)MG'yO-
+ )o(*(*;:)*:!-
+:(';'(;)-
+(!:):"PZg;:; :'::7!))v*Ǿ:--BEGIN 6;!(;)--
+----END /!-----
+-
+kqU;!:O'U|:؎8*:;s(f!;;)--*----
+----BEGIN O-----
+----(END /!-----BEGIN 6
+j-
+;!(;)-----END 6( \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf b/fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf
new file mode 100644
index 00000000..06f32836
--- /dev/null
+++ b/fuzz/read_pem_corpus/fd1cc706033976b86a93d2b0c74b15bb2f31fccf
@@ -0,0 +1,18 @@
+-6(
+
+-----
+----BEGIN 6(
+
+----N!(ED /-----BEGI 6;!(;)--'-8-END -
+---BEGIN O-----
+----(END--=--END -----BEGIN O-----
+----(END /!-----BEGIN 7;!(;)-----END //!-----!;BE-----END GI 5;!(;)-----END -----
+/!---
+
+-
+7/!--!-----
+6(-
+
+-
+6((-
+ \ No newline at end of file
diff --git a/fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded b/fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded
new file mode 100644
index 00000000..88fd2b03
--- /dev/null
+++ b/fuzz/read_pem_corpus/ff7dcdb0fc13ddea6e82cac7bf3a0414cb772ded
Binary files differ
diff --git a/fuzz/server.cc b/fuzz/server.cc
index f4f999a9..75522bac 100644
--- a/fuzz/server.cc
+++ b/fuzz/server.cc
@@ -1,5 +1,20 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
#include <assert.h>
+#include <openssl/rand.h>
#include <openssl/ssl.h>
static const uint8_t kCertificateDER[] = {
@@ -204,7 +219,8 @@ struct GlobalState {
static GlobalState g_state;
extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
- // This only fuzzes the initial flow from the client so far.
+ RAND_reset_for_fuzzing();
+
SSL *server = SSL_new(g_state.ctx);
BIO *in = BIO_new(BIO_s_mem());
BIO *out = BIO_new(BIO_s_mem());
@@ -212,7 +228,15 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
SSL_set_accept_state(server);
BIO_write(in, buf, len);
- SSL_do_handshake(server);
+ if (SSL_do_handshake(server) == 1) {
+ // Keep reading application data until error or EOF.
+ uint8_t tmp[1024];
+ for (;;) {
+ if (SSL_read(server, tmp, sizeof(tmp)) <= 0) {
+ break;
+ }
+ }
+ }
SSL_free(server);
return 0;
diff --git a/fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49c b/fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49c
new file mode 100644
index 00000000..1a881d4b
--- /dev/null
+++ b/fuzz/server_corpus/009baa11e6cfa1713bc175dbf069d3bdf0c5b49c
Binary files differ
diff --git a/fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9ab b/fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9ab
new file mode 100644
index 00000000..34c02a03
--- /dev/null
+++ b/fuzz/server_corpus/02601bb35ae3de52d87fc0b48188195b7c07e9ab
Binary files differ
diff --git a/fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2b b/fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2b
new file mode 100644
index 00000000..fc4c5056
--- /dev/null
+++ b/fuzz/server_corpus/0293d811efcdbb311aa55d23fa9fe9566a64bd2b
Binary files differ
diff --git a/fuzz/server_corpus/0319960c7e36d77b16ed5e8ca21c9661020837a2 b/fuzz/server_corpus/0319960c7e36d77b16ed5e8ca21c9661020837a2
deleted file mode 100644
index b15cd43e..00000000
--- a/fuzz/server_corpus/0319960c7e36d77b16ed5e8ca21c9661020837a2
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9 b/fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9
new file mode 100644
index 00000000..a05a6e5b
--- /dev/null
+++ b/fuzz/server_corpus/0339d4398642097dd08378d2de67f45825d623b9
Binary files differ
diff --git a/fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480 b/fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480
new file mode 100644
index 00000000..2851119a
--- /dev/null
+++ b/fuzz/server_corpus/0356ffe0a247cb950a3c2fc4b125c2ec1d19e480
Binary files differ
diff --git a/fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27 b/fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27
new file mode 100644
index 00000000..56c728bb
--- /dev/null
+++ b/fuzz/server_corpus/03c9f2cc53c803b0cfa115e252ed40f2546cde27
Binary files differ
diff --git a/fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d b/fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d
new file mode 100644
index 00000000..1ef5ad73
--- /dev/null
+++ b/fuzz/server_corpus/0475246ec9d1587d2e0a6bf08ea99bfa2e37f78d
Binary files differ
diff --git a/fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719c b/fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719c
new file mode 100644
index 00000000..772f7cb0
--- /dev/null
+++ b/fuzz/server_corpus/04a3dd601cad12e190ceeddb450e6314c602719c
Binary files differ
diff --git a/fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400e b/fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400e
new file mode 100644
index 00000000..42150a6a
--- /dev/null
+++ b/fuzz/server_corpus/05f1de3d83b0d836b0e504f127f6e7445e61400e
Binary files differ
diff --git a/fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8fe b/fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8fe
new file mode 100644
index 00000000..e8baa399
--- /dev/null
+++ b/fuzz/server_corpus/06c1bbafe734f1bce369c330411e508dda42f8fe
Binary files differ
diff --git a/fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6 b/fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6
new file mode 100644
index 00000000..a24811b4
--- /dev/null
+++ b/fuzz/server_corpus/06f786810efbda4369f4d6ae5613eec10c64b2a6
Binary files differ
diff --git a/fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44 b/fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44
new file mode 100644
index 00000000..b4d0f61c
--- /dev/null
+++ b/fuzz/server_corpus/078734f3f4e18e155dd4252624103b2d890f1e44
Binary files differ
diff --git a/fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baa b/fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baa
new file mode 100644
index 00000000..db157b48
--- /dev/null
+++ b/fuzz/server_corpus/086d77d2f6efbdf4be783a888a44611cf9b14baa
Binary files differ
diff --git a/fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efe b/fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efe
new file mode 100644
index 00000000..ac80ae43
--- /dev/null
+++ b/fuzz/server_corpus/08bff079591413942c31a9d927f12d39bb9e4efe
Binary files differ
diff --git a/fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578f b/fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578f
new file mode 100644
index 00000000..96324aa7
--- /dev/null
+++ b/fuzz/server_corpus/0a331b0b018d33b9eb78982b333415dfc24b578f
Binary files differ
diff --git a/fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87ad b/fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87ad
new file mode 100644
index 00000000..76eb151b
--- /dev/null
+++ b/fuzz/server_corpus/0ad3635fc2fb35c1250f4abddbc4bf40553f87ad
Binary files differ
diff --git a/fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785f b/fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785f
new file mode 100644
index 00000000..f816d1f6
--- /dev/null
+++ b/fuzz/server_corpus/0b313e12e6182402ed9e6c968cfc82f305db785f
Binary files differ
diff --git a/fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c b/fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c
new file mode 100644
index 00000000..a57a49da
--- /dev/null
+++ b/fuzz/server_corpus/0b9ceba9ca962d9e6aa94dffa9fce3004a587c4c
Binary files differ
diff --git a/fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cf b/fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cf
new file mode 100644
index 00000000..417188c7
--- /dev/null
+++ b/fuzz/server_corpus/0c3dce9c0c0498f100445c9bfe487aefa63d16cf
Binary files differ
diff --git a/fuzz/server_corpus/0c64a61be4a1b249f51c495042b62b6693589e2a b/fuzz/server_corpus/0c64a61be4a1b249f51c495042b62b6693589e2a
deleted file mode 100644
index 0d592f71..00000000
--- a/fuzz/server_corpus/0c64a61be4a1b249f51c495042b62b6693589e2a
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/0cc23c401fcdf25c2e4dc4bbe343039b1689998b b/fuzz/server_corpus/0cc23c401fcdf25c2e4dc4bbe343039b1689998b
deleted file mode 100644
index 0d27caaa..00000000
--- a/fuzz/server_corpus/0cc23c401fcdf25c2e4dc4bbe343039b1689998b
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822 b/fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822
new file mode 100644
index 00000000..3ce76341
--- /dev/null
+++ b/fuzz/server_corpus/0cecf043638810fa52a2491cfbcd348613753822
Binary files differ
diff --git a/fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93a b/fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93a
new file mode 100644
index 00000000..237169f6
--- /dev/null
+++ b/fuzz/server_corpus/0d05d41086700c7ebba2cc83461cfacd83a4c93a
Binary files differ
diff --git a/fuzz/server_corpus/0d1120af6afd2b1cab54482c2b8cccd4db904fe9 b/fuzz/server_corpus/0d1120af6afd2b1cab54482c2b8cccd4db904fe9
deleted file mode 100644
index b6020da6..00000000
--- a/fuzz/server_corpus/0d1120af6afd2b1cab54482c2b8cccd4db904fe9
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/0dbf6ef7bd2d0ffae28bff580783d478c82ec5ad b/fuzz/server_corpus/0dbf6ef7bd2d0ffae28bff580783d478c82ec5ad
deleted file mode 100644
index 66f4bf42..00000000
--- a/fuzz/server_corpus/0dbf6ef7bd2d0ffae28bff580783d478c82ec5ad
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8 b/fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8
new file mode 100644
index 00000000..4a7e4e67
--- /dev/null
+++ b/fuzz/server_corpus/0ecf26dbd7d24b25a474acc633d53f524ba118a8
Binary files differ
diff --git a/fuzz/server_corpus/0faa1b0050add2d921b24a9f50181d605cf6f2ee b/fuzz/server_corpus/0faa1b0050add2d921b24a9f50181d605cf6f2ee
deleted file mode 100644
index 2f00f866..00000000
--- a/fuzz/server_corpus/0faa1b0050add2d921b24a9f50181d605cf6f2ee
+++ /dev/null
@@ -1 +0,0 @@
-:(:q* \ No newline at end of file
diff --git a/fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16 b/fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16
new file mode 100644
index 00000000..a8f2e1ef
--- /dev/null
+++ b/fuzz/server_corpus/10aab907c39d9f80fe8e8641e1931ee2ad270e16
Binary files differ
diff --git a/fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906 b/fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906
new file mode 100644
index 00000000..764778bd
--- /dev/null
+++ b/fuzz/server_corpus/136480311a2064a853c568d8d41b0d9c62b3d906
Binary files differ
diff --git a/fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1 b/fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1
new file mode 100644
index 00000000..c90b5a06
--- /dev/null
+++ b/fuzz/server_corpus/1378a7c740e1608a0075be8dc362445b691eaca1
Binary files differ
diff --git a/fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546 b/fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546
new file mode 100644
index 00000000..2b5a6467
--- /dev/null
+++ b/fuzz/server_corpus/13ef34ae06ef674c04808db2c0a8adb1de856546
Binary files differ
diff --git a/fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489 b/fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489
new file mode 100644
index 00000000..95ff827f
--- /dev/null
+++ b/fuzz/server_corpus/14ce51872fcd9e415b14936b6692472f445f4489
Binary files differ
diff --git a/fuzz/server_corpus/152e065473369bd8a6a060d8641db52699a0dec4 b/fuzz/server_corpus/152e065473369bd8a6a060d8641db52699a0dec4
deleted file mode 100644
index 0882b56d..00000000
--- a/fuzz/server_corpus/152e065473369bd8a6a060d8641db52699a0dec4
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/155dbc7d80f78358598985efc616ee1c9a95b732 b/fuzz/server_corpus/155dbc7d80f78358598985efc616ee1c9a95b732
deleted file mode 100644
index 4a68b104..00000000
--- a/fuzz/server_corpus/155dbc7d80f78358598985efc616ee1c9a95b732
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdac b/fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdac
new file mode 100644
index 00000000..f8d6ce72
--- /dev/null
+++ b/fuzz/server_corpus/1628ba4f9bbb8c96aecc47305f93e028040bbdac
Binary files differ
diff --git a/fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4 b/fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4
new file mode 100644
index 00000000..82ccfb62
--- /dev/null
+++ b/fuzz/server_corpus/167171e86e3539873f2f6d19146c797774a6bcb4
Binary files differ
diff --git a/fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659 b/fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659
new file mode 100644
index 00000000..81f37cba
--- /dev/null
+++ b/fuzz/server_corpus/169029c8da9497dd15c0f8ae2f2ce585568e0659
Binary files differ
diff --git a/fuzz/server_corpus/16baa1a9d032ff13f4c97dbde84fd9771756c20e b/fuzz/server_corpus/16baa1a9d032ff13f4c97dbde84fd9771756c20e
deleted file mode 100644
index 6ad6da01..00000000
--- a/fuzz/server_corpus/16baa1a9d032ff13f4c97dbde84fd9771756c20e
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506 b/fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506
new file mode 100644
index 00000000..84fd5622
--- /dev/null
+++ b/fuzz/server_corpus/1754c50fb526624f67c4c286a29b47da5caea506
Binary files differ
diff --git a/fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39c b/fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39c
new file mode 100644
index 00000000..69f0a264
--- /dev/null
+++ b/fuzz/server_corpus/1776797c43f6caab7f17dcd0ba1ea74e7a94b39c
Binary files differ
diff --git a/fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffd b/fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffd
new file mode 100644
index 00000000..716e36a0
--- /dev/null
+++ b/fuzz/server_corpus/19a2a537172038059839e797eaf487cc317e9ffd
Binary files differ
diff --git a/fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97 b/fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97
new file mode 100644
index 00000000..12d0b42d
--- /dev/null
+++ b/fuzz/server_corpus/1b163f7dc072468d689581829dcb93b9560e4e97
Binary files differ
diff --git a/fuzz/server_corpus/1d676a51656b8d4ef24a461e29c9fed2807f7e50 b/fuzz/server_corpus/1d676a51656b8d4ef24a461e29c9fed2807f7e50
deleted file mode 100644
index d70b6afa..00000000
--- a/fuzz/server_corpus/1d676a51656b8d4ef24a461e29c9fed2807f7e50
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33c b/fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33c
new file mode 100644
index 00000000..a1aa7bb2
--- /dev/null
+++ b/fuzz/server_corpus/1d9b4cbce0998360304d17a5273b57d1bb6fb33c
Binary files differ
diff --git a/fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3 b/fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3
new file mode 100644
index 00000000..dbb2e236
--- /dev/null
+++ b/fuzz/server_corpus/1de612cf9b75c023cf183e85997a0797657266a3
Binary files differ
diff --git a/fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0aff b/fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0aff
new file mode 100644
index 00000000..08901d61
--- /dev/null
+++ b/fuzz/server_corpus/1de66d7e26f3df137ad2868570263e7fa14c0aff
Binary files differ
diff --git a/fuzz/server_corpus/1e40a60f3553be1e5ed6f95b369b49e75ffc97e7 b/fuzz/server_corpus/1e40a60f3553be1e5ed6f95b369b49e75ffc97e7
deleted file mode 100644
index f56240d8..00000000
--- a/fuzz/server_corpus/1e40a60f3553be1e5ed6f95b369b49e75ffc97e7
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537 b/fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537
new file mode 100644
index 00000000..0bf1d723
--- /dev/null
+++ b/fuzz/server_corpus/201a57ee9fff7cb160f28aea6084c520d59d5537
Binary files differ
diff --git a/fuzz/server_corpus/2053722a3a832b256088576903f78b3a521036ef b/fuzz/server_corpus/2053722a3a832b256088576903f78b3a521036ef
deleted file mode 100644
index f98dd68a..00000000
--- a/fuzz/server_corpus/2053722a3a832b256088576903f78b3a521036ef
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4 b/fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4
new file mode 100644
index 00000000..dd15230a
--- /dev/null
+++ b/fuzz/server_corpus/205c2b1f4683eef4f65ca1dce4e39ee5a0423bd4
Binary files differ
diff --git a/fuzz/server_corpus/20cf74e48a97d8db12cbbc66c6c7f5eb8bba9ee0 b/fuzz/server_corpus/20cf74e48a97d8db12cbbc66c6c7f5eb8bba9ee0
deleted file mode 100644
index 6df4f67b..00000000
--- a/fuzz/server_corpus/20cf74e48a97d8db12cbbc66c6c7f5eb8bba9ee0
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4d b/fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4d
new file mode 100644
index 00000000..dac432be
--- /dev/null
+++ b/fuzz/server_corpus/20d3cfe62b986e9fc74c2bd4f8d793928df88f4d
Binary files differ
diff --git a/fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1 b/fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1
new file mode 100644
index 00000000..42c85798
--- /dev/null
+++ b/fuzz/server_corpus/217f128931d1db8e7a12784e793d3613f7a584b1
Binary files differ
diff --git a/fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0 b/fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0
new file mode 100644
index 00000000..efeb24e1
--- /dev/null
+++ b/fuzz/server_corpus/22eda57a5819d876bbe9e0d938d4ceec5ef7bde0
Binary files differ
diff --git a/fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29 b/fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29
new file mode 100644
index 00000000..e34a6c97
--- /dev/null
+++ b/fuzz/server_corpus/238118230b83a2beac4fc04e8ace080c96427e29
Binary files differ
diff --git a/fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59b b/fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59b
new file mode 100644
index 00000000..4231b08e
--- /dev/null
+++ b/fuzz/server_corpus/2694758ce91a4233066ec157880fec851c16c59b
Binary files differ
diff --git a/fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08c b/fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08c
new file mode 100644
index 00000000..40eb6011
--- /dev/null
+++ b/fuzz/server_corpus/26962d40bfb0f49cdded97cc981d789e4699b08c
Binary files differ
diff --git a/fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dff b/fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dff
new file mode 100644
index 00000000..684e9878
--- /dev/null
+++ b/fuzz/server_corpus/27e55ccf7c64899aeb1011629cd1edc492730dff
Binary files differ
diff --git a/fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513a b/fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513a
new file mode 100644
index 00000000..2530dc26
--- /dev/null
+++ b/fuzz/server_corpus/280376c0907c566a201a131ab01e567aca85513a
Binary files differ
diff --git a/fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3 b/fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3
new file mode 100644
index 00000000..d211553d
--- /dev/null
+++ b/fuzz/server_corpus/286456dce363ae8bf19ce6ebbf027889cdd351f3
Binary files differ
diff --git a/fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7 b/fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7
new file mode 100644
index 00000000..72242065
--- /dev/null
+++ b/fuzz/server_corpus/28bd4185ae535c2d6bc9d848db4b4039e60dcfa7
Binary files differ
diff --git a/fuzz/server_corpus/28e593bf15b1e6b2a1f7a6dd21a449965d89d31b b/fuzz/server_corpus/28e593bf15b1e6b2a1f7a6dd21a449965d89d31b
deleted file mode 100644
index 543078fc..00000000
--- a/fuzz/server_corpus/28e593bf15b1e6b2a1f7a6dd21a449965d89d31b
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3 b/fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3
new file mode 100644
index 00000000..371ebbff
--- /dev/null
+++ b/fuzz/server_corpus/29000511dd6707b7e8c7f10ed70340e1391dd3c3
Binary files differ
diff --git a/fuzz/server_corpus/297c57f486feb89ef6b6b2dbba3f512275276b2f b/fuzz/server_corpus/297c57f486feb89ef6b6b2dbba3f512275276b2f
deleted file mode 100644
index aff13fe8..00000000
--- a/fuzz/server_corpus/297c57f486feb89ef6b6b2dbba3f512275276b2f
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24 b/fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24
new file mode 100644
index 00000000..5c717a89
--- /dev/null
+++ b/fuzz/server_corpus/298752b8d5f8cae623a95764289da5f0d94afb24
Binary files differ
diff --git a/fuzz/server_corpus/2b7d9ae0424f5301bd7ab12386cf24dbf142f7e5 b/fuzz/server_corpus/2b7d9ae0424f5301bd7ab12386cf24dbf142f7e5
deleted file mode 100644
index db3393f1..00000000
--- a/fuzz/server_corpus/2b7d9ae0424f5301bd7ab12386cf24dbf142f7e5
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390 b/fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390
new file mode 100644
index 00000000..014e4bd5
--- /dev/null
+++ b/fuzz/server_corpus/2badd38a1ebbaccd61bfdc3d79e1f79f585ed390
Binary files differ
diff --git a/fuzz/server_corpus/2c6ecbe428cdf047527f655527a9c73ccca9e2e1 b/fuzz/server_corpus/2c6ecbe428cdf047527f655527a9c73ccca9e2e1
deleted file mode 100644
index 6731d00d..00000000
--- a/fuzz/server_corpus/2c6ecbe428cdf047527f655527a9c73ccca9e2e1
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651 b/fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651
new file mode 100644
index 00000000..c9a38a67
--- /dev/null
+++ b/fuzz/server_corpus/2c79975ee52b16aa14b8faaaf43eccfac72f4651
Binary files differ
diff --git a/fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17 b/fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17
new file mode 100644
index 00000000..13a210fe
--- /dev/null
+++ b/fuzz/server_corpus/2d85badb9e3e4c1639e2a895d5cf9a864ba5ce17
Binary files differ
diff --git a/fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2a b/fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2a
new file mode 100644
index 00000000..0d7869c5
--- /dev/null
+++ b/fuzz/server_corpus/2de59b00466c89d774e8dbf353761c4611d65e2a
Binary files differ
diff --git a/fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41 b/fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41
new file mode 100644
index 00000000..894d17bb
--- /dev/null
+++ b/fuzz/server_corpus/30215b01f68c655988e2be5d071767adb918ab41
Binary files differ
diff --git a/fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508e b/fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508e
new file mode 100644
index 00000000..cd93906b
--- /dev/null
+++ b/fuzz/server_corpus/302f9b349fc7d906fd38893a85431925e319508e
Binary files differ
diff --git a/fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7 b/fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7
new file mode 100644
index 00000000..629c966d
--- /dev/null
+++ b/fuzz/server_corpus/317bc318af6286bf0ac2d679d3518b12b75c49e7
Binary files differ
diff --git a/fuzz/server_corpus/319a6b4d218465966a29b5152fe9eb83003a41fe b/fuzz/server_corpus/319a6b4d218465966a29b5152fe9eb83003a41fe
deleted file mode 100644
index 9eff9a6a..00000000
--- a/fuzz/server_corpus/319a6b4d218465966a29b5152fe9eb83003a41fe
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dc b/fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dc
new file mode 100644
index 00000000..8465bcd3
--- /dev/null
+++ b/fuzz/server_corpus/31f6f995d8cbf4291e5197d421e78de61bcf53dc
Binary files differ
diff --git a/fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3 b/fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3
new file mode 100644
index 00000000..4c92569d
--- /dev/null
+++ b/fuzz/server_corpus/32302b428fdb884e4de50171bf7897354ee35ee3
Binary files differ
diff --git a/fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768 b/fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768
new file mode 100644
index 00000000..56f81e75
--- /dev/null
+++ b/fuzz/server_corpus/324bf110726da4cf6de7bb28a0b2a99dac045768
Binary files differ
diff --git a/fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6da b/fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6da
new file mode 100644
index 00000000..6610efca
--- /dev/null
+++ b/fuzz/server_corpus/32cf502f739bb71624940b06ce964422a175b6da
Binary files differ
diff --git a/fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9 b/fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9
new file mode 100644
index 00000000..a7d29e89
--- /dev/null
+++ b/fuzz/server_corpus/32d38a0276c734a25c88823b79710dafce4721f9
Binary files differ
diff --git a/fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9 b/fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9
new file mode 100644
index 00000000..62a538a7
--- /dev/null
+++ b/fuzz/server_corpus/337d50236ca01f8e660527e1c7f1190188cc5af9
Binary files differ
diff --git a/fuzz/server_corpus/33d623eb76b1539ff7e44ce81784b5ef42b70df4 b/fuzz/server_corpus/33d623eb76b1539ff7e44ce81784b5ef42b70df4
deleted file mode 100644
index e5ea20a8..00000000
--- a/fuzz/server_corpus/33d623eb76b1539ff7e44ce81784b5ef42b70df4
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43 b/fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43
new file mode 100644
index 00000000..07b0690e
--- /dev/null
+++ b/fuzz/server_corpus/34b4eb249c57036a82496931b7823a8abffbfe43
Binary files differ
diff --git a/fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7c b/fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7c
new file mode 100644
index 00000000..a16ba3d1
--- /dev/null
+++ b/fuzz/server_corpus/34f2704805423aee640b1ad1fefb54ff5c49bf7c
Binary files differ
diff --git a/fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206 b/fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206
new file mode 100644
index 00000000..f9b79dc4
--- /dev/null
+++ b/fuzz/server_corpus/3593bd1cfd62ca2f53432dd7444b452e1d7c7206
Binary files differ
diff --git a/fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3 b/fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3
new file mode 100644
index 00000000..35e2d47e
--- /dev/null
+++ b/fuzz/server_corpus/35fe7fd7c3ee1858cec80fef8f18bb5c5da5dcd3
Binary files differ
diff --git a/fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515d b/fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515d
new file mode 100644
index 00000000..8b24b7dc
--- /dev/null
+++ b/fuzz/server_corpus/364ff4d7992806bf179b156ab465400e46fa515d
Binary files differ
diff --git a/fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3 b/fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3
new file mode 100644
index 00000000..c0ec1c13
--- /dev/null
+++ b/fuzz/server_corpus/3697165cd5d8c192e32be9f6f62fb514910fd1e3
Binary files differ
diff --git a/fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770 b/fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770
new file mode 100644
index 00000000..f598c540
--- /dev/null
+++ b/fuzz/server_corpus/37826e5324f024632f3fe4d6aeb6c5e0cd33b770
Binary files differ
diff --git a/fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89 b/fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89
new file mode 100644
index 00000000..058393a7
--- /dev/null
+++ b/fuzz/server_corpus/3791653050209ed3d11f6749e0d8e874fdc68b89
Binary files differ
diff --git a/fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661 b/fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661
new file mode 100644
index 00000000..963a6860
--- /dev/null
+++ b/fuzz/server_corpus/37a863dd9c47ee54937c65c6e43ee95667808661
Binary files differ
diff --git a/fuzz/server_corpus/37dbd1d658bb90da84a14aeb9f24db0200c20c4d b/fuzz/server_corpus/37dbd1d658bb90da84a14aeb9f24db0200c20c4d
deleted file mode 100644
index 49a8163d..00000000
--- a/fuzz/server_corpus/37dbd1d658bb90da84a14aeb9f24db0200c20c4d
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14 b/fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14
new file mode 100644
index 00000000..0ea0d46e
--- /dev/null
+++ b/fuzz/server_corpus/38fb26179fe6db37a43708ebc02df87cfe01fd14
Binary files differ
diff --git a/fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74b b/fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74b
new file mode 100644
index 00000000..1937185d
--- /dev/null
+++ b/fuzz/server_corpus/397b7e5b1afb2f886fa46fe47e3340e9e25db74b
Binary files differ
diff --git a/fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528 b/fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528
new file mode 100644
index 00000000..577cc6d9
--- /dev/null
+++ b/fuzz/server_corpus/399976c7723f20941ac86dfbc66090453e496528
Binary files differ
diff --git a/fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e b/fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e
new file mode 100644
index 00000000..f4ebdd51
--- /dev/null
+++ b/fuzz/server_corpus/39d8e38c9f3e5c310068ca78d532c61c4dbb7f5e
Binary files differ
diff --git a/fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2 b/fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2
new file mode 100644
index 00000000..8aa09bb9
--- /dev/null
+++ b/fuzz/server_corpus/3aaf48199b093ba93f0e1ddf972782cc99e613d2
Binary files differ
diff --git a/fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1 b/fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1
new file mode 100644
index 00000000..67d5849a
--- /dev/null
+++ b/fuzz/server_corpus/3aec20067842293ca181d1c98b1caad6b10153c1
Binary files differ
diff --git a/fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843 b/fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843
new file mode 100644
index 00000000..209a0ff3
--- /dev/null
+++ b/fuzz/server_corpus/3c4f860903933d2305eb9ce4eaf53144d79c5843
Binary files differ
diff --git a/fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294 b/fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294
new file mode 100644
index 00000000..9a7cc9a1
--- /dev/null
+++ b/fuzz/server_corpus/3cbf37bfdfe9dd100367e512ba6298dfba7bf294
Binary files differ
diff --git a/fuzz/server_corpus/3d1395e75201e8329b26520c1488a92b0cb14f0d b/fuzz/server_corpus/3d1395e75201e8329b26520c1488a92b0cb14f0d
deleted file mode 100644
index 39119ce0..00000000
--- a/fuzz/server_corpus/3d1395e75201e8329b26520c1488a92b0cb14f0d
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884 b/fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884
new file mode 100644
index 00000000..cb28091e
--- /dev/null
+++ b/fuzz/server_corpus/3d1a07692bc1687bfe9d4ee6f54811578fc54884
Binary files differ
diff --git a/fuzz/server_corpus/3e62dce3a399b97744c41563672fb3b67a3981fc b/fuzz/server_corpus/3e62dce3a399b97744c41563672fb3b67a3981fc
deleted file mode 100644
index 8f3cd1b7..00000000
--- a/fuzz/server_corpus/3e62dce3a399b97744c41563672fb3b67a3981fc
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7 b/fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7
new file mode 100644
index 00000000..68be63be
--- /dev/null
+++ b/fuzz/server_corpus/3f66254e9c33487a194952aef2b4b38cae181ff7
Binary files differ
diff --git a/fuzz/server_corpus/3fd252919651c9895feba5659a564fc1f4f7d3c6 b/fuzz/server_corpus/3fd252919651c9895feba5659a564fc1f4f7d3c6
deleted file mode 100644
index b3ca9632..00000000
--- a/fuzz/server_corpus/3fd252919651c9895feba5659a564fc1f4f7d3c6
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9 b/fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9
new file mode 100644
index 00000000..6d133f20
--- /dev/null
+++ b/fuzz/server_corpus/40ce675771c2d778f8c746a5d0adc41d6236ecf9
Binary files differ
diff --git a/fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9 b/fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9
new file mode 100644
index 00000000..a39b6bde
--- /dev/null
+++ b/fuzz/server_corpus/4108e3cf35e8e7bffe615ed6c1f898df52ac5fb9
Binary files differ
diff --git a/fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929 b/fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929
new file mode 100644
index 00000000..fcd82420
--- /dev/null
+++ b/fuzz/server_corpus/41aa254eb9cf327e23976ad968de5f6c6fd41929
Binary files differ
diff --git a/fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384 b/fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384
new file mode 100644
index 00000000..4a55d149
--- /dev/null
+++ b/fuzz/server_corpus/41b3e56ab8d7752ea12fb170efdc8318f822a384
Binary files differ
diff --git a/fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44 b/fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44
new file mode 100644
index 00000000..65de38ef
--- /dev/null
+++ b/fuzz/server_corpus/41fddbda3d28306beb8045d74be6c048c8d95a44
Binary files differ
diff --git a/fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348 b/fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348
new file mode 100644
index 00000000..8cd9757d
--- /dev/null
+++ b/fuzz/server_corpus/435e84066c2a010e52c2452852816bf2ac8ab348
Binary files differ
diff --git a/fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814 b/fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814
new file mode 100644
index 00000000..53cdafed
--- /dev/null
+++ b/fuzz/server_corpus/448cdd2ee6d4f30585785ee406d7a5be76783814
Binary files differ
diff --git a/fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81 b/fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81
new file mode 100644
index 00000000..04ae71e2
--- /dev/null
+++ b/fuzz/server_corpus/45331d2e2c0f21e6f070d26e381bd0fa0c82ab81
Binary files differ
diff --git a/fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550 b/fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550
new file mode 100644
index 00000000..9e9060f8
--- /dev/null
+++ b/fuzz/server_corpus/463538114921dd033e2b968874a8d0103d8a0550
Binary files differ
diff --git a/fuzz/server_corpus/48b6e6c2a8d277c48f6272981d3ac13458bda2fc b/fuzz/server_corpus/48b6e6c2a8d277c48f6272981d3ac13458bda2fc
deleted file mode 100644
index 96cd018a..00000000
--- a/fuzz/server_corpus/48b6e6c2a8d277c48f6272981d3ac13458bda2fc
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6 b/fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6
new file mode 100644
index 00000000..001de81a
--- /dev/null
+++ b/fuzz/server_corpus/492a81af49a5a0f6e88192f8d8a6212bb15671f6
Binary files differ
diff --git a/fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61 b/fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61
new file mode 100644
index 00000000..0e65d7b8
--- /dev/null
+++ b/fuzz/server_corpus/49c09c1aa90fb1879802f348f2564c7a67f07f61
Binary files differ
diff --git a/fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5 b/fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5
new file mode 100644
index 00000000..e73f0a22
--- /dev/null
+++ b/fuzz/server_corpus/49d88822047d201e1ffc6759e61a917886c899c5
Binary files differ
diff --git a/fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345 b/fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345
new file mode 100644
index 00000000..4251d551
--- /dev/null
+++ b/fuzz/server_corpus/4a33f80e3245dbac94867a309485514038284345
Binary files differ
diff --git a/fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1 b/fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1
new file mode 100644
index 00000000..4f46103d
--- /dev/null
+++ b/fuzz/server_corpus/4b2338c4375e3dc2e6a1aa3684de4a163f7c83c1
Binary files differ
diff --git a/fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39be b/fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39be
new file mode 100644
index 00000000..5b1f7bda
--- /dev/null
+++ b/fuzz/server_corpus/4c19babb1cd203839c0849f977058b7eaddf39be
Binary files differ
diff --git a/fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99dd b/fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99dd
new file mode 100644
index 00000000..e9e7ef25
--- /dev/null
+++ b/fuzz/server_corpus/4c948e8277af54d8f79adf1fc5f748f51f2f99dd
Binary files differ
diff --git a/fuzz/server_corpus/4d0beb8342107afedf7ad91e13c3b8d2cf558ecf b/fuzz/server_corpus/4d0beb8342107afedf7ad91e13c3b8d2cf558ecf
deleted file mode 100644
index ea0eea78..00000000
--- a/fuzz/server_corpus/4d0beb8342107afedf7ad91e13c3b8d2cf558ecf
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110d b/fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110d
new file mode 100644
index 00000000..b22804bc
--- /dev/null
+++ b/fuzz/server_corpus/50a4c64c532174353794ca054ad60e30ef25110d
Binary files differ
diff --git a/fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caa b/fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caa
new file mode 100644
index 00000000..43326c51
--- /dev/null
+++ b/fuzz/server_corpus/50bb213c61033f9305b0bd3828c72505ec6a1caa
Binary files differ
diff --git a/fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72 b/fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72
new file mode 100644
index 00000000..359fd8fc
--- /dev/null
+++ b/fuzz/server_corpus/52a47ded2085baa31ad7c7ef5b8f5fd7d124bf72
Binary files differ
diff --git a/fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553 b/fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553
new file mode 100644
index 00000000..b07a9cd6
--- /dev/null
+++ b/fuzz/server_corpus/52bd453551c468e4fa1503fb4b113d6b143dc553
Binary files differ
diff --git a/fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045 b/fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045
new file mode 100644
index 00000000..e268ecc9
--- /dev/null
+++ b/fuzz/server_corpus/530aeb352e1f3e82138f4a3325463ab8738ee045
Binary files differ
diff --git a/fuzz/server_corpus/53f52c2e3ddcfb9734487f3efdb568de0a689cc4 b/fuzz/server_corpus/53f52c2e3ddcfb9734487f3efdb568de0a689cc4
deleted file mode 100644
index 63e15165..00000000
--- a/fuzz/server_corpus/53f52c2e3ddcfb9734487f3efdb568de0a689cc4
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbf b/fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbf
new file mode 100644
index 00000000..699da8e2
--- /dev/null
+++ b/fuzz/server_corpus/545801d21d7321adfc5e2fec30ad21125c612bbf
Binary files differ
diff --git a/fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838 b/fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838
new file mode 100644
index 00000000..52130fa8
--- /dev/null
+++ b/fuzz/server_corpus/557f33e444c12f4ae11cbed2463509e2b76c4838
Binary files differ
diff --git a/fuzz/server_corpus/56b58b030f049497826cad828107c886c244e5c3 b/fuzz/server_corpus/56b58b030f049497826cad828107c886c244e5c3
deleted file mode 100644
index e9ae6fc1..00000000
--- a/fuzz/server_corpus/56b58b030f049497826cad828107c886c244e5c3
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/57662bdb72f6c06ac58cdd7d97a165b101a3b4a6 b/fuzz/server_corpus/57662bdb72f6c06ac58cdd7d97a165b101a3b4a6
deleted file mode 100644
index a125419b..00000000
--- a/fuzz/server_corpus/57662bdb72f6c06ac58cdd7d97a165b101a3b4a6
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cd b/fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cd
new file mode 100644
index 00000000..d345376f
--- /dev/null
+++ b/fuzz/server_corpus/57bed14657b0ba761b67f5663af6dbcf891e06cd
Binary files differ
diff --git a/fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6 b/fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6
new file mode 100644
index 00000000..a4005344
--- /dev/null
+++ b/fuzz/server_corpus/58080a322d37e7d8cb9fa7585be92689a971ffd6
Binary files differ
diff --git a/fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281 b/fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281
new file mode 100644
index 00000000..e6f1b1ca
--- /dev/null
+++ b/fuzz/server_corpus/59849e9352267bb6c79fe78960a8369797da6281
Binary files differ
diff --git a/fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604 b/fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604
new file mode 100644
index 00000000..31748097
--- /dev/null
+++ b/fuzz/server_corpus/5a09520c67133379b720d9b4aa549e6a4f76b604
Binary files differ
diff --git a/fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8 b/fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8
new file mode 100644
index 00000000..3a9a0ba6
--- /dev/null
+++ b/fuzz/server_corpus/5b492ed27785260ed00654e71e9b272071618fc8
Binary files differ
diff --git a/fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879 b/fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879
new file mode 100644
index 00000000..d1a5ae5e
--- /dev/null
+++ b/fuzz/server_corpus/5b598ddf2bc6d1b376c733a935306e45cb247879
Binary files differ
diff --git a/fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a b/fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a
new file mode 100644
index 00000000..218ac16a
--- /dev/null
+++ b/fuzz/server_corpus/5ed11035d4c1eb0685d4b4aa9e153e0b394b8f7a
Binary files differ
diff --git a/fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adf b/fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adf
new file mode 100644
index 00000000..eb5fa112
--- /dev/null
+++ b/fuzz/server_corpus/5edf5a17f9862feb006b9400cafed2843ff80adf
Binary files differ
diff --git a/fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0 b/fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0
new file mode 100644
index 00000000..fcc90d98
--- /dev/null
+++ b/fuzz/server_corpus/5f05a5fac8c767208fcfc64dd55ac78c24bf4ea0
Binary files differ
diff --git a/fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8 b/fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8
new file mode 100644
index 00000000..8baefef1
--- /dev/null
+++ b/fuzz/server_corpus/5f25cbe4c0e5b376a9b8c1b820c448fe5915c8a8
Binary files differ
diff --git a/fuzz/server_corpus/5f467faeb38fe5ca5d024a5a6816b79da9767732 b/fuzz/server_corpus/5f467faeb38fe5ca5d024a5a6816b79da9767732
deleted file mode 100644
index 2031c654..00000000
--- a/fuzz/server_corpus/5f467faeb38fe5ca5d024a5a6816b79da9767732
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/5f87f3a402d733e677621e099eb9dd4903170ad6 b/fuzz/server_corpus/5f87f3a402d733e677621e099eb9dd4903170ad6
deleted file mode 100644
index cc5e5c3f..00000000
--- a/fuzz/server_corpus/5f87f3a402d733e677621e099eb9dd4903170ad6
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/5f9e63c922f729be467f5c33991ba7ddc675513f b/fuzz/server_corpus/5f9e63c922f729be467f5c33991ba7ddc675513f
deleted file mode 100644
index 111ea158..00000000
--- a/fuzz/server_corpus/5f9e63c922f729be467f5c33991ba7ddc675513f
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/5fb64e97081500493ecb3941672157d9c99ca14e b/fuzz/server_corpus/5fb64e97081500493ecb3941672157d9c99ca14e
deleted file mode 100644
index b03c3c71..00000000
--- a/fuzz/server_corpus/5fb64e97081500493ecb3941672157d9c99ca14e
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902 b/fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902
new file mode 100644
index 00000000..ca4283ae
--- /dev/null
+++ b/fuzz/server_corpus/60b3caaf413cf16a1bbb4741cdbbe66259540902
Binary files differ
diff --git a/fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644e b/fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644e
new file mode 100644
index 00000000..9311b157
--- /dev/null
+++ b/fuzz/server_corpus/610e3905ae7cbfb26c383c894489c45fddcc644e
Binary files differ
diff --git a/fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591f b/fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591f
new file mode 100644
index 00000000..b649ff11
--- /dev/null
+++ b/fuzz/server_corpus/61d0f602fbb64038787d3c79591a4673f84d591f
Binary files differ
diff --git a/fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7ee b/fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7ee
new file mode 100644
index 00000000..d4d6b86c
--- /dev/null
+++ b/fuzz/server_corpus/6288b112228f24ecbe24c87d06698e244e15a7ee
Binary files differ
diff --git a/fuzz/server_corpus/6297728e4a0eafcbd2cbda655014c10578b8a035 b/fuzz/server_corpus/6297728e4a0eafcbd2cbda655014c10578b8a035
deleted file mode 100644
index 6286ea38..00000000
--- a/fuzz/server_corpus/6297728e4a0eafcbd2cbda655014c10578b8a035
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485 b/fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485
new file mode 100644
index 00000000..9f7446b2
--- /dev/null
+++ b/fuzz/server_corpus/63103eb0da3c238ad20edd649bc2e0ff1d65d485
Binary files differ
diff --git a/fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea b/fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea
new file mode 100644
index 00000000..a472e666
--- /dev/null
+++ b/fuzz/server_corpus/63ed349b02542d6a86a6dc2cbbfad610f9c3e8ea
Binary files differ
diff --git a/fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3 b/fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3
new file mode 100644
index 00000000..cc47908a
--- /dev/null
+++ b/fuzz/server_corpus/6427c33410538cfa3263291caefc5fef483baee3
Binary files differ
diff --git a/fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7 b/fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7
new file mode 100644
index 00000000..fa3fd115
--- /dev/null
+++ b/fuzz/server_corpus/64b9b46b076ce2b5c3f9d4958cf292e0e55b5be7
Binary files differ
diff --git a/fuzz/server_corpus/669cc7dc49dbbd7ad6019ffcf7396981b830c0a2 b/fuzz/server_corpus/669cc7dc49dbbd7ad6019ffcf7396981b830c0a2
deleted file mode 100644
index ddd1c340..00000000
--- a/fuzz/server_corpus/669cc7dc49dbbd7ad6019ffcf7396981b830c0a2
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/678c4b5373f970b0e5b0231045e2318886f0443b b/fuzz/server_corpus/678c4b5373f970b0e5b0231045e2318886f0443b
deleted file mode 100644
index e9795c8c..00000000
--- a/fuzz/server_corpus/678c4b5373f970b0e5b0231045e2318886f0443b
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10 b/fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10
new file mode 100644
index 00000000..5c2a80d7
--- /dev/null
+++ b/fuzz/server_corpus/6804200e6128651336b64a491deff4c045edea10
Binary files differ
diff --git a/fuzz/server_corpus/687ad0e578cd6c67aa8ab45d79c5f05efa7b09a4 b/fuzz/server_corpus/687ad0e578cd6c67aa8ab45d79c5f05efa7b09a4
deleted file mode 100644
index c960ab4d..00000000
--- a/fuzz/server_corpus/687ad0e578cd6c67aa8ab45d79c5f05efa7b09a4
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739f b/fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739f
new file mode 100644
index 00000000..b08dd29c
--- /dev/null
+++ b/fuzz/server_corpus/68ed9e990a43456def6c94ea616668f5d17d739f
Binary files differ
diff --git a/fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78 b/fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78
new file mode 100644
index 00000000..45f03437
--- /dev/null
+++ b/fuzz/server_corpus/6a28ed0197ddb6f8ceb4ca87ab463fa80152db78
Binary files differ
diff --git a/fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02ce b/fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02ce
new file mode 100644
index 00000000..a929eb92
--- /dev/null
+++ b/fuzz/server_corpus/6adff19a28e5d20cbf9cb4cc576b86718d7b02ce
Binary files differ
diff --git a/fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7 b/fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7
new file mode 100644
index 00000000..7de3f898
--- /dev/null
+++ b/fuzz/server_corpus/6afb292e0d86866ead887381e4bb95c6abbd00a7
Binary files differ
diff --git a/fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753 b/fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753
new file mode 100644
index 00000000..873195c9
--- /dev/null
+++ b/fuzz/server_corpus/6ce759d9375ef41abf26be9e5f79447f9cd10753
Binary files differ
diff --git a/fuzz/server_corpus/6d52942721bf6fe08707bc9704f9b5a217604040 b/fuzz/server_corpus/6d52942721bf6fe08707bc9704f9b5a217604040
deleted file mode 100644
index a280f784..00000000
--- a/fuzz/server_corpus/6d52942721bf6fe08707bc9704f9b5a217604040
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5c b/fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5c
new file mode 100644
index 00000000..5f9a8cbe
--- /dev/null
+++ b/fuzz/server_corpus/6d77b6fa38172e6716a8faa9672364199025be5c
Binary files differ
diff --git a/fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06 b/fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06
new file mode 100644
index 00000000..0bb854dc
--- /dev/null
+++ b/fuzz/server_corpus/6dca0b5a9175bcc8bf0da3b0efbe48fcc67aca06
Binary files differ
diff --git a/fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532c b/fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532c
new file mode 100644
index 00000000..f065dcc8
--- /dev/null
+++ b/fuzz/server_corpus/6de87dc2626b2b0068ba2d981665d6b366c3532c
Binary files differ
diff --git a/fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0 b/fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0
new file mode 100644
index 00000000..708bed8d
--- /dev/null
+++ b/fuzz/server_corpus/6eb8ee617c043084a08fd19105f897bf9a5ce7f0
Binary files differ
diff --git a/fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359 b/fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359
new file mode 100644
index 00000000..9ab40cb4
--- /dev/null
+++ b/fuzz/server_corpus/6ede1a48fb0da7644f9bc8f91c9b8d717710a359
Binary files differ
diff --git a/fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890 b/fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890
new file mode 100644
index 00000000..97255643
--- /dev/null
+++ b/fuzz/server_corpus/6f65f68defc58c4e70ac774728d73df16b035890
Binary files differ
diff --git a/fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a b/fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a
new file mode 100644
index 00000000..f7c04968
--- /dev/null
+++ b/fuzz/server_corpus/6f89a51d7c8c7f4f467d4deda8b8d3d74711bd7a
Binary files differ
diff --git a/fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83be b/fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83be
new file mode 100644
index 00000000..d0b0a4f6
--- /dev/null
+++ b/fuzz/server_corpus/7033506106b6f14d4b73713d409503581d6d83be
Binary files differ
diff --git a/fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634 b/fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634
new file mode 100644
index 00000000..aab47592
--- /dev/null
+++ b/fuzz/server_corpus/7073f6010cff349f012670f14da7428b53755634
Binary files differ
diff --git a/fuzz/server_corpus/71c04cb636abfba7a375ee53fff441976b476782 b/fuzz/server_corpus/71c04cb636abfba7a375ee53fff441976b476782
deleted file mode 100644
index c7b972ca..00000000
--- a/fuzz/server_corpus/71c04cb636abfba7a375ee53fff441976b476782
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/7313ac031df5c44dc34dd2b00f934df695099a50 b/fuzz/server_corpus/7313ac031df5c44dc34dd2b00f934df695099a50
deleted file mode 100644
index 33577dae..00000000
--- a/fuzz/server_corpus/7313ac031df5c44dc34dd2b00f934df695099a50
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aad b/fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aad
new file mode 100644
index 00000000..73bafa66
--- /dev/null
+++ b/fuzz/server_corpus/743fd36937f52741a4cc0a8657203cfd02c46aad
Binary files differ
diff --git a/fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af b/fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af
new file mode 100644
index 00000000..413b6ec3
--- /dev/null
+++ b/fuzz/server_corpus/75f7f0ca59f5ed0bbdb782a7e37f8fb79c7a69af
Binary files differ
diff --git a/fuzz/server_corpus/779a028692898b11fe8b382387de47ab5975a96f b/fuzz/server_corpus/779a028692898b11fe8b382387de47ab5975a96f
deleted file mode 100644
index 4768173d..00000000
--- a/fuzz/server_corpus/779a028692898b11fe8b382387de47ab5975a96f
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232 b/fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232
new file mode 100644
index 00000000..55de2e0f
--- /dev/null
+++ b/fuzz/server_corpus/77b55b3457cd7ea618c65886edf5661322f94232
Binary files differ
diff --git a/fuzz/server_corpus/78866cc7c4e60906cf1d7de6bc6dde5dfc32b829 b/fuzz/server_corpus/78866cc7c4e60906cf1d7de6bc6dde5dfc32b829
deleted file mode 100644
index aae562b9..00000000
--- a/fuzz/server_corpus/78866cc7c4e60906cf1d7de6bc6dde5dfc32b829
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58 b/fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58
new file mode 100644
index 00000000..5c4d4670
--- /dev/null
+++ b/fuzz/server_corpus/7a4ac7e949d3a80da8e02b5cf09aa586d5fc2c58
Binary files differ
diff --git a/fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93e b/fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93e
new file mode 100644
index 00000000..4fe9104e
--- /dev/null
+++ b/fuzz/server_corpus/7ad83ae355cd42307de44effef5fa238db8de93e
Binary files differ
diff --git a/fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762d b/fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762d
new file mode 100644
index 00000000..052f2388
--- /dev/null
+++ b/fuzz/server_corpus/7c13a00efcf05848cca0015ec99705939bd7762d
Binary files differ
diff --git a/fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2 b/fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2
new file mode 100644
index 00000000..774c1e48
--- /dev/null
+++ b/fuzz/server_corpus/7c1cb7d73425b8f58dc83ed2a058b28d6c8910e2
Binary files differ
diff --git a/fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457f b/fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457f
new file mode 100644
index 00000000..69d8b617
--- /dev/null
+++ b/fuzz/server_corpus/7c8d8a6475c235eee93a9132e3efcc2d8cf2457f
Binary files differ
diff --git a/fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10 b/fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10
new file mode 100644
index 00000000..f4f843b3
--- /dev/null
+++ b/fuzz/server_corpus/7e1dd1d1d2f30337a345ee16662089530e19ba10
Binary files differ
diff --git a/fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35 b/fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35
new file mode 100644
index 00000000..f588f54f
--- /dev/null
+++ b/fuzz/server_corpus/7ecae41dba4999017c7282a2e17c5be94d13bb35
Binary files differ
diff --git a/fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02 b/fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02
new file mode 100644
index 00000000..10abd484
--- /dev/null
+++ b/fuzz/server_corpus/7eda66afbb955d4d0c1fb9c3236aaf01bcbfcd02
Binary files differ
diff --git a/fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943a b/fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943a
new file mode 100644
index 00000000..d8277a1e
--- /dev/null
+++ b/fuzz/server_corpus/7ff26dd574e66a7f3425f1aa68717beb16a6943a
Binary files differ
diff --git a/fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2 b/fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2
new file mode 100644
index 00000000..592f779e
--- /dev/null
+++ b/fuzz/server_corpus/7ff47a645111533c4c4a5680485aebec1fc71ba2
Binary files differ
diff --git a/fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079 b/fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079
new file mode 100644
index 00000000..f019d591
--- /dev/null
+++ b/fuzz/server_corpus/807e902da37bf045992967c88bdd7ef5e3311079
Binary files differ
diff --git a/fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538e b/fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538e
new file mode 100644
index 00000000..17b689bf
--- /dev/null
+++ b/fuzz/server_corpus/81002fc62e533b6df9bac981650d9379efa1538e
Binary files differ
diff --git a/fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1a b/fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1a
new file mode 100644
index 00000000..d5c676f1
--- /dev/null
+++ b/fuzz/server_corpus/815efc8337a4dafb7acac5e27f188729e794ec1a
Binary files differ
diff --git a/fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629 b/fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629
new file mode 100644
index 00000000..c2769f71
--- /dev/null
+++ b/fuzz/server_corpus/81908c24376fd3bb3e3678298583972f3bc21629
Binary files differ
diff --git a/fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9 b/fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9
new file mode 100644
index 00000000..6599cd0e
--- /dev/null
+++ b/fuzz/server_corpus/81a73f364c5a7966e7fc06aa0208e16836324ff9
Binary files differ
diff --git a/fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27 b/fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27
new file mode 100644
index 00000000..e337f126
--- /dev/null
+++ b/fuzz/server_corpus/832fd1d40a6a34cb526a2a0d51d7f98c01216e27
Binary files differ
diff --git a/fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4 b/fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4
new file mode 100644
index 00000000..19d848a4
--- /dev/null
+++ b/fuzz/server_corpus/83a1fe57841a03e9f62e5c4c98121779d027d7f4
Binary files differ
diff --git a/fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095 b/fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095
new file mode 100644
index 00000000..8b115c89
--- /dev/null
+++ b/fuzz/server_corpus/83a7146b87bdb59b9d181983c0b15934fa141095
Binary files differ
diff --git a/fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1 b/fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1
new file mode 100644
index 00000000..cbe945fb
--- /dev/null
+++ b/fuzz/server_corpus/84cd4487cc10e218fac4e005a2f36e6cda07f2f1
Binary files differ
diff --git a/fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097 b/fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097
new file mode 100644
index 00000000..93d88c2c
--- /dev/null
+++ b/fuzz/server_corpus/8538cd3259ad3d8f06f9ae921b6a365b33548097
Binary files differ
diff --git a/fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77 b/fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77
new file mode 100644
index 00000000..97552b02
--- /dev/null
+++ b/fuzz/server_corpus/87312b033ed008fdeb949278f51403dd15ca3f77
Binary files differ
diff --git a/fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01 b/fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01
new file mode 100644
index 00000000..f33611bf
--- /dev/null
+++ b/fuzz/server_corpus/87bb4f11ea55340864b41f92cfd96699e34dcb01
Binary files differ
diff --git a/fuzz/server_corpus/8aa81c0c002cac098bd1edd10c052fb57e69679c b/fuzz/server_corpus/8aa81c0c002cac098bd1edd10c052fb57e69679c
deleted file mode 100644
index a21731cd..00000000
--- a/fuzz/server_corpus/8aa81c0c002cac098bd1edd10c052fb57e69679c
+++ /dev/null
@@ -1 +0,0 @@
-));(*;;:;Û(*;!);:! \ No newline at end of file
diff --git a/fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9 b/fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9
new file mode 100644
index 00000000..075884c8
--- /dev/null
+++ b/fuzz/server_corpus/8ae391773c823fc455913bb5ec33047dd840e9f9
Binary files differ
diff --git a/fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6 b/fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6
new file mode 100644
index 00000000..a826a36c
--- /dev/null
+++ b/fuzz/server_corpus/8b4aeaa1d3ce97c435b07445e55b778db0f8fda6
Binary files differ
diff --git a/fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c b/fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c
new file mode 100644
index 00000000..4adecc39
--- /dev/null
+++ b/fuzz/server_corpus/8b7fab7b5c33fbb29a8cc5d48040f30b06c16f4c
Binary files differ
diff --git a/fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338 b/fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338
new file mode 100644
index 00000000..ead297a6
--- /dev/null
+++ b/fuzz/server_corpus/8bb068ede7bfaba9627d9820634c0eb4289db338
Binary files differ
diff --git a/fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4 b/fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4
new file mode 100644
index 00000000..9322726d
--- /dev/null
+++ b/fuzz/server_corpus/8d8899a4a0aca676e6e4df78003f237073f850e4
Binary files differ
diff --git a/fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779 b/fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779
new file mode 100644
index 00000000..d18b36cf
--- /dev/null
+++ b/fuzz/server_corpus/909f5acb8de0079ff4c8b107d272574085c8f779
Binary files differ
diff --git a/fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006 b/fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006
new file mode 100644
index 00000000..da859b9e
--- /dev/null
+++ b/fuzz/server_corpus/92d1725e6cd758eeb1139f214d4431b8c8cc8006
Binary files differ
diff --git a/fuzz/server_corpus/92eaac1d235e5124e25bb36027fbf6e25084f386 b/fuzz/server_corpus/92eaac1d235e5124e25bb36027fbf6e25084f386
deleted file mode 100644
index 17dbeb20..00000000
--- a/fuzz/server_corpus/92eaac1d235e5124e25bb36027fbf6e25084f386
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86 b/fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86
new file mode 100644
index 00000000..18ae783d
--- /dev/null
+++ b/fuzz/server_corpus/93fd04136be09b9ff4986bb17fee653ba10c3f86
Binary files differ
diff --git a/fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41d b/fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41d
new file mode 100644
index 00000000..c11faaf6
--- /dev/null
+++ b/fuzz/server_corpus/94581aeb5d99c7ec11279264a94e4d3fa845c41d
Binary files differ
diff --git a/fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726 b/fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726
new file mode 100644
index 00000000..8cea4be0
--- /dev/null
+++ b/fuzz/server_corpus/971714820d6742e5e6d84e95a26c1e526898c726
Binary files differ
diff --git a/fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358 b/fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358
new file mode 100644
index 00000000..fe3e5811
--- /dev/null
+++ b/fuzz/server_corpus/97835515e9845c8094b017636f42e40db853e358
Binary files differ
diff --git a/fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13ca b/fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13ca
new file mode 100644
index 00000000..33b41b61
--- /dev/null
+++ b/fuzz/server_corpus/9841a3665b7d75fd247655a673018735e69e13ca
Binary files differ
diff --git a/fuzz/server_corpus/98aa9c388466c7236d35ce5efb9082bc1346a686 b/fuzz/server_corpus/98aa9c388466c7236d35ce5efb9082bc1346a686
deleted file mode 100644
index 6df1eebd..00000000
--- a/fuzz/server_corpus/98aa9c388466c7236d35ce5efb9082bc1346a686
+++ /dev/null
@@ -1 +0,0 @@
-) \ No newline at end of file
diff --git a/fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335 b/fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335
new file mode 100644
index 00000000..ea94415f
--- /dev/null
+++ b/fuzz/server_corpus/98c12c0d2c35bc2141a8c5fd2438bc6e237df335
Binary files differ
diff --git a/fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcb b/fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcb
new file mode 100644
index 00000000..3538d11b
--- /dev/null
+++ b/fuzz/server_corpus/990b7bec61d2e85dc617b456db532b738791dfcb
Binary files differ
diff --git a/fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0 b/fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0
new file mode 100644
index 00000000..7ce0c54e
--- /dev/null
+++ b/fuzz/server_corpus/999678f54ffad44b964188ff7b839fe323e5d8a0
Binary files differ
diff --git a/fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74 b/fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74
new file mode 100644
index 00000000..947ac61a
--- /dev/null
+++ b/fuzz/server_corpus/99f84ab3877198979a5644873f3078e56d9bce74
Binary files differ
diff --git a/fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3ad b/fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3ad
new file mode 100644
index 00000000..5c5a5171
--- /dev/null
+++ b/fuzz/server_corpus/9a0a22651c45daadb5e28c2fb5a722050242e3ad
Binary files differ
diff --git a/fuzz/server_corpus/9db1a56028c509382bc7c788278a58eab7165331 b/fuzz/server_corpus/9db1a56028c509382bc7c788278a58eab7165331
deleted file mode 100644
index dc748887..00000000
--- a/fuzz/server_corpus/9db1a56028c509382bc7c788278a58eab7165331
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/9ee8b26d5f9c65fb5c4464b19a868b524923029c b/fuzz/server_corpus/9ee8b26d5f9c65fb5c4464b19a868b524923029c
deleted file mode 100644
index a5110e46..00000000
--- a/fuzz/server_corpus/9ee8b26d5f9c65fb5c4464b19a868b524923029c
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4c b/fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4c
new file mode 100644
index 00000000..796363f3
--- /dev/null
+++ b/fuzz/server_corpus/9f47049690a48658cf855cada2ba67ca467f6b4c
Binary files differ
diff --git a/fuzz/server_corpus/9fc76fdbf45c5c3b5464b9c0a94bb28945f7e0dc b/fuzz/server_corpus/9fc76fdbf45c5c3b5464b9c0a94bb28945f7e0dc
deleted file mode 100644
index b182f61e..00000000
--- a/fuzz/server_corpus/9fc76fdbf45c5c3b5464b9c0a94bb28945f7e0dc
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/a04653e24258549b1a8030ed1bc0bdf91df94d87 b/fuzz/server_corpus/a04653e24258549b1a8030ed1bc0bdf91df94d87
deleted file mode 100644
index e69c702c..00000000
--- a/fuzz/server_corpus/a04653e24258549b1a8030ed1bc0bdf91df94d87
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/a07be10e0f08da224595bfa5e686165755f2de77 b/fuzz/server_corpus/a07be10e0f08da224595bfa5e686165755f2de77
deleted file mode 100644
index 848e11a3..00000000
--- a/fuzz/server_corpus/a07be10e0f08da224595bfa5e686165755f2de77
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/a239133c8b8600e62206633d3da02c8fd7a46399 b/fuzz/server_corpus/a239133c8b8600e62206633d3da02c8fd7a46399
deleted file mode 100644
index 601afcab..00000000
--- a/fuzz/server_corpus/a239133c8b8600e62206633d3da02c8fd7a46399
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b b/fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b
new file mode 100644
index 00000000..f8bcb04e
--- /dev/null
+++ b/fuzz/server_corpus/a38b5e4d0ec3ea571a38c35c2ed3c72772c4732b
Binary files differ
diff --git a/fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3ac b/fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3ac
new file mode 100644
index 00000000..5c9c674f
--- /dev/null
+++ b/fuzz/server_corpus/a499e6063ea86dada60bc06951f13039e9c1f3ac
Binary files differ
diff --git a/fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5 b/fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5
new file mode 100644
index 00000000..96e5a925
--- /dev/null
+++ b/fuzz/server_corpus/a501e54923687ec3b05c49c06457d145342f47f5
Binary files differ
diff --git a/fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39ac b/fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39ac
new file mode 100644
index 00000000..8621d3ef
--- /dev/null
+++ b/fuzz/server_corpus/a6d011ffcc98cf16234a7d20ccd4db30809b39ac
Binary files differ
diff --git a/fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9 b/fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9
new file mode 100644
index 00000000..1d2f6cc5
--- /dev/null
+++ b/fuzz/server_corpus/a7b732b28fef3a7d2797d793c1d972f3460e50c9
Binary files differ
diff --git a/fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1a b/fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1a
new file mode 100644
index 00000000..14d15477
--- /dev/null
+++ b/fuzz/server_corpus/a805ac78ea5ac34b9f16d1db6a2586bebb804d1a
Binary files differ
diff --git a/fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786b b/fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786b
new file mode 100644
index 00000000..329cbf8f
--- /dev/null
+++ b/fuzz/server_corpus/a851fcf09f23a5980550492a7b6a9af5e55c786b
Binary files differ
diff --git a/fuzz/server_corpus/a894fe7af5ae98da6ae8220acd2284105b637607 b/fuzz/server_corpus/a894fe7af5ae98da6ae8220acd2284105b637607
deleted file mode 100644
index bb29f7f4..00000000
--- a/fuzz/server_corpus/a894fe7af5ae98da6ae8220acd2284105b637607
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085f b/fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085f
new file mode 100644
index 00000000..778f1222
--- /dev/null
+++ b/fuzz/server_corpus/a94773a424fb3dd39e61ef294cce3a226002085f
Binary files differ
diff --git a/fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715 b/fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715
new file mode 100644
index 00000000..a13ec20a
--- /dev/null
+++ b/fuzz/server_corpus/a9aaf8b0c4396ca9a8905c257cadad38b015f715
Binary files differ
diff --git a/fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cb b/fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cb
new file mode 100644
index 00000000..18e012b1
--- /dev/null
+++ b/fuzz/server_corpus/abbc509bc116d4cb303b4efc226110e3d2b1f9cb
Binary files differ
diff --git a/fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75 b/fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75
new file mode 100644
index 00000000..5f91127d
--- /dev/null
+++ b/fuzz/server_corpus/ad657af7ec670f63bf7b699bfc2d7784d9679c75
Binary files differ
diff --git a/fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498 b/fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498
new file mode 100644
index 00000000..981d72ca
--- /dev/null
+++ b/fuzz/server_corpus/adbf34bf3b6c339e3aedeb5bda369026f1041498
Binary files differ
diff --git a/fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79 b/fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79
new file mode 100644
index 00000000..7a2da9f4
--- /dev/null
+++ b/fuzz/server_corpus/ae1addcfe82e6e924c3d5186aebc7f4595a34f79
Binary files differ
diff --git a/fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221b b/fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221b
new file mode 100644
index 00000000..5f40826c
--- /dev/null
+++ b/fuzz/server_corpus/afb52e07276941f1176601b4855bf5d96773221b
Binary files differ
diff --git a/fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27 b/fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27
new file mode 100644
index 00000000..b21b6022
--- /dev/null
+++ b/fuzz/server_corpus/b0d31fd682c73610a7879d9f4932388b95d0bc27
Binary files differ
diff --git a/fuzz/server_corpus/b15e07a299b22507059c03efdfcba56e4451ce38 b/fuzz/server_corpus/b15e07a299b22507059c03efdfcba56e4451ce38
deleted file mode 100644
index 5c27acd2..00000000
--- a/fuzz/server_corpus/b15e07a299b22507059c03efdfcba56e4451ce38
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/b31b285a8d1786c2cf196026bfbec9858c6b22e3 b/fuzz/server_corpus/b31b285a8d1786c2cf196026bfbec9858c6b22e3
deleted file mode 100644
index f30a9be4..00000000
--- a/fuzz/server_corpus/b31b285a8d1786c2cf196026bfbec9858c6b22e3
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74 b/fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74
new file mode 100644
index 00000000..e42d3e90
--- /dev/null
+++ b/fuzz/server_corpus/b3c32ca3d0de7706ec31c174e56d3f3a02a29e74
Binary files differ
diff --git a/fuzz/server_corpus/b4bfe396d8dc5ac821725464c5fb36a09fe0530c b/fuzz/server_corpus/b4bfe396d8dc5ac821725464c5fb36a09fe0530c
deleted file mode 100644
index 98875f61..00000000
--- a/fuzz/server_corpus/b4bfe396d8dc5ac821725464c5fb36a09fe0530c
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518c b/fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518c
new file mode 100644
index 00000000..248229a1
--- /dev/null
+++ b/fuzz/server_corpus/b5a0df0a67120a113aaa8e66d2a89e92eb83518c
Binary files differ
diff --git a/fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938 b/fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938
new file mode 100644
index 00000000..9fca7cf4
--- /dev/null
+++ b/fuzz/server_corpus/b635afc6b7eb4837e06e295a0b7be1dd4304c938
Binary files differ
diff --git a/fuzz/server_corpus/b63a416f846daa9a2dcb166848461797dba4e312 b/fuzz/server_corpus/b63a416f846daa9a2dcb166848461797dba4e312
deleted file mode 100644
index 9ff13e04..00000000
--- a/fuzz/server_corpus/b63a416f846daa9a2dcb166848461797dba4e312
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571 b/fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571
new file mode 100644
index 00000000..b5baa8be
--- /dev/null
+++ b/fuzz/server_corpus/b68c52bcc48b4828c3b9c0a1e549333b33fc3571
Binary files differ
diff --git a/fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9b b/fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9b
new file mode 100644
index 00000000..e95a34a1
--- /dev/null
+++ b/fuzz/server_corpus/b6a51620f85e0bf69b534402b0d0397ceb834e9b
Binary files differ
diff --git a/fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902f b/fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902f
new file mode 100644
index 00000000..79fa0289
--- /dev/null
+++ b/fuzz/server_corpus/b6b9e9149d9da8a20823ddd794b17f3e07c5902f
Binary files differ
diff --git a/fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368 b/fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368
new file mode 100644
index 00000000..f4b7f477
--- /dev/null
+++ b/fuzz/server_corpus/b6cc929d3a3e0c526463b451e5a9e3b00d105368
Binary files differ
diff --git a/fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32 b/fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32
new file mode 100644
index 00000000..67681901
--- /dev/null
+++ b/fuzz/server_corpus/b6e477f0159ebe9a37e048602f357a148ddb3b32
Binary files differ
diff --git a/fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257 b/fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257
new file mode 100644
index 00000000..63ba0b0b
--- /dev/null
+++ b/fuzz/server_corpus/b7801a9236dd2281a0acc933019224d6c1dbf257
Binary files differ
diff --git a/fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5e b/fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5e
new file mode 100644
index 00000000..6b937d84
--- /dev/null
+++ b/fuzz/server_corpus/b832a18069022b70323d9a0ccdf38a6bd3d9aa5e
Binary files differ
diff --git a/fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7e b/fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7e
new file mode 100644
index 00000000..c6e45f62
--- /dev/null
+++ b/fuzz/server_corpus/b8a03d1b641ed88f0951d04943b8a07050370f7e
Binary files differ
diff --git a/fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bf b/fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bf
new file mode 100644
index 00000000..e5457d8b
--- /dev/null
+++ b/fuzz/server_corpus/b8dbc8daf864513bd67dfd27651067ec8cee20bf
Binary files differ
diff --git a/fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9c b/fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9c
new file mode 100644
index 00000000..83c409b9
--- /dev/null
+++ b/fuzz/server_corpus/b9331377e2a9f03a15649ff1ed311d9c70057b9c
Binary files differ
diff --git a/fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8 b/fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8
new file mode 100644
index 00000000..96dd7ba8
--- /dev/null
+++ b/fuzz/server_corpus/bcbe93c3346d8dc6de9b6db6963d7787440498a8
Binary files differ
diff --git a/fuzz/server_corpus/bd35db56de383d4c9ec3c2834270f4a062385022 b/fuzz/server_corpus/bd35db56de383d4c9ec3c2834270f4a062385022
deleted file mode 100644
index 49bb4ded..00000000
--- a/fuzz/server_corpus/bd35db56de383d4c9ec3c2834270f4a062385022
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7f b/fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7f
new file mode 100644
index 00000000..19bc5c99
--- /dev/null
+++ b/fuzz/server_corpus/bf85c5738caa0751b6192e3f2210153e16190e7f
Binary files differ
diff --git a/fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72 b/fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72
new file mode 100644
index 00000000..026b1013
--- /dev/null
+++ b/fuzz/server_corpus/c095ac0fc0793343959fb8ce7b9f0a448a679a72
Binary files differ
diff --git a/fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246 b/fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246
new file mode 100644
index 00000000..11e51f59
--- /dev/null
+++ b/fuzz/server_corpus/c0b121e41d0a429854a5967bd6d1367414333246
Binary files differ
diff --git a/fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0 b/fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0
new file mode 100644
index 00000000..d0802689
--- /dev/null
+++ b/fuzz/server_corpus/c1324667e62ed6cc878ebab4c7e8a8ce4cb7dbe0
Binary files differ
diff --git a/fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abb b/fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abb
new file mode 100644
index 00000000..79e8819c
--- /dev/null
+++ b/fuzz/server_corpus/c2316b3de8f79e6021ba25dc3522c440cce56abb
Binary files differ
diff --git a/fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8d b/fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8d
new file mode 100644
index 00000000..e37f867c
--- /dev/null
+++ b/fuzz/server_corpus/c25117880ac0e46d72797ac80e67ea5c8d8d0e8d
Binary files differ
diff --git a/fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8 b/fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8
new file mode 100644
index 00000000..aa63ecf0
--- /dev/null
+++ b/fuzz/server_corpus/c367c8c9fb925f801d2b3a21bf1738ee5cfe57a8
Binary files differ
diff --git a/fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84 b/fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84
new file mode 100644
index 00000000..dec01c1f
--- /dev/null
+++ b/fuzz/server_corpus/c39ffbdda14f7196ff35c67a2589bcd873e07e84
Binary files differ
diff --git a/fuzz/server_corpus/c403d080cf1affbebce0dddc32091a8f5cbeae9f b/fuzz/server_corpus/c403d080cf1affbebce0dddc32091a8f5cbeae9f
deleted file mode 100644
index f4365fe7..00000000
--- a/fuzz/server_corpus/c403d080cf1affbebce0dddc32091a8f5cbeae9f
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/c410f6d6cfad7593f57d1ddb73d9d9eca03e5267 b/fuzz/server_corpus/c410f6d6cfad7593f57d1ddb73d9d9eca03e5267
deleted file mode 100644
index 1894c3db..00000000
--- a/fuzz/server_corpus/c410f6d6cfad7593f57d1ddb73d9d9eca03e5267
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25 b/fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25
new file mode 100644
index 00000000..5bd24ee0
--- /dev/null
+++ b/fuzz/server_corpus/c4530fd98a3f55c874638e7703b4755dcbf03d25
Binary files differ
diff --git a/fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40ee b/fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40ee
new file mode 100644
index 00000000..1d59155c
--- /dev/null
+++ b/fuzz/server_corpus/c488daaa980c5b4637c14a7a9dba41f905ad40ee
Binary files differ
diff --git a/fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671 b/fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671
new file mode 100644
index 00000000..6e17df01
--- /dev/null
+++ b/fuzz/server_corpus/c4e90f27e3780d2596c565dbc6b23e8a62a32671
Binary files differ
diff --git a/fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122 b/fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122
new file mode 100644
index 00000000..112e8ce6
--- /dev/null
+++ b/fuzz/server_corpus/c5d128e9ef95c5ea1941b1583bf5d67433efa122
Binary files differ
diff --git a/fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910 b/fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910
new file mode 100644
index 00000000..782e94e4
--- /dev/null
+++ b/fuzz/server_corpus/c6f9e5c4cc9a6f8af4df7e633ba7267244810910
Binary files differ
diff --git a/fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3ac b/fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3ac
new file mode 100644
index 00000000..bc2aab61
--- /dev/null
+++ b/fuzz/server_corpus/c783f8c9cfb382374aa8359a3ecdd689140aa3ac
Binary files differ
diff --git a/fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7 b/fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7
new file mode 100644
index 00000000..9898ee46
--- /dev/null
+++ b/fuzz/server_corpus/c83f7080ddbe04198dd715887ca44666a1fb29b7
Binary files differ
diff --git a/fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970 b/fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970
new file mode 100644
index 00000000..13a0f6d1
--- /dev/null
+++ b/fuzz/server_corpus/c877371f7bb5a27b25fd354f7643c95481f7c970
Binary files differ
diff --git a/fuzz/server_corpus/c94f15684be5de1fe2272367a968c9bfc6bc4064 b/fuzz/server_corpus/c94f15684be5de1fe2272367a968c9bfc6bc4064
deleted file mode 100644
index e8f598df..00000000
--- a/fuzz/server_corpus/c94f15684be5de1fe2272367a968c9bfc6bc4064
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/c9cf42a05289ee11b545fb3b7a33620e7609791e b/fuzz/server_corpus/c9cf42a05289ee11b545fb3b7a33620e7609791e
deleted file mode 100644
index 874cbaf2..00000000
--- a/fuzz/server_corpus/c9cf42a05289ee11b545fb3b7a33620e7609791e
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590d b/fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590d
new file mode 100644
index 00000000..66826871
--- /dev/null
+++ b/fuzz/server_corpus/cb3f92a2f51c86bd52c598116e73e393d003590d
Binary files differ
diff --git a/fuzz/server_corpus/cb4ea46b40db7f46626bcf377a30484adc2f0464 b/fuzz/server_corpus/cb4ea46b40db7f46626bcf377a30484adc2f0464
deleted file mode 100644
index caa66130..00000000
--- a/fuzz/server_corpus/cb4ea46b40db7f46626bcf377a30484adc2f0464
+++ /dev/null
@@ -1 +0,0 @@
-*);)(*; \ No newline at end of file
diff --git a/fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2 b/fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2
new file mode 100644
index 00000000..f46c0a38
--- /dev/null
+++ b/fuzz/server_corpus/cc060d9eb0217741ce6e78b428aad5e49f26d6a2
Binary files differ
diff --git a/fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800 b/fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800
new file mode 100644
index 00000000..36bc114f
--- /dev/null
+++ b/fuzz/server_corpus/ccaa1ac7731c409ffde2f89e8cbf71bc7b1a3800
Binary files differ
diff --git a/fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc b/fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc
new file mode 100644
index 00000000..50de2c0a
--- /dev/null
+++ b/fuzz/server_corpus/ccf7f63d6c7c9cb39f7ab1e160f2f6a98bce67dc
Binary files differ
diff --git a/fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743 b/fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743
new file mode 100644
index 00000000..7e748ccc
--- /dev/null
+++ b/fuzz/server_corpus/cea030f4e5beef22bd9892408a0708bdaf3c3743
Binary files differ
diff --git a/fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75 b/fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75
new file mode 100644
index 00000000..f4517e63
--- /dev/null
+++ b/fuzz/server_corpus/cfeda2740e1750c2a71175a21457eb3359d36e75
Binary files differ
diff --git a/fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912 b/fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912
new file mode 100644
index 00000000..b8f7fdd4
--- /dev/null
+++ b/fuzz/server_corpus/cff5833dd4809d38118c760600d7a4a06fb63912
Binary files differ
diff --git a/fuzz/server_corpus/d033c7d8801423bf221f9c3100a11f430e77ae7f b/fuzz/server_corpus/d033c7d8801423bf221f9c3100a11f430e77ae7f
deleted file mode 100644
index 7a53e730..00000000
--- a/fuzz/server_corpus/d033c7d8801423bf221f9c3100a11f430e77ae7f
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9 b/fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9
new file mode 100644
index 00000000..d74dbd89
--- /dev/null
+++ b/fuzz/server_corpus/d044e375a03f40f24ca4fa054419d5425912d8f9
Binary files differ
diff --git a/fuzz/server_corpus/d05db6bc123e01b5d8369d712adb0bd381a37cbd b/fuzz/server_corpus/d05db6bc123e01b5d8369d712adb0bd381a37cbd
deleted file mode 100644
index b86d3355..00000000
--- a/fuzz/server_corpus/d05db6bc123e01b5d8369d712adb0bd381a37cbd
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488ce b/fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488ce
new file mode 100644
index 00000000..a80c920c
--- /dev/null
+++ b/fuzz/server_corpus/d0d6d66d04f08f11ad9fb417b8482b62a1c488ce
Binary files differ
diff --git a/fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6 b/fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6
new file mode 100644
index 00000000..335aacd2
--- /dev/null
+++ b/fuzz/server_corpus/d129f7b49f19f3ff63cc8b8c8b27757c3ba968e6
Binary files differ
diff --git a/fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9 b/fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9
new file mode 100644
index 00000000..53e21e5c
--- /dev/null
+++ b/fuzz/server_corpus/d1730107611b33be2922586c05825454c3bb9cc9
Binary files differ
diff --git a/fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079 b/fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079
new file mode 100644
index 00000000..2e9fc98b
--- /dev/null
+++ b/fuzz/server_corpus/d19c0da91a0bb15ee5b7b480ab2304557ba9c079
Binary files differ
diff --git a/fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799 b/fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799
new file mode 100644
index 00000000..84352df8
--- /dev/null
+++ b/fuzz/server_corpus/d2c6c9be5638d2a45f14c15f4f73c14f3ef59799
Binary files differ
diff --git a/fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767e b/fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767e
new file mode 100644
index 00000000..274d55d3
--- /dev/null
+++ b/fuzz/server_corpus/d2ea7356790b71e17270aa885b1440228810767e
Binary files differ
diff --git a/fuzz/server_corpus/d3b4953343a95775199eb405d5949cb03a3578d8 b/fuzz/server_corpus/d3b4953343a95775199eb405d5949cb03a3578d8
deleted file mode 100644
index 2298b1c8..00000000
--- a/fuzz/server_corpus/d3b4953343a95775199eb405d5949cb03a3578d8
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773 b/fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773
new file mode 100644
index 00000000..53b3eca0
--- /dev/null
+++ b/fuzz/server_corpus/d3cf42aee90dedb4148eba308eaa0087219d8773
Binary files differ
diff --git a/fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72 b/fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72
new file mode 100644
index 00000000..af49b1ca
--- /dev/null
+++ b/fuzz/server_corpus/d47d2dc334230da3acf3f34b782e2fbb79dcce72
Binary files differ
diff --git a/fuzz/server_corpus/d5b66a02820057294711f8c80650bd921b8c8600 b/fuzz/server_corpus/d5b66a02820057294711f8c80650bd921b8c8600
deleted file mode 100644
index dfc239b2..00000000
--- a/fuzz/server_corpus/d5b66a02820057294711f8c80650bd921b8c8600
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60 b/fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60
new file mode 100644
index 00000000..c9d409fc
--- /dev/null
+++ b/fuzz/server_corpus/d7247e3132134e04b695907afdce71681fe30f60
Binary files differ
diff --git a/fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447 b/fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447
new file mode 100644
index 00000000..76012ddd
--- /dev/null
+++ b/fuzz/server_corpus/d741dcf9b121e34a0141845b9329ea92f15ff447
Binary files differ
diff --git a/fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27 b/fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27
new file mode 100644
index 00000000..9f2f3ec0
--- /dev/null
+++ b/fuzz/server_corpus/d757fd2f32ef978a9d45f8dc90c1c310d6cdfc27
Binary files differ
diff --git a/fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8 b/fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8
new file mode 100644
index 00000000..00cd2d20
--- /dev/null
+++ b/fuzz/server_corpus/d8425676bd4a9091fee7680cc80ec7003a8230c8
Binary files differ
diff --git a/fuzz/server_corpus/d89bbcf5a9f5e1684061db8481080ded6fa79f13 b/fuzz/server_corpus/d89bbcf5a9f5e1684061db8481080ded6fa79f13
deleted file mode 100644
index 54986c19..00000000
--- a/fuzz/server_corpus/d89bbcf5a9f5e1684061db8481080ded6fa79f13
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1 b/fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1
new file mode 100644
index 00000000..8eeb76f2
--- /dev/null
+++ b/fuzz/server_corpus/d8f891994e13e538a9ad177d687423c92cc9a6c1
Binary files differ
diff --git a/fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0 b/fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0
new file mode 100644
index 00000000..24bbcf3e
--- /dev/null
+++ b/fuzz/server_corpus/d94aefab9d08d20cd1703e87f92501579ddb9fe0
Binary files differ
diff --git a/fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677 b/fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677
new file mode 100644
index 00000000..17a62800
--- /dev/null
+++ b/fuzz/server_corpus/d95337213aefb62a5cac46bca1b4bc2c61538677
Binary files differ
diff --git a/fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434 b/fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434
new file mode 100644
index 00000000..57ea4bd6
--- /dev/null
+++ b/fuzz/server_corpus/d9d4ac3b729317fced3cd857d1c6b1896b798434
Binary files differ
diff --git a/fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9a b/fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9a
new file mode 100644
index 00000000..ad663344
--- /dev/null
+++ b/fuzz/server_corpus/daf8423d0e1956a5daa501ed104e5b6d08cf4e9a
Binary files differ
diff --git a/fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e b/fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e
new file mode 100644
index 00000000..d228ed57
--- /dev/null
+++ b/fuzz/server_corpus/db8c5c0ef970ec9116de7b29a6af3f15d3a6df3e
Binary files differ
diff --git a/fuzz/server_corpus/dc429b08b66a1dcdd8d09991a41c041f00f1a671 b/fuzz/server_corpus/dc429b08b66a1dcdd8d09991a41c041f00f1a671
deleted file mode 100644
index 04fbfb6e..00000000
--- a/fuzz/server_corpus/dc429b08b66a1dcdd8d09991a41c041f00f1a671
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5 b/fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5
new file mode 100644
index 00000000..7ccbdb4e
--- /dev/null
+++ b/fuzz/server_corpus/dcd0ac87b1cae69418b6f6f95154186f6f039dd5
Binary files differ
diff --git a/fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5f b/fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5f
new file mode 100644
index 00000000..75751599
--- /dev/null
+++ b/fuzz/server_corpus/dcf711a0bfa12e4616d3b644d381cb75d3113a5f
Binary files differ
diff --git a/fuzz/server_corpus/dd2546c77bfdc7ce8418aee8d4b637a854cc20c7 b/fuzz/server_corpus/dd2546c77bfdc7ce8418aee8d4b637a854cc20c7
deleted file mode 100644
index 14122477..00000000
--- a/fuzz/server_corpus/dd2546c77bfdc7ce8418aee8d4b637a854cc20c7
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155 b/fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155
new file mode 100644
index 00000000..36d06275
--- /dev/null
+++ b/fuzz/server_corpus/ddca9eec2e1401c8c1f7dc2fe7c2a6e2a187b155
Binary files differ
diff --git a/fuzz/server_corpus/df656c7ba5c20e78362830e3ef5b4fc39e80f6a0 b/fuzz/server_corpus/df656c7ba5c20e78362830e3ef5b4fc39e80f6a0
deleted file mode 100644
index de79facd..00000000
--- a/fuzz/server_corpus/df656c7ba5c20e78362830e3ef5b4fc39e80f6a0
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0e b/fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0e
new file mode 100644
index 00000000..f10b53b5
--- /dev/null
+++ b/fuzz/server_corpus/dfc889e877441114c78c93a2c27862d90b8ceb0e
Binary files differ
diff --git a/fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1 b/fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1
new file mode 100644
index 00000000..f7359ff8
--- /dev/null
+++ b/fuzz/server_corpus/e0c910a95189f32b6f53ae4738352abd5a02bae1
Binary files differ
diff --git a/fuzz/server_corpus/e19d0f7a58cf60af5ab08b380a1a4fce93c28930 b/fuzz/server_corpus/e19d0f7a58cf60af5ab08b380a1a4fce93c28930
deleted file mode 100644
index f1d9f59d..00000000
--- a/fuzz/server_corpus/e19d0f7a58cf60af5ab08b380a1a4fce93c28930
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/e208b4ef816f4d964426345d782bc3a9d009e515 b/fuzz/server_corpus/e208b4ef816f4d964426345d782bc3a9d009e515
deleted file mode 100644
index 839fb179..00000000
--- a/fuzz/server_corpus/e208b4ef816f4d964426345d782bc3a9d009e515
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/e28cb4459b7e5473200931b48e935805a8e6981b b/fuzz/server_corpus/e28cb4459b7e5473200931b48e935805a8e6981b
deleted file mode 100644
index 20830f68..00000000
--- a/fuzz/server_corpus/e28cb4459b7e5473200931b48e935805a8e6981b
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/e2f78c652cc04edb51f9afaf8a1cf45e87d64ca8 b/fuzz/server_corpus/e2f78c652cc04edb51f9afaf8a1cf45e87d64ca8
deleted file mode 100644
index 81d9ea06..00000000
--- a/fuzz/server_corpus/e2f78c652cc04edb51f9afaf8a1cf45e87d64ca8
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11 b/fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11
new file mode 100644
index 00000000..7db1b160
--- /dev/null
+++ b/fuzz/server_corpus/e4cd6455558a3a56b6cc322044eb2e76bb204c11
Binary files differ
diff --git a/fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846e b/fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846e
new file mode 100644
index 00000000..3235a01b
--- /dev/null
+++ b/fuzz/server_corpus/e4f601c4530865ed5c238194692199b65cf6846e
Binary files differ
diff --git a/fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60 b/fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60
new file mode 100644
index 00000000..4dde4ce3
--- /dev/null
+++ b/fuzz/server_corpus/e58ab0cf342c2e3f7d71b68e7a18e219f86b9a60
Binary files differ
diff --git a/fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf b/fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf
new file mode 100644
index 00000000..e7a5d3ad
--- /dev/null
+++ b/fuzz/server_corpus/e5adcc3d74b69a26f7dd56c70d37ffd8e472a1bf
Binary files differ
diff --git a/fuzz/server_corpus/e5b19696b772ec3b5f68e10e5022a65377d1edf7 b/fuzz/server_corpus/e5b19696b772ec3b5f68e10e5022a65377d1edf7
deleted file mode 100644
index dd885863..00000000
--- a/fuzz/server_corpus/e5b19696b772ec3b5f68e10e5022a65377d1edf7
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3c b/fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3c
new file mode 100644
index 00000000..2eb68a2d
--- /dev/null
+++ b/fuzz/server_corpus/e76d51463070189be289c46db1fef08f8c44ce3c
Binary files differ
diff --git a/fuzz/server_corpus/e7d86d43ca9db0835b3060862e06f653f9ec66ac b/fuzz/server_corpus/e7d86d43ca9db0835b3060862e06f653f9ec66ac
deleted file mode 100644
index c6dfca7d..00000000
--- a/fuzz/server_corpus/e7d86d43ca9db0835b3060862e06f653f9ec66ac
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2b b/fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2b
new file mode 100644
index 00000000..18ade57a
--- /dev/null
+++ b/fuzz/server_corpus/e7ef72fdab634ae7658cd862feaf944d0ea3ce2b
Binary files differ
diff --git a/fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557 b/fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557
new file mode 100644
index 00000000..28a5b87c
--- /dev/null
+++ b/fuzz/server_corpus/e82273fd2b509ffeaa0a06138fd48878b708c557
Binary files differ
diff --git a/fuzz/server_corpus/ea7ea348e64152ab70f5f54bcc1da81915a22506 b/fuzz/server_corpus/ea7ea348e64152ab70f5f54bcc1da81915a22506
deleted file mode 100644
index c1fa93c1..00000000
--- a/fuzz/server_corpus/ea7ea348e64152ab70f5f54bcc1da81915a22506
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/eab0cce27bc8b7edbfe0052aecb05edb3f0b941d b/fuzz/server_corpus/eab0cce27bc8b7edbfe0052aecb05edb3f0b941d
deleted file mode 100644
index 09d46c4b..00000000
--- a/fuzz/server_corpus/eab0cce27bc8b7edbfe0052aecb05edb3f0b941d
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874 b/fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874
new file mode 100644
index 00000000..0cd45062
--- /dev/null
+++ b/fuzz/server_corpus/ec1a7fa84fb643ff5d8c52e225edfd1605218874
Binary files differ
diff --git a/fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976 b/fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976
new file mode 100644
index 00000000..341bafa7
--- /dev/null
+++ b/fuzz/server_corpus/ec744f66e6351373f00a36829029d73d597cb976
Binary files differ
diff --git a/fuzz/server_corpus/ed379815625c97a8821c47db565c7b4284e1fe1d b/fuzz/server_corpus/ed379815625c97a8821c47db565c7b4284e1fe1d
deleted file mode 100644
index dd15182d..00000000
--- a/fuzz/server_corpus/ed379815625c97a8821c47db565c7b4284e1fe1d
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41dec b/fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41dec
new file mode 100644
index 00000000..a4c6030d
--- /dev/null
+++ b/fuzz/server_corpus/edd61df88481ddefc20a02e326ada5a6eaa41dec
Binary files differ
diff --git a/fuzz/server_corpus/ee6080e7aa0f9fd158ce42f1917f20332244d69c b/fuzz/server_corpus/ee6080e7aa0f9fd158ce42f1917f20332244d69c
deleted file mode 100644
index f10e0ed6..00000000
--- a/fuzz/server_corpus/ee6080e7aa0f9fd158ce42f1917f20332244d69c
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4 b/fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4
new file mode 100644
index 00000000..27e89115
--- /dev/null
+++ b/fuzz/server_corpus/eee65b9d72dd80d44e3d9f7fb7115503131bdad4
Binary files differ
diff --git a/fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679d b/fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679d
new file mode 100644
index 00000000..d891fe2f
--- /dev/null
+++ b/fuzz/server_corpus/eef1516de918dcc086d39edc23206bcc7715679d
Binary files differ
diff --git a/fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18 b/fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18
new file mode 100644
index 00000000..e13614bf
--- /dev/null
+++ b/fuzz/server_corpus/f06014fa4a9681f2e1e977e4bca8d86a575a8c18
Binary files differ
diff --git a/fuzz/server_corpus/f07ec159fd7bbb172e2821d911a9981ed26d90a1 b/fuzz/server_corpus/f07ec159fd7bbb172e2821d911a9981ed26d90a1
deleted file mode 100644
index 47a8b59c..00000000
--- a/fuzz/server_corpus/f07ec159fd7bbb172e2821d911a9981ed26d90a1
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30 b/fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30
new file mode 100644
index 00000000..4b416c84
--- /dev/null
+++ b/fuzz/server_corpus/f102f1e3eb74b2b872523c5bcfe1fa0de9d9da30
Binary files differ
diff --git a/fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86 b/fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86
new file mode 100644
index 00000000..45ea2044
--- /dev/null
+++ b/fuzz/server_corpus/f1d972ed5d10bcd4741c0f5eeee723ad245a6a86
Binary files differ
diff --git a/fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691b b/fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691b
new file mode 100644
index 00000000..c0b8495c
--- /dev/null
+++ b/fuzz/server_corpus/f219ee1ce52714fbdbd6e33c012ec4082efc691b
Binary files differ
diff --git a/fuzz/server_corpus/f3395540f28e50b851c15db0aad8443aa2b2a70f b/fuzz/server_corpus/f3395540f28e50b851c15db0aad8443aa2b2a70f
deleted file mode 100644
index 57545c69..00000000
--- a/fuzz/server_corpus/f3395540f28e50b851c15db0aad8443aa2b2a70f
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/f393d580ec06b3de83b72825b22087c99fbd18b3 b/fuzz/server_corpus/f393d580ec06b3de83b72825b22087c99fbd18b3
deleted file mode 100644
index 8bda2c3a..00000000
--- a/fuzz/server_corpus/f393d580ec06b3de83b72825b22087c99fbd18b3
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134a b/fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134a
new file mode 100644
index 00000000..34d168b8
--- /dev/null
+++ b/fuzz/server_corpus/f3c3c4eb731e6cfafa5b13667bf2928646d8134a
Binary files differ
diff --git a/fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322 b/fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322
new file mode 100644
index 00000000..1d2f857d
--- /dev/null
+++ b/fuzz/server_corpus/f465f74ff5a9e4248a332bf306f45cecd8314322
Binary files differ
diff --git a/fuzz/server_corpus/f5bd02993373de994d1ef28348706b7193a1509e b/fuzz/server_corpus/f5bd02993373de994d1ef28348706b7193a1509e
deleted file mode 100644
index f35e14db..00000000
--- a/fuzz/server_corpus/f5bd02993373de994d1ef28348706b7193a1509e
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9 b/fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9
new file mode 100644
index 00000000..32b3d384
--- /dev/null
+++ b/fuzz/server_corpus/f7bf8c5ec7a71cf8a7f713279901817705eb6ab9
Binary files differ
diff --git a/fuzz/server_corpus/f7e8f0def8a249d042f68fe2a0b5e31d23fbafee b/fuzz/server_corpus/f7e8f0def8a249d042f68fe2a0b5e31d23fbafee
deleted file mode 100644
index 1fc76ff5..00000000
--- a/fuzz/server_corpus/f7e8f0def8a249d042f68fe2a0b5e31d23fbafee
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6 b/fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6
new file mode 100644
index 00000000..ee717486
--- /dev/null
+++ b/fuzz/server_corpus/f80cb481d2d6d253dd4fe0140055a69699ae8fe6
Binary files differ
diff --git a/fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0b b/fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0b
new file mode 100644
index 00000000..a6c5c44f
--- /dev/null
+++ b/fuzz/server_corpus/f8c000e8f3090950de2c5c1844a45c9148fb9a0b
Binary files differ
diff --git a/fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149e b/fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149e
new file mode 100644
index 00000000..972ff639
--- /dev/null
+++ b/fuzz/server_corpus/f93d7c03d0cdf7ca4313c80a2912ffb1c512149e
Binary files differ
diff --git a/fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82 b/fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82
new file mode 100644
index 00000000..cfbf8d11
--- /dev/null
+++ b/fuzz/server_corpus/f968e146e317dbb5281aca4634de84461fd1ff82
Binary files differ
diff --git a/fuzz/server_corpus/f9d559051861eb3b763b00700696e730beb170b1 b/fuzz/server_corpus/f9d559051861eb3b763b00700696e730beb170b1
deleted file mode 100644
index 72985f16..00000000
--- a/fuzz/server_corpus/f9d559051861eb3b763b00700696e730beb170b1
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1 b/fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1
new file mode 100644
index 00000000..3e346fd2
--- /dev/null
+++ b/fuzz/server_corpus/fa1a1093d1da4f71b18d30481f09eeb7d61e6de1
Binary files differ
diff --git a/fuzz/server_corpus/fa3f57c938561581946d3707058b7f7b8686d259 b/fuzz/server_corpus/fa3f57c938561581946d3707058b7f7b8686d259
deleted file mode 100644
index 6429ca9f..00000000
--- a/fuzz/server_corpus/fa3f57c938561581946d3707058b7f7b8686d259
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/fa556d46b2eca915290c9cbadc192ea9c1917117 b/fuzz/server_corpus/fa556d46b2eca915290c9cbadc192ea9c1917117
deleted file mode 100644
index b46290f2..00000000
--- a/fuzz/server_corpus/fa556d46b2eca915290c9cbadc192ea9c1917117
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685 b/fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685
new file mode 100644
index 00000000..e16b31f8
--- /dev/null
+++ b/fuzz/server_corpus/fa929c8218dd1b0676db695576a8f1a66067c685
Binary files differ
diff --git a/fuzz/server_corpus/fae5fdce7b5b57550c05aab5d8ac738beb4eaa1a b/fuzz/server_corpus/fae5fdce7b5b57550c05aab5d8ac738beb4eaa1a
deleted file mode 100644
index f55a2f07..00000000
--- a/fuzz/server_corpus/fae5fdce7b5b57550c05aab5d8ac738beb4eaa1a
+++ /dev/null
Binary files differ
diff --git a/fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99 b/fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99
new file mode 100644
index 00000000..c0d36960
--- /dev/null
+++ b/fuzz/server_corpus/fba6554348b195a4752225342ded315662a11a99
Binary files differ
diff --git a/fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38 b/fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38
new file mode 100644
index 00000000..345895c4
--- /dev/null
+++ b/fuzz/server_corpus/fc0f2acceb87b5396e0a10054b7ca35a2a124f38
Binary files differ
diff --git a/fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61 b/fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61
new file mode 100644
index 00000000..539f0a14
--- /dev/null
+++ b/fuzz/server_corpus/fcf1e81b7005c8aea37b5d8f0949a5d3048caf61
Binary files differ
diff --git a/fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07db b/fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07db
new file mode 100644
index 00000000..a0b073dc
--- /dev/null
+++ b/fuzz/server_corpus/feb2a10cc688251772b52cbdf910f45130ed07db
Binary files differ
diff --git a/fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602 b/fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602
new file mode 100644
index 00000000..515f40f0
--- /dev/null
+++ b/fuzz/server_corpus/fed06ee7931bb35a7cfdc9699f928df530bc2602
Binary files differ
diff --git a/fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0f b/fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0f
new file mode 100644
index 00000000..583d85bf
--- /dev/null
+++ b/fuzz/server_corpus/ff01b583eddbccbe7c7ea08e7f83873310d91f0f
Binary files differ
diff --git a/fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439 b/fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439
new file mode 100644
index 00000000..87d99998
--- /dev/null
+++ b/fuzz/server_corpus/ff164d41110cbdcf7b035bd2eeb1c0fdabeaf439
Binary files differ
diff --git a/fuzz/server_corpus/ffd7d5299d017ec7104e3e6a744f4b946461e7f3 b/fuzz/server_corpus/ffd7d5299d017ec7104e3e6a744f4b946461e7f3
deleted file mode 100644
index ccb6736f..00000000
--- a/fuzz/server_corpus/ffd7d5299d017ec7104e3e6a744f4b946461e7f3
+++ /dev/null
Binary files differ
diff --git a/fuzz/spki.cc b/fuzz/spki.cc
new file mode 100644
index 00000000..939d7196
--- /dev/null
+++ b/fuzz/spki.cc
@@ -0,0 +1,38 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/bytestring.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
+ CBS cbs;
+ CBS_init(&cbs, buf, len);
+ EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
+ if (pkey == NULL) {
+ return 0;
+ }
+
+ uint8_t *der;
+ size_t der_len;
+ CBB cbb;
+ if (CBB_init(&cbb, 0) &&
+ EVP_marshal_public_key(&cbb, pkey) &&
+ CBB_finish(&cbb, &der, &der_len)) {
+ OPENSSL_free(der);
+ }
+ CBB_cleanup(&cbb);
+ EVP_PKEY_free(pkey);
+ return 0;
+}
diff --git a/fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263ee b/fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263ee
new file mode 100644
index 00000000..d1eac6d5
--- /dev/null
+++ b/fuzz/spki_corpus/04f58baf6e4bba0bb3094e2e26d3a531a7c263ee
Binary files differ
diff --git a/fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3a b/fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3a
new file mode 100644
index 00000000..a6eb9d4c
--- /dev/null
+++ b/fuzz/spki_corpus/079bdf85c086ad0a92bd01f1f70c645d81053f3a
Binary files differ
diff --git a/fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548f b/fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548f
new file mode 100644
index 00000000..2bd95c3b
--- /dev/null
+++ b/fuzz/spki_corpus/0f5bd094b20a4632f14903bf62db8d467d2c548f
Binary files differ
diff --git a/fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587 b/fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587
new file mode 100644
index 00000000..e3a1ed7b
--- /dev/null
+++ b/fuzz/spki_corpus/183c579d75863c1e10100f76e3ffb757b44a9587
Binary files differ
diff --git a/fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0c b/fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0c
new file mode 100644
index 00000000..471dddf6
--- /dev/null
+++ b/fuzz/spki_corpus/4ee178363e1d8411f30e540cb97d550d4ce62f0c
Binary files differ
diff --git a/fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915 b/fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915
new file mode 100644
index 00000000..e6deda10
--- /dev/null
+++ b/fuzz/spki_corpus/70da87d1d374ade329433dde31805abc8d80d915
Binary files differ
diff --git a/fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00 b/fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00
new file mode 100644
index 00000000..81cbe26f
--- /dev/null
+++ b/fuzz/spki_corpus/de0338b0c809548dc79d5a34e28b0010852a8f00
Binary files differ
diff --git a/fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6 b/fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6
new file mode 100644
index 00000000..10e16744
--- /dev/null
+++ b/fuzz/spki_corpus/fc941f77c710354d3c3c1426432a5ee935d51dd6
Binary files differ
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index 092d2f62..7895825c 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -135,49 +135,6 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void);
OPENSSL_EXPORT int EVP_has_aes_hardware(void);
-/* TLS-specific AEAD algorithms.
- *
- * These AEAD primitives do not meet the definition of generic AEADs. They are
- * all specific to TLS and should not be used outside of that context. They must
- * be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, and may
- * not be used concurrently. Any nonces are used as IVs, so they must be
- * unpredictable. They only accept an |ad| parameter of length 11 (the standard
- * TLS one with length omitted). */
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_tls(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_tls(void);
-
-
-/* SSLv3-specific AEAD algorithms.
- *
- * These AEAD primitives do not meet the definition of generic AEADs. They are
- * all specific to SSLv3 and should not be used outside of that context. They
- * must be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful,
- * and may not be used concurrently. They only accept an |ad| parameter of
- * length 9 (the standard TLS one with length and version omitted). */
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_ssl3(void);
-
-
/* Utility functions. */
/* EVP_AEAD_key_length returns the length, in bytes, of the keys used by
@@ -226,12 +183,6 @@ typedef struct evp_aead_ctx_st {
* be used. */
#define EVP_AEAD_DEFAULT_TAG_LENGTH 0
-/* evp_aead_direction_t denotes the direction of an AEAD operation. */
-enum evp_aead_direction_t {
- evp_aead_open,
- evp_aead_seal,
-};
-
/* EVP_AEAD_CTX_zero sets an uninitialized |ctx| to the zero state. It must be
* initialized with |EVP_AEAD_CTX_init| before use. It is safe, but not
* necessary, to call |EVP_AEAD_CTX_cleanup| in this state. This may be used for
@@ -251,13 +202,6 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len,
size_t tag_len, ENGINE *impl);
-/* EVP_AEAD_CTX_init_with_direction calls |EVP_AEAD_CTX_init| for normal
- * AEADs. For TLS-specific and SSL3-specific AEADs, it initializes |ctx| for a
- * given direction. */
-OPENSSL_EXPORT int EVP_AEAD_CTX_init_with_direction(
- EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, const uint8_t *key, size_t key_len,
- size_t tag_len, enum evp_aead_direction_t dir);
-
/* EVP_AEAD_CTX_cleanup frees any data allocated by |ctx|. It is a no-op to
* call |EVP_AEAD_CTX_cleanup| on a |EVP_AEAD_CTX| that has been |memset| to
* all zeros. */
@@ -282,7 +226,7 @@ OPENSSL_EXPORT void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx);
* insufficient, zero will be returned. (In this case, |*out_len| is set to
* zero.)
*
- * If |in| and |out| alias then |out| must be <= |in|. */
+ * If |in| and |out| alias then |out| must be == |in|. */
OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
@@ -307,7 +251,7 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
* insufficient, zero will be returned. (In this case, |*out_len| is set to
* zero.)
*
- * If |in| and |out| alias then |out| must be <= |in|. */
+ * If |in| and |out| alias then |out| must be == |in|. */
OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
@@ -315,8 +259,64 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *ad, size_t ad_len);
+/* TLS-specific AEAD algorithms.
+ *
+ * These AEAD primitives do not meet the definition of generic AEADs. They are
+ * all specific to TLS and should not be used outside of that context. They must
+ * be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, and may
+ * not be used concurrently. Any nonces are used as IVs, so they must be
+ * unpredictable. They only accept an |ad| parameter of length 11 (the standard
+ * TLS one with length omitted). */
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_tls(void);
+
+
+/* SSLv3-specific AEAD algorithms.
+ *
+ * These AEAD primitives do not meet the definition of generic AEADs. They are
+ * all specific to SSLv3 and should not be used outside of that context. They
+ * must be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful,
+ * and may not be used concurrently. They only accept an |ad| parameter of
+ * length 9 (the standard TLS one with length and version omitted). */
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_ssl3(void);
+
+
/* Obscure functions. */
+/* evp_aead_direction_t denotes the direction of an AEAD operation. */
+enum evp_aead_direction_t {
+ evp_aead_open,
+ evp_aead_seal,
+};
+
+/* EVP_AEAD_CTX_init_with_direction calls |EVP_AEAD_CTX_init| for normal
+ * AEADs. For TLS-specific and SSL3-specific AEADs, it initializes |ctx| for a
+ * given direction. */
+OPENSSL_EXPORT int EVP_AEAD_CTX_init_with_direction(
+ EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, const uint8_t *key, size_t key_len,
+ size_t tag_len, enum evp_aead_direction_t dir);
+
/* EVP_AEAD_CTX_get_rc4_state sets |*out_key| to point to an RC4 key structure.
* It returns one on success or zero if |ctx| doesn't have an RC4 key. */
OPENSSL_EXPORT int EVP_AEAD_CTX_get_rc4_state(const EVP_AEAD_CTX *ctx,
@@ -331,14 +331,6 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx,
const uint8_t **out_iv, size_t *out_len);
-/* Deprecated functions. */
-
-/* EVP_aead_chacha20_poly1305_rfc7539 calls |EVP_aead_chacha20_poly1305|.
- *
- * TODO(davidben): Remove this. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void);
-
-
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/include/openssl/arm_arch.h b/include/openssl/arm_arch.h
index 1471db90..e7010f40 100644
--- a/include/openssl/arm_arch.h
+++ b/include/openssl/arm_arch.h
@@ -105,12 +105,6 @@
/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */
#define ARMV7_NEON (1 << 0)
-/* ARMV7_NEON_FUNCTIONAL is true when the NEON unit doesn't contain subtle bugs.
- * The Poly1305 NEON code is known to trigger bugs in the NEON units of some
- * phones. If this bit isn't set then the Poly1305 NEON code won't be used.
- * See https://code.google.com/p/chromium/issues/detail?id=341598. */
-#define ARMV7_NEON_FUNCTIONAL (1 << 10)
-
/* ARMV8_AES indicates support for hardware AES instructions. */
#define ARMV8_AES (1 << 2)
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
index e27164eb..42c95351 100644
--- a/include/openssl/asn1.h
+++ b/include/openssl/asn1.h
@@ -969,9 +969,6 @@ OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIM
OPENSSL_EXPORT int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a);
OPENSSL_EXPORT int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
OPENSSL_EXPORT int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
-OPENSSL_EXPORT int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, unsigned char *buf, int off);
-OPENSSL_EXPORT int ASN1_parse(BIO *bp,const unsigned char *pp,long len,int indent);
-OPENSSL_EXPORT int ASN1_parse_dump(BIO *bp,const unsigned char *pp,long len,int indent,int dump);
OPENSSL_EXPORT const char *ASN1_tag2str(int tag);
/* Used to load and write netscape format cert */
@@ -1013,67 +1010,9 @@ OPENSSL_EXPORT ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char
OPENSSL_EXPORT int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
OPENSSL_EXPORT int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
-OPENSSL_EXPORT void ASN1_add_oid_module(void);
-
OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
-/* ASN1 Print flags */
-
-/* Indicate missing OPTIONAL fields */
-#define ASN1_PCTX_FLAGS_SHOW_ABSENT 0x001
-/* Mark start and end of SEQUENCE */
-#define ASN1_PCTX_FLAGS_SHOW_SEQUENCE 0x002
-/* Mark start and end of SEQUENCE/SET OF */
-#define ASN1_PCTX_FLAGS_SHOW_SSOF 0x004
-/* Show the ASN1 type of primitives */
-#define ASN1_PCTX_FLAGS_SHOW_TYPE 0x008
-/* Don't show ASN1 type of ANY */
-#define ASN1_PCTX_FLAGS_NO_ANY_TYPE 0x010
-/* Don't show ASN1 type of MSTRINGs */
-#define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE 0x020
-/* Don't show field names in SEQUENCE */
-#define ASN1_PCTX_FLAGS_NO_FIELD_NAME 0x040
-/* Show structure names of each SEQUENCE field */
-#define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME 0x080
-/* Don't show structure name even at top level */
-#define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100
-
-OPENSSL_EXPORT int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, const ASN1_ITEM *it, const ASN1_PCTX *pctx);
-OPENSSL_EXPORT ASN1_PCTX *ASN1_PCTX_new(void);
-OPENSSL_EXPORT void ASN1_PCTX_free(ASN1_PCTX *p);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
-
-OPENSSL_EXPORT const BIO_METHOD *BIO_f_asn1(void);
-
-OPENSSL_EXPORT BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
-
-OPENSSL_EXPORT int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, const ASN1_ITEM *it);
-OPENSSL_EXPORT int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, const char *hdr, const ASN1_ITEM *it);
-OPENSSL_EXPORT ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
-OPENSSL_EXPORT int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
-OPENSSL_EXPORT int SMIME_text(BIO *in, BIO *out);
-
-/* BEGIN ERROR CODES */
-/* The following lines are auto generated by the script mkerr.pl. Any changes
- * made after this point may be overwritten when the script is next run.
- */
-void ERR_load_ASN1_strings(void);
-
-typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-OPENSSL_EXPORT int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free);
-OPENSSL_EXPORT int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free);
-OPENSSL_EXPORT int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free);
-OPENSSL_EXPORT int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free);
#ifdef __cplusplus
}
@@ -1087,84 +1026,89 @@ OPENSSL_EXPORT int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_f
#define ASN1_R_BN_LIB 105
#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
#define ASN1_R_BUFFER_TOO_SMALL 107
-#define ASN1_R_DECODE_ERROR 108
-#define ASN1_R_DEPTH_EXCEEDED 109
-#define ASN1_R_ENCODE_ERROR 110
-#define ASN1_R_ERROR_GETTING_TIME 111
-#define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 112
-#define ASN1_R_EXPECTING_AN_INTEGER 113
-#define ASN1_R_EXPECTING_AN_OBJECT 114
-#define ASN1_R_EXPECTING_A_BOOLEAN 115
-#define ASN1_R_EXPECTING_A_TIME 116
-#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 117
-#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 118
-#define ASN1_R_FIELD_MISSING 119
-#define ASN1_R_FIRST_NUM_TOO_LARGE 120
-#define ASN1_R_HEADER_TOO_LONG 121
-#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 122
-#define ASN1_R_ILLEGAL_BOOLEAN 123
-#define ASN1_R_ILLEGAL_CHARACTERS 124
-#define ASN1_R_ILLEGAL_FORMAT 125
-#define ASN1_R_ILLEGAL_HEX 126
-#define ASN1_R_ILLEGAL_IMPLICIT_TAG 127
-#define ASN1_R_ILLEGAL_INTEGER 128
-#define ASN1_R_ILLEGAL_NESTED_TAGGING 129
-#define ASN1_R_ILLEGAL_NULL 130
-#define ASN1_R_ILLEGAL_NULL_VALUE 131
-#define ASN1_R_ILLEGAL_OBJECT 132
-#define ASN1_R_ILLEGAL_OPTIONAL_ANY 133
-#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 134
-#define ASN1_R_ILLEGAL_TAGGED_ANY 135
-#define ASN1_R_ILLEGAL_TIME_VALUE 136
-#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 137
-#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 138
-#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 139
-#define ASN1_R_INVALID_BMPSTRING_LENGTH 140
-#define ASN1_R_INVALID_DIGIT 141
-#define ASN1_R_INVALID_MODIFIER 142
-#define ASN1_R_INVALID_NUMBER 143
-#define ASN1_R_INVALID_OBJECT_ENCODING 144
-#define ASN1_R_INVALID_SEPARATOR 145
-#define ASN1_R_INVALID_TIME_FORMAT 146
-#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 147
-#define ASN1_R_INVALID_UTF8STRING 148
-#define ASN1_R_LIST_ERROR 149
-#define ASN1_R_MISSING_ASN1_EOS 150
-#define ASN1_R_MISSING_EOC 151
-#define ASN1_R_MISSING_SECOND_NUMBER 152
-#define ASN1_R_MISSING_VALUE 153
-#define ASN1_R_MSTRING_NOT_UNIVERSAL 154
-#define ASN1_R_MSTRING_WRONG_TAG 155
-#define ASN1_R_NESTED_ASN1_ERROR 156
-#define ASN1_R_NESTED_ASN1_STRING 157
-#define ASN1_R_NON_HEX_CHARACTERS 158
-#define ASN1_R_NOT_ASCII_FORMAT 159
-#define ASN1_R_NOT_ENOUGH_DATA 160
-#define ASN1_R_NO_MATCHING_CHOICE_TYPE 161
-#define ASN1_R_NULL_IS_WRONG_LENGTH 162
-#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 163
-#define ASN1_R_ODD_NUMBER_OF_CHARS 164
-#define ASN1_R_SECOND_NUMBER_TOO_LARGE 165
-#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 166
-#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 167
-#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 168
-#define ASN1_R_SHORT_LINE 169
-#define ASN1_R_STREAMING_NOT_SUPPORTED 170
-#define ASN1_R_STRING_TOO_LONG 171
-#define ASN1_R_STRING_TOO_SHORT 172
-#define ASN1_R_TAG_VALUE_TOO_HIGH 173
-#define ASN1_R_TIME_NOT_ASCII_FORMAT 174
-#define ASN1_R_TOO_LONG 175
-#define ASN1_R_TYPE_NOT_CONSTRUCTED 176
-#define ASN1_R_TYPE_NOT_PRIMITIVE 177
-#define ASN1_R_UNEXPECTED_EOC 178
-#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 179
-#define ASN1_R_UNKNOWN_FORMAT 180
-#define ASN1_R_UNKNOWN_TAG 181
-#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 182
-#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 183
-#define ASN1_R_UNSUPPORTED_TYPE 184
-#define ASN1_R_WRONG_TAG 185
-#define ASN1_R_WRONG_TYPE 186
+#define ASN1_R_CONTEXT_NOT_INITIALISED 108
+#define ASN1_R_DECODE_ERROR 109
+#define ASN1_R_DEPTH_EXCEEDED 110
+#define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 111
+#define ASN1_R_ENCODE_ERROR 112
+#define ASN1_R_ERROR_GETTING_TIME 113
+#define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 114
+#define ASN1_R_EXPECTING_AN_INTEGER 115
+#define ASN1_R_EXPECTING_AN_OBJECT 116
+#define ASN1_R_EXPECTING_A_BOOLEAN 117
+#define ASN1_R_EXPECTING_A_TIME 118
+#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119
+#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
+#define ASN1_R_FIELD_MISSING 121
+#define ASN1_R_FIRST_NUM_TOO_LARGE 122
+#define ASN1_R_HEADER_TOO_LONG 123
+#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 124
+#define ASN1_R_ILLEGAL_BOOLEAN 125
+#define ASN1_R_ILLEGAL_CHARACTERS 126
+#define ASN1_R_ILLEGAL_FORMAT 127
+#define ASN1_R_ILLEGAL_HEX 128
+#define ASN1_R_ILLEGAL_IMPLICIT_TAG 129
+#define ASN1_R_ILLEGAL_INTEGER 130
+#define ASN1_R_ILLEGAL_NESTED_TAGGING 131
+#define ASN1_R_ILLEGAL_NULL 132
+#define ASN1_R_ILLEGAL_NULL_VALUE 133
+#define ASN1_R_ILLEGAL_OBJECT 134
+#define ASN1_R_ILLEGAL_OPTIONAL_ANY 135
+#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 136
+#define ASN1_R_ILLEGAL_TAGGED_ANY 137
+#define ASN1_R_ILLEGAL_TIME_VALUE 138
+#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 139
+#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 140
+#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 141
+#define ASN1_R_INVALID_BMPSTRING_LENGTH 142
+#define ASN1_R_INVALID_DIGIT 143
+#define ASN1_R_INVALID_MODIFIER 144
+#define ASN1_R_INVALID_NUMBER 145
+#define ASN1_R_INVALID_OBJECT_ENCODING 146
+#define ASN1_R_INVALID_SEPARATOR 147
+#define ASN1_R_INVALID_TIME_FORMAT 148
+#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 149
+#define ASN1_R_INVALID_UTF8STRING 150
+#define ASN1_R_LIST_ERROR 151
+#define ASN1_R_MISSING_ASN1_EOS 152
+#define ASN1_R_MISSING_EOC 153
+#define ASN1_R_MISSING_SECOND_NUMBER 154
+#define ASN1_R_MISSING_VALUE 155
+#define ASN1_R_MSTRING_NOT_UNIVERSAL 156
+#define ASN1_R_MSTRING_WRONG_TAG 157
+#define ASN1_R_NESTED_ASN1_ERROR 158
+#define ASN1_R_NESTED_ASN1_STRING 159
+#define ASN1_R_NON_HEX_CHARACTERS 160
+#define ASN1_R_NOT_ASCII_FORMAT 161
+#define ASN1_R_NOT_ENOUGH_DATA 162
+#define ASN1_R_NO_MATCHING_CHOICE_TYPE 163
+#define ASN1_R_NULL_IS_WRONG_LENGTH 164
+#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 165
+#define ASN1_R_ODD_NUMBER_OF_CHARS 166
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE 167
+#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 168
+#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 169
+#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 170
+#define ASN1_R_SHORT_LINE 171
+#define ASN1_R_STREAMING_NOT_SUPPORTED 172
+#define ASN1_R_STRING_TOO_LONG 173
+#define ASN1_R_STRING_TOO_SHORT 174
+#define ASN1_R_TAG_VALUE_TOO_HIGH 175
+#define ASN1_R_TIME_NOT_ASCII_FORMAT 176
+#define ASN1_R_TOO_LONG 177
+#define ASN1_R_TYPE_NOT_CONSTRUCTED 178
+#define ASN1_R_TYPE_NOT_PRIMITIVE 179
+#define ASN1_R_UNEXPECTED_EOC 180
+#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 181
+#define ASN1_R_UNKNOWN_FORMAT 182
+#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 183
+#define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 184
+#define ASN1_R_UNKNOWN_TAG 185
+#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 186
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 187
+#define ASN1_R_UNSUPPORTED_TYPE 188
+#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 189
+#define ASN1_R_WRONG_TAG 190
+#define ASN1_R_WRONG_TYPE 191
#endif
diff --git a/include/openssl/asn1t.h b/include/openssl/asn1t.h
index b43c3328..10d32c43 100644
--- a/include/openssl/asn1t.h
+++ b/include/openssl/asn1t.h
@@ -631,6 +631,7 @@ typedef struct ASN1_EXTERN_FUNCS_st {
ASN1_ex_free_func *asn1_ex_clear;
ASN1_ex_d2i *asn1_ex_d2i;
ASN1_ex_i2d *asn1_ex_i2d;
+ /* asn1_ex_print is unused. */
ASN1_ex_print_func *asn1_ex_print;
} ASN1_EXTERN_FUNCS;
@@ -835,17 +836,6 @@ typedef struct ASN1_STREAM_ARG_st {
return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
}
-#define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \
- IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
-
-#define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
- int fname##_print_ctx(BIO *out, stname *x, int indent, \
- const ASN1_PCTX *pctx) \
- { \
- return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \
- ASN1_ITEM_rptr(itname), pctx); \
- }
-
#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 413c1630..96eb6936 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -60,7 +60,11 @@
#include <stdint.h>
#include <sys/types.h>
-#include <openssl/opensslfeatures.h>
+#include <openssl/opensslconf.h>
+
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols.h>
+#endif
#if defined(__cplusplus)
extern "C" {
@@ -112,9 +116,20 @@ extern "C" {
#define OPENSSL_IS_BORINGSSL
#define BORINGSSL_201512
+#define BORINGSSL_201603
#define OPENSSL_VERSION_NUMBER 0x10002000
#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
+/* BORINGSSL_API_VERSION is a positive integer that increments as BoringSSL
+ * changes over time. The value itself is not meaningful. It will be incremented
+ * whenever is convenient to coordinate an API change with consumers. This will
+ * not denote any special point in development.
+ *
+ * A consumer may use this symbol in the preprocessor to temporarily build
+ * against multiple revisions of BoringSSL at the same time. It is not
+ * recommended to do so for longer than is necessary. */
+#define BORINGSSL_API_VERSION 1
+
#if defined(BORINGSSL_SHARED_LIBRARY)
#if defined(OPENSSL_WINDOWS)
@@ -144,11 +159,18 @@ extern "C" {
#if defined(__GNUC__)
#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \
- __attribute__((format(printf, string_index, first_to_check)))
+ __attribute__((__format__(__printf__, string_index, first_to_check)))
#else
#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check)
#endif
+/* OPENSSL_MSVC_PRAGMA emits a pragma on MSVC and nothing on other compilers. */
+#if defined(_MSC_VER)
+#define OPENSSL_MSVC_PRAGMA(arg) __pragma(arg)
+#else
+#define OPENSSL_MSVC_PRAGMA(arg)
+#endif
+
/* CRYPTO_THREADID is a dummy value. */
typedef int CRYPTO_THREADID;
@@ -185,6 +207,7 @@ typedef struct Netscape_spki_st NETSCAPE_SPKI;
typedef struct PBE2PARAM_st PBE2PARAM;
typedef struct PBEPARAM_st PBEPARAM;
typedef struct PBKDF2PARAM_st PBKDF2PARAM;
+typedef struct RIPEMD160state_st RIPEMD160_CTX;
typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
@@ -233,6 +256,7 @@ typedef struct evp_pkey_st EVP_PKEY;
typedef struct hmac_ctx_st HMAC_CTX;
typedef struct md4_state_st MD4_CTX;
typedef struct md5_state_st MD5_CTX;
+typedef struct newhope_poly_st NEWHOPE_POLY;
typedef struct pkcs12_st PKCS12;
typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
typedef struct private_key_st X509_PKEY;
@@ -243,6 +267,7 @@ typedef struct rsa_st RSA;
typedef struct sha256_state_st SHA256_CTX;
typedef struct sha512_state_st SHA512_CTX;
typedef struct sha_state_st SHA_CTX;
+typedef struct spake2_ctx_st SPAKE2_CTX;
typedef struct srtp_protection_profile_st SRTP_PROTECTION_PROFILE;
typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_ctx_st SSL_CTX;
diff --git a/include/openssl/base64.h b/include/openssl/base64.h
index f28e7ddb..4bf3888c 100644
--- a/include/openssl/base64.h
+++ b/include/openssl/base64.h
@@ -87,15 +87,16 @@ OPENSSL_EXPORT int EVP_EncodedLength(size_t *out_len, size_t len);
/* Decoding */
-/* EVP_DecodedLength sets |*out_len| to the maximum number of bytes
- * that will be needed to call |EVP_DecodeBase64| on an input of
- * length |len|. */
+/* EVP_DecodedLength sets |*out_len| to the maximum number of bytes that will
+ * be needed to call |EVP_DecodeBase64| on an input of length |len|. It returns
+ * one on success or zero if |len| is not a valid length for a base64-encoded
+ * string. */
OPENSSL_EXPORT int EVP_DecodedLength(size_t *out_len, size_t len);
/* EVP_DecodeBase64 decodes |in_len| bytes from base64 and writes
* |*out_len| bytes to |out|. |max_out| is the size of the output
* buffer. If it is not enough for the maximum output size, the
- * operation fails. */
+ * operation fails. It returns one on success or zero on error. */
OPENSSL_EXPORT int EVP_DecodeBase64(uint8_t *out, size_t *out_len,
size_t max_out, const uint8_t *in,
size_t in_len);
@@ -105,9 +106,7 @@ OPENSSL_EXPORT int EVP_DecodeBase64(uint8_t *out, size_t *out_len,
*
* OpenSSL provides a streaming base64 implementation, however its behavior is
* very specific to PEM. It is also very lenient of invalid input. Use of any of
- * these functions is thus deprecated.
- *
- * TODO(davidben): Import upstream's rewrite that rejects the invalid input. */
+ * these functions is thus deprecated. */
/* EVP_EncodeInit initialises |*ctx|, which is typically stack
* allocated, for an encoding operation.
@@ -159,21 +158,25 @@ OPENSSL_EXPORT int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out,
*
* WARNING: EVP_DecodeBlock's return value does not take padding into
* account. It also strips leading whitespace and trailing
- * whitespace. */
+ * whitespace and minuses. */
OPENSSL_EXPORT int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src,
size_t src_len);
struct evp_encode_ctx_st {
- unsigned num; /* number saved in a partial encode/decode */
- unsigned length; /* The length is either the output line length
- * (in input bytes) or the shortest input line
- * length that is ok. Once decoding begins,
- * the length is adjusted up each time a longer
- * line is decoded */
- uint8_t enc_data[80]; /* data to encode */
- unsigned line_num; /* number read on current line */
- int expect_nl;
+ /* data_used indicates the number of bytes of |data| that are valid. When
+ * encoding, |data| will be filled and encoded as a lump. When decoding, only
+ * the first four bytes of |data| will be used. */
+ unsigned data_used;
+ uint8_t data[48];
+
+ /* eof_seen indicates that the end of the base64 data has been seen when
+ * decoding. Only whitespace can follow. */
+ char eof_seen;
+
+ /* error_encountered indicates that invalid base64 data was found. This will
+ * cause all future calls to fail. */
+ char error_encountered;
};
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index 6ca35751..5416c657 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -61,6 +61,7 @@
#include <stdio.h> /* For FILE */
+#include <openssl/buffer.h>
#include <openssl/err.h> /* for ERR_print_errors_fp */
#include <openssl/ex_data.h>
#include <openssl/stack.h>
@@ -361,19 +362,17 @@ OPENSSL_EXPORT int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len,
*
* Memory BIOs support |BIO_gets| and |BIO_puts|.
*
- * |BIO_eof| is true if no data is in the BIO.
- *
* |BIO_ctrl_pending| returns the number of bytes currently stored. */
/* BIO_s_mem returns a |BIO_METHOD| that uses a in-memory buffer. */
OPENSSL_EXPORT const BIO_METHOD *BIO_s_mem(void);
-/* BIO_new_mem_buf creates BIO that reads and writes from |len| bytes at |buf|.
+/* BIO_new_mem_buf creates read-only BIO that reads from |len| bytes at |buf|.
* It does not take ownership of |buf|. It returns the BIO or NULL on error.
*
* If |len| is negative, then |buf| is treated as a NUL-terminated string, but
* don't depend on this in new code. */
-OPENSSL_EXPORT BIO *BIO_new_mem_buf(void *buf, int len);
+OPENSSL_EXPORT BIO *BIO_new_mem_buf(const void *buf, int len);
/* BIO_mem_contents sets |*out_contents| to point to the current contents of
* |bio| and |*out_len| to contain the length of that data. It returns one on
@@ -419,12 +418,7 @@ OPENSSL_EXPORT int BIO_set_mem_eof_return(BIO *bio, int eof_value);
* underlying file descriptor when the BIO is freed.
*
* |BIO_reset| attempts to seek the file pointer to the start of file using
- * |lseek|.
- *
- * |BIO_seek| sets the file pointer to position |off| from start of file using
- * |lseek|.
- *
- * |BIO_tell| returns the current file position. */
+ * |lseek|. */
/* BIO_s_fd returns a |BIO_METHOD| for file descriptor fds. */
OPENSSL_EXPORT const BIO_METHOD *BIO_s_fd(void);
@@ -435,12 +429,18 @@ OPENSSL_EXPORT BIO *BIO_new_fd(int fd, int close_flag);
/* BIO_set_fd sets the file descriptor of |bio| to |fd|. If |close_flag| is
* non-zero then |fd| will be closed when |bio| is. It returns one on success
- * or zero on error. */
+ * or zero on error.
+ *
+ * This function may also be used with socket BIOs (see |BIO_s_socket| and
+ * |BIO_new_socket|). */
OPENSSL_EXPORT int BIO_set_fd(BIO *bio, int fd, int close_flag);
/* BIO_get_fd returns the file descriptor currently in use by |bio| or -1 if
* |bio| does not wrap a file descriptor. If there is a file descriptor and
- * |out_fd| is not NULL, it also sets |*out_fd| to the file descriptor. */
+ * |out_fd| is not NULL, it also sets |*out_fd| to the file descriptor.
+ *
+ * This function may also be used with socket BIOs (see |BIO_s_socket| and
+ * |BIO_new_socket|). */
OPENSSL_EXPORT int BIO_get_fd(BIO *bio, int *out_fd);
@@ -453,11 +453,6 @@ OPENSSL_EXPORT int BIO_get_fd(BIO *bio, int *out_fd);
* |BIO_reset| attempts to seek the file pointer to the start of file using
* |fseek|.
*
- * |BIO_seek| sets the file pointer to the given position from the start of
- * file using |fseek|.
- *
- * |BIO_eof| calls |feof|.
- *
* Setting the close flag causes |fclose| to be called on the stream when the
* BIO is freed. */
@@ -520,7 +515,17 @@ OPENSSL_EXPORT int BIO_set_read_buffer_size(BIO *bio, int buffer_size);
OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size);
-/* Socket BIOs. */
+/* Socket BIOs.
+ *
+ * Socket BIOs behave like file descriptor BIOs but, on Windows systems, wrap
+ * the system's |recv| and |send| functions instead of |read| and |write|. On
+ * Windows, file descriptors are provided by C runtime and are not
+ * interchangeable with sockets.
+ *
+ * Socket BIOs may be used with |BIO_set_fd| and |BIO_get_fd|.
+ *
+ * TODO(davidben): Add separate APIs and fix the internals to use |SOCKET|s
+ * around rather than rely on int casts. */
OPENSSL_EXPORT const BIO_METHOD *BIO_s_socket(void);
@@ -557,10 +562,18 @@ OPENSSL_EXPORT int BIO_set_conn_hostname(BIO *bio,
* will connect to. It returns one on success and zero otherwise. */
OPENSSL_EXPORT int BIO_set_conn_port(BIO *bio, const char *port_str);
+/* BIO_set_conn_int_port sets |*port| as the port that |bio| will connect to.
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int BIO_set_conn_int_port(BIO *bio, const int *port);
+
/* BIO_set_nbio sets whether |bio| will use non-blocking I/O operations. It
* returns one on success and zero otherwise. */
OPENSSL_EXPORT int BIO_set_nbio(BIO *bio, int on);
+/* BIO_do_connect connects |bio| if it has not been connected yet. It returns
+ * one on success and <= 0 otherwise. */
+OPENSSL_EXPORT int BIO_do_connect(BIO *bio);
+
/* Datagram BIOs.
*
@@ -574,8 +587,12 @@ OPENSSL_EXPORT int BIO_set_nbio(BIO *bio, int on);
#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU was exceed in
the previous write operation. */
-#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT \
- 45 /* Next DTLS handshake timeout to adjust socket timeouts */
+/* BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT sets a read deadline to drive
+ * retransmits. The |parg| argument to |BIO_ctrl| will be a pointer to a
+ * |timeval| struct. If the structure is all zeros, it clears the read
+ * deadline. Otherwise, |BIO_read| must fail with a temporary error
+ * (e.g. |EAGAIN|) after the deadline. */
+#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45
#define BIO_CTRL_DGRAM_GET_PEER 46
@@ -701,6 +718,8 @@ OPENSSL_EXPORT int BIO_zero_copy_get_write_buf_done(BIO* bio,
#define BIO_CTRL_INFO 3 /* opt - extra tit-bits */
#define BIO_CTRL_SET 4 /* man - set the 'IO' type */
#define BIO_CTRL_GET 5 /* man - get the 'IO' type */
+#define BIO_CTRL_PUSH 6
+#define BIO_CTRL_POP 7
#define BIO_CTRL_GET_CLOSE 8 /* man - set the 'close' on free */
#define BIO_CTRL_SET_CLOSE 9 /* man - set the 'close' on free */
#define BIO_CTRL_PENDING 10 /* opt - is their more data buffered */
@@ -711,10 +730,8 @@ OPENSSL_EXPORT int BIO_zero_copy_get_write_buf_done(BIO* bio,
#define BIO_CTRL_GET_CALLBACK 15 /* opt - set callback function */
#define BIO_CTRL_SET_FILENAME 30 /* BIO_s_file special */
-/* These are never used, but exist to allow code to compile more easily. */
-#define BIO_CTRL_DUP 100
-#define BIO_CTRL_PUSH 101
-#define BIO_CTRL_POP 102
+/* BIO_CTRL_DUP is never used, but exists to allow code to compile more easily. */
+#define BIO_CTRL_DUP 12
/* Android compatibility section.
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index 64ec5c96..e9be0f5b 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -441,6 +441,11 @@ OPENSSL_EXPORT int BN_cmp(const BIGNUM *a, const BIGNUM *b);
* value of |b|, respectively. */
OPENSSL_EXPORT int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
+/* BN_equal_consttime returns one if |a| is equal to |b|, and zero otherwise.
+ * It takes an amount of time dependent on the sizes of |a| and |b|, but
+ * independent of the contents (including the signs) of |a| and |b|. */
+OPENSSL_EXPORT int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b);
+
/* BN_abs_is_word returns one if the absolute value of |bn| equals |w| and zero
* otherwise. */
OPENSSL_EXPORT int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w);
@@ -749,11 +754,11 @@ OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod,
/* BN_MONT_CTX_set_locked takes |lock| and checks whether |*pmont| is NULL. If
* so, it creates a new |BN_MONT_CTX| and sets the modulus for it to |mod|. It
- * then stores it as |*pmont| and returns it, or NULL on error.
+ * then stores it as |*pmont|. It returns one on success and zero on error.
*
- * If |*pmont| is already non-NULL then the existing value is returned. */
-BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
- const BIGNUM *mod, BN_CTX *bn_ctx);
+ * If |*pmont| is already non-NULL then it does nothing and returns one. */
+int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
+ const BIGNUM *mod, BN_CTX *bn_ctx);
/* BN_to_montgomery sets |ret| equal to |a| in the Montgomery domain. It
* returns one on success and zero on error. */
@@ -797,14 +802,6 @@ OPENSSL_EXPORT int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a,
BN_CTX *ctx,
const BN_MONT_CTX *mont);
-OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx,
- const BN_MONT_CTX *mont);
-OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1,
- const BIGNUM *p1, const BIGNUM *a2,
- const BIGNUM *p2, const BIGNUM *m,
- BN_CTX *ctx, const BN_MONT_CTX *mont);
-
/* Deprecated functions */
@@ -824,6 +821,20 @@ OPENSSL_EXPORT size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out);
* is updated. */
OPENSSL_EXPORT BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out);
+/* BN_mod_exp_mont_word is like |BN_mod_exp_mont| except that the base |a| is
+ * given as a |BN_ULONG| instead of a |BIGNUM *|. It returns one on success
+ * or zero otherwise. */
+OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ const BN_MONT_CTX *mont);
+
+/* BN_mod_exp2_mont calculates (a1^p1) * (a2^p2) mod m. It returns 1 on success
+ * or zero otherwise. */
+OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1,
+ const BIGNUM *p1, const BIGNUM *a2,
+ const BIGNUM *p2, const BIGNUM *m,
+ BN_CTX *ctx, const BN_MONT_CTX *mont);
+
/* Private functions */
@@ -852,15 +863,6 @@ OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l);
#define BN_FLG_CONSTTIME 0x04
-/* Android compatibility section.
- *
- * These functions are declared, temporarily, for Android because
- * wpa_supplicant will take a little time to sync with upstream. Outside of
- * Android they'll have no definition. */
-
-OPENSSL_EXPORT BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn);
-
-
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/include/openssl/buf.h b/include/openssl/buf.h
index f4e315cd..8ae856b6 100644
--- a/include/openssl/buf.h
+++ b/include/openssl/buf.h
@@ -80,6 +80,10 @@ OPENSSL_EXPORT BUF_MEM *BUF_MEM_new(void);
/* BUF_MEM_free frees |buf->data| if needed and then frees |buf| itself. */
OPENSSL_EXPORT void BUF_MEM_free(BUF_MEM *buf);
+/* BUF_MEM_reserve ensures |buf| has capacity |cap| and allocates memory if
+ * needed. It returns one on success and zero on error. */
+OPENSSL_EXPORT int BUF_MEM_reserve(BUF_MEM *buf, size_t cap);
+
/* BUF_MEM_grow ensures that |buf| has length |len| and allocates memory if
* needed. If the length of |buf| increased, the new bytes are filled with
* zeros. It returns the length of |buf|, or zero if there's an error. */
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index cf424d07..3a8d4e53 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -95,6 +95,10 @@ OPENSSL_EXPORT int CBS_get_u24(CBS *cbs, uint32_t *out);
* and advances |cbs|. It returns one on success and zero on error. */
OPENSSL_EXPORT int CBS_get_u32(CBS *cbs, uint32_t *out);
+/* CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens
+ * |cbs|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out);
+
/* CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances
* |cbs|. It returns one on success and zero on error. */
OPENSSL_EXPORT int CBS_get_bytes(CBS *cbs, CBS *out, size_t len);
@@ -128,6 +132,7 @@ OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
#define CBS_ASN1_NULL 0x5
#define CBS_ASN1_OBJECT 0x6
#define CBS_ASN1_ENUMERATED 0xa
+#define CBS_ASN1_UTF8STRING 0xc
#define CBS_ASN1_SEQUENCE (0x10 | CBS_ASN1_CONSTRUCTED)
#define CBS_ASN1_SET (0x11 | CBS_ASN1_CONSTRUCTED)
#define CBS_ASN1_NUMERICSTRING 0x12
diff --git a/include/openssl/chacha.h b/include/openssl/chacha.h
index 64713c24..3d035e69 100644
--- a/include/openssl/chacha.h
+++ b/include/openssl/chacha.h
@@ -23,8 +23,8 @@ extern "C" {
/* CRYPTO_chacha_20 encrypts |in_len| bytes from |in| with the given key and
- * nonce and writes the result to |out|, which may be equal to |in|. The
- * initial block counter is specified by |counter|. */
+ * nonce and writes the result to |out|. If |in| and |out| alias, they must be
+ * equal. The initial block counter is specified by |counter|. */
OPENSSL_EXPORT void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in,
size_t in_len, const uint8_t key[32],
const uint8_t nonce[12], uint32_t counter);
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
index fb7171f0..53123086 100644
--- a/include/openssl/cipher.h
+++ b/include/openssl/cipher.h
@@ -481,7 +481,7 @@ struct evp_cipher_ctx_st {
/* num contains the number of bytes of |iv| which are valid for modes that
* manage partial blocks themselves. */
- int num;
+ unsigned num;
/* final_used is non-zero if the |final| buffer contains plaintext. */
int final_used;
diff --git a/include/openssl/conf.h b/include/openssl/conf.h
index 75f14f5b..2aa3b79e 100644
--- a/include/openssl/conf.h
+++ b/include/openssl/conf.h
@@ -92,10 +92,10 @@ struct conf_st {
/* NCONF_new returns a fresh, empty |CONF|, or NULL on error. The |method|
* argument must be NULL. */
-CONF *NCONF_new(void *method);
+OPENSSL_EXPORT CONF *NCONF_new(void *method);
/* NCONF_free frees all the data owned by |conf| and then |conf| itself. */
-void NCONF_free(CONF *conf);
+OPENSSL_EXPORT void NCONF_free(CONF *conf);
/* NCONF_load parses the file named |filename| and adds the values found to
* |conf|. It returns one on success and zero on error. In the event of an
diff --git a/include/openssl/cpu.h b/include/openssl/cpu.h
index e946304a..55be4c1f 100644
--- a/include/openssl/cpu.h
+++ b/include/openssl/cpu.h
@@ -110,30 +110,23 @@ OPENSSL_EXPORT char CRYPTO_is_NEON_capable_at_runtime(void);
/* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. If
* this is known statically then it returns one immediately. */
static inline int CRYPTO_is_NEON_capable(void) {
-#if defined(__ARM_NEON__)
+ /* Only statically skip the runtime lookup on aarch64. On arm, one CPU is
+ * known to have a broken NEON unit which is known to fail with on some
+ * hand-written NEON assembly. For now, continue to apply the workaround even
+ * when the compiler is instructed to freely emit NEON code. See
+ * https://crbug.com/341598 and https://crbug.com/606629. */
+#if defined(__ARM_NEON__) && !defined(OPENSSL_ARM)
return 1;
#else
return CRYPTO_is_NEON_capable_at_runtime();
#endif
}
-/* CRYPTO_set_NEON_capable sets the return value of |CRYPTO_is_NEON_capable|.
- * By default, unless the code was compiled with |-mfpu=neon|, NEON is assumed
- * not to be present. It is not autodetected. Calling this with a zero
- * argument also causes |CRYPTO_is_NEON_functional| to return false. */
-OPENSSL_EXPORT void CRYPTO_set_NEON_capable(char neon_capable);
-
-/* CRYPTO_is_NEON_functional returns true if the current CPU has a /working/
- * NEON unit. Some phones have a NEON unit, but the Poly1305 NEON code causes
- * it to fail. See https://code.google.com/p/chromium/issues/detail?id=341598 */
-OPENSSL_EXPORT char CRYPTO_is_NEON_functional(void);
-
-/* CRYPTO_set_NEON_functional sets the "NEON functional" flag. For
- * |CRYPTO_is_NEON_functional| to return true, both this flag and the NEON flag
- * must be true. By default NEON is assumed to be functional if the code was
- * compiled with |-mfpu=neon| or if |CRYPTO_set_NEON_capable| has been called
- * with a non-zero argument. */
-OPENSSL_EXPORT void CRYPTO_set_NEON_functional(char neon_functional);
+#if defined(OPENSSL_ARM)
+/* CRYPTO_has_broken_NEON returns one if the current CPU is known to have a
+ * broken NEON unit. See https://crbug.com/341598. */
+OPENSSL_EXPORT int CRYPTO_has_broken_NEON(void);
+#endif
/* CRYPTO_is_ARMv8_AES_capable returns true if the current CPU supports the
* ARMv8 AES instruction. */
@@ -153,10 +146,6 @@ static inline int CRYPTO_is_NEON_capable(void) {
#endif
}
-static inline int CRYPTO_is_NEON_functional(void) {
- return CRYPTO_is_NEON_capable();
-}
-
static inline int CRYPTO_is_ARMv8_AES_capable(void) {
#if defined(OPENSSL_STATIC_ARMCAP_AES)
return 1;
@@ -174,7 +163,7 @@ static inline int CRYPTO_is_ARMv8_PMULL_capable(void) {
}
#endif /* OPENSSL_STATIC_ARMCAP */
-#endif /* OPENSSL_ARM */
+#endif /* OPENSSL_ARM || OPENSSL_AARCH64 */
#if defined(__cplusplus)
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index 29d58921..80d71969 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -36,9 +36,24 @@ extern "C" {
/* CRYPTO_library_init initializes the crypto library. It must be called if the
* library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does
- * nothing and a static initializer is used instead. */
+ * nothing and a static initializer is used instead. It is safe to call this
+ * function multiple times and concurrently from multiple threads.
+ *
+ * On some ARM configurations, this function may require filesystem access and
+ * should be called before entering a sandbox. */
OPENSSL_EXPORT void CRYPTO_library_init(void);
+/* CRYPTO_is_confidential_build returns one if the linked version of BoringSSL
+ * has been built with the BORINGSSL_CONFIDENTIAL define and zero otherwise.
+ *
+ * This is used by some consumers to identify whether they are using an
+ * internal version of BoringSSL. */
+OPENSSL_EXPORT int CRYPTO_is_confidential_build(void);
+
+/* CRYPTO_has_asm returns one unless BoringSSL was built with OPENSSL_NO_ASM,
+ * in which case it returns zero. */
+OPENSSL_EXPORT int CRYPTO_has_asm(void);
+
/* Deprecated functions. */
@@ -65,6 +80,9 @@ OPENSSL_EXPORT void ENGINE_load_builtin_engines(void);
/* OPENSSL_load_builtin_modules does nothing. */
OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void);
+/* FIPS_mode returns zero. */
+OPENSSL_EXPORT int FIPS_mode(void);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/include/openssl/curve25519.h b/include/openssl/curve25519.h
index c202575f..a9441cd4 100644
--- a/include/openssl/curve25519.h
+++ b/include/openssl/curve25519.h
@@ -29,10 +29,9 @@ extern "C" {
/* X25519.
*
- * Curve25519 is an elliptic curve. The same name is also sometimes used for
- * the Diffie-Hellman primitive built from it but “X25519” is a more precise
- * name for that, which is the one used here. See http://cr.yp.to/ecdh.html and
- * https://tools.ietf.org/html/rfc7748. */
+ * X25519 is the Diffie-Hellman primitive built from curve25519. It is
+ * sometimes referred to as “curve25519”, but “X25519” is a more precise name.
+ * See http://cr.yp.to/ecdh.html and https://tools.ietf.org/html/rfc7748. */
/* X25519_keypair sets |out_public_value| and |out_private_key| to a freshly
* generated, public–private key pair. */
@@ -84,6 +83,88 @@ OPENSSL_EXPORT int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t public_key[32]);
+/* SPAKE2.
+ *
+ * SPAKE2 is a password-authenticated key-exchange. It allows two parties,
+ * who share a low-entropy secret (i.e. password), to agree on a shared key.
+ * An attacker can only make one guess of the password per execution of the
+ * protocol.
+ *
+ * See https://tools.ietf.org/html/draft-irtf-cfrg-spake2-02. */
+
+/* spake2_role_t enumerates the different “roles” in SPAKE2. The protocol
+ * requires that the symmetry of the two parties be broken so one participant
+ * must be “Alice” and the other be “Bob”. */
+enum spake2_role_t {
+ spake2_role_alice,
+ spake2_role_bob,
+};
+
+/* SPAKE2_CTX_new creates a new |SPAKE2_CTX| (which can only be used for a
+ * single execution of the protocol). SPAKE2 requires the symmetry of the two
+ * parties to be broken which is indicated via |my_role| – each party must pass
+ * a different value for this argument.
+ *
+ * The |my_name| and |their_name| arguments allow optional, opaque names to be
+ * bound into the protocol. For example MAC addresses, hostnames, usernames
+ * etc. These values are not exposed and can avoid context-confusion attacks
+ * when a password is shared between several devices. */
+OPENSSL_EXPORT SPAKE2_CTX *SPAKE2_CTX_new(
+ enum spake2_role_t my_role,
+ const uint8_t *my_name, size_t my_name_len,
+ const uint8_t *their_name, size_t their_name_len);
+
+/* SPAKE2_CTX_free frees |ctx| and all the resources that it has allocated. */
+OPENSSL_EXPORT void SPAKE2_CTX_free(SPAKE2_CTX *ctx);
+
+/* SPAKE2_MAX_MSG_SIZE is the maximum size of a SPAKE2 message. */
+#define SPAKE2_MAX_MSG_SIZE 32
+
+/* SPAKE2_generate_msg generates a SPAKE2 message given |password|, writes
+ * it to |out| and sets |*out_len| to the number of bytes written.
+ *
+ * At most |max_out_len| bytes are written to |out| and, in order to ensure
+ * success, |max_out_len| should be at least |SPAKE2_MAX_MSG_SIZE| bytes.
+ *
+ * This function can only be called once for a given |SPAKE2_CTX|.
+ *
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *password,
+ size_t password_len);
+
+/* SPAKE2_MAX_KEY_SIZE is the maximum amount of key material that SPAKE2 will
+ * produce. */
+#define SPAKE2_MAX_KEY_SIZE 64
+
+/* SPAKE2_process_msg completes the SPAKE2 exchange given the peer's message in
+ * |their_msg|, writes at most |max_out_key_len| bytes to |out_key| and sets
+ * |*out_key_len| to the number of bytes written.
+ *
+ * The resulting keying material is suitable for:
+ * a) Using directly in a key-confirmation step: i.e. each side could
+ * transmit a hash of their role, a channel-binding value and the key
+ * material to prove to the other side that they know the shared key.
+ * b) Using as input keying material to HKDF to generate a variety of subkeys
+ * for encryption etc.
+ *
+ * If |max_out_key_key| is smaller than the amount of key material generated
+ * then the key is silently truncated. If you want to ensure that no truncation
+ * occurs then |max_out_key| should be at least |SPAKE2_MAX_KEY_SIZE|.
+ *
+ * You must call |SPAKE2_generate_msg| on a given |SPAKE2_CTX| before calling
+ * this function. On successful return, |ctx| is complete and calling
+ * |SPAKE2_CTX_free| is the only acceptable operation on it.
+ *
+ * Returns one on success or zero on error. */
+OPENSSL_EXPORT int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key,
+ size_t *out_key_len,
+ size_t max_out_key_len,
+ const uint8_t *their_msg,
+ size_t their_msg_len);
+
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index 4066ae17..a0876518 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -174,22 +174,15 @@ OPENSSL_EXPORT DH *DHparams_dup(const DH *dh);
/* ASN.1 functions. */
-/* d2i_DHparams parses an ASN.1, DER encoded Diffie-Hellman parameters
- * structure from |len| bytes at |*inp|. If |ret| is not NULL then, on exit, a
- * pointer to the result is in |*ret|. If |*ret| is already non-NULL on entry
- * then the result is written directly into |*ret|, otherwise a fresh |DH| is
- * allocated. However, one should not depend on writing into |*ret| because
- * this behaviour is likely to change in the future.
- *
- * On successful exit, |*inp| is advanced past the DER structure. It
- * returns the result or NULL on error. */
-OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len);
+/* DH_parse_parameters decodes a DER-encoded DHParameter structure (PKCS #3)
+ * from |cbs| and advances |cbs|. It returns a newly-allocated |DH| or NULL on
+ * error. */
+OPENSSL_EXPORT DH *DH_parse_parameters(CBS *cbs);
-/* i2d_DHparams marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
- * then the result is written to |*outp| and |*outp| is advanced just past the
- * output. It returns the number of bytes in the result, whether written or
- * not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp);
+/* DH_marshal_parameters marshals |dh| as a DER-encoded DHParameter structure
+ * (PKCS #3) and appends the result to |cbb|. It returns one on success and zero
+ * on error. */
+OPENSSL_EXPORT int DH_marshal_parameters(CBB *cbb, const DH *dh);
/* ex_data functions.
@@ -204,6 +197,36 @@ OPENSSL_EXPORT int DH_set_ex_data(DH *d, int idx, void *arg);
OPENSSL_EXPORT void *DH_get_ex_data(DH *d, int idx);
+/* Deprecated functions. */
+
+/* DH_generate_parameters behaves like |DH_generate_parameters_ex|, which is
+ * what you should use instead. It returns NULL on error, or a newly-allocated
+ * |DH| on success. This function is provided for compatibility only. */
+OPENSSL_EXPORT DH *DH_generate_parameters(int prime_len, int generator,
+ void (*callback)(int, int, void *),
+ void *cb_arg);
+
+/* d2i_DHparams parses an ASN.1, DER encoded Diffie-Hellman parameters structure
+ * from |len| bytes at |*inp|. If |ret| is not NULL then, on exit, a pointer to
+ * the result is in |*ret|. Note that, even if |*ret| is already non-NULL on
+ * entry, it will not be written to. Rather, a fresh |DH| is allocated and the
+ * previous one is freed.
+ *
+ * On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error.
+ *
+ * Use |DH_parse_parameters| instead. */
+OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len);
+
+/* i2d_DHparams marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
+ * then the result is written to |*outp| and |*outp| is advanced just past the
+ * output. It returns the number of bytes in the result, whether written or
+ * not, or a negative value on error.
+ *
+ * Use |DH_marshal_parameters| instead. */
+OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp);
+
+
struct dh_st {
BIGNUM *p;
BIGNUM *g;
@@ -238,5 +261,7 @@ struct dh_st {
#define DH_R_INVALID_PUBKEY 101
#define DH_R_MODULUS_TOO_LARGE 102
#define DH_R_NO_PRIVATE_VALUE 103
+#define DH_R_DECODE_ERROR 104
+#define DH_R_ENCODE_ERROR 105
#endif /* OPENSSL_HEADER_DH_H */
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
index 80028efd..07ea07a6 100644
--- a/include/openssl/digest.h
+++ b/include/openssl/digest.h
@@ -143,6 +143,9 @@ OPENSSL_EXPORT int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data,
* at least this much space. */
#define EVP_MAX_MD_SIZE 64 /* SHA-512 is the longest so far. */
+/* EVP_MAX_MD_BLOCK_SIZE is the largest digest block size supported, in bytes. */
+#define EVP_MAX_MD_BLOCK_SIZE 128 /* SHA-512 is the longest so far. */
+
/* EVP_DigestFinal_ex finishes the digest in |ctx| and writes the output to
* |md_out|. At most |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not
* NULL then |*out_size| is set to the number of bytes written. It returns one.
@@ -209,6 +212,12 @@ OPENSSL_EXPORT int EVP_add_digest(const EVP_MD *digest);
* |name|, or NULL if the name is unknown. */
OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyname(const char *);
+/* EVP_dss1 returns the value of EVP_sha1(). This was provided by OpenSSL to
+ * specifiy the original DSA signatures, which were fixed to use SHA-1. Note,
+ * however, that attempting to sign or verify DSA signatures with the EVP
+ * interface will always fail. */
+OPENSSL_EXPORT const EVP_MD *EVP_dss1(void);
+
/* Digest operation accessors. */
@@ -218,11 +227,11 @@ OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
/* EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It
* will crash if a digest hasn't been set on |ctx|. */
-OPENSSL_EXPORT unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
+OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
/* EVP_MD_CTX_block_size returns the block size of the digest function used by
* |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|. */
-OPENSSL_EXPORT unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
+OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
/* EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|.
* (For example, |NID_sha256|.) It will crash if a digest hasn't been set on
diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h
index 8cf008b6..0077a722 100644
--- a/include/openssl/dsa.h
+++ b/include/openssl/dsa.h
@@ -363,6 +363,15 @@ OPENSSL_EXPORT DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len);
* Use |DSA_marshal_parameters| instead. */
OPENSSL_EXPORT int i2d_DSAparams(const DSA *in, uint8_t **outp);
+/* DSA_generate_parameters is a deprecated version of
+ * |DSA_generate_parameters_ex| that creates and returns a |DSA*|. Don't use
+ * it. */
+OPENSSL_EXPORT DSA *DSA_generate_parameters(int bits, unsigned char *seed,
+ int seed_len, int *counter_ret,
+ unsigned long *h_ret,
+ void (*callback)(int, int, void *),
+ void *cb_arg);
+
struct dsa_st {
long version;
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index 4957066f..143aa96c 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -189,12 +189,13 @@ OPENSSL_EXPORT int EC_POINT_is_at_infinity(const EC_GROUP *group,
const EC_POINT *point);
/* EC_POINT_is_on_curve returns one if |point| is an element of |group| and
- * zero otheriwse. If |ctx| is non-NULL, it may be used. */
+ * and zero otherwise or when an error occurs. This is different from OpenSSL,
+ * which returns -1 on error. If |ctx| is non-NULL, it may be used. */
OPENSSL_EXPORT int EC_POINT_is_on_curve(const EC_GROUP *group,
const EC_POINT *point, BN_CTX *ctx);
-/* EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero is
- * non-equal and -1 on error. If |ctx| is not NULL, it may be used. */
+/* EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero if
+ * not equal and -1 on error. If |ctx| is not NULL, it may be used. */
OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx);
@@ -220,10 +221,10 @@ OPENSSL_EXPORT int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
BIGNUM *x, BIGNUM *y,
BN_CTX *ctx);
-/* EC_POINT_set_affine_coordinates_GFp sets the value of |p| to be (|x|, |y|).
- * The |ctx| argument may be used if not NULL. It returns one on success or
- * zero on error. Note that, unlike with OpenSSL, it's considered an error if
- * the point is not on the curve. */
+/* EC_POINT_set_affine_coordinates_GFp sets the value of |point| to be
+ * (|x|, |y|). The |ctx| argument may be used if not NULL. It returns one
+ * on success or zero on error. Note that, unlike with OpenSSL, it's
+ * considered an error if the point is not on the curve. */
OPENSSL_EXPORT int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point,
const BIGNUM *x,
@@ -288,13 +289,37 @@ OPENSSL_EXPORT int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r,
/* Deprecated functions. */
-/* EC_GROUP_new_arbitrary creates a new, arbitrary elliptic curve group based on
- * the equation y² = x³ + a·x + b. The generator is set to (gx, gy) which must
- * have the given order and cofactor. It returns the new group or NULL on error.
+/* EC_GROUP_new_curve_GFp creates a new, arbitrary elliptic curve group based
+ * on the equation y² = x³ + a·x + b. It returns the new group or NULL on
+ * error.
+ *
+ * This new group has no generator. It is an error to use a generator-less group
+ * with any functions except for |EC_GROUP_free|, |EC_POINT_new|,
+ * |EC_POINT_set_affine_coordinates_GFp|, and |EC_GROUP_set_generator|.
*
* |EC_GROUP|s returned by this function will always compare as unequal via
* |EC_GROUP_cmp| (even to themselves). |EC_GROUP_get_curve_name| will always
- * return |NID_undef|. */
+ * return |NID_undef|.
+ *
+ * Avoid using arbitrary curves and use |EC_GROUP_new_by_curve_name| instead. */
+OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p,
+ const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx);
+
+/* EC_GROUP_set_generator sets the generator for |group| to |generator|, which
+ * must have the given order and cofactor. It may only be used with |EC_GROUP|
+ * objects returned by |EC_GROUP_new_curve_GFp| and may only be used once on
+ * each group. */
+OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group,
+ const EC_POINT *generator,
+ const BIGNUM *order,
+ const BIGNUM *cofactor);
+
+/* EC_GROUP_new_arbitrary calls |EC_GROUP_new_curve_GFp| and
+ * |EC_GROUP_set_generator|.
+ *
+ * TODO(davidben): Remove this once
+ * https://android-review.googlesource.com/#/c/207990/ has cycled in. */
OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_arbitrary(
const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, const BIGNUM *gx,
const BIGNUM *gy, const BIGNUM *order, const BIGNUM *cofactor);
diff --git a/include/openssl/ec_key.h b/include/openssl/ec_key.h
index 27423558..63554a78 100644
--- a/include/openssl/ec_key.h
+++ b/include/openssl/ec_key.h
@@ -192,10 +192,21 @@ OPENSSL_EXPORT EC_KEY *EC_KEY_parse_private_key(CBS *cbs,
OPENSSL_EXPORT int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
unsigned enc_flags);
+/* EC_KEY_parse_curve_name parses a DER-encoded OBJECT IDENTIFIER as a curve
+ * name from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP|
+ * or NULL on error. */
+OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs);
+
+/* EC_KEY_marshal_curve_name marshals |group| as a DER-encoded OBJECT IDENTIFIER
+ * and appends the result to |cbb|. It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group);
+
/* EC_KEY_parse_parameters parses a DER-encoded ECParameters structure (RFC
* 5480) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP|
* or NULL on error. It supports the namedCurve and specifiedCurve options, but
- * use of specifiedCurve is deprecated. */
+ * use of specifiedCurve is deprecated. Use |EC_KEY_parse_curve_name|
+ * instead. */
OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_parameters(CBS *cbs);
@@ -237,7 +248,7 @@ struct ecdsa_method_st {
int (*sign)(const uint8_t *digest, size_t digest_len, uint8_t *sig,
unsigned int *sig_len, EC_KEY *eckey);
- /* verify matches the arguments and behaviour of |ECDSA_verify|. */
+ /* Ignored. Set this to NULL. */
int (*verify)(const uint8_t *digest, size_t digest_len, const uint8_t *sig,
size_t sig_len, EC_KEY *eckey);
@@ -279,7 +290,7 @@ OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp);
* allocated and the previous one is freed. On successful exit, |*inp| is
* advanced past the DER structure. It returns the result or NULL on error.
*
- * Use EC_KEY_parse_parameters instead. */
+ * Use |EC_KEY_parse_parameters| or |EC_KEY_parse_curve_name| instead. */
OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
long len);
@@ -288,7 +299,7 @@ OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
* |*outp| is advanced just past the output. It returns the number of bytes in
* the result, whether written or not, or a negative value on error.
*
- * Use |OBJ_nid2cbb| and |EC_GROUP_get_curve_name| instead. */
+ * Use |EC_KEY_marshal_curve_name| instead. */
OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp);
/* o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 3db135bb..54074073 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -69,7 +69,7 @@
#include <openssl/base64.h>
#include <openssl/cipher.h>
#include <openssl/digest.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#if defined(__cplusplus)
extern "C" {
@@ -250,15 +250,6 @@ OPENSSL_EXPORT int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data,
OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
size_t *out_sig_len);
-/* EVP_DigestSignAlgorithm encodes the signing parameters of |ctx| as an
- * AlgorithmIdentifer and saves the result in |algor|.
- *
- * It returns one on success, or zero on error.
- *
- * TODO(davidben): This API should eventually lose the dependency on
- * crypto/asn1/. */
-OPENSSL_EXPORT int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
-
/* Verifying */
@@ -273,18 +264,6 @@ OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e,
EVP_PKEY *pkey);
-/* EVP_DigestVerifyInitFromAlgorithm sets up |ctx| for a signature verification
- * operation with public key |pkey| and parameters from |algor|. The |ctx|
- * argument must have been initialised with |EVP_MD_CTX_init|.
- *
- * It returns one on success, or zero on error.
- *
- * TODO(davidben): This API should eventually lose the dependency on
- * crypto/asn1/. */
-OPENSSL_EXPORT int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
- X509_ALGOR *algor,
- EVP_PKEY *pkey);
-
/* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which
* will be verified by |EVP_DigestVerifyFinal|. It returns one. */
OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data,
@@ -675,6 +654,9 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
/* OpenSSL_add_all_algorithms does nothing. */
OPENSSL_EXPORT void OpenSSL_add_all_algorithms(void);
+/* OPENSSL_add_all_algorithms_conf does nothing. */
+OPENSSL_EXPORT void OPENSSL_add_all_algorithms_conf(void);
+
/* OpenSSL_add_all_ciphers does nothing. */
OPENSSL_EXPORT void OpenSSL_add_all_ciphers(void);
@@ -719,11 +701,10 @@ OPENSSL_EXPORT int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp);
/* d2i_PrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes at
* |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
- * |*out|. If |*out| is already non-NULL on entry then the result is written
- * directly into |*out|, otherwise a fresh |EVP_PKEY| is allocated. However,
- * one should not depend on writing into |*out| because this behaviour is
- * likely to change in the future. On successful exit, |*inp| is advanced past
- * the DER structure. It returns the result or NULL on error.
+ * |*out|. Note that, even if |*out| is already non-NULL on entry, it will not
+ * be written to. Rather, a fresh |EVP_PKEY| is allocated and the previous one
+ * is freed. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error.
*
* This function tries to detect one of several formats. Instead, use
* |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an
@@ -741,21 +722,7 @@ OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
long len);
-/* Private functions */
-
-/* EVP_PKEY_asn1_find returns the ASN.1 method table for the given |nid|, which
- * should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
- * unknown. */
-OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine,
- int nid);
-
-/* EVP_PKEY_asn1_find_str returns an |EVP_PKEY_ASN1_METHOD| by matching values
- * of the |len| bytes at |name|. For example, if name equals "EC" then it will
- * return an ECC method. The |pengine| argument is ignored.
- *
- * TODO(fork): move to PEM? */
-OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(
- ENGINE **pengine, const char *name, size_t len);
+/* Private structures. */
struct evp_pkey_st {
CRYPTO_refcount_t references;
@@ -784,50 +751,33 @@ struct evp_pkey_st {
#define EVP_R_BUFFER_TOO_SMALL 100
#define EVP_R_COMMAND_NOT_SUPPORTED 101
-#define EVP_R_DIFFERENT_KEY_TYPES 104
-#define EVP_R_DIFFERENT_PARAMETERS 105
-#define EVP_R_EXPECTING_AN_EC_KEY_KEY 107
-#define EVP_R_EXPECTING_A_DH_KEY 109
-#define EVP_R_EXPECTING_A_DSA_KEY 110
-#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 111
-#define EVP_R_INVALID_CURVE 112
-#define EVP_R_INVALID_DIGEST_LENGTH 113
-#define EVP_R_INVALID_DIGEST_TYPE 114
-#define EVP_R_INVALID_KEYBITS 115
-#define EVP_R_INVALID_MGF1_MD 116
-#define EVP_R_INVALID_PADDING_MODE 118
-#define EVP_R_INVALID_PSS_PARAMETERS 119
-#define EVP_R_INVALID_SALT_LENGTH 121
-#define EVP_R_INVALID_TRAILER 122
-#define EVP_R_KEYS_NOT_SET 123
-#define EVP_R_MISSING_PARAMETERS 124
-#define EVP_R_NO_DEFAULT_DIGEST 125
-#define EVP_R_NO_KEY_SET 126
-#define EVP_R_NO_MDC2_SUPPORT 127
-#define EVP_R_NO_NID_FOR_CURVE 128
-#define EVP_R_NO_OPERATION_SET 129
-#define EVP_R_NO_PARAMETERS_SET 130
-#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 131
-#define EVP_R_OPERATON_NOT_INITIALIZED 132
-#define EVP_R_UNKNOWN_DIGEST 133
-#define EVP_R_UNKNOWN_MASK_DIGEST 134
-#define EVP_R_UNSUPPORTED_ALGORITHM 138
-#define EVP_R_UNSUPPORTED_MASK_ALGORITHM 139
-#define EVP_R_UNSUPPORTED_MASK_PARAMETER 140
-#define EVP_R_EXPECTING_AN_RSA_KEY 141
-#define EVP_R_INVALID_OPERATION 142
-#define EVP_R_DECODE_ERROR 143
-#define EVP_R_INVALID_PSS_SALTLEN 144
-#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 145
-#define EVP_R_CONTEXT_NOT_INITIALISED 146
-#define EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 147
-#define EVP_R_WRONG_PUBLIC_KEY_TYPE 148
-#define EVP_R_UNKNOWN_SIGNATURE_ALGORITHM 149
-#define EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 150
-#define EVP_R_BN_DECODE_ERROR 151
-#define EVP_R_PARAMETER_ENCODING_ERROR 152
-#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 153
-#define EVP_R_UNSUPPORTED_SIGNATURE_TYPE 154
-#define EVP_R_ENCODE_ERROR 155
+#define EVP_R_DECODE_ERROR 102
+#define EVP_R_DIFFERENT_KEY_TYPES 103
+#define EVP_R_DIFFERENT_PARAMETERS 104
+#define EVP_R_ENCODE_ERROR 105
+#define EVP_R_EXPECTING_AN_EC_KEY_KEY 106
+#define EVP_R_EXPECTING_AN_RSA_KEY 107
+#define EVP_R_EXPECTING_A_DSA_KEY 108
+#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 109
+#define EVP_R_INVALID_DIGEST_LENGTH 110
+#define EVP_R_INVALID_DIGEST_TYPE 111
+#define EVP_R_INVALID_KEYBITS 112
+#define EVP_R_INVALID_MGF1_MD 113
+#define EVP_R_INVALID_OPERATION 114
+#define EVP_R_INVALID_PADDING_MODE 115
+#define EVP_R_INVALID_PSS_SALTLEN 116
+#define EVP_R_KEYS_NOT_SET 117
+#define EVP_R_MISSING_PARAMETERS 118
+#define EVP_R_NO_DEFAULT_DIGEST 119
+#define EVP_R_NO_KEY_SET 120
+#define EVP_R_NO_MDC2_SUPPORT 121
+#define EVP_R_NO_NID_FOR_CURVE 122
+#define EVP_R_NO_OPERATION_SET 123
+#define EVP_R_NO_PARAMETERS_SET 124
+#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 125
+#define EVP_R_OPERATON_NOT_INITIALIZED 126
+#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 127
+#define EVP_R_UNSUPPORTED_ALGORITHM 128
+#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 129
#endif /* OPENSSL_HEADER_EVP_H */
diff --git a/include/openssl/hkdf.h b/include/openssl/hkdf.h
index b7a0dc25..a484a309 100644
--- a/include/openssl/hkdf.h
+++ b/include/openssl/hkdf.h
@@ -17,14 +17,17 @@
#include <openssl/base.h>
-#ifdef __cplusplus
+#if defined(__cplusplus)
extern "C" {
#endif
-/* Computes HKDF (as specified by RFC 5869) of initial keying material |secret|
- * with |salt| and |info| using |digest|, and outputs |out_len| bytes to
- * |out_key|. It returns one on success and zero on error.
+/* HKDF. */
+
+
+/* HKDF computes HKDF (as specified by RFC 5869) of initial keying material
+ * |secret| with |salt| and |info| using |digest|, and outputs |out_len| bytes
+ * to |out_key|. It returns one on success and zero on error.
*
* HKDF is an Extract-and-Expand algorithm. It does not do any key stretching,
* and as such, is not suited to be used alone to generate a key from a
@@ -34,6 +37,23 @@ OPENSSL_EXPORT int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
const uint8_t *salt, size_t salt_len,
const uint8_t *info, size_t info_len);
+/* HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from initial
+ * keying material |secret| and salt |salt| using |digest|, and outputs
+ * |out_len| bytes to |out_key|. The maximum output size is |EVP_MAX_MD_SIZE|.
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int HKDF_extract(uint8_t *out_key, size_t *out_len,
+ const EVP_MD *digest, const uint8_t *secret,
+ size_t secret_len, const uint8_t *salt,
+ size_t salt_len);
+
+/* HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of length
+ * |out_len| from the PRK |prk| and info |info| using |digest|, and outputs
+ * the result to |out_key|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int HKDF_expand(uint8_t *out_key, size_t out_len,
+ const EVP_MD *digest, uint8_t *prk,
+ size_t prk_len, const uint8_t *info,
+ size_t info_len);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/include/openssl/hmac.h b/include/openssl/hmac.h
index e521212d..5a4e9c7f 100644
--- a/include/openssl/hmac.h
+++ b/include/openssl/hmac.h
@@ -143,8 +143,6 @@ OPENSSL_EXPORT int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src);
/* Private functions */
-#define HMAC_MAX_MD_CBLOCK 128 /* largest known is SHA512 */
-
struct hmac_ctx_st {
const EVP_MD *md;
EVP_MD_CTX md_ctx;
diff --git a/include/openssl/md4.h b/include/openssl/md4.h
index 93c7af83..b66fcb0f 100644
--- a/include/openssl/md4.h
+++ b/include/openssl/md4.h
@@ -83,6 +83,10 @@ OPENSSL_EXPORT int MD4_Update(MD4_CTX *md4, const void *data, size_t len);
* returns one. */
OPENSSL_EXPORT int MD4_Final(uint8_t *md, MD4_CTX *md4);
+/* MD4 writes the digest of |len| bytes from |data| to |out| and returns |out|.
+ * There must be at least |MD4_DIGEST_LENGTH| bytes of space in |out|. */
+OPENSSL_EXPORT uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out);
+
/* MD4_Transform is a low-level function that performs a single, MD4 block
* transformation using the state from |md4| and 64 bytes from |block|. */
OPENSSL_EXPORT void MD4_Transform(MD4_CTX *md4, const uint8_t *block);
diff --git a/include/openssl/mem.h b/include/openssl/mem.h
index ba48f078..31756f03 100644
--- a/include/openssl/mem.h
+++ b/include/openssl/mem.h
@@ -124,6 +124,13 @@ OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format,
OPENSSL_PRINTF_FORMAT_FUNC(3, 0);
+/* Deprecated functions. */
+
+#define CRYPTO_malloc OPENSSL_malloc
+#define CRYPTO_realloc OPENSSL_realloc
+#define CRYPTO_free OPENSSL_free
+
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/include/openssl/newhope.h b/include/openssl/newhope.h
new file mode 100644
index 00000000..487e03f6
--- /dev/null
+++ b/include/openssl/newhope.h
@@ -0,0 +1,147 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_NEWHOPE_H
+#define OPENSSL_HEADER_NEWHOPE_H
+
+#include <openssl/base.h>
+#include <openssl/sha.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Post-quantum key agreement, based upon the reference
+ * implementation. Note: this implementation does not interoperate
+ * with the reference implementation!
+ *
+ * Source: https://github.com/tpoeppelmann/newhope
+ *
+ * The authors' permission to use their code is gratefully acknowledged. */
+
+
+/* NEWHOPE_POLY_new returns a new |NEWHOPE_POLY| object, or NULL on error. */
+OPENSSL_EXPORT NEWHOPE_POLY *NEWHOPE_POLY_new(void);
+
+/* NEWHOPE_POLY_free frees |p|. */
+OPENSSL_EXPORT void NEWHOPE_POLY_free(NEWHOPE_POLY *p);
+
+/* NEWHOPE_POLY_LENGTH is the size in bytes of the packed representation of a
+ * polynomial, encoded with 14 bits per coefficient. */
+#define NEWHOPE_POLY_LENGTH ((1024 * 14) / 8)
+
+/* NEWHOPE_RECONCILIATION_LENGTH is the size in bytes of the packed
+ * representation of the reconciliation data, encoded as 2 bits per
+ * coefficient. */
+#define NEWHOPE_RECONCILIATION_LENGTH ((1024 * 2) / 8)
+
+/* NEWHOPE_OFFERMSG_LENGTH is the length of the offering party's message to the
+ * accepting party. */
+#define NEWHOPE_OFFERMSG_LENGTH (NEWHOPE_POLY_LENGTH + 32)
+
+/* NEWHOPE_ACCEPTMSG_LENGTH is the length of the accepting party's message to
+ * the offering party. */
+#define NEWHOPE_ACCEPTMSG_LENGTH \
+ (NEWHOPE_POLY_LENGTH + NEWHOPE_RECONCILIATION_LENGTH)
+
+/* NEWHOPE_KEY_LENGTH is the size of the result of the key agreement. This
+ * result is not exposed to callers: instead, it is whitened with SHA-256, whose
+ * output happens to be the same size. */
+#define NEWHOPE_KEY_LENGTH 32
+
+/* NEWHOPE_offer initializes |out_msg| and |out_sk| for a new key
+ * exchange. |msg| must have room for |NEWHOPE_OFFERMSG_LENGTH| bytes. Neither
+ * output may be cached. */
+OPENSSL_EXPORT void NEWHOPE_offer(uint8_t out_msg[NEWHOPE_OFFERMSG_LENGTH],
+ NEWHOPE_POLY *out_sk);
+
+/* NEWHOPE_accept completes a key exchange given an offer message |msg|. The
+ * result of the key exchange is written to |out_key|, which must have space for
+ * |SHA256_DIGEST_LENGTH| bytes. The message to be send to the offering party is
+ * written to |out_msg|, which must have room for |NEWHOPE_ACCEPTMSG_LENGTH|
+ * bytes. Returns 1 on success and 0 on error. */
+OPENSSL_EXPORT int NEWHOPE_accept(uint8_t out_key[SHA256_DIGEST_LENGTH],
+ uint8_t out_msg[NEWHOPE_ACCEPTMSG_LENGTH],
+ const uint8_t msg[NEWHOPE_OFFERMSG_LENGTH],
+ size_t msg_len);
+
+/* NEWHOPE_finish completes a key exchange for the offering party, given an
+ * accept message |msg| and the previously generated secret |sk|. The result of
+ * the key exchange is written to |out_key|, which must have space for
+ * |SHA256_DIGEST_LENGTH| bytes. Returns 1 on success and 0 on error. */
+OPENSSL_EXPORT int NEWHOPE_finish(uint8_t out_key[SHA256_DIGEST_LENGTH],
+ const NEWHOPE_POLY *sk,
+ const uint8_t msg[NEWHOPE_ACCEPTMSG_LENGTH],
+ size_t msg_len);
+
+
+/* Lower-level functions. */
+
+/* NEWHOPE_POLY_noise sets |r| to a random polynomial where the coefficients are
+ * sampled from the noise distribution. */
+OPENSSL_EXPORT void NEWHOPE_POLY_noise(NEWHOPE_POLY* r);
+
+/* NEWHOPE_POLY_noise_ntt sets |r| to an output of NEWHOPE_POLY_noise, and then
+ * applies NTT(r) in-place. */
+OPENSSL_EXPORT void NEWHOPE_POLY_noise_ntt(NEWHOPE_POLY* r);
+
+/* NEWHOPE_offer_computation is the work of |NEWHOPE_offer|, less the encoding
+ * parts. The inputs are the noise polynomials |s| and |e|, and random
+ * polynomial |a|. The output is the polynomial |pk|. */
+OPENSSL_EXPORT void NEWHOPE_offer_computation(
+ NEWHOPE_POLY *out_pk,
+ const NEWHOPE_POLY *s, const NEWHOPE_POLY *e, const NEWHOPE_POLY *a);
+
+/* NEWHOPE_accept_computation is the work of |NEWHOPE_accept|, less the encoding
+ * parts. The inputs from the peer are |pk| and |a|. The locally-generated
+ * inputs are the noise polynomials |sp|, |ep|, and |epp|, and the random bytes
+ * |rand|. The outputs are |out_bp| and |out_reconciliation|, and the result of
+ * key agreement |key|. Returns 1 on success and 0 on failure. */
+OPENSSL_EXPORT void NEWHOPE_accept_computation(
+ uint8_t out_key[NEWHOPE_KEY_LENGTH], NEWHOPE_POLY *out_bp,
+ NEWHOPE_POLY *out_reconciliation,
+ const NEWHOPE_POLY *sp, const NEWHOPE_POLY *ep, const NEWHOPE_POLY *epp,
+ const uint8_t rand[32],
+ const NEWHOPE_POLY *pk, const NEWHOPE_POLY *a);
+
+/* NEWHOPE_finish_computation is the work of |NEWHOPE_finish|, less the encoding
+ * parts. Given the peer's |bp| and |reconciliation|, and locally-generated
+ * noise |noise|, the result of the key agreement is written to out_key.
+ * Returns 1 on success and 0 on failure. */
+OPENSSL_EXPORT void NEWHOPE_finish_computation(
+ uint8_t out_key[NEWHOPE_KEY_LENGTH], const NEWHOPE_POLY *noise,
+ const NEWHOPE_POLY *bp, const NEWHOPE_POLY *reconciliation);
+
+/* NEWHOPE_POLY_frombytes decodes |a| into |r|. */
+OPENSSL_EXPORT void NEWHOPE_POLY_frombytes(
+ NEWHOPE_POLY *r, const uint8_t a[NEWHOPE_POLY_LENGTH]);
+
+/* NEWHOPE_POLY_tobytes packs the polynomial |p| into the compact representation
+ * |r|. */
+OPENSSL_EXPORT void NEWHOPE_POLY_tobytes(uint8_t r[NEWHOPE_POLY_LENGTH],
+ const NEWHOPE_POLY* p);
+
+/* NEWHOPE_offer_frommsg decodes an offer message |msg| into its constituent
+ * polynomials |out_pk| and |a|. */
+OPENSSL_EXPORT void NEWHOPE_offer_frommsg(
+ NEWHOPE_POLY *out_pk, NEWHOPE_POLY *out_a,
+ const uint8_t msg[NEWHOPE_OFFERMSG_LENGTH]);
+
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+#endif /* OPENSSL_HEADER_NEWHOPE_H */
diff --git a/include/openssl/nid.h b/include/openssl/nid.h
new file mode 100644
index 00000000..5ed44ee3
--- /dev/null
+++ b/include/openssl/nid.h
@@ -0,0 +1,4166 @@
+/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
+ * following command:
+ * perl objects.pl objects.txt obj_mac.num ../../include/openssl/nid.h */
+
+/* Copyright (C) 1995-1997 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.]
+ */
+
+#ifndef OPENSSL_HEADER_NID_H
+#define OPENSSL_HEADER_NID_H
+
+
+/* The nid library provides numbered values for ASN.1 object identifiers and
+ * other symbols. These values are used by other libraries to identify
+ * cryptographic primitives.
+ *
+ * A separate objects library, obj.h, provides functions for converting between
+ * nids and object identifiers. However it depends on large internal tables with
+ * the encodings of every nid defind. Consumers concerned with binary size
+ * should instead embed the encodings of the few consumed OIDs and compare
+ * against those.
+ *
+ * These values should not be used outside of a single process; they are not
+ * stable identifiers. */
+
+
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
+
+#define SN_itu_t "ITU-T"
+#define LN_itu_t "itu-t"
+#define NID_itu_t 645
+#define OBJ_itu_t 0L
+
+#define NID_ccitt 404
+#define OBJ_ccitt OBJ_itu_t
+
+#define SN_iso "ISO"
+#define LN_iso "iso"
+#define NID_iso 181
+#define OBJ_iso 1L
+
+#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T"
+#define LN_joint_iso_itu_t "joint-iso-itu-t"
+#define NID_joint_iso_itu_t 646
+#define OBJ_joint_iso_itu_t 2L
+
+#define NID_joint_iso_ccitt 393
+#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t
+
+#define SN_member_body "member-body"
+#define LN_member_body "ISO Member Body"
+#define NID_member_body 182
+#define OBJ_member_body OBJ_iso,2L
+
+#define SN_identified_organization "identified-organization"
+#define NID_identified_organization 676
+#define OBJ_identified_organization OBJ_iso,3L
+
+#define SN_hmac_md5 "HMAC-MD5"
+#define LN_hmac_md5 "hmac-md5"
+#define NID_hmac_md5 780
+#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
+
+#define SN_hmac_sha1 "HMAC-SHA1"
+#define LN_hmac_sha1 "hmac-sha1"
+#define NID_hmac_sha1 781
+#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
+
+#define SN_certicom_arc "certicom-arc"
+#define NID_certicom_arc 677
+#define OBJ_certicom_arc OBJ_identified_organization,132L
+
+#define SN_international_organizations "international-organizations"
+#define LN_international_organizations "International Organizations"
+#define NID_international_organizations 647
+#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L
+
+#define SN_wap "wap"
+#define NID_wap 678
+#define OBJ_wap OBJ_international_organizations,43L
+
+#define SN_wap_wsg "wap-wsg"
+#define NID_wap_wsg 679
+#define OBJ_wap_wsg OBJ_wap,1L
+
+#define SN_selected_attribute_types "selected-attribute-types"
+#define LN_selected_attribute_types "Selected Attribute Types"
+#define NID_selected_attribute_types 394
+#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L
+
+#define SN_clearance "clearance"
+#define NID_clearance 395
+#define OBJ_clearance OBJ_selected_attribute_types,55L
+
+#define SN_ISO_US "ISO-US"
+#define LN_ISO_US "ISO US Member Body"
+#define NID_ISO_US 183
+#define OBJ_ISO_US OBJ_member_body,840L
+
+#define SN_X9_57 "X9-57"
+#define LN_X9_57 "X9.57"
+#define NID_X9_57 184
+#define OBJ_X9_57 OBJ_ISO_US,10040L
+
+#define SN_X9cm "X9cm"
+#define LN_X9cm "X9.57 CM ?"
+#define NID_X9cm 185
+#define OBJ_X9cm OBJ_X9_57,4L
+
+#define SN_dsa "DSA"
+#define LN_dsa "dsaEncryption"
+#define NID_dsa 116
+#define OBJ_dsa OBJ_X9cm,1L
+
+#define SN_dsaWithSHA1 "DSA-SHA1"
+#define LN_dsaWithSHA1 "dsaWithSHA1"
+#define NID_dsaWithSHA1 113
+#define OBJ_dsaWithSHA1 OBJ_X9cm,3L
+
+#define SN_ansi_X9_62 "ansi-X9-62"
+#define LN_ansi_X9_62 "ANSI X9.62"
+#define NID_ansi_X9_62 405
+#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L
+
+#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L
+
+#define SN_X9_62_prime_field "prime-field"
+#define NID_X9_62_prime_field 406
+#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L
+
+#define SN_X9_62_characteristic_two_field "characteristic-two-field"
+#define NID_X9_62_characteristic_two_field 407
+#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L
+
+#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis"
+#define NID_X9_62_id_characteristic_two_basis 680
+#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L
+
+#define SN_X9_62_onBasis "onBasis"
+#define NID_X9_62_onBasis 681
+#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L
+
+#define SN_X9_62_tpBasis "tpBasis"
+#define NID_X9_62_tpBasis 682
+#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L
+
+#define SN_X9_62_ppBasis "ppBasis"
+#define NID_X9_62_ppBasis 683
+#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L
+
+#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L
+
+#define SN_X9_62_id_ecPublicKey "id-ecPublicKey"
+#define NID_X9_62_id_ecPublicKey 408
+#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L
+
+#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L
+
+#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L
+
+#define SN_X9_62_c2pnb163v1 "c2pnb163v1"
+#define NID_X9_62_c2pnb163v1 684
+#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L
+
+#define SN_X9_62_c2pnb163v2 "c2pnb163v2"
+#define NID_X9_62_c2pnb163v2 685
+#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L
+
+#define SN_X9_62_c2pnb163v3 "c2pnb163v3"
+#define NID_X9_62_c2pnb163v3 686
+#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L
+
+#define SN_X9_62_c2pnb176v1 "c2pnb176v1"
+#define NID_X9_62_c2pnb176v1 687
+#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L
+
+#define SN_X9_62_c2tnb191v1 "c2tnb191v1"
+#define NID_X9_62_c2tnb191v1 688
+#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L
+
+#define SN_X9_62_c2tnb191v2 "c2tnb191v2"
+#define NID_X9_62_c2tnb191v2 689
+#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L
+
+#define SN_X9_62_c2tnb191v3 "c2tnb191v3"
+#define NID_X9_62_c2tnb191v3 690
+#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L
+
+#define SN_X9_62_c2onb191v4 "c2onb191v4"
+#define NID_X9_62_c2onb191v4 691
+#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L
+
+#define SN_X9_62_c2onb191v5 "c2onb191v5"
+#define NID_X9_62_c2onb191v5 692
+#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L
+
+#define SN_X9_62_c2pnb208w1 "c2pnb208w1"
+#define NID_X9_62_c2pnb208w1 693
+#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L
+
+#define SN_X9_62_c2tnb239v1 "c2tnb239v1"
+#define NID_X9_62_c2tnb239v1 694
+#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L
+
+#define SN_X9_62_c2tnb239v2 "c2tnb239v2"
+#define NID_X9_62_c2tnb239v2 695
+#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L
+
+#define SN_X9_62_c2tnb239v3 "c2tnb239v3"
+#define NID_X9_62_c2tnb239v3 696
+#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L
+
+#define SN_X9_62_c2onb239v4 "c2onb239v4"
+#define NID_X9_62_c2onb239v4 697
+#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L
+
+#define SN_X9_62_c2onb239v5 "c2onb239v5"
+#define NID_X9_62_c2onb239v5 698
+#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L
+
+#define SN_X9_62_c2pnb272w1 "c2pnb272w1"
+#define NID_X9_62_c2pnb272w1 699
+#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L
+
+#define SN_X9_62_c2pnb304w1 "c2pnb304w1"
+#define NID_X9_62_c2pnb304w1 700
+#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L
+
+#define SN_X9_62_c2tnb359v1 "c2tnb359v1"
+#define NID_X9_62_c2tnb359v1 701
+#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L
+
+#define SN_X9_62_c2pnb368w1 "c2pnb368w1"
+#define NID_X9_62_c2pnb368w1 702
+#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L
+
+#define SN_X9_62_c2tnb431r1 "c2tnb431r1"
+#define NID_X9_62_c2tnb431r1 703
+#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L
+
+#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L
+
+#define SN_X9_62_prime192v1 "prime192v1"
+#define NID_X9_62_prime192v1 409
+#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L
+
+#define SN_X9_62_prime192v2 "prime192v2"
+#define NID_X9_62_prime192v2 410
+#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L
+
+#define SN_X9_62_prime192v3 "prime192v3"
+#define NID_X9_62_prime192v3 411
+#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L
+
+#define SN_X9_62_prime239v1 "prime239v1"
+#define NID_X9_62_prime239v1 412
+#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L
+
+#define SN_X9_62_prime239v2 "prime239v2"
+#define NID_X9_62_prime239v2 413
+#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L
+
+#define SN_X9_62_prime239v3 "prime239v3"
+#define NID_X9_62_prime239v3 414
+#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L
+
+#define SN_X9_62_prime256v1 "prime256v1"
+#define NID_X9_62_prime256v1 415
+#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L
+
+#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L
+
+#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1"
+#define NID_ecdsa_with_SHA1 416
+#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L
+
+#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended"
+#define NID_ecdsa_with_Recommended 791
+#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L
+
+#define SN_ecdsa_with_Specified "ecdsa-with-Specified"
+#define NID_ecdsa_with_Specified 792
+#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L
+
+#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224"
+#define NID_ecdsa_with_SHA224 793
+#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L
+
+#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256"
+#define NID_ecdsa_with_SHA256 794
+#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L
+
+#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384"
+#define NID_ecdsa_with_SHA384 795
+#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L
+
+#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512"
+#define NID_ecdsa_with_SHA512 796
+#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L
+
+#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L
+
+#define SN_secp112r1 "secp112r1"
+#define NID_secp112r1 704
+#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L
+
+#define SN_secp112r2 "secp112r2"
+#define NID_secp112r2 705
+#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L
+
+#define SN_secp128r1 "secp128r1"
+#define NID_secp128r1 706
+#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L
+
+#define SN_secp128r2 "secp128r2"
+#define NID_secp128r2 707
+#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L
+
+#define SN_secp160k1 "secp160k1"
+#define NID_secp160k1 708
+#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L
+
+#define SN_secp160r1 "secp160r1"
+#define NID_secp160r1 709
+#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L
+
+#define SN_secp160r2 "secp160r2"
+#define NID_secp160r2 710
+#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L
+
+#define SN_secp192k1 "secp192k1"
+#define NID_secp192k1 711
+#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L
+
+#define SN_secp224k1 "secp224k1"
+#define NID_secp224k1 712
+#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L
+
+#define SN_secp224r1 "secp224r1"
+#define NID_secp224r1 713
+#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L
+
+#define SN_secp256k1 "secp256k1"
+#define NID_secp256k1 714
+#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L
+
+#define SN_secp384r1 "secp384r1"
+#define NID_secp384r1 715
+#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L
+
+#define SN_secp521r1 "secp521r1"
+#define NID_secp521r1 716
+#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L
+
+#define SN_sect113r1 "sect113r1"
+#define NID_sect113r1 717
+#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L
+
+#define SN_sect113r2 "sect113r2"
+#define NID_sect113r2 718
+#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L
+
+#define SN_sect131r1 "sect131r1"
+#define NID_sect131r1 719
+#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L
+
+#define SN_sect131r2 "sect131r2"
+#define NID_sect131r2 720
+#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L
+
+#define SN_sect163k1 "sect163k1"
+#define NID_sect163k1 721
+#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L
+
+#define SN_sect163r1 "sect163r1"
+#define NID_sect163r1 722
+#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L
+
+#define SN_sect163r2 "sect163r2"
+#define NID_sect163r2 723
+#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L
+
+#define SN_sect193r1 "sect193r1"
+#define NID_sect193r1 724
+#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L
+
+#define SN_sect193r2 "sect193r2"
+#define NID_sect193r2 725
+#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L
+
+#define SN_sect233k1 "sect233k1"
+#define NID_sect233k1 726
+#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L
+
+#define SN_sect233r1 "sect233r1"
+#define NID_sect233r1 727
+#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L
+
+#define SN_sect239k1 "sect239k1"
+#define NID_sect239k1 728
+#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L
+
+#define SN_sect283k1 "sect283k1"
+#define NID_sect283k1 729
+#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L
+
+#define SN_sect283r1 "sect283r1"
+#define NID_sect283r1 730
+#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L
+
+#define SN_sect409k1 "sect409k1"
+#define NID_sect409k1 731
+#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L
+
+#define SN_sect409r1 "sect409r1"
+#define NID_sect409r1 732
+#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L
+
+#define SN_sect571k1 "sect571k1"
+#define NID_sect571k1 733
+#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L
+
+#define SN_sect571r1 "sect571r1"
+#define NID_sect571r1 734
+#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L
+
+#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L
+
+#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1"
+#define NID_wap_wsg_idm_ecid_wtls1 735
+#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L
+
+#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3"
+#define NID_wap_wsg_idm_ecid_wtls3 736
+#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L
+
+#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4"
+#define NID_wap_wsg_idm_ecid_wtls4 737
+#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L
+
+#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5"
+#define NID_wap_wsg_idm_ecid_wtls5 738
+#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L
+
+#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6"
+#define NID_wap_wsg_idm_ecid_wtls6 739
+#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L
+
+#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7"
+#define NID_wap_wsg_idm_ecid_wtls7 740
+#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L
+
+#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8"
+#define NID_wap_wsg_idm_ecid_wtls8 741
+#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L
+
+#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9"
+#define NID_wap_wsg_idm_ecid_wtls9 742
+#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L
+
+#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10"
+#define NID_wap_wsg_idm_ecid_wtls10 743
+#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L
+
+#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11"
+#define NID_wap_wsg_idm_ecid_wtls11 744
+#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L
+
+#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12"
+#define NID_wap_wsg_idm_ecid_wtls12 745
+#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L
+
+#define SN_cast5_cbc "CAST5-CBC"
+#define LN_cast5_cbc "cast5-cbc"
+#define NID_cast5_cbc 108
+#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L
+
+#define SN_cast5_ecb "CAST5-ECB"
+#define LN_cast5_ecb "cast5-ecb"
+#define NID_cast5_ecb 109
+
+#define SN_cast5_cfb64 "CAST5-CFB"
+#define LN_cast5_cfb64 "cast5-cfb"
+#define NID_cast5_cfb64 110
+
+#define SN_cast5_ofb64 "CAST5-OFB"
+#define LN_cast5_ofb64 "cast5-ofb"
+#define NID_cast5_ofb64 111
+
+#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC 112
+#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L
+
+#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC"
+#define LN_id_PasswordBasedMAC "password based MAC"
+#define NID_id_PasswordBasedMAC 782
+#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L
+
+#define SN_id_DHBasedMac "id-DHBasedMac"
+#define LN_id_DHBasedMac "Diffie-Hellman based MAC"
+#define NID_id_DHBasedMac 783
+#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L
+
+#define SN_rsadsi "rsadsi"
+#define LN_rsadsi "RSA Data Security, Inc."
+#define NID_rsadsi 1
+#define OBJ_rsadsi OBJ_ISO_US,113549L
+
+#define SN_pkcs "pkcs"
+#define LN_pkcs "RSA Data Security, Inc. PKCS"
+#define NID_pkcs 2
+#define OBJ_pkcs OBJ_rsadsi,1L
+
+#define SN_pkcs1 "pkcs1"
+#define NID_pkcs1 186
+#define OBJ_pkcs1 OBJ_pkcs,1L
+
+#define LN_rsaEncryption "rsaEncryption"
+#define NID_rsaEncryption 6
+#define OBJ_rsaEncryption OBJ_pkcs1,1L
+
+#define SN_md2WithRSAEncryption "RSA-MD2"
+#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption 7
+#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L
+
+#define SN_md4WithRSAEncryption "RSA-MD4"
+#define LN_md4WithRSAEncryption "md4WithRSAEncryption"
+#define NID_md4WithRSAEncryption 396
+#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L
+
+#define SN_md5WithRSAEncryption "RSA-MD5"
+#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption 8
+#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L
+
+#define SN_sha1WithRSAEncryption "RSA-SHA1"
+#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption 65
+#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L
+
+#define SN_rsaesOaep "RSAES-OAEP"
+#define LN_rsaesOaep "rsaesOaep"
+#define NID_rsaesOaep 919
+#define OBJ_rsaesOaep OBJ_pkcs1,7L
+
+#define SN_mgf1 "MGF1"
+#define LN_mgf1 "mgf1"
+#define NID_mgf1 911
+#define OBJ_mgf1 OBJ_pkcs1,8L
+
+#define SN_pSpecified "PSPECIFIED"
+#define LN_pSpecified "pSpecified"
+#define NID_pSpecified 935
+#define OBJ_pSpecified OBJ_pkcs1,9L
+
+#define SN_rsassaPss "RSASSA-PSS"
+#define LN_rsassaPss "rsassaPss"
+#define NID_rsassaPss 912
+#define OBJ_rsassaPss OBJ_pkcs1,10L
+
+#define SN_sha256WithRSAEncryption "RSA-SHA256"
+#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption"
+#define NID_sha256WithRSAEncryption 668
+#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L
+
+#define SN_sha384WithRSAEncryption "RSA-SHA384"
+#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption"
+#define NID_sha384WithRSAEncryption 669
+#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L
+
+#define SN_sha512WithRSAEncryption "RSA-SHA512"
+#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption"
+#define NID_sha512WithRSAEncryption 670
+#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L
+
+#define SN_sha224WithRSAEncryption "RSA-SHA224"
+#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption"
+#define NID_sha224WithRSAEncryption 671
+#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L
+
+#define SN_pkcs3 "pkcs3"
+#define NID_pkcs3 27
+#define OBJ_pkcs3 OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement "dhKeyAgreement"
+#define NID_dhKeyAgreement 28
+#define OBJ_dhKeyAgreement OBJ_pkcs3,1L
+
+#define SN_pkcs5 "pkcs5"
+#define NID_pkcs5 187
+#define OBJ_pkcs5 OBJ_pkcs,5L
+
+#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC 9
+#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L
+
+#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC 10
+#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L
+
+#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC 168
+#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L
+
+#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC 169
+#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L
+
+#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC 170
+#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L
+
+#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC 68
+#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L
+
+#define LN_id_pbkdf2 "PBKDF2"
+#define NID_id_pbkdf2 69
+#define OBJ_id_pbkdf2 OBJ_pkcs5,12L
+
+#define LN_pbes2 "PBES2"
+#define NID_pbes2 161
+#define OBJ_pbes2 OBJ_pkcs5,13L
+
+#define LN_pbmac1 "PBMAC1"
+#define NID_pbmac1 162
+#define OBJ_pbmac1 OBJ_pkcs5,14L
+
+#define SN_pkcs7 "pkcs7"
+#define NID_pkcs7 20
+#define OBJ_pkcs7 OBJ_pkcs,7L
+
+#define LN_pkcs7_data "pkcs7-data"
+#define NID_pkcs7_data 21
+#define OBJ_pkcs7_data OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed "pkcs7-signedData"
+#define NID_pkcs7_signed 22
+#define OBJ_pkcs7_signed OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped "pkcs7-envelopedData"
+#define NID_pkcs7_enveloped 23
+#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped 24
+#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest "pkcs7-digestData"
+#define NID_pkcs7_digest 25
+#define OBJ_pkcs7_digest OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted "pkcs7-encryptedData"
+#define NID_pkcs7_encrypted 26
+#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L
+
+#define SN_pkcs9 "pkcs9"
+#define NID_pkcs9 47
+#define OBJ_pkcs9 OBJ_pkcs,9L
+
+#define LN_pkcs9_emailAddress "emailAddress"
+#define NID_pkcs9_emailAddress 48
+#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName "unstructuredName"
+#define NID_pkcs9_unstructuredName 49
+#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType "contentType"
+#define NID_pkcs9_contentType 50
+#define OBJ_pkcs9_contentType OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest "messageDigest"
+#define NID_pkcs9_messageDigest 51
+#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime "signingTime"
+#define NID_pkcs9_signingTime 52
+#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature "countersignature"
+#define NID_pkcs9_countersignature 53
+#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword "challengePassword"
+#define NID_pkcs9_challengePassword 54
+#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress 55
+#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes 56
+#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L
+
+#define SN_ext_req "extReq"
+#define LN_ext_req "Extension Request"
+#define NID_ext_req 172
+#define OBJ_ext_req OBJ_pkcs9,14L
+
+#define SN_SMIMECapabilities "SMIME-CAPS"
+#define LN_SMIMECapabilities "S/MIME Capabilities"
+#define NID_SMIMECapabilities 167
+#define OBJ_SMIMECapabilities OBJ_pkcs9,15L
+
+#define SN_SMIME "SMIME"
+#define LN_SMIME "S/MIME"
+#define NID_SMIME 188
+#define OBJ_SMIME OBJ_pkcs9,16L
+
+#define SN_id_smime_mod "id-smime-mod"
+#define NID_id_smime_mod 189
+#define OBJ_id_smime_mod OBJ_SMIME,0L
+
+#define SN_id_smime_ct "id-smime-ct"
+#define NID_id_smime_ct 190
+#define OBJ_id_smime_ct OBJ_SMIME,1L
+
+#define SN_id_smime_aa "id-smime-aa"
+#define NID_id_smime_aa 191
+#define OBJ_id_smime_aa OBJ_SMIME,2L
+
+#define SN_id_smime_alg "id-smime-alg"
+#define NID_id_smime_alg 192
+#define OBJ_id_smime_alg OBJ_SMIME,3L
+
+#define SN_id_smime_cd "id-smime-cd"
+#define NID_id_smime_cd 193
+#define OBJ_id_smime_cd OBJ_SMIME,4L
+
+#define SN_id_smime_spq "id-smime-spq"
+#define NID_id_smime_spq 194
+#define OBJ_id_smime_spq OBJ_SMIME,5L
+
+#define SN_id_smime_cti "id-smime-cti"
+#define NID_id_smime_cti 195
+#define OBJ_id_smime_cti OBJ_SMIME,6L
+
+#define SN_id_smime_mod_cms "id-smime-mod-cms"
+#define NID_id_smime_mod_cms 196
+#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
+
+#define SN_id_smime_mod_ess "id-smime-mod-ess"
+#define NID_id_smime_mod_ess 197
+#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L
+
+#define SN_id_smime_mod_oid "id-smime-mod-oid"
+#define NID_id_smime_mod_oid 198
+#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L
+
+#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3"
+#define NID_id_smime_mod_msg_v3 199
+#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L
+
+#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88"
+#define NID_id_smime_mod_ets_eSignature_88 200
+#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L
+
+#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97"
+#define NID_id_smime_mod_ets_eSignature_97 201
+#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L
+
+#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88"
+#define NID_id_smime_mod_ets_eSigPolicy_88 202
+#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L
+
+#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97"
+#define NID_id_smime_mod_ets_eSigPolicy_97 203
+#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L
+
+#define SN_id_smime_ct_receipt "id-smime-ct-receipt"
+#define NID_id_smime_ct_receipt 204
+#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L
+
+#define SN_id_smime_ct_authData "id-smime-ct-authData"
+#define NID_id_smime_ct_authData 205
+#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L
+
+#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert"
+#define NID_id_smime_ct_publishCert 206
+#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L
+
+#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo"
+#define NID_id_smime_ct_TSTInfo 207
+#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L
+
+#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo"
+#define NID_id_smime_ct_TDTInfo 208
+#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L
+
+#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo"
+#define NID_id_smime_ct_contentInfo 209
+#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L
+
+#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData"
+#define NID_id_smime_ct_DVCSRequestData 210
+#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L
+
+#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData"
+#define NID_id_smime_ct_DVCSResponseData 211
+#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L
+
+#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData"
+#define NID_id_smime_ct_compressedData 786
+#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L
+
+#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
+#define NID_id_ct_asciiTextWithCRLF 787
+#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L
+
+#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest"
+#define NID_id_smime_aa_receiptRequest 212
+#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L
+
+#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel"
+#define NID_id_smime_aa_securityLabel 213
+#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L
+
+#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory"
+#define NID_id_smime_aa_mlExpandHistory 214
+#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L
+
+#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint"
+#define NID_id_smime_aa_contentHint 215
+#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L
+
+#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest"
+#define NID_id_smime_aa_msgSigDigest 216
+#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L
+
+#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType"
+#define NID_id_smime_aa_encapContentType 217
+#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L
+
+#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier"
+#define NID_id_smime_aa_contentIdentifier 218
+#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L
+
+#define SN_id_smime_aa_macValue "id-smime-aa-macValue"
+#define NID_id_smime_aa_macValue 219
+#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L
+
+#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels"
+#define NID_id_smime_aa_equivalentLabels 220
+#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L
+
+#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference"
+#define NID_id_smime_aa_contentReference 221
+#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L
+
+#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref"
+#define NID_id_smime_aa_encrypKeyPref 222
+#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L
+
+#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate"
+#define NID_id_smime_aa_signingCertificate 223
+#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L
+
+#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts"
+#define NID_id_smime_aa_smimeEncryptCerts 224
+#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L
+
+#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken"
+#define NID_id_smime_aa_timeStampToken 225
+#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L
+
+#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId"
+#define NID_id_smime_aa_ets_sigPolicyId 226
+#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L
+
+#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType"
+#define NID_id_smime_aa_ets_commitmentType 227
+#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L
+
+#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation"
+#define NID_id_smime_aa_ets_signerLocation 228
+#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L
+
+#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr"
+#define NID_id_smime_aa_ets_signerAttr 229
+#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L
+
+#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert"
+#define NID_id_smime_aa_ets_otherSigCert 230
+#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L
+
+#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp"
+#define NID_id_smime_aa_ets_contentTimestamp 231
+#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L
+
+#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs"
+#define NID_id_smime_aa_ets_CertificateRefs 232
+#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L
+
+#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs"
+#define NID_id_smime_aa_ets_RevocationRefs 233
+#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L
+
+#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues"
+#define NID_id_smime_aa_ets_certValues 234
+#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L
+
+#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues"
+#define NID_id_smime_aa_ets_revocationValues 235
+#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L
+
+#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp"
+#define NID_id_smime_aa_ets_escTimeStamp 236
+#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L
+
+#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp"
+#define NID_id_smime_aa_ets_certCRLTimestamp 237
+#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L
+
+#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp"
+#define NID_id_smime_aa_ets_archiveTimeStamp 238
+#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L
+
+#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType"
+#define NID_id_smime_aa_signatureType 239
+#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L
+
+#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc"
+#define NID_id_smime_aa_dvcs_dvc 240
+#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L
+
+#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES"
+#define NID_id_smime_alg_ESDHwith3DES 241
+#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L
+
+#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2"
+#define NID_id_smime_alg_ESDHwithRC2 242
+#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L
+
+#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap"
+#define NID_id_smime_alg_3DESwrap 243
+#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L
+
+#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap"
+#define NID_id_smime_alg_RC2wrap 244
+#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L
+
+#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH"
+#define NID_id_smime_alg_ESDH 245
+#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L
+
+#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap"
+#define NID_id_smime_alg_CMS3DESwrap 246
+#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L
+
+#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap"
+#define NID_id_smime_alg_CMSRC2wrap 247
+#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L
+
+#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK"
+#define NID_id_alg_PWRI_KEK 893
+#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L
+
+#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
+#define NID_id_smime_cd_ldap 248
+#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L
+
+#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri"
+#define NID_id_smime_spq_ets_sqt_uri 249
+#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L
+
+#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice"
+#define NID_id_smime_spq_ets_sqt_unotice 250
+#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L
+
+#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin"
+#define NID_id_smime_cti_ets_proofOfOrigin 251
+#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L
+
+#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt"
+#define NID_id_smime_cti_ets_proofOfReceipt 252
+#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L
+
+#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery"
+#define NID_id_smime_cti_ets_proofOfDelivery 253
+#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L
+
+#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender"
+#define NID_id_smime_cti_ets_proofOfSender 254
+#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L
+
+#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval"
+#define NID_id_smime_cti_ets_proofOfApproval 255
+#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L
+
+#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation"
+#define NID_id_smime_cti_ets_proofOfCreation 256
+#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
+
+#define LN_friendlyName "friendlyName"
+#define NID_friendlyName 156
+#define OBJ_friendlyName OBJ_pkcs9,20L
+
+#define LN_localKeyID "localKeyID"
+#define NID_localKeyID 157
+#define OBJ_localKeyID OBJ_pkcs9,21L
+
+#define SN_ms_csp_name "CSPName"
+#define LN_ms_csp_name "Microsoft CSP Name"
+#define NID_ms_csp_name 417
+#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L
+
+#define SN_LocalKeySet "LocalKeySet"
+#define LN_LocalKeySet "Microsoft Local Key set"
+#define NID_LocalKeySet 856
+#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L
+
+#define OBJ_certTypes OBJ_pkcs9,22L
+
+#define LN_x509Certificate "x509Certificate"
+#define NID_x509Certificate 158
+#define OBJ_x509Certificate OBJ_certTypes,1L
+
+#define LN_sdsiCertificate "sdsiCertificate"
+#define NID_sdsiCertificate 159
+#define OBJ_sdsiCertificate OBJ_certTypes,2L
+
+#define OBJ_crlTypes OBJ_pkcs9,23L
+
+#define LN_x509Crl "x509Crl"
+#define NID_x509Crl 160
+#define OBJ_x509Crl OBJ_crlTypes,1L
+
+#define OBJ_pkcs12 OBJ_pkcs,12L
+
+#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L
+
+#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4 144
+#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L
+
+#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4 145
+#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC 148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC 149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L
+
+#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L
+
+#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L
+
+#define LN_keyBag "keyBag"
+#define NID_keyBag 150
+#define OBJ_keyBag OBJ_pkcs12_BagIds,1L
+
+#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag 151
+#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L
+
+#define LN_certBag "certBag"
+#define NID_certBag 152
+#define OBJ_certBag OBJ_pkcs12_BagIds,3L
+
+#define LN_crlBag "crlBag"
+#define NID_crlBag 153
+#define OBJ_crlBag OBJ_pkcs12_BagIds,4L
+
+#define LN_secretBag "secretBag"
+#define NID_secretBag 154
+#define OBJ_secretBag OBJ_pkcs12_BagIds,5L
+
+#define LN_safeContentsBag "safeContentsBag"
+#define NID_safeContentsBag 155
+#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L
+
+#define SN_md2 "MD2"
+#define LN_md2 "md2"
+#define NID_md2 3
+#define OBJ_md2 OBJ_rsadsi,2L,2L
+
+#define SN_md4 "MD4"
+#define LN_md4 "md4"
+#define NID_md4 257
+#define OBJ_md4 OBJ_rsadsi,2L,4L
+
+#define SN_md5 "MD5"
+#define LN_md5 "md5"
+#define NID_md5 4
+#define OBJ_md5 OBJ_rsadsi,2L,5L
+
+#define SN_md5_sha1 "MD5-SHA1"
+#define LN_md5_sha1 "md5-sha1"
+#define NID_md5_sha1 114
+
+#define LN_hmacWithMD5 "hmacWithMD5"
+#define NID_hmacWithMD5 797
+#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L
+
+#define LN_hmacWithSHA1 "hmacWithSHA1"
+#define NID_hmacWithSHA1 163
+#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
+
+#define LN_hmacWithSHA224 "hmacWithSHA224"
+#define NID_hmacWithSHA224 798
+#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L
+
+#define LN_hmacWithSHA256 "hmacWithSHA256"
+#define NID_hmacWithSHA256 799
+#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L
+
+#define LN_hmacWithSHA384 "hmacWithSHA384"
+#define NID_hmacWithSHA384 800
+#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L
+
+#define LN_hmacWithSHA512 "hmacWithSHA512"
+#define NID_hmacWithSHA512 801
+#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L
+
+#define SN_rc2_cbc "RC2-CBC"
+#define LN_rc2_cbc "rc2-cbc"
+#define NID_rc2_cbc 37
+#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb "RC2-ECB"
+#define LN_rc2_ecb "rc2-ecb"
+#define NID_rc2_ecb 38
+
+#define SN_rc2_cfb64 "RC2-CFB"
+#define LN_rc2_cfb64 "rc2-cfb"
+#define NID_rc2_cfb64 39
+
+#define SN_rc2_ofb64 "RC2-OFB"
+#define LN_rc2_ofb64 "rc2-ofb"
+#define NID_rc2_ofb64 40
+
+#define SN_rc2_40_cbc "RC2-40-CBC"
+#define LN_rc2_40_cbc "rc2-40-cbc"
+#define NID_rc2_40_cbc 98
+
+#define SN_rc2_64_cbc "RC2-64-CBC"
+#define LN_rc2_64_cbc "rc2-64-cbc"
+#define NID_rc2_64_cbc 166
+
+#define SN_rc4 "RC4"
+#define LN_rc4 "rc4"
+#define NID_rc4 5
+#define OBJ_rc4 OBJ_rsadsi,3L,4L
+
+#define SN_rc4_40 "RC4-40"
+#define LN_rc4_40 "rc4-40"
+#define NID_rc4_40 97
+
+#define SN_des_ede3_cbc "DES-EDE3-CBC"
+#define LN_des_ede3_cbc "des-ede3-cbc"
+#define NID_des_ede3_cbc 44
+#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L
+
+#define SN_rc5_cbc "RC5-CBC"
+#define LN_rc5_cbc "rc5-cbc"
+#define NID_rc5_cbc 120
+#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb "RC5-ECB"
+#define LN_rc5_ecb "rc5-ecb"
+#define NID_rc5_ecb 121
+
+#define SN_rc5_cfb64 "RC5-CFB"
+#define LN_rc5_cfb64 "rc5-cfb"
+#define NID_rc5_cfb64 122
+
+#define SN_rc5_ofb64 "RC5-OFB"
+#define LN_rc5_ofb64 "rc5-ofb"
+#define NID_rc5_ofb64 123
+
+#define SN_ms_ext_req "msExtReq"
+#define LN_ms_ext_req "Microsoft Extension Request"
+#define NID_ms_ext_req 171
+#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define SN_ms_code_ind "msCodeInd"
+#define LN_ms_code_ind "Microsoft Individual Code Signing"
+#define NID_ms_code_ind 134
+#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com "msCodeCom"
+#define LN_ms_code_com "Microsoft Commercial Code Signing"
+#define NID_ms_code_com 135
+#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign "msCTLSign"
+#define LN_ms_ctl_sign "Microsoft Trust List Signing"
+#define NID_ms_ctl_sign 136
+#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc "msSGC"
+#define LN_ms_sgc "Microsoft Server Gated Crypto"
+#define NID_ms_sgc 137
+#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs "msEFS"
+#define LN_ms_efs "Microsoft Encrypted File System"
+#define NID_ms_efs 138
+#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+#define SN_ms_smartcard_login "msSmartcardLogin"
+#define LN_ms_smartcard_login "Microsoft Smartcardlogin"
+#define NID_ms_smartcard_login 648
+#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
+
+#define SN_ms_upn "msUPN"
+#define LN_ms_upn "Microsoft Universal Principal Name"
+#define NID_ms_upn 649
+#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
+
+#define SN_idea_cbc "IDEA-CBC"
+#define LN_idea_cbc "idea-cbc"
+#define NID_idea_cbc 34
+#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_ecb "IDEA-ECB"
+#define LN_idea_ecb "idea-ecb"
+#define NID_idea_ecb 36
+
+#define SN_idea_cfb64 "IDEA-CFB"
+#define LN_idea_cfb64 "idea-cfb"
+#define NID_idea_cfb64 35
+
+#define SN_idea_ofb64 "IDEA-OFB"
+#define LN_idea_ofb64 "idea-ofb"
+#define NID_idea_ofb64 46
+
+#define SN_bf_cbc "BF-CBC"
+#define LN_bf_cbc "bf-cbc"
+#define NID_bf_cbc 91
+#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb "BF-ECB"
+#define LN_bf_ecb "bf-ecb"
+#define NID_bf_ecb 92
+
+#define SN_bf_cfb64 "BF-CFB"
+#define LN_bf_cfb64 "bf-cfb"
+#define NID_bf_cfb64 93
+
+#define SN_bf_ofb64 "BF-OFB"
+#define LN_bf_ofb64 "bf-ofb"
+#define NID_bf_ofb64 94
+
+#define SN_id_pkix "PKIX"
+#define NID_id_pkix 127
+#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_pkix_mod "id-pkix-mod"
+#define NID_id_pkix_mod 258
+#define OBJ_id_pkix_mod OBJ_id_pkix,0L
+
+#define SN_id_pe "id-pe"
+#define NID_id_pe 175
+#define OBJ_id_pe OBJ_id_pkix,1L
+
+#define SN_id_qt "id-qt"
+#define NID_id_qt 259
+#define OBJ_id_qt OBJ_id_pkix,2L
+
+#define SN_id_kp "id-kp"
+#define NID_id_kp 128
+#define OBJ_id_kp OBJ_id_pkix,3L
+
+#define SN_id_it "id-it"
+#define NID_id_it 260
+#define OBJ_id_it OBJ_id_pkix,4L
+
+#define SN_id_pkip "id-pkip"
+#define NID_id_pkip 261
+#define OBJ_id_pkip OBJ_id_pkix,5L
+
+#define SN_id_alg "id-alg"
+#define NID_id_alg 262
+#define OBJ_id_alg OBJ_id_pkix,6L
+
+#define SN_id_cmc "id-cmc"
+#define NID_id_cmc 263
+#define OBJ_id_cmc OBJ_id_pkix,7L
+
+#define SN_id_on "id-on"
+#define NID_id_on 264
+#define OBJ_id_on OBJ_id_pkix,8L
+
+#define SN_id_pda "id-pda"
+#define NID_id_pda 265
+#define OBJ_id_pda OBJ_id_pkix,9L
+
+#define SN_id_aca "id-aca"
+#define NID_id_aca 266
+#define OBJ_id_aca OBJ_id_pkix,10L
+
+#define SN_id_qcs "id-qcs"
+#define NID_id_qcs 267
+#define OBJ_id_qcs OBJ_id_pkix,11L
+
+#define SN_id_cct "id-cct"
+#define NID_id_cct 268
+#define OBJ_id_cct OBJ_id_pkix,12L
+
+#define SN_id_ppl "id-ppl"
+#define NID_id_ppl 662
+#define OBJ_id_ppl OBJ_id_pkix,21L
+
+#define SN_id_ad "id-ad"
+#define NID_id_ad 176
+#define OBJ_id_ad OBJ_id_pkix,48L
+
+#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88"
+#define NID_id_pkix1_explicit_88 269
+#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L
+
+#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88"
+#define NID_id_pkix1_implicit_88 270
+#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L
+
+#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93"
+#define NID_id_pkix1_explicit_93 271
+#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L
+
+#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93"
+#define NID_id_pkix1_implicit_93 272
+#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L
+
+#define SN_id_mod_crmf "id-mod-crmf"
+#define NID_id_mod_crmf 273
+#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L
+
+#define SN_id_mod_cmc "id-mod-cmc"
+#define NID_id_mod_cmc 274
+#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L
+
+#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88"
+#define NID_id_mod_kea_profile_88 275
+#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L
+
+#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93"
+#define NID_id_mod_kea_profile_93 276
+#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L
+
+#define SN_id_mod_cmp "id-mod-cmp"
+#define NID_id_mod_cmp 277
+#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L
+
+#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88"
+#define NID_id_mod_qualified_cert_88 278
+#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L
+
+#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93"
+#define NID_id_mod_qualified_cert_93 279
+#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L
+
+#define SN_id_mod_attribute_cert "id-mod-attribute-cert"
+#define NID_id_mod_attribute_cert 280
+#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L
+
+#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol"
+#define NID_id_mod_timestamp_protocol 281
+#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L
+
+#define SN_id_mod_ocsp "id-mod-ocsp"
+#define NID_id_mod_ocsp 282
+#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L
+
+#define SN_id_mod_dvcs "id-mod-dvcs"
+#define NID_id_mod_dvcs 283
+#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L
+
+#define SN_id_mod_cmp2000 "id-mod-cmp2000"
+#define NID_id_mod_cmp2000 284
+#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L
+
+#define SN_info_access "authorityInfoAccess"
+#define LN_info_access "Authority Information Access"
+#define NID_info_access 177
+#define OBJ_info_access OBJ_id_pe,1L
+
+#define SN_biometricInfo "biometricInfo"
+#define LN_biometricInfo "Biometric Info"
+#define NID_biometricInfo 285
+#define OBJ_biometricInfo OBJ_id_pe,2L
+
+#define SN_qcStatements "qcStatements"
+#define NID_qcStatements 286
+#define OBJ_qcStatements OBJ_id_pe,3L
+
+#define SN_ac_auditEntity "ac-auditEntity"
+#define NID_ac_auditEntity 287
+#define OBJ_ac_auditEntity OBJ_id_pe,4L
+
+#define SN_ac_targeting "ac-targeting"
+#define NID_ac_targeting 288
+#define OBJ_ac_targeting OBJ_id_pe,5L
+
+#define SN_aaControls "aaControls"
+#define NID_aaControls 289
+#define OBJ_aaControls OBJ_id_pe,6L
+
+#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock"
+#define NID_sbgp_ipAddrBlock 290
+#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L
+
+#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum"
+#define NID_sbgp_autonomousSysNum 291
+#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L
+
+#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier"
+#define NID_sbgp_routerIdentifier 292
+#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L
+
+#define SN_ac_proxying "ac-proxying"
+#define NID_ac_proxying 397
+#define OBJ_ac_proxying OBJ_id_pe,10L
+
+#define SN_sinfo_access "subjectInfoAccess"
+#define LN_sinfo_access "Subject Information Access"
+#define NID_sinfo_access 398
+#define OBJ_sinfo_access OBJ_id_pe,11L
+
+#define SN_proxyCertInfo "proxyCertInfo"
+#define LN_proxyCertInfo "Proxy Certificate Information"
+#define NID_proxyCertInfo 663
+#define OBJ_proxyCertInfo OBJ_id_pe,14L
+
+#define SN_id_qt_cps "id-qt-cps"
+#define LN_id_qt_cps "Policy Qualifier CPS"
+#define NID_id_qt_cps 164
+#define OBJ_id_qt_cps OBJ_id_qt,1L
+
+#define SN_id_qt_unotice "id-qt-unotice"
+#define LN_id_qt_unotice "Policy Qualifier User Notice"
+#define NID_id_qt_unotice 165
+#define OBJ_id_qt_unotice OBJ_id_qt,2L
+
+#define SN_textNotice "textNotice"
+#define NID_textNotice 293
+#define OBJ_textNotice OBJ_id_qt,3L
+
+#define SN_server_auth "serverAuth"
+#define LN_server_auth "TLS Web Server Authentication"
+#define NID_server_auth 129
+#define OBJ_server_auth OBJ_id_kp,1L
+
+#define SN_client_auth "clientAuth"
+#define LN_client_auth "TLS Web Client Authentication"
+#define NID_client_auth 130
+#define OBJ_client_auth OBJ_id_kp,2L
+
+#define SN_code_sign "codeSigning"
+#define LN_code_sign "Code Signing"
+#define NID_code_sign 131
+#define OBJ_code_sign OBJ_id_kp,3L
+
+#define SN_email_protect "emailProtection"
+#define LN_email_protect "E-mail Protection"
+#define NID_email_protect 132
+#define OBJ_email_protect OBJ_id_kp,4L
+
+#define SN_ipsecEndSystem "ipsecEndSystem"
+#define LN_ipsecEndSystem "IPSec End System"
+#define NID_ipsecEndSystem 294
+#define OBJ_ipsecEndSystem OBJ_id_kp,5L
+
+#define SN_ipsecTunnel "ipsecTunnel"
+#define LN_ipsecTunnel "IPSec Tunnel"
+#define NID_ipsecTunnel 295
+#define OBJ_ipsecTunnel OBJ_id_kp,6L
+
+#define SN_ipsecUser "ipsecUser"
+#define LN_ipsecUser "IPSec User"
+#define NID_ipsecUser 296
+#define OBJ_ipsecUser OBJ_id_kp,7L
+
+#define SN_time_stamp "timeStamping"
+#define LN_time_stamp "Time Stamping"
+#define NID_time_stamp 133
+#define OBJ_time_stamp OBJ_id_kp,8L
+
+#define SN_OCSP_sign "OCSPSigning"
+#define LN_OCSP_sign "OCSP Signing"
+#define NID_OCSP_sign 180
+#define OBJ_OCSP_sign OBJ_id_kp,9L
+
+#define SN_dvcs "DVCS"
+#define LN_dvcs "dvcs"
+#define NID_dvcs 297
+#define OBJ_dvcs OBJ_id_kp,10L
+
+#define SN_id_it_caProtEncCert "id-it-caProtEncCert"
+#define NID_id_it_caProtEncCert 298
+#define OBJ_id_it_caProtEncCert OBJ_id_it,1L
+
+#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes"
+#define NID_id_it_signKeyPairTypes 299
+#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L
+
+#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes"
+#define NID_id_it_encKeyPairTypes 300
+#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L
+
+#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg"
+#define NID_id_it_preferredSymmAlg 301
+#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L
+
+#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo"
+#define NID_id_it_caKeyUpdateInfo 302
+#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L
+
+#define SN_id_it_currentCRL "id-it-currentCRL"
+#define NID_id_it_currentCRL 303
+#define OBJ_id_it_currentCRL OBJ_id_it,6L
+
+#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs"
+#define NID_id_it_unsupportedOIDs 304
+#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L
+
+#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest"
+#define NID_id_it_subscriptionRequest 305
+#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L
+
+#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse"
+#define NID_id_it_subscriptionResponse 306
+#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L
+
+#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq"
+#define NID_id_it_keyPairParamReq 307
+#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L
+
+#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep"
+#define NID_id_it_keyPairParamRep 308
+#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L
+
+#define SN_id_it_revPassphrase "id-it-revPassphrase"
+#define NID_id_it_revPassphrase 309
+#define OBJ_id_it_revPassphrase OBJ_id_it,12L
+
+#define SN_id_it_implicitConfirm "id-it-implicitConfirm"
+#define NID_id_it_implicitConfirm 310
+#define OBJ_id_it_implicitConfirm OBJ_id_it,13L
+
+#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime"
+#define NID_id_it_confirmWaitTime 311
+#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L
+
+#define SN_id_it_origPKIMessage "id-it-origPKIMessage"
+#define NID_id_it_origPKIMessage 312
+#define OBJ_id_it_origPKIMessage OBJ_id_it,15L
+
+#define SN_id_it_suppLangTags "id-it-suppLangTags"
+#define NID_id_it_suppLangTags 784
+#define OBJ_id_it_suppLangTags OBJ_id_it,16L
+
+#define SN_id_regCtrl "id-regCtrl"
+#define NID_id_regCtrl 313
+#define OBJ_id_regCtrl OBJ_id_pkip,1L
+
+#define SN_id_regInfo "id-regInfo"
+#define NID_id_regInfo 314
+#define OBJ_id_regInfo OBJ_id_pkip,2L
+
+#define SN_id_regCtrl_regToken "id-regCtrl-regToken"
+#define NID_id_regCtrl_regToken 315
+#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L
+
+#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator"
+#define NID_id_regCtrl_authenticator 316
+#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L
+
+#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo"
+#define NID_id_regCtrl_pkiPublicationInfo 317
+#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L
+
+#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions"
+#define NID_id_regCtrl_pkiArchiveOptions 318
+#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L
+
+#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID"
+#define NID_id_regCtrl_oldCertID 319
+#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L
+
+#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey"
+#define NID_id_regCtrl_protocolEncrKey 320
+#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L
+
+#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs"
+#define NID_id_regInfo_utf8Pairs 321
+#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L
+
+#define SN_id_regInfo_certReq "id-regInfo-certReq"
+#define NID_id_regInfo_certReq 322
+#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L
+
+#define SN_id_alg_des40 "id-alg-des40"
+#define NID_id_alg_des40 323
+#define OBJ_id_alg_des40 OBJ_id_alg,1L
+
+#define SN_id_alg_noSignature "id-alg-noSignature"
+#define NID_id_alg_noSignature 324
+#define OBJ_id_alg_noSignature OBJ_id_alg,2L
+
+#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1"
+#define NID_id_alg_dh_sig_hmac_sha1 325
+#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L
+
+#define SN_id_alg_dh_pop "id-alg-dh-pop"
+#define NID_id_alg_dh_pop 326
+#define OBJ_id_alg_dh_pop OBJ_id_alg,4L
+
+#define SN_id_cmc_statusInfo "id-cmc-statusInfo"
+#define NID_id_cmc_statusInfo 327
+#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L
+
+#define SN_id_cmc_identification "id-cmc-identification"
+#define NID_id_cmc_identification 328
+#define OBJ_id_cmc_identification OBJ_id_cmc,2L
+
+#define SN_id_cmc_identityProof "id-cmc-identityProof"
+#define NID_id_cmc_identityProof 329
+#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L
+
+#define SN_id_cmc_dataReturn "id-cmc-dataReturn"
+#define NID_id_cmc_dataReturn 330
+#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L
+
+#define SN_id_cmc_transactionId "id-cmc-transactionId"
+#define NID_id_cmc_transactionId 331
+#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L
+
+#define SN_id_cmc_senderNonce "id-cmc-senderNonce"
+#define NID_id_cmc_senderNonce 332
+#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L
+
+#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce"
+#define NID_id_cmc_recipientNonce 333
+#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L
+
+#define SN_id_cmc_addExtensions "id-cmc-addExtensions"
+#define NID_id_cmc_addExtensions 334
+#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L
+
+#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP"
+#define NID_id_cmc_encryptedPOP 335
+#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L
+
+#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP"
+#define NID_id_cmc_decryptedPOP 336
+#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L
+
+#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness"
+#define NID_id_cmc_lraPOPWitness 337
+#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L
+
+#define SN_id_cmc_getCert "id-cmc-getCert"
+#define NID_id_cmc_getCert 338
+#define OBJ_id_cmc_getCert OBJ_id_cmc,15L
+
+#define SN_id_cmc_getCRL "id-cmc-getCRL"
+#define NID_id_cmc_getCRL 339
+#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L
+
+#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest"
+#define NID_id_cmc_revokeRequest 340
+#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L
+
+#define SN_id_cmc_regInfo "id-cmc-regInfo"
+#define NID_id_cmc_regInfo 341
+#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L
+
+#define SN_id_cmc_responseInfo "id-cmc-responseInfo"
+#define NID_id_cmc_responseInfo 342
+#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L
+
+#define SN_id_cmc_queryPending "id-cmc-queryPending"
+#define NID_id_cmc_queryPending 343
+#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L
+
+#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom"
+#define NID_id_cmc_popLinkRandom 344
+#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L
+
+#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness"
+#define NID_id_cmc_popLinkWitness 345
+#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L
+
+#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance"
+#define NID_id_cmc_confirmCertAcceptance 346
+#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L
+
+#define SN_id_on_personalData "id-on-personalData"
+#define NID_id_on_personalData 347
+#define OBJ_id_on_personalData OBJ_id_on,1L
+
+#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier"
+#define LN_id_on_permanentIdentifier "Permanent Identifier"
+#define NID_id_on_permanentIdentifier 858
+#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L
+
+#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth"
+#define NID_id_pda_dateOfBirth 348
+#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L
+
+#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth"
+#define NID_id_pda_placeOfBirth 349
+#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L
+
+#define SN_id_pda_gender "id-pda-gender"
+#define NID_id_pda_gender 351
+#define OBJ_id_pda_gender OBJ_id_pda,3L
+
+#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship"
+#define NID_id_pda_countryOfCitizenship 352
+#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L
+
+#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence"
+#define NID_id_pda_countryOfResidence 353
+#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L
+
+#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo"
+#define NID_id_aca_authenticationInfo 354
+#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L
+
+#define SN_id_aca_accessIdentity "id-aca-accessIdentity"
+#define NID_id_aca_accessIdentity 355
+#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L
+
+#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity"
+#define NID_id_aca_chargingIdentity 356
+#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L
+
+#define SN_id_aca_group "id-aca-group"
+#define NID_id_aca_group 357
+#define OBJ_id_aca_group OBJ_id_aca,4L
+
+#define SN_id_aca_role "id-aca-role"
+#define NID_id_aca_role 358
+#define OBJ_id_aca_role OBJ_id_aca,5L
+
+#define SN_id_aca_encAttrs "id-aca-encAttrs"
+#define NID_id_aca_encAttrs 399
+#define OBJ_id_aca_encAttrs OBJ_id_aca,6L
+
+#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1"
+#define NID_id_qcs_pkixQCSyntax_v1 359
+#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L
+
+#define SN_id_cct_crs "id-cct-crs"
+#define NID_id_cct_crs 360
+#define OBJ_id_cct_crs OBJ_id_cct,1L
+
+#define SN_id_cct_PKIData "id-cct-PKIData"
+#define NID_id_cct_PKIData 361
+#define OBJ_id_cct_PKIData OBJ_id_cct,2L
+
+#define SN_id_cct_PKIResponse "id-cct-PKIResponse"
+#define NID_id_cct_PKIResponse 362
+#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L
+
+#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage"
+#define LN_id_ppl_anyLanguage "Any language"
+#define NID_id_ppl_anyLanguage 664
+#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L
+
+#define SN_id_ppl_inheritAll "id-ppl-inheritAll"
+#define LN_id_ppl_inheritAll "Inherit all"
+#define NID_id_ppl_inheritAll 665
+#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L
+
+#define SN_Independent "id-ppl-independent"
+#define LN_Independent "Independent"
+#define NID_Independent 667
+#define OBJ_Independent OBJ_id_ppl,2L
+
+#define SN_ad_OCSP "OCSP"
+#define LN_ad_OCSP "OCSP"
+#define NID_ad_OCSP 178
+#define OBJ_ad_OCSP OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers "caIssuers"
+#define LN_ad_ca_issuers "CA Issuers"
+#define NID_ad_ca_issuers 179
+#define OBJ_ad_ca_issuers OBJ_id_ad,2L
+
+#define SN_ad_timeStamping "ad_timestamping"
+#define LN_ad_timeStamping "AD Time Stamping"
+#define NID_ad_timeStamping 363
+#define OBJ_ad_timeStamping OBJ_id_ad,3L
+
+#define SN_ad_dvcs "AD_DVCS"
+#define LN_ad_dvcs "ad dvcs"
+#define NID_ad_dvcs 364
+#define OBJ_ad_dvcs OBJ_id_ad,4L
+
+#define SN_caRepository "caRepository"
+#define LN_caRepository "CA Repository"
+#define NID_caRepository 785
+#define OBJ_caRepository OBJ_id_ad,5L
+
+#define OBJ_id_pkix_OCSP OBJ_ad_OCSP
+
+#define SN_id_pkix_OCSP_basic "basicOCSPResponse"
+#define LN_id_pkix_OCSP_basic "Basic OCSP Response"
+#define NID_id_pkix_OCSP_basic 365
+#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L
+
+#define SN_id_pkix_OCSP_Nonce "Nonce"
+#define LN_id_pkix_OCSP_Nonce "OCSP Nonce"
+#define NID_id_pkix_OCSP_Nonce 366
+#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L
+
+#define SN_id_pkix_OCSP_CrlID "CrlID"
+#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID"
+#define NID_id_pkix_OCSP_CrlID 367
+#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L
+
+#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses"
+#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses"
+#define NID_id_pkix_OCSP_acceptableResponses 368
+#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L
+
+#define SN_id_pkix_OCSP_noCheck "noCheck"
+#define LN_id_pkix_OCSP_noCheck "OCSP No Check"
+#define NID_id_pkix_OCSP_noCheck 369
+#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L
+
+#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff"
+#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff"
+#define NID_id_pkix_OCSP_archiveCutoff 370
+#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L
+
+#define SN_id_pkix_OCSP_serviceLocator "serviceLocator"
+#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator"
+#define NID_id_pkix_OCSP_serviceLocator 371
+#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L
+
+#define SN_id_pkix_OCSP_extendedStatus "extendedStatus"
+#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status"
+#define NID_id_pkix_OCSP_extendedStatus 372
+#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L
+
+#define SN_id_pkix_OCSP_valid "valid"
+#define NID_id_pkix_OCSP_valid 373
+#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L
+
+#define SN_id_pkix_OCSP_path "path"
+#define NID_id_pkix_OCSP_path 374
+#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L
+
+#define SN_id_pkix_OCSP_trustRoot "trustRoot"
+#define LN_id_pkix_OCSP_trustRoot "Trust Root"
+#define NID_id_pkix_OCSP_trustRoot 375
+#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L
+
+#define SN_algorithm "algorithm"
+#define LN_algorithm "algorithm"
+#define NID_algorithm 376
+#define OBJ_algorithm 1L,3L,14L,3L,2L
+
+#define SN_md5WithRSA "RSA-NP-MD5"
+#define LN_md5WithRSA "md5WithRSA"
+#define NID_md5WithRSA 104
+#define OBJ_md5WithRSA OBJ_algorithm,3L
+
+#define SN_des_ecb "DES-ECB"
+#define LN_des_ecb "des-ecb"
+#define NID_des_ecb 29
+#define OBJ_des_ecb OBJ_algorithm,6L
+
+#define SN_des_cbc "DES-CBC"
+#define LN_des_cbc "des-cbc"
+#define NID_des_cbc 31
+#define OBJ_des_cbc OBJ_algorithm,7L
+
+#define SN_des_ofb64 "DES-OFB"
+#define LN_des_ofb64 "des-ofb"
+#define NID_des_ofb64 45
+#define OBJ_des_ofb64 OBJ_algorithm,8L
+
+#define SN_des_cfb64 "DES-CFB"
+#define LN_des_cfb64 "des-cfb"
+#define NID_des_cfb64 30
+#define OBJ_des_cfb64 OBJ_algorithm,9L
+
+#define SN_rsaSignature "rsaSignature"
+#define NID_rsaSignature 377
+#define OBJ_rsaSignature OBJ_algorithm,11L
+
+#define SN_dsa_2 "DSA-old"
+#define LN_dsa_2 "dsaEncryption-old"
+#define NID_dsa_2 67
+#define OBJ_dsa_2 OBJ_algorithm,12L
+
+#define SN_dsaWithSHA "DSA-SHA"
+#define LN_dsaWithSHA "dsaWithSHA"
+#define NID_dsaWithSHA 66
+#define OBJ_dsaWithSHA OBJ_algorithm,13L
+
+#define SN_shaWithRSAEncryption "RSA-SHA"
+#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption 42
+#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L
+
+#define SN_des_ede_ecb "DES-EDE"
+#define LN_des_ede_ecb "des-ede"
+#define NID_des_ede_ecb 32
+#define OBJ_des_ede_ecb OBJ_algorithm,17L
+
+#define SN_des_ede3_ecb "DES-EDE3"
+#define LN_des_ede3_ecb "des-ede3"
+#define NID_des_ede3_ecb 33
+
+#define SN_des_ede_cbc "DES-EDE-CBC"
+#define LN_des_ede_cbc "des-ede-cbc"
+#define NID_des_ede_cbc 43
+
+#define SN_des_ede_cfb64 "DES-EDE-CFB"
+#define LN_des_ede_cfb64 "des-ede-cfb"
+#define NID_des_ede_cfb64 60
+
+#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
+#define LN_des_ede3_cfb64 "des-ede3-cfb"
+#define NID_des_ede3_cfb64 61
+
+#define SN_des_ede_ofb64 "DES-EDE-OFB"
+#define LN_des_ede_ofb64 "des-ede-ofb"
+#define NID_des_ede_ofb64 62
+
+#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
+#define LN_des_ede3_ofb64 "des-ede3-ofb"
+#define NID_des_ede3_ofb64 63
+
+#define SN_desx_cbc "DESX-CBC"
+#define LN_desx_cbc "desx-cbc"
+#define NID_desx_cbc 80
+
+#define SN_sha "SHA"
+#define LN_sha "sha"
+#define NID_sha 41
+#define OBJ_sha OBJ_algorithm,18L
+
+#define SN_sha1 "SHA1"
+#define LN_sha1 "sha1"
+#define NID_sha1 64
+#define OBJ_sha1 OBJ_algorithm,26L
+
+#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
+#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2 70
+#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L
+
+#define SN_sha1WithRSA "RSA-SHA1-2"
+#define LN_sha1WithRSA "sha1WithRSA"
+#define NID_sha1WithRSA 115
+#define OBJ_sha1WithRSA OBJ_algorithm,29L
+
+#define SN_ripemd160 "RIPEMD160"
+#define LN_ripemd160 "ripemd160"
+#define NID_ripemd160 117
+#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L
+
+#define SN_ripemd160WithRSA "RSA-RIPEMD160"
+#define LN_ripemd160WithRSA "ripemd160WithRSA"
+#define NID_ripemd160WithRSA 119
+#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
+
+#define SN_sxnet "SXNetID"
+#define LN_sxnet "Strong Extranet ID"
+#define NID_sxnet 143
+#define OBJ_sxnet 1L,3L,101L,1L,4L,1L
+
+#define SN_X500 "X500"
+#define LN_X500 "directory services (X.500)"
+#define NID_X500 11
+#define OBJ_X500 2L,5L
+
+#define SN_X509 "X509"
+#define NID_X509 12
+#define OBJ_X509 OBJ_X500,4L
+
+#define SN_commonName "CN"
+#define LN_commonName "commonName"
+#define NID_commonName 13
+#define OBJ_commonName OBJ_X509,3L
+
+#define SN_surname "SN"
+#define LN_surname "surname"
+#define NID_surname 100
+#define OBJ_surname OBJ_X509,4L
+
+#define LN_serialNumber "serialNumber"
+#define NID_serialNumber 105
+#define OBJ_serialNumber OBJ_X509,5L
+
+#define SN_countryName "C"
+#define LN_countryName "countryName"
+#define NID_countryName 14
+#define OBJ_countryName OBJ_X509,6L
+
+#define SN_localityName "L"
+#define LN_localityName "localityName"
+#define NID_localityName 15
+#define OBJ_localityName OBJ_X509,7L
+
+#define SN_stateOrProvinceName "ST"
+#define LN_stateOrProvinceName "stateOrProvinceName"
+#define NID_stateOrProvinceName 16
+#define OBJ_stateOrProvinceName OBJ_X509,8L
+
+#define SN_streetAddress "street"
+#define LN_streetAddress "streetAddress"
+#define NID_streetAddress 660
+#define OBJ_streetAddress OBJ_X509,9L
+
+#define SN_organizationName "O"
+#define LN_organizationName "organizationName"
+#define NID_organizationName 17
+#define OBJ_organizationName OBJ_X509,10L
+
+#define SN_organizationalUnitName "OU"
+#define LN_organizationalUnitName "organizationalUnitName"
+#define NID_organizationalUnitName 18
+#define OBJ_organizationalUnitName OBJ_X509,11L
+
+#define SN_title "title"
+#define LN_title "title"
+#define NID_title 106
+#define OBJ_title OBJ_X509,12L
+
+#define LN_description "description"
+#define NID_description 107
+#define OBJ_description OBJ_X509,13L
+
+#define LN_searchGuide "searchGuide"
+#define NID_searchGuide 859
+#define OBJ_searchGuide OBJ_X509,14L
+
+#define LN_businessCategory "businessCategory"
+#define NID_businessCategory 860
+#define OBJ_businessCategory OBJ_X509,15L
+
+#define LN_postalAddress "postalAddress"
+#define NID_postalAddress 861
+#define OBJ_postalAddress OBJ_X509,16L
+
+#define LN_postalCode "postalCode"
+#define NID_postalCode 661
+#define OBJ_postalCode OBJ_X509,17L
+
+#define LN_postOfficeBox "postOfficeBox"
+#define NID_postOfficeBox 862
+#define OBJ_postOfficeBox OBJ_X509,18L
+
+#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName"
+#define NID_physicalDeliveryOfficeName 863
+#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L
+
+#define LN_telephoneNumber "telephoneNumber"
+#define NID_telephoneNumber 864
+#define OBJ_telephoneNumber OBJ_X509,20L
+
+#define LN_telexNumber "telexNumber"
+#define NID_telexNumber 865
+#define OBJ_telexNumber OBJ_X509,21L
+
+#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier"
+#define NID_teletexTerminalIdentifier 866
+#define OBJ_teletexTerminalIdentifier OBJ_X509,22L
+
+#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber"
+#define NID_facsimileTelephoneNumber 867
+#define OBJ_facsimileTelephoneNumber OBJ_X509,23L
+
+#define LN_x121Address "x121Address"
+#define NID_x121Address 868
+#define OBJ_x121Address OBJ_X509,24L
+
+#define LN_internationaliSDNNumber "internationaliSDNNumber"
+#define NID_internationaliSDNNumber 869
+#define OBJ_internationaliSDNNumber OBJ_X509,25L
+
+#define LN_registeredAddress "registeredAddress"
+#define NID_registeredAddress 870
+#define OBJ_registeredAddress OBJ_X509,26L
+
+#define LN_destinationIndicator "destinationIndicator"
+#define NID_destinationIndicator 871
+#define OBJ_destinationIndicator OBJ_X509,27L
+
+#define LN_preferredDeliveryMethod "preferredDeliveryMethod"
+#define NID_preferredDeliveryMethod 872
+#define OBJ_preferredDeliveryMethod OBJ_X509,28L
+
+#define LN_presentationAddress "presentationAddress"
+#define NID_presentationAddress 873
+#define OBJ_presentationAddress OBJ_X509,29L
+
+#define LN_supportedApplicationContext "supportedApplicationContext"
+#define NID_supportedApplicationContext 874
+#define OBJ_supportedApplicationContext OBJ_X509,30L
+
+#define SN_member "member"
+#define NID_member 875
+#define OBJ_member OBJ_X509,31L
+
+#define SN_owner "owner"
+#define NID_owner 876
+#define OBJ_owner OBJ_X509,32L
+
+#define LN_roleOccupant "roleOccupant"
+#define NID_roleOccupant 877
+#define OBJ_roleOccupant OBJ_X509,33L
+
+#define SN_seeAlso "seeAlso"
+#define NID_seeAlso 878
+#define OBJ_seeAlso OBJ_X509,34L
+
+#define LN_userPassword "userPassword"
+#define NID_userPassword 879
+#define OBJ_userPassword OBJ_X509,35L
+
+#define LN_userCertificate "userCertificate"
+#define NID_userCertificate 880
+#define OBJ_userCertificate OBJ_X509,36L
+
+#define LN_cACertificate "cACertificate"
+#define NID_cACertificate 881
+#define OBJ_cACertificate OBJ_X509,37L
+
+#define LN_authorityRevocationList "authorityRevocationList"
+#define NID_authorityRevocationList 882
+#define OBJ_authorityRevocationList OBJ_X509,38L
+
+#define LN_certificateRevocationList "certificateRevocationList"
+#define NID_certificateRevocationList 883
+#define OBJ_certificateRevocationList OBJ_X509,39L
+
+#define LN_crossCertificatePair "crossCertificatePair"
+#define NID_crossCertificatePair 884
+#define OBJ_crossCertificatePair OBJ_X509,40L
+
+#define SN_name "name"
+#define LN_name "name"
+#define NID_name 173
+#define OBJ_name OBJ_X509,41L
+
+#define SN_givenName "GN"
+#define LN_givenName "givenName"
+#define NID_givenName 99
+#define OBJ_givenName OBJ_X509,42L
+
+#define SN_initials "initials"
+#define LN_initials "initials"
+#define NID_initials 101
+#define OBJ_initials OBJ_X509,43L
+
+#define LN_generationQualifier "generationQualifier"
+#define NID_generationQualifier 509
+#define OBJ_generationQualifier OBJ_X509,44L
+
+#define LN_x500UniqueIdentifier "x500UniqueIdentifier"
+#define NID_x500UniqueIdentifier 503
+#define OBJ_x500UniqueIdentifier OBJ_X509,45L
+
+#define SN_dnQualifier "dnQualifier"
+#define LN_dnQualifier "dnQualifier"
+#define NID_dnQualifier 174
+#define OBJ_dnQualifier OBJ_X509,46L
+
+#define LN_enhancedSearchGuide "enhancedSearchGuide"
+#define NID_enhancedSearchGuide 885
+#define OBJ_enhancedSearchGuide OBJ_X509,47L
+
+#define LN_protocolInformation "protocolInformation"
+#define NID_protocolInformation 886
+#define OBJ_protocolInformation OBJ_X509,48L
+
+#define LN_distinguishedName "distinguishedName"
+#define NID_distinguishedName 887
+#define OBJ_distinguishedName OBJ_X509,49L
+
+#define LN_uniqueMember "uniqueMember"
+#define NID_uniqueMember 888
+#define OBJ_uniqueMember OBJ_X509,50L
+
+#define LN_houseIdentifier "houseIdentifier"
+#define NID_houseIdentifier 889
+#define OBJ_houseIdentifier OBJ_X509,51L
+
+#define LN_supportedAlgorithms "supportedAlgorithms"
+#define NID_supportedAlgorithms 890
+#define OBJ_supportedAlgorithms OBJ_X509,52L
+
+#define LN_deltaRevocationList "deltaRevocationList"
+#define NID_deltaRevocationList 891
+#define OBJ_deltaRevocationList OBJ_X509,53L
+
+#define SN_dmdName "dmdName"
+#define NID_dmdName 892
+#define OBJ_dmdName OBJ_X509,54L
+
+#define LN_pseudonym "pseudonym"
+#define NID_pseudonym 510
+#define OBJ_pseudonym OBJ_X509,65L
+
+#define SN_role "role"
+#define LN_role "role"
+#define NID_role 400
+#define OBJ_role OBJ_X509,72L
+
+#define SN_X500algorithms "X500algorithms"
+#define LN_X500algorithms "directory services - algorithms"
+#define NID_X500algorithms 378
+#define OBJ_X500algorithms OBJ_X500,8L
+
+#define SN_rsa "RSA"
+#define LN_rsa "rsa"
+#define NID_rsa 19
+#define OBJ_rsa OBJ_X500algorithms,1L,1L
+
+#define SN_mdc2WithRSA "RSA-MDC2"
+#define LN_mdc2WithRSA "mdc2WithRSA"
+#define NID_mdc2WithRSA 96
+#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L
+
+#define SN_mdc2 "MDC2"
+#define LN_mdc2 "mdc2"
+#define NID_mdc2 95
+#define OBJ_mdc2 OBJ_X500algorithms,3L,101L
+
+#define SN_id_ce "id-ce"
+#define NID_id_ce 81
+#define OBJ_id_ce OBJ_X500,29L
+
+#define SN_subject_directory_attributes "subjectDirectoryAttributes"
+#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes"
+#define NID_subject_directory_attributes 769
+#define OBJ_subject_directory_attributes OBJ_id_ce,9L
+
+#define SN_subject_key_identifier "subjectKeyIdentifier"
+#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier 82
+#define OBJ_subject_key_identifier OBJ_id_ce,14L
+
+#define SN_key_usage "keyUsage"
+#define LN_key_usage "X509v3 Key Usage"
+#define NID_key_usage 83
+#define OBJ_key_usage OBJ_id_ce,15L
+
+#define SN_private_key_usage_period "privateKeyUsagePeriod"
+#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period 84
+#define OBJ_private_key_usage_period OBJ_id_ce,16L
+
+#define SN_subject_alt_name "subjectAltName"
+#define LN_subject_alt_name "X509v3 Subject Alternative Name"
+#define NID_subject_alt_name 85
+#define OBJ_subject_alt_name OBJ_id_ce,17L
+
+#define SN_issuer_alt_name "issuerAltName"
+#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name 86
+#define OBJ_issuer_alt_name OBJ_id_ce,18L
+
+#define SN_basic_constraints "basicConstraints"
+#define LN_basic_constraints "X509v3 Basic Constraints"
+#define NID_basic_constraints 87
+#define OBJ_basic_constraints OBJ_id_ce,19L
+
+#define SN_crl_number "crlNumber"
+#define LN_crl_number "X509v3 CRL Number"
+#define NID_crl_number 88
+#define OBJ_crl_number OBJ_id_ce,20L
+
+#define SN_crl_reason "CRLReason"
+#define LN_crl_reason "X509v3 CRL Reason Code"
+#define NID_crl_reason 141
+#define OBJ_crl_reason OBJ_id_ce,21L
+
+#define SN_invalidity_date "invalidityDate"
+#define LN_invalidity_date "Invalidity Date"
+#define NID_invalidity_date 142
+#define OBJ_invalidity_date OBJ_id_ce,24L
+
+#define SN_delta_crl "deltaCRL"
+#define LN_delta_crl "X509v3 Delta CRL Indicator"
+#define NID_delta_crl 140
+#define OBJ_delta_crl OBJ_id_ce,27L
+
+#define SN_issuing_distribution_point "issuingDistributionPoint"
+#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point"
+#define NID_issuing_distribution_point 770
+#define OBJ_issuing_distribution_point OBJ_id_ce,28L
+
+#define SN_certificate_issuer "certificateIssuer"
+#define LN_certificate_issuer "X509v3 Certificate Issuer"
+#define NID_certificate_issuer 771
+#define OBJ_certificate_issuer OBJ_id_ce,29L
+
+#define SN_name_constraints "nameConstraints"
+#define LN_name_constraints "X509v3 Name Constraints"
+#define NID_name_constraints 666
+#define OBJ_name_constraints OBJ_id_ce,30L
+
+#define SN_crl_distribution_points "crlDistributionPoints"
+#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points 103
+#define OBJ_crl_distribution_points OBJ_id_ce,31L
+
+#define SN_certificate_policies "certificatePolicies"
+#define LN_certificate_policies "X509v3 Certificate Policies"
+#define NID_certificate_policies 89
+#define OBJ_certificate_policies OBJ_id_ce,32L
+
+#define SN_any_policy "anyPolicy"
+#define LN_any_policy "X509v3 Any Policy"
+#define NID_any_policy 746
+#define OBJ_any_policy OBJ_certificate_policies,0L
+
+#define SN_policy_mappings "policyMappings"
+#define LN_policy_mappings "X509v3 Policy Mappings"
+#define NID_policy_mappings 747
+#define OBJ_policy_mappings OBJ_id_ce,33L
+
+#define SN_authority_key_identifier "authorityKeyIdentifier"
+#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier 90
+#define OBJ_authority_key_identifier OBJ_id_ce,35L
+
+#define SN_policy_constraints "policyConstraints"
+#define LN_policy_constraints "X509v3 Policy Constraints"
+#define NID_policy_constraints 401
+#define OBJ_policy_constraints OBJ_id_ce,36L
+
+#define SN_ext_key_usage "extendedKeyUsage"
+#define LN_ext_key_usage "X509v3 Extended Key Usage"
+#define NID_ext_key_usage 126
+#define OBJ_ext_key_usage OBJ_id_ce,37L
+
+#define SN_freshest_crl "freshestCRL"
+#define LN_freshest_crl "X509v3 Freshest CRL"
+#define NID_freshest_crl 857
+#define OBJ_freshest_crl OBJ_id_ce,46L
+
+#define SN_inhibit_any_policy "inhibitAnyPolicy"
+#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy"
+#define NID_inhibit_any_policy 748
+#define OBJ_inhibit_any_policy OBJ_id_ce,54L
+
+#define SN_target_information "targetInformation"
+#define LN_target_information "X509v3 AC Targeting"
+#define NID_target_information 402
+#define OBJ_target_information OBJ_id_ce,55L
+
+#define SN_no_rev_avail "noRevAvail"
+#define LN_no_rev_avail "X509v3 No Revocation Available"
+#define NID_no_rev_avail 403
+#define OBJ_no_rev_avail OBJ_id_ce,56L
+
+#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage"
+#define LN_anyExtendedKeyUsage "Any Extended Key Usage"
+#define NID_anyExtendedKeyUsage 910
+#define OBJ_anyExtendedKeyUsage OBJ_ext_key_usage,0L
+
+#define SN_netscape "Netscape"
+#define LN_netscape "Netscape Communications Corp."
+#define NID_netscape 57
+#define OBJ_netscape 2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension "nsCertExt"
+#define LN_netscape_cert_extension "Netscape Certificate Extension"
+#define NID_netscape_cert_extension 58
+#define OBJ_netscape_cert_extension OBJ_netscape,1L
+
+#define SN_netscape_data_type "nsDataType"
+#define LN_netscape_data_type "Netscape Data Type"
+#define NID_netscape_data_type 59
+#define OBJ_netscape_data_type OBJ_netscape,2L
+
+#define SN_netscape_cert_type "nsCertType"
+#define LN_netscape_cert_type "Netscape Cert Type"
+#define NID_netscape_cert_type 71
+#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url "nsBaseUrl"
+#define LN_netscape_base_url "Netscape Base Url"
+#define NID_netscape_base_url 72
+#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url "nsRevocationUrl"
+#define LN_netscape_revocation_url "Netscape Revocation Url"
+#define NID_netscape_revocation_url 73
+#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url 74
+#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url "nsRenewalUrl"
+#define LN_netscape_renewal_url "Netscape Renewal Url"
+#define NID_netscape_renewal_url 75
+#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url 76
+#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name "nsSslServerName"
+#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name 77
+#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment "nsComment"
+#define LN_netscape_comment "Netscape Comment"
+#define NID_netscape_comment 78
+#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence "nsCertSequence"
+#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence 79
+#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L
+
+#define SN_ns_sgc "nsSGC"
+#define LN_ns_sgc "Netscape Server Gated Crypto"
+#define NID_ns_sgc 139
+#define OBJ_ns_sgc OBJ_netscape,4L,1L
+
+#define SN_org "ORG"
+#define LN_org "org"
+#define NID_org 379
+#define OBJ_org OBJ_iso,3L
+
+#define SN_dod "DOD"
+#define LN_dod "dod"
+#define NID_dod 380
+#define OBJ_dod OBJ_org,6L
+
+#define SN_iana "IANA"
+#define LN_iana "iana"
+#define NID_iana 381
+#define OBJ_iana OBJ_dod,1L
+
+#define OBJ_internet OBJ_iana
+
+#define SN_Directory "directory"
+#define LN_Directory "Directory"
+#define NID_Directory 382
+#define OBJ_Directory OBJ_internet,1L
+
+#define SN_Management "mgmt"
+#define LN_Management "Management"
+#define NID_Management 383
+#define OBJ_Management OBJ_internet,2L
+
+#define SN_Experimental "experimental"
+#define LN_Experimental "Experimental"
+#define NID_Experimental 384
+#define OBJ_Experimental OBJ_internet,3L
+
+#define SN_Private "private"
+#define LN_Private "Private"
+#define NID_Private 385
+#define OBJ_Private OBJ_internet,4L
+
+#define SN_Security "security"
+#define LN_Security "Security"
+#define NID_Security 386
+#define OBJ_Security OBJ_internet,5L
+
+#define SN_SNMPv2 "snmpv2"
+#define LN_SNMPv2 "SNMPv2"
+#define NID_SNMPv2 387
+#define OBJ_SNMPv2 OBJ_internet,6L
+
+#define LN_Mail "Mail"
+#define NID_Mail 388
+#define OBJ_Mail OBJ_internet,7L
+
+#define SN_Enterprises "enterprises"
+#define LN_Enterprises "Enterprises"
+#define NID_Enterprises 389
+#define OBJ_Enterprises OBJ_Private,1L
+
+#define SN_dcObject "dcobject"
+#define LN_dcObject "dcObject"
+#define NID_dcObject 390
+#define OBJ_dcObject OBJ_Enterprises,1466L,344L
+
+#define SN_mime_mhs "mime-mhs"
+#define LN_mime_mhs "MIME MHS"
+#define NID_mime_mhs 504
+#define OBJ_mime_mhs OBJ_Mail,1L
+
+#define SN_mime_mhs_headings "mime-mhs-headings"
+#define LN_mime_mhs_headings "mime-mhs-headings"
+#define NID_mime_mhs_headings 505
+#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L
+
+#define SN_mime_mhs_bodies "mime-mhs-bodies"
+#define LN_mime_mhs_bodies "mime-mhs-bodies"
+#define NID_mime_mhs_bodies 506
+#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L
+
+#define SN_id_hex_partial_message "id-hex-partial-message"
+#define LN_id_hex_partial_message "id-hex-partial-message"
+#define NID_id_hex_partial_message 507
+#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L
+
+#define SN_id_hex_multipart_message "id-hex-multipart-message"
+#define LN_id_hex_multipart_message "id-hex-multipart-message"
+#define NID_id_hex_multipart_message 508
+#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L
+
+#define SN_zlib_compression "ZLIB"
+#define LN_zlib_compression "zlib compression"
+#define NID_zlib_compression 125
+#define OBJ_zlib_compression OBJ_id_smime_alg,8L
+
+#define OBJ_csor 2L,16L,840L,1L,101L,3L
+
+#define OBJ_nistAlgorithms OBJ_csor,4L
+
+#define OBJ_aes OBJ_nistAlgorithms,1L
+
+#define SN_aes_128_ecb "AES-128-ECB"
+#define LN_aes_128_ecb "aes-128-ecb"
+#define NID_aes_128_ecb 418
+#define OBJ_aes_128_ecb OBJ_aes,1L
+
+#define SN_aes_128_cbc "AES-128-CBC"
+#define LN_aes_128_cbc "aes-128-cbc"
+#define NID_aes_128_cbc 419
+#define OBJ_aes_128_cbc OBJ_aes,2L
+
+#define SN_aes_128_ofb128 "AES-128-OFB"
+#define LN_aes_128_ofb128 "aes-128-ofb"
+#define NID_aes_128_ofb128 420
+#define OBJ_aes_128_ofb128 OBJ_aes,3L
+
+#define SN_aes_128_cfb128 "AES-128-CFB"
+#define LN_aes_128_cfb128 "aes-128-cfb"
+#define NID_aes_128_cfb128 421
+#define OBJ_aes_128_cfb128 OBJ_aes,4L
+
+#define SN_id_aes128_wrap "id-aes128-wrap"
+#define NID_id_aes128_wrap 788
+#define OBJ_id_aes128_wrap OBJ_aes,5L
+
+#define SN_aes_128_gcm "id-aes128-GCM"
+#define LN_aes_128_gcm "aes-128-gcm"
+#define NID_aes_128_gcm 895
+#define OBJ_aes_128_gcm OBJ_aes,6L
+
+#define SN_aes_128_ccm "id-aes128-CCM"
+#define LN_aes_128_ccm "aes-128-ccm"
+#define NID_aes_128_ccm 896
+#define OBJ_aes_128_ccm OBJ_aes,7L
+
+#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad"
+#define NID_id_aes128_wrap_pad 897
+#define OBJ_id_aes128_wrap_pad OBJ_aes,8L
+
+#define SN_aes_192_ecb "AES-192-ECB"
+#define LN_aes_192_ecb "aes-192-ecb"
+#define NID_aes_192_ecb 422
+#define OBJ_aes_192_ecb OBJ_aes,21L
+
+#define SN_aes_192_cbc "AES-192-CBC"
+#define LN_aes_192_cbc "aes-192-cbc"
+#define NID_aes_192_cbc 423
+#define OBJ_aes_192_cbc OBJ_aes,22L
+
+#define SN_aes_192_ofb128 "AES-192-OFB"
+#define LN_aes_192_ofb128 "aes-192-ofb"
+#define NID_aes_192_ofb128 424
+#define OBJ_aes_192_ofb128 OBJ_aes,23L
+
+#define SN_aes_192_cfb128 "AES-192-CFB"
+#define LN_aes_192_cfb128 "aes-192-cfb"
+#define NID_aes_192_cfb128 425
+#define OBJ_aes_192_cfb128 OBJ_aes,24L
+
+#define SN_id_aes192_wrap "id-aes192-wrap"
+#define NID_id_aes192_wrap 789
+#define OBJ_id_aes192_wrap OBJ_aes,25L
+
+#define SN_aes_192_gcm "id-aes192-GCM"
+#define LN_aes_192_gcm "aes-192-gcm"
+#define NID_aes_192_gcm 898
+#define OBJ_aes_192_gcm OBJ_aes,26L
+
+#define SN_aes_192_ccm "id-aes192-CCM"
+#define LN_aes_192_ccm "aes-192-ccm"
+#define NID_aes_192_ccm 899
+#define OBJ_aes_192_ccm OBJ_aes,27L
+
+#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad"
+#define NID_id_aes192_wrap_pad 900
+#define OBJ_id_aes192_wrap_pad OBJ_aes,28L
+
+#define SN_aes_256_ecb "AES-256-ECB"
+#define LN_aes_256_ecb "aes-256-ecb"
+#define NID_aes_256_ecb 426
+#define OBJ_aes_256_ecb OBJ_aes,41L
+
+#define SN_aes_256_cbc "AES-256-CBC"
+#define LN_aes_256_cbc "aes-256-cbc"
+#define NID_aes_256_cbc 427
+#define OBJ_aes_256_cbc OBJ_aes,42L
+
+#define SN_aes_256_ofb128 "AES-256-OFB"
+#define LN_aes_256_ofb128 "aes-256-ofb"
+#define NID_aes_256_ofb128 428
+#define OBJ_aes_256_ofb128 OBJ_aes,43L
+
+#define SN_aes_256_cfb128 "AES-256-CFB"
+#define LN_aes_256_cfb128 "aes-256-cfb"
+#define NID_aes_256_cfb128 429
+#define OBJ_aes_256_cfb128 OBJ_aes,44L
+
+#define SN_id_aes256_wrap "id-aes256-wrap"
+#define NID_id_aes256_wrap 790
+#define OBJ_id_aes256_wrap OBJ_aes,45L
+
+#define SN_aes_256_gcm "id-aes256-GCM"
+#define LN_aes_256_gcm "aes-256-gcm"
+#define NID_aes_256_gcm 901
+#define OBJ_aes_256_gcm OBJ_aes,46L
+
+#define SN_aes_256_ccm "id-aes256-CCM"
+#define LN_aes_256_ccm "aes-256-ccm"
+#define NID_aes_256_ccm 902
+#define OBJ_aes_256_ccm OBJ_aes,47L
+
+#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad"
+#define NID_id_aes256_wrap_pad 903
+#define OBJ_id_aes256_wrap_pad OBJ_aes,48L
+
+#define SN_aes_128_cfb1 "AES-128-CFB1"
+#define LN_aes_128_cfb1 "aes-128-cfb1"
+#define NID_aes_128_cfb1 650
+
+#define SN_aes_192_cfb1 "AES-192-CFB1"
+#define LN_aes_192_cfb1 "aes-192-cfb1"
+#define NID_aes_192_cfb1 651
+
+#define SN_aes_256_cfb1 "AES-256-CFB1"
+#define LN_aes_256_cfb1 "aes-256-cfb1"
+#define NID_aes_256_cfb1 652
+
+#define SN_aes_128_cfb8 "AES-128-CFB8"
+#define LN_aes_128_cfb8 "aes-128-cfb8"
+#define NID_aes_128_cfb8 653
+
+#define SN_aes_192_cfb8 "AES-192-CFB8"
+#define LN_aes_192_cfb8 "aes-192-cfb8"
+#define NID_aes_192_cfb8 654
+
+#define SN_aes_256_cfb8 "AES-256-CFB8"
+#define LN_aes_256_cfb8 "aes-256-cfb8"
+#define NID_aes_256_cfb8 655
+
+#define SN_aes_128_ctr "AES-128-CTR"
+#define LN_aes_128_ctr "aes-128-ctr"
+#define NID_aes_128_ctr 904
+
+#define SN_aes_192_ctr "AES-192-CTR"
+#define LN_aes_192_ctr "aes-192-ctr"
+#define NID_aes_192_ctr 905
+
+#define SN_aes_256_ctr "AES-256-CTR"
+#define LN_aes_256_ctr "aes-256-ctr"
+#define NID_aes_256_ctr 906
+
+#define SN_aes_128_xts "AES-128-XTS"
+#define LN_aes_128_xts "aes-128-xts"
+#define NID_aes_128_xts 913
+
+#define SN_aes_256_xts "AES-256-XTS"
+#define LN_aes_256_xts "aes-256-xts"
+#define NID_aes_256_xts 914
+
+#define SN_des_cfb1 "DES-CFB1"
+#define LN_des_cfb1 "des-cfb1"
+#define NID_des_cfb1 656
+
+#define SN_des_cfb8 "DES-CFB8"
+#define LN_des_cfb8 "des-cfb8"
+#define NID_des_cfb8 657
+
+#define SN_des_ede3_cfb1 "DES-EDE3-CFB1"
+#define LN_des_ede3_cfb1 "des-ede3-cfb1"
+#define NID_des_ede3_cfb1 658
+
+#define SN_des_ede3_cfb8 "DES-EDE3-CFB8"
+#define LN_des_ede3_cfb8 "des-ede3-cfb8"
+#define NID_des_ede3_cfb8 659
+
+#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L
+
+#define SN_sha256 "SHA256"
+#define LN_sha256 "sha256"
+#define NID_sha256 672
+#define OBJ_sha256 OBJ_nist_hashalgs,1L
+
+#define SN_sha384 "SHA384"
+#define LN_sha384 "sha384"
+#define NID_sha384 673
+#define OBJ_sha384 OBJ_nist_hashalgs,2L
+
+#define SN_sha512 "SHA512"
+#define LN_sha512 "sha512"
+#define NID_sha512 674
+#define OBJ_sha512 OBJ_nist_hashalgs,3L
+
+#define SN_sha224 "SHA224"
+#define LN_sha224 "sha224"
+#define NID_sha224 675
+#define OBJ_sha224 OBJ_nist_hashalgs,4L
+
+#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L
+
+#define SN_dsa_with_SHA224 "dsa_with_SHA224"
+#define NID_dsa_with_SHA224 802
+#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L
+
+#define SN_dsa_with_SHA256 "dsa_with_SHA256"
+#define NID_dsa_with_SHA256 803
+#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L
+
+#define SN_hold_instruction_code "holdInstructionCode"
+#define LN_hold_instruction_code "Hold Instruction Code"
+#define NID_hold_instruction_code 430
+#define OBJ_hold_instruction_code OBJ_id_ce,23L
+
+#define OBJ_holdInstruction OBJ_X9_57,2L
+
+#define SN_hold_instruction_none "holdInstructionNone"
+#define LN_hold_instruction_none "Hold Instruction None"
+#define NID_hold_instruction_none 431
+#define OBJ_hold_instruction_none OBJ_holdInstruction,1L
+
+#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer"
+#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer"
+#define NID_hold_instruction_call_issuer 432
+#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L
+
+#define SN_hold_instruction_reject "holdInstructionReject"
+#define LN_hold_instruction_reject "Hold Instruction Reject"
+#define NID_hold_instruction_reject 433
+#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L
+
+#define SN_data "data"
+#define NID_data 434
+#define OBJ_data OBJ_itu_t,9L
+
+#define SN_pss "pss"
+#define NID_pss 435
+#define OBJ_pss OBJ_data,2342L
+
+#define SN_ucl "ucl"
+#define NID_ucl 436
+#define OBJ_ucl OBJ_pss,19200300L
+
+#define SN_pilot "pilot"
+#define NID_pilot 437
+#define OBJ_pilot OBJ_ucl,100L
+
+#define LN_pilotAttributeType "pilotAttributeType"
+#define NID_pilotAttributeType 438
+#define OBJ_pilotAttributeType OBJ_pilot,1L
+
+#define LN_pilotAttributeSyntax "pilotAttributeSyntax"
+#define NID_pilotAttributeSyntax 439
+#define OBJ_pilotAttributeSyntax OBJ_pilot,3L
+
+#define LN_pilotObjectClass "pilotObjectClass"
+#define NID_pilotObjectClass 440
+#define OBJ_pilotObjectClass OBJ_pilot,4L
+
+#define LN_pilotGroups "pilotGroups"
+#define NID_pilotGroups 441
+#define OBJ_pilotGroups OBJ_pilot,10L
+
+#define LN_iA5StringSyntax "iA5StringSyntax"
+#define NID_iA5StringSyntax 442
+#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L
+
+#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax"
+#define NID_caseIgnoreIA5StringSyntax 443
+#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L
+
+#define LN_pilotObject "pilotObject"
+#define NID_pilotObject 444
+#define OBJ_pilotObject OBJ_pilotObjectClass,3L
+
+#define LN_pilotPerson "pilotPerson"
+#define NID_pilotPerson 445
+#define OBJ_pilotPerson OBJ_pilotObjectClass,4L
+
+#define SN_account "account"
+#define NID_account 446
+#define OBJ_account OBJ_pilotObjectClass,5L
+
+#define SN_document "document"
+#define NID_document 447
+#define OBJ_document OBJ_pilotObjectClass,6L
+
+#define SN_room "room"
+#define NID_room 448
+#define OBJ_room OBJ_pilotObjectClass,7L
+
+#define LN_documentSeries "documentSeries"
+#define NID_documentSeries 449
+#define OBJ_documentSeries OBJ_pilotObjectClass,9L
+
+#define SN_Domain "domain"
+#define LN_Domain "Domain"
+#define NID_Domain 392
+#define OBJ_Domain OBJ_pilotObjectClass,13L
+
+#define LN_rFC822localPart "rFC822localPart"
+#define NID_rFC822localPart 450
+#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L
+
+#define LN_dNSDomain "dNSDomain"
+#define NID_dNSDomain 451
+#define OBJ_dNSDomain OBJ_pilotObjectClass,15L
+
+#define LN_domainRelatedObject "domainRelatedObject"
+#define NID_domainRelatedObject 452
+#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L
+
+#define LN_friendlyCountry "friendlyCountry"
+#define NID_friendlyCountry 453
+#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L
+
+#define LN_simpleSecurityObject "simpleSecurityObject"
+#define NID_simpleSecurityObject 454
+#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L
+
+#define LN_pilotOrganization "pilotOrganization"
+#define NID_pilotOrganization 455
+#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L
+
+#define LN_pilotDSA "pilotDSA"
+#define NID_pilotDSA 456
+#define OBJ_pilotDSA OBJ_pilotObjectClass,21L
+
+#define LN_qualityLabelledData "qualityLabelledData"
+#define NID_qualityLabelledData 457
+#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L
+
+#define SN_userId "UID"
+#define LN_userId "userId"
+#define NID_userId 458
+#define OBJ_userId OBJ_pilotAttributeType,1L
+
+#define LN_textEncodedORAddress "textEncodedORAddress"
+#define NID_textEncodedORAddress 459
+#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L
+
+#define SN_rfc822Mailbox "mail"
+#define LN_rfc822Mailbox "rfc822Mailbox"
+#define NID_rfc822Mailbox 460
+#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L
+
+#define SN_info "info"
+#define NID_info 461
+#define OBJ_info OBJ_pilotAttributeType,4L
+
+#define LN_favouriteDrink "favouriteDrink"
+#define NID_favouriteDrink 462
+#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L
+
+#define LN_roomNumber "roomNumber"
+#define NID_roomNumber 463
+#define OBJ_roomNumber OBJ_pilotAttributeType,6L
+
+#define SN_photo "photo"
+#define NID_photo 464
+#define OBJ_photo OBJ_pilotAttributeType,7L
+
+#define LN_userClass "userClass"
+#define NID_userClass 465
+#define OBJ_userClass OBJ_pilotAttributeType,8L
+
+#define SN_host "host"
+#define NID_host 466
+#define OBJ_host OBJ_pilotAttributeType,9L
+
+#define SN_manager "manager"
+#define NID_manager 467
+#define OBJ_manager OBJ_pilotAttributeType,10L
+
+#define LN_documentIdentifier "documentIdentifier"
+#define NID_documentIdentifier 468
+#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L
+
+#define LN_documentTitle "documentTitle"
+#define NID_documentTitle 469
+#define OBJ_documentTitle OBJ_pilotAttributeType,12L
+
+#define LN_documentVersion "documentVersion"
+#define NID_documentVersion 470
+#define OBJ_documentVersion OBJ_pilotAttributeType,13L
+
+#define LN_documentAuthor "documentAuthor"
+#define NID_documentAuthor 471
+#define OBJ_documentAuthor OBJ_pilotAttributeType,14L
+
+#define LN_documentLocation "documentLocation"
+#define NID_documentLocation 472
+#define OBJ_documentLocation OBJ_pilotAttributeType,15L
+
+#define LN_homeTelephoneNumber "homeTelephoneNumber"
+#define NID_homeTelephoneNumber 473
+#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L
+
+#define SN_secretary "secretary"
+#define NID_secretary 474
+#define OBJ_secretary OBJ_pilotAttributeType,21L
+
+#define LN_otherMailbox "otherMailbox"
+#define NID_otherMailbox 475
+#define OBJ_otherMailbox OBJ_pilotAttributeType,22L
+
+#define LN_lastModifiedTime "lastModifiedTime"
+#define NID_lastModifiedTime 476
+#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L
+
+#define LN_lastModifiedBy "lastModifiedBy"
+#define NID_lastModifiedBy 477
+#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L
+
+#define SN_domainComponent "DC"
+#define LN_domainComponent "domainComponent"
+#define NID_domainComponent 391
+#define OBJ_domainComponent OBJ_pilotAttributeType,25L
+
+#define LN_aRecord "aRecord"
+#define NID_aRecord 478
+#define OBJ_aRecord OBJ_pilotAttributeType,26L
+
+#define LN_pilotAttributeType27 "pilotAttributeType27"
+#define NID_pilotAttributeType27 479
+#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L
+
+#define LN_mXRecord "mXRecord"
+#define NID_mXRecord 480
+#define OBJ_mXRecord OBJ_pilotAttributeType,28L
+
+#define LN_nSRecord "nSRecord"
+#define NID_nSRecord 481
+#define OBJ_nSRecord OBJ_pilotAttributeType,29L
+
+#define LN_sOARecord "sOARecord"
+#define NID_sOARecord 482
+#define OBJ_sOARecord OBJ_pilotAttributeType,30L
+
+#define LN_cNAMERecord "cNAMERecord"
+#define NID_cNAMERecord 483
+#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L
+
+#define LN_associatedDomain "associatedDomain"
+#define NID_associatedDomain 484
+#define OBJ_associatedDomain OBJ_pilotAttributeType,37L
+
+#define LN_associatedName "associatedName"
+#define NID_associatedName 485
+#define OBJ_associatedName OBJ_pilotAttributeType,38L
+
+#define LN_homePostalAddress "homePostalAddress"
+#define NID_homePostalAddress 486
+#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L
+
+#define LN_personalTitle "personalTitle"
+#define NID_personalTitle 487
+#define OBJ_personalTitle OBJ_pilotAttributeType,40L
+
+#define LN_mobileTelephoneNumber "mobileTelephoneNumber"
+#define NID_mobileTelephoneNumber 488
+#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L
+
+#define LN_pagerTelephoneNumber "pagerTelephoneNumber"
+#define NID_pagerTelephoneNumber 489
+#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L
+
+#define LN_friendlyCountryName "friendlyCountryName"
+#define NID_friendlyCountryName 490
+#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L
+
+#define LN_organizationalStatus "organizationalStatus"
+#define NID_organizationalStatus 491
+#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L
+
+#define LN_janetMailbox "janetMailbox"
+#define NID_janetMailbox 492
+#define OBJ_janetMailbox OBJ_pilotAttributeType,46L
+
+#define LN_mailPreferenceOption "mailPreferenceOption"
+#define NID_mailPreferenceOption 493
+#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L
+
+#define LN_buildingName "buildingName"
+#define NID_buildingName 494
+#define OBJ_buildingName OBJ_pilotAttributeType,48L
+
+#define LN_dSAQuality "dSAQuality"
+#define NID_dSAQuality 495
+#define OBJ_dSAQuality OBJ_pilotAttributeType,49L
+
+#define LN_singleLevelQuality "singleLevelQuality"
+#define NID_singleLevelQuality 496
+#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L
+
+#define LN_subtreeMinimumQuality "subtreeMinimumQuality"
+#define NID_subtreeMinimumQuality 497
+#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L
+
+#define LN_subtreeMaximumQuality "subtreeMaximumQuality"
+#define NID_subtreeMaximumQuality 498
+#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L
+
+#define LN_personalSignature "personalSignature"
+#define NID_personalSignature 499
+#define OBJ_personalSignature OBJ_pilotAttributeType,53L
+
+#define LN_dITRedirect "dITRedirect"
+#define NID_dITRedirect 500
+#define OBJ_dITRedirect OBJ_pilotAttributeType,54L
+
+#define SN_audio "audio"
+#define NID_audio 501
+#define OBJ_audio OBJ_pilotAttributeType,55L
+
+#define LN_documentPublisher "documentPublisher"
+#define NID_documentPublisher 502
+#define OBJ_documentPublisher OBJ_pilotAttributeType,56L
+
+#define SN_id_set "id-set"
+#define LN_id_set "Secure Electronic Transactions"
+#define NID_id_set 512
+#define OBJ_id_set OBJ_international_organizations,42L
+
+#define SN_set_ctype "set-ctype"
+#define LN_set_ctype "content types"
+#define NID_set_ctype 513
+#define OBJ_set_ctype OBJ_id_set,0L
+
+#define SN_set_msgExt "set-msgExt"
+#define LN_set_msgExt "message extensions"
+#define NID_set_msgExt 514
+#define OBJ_set_msgExt OBJ_id_set,1L
+
+#define SN_set_attr "set-attr"
+#define NID_set_attr 515
+#define OBJ_set_attr OBJ_id_set,3L
+
+#define SN_set_policy "set-policy"
+#define NID_set_policy 516
+#define OBJ_set_policy OBJ_id_set,5L
+
+#define SN_set_certExt "set-certExt"
+#define LN_set_certExt "certificate extensions"
+#define NID_set_certExt 517
+#define OBJ_set_certExt OBJ_id_set,7L
+
+#define SN_set_brand "set-brand"
+#define NID_set_brand 518
+#define OBJ_set_brand OBJ_id_set,8L
+
+#define SN_setct_PANData "setct-PANData"
+#define NID_setct_PANData 519
+#define OBJ_setct_PANData OBJ_set_ctype,0L
+
+#define SN_setct_PANToken "setct-PANToken"
+#define NID_setct_PANToken 520
+#define OBJ_setct_PANToken OBJ_set_ctype,1L
+
+#define SN_setct_PANOnly "setct-PANOnly"
+#define NID_setct_PANOnly 521
+#define OBJ_setct_PANOnly OBJ_set_ctype,2L
+
+#define SN_setct_OIData "setct-OIData"
+#define NID_setct_OIData 522
+#define OBJ_setct_OIData OBJ_set_ctype,3L
+
+#define SN_setct_PI "setct-PI"
+#define NID_setct_PI 523
+#define OBJ_setct_PI OBJ_set_ctype,4L
+
+#define SN_setct_PIData "setct-PIData"
+#define NID_setct_PIData 524
+#define OBJ_setct_PIData OBJ_set_ctype,5L
+
+#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned"
+#define NID_setct_PIDataUnsigned 525
+#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L
+
+#define SN_setct_HODInput "setct-HODInput"
+#define NID_setct_HODInput 526
+#define OBJ_setct_HODInput OBJ_set_ctype,7L
+
+#define SN_setct_AuthResBaggage "setct-AuthResBaggage"
+#define NID_setct_AuthResBaggage 527
+#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L
+
+#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage"
+#define NID_setct_AuthRevReqBaggage 528
+#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L
+
+#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage"
+#define NID_setct_AuthRevResBaggage 529
+#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L
+
+#define SN_setct_CapTokenSeq "setct-CapTokenSeq"
+#define NID_setct_CapTokenSeq 530
+#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L
+
+#define SN_setct_PInitResData "setct-PInitResData"
+#define NID_setct_PInitResData 531
+#define OBJ_setct_PInitResData OBJ_set_ctype,12L
+
+#define SN_setct_PI_TBS "setct-PI-TBS"
+#define NID_setct_PI_TBS 532
+#define OBJ_setct_PI_TBS OBJ_set_ctype,13L
+
+#define SN_setct_PResData "setct-PResData"
+#define NID_setct_PResData 533
+#define OBJ_setct_PResData OBJ_set_ctype,14L
+
+#define SN_setct_AuthReqTBS "setct-AuthReqTBS"
+#define NID_setct_AuthReqTBS 534
+#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L
+
+#define SN_setct_AuthResTBS "setct-AuthResTBS"
+#define NID_setct_AuthResTBS 535
+#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L
+
+#define SN_setct_AuthResTBSX "setct-AuthResTBSX"
+#define NID_setct_AuthResTBSX 536
+#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L
+
+#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS"
+#define NID_setct_AuthTokenTBS 537
+#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L
+
+#define SN_setct_CapTokenData "setct-CapTokenData"
+#define NID_setct_CapTokenData 538
+#define OBJ_setct_CapTokenData OBJ_set_ctype,20L
+
+#define SN_setct_CapTokenTBS "setct-CapTokenTBS"
+#define NID_setct_CapTokenTBS 539
+#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L
+
+#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg"
+#define NID_setct_AcqCardCodeMsg 540
+#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L
+
+#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS"
+#define NID_setct_AuthRevReqTBS 541
+#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L
+
+#define SN_setct_AuthRevResData "setct-AuthRevResData"
+#define NID_setct_AuthRevResData 542
+#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L
+
+#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS"
+#define NID_setct_AuthRevResTBS 543
+#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L
+
+#define SN_setct_CapReqTBS "setct-CapReqTBS"
+#define NID_setct_CapReqTBS 544
+#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L
+
+#define SN_setct_CapReqTBSX "setct-CapReqTBSX"
+#define NID_setct_CapReqTBSX 545
+#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L
+
+#define SN_setct_CapResData "setct-CapResData"
+#define NID_setct_CapResData 546
+#define OBJ_setct_CapResData OBJ_set_ctype,28L
+
+#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS"
+#define NID_setct_CapRevReqTBS 547
+#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L
+
+#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX"
+#define NID_setct_CapRevReqTBSX 548
+#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L
+
+#define SN_setct_CapRevResData "setct-CapRevResData"
+#define NID_setct_CapRevResData 549
+#define OBJ_setct_CapRevResData OBJ_set_ctype,31L
+
+#define SN_setct_CredReqTBS "setct-CredReqTBS"
+#define NID_setct_CredReqTBS 550
+#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L
+
+#define SN_setct_CredReqTBSX "setct-CredReqTBSX"
+#define NID_setct_CredReqTBSX 551
+#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L
+
+#define SN_setct_CredResData "setct-CredResData"
+#define NID_setct_CredResData 552
+#define OBJ_setct_CredResData OBJ_set_ctype,34L
+
+#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS"
+#define NID_setct_CredRevReqTBS 553
+#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L
+
+#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX"
+#define NID_setct_CredRevReqTBSX 554
+#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L
+
+#define SN_setct_CredRevResData "setct-CredRevResData"
+#define NID_setct_CredRevResData 555
+#define OBJ_setct_CredRevResData OBJ_set_ctype,37L
+
+#define SN_setct_PCertReqData "setct-PCertReqData"
+#define NID_setct_PCertReqData 556
+#define OBJ_setct_PCertReqData OBJ_set_ctype,38L
+
+#define SN_setct_PCertResTBS "setct-PCertResTBS"
+#define NID_setct_PCertResTBS 557
+#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L
+
+#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData"
+#define NID_setct_BatchAdminReqData 558
+#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L
+
+#define SN_setct_BatchAdminResData "setct-BatchAdminResData"
+#define NID_setct_BatchAdminResData 559
+#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L
+
+#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS"
+#define NID_setct_CardCInitResTBS 560
+#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L
+
+#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS"
+#define NID_setct_MeAqCInitResTBS 561
+#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L
+
+#define SN_setct_RegFormResTBS "setct-RegFormResTBS"
+#define NID_setct_RegFormResTBS 562
+#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L
+
+#define SN_setct_CertReqData "setct-CertReqData"
+#define NID_setct_CertReqData 563
+#define OBJ_setct_CertReqData OBJ_set_ctype,45L
+
+#define SN_setct_CertReqTBS "setct-CertReqTBS"
+#define NID_setct_CertReqTBS 564
+#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L
+
+#define SN_setct_CertResData "setct-CertResData"
+#define NID_setct_CertResData 565
+#define OBJ_setct_CertResData OBJ_set_ctype,47L
+
+#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS"
+#define NID_setct_CertInqReqTBS 566
+#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L
+
+#define SN_setct_ErrorTBS "setct-ErrorTBS"
+#define NID_setct_ErrorTBS 567
+#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L
+
+#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE"
+#define NID_setct_PIDualSignedTBE 568
+#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L
+
+#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE"
+#define NID_setct_PIUnsignedTBE 569
+#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L
+
+#define SN_setct_AuthReqTBE "setct-AuthReqTBE"
+#define NID_setct_AuthReqTBE 570
+#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L
+
+#define SN_setct_AuthResTBE "setct-AuthResTBE"
+#define NID_setct_AuthResTBE 571
+#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L
+
+#define SN_setct_AuthResTBEX "setct-AuthResTBEX"
+#define NID_setct_AuthResTBEX 572
+#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L
+
+#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE"
+#define NID_setct_AuthTokenTBE 573
+#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L
+
+#define SN_setct_CapTokenTBE "setct-CapTokenTBE"
+#define NID_setct_CapTokenTBE 574
+#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L
+
+#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX"
+#define NID_setct_CapTokenTBEX 575
+#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L
+
+#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE"
+#define NID_setct_AcqCardCodeMsgTBE 576
+#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L
+
+#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE"
+#define NID_setct_AuthRevReqTBE 577
+#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L
+
+#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE"
+#define NID_setct_AuthRevResTBE 578
+#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L
+
+#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB"
+#define NID_setct_AuthRevResTBEB 579
+#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L
+
+#define SN_setct_CapReqTBE "setct-CapReqTBE"
+#define NID_setct_CapReqTBE 580
+#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L
+
+#define SN_setct_CapReqTBEX "setct-CapReqTBEX"
+#define NID_setct_CapReqTBEX 581
+#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L
+
+#define SN_setct_CapResTBE "setct-CapResTBE"
+#define NID_setct_CapResTBE 582
+#define OBJ_setct_CapResTBE OBJ_set_ctype,64L
+
+#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE"
+#define NID_setct_CapRevReqTBE 583
+#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L
+
+#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX"
+#define NID_setct_CapRevReqTBEX 584
+#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L
+
+#define SN_setct_CapRevResTBE "setct-CapRevResTBE"
+#define NID_setct_CapRevResTBE 585
+#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L
+
+#define SN_setct_CredReqTBE "setct-CredReqTBE"
+#define NID_setct_CredReqTBE 586
+#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L
+
+#define SN_setct_CredReqTBEX "setct-CredReqTBEX"
+#define NID_setct_CredReqTBEX 587
+#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L
+
+#define SN_setct_CredResTBE "setct-CredResTBE"
+#define NID_setct_CredResTBE 588
+#define OBJ_setct_CredResTBE OBJ_set_ctype,70L
+
+#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE"
+#define NID_setct_CredRevReqTBE 589
+#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L
+
+#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX"
+#define NID_setct_CredRevReqTBEX 590
+#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L
+
+#define SN_setct_CredRevResTBE "setct-CredRevResTBE"
+#define NID_setct_CredRevResTBE 591
+#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L
+
+#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE"
+#define NID_setct_BatchAdminReqTBE 592
+#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L
+
+#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE"
+#define NID_setct_BatchAdminResTBE 593
+#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L
+
+#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE"
+#define NID_setct_RegFormReqTBE 594
+#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L
+
+#define SN_setct_CertReqTBE "setct-CertReqTBE"
+#define NID_setct_CertReqTBE 595
+#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L
+
+#define SN_setct_CertReqTBEX "setct-CertReqTBEX"
+#define NID_setct_CertReqTBEX 596
+#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L
+
+#define SN_setct_CertResTBE "setct-CertResTBE"
+#define NID_setct_CertResTBE 597
+#define OBJ_setct_CertResTBE OBJ_set_ctype,79L
+
+#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS"
+#define NID_setct_CRLNotificationTBS 598
+#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L
+
+#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS"
+#define NID_setct_CRLNotificationResTBS 599
+#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L
+
+#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS"
+#define NID_setct_BCIDistributionTBS 600
+#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L
+
+#define SN_setext_genCrypt "setext-genCrypt"
+#define LN_setext_genCrypt "generic cryptogram"
+#define NID_setext_genCrypt 601
+#define OBJ_setext_genCrypt OBJ_set_msgExt,1L
+
+#define SN_setext_miAuth "setext-miAuth"
+#define LN_setext_miAuth "merchant initiated auth"
+#define NID_setext_miAuth 602
+#define OBJ_setext_miAuth OBJ_set_msgExt,3L
+
+#define SN_setext_pinSecure "setext-pinSecure"
+#define NID_setext_pinSecure 603
+#define OBJ_setext_pinSecure OBJ_set_msgExt,4L
+
+#define SN_setext_pinAny "setext-pinAny"
+#define NID_setext_pinAny 604
+#define OBJ_setext_pinAny OBJ_set_msgExt,5L
+
+#define SN_setext_track2 "setext-track2"
+#define NID_setext_track2 605
+#define OBJ_setext_track2 OBJ_set_msgExt,7L
+
+#define SN_setext_cv "setext-cv"
+#define LN_setext_cv "additional verification"
+#define NID_setext_cv 606
+#define OBJ_setext_cv OBJ_set_msgExt,8L
+
+#define SN_set_policy_root "set-policy-root"
+#define NID_set_policy_root 607
+#define OBJ_set_policy_root OBJ_set_policy,0L
+
+#define SN_setCext_hashedRoot "setCext-hashedRoot"
+#define NID_setCext_hashedRoot 608
+#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L
+
+#define SN_setCext_certType "setCext-certType"
+#define NID_setCext_certType 609
+#define OBJ_setCext_certType OBJ_set_certExt,1L
+
+#define SN_setCext_merchData "setCext-merchData"
+#define NID_setCext_merchData 610
+#define OBJ_setCext_merchData OBJ_set_certExt,2L
+
+#define SN_setCext_cCertRequired "setCext-cCertRequired"
+#define NID_setCext_cCertRequired 611
+#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L
+
+#define SN_setCext_tunneling "setCext-tunneling"
+#define NID_setCext_tunneling 612
+#define OBJ_setCext_tunneling OBJ_set_certExt,4L
+
+#define SN_setCext_setExt "setCext-setExt"
+#define NID_setCext_setExt 613
+#define OBJ_setCext_setExt OBJ_set_certExt,5L
+
+#define SN_setCext_setQualf "setCext-setQualf"
+#define NID_setCext_setQualf 614
+#define OBJ_setCext_setQualf OBJ_set_certExt,6L
+
+#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities"
+#define NID_setCext_PGWYcapabilities 615
+#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L
+
+#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier"
+#define NID_setCext_TokenIdentifier 616
+#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L
+
+#define SN_setCext_Track2Data "setCext-Track2Data"
+#define NID_setCext_Track2Data 617
+#define OBJ_setCext_Track2Data OBJ_set_certExt,9L
+
+#define SN_setCext_TokenType "setCext-TokenType"
+#define NID_setCext_TokenType 618
+#define OBJ_setCext_TokenType OBJ_set_certExt,10L
+
+#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities"
+#define NID_setCext_IssuerCapabilities 619
+#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L
+
+#define SN_setAttr_Cert "setAttr-Cert"
+#define NID_setAttr_Cert 620
+#define OBJ_setAttr_Cert OBJ_set_attr,0L
+
+#define SN_setAttr_PGWYcap "setAttr-PGWYcap"
+#define LN_setAttr_PGWYcap "payment gateway capabilities"
+#define NID_setAttr_PGWYcap 621
+#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L
+
+#define SN_setAttr_TokenType "setAttr-TokenType"
+#define NID_setAttr_TokenType 622
+#define OBJ_setAttr_TokenType OBJ_set_attr,2L
+
+#define SN_setAttr_IssCap "setAttr-IssCap"
+#define LN_setAttr_IssCap "issuer capabilities"
+#define NID_setAttr_IssCap 623
+#define OBJ_setAttr_IssCap OBJ_set_attr,3L
+
+#define SN_set_rootKeyThumb "set-rootKeyThumb"
+#define NID_set_rootKeyThumb 624
+#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L
+
+#define SN_set_addPolicy "set-addPolicy"
+#define NID_set_addPolicy 625
+#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L
+
+#define SN_setAttr_Token_EMV "setAttr-Token-EMV"
+#define NID_setAttr_Token_EMV 626
+#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L
+
+#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime"
+#define NID_setAttr_Token_B0Prime 627
+#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L
+
+#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM"
+#define NID_setAttr_IssCap_CVM 628
+#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L
+
+#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2"
+#define NID_setAttr_IssCap_T2 629
+#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L
+
+#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig"
+#define NID_setAttr_IssCap_Sig 630
+#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L
+
+#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm"
+#define LN_setAttr_GenCryptgrm "generate cryptogram"
+#define NID_setAttr_GenCryptgrm 631
+#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L
+
+#define SN_setAttr_T2Enc "setAttr-T2Enc"
+#define LN_setAttr_T2Enc "encrypted track 2"
+#define NID_setAttr_T2Enc 632
+#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L
+
+#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt"
+#define LN_setAttr_T2cleartxt "cleartext track 2"
+#define NID_setAttr_T2cleartxt 633
+#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L
+
+#define SN_setAttr_TokICCsig "setAttr-TokICCsig"
+#define LN_setAttr_TokICCsig "ICC or token signature"
+#define NID_setAttr_TokICCsig 634
+#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L
+
+#define SN_setAttr_SecDevSig "setAttr-SecDevSig"
+#define LN_setAttr_SecDevSig "secure device signature"
+#define NID_setAttr_SecDevSig 635
+#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L
+
+#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA"
+#define NID_set_brand_IATA_ATA 636
+#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L
+
+#define SN_set_brand_Diners "set-brand-Diners"
+#define NID_set_brand_Diners 637
+#define OBJ_set_brand_Diners OBJ_set_brand,30L
+
+#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress"
+#define NID_set_brand_AmericanExpress 638
+#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L
+
+#define SN_set_brand_JCB "set-brand-JCB"
+#define NID_set_brand_JCB 639
+#define OBJ_set_brand_JCB OBJ_set_brand,35L
+
+#define SN_set_brand_Visa "set-brand-Visa"
+#define NID_set_brand_Visa 640
+#define OBJ_set_brand_Visa OBJ_set_brand,4L
+
+#define SN_set_brand_MasterCard "set-brand-MasterCard"
+#define NID_set_brand_MasterCard 641
+#define OBJ_set_brand_MasterCard OBJ_set_brand,5L
+
+#define SN_set_brand_Novus "set-brand-Novus"
+#define NID_set_brand_Novus 642
+#define OBJ_set_brand_Novus OBJ_set_brand,6011L
+
+#define SN_des_cdmf "DES-CDMF"
+#define LN_des_cdmf "des-cdmf"
+#define NID_des_cdmf 643
+#define OBJ_des_cdmf OBJ_rsadsi,3L,10L
+
+#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET"
+#define NID_rsaOAEPEncryptionSET 644
+#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L
+
+#define SN_ipsec3 "Oakley-EC2N-3"
+#define LN_ipsec3 "ipsec3"
+#define NID_ipsec3 749
+
+#define SN_ipsec4 "Oakley-EC2N-4"
+#define LN_ipsec4 "ipsec4"
+#define NID_ipsec4 750
+
+#define SN_whirlpool "whirlpool"
+#define NID_whirlpool 804
+#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L
+
+#define SN_cryptopro "cryptopro"
+#define NID_cryptopro 805
+#define OBJ_cryptopro OBJ_member_body,643L,2L,2L
+
+#define SN_cryptocom "cryptocom"
+#define NID_cryptocom 806
+#define OBJ_cryptocom OBJ_member_body,643L,2L,9L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001"
+#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001"
+#define NID_id_GostR3411_94_with_GostR3410_2001 807
+#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94"
+#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94"
+#define NID_id_GostR3411_94_with_GostR3410_94 808
+#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L
+
+#define SN_id_GostR3411_94 "md_gost94"
+#define LN_id_GostR3411_94 "GOST R 34.11-94"
+#define NID_id_GostR3411_94 809
+#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L
+
+#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94"
+#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94"
+#define NID_id_HMACGostR3411_94 810
+#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L
+
+#define SN_id_GostR3410_2001 "gost2001"
+#define LN_id_GostR3410_2001 "GOST R 34.10-2001"
+#define NID_id_GostR3410_2001 811
+#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L
+
+#define SN_id_GostR3410_94 "gost94"
+#define LN_id_GostR3410_94 "GOST R 34.10-94"
+#define NID_id_GostR3410_94 812
+#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L
+
+#define SN_id_Gost28147_89 "gost89"
+#define LN_id_Gost28147_89 "GOST 28147-89"
+#define NID_id_Gost28147_89 813
+#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L
+
+#define SN_gost89_cnt "gost89-cnt"
+#define NID_gost89_cnt 814
+
+#define SN_id_Gost28147_89_MAC "gost-mac"
+#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC"
+#define NID_id_Gost28147_89_MAC 815
+#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L
+
+#define SN_id_GostR3411_94_prf "prf-gostr3411-94"
+#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF"
+#define NID_id_GostR3411_94_prf 816
+#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L
+
+#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH"
+#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH"
+#define NID_id_GostR3410_2001DH 817
+#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L
+
+#define SN_id_GostR3410_94DH "id-GostR3410-94DH"
+#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH"
+#define NID_id_GostR3410_94DH 818
+#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L
+
+#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing"
+#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819
+#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L
+
+#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing"
+#define NID_id_Gost28147_89_None_KeyMeshing 820
+#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L
+
+#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet"
+#define NID_id_GostR3411_94_TestParamSet 821
+#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L
+
+#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet"
+#define NID_id_GostR3411_94_CryptoProParamSet 822
+#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L
+
+#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet"
+#define NID_id_Gost28147_89_TestParamSet 823
+#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L
+
+#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824
+#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L
+
+#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825
+#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L
+
+#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826
+#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L
+
+#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827
+#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L
+
+#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830
+#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L
+
+#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet"
+#define NID_id_GostR3410_94_TestParamSet 831
+#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L
+
+#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832
+#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833
+#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L
+
+#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834
+#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L
+
+#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835
+#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L
+
+#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836
+#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L
+
+#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837
+#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838
+#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L
+
+#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet"
+#define NID_id_GostR3410_2001_TestParamSet 839
+#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840
+#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L
+
+#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841
+#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L
+
+#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842
+#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843
+#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844
+#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L
+
+#define SN_id_GostR3410_94_a "id-GostR3410-94-a"
+#define NID_id_GostR3410_94_a 845
+#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L
+
+#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis"
+#define NID_id_GostR3410_94_aBis 846
+#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L
+
+#define SN_id_GostR3410_94_b "id-GostR3410-94-b"
+#define NID_id_GostR3410_94_b 847
+#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L
+
+#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis"
+#define NID_id_GostR3410_94_bBis 848
+#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L
+
+#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc"
+#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet"
+#define NID_id_Gost28147_89_cc 849
+#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L
+
+#define SN_id_GostR3410_94_cc "gost94cc"
+#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom"
+#define NID_id_GostR3410_94_cc 850
+#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L
+
+#define SN_id_GostR3410_2001_cc "gost2001cc"
+#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom"
+#define NID_id_GostR3410_2001_cc 851
+#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L
+
+#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc"
+#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_94_cc 852
+#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc"
+#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853
+#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L
+
+#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc"
+#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom"
+#define NID_id_GostR3410_2001_ParamSet_cc 854
+#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L
+
+#define SN_camellia_128_cbc "CAMELLIA-128-CBC"
+#define LN_camellia_128_cbc "camellia-128-cbc"
+#define NID_camellia_128_cbc 751
+#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L
+
+#define SN_camellia_192_cbc "CAMELLIA-192-CBC"
+#define LN_camellia_192_cbc "camellia-192-cbc"
+#define NID_camellia_192_cbc 752
+#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L
+
+#define SN_camellia_256_cbc "CAMELLIA-256-CBC"
+#define LN_camellia_256_cbc "camellia-256-cbc"
+#define NID_camellia_256_cbc 753
+#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L
+
+#define SN_id_camellia128_wrap "id-camellia128-wrap"
+#define NID_id_camellia128_wrap 907
+#define OBJ_id_camellia128_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,2L
+
+#define SN_id_camellia192_wrap "id-camellia192-wrap"
+#define NID_id_camellia192_wrap 908
+#define OBJ_id_camellia192_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,3L
+
+#define SN_id_camellia256_wrap "id-camellia256-wrap"
+#define NID_id_camellia256_wrap 909
+#define OBJ_id_camellia256_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,4L
+
+#define OBJ_ntt_ds 0L,3L,4401L,5L
+
+#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L
+
+#define SN_camellia_128_ecb "CAMELLIA-128-ECB"
+#define LN_camellia_128_ecb "camellia-128-ecb"
+#define NID_camellia_128_ecb 754
+#define OBJ_camellia_128_ecb OBJ_camellia,1L
+
+#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB"
+#define LN_camellia_128_ofb128 "camellia-128-ofb"
+#define NID_camellia_128_ofb128 766
+#define OBJ_camellia_128_ofb128 OBJ_camellia,3L
+
+#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB"
+#define LN_camellia_128_cfb128 "camellia-128-cfb"
+#define NID_camellia_128_cfb128 757
+#define OBJ_camellia_128_cfb128 OBJ_camellia,4L
+
+#define SN_camellia_192_ecb "CAMELLIA-192-ECB"
+#define LN_camellia_192_ecb "camellia-192-ecb"
+#define NID_camellia_192_ecb 755
+#define OBJ_camellia_192_ecb OBJ_camellia,21L
+
+#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB"
+#define LN_camellia_192_ofb128 "camellia-192-ofb"
+#define NID_camellia_192_ofb128 767
+#define OBJ_camellia_192_ofb128 OBJ_camellia,23L
+
+#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB"
+#define LN_camellia_192_cfb128 "camellia-192-cfb"
+#define NID_camellia_192_cfb128 758
+#define OBJ_camellia_192_cfb128 OBJ_camellia,24L
+
+#define SN_camellia_256_ecb "CAMELLIA-256-ECB"
+#define LN_camellia_256_ecb "camellia-256-ecb"
+#define NID_camellia_256_ecb 756
+#define OBJ_camellia_256_ecb OBJ_camellia,41L
+
+#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB"
+#define LN_camellia_256_ofb128 "camellia-256-ofb"
+#define NID_camellia_256_ofb128 768
+#define OBJ_camellia_256_ofb128 OBJ_camellia,43L
+
+#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB"
+#define LN_camellia_256_cfb128 "camellia-256-cfb"
+#define NID_camellia_256_cfb128 759
+#define OBJ_camellia_256_cfb128 OBJ_camellia,44L
+
+#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1"
+#define LN_camellia_128_cfb1 "camellia-128-cfb1"
+#define NID_camellia_128_cfb1 760
+
+#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1"
+#define LN_camellia_192_cfb1 "camellia-192-cfb1"
+#define NID_camellia_192_cfb1 761
+
+#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1"
+#define LN_camellia_256_cfb1 "camellia-256-cfb1"
+#define NID_camellia_256_cfb1 762
+
+#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8"
+#define LN_camellia_128_cfb8 "camellia-128-cfb8"
+#define NID_camellia_128_cfb8 763
+
+#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8"
+#define LN_camellia_192_cfb8 "camellia-192-cfb8"
+#define NID_camellia_192_cfb8 764
+
+#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8"
+#define LN_camellia_256_cfb8 "camellia-256-cfb8"
+#define NID_camellia_256_cfb8 765
+
+#define SN_kisa "KISA"
+#define LN_kisa "kisa"
+#define NID_kisa 773
+#define OBJ_kisa OBJ_member_body,410L,200004L
+
+#define SN_seed_ecb "SEED-ECB"
+#define LN_seed_ecb "seed-ecb"
+#define NID_seed_ecb 776
+#define OBJ_seed_ecb OBJ_kisa,1L,3L
+
+#define SN_seed_cbc "SEED-CBC"
+#define LN_seed_cbc "seed-cbc"
+#define NID_seed_cbc 777
+#define OBJ_seed_cbc OBJ_kisa,1L,4L
+
+#define SN_seed_cfb128 "SEED-CFB"
+#define LN_seed_cfb128 "seed-cfb"
+#define NID_seed_cfb128 779
+#define OBJ_seed_cfb128 OBJ_kisa,1L,5L
+
+#define SN_seed_ofb128 "SEED-OFB"
+#define LN_seed_ofb128 "seed-ofb"
+#define NID_seed_ofb128 778
+#define OBJ_seed_ofb128 OBJ_kisa,1L,6L
+
+#define SN_hmac "HMAC"
+#define LN_hmac "hmac"
+#define NID_hmac 855
+
+#define SN_cmac "CMAC"
+#define LN_cmac "cmac"
+#define NID_cmac 894
+
+#define SN_rc4_hmac_md5 "RC4-HMAC-MD5"
+#define LN_rc4_hmac_md5 "rc4-hmac-md5"
+#define NID_rc4_hmac_md5 915
+
+#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1"
+#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1"
+#define NID_aes_128_cbc_hmac_sha1 916
+
+#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1"
+#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1"
+#define NID_aes_192_cbc_hmac_sha1 917
+
+#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1"
+#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1"
+#define NID_aes_256_cbc_hmac_sha1 918
+
+#define SN_dhpublicnumber "dhpublicnumber"
+#define LN_dhpublicnumber "X9.42 DH"
+#define NID_dhpublicnumber 920
+#define OBJ_dhpublicnumber OBJ_ISO_US,10046L,2L,1L
+
+#define SN_brainpoolP160r1 "brainpoolP160r1"
+#define NID_brainpoolP160r1 921
+#define OBJ_brainpoolP160r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,1L
+
+#define SN_brainpoolP160t1 "brainpoolP160t1"
+#define NID_brainpoolP160t1 922
+#define OBJ_brainpoolP160t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,2L
+
+#define SN_brainpoolP192r1 "brainpoolP192r1"
+#define NID_brainpoolP192r1 923
+#define OBJ_brainpoolP192r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,3L
+
+#define SN_brainpoolP192t1 "brainpoolP192t1"
+#define NID_brainpoolP192t1 924
+#define OBJ_brainpoolP192t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,4L
+
+#define SN_brainpoolP224r1 "brainpoolP224r1"
+#define NID_brainpoolP224r1 925
+#define OBJ_brainpoolP224r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,5L
+
+#define SN_brainpoolP224t1 "brainpoolP224t1"
+#define NID_brainpoolP224t1 926
+#define OBJ_brainpoolP224t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,6L
+
+#define SN_brainpoolP256r1 "brainpoolP256r1"
+#define NID_brainpoolP256r1 927
+#define OBJ_brainpoolP256r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,7L
+
+#define SN_brainpoolP256t1 "brainpoolP256t1"
+#define NID_brainpoolP256t1 928
+#define OBJ_brainpoolP256t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,8L
+
+#define SN_brainpoolP320r1 "brainpoolP320r1"
+#define NID_brainpoolP320r1 929
+#define OBJ_brainpoolP320r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,9L
+
+#define SN_brainpoolP320t1 "brainpoolP320t1"
+#define NID_brainpoolP320t1 930
+#define OBJ_brainpoolP320t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,10L
+
+#define SN_brainpoolP384r1 "brainpoolP384r1"
+#define NID_brainpoolP384r1 931
+#define OBJ_brainpoolP384r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,11L
+
+#define SN_brainpoolP384t1 "brainpoolP384t1"
+#define NID_brainpoolP384t1 932
+#define OBJ_brainpoolP384t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,12L
+
+#define SN_brainpoolP512r1 "brainpoolP512r1"
+#define NID_brainpoolP512r1 933
+#define OBJ_brainpoolP512r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,13L
+
+#define SN_brainpoolP512t1 "brainpoolP512t1"
+#define NID_brainpoolP512t1 934
+#define OBJ_brainpoolP512t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,14L
+
+#define OBJ_x9_63_scheme 1L,3L,133L,16L,840L,63L,0L
+
+#define OBJ_secg_scheme OBJ_certicom_arc,1L
+
+#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936
+#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme OBJ_x9_63_scheme,2L
+
+#define SN_dhSinglePass_stdDH_sha224kdf_scheme "dhSinglePass-stdDH-sha224kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937
+#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme OBJ_secg_scheme,11L,0L
+
+#define SN_dhSinglePass_stdDH_sha256kdf_scheme "dhSinglePass-stdDH-sha256kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938
+#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme OBJ_secg_scheme,11L,1L
+
+#define SN_dhSinglePass_stdDH_sha384kdf_scheme "dhSinglePass-stdDH-sha384kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939
+#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme OBJ_secg_scheme,11L,2L
+
+#define SN_dhSinglePass_stdDH_sha512kdf_scheme "dhSinglePass-stdDH-sha512kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940
+#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme OBJ_secg_scheme,11L,3L
+
+#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme "dhSinglePass-cofactorDH-sha1kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941
+#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme OBJ_x9_63_scheme,3L
+
+#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme "dhSinglePass-cofactorDH-sha224kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942
+#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme OBJ_secg_scheme,14L,0L
+
+#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme "dhSinglePass-cofactorDH-sha256kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943
+#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme OBJ_secg_scheme,14L,1L
+
+#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme "dhSinglePass-cofactorDH-sha384kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944
+#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme OBJ_secg_scheme,14L,2L
+
+#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme "dhSinglePass-cofactorDH-sha512kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945
+#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L
+
+#define SN_dh_std_kdf "dh-std-kdf"
+#define NID_dh_std_kdf 946
+
+#define SN_dh_cofactor_kdf "dh-cofactor-kdf"
+#define NID_dh_cofactor_kdf 947
+
+#define SN_X25519 "X25519"
+#define NID_X25519 948
+
+#define SN_cecpq1 "cecpq1"
+#define NID_cecpq1 949
+
+
+#endif /* OPENSSL_HEADER_NID_H */
diff --git a/include/openssl/obj.h b/include/openssl/obj.h
index 32a48948..7e24820c 100644
--- a/include/openssl/obj.h
+++ b/include/openssl/obj.h
@@ -60,7 +60,7 @@
#include <openssl/base.h>
#include <openssl/bytestring.h>
-#include <openssl/obj_mac.h>
+#include <openssl/nid.h>
#if defined(__cplusplus)
extern "C" {
@@ -189,6 +189,32 @@ OPENSSL_EXPORT int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid,
int pkey_nid);
+/* Deprecated functions. */
+
+typedef struct obj_name_st {
+ int type;
+ const char *name;
+} OBJ_NAME;
+
+#define OBJ_NAME_TYPE_MD_METH 1
+#define OBJ_NAME_TYPE_CIPHER_METH 2
+
+/* OBJ_NAME_do_all_sorted calls |callback| zero or more times, each time with
+ * the name of a different primitive. If |type| is |OBJ_NAME_TYPE_MD_METH| then
+ * the primitives will be hash functions, alternatively if |type| is
+ * |OBJ_NAME_TYPE_CIPHER_METH| then the primitives will be ciphers or cipher
+ * modes.
+ *
+ * This function is ill-specified and should never be used. */
+OPENSSL_EXPORT void OBJ_NAME_do_all_sorted(
+ int type, void (*callback)(const OBJ_NAME *, void *arg), void *arg);
+
+/* OBJ_NAME_do_all calls |OBJ_NAME_do_all_sorted|. */
+OPENSSL_EXPORT void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *,
+ void *arg),
+ void *arg);
+
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index b636adcf..e7ccadc1 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -1,4144 +1,18 @@
-/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
- * following command:
- * perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h */
-
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
+/* Copyright (c) 2016, Google Inc.
*
- * 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.]
- */
-
-#define SN_undef "UNDEF"
-#define LN_undef "undefined"
-#define NID_undef 0
-#define OBJ_undef 0L
-
-#define SN_itu_t "ITU-T"
-#define LN_itu_t "itu-t"
-#define NID_itu_t 645
-#define OBJ_itu_t 0L
-
-#define NID_ccitt 404
-#define OBJ_ccitt OBJ_itu_t
-
-#define SN_iso "ISO"
-#define LN_iso "iso"
-#define NID_iso 181
-#define OBJ_iso 1L
-
-#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T"
-#define LN_joint_iso_itu_t "joint-iso-itu-t"
-#define NID_joint_iso_itu_t 646
-#define OBJ_joint_iso_itu_t 2L
-
-#define NID_joint_iso_ccitt 393
-#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t
-
-#define SN_member_body "member-body"
-#define LN_member_body "ISO Member Body"
-#define NID_member_body 182
-#define OBJ_member_body OBJ_iso,2L
-
-#define SN_identified_organization "identified-organization"
-#define NID_identified_organization 676
-#define OBJ_identified_organization OBJ_iso,3L
-
-#define SN_hmac_md5 "HMAC-MD5"
-#define LN_hmac_md5 "hmac-md5"
-#define NID_hmac_md5 780
-#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
-
-#define SN_hmac_sha1 "HMAC-SHA1"
-#define LN_hmac_sha1 "hmac-sha1"
-#define NID_hmac_sha1 781
-#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
-
-#define SN_certicom_arc "certicom-arc"
-#define NID_certicom_arc 677
-#define OBJ_certicom_arc OBJ_identified_organization,132L
-
-#define SN_international_organizations "international-organizations"
-#define LN_international_organizations "International Organizations"
-#define NID_international_organizations 647
-#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L
-
-#define SN_wap "wap"
-#define NID_wap 678
-#define OBJ_wap OBJ_international_organizations,43L
-
-#define SN_wap_wsg "wap-wsg"
-#define NID_wap_wsg 679
-#define OBJ_wap_wsg OBJ_wap,1L
-
-#define SN_selected_attribute_types "selected-attribute-types"
-#define LN_selected_attribute_types "Selected Attribute Types"
-#define NID_selected_attribute_types 394
-#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L
-
-#define SN_clearance "clearance"
-#define NID_clearance 395
-#define OBJ_clearance OBJ_selected_attribute_types,55L
-
-#define SN_ISO_US "ISO-US"
-#define LN_ISO_US "ISO US Member Body"
-#define NID_ISO_US 183
-#define OBJ_ISO_US OBJ_member_body,840L
-
-#define SN_X9_57 "X9-57"
-#define LN_X9_57 "X9.57"
-#define NID_X9_57 184
-#define OBJ_X9_57 OBJ_ISO_US,10040L
-
-#define SN_X9cm "X9cm"
-#define LN_X9cm "X9.57 CM ?"
-#define NID_X9cm 185
-#define OBJ_X9cm OBJ_X9_57,4L
-
-#define SN_dsa "DSA"
-#define LN_dsa "dsaEncryption"
-#define NID_dsa 116
-#define OBJ_dsa OBJ_X9cm,1L
-
-#define SN_dsaWithSHA1 "DSA-SHA1"
-#define LN_dsaWithSHA1 "dsaWithSHA1"
-#define NID_dsaWithSHA1 113
-#define OBJ_dsaWithSHA1 OBJ_X9cm,3L
-
-#define SN_ansi_X9_62 "ansi-X9-62"
-#define LN_ansi_X9_62 "ANSI X9.62"
-#define NID_ansi_X9_62 405
-#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L
-
-#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L
-
-#define SN_X9_62_prime_field "prime-field"
-#define NID_X9_62_prime_field 406
-#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L
-
-#define SN_X9_62_characteristic_two_field "characteristic-two-field"
-#define NID_X9_62_characteristic_two_field 407
-#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L
-
-#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis"
-#define NID_X9_62_id_characteristic_two_basis 680
-#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L
-
-#define SN_X9_62_onBasis "onBasis"
-#define NID_X9_62_onBasis 681
-#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L
-
-#define SN_X9_62_tpBasis "tpBasis"
-#define NID_X9_62_tpBasis 682
-#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L
-
-#define SN_X9_62_ppBasis "ppBasis"
-#define NID_X9_62_ppBasis 683
-#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L
-
-#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L
-
-#define SN_X9_62_id_ecPublicKey "id-ecPublicKey"
-#define NID_X9_62_id_ecPublicKey 408
-#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L
-
-#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L
-
-#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L
-
-#define SN_X9_62_c2pnb163v1 "c2pnb163v1"
-#define NID_X9_62_c2pnb163v1 684
-#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L
-
-#define SN_X9_62_c2pnb163v2 "c2pnb163v2"
-#define NID_X9_62_c2pnb163v2 685
-#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L
-
-#define SN_X9_62_c2pnb163v3 "c2pnb163v3"
-#define NID_X9_62_c2pnb163v3 686
-#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L
-
-#define SN_X9_62_c2pnb176v1 "c2pnb176v1"
-#define NID_X9_62_c2pnb176v1 687
-#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L
-
-#define SN_X9_62_c2tnb191v1 "c2tnb191v1"
-#define NID_X9_62_c2tnb191v1 688
-#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L
-
-#define SN_X9_62_c2tnb191v2 "c2tnb191v2"
-#define NID_X9_62_c2tnb191v2 689
-#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L
-
-#define SN_X9_62_c2tnb191v3 "c2tnb191v3"
-#define NID_X9_62_c2tnb191v3 690
-#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L
-
-#define SN_X9_62_c2onb191v4 "c2onb191v4"
-#define NID_X9_62_c2onb191v4 691
-#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L
-
-#define SN_X9_62_c2onb191v5 "c2onb191v5"
-#define NID_X9_62_c2onb191v5 692
-#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L
-
-#define SN_X9_62_c2pnb208w1 "c2pnb208w1"
-#define NID_X9_62_c2pnb208w1 693
-#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L
-
-#define SN_X9_62_c2tnb239v1 "c2tnb239v1"
-#define NID_X9_62_c2tnb239v1 694
-#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L
-
-#define SN_X9_62_c2tnb239v2 "c2tnb239v2"
-#define NID_X9_62_c2tnb239v2 695
-#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L
-
-#define SN_X9_62_c2tnb239v3 "c2tnb239v3"
-#define NID_X9_62_c2tnb239v3 696
-#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L
-
-#define SN_X9_62_c2onb239v4 "c2onb239v4"
-#define NID_X9_62_c2onb239v4 697
-#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L
-
-#define SN_X9_62_c2onb239v5 "c2onb239v5"
-#define NID_X9_62_c2onb239v5 698
-#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L
-
-#define SN_X9_62_c2pnb272w1 "c2pnb272w1"
-#define NID_X9_62_c2pnb272w1 699
-#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L
-
-#define SN_X9_62_c2pnb304w1 "c2pnb304w1"
-#define NID_X9_62_c2pnb304w1 700
-#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L
-
-#define SN_X9_62_c2tnb359v1 "c2tnb359v1"
-#define NID_X9_62_c2tnb359v1 701
-#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L
-
-#define SN_X9_62_c2pnb368w1 "c2pnb368w1"
-#define NID_X9_62_c2pnb368w1 702
-#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L
-
-#define SN_X9_62_c2tnb431r1 "c2tnb431r1"
-#define NID_X9_62_c2tnb431r1 703
-#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L
-
-#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L
-
-#define SN_X9_62_prime192v1 "prime192v1"
-#define NID_X9_62_prime192v1 409
-#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L
-
-#define SN_X9_62_prime192v2 "prime192v2"
-#define NID_X9_62_prime192v2 410
-#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L
-
-#define SN_X9_62_prime192v3 "prime192v3"
-#define NID_X9_62_prime192v3 411
-#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L
-
-#define SN_X9_62_prime239v1 "prime239v1"
-#define NID_X9_62_prime239v1 412
-#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L
-
-#define SN_X9_62_prime239v2 "prime239v2"
-#define NID_X9_62_prime239v2 413
-#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L
-
-#define SN_X9_62_prime239v3 "prime239v3"
-#define NID_X9_62_prime239v3 414
-#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L
-
-#define SN_X9_62_prime256v1 "prime256v1"
-#define NID_X9_62_prime256v1 415
-#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L
-
-#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L
-
-#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1"
-#define NID_ecdsa_with_SHA1 416
-#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L
-
-#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended"
-#define NID_ecdsa_with_Recommended 791
-#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L
-
-#define SN_ecdsa_with_Specified "ecdsa-with-Specified"
-#define NID_ecdsa_with_Specified 792
-#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L
-
-#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224"
-#define NID_ecdsa_with_SHA224 793
-#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L
-
-#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256"
-#define NID_ecdsa_with_SHA256 794
-#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L
-
-#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384"
-#define NID_ecdsa_with_SHA384 795
-#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L
-
-#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512"
-#define NID_ecdsa_with_SHA512 796
-#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L
-
-#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L
-
-#define SN_secp112r1 "secp112r1"
-#define NID_secp112r1 704
-#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L
-
-#define SN_secp112r2 "secp112r2"
-#define NID_secp112r2 705
-#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L
-
-#define SN_secp128r1 "secp128r1"
-#define NID_secp128r1 706
-#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L
-
-#define SN_secp128r2 "secp128r2"
-#define NID_secp128r2 707
-#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L
-
-#define SN_secp160k1 "secp160k1"
-#define NID_secp160k1 708
-#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L
-
-#define SN_secp160r1 "secp160r1"
-#define NID_secp160r1 709
-#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L
-
-#define SN_secp160r2 "secp160r2"
-#define NID_secp160r2 710
-#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L
-
-#define SN_secp192k1 "secp192k1"
-#define NID_secp192k1 711
-#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L
-
-#define SN_secp224k1 "secp224k1"
-#define NID_secp224k1 712
-#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L
-
-#define SN_secp224r1 "secp224r1"
-#define NID_secp224r1 713
-#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L
-
-#define SN_secp256k1 "secp256k1"
-#define NID_secp256k1 714
-#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L
-
-#define SN_secp384r1 "secp384r1"
-#define NID_secp384r1 715
-#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L
-
-#define SN_secp521r1 "secp521r1"
-#define NID_secp521r1 716
-#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L
-
-#define SN_sect113r1 "sect113r1"
-#define NID_sect113r1 717
-#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L
-
-#define SN_sect113r2 "sect113r2"
-#define NID_sect113r2 718
-#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L
-
-#define SN_sect131r1 "sect131r1"
-#define NID_sect131r1 719
-#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L
-
-#define SN_sect131r2 "sect131r2"
-#define NID_sect131r2 720
-#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L
-
-#define SN_sect163k1 "sect163k1"
-#define NID_sect163k1 721
-#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L
-
-#define SN_sect163r1 "sect163r1"
-#define NID_sect163r1 722
-#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L
-
-#define SN_sect163r2 "sect163r2"
-#define NID_sect163r2 723
-#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L
-
-#define SN_sect193r1 "sect193r1"
-#define NID_sect193r1 724
-#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L
-
-#define SN_sect193r2 "sect193r2"
-#define NID_sect193r2 725
-#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L
-
-#define SN_sect233k1 "sect233k1"
-#define NID_sect233k1 726
-#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L
-
-#define SN_sect233r1 "sect233r1"
-#define NID_sect233r1 727
-#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L
-
-#define SN_sect239k1 "sect239k1"
-#define NID_sect239k1 728
-#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L
-
-#define SN_sect283k1 "sect283k1"
-#define NID_sect283k1 729
-#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L
-
-#define SN_sect283r1 "sect283r1"
-#define NID_sect283r1 730
-#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L
-
-#define SN_sect409k1 "sect409k1"
-#define NID_sect409k1 731
-#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L
-
-#define SN_sect409r1 "sect409r1"
-#define NID_sect409r1 732
-#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L
-
-#define SN_sect571k1 "sect571k1"
-#define NID_sect571k1 733
-#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L
-
-#define SN_sect571r1 "sect571r1"
-#define NID_sect571r1 734
-#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L
-
-#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L
-
-#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1"
-#define NID_wap_wsg_idm_ecid_wtls1 735
-#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L
-
-#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3"
-#define NID_wap_wsg_idm_ecid_wtls3 736
-#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L
-
-#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4"
-#define NID_wap_wsg_idm_ecid_wtls4 737
-#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L
-
-#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5"
-#define NID_wap_wsg_idm_ecid_wtls5 738
-#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L
-
-#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6"
-#define NID_wap_wsg_idm_ecid_wtls6 739
-#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L
-
-#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7"
-#define NID_wap_wsg_idm_ecid_wtls7 740
-#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L
-
-#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8"
-#define NID_wap_wsg_idm_ecid_wtls8 741
-#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L
-
-#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9"
-#define NID_wap_wsg_idm_ecid_wtls9 742
-#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L
-
-#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10"
-#define NID_wap_wsg_idm_ecid_wtls10 743
-#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L
-
-#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11"
-#define NID_wap_wsg_idm_ecid_wtls11 744
-#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L
-
-#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12"
-#define NID_wap_wsg_idm_ecid_wtls12 745
-#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L
-
-#define SN_cast5_cbc "CAST5-CBC"
-#define LN_cast5_cbc "cast5-cbc"
-#define NID_cast5_cbc 108
-#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L
-
-#define SN_cast5_ecb "CAST5-ECB"
-#define LN_cast5_ecb "cast5-ecb"
-#define NID_cast5_ecb 109
-
-#define SN_cast5_cfb64 "CAST5-CFB"
-#define LN_cast5_cfb64 "cast5-cfb"
-#define NID_cast5_cfb64 110
-
-#define SN_cast5_ofb64 "CAST5-OFB"
-#define LN_cast5_ofb64 "cast5-ofb"
-#define NID_cast5_ofb64 111
-
-#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
-#define NID_pbeWithMD5AndCast5_CBC 112
-#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L
-
-#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC"
-#define LN_id_PasswordBasedMAC "password based MAC"
-#define NID_id_PasswordBasedMAC 782
-#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L
-
-#define SN_id_DHBasedMac "id-DHBasedMac"
-#define LN_id_DHBasedMac "Diffie-Hellman based MAC"
-#define NID_id_DHBasedMac 783
-#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L
-
-#define SN_rsadsi "rsadsi"
-#define LN_rsadsi "RSA Data Security, Inc."
-#define NID_rsadsi 1
-#define OBJ_rsadsi OBJ_ISO_US,113549L
-
-#define SN_pkcs "pkcs"
-#define LN_pkcs "RSA Data Security, Inc. PKCS"
-#define NID_pkcs 2
-#define OBJ_pkcs OBJ_rsadsi,1L
-
-#define SN_pkcs1 "pkcs1"
-#define NID_pkcs1 186
-#define OBJ_pkcs1 OBJ_pkcs,1L
-
-#define LN_rsaEncryption "rsaEncryption"
-#define NID_rsaEncryption 6
-#define OBJ_rsaEncryption OBJ_pkcs1,1L
-
-#define SN_md2WithRSAEncryption "RSA-MD2"
-#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
-#define NID_md2WithRSAEncryption 7
-#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L
-
-#define SN_md4WithRSAEncryption "RSA-MD4"
-#define LN_md4WithRSAEncryption "md4WithRSAEncryption"
-#define NID_md4WithRSAEncryption 396
-#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L
-
-#define SN_md5WithRSAEncryption "RSA-MD5"
-#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
-#define NID_md5WithRSAEncryption 8
-#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L
-
-#define SN_sha1WithRSAEncryption "RSA-SHA1"
-#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
-#define NID_sha1WithRSAEncryption 65
-#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L
-
-#define SN_rsaesOaep "RSAES-OAEP"
-#define LN_rsaesOaep "rsaesOaep"
-#define NID_rsaesOaep 919
-#define OBJ_rsaesOaep OBJ_pkcs1,7L
-
-#define SN_mgf1 "MGF1"
-#define LN_mgf1 "mgf1"
-#define NID_mgf1 911
-#define OBJ_mgf1 OBJ_pkcs1,8L
-
-#define SN_pSpecified "PSPECIFIED"
-#define LN_pSpecified "pSpecified"
-#define NID_pSpecified 935
-#define OBJ_pSpecified OBJ_pkcs1,9L
-
-#define SN_rsassaPss "RSASSA-PSS"
-#define LN_rsassaPss "rsassaPss"
-#define NID_rsassaPss 912
-#define OBJ_rsassaPss OBJ_pkcs1,10L
-
-#define SN_sha256WithRSAEncryption "RSA-SHA256"
-#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption"
-#define NID_sha256WithRSAEncryption 668
-#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L
-
-#define SN_sha384WithRSAEncryption "RSA-SHA384"
-#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption"
-#define NID_sha384WithRSAEncryption 669
-#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L
-
-#define SN_sha512WithRSAEncryption "RSA-SHA512"
-#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption"
-#define NID_sha512WithRSAEncryption 670
-#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L
-
-#define SN_sha224WithRSAEncryption "RSA-SHA224"
-#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption"
-#define NID_sha224WithRSAEncryption 671
-#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L
-
-#define SN_pkcs3 "pkcs3"
-#define NID_pkcs3 27
-#define OBJ_pkcs3 OBJ_pkcs,3L
-
-#define LN_dhKeyAgreement "dhKeyAgreement"
-#define NID_dhKeyAgreement 28
-#define OBJ_dhKeyAgreement OBJ_pkcs3,1L
-
-#define SN_pkcs5 "pkcs5"
-#define NID_pkcs5 187
-#define OBJ_pkcs5 OBJ_pkcs,5L
-
-#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
-#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
-#define NID_pbeWithMD2AndDES_CBC 9
-#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L
-
-#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
-#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
-#define NID_pbeWithMD5AndDES_CBC 10
-#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L
-
-#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
-#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
-#define NID_pbeWithMD2AndRC2_CBC 168
-#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L
-
-#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
-#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
-#define NID_pbeWithMD5AndRC2_CBC 169
-#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L
-
-#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
-#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
-#define NID_pbeWithSHA1AndDES_CBC 170
-#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L
-
-#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
-#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
-#define NID_pbeWithSHA1AndRC2_CBC 68
-#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L
-
-#define LN_id_pbkdf2 "PBKDF2"
-#define NID_id_pbkdf2 69
-#define OBJ_id_pbkdf2 OBJ_pkcs5,12L
-
-#define LN_pbes2 "PBES2"
-#define NID_pbes2 161
-#define OBJ_pbes2 OBJ_pkcs5,13L
-
-#define LN_pbmac1 "PBMAC1"
-#define NID_pbmac1 162
-#define OBJ_pbmac1 OBJ_pkcs5,14L
-
-#define SN_pkcs7 "pkcs7"
-#define NID_pkcs7 20
-#define OBJ_pkcs7 OBJ_pkcs,7L
-
-#define LN_pkcs7_data "pkcs7-data"
-#define NID_pkcs7_data 21
-#define OBJ_pkcs7_data OBJ_pkcs7,1L
-
-#define LN_pkcs7_signed "pkcs7-signedData"
-#define NID_pkcs7_signed 22
-#define OBJ_pkcs7_signed OBJ_pkcs7,2L
-
-#define LN_pkcs7_enveloped "pkcs7-envelopedData"
-#define NID_pkcs7_enveloped 23
-#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L
-
-#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
-#define NID_pkcs7_signedAndEnveloped 24
-#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L
-
-#define LN_pkcs7_digest "pkcs7-digestData"
-#define NID_pkcs7_digest 25
-#define OBJ_pkcs7_digest OBJ_pkcs7,5L
-
-#define LN_pkcs7_encrypted "pkcs7-encryptedData"
-#define NID_pkcs7_encrypted 26
-#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L
-
-#define SN_pkcs9 "pkcs9"
-#define NID_pkcs9 47
-#define OBJ_pkcs9 OBJ_pkcs,9L
-
-#define LN_pkcs9_emailAddress "emailAddress"
-#define NID_pkcs9_emailAddress 48
-#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L
-
-#define LN_pkcs9_unstructuredName "unstructuredName"
-#define NID_pkcs9_unstructuredName 49
-#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L
-
-#define LN_pkcs9_contentType "contentType"
-#define NID_pkcs9_contentType 50
-#define OBJ_pkcs9_contentType OBJ_pkcs9,3L
-
-#define LN_pkcs9_messageDigest "messageDigest"
-#define NID_pkcs9_messageDigest 51
-#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L
-
-#define LN_pkcs9_signingTime "signingTime"
-#define NID_pkcs9_signingTime 52
-#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L
-
-#define LN_pkcs9_countersignature "countersignature"
-#define NID_pkcs9_countersignature 53
-#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L
-
-#define LN_pkcs9_challengePassword "challengePassword"
-#define NID_pkcs9_challengePassword 54
-#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L
-
-#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
-#define NID_pkcs9_unstructuredAddress 55
-#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L
-
-#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
-#define NID_pkcs9_extCertAttributes 56
-#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L
-
-#define SN_ext_req "extReq"
-#define LN_ext_req "Extension Request"
-#define NID_ext_req 172
-#define OBJ_ext_req OBJ_pkcs9,14L
-
-#define SN_SMIMECapabilities "SMIME-CAPS"
-#define LN_SMIMECapabilities "S/MIME Capabilities"
-#define NID_SMIMECapabilities 167
-#define OBJ_SMIMECapabilities OBJ_pkcs9,15L
-
-#define SN_SMIME "SMIME"
-#define LN_SMIME "S/MIME"
-#define NID_SMIME 188
-#define OBJ_SMIME OBJ_pkcs9,16L
-
-#define SN_id_smime_mod "id-smime-mod"
-#define NID_id_smime_mod 189
-#define OBJ_id_smime_mod OBJ_SMIME,0L
-
-#define SN_id_smime_ct "id-smime-ct"
-#define NID_id_smime_ct 190
-#define OBJ_id_smime_ct OBJ_SMIME,1L
-
-#define SN_id_smime_aa "id-smime-aa"
-#define NID_id_smime_aa 191
-#define OBJ_id_smime_aa OBJ_SMIME,2L
-
-#define SN_id_smime_alg "id-smime-alg"
-#define NID_id_smime_alg 192
-#define OBJ_id_smime_alg OBJ_SMIME,3L
-
-#define SN_id_smime_cd "id-smime-cd"
-#define NID_id_smime_cd 193
-#define OBJ_id_smime_cd OBJ_SMIME,4L
-
-#define SN_id_smime_spq "id-smime-spq"
-#define NID_id_smime_spq 194
-#define OBJ_id_smime_spq OBJ_SMIME,5L
-
-#define SN_id_smime_cti "id-smime-cti"
-#define NID_id_smime_cti 195
-#define OBJ_id_smime_cti OBJ_SMIME,6L
-
-#define SN_id_smime_mod_cms "id-smime-mod-cms"
-#define NID_id_smime_mod_cms 196
-#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
-
-#define SN_id_smime_mod_ess "id-smime-mod-ess"
-#define NID_id_smime_mod_ess 197
-#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L
-
-#define SN_id_smime_mod_oid "id-smime-mod-oid"
-#define NID_id_smime_mod_oid 198
-#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L
-
-#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3"
-#define NID_id_smime_mod_msg_v3 199
-#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L
-
-#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88"
-#define NID_id_smime_mod_ets_eSignature_88 200
-#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L
-
-#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97"
-#define NID_id_smime_mod_ets_eSignature_97 201
-#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L
-
-#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88"
-#define NID_id_smime_mod_ets_eSigPolicy_88 202
-#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L
-
-#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97"
-#define NID_id_smime_mod_ets_eSigPolicy_97 203
-#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L
-
-#define SN_id_smime_ct_receipt "id-smime-ct-receipt"
-#define NID_id_smime_ct_receipt 204
-#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L
-
-#define SN_id_smime_ct_authData "id-smime-ct-authData"
-#define NID_id_smime_ct_authData 205
-#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L
-
-#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert"
-#define NID_id_smime_ct_publishCert 206
-#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L
-
-#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo"
-#define NID_id_smime_ct_TSTInfo 207
-#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L
-
-#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo"
-#define NID_id_smime_ct_TDTInfo 208
-#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L
-
-#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo"
-#define NID_id_smime_ct_contentInfo 209
-#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L
-
-#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData"
-#define NID_id_smime_ct_DVCSRequestData 210
-#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L
-
-#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData"
-#define NID_id_smime_ct_DVCSResponseData 211
-#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L
-
-#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData"
-#define NID_id_smime_ct_compressedData 786
-#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L
-
-#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
-#define NID_id_ct_asciiTextWithCRLF 787
-#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L
-
-#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest"
-#define NID_id_smime_aa_receiptRequest 212
-#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L
-
-#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel"
-#define NID_id_smime_aa_securityLabel 213
-#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L
-
-#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory"
-#define NID_id_smime_aa_mlExpandHistory 214
-#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L
-
-#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint"
-#define NID_id_smime_aa_contentHint 215
-#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L
-
-#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest"
-#define NID_id_smime_aa_msgSigDigest 216
-#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L
-
-#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType"
-#define NID_id_smime_aa_encapContentType 217
-#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L
-
-#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier"
-#define NID_id_smime_aa_contentIdentifier 218
-#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L
-
-#define SN_id_smime_aa_macValue "id-smime-aa-macValue"
-#define NID_id_smime_aa_macValue 219
-#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L
-
-#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels"
-#define NID_id_smime_aa_equivalentLabels 220
-#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L
-
-#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference"
-#define NID_id_smime_aa_contentReference 221
-#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L
-
-#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref"
-#define NID_id_smime_aa_encrypKeyPref 222
-#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L
-
-#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate"
-#define NID_id_smime_aa_signingCertificate 223
-#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L
-
-#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts"
-#define NID_id_smime_aa_smimeEncryptCerts 224
-#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L
-
-#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken"
-#define NID_id_smime_aa_timeStampToken 225
-#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L
-
-#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId"
-#define NID_id_smime_aa_ets_sigPolicyId 226
-#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L
-
-#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType"
-#define NID_id_smime_aa_ets_commitmentType 227
-#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L
-
-#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation"
-#define NID_id_smime_aa_ets_signerLocation 228
-#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L
-
-#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr"
-#define NID_id_smime_aa_ets_signerAttr 229
-#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L
-
-#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert"
-#define NID_id_smime_aa_ets_otherSigCert 230
-#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L
-
-#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp"
-#define NID_id_smime_aa_ets_contentTimestamp 231
-#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L
-
-#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs"
-#define NID_id_smime_aa_ets_CertificateRefs 232
-#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L
-
-#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs"
-#define NID_id_smime_aa_ets_RevocationRefs 233
-#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L
-
-#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues"
-#define NID_id_smime_aa_ets_certValues 234
-#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L
-
-#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues"
-#define NID_id_smime_aa_ets_revocationValues 235
-#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L
-
-#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp"
-#define NID_id_smime_aa_ets_escTimeStamp 236
-#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L
-
-#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp"
-#define NID_id_smime_aa_ets_certCRLTimestamp 237
-#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L
-
-#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp"
-#define NID_id_smime_aa_ets_archiveTimeStamp 238
-#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L
-
-#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType"
-#define NID_id_smime_aa_signatureType 239
-#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L
-
-#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc"
-#define NID_id_smime_aa_dvcs_dvc 240
-#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L
-
-#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES"
-#define NID_id_smime_alg_ESDHwith3DES 241
-#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L
-
-#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2"
-#define NID_id_smime_alg_ESDHwithRC2 242
-#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L
-
-#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap"
-#define NID_id_smime_alg_3DESwrap 243
-#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L
-
-#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap"
-#define NID_id_smime_alg_RC2wrap 244
-#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L
-
-#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH"
-#define NID_id_smime_alg_ESDH 245
-#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L
-
-#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap"
-#define NID_id_smime_alg_CMS3DESwrap 246
-#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L
-
-#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap"
-#define NID_id_smime_alg_CMSRC2wrap 247
-#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L
-
-#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK"
-#define NID_id_alg_PWRI_KEK 893
-#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L
-
-#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
-#define NID_id_smime_cd_ldap 248
-#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L
-
-#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri"
-#define NID_id_smime_spq_ets_sqt_uri 249
-#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L
-
-#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice"
-#define NID_id_smime_spq_ets_sqt_unotice 250
-#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L
-
-#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin"
-#define NID_id_smime_cti_ets_proofOfOrigin 251
-#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L
-
-#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt"
-#define NID_id_smime_cti_ets_proofOfReceipt 252
-#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L
-
-#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery"
-#define NID_id_smime_cti_ets_proofOfDelivery 253
-#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L
-
-#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender"
-#define NID_id_smime_cti_ets_proofOfSender 254
-#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L
-
-#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval"
-#define NID_id_smime_cti_ets_proofOfApproval 255
-#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L
-
-#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation"
-#define NID_id_smime_cti_ets_proofOfCreation 256
-#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
-
-#define LN_friendlyName "friendlyName"
-#define NID_friendlyName 156
-#define OBJ_friendlyName OBJ_pkcs9,20L
-
-#define LN_localKeyID "localKeyID"
-#define NID_localKeyID 157
-#define OBJ_localKeyID OBJ_pkcs9,21L
-
-#define SN_ms_csp_name "CSPName"
-#define LN_ms_csp_name "Microsoft CSP Name"
-#define NID_ms_csp_name 417
-#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L
-
-#define SN_LocalKeySet "LocalKeySet"
-#define LN_LocalKeySet "Microsoft Local Key set"
-#define NID_LocalKeySet 856
-#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L
-
-#define OBJ_certTypes OBJ_pkcs9,22L
-
-#define LN_x509Certificate "x509Certificate"
-#define NID_x509Certificate 158
-#define OBJ_x509Certificate OBJ_certTypes,1L
-
-#define LN_sdsiCertificate "sdsiCertificate"
-#define NID_sdsiCertificate 159
-#define OBJ_sdsiCertificate OBJ_certTypes,2L
-
-#define OBJ_crlTypes OBJ_pkcs9,23L
-
-#define LN_x509Crl "x509Crl"
-#define NID_x509Crl 160
-#define OBJ_x509Crl OBJ_crlTypes,1L
-
-#define OBJ_pkcs12 OBJ_pkcs,12L
-
-#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L
-
-#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
-#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
-#define NID_pbe_WithSHA1And128BitRC4 144
-#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L
-
-#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
-#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
-#define NID_pbe_WithSHA1And40BitRC4 145
-#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L
-
-#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
-#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
-#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
-#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L
-
-#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
-#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
-#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
-#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L
-
-#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
-#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
-#define NID_pbe_WithSHA1And128BitRC2_CBC 148
-#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L
-
-#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
-#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
-#define NID_pbe_WithSHA1And40BitRC2_CBC 149
-#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L
-
-#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L
-
-#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L
-
-#define LN_keyBag "keyBag"
-#define NID_keyBag 150
-#define OBJ_keyBag OBJ_pkcs12_BagIds,1L
-
-#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
-#define NID_pkcs8ShroudedKeyBag 151
-#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L
-
-#define LN_certBag "certBag"
-#define NID_certBag 152
-#define OBJ_certBag OBJ_pkcs12_BagIds,3L
-
-#define LN_crlBag "crlBag"
-#define NID_crlBag 153
-#define OBJ_crlBag OBJ_pkcs12_BagIds,4L
-
-#define LN_secretBag "secretBag"
-#define NID_secretBag 154
-#define OBJ_secretBag OBJ_pkcs12_BagIds,5L
-
-#define LN_safeContentsBag "safeContentsBag"
-#define NID_safeContentsBag 155
-#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L
-
-#define SN_md2 "MD2"
-#define LN_md2 "md2"
-#define NID_md2 3
-#define OBJ_md2 OBJ_rsadsi,2L,2L
-
-#define SN_md4 "MD4"
-#define LN_md4 "md4"
-#define NID_md4 257
-#define OBJ_md4 OBJ_rsadsi,2L,4L
-
-#define SN_md5 "MD5"
-#define LN_md5 "md5"
-#define NID_md5 4
-#define OBJ_md5 OBJ_rsadsi,2L,5L
-
-#define SN_md5_sha1 "MD5-SHA1"
-#define LN_md5_sha1 "md5-sha1"
-#define NID_md5_sha1 114
-
-#define LN_hmacWithMD5 "hmacWithMD5"
-#define NID_hmacWithMD5 797
-#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L
-
-#define LN_hmacWithSHA1 "hmacWithSHA1"
-#define NID_hmacWithSHA1 163
-#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
-
-#define LN_hmacWithSHA224 "hmacWithSHA224"
-#define NID_hmacWithSHA224 798
-#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L
-
-#define LN_hmacWithSHA256 "hmacWithSHA256"
-#define NID_hmacWithSHA256 799
-#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L
-
-#define LN_hmacWithSHA384 "hmacWithSHA384"
-#define NID_hmacWithSHA384 800
-#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L
-
-#define LN_hmacWithSHA512 "hmacWithSHA512"
-#define NID_hmacWithSHA512 801
-#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L
-
-#define SN_rc2_cbc "RC2-CBC"
-#define LN_rc2_cbc "rc2-cbc"
-#define NID_rc2_cbc 37
-#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L
-
-#define SN_rc2_ecb "RC2-ECB"
-#define LN_rc2_ecb "rc2-ecb"
-#define NID_rc2_ecb 38
-
-#define SN_rc2_cfb64 "RC2-CFB"
-#define LN_rc2_cfb64 "rc2-cfb"
-#define NID_rc2_cfb64 39
-
-#define SN_rc2_ofb64 "RC2-OFB"
-#define LN_rc2_ofb64 "rc2-ofb"
-#define NID_rc2_ofb64 40
-
-#define SN_rc2_40_cbc "RC2-40-CBC"
-#define LN_rc2_40_cbc "rc2-40-cbc"
-#define NID_rc2_40_cbc 98
-
-#define SN_rc2_64_cbc "RC2-64-CBC"
-#define LN_rc2_64_cbc "rc2-64-cbc"
-#define NID_rc2_64_cbc 166
-
-#define SN_rc4 "RC4"
-#define LN_rc4 "rc4"
-#define NID_rc4 5
-#define OBJ_rc4 OBJ_rsadsi,3L,4L
-
-#define SN_rc4_40 "RC4-40"
-#define LN_rc4_40 "rc4-40"
-#define NID_rc4_40 97
-
-#define SN_des_ede3_cbc "DES-EDE3-CBC"
-#define LN_des_ede3_cbc "des-ede3-cbc"
-#define NID_des_ede3_cbc 44
-#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L
-
-#define SN_rc5_cbc "RC5-CBC"
-#define LN_rc5_cbc "rc5-cbc"
-#define NID_rc5_cbc 120
-#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L
-
-#define SN_rc5_ecb "RC5-ECB"
-#define LN_rc5_ecb "rc5-ecb"
-#define NID_rc5_ecb 121
-
-#define SN_rc5_cfb64 "RC5-CFB"
-#define LN_rc5_cfb64 "rc5-cfb"
-#define NID_rc5_cfb64 122
-
-#define SN_rc5_ofb64 "RC5-OFB"
-#define LN_rc5_ofb64 "rc5-ofb"
-#define NID_rc5_ofb64 123
-
-#define SN_ms_ext_req "msExtReq"
-#define LN_ms_ext_req "Microsoft Extension Request"
-#define NID_ms_ext_req 171
-#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
-
-#define SN_ms_code_ind "msCodeInd"
-#define LN_ms_code_ind "Microsoft Individual Code Signing"
-#define NID_ms_code_ind 134
-#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
-
-#define SN_ms_code_com "msCodeCom"
-#define LN_ms_code_com "Microsoft Commercial Code Signing"
-#define NID_ms_code_com 135
-#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
-
-#define SN_ms_ctl_sign "msCTLSign"
-#define LN_ms_ctl_sign "Microsoft Trust List Signing"
-#define NID_ms_ctl_sign 136
-#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
-
-#define SN_ms_sgc "msSGC"
-#define LN_ms_sgc "Microsoft Server Gated Crypto"
-#define NID_ms_sgc 137
-#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
-
-#define SN_ms_efs "msEFS"
-#define LN_ms_efs "Microsoft Encrypted File System"
-#define NID_ms_efs 138
-#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
-
-#define SN_ms_smartcard_login "msSmartcardLogin"
-#define LN_ms_smartcard_login "Microsoft Smartcardlogin"
-#define NID_ms_smartcard_login 648
-#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
-
-#define SN_ms_upn "msUPN"
-#define LN_ms_upn "Microsoft Universal Principal Name"
-#define NID_ms_upn 649
-#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
-
-#define SN_idea_cbc "IDEA-CBC"
-#define LN_idea_cbc "idea-cbc"
-#define NID_idea_cbc 34
-#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
-
-#define SN_idea_ecb "IDEA-ECB"
-#define LN_idea_ecb "idea-ecb"
-#define NID_idea_ecb 36
-
-#define SN_idea_cfb64 "IDEA-CFB"
-#define LN_idea_cfb64 "idea-cfb"
-#define NID_idea_cfb64 35
-
-#define SN_idea_ofb64 "IDEA-OFB"
-#define LN_idea_ofb64 "idea-ofb"
-#define NID_idea_ofb64 46
-
-#define SN_bf_cbc "BF-CBC"
-#define LN_bf_cbc "bf-cbc"
-#define NID_bf_cbc 91
-#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L
-
-#define SN_bf_ecb "BF-ECB"
-#define LN_bf_ecb "bf-ecb"
-#define NID_bf_ecb 92
-
-#define SN_bf_cfb64 "BF-CFB"
-#define LN_bf_cfb64 "bf-cfb"
-#define NID_bf_cfb64 93
-
-#define SN_bf_ofb64 "BF-OFB"
-#define LN_bf_ofb64 "bf-ofb"
-#define NID_bf_ofb64 94
-
-#define SN_id_pkix "PKIX"
-#define NID_id_pkix 127
-#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L
-
-#define SN_id_pkix_mod "id-pkix-mod"
-#define NID_id_pkix_mod 258
-#define OBJ_id_pkix_mod OBJ_id_pkix,0L
-
-#define SN_id_pe "id-pe"
-#define NID_id_pe 175
-#define OBJ_id_pe OBJ_id_pkix,1L
-
-#define SN_id_qt "id-qt"
-#define NID_id_qt 259
-#define OBJ_id_qt OBJ_id_pkix,2L
-
-#define SN_id_kp "id-kp"
-#define NID_id_kp 128
-#define OBJ_id_kp OBJ_id_pkix,3L
-
-#define SN_id_it "id-it"
-#define NID_id_it 260
-#define OBJ_id_it OBJ_id_pkix,4L
-
-#define SN_id_pkip "id-pkip"
-#define NID_id_pkip 261
-#define OBJ_id_pkip OBJ_id_pkix,5L
-
-#define SN_id_alg "id-alg"
-#define NID_id_alg 262
-#define OBJ_id_alg OBJ_id_pkix,6L
-
-#define SN_id_cmc "id-cmc"
-#define NID_id_cmc 263
-#define OBJ_id_cmc OBJ_id_pkix,7L
-
-#define SN_id_on "id-on"
-#define NID_id_on 264
-#define OBJ_id_on OBJ_id_pkix,8L
-
-#define SN_id_pda "id-pda"
-#define NID_id_pda 265
-#define OBJ_id_pda OBJ_id_pkix,9L
-
-#define SN_id_aca "id-aca"
-#define NID_id_aca 266
-#define OBJ_id_aca OBJ_id_pkix,10L
-
-#define SN_id_qcs "id-qcs"
-#define NID_id_qcs 267
-#define OBJ_id_qcs OBJ_id_pkix,11L
-
-#define SN_id_cct "id-cct"
-#define NID_id_cct 268
-#define OBJ_id_cct OBJ_id_pkix,12L
-
-#define SN_id_ppl "id-ppl"
-#define NID_id_ppl 662
-#define OBJ_id_ppl OBJ_id_pkix,21L
-
-#define SN_id_ad "id-ad"
-#define NID_id_ad 176
-#define OBJ_id_ad OBJ_id_pkix,48L
-
-#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88"
-#define NID_id_pkix1_explicit_88 269
-#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L
-
-#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88"
-#define NID_id_pkix1_implicit_88 270
-#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L
-
-#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93"
-#define NID_id_pkix1_explicit_93 271
-#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L
-
-#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93"
-#define NID_id_pkix1_implicit_93 272
-#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L
-
-#define SN_id_mod_crmf "id-mod-crmf"
-#define NID_id_mod_crmf 273
-#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L
-
-#define SN_id_mod_cmc "id-mod-cmc"
-#define NID_id_mod_cmc 274
-#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L
-
-#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88"
-#define NID_id_mod_kea_profile_88 275
-#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L
-
-#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93"
-#define NID_id_mod_kea_profile_93 276
-#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L
-
-#define SN_id_mod_cmp "id-mod-cmp"
-#define NID_id_mod_cmp 277
-#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L
-
-#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88"
-#define NID_id_mod_qualified_cert_88 278
-#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L
-
-#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93"
-#define NID_id_mod_qualified_cert_93 279
-#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L
-
-#define SN_id_mod_attribute_cert "id-mod-attribute-cert"
-#define NID_id_mod_attribute_cert 280
-#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L
-
-#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol"
-#define NID_id_mod_timestamp_protocol 281
-#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L
-
-#define SN_id_mod_ocsp "id-mod-ocsp"
-#define NID_id_mod_ocsp 282
-#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L
-
-#define SN_id_mod_dvcs "id-mod-dvcs"
-#define NID_id_mod_dvcs 283
-#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L
-
-#define SN_id_mod_cmp2000 "id-mod-cmp2000"
-#define NID_id_mod_cmp2000 284
-#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L
-
-#define SN_info_access "authorityInfoAccess"
-#define LN_info_access "Authority Information Access"
-#define NID_info_access 177
-#define OBJ_info_access OBJ_id_pe,1L
-
-#define SN_biometricInfo "biometricInfo"
-#define LN_biometricInfo "Biometric Info"
-#define NID_biometricInfo 285
-#define OBJ_biometricInfo OBJ_id_pe,2L
-
-#define SN_qcStatements "qcStatements"
-#define NID_qcStatements 286
-#define OBJ_qcStatements OBJ_id_pe,3L
-
-#define SN_ac_auditEntity "ac-auditEntity"
-#define NID_ac_auditEntity 287
-#define OBJ_ac_auditEntity OBJ_id_pe,4L
-
-#define SN_ac_targeting "ac-targeting"
-#define NID_ac_targeting 288
-#define OBJ_ac_targeting OBJ_id_pe,5L
-
-#define SN_aaControls "aaControls"
-#define NID_aaControls 289
-#define OBJ_aaControls OBJ_id_pe,6L
-
-#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock"
-#define NID_sbgp_ipAddrBlock 290
-#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L
-
-#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum"
-#define NID_sbgp_autonomousSysNum 291
-#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L
-
-#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier"
-#define NID_sbgp_routerIdentifier 292
-#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L
-
-#define SN_ac_proxying "ac-proxying"
-#define NID_ac_proxying 397
-#define OBJ_ac_proxying OBJ_id_pe,10L
-
-#define SN_sinfo_access "subjectInfoAccess"
-#define LN_sinfo_access "Subject Information Access"
-#define NID_sinfo_access 398
-#define OBJ_sinfo_access OBJ_id_pe,11L
-
-#define SN_proxyCertInfo "proxyCertInfo"
-#define LN_proxyCertInfo "Proxy Certificate Information"
-#define NID_proxyCertInfo 663
-#define OBJ_proxyCertInfo OBJ_id_pe,14L
-
-#define SN_id_qt_cps "id-qt-cps"
-#define LN_id_qt_cps "Policy Qualifier CPS"
-#define NID_id_qt_cps 164
-#define OBJ_id_qt_cps OBJ_id_qt,1L
-
-#define SN_id_qt_unotice "id-qt-unotice"
-#define LN_id_qt_unotice "Policy Qualifier User Notice"
-#define NID_id_qt_unotice 165
-#define OBJ_id_qt_unotice OBJ_id_qt,2L
-
-#define SN_textNotice "textNotice"
-#define NID_textNotice 293
-#define OBJ_textNotice OBJ_id_qt,3L
-
-#define SN_server_auth "serverAuth"
-#define LN_server_auth "TLS Web Server Authentication"
-#define NID_server_auth 129
-#define OBJ_server_auth OBJ_id_kp,1L
-
-#define SN_client_auth "clientAuth"
-#define LN_client_auth "TLS Web Client Authentication"
-#define NID_client_auth 130
-#define OBJ_client_auth OBJ_id_kp,2L
-
-#define SN_code_sign "codeSigning"
-#define LN_code_sign "Code Signing"
-#define NID_code_sign 131
-#define OBJ_code_sign OBJ_id_kp,3L
-
-#define SN_email_protect "emailProtection"
-#define LN_email_protect "E-mail Protection"
-#define NID_email_protect 132
-#define OBJ_email_protect OBJ_id_kp,4L
-
-#define SN_ipsecEndSystem "ipsecEndSystem"
-#define LN_ipsecEndSystem "IPSec End System"
-#define NID_ipsecEndSystem 294
-#define OBJ_ipsecEndSystem OBJ_id_kp,5L
-
-#define SN_ipsecTunnel "ipsecTunnel"
-#define LN_ipsecTunnel "IPSec Tunnel"
-#define NID_ipsecTunnel 295
-#define OBJ_ipsecTunnel OBJ_id_kp,6L
-
-#define SN_ipsecUser "ipsecUser"
-#define LN_ipsecUser "IPSec User"
-#define NID_ipsecUser 296
-#define OBJ_ipsecUser OBJ_id_kp,7L
-
-#define SN_time_stamp "timeStamping"
-#define LN_time_stamp "Time Stamping"
-#define NID_time_stamp 133
-#define OBJ_time_stamp OBJ_id_kp,8L
-
-#define SN_OCSP_sign "OCSPSigning"
-#define LN_OCSP_sign "OCSP Signing"
-#define NID_OCSP_sign 180
-#define OBJ_OCSP_sign OBJ_id_kp,9L
-
-#define SN_dvcs "DVCS"
-#define LN_dvcs "dvcs"
-#define NID_dvcs 297
-#define OBJ_dvcs OBJ_id_kp,10L
-
-#define SN_id_it_caProtEncCert "id-it-caProtEncCert"
-#define NID_id_it_caProtEncCert 298
-#define OBJ_id_it_caProtEncCert OBJ_id_it,1L
-
-#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes"
-#define NID_id_it_signKeyPairTypes 299
-#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L
-
-#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes"
-#define NID_id_it_encKeyPairTypes 300
-#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L
-
-#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg"
-#define NID_id_it_preferredSymmAlg 301
-#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L
-
-#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo"
-#define NID_id_it_caKeyUpdateInfo 302
-#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L
-
-#define SN_id_it_currentCRL "id-it-currentCRL"
-#define NID_id_it_currentCRL 303
-#define OBJ_id_it_currentCRL OBJ_id_it,6L
-
-#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs"
-#define NID_id_it_unsupportedOIDs 304
-#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L
-
-#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest"
-#define NID_id_it_subscriptionRequest 305
-#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L
-
-#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse"
-#define NID_id_it_subscriptionResponse 306
-#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L
-
-#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq"
-#define NID_id_it_keyPairParamReq 307
-#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L
-
-#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep"
-#define NID_id_it_keyPairParamRep 308
-#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L
-
-#define SN_id_it_revPassphrase "id-it-revPassphrase"
-#define NID_id_it_revPassphrase 309
-#define OBJ_id_it_revPassphrase OBJ_id_it,12L
-
-#define SN_id_it_implicitConfirm "id-it-implicitConfirm"
-#define NID_id_it_implicitConfirm 310
-#define OBJ_id_it_implicitConfirm OBJ_id_it,13L
-
-#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime"
-#define NID_id_it_confirmWaitTime 311
-#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L
-
-#define SN_id_it_origPKIMessage "id-it-origPKIMessage"
-#define NID_id_it_origPKIMessage 312
-#define OBJ_id_it_origPKIMessage OBJ_id_it,15L
-
-#define SN_id_it_suppLangTags "id-it-suppLangTags"
-#define NID_id_it_suppLangTags 784
-#define OBJ_id_it_suppLangTags OBJ_id_it,16L
-
-#define SN_id_regCtrl "id-regCtrl"
-#define NID_id_regCtrl 313
-#define OBJ_id_regCtrl OBJ_id_pkip,1L
-
-#define SN_id_regInfo "id-regInfo"
-#define NID_id_regInfo 314
-#define OBJ_id_regInfo OBJ_id_pkip,2L
-
-#define SN_id_regCtrl_regToken "id-regCtrl-regToken"
-#define NID_id_regCtrl_regToken 315
-#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L
-
-#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator"
-#define NID_id_regCtrl_authenticator 316
-#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L
-
-#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo"
-#define NID_id_regCtrl_pkiPublicationInfo 317
-#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L
-
-#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions"
-#define NID_id_regCtrl_pkiArchiveOptions 318
-#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L
-
-#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID"
-#define NID_id_regCtrl_oldCertID 319
-#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L
-
-#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey"
-#define NID_id_regCtrl_protocolEncrKey 320
-#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L
-
-#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs"
-#define NID_id_regInfo_utf8Pairs 321
-#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L
-
-#define SN_id_regInfo_certReq "id-regInfo-certReq"
-#define NID_id_regInfo_certReq 322
-#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L
-
-#define SN_id_alg_des40 "id-alg-des40"
-#define NID_id_alg_des40 323
-#define OBJ_id_alg_des40 OBJ_id_alg,1L
-
-#define SN_id_alg_noSignature "id-alg-noSignature"
-#define NID_id_alg_noSignature 324
-#define OBJ_id_alg_noSignature OBJ_id_alg,2L
-
-#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1"
-#define NID_id_alg_dh_sig_hmac_sha1 325
-#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L
-
-#define SN_id_alg_dh_pop "id-alg-dh-pop"
-#define NID_id_alg_dh_pop 326
-#define OBJ_id_alg_dh_pop OBJ_id_alg,4L
-
-#define SN_id_cmc_statusInfo "id-cmc-statusInfo"
-#define NID_id_cmc_statusInfo 327
-#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L
-
-#define SN_id_cmc_identification "id-cmc-identification"
-#define NID_id_cmc_identification 328
-#define OBJ_id_cmc_identification OBJ_id_cmc,2L
-
-#define SN_id_cmc_identityProof "id-cmc-identityProof"
-#define NID_id_cmc_identityProof 329
-#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L
-
-#define SN_id_cmc_dataReturn "id-cmc-dataReturn"
-#define NID_id_cmc_dataReturn 330
-#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L
-
-#define SN_id_cmc_transactionId "id-cmc-transactionId"
-#define NID_id_cmc_transactionId 331
-#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L
-
-#define SN_id_cmc_senderNonce "id-cmc-senderNonce"
-#define NID_id_cmc_senderNonce 332
-#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L
-
-#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce"
-#define NID_id_cmc_recipientNonce 333
-#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L
-
-#define SN_id_cmc_addExtensions "id-cmc-addExtensions"
-#define NID_id_cmc_addExtensions 334
-#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L
-
-#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP"
-#define NID_id_cmc_encryptedPOP 335
-#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L
-
-#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP"
-#define NID_id_cmc_decryptedPOP 336
-#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L
-
-#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness"
-#define NID_id_cmc_lraPOPWitness 337
-#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L
-
-#define SN_id_cmc_getCert "id-cmc-getCert"
-#define NID_id_cmc_getCert 338
-#define OBJ_id_cmc_getCert OBJ_id_cmc,15L
-
-#define SN_id_cmc_getCRL "id-cmc-getCRL"
-#define NID_id_cmc_getCRL 339
-#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L
-
-#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest"
-#define NID_id_cmc_revokeRequest 340
-#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L
-
-#define SN_id_cmc_regInfo "id-cmc-regInfo"
-#define NID_id_cmc_regInfo 341
-#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L
-
-#define SN_id_cmc_responseInfo "id-cmc-responseInfo"
-#define NID_id_cmc_responseInfo 342
-#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L
-
-#define SN_id_cmc_queryPending "id-cmc-queryPending"
-#define NID_id_cmc_queryPending 343
-#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L
-
-#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom"
-#define NID_id_cmc_popLinkRandom 344
-#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L
-
-#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness"
-#define NID_id_cmc_popLinkWitness 345
-#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L
-
-#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance"
-#define NID_id_cmc_confirmCertAcceptance 346
-#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L
-
-#define SN_id_on_personalData "id-on-personalData"
-#define NID_id_on_personalData 347
-#define OBJ_id_on_personalData OBJ_id_on,1L
-
-#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier"
-#define LN_id_on_permanentIdentifier "Permanent Identifier"
-#define NID_id_on_permanentIdentifier 858
-#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L
-
-#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth"
-#define NID_id_pda_dateOfBirth 348
-#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L
-
-#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth"
-#define NID_id_pda_placeOfBirth 349
-#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L
-
-#define SN_id_pda_gender "id-pda-gender"
-#define NID_id_pda_gender 351
-#define OBJ_id_pda_gender OBJ_id_pda,3L
-
-#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship"
-#define NID_id_pda_countryOfCitizenship 352
-#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L
-
-#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence"
-#define NID_id_pda_countryOfResidence 353
-#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L
-
-#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo"
-#define NID_id_aca_authenticationInfo 354
-#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L
-
-#define SN_id_aca_accessIdentity "id-aca-accessIdentity"
-#define NID_id_aca_accessIdentity 355
-#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L
-
-#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity"
-#define NID_id_aca_chargingIdentity 356
-#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L
-
-#define SN_id_aca_group "id-aca-group"
-#define NID_id_aca_group 357
-#define OBJ_id_aca_group OBJ_id_aca,4L
-
-#define SN_id_aca_role "id-aca-role"
-#define NID_id_aca_role 358
-#define OBJ_id_aca_role OBJ_id_aca,5L
-
-#define SN_id_aca_encAttrs "id-aca-encAttrs"
-#define NID_id_aca_encAttrs 399
-#define OBJ_id_aca_encAttrs OBJ_id_aca,6L
-
-#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1"
-#define NID_id_qcs_pkixQCSyntax_v1 359
-#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L
-
-#define SN_id_cct_crs "id-cct-crs"
-#define NID_id_cct_crs 360
-#define OBJ_id_cct_crs OBJ_id_cct,1L
-
-#define SN_id_cct_PKIData "id-cct-PKIData"
-#define NID_id_cct_PKIData 361
-#define OBJ_id_cct_PKIData OBJ_id_cct,2L
-
-#define SN_id_cct_PKIResponse "id-cct-PKIResponse"
-#define NID_id_cct_PKIResponse 362
-#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L
-
-#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage"
-#define LN_id_ppl_anyLanguage "Any language"
-#define NID_id_ppl_anyLanguage 664
-#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L
-
-#define SN_id_ppl_inheritAll "id-ppl-inheritAll"
-#define LN_id_ppl_inheritAll "Inherit all"
-#define NID_id_ppl_inheritAll 665
-#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L
-
-#define SN_Independent "id-ppl-independent"
-#define LN_Independent "Independent"
-#define NID_Independent 667
-#define OBJ_Independent OBJ_id_ppl,2L
-
-#define SN_ad_OCSP "OCSP"
-#define LN_ad_OCSP "OCSP"
-#define NID_ad_OCSP 178
-#define OBJ_ad_OCSP OBJ_id_ad,1L
-
-#define SN_ad_ca_issuers "caIssuers"
-#define LN_ad_ca_issuers "CA Issuers"
-#define NID_ad_ca_issuers 179
-#define OBJ_ad_ca_issuers OBJ_id_ad,2L
-
-#define SN_ad_timeStamping "ad_timestamping"
-#define LN_ad_timeStamping "AD Time Stamping"
-#define NID_ad_timeStamping 363
-#define OBJ_ad_timeStamping OBJ_id_ad,3L
-
-#define SN_ad_dvcs "AD_DVCS"
-#define LN_ad_dvcs "ad dvcs"
-#define NID_ad_dvcs 364
-#define OBJ_ad_dvcs OBJ_id_ad,4L
-
-#define SN_caRepository "caRepository"
-#define LN_caRepository "CA Repository"
-#define NID_caRepository 785
-#define OBJ_caRepository OBJ_id_ad,5L
-
-#define OBJ_id_pkix_OCSP OBJ_ad_OCSP
-
-#define SN_id_pkix_OCSP_basic "basicOCSPResponse"
-#define LN_id_pkix_OCSP_basic "Basic OCSP Response"
-#define NID_id_pkix_OCSP_basic 365
-#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L
-
-#define SN_id_pkix_OCSP_Nonce "Nonce"
-#define LN_id_pkix_OCSP_Nonce "OCSP Nonce"
-#define NID_id_pkix_OCSP_Nonce 366
-#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L
-
-#define SN_id_pkix_OCSP_CrlID "CrlID"
-#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID"
-#define NID_id_pkix_OCSP_CrlID 367
-#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L
-
-#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses"
-#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses"
-#define NID_id_pkix_OCSP_acceptableResponses 368
-#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L
-
-#define SN_id_pkix_OCSP_noCheck "noCheck"
-#define LN_id_pkix_OCSP_noCheck "OCSP No Check"
-#define NID_id_pkix_OCSP_noCheck 369
-#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L
-
-#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff"
-#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff"
-#define NID_id_pkix_OCSP_archiveCutoff 370
-#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L
-
-#define SN_id_pkix_OCSP_serviceLocator "serviceLocator"
-#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator"
-#define NID_id_pkix_OCSP_serviceLocator 371
-#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L
-
-#define SN_id_pkix_OCSP_extendedStatus "extendedStatus"
-#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status"
-#define NID_id_pkix_OCSP_extendedStatus 372
-#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L
-
-#define SN_id_pkix_OCSP_valid "valid"
-#define NID_id_pkix_OCSP_valid 373
-#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L
-
-#define SN_id_pkix_OCSP_path "path"
-#define NID_id_pkix_OCSP_path 374
-#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L
-
-#define SN_id_pkix_OCSP_trustRoot "trustRoot"
-#define LN_id_pkix_OCSP_trustRoot "Trust Root"
-#define NID_id_pkix_OCSP_trustRoot 375
-#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L
-
-#define SN_algorithm "algorithm"
-#define LN_algorithm "algorithm"
-#define NID_algorithm 376
-#define OBJ_algorithm 1L,3L,14L,3L,2L
-
-#define SN_md5WithRSA "RSA-NP-MD5"
-#define LN_md5WithRSA "md5WithRSA"
-#define NID_md5WithRSA 104
-#define OBJ_md5WithRSA OBJ_algorithm,3L
-
-#define SN_des_ecb "DES-ECB"
-#define LN_des_ecb "des-ecb"
-#define NID_des_ecb 29
-#define OBJ_des_ecb OBJ_algorithm,6L
-
-#define SN_des_cbc "DES-CBC"
-#define LN_des_cbc "des-cbc"
-#define NID_des_cbc 31
-#define OBJ_des_cbc OBJ_algorithm,7L
-
-#define SN_des_ofb64 "DES-OFB"
-#define LN_des_ofb64 "des-ofb"
-#define NID_des_ofb64 45
-#define OBJ_des_ofb64 OBJ_algorithm,8L
-
-#define SN_des_cfb64 "DES-CFB"
-#define LN_des_cfb64 "des-cfb"
-#define NID_des_cfb64 30
-#define OBJ_des_cfb64 OBJ_algorithm,9L
-
-#define SN_rsaSignature "rsaSignature"
-#define NID_rsaSignature 377
-#define OBJ_rsaSignature OBJ_algorithm,11L
-
-#define SN_dsa_2 "DSA-old"
-#define LN_dsa_2 "dsaEncryption-old"
-#define NID_dsa_2 67
-#define OBJ_dsa_2 OBJ_algorithm,12L
-
-#define SN_dsaWithSHA "DSA-SHA"
-#define LN_dsaWithSHA "dsaWithSHA"
-#define NID_dsaWithSHA 66
-#define OBJ_dsaWithSHA OBJ_algorithm,13L
-
-#define SN_shaWithRSAEncryption "RSA-SHA"
-#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
-#define NID_shaWithRSAEncryption 42
-#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L
-
-#define SN_des_ede_ecb "DES-EDE"
-#define LN_des_ede_ecb "des-ede"
-#define NID_des_ede_ecb 32
-#define OBJ_des_ede_ecb OBJ_algorithm,17L
-
-#define SN_des_ede3_ecb "DES-EDE3"
-#define LN_des_ede3_ecb "des-ede3"
-#define NID_des_ede3_ecb 33
-
-#define SN_des_ede_cbc "DES-EDE-CBC"
-#define LN_des_ede_cbc "des-ede-cbc"
-#define NID_des_ede_cbc 43
-
-#define SN_des_ede_cfb64 "DES-EDE-CFB"
-#define LN_des_ede_cfb64 "des-ede-cfb"
-#define NID_des_ede_cfb64 60
-
-#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
-#define LN_des_ede3_cfb64 "des-ede3-cfb"
-#define NID_des_ede3_cfb64 61
-
-#define SN_des_ede_ofb64 "DES-EDE-OFB"
-#define LN_des_ede_ofb64 "des-ede-ofb"
-#define NID_des_ede_ofb64 62
-
-#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
-#define LN_des_ede3_ofb64 "des-ede3-ofb"
-#define NID_des_ede3_ofb64 63
-
-#define SN_desx_cbc "DESX-CBC"
-#define LN_desx_cbc "desx-cbc"
-#define NID_desx_cbc 80
-
-#define SN_sha "SHA"
-#define LN_sha "sha"
-#define NID_sha 41
-#define OBJ_sha OBJ_algorithm,18L
-
-#define SN_sha1 "SHA1"
-#define LN_sha1 "sha1"
-#define NID_sha1 64
-#define OBJ_sha1 OBJ_algorithm,26L
-
-#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
-#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
-#define NID_dsaWithSHA1_2 70
-#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L
-
-#define SN_sha1WithRSA "RSA-SHA1-2"
-#define LN_sha1WithRSA "sha1WithRSA"
-#define NID_sha1WithRSA 115
-#define OBJ_sha1WithRSA OBJ_algorithm,29L
-
-#define SN_ripemd160 "RIPEMD160"
-#define LN_ripemd160 "ripemd160"
-#define NID_ripemd160 117
-#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L
-
-#define SN_ripemd160WithRSA "RSA-RIPEMD160"
-#define LN_ripemd160WithRSA "ripemd160WithRSA"
-#define NID_ripemd160WithRSA 119
-#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
-
-#define SN_sxnet "SXNetID"
-#define LN_sxnet "Strong Extranet ID"
-#define NID_sxnet 143
-#define OBJ_sxnet 1L,3L,101L,1L,4L,1L
-
-#define SN_X500 "X500"
-#define LN_X500 "directory services (X.500)"
-#define NID_X500 11
-#define OBJ_X500 2L,5L
-
-#define SN_X509 "X509"
-#define NID_X509 12
-#define OBJ_X509 OBJ_X500,4L
-
-#define SN_commonName "CN"
-#define LN_commonName "commonName"
-#define NID_commonName 13
-#define OBJ_commonName OBJ_X509,3L
-
-#define SN_surname "SN"
-#define LN_surname "surname"
-#define NID_surname 100
-#define OBJ_surname OBJ_X509,4L
-
-#define LN_serialNumber "serialNumber"
-#define NID_serialNumber 105
-#define OBJ_serialNumber OBJ_X509,5L
-
-#define SN_countryName "C"
-#define LN_countryName "countryName"
-#define NID_countryName 14
-#define OBJ_countryName OBJ_X509,6L
-
-#define SN_localityName "L"
-#define LN_localityName "localityName"
-#define NID_localityName 15
-#define OBJ_localityName OBJ_X509,7L
-
-#define SN_stateOrProvinceName "ST"
-#define LN_stateOrProvinceName "stateOrProvinceName"
-#define NID_stateOrProvinceName 16
-#define OBJ_stateOrProvinceName OBJ_X509,8L
-
-#define SN_streetAddress "street"
-#define LN_streetAddress "streetAddress"
-#define NID_streetAddress 660
-#define OBJ_streetAddress OBJ_X509,9L
-
-#define SN_organizationName "O"
-#define LN_organizationName "organizationName"
-#define NID_organizationName 17
-#define OBJ_organizationName OBJ_X509,10L
-
-#define SN_organizationalUnitName "OU"
-#define LN_organizationalUnitName "organizationalUnitName"
-#define NID_organizationalUnitName 18
-#define OBJ_organizationalUnitName OBJ_X509,11L
-
-#define SN_title "title"
-#define LN_title "title"
-#define NID_title 106
-#define OBJ_title OBJ_X509,12L
-
-#define LN_description "description"
-#define NID_description 107
-#define OBJ_description OBJ_X509,13L
-
-#define LN_searchGuide "searchGuide"
-#define NID_searchGuide 859
-#define OBJ_searchGuide OBJ_X509,14L
-
-#define LN_businessCategory "businessCategory"
-#define NID_businessCategory 860
-#define OBJ_businessCategory OBJ_X509,15L
-
-#define LN_postalAddress "postalAddress"
-#define NID_postalAddress 861
-#define OBJ_postalAddress OBJ_X509,16L
-
-#define LN_postalCode "postalCode"
-#define NID_postalCode 661
-#define OBJ_postalCode OBJ_X509,17L
-
-#define LN_postOfficeBox "postOfficeBox"
-#define NID_postOfficeBox 862
-#define OBJ_postOfficeBox OBJ_X509,18L
-
-#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName"
-#define NID_physicalDeliveryOfficeName 863
-#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L
-
-#define LN_telephoneNumber "telephoneNumber"
-#define NID_telephoneNumber 864
-#define OBJ_telephoneNumber OBJ_X509,20L
-
-#define LN_telexNumber "telexNumber"
-#define NID_telexNumber 865
-#define OBJ_telexNumber OBJ_X509,21L
-
-#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier"
-#define NID_teletexTerminalIdentifier 866
-#define OBJ_teletexTerminalIdentifier OBJ_X509,22L
-
-#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber"
-#define NID_facsimileTelephoneNumber 867
-#define OBJ_facsimileTelephoneNumber OBJ_X509,23L
-
-#define LN_x121Address "x121Address"
-#define NID_x121Address 868
-#define OBJ_x121Address OBJ_X509,24L
-
-#define LN_internationaliSDNNumber "internationaliSDNNumber"
-#define NID_internationaliSDNNumber 869
-#define OBJ_internationaliSDNNumber OBJ_X509,25L
-
-#define LN_registeredAddress "registeredAddress"
-#define NID_registeredAddress 870
-#define OBJ_registeredAddress OBJ_X509,26L
-
-#define LN_destinationIndicator "destinationIndicator"
-#define NID_destinationIndicator 871
-#define OBJ_destinationIndicator OBJ_X509,27L
-
-#define LN_preferredDeliveryMethod "preferredDeliveryMethod"
-#define NID_preferredDeliveryMethod 872
-#define OBJ_preferredDeliveryMethod OBJ_X509,28L
-
-#define LN_presentationAddress "presentationAddress"
-#define NID_presentationAddress 873
-#define OBJ_presentationAddress OBJ_X509,29L
-
-#define LN_supportedApplicationContext "supportedApplicationContext"
-#define NID_supportedApplicationContext 874
-#define OBJ_supportedApplicationContext OBJ_X509,30L
-
-#define SN_member "member"
-#define NID_member 875
-#define OBJ_member OBJ_X509,31L
-
-#define SN_owner "owner"
-#define NID_owner 876
-#define OBJ_owner OBJ_X509,32L
-
-#define LN_roleOccupant "roleOccupant"
-#define NID_roleOccupant 877
-#define OBJ_roleOccupant OBJ_X509,33L
-
-#define SN_seeAlso "seeAlso"
-#define NID_seeAlso 878
-#define OBJ_seeAlso OBJ_X509,34L
-
-#define LN_userPassword "userPassword"
-#define NID_userPassword 879
-#define OBJ_userPassword OBJ_X509,35L
-
-#define LN_userCertificate "userCertificate"
-#define NID_userCertificate 880
-#define OBJ_userCertificate OBJ_X509,36L
-
-#define LN_cACertificate "cACertificate"
-#define NID_cACertificate 881
-#define OBJ_cACertificate OBJ_X509,37L
-
-#define LN_authorityRevocationList "authorityRevocationList"
-#define NID_authorityRevocationList 882
-#define OBJ_authorityRevocationList OBJ_X509,38L
-
-#define LN_certificateRevocationList "certificateRevocationList"
-#define NID_certificateRevocationList 883
-#define OBJ_certificateRevocationList OBJ_X509,39L
-
-#define LN_crossCertificatePair "crossCertificatePair"
-#define NID_crossCertificatePair 884
-#define OBJ_crossCertificatePair OBJ_X509,40L
-
-#define SN_name "name"
-#define LN_name "name"
-#define NID_name 173
-#define OBJ_name OBJ_X509,41L
-
-#define SN_givenName "GN"
-#define LN_givenName "givenName"
-#define NID_givenName 99
-#define OBJ_givenName OBJ_X509,42L
-
-#define SN_initials "initials"
-#define LN_initials "initials"
-#define NID_initials 101
-#define OBJ_initials OBJ_X509,43L
-
-#define LN_generationQualifier "generationQualifier"
-#define NID_generationQualifier 509
-#define OBJ_generationQualifier OBJ_X509,44L
-
-#define LN_x500UniqueIdentifier "x500UniqueIdentifier"
-#define NID_x500UniqueIdentifier 503
-#define OBJ_x500UniqueIdentifier OBJ_X509,45L
-
-#define SN_dnQualifier "dnQualifier"
-#define LN_dnQualifier "dnQualifier"
-#define NID_dnQualifier 174
-#define OBJ_dnQualifier OBJ_X509,46L
-
-#define LN_enhancedSearchGuide "enhancedSearchGuide"
-#define NID_enhancedSearchGuide 885
-#define OBJ_enhancedSearchGuide OBJ_X509,47L
-
-#define LN_protocolInformation "protocolInformation"
-#define NID_protocolInformation 886
-#define OBJ_protocolInformation OBJ_X509,48L
-
-#define LN_distinguishedName "distinguishedName"
-#define NID_distinguishedName 887
-#define OBJ_distinguishedName OBJ_X509,49L
-
-#define LN_uniqueMember "uniqueMember"
-#define NID_uniqueMember 888
-#define OBJ_uniqueMember OBJ_X509,50L
-
-#define LN_houseIdentifier "houseIdentifier"
-#define NID_houseIdentifier 889
-#define OBJ_houseIdentifier OBJ_X509,51L
-
-#define LN_supportedAlgorithms "supportedAlgorithms"
-#define NID_supportedAlgorithms 890
-#define OBJ_supportedAlgorithms OBJ_X509,52L
-
-#define LN_deltaRevocationList "deltaRevocationList"
-#define NID_deltaRevocationList 891
-#define OBJ_deltaRevocationList OBJ_X509,53L
-
-#define SN_dmdName "dmdName"
-#define NID_dmdName 892
-#define OBJ_dmdName OBJ_X509,54L
-
-#define LN_pseudonym "pseudonym"
-#define NID_pseudonym 510
-#define OBJ_pseudonym OBJ_X509,65L
-
-#define SN_role "role"
-#define LN_role "role"
-#define NID_role 400
-#define OBJ_role OBJ_X509,72L
-
-#define SN_X500algorithms "X500algorithms"
-#define LN_X500algorithms "directory services - algorithms"
-#define NID_X500algorithms 378
-#define OBJ_X500algorithms OBJ_X500,8L
-
-#define SN_rsa "RSA"
-#define LN_rsa "rsa"
-#define NID_rsa 19
-#define OBJ_rsa OBJ_X500algorithms,1L,1L
-
-#define SN_mdc2WithRSA "RSA-MDC2"
-#define LN_mdc2WithRSA "mdc2WithRSA"
-#define NID_mdc2WithRSA 96
-#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L
-
-#define SN_mdc2 "MDC2"
-#define LN_mdc2 "mdc2"
-#define NID_mdc2 95
-#define OBJ_mdc2 OBJ_X500algorithms,3L,101L
-
-#define SN_id_ce "id-ce"
-#define NID_id_ce 81
-#define OBJ_id_ce OBJ_X500,29L
-
-#define SN_subject_directory_attributes "subjectDirectoryAttributes"
-#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes"
-#define NID_subject_directory_attributes 769
-#define OBJ_subject_directory_attributes OBJ_id_ce,9L
-
-#define SN_subject_key_identifier "subjectKeyIdentifier"
-#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
-#define NID_subject_key_identifier 82
-#define OBJ_subject_key_identifier OBJ_id_ce,14L
-
-#define SN_key_usage "keyUsage"
-#define LN_key_usage "X509v3 Key Usage"
-#define NID_key_usage 83
-#define OBJ_key_usage OBJ_id_ce,15L
-
-#define SN_private_key_usage_period "privateKeyUsagePeriod"
-#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
-#define NID_private_key_usage_period 84
-#define OBJ_private_key_usage_period OBJ_id_ce,16L
-
-#define SN_subject_alt_name "subjectAltName"
-#define LN_subject_alt_name "X509v3 Subject Alternative Name"
-#define NID_subject_alt_name 85
-#define OBJ_subject_alt_name OBJ_id_ce,17L
-
-#define SN_issuer_alt_name "issuerAltName"
-#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
-#define NID_issuer_alt_name 86
-#define OBJ_issuer_alt_name OBJ_id_ce,18L
-
-#define SN_basic_constraints "basicConstraints"
-#define LN_basic_constraints "X509v3 Basic Constraints"
-#define NID_basic_constraints 87
-#define OBJ_basic_constraints OBJ_id_ce,19L
-
-#define SN_crl_number "crlNumber"
-#define LN_crl_number "X509v3 CRL Number"
-#define NID_crl_number 88
-#define OBJ_crl_number OBJ_id_ce,20L
-
-#define SN_crl_reason "CRLReason"
-#define LN_crl_reason "X509v3 CRL Reason Code"
-#define NID_crl_reason 141
-#define OBJ_crl_reason OBJ_id_ce,21L
-
-#define SN_invalidity_date "invalidityDate"
-#define LN_invalidity_date "Invalidity Date"
-#define NID_invalidity_date 142
-#define OBJ_invalidity_date OBJ_id_ce,24L
-
-#define SN_delta_crl "deltaCRL"
-#define LN_delta_crl "X509v3 Delta CRL Indicator"
-#define NID_delta_crl 140
-#define OBJ_delta_crl OBJ_id_ce,27L
-
-#define SN_issuing_distribution_point "issuingDistributionPoint"
-#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point"
-#define NID_issuing_distribution_point 770
-#define OBJ_issuing_distribution_point OBJ_id_ce,28L
-
-#define SN_certificate_issuer "certificateIssuer"
-#define LN_certificate_issuer "X509v3 Certificate Issuer"
-#define NID_certificate_issuer 771
-#define OBJ_certificate_issuer OBJ_id_ce,29L
-
-#define SN_name_constraints "nameConstraints"
-#define LN_name_constraints "X509v3 Name Constraints"
-#define NID_name_constraints 666
-#define OBJ_name_constraints OBJ_id_ce,30L
-
-#define SN_crl_distribution_points "crlDistributionPoints"
-#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
-#define NID_crl_distribution_points 103
-#define OBJ_crl_distribution_points OBJ_id_ce,31L
-
-#define SN_certificate_policies "certificatePolicies"
-#define LN_certificate_policies "X509v3 Certificate Policies"
-#define NID_certificate_policies 89
-#define OBJ_certificate_policies OBJ_id_ce,32L
-
-#define SN_any_policy "anyPolicy"
-#define LN_any_policy "X509v3 Any Policy"
-#define NID_any_policy 746
-#define OBJ_any_policy OBJ_certificate_policies,0L
-
-#define SN_policy_mappings "policyMappings"
-#define LN_policy_mappings "X509v3 Policy Mappings"
-#define NID_policy_mappings 747
-#define OBJ_policy_mappings OBJ_id_ce,33L
-
-#define SN_authority_key_identifier "authorityKeyIdentifier"
-#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
-#define NID_authority_key_identifier 90
-#define OBJ_authority_key_identifier OBJ_id_ce,35L
-
-#define SN_policy_constraints "policyConstraints"
-#define LN_policy_constraints "X509v3 Policy Constraints"
-#define NID_policy_constraints 401
-#define OBJ_policy_constraints OBJ_id_ce,36L
-
-#define SN_ext_key_usage "extendedKeyUsage"
-#define LN_ext_key_usage "X509v3 Extended Key Usage"
-#define NID_ext_key_usage 126
-#define OBJ_ext_key_usage OBJ_id_ce,37L
-
-#define SN_freshest_crl "freshestCRL"
-#define LN_freshest_crl "X509v3 Freshest CRL"
-#define NID_freshest_crl 857
-#define OBJ_freshest_crl OBJ_id_ce,46L
-
-#define SN_inhibit_any_policy "inhibitAnyPolicy"
-#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy"
-#define NID_inhibit_any_policy 748
-#define OBJ_inhibit_any_policy OBJ_id_ce,54L
-
-#define SN_target_information "targetInformation"
-#define LN_target_information "X509v3 AC Targeting"
-#define NID_target_information 402
-#define OBJ_target_information OBJ_id_ce,55L
-
-#define SN_no_rev_avail "noRevAvail"
-#define LN_no_rev_avail "X509v3 No Revocation Available"
-#define NID_no_rev_avail 403
-#define OBJ_no_rev_avail OBJ_id_ce,56L
-
-#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage"
-#define LN_anyExtendedKeyUsage "Any Extended Key Usage"
-#define NID_anyExtendedKeyUsage 910
-#define OBJ_anyExtendedKeyUsage OBJ_ext_key_usage,0L
-
-#define SN_netscape "Netscape"
-#define LN_netscape "Netscape Communications Corp."
-#define NID_netscape 57
-#define OBJ_netscape 2L,16L,840L,1L,113730L
-
-#define SN_netscape_cert_extension "nsCertExt"
-#define LN_netscape_cert_extension "Netscape Certificate Extension"
-#define NID_netscape_cert_extension 58
-#define OBJ_netscape_cert_extension OBJ_netscape,1L
-
-#define SN_netscape_data_type "nsDataType"
-#define LN_netscape_data_type "Netscape Data Type"
-#define NID_netscape_data_type 59
-#define OBJ_netscape_data_type OBJ_netscape,2L
-
-#define SN_netscape_cert_type "nsCertType"
-#define LN_netscape_cert_type "Netscape Cert Type"
-#define NID_netscape_cert_type 71
-#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L
-
-#define SN_netscape_base_url "nsBaseUrl"
-#define LN_netscape_base_url "Netscape Base Url"
-#define NID_netscape_base_url 72
-#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L
-
-#define SN_netscape_revocation_url "nsRevocationUrl"
-#define LN_netscape_revocation_url "Netscape Revocation Url"
-#define NID_netscape_revocation_url 73
-#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L
-
-#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
-#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
-#define NID_netscape_ca_revocation_url 74
-#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L
-
-#define SN_netscape_renewal_url "nsRenewalUrl"
-#define LN_netscape_renewal_url "Netscape Renewal Url"
-#define NID_netscape_renewal_url 75
-#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L
-
-#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
-#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
-#define NID_netscape_ca_policy_url 76
-#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L
-
-#define SN_netscape_ssl_server_name "nsSslServerName"
-#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
-#define NID_netscape_ssl_server_name 77
-#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L
-
-#define SN_netscape_comment "nsComment"
-#define LN_netscape_comment "Netscape Comment"
-#define NID_netscape_comment 78
-#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L
-
-#define SN_netscape_cert_sequence "nsCertSequence"
-#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
-#define NID_netscape_cert_sequence 79
-#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L
-
-#define SN_ns_sgc "nsSGC"
-#define LN_ns_sgc "Netscape Server Gated Crypto"
-#define NID_ns_sgc 139
-#define OBJ_ns_sgc OBJ_netscape,4L,1L
-
-#define SN_org "ORG"
-#define LN_org "org"
-#define NID_org 379
-#define OBJ_org OBJ_iso,3L
-
-#define SN_dod "DOD"
-#define LN_dod "dod"
-#define NID_dod 380
-#define OBJ_dod OBJ_org,6L
-
-#define SN_iana "IANA"
-#define LN_iana "iana"
-#define NID_iana 381
-#define OBJ_iana OBJ_dod,1L
-
-#define OBJ_internet OBJ_iana
-
-#define SN_Directory "directory"
-#define LN_Directory "Directory"
-#define NID_Directory 382
-#define OBJ_Directory OBJ_internet,1L
-
-#define SN_Management "mgmt"
-#define LN_Management "Management"
-#define NID_Management 383
-#define OBJ_Management OBJ_internet,2L
-
-#define SN_Experimental "experimental"
-#define LN_Experimental "Experimental"
-#define NID_Experimental 384
-#define OBJ_Experimental OBJ_internet,3L
-
-#define SN_Private "private"
-#define LN_Private "Private"
-#define NID_Private 385
-#define OBJ_Private OBJ_internet,4L
-
-#define SN_Security "security"
-#define LN_Security "Security"
-#define NID_Security 386
-#define OBJ_Security OBJ_internet,5L
-
-#define SN_SNMPv2 "snmpv2"
-#define LN_SNMPv2 "SNMPv2"
-#define NID_SNMPv2 387
-#define OBJ_SNMPv2 OBJ_internet,6L
-
-#define LN_Mail "Mail"
-#define NID_Mail 388
-#define OBJ_Mail OBJ_internet,7L
-
-#define SN_Enterprises "enterprises"
-#define LN_Enterprises "Enterprises"
-#define NID_Enterprises 389
-#define OBJ_Enterprises OBJ_Private,1L
-
-#define SN_dcObject "dcobject"
-#define LN_dcObject "dcObject"
-#define NID_dcObject 390
-#define OBJ_dcObject OBJ_Enterprises,1466L,344L
-
-#define SN_mime_mhs "mime-mhs"
-#define LN_mime_mhs "MIME MHS"
-#define NID_mime_mhs 504
-#define OBJ_mime_mhs OBJ_Mail,1L
-
-#define SN_mime_mhs_headings "mime-mhs-headings"
-#define LN_mime_mhs_headings "mime-mhs-headings"
-#define NID_mime_mhs_headings 505
-#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L
-
-#define SN_mime_mhs_bodies "mime-mhs-bodies"
-#define LN_mime_mhs_bodies "mime-mhs-bodies"
-#define NID_mime_mhs_bodies 506
-#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L
-
-#define SN_id_hex_partial_message "id-hex-partial-message"
-#define LN_id_hex_partial_message "id-hex-partial-message"
-#define NID_id_hex_partial_message 507
-#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L
-
-#define SN_id_hex_multipart_message "id-hex-multipart-message"
-#define LN_id_hex_multipart_message "id-hex-multipart-message"
-#define NID_id_hex_multipart_message 508
-#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L
-
-#define SN_zlib_compression "ZLIB"
-#define LN_zlib_compression "zlib compression"
-#define NID_zlib_compression 125
-#define OBJ_zlib_compression OBJ_id_smime_alg,8L
-
-#define OBJ_csor 2L,16L,840L,1L,101L,3L
-
-#define OBJ_nistAlgorithms OBJ_csor,4L
-
-#define OBJ_aes OBJ_nistAlgorithms,1L
-
-#define SN_aes_128_ecb "AES-128-ECB"
-#define LN_aes_128_ecb "aes-128-ecb"
-#define NID_aes_128_ecb 418
-#define OBJ_aes_128_ecb OBJ_aes,1L
-
-#define SN_aes_128_cbc "AES-128-CBC"
-#define LN_aes_128_cbc "aes-128-cbc"
-#define NID_aes_128_cbc 419
-#define OBJ_aes_128_cbc OBJ_aes,2L
-
-#define SN_aes_128_ofb128 "AES-128-OFB"
-#define LN_aes_128_ofb128 "aes-128-ofb"
-#define NID_aes_128_ofb128 420
-#define OBJ_aes_128_ofb128 OBJ_aes,3L
-
-#define SN_aes_128_cfb128 "AES-128-CFB"
-#define LN_aes_128_cfb128 "aes-128-cfb"
-#define NID_aes_128_cfb128 421
-#define OBJ_aes_128_cfb128 OBJ_aes,4L
-
-#define SN_id_aes128_wrap "id-aes128-wrap"
-#define NID_id_aes128_wrap 788
-#define OBJ_id_aes128_wrap OBJ_aes,5L
-
-#define SN_aes_128_gcm "id-aes128-GCM"
-#define LN_aes_128_gcm "aes-128-gcm"
-#define NID_aes_128_gcm 895
-#define OBJ_aes_128_gcm OBJ_aes,6L
-
-#define SN_aes_128_ccm "id-aes128-CCM"
-#define LN_aes_128_ccm "aes-128-ccm"
-#define NID_aes_128_ccm 896
-#define OBJ_aes_128_ccm OBJ_aes,7L
-
-#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad"
-#define NID_id_aes128_wrap_pad 897
-#define OBJ_id_aes128_wrap_pad OBJ_aes,8L
-
-#define SN_aes_192_ecb "AES-192-ECB"
-#define LN_aes_192_ecb "aes-192-ecb"
-#define NID_aes_192_ecb 422
-#define OBJ_aes_192_ecb OBJ_aes,21L
-
-#define SN_aes_192_cbc "AES-192-CBC"
-#define LN_aes_192_cbc "aes-192-cbc"
-#define NID_aes_192_cbc 423
-#define OBJ_aes_192_cbc OBJ_aes,22L
-
-#define SN_aes_192_ofb128 "AES-192-OFB"
-#define LN_aes_192_ofb128 "aes-192-ofb"
-#define NID_aes_192_ofb128 424
-#define OBJ_aes_192_ofb128 OBJ_aes,23L
-
-#define SN_aes_192_cfb128 "AES-192-CFB"
-#define LN_aes_192_cfb128 "aes-192-cfb"
-#define NID_aes_192_cfb128 425
-#define OBJ_aes_192_cfb128 OBJ_aes,24L
-
-#define SN_id_aes192_wrap "id-aes192-wrap"
-#define NID_id_aes192_wrap 789
-#define OBJ_id_aes192_wrap OBJ_aes,25L
-
-#define SN_aes_192_gcm "id-aes192-GCM"
-#define LN_aes_192_gcm "aes-192-gcm"
-#define NID_aes_192_gcm 898
-#define OBJ_aes_192_gcm OBJ_aes,26L
-
-#define SN_aes_192_ccm "id-aes192-CCM"
-#define LN_aes_192_ccm "aes-192-ccm"
-#define NID_aes_192_ccm 899
-#define OBJ_aes_192_ccm OBJ_aes,27L
-
-#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad"
-#define NID_id_aes192_wrap_pad 900
-#define OBJ_id_aes192_wrap_pad OBJ_aes,28L
-
-#define SN_aes_256_ecb "AES-256-ECB"
-#define LN_aes_256_ecb "aes-256-ecb"
-#define NID_aes_256_ecb 426
-#define OBJ_aes_256_ecb OBJ_aes,41L
-
-#define SN_aes_256_cbc "AES-256-CBC"
-#define LN_aes_256_cbc "aes-256-cbc"
-#define NID_aes_256_cbc 427
-#define OBJ_aes_256_cbc OBJ_aes,42L
-
-#define SN_aes_256_ofb128 "AES-256-OFB"
-#define LN_aes_256_ofb128 "aes-256-ofb"
-#define NID_aes_256_ofb128 428
-#define OBJ_aes_256_ofb128 OBJ_aes,43L
-
-#define SN_aes_256_cfb128 "AES-256-CFB"
-#define LN_aes_256_cfb128 "aes-256-cfb"
-#define NID_aes_256_cfb128 429
-#define OBJ_aes_256_cfb128 OBJ_aes,44L
-
-#define SN_id_aes256_wrap "id-aes256-wrap"
-#define NID_id_aes256_wrap 790
-#define OBJ_id_aes256_wrap OBJ_aes,45L
-
-#define SN_aes_256_gcm "id-aes256-GCM"
-#define LN_aes_256_gcm "aes-256-gcm"
-#define NID_aes_256_gcm 901
-#define OBJ_aes_256_gcm OBJ_aes,46L
-
-#define SN_aes_256_ccm "id-aes256-CCM"
-#define LN_aes_256_ccm "aes-256-ccm"
-#define NID_aes_256_ccm 902
-#define OBJ_aes_256_ccm OBJ_aes,47L
-
-#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad"
-#define NID_id_aes256_wrap_pad 903
-#define OBJ_id_aes256_wrap_pad OBJ_aes,48L
-
-#define SN_aes_128_cfb1 "AES-128-CFB1"
-#define LN_aes_128_cfb1 "aes-128-cfb1"
-#define NID_aes_128_cfb1 650
-
-#define SN_aes_192_cfb1 "AES-192-CFB1"
-#define LN_aes_192_cfb1 "aes-192-cfb1"
-#define NID_aes_192_cfb1 651
-
-#define SN_aes_256_cfb1 "AES-256-CFB1"
-#define LN_aes_256_cfb1 "aes-256-cfb1"
-#define NID_aes_256_cfb1 652
-
-#define SN_aes_128_cfb8 "AES-128-CFB8"
-#define LN_aes_128_cfb8 "aes-128-cfb8"
-#define NID_aes_128_cfb8 653
-
-#define SN_aes_192_cfb8 "AES-192-CFB8"
-#define LN_aes_192_cfb8 "aes-192-cfb8"
-#define NID_aes_192_cfb8 654
-
-#define SN_aes_256_cfb8 "AES-256-CFB8"
-#define LN_aes_256_cfb8 "aes-256-cfb8"
-#define NID_aes_256_cfb8 655
-
-#define SN_aes_128_ctr "AES-128-CTR"
-#define LN_aes_128_ctr "aes-128-ctr"
-#define NID_aes_128_ctr 904
-
-#define SN_aes_192_ctr "AES-192-CTR"
-#define LN_aes_192_ctr "aes-192-ctr"
-#define NID_aes_192_ctr 905
-
-#define SN_aes_256_ctr "AES-256-CTR"
-#define LN_aes_256_ctr "aes-256-ctr"
-#define NID_aes_256_ctr 906
-
-#define SN_aes_128_xts "AES-128-XTS"
-#define LN_aes_128_xts "aes-128-xts"
-#define NID_aes_128_xts 913
-
-#define SN_aes_256_xts "AES-256-XTS"
-#define LN_aes_256_xts "aes-256-xts"
-#define NID_aes_256_xts 914
-
-#define SN_des_cfb1 "DES-CFB1"
-#define LN_des_cfb1 "des-cfb1"
-#define NID_des_cfb1 656
-
-#define SN_des_cfb8 "DES-CFB8"
-#define LN_des_cfb8 "des-cfb8"
-#define NID_des_cfb8 657
-
-#define SN_des_ede3_cfb1 "DES-EDE3-CFB1"
-#define LN_des_ede3_cfb1 "des-ede3-cfb1"
-#define NID_des_ede3_cfb1 658
-
-#define SN_des_ede3_cfb8 "DES-EDE3-CFB8"
-#define LN_des_ede3_cfb8 "des-ede3-cfb8"
-#define NID_des_ede3_cfb8 659
-
-#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L
-
-#define SN_sha256 "SHA256"
-#define LN_sha256 "sha256"
-#define NID_sha256 672
-#define OBJ_sha256 OBJ_nist_hashalgs,1L
-
-#define SN_sha384 "SHA384"
-#define LN_sha384 "sha384"
-#define NID_sha384 673
-#define OBJ_sha384 OBJ_nist_hashalgs,2L
-
-#define SN_sha512 "SHA512"
-#define LN_sha512 "sha512"
-#define NID_sha512 674
-#define OBJ_sha512 OBJ_nist_hashalgs,3L
-
-#define SN_sha224 "SHA224"
-#define LN_sha224 "sha224"
-#define NID_sha224 675
-#define OBJ_sha224 OBJ_nist_hashalgs,4L
-
-#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L
-
-#define SN_dsa_with_SHA224 "dsa_with_SHA224"
-#define NID_dsa_with_SHA224 802
-#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L
-
-#define SN_dsa_with_SHA256 "dsa_with_SHA256"
-#define NID_dsa_with_SHA256 803
-#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L
-
-#define SN_hold_instruction_code "holdInstructionCode"
-#define LN_hold_instruction_code "Hold Instruction Code"
-#define NID_hold_instruction_code 430
-#define OBJ_hold_instruction_code OBJ_id_ce,23L
-
-#define OBJ_holdInstruction OBJ_X9_57,2L
-
-#define SN_hold_instruction_none "holdInstructionNone"
-#define LN_hold_instruction_none "Hold Instruction None"
-#define NID_hold_instruction_none 431
-#define OBJ_hold_instruction_none OBJ_holdInstruction,1L
-
-#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer"
-#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer"
-#define NID_hold_instruction_call_issuer 432
-#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L
-
-#define SN_hold_instruction_reject "holdInstructionReject"
-#define LN_hold_instruction_reject "Hold Instruction Reject"
-#define NID_hold_instruction_reject 433
-#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L
-
-#define SN_data "data"
-#define NID_data 434
-#define OBJ_data OBJ_itu_t,9L
-
-#define SN_pss "pss"
-#define NID_pss 435
-#define OBJ_pss OBJ_data,2342L
-
-#define SN_ucl "ucl"
-#define NID_ucl 436
-#define OBJ_ucl OBJ_pss,19200300L
-
-#define SN_pilot "pilot"
-#define NID_pilot 437
-#define OBJ_pilot OBJ_ucl,100L
-
-#define LN_pilotAttributeType "pilotAttributeType"
-#define NID_pilotAttributeType 438
-#define OBJ_pilotAttributeType OBJ_pilot,1L
-
-#define LN_pilotAttributeSyntax "pilotAttributeSyntax"
-#define NID_pilotAttributeSyntax 439
-#define OBJ_pilotAttributeSyntax OBJ_pilot,3L
-
-#define LN_pilotObjectClass "pilotObjectClass"
-#define NID_pilotObjectClass 440
-#define OBJ_pilotObjectClass OBJ_pilot,4L
-
-#define LN_pilotGroups "pilotGroups"
-#define NID_pilotGroups 441
-#define OBJ_pilotGroups OBJ_pilot,10L
-
-#define LN_iA5StringSyntax "iA5StringSyntax"
-#define NID_iA5StringSyntax 442
-#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L
-
-#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax"
-#define NID_caseIgnoreIA5StringSyntax 443
-#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L
-
-#define LN_pilotObject "pilotObject"
-#define NID_pilotObject 444
-#define OBJ_pilotObject OBJ_pilotObjectClass,3L
-
-#define LN_pilotPerson "pilotPerson"
-#define NID_pilotPerson 445
-#define OBJ_pilotPerson OBJ_pilotObjectClass,4L
-
-#define SN_account "account"
-#define NID_account 446
-#define OBJ_account OBJ_pilotObjectClass,5L
-
-#define SN_document "document"
-#define NID_document 447
-#define OBJ_document OBJ_pilotObjectClass,6L
-
-#define SN_room "room"
-#define NID_room 448
-#define OBJ_room OBJ_pilotObjectClass,7L
-
-#define LN_documentSeries "documentSeries"
-#define NID_documentSeries 449
-#define OBJ_documentSeries OBJ_pilotObjectClass,9L
-
-#define SN_Domain "domain"
-#define LN_Domain "Domain"
-#define NID_Domain 392
-#define OBJ_Domain OBJ_pilotObjectClass,13L
-
-#define LN_rFC822localPart "rFC822localPart"
-#define NID_rFC822localPart 450
-#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L
-
-#define LN_dNSDomain "dNSDomain"
-#define NID_dNSDomain 451
-#define OBJ_dNSDomain OBJ_pilotObjectClass,15L
-
-#define LN_domainRelatedObject "domainRelatedObject"
-#define NID_domainRelatedObject 452
-#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L
-
-#define LN_friendlyCountry "friendlyCountry"
-#define NID_friendlyCountry 453
-#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L
-
-#define LN_simpleSecurityObject "simpleSecurityObject"
-#define NID_simpleSecurityObject 454
-#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L
-
-#define LN_pilotOrganization "pilotOrganization"
-#define NID_pilotOrganization 455
-#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L
-
-#define LN_pilotDSA "pilotDSA"
-#define NID_pilotDSA 456
-#define OBJ_pilotDSA OBJ_pilotObjectClass,21L
-
-#define LN_qualityLabelledData "qualityLabelledData"
-#define NID_qualityLabelledData 457
-#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L
-
-#define SN_userId "UID"
-#define LN_userId "userId"
-#define NID_userId 458
-#define OBJ_userId OBJ_pilotAttributeType,1L
-
-#define LN_textEncodedORAddress "textEncodedORAddress"
-#define NID_textEncodedORAddress 459
-#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L
-
-#define SN_rfc822Mailbox "mail"
-#define LN_rfc822Mailbox "rfc822Mailbox"
-#define NID_rfc822Mailbox 460
-#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L
-
-#define SN_info "info"
-#define NID_info 461
-#define OBJ_info OBJ_pilotAttributeType,4L
-
-#define LN_favouriteDrink "favouriteDrink"
-#define NID_favouriteDrink 462
-#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L
-
-#define LN_roomNumber "roomNumber"
-#define NID_roomNumber 463
-#define OBJ_roomNumber OBJ_pilotAttributeType,6L
-
-#define SN_photo "photo"
-#define NID_photo 464
-#define OBJ_photo OBJ_pilotAttributeType,7L
-
-#define LN_userClass "userClass"
-#define NID_userClass 465
-#define OBJ_userClass OBJ_pilotAttributeType,8L
-
-#define SN_host "host"
-#define NID_host 466
-#define OBJ_host OBJ_pilotAttributeType,9L
-
-#define SN_manager "manager"
-#define NID_manager 467
-#define OBJ_manager OBJ_pilotAttributeType,10L
-
-#define LN_documentIdentifier "documentIdentifier"
-#define NID_documentIdentifier 468
-#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L
-
-#define LN_documentTitle "documentTitle"
-#define NID_documentTitle 469
-#define OBJ_documentTitle OBJ_pilotAttributeType,12L
-
-#define LN_documentVersion "documentVersion"
-#define NID_documentVersion 470
-#define OBJ_documentVersion OBJ_pilotAttributeType,13L
-
-#define LN_documentAuthor "documentAuthor"
-#define NID_documentAuthor 471
-#define OBJ_documentAuthor OBJ_pilotAttributeType,14L
-
-#define LN_documentLocation "documentLocation"
-#define NID_documentLocation 472
-#define OBJ_documentLocation OBJ_pilotAttributeType,15L
-
-#define LN_homeTelephoneNumber "homeTelephoneNumber"
-#define NID_homeTelephoneNumber 473
-#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L
-
-#define SN_secretary "secretary"
-#define NID_secretary 474
-#define OBJ_secretary OBJ_pilotAttributeType,21L
-
-#define LN_otherMailbox "otherMailbox"
-#define NID_otherMailbox 475
-#define OBJ_otherMailbox OBJ_pilotAttributeType,22L
-
-#define LN_lastModifiedTime "lastModifiedTime"
-#define NID_lastModifiedTime 476
-#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L
-
-#define LN_lastModifiedBy "lastModifiedBy"
-#define NID_lastModifiedBy 477
-#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L
-
-#define SN_domainComponent "DC"
-#define LN_domainComponent "domainComponent"
-#define NID_domainComponent 391
-#define OBJ_domainComponent OBJ_pilotAttributeType,25L
-
-#define LN_aRecord "aRecord"
-#define NID_aRecord 478
-#define OBJ_aRecord OBJ_pilotAttributeType,26L
-
-#define LN_pilotAttributeType27 "pilotAttributeType27"
-#define NID_pilotAttributeType27 479
-#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L
-
-#define LN_mXRecord "mXRecord"
-#define NID_mXRecord 480
-#define OBJ_mXRecord OBJ_pilotAttributeType,28L
-
-#define LN_nSRecord "nSRecord"
-#define NID_nSRecord 481
-#define OBJ_nSRecord OBJ_pilotAttributeType,29L
-
-#define LN_sOARecord "sOARecord"
-#define NID_sOARecord 482
-#define OBJ_sOARecord OBJ_pilotAttributeType,30L
-
-#define LN_cNAMERecord "cNAMERecord"
-#define NID_cNAMERecord 483
-#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L
-
-#define LN_associatedDomain "associatedDomain"
-#define NID_associatedDomain 484
-#define OBJ_associatedDomain OBJ_pilotAttributeType,37L
-
-#define LN_associatedName "associatedName"
-#define NID_associatedName 485
-#define OBJ_associatedName OBJ_pilotAttributeType,38L
-
-#define LN_homePostalAddress "homePostalAddress"
-#define NID_homePostalAddress 486
-#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L
-
-#define LN_personalTitle "personalTitle"
-#define NID_personalTitle 487
-#define OBJ_personalTitle OBJ_pilotAttributeType,40L
-
-#define LN_mobileTelephoneNumber "mobileTelephoneNumber"
-#define NID_mobileTelephoneNumber 488
-#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L
-
-#define LN_pagerTelephoneNumber "pagerTelephoneNumber"
-#define NID_pagerTelephoneNumber 489
-#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L
-
-#define LN_friendlyCountryName "friendlyCountryName"
-#define NID_friendlyCountryName 490
-#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L
-
-#define LN_organizationalStatus "organizationalStatus"
-#define NID_organizationalStatus 491
-#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L
-
-#define LN_janetMailbox "janetMailbox"
-#define NID_janetMailbox 492
-#define OBJ_janetMailbox OBJ_pilotAttributeType,46L
-
-#define LN_mailPreferenceOption "mailPreferenceOption"
-#define NID_mailPreferenceOption 493
-#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L
-
-#define LN_buildingName "buildingName"
-#define NID_buildingName 494
-#define OBJ_buildingName OBJ_pilotAttributeType,48L
-
-#define LN_dSAQuality "dSAQuality"
-#define NID_dSAQuality 495
-#define OBJ_dSAQuality OBJ_pilotAttributeType,49L
-
-#define LN_singleLevelQuality "singleLevelQuality"
-#define NID_singleLevelQuality 496
-#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L
-
-#define LN_subtreeMinimumQuality "subtreeMinimumQuality"
-#define NID_subtreeMinimumQuality 497
-#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L
-
-#define LN_subtreeMaximumQuality "subtreeMaximumQuality"
-#define NID_subtreeMaximumQuality 498
-#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L
-
-#define LN_personalSignature "personalSignature"
-#define NID_personalSignature 499
-#define OBJ_personalSignature OBJ_pilotAttributeType,53L
-
-#define LN_dITRedirect "dITRedirect"
-#define NID_dITRedirect 500
-#define OBJ_dITRedirect OBJ_pilotAttributeType,54L
-
-#define SN_audio "audio"
-#define NID_audio 501
-#define OBJ_audio OBJ_pilotAttributeType,55L
-
-#define LN_documentPublisher "documentPublisher"
-#define NID_documentPublisher 502
-#define OBJ_documentPublisher OBJ_pilotAttributeType,56L
-
-#define SN_id_set "id-set"
-#define LN_id_set "Secure Electronic Transactions"
-#define NID_id_set 512
-#define OBJ_id_set OBJ_international_organizations,42L
-
-#define SN_set_ctype "set-ctype"
-#define LN_set_ctype "content types"
-#define NID_set_ctype 513
-#define OBJ_set_ctype OBJ_id_set,0L
-
-#define SN_set_msgExt "set-msgExt"
-#define LN_set_msgExt "message extensions"
-#define NID_set_msgExt 514
-#define OBJ_set_msgExt OBJ_id_set,1L
-
-#define SN_set_attr "set-attr"
-#define NID_set_attr 515
-#define OBJ_set_attr OBJ_id_set,3L
-
-#define SN_set_policy "set-policy"
-#define NID_set_policy 516
-#define OBJ_set_policy OBJ_id_set,5L
-
-#define SN_set_certExt "set-certExt"
-#define LN_set_certExt "certificate extensions"
-#define NID_set_certExt 517
-#define OBJ_set_certExt OBJ_id_set,7L
-
-#define SN_set_brand "set-brand"
-#define NID_set_brand 518
-#define OBJ_set_brand OBJ_id_set,8L
-
-#define SN_setct_PANData "setct-PANData"
-#define NID_setct_PANData 519
-#define OBJ_setct_PANData OBJ_set_ctype,0L
-
-#define SN_setct_PANToken "setct-PANToken"
-#define NID_setct_PANToken 520
-#define OBJ_setct_PANToken OBJ_set_ctype,1L
-
-#define SN_setct_PANOnly "setct-PANOnly"
-#define NID_setct_PANOnly 521
-#define OBJ_setct_PANOnly OBJ_set_ctype,2L
-
-#define SN_setct_OIData "setct-OIData"
-#define NID_setct_OIData 522
-#define OBJ_setct_OIData OBJ_set_ctype,3L
-
-#define SN_setct_PI "setct-PI"
-#define NID_setct_PI 523
-#define OBJ_setct_PI OBJ_set_ctype,4L
-
-#define SN_setct_PIData "setct-PIData"
-#define NID_setct_PIData 524
-#define OBJ_setct_PIData OBJ_set_ctype,5L
-
-#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned"
-#define NID_setct_PIDataUnsigned 525
-#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L
-
-#define SN_setct_HODInput "setct-HODInput"
-#define NID_setct_HODInput 526
-#define OBJ_setct_HODInput OBJ_set_ctype,7L
-
-#define SN_setct_AuthResBaggage "setct-AuthResBaggage"
-#define NID_setct_AuthResBaggage 527
-#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L
-
-#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage"
-#define NID_setct_AuthRevReqBaggage 528
-#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L
-
-#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage"
-#define NID_setct_AuthRevResBaggage 529
-#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L
-
-#define SN_setct_CapTokenSeq "setct-CapTokenSeq"
-#define NID_setct_CapTokenSeq 530
-#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L
-
-#define SN_setct_PInitResData "setct-PInitResData"
-#define NID_setct_PInitResData 531
-#define OBJ_setct_PInitResData OBJ_set_ctype,12L
-
-#define SN_setct_PI_TBS "setct-PI-TBS"
-#define NID_setct_PI_TBS 532
-#define OBJ_setct_PI_TBS OBJ_set_ctype,13L
-
-#define SN_setct_PResData "setct-PResData"
-#define NID_setct_PResData 533
-#define OBJ_setct_PResData OBJ_set_ctype,14L
-
-#define SN_setct_AuthReqTBS "setct-AuthReqTBS"
-#define NID_setct_AuthReqTBS 534
-#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L
-
-#define SN_setct_AuthResTBS "setct-AuthResTBS"
-#define NID_setct_AuthResTBS 535
-#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L
-
-#define SN_setct_AuthResTBSX "setct-AuthResTBSX"
-#define NID_setct_AuthResTBSX 536
-#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L
-
-#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS"
-#define NID_setct_AuthTokenTBS 537
-#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L
-
-#define SN_setct_CapTokenData "setct-CapTokenData"
-#define NID_setct_CapTokenData 538
-#define OBJ_setct_CapTokenData OBJ_set_ctype,20L
-
-#define SN_setct_CapTokenTBS "setct-CapTokenTBS"
-#define NID_setct_CapTokenTBS 539
-#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L
-
-#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg"
-#define NID_setct_AcqCardCodeMsg 540
-#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L
-
-#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS"
-#define NID_setct_AuthRevReqTBS 541
-#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L
-
-#define SN_setct_AuthRevResData "setct-AuthRevResData"
-#define NID_setct_AuthRevResData 542
-#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L
-
-#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS"
-#define NID_setct_AuthRevResTBS 543
-#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L
-
-#define SN_setct_CapReqTBS "setct-CapReqTBS"
-#define NID_setct_CapReqTBS 544
-#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L
-
-#define SN_setct_CapReqTBSX "setct-CapReqTBSX"
-#define NID_setct_CapReqTBSX 545
-#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L
-
-#define SN_setct_CapResData "setct-CapResData"
-#define NID_setct_CapResData 546
-#define OBJ_setct_CapResData OBJ_set_ctype,28L
-
-#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS"
-#define NID_setct_CapRevReqTBS 547
-#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L
-
-#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX"
-#define NID_setct_CapRevReqTBSX 548
-#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L
-
-#define SN_setct_CapRevResData "setct-CapRevResData"
-#define NID_setct_CapRevResData 549
-#define OBJ_setct_CapRevResData OBJ_set_ctype,31L
-
-#define SN_setct_CredReqTBS "setct-CredReqTBS"
-#define NID_setct_CredReqTBS 550
-#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L
-
-#define SN_setct_CredReqTBSX "setct-CredReqTBSX"
-#define NID_setct_CredReqTBSX 551
-#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L
-
-#define SN_setct_CredResData "setct-CredResData"
-#define NID_setct_CredResData 552
-#define OBJ_setct_CredResData OBJ_set_ctype,34L
-
-#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS"
-#define NID_setct_CredRevReqTBS 553
-#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L
-
-#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX"
-#define NID_setct_CredRevReqTBSX 554
-#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L
-
-#define SN_setct_CredRevResData "setct-CredRevResData"
-#define NID_setct_CredRevResData 555
-#define OBJ_setct_CredRevResData OBJ_set_ctype,37L
-
-#define SN_setct_PCertReqData "setct-PCertReqData"
-#define NID_setct_PCertReqData 556
-#define OBJ_setct_PCertReqData OBJ_set_ctype,38L
-
-#define SN_setct_PCertResTBS "setct-PCertResTBS"
-#define NID_setct_PCertResTBS 557
-#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L
-
-#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData"
-#define NID_setct_BatchAdminReqData 558
-#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L
-
-#define SN_setct_BatchAdminResData "setct-BatchAdminResData"
-#define NID_setct_BatchAdminResData 559
-#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L
-
-#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS"
-#define NID_setct_CardCInitResTBS 560
-#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L
-
-#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS"
-#define NID_setct_MeAqCInitResTBS 561
-#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L
-
-#define SN_setct_RegFormResTBS "setct-RegFormResTBS"
-#define NID_setct_RegFormResTBS 562
-#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L
-
-#define SN_setct_CertReqData "setct-CertReqData"
-#define NID_setct_CertReqData 563
-#define OBJ_setct_CertReqData OBJ_set_ctype,45L
-
-#define SN_setct_CertReqTBS "setct-CertReqTBS"
-#define NID_setct_CertReqTBS 564
-#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L
-
-#define SN_setct_CertResData "setct-CertResData"
-#define NID_setct_CertResData 565
-#define OBJ_setct_CertResData OBJ_set_ctype,47L
-
-#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS"
-#define NID_setct_CertInqReqTBS 566
-#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L
-
-#define SN_setct_ErrorTBS "setct-ErrorTBS"
-#define NID_setct_ErrorTBS 567
-#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L
-
-#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE"
-#define NID_setct_PIDualSignedTBE 568
-#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L
-
-#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE"
-#define NID_setct_PIUnsignedTBE 569
-#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L
-
-#define SN_setct_AuthReqTBE "setct-AuthReqTBE"
-#define NID_setct_AuthReqTBE 570
-#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L
-
-#define SN_setct_AuthResTBE "setct-AuthResTBE"
-#define NID_setct_AuthResTBE 571
-#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L
-
-#define SN_setct_AuthResTBEX "setct-AuthResTBEX"
-#define NID_setct_AuthResTBEX 572
-#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L
-
-#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE"
-#define NID_setct_AuthTokenTBE 573
-#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L
-
-#define SN_setct_CapTokenTBE "setct-CapTokenTBE"
-#define NID_setct_CapTokenTBE 574
-#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L
-
-#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX"
-#define NID_setct_CapTokenTBEX 575
-#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L
-
-#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE"
-#define NID_setct_AcqCardCodeMsgTBE 576
-#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L
-
-#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE"
-#define NID_setct_AuthRevReqTBE 577
-#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L
-
-#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE"
-#define NID_setct_AuthRevResTBE 578
-#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L
-
-#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB"
-#define NID_setct_AuthRevResTBEB 579
-#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L
-
-#define SN_setct_CapReqTBE "setct-CapReqTBE"
-#define NID_setct_CapReqTBE 580
-#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L
-
-#define SN_setct_CapReqTBEX "setct-CapReqTBEX"
-#define NID_setct_CapReqTBEX 581
-#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L
-
-#define SN_setct_CapResTBE "setct-CapResTBE"
-#define NID_setct_CapResTBE 582
-#define OBJ_setct_CapResTBE OBJ_set_ctype,64L
-
-#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE"
-#define NID_setct_CapRevReqTBE 583
-#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L
-
-#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX"
-#define NID_setct_CapRevReqTBEX 584
-#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L
-
-#define SN_setct_CapRevResTBE "setct-CapRevResTBE"
-#define NID_setct_CapRevResTBE 585
-#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L
-
-#define SN_setct_CredReqTBE "setct-CredReqTBE"
-#define NID_setct_CredReqTBE 586
-#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L
-
-#define SN_setct_CredReqTBEX "setct-CredReqTBEX"
-#define NID_setct_CredReqTBEX 587
-#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L
-
-#define SN_setct_CredResTBE "setct-CredResTBE"
-#define NID_setct_CredResTBE 588
-#define OBJ_setct_CredResTBE OBJ_set_ctype,70L
-
-#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE"
-#define NID_setct_CredRevReqTBE 589
-#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L
-
-#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX"
-#define NID_setct_CredRevReqTBEX 590
-#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L
-
-#define SN_setct_CredRevResTBE "setct-CredRevResTBE"
-#define NID_setct_CredRevResTBE 591
-#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L
-
-#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE"
-#define NID_setct_BatchAdminReqTBE 592
-#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L
-
-#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE"
-#define NID_setct_BatchAdminResTBE 593
-#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L
-
-#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE"
-#define NID_setct_RegFormReqTBE 594
-#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L
-
-#define SN_setct_CertReqTBE "setct-CertReqTBE"
-#define NID_setct_CertReqTBE 595
-#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L
-
-#define SN_setct_CertReqTBEX "setct-CertReqTBEX"
-#define NID_setct_CertReqTBEX 596
-#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L
-
-#define SN_setct_CertResTBE "setct-CertResTBE"
-#define NID_setct_CertResTBE 597
-#define OBJ_setct_CertResTBE OBJ_set_ctype,79L
-
-#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS"
-#define NID_setct_CRLNotificationTBS 598
-#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L
-
-#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS"
-#define NID_setct_CRLNotificationResTBS 599
-#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L
-
-#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS"
-#define NID_setct_BCIDistributionTBS 600
-#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L
-
-#define SN_setext_genCrypt "setext-genCrypt"
-#define LN_setext_genCrypt "generic cryptogram"
-#define NID_setext_genCrypt 601
-#define OBJ_setext_genCrypt OBJ_set_msgExt,1L
-
-#define SN_setext_miAuth "setext-miAuth"
-#define LN_setext_miAuth "merchant initiated auth"
-#define NID_setext_miAuth 602
-#define OBJ_setext_miAuth OBJ_set_msgExt,3L
-
-#define SN_setext_pinSecure "setext-pinSecure"
-#define NID_setext_pinSecure 603
-#define OBJ_setext_pinSecure OBJ_set_msgExt,4L
-
-#define SN_setext_pinAny "setext-pinAny"
-#define NID_setext_pinAny 604
-#define OBJ_setext_pinAny OBJ_set_msgExt,5L
-
-#define SN_setext_track2 "setext-track2"
-#define NID_setext_track2 605
-#define OBJ_setext_track2 OBJ_set_msgExt,7L
-
-#define SN_setext_cv "setext-cv"
-#define LN_setext_cv "additional verification"
-#define NID_setext_cv 606
-#define OBJ_setext_cv OBJ_set_msgExt,8L
-
-#define SN_set_policy_root "set-policy-root"
-#define NID_set_policy_root 607
-#define OBJ_set_policy_root OBJ_set_policy,0L
-
-#define SN_setCext_hashedRoot "setCext-hashedRoot"
-#define NID_setCext_hashedRoot 608
-#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L
-
-#define SN_setCext_certType "setCext-certType"
-#define NID_setCext_certType 609
-#define OBJ_setCext_certType OBJ_set_certExt,1L
-
-#define SN_setCext_merchData "setCext-merchData"
-#define NID_setCext_merchData 610
-#define OBJ_setCext_merchData OBJ_set_certExt,2L
-
-#define SN_setCext_cCertRequired "setCext-cCertRequired"
-#define NID_setCext_cCertRequired 611
-#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L
-
-#define SN_setCext_tunneling "setCext-tunneling"
-#define NID_setCext_tunneling 612
-#define OBJ_setCext_tunneling OBJ_set_certExt,4L
-
-#define SN_setCext_setExt "setCext-setExt"
-#define NID_setCext_setExt 613
-#define OBJ_setCext_setExt OBJ_set_certExt,5L
-
-#define SN_setCext_setQualf "setCext-setQualf"
-#define NID_setCext_setQualf 614
-#define OBJ_setCext_setQualf OBJ_set_certExt,6L
-
-#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities"
-#define NID_setCext_PGWYcapabilities 615
-#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L
-
-#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier"
-#define NID_setCext_TokenIdentifier 616
-#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L
-
-#define SN_setCext_Track2Data "setCext-Track2Data"
-#define NID_setCext_Track2Data 617
-#define OBJ_setCext_Track2Data OBJ_set_certExt,9L
-
-#define SN_setCext_TokenType "setCext-TokenType"
-#define NID_setCext_TokenType 618
-#define OBJ_setCext_TokenType OBJ_set_certExt,10L
-
-#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities"
-#define NID_setCext_IssuerCapabilities 619
-#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L
-
-#define SN_setAttr_Cert "setAttr-Cert"
-#define NID_setAttr_Cert 620
-#define OBJ_setAttr_Cert OBJ_set_attr,0L
-
-#define SN_setAttr_PGWYcap "setAttr-PGWYcap"
-#define LN_setAttr_PGWYcap "payment gateway capabilities"
-#define NID_setAttr_PGWYcap 621
-#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L
-
-#define SN_setAttr_TokenType "setAttr-TokenType"
-#define NID_setAttr_TokenType 622
-#define OBJ_setAttr_TokenType OBJ_set_attr,2L
-
-#define SN_setAttr_IssCap "setAttr-IssCap"
-#define LN_setAttr_IssCap "issuer capabilities"
-#define NID_setAttr_IssCap 623
-#define OBJ_setAttr_IssCap OBJ_set_attr,3L
-
-#define SN_set_rootKeyThumb "set-rootKeyThumb"
-#define NID_set_rootKeyThumb 624
-#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L
-
-#define SN_set_addPolicy "set-addPolicy"
-#define NID_set_addPolicy 625
-#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L
-
-#define SN_setAttr_Token_EMV "setAttr-Token-EMV"
-#define NID_setAttr_Token_EMV 626
-#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L
-
-#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime"
-#define NID_setAttr_Token_B0Prime 627
-#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L
-
-#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM"
-#define NID_setAttr_IssCap_CVM 628
-#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L
-
-#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2"
-#define NID_setAttr_IssCap_T2 629
-#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L
-
-#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig"
-#define NID_setAttr_IssCap_Sig 630
-#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L
-
-#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm"
-#define LN_setAttr_GenCryptgrm "generate cryptogram"
-#define NID_setAttr_GenCryptgrm 631
-#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L
-
-#define SN_setAttr_T2Enc "setAttr-T2Enc"
-#define LN_setAttr_T2Enc "encrypted track 2"
-#define NID_setAttr_T2Enc 632
-#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L
-
-#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt"
-#define LN_setAttr_T2cleartxt "cleartext track 2"
-#define NID_setAttr_T2cleartxt 633
-#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L
-
-#define SN_setAttr_TokICCsig "setAttr-TokICCsig"
-#define LN_setAttr_TokICCsig "ICC or token signature"
-#define NID_setAttr_TokICCsig 634
-#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L
-
-#define SN_setAttr_SecDevSig "setAttr-SecDevSig"
-#define LN_setAttr_SecDevSig "secure device signature"
-#define NID_setAttr_SecDevSig 635
-#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L
-
-#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA"
-#define NID_set_brand_IATA_ATA 636
-#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L
-
-#define SN_set_brand_Diners "set-brand-Diners"
-#define NID_set_brand_Diners 637
-#define OBJ_set_brand_Diners OBJ_set_brand,30L
-
-#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress"
-#define NID_set_brand_AmericanExpress 638
-#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L
-
-#define SN_set_brand_JCB "set-brand-JCB"
-#define NID_set_brand_JCB 639
-#define OBJ_set_brand_JCB OBJ_set_brand,35L
-
-#define SN_set_brand_Visa "set-brand-Visa"
-#define NID_set_brand_Visa 640
-#define OBJ_set_brand_Visa OBJ_set_brand,4L
-
-#define SN_set_brand_MasterCard "set-brand-MasterCard"
-#define NID_set_brand_MasterCard 641
-#define OBJ_set_brand_MasterCard OBJ_set_brand,5L
-
-#define SN_set_brand_Novus "set-brand-Novus"
-#define NID_set_brand_Novus 642
-#define OBJ_set_brand_Novus OBJ_set_brand,6011L
-
-#define SN_des_cdmf "DES-CDMF"
-#define LN_des_cdmf "des-cdmf"
-#define NID_des_cdmf 643
-#define OBJ_des_cdmf OBJ_rsadsi,3L,10L
-
-#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET"
-#define NID_rsaOAEPEncryptionSET 644
-#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L
-
-#define SN_ipsec3 "Oakley-EC2N-3"
-#define LN_ipsec3 "ipsec3"
-#define NID_ipsec3 749
-
-#define SN_ipsec4 "Oakley-EC2N-4"
-#define LN_ipsec4 "ipsec4"
-#define NID_ipsec4 750
-
-#define SN_whirlpool "whirlpool"
-#define NID_whirlpool 804
-#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L
-
-#define SN_cryptopro "cryptopro"
-#define NID_cryptopro 805
-#define OBJ_cryptopro OBJ_member_body,643L,2L,2L
-
-#define SN_cryptocom "cryptocom"
-#define NID_cryptocom 806
-#define OBJ_cryptocom OBJ_member_body,643L,2L,9L
-
-#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001"
-#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001"
-#define NID_id_GostR3411_94_with_GostR3410_2001 807
-#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L
-
-#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94"
-#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94"
-#define NID_id_GostR3411_94_with_GostR3410_94 808
-#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L
-
-#define SN_id_GostR3411_94 "md_gost94"
-#define LN_id_GostR3411_94 "GOST R 34.11-94"
-#define NID_id_GostR3411_94 809
-#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L
-
-#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94"
-#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94"
-#define NID_id_HMACGostR3411_94 810
-#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L
-
-#define SN_id_GostR3410_2001 "gost2001"
-#define LN_id_GostR3410_2001 "GOST R 34.10-2001"
-#define NID_id_GostR3410_2001 811
-#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L
-
-#define SN_id_GostR3410_94 "gost94"
-#define LN_id_GostR3410_94 "GOST R 34.10-94"
-#define NID_id_GostR3410_94 812
-#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L
-
-#define SN_id_Gost28147_89 "gost89"
-#define LN_id_Gost28147_89 "GOST 28147-89"
-#define NID_id_Gost28147_89 813
-#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L
-
-#define SN_gost89_cnt "gost89-cnt"
-#define NID_gost89_cnt 814
-
-#define SN_id_Gost28147_89_MAC "gost-mac"
-#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC"
-#define NID_id_Gost28147_89_MAC 815
-#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L
-
-#define SN_id_GostR3411_94_prf "prf-gostr3411-94"
-#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF"
-#define NID_id_GostR3411_94_prf 816
-#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L
-
-#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH"
-#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH"
-#define NID_id_GostR3410_2001DH 817
-#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L
-
-#define SN_id_GostR3410_94DH "id-GostR3410-94DH"
-#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH"
-#define NID_id_GostR3410_94DH 818
-#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L
-
-#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing"
-#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819
-#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L
-
-#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing"
-#define NID_id_Gost28147_89_None_KeyMeshing 820
-#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L
-
-#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet"
-#define NID_id_GostR3411_94_TestParamSet 821
-#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L
-
-#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet"
-#define NID_id_GostR3411_94_CryptoProParamSet 822
-#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L
-
-#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet"
-#define NID_id_Gost28147_89_TestParamSet 823
-#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L
-
-#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824
-#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L
-
-#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825
-#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L
-
-#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826
-#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L
-
-#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827
-#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L
-
-#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828
-#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L
-
-#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829
-#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L
-
-#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830
-#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L
-
-#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet"
-#define NID_id_GostR3410_94_TestParamSet 831
-#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L
-
-#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832
-#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L
-
-#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833
-#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L
-
-#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834
-#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L
-
-#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835
-#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L
-
-#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836
-#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L
-
-#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837
-#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L
-
-#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838
-#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L
-
-#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet"
-#define NID_id_GostR3410_2001_TestParamSet 839
-#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L
-
-#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840
-#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L
-
-#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841
-#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L
-
-#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842
-#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L
-
-#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843
-#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L
-
-#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844
-#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L
-
-#define SN_id_GostR3410_94_a "id-GostR3410-94-a"
-#define NID_id_GostR3410_94_a 845
-#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L
-
-#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis"
-#define NID_id_GostR3410_94_aBis 846
-#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L
-
-#define SN_id_GostR3410_94_b "id-GostR3410-94-b"
-#define NID_id_GostR3410_94_b 847
-#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L
-
-#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis"
-#define NID_id_GostR3410_94_bBis 848
-#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L
-
-#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc"
-#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet"
-#define NID_id_Gost28147_89_cc 849
-#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L
-
-#define SN_id_GostR3410_94_cc "gost94cc"
-#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom"
-#define NID_id_GostR3410_94_cc 850
-#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L
-
-#define SN_id_GostR3410_2001_cc "gost2001cc"
-#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom"
-#define NID_id_GostR3410_2001_cc 851
-#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L
-
-#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc"
-#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
-#define NID_id_GostR3411_94_with_GostR3410_94_cc 852
-#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L
-
-#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc"
-#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
-#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853
-#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L
-
-#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc"
-#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom"
-#define NID_id_GostR3410_2001_ParamSet_cc 854
-#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L
-
-#define SN_camellia_128_cbc "CAMELLIA-128-CBC"
-#define LN_camellia_128_cbc "camellia-128-cbc"
-#define NID_camellia_128_cbc 751
-#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L
-
-#define SN_camellia_192_cbc "CAMELLIA-192-CBC"
-#define LN_camellia_192_cbc "camellia-192-cbc"
-#define NID_camellia_192_cbc 752
-#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L
-
-#define SN_camellia_256_cbc "CAMELLIA-256-CBC"
-#define LN_camellia_256_cbc "camellia-256-cbc"
-#define NID_camellia_256_cbc 753
-#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L
-
-#define SN_id_camellia128_wrap "id-camellia128-wrap"
-#define NID_id_camellia128_wrap 907
-#define OBJ_id_camellia128_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,2L
-
-#define SN_id_camellia192_wrap "id-camellia192-wrap"
-#define NID_id_camellia192_wrap 908
-#define OBJ_id_camellia192_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,3L
-
-#define SN_id_camellia256_wrap "id-camellia256-wrap"
-#define NID_id_camellia256_wrap 909
-#define OBJ_id_camellia256_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,4L
-
-#define OBJ_ntt_ds 0L,3L,4401L,5L
-
-#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L
-
-#define SN_camellia_128_ecb "CAMELLIA-128-ECB"
-#define LN_camellia_128_ecb "camellia-128-ecb"
-#define NID_camellia_128_ecb 754
-#define OBJ_camellia_128_ecb OBJ_camellia,1L
-
-#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB"
-#define LN_camellia_128_ofb128 "camellia-128-ofb"
-#define NID_camellia_128_ofb128 766
-#define OBJ_camellia_128_ofb128 OBJ_camellia,3L
-
-#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB"
-#define LN_camellia_128_cfb128 "camellia-128-cfb"
-#define NID_camellia_128_cfb128 757
-#define OBJ_camellia_128_cfb128 OBJ_camellia,4L
-
-#define SN_camellia_192_ecb "CAMELLIA-192-ECB"
-#define LN_camellia_192_ecb "camellia-192-ecb"
-#define NID_camellia_192_ecb 755
-#define OBJ_camellia_192_ecb OBJ_camellia,21L
-
-#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB"
-#define LN_camellia_192_ofb128 "camellia-192-ofb"
-#define NID_camellia_192_ofb128 767
-#define OBJ_camellia_192_ofb128 OBJ_camellia,23L
-
-#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB"
-#define LN_camellia_192_cfb128 "camellia-192-cfb"
-#define NID_camellia_192_cfb128 758
-#define OBJ_camellia_192_cfb128 OBJ_camellia,24L
-
-#define SN_camellia_256_ecb "CAMELLIA-256-ECB"
-#define LN_camellia_256_ecb "camellia-256-ecb"
-#define NID_camellia_256_ecb 756
-#define OBJ_camellia_256_ecb OBJ_camellia,41L
-
-#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB"
-#define LN_camellia_256_ofb128 "camellia-256-ofb"
-#define NID_camellia_256_ofb128 768
-#define OBJ_camellia_256_ofb128 OBJ_camellia,43L
-
-#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB"
-#define LN_camellia_256_cfb128 "camellia-256-cfb"
-#define NID_camellia_256_cfb128 759
-#define OBJ_camellia_256_cfb128 OBJ_camellia,44L
-
-#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1"
-#define LN_camellia_128_cfb1 "camellia-128-cfb1"
-#define NID_camellia_128_cfb1 760
-
-#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1"
-#define LN_camellia_192_cfb1 "camellia-192-cfb1"
-#define NID_camellia_192_cfb1 761
-
-#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1"
-#define LN_camellia_256_cfb1 "camellia-256-cfb1"
-#define NID_camellia_256_cfb1 762
-
-#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8"
-#define LN_camellia_128_cfb8 "camellia-128-cfb8"
-#define NID_camellia_128_cfb8 763
-
-#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8"
-#define LN_camellia_192_cfb8 "camellia-192-cfb8"
-#define NID_camellia_192_cfb8 764
-
-#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8"
-#define LN_camellia_256_cfb8 "camellia-256-cfb8"
-#define NID_camellia_256_cfb8 765
-
-#define SN_kisa "KISA"
-#define LN_kisa "kisa"
-#define NID_kisa 773
-#define OBJ_kisa OBJ_member_body,410L,200004L
-
-#define SN_seed_ecb "SEED-ECB"
-#define LN_seed_ecb "seed-ecb"
-#define NID_seed_ecb 776
-#define OBJ_seed_ecb OBJ_kisa,1L,3L
-
-#define SN_seed_cbc "SEED-CBC"
-#define LN_seed_cbc "seed-cbc"
-#define NID_seed_cbc 777
-#define OBJ_seed_cbc OBJ_kisa,1L,4L
-
-#define SN_seed_cfb128 "SEED-CFB"
-#define LN_seed_cfb128 "seed-cfb"
-#define NID_seed_cfb128 779
-#define OBJ_seed_cfb128 OBJ_kisa,1L,5L
-
-#define SN_seed_ofb128 "SEED-OFB"
-#define LN_seed_ofb128 "seed-ofb"
-#define NID_seed_ofb128 778
-#define OBJ_seed_ofb128 OBJ_kisa,1L,6L
-
-#define SN_hmac "HMAC"
-#define LN_hmac "hmac"
-#define NID_hmac 855
-
-#define SN_cmac "CMAC"
-#define LN_cmac "cmac"
-#define NID_cmac 894
-
-#define SN_rc4_hmac_md5 "RC4-HMAC-MD5"
-#define LN_rc4_hmac_md5 "rc4-hmac-md5"
-#define NID_rc4_hmac_md5 915
-
-#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1"
-#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1"
-#define NID_aes_128_cbc_hmac_sha1 916
-
-#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1"
-#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1"
-#define NID_aes_192_cbc_hmac_sha1 917
-
-#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1"
-#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1"
-#define NID_aes_256_cbc_hmac_sha1 918
-
-#define SN_dhpublicnumber "dhpublicnumber"
-#define LN_dhpublicnumber "X9.42 DH"
-#define NID_dhpublicnumber 920
-#define OBJ_dhpublicnumber OBJ_ISO_US,10046L,2L,1L
-
-#define SN_brainpoolP160r1 "brainpoolP160r1"
-#define NID_brainpoolP160r1 921
-#define OBJ_brainpoolP160r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,1L
-
-#define SN_brainpoolP160t1 "brainpoolP160t1"
-#define NID_brainpoolP160t1 922
-#define OBJ_brainpoolP160t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,2L
-
-#define SN_brainpoolP192r1 "brainpoolP192r1"
-#define NID_brainpoolP192r1 923
-#define OBJ_brainpoolP192r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,3L
-
-#define SN_brainpoolP192t1 "brainpoolP192t1"
-#define NID_brainpoolP192t1 924
-#define OBJ_brainpoolP192t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,4L
-
-#define SN_brainpoolP224r1 "brainpoolP224r1"
-#define NID_brainpoolP224r1 925
-#define OBJ_brainpoolP224r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,5L
-
-#define SN_brainpoolP224t1 "brainpoolP224t1"
-#define NID_brainpoolP224t1 926
-#define OBJ_brainpoolP224t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,6L
-
-#define SN_brainpoolP256r1 "brainpoolP256r1"
-#define NID_brainpoolP256r1 927
-#define OBJ_brainpoolP256r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,7L
-
-#define SN_brainpoolP256t1 "brainpoolP256t1"
-#define NID_brainpoolP256t1 928
-#define OBJ_brainpoolP256t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,8L
-
-#define SN_brainpoolP320r1 "brainpoolP320r1"
-#define NID_brainpoolP320r1 929
-#define OBJ_brainpoolP320r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,9L
-
-#define SN_brainpoolP320t1 "brainpoolP320t1"
-#define NID_brainpoolP320t1 930
-#define OBJ_brainpoolP320t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,10L
-
-#define SN_brainpoolP384r1 "brainpoolP384r1"
-#define NID_brainpoolP384r1 931
-#define OBJ_brainpoolP384r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,11L
-
-#define SN_brainpoolP384t1 "brainpoolP384t1"
-#define NID_brainpoolP384t1 932
-#define OBJ_brainpoolP384t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,12L
-
-#define SN_brainpoolP512r1 "brainpoolP512r1"
-#define NID_brainpoolP512r1 933
-#define OBJ_brainpoolP512r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,13L
-
-#define SN_brainpoolP512t1 "brainpoolP512t1"
-#define NID_brainpoolP512t1 934
-#define OBJ_brainpoolP512t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,14L
-
-#define OBJ_x9_63_scheme 1L,3L,133L,16L,840L,63L,0L
-
-#define OBJ_secg_scheme OBJ_certicom_arc,1L
-
-#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936
-#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme OBJ_x9_63_scheme,2L
-
-#define SN_dhSinglePass_stdDH_sha224kdf_scheme "dhSinglePass-stdDH-sha224kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937
-#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme OBJ_secg_scheme,11L,0L
-
-#define SN_dhSinglePass_stdDH_sha256kdf_scheme "dhSinglePass-stdDH-sha256kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938
-#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme OBJ_secg_scheme,11L,1L
-
-#define SN_dhSinglePass_stdDH_sha384kdf_scheme "dhSinglePass-stdDH-sha384kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939
-#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme OBJ_secg_scheme,11L,2L
-
-#define SN_dhSinglePass_stdDH_sha512kdf_scheme "dhSinglePass-stdDH-sha512kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940
-#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme OBJ_secg_scheme,11L,3L
-
-#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme "dhSinglePass-cofactorDH-sha1kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941
-#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme OBJ_x9_63_scheme,3L
-
-#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme "dhSinglePass-cofactorDH-sha224kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942
-#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme OBJ_secg_scheme,14L,0L
-
-#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme "dhSinglePass-cofactorDH-sha256kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943
-#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme OBJ_secg_scheme,14L,1L
-
-#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme "dhSinglePass-cofactorDH-sha384kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944
-#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme OBJ_secg_scheme,14L,2L
-
-#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme "dhSinglePass-cofactorDH-sha512kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945
-#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L
-
-#define SN_dh_std_kdf "dh-std-kdf"
-#define NID_dh_std_kdf 946
-
-#define SN_dh_cofactor_kdf "dh-cofactor-kdf"
-#define NID_dh_cofactor_kdf 947
-
-#define SN_x25519 "X25519"
-#define LN_x25519 "x25519"
-#define NID_x25519 948
-
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
+
+#include "nid.h"
diff --git a/include/openssl/opensslconf.h b/include/openssl/opensslconf.h
new file mode 100644
index 00000000..bf65fc3b
--- /dev/null
+++ b/include/openssl/opensslconf.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
+
+#ifndef OPENSSL_HEADER_OPENSSLCONF_H
+#define OPENSSL_HEADER_OPENSSLCONF_H
+
+
+#define OPENSSL_NO_BF
+#define OPENSSL_NO_BUF_FREELISTS
+#define OPENSSL_NO_CAMELLIA
+#define OPENSSL_NO_CAPIENG
+#define OPENSSL_NO_CAST
+#define OPENSSL_NO_CMS
+#define OPENSSL_NO_COMP
+#define OPENSSL_NO_DANE
+#define OPENSSL_NO_DEPRECATED
+#define OPENSSL_NO_DYNAMIC_ENGINE
+#define OPENSSL_NO_EC_NISTP_64_GCC_128
+#define OPENSSL_NO_EC2M
+#define OPENSSL_NO_ENGINE
+#define OPENSSL_NO_GMP
+#define OPENSSL_NO_GOST
+#define OPENSSL_NO_HEARTBEATS
+#define OPENSSL_NO_HW
+#define OPENSSL_NO_IDEA
+#define OPENSSL_NO_JPAKE
+#define OPENSSL_NO_KRB5
+#define OPENSSL_NO_MD2
+#define OPENSSL_NO_MDC2
+#define OPENSSL_NO_OCB
+#define OPENSSL_NO_OCSP
+#define OPENSSL_NO_RC2
+#define OPENSSL_NO_RC5
+#define OPENSSL_NO_RFC3779
+#define OPENSSL_NO_RIPEMD
+#define OPENSSL_NO_RMD160
+#define OPENSSL_NO_SCTP
+#define OPENSSL_NO_SEED
+#define OPENSSL_NO_SRP
+#define OPENSSL_NO_SSL2
+#define OPENSSL_NO_STATIC_ENGINE
+#define OPENSSL_NO_STORE
+#define OPENSSL_NO_WHIRLPOOL
+
+
+#endif /* OPENSSL_HEADER_OPENSSLCONF_H */
diff --git a/include/openssl/opensslfeatures.h b/include/openssl/opensslfeatures.h
deleted file mode 100644
index c3f97d5a..00000000
--- a/include/openssl/opensslfeatures.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* This header is provided in order to make compiling against code that expects
- OpenSSL easier. */
-
-#ifndef OPENSSL_HEADER_OPENSSLFEATURES_H
-#define OPENSSL_HEADER_OPENSSLFEATURES_H
-
-
-#define OPENSSL_NO_BF
-#define OPENSSL_NO_BUF_FREELISTS
-#define OPENSSL_NO_CAMELLIA
-#define OPENSSL_NO_CAPIENG
-#define OPENSSL_NO_CAST
-#define OPENSSL_NO_CMS
-#define OPENSSL_NO_COMP
-#define OPENSSL_NO_DANE
-#define OPENSSL_NO_DEPRECATED
-#define OPENSSL_NO_DYNAMIC_ENGINE
-#define OPENSSL_NO_EC_NISTP_64_GCC_128
-#define OPENSSL_NO_EC2M
-#define OPENSSL_NO_ENGINE
-#define OPENSSL_NO_GMP
-#define OPENSSL_NO_GOST
-#define OPENSSL_NO_HEARTBEATS
-#define OPENSSL_NO_HW
-#define OPENSSL_NO_IDEA
-#define OPENSSL_NO_JPAKE
-#define OPENSSL_NO_KRB5
-#define OPENSSL_NO_MD2
-#define OPENSSL_NO_MDC2
-#define OPENSSL_NO_OCB
-#define OPENSSL_NO_OCSP
-#define OPENSSL_NO_RC2
-#define OPENSSL_NO_RC5
-#define OPENSSL_NO_RFC3779
-#define OPENSSL_NO_RIPEMD
-#define OPENSSL_NO_RMD160
-#define OPENSSL_NO_SCTP
-#define OPENSSL_NO_SEED
-#define OPENSSL_NO_SRP
-#define OPENSSL_NO_SSL2
-#define OPENSSL_NO_STATIC_ENGINE
-#define OPENSSL_NO_STORE
-#define OPENSSL_NO_WHIRLPOOL
-
-
-#endif /* OPENSSL_HEADER_OPENSSLFEATURES_H */
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index c233a501..58aecaf5 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -65,6 +65,10 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
+/* For compatibility with open-iscsi, which assumes that it can get
+ * |OPENSSL_malloc| from pem.h or err.h */
+#include <openssl/crypto.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -120,6 +124,7 @@ extern "C" {
#define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY"
#define PEM_STRING_DSA "DSA PRIVATE KEY"
#define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY"
+#define PEM_STRING_EC "EC PRIVATE KEY"
#define PEM_STRING_PKCS7 "PKCS7"
#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA"
#define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY"
diff --git a/include/openssl/rand.h b/include/openssl/rand.h
index 2c9c9697..322249c9 100644
--- a/include/openssl/rand.h
+++ b/include/openssl/rand.h
@@ -62,6 +62,12 @@ OPENSSL_EXPORT void RAND_set_urandom_fd(int fd);
OPENSSL_EXPORT void RAND_enable_fork_unsafe_buffering(int fd);
#endif
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+/* RAND_reset_for_fuzzing resets the fuzzer-only deterministic RNG. This
+ * function is only defined in the fuzzer-only build configuration. */
+OPENSSL_EXPORT void RAND_reset_for_fuzzing(void);
+#endif
+
/* Deprecated functions */
diff --git a/include/openssl/rc4.h b/include/openssl/rc4.h
index 0619cac3..68af8782 100644
--- a/include/openssl/rc4.h
+++ b/include/openssl/rc4.h
@@ -83,6 +83,12 @@ OPENSSL_EXPORT void RC4(RC4_KEY *key, size_t len, const uint8_t *in,
uint8_t *out);
+/* Deprecated functions. */
+
+/* RC4_options returns the string "rc4(ptr,int)". */
+OPENSSL_EXPORT const char *RC4_options(void);
+
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/include/openssl/ripemd.h b/include/openssl/ripemd.h
new file mode 100644
index 00000000..cf1e49e2
--- /dev/null
+++ b/include/openssl/ripemd.h
@@ -0,0 +1,107 @@
+/* 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.] */
+
+#ifndef OPENSSL_HEADER_RIPEMD_H
+#define OPENSSL_HEADER_RIPEMD_H
+
+#include <openssl/base.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+# define RIPEMD160_CBLOCK 64
+# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4)
+# define RIPEMD160_DIGEST_LENGTH 20
+
+struct RIPEMD160state_st {
+ uint32_t h[5];
+ uint32_t Nl, Nh;
+ uint8_t data[RIPEMD160_CBLOCK];
+ unsigned num;
+};
+
+/* RIPEMD160_Init initialises |ctx| and returns one. */
+OPENSSL_EXPORT int RIPEMD160_Init(RIPEMD160_CTX *ctx);
+
+/* RIPEMD160_Update adds |len| bytes from |data| to |ctx| and returns one. */
+OPENSSL_EXPORT int RIPEMD160_Update(RIPEMD160_CTX *ctx, const void *data,
+ size_t len);
+
+/* RIPEMD160_Final adds the final padding to |ctx| and writes the resulting
+ * digest to |md|, which must have at least |RIPEMD160_DIGEST_LENGTH| bytes of
+ * space. It returns one. */
+OPENSSL_EXPORT int RIPEMD160_Final(uint8_t *md, RIPEMD160_CTX *ctx);
+
+/* RIPEMD160 writes the digest of |len| bytes from |data| to |out| and returns
+ * |out|. There must be at least |RIPEMD160_DIGEST_LENGTH| bytes of space in
+ * |out|. */
+OPENSSL_EXPORT uint8_t *RIPEMD160(const uint8_t *data, size_t len,
+ uint8_t *out);
+
+/* RIPEMD160_Transform is a low-level function that performs a single,
+ * RIPEMD160 block transformation using the state from |ctx| and 64 bytes from
+ * |block|. */
+OPENSSL_EXPORT void RIPEMD160_Transform(RIPEMD160_CTX *ctx,
+ const uint8_t *block);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_RIPEMD_H */
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index 62d5935f..063d2e8b 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -59,7 +59,6 @@
#include <openssl/base.h>
-#include <openssl/asn1.h>
#include <openssl/engine.h>
#include <openssl/ex_data.h>
#include <openssl/thread.h>
@@ -322,6 +321,17 @@ OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, uint8_t *EM,
const EVP_MD *mgf1Hash,
int sLen);
+/* RSA_padding_add_PKCS1_OAEP_mgf1 writes an OAEP padding of |from| to |to|
+ * with the given parameters and hash functions. If |md| is NULL then SHA-1 is
+ * used. If |mgf1md| is NULL then the value of |md| is used (which means SHA-1
+ * if that, in turn, is NULL).
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT 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, const EVP_MD *md,
+ const EVP_MD *mgf1md);
+
/* RSA_add_pkcs1_prefix builds a version of |msg| prefixed with the DigestInfo
* header for the given hash function and sets |out_msg| to point to it. On
* successful return, |*out_msg| may be allocated memory and, if so,
@@ -400,20 +410,21 @@ OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *r, int idx);
* API, like a platform key store. */
#define RSA_FLAG_OPAQUE 1
-/* RSA_FLAG_CACHE_PUBLIC causes a precomputed Montgomery context to be created,
- * on demand, for the public key operations. */
+/* Deprecated and ignored. */
#define RSA_FLAG_CACHE_PUBLIC 2
-/* RSA_FLAG_CACHE_PRIVATE causes a precomputed Montgomery context to be
- * created, on demand, for the private key operations. */
+/* Deprecated and ignored. */
#define RSA_FLAG_CACHE_PRIVATE 4
-/* RSA_FLAG_NO_BLINDING disables blinding of private operations. */
+/* RSA_FLAG_NO_BLINDING disables blinding of private operations, which is a
+ * dangerous thing to do. It is deprecated and should not be used. It will
+ * be ignored whenever possible.
+ *
+ * This flag must be used if a key without the public exponent |e| is used for
+ * private key operations; avoid using such keys whenever possible. */
#define RSA_FLAG_NO_BLINDING 8
-/* RSA_FLAG_EXT_PKEY means that private key operations will be handled by
- * |mod_exp| and that they do not depend on the private key components being
- * present: for example a key stored in external hardware. */
+/* RSA_FLAG_EXT_PKEY is deprecated and ignored. */
#define RSA_FLAG_EXT_PKEY 0x20
/* RSA_FLAG_SIGN_VER causes the |sign| and |verify| functions of |rsa_meth_st|
@@ -467,14 +478,26 @@ OPENSSL_EXPORT RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
* not, or a negative value on error. */
OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp);
-typedef struct rsa_pss_params_st {
- X509_ALGOR *hashAlgorithm;
- X509_ALGOR *maskGenAlgorithm;
- ASN1_INTEGER *saltLength;
- ASN1_INTEGER *trailerField;
-} RSA_PSS_PARAMS;
+/* RSA_padding_add_PKCS1_PSS acts like |RSA_padding_add_PKCS1_PSS_mgf1| but the
+ * |mgf1Hash| parameter of the latter is implicitly set to |Hash|. */
+OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM,
+ const uint8_t *mHash,
+ const EVP_MD *Hash, int sLen);
+
+/* RSA_verify_PKCS1_PSS acts like |RSA_verify_PKCS1_PSS_mgf1| but the
+ * |mgf1Hash| parameter of the latter is implicitly set to |Hash|. */
+OPENSSL_EXPORT int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash,
+ const EVP_MD *Hash, const uint8_t *EM,
+ int sLen);
-DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+/* RSA_padding_add_PKCS1_OAEP acts like |RSA_padding_add_PKCS1_OAEP_mgf1| but
+ * the |md| and |mgf1md| paramaters of the latter are implicitly set to NULL,
+ * which means SHA-1. */
+OPENSSL_EXPORT 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);
struct rsa_meth_st {
@@ -491,6 +514,7 @@ struct rsa_meth_st {
int (*sign)(int type, const uint8_t *m, unsigned int m_length,
uint8_t *sigret, unsigned int *siglen, const RSA *rsa);
+ /* Ignored. Set this to NULL. */
int (*verify)(int dtype, const uint8_t *m, unsigned int m_length,
const uint8_t *sigbuf, unsigned int siglen, const RSA *rsa);
@@ -503,6 +527,7 @@ struct rsa_meth_st {
int (*decrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding);
+ /* Ignored. Set this to NULL. */
int (*verify_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding);
@@ -521,8 +546,10 @@ struct rsa_meth_st {
int (*private_transform)(RSA *rsa, uint8_t *out, const uint8_t *in,
size_t len);
- int (*mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
- BN_CTX *ctx); /* Can be null */
+ /* mod_exp is deprecated and ignored. Set it to NULL. */
+ int (*mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+
+ /* bn_mod_exp is deprecated and ignored. Set it to NULL. */
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
const BN_MONT_CTX *mont);
@@ -587,51 +614,51 @@ struct rsa_st {
} /* extern C */
#endif
-#define RSA_R_BAD_E_VALUE 100
-#define RSA_R_BAD_FIXED_HEADER_DECRYPT 101
-#define RSA_R_BAD_PAD_BYTE_COUNT 102
-#define RSA_R_BAD_RSA_PARAMETERS 103
-#define RSA_R_BAD_SIGNATURE 104
-#define RSA_R_BLOCK_TYPE_IS_NOT_01 105
-#define RSA_R_BN_NOT_INITIALIZED 106
-#define RSA_R_CRT_PARAMS_ALREADY_GIVEN 107
-#define RSA_R_CRT_VALUES_INCORRECT 108
-#define RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN 109
-#define RSA_R_DATA_TOO_LARGE 110
-#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 111
-#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 112
-#define RSA_R_DATA_TOO_SMALL 113
-#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 114
-#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 115
-#define RSA_R_D_E_NOT_CONGRUENT_TO_1 116
-#define RSA_R_EMPTY_PUBLIC_KEY 117
-#define RSA_R_FIRST_OCTET_INVALID 118
-#define RSA_R_INCONSISTENT_SET_OF_CRT_VALUES 119
-#define RSA_R_INTERNAL_ERROR 120
-#define RSA_R_INVALID_MESSAGE_LENGTH 121
-#define RSA_R_KEY_SIZE_TOO_SMALL 122
-#define RSA_R_LAST_OCTET_INVALID 123
-#define RSA_R_MODULUS_TOO_LARGE 124
-#define RSA_R_NO_PUBLIC_EXPONENT 125
-#define RSA_R_NULL_BEFORE_BLOCK_MISSING 126
-#define RSA_R_N_NOT_EQUAL_P_Q 127
-#define RSA_R_OAEP_DECODING_ERROR 128
-#define RSA_R_ONLY_ONE_OF_P_Q_GIVEN 129
-#define RSA_R_OUTPUT_BUFFER_TOO_SMALL 130
-#define RSA_R_PADDING_CHECK_FAILED 131
-#define RSA_R_PKCS_DECODING_ERROR 132
-#define RSA_R_SLEN_CHECK_FAILED 133
-#define RSA_R_SLEN_RECOVERY_FAILED 134
-#define RSA_R_TOO_LONG 135
-#define RSA_R_TOO_MANY_ITERATIONS 136
-#define RSA_R_UNKNOWN_ALGORITHM_TYPE 137
-#define RSA_R_UNKNOWN_PADDING_TYPE 138
-#define RSA_R_VALUE_MISSING 139
-#define RSA_R_WRONG_SIGNATURE_LENGTH 140
-#define RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES 141
-#define RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY 142
-#define RSA_R_BAD_ENCODING 143
-#define RSA_R_ENCODE_ERROR 144
-#define RSA_R_BAD_VERSION 145
+#define RSA_R_BAD_ENCODING 100
+#define RSA_R_BAD_E_VALUE 101
+#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102
+#define RSA_R_BAD_PAD_BYTE_COUNT 103
+#define RSA_R_BAD_RSA_PARAMETERS 104
+#define RSA_R_BAD_SIGNATURE 105
+#define RSA_R_BAD_VERSION 106
+#define RSA_R_BLOCK_TYPE_IS_NOT_01 107
+#define RSA_R_BN_NOT_INITIALIZED 108
+#define RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY 109
+#define RSA_R_CRT_PARAMS_ALREADY_GIVEN 110
+#define RSA_R_CRT_VALUES_INCORRECT 111
+#define RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN 112
+#define RSA_R_DATA_TOO_LARGE 113
+#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 114
+#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 115
+#define RSA_R_DATA_TOO_SMALL 116
+#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 117
+#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 118
+#define RSA_R_D_E_NOT_CONGRUENT_TO_1 119
+#define RSA_R_EMPTY_PUBLIC_KEY 120
+#define RSA_R_ENCODE_ERROR 121
+#define RSA_R_FIRST_OCTET_INVALID 122
+#define RSA_R_INCONSISTENT_SET_OF_CRT_VALUES 123
+#define RSA_R_INTERNAL_ERROR 124
+#define RSA_R_INVALID_MESSAGE_LENGTH 125
+#define RSA_R_KEY_SIZE_TOO_SMALL 126
+#define RSA_R_LAST_OCTET_INVALID 127
+#define RSA_R_MODULUS_TOO_LARGE 128
+#define RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES 129
+#define RSA_R_NO_PUBLIC_EXPONENT 130
+#define RSA_R_NULL_BEFORE_BLOCK_MISSING 131
+#define RSA_R_N_NOT_EQUAL_P_Q 132
+#define RSA_R_OAEP_DECODING_ERROR 133
+#define RSA_R_ONLY_ONE_OF_P_Q_GIVEN 134
+#define RSA_R_OUTPUT_BUFFER_TOO_SMALL 135
+#define RSA_R_PADDING_CHECK_FAILED 136
+#define RSA_R_PKCS_DECODING_ERROR 137
+#define RSA_R_SLEN_CHECK_FAILED 138
+#define RSA_R_SLEN_RECOVERY_FAILED 139
+#define RSA_R_TOO_LONG 140
+#define RSA_R_TOO_MANY_ITERATIONS 141
+#define RSA_R_UNKNOWN_ALGORITHM_TYPE 142
+#define RSA_R_UNKNOWN_PADDING_TYPE 143
+#define RSA_R_VALUE_MISSING 144
+#define RSA_R_WRONG_SIGNATURE_LENGTH 145
#endif /* OPENSSL_HEADER_RSA_H */
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 41813b2c..b8d1f7b5 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -237,7 +237,10 @@ OPENSSL_EXPORT int SSL_is_server(SSL *ssl);
* In DTLS, if |rbio| is blocking, it must handle
* |BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT| control requests to set read timeouts.
*
- * Calling this function on an already-configured |ssl| is deprecated. */
+ * If |rbio| (respectively, |wbio|) is the same as the currently configured
+ * |BIO| for reading (respectively, writing), that side is left untouched and is
+ * not freed. Using this behavior and calling this function if |ssl| already has
+ * |BIO|s configured is deprecated. */
OPENSSL_EXPORT void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio);
/* SSL_get_rbio returns the |BIO| that |ssl| reads from. */
@@ -251,25 +254,39 @@ OPENSSL_EXPORT int SSL_get_fd(const SSL *ssl);
/* SSL_get_rfd returns the file descriptor that |ssl| is configured to read
* from. If |ssl|'s read |BIO| is not configured or doesn't wrap a file
- * descriptor then it returns -1. */
+ * descriptor then it returns -1.
+ *
+ * Note: On Windows, this may return either a file descriptor or a socket (cast
+ * to int), depending on whether |ssl| was configured with a file descriptor or
+ * socket |BIO|. */
OPENSSL_EXPORT int SSL_get_rfd(const SSL *ssl);
/* SSL_get_wfd returns the file descriptor that |ssl| is configured to write
* to. If |ssl|'s write |BIO| is not configured or doesn't wrap a file
- * descriptor then it returns -1. */
+ * descriptor then it returns -1.
+ *
+ * Note: On Windows, this may return either a file descriptor or a socket (cast
+ * to int), depending on whether |ssl| was configured with a file descriptor or
+ * socket |BIO|. */
OPENSSL_EXPORT int SSL_get_wfd(const SSL *ssl);
/* SSL_set_fd configures |ssl| to read from and write to |fd|. It returns one
* on success and zero on allocation error. The caller retains ownership of
- * |fd|. */
+ * |fd|.
+ *
+ * On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. */
OPENSSL_EXPORT int SSL_set_fd(SSL *ssl, int fd);
/* SSL_set_rfd configures |ssl| to read from |fd|. It returns one on success and
- * zero on allocation error. The caller retains ownership of |fd|. */
+ * zero on allocation error. The caller retains ownership of |fd|.
+ *
+ * On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. */
OPENSSL_EXPORT int SSL_set_rfd(SSL *ssl, int fd);
/* SSL_set_wfd configures |ssl| to write to |fd|. It returns one on success and
- * zero on allocation error. The caller retains ownership of |fd|. */
+ * zero on allocation error. The caller retains ownership of |fd|.
+ *
+ * On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. */
OPENSSL_EXPORT int SSL_set_wfd(SSL *ssl, int fd);
/* SSL_do_handshake continues the current handshake. If there is none or the
@@ -465,13 +482,24 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
* a private key operation was unfinished. The caller may retry the operation
* when the private key operation is complete.
*
- * See also |SSL_set_private_key_method|. */
+ * See also |SSL_set_private_key_method| and
+ * |SSL_CTX_set_private_key_method|. */
#define SSL_ERROR_WANT_PRIVATE_KEY_OPERATION 13
/* SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success
* and zero on failure. */
OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);
+/* DTLSv1_set_initial_timeout_duration sets the initial duration for a DTLS
+ * handshake timeout.
+ *
+ * This duration overrides the default of 1 second, which is the strong
+ * recommendation of RFC 6347 (see section 4.2.4.1). However, there may exist
+ * situations where a shorter timeout would be beneficial, such as for
+ * time-sensitive applications. */
+OPENSSL_EXPORT void DTLSv1_set_initial_timeout_duration(SSL *ssl,
+ unsigned duration_ms);
+
/* DTLSv1_get_timeout queries the next DTLS handshake timeout. If there is a
* timeout in progress, it sets |*out| to the time remaining and returns one.
* Otherwise, it returns zero.
@@ -512,6 +540,7 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl);
#define TLS1_VERSION 0x0301
#define TLS1_1_VERSION 0x0302
#define TLS1_2_VERSION 0x0303
+#define TLS1_3_VERSION 0x0304
#define DTLS1_VERSION 0xfeff
#define DTLS1_2_VERSION 0xfefd
@@ -1003,6 +1032,11 @@ typedef struct ssl_private_key_method_st {
OPENSSL_EXPORT void SSL_set_private_key_method(
SSL *ssl, const SSL_PRIVATE_KEY_METHOD *key_method);
+/* SSL_CTX_set_private_key_method configures a custom private key on |ctx|.
+ * |key_method| must remain valid for the lifetime of |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_set_private_key_method(
+ SSL_CTX *ctx, const SSL_PRIVATE_KEY_METHOD *key_method);
+
/* Cipher suites.
*
@@ -1029,6 +1063,9 @@ OPENSSL_EXPORT int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *cipher);
/* SSL_CIPHER_has_SHA1_HMAC returns one if |cipher| uses HMAC-SHA1. */
OPENSSL_EXPORT int SSL_CIPHER_has_SHA1_HMAC(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_has_SHA256_HMAC returns one if |cipher| uses HMAC-SHA256. */
+OPENSSL_EXPORT int SSL_CIPHER_has_SHA256_HMAC(const SSL_CIPHER *cipher);
+
/* SSL_CIPHER_is_AESGCM returns one if |cipher| uses AES-GCM. */
OPENSSL_EXPORT int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher);
@@ -1061,9 +1098,15 @@ OPENSSL_EXPORT int SSL_CIPHER_is_block_cipher(const SSL_CIPHER *cipher);
/* SSL_CIPHER_is_ECDSA returns one if |cipher| uses ECDSA. */
OPENSSL_EXPORT int SSL_CIPHER_is_ECDSA(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_is_DHE returns one if |cipher| uses DHE. */
+OPENSSL_EXPORT int SSL_CIPHER_is_DHE(const SSL_CIPHER *cipher);
+
/* SSL_CIPHER_is_ECDHE returns one if |cipher| uses ECDHE. */
OPENSSL_EXPORT int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_is_CECPQ1 returns one if |cipher| uses CECPQ1. */
+OPENSSL_EXPORT int SSL_CIPHER_is_CECPQ1(const SSL_CIPHER *cipher);
+
/* SSL_CIPHER_get_min_version returns the minimum protocol version required
* for |cipher|. */
OPENSSL_EXPORT uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher);
@@ -1473,6 +1516,16 @@ OPENSSL_EXPORT uint32_t SSL_SESSION_get_key_exchange_info(
* TODO(davidben): This should return a const X509 *. */
OPENSSL_EXPORT X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session);
+/* TODO(davidben): Remove this when wpa_supplicant in Android has synced with
+ * upstream. */
+#if !defined(BORINGSSL_SUPPRESS_ACCESSORS)
+/* SSL_SESSION_get_master_key writes up to |max_out| bytes of |session|'s master
+ * secret to |out| and returns the number of bytes written. If |max_out| is
+ * zero, it returns the size of the master secret. */
+OPENSSL_EXPORT size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
+ uint8_t *out, size_t max_out);
+#endif
+
/* SSL_SESSION_set_time sets |session|'s creation time to |time| and returns
* |time|. This function may be useful in writing tests but otherwise should not
* be used. */
@@ -1796,9 +1849,9 @@ OPENSSL_EXPORT int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves,
OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves,
size_t curves_len);
-/* SSL_get_curve_name returns a human-readable name for the elliptic curve
- * specified by the given TLS curve id, or NULL if the curve if unknown. */
-OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t curve_id);
+/* SSL_get_curve_name returns a human-readable name for the group specified by
+ * the given TLS group id, or NULL if the group is unknown. */
+OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t group_id);
/* Multiplicative Diffie-Hellman.
@@ -2062,6 +2115,28 @@ OPENSSL_EXPORT int SSL_enable_ocsp_stapling(SSL *ssl);
* handshake. */
OPENSSL_EXPORT void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx);
+/* SSL_CTX_set0_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. Ownership of
+ * |store| is transferred to the |SSL_CTX|. */
+OPENSSL_EXPORT int SSL_CTX_set0_verify_cert_store(SSL_CTX *ctx,
+ X509_STORE *store);
+
+/* SSL_CTX_set1_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. An additional
+ * reference to |store| will be taken. */
+OPENSSL_EXPORT int SSL_CTX_set1_verify_cert_store(SSL_CTX *ctx,
+ X509_STORE *store);
+
+/* SSL_set0_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. Ownership of
+ * |store| is transferred to the |SSL|. */
+OPENSSL_EXPORT int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store);
+
+/* SSL_set1_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. An additional
+ * reference to |store| will be taken. */
+OPENSSL_EXPORT int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store);
+
/* Client certificate CA list.
*
@@ -2118,12 +2193,6 @@ OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list);
OPENSSL_EXPORT int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
const char *file);
-/* SSL_add_dir_cert_subjects_to_stack lists files in directory |dir|. It calls
- * |SSL_add_file_cert_subjects_to_stack| on each file and returns one on success
- * or zero on error. */
-OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
- const char *dir);
-
/* Server name indication.
*
@@ -2662,6 +2731,13 @@ OPENSSL_EXPORT void SSL_set_msg_callback_arg(SSL *ssl, void *arg);
OPENSSL_EXPORT void SSL_CTX_set_keylog_callback(
SSL_CTX *ctx, void (*cb)(const SSL *ssl, const char *line));
+/* SSL_CTX_set_current_time_cb configures a callback to retrieve the current
+ * time, which should be set in |*out_clock|. This can be used for testing
+ * purposes; for example, a callback can be configured that returns a time
+ * set explicitly by the test. */
+OPENSSL_EXPORT void SSL_CTX_set_current_time_cb(
+ SSL_CTX *ctx, void (*cb)(const SSL *ssl, struct timeval *out_clock));
+
enum ssl_renegotiate_mode_t {
ssl_renegotiate_never = 0,
ssl_renegotiate_once,
@@ -2884,6 +2960,9 @@ OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl);
* |TLSEXT_hash_none|. */
OPENSSL_EXPORT uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl);
+/* TODO(davidben): Remove this when wpa_supplicant in Android has synced with
+ * upstream. */
+#if !defined(BORINGSSL_SUPPRESS_ACCESSORS)
/* SSL_get_client_random writes up to |max_out| bytes of the most recent
* handshake's client_random to |out| and returns the number of bytes written.
* If |max_out| is zero, it returns the size of the client_random. */
@@ -2895,6 +2974,7 @@ OPENSSL_EXPORT size_t SSL_get_client_random(const SSL *ssl, uint8_t *out,
* If |max_out| is zero, it returns the size of the server_random. */
OPENSSL_EXPORT size_t SSL_get_server_random(const SSL *ssl, uint8_t *out,
size_t max_out);
+#endif
/* SSL_get_pending_cipher returns the cipher suite for the current handshake or
* NULL if one has not been negotiated yet or there is no pending handshake. */
@@ -3061,6 +3141,10 @@ OPENSSL_EXPORT int SSL_renegotiate(SSL *ssl);
/* SSL_set_state does nothing. */
OPENSSL_EXPORT void SSL_set_state(SSL *ssl, int state);
+/* SSL_get_shared_ciphers writes an empty string to |buf| and returns a
+ * pointer to |buf|, or NULL if |len| is less than or equal to zero. */
+OPENSSL_EXPORT char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len);
+
/* SSL_MODE_HANDSHAKE_CUTTHROUGH is the same as SSL_MODE_ENABLE_FALSE_START. */
#define SSL_MODE_HANDSHAKE_CUTTHROUGH SSL_MODE_ENABLE_FALSE_START
@@ -3119,6 +3203,9 @@ OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_compression(SSL *s);
/* SSL_get_current_expansion returns NULL. */
OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_expansion(SSL *s);
+/* SSL_get_server_tmp_key returns zero. */
+OPENSSL_EXPORT int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key);
+
#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
#define SSL_SESSION_set_app_data(s, a) \
@@ -3160,6 +3247,7 @@ DECLARE_STACK_OF(SSL_COMP)
#define SSL_OP_NO_TLSv1 0x04000000L
#define SSL_OP_NO_TLSv1_2 0x08000000L
#define SSL_OP_NO_TLSv1_1 0x10000000L
+#define SSL_OP_NO_TLSv1_3 0x20000000L
#define SSL_OP_NO_DTLSv1 SSL_OP_NO_TLSv1
#define SSL_OP_NO_DTLSv1_2 SSL_OP_NO_TLSv1_2
@@ -3286,6 +3374,7 @@ OPENSSL_EXPORT const char *SSL_alert_desc_string(int value);
#define SSL_TXT_kDHE "kDHE"
#define SSL_TXT_kEDH "kEDH"
#define SSL_TXT_kECDHE "kECDHE"
+#define SSL_TXT_kCECPQ1 "kCECPQ1"
#define SSL_TXT_kEECDH "kEECDH"
#define SSL_TXT_kPSK "kPSK"
#define SSL_TXT_aRSA "aRSA"
@@ -3316,6 +3405,7 @@ OPENSSL_EXPORT const char *SSL_alert_desc_string(int value);
#define SSL_TXT_TLSV1 "TLSv1"
#define SSL_TXT_TLSV1_1 "TLSv1.1"
#define SSL_TXT_TLSV1_2 "TLSv1.2"
+#define SSL_TXT_TLSV1_3 "TLSv1.3"
#define SSL_TXT_ALL "ALL"
#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
@@ -3351,6 +3441,13 @@ OPENSSL_EXPORT int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key);
* |ec_key|'s curve. */
OPENSSL_EXPORT int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key);
+/* SSL_add_dir_cert_subjects_to_stack lists files in directory |dir|. It calls
+ * |SSL_add_file_cert_subjects_to_stack| on each file and returns one on success
+ * or zero on error. This function is only available from the libdecrepit
+ * library. */
+OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
+ const char *dir);
+
/* Private structures.
*
@@ -3718,9 +3815,9 @@ struct ssl_ctx_st {
/* SRTP profiles we are willing to do from RFC 5764 */
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
- /* EC extension values inherited by SSL structure */
- size_t tlsext_ellipticcurvelist_length;
- uint16_t *tlsext_ellipticcurvelist;
+ /* Supported group values inherited by SSL structure */
+ size_t supported_group_list_len;
+ uint16_t *supported_group_list;
/* The client's Channel ID private key. */
EVP_PKEY *tlsext_channel_id_private;
@@ -3738,7 +3835,8 @@ struct ssl_ctx_st {
void (*keylog_callback)(const SSL *ssl, const char *line);
/* current_time_cb, if not NULL, is the function to use to get the current
- * time. It sets |*out_clock| to the current time. */
+ * time. It sets |*out_clock| to the current time. See
+ * |SSL_CTX_set_current_time_cb|. */
void (*current_time_cb)(const SSL *ssl, struct timeval *out_clock);
/* quiet_shutdown is true if the connection should not send a close_notify on
@@ -3786,7 +3884,9 @@ struct ssl_st {
BIO *wbio; /* used by SSL_write */
/* bbio, if non-NULL, is a buffer placed in front of |wbio| to pack handshake
- * messages within one flight into a single |BIO_write|.
+ * messages within one flight into a single |BIO_write|. In this case, |wbio|
+ * and |bbio| are equal and the true caller-configured BIO is
+ * |bbio->next_bio|.
*
* TODO(davidben): This does not work right for DTLS. It assumes the MTU is
* smaller than the buffer size so that the buffer's internal flushing never
@@ -3802,8 +3902,6 @@ struct ssl_st {
* handshake_func is == 0 until then, we use this test instead of an "init"
* member. */
- int shutdown; /* we have shut things down, 0x01 sent, 0x02
- * for received */
int state; /* where we are */
BUF_MEM *init_buf; /* buffer used during init */
@@ -3815,6 +3913,10 @@ struct ssl_st {
struct ssl3_state_st *s3; /* SSLv3 variables */
struct dtls1_state_st *d1; /* DTLSv1 variables */
+ /* initial_timeout_duration_ms is the default DTLS timeout duration in
+ * milliseconds. It's used to initialize the timer any time it's restarted. */
+ unsigned initial_timeout_duration_ms;
+
/* callback that allows applications to peek at protocol messages */
void (*msg_callback)(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);
@@ -3879,8 +3981,8 @@ struct ssl_st {
char *tlsext_hostname;
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
- size_t tlsext_ellipticcurvelist_length;
- uint16_t *tlsext_ellipticcurvelist; /* our list */
+ size_t supported_group_list_len;
+ uint16_t *supported_group_list; /* our list */
SSL_CTX *initial_ctx; /* initial ctx, used to store sessions */
@@ -3909,10 +4011,6 @@ struct ssl_st {
EVP_CIPHER_CTX *enc_read_ctx;
EVP_MD_CTX *read_hash;
- /* in_handshake is non-zero when we are actually in SSL_accept() or
- * SSL_connect() */
- int in_handshake;
-
/* verify_mode is a bitmask of |SSL_VERIFY_*| values. */
uint8_t verify_mode;
@@ -3964,6 +4062,14 @@ typedef struct ssl3_buffer_st {
uint16_t cap;
} SSL3_BUFFER;
+/* An ssl_shutdown_t describes the shutdown state of one end of the connection,
+ * whether it is alive or has been shutdown via close_notify or fatal alert. */
+enum ssl_shutdown_t {
+ ssl_shutdown_none = 0,
+ ssl_shutdown_close_notify = 1,
+ ssl_shutdown_fatal_alert = 2,
+};
+
typedef struct ssl3_state_st {
uint8_t read_sequence[8];
uint8_t write_sequence[8];
@@ -4006,10 +4112,13 @@ typedef struct ssl3_state_st {
* the handshake hash for TLS 1.1 and below. */
EVP_MD_CTX handshake_md5;
- int warn_alert;
- int fatal_alert;
- /* we allow one fatal and one warning alert to be outstanding, send close
- * alert via the warning alert */
+ /* recv_shutdown is the shutdown state for the receive half of the
+ * connection. */
+ enum ssl_shutdown_t recv_shutdown;
+
+ /* recv_shutdown is the shutdown state for the send half of the connection. */
+ enum ssl_shutdown_t send_shutdown;
+
int alert_dispatch;
uint8_t send_alert[2];
@@ -4043,9 +4152,12 @@ typedef struct ssl3_state_st {
uint8_t peer_finish_md[EVP_MAX_MD_SIZE];
int peer_finish_md_len;
- unsigned long message_size;
int message_type;
+ /* message_complete is one if the current message is complete and zero
+ * otherwise. */
+ unsigned message_complete:1;
+
/* used to hold the new cipher we are going to use */
const SSL_CIPHER *new_cipher;
@@ -4075,13 +4187,10 @@ typedef struct ssl3_state_st {
uint16_t received;
} custom_extensions;
- /* SNI extension */
-
/* should_ack_sni is used by a server and indicates that the SNI extension
* should be echoed in the ServerHello. */
unsigned should_ack_sni:1;
-
/* Client-only: cert_req determines if a client certificate is to be sent.
* This is 0 if no client Certificate message is to be sent, 1 if there is
* a client certificate, and 2 to send an empty client Certificate
@@ -4116,11 +4225,11 @@ typedef struct ssl3_state_st {
/* ocsp_stapling_requested is true if a client requested OCSP stapling. */
unsigned ocsp_stapling_requested:1;
- /* Server-only: peer_ellipticcurvelist contains the EC curve IDs advertised
- * by the peer. This is only set on the server's end. The server does not
- * advertise this extension to the client. */
- uint16_t *peer_ellipticcurvelist;
- size_t peer_ellipticcurvelist_length;
+ /* Server-only: peer_supported_group_list contains the supported group IDs
+ * advertised by the peer. This is only set on the server's end. The server
+ * does not advertise this extension to the client. */
+ uint16_t *peer_supported_group_list;
+ size_t peer_supported_group_list_len;
/* extended_master_secret indicates whether the extended master secret
* computation is used in this handshake. Note that this is different from
@@ -4202,8 +4311,6 @@ typedef struct ssl3_state_st {
* wpa_supplicant will take a little time to sync with upstream. Outside of
* Android they'll have no definition. */
-#define SSL_F_SSL_SET_SESSION_TICKET_EXT doesnt_exist
-
OPENSSL_EXPORT int SSL_set_session_ticket_ext(SSL *s, void *ext_data,
int ext_len);
OPENSSL_EXPORT int SSL_set_session_secret_cb(SSL *s, void *cb, void *arg);
@@ -4506,6 +4613,7 @@ OPENSSL_EXPORT int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
#define SSL_R_WRONG_VERSION_NUMBER 247
#define SSL_R_X509_LIB 248
#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 249
+#define SSL_R_SHUTDOWN_WHILE_IN_INIT 250
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index 957b740e..1da5de72 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -312,17 +312,12 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_CW_CLNT_HELLO_B (0x111 | SSL_ST_CONNECT)
/* read from server */
#define SSL3_ST_CR_SRVR_HELLO_A (0x120 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_SRVR_HELLO_B (0x121 | SSL_ST_CONNECT)
#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126 | SSL_ST_CONNECT)
-#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127 | SSL_ST_CONNECT)
#define SSL3_ST_CR_CERT_A (0x130 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_CERT_B (0x131 | SSL_ST_CONNECT)
#define SSL3_ST_CR_KEY_EXCH_A (0x140 | SSL_ST_CONNECT)
#define SSL3_ST_CR_KEY_EXCH_B (0x141 | SSL_ST_CONNECT)
#define SSL3_ST_CR_CERT_REQ_A (0x150 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_CERT_REQ_B (0x151 | SSL_ST_CONNECT)
#define SSL3_ST_CR_SRVR_DONE_A (0x160 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_SRVR_DONE_B (0x161 | SSL_ST_CONNECT)
/* write to server */
#define SSL3_ST_CW_CERT_A (0x170 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_B (0x171 | SSL_ST_CONNECT)
@@ -344,11 +339,12 @@ OPENSSL_COMPILE_ASSERT(
/* read from server */
#define SSL3_ST_CR_CHANGE (0x1C0 | SSL_ST_CONNECT)
#define SSL3_ST_CR_FINISHED_A (0x1D0 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_FINISHED_B (0x1D1 | SSL_ST_CONNECT)
#define SSL3_ST_CR_SESSION_TICKET_A (0x1E0 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_SESSION_TICKET_B (0x1E1 | SSL_ST_CONNECT)
#define SSL3_ST_CR_CERT_STATUS_A (0x1F0 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_CERT_STATUS_B (0x1F1 | SSL_ST_CONNECT)
+
+/* SSL3_ST_CR_SRVR_HELLO_B is a legacy alias for |SSL3_ST_CR_SRVR_HELLO_A| used
+ * by some consumers which check |SSL_state|. */
+#define SSL3_ST_CR_SRVR_HELLO_B SSL3_ST_CR_SRVR_HELLO_A
/* server */
/* extra state */
@@ -359,7 +355,6 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_SR_CLNT_HELLO_A (0x110 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CLNT_HELLO_B (0x111 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CLNT_HELLO_C (0x112 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CLNT_HELLO_D (0x115 | SSL_ST_ACCEPT)
/* write to client */
#define SSL3_ST_SW_HELLO_REQ_A (0x120 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_HELLO_REQ_B (0x121 | SSL_ST_ACCEPT)
@@ -377,19 +372,13 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_SW_SRVR_DONE_B (0x171 | SSL_ST_ACCEPT)
/* read from client */
#define SSL3_ST_SR_CERT_A (0x180 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CERT_B (0x181 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_KEY_EXCH_A (0x190 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_KEY_EXCH_B (0x191 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_KEY_EXCH_C (0x192 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CERT_VRFY_A (0x1A0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CERT_VRFY_B (0x1A1 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CHANGE (0x1B0 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_NEXT_PROTO_A (0x210 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_NEXT_PROTO_B (0x211 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CHANNEL_ID_A (0x230 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CHANNEL_ID_B (0x231 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_FINISHED_A (0x1C0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_FINISHED_B (0x1C1 | SSL_ST_ACCEPT)
/* write to client */
#define SSL3_ST_SW_CHANGE_A (0x1D0 | SSL_ST_ACCEPT)
@@ -406,20 +395,25 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_MT_HELLO_REQUEST 0
#define SSL3_MT_CLIENT_HELLO 1
#define SSL3_MT_SERVER_HELLO 2
-#define SSL3_MT_NEWSESSION_TICKET 4
+#define SSL3_MT_NEW_SESSION_TICKET 4
#define SSL3_MT_CERTIFICATE 11
#define SSL3_MT_SERVER_KEY_EXCHANGE 12
#define SSL3_MT_CERTIFICATE_REQUEST 13
-#define SSL3_MT_SERVER_DONE 14
+#define SSL3_MT_SERVER_HELLO_DONE 14
#define SSL3_MT_CERTIFICATE_VERIFY 15
#define SSL3_MT_CLIENT_KEY_EXCHANGE 16
#define SSL3_MT_FINISHED 20
#define SSL3_MT_CERTIFICATE_STATUS 22
#define SSL3_MT_SUPPLEMENTAL_DATA 23
#define SSL3_MT_NEXT_PROTO 67
-#define SSL3_MT_ENCRYPTED_EXTENSIONS 203
+#define SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS 203
#define DTLS1_MT_HELLO_VERIFY_REQUEST 3
+/* The following are legacy aliases for consumers which use
+ * |SSL_CTX_set_msg_callback|. */
+#define SSL3_MT_SERVER_DONE SSL3_MT_SERVER_HELLO_DONE
+#define SSL3_MT_NEWSESSION_TICKET SSL3_MT_NEW_SESSION_TICKET
+
#define SSL3_MT_CCS 1
diff --git a/include/openssl/stack_macros.h b/include/openssl/stack_macros.h
index 809424c7..2a60b8f9 100644
--- a/include/openssl/stack_macros.h
+++ b/include/openssl/stack_macros.h
@@ -27,14 +27,15 @@
((STACK_OF(ACCESS_DESCRIPTION) *)sk_new_null())
#define sk_ACCESS_DESCRIPTION_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk))
#define sk_ACCESS_DESCRIPTION_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk));
-#define sk_ACCESS_DESCRIPTION_value(sk, i) \
- ((ACCESS_DESCRIPTION *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk), (i)))
+#define sk_ACCESS_DESCRIPTION_value(sk, i) \
+ ((ACCESS_DESCRIPTION *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+ (i)))
#define sk_ACCESS_DESCRIPTION_set(sk, i, p) \
((ACCESS_DESCRIPTION *)sk_set( \
@@ -80,13 +81,14 @@
#define sk_ACCESS_DESCRIPTION_dup(sk) \
((STACK_OF(ACCESS_DESCRIPTION) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk)))
#define sk_ACCESS_DESCRIPTION_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk))
#define sk_ACCESS_DESCRIPTION_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk))
#define sk_ACCESS_DESCRIPTION_set_cmp_func(sk, comp) \
((int (*)(const ACCESS_DESCRIPTION **a, const ACCESS_DESCRIPTION **b)) \
@@ -113,14 +115,15 @@
#define sk_ASN1_ADB_TABLE_new_null() ((STACK_OF(ASN1_ADB_TABLE) *)sk_new_null())
#define sk_ASN1_ADB_TABLE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk))
#define sk_ASN1_ADB_TABLE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk));
-#define sk_ASN1_ADB_TABLE_value(sk, i) \
- ((ASN1_ADB_TABLE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk), (i)))
+#define sk_ASN1_ADB_TABLE_value(sk, i) \
+ ((ASN1_ADB_TABLE *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk), \
+ (i)))
#define sk_ASN1_ADB_TABLE_set(sk, i, p) \
((ASN1_ADB_TABLE *)sk_set( \
@@ -166,13 +169,14 @@
#define sk_ASN1_ADB_TABLE_dup(sk) \
((STACK_OF(ASN1_ADB_TABLE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk)))
#define sk_ASN1_ADB_TABLE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk))
#define sk_ASN1_ADB_TABLE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk))
#define sk_ASN1_ADB_TABLE_set_cmp_func(sk, comp) \
((int (*)(const ASN1_ADB_TABLE **a, const ASN1_ADB_TABLE **b)) \
@@ -200,14 +204,15 @@
((STACK_OF(ASN1_GENERALSTRING) *)sk_new_null())
#define sk_ASN1_GENERALSTRING_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk))
#define sk_ASN1_GENERALSTRING_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk));
-#define sk_ASN1_GENERALSTRING_value(sk, i) \
- ((ASN1_GENERALSTRING *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk), (i)))
+#define sk_ASN1_GENERALSTRING_value(sk, i) \
+ ((ASN1_GENERALSTRING *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk), \
+ (i)))
#define sk_ASN1_GENERALSTRING_set(sk, i, p) \
((ASN1_GENERALSTRING *)sk_set( \
@@ -253,13 +258,14 @@
#define sk_ASN1_GENERALSTRING_dup(sk) \
((STACK_OF(ASN1_GENERALSTRING) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk)))
#define sk_ASN1_GENERALSTRING_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk))
#define sk_ASN1_GENERALSTRING_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk))
#define sk_ASN1_GENERALSTRING_set_cmp_func(sk, comp) \
((int (*)(const ASN1_GENERALSTRING **a, const ASN1_GENERALSTRING **b)) \
@@ -286,14 +292,14 @@
#define sk_ASN1_INTEGER_new_null() ((STACK_OF(ASN1_INTEGER) *)sk_new_null())
#define sk_ASN1_INTEGER_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk))
#define sk_ASN1_INTEGER_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk));
#define sk_ASN1_INTEGER_value(sk, i) \
((ASN1_INTEGER *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk), (i)))
#define sk_ASN1_INTEGER_set(sk, i, p) \
((ASN1_INTEGER *)sk_set( \
@@ -338,13 +344,13 @@
#define sk_ASN1_INTEGER_dup(sk) \
((STACK_OF(ASN1_INTEGER) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk)))
#define sk_ASN1_INTEGER_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk))
#define sk_ASN1_INTEGER_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk))
#define sk_ASN1_INTEGER_set_cmp_func(sk, comp) \
((int (*)(const ASN1_INTEGER **a, const ASN1_INTEGER **b))sk_set_cmp_func( \
@@ -369,14 +375,14 @@
#define sk_ASN1_OBJECT_new_null() ((STACK_OF(ASN1_OBJECT) *)sk_new_null())
#define sk_ASN1_OBJECT_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk))
#define sk_ASN1_OBJECT_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk));
#define sk_ASN1_OBJECT_value(sk, i) \
((ASN1_OBJECT *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk), (i)))
#define sk_ASN1_OBJECT_set(sk, i, p) \
((ASN1_OBJECT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
@@ -419,13 +425,13 @@
#define sk_ASN1_OBJECT_dup(sk) \
((STACK_OF(ASN1_OBJECT) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk)))
#define sk_ASN1_OBJECT_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk))
#define sk_ASN1_OBJECT_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk))
#define sk_ASN1_OBJECT_set_cmp_func(sk, comp) \
((int (*)(const ASN1_OBJECT **a, const ASN1_OBJECT **b))sk_set_cmp_func( \
@@ -452,14 +458,15 @@
((STACK_OF(ASN1_STRING_TABLE) *)sk_new_null())
#define sk_ASN1_STRING_TABLE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk))
#define sk_ASN1_STRING_TABLE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk));
-#define sk_ASN1_STRING_TABLE_value(sk, i) \
- ((ASN1_STRING_TABLE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk), (i)))
+#define sk_ASN1_STRING_TABLE_value(sk, i) \
+ ((ASN1_STRING_TABLE *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk), \
+ (i)))
#define sk_ASN1_STRING_TABLE_set(sk, i, p) \
((ASN1_STRING_TABLE *)sk_set( \
@@ -505,13 +512,14 @@
#define sk_ASN1_STRING_TABLE_dup(sk) \
((STACK_OF(ASN1_STRING_TABLE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk)))
#define sk_ASN1_STRING_TABLE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk))
#define sk_ASN1_STRING_TABLE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk))
#define sk_ASN1_STRING_TABLE_set_cmp_func(sk, comp) \
((int (*)(const ASN1_STRING_TABLE **a, const ASN1_STRING_TABLE **b)) \
@@ -538,14 +546,14 @@
#define sk_ASN1_TYPE_new_null() ((STACK_OF(ASN1_TYPE) *)sk_new_null())
#define sk_ASN1_TYPE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk))
#define sk_ASN1_TYPE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk));
#define sk_ASN1_TYPE_value(sk, i) \
((ASN1_TYPE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk), (i)))
#define sk_ASN1_TYPE_set(sk, i, p) \
((ASN1_TYPE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), (i), \
@@ -588,13 +596,13 @@
#define sk_ASN1_TYPE_dup(sk) \
((STACK_OF(ASN1_TYPE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk)))
#define sk_ASN1_TYPE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk))
#define sk_ASN1_TYPE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk))
#define sk_ASN1_TYPE_set_cmp_func(sk, comp) \
((int (*)(const ASN1_TYPE **a, const ASN1_TYPE **b))sk_set_cmp_func( \
@@ -617,14 +625,14 @@
#define sk_ASN1_VALUE_new_null() ((STACK_OF(ASN1_VALUE) *)sk_new_null())
#define sk_ASN1_VALUE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk))
#define sk_ASN1_VALUE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk));
#define sk_ASN1_VALUE_value(sk, i) \
((ASN1_VALUE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk), (i)))
#define sk_ASN1_VALUE_set(sk, i, p) \
((ASN1_VALUE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
@@ -667,13 +675,13 @@
#define sk_ASN1_VALUE_dup(sk) \
((STACK_OF(ASN1_VALUE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk)))
#define sk_ASN1_VALUE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk))
#define sk_ASN1_VALUE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk))
#define sk_ASN1_VALUE_set_cmp_func(sk, comp) \
((int (*)(const ASN1_VALUE **a, const ASN1_VALUE **b))sk_set_cmp_func( \
@@ -696,12 +704,14 @@
#define sk_BIO_new_null() ((STACK_OF(BIO) *)sk_new_null())
-#define sk_BIO_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk))
+#define sk_BIO_num(sk) \
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk))
#define sk_BIO_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk));
-#define sk_BIO_value(sk, i) \
- ((BIO *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk), (i)))
+#define sk_BIO_value(sk, i) \
+ ((BIO *)sk_value(CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk), \
+ (i)))
#define sk_BIO_set(sk, i, p) \
((BIO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), (i), \
@@ -738,13 +748,14 @@
#define sk_BIO_pop(sk) \
((BIO *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk)))
-#define sk_BIO_dup(sk) \
- ((STACK_OF(BIO) *)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk)))
+#define sk_BIO_dup(sk) \
+ ((STACK_OF(BIO) *)sk_dup( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk)))
#define sk_BIO_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk))
#define sk_BIO_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk))
#define sk_BIO_set_cmp_func(sk, comp) \
((int (*)(const BIO **a, const BIO **b))sk_set_cmp_func( \
@@ -767,14 +778,14 @@
#define sk_BY_DIR_ENTRY_new_null() ((STACK_OF(BY_DIR_ENTRY) *)sk_new_null())
#define sk_BY_DIR_ENTRY_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk))
#define sk_BY_DIR_ENTRY_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk));
#define sk_BY_DIR_ENTRY_value(sk, i) \
((BY_DIR_ENTRY *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk), (i)))
#define sk_BY_DIR_ENTRY_set(sk, i, p) \
((BY_DIR_ENTRY *)sk_set( \
@@ -819,13 +830,13 @@
#define sk_BY_DIR_ENTRY_dup(sk) \
((STACK_OF(BY_DIR_ENTRY) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk)))
#define sk_BY_DIR_ENTRY_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk))
#define sk_BY_DIR_ENTRY_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk))
#define sk_BY_DIR_ENTRY_set_cmp_func(sk, comp) \
((int (*)(const BY_DIR_ENTRY **a, const BY_DIR_ENTRY **b))sk_set_cmp_func( \
@@ -850,14 +861,14 @@
#define sk_BY_DIR_HASH_new_null() ((STACK_OF(BY_DIR_HASH) *)sk_new_null())
#define sk_BY_DIR_HASH_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk))
#define sk_BY_DIR_HASH_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk));
#define sk_BY_DIR_HASH_value(sk, i) \
((BY_DIR_HASH *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk), (i)))
#define sk_BY_DIR_HASH_set(sk, i, p) \
((BY_DIR_HASH *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
@@ -900,13 +911,13 @@
#define sk_BY_DIR_HASH_dup(sk) \
((STACK_OF(BY_DIR_HASH) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk)))
#define sk_BY_DIR_HASH_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk))
#define sk_BY_DIR_HASH_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk))
#define sk_BY_DIR_HASH_set_cmp_func(sk, comp) \
((int (*)(const BY_DIR_HASH **a, const BY_DIR_HASH **b))sk_set_cmp_func( \
@@ -931,14 +942,14 @@
#define sk_CONF_VALUE_new_null() ((STACK_OF(CONF_VALUE) *)sk_new_null())
#define sk_CONF_VALUE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk))
#define sk_CONF_VALUE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk));
#define sk_CONF_VALUE_value(sk, i) \
((CONF_VALUE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk), (i)))
#define sk_CONF_VALUE_set(sk, i, p) \
((CONF_VALUE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
@@ -981,13 +992,13 @@
#define sk_CONF_VALUE_dup(sk) \
((STACK_OF(CONF_VALUE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk)))
#define sk_CONF_VALUE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk))
#define sk_CONF_VALUE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk))
#define sk_CONF_VALUE_set_cmp_func(sk, comp) \
((int (*)(const CONF_VALUE **a, const CONF_VALUE **b))sk_set_cmp_func( \
@@ -1013,15 +1024,17 @@
#define sk_CRYPTO_EX_DATA_FUNCS_new_null() \
((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_new_null())
-#define sk_CRYPTO_EX_DATA_FUNCS_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+#define sk_CRYPTO_EX_DATA_FUNCS_num(sk) \
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, \
+ sk))
#define sk_CRYPTO_EX_DATA_FUNCS_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk));
-#define sk_CRYPTO_EX_DATA_FUNCS_value(sk, i) \
- ((CRYPTO_EX_DATA_FUNCS *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+#define sk_CRYPTO_EX_DATA_FUNCS_value(sk, i) \
+ ((CRYPTO_EX_DATA_FUNCS *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, \
+ sk), \
(i)))
#define sk_CRYPTO_EX_DATA_FUNCS_set(sk, i, p) \
@@ -1066,16 +1079,16 @@
((CRYPTO_EX_DATA_FUNCS *)sk_pop( \
CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
-#define sk_CRYPTO_EX_DATA_FUNCS_dup(sk) \
- ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
+#define sk_CRYPTO_EX_DATA_FUNCS_dup(sk) \
+ ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_dup(CHECKED_CAST( \
+ const _STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
#define sk_CRYPTO_EX_DATA_FUNCS_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
#define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(sk) \
- sk_is_sorted( \
- CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, \
+ const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
#define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(sk, comp) \
((int (*)(const CRYPTO_EX_DATA_FUNCS **a, const CRYPTO_EX_DATA_FUNCS **b)) \
@@ -1105,14 +1118,14 @@
#define sk_DIST_POINT_new_null() ((STACK_OF(DIST_POINT) *)sk_new_null())
#define sk_DIST_POINT_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk))
#define sk_DIST_POINT_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk));
#define sk_DIST_POINT_value(sk, i) \
((DIST_POINT *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk), (i)))
#define sk_DIST_POINT_set(sk, i, p) \
((DIST_POINT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
@@ -1155,13 +1168,13 @@
#define sk_DIST_POINT_dup(sk) \
((STACK_OF(DIST_POINT) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk)))
#define sk_DIST_POINT_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk))
#define sk_DIST_POINT_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk))
#define sk_DIST_POINT_set_cmp_func(sk, comp) \
((int (*)(const DIST_POINT **a, const DIST_POINT **b))sk_set_cmp_func( \
@@ -1186,14 +1199,14 @@
#define sk_GENERAL_NAME_new_null() ((STACK_OF(GENERAL_NAME) *)sk_new_null())
#define sk_GENERAL_NAME_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk))
#define sk_GENERAL_NAME_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk));
#define sk_GENERAL_NAME_value(sk, i) \
((GENERAL_NAME *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk), (i)))
#define sk_GENERAL_NAME_set(sk, i, p) \
((GENERAL_NAME *)sk_set( \
@@ -1238,13 +1251,13 @@
#define sk_GENERAL_NAME_dup(sk) \
((STACK_OF(GENERAL_NAME) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk)))
#define sk_GENERAL_NAME_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk))
#define sk_GENERAL_NAME_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk))
#define sk_GENERAL_NAME_set_cmp_func(sk, comp) \
((int (*)(const GENERAL_NAME **a, const GENERAL_NAME **b))sk_set_cmp_func( \
@@ -1269,14 +1282,14 @@
#define sk_GENERAL_NAMES_new_null() ((STACK_OF(GENERAL_NAMES) *)sk_new_null())
#define sk_GENERAL_NAMES_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk))
#define sk_GENERAL_NAMES_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk));
#define sk_GENERAL_NAMES_value(sk, i) \
((GENERAL_NAMES *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk), (i)))
#define sk_GENERAL_NAMES_set(sk, i, p) \
((GENERAL_NAMES *)sk_set( \
@@ -1322,13 +1335,14 @@
#define sk_GENERAL_NAMES_dup(sk) \
((STACK_OF(GENERAL_NAMES) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk)))
#define sk_GENERAL_NAMES_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk))
#define sk_GENERAL_NAMES_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk))
#define sk_GENERAL_NAMES_set_cmp_func(sk, comp) \
((int (*)(const GENERAL_NAMES **a, const GENERAL_NAMES **b))sk_set_cmp_func( \
@@ -1354,14 +1368,15 @@
((STACK_OF(GENERAL_SUBTREE) *)sk_new_null())
#define sk_GENERAL_SUBTREE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk))
#define sk_GENERAL_SUBTREE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk));
-#define sk_GENERAL_SUBTREE_value(sk, i) \
- ((GENERAL_SUBTREE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk), (i)))
+#define sk_GENERAL_SUBTREE_value(sk, i) \
+ ((GENERAL_SUBTREE *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk), \
+ (i)))
#define sk_GENERAL_SUBTREE_set(sk, i, p) \
((GENERAL_SUBTREE *)sk_set( \
@@ -1407,13 +1422,14 @@
#define sk_GENERAL_SUBTREE_dup(sk) \
((STACK_OF(GENERAL_SUBTREE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk)))
#define sk_GENERAL_SUBTREE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk))
#define sk_GENERAL_SUBTREE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk))
#define sk_GENERAL_SUBTREE_set_cmp_func(sk, comp) \
((int (*)(const GENERAL_SUBTREE **a, const GENERAL_SUBTREE **b)) \
@@ -1439,14 +1455,14 @@
#define sk_POLICYINFO_new_null() ((STACK_OF(POLICYINFO) *)sk_new_null())
#define sk_POLICYINFO_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk))
#define sk_POLICYINFO_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk));
#define sk_POLICYINFO_value(sk, i) \
((POLICYINFO *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk), (i)))
#define sk_POLICYINFO_set(sk, i, p) \
((POLICYINFO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
@@ -1489,13 +1505,13 @@
#define sk_POLICYINFO_dup(sk) \
((STACK_OF(POLICYINFO) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk)))
#define sk_POLICYINFO_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk))
#define sk_POLICYINFO_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk))
#define sk_POLICYINFO_set_cmp_func(sk, comp) \
((int (*)(const POLICYINFO **a, const POLICYINFO **b))sk_set_cmp_func( \
@@ -1520,14 +1536,15 @@
#define sk_POLICYQUALINFO_new_null() ((STACK_OF(POLICYQUALINFO) *)sk_new_null())
#define sk_POLICYQUALINFO_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk))
#define sk_POLICYQUALINFO_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk));
-#define sk_POLICYQUALINFO_value(sk, i) \
- ((POLICYQUALINFO *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk), (i)))
+#define sk_POLICYQUALINFO_value(sk, i) \
+ ((POLICYQUALINFO *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk), \
+ (i)))
#define sk_POLICYQUALINFO_set(sk, i, p) \
((POLICYQUALINFO *)sk_set( \
@@ -1573,13 +1590,14 @@
#define sk_POLICYQUALINFO_dup(sk) \
((STACK_OF(POLICYQUALINFO) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk)))
#define sk_POLICYQUALINFO_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk))
#define sk_POLICYQUALINFO_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk))
#define sk_POLICYQUALINFO_set_cmp_func(sk, comp) \
((int (*)(const POLICYQUALINFO **a, const POLICYQUALINFO **b)) \
@@ -1605,14 +1623,15 @@
#define sk_POLICY_MAPPING_new_null() ((STACK_OF(POLICY_MAPPING) *)sk_new_null())
#define sk_POLICY_MAPPING_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk))
#define sk_POLICY_MAPPING_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk));
-#define sk_POLICY_MAPPING_value(sk, i) \
- ((POLICY_MAPPING *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk), (i)))
+#define sk_POLICY_MAPPING_value(sk, i) \
+ ((POLICY_MAPPING *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk), \
+ (i)))
#define sk_POLICY_MAPPING_set(sk, i, p) \
((POLICY_MAPPING *)sk_set( \
@@ -1658,13 +1677,14 @@
#define sk_POLICY_MAPPING_dup(sk) \
((STACK_OF(POLICY_MAPPING) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk)))
#define sk_POLICY_MAPPING_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk))
#define sk_POLICY_MAPPING_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk))
#define sk_POLICY_MAPPING_set_cmp_func(sk, comp) \
((int (*)(const POLICY_MAPPING **a, const POLICY_MAPPING **b)) \
@@ -1691,15 +1711,17 @@
#define sk_RSA_additional_prime_new_null() \
((STACK_OF(RSA_additional_prime) *)sk_new_null())
-#define sk_RSA_additional_prime_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk))
+#define sk_RSA_additional_prime_num(sk) \
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(RSA_additional_prime) *, \
+ sk))
#define sk_RSA_additional_prime_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk));
-#define sk_RSA_additional_prime_value(sk, i) \
- ((RSA_additional_prime *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(RSA_additional_prime) *, sk), \
+#define sk_RSA_additional_prime_value(sk, i) \
+ ((RSA_additional_prime *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(RSA_additional_prime) *, \
+ sk), \
(i)))
#define sk_RSA_additional_prime_set(sk, i, p) \
@@ -1744,16 +1766,16 @@
((RSA_additional_prime *)sk_pop( \
CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk)))
-#define sk_RSA_additional_prime_dup(sk) \
- ((STACK_OF(RSA_additional_prime) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(RSA_additional_prime) *, sk)))
+#define sk_RSA_additional_prime_dup(sk) \
+ ((STACK_OF(RSA_additional_prime) *)sk_dup(CHECKED_CAST( \
+ const _STACK *, const STACK_OF(RSA_additional_prime) *, sk)))
#define sk_RSA_additional_prime_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk))
#define sk_RSA_additional_prime_is_sorted(sk) \
- sk_is_sorted( \
- CHECKED_CAST(_STACK *, const STACK_OF(RSA_additional_prime) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, \
+ const STACK_OF(RSA_additional_prime) *, sk))
#define sk_RSA_additional_prime_set_cmp_func(sk, comp) \
((int (*)(const RSA_additional_prime **a, const RSA_additional_prime **b)) \
@@ -1782,14 +1804,14 @@
#define sk_SSL_COMP_new_null() ((STACK_OF(SSL_COMP) *)sk_new_null())
#define sk_SSL_COMP_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk))
#define sk_SSL_COMP_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk));
#define sk_SSL_COMP_value(sk, i) \
((SSL_COMP *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk), (i)))
#define sk_SSL_COMP_set(sk, i, p) \
((SSL_COMP *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), (i), \
@@ -1830,13 +1852,13 @@
#define sk_SSL_COMP_dup(sk) \
((STACK_OF(SSL_COMP) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk)))
#define sk_SSL_COMP_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk))
#define sk_SSL_COMP_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk))
#define sk_SSL_COMP_set_cmp_func(sk, comp) \
((int (*)(const SSL_COMP **a, const SSL_COMP **b))sk_set_cmp_func( \
@@ -1860,15 +1882,17 @@
#define sk_SSL_CUSTOM_EXTENSION_new_null() \
((STACK_OF(SSL_CUSTOM_EXTENSION) *)sk_new_null())
-#define sk_SSL_CUSTOM_EXTENSION_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
+#define sk_SSL_CUSTOM_EXTENSION_num(sk) \
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, \
+ sk))
#define sk_SSL_CUSTOM_EXTENSION_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk));
-#define sk_SSL_CUSTOM_EXTENSION_value(sk, i) \
- ((SSL_CUSTOM_EXTENSION *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk), \
+#define sk_SSL_CUSTOM_EXTENSION_value(sk, i) \
+ ((SSL_CUSTOM_EXTENSION *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, \
+ sk), \
(i)))
#define sk_SSL_CUSTOM_EXTENSION_set(sk, i, p) \
@@ -1913,16 +1937,16 @@
((SSL_CUSTOM_EXTENSION *)sk_pop( \
CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk)))
-#define sk_SSL_CUSTOM_EXTENSION_dup(sk) \
- ((STACK_OF(SSL_CUSTOM_EXTENSION) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk)))
+#define sk_SSL_CUSTOM_EXTENSION_dup(sk) \
+ ((STACK_OF(SSL_CUSTOM_EXTENSION) *)sk_dup(CHECKED_CAST( \
+ const _STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk)))
#define sk_SSL_CUSTOM_EXTENSION_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
#define sk_SSL_CUSTOM_EXTENSION_is_sorted(sk) \
- sk_is_sorted( \
- CHECKED_CAST(_STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, \
+ const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
#define sk_SSL_CUSTOM_EXTENSION_set_cmp_func(sk, comp) \
((int (*)(const SSL_CUSTOM_EXTENSION **a, const SSL_CUSTOM_EXTENSION **b)) \
@@ -1954,14 +1978,16 @@
((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_new_null())
#define sk_STACK_OF_X509_NAME_ENTRY_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, \
+ const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
#define sk_STACK_OF_X509_NAME_ENTRY_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk));
-#define sk_STACK_OF_X509_NAME_ENTRY_value(sk, i) \
- ((STACK_OF_X509_NAME_ENTRY *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+#define sk_STACK_OF_X509_NAME_ENTRY_value(sk, i) \
+ ((STACK_OF_X509_NAME_ENTRY *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, \
+ sk), \
(i)))
#define sk_STACK_OF_X509_NAME_ENTRY_set(sk, i, p) \
@@ -2008,16 +2034,16 @@
((STACK_OF_X509_NAME_ENTRY *)sk_pop( \
CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
-#define sk_STACK_OF_X509_NAME_ENTRY_dup(sk) \
- ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
+#define sk_STACK_OF_X509_NAME_ENTRY_dup(sk) \
+ ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_dup(CHECKED_CAST( \
+ const _STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
#define sk_STACK_OF_X509_NAME_ENTRY_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
#define sk_STACK_OF_X509_NAME_ENTRY_is_sorted(sk) \
- sk_is_sorted( \
- CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, \
+ const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
#define sk_STACK_OF_X509_NAME_ENTRY_set_cmp_func(sk, comp) \
((int (*)(const STACK_OF_X509_NAME_ENTRY **a, \
@@ -2047,14 +2073,14 @@
#define sk_SXNETID_new_null() ((STACK_OF(SXNETID) *)sk_new_null())
#define sk_SXNETID_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk))
#define sk_SXNETID_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk));
-#define sk_SXNETID_value(sk, i) \
- ((SXNETID *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk), \
- (i)))
+#define sk_SXNETID_value(sk, i) \
+ ((SXNETID *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk), (i)))
#define sk_SXNETID_set(sk, i, p) \
((SXNETID *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), (i), \
@@ -2095,13 +2121,13 @@
#define sk_SXNETID_dup(sk) \
((STACK_OF(SXNETID) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk)))
#define sk_SXNETID_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk))
#define sk_SXNETID_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk))
#define sk_SXNETID_set_cmp_func(sk, comp) \
((int (*)(const SXNETID **a, const SXNETID **b))sk_set_cmp_func( \
@@ -2122,12 +2148,14 @@
#define sk_X509_new_null() ((STACK_OF(X509) *)sk_new_null())
-#define sk_X509_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk))
+#define sk_X509_num(sk) \
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk))
#define sk_X509_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk));
-#define sk_X509_value(sk, i) \
- ((X509 *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk), (i)))
+#define sk_X509_value(sk, i) \
+ ((X509 *)sk_value(CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk), \
+ (i)))
#define sk_X509_set(sk, i, p) \
((X509 *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), (i), \
@@ -2164,13 +2192,14 @@
#define sk_X509_pop(sk) \
((X509 *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk)))
-#define sk_X509_dup(sk) \
- ((STACK_OF(X509) *)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk)))
+#define sk_X509_dup(sk) \
+ ((STACK_OF(X509) *)sk_dup( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk)))
#define sk_X509_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk))
#define sk_X509_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk))
#define sk_X509_set_cmp_func(sk, comp) \
((int (*)(const X509 **a, const X509 **b))sk_set_cmp_func( \
@@ -2195,14 +2224,15 @@
((STACK_OF(X509V3_EXT_METHOD) *)sk_new_null())
#define sk_X509V3_EXT_METHOD_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk))
#define sk_X509V3_EXT_METHOD_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk));
-#define sk_X509V3_EXT_METHOD_value(sk, i) \
- ((X509V3_EXT_METHOD *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk), (i)))
+#define sk_X509V3_EXT_METHOD_value(sk, i) \
+ ((X509V3_EXT_METHOD *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk), \
+ (i)))
#define sk_X509V3_EXT_METHOD_set(sk, i, p) \
((X509V3_EXT_METHOD *)sk_set( \
@@ -2248,13 +2278,14 @@
#define sk_X509V3_EXT_METHOD_dup(sk) \
((STACK_OF(X509V3_EXT_METHOD) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk)))
#define sk_X509V3_EXT_METHOD_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk))
#define sk_X509V3_EXT_METHOD_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk))
#define sk_X509V3_EXT_METHOD_set_cmp_func(sk, comp) \
((int (*)(const X509V3_EXT_METHOD **a, const X509V3_EXT_METHOD **b)) \
@@ -2281,14 +2312,14 @@
#define sk_X509_ALGOR_new_null() ((STACK_OF(X509_ALGOR) *)sk_new_null())
#define sk_X509_ALGOR_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk))
#define sk_X509_ALGOR_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk));
#define sk_X509_ALGOR_value(sk, i) \
((X509_ALGOR *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk), (i)))
#define sk_X509_ALGOR_set(sk, i, p) \
((X509_ALGOR *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
@@ -2331,13 +2362,13 @@
#define sk_X509_ALGOR_dup(sk) \
((STACK_OF(X509_ALGOR) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk)))
#define sk_X509_ALGOR_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk))
#define sk_X509_ALGOR_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk))
#define sk_X509_ALGOR_set_cmp_func(sk, comp) \
((int (*)(const X509_ALGOR **a, const X509_ALGOR **b))sk_set_cmp_func( \
@@ -2362,14 +2393,15 @@
#define sk_X509_ATTRIBUTE_new_null() ((STACK_OF(X509_ATTRIBUTE) *)sk_new_null())
#define sk_X509_ATTRIBUTE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk))
#define sk_X509_ATTRIBUTE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk));
-#define sk_X509_ATTRIBUTE_value(sk, i) \
- ((X509_ATTRIBUTE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk), (i)))
+#define sk_X509_ATTRIBUTE_value(sk, i) \
+ ((X509_ATTRIBUTE *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk), \
+ (i)))
#define sk_X509_ATTRIBUTE_set(sk, i, p) \
((X509_ATTRIBUTE *)sk_set( \
@@ -2415,13 +2447,14 @@
#define sk_X509_ATTRIBUTE_dup(sk) \
((STACK_OF(X509_ATTRIBUTE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk)))
#define sk_X509_ATTRIBUTE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk))
#define sk_X509_ATTRIBUTE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk))
#define sk_X509_ATTRIBUTE_set_cmp_func(sk, comp) \
((int (*)(const X509_ATTRIBUTE **a, const X509_ATTRIBUTE **b)) \
@@ -2446,14 +2479,14 @@
#define sk_X509_CRL_new_null() ((STACK_OF(X509_CRL) *)sk_new_null())
#define sk_X509_CRL_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk))
#define sk_X509_CRL_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk));
#define sk_X509_CRL_value(sk, i) \
((X509_CRL *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk), (i)))
#define sk_X509_CRL_set(sk, i, p) \
((X509_CRL *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), (i), \
@@ -2494,13 +2527,13 @@
#define sk_X509_CRL_dup(sk) \
((STACK_OF(X509_CRL) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk)))
#define sk_X509_CRL_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk))
#define sk_X509_CRL_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk))
#define sk_X509_CRL_set_cmp_func(sk, comp) \
((int (*)(const X509_CRL **a, const X509_CRL **b))sk_set_cmp_func( \
@@ -2523,14 +2556,15 @@
#define sk_X509_EXTENSION_new_null() ((STACK_OF(X509_EXTENSION) *)sk_new_null())
#define sk_X509_EXTENSION_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk))
#define sk_X509_EXTENSION_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk));
-#define sk_X509_EXTENSION_value(sk, i) \
- ((X509_EXTENSION *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk), (i)))
+#define sk_X509_EXTENSION_value(sk, i) \
+ ((X509_EXTENSION *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk), \
+ (i)))
#define sk_X509_EXTENSION_set(sk, i, p) \
((X509_EXTENSION *)sk_set( \
@@ -2576,13 +2610,14 @@
#define sk_X509_EXTENSION_dup(sk) \
((STACK_OF(X509_EXTENSION) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk)))
#define sk_X509_EXTENSION_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk))
#define sk_X509_EXTENSION_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk))
#define sk_X509_EXTENSION_set_cmp_func(sk, comp) \
((int (*)(const X509_EXTENSION **a, const X509_EXTENSION **b)) \
@@ -2608,14 +2643,14 @@
#define sk_X509_INFO_new_null() ((STACK_OF(X509_INFO) *)sk_new_null())
#define sk_X509_INFO_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk))
#define sk_X509_INFO_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk));
#define sk_X509_INFO_value(sk, i) \
((X509_INFO *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk), (i)))
#define sk_X509_INFO_set(sk, i, p) \
((X509_INFO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), (i), \
@@ -2658,13 +2693,13 @@
#define sk_X509_INFO_dup(sk) \
((STACK_OF(X509_INFO) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk)))
#define sk_X509_INFO_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk))
#define sk_X509_INFO_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk))
#define sk_X509_INFO_set_cmp_func(sk, comp) \
((int (*)(const X509_INFO **a, const X509_INFO **b))sk_set_cmp_func( \
@@ -2687,14 +2722,14 @@
#define sk_X509_LOOKUP_new_null() ((STACK_OF(X509_LOOKUP) *)sk_new_null())
#define sk_X509_LOOKUP_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk))
#define sk_X509_LOOKUP_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk));
#define sk_X509_LOOKUP_value(sk, i) \
((X509_LOOKUP *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk), (i)))
#define sk_X509_LOOKUP_set(sk, i, p) \
((X509_LOOKUP *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
@@ -2737,13 +2772,13 @@
#define sk_X509_LOOKUP_dup(sk) \
((STACK_OF(X509_LOOKUP) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk)))
#define sk_X509_LOOKUP_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk))
#define sk_X509_LOOKUP_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk))
#define sk_X509_LOOKUP_set_cmp_func(sk, comp) \
((int (*)(const X509_LOOKUP **a, const X509_LOOKUP **b))sk_set_cmp_func( \
@@ -2768,14 +2803,14 @@
#define sk_X509_NAME_new_null() ((STACK_OF(X509_NAME) *)sk_new_null())
#define sk_X509_NAME_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk))
#define sk_X509_NAME_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk));
#define sk_X509_NAME_value(sk, i) \
((X509_NAME *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk), (i)))
#define sk_X509_NAME_set(sk, i, p) \
((X509_NAME *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), (i), \
@@ -2818,13 +2853,13 @@
#define sk_X509_NAME_dup(sk) \
((STACK_OF(X509_NAME) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk)))
#define sk_X509_NAME_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk))
#define sk_X509_NAME_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk))
#define sk_X509_NAME_set_cmp_func(sk, comp) \
((int (*)(const X509_NAME **a, const X509_NAME **b))sk_set_cmp_func( \
@@ -2848,14 +2883,15 @@
((STACK_OF(X509_NAME_ENTRY) *)sk_new_null())
#define sk_X509_NAME_ENTRY_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk))
#define sk_X509_NAME_ENTRY_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk));
-#define sk_X509_NAME_ENTRY_value(sk, i) \
- ((X509_NAME_ENTRY *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk), (i)))
+#define sk_X509_NAME_ENTRY_value(sk, i) \
+ ((X509_NAME_ENTRY *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk), \
+ (i)))
#define sk_X509_NAME_ENTRY_set(sk, i, p) \
((X509_NAME_ENTRY *)sk_set( \
@@ -2901,13 +2937,14 @@
#define sk_X509_NAME_ENTRY_dup(sk) \
((STACK_OF(X509_NAME_ENTRY) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk)))
#define sk_X509_NAME_ENTRY_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk))
#define sk_X509_NAME_ENTRY_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk))
#define sk_X509_NAME_ENTRY_set_cmp_func(sk, comp) \
((int (*)(const X509_NAME_ENTRY **a, const X509_NAME_ENTRY **b)) \
@@ -2933,14 +2970,14 @@
#define sk_X509_OBJECT_new_null() ((STACK_OF(X509_OBJECT) *)sk_new_null())
#define sk_X509_OBJECT_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk))
#define sk_X509_OBJECT_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk));
#define sk_X509_OBJECT_value(sk, i) \
((X509_OBJECT *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk), (i)))
#define sk_X509_OBJECT_set(sk, i, p) \
((X509_OBJECT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
@@ -2983,13 +3020,13 @@
#define sk_X509_OBJECT_dup(sk) \
((STACK_OF(X509_OBJECT) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk)))
#define sk_X509_OBJECT_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk))
#define sk_X509_OBJECT_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk))
#define sk_X509_OBJECT_set_cmp_func(sk, comp) \
((int (*)(const X509_OBJECT **a, const X509_OBJECT **b))sk_set_cmp_func( \
@@ -3015,14 +3052,15 @@
((STACK_OF(X509_POLICY_DATA) *)sk_new_null())
#define sk_X509_POLICY_DATA_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk))
#define sk_X509_POLICY_DATA_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk));
-#define sk_X509_POLICY_DATA_value(sk, i) \
- ((X509_POLICY_DATA *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk), (i)))
+#define sk_X509_POLICY_DATA_value(sk, i) \
+ ((X509_POLICY_DATA *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk), \
+ (i)))
#define sk_X509_POLICY_DATA_set(sk, i, p) \
((X509_POLICY_DATA *)sk_set( \
@@ -3068,13 +3106,14 @@
#define sk_X509_POLICY_DATA_dup(sk) \
((STACK_OF(X509_POLICY_DATA) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk)))
#define sk_X509_POLICY_DATA_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk))
#define sk_X509_POLICY_DATA_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk))
#define sk_X509_POLICY_DATA_set_cmp_func(sk, comp) \
((int (*)(const X509_POLICY_DATA **a, const X509_POLICY_DATA **b)) \
@@ -3102,14 +3141,15 @@
((STACK_OF(X509_POLICY_NODE) *)sk_new_null())
#define sk_X509_POLICY_NODE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk))
#define sk_X509_POLICY_NODE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk));
-#define sk_X509_POLICY_NODE_value(sk, i) \
- ((X509_POLICY_NODE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk), (i)))
+#define sk_X509_POLICY_NODE_value(sk, i) \
+ ((X509_POLICY_NODE *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk), \
+ (i)))
#define sk_X509_POLICY_NODE_set(sk, i, p) \
((X509_POLICY_NODE *)sk_set( \
@@ -3155,13 +3195,14 @@
#define sk_X509_POLICY_NODE_dup(sk) \
((STACK_OF(X509_POLICY_NODE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk)))
#define sk_X509_POLICY_NODE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk))
#define sk_X509_POLICY_NODE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk))
#define sk_X509_POLICY_NODE_set_cmp_func(sk, comp) \
((int (*)(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b)) \
@@ -3188,14 +3229,14 @@
#define sk_X509_PURPOSE_new_null() ((STACK_OF(X509_PURPOSE) *)sk_new_null())
#define sk_X509_PURPOSE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk))
#define sk_X509_PURPOSE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk));
#define sk_X509_PURPOSE_value(sk, i) \
((X509_PURPOSE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk), (i)))
#define sk_X509_PURPOSE_set(sk, i, p) \
((X509_PURPOSE *)sk_set( \
@@ -3240,13 +3281,13 @@
#define sk_X509_PURPOSE_dup(sk) \
((STACK_OF(X509_PURPOSE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk)))
#define sk_X509_PURPOSE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk))
#define sk_X509_PURPOSE_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk))
#define sk_X509_PURPOSE_set_cmp_func(sk, comp) \
((int (*)(const X509_PURPOSE **a, const X509_PURPOSE **b))sk_set_cmp_func( \
@@ -3271,14 +3312,14 @@
#define sk_X509_REVOKED_new_null() ((STACK_OF(X509_REVOKED) *)sk_new_null())
#define sk_X509_REVOKED_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk))
#define sk_X509_REVOKED_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk));
#define sk_X509_REVOKED_value(sk, i) \
((X509_REVOKED *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk), (i)))
#define sk_X509_REVOKED_set(sk, i, p) \
((X509_REVOKED *)sk_set( \
@@ -3323,13 +3364,13 @@
#define sk_X509_REVOKED_dup(sk) \
((STACK_OF(X509_REVOKED) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk)))
#define sk_X509_REVOKED_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk))
#define sk_X509_REVOKED_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk))
#define sk_X509_REVOKED_set_cmp_func(sk, comp) \
((int (*)(const X509_REVOKED **a, const X509_REVOKED **b))sk_set_cmp_func( \
@@ -3354,14 +3395,14 @@
#define sk_X509_TRUST_new_null() ((STACK_OF(X509_TRUST) *)sk_new_null())
#define sk_X509_TRUST_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk))
#define sk_X509_TRUST_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk));
#define sk_X509_TRUST_value(sk, i) \
((X509_TRUST *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk), (i)))
#define sk_X509_TRUST_set(sk, i, p) \
((X509_TRUST *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
@@ -3404,13 +3445,13 @@
#define sk_X509_TRUST_dup(sk) \
((STACK_OF(X509_TRUST) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk)))
#define sk_X509_TRUST_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk))
#define sk_X509_TRUST_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk))
#define sk_X509_TRUST_set_cmp_func(sk, comp) \
((int (*)(const X509_TRUST **a, const X509_TRUST **b))sk_set_cmp_func( \
@@ -3437,14 +3478,15 @@
((STACK_OF(X509_VERIFY_PARAM) *)sk_new_null())
#define sk_X509_VERIFY_PARAM_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk))
#define sk_X509_VERIFY_PARAM_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk));
-#define sk_X509_VERIFY_PARAM_value(sk, i) \
- ((X509_VERIFY_PARAM *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk), (i)))
+#define sk_X509_VERIFY_PARAM_value(sk, i) \
+ ((X509_VERIFY_PARAM *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk), \
+ (i)))
#define sk_X509_VERIFY_PARAM_set(sk, i, p) \
((X509_VERIFY_PARAM *)sk_set( \
@@ -3490,13 +3532,14 @@
#define sk_X509_VERIFY_PARAM_dup(sk) \
((STACK_OF(X509_VERIFY_PARAM) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk)))
#define sk_X509_VERIFY_PARAM_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk))
#define sk_X509_VERIFY_PARAM_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk))
#define sk_X509_VERIFY_PARAM_set_cmp_func(sk, comp) \
((int (*)(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b)) \
@@ -3515,21 +3558,23 @@
free_func)))
/* void */
-#define sk_void_new(comp) \
- ((STACK_OF(void)*)sk_new(CHECKED_CAST( \
+#define sk_void_new(comp) \
+ ((STACK_OF(void) *)sk_new(CHECKED_CAST( \
stack_cmp_func, int (*)(const void **a, const void **b), comp)))
-#define sk_void_new_null() ((STACK_OF(void)*)sk_new_null())
+#define sk_void_new_null() ((STACK_OF(void) *)sk_new_null())
-#define sk_void_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk))
+#define sk_void_num(sk) \
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk))
#define sk_void_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk));
-#define sk_void_value(sk, i) \
- ((void *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(void) *, sk), (i)))
+#define sk_void_value(sk, i) \
+ ((void *)sk_value(CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk), \
+ (i)))
-#define sk_void_set(sk, i, p) \
- ((void *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), (i), \
+#define sk_void_set(sk, i, p) \
+ ((void *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), (i), \
CHECKED_CAST(void *, void *, p)))
#define sk_void_free(sk) sk_free(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk))
@@ -3543,10 +3588,10 @@
CHECKED_CAST(void *, void *, p), (where))
#define sk_void_delete(sk, where) \
- ((void *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), (where)))
+ ((void *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), (where)))
-#define sk_void_delete_ptr(sk, p) \
- ((void *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+#define sk_void_delete_ptr(sk, p) \
+ ((void *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), \
CHECKED_CAST(void *, void *, p)))
#define sk_void_find(sk, out_index, p) \
@@ -3554,31 +3599,32 @@
CHECKED_CAST(void *, void *, p))
#define sk_void_shift(sk) \
- ((void *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk)))
+ ((void *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk)))
#define sk_void_push(sk, p) \
sk_push(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), \
CHECKED_CAST(void *, void *, p))
#define sk_void_pop(sk) \
- ((void *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk)))
+ ((void *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk)))
-#define sk_void_dup(sk) \
- ((STACK_OF(void)*)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(void) *, sk)))
+#define sk_void_dup(sk) \
+ ((STACK_OF(void) *)sk_dup( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk)))
#define sk_void_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk))
#define sk_void_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(void) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk))
#define sk_void_set_cmp_func(sk, comp) \
((int (*)(const void **a, const void **b))sk_set_cmp_func( \
- CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+ CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), \
CHECKED_CAST(stack_cmp_func, int (*)(const void **a, const void **b), \
comp)))
#define sk_void_deep_copy(sk, copy_func, free_func) \
- ((STACK_OF(void)*)sk_deep_copy( \
+ ((STACK_OF(void) *)sk_deep_copy( \
CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk), \
CHECKED_CAST(void *(*)(void *), void *(*)(void *), copy_func), \
CHECKED_CAST(void (*)(void *), void (*)(void *), free_func)))
@@ -3594,14 +3640,16 @@
((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_new_null())
#define sk_SRTP_PROTECTION_PROFILE_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, \
+ const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
#define sk_SRTP_PROTECTION_PROFILE_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk));
-#define sk_SRTP_PROTECTION_PROFILE_value(sk, i) \
- ((const SRTP_PROTECTION_PROFILE *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+#define sk_SRTP_PROTECTION_PROFILE_value(sk, i) \
+ ((const SRTP_PROTECTION_PROFILE *)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, \
+ sk), \
(i)))
#define sk_SRTP_PROTECTION_PROFILE_set(sk, i, p) \
@@ -3649,16 +3697,16 @@
((const SRTP_PROTECTION_PROFILE *)sk_pop( \
CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
-#define sk_SRTP_PROTECTION_PROFILE_dup(sk) \
- ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
+#define sk_SRTP_PROTECTION_PROFILE_dup(sk) \
+ ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_dup(CHECKED_CAST( \
+ const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
#define sk_SRTP_PROTECTION_PROFILE_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
#define sk_SRTP_PROTECTION_PROFILE_is_sorted(sk) \
- sk_is_sorted( \
- CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, \
+ const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
#define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(sk, comp) \
((int (*)(const SRTP_PROTECTION_PROFILE **a, \
@@ -3670,14 +3718,15 @@
const SRTP_PROTECTION_PROFILE **b), \
comp)))
-#define sk_SRTP_PROTECTION_PROFILE_deep_copy(sk, copy_func, free_func) \
- ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_deep_copy( \
- CHECKED_CAST(const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, \
- sk), \
- CHECKED_CAST(void *(*)(void *), const SRTP_PROTECTION_PROFILE *(*)( \
- const SRTP_PROTECTION_PROFILE *), \
- copy_func), \
- CHECKED_CAST(void (*)(void *), \
+#define sk_SRTP_PROTECTION_PROFILE_deep_copy(sk, copy_func, free_func) \
+ ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_deep_copy( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, \
+ sk), \
+ CHECKED_CAST( \
+ void *(*)(void *), \
+ const SRTP_PROTECTION_PROFILE *(*)(const SRTP_PROTECTION_PROFILE *), \
+ copy_func), \
+ CHECKED_CAST(void (*)(void *), \
void (*)(const SRTP_PROTECTION_PROFILE *), free_func)))
/* SSL_CIPHER */
@@ -3689,14 +3738,14 @@
#define sk_SSL_CIPHER_new_null() ((STACK_OF(SSL_CIPHER) *)sk_new_null())
#define sk_SSL_CIPHER_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk))
#define sk_SSL_CIPHER_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk));
#define sk_SSL_CIPHER_value(sk, i) \
((const SSL_CIPHER *)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk), (i)))
#define sk_SSL_CIPHER_set(sk, i, p) \
((const SSL_CIPHER *)sk_set( \
@@ -3742,13 +3791,13 @@
#define sk_SSL_CIPHER_dup(sk) \
((STACK_OF(SSL_CIPHER) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk)))
#define sk_SSL_CIPHER_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk))
#define sk_SSL_CIPHER_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk))
+ sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk))
#define sk_SSL_CIPHER_set_cmp_func(sk, comp) \
((int (*)(const SSL_CIPHER **a, const SSL_CIPHER **b))sk_set_cmp_func( \
@@ -3774,14 +3823,15 @@
#define sk_OPENSSL_STRING_new_null() ((STACK_OF(OPENSSL_STRING) *)sk_new_null())
#define sk_OPENSSL_STRING_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk))
#define sk_OPENSSL_STRING_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk));
-#define sk_OPENSSL_STRING_value(sk, i) \
- ((OPENSSL_STRING)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk), (i)))
+#define sk_OPENSSL_STRING_value(sk, i) \
+ ((OPENSSL_STRING)sk_value( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk), \
+ (i)))
#define sk_OPENSSL_STRING_set(sk, i, p) \
((OPENSSL_STRING)sk_set( \
@@ -3827,13 +3877,14 @@
#define sk_OPENSSL_STRING_dup(sk) \
((STACK_OF(OPENSSL_STRING) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk)))
#define sk_OPENSSL_STRING_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk))
#define sk_OPENSSL_STRING_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk))
#define sk_OPENSSL_STRING_set_cmp_func(sk, comp) \
((int (*)(const OPENSSL_STRING **a, const OPENSSL_STRING **b)) \
@@ -3859,14 +3910,14 @@
#define sk_OPENSSL_BLOCK_new_null() ((STACK_OF(OPENSSL_BLOCK) *)sk_new_null())
#define sk_OPENSSL_BLOCK_num(sk) \
- sk_num(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
+ sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk))
#define sk_OPENSSL_BLOCK_zero(sk) \
sk_zero(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk));
#define sk_OPENSSL_BLOCK_value(sk, i) \
((OPENSSL_BLOCK)sk_value( \
- CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk), (i)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk), (i)))
#define sk_OPENSSL_BLOCK_set(sk, i, p) \
((OPENSSL_BLOCK)sk_set( \
@@ -3911,13 +3962,14 @@
#define sk_OPENSSL_BLOCK_dup(sk) \
((STACK_OF(OPENSSL_BLOCK) *)sk_dup( \
- CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk)))
+ CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk)))
#define sk_OPENSSL_BLOCK_sort(sk) \
sk_sort(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
#define sk_OPENSSL_BLOCK_is_sorted(sk) \
- sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk))
+ sk_is_sorted( \
+ CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk))
#define sk_OPENSSL_BLOCK_set_cmp_func(sk, comp) \
((int (*)(const OPENSSL_BLOCK **a, const OPENSSL_BLOCK **b))sk_set_cmp_func( \
diff --git a/include/openssl/thread.h b/include/openssl/thread.h
index 568a8583..9a96fb43 100644
--- a/include/openssl/thread.h
+++ b/include/openssl/thread.h
@@ -67,14 +67,15 @@ extern "C" {
#if defined(OPENSSL_NO_THREADS)
-typedef struct crypto_mutex_st {} CRYPTO_MUTEX;
+typedef struct crypto_mutex_st {
+ char padding; /* Empty structs have different sizes in C and C++. */
+} CRYPTO_MUTEX;
#elif defined(OPENSSL_WINDOWS)
/* CRYPTO_MUTEX can appear in public header files so we really don't want to
* pull in windows.h. It's statically asserted that this structure is large
- * enough to contain a Windows CRITICAL_SECTION by thread_win.c. */
+ * enough to contain a Windows SRWLOCK by thread_win.c. */
typedef union crypto_mutex_st {
- double alignment;
- uint8_t padding[4*sizeof(void*) + 2*sizeof(int)];
+ void *handle;
} CRYPTO_MUTEX;
#elif defined(__MACH__) && defined(__APPLE__)
typedef pthread_rwlock_t CRYPTO_MUTEX;
@@ -100,7 +101,11 @@ typedef union crypto_mutex_st {
typedef uint32_t CRYPTO_refcount_t;
-/* Deprecated functions */
+/* Deprecated functions.
+ *
+ * Historically, OpenSSL required callers to provide locking callbacks.
+ * BoringSSL is thread-safe by default, but some old code calls these functions
+ * and so no-op implementations are provided. */
/* These defines do nothing but are provided to make old code easier to
* compile. */
@@ -122,6 +127,11 @@ OPENSSL_EXPORT void CRYPTO_set_locking_callback(
OPENSSL_EXPORT void CRYPTO_set_add_lock_callback(int (*func)(
int *num, int amount, int lock_num, const char *file, int line));
+/* CRYPTO_get_locking_callback returns NULL. */
+OPENSSL_EXPORT void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
+ const char *file,
+ int line);
+
/* CRYPTO_get_lock_name returns a fixed, dummy string. */
OPENSSL_EXPORT const char *CRYPTO_get_lock_name(int lock_num);
@@ -139,14 +149,6 @@ OPENSSL_EXPORT void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr);
/* CRYPTO_THREADID_current does nothing. */
OPENSSL_EXPORT void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
-
-/* Private functions.
- *
- * Some old code calls these functions and so no-op implementations are
- * provided.
- *
- * TODO(fork): cleanup callers and remove. */
-
OPENSSL_EXPORT void CRYPTO_set_id_callback(unsigned long (*func)(void));
typedef struct {
@@ -165,6 +167,15 @@ OPENSSL_EXPORT void CRYPTO_set_dynlock_destroy_callback(
void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l,
const char *file, int line));
+OPENSSL_EXPORT struct CRYPTO_dynlock_value *(
+ *CRYPTO_get_dynlock_create_callback(void))(const char *file, int line);
+
+OPENSSL_EXPORT void (*CRYPTO_get_dynlock_lock_callback(void))(
+ int mode, struct CRYPTO_dynlock_value *l, const char *file, int line);
+
+OPENSSL_EXPORT void (*CRYPTO_get_dynlock_destroy_callback(void))(
+ struct CRYPTO_dynlock_value *l, const char *file, int line);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/include/openssl/time_support.h b/include/openssl/time_support.h
index cec430d3..274b17d1 100644
--- a/include/openssl/time_support.h
+++ b/include/openssl/time_support.h
@@ -60,6 +60,7 @@
#include <openssl/base.h>
+#include <time.h>
#if defined(__cplusplus)
extern "C" {
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index e0f13997..d195940b 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -196,8 +196,10 @@ extern "C" {
/* ExtensionType values from RFC6091 */
#define TLSEXT_TYPE_cert_type 9
+/* ExtensionType values from draft-ietf-tls-tls13-latest */
+#define TLSEXT_TYPE_supported_groups 10
+
/* ExtensionType values from RFC4492 */
-#define TLSEXT_TYPE_elliptic_curves 10
#define TLSEXT_TYPE_ec_point_formats 11
/* ExtensionType value from RFC5054 */
@@ -434,11 +436,21 @@ extern "C" {
#define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA9
#define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0x0300CCAC
+/* PSK ciphersuites from mattsson-tls-ecdhe-psk-aead */
+#define TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256 0x0300D001
+#define TLS1_CK_ECDHE_PSK_WITH_AES_256_GCM_SHA384 0x0300D002
+
/* TODO(davidben): Remove this. Historically, the CK names for CHACHA20_POLY1305
* were missing 'WITH' and 'SHA256'. */
#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 \
TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+/* CECPQ1 ciphersuites. These are specific to BoringSSL and not standard. */
+#define TLS1_CK_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 0x030016B7
+#define TLS1_CK_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x030016B8
+#define TLS1_CK_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 0x030016B9
+#define TLS1_CK_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 0x030016BA
+
/* XXX
* Inconsistency alert:
* The OpenSSL names of ciphers with ephemeral DH here include the string
@@ -619,6 +631,21 @@ extern "C" {
#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 \
TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+/* PSK ciphersuites from mattsson-tls-ecdhe-psk-aead */
+#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256 "ECDHE-PSK-AES128-GCM-SHA256"
+#define TLS1_TXT_ECDHE_PSK_WITH_AES_256_GCM_SHA384 "ECDHE-PSK-AES256-GCM-SHA384"
+
+/* CECPQ1 ciphersuites. These are specific to BoringSSL and not standard. */
+#define TLS1_TXT_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 \
+ "CECPQ1-RSA-CHACHA20-POLY1305-SHA256"
+#define TLS1_TXT_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \
+ "CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256"
+#define TLS1_TXT_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 \
+ "CECPQ1-RSA-AES256-GCM-SHA384"
+#define TLS1_TXT_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 \
+ "CECPQ1-ECDSA-AES256-GCM-SHA384"
+
+
#define TLS_CT_RSA_SIGN 1
#define TLS_CT_DSS_SIGN 2
#define TLS_CT_RSA_FIXED_DH 3
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index a5aaf31b..bbc263e0 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -76,6 +76,7 @@
#include <openssl/ecdsa.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
+#include <openssl/obj.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/stack.h>
@@ -1153,6 +1154,17 @@ OPENSSL_EXPORT int X509_TRUST_get_flags(X509_TRUST *xp);
OPENSSL_EXPORT char *X509_TRUST_get0_name(X509_TRUST *xp);
OPENSSL_EXPORT int X509_TRUST_get_trust(X509_TRUST *xp);
+
+typedef struct rsa_pss_params_st {
+ X509_ALGOR *hashAlgorithm;
+ X509_ALGOR *maskGenAlgorithm;
+ ASN1_INTEGER *saltLength;
+ ASN1_INTEGER *trailerField;
+} RSA_PSS_PARAMS;
+
+DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+
+
/* PKCS7_get_certificates parses a PKCS#7, SignedData structure from |cbs| and
* appends the included certificates to |out_certs|. It returns one on success
* and zero on error. */
@@ -1227,30 +1239,29 @@ OPENSSL_EXPORT int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls,
#define X509_R_INVALID_BIT_STRING_BITS_LEFT 109
#define X509_R_INVALID_DIRECTORY 110
#define X509_R_INVALID_FIELD_NAME 111
-#define X509_R_INVALID_TRUST 112
-#define X509_R_ISSUER_MISMATCH 113
-#define X509_R_KEY_TYPE_MISMATCH 114
-#define X509_R_KEY_VALUES_MISMATCH 115
-#define X509_R_LOADING_CERT_DIR 116
-#define X509_R_LOADING_DEFAULTS 117
-#define X509_R_METHOD_NOT_SUPPORTED 118
+#define X509_R_INVALID_PSS_PARAMETERS 112
+#define X509_R_INVALID_TRUST 113
+#define X509_R_ISSUER_MISMATCH 114
+#define X509_R_KEY_TYPE_MISMATCH 115
+#define X509_R_KEY_VALUES_MISMATCH 116
+#define X509_R_LOADING_CERT_DIR 117
+#define X509_R_LOADING_DEFAULTS 118
#define X509_R_NEWER_CRL_NOT_NEWER 119
#define X509_R_NOT_PKCS7_SIGNED_DATA 120
#define X509_R_NO_CERTIFICATES_INCLUDED 121
#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 122
-#define X509_R_NO_CRL_NUMBER 123
-#define X509_R_PUBLIC_KEY_DECODE_ERROR 124
-#define X509_R_PUBLIC_KEY_ENCODE_ERROR 125
-#define X509_R_SHOULD_RETRY 126
-#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 127
-#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 128
-#define X509_R_UNKNOWN_KEY_TYPE 129
-#define X509_R_UNKNOWN_NID 130
-#define X509_R_UNKNOWN_PURPOSE_ID 131
-#define X509_R_UNKNOWN_TRUST_ID 132
-#define X509_R_UNSUPPORTED_ALGORITHM 133
-#define X509_R_WRONG_LOOKUP_TYPE 134
-#define X509_R_WRONG_TYPE 135
-#define X509_R_NO_CRLS_INCLUDED 136
+#define X509_R_NO_CRLS_INCLUDED 123
+#define X509_R_NO_CRL_NUMBER 124
+#define X509_R_PUBLIC_KEY_DECODE_ERROR 125
+#define X509_R_PUBLIC_KEY_ENCODE_ERROR 126
+#define X509_R_SHOULD_RETRY 127
+#define X509_R_UNKNOWN_KEY_TYPE 128
+#define X509_R_UNKNOWN_NID 129
+#define X509_R_UNKNOWN_PURPOSE_ID 130
+#define X509_R_UNKNOWN_TRUST_ID 131
+#define X509_R_UNSUPPORTED_ALGORITHM 132
+#define X509_R_WRONG_LOOKUP_TYPE 133
+#define X509_R_WRONG_TYPE 134
+#define X509_R_NAME_TOO_LONG 135
#endif
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index bd7ded76..5343dbd7 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -109,8 +109,10 @@ The X509_STORE then calls a function to actually verify the
certificate chain.
*/
+/* The following are legacy constants that should not be used. */
#define X509_LU_RETRY -1
#define X509_LU_FAIL 0
+
#define X509_LU_X509 1
#define X509_LU_CRL 2
#define X509_LU_PKEY 3
@@ -228,7 +230,6 @@ struct x509_lookup_st
struct x509_store_ctx_st /* X509_STORE_CTX */
{
X509_STORE *ctx;
- int current_method; /* used when looking up certs */
/* The following are set by the caller */
X509 *cert; /* The cert to check */
@@ -292,7 +293,7 @@ OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
#define X509_V_OK 0
-/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+#define X509_V_ERR_UNSPECIFIED 1
#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
#define X509_V_ERR_UNABLE_TO_GET_CRL 3
@@ -347,6 +348,7 @@ OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
#define X509_V_ERR_PERMITTED_VIOLATION 47
#define X509_V_ERR_EXCLUDED_VIOLATION 48
#define X509_V_ERR_SUBTREE_MINMAX 49
+#define X509_V_ERR_APPLICATION_VERIFICATION 50
#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51
#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52
#define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53
@@ -365,8 +367,10 @@ OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
#define X509_V_ERR_EMAIL_MISMATCH 63
#define X509_V_ERR_IP_ADDRESS_MISMATCH 64
-/* The application is not happy */
-#define X509_V_ERR_APPLICATION_VERIFICATION 50
+/* Caller error */
+#define X509_V_ERR_INVALID_CALL 65
+/* Issuer lookup error */
+#define X509_V_ERR_STORE_LOOKUP 66
/* Certificate verify flags */
@@ -436,6 +440,7 @@ OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
OPENSSL_EXPORT void X509_OBJECT_up_ref_count(X509_OBJECT *a);
OPENSSL_EXPORT void X509_OBJECT_free_contents(X509_OBJECT *a);
OPENSSL_EXPORT X509_STORE *X509_STORE_new(void );
+OPENSSL_EXPORT void X509_STORE_up_ref(X509_STORE *store);
OPENSSL_EXPORT void X509_STORE_free(X509_STORE *v);
OPENSSL_EXPORT STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm);
@@ -613,4 +618,3 @@ OPENSSL_EXPORT const X509_POLICY_NODE *
}
#endif
#endif
-
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index b7b8ba71..fa78f33a 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -600,6 +600,7 @@ OPENSSL_EXPORT GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
OPENSSL_EXPORT void X509V3_conf_free(CONF_VALUE *val);
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, int ext_nid, char *value);
OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value);
OPENSSL_EXPORT int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk);
@@ -646,6 +647,7 @@ OPENSSL_EXPORT int X509V3_add_standard_extensions(void);
OPENSSL_EXPORT STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
OPENSSL_EXPORT void *X509V3_EXT_d2i(X509_EXTENSION *ext);
OPENSSL_EXPORT void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx);
+OPENSSL_EXPORT int X509V3_EXT_free(int nid, void *ext_data);
OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt
index 9bd715a4..2eddc50d 100644
--- a/ssl/CMakeLists.txt
+++ b/ssl/CMakeLists.txt
@@ -12,21 +12,19 @@ add_library(
ssl-objects OBJECT
custom_extensions.c
+ handshake_server.c
+ handshake_client.c
d1_both.c
- d1_clnt.c
d1_lib.c
d1_meth.c
d1_pkt.c
d1_srtp.c
- d1_srvr.c
dtls_record.c
s3_both.c
- s3_clnt.c
s3_enc.c
s3_lib.c
s3_meth.c
s3_pkt.c
- s3_srvr.c
ssl_aead_ctx.c
ssl_asn1.c
ssl_buffer.c
@@ -47,21 +45,19 @@ add_library(
ssl
custom_extensions.c
+ handshake_server.c
+ handshake_client.c
d1_both.c
- d1_clnt.c
d1_lib.c
d1_meth.c
d1_pkt.c
d1_srtp.c
- d1_srvr.c
dtls_record.c
s3_both.c
- s3_clnt.c
s3_enc.c
s3_lib.c
s3_meth.c
s3_pkt.c
- s3_srvr.c
ssl_aead_ctx.c
ssl_asn1.c
ssl_buffer.c
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index ee4cbc9e..78f566e5 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -115,14 +115,12 @@
#include <assert.h>
#include <limits.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
@@ -251,12 +249,12 @@ static void dtls1_update_mtu(SSL *ssl) {
/* TODO(davidben): What is this code doing and do we need it? */
if (ssl->d1->mtu < dtls1_min_mtu() &&
!(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
- long mtu = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+ long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
ssl->d1->mtu = (unsigned)mtu;
} else {
ssl->d1->mtu = kDefaultMTU;
- BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, ssl->d1->mtu, NULL);
+ BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_SET_MTU, ssl->d1->mtu, NULL);
}
}
@@ -276,7 +274,7 @@ static size_t dtls1_max_record_size(SSL *ssl) {
}
ret -= overhead;
- size_t pending = BIO_wpending(SSL_get_wbio(ssl));
+ size_t pending = BIO_wpending(ssl->wbio);
if (ret <= pending) {
return 0;
}
@@ -292,28 +290,24 @@ static int dtls1_write_change_cipher_spec(SSL *ssl,
/* During the handshake, wbio is buffered to pack messages together. Flush the
* buffer if the ChangeCipherSpec would not fit in a packet. */
if (dtls1_max_record_size(ssl) == 0) {
- ssl->rwstate = SSL_WRITING;
- int ret = BIO_flush(SSL_get_wbio(ssl));
+ int ret = BIO_flush(ssl->wbio);
if (ret <= 0) {
+ ssl->rwstate = SSL_WRITING;
return ret;
}
- ssl->rwstate = SSL_NOTHING;
}
static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS};
int ret =
- dtls1_write_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
- sizeof(kChangeCipherSpec), use_epoch);
+ dtls1_write_record(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
+ sizeof(kChangeCipherSpec), use_epoch);
if (ret <= 0) {
return ret;
}
- if (ssl->msg_callback != NULL) {
- ssl->msg_callback(1 /* write */, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC,
- kChangeCipherSpec, sizeof(kChangeCipherSpec), ssl,
- ssl->msg_callback_arg);
- }
-
+ ssl_do_msg_callback(ssl, 1 /* write */, ssl->version,
+ SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
+ sizeof(kChangeCipherSpec));
return 1;
}
@@ -342,14 +336,13 @@ int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch) {
/* During the handshake, wbio is buffered to pack messages together. Flush
* the buffer if there isn't enough room to make progress. */
if (dtls1_max_record_size(ssl) < DTLS1_HM_HEADER_LENGTH + 1) {
- ssl->rwstate = SSL_WRITING;
- int flush_ret = BIO_flush(SSL_get_wbio(ssl));
+ int flush_ret = BIO_flush(ssl->wbio);
if (flush_ret <= 0) {
+ ssl->rwstate = SSL_WRITING;
ret = flush_ret;
goto err;
}
- ssl->rwstate = SSL_NOTHING;
- assert(BIO_wpending(SSL_get_wbio(ssl)) == 0);
+ assert(BIO_wpending(ssl->wbio) == 0);
}
size_t todo = dtls1_max_record_size(ssl);
@@ -382,8 +375,8 @@ int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch) {
goto err;
}
- int write_ret = dtls1_write_bytes(ssl, SSL3_RT_HANDSHAKE, buf, len,
- use_epoch);
+ int write_ret =
+ dtls1_write_record(ssl, SSL3_RT_HANDSHAKE, buf, len, use_epoch);
if (write_ret <= 0) {
ret = write_ret;
goto err;
@@ -392,11 +385,9 @@ int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch) {
ssl->init_num -= todo;
} while (ssl->init_num > 0);
- if (ssl->msg_callback != NULL) {
- ssl->msg_callback(
- 1 /* write */, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
- (size_t)(ssl->init_off + ssl->init_num), ssl, ssl->msg_callback_arg);
- }
+ ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_HANDSHAKE,
+ ssl->init_buf->data,
+ (size_t)(ssl->init_off + ssl->init_num));
ssl->init_off = 0;
ssl->init_num = 0;
@@ -424,24 +415,6 @@ static int dtls1_is_next_message_complete(SSL *ssl) {
frag->reassembly == NULL;
}
-/* dtls1_discard_fragment_body discards a handshake fragment body of length
- * |frag_len|. It returns one on success and zero on error.
- *
- * TODO(davidben): This function will go away when ssl_read_bytes is gone from
- * the DTLS side. */
-static int dtls1_discard_fragment_body(SSL *ssl, size_t frag_len) {
- uint8_t discard[256];
- while (frag_len > 0) {
- size_t chunk = frag_len < sizeof(discard) ? frag_len : sizeof(discard);
- int ret = dtls1_read_bytes(ssl, SSL3_RT_HANDSHAKE, discard, chunk, 0);
- if (ret != (int) chunk) {
- return 0;
- }
- frag_len -= chunk;
- }
- return 1;
-}
-
/* dtls1_get_buffered_message returns the buffered message corresponding to
* |msg_hdr|. If none exists, it creates a new one and inserts it in the
* queue. Otherwise, it checks |msg_hdr| is consistent with the existing one. It
@@ -487,93 +460,99 @@ static hm_fragment *dtls1_get_buffered_message(
return frag;
}
-/* dtls1_max_handshake_message_len returns the maximum number of bytes
- * permitted in a DTLS handshake message for |ssl|. The minimum is 16KB, but may
- * be greater if the maximum certificate list size requires it. */
-static size_t dtls1_max_handshake_message_len(const SSL *ssl) {
- size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
- if (max_len < ssl->max_cert_list) {
- return ssl->max_cert_list;
- }
- return max_len;
-}
+/* dtls1_process_handshake_record reads a handshake record and processes it. It
+ * returns one if the record was successfully processed and 0 or -1 on error. */
+static int dtls1_process_handshake_record(SSL *ssl) {
+ SSL3_RECORD *rr = &ssl->s3->rrec;
-/* dtls1_process_fragment reads a handshake fragment and processes it. It
- * returns one if a fragment was successfully processed and 0 or -1 on error. */
-static int dtls1_process_fragment(SSL *ssl) {
- /* Read handshake message header. */
- uint8_t header[DTLS1_HM_HEADER_LENGTH];
- int ret = dtls1_read_bytes(ssl, SSL3_RT_HANDSHAKE, header,
- DTLS1_HM_HEADER_LENGTH, 0);
- if (ret <= 0) {
- return ret;
+start:
+ if (rr->length == 0) {
+ int ret = dtls1_get_record(ssl);
+ if (ret <= 0) {
+ return ret;
+ }
}
- if (ret != DTLS1_HM_HEADER_LENGTH) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+
+ /* Cross-epoch records are discarded, but we may receive out-of-order
+ * application data between ChangeCipherSpec and Finished or a ChangeCipherSpec
+ * before the appropriate point in the handshake. Those must be silently
+ * discarded.
+ *
+ * However, only allow the out-of-order records in the correct epoch.
+ * Application data must come in the encrypted epoch, and ChangeCipherSpec in
+ * the unencrypted epoch (we never renegotiate). Other cases fall through and
+ * fail with a fatal error. */
+ if ((rr->type == SSL3_RT_APPLICATION_DATA &&
+ ssl->s3->aead_read_ctx != NULL) ||
+ (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC &&
+ ssl->s3->aead_read_ctx == NULL)) {
+ rr->length = 0;
+ goto start;
+ }
+
+ if (rr->type != SSL3_RT_HANDSHAKE) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
return -1;
}
- /* Parse the message fragment header. */
- struct hm_header_st msg_hdr;
- dtls1_get_message_header(header, &msg_hdr);
-
- /* TODO(davidben): dtls1_read_bytes is the wrong abstraction for DTLS. There
- * should be no need to reach into |ssl->s3->rrec.length|. */
- const size_t frag_off = msg_hdr.frag_off;
- const size_t frag_len = msg_hdr.frag_len;
- const size_t msg_len = msg_hdr.msg_len;
- if (frag_off > msg_len || frag_off + frag_len < frag_off ||
- frag_off + frag_len > msg_len ||
- msg_len > dtls1_max_handshake_message_len(ssl) ||
- frag_len > ssl->s3->rrec.length) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- return -1;
- }
+ CBS cbs;
+ CBS_init(&cbs, rr->data, rr->length);
- if (msg_hdr.seq < ssl->d1->handshake_read_seq ||
- msg_hdr.seq > (unsigned)ssl->d1->handshake_read_seq +
- kHandshakeBufferSize) {
- /* Ignore fragments from the past, or ones too far in the future. */
- if (!dtls1_discard_fragment_body(ssl, frag_len)) {
+ while (CBS_len(&cbs) > 0) {
+ /* Read a handshake fragment. */
+ struct hm_header_st msg_hdr;
+ CBS body;
+ if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
}
- return 1;
- }
- hm_fragment *frag = dtls1_get_buffered_message(ssl, &msg_hdr);
- if (frag == NULL) {
- return -1;
- }
- assert(frag->msg_header.msg_len == msg_len);
+ const size_t frag_off = msg_hdr.frag_off;
+ const size_t frag_len = msg_hdr.frag_len;
+ const size_t msg_len = msg_hdr.msg_len;
+ if (frag_off > msg_len || frag_off + frag_len < frag_off ||
+ frag_off + frag_len > msg_len ||
+ msg_len > ssl_max_handshake_message_len(ssl)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ return -1;
+ }
- if (frag->reassembly == NULL) {
- /* The message is already assembled. */
- if (!dtls1_discard_fragment_body(ssl, frag_len)) {
+ if (msg_hdr.seq < ssl->d1->handshake_read_seq ||
+ msg_hdr.seq >
+ (unsigned)ssl->d1->handshake_read_seq + kHandshakeBufferSize) {
+ /* Ignore fragments from the past, or ones too far in the future. */
+ continue;
+ }
+
+ hm_fragment *frag = dtls1_get_buffered_message(ssl, &msg_hdr);
+ if (frag == NULL) {
return -1;
}
- return 1;
- }
- assert(msg_len > 0);
+ assert(frag->msg_header.msg_len == msg_len);
- /* Read the body of the fragment. */
- ret = dtls1_read_bytes(ssl, SSL3_RT_HANDSHAKE, frag->fragment + frag_off,
- frag_len, 0);
- if (ret != (int) frag_len) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- return -1;
+ if (frag->reassembly == NULL) {
+ /* The message is already assembled. */
+ continue;
+ }
+ assert(msg_len > 0);
+
+ /* Copy the body into the fragment. */
+ memcpy(frag->fragment + frag_off, CBS_data(&body), CBS_len(&body));
+ dtls1_hm_fragment_mark(frag, frag_off, frag_off + frag_len);
}
- dtls1_hm_fragment_mark(frag, frag_off, frag_off + frag_len);
+ rr->length = 0;
+ ssl_read_buffer_discard(ssl);
return 1;
}
/* dtls1_get_message reads a handshake message of message type |msg_type| (any
- * if |msg_type| == -1), maximum acceptable body length |max|. Read an entire
- * handshake message. Handshake messages arrive in fragments. */
-long dtls1_get_message(SSL *ssl, int st1, int stn, int msg_type, long max,
+ * if |msg_type| == -1). Read an entire handshake message. Handshake messages
+ * arrive in fragments. */
+long dtls1_get_message(SSL *ssl, int msg_type,
enum ssl_hash_message_t hash_message, int *ok) {
pitem *item = NULL;
hm_fragment *frag = NULL;
@@ -593,14 +572,15 @@ long dtls1_get_message(SSL *ssl, int st1, int stn, int msg_type, long max,
goto f_err;
}
*ok = 1;
+ assert(ssl->init_buf->length >= DTLS1_HM_HEADER_LENGTH);
ssl->init_msg = (uint8_t *)ssl->init_buf->data + DTLS1_HM_HEADER_LENGTH;
- ssl->init_num = (int)ssl->s3->tmp.message_size;
+ ssl->init_num = (int)ssl->init_buf->length - DTLS1_HM_HEADER_LENGTH;
return ssl->init_num;
}
- /* Process fragments until one is found. */
+ /* Process handshake records until the next message is ready. */
while (!dtls1_is_next_message_complete(ssl)) {
- int ret = dtls1_process_fragment(ssl);
+ int ret = dtls1_process_handshake_record(ssl);
if (ret <= 0) {
*ok = 0;
return ret;
@@ -614,17 +594,11 @@ long dtls1_get_message(SSL *ssl, int st1, int stn, int msg_type, long max,
assert(ssl->d1->handshake_read_seq == frag->msg_header.seq);
assert(frag->reassembly == NULL);
- if (frag->msg_header.msg_len > (size_t)max) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
- goto err;
- }
-
/* Reconstruct the assembled message. */
- size_t len;
CBB cbb;
CBB_zero(&cbb);
- if (!BUF_MEM_grow(ssl->init_buf, (size_t)frag->msg_header.msg_len +
- DTLS1_HM_HEADER_LENGTH) ||
+ if (!BUF_MEM_reserve(ssl->init_buf, (size_t)frag->msg_header.msg_len +
+ DTLS1_HM_HEADER_LENGTH) ||
!CBB_init_fixed(&cbb, (uint8_t *)ssl->init_buf->data,
ssl->init_buf->max) ||
!CBB_add_u8(&cbb, frag->msg_header.type) ||
@@ -633,19 +607,19 @@ long dtls1_get_message(SSL *ssl, int st1, int stn, int msg_type, long max,
!CBB_add_u24(&cbb, 0 /* frag_off */) ||
!CBB_add_u24(&cbb, frag->msg_header.msg_len) ||
!CBB_add_bytes(&cbb, frag->fragment, frag->msg_header.msg_len) ||
- !CBB_finish(&cbb, NULL, &len)) {
+ !CBB_finish(&cbb, NULL, &ssl->init_buf->length)) {
CBB_cleanup(&cbb);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- assert(len == (size_t)frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH);
+ assert(ssl->init_buf->length ==
+ (size_t)frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH);
ssl->d1->handshake_read_seq++;
/* TODO(davidben): This function has a lot of implicit outputs. Simplify the
* |ssl_get_message| API. */
ssl->s3->tmp.message_type = frag->msg_header.type;
- ssl->s3->tmp.message_size = frag->msg_header.msg_len;
ssl->init_msg = (uint8_t *)ssl->init_buf->data + DTLS1_HM_HEADER_LENGTH;
ssl->init_num = frag->msg_header.msg_len;
@@ -657,16 +631,14 @@ long dtls1_get_message(SSL *ssl, int st1, int stn, int msg_type, long max,
if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
goto err;
}
- if (ssl->msg_callback) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
- ssl->init_num + DTLS1_HM_HEADER_LENGTH, ssl,
- ssl->msg_callback_arg);
- }
+
+ ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
+ ssl->init_buf->data,
+ ssl->init_num + DTLS1_HM_HEADER_LENGTH);
pitem_free(item);
dtls1_hm_fragment_free(frag);
- ssl->state = stn;
*ok = 1;
return ssl->init_num;
@@ -679,27 +651,6 @@ err:
return -1;
}
-int dtls1_read_failed(SSL *ssl, int code) {
- if (code > 0) {
- assert(0);
- return 1;
- }
-
- if (!dtls1_is_timer_expired(ssl)) {
- /* not a timeout, none of our business, let higher layers handle this. In
- * fact, it's probably an error */
- return code;
- }
-
- if (!SSL_in_init(ssl)) {
- /* done, no need to send a retransmit */
- BIO_set_flags(SSL_get_rbio(ssl), BIO_FLAGS_READ);
- return code;
- }
-
- return DTLSv1_handle_timeout(ssl);
-}
-
static uint16_t dtls1_get_queue_priority(uint16_t seq, int is_ccs) {
assert(seq * 2 >= seq);
@@ -741,25 +692,39 @@ static int dtls1_retransmit_message(SSL *ssl, hm_fragment *frag) {
ret = dtls1_do_handshake_write(ssl, use_epoch);
}
- /* TODO(davidben): Check return value? */
- (void)BIO_flush(SSL_get_wbio(ssl));
return ret;
}
-
int dtls1_retransmit_buffered_messages(SSL *ssl) {
- pqueue sent = ssl->d1->sent_messages;
- piterator iter = pqueue_iterator(sent);
- pitem *item;
+ /* Ensure we are packing handshake messages. */
+ const int was_buffered = ssl_is_wbio_buffered(ssl);
+ assert(was_buffered == SSL_in_init(ssl));
+ if (!was_buffered && !ssl_init_wbio_buffer(ssl)) {
+ return -1;
+ }
+ assert(ssl_is_wbio_buffered(ssl));
+ int ret = -1;
+ piterator iter = pqueue_iterator(ssl->d1->sent_messages);
+ pitem *item;
for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) {
hm_fragment *frag = (hm_fragment *)item->data;
if (dtls1_retransmit_message(ssl, frag) <= 0) {
- return -1;
+ goto err;
}
}
- return 1;
+ ret = BIO_flush(ssl->wbio);
+ if (ret <= 0) {
+ ssl->rwstate = SSL_WRITING;
+ goto err;
+ }
+
+err:
+ if (!was_buffered) {
+ ssl_free_wbio_buffer(ssl);
+ }
+ return ret;
}
/* dtls1_buffer_change_cipher_spec adds a ChangeCipherSpec to the current
@@ -869,13 +834,18 @@ unsigned int dtls1_min_mtu(void) {
return kMinMTU;
}
-void dtls1_get_message_header(uint8_t *data,
- struct hm_header_st *msg_hdr) {
- memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
- msg_hdr->type = *(data++);
- n2l3(data, msg_hdr->msg_len);
+int dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr,
+ CBS *out_body) {
+ memset(out_hdr, 0x00, sizeof(struct hm_header_st));
- n2s(data, msg_hdr->seq);
- n2l3(data, msg_hdr->frag_off);
- n2l3(data, msg_hdr->frag_len);
+ if (!CBS_get_u8(cbs, &out_hdr->type) ||
+ !CBS_get_u24(cbs, &out_hdr->msg_len) ||
+ !CBS_get_u16(cbs, &out_hdr->seq) ||
+ !CBS_get_u24(cbs, &out_hdr->frag_off) ||
+ !CBS_get_u24(cbs, &out_hdr->frag_len) ||
+ !CBS_get_bytes(cbs, out_body, out_hdr->frag_len)) {
+ return 0;
+ }
+
+ return 1;
}
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
deleted file mode 100644
index 7b311d62..00000000
--- a/ssl/d1_clnt.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
- */
-/* ====================================================================
- * Copyright (c) 1999-2007 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
- * openssl-core@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).
- *
- */
-/* 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/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/dh.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/md5.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-
-#include "internal.h"
-
-
-static int dtls1_get_hello_verify(SSL *ssl);
-
-int dtls1_connect(SSL *ssl) {
- BUF_MEM *buf = NULL;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
- int ret = -1;
- int new_state, state, skip = 0;
-
- assert(ssl->handshake_func == dtls1_connect);
- assert(!ssl->server);
- assert(SSL_IS_DTLS(ssl));
-
- ERR_clear_error();
- ERR_clear_system_error();
-
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
-
- ssl->in_handshake++;
-
- for (;;) {
- state = ssl->state;
-
- switch (ssl->state) {
- case SSL_ST_CONNECT:
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_START, 1);
- }
-
- if (ssl->init_buf == NULL) {
- buf = BUF_MEM_new();
- if (buf == NULL ||
- !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
- ret = -1;
- goto end;
- }
- ssl->init_buf = buf;
- buf = NULL;
- }
-
- if (!ssl_init_wbio_buffer(ssl, 0)) {
- ret = -1;
- goto end;
- }
-
- /* don't push the buffering BIO quite yet */
-
- ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
- ssl->init_num = 0;
- ssl->d1->send_cookie = 0;
- ssl->hit = 0;
- break;
-
- case SSL3_ST_CW_CLNT_HELLO_A:
- case SSL3_ST_CW_CLNT_HELLO_B:
- ssl->shutdown = 0;
- dtls1_start_timer(ssl);
- ret = ssl3_send_client_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (ssl->d1->send_cookie) {
- ssl->state = SSL3_ST_CW_FLUSH;
- ssl->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
- } else {
- ssl->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
- }
-
- ssl->init_num = 0;
- /* turn on buffering for the next lot of output */
- if (ssl->bbio != ssl->wbio) {
- ssl->wbio = BIO_push(ssl->bbio, ssl->wbio);
- }
-
- break;
-
- case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
- case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
- ret = dtls1_get_hello_verify(ssl);
- if (ret <= 0) {
- goto end;
- }
- if (ssl->d1->send_cookie) {
- /* start again, with a cookie */
- dtls1_stop_timer(ssl);
- ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
- } else {
- ssl->state = SSL3_ST_CR_SRVR_HELLO_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_SRVR_HELLO_A:
- case SSL3_ST_CR_SRVR_HELLO_B:
- ret = ssl3_get_server_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (ssl->hit) {
- ssl->state = SSL3_ST_CR_CHANGE;
- if (ssl->tlsext_ticket_expected) {
- /* receive renewed session ticket */
- ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
- }
- } else {
- ssl->state = SSL3_ST_CR_CERT_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CERT_A:
- case SSL3_ST_CR_CERT_B:
- if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
- ret = ssl3_get_server_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- if (ssl->s3->tmp.certificate_status_expected) {
- ssl->state = SSL3_ST_CR_CERT_STATUS_A;
- } else {
- ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
- }
- } else {
- skip = 1;
- ssl->state = SSL3_ST_CR_KEY_EXCH_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_VERIFY_SERVER_CERT:
- ret = ssl3_verify_server_cert(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- ssl->state = SSL3_ST_CR_KEY_EXCH_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_KEY_EXCH_A:
- case SSL3_ST_CR_KEY_EXCH_B:
- ret = ssl3_get_server_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CR_CERT_REQ_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CERT_REQ_A:
- case SSL3_ST_CR_CERT_REQ_B:
- ret = ssl3_get_certificate_request(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CR_SRVR_DONE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_SRVR_DONE_A:
- case SSL3_ST_CR_SRVR_DONE_B:
- ret = ssl3_get_server_done(ssl);
- if (ret <= 0) {
- goto end;
- }
- dtls1_stop_timer(ssl);
- if (ssl->s3->tmp.cert_req) {
- ssl->s3->tmp.next_state = SSL3_ST_CW_CERT_A;
- } else {
- ssl->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A;
- }
- ssl->init_num = 0;
- ssl->state = ssl->s3->tmp.next_state;
- break;
-
- case SSL3_ST_CW_CERT_A:
- case SSL3_ST_CW_CERT_B:
- case SSL3_ST_CW_CERT_C:
- case SSL3_ST_CW_CERT_D:
- dtls1_start_timer(ssl);
- ret = ssl3_send_client_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CW_KEY_EXCH_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_KEY_EXCH_A:
- case SSL3_ST_CW_KEY_EXCH_B:
- dtls1_start_timer(ssl);
- ret = ssl3_send_client_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- /* For TLS, cert_req is set to 2, so a cert chain
- * of nothing is sent, but no verify packet is sent */
- if (ssl->s3->tmp.cert_req == 1) {
- ssl->state = SSL3_ST_CW_CERT_VRFY_A;
- } else {
- ssl->state = SSL3_ST_CW_CHANGE_A;
- }
-
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_CERT_VRFY_A:
- case SSL3_ST_CW_CERT_VRFY_B:
- case SSL3_ST_CW_CERT_VRFY_C:
- dtls1_start_timer(ssl);
- ret = ssl3_send_cert_verify(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CW_CHANGE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_CHANGE_A:
- case SSL3_ST_CW_CHANGE_B:
- if (!ssl->hit) {
- dtls1_start_timer(ssl);
- }
- ret = dtls1_send_change_cipher_spec(ssl, SSL3_ST_CW_CHANGE_A,
- SSL3_ST_CW_CHANGE_B);
- if (ret <= 0) {
- goto end;
- }
-
- ssl->state = SSL3_ST_CW_FINISHED_A;
- ssl->init_num = 0;
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
- ret = -1;
- goto end;
- }
- break;
-
- case SSL3_ST_CW_FINISHED_A:
- case SSL3_ST_CW_FINISHED_B:
- if (!ssl->hit) {
- dtls1_start_timer(ssl);
- }
-
- ret = ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A,
- SSL3_ST_CW_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CW_FLUSH;
-
- if (ssl->hit) {
- ssl->s3->tmp.next_state = SSL_ST_OK;
- } else {
- /* Allow NewSessionTicket if ticket expected */
- if (ssl->tlsext_ticket_expected) {
- ssl->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
- } else {
- ssl->s3->tmp.next_state = SSL3_ST_CR_CHANGE;
- }
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_SESSION_TICKET_A:
- case SSL3_ST_CR_SESSION_TICKET_B:
- ret = ssl3_get_new_session_ticket(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CR_CHANGE;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CERT_STATUS_A:
- case SSL3_ST_CR_CERT_STATUS_B:
- ret = ssl3_get_cert_status(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CHANGE:
- ret = ssl->method->ssl_read_change_cipher_spec(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_READ)) {
- ret = -1;
- goto end;
- }
- ssl->state = SSL3_ST_CR_FINISHED_A;
- break;
-
- case SSL3_ST_CR_FINISHED_A:
- case SSL3_ST_CR_FINISHED_B:
- ret =
- ssl3_get_finished(ssl, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
- dtls1_stop_timer(ssl);
-
- if (ssl->hit) {
- ssl->state = SSL3_ST_CW_CHANGE_A;
- } else {
- ssl->state = SSL_ST_OK;
- }
-
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_FLUSH:
- ssl->rwstate = SSL_WRITING;
- if (BIO_flush(ssl->wbio) <= 0) {
- ret = -1;
- goto end;
- }
- ssl->rwstate = SSL_NOTHING;
- ssl->state = ssl->s3->tmp.next_state;
- break;
-
- case SSL_ST_OK:
- /* clean a few things up */
- ssl3_cleanup_key_block(ssl);
-
- /* Remove write buffering now. */
- ssl_free_wbio_buffer(ssl);
-
- ssl->init_num = 0;
- ssl->s3->initial_handshake_complete = 1;
-
- ssl_update_cache(ssl, SSL_SESS_CACHE_CLIENT);
-
- ret = 1;
-
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
- }
-
- /* done with handshaking */
- ssl->d1->handshake_read_seq = 0;
- ssl->d1->next_handshake_write_seq = 0;
- goto end;
-
- default:
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
- ret = -1;
- goto end;
- }
-
- /* did we do anything? */
- if (!ssl->s3->tmp.reuse_message && !skip) {
- if ((cb != NULL) && (ssl->state != state)) {
- new_state = ssl->state;
- ssl->state = state;
- cb(ssl, SSL_CB_CONNECT_LOOP, 1);
- ssl->state = new_state;
- }
- }
- skip = 0;
- }
-
-end:
- ssl->in_handshake--;
-
- BUF_MEM_free(buf);
- if (cb != NULL) {
- cb(ssl, SSL_CB_CONNECT_EXIT, ret);
- }
- return ret;
-}
-
-static int dtls1_get_hello_verify(SSL *ssl) {
- long n;
- int al, ok = 0;
- CBS hello_verify_request, cookie;
- uint16_t server_version;
-
- n = ssl->method->ssl_get_message(
- ssl, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
- DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, -1,
- /* Use the same maximum size as ssl3_get_server_hello. */
- 20000, ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- if (ssl->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
- ssl->d1->send_cookie = 0;
- ssl->s3->tmp.reuse_message = 1;
- return 1;
- }
-
- CBS_init(&hello_verify_request, ssl->init_msg, n);
-
- if (!CBS_get_u16(&hello_verify_request, &server_version) ||
- !CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
- CBS_len(&hello_verify_request) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (CBS_len(&cookie) > sizeof(ssl->d1->cookie)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- goto f_err;
- }
-
- memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
- ssl->d1->cookie_len = CBS_len(&cookie);
-
- ssl->d1->send_cookie = 1;
- return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- return -1;
-}
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 81079f48..73ae4cfd 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -57,12 +57,11 @@
#include <openssl/ssl.h>
#include <limits.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
@@ -158,18 +157,27 @@ int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
return cipher->algorithm_enc != SSL_RC4 && cipher->algorithm_enc != SSL_eNULL;
}
+void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
+ ssl->initial_timeout_duration_ms = duration_ms;
+}
+
void dtls1_start_timer(SSL *ssl) {
- /* If timer is not set, initialize duration with 1 second */
+ /* If timer is not set, initialize duration (by default, 1 second) */
if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
- ssl->d1->timeout_duration = 1;
+ ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
}
/* Set timeout to current time */
get_current_time(ssl, &ssl->d1->next_timeout);
/* Add duration to current time */
- ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration;
- BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
+ ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration_ms / 1000;
+ ssl->d1->next_timeout.tv_usec += (ssl->d1->timeout_duration_ms % 1000) * 1000;
+ if (ssl->d1->next_timeout.tv_usec >= 1000000) {
+ ssl->d1->next_timeout.tv_sec++;
+ ssl->d1->next_timeout.tv_usec -= 1000000;
+ }
+ BIO_ctrl(ssl->rbio, BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&ssl->d1->next_timeout);
}
@@ -231,9 +239,9 @@ int dtls1_is_timer_expired(SSL *ssl) {
}
void dtls1_double_timeout(SSL *ssl) {
- ssl->d1->timeout_duration *= 2;
- if (ssl->d1->timeout_duration > 60) {
- ssl->d1->timeout_duration = 60;
+ ssl->d1->timeout_duration_ms *= 2;
+ if (ssl->d1->timeout_duration_ms > 60000) {
+ ssl->d1->timeout_duration_ms = 60000;
}
dtls1_start_timer(ssl);
}
@@ -242,8 +250,8 @@ void dtls1_stop_timer(SSL *ssl) {
/* Reset everything */
ssl->d1->num_timeouts = 0;
memset(&ssl->d1->next_timeout, 0, sizeof(struct timeval));
- ssl->d1->timeout_duration = 1;
- BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
+ ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
+ BIO_ctrl(ssl->rbio, BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&ssl->d1->next_timeout);
/* Clear retransmission buffer */
dtls1_clear_record_buffer(ssl);
@@ -255,8 +263,7 @@ int dtls1_check_timeout_num(SSL *ssl) {
/* Reduce MTU after 2 unsuccessful retransmissions */
if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS &&
!(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
- long mtu = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0,
- NULL);
+ long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
ssl->d1->mtu = (unsigned)mtu;
}
@@ -272,6 +279,10 @@ int dtls1_check_timeout_num(SSL *ssl) {
}
int DTLSv1_handle_timeout(SSL *ssl) {
+ ssl->rwstate = SSL_NOTHING;
+ /* Functions which use SSL_get_error must clear the error queue on entry. */
+ ERR_clear_error();
+
if (!SSL_IS_DTLS(ssl)) {
return -1;
}
@@ -339,3 +350,11 @@ int dtls1_set_handshake_header(SSL *ssl, int htype, unsigned long len) {
int dtls1_handshake_write(SSL *ssl) {
return dtls1_do_handshake_write(ssl, dtls1_use_current_epoch);
}
+
+void dtls1_expect_flight(SSL *ssl) {
+ dtls1_start_timer(ssl);
+}
+
+void dtls1_received_flight(SSL *ssl) {
+ dtls1_stop_timer(ssl);
+}
diff --git a/ssl/d1_meth.c b/ssl/d1_meth.c
index 49a2595e..32a4651a 100644
--- a/ssl/d1_meth.c
+++ b/ssl/d1_meth.c
@@ -63,8 +63,6 @@ static const SSL_PROTOCOL_METHOD DTLS_protocol_method = {
1 /* is_dtls */,
dtls1_new,
dtls1_free,
- dtls1_accept,
- dtls1_connect,
dtls1_get_message,
dtls1_read_app_data,
dtls1_read_change_cipher_spec,
@@ -75,6 +73,9 @@ static const SSL_PROTOCOL_METHOD DTLS_protocol_method = {
DTLS1_HM_HEADER_LENGTH,
dtls1_set_handshake_header,
dtls1_handshake_write,
+ dtls1_send_change_cipher_spec,
+ dtls1_expect_flight,
+ dtls1_received_flight,
};
const SSL_METHOD *DTLS_method(void) {
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 7b7b2b0f..b821ab31 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -112,10 +112,11 @@
#include <openssl/ssl.h>
#include <assert.h>
-#include <stdio.h>
#include <string.h>
+#include <openssl/bio.h>
#include <openssl/buf.h>
+#include <openssl/bytestring.h>
#include <openssl/mem.h>
#include <openssl/evp.h>
#include <openssl/err.h>
@@ -124,60 +125,71 @@
#include "internal.h"
-static int do_dtls1_write(SSL *ssl, int type, const uint8_t *buf,
- unsigned int len, enum dtls1_use_epoch_t use_epoch);
-
-/* dtls1_get_record reads a new input record. On success, it places it in
- * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
- * more data is needed. */
-static int dtls1_get_record(SSL *ssl) {
+int dtls1_get_record(SSL *ssl) {
again:
+ switch (ssl->s3->recv_shutdown) {
+ case ssl_shutdown_none:
+ break;
+ case ssl_shutdown_fatal_alert:
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ return -1;
+ case ssl_shutdown_close_notify:
+ return 0;
+ }
+
/* Read a new packet if there is no unconsumed one. */
if (ssl_read_buffer_len(ssl) == 0) {
- int ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */);
- if (ret <= 0) {
- return ret;
+ int read_ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */);
+ if (read_ret < 0 && dtls1_is_timer_expired(ssl)) {
+ /* For blocking BIOs, retransmits must be handled internally. */
+ int timeout_ret = DTLSv1_handle_timeout(ssl);
+ if (timeout_ret <= 0) {
+ return timeout_ret;
+ }
+ goto again;
+ }
+ if (read_ret <= 0) {
+ return read_ret;
}
}
assert(ssl_read_buffer_len(ssl) > 0);
- /* Ensure the packet is large enough to decrypt in-place. */
- if (ssl_read_buffer_len(ssl) < ssl_record_prefix_len(ssl)) {
- ssl_read_buffer_clear(ssl);
- goto again;
- }
-
- uint8_t *out = ssl_read_buffer(ssl) + ssl_record_prefix_len(ssl);
- size_t max_out = ssl_read_buffer_len(ssl) - ssl_record_prefix_len(ssl);
+ CBS body;
uint8_t type, alert;
- size_t len, consumed;
- switch (dtls_open_record(ssl, &type, out, &len, &consumed, &alert, max_out,
- ssl_read_buffer(ssl), ssl_read_buffer_len(ssl))) {
- case ssl_open_record_success:
- ssl_read_buffer_consume(ssl, consumed);
+ size_t consumed;
+ enum ssl_open_record_t open_ret =
+ dtls_open_record(ssl, &type, &body, &consumed, &alert,
+ ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
+ ssl_read_buffer_consume(ssl, consumed);
+ switch (open_ret) {
+ case ssl_open_record_partial:
+ /* Impossible in DTLS. */
+ break;
- if (len > 0xffff) {
+ case ssl_open_record_success:
+ if (CBS_len(&body) > 0xffff) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return -1;
}
SSL3_RECORD *rr = &ssl->s3->rrec;
rr->type = type;
- rr->length = (uint16_t)len;
- rr->data = out;
+ rr->length = (uint16_t)CBS_len(&body);
+ rr->data = (uint8_t *)CBS_data(&body);
return 1;
case ssl_open_record_discard:
- ssl_read_buffer_consume(ssl, consumed);
goto again;
+ case ssl_open_record_close_notify:
+ return 0;
+
+ case ssl_open_record_fatal_alert:
+ return -1;
+
case ssl_open_record_error:
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
-
- case ssl_open_record_partial:
- /* Impossible in DTLS. */
- break;
}
assert(0);
@@ -186,250 +198,30 @@ again:
}
int dtls1_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek) {
- return dtls1_read_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len, peek);
-}
-
-int dtls1_read_change_cipher_spec(SSL *ssl) {
- uint8_t byte;
- int ret = dtls1_read_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, &byte,
- 1 /* len */, 0 /* no peek */);
- if (ret <= 0) {
- return ret;
- }
- assert(ret == 1);
-
- if (ssl->s3->rrec.length != 0 || byte != SSL3_MT_CCS) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- return -1;
- }
-
- if (ssl->msg_callback != NULL) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1,
- ssl, ssl->msg_callback_arg);
- }
-
- return 1;
-}
-
-void dtls1_read_close_notify(SSL *ssl) {
- /* Bidirectional shutdown doesn't make sense for an unordered transport. DTLS
- * alerts also aren't delivered reliably, so we may even time out because the
- * peer never received our close_notify. Report to the caller that the channel
- * has fully shut down. */
- ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
-}
-
-/* Return up to 'len' payload bytes received in 'type' records.
- * 'type' is one of the following:
- *
- * - SSL3_RT_HANDSHAKE (when dtls1_get_message calls us)
- * - SSL3_RT_CHANGE_CIPHER_SPEC (when dtls1_read_change_cipher_spec calls us)
- * - SSL3_RT_APPLICATION_DATA (when dtls1_read_app_data calls us)
- *
- * If we don't have stored data to work from, read a DTLS record first (possibly
- * multiple records if we still don't have anything to return).
- *
- * This function must handle any surprises the peer may have for us, such as
- * Alert records (e.g. close_notify) and out of records. */
-int dtls1_read_bytes(SSL *ssl, int type, unsigned char *buf, int len, int peek) {
- int al, i, ret;
- unsigned int n;
- SSL3_RECORD *rr;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
-
- if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE &&
- type != SSL3_RT_CHANGE_CIPHER_SPEC) ||
- (peek && type != SSL3_RT_APPLICATION_DATA)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
- if (!ssl->in_handshake && SSL_in_init(ssl)) {
- /* type == SSL3_RT_APPLICATION_DATA */
- i = ssl->handshake_func(ssl);
- if (i < 0) {
- return i;
- }
- if (i == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
- return -1;
- }
- }
-
-start:
- ssl->rwstate = SSL_NOTHING;
+ assert(!SSL_in_init(ssl));
- /* ssl->s3->rrec.type - is the type of record
- * ssl->s3->rrec.data - data
- * ssl->s3->rrec.off - offset into 'data' for next read
- * ssl->s3->rrec.length - number of bytes. */
- rr = &ssl->s3->rrec;
+ SSL3_RECORD *rr = &ssl->s3->rrec;
- /* Check for timeout */
- if (DTLSv1_handle_timeout(ssl) > 0) {
- goto start;
- }
-
- /* get new packet if necessary */
+again:
if (rr->length == 0) {
- ret = dtls1_get_record(ssl);
+ int ret = dtls1_get_record(ssl);
if (ret <= 0) {
- ret = dtls1_read_failed(ssl, ret);
- /* anything other than a timeout is an error */
- if (ret <= 0) {
- return ret;
- } else {
- goto start;
- }
- }
- }
-
- /* we now have a packet which can be read and processed */
-
- /* If the other end has shut down, throw anything we read away (even in
- * 'peek' mode) */
- if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
- rr->length = 0;
- ssl->rwstate = SSL_NOTHING;
- return 0;
- }
-
-
- if (type == rr->type) {
- /* Make sure that we are not getting application data when we
- * are doing a handshake for the first time. */
- if (SSL_in_init(ssl) && (type == SSL3_RT_APPLICATION_DATA) &&
- (ssl->s3->aead_read_ctx == NULL)) {
- /* TODO(davidben): Is this check redundant with the handshake_func
- * check? */
- al = SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_APP_DATA_IN_HANDSHAKE);
- goto f_err;
- }
-
- /* Discard empty records. */
- if (rr->length == 0) {
- goto start;
- }
-
- if (len <= 0) {
- return len;
- }
-
- if ((unsigned int)len > rr->length) {
- n = rr->length;
- } else {
- n = (unsigned int)len;
- }
-
- memcpy(buf, rr->data, n);
- if (!peek) {
- rr->length -= n;
- rr->data += n;
- if (rr->length == 0) {
- /* The record has been consumed, so we may now clear the buffer. */
- ssl_read_buffer_discard(ssl);
- }
- }
-
- return n;
- }
-
- /* If we get here, then type != rr->type. */
-
- /* If an alert record, process one alert out of the record. Note that we allow
- * a single record to contain multiple alerts. */
- if (rr->type == SSL3_RT_ALERT) {
- /* Alerts may not be fragmented. */
- if (rr->length < 2) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
- goto f_err;
- }
-
- if (ssl->msg_callback) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_ALERT, rr->data, 2, ssl,
- ssl->msg_callback_arg);
- }
- const uint8_t alert_level = rr->data[0];
- const uint8_t alert_descr = rr->data[1];
- rr->length -= 2;
- rr->data += 2;
-
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
-
- if (cb != NULL) {
- uint16_t alert = (alert_level << 8) | alert_descr;
- cb(ssl, SSL_CB_READ_ALERT, alert);
- }
-
- if (alert_level == SSL3_AL_WARNING) {
- ssl->s3->warn_alert = alert_descr;
- if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
- ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
- return 0;
- }
- } else if (alert_level == SSL3_AL_FATAL) {
- char tmp[16];
-
- ssl->rwstate = SSL_NOTHING;
- ssl->s3->fatal_alert = alert_descr;
- OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
- BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
- ERR_add_error_data(2, "SSL alert number ", tmp);
- ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
- SSL_CTX_remove_session(ssl->ctx, ssl->session);
- return 0;
- } else {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
- goto f_err;
+ return ret;
}
-
- goto start;
- }
-
- /* Cross-epoch records are discarded, but we may receive out-of-order
- * application data between ChangeCipherSpec and Finished or a ChangeCipherSpec
- * before the appropriate point in the handshake. Those must be silently
- * discarded.
- *
- * However, only allow the out-of-order records in the correct epoch.
- * Application data must come in the encrypted epoch, and ChangeCipherSpec in
- * the unencrypted epoch (we never renegotiate). Other cases fall through and
- * fail with a fatal error. */
- if ((rr->type == SSL3_RT_APPLICATION_DATA &&
- ssl->s3->aead_read_ctx != NULL) ||
- (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC &&
- ssl->s3->aead_read_ctx == NULL)) {
- rr->length = 0;
- goto start;
}
if (rr->type == SSL3_RT_HANDSHAKE) {
- if (type != SSL3_RT_APPLICATION_DATA) {
- /* Out-of-order handshake record while looking for ChangeCipherSpec. Drop
- * it silently. */
- assert(type == SSL3_RT_CHANGE_CIPHER_SPEC);
- rr->length = 0;
- goto start;
- }
-
/* Parse the first fragment header to determine if this is a pre-CCS or
* post-CCS handshake record. DTLS resets handshake message numbers on each
* handshake, so renegotiations and retransmissions are ambiguous. */
- if (rr->length < DTLS1_HM_HEADER_LENGTH) {
- al = SSL_AD_DECODE_ERROR;
+ CBS cbs, body;
+ struct hm_header_st msg_hdr;
+ CBS_init(&cbs, rr->data, rr->length);
+ if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
- goto f_err;
+ return -1;
}
- struct hm_header_st msg_hdr;
- dtls1_get_message_header(rr->data, &msg_hdr);
if (msg_hdr.type == SSL3_MT_FINISHED) {
if (msg_hdr.frag_off == 0) {
@@ -444,59 +236,125 @@ start:
}
rr->length = 0;
- goto start;
+ goto again;
}
/* Otherwise, this is a pre-CCS handshake message from an unsupported
* renegotiation attempt. Fall through to the error path. */
}
- al = SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+ if (rr->type != SSL3_RT_APPLICATION_DATA) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+ return -1;
+ }
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- return -1;
-}
+ /* Discard empty records. */
+ if (rr->length == 0) {
+ goto again;
+ }
-int dtls1_write_app_data(SSL *ssl, const void *buf_, int len) {
- int i;
+ if (len <= 0) {
+ return len;
+ }
+
+ if ((unsigned)len > rr->length) {
+ len = rr->length;
+ }
- if (SSL_in_init(ssl) && !ssl->in_handshake) {
- i = ssl->handshake_func(ssl);
- if (i < 0) {
- return i;
+ memcpy(buf, rr->data, len);
+ if (!peek) {
+ /* TODO(davidben): Should the record be truncated instead? This is a
+ * datagram transport. See https://crbug.com/boringssl/65. */
+ rr->length -= len;
+ rr->data += len;
+ if (rr->length == 0) {
+ /* The record has been consumed, so we may now clear the buffer. */
+ ssl_read_buffer_discard(ssl);
}
- if (i == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
- return -1;
+ }
+
+ return len;
+}
+
+int dtls1_read_change_cipher_spec(SSL *ssl) {
+ SSL3_RECORD *rr = &ssl->s3->rrec;
+
+again:
+ if (rr->length == 0) {
+ int ret = dtls1_get_record(ssl);
+ if (ret <= 0) {
+ return ret;
}
}
+ /* Drop handshake records silently. The epochs match, so this must be a
+ * retransmit of a message we already received. */
+ if (rr->type == SSL3_RT_HANDSHAKE) {
+ rr->length = 0;
+ goto again;
+ }
+
+ /* Other record types are illegal in this epoch. Note all application data
+ * records come in the encrypted epoch. */
+ if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+ return -1;
+ }
+
+ if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ return -1;
+ }
+
+ ssl_do_msg_callback(ssl, 0 /* read */, ssl->version,
+ SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, rr->length);
+
+ rr->length = 0;
+ ssl_read_buffer_discard(ssl);
+ return 1;
+}
+
+void dtls1_read_close_notify(SSL *ssl) {
+ /* Bidirectional shutdown doesn't make sense for an unordered transport. DTLS
+ * alerts also aren't delivered reliably, so we may even time out because the
+ * peer never received our close_notify. Report to the caller that the channel
+ * has fully shut down. */
+ if (ssl->s3->recv_shutdown == ssl_shutdown_none) {
+ ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
+ }
+}
+
+int dtls1_write_app_data(SSL *ssl, const void *buf_, int len) {
+ assert(!SSL_in_init(ssl));
+
if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
return -1;
}
- i = dtls1_write_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf_, len,
- dtls1_use_current_epoch);
- return i;
-}
+ if (len < 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
+ return -1;
+ }
-/* Call this to write data in records of type 'type' It will return <= 0 if not
- * all data has been sent or non-blocking IO. */
-int dtls1_write_bytes(SSL *ssl, int type, const void *buf, int len,
- enum dtls1_use_epoch_t use_epoch) {
- int i;
+ if (len == 0) {
+ return 0;
+ }
- assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
- ssl->rwstate = SSL_NOTHING;
- i = do_dtls1_write(ssl, type, buf, len, use_epoch);
- return i;
+ int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, buf_, (size_t)len,
+ dtls1_use_current_epoch);
+ if (ret <= 0) {
+ return ret;
+ }
+ return len;
}
-static int do_dtls1_write(SSL *ssl, int type, const uint8_t *buf,
- unsigned int len, enum dtls1_use_epoch_t use_epoch) {
+int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len,
+ enum dtls1_use_epoch_t use_epoch) {
+ assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
/* There should never be a pending write buffer in DTLS. One can't write half
* a datagram, so the write buffer is always dropped in
* |ssl_write_buffer_flush|. */
@@ -516,10 +374,6 @@ static int do_dtls1_write(SSL *ssl, int type, const uint8_t *buf,
return -1;
}
- if (len == 0) {
- return 0;
- }
-
size_t max_out = len + ssl_max_seal_overhead(ssl);
uint8_t *out;
size_t ciphertext_len;
@@ -535,46 +389,28 @@ static int do_dtls1_write(SSL *ssl, int type, const uint8_t *buf,
if (ret <= 0) {
return ret;
}
- return (int)len;
+ return 1;
}
int dtls1_dispatch_alert(SSL *ssl) {
- int i, j;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
- uint8_t buf[DTLS1_AL_HEADER_LENGTH];
- uint8_t *ptr = &buf[0];
-
ssl->s3->alert_dispatch = 0;
-
- memset(buf, 0x00, sizeof(buf));
- *ptr++ = ssl->s3->send_alert[0];
- *ptr++ = ssl->s3->send_alert[1];
-
- i = do_dtls1_write(ssl, SSL3_RT_ALERT, &buf[0], sizeof(buf),
- dtls1_use_current_epoch);
- if (i <= 0) {
+ int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2,
+ dtls1_use_current_epoch);
+ if (ret <= 0) {
ssl->s3->alert_dispatch = 1;
- } else {
- if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
- (void)BIO_flush(ssl->wbio);
- }
+ return ret;
+ }
- if (ssl->msg_callback) {
- ssl->msg_callback(1, ssl->version, SSL3_RT_ALERT, ssl->s3->send_alert, 2,
- ssl, ssl->msg_callback_arg);
- }
+ /* If the alert is fatal, flush the BIO now. */
+ if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
+ BIO_flush(ssl->wbio);
+ }
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
+ ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_ALERT,
+ ssl->s3->send_alert, 2);
- if (cb != NULL) {
- j = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
- cb(ssl, SSL_CB_WRITE_ALERT, j);
- }
- }
+ int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
+ ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
- return i;
+ return 1;
}
diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c
index 5dba8ef8..324bff77 100644
--- a/ssl/d1_srtp.c
+++ b/ssl/d1_srtp.c
@@ -116,17 +116,15 @@
#include <openssl/ssl.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
#include "internal.h"
-const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
+static const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
{
"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80,
},
@@ -190,6 +188,7 @@ static int ssl_ctx_make_profiles(const char *profiles_string,
}
} while (col);
+ sk_SRTP_PROTECTION_PROFILE_free(*out);
*out = profiles;
return 1;
@@ -212,7 +211,7 @@ STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl) {
return ssl->srtp_profiles;
}
- if (ssl->ctx != NULL && ssl->ctx->srtp_profiles != NULL) {
+ if (ssl->ctx->srtp_profiles != NULL) {
return ssl->ctx->srtp_profiles;
}
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
deleted file mode 100644
index 5c9624a3..00000000
--- a/ssl/d1_srvr.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
- */
-/* ====================================================================
- * Copyright (c) 1999-2007 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
- * openssl-core@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).
- *
- */
-/* 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/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/dh.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/md5.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-
-#include "internal.h"
-
-
-int dtls1_accept(SSL *ssl) {
- BUF_MEM *buf = NULL;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
- uint32_t alg_a;
- int ret = -1;
- int new_state, state, skip = 0;
-
- assert(ssl->handshake_func == dtls1_accept);
- assert(ssl->server);
- assert(SSL_IS_DTLS(ssl));
-
- ERR_clear_error();
- ERR_clear_system_error();
-
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
-
- ssl->in_handshake++;
-
- for (;;) {
- state = ssl->state;
-
- switch (ssl->state) {
- case SSL_ST_ACCEPT:
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_START, 1);
- }
-
- if (ssl->init_buf == NULL) {
- buf = BUF_MEM_new();
- if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
- ret = -1;
- goto end;
- }
- ssl->init_buf = buf;
- buf = NULL;
- }
-
- ssl->init_num = 0;
-
- if (!ssl_init_wbio_buffer(ssl, 1)) {
- ret = -1;
- goto end;
- }
-
- if (!ssl3_init_handshake_buffer(ssl)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- ret = -1;
- goto end;
- }
-
- ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
- break;
-
- case SSL3_ST_SR_CLNT_HELLO_A:
- case SSL3_ST_SR_CLNT_HELLO_B:
- case SSL3_ST_SR_CLNT_HELLO_C:
- case SSL3_ST_SR_CLNT_HELLO_D:
- ssl->shutdown = 0;
- ret = ssl3_get_client_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
- dtls1_stop_timer(ssl);
- ssl->state = SSL3_ST_SW_SRVR_HELLO_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_SRVR_HELLO_A:
- case SSL3_ST_SW_SRVR_HELLO_B:
- dtls1_start_timer(ssl);
- ret = ssl3_send_server_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (ssl->hit) {
- if (ssl->tlsext_ticket_expected) {
- ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
- } else {
- ssl->state = SSL3_ST_SW_CHANGE_A;
- }
- } else {
- ssl->state = SSL3_ST_SW_CERT_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CERT_A:
- case SSL3_ST_SW_CERT_B:
- if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
- dtls1_start_timer(ssl);
- ret = ssl3_send_server_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- if (ssl->s3->tmp.certificate_status_expected) {
- ssl->state = SSL3_ST_SW_CERT_STATUS_A;
- } else {
- ssl->state = SSL3_ST_SW_KEY_EXCH_A;
- }
- } else {
- skip = 1;
- ssl->state = SSL3_ST_SW_KEY_EXCH_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CERT_STATUS_A:
- case SSL3_ST_SW_CERT_STATUS_B:
- ret = ssl3_send_certificate_status(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_KEY_EXCH_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_KEY_EXCH_A:
- case SSL3_ST_SW_KEY_EXCH_B:
- case SSL3_ST_SW_KEY_EXCH_C:
- alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
- /* Send a ServerKeyExchange message if:
- * - The key exchange is ephemeral or anonymous
- * Diffie-Hellman.
- * - There is a PSK identity hint.
- *
- * TODO(davidben): This logic is currently duplicated
- * in s3_srvr.c. Fix this. In the meantime, keep them
- * in sync. */
- if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
- ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
- dtls1_start_timer(ssl);
- ret = ssl3_send_server_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- } else {
- skip = 1;
- }
-
- ssl->state = SSL3_ST_SW_CERT_REQ_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CERT_REQ_A:
- case SSL3_ST_SW_CERT_REQ_B:
- if (ssl->s3->tmp.cert_request) {
- dtls1_start_timer(ssl);
- ret = ssl3_send_certificate_request(ssl);
- if (ret <= 0) {
- goto end;
- }
- } else {
- skip = 1;
- }
- ssl->state = SSL3_ST_SW_SRVR_DONE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_SRVR_DONE_A:
- case SSL3_ST_SW_SRVR_DONE_B:
- dtls1_start_timer(ssl);
- ret = ssl3_send_server_done(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
- ssl->state = SSL3_ST_SW_FLUSH;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_FLUSH:
- ssl->rwstate = SSL_WRITING;
- if (BIO_flush(ssl->wbio) <= 0) {
- ret = -1;
- goto end;
- }
- ssl->rwstate = SSL_NOTHING;
- ssl->state = ssl->s3->tmp.next_state;
- break;
-
- case SSL3_ST_SR_CERT_A:
- case SSL3_ST_SR_CERT_B:
- if (ssl->s3->tmp.cert_request) {
- ret = ssl3_get_client_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- }
- ssl->init_num = 0;
- ssl->state = SSL3_ST_SR_KEY_EXCH_A;
- break;
-
- case SSL3_ST_SR_KEY_EXCH_A:
- case SSL3_ST_SR_KEY_EXCH_B:
- case SSL3_ST_SR_KEY_EXCH_C:
- ret = ssl3_get_client_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SR_CERT_VRFY_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SR_CERT_VRFY_A:
- case SSL3_ST_SR_CERT_VRFY_B:
- ret = ssl3_get_cert_verify(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SR_CHANGE;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SR_CHANGE:
- ret = ssl->method->ssl_read_change_cipher_spec(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_READ)) {
- ret = -1;
- goto end;
- }
-
- ssl->state = SSL3_ST_SR_FINISHED_A;
- break;
-
- case SSL3_ST_SR_FINISHED_A:
- case SSL3_ST_SR_FINISHED_B:
- ret = ssl3_get_finished(ssl, SSL3_ST_SR_FINISHED_A,
- SSL3_ST_SR_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
- dtls1_stop_timer(ssl);
- if (ssl->hit) {
- ssl->state = SSL_ST_OK;
- } else if (ssl->tlsext_ticket_expected) {
- ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
- } else {
- ssl->state = SSL3_ST_SW_CHANGE_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_SESSION_TICKET_A:
- case SSL3_ST_SW_SESSION_TICKET_B:
- ret = ssl3_send_new_session_ticket(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_CHANGE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CHANGE_A:
- case SSL3_ST_SW_CHANGE_B:
- ret = dtls1_send_change_cipher_spec(ssl, SSL3_ST_SW_CHANGE_A,
- SSL3_ST_SW_CHANGE_B);
-
- if (ret <= 0) {
- goto end;
- }
-
- ssl->state = SSL3_ST_SW_FINISHED_A;
- ssl->init_num = 0;
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
- ret = -1;
- goto end;
- }
- break;
-
- case SSL3_ST_SW_FINISHED_A:
- case SSL3_ST_SW_FINISHED_B:
- ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
- SSL3_ST_SW_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_FLUSH;
- if (ssl->hit) {
- ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
- } else {
- ssl->s3->tmp.next_state = SSL_ST_OK;
- }
- ssl->init_num = 0;
- break;
-
- case SSL_ST_OK:
- ssl3_cleanup_key_block(ssl);
-
- /* remove buffering on output */
- ssl_free_wbio_buffer(ssl);
-
- ssl->init_num = 0;
- ssl->s3->initial_handshake_complete = 1;
-
- ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
-
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
- }
-
- ret = 1;
-
- /* done handshaking, next message is client hello */
- ssl->d1->handshake_read_seq = 0;
- /* next message is server hello */
- ssl->d1->handshake_write_seq = 0;
- ssl->d1->next_handshake_write_seq = 0;
- goto end;
-
- default:
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
- ret = -1;
- goto end;
- }
-
- if (!ssl->s3->tmp.reuse_message && !skip) {
- if (cb != NULL && ssl->state != state) {
- new_state = ssl->state;
- ssl->state = state;
- cb(ssl, SSL_CB_ACCEPT_LOOP, 1);
- ssl->state = new_state;
- }
- }
- skip = 0;
- }
-
-end:
- ssl->in_handshake--;
- BUF_MEM_free(buf);
- if (cb != NULL) {
- cb(ssl, SSL_CB_ACCEPT_EXIT, ret);
- }
- return ret;
-}
diff --git a/ssl/dtls_record.c b/ssl/dtls_record.c
index eaf6df76..e784e556 100644
--- a/ssl/dtls_record.c
+++ b/ssl/dtls_record.c
@@ -118,6 +118,7 @@
#include <openssl/err.h>
#include "internal.h"
+#include "../crypto/internal.h"
/* to_u64_be treats |in| as a 8-byte big-endian integer and returns the value as
@@ -171,10 +172,12 @@ static void dtls1_bitmap_record(DTLS1_BITMAP *bitmap,
}
}
-enum ssl_open_record_t dtls_open_record(
- SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
- size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
- size_t in_len) {
+enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+ size_t *out_consumed,
+ uint8_t *out_alert, uint8_t *in,
+ size_t in_len) {
+ *out_consumed = 0;
+
CBS cbs;
CBS_init(&cbs, in, in_len);
@@ -195,10 +198,8 @@ enum ssl_open_record_t dtls_open_record(
return ssl_open_record_discard;
}
- if (ssl->msg_callback != NULL) {
- ssl->msg_callback(0 /* read */, 0, SSL3_RT_HEADER, in,
- DTLS1_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
- }
+ ssl_do_msg_callback(ssl, 0 /* read */, 0, SSL3_RT_HEADER, in,
+ DTLS1_RT_HEADER_LENGTH);
uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1];
if (epoch != ssl->d1->r_epoch ||
@@ -211,11 +212,9 @@ enum ssl_open_record_t dtls_open_record(
return ssl_open_record_discard;
}
- /* Decrypt the body. */
- size_t plaintext_len;
- if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, &plaintext_len, max_out,
- type, version, sequence, CBS_data(&body),
- CBS_len(&body))) {
+ /* Decrypt the body in-place. */
+ if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version, sequence,
+ (uint8_t *)CBS_data(&body), CBS_len(&body))) {
/* Bad packets are silently dropped in DTLS. See section 4.2.1 of RFC 6347.
* Clear the error queue of any errors decryption may have added. Drop the
* entire packet as it must not have come from the peer.
@@ -226,9 +225,10 @@ enum ssl_open_record_t dtls_open_record(
*out_consumed = in_len - CBS_len(&cbs);
return ssl_open_record_discard;
}
+ *out_consumed = in_len - CBS_len(&cbs);
/* Check the plaintext length. */
- if (plaintext_len > SSL3_RT_MAX_PLAIN_LENGTH) {
+ if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
*out_alert = SSL_AD_RECORD_OVERFLOW;
return ssl_open_record_error;
@@ -239,15 +239,24 @@ enum ssl_open_record_t dtls_open_record(
/* TODO(davidben): Limit the number of empty records as in TLS? This is only
* useful if we also limit discarded packets. */
+ if (type == SSL3_RT_ALERT) {
+ return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out));
+ }
+
+ ssl->s3->warning_alert_count = 0;
+
*out_type = type;
- *out_len = plaintext_len;
- *out_consumed = in_len - CBS_len(&cbs);
return ssl_open_record_success;
}
int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
uint8_t type, const uint8_t *in, size_t in_len,
enum dtls1_use_epoch_t use_epoch) {
+ if (buffers_alias(in, in_len, out, max_out)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
+ return 0;
+ }
+
/* Determine the parameters for the current epoch. */
uint16_t epoch = ssl->d1->w_epoch;
SSL_AEAD_CTX *aead = ssl->s3->aead_write_ctx;
@@ -265,12 +274,6 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
return 0;
}
- /* Check the record header does not alias any part of the input.
- * |SSL_AEAD_CTX_seal| will internally enforce other aliasing requirements. */
- if (in < out + DTLS1_RT_HEADER_LENGTH && out < in + in_len) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
- return 0;
- }
out[0] = type;
@@ -299,10 +302,8 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
*out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len;
- if (ssl->msg_callback) {
- ssl->msg_callback(1 /* write */, 0, SSL3_RT_HEADER, out,
- DTLS1_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
- }
+ ssl_do_msg_callback(ssl, 1 /* write */, 0, SSL3_RT_HEADER, out,
+ DTLS1_RT_HEADER_LENGTH);
return 1;
}
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
new file mode 100644
index 00000000..9b96bcd1
--- /dev/null
+++ b/ssl/handshake_client.c
@@ -0,0 +1,2107 @@
+/* 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.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 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
+ * openssl-core@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).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/dh.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "internal.h"
+#include "../crypto/dh/internal.h"
+
+
+static int ssl3_send_client_hello(SSL *ssl);
+static int dtls1_get_hello_verify(SSL *ssl);
+static int ssl3_get_server_hello(SSL *ssl);
+static int ssl3_get_server_certificate(SSL *ssl);
+static int ssl3_get_cert_status(SSL *ssl);
+static int ssl3_verify_server_cert(SSL *ssl);
+static int ssl3_get_server_key_exchange(SSL *ssl);
+static int ssl3_get_certificate_request(SSL *ssl);
+static int ssl3_get_server_hello_done(SSL *ssl);
+static int ssl3_send_client_certificate(SSL *ssl);
+static int ssl3_send_client_key_exchange(SSL *ssl);
+static int ssl3_send_cert_verify(SSL *ssl);
+static int ssl3_send_next_proto(SSL *ssl);
+static int ssl3_send_channel_id(SSL *ssl);
+static int ssl3_get_new_session_ticket(SSL *ssl);
+
+int ssl3_connect(SSL *ssl) {
+ BUF_MEM *buf = NULL;
+ int ret = -1;
+ int state, skip = 0;
+
+ assert(ssl->handshake_func == ssl3_connect);
+ assert(!ssl->server);
+
+ for (;;) {
+ state = ssl->state;
+
+ switch (ssl->state) {
+ case SSL_ST_CONNECT:
+ ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
+
+ if (ssl->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (buf == NULL ||
+ !BUF_MEM_reserve(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+
+ ssl->init_buf = buf;
+ buf = NULL;
+ }
+ ssl->init_num = 0;
+
+ if (!ssl_init_wbio_buffer(ssl)) {
+ ret = -1;
+ goto end;
+ }
+
+ ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
+ break;
+
+ case SSL3_ST_CW_CLNT_HELLO_A:
+ case SSL3_ST_CW_CLNT_HELLO_B:
+ ret = ssl3_send_client_hello(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (!SSL_IS_DTLS(ssl) || ssl->d1->send_cookie) {
+ ssl->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
+ } else {
+ ssl->s3->tmp.next_state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
+ }
+ ssl->state = SSL3_ST_CW_FLUSH;
+ break;
+
+ case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
+ assert(SSL_IS_DTLS(ssl));
+ ret = dtls1_get_hello_verify(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (ssl->d1->send_cookie) {
+ ssl->method->received_flight(ssl);
+ ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
+ } else {
+ ssl->state = SSL3_ST_CR_SRVR_HELLO_A;
+ }
+ break;
+
+ case SSL3_ST_CR_SRVR_HELLO_A:
+ ret = ssl3_get_server_hello(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (ssl->hit) {
+ ssl->state = SSL3_ST_CR_CHANGE;
+ if (ssl->tlsext_ticket_expected) {
+ /* receive renewed session ticket */
+ ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
+ }
+ } else {
+ ssl->state = SSL3_ST_CR_CERT_A;
+ }
+ break;
+
+ case SSL3_ST_CR_CERT_A:
+ if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ ret = ssl3_get_server_certificate(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (ssl->s3->tmp.certificate_status_expected) {
+ ssl->state = SSL3_ST_CR_CERT_STATUS_A;
+ } else {
+ ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
+ }
+ } else {
+ skip = 1;
+ ssl->state = SSL3_ST_CR_KEY_EXCH_A;
+ }
+ break;
+
+ case SSL3_ST_CR_CERT_STATUS_A:
+ ret = ssl3_get_cert_status(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
+ break;
+
+ case SSL3_ST_VERIFY_SERVER_CERT:
+ ret = ssl3_verify_server_cert(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ ssl->state = SSL3_ST_CR_KEY_EXCH_A;
+ break;
+
+ case SSL3_ST_CR_KEY_EXCH_A:
+ ret = ssl3_get_server_key_exchange(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ ssl->state = SSL3_ST_CR_CERT_REQ_A;
+ } else {
+ ssl->state = SSL3_ST_CR_SRVR_DONE_A;
+ }
+ break;
+
+ case SSL3_ST_CR_CERT_REQ_A:
+ ret = ssl3_get_certificate_request(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_CR_SRVR_DONE_A;
+ break;
+
+ case SSL3_ST_CR_SRVR_DONE_A:
+ ret = ssl3_get_server_hello_done(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->method->received_flight(ssl);
+ if (ssl->s3->tmp.cert_req) {
+ ssl->state = SSL3_ST_CW_CERT_A;
+ } else {
+ ssl->state = SSL3_ST_CW_KEY_EXCH_A;
+ }
+ break;
+
+ case SSL3_ST_CW_CERT_A:
+ case SSL3_ST_CW_CERT_B:
+ case SSL3_ST_CW_CERT_C:
+ case SSL3_ST_CW_CERT_D:
+ ret = ssl3_send_client_certificate(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_CW_KEY_EXCH_A;
+ break;
+
+ case SSL3_ST_CW_KEY_EXCH_A:
+ case SSL3_ST_CW_KEY_EXCH_B:
+ ret = ssl3_send_client_key_exchange(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ /* For TLS, cert_req is set to 2, so a cert chain
+ * of nothing is sent, but no verify packet is sent */
+ if (ssl->s3->tmp.cert_req == 1) {
+ ssl->state = SSL3_ST_CW_CERT_VRFY_A;
+ } else {
+ ssl->state = SSL3_ST_CW_CHANGE_A;
+ }
+ break;
+
+ case SSL3_ST_CW_CERT_VRFY_A:
+ case SSL3_ST_CW_CERT_VRFY_B:
+ case SSL3_ST_CW_CERT_VRFY_C:
+ ret = ssl3_send_cert_verify(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_CW_CHANGE_A;
+ break;
+
+ case SSL3_ST_CW_CHANGE_A:
+ case SSL3_ST_CW_CHANGE_B:
+ ret = ssl->method->send_change_cipher_spec(ssl, SSL3_ST_CW_CHANGE_A,
+ SSL3_ST_CW_CHANGE_B);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ ssl->state = SSL3_ST_CW_FINISHED_A;
+ if (ssl->s3->tlsext_channel_id_valid) {
+ ssl->state = SSL3_ST_CW_CHANNEL_ID_A;
+ }
+ if (ssl->s3->next_proto_neg_seen) {
+ ssl->state = SSL3_ST_CW_NEXT_PROTO_A;
+ }
+
+ if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ ret = -1;
+ goto end;
+ }
+
+ break;
+
+ case SSL3_ST_CW_NEXT_PROTO_A:
+ case SSL3_ST_CW_NEXT_PROTO_B:
+ ret = ssl3_send_next_proto(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (ssl->s3->tlsext_channel_id_valid) {
+ ssl->state = SSL3_ST_CW_CHANNEL_ID_A;
+ } else {
+ ssl->state = SSL3_ST_CW_FINISHED_A;
+ }
+ break;
+
+ case SSL3_ST_CW_CHANNEL_ID_A:
+ case SSL3_ST_CW_CHANNEL_ID_B:
+ ret = ssl3_send_channel_id(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_CW_FINISHED_A;
+ break;
+
+ case SSL3_ST_CW_FINISHED_A:
+ case SSL3_ST_CW_FINISHED_B:
+ ret = ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A,
+ SSL3_ST_CW_FINISHED_B);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_CW_FLUSH;
+
+ if (ssl->hit) {
+ ssl->s3->tmp.next_state = SSL_ST_OK;
+ } else {
+ /* This is a non-resumption handshake. If it involves ChannelID, then
+ * record the handshake hashes at this point in the session so that
+ * any resumption of this session with ChannelID can sign those
+ * hashes. */
+ ret = tls1_record_handshake_hashes_for_channel_id(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ if ((SSL_get_mode(ssl) & SSL_MODE_ENABLE_FALSE_START) &&
+ ssl3_can_false_start(ssl) &&
+ /* No False Start on renegotiation (would complicate the state
+ * machine). */
+ !ssl->s3->initial_handshake_complete) {
+ ssl->s3->tmp.next_state = SSL3_ST_FALSE_START;
+ } else {
+ /* Allow NewSessionTicket if ticket expected */
+ if (ssl->tlsext_ticket_expected) {
+ ssl->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
+ } else {
+ ssl->s3->tmp.next_state = SSL3_ST_CR_CHANGE;
+ }
+ }
+ }
+ break;
+
+ case SSL3_ST_FALSE_START:
+ /* Allow NewSessionTicket if ticket expected */
+ if (ssl->tlsext_ticket_expected) {
+ ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
+ } else {
+ ssl->state = SSL3_ST_CR_CHANGE;
+ }
+ ssl->s3->tmp.in_false_start = 1;
+
+ ssl_free_wbio_buffer(ssl);
+ ret = 1;
+ goto end;
+
+ case SSL3_ST_CR_SESSION_TICKET_A:
+ ret = ssl3_get_new_session_ticket(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_CR_CHANGE;
+ break;
+
+ case SSL3_ST_CR_CHANGE:
+ ret = ssl->method->ssl_read_change_cipher_spec(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_READ)) {
+ ret = -1;
+ goto end;
+ }
+ ssl->state = SSL3_ST_CR_FINISHED_A;
+ break;
+
+ case SSL3_ST_CR_FINISHED_A:
+ ret = ssl3_get_finished(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->method->received_flight(ssl);
+
+ if (ssl->hit) {
+ ssl->state = SSL3_ST_CW_CHANGE_A;
+ } else {
+ ssl->state = SSL_ST_OK;
+ }
+ break;
+
+ case SSL3_ST_CW_FLUSH:
+ if (BIO_flush(ssl->wbio) <= 0) {
+ ssl->rwstate = SSL_WRITING;
+ ret = -1;
+ goto end;
+ }
+ ssl->state = ssl->s3->tmp.next_state;
+ if (ssl->state != SSL_ST_OK) {
+ ssl->method->expect_flight(ssl);
+ }
+ break;
+
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(ssl);
+
+ /* |init_buf| cannot be released in DTLS because post-handshake
+ * retransmit relies on that buffer being available as scratch space.
+ *
+ * TODO(davidben): Fix this. */
+ if (!SSL_IS_DTLS(ssl)) {
+ BUF_MEM_free(ssl->init_buf);
+ ssl->init_buf = NULL;
+ ssl->init_num = 0;
+ }
+
+ /* Remove write buffering now. */
+ ssl_free_wbio_buffer(ssl);
+
+ const int is_initial_handshake = !ssl->s3->initial_handshake_complete;
+
+ ssl->s3->tmp.in_false_start = 0;
+ ssl->s3->initial_handshake_complete = 1;
+
+ if (is_initial_handshake) {
+ /* Renegotiations do not participate in session resumption. */
+ ssl_update_cache(ssl, SSL_SESS_CACHE_CLIENT);
+ }
+
+ if (SSL_IS_DTLS(ssl)) {
+ ssl->d1->handshake_read_seq = 0;
+ ssl->d1->next_handshake_write_seq = 0;
+ }
+
+ ret = 1;
+ ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
+ goto end;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ }
+
+ if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
+ int new_state = ssl->state;
+ ssl->state = state;
+ ssl_do_info_callback(ssl, SSL_CB_CONNECT_LOOP, 1);
+ ssl->state = new_state;
+ }
+ skip = 0;
+ }
+
+end:
+ BUF_MEM_free(buf);
+ ssl_do_info_callback(ssl, SSL_CB_CONNECT_EXIT, ret);
+ return ret;
+}
+
+static int ssl3_write_client_cipher_list(SSL *ssl, CBB *out) {
+ /* Prepare disabled cipher masks. */
+ ssl_set_client_disabled(ssl);
+
+ CBB child;
+ if (!CBB_add_u16_length_prefixed(out, &child)) {
+ return 0;
+ }
+
+ STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
+
+ int any_enabled = 0;
+ size_t i;
+ for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
+ const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
+ /* Skip disabled ciphers */
+ if ((cipher->algorithm_mkey & ssl->cert->mask_k) ||
+ (cipher->algorithm_auth & ssl->cert->mask_a)) {
+ continue;
+ }
+ if (SSL_CIPHER_get_min_version(cipher) >
+ ssl3_version_from_wire(ssl, ssl->client_version)) {
+ continue;
+ }
+ any_enabled = 1;
+ if (!CBB_add_u16(&child, ssl_cipher_get_value(cipher))) {
+ return 0;
+ }
+ }
+
+ /* If all ciphers were disabled, return the error to the caller. */
+ if (!any_enabled) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_AVAILABLE);
+ return 0;
+ }
+
+ /* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is
+ * added. */
+ if (ssl->client_version == SSL3_VERSION &&
+ !ssl->s3->initial_handshake_complete) {
+ if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) {
+ return 0;
+ }
+ /* The renegotiation extension is required to be at index zero. */
+ ssl->s3->tmp.extensions.sent |= (1u << 0);
+ }
+
+ if ((ssl->mode & SSL_MODE_SEND_FALLBACK_SCSV) &&
+ !CBB_add_u16(&child, SSL3_CK_FALLBACK_SCSV & 0xffff)) {
+ return 0;
+ }
+
+ return CBB_flush(out);
+}
+
+static int ssl3_send_client_hello(SSL *ssl) {
+ if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) {
+ return ssl_do_write(ssl);
+ }
+
+ /* The handshake buffer is reset on every ClientHello. Notably, in DTLS, we
+ * may send multiple ClientHellos if we receive HelloVerifyRequest. */
+ if (!ssl3_init_handshake_buffer(ssl)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ CBB cbb;
+ CBB_zero(&cbb);
+
+ assert(ssl->state == SSL3_ST_CW_CLNT_HELLO_A);
+ if (!ssl->s3->have_version) {
+ uint16_t max_version = ssl3_get_max_client_version(ssl);
+ /* Disabling all versions is silly: return an error. */
+ if (max_version == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
+ goto err;
+ }
+
+ ssl->version = max_version;
+ /* Only set |ssl->client_version| on the initial handshake. Renegotiations,
+ * although locked to a version, reuse the value. When using the plain RSA
+ * key exchange, the ClientHello version is checked in the premaster secret.
+ * Some servers fail when this value changes. */
+ ssl->client_version = max_version;
+ }
+
+ /* If the configured session has expired or was created at a disabled
+ * version, drop it. */
+ if (ssl->session != NULL &&
+ (ssl->session->session_id_length == 0 || ssl->session->not_resumable ||
+ ssl->session->timeout < (long)(time(NULL) - ssl->session->time) ||
+ !ssl3_is_version_enabled(ssl, ssl->session->ssl_version))) {
+ SSL_set_session(ssl, NULL);
+ }
+
+ /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't
+ * renegerate the client_random. The random must be reused. */
+ if ((!SSL_IS_DTLS(ssl) || !ssl->d1->send_cookie) &&
+ !ssl_fill_hello_random(ssl->s3->client_random,
+ sizeof(ssl->s3->client_random), 0 /* client */)) {
+ goto err;
+ }
+
+ /* Renegotiations do not participate in session resumption. */
+ int has_session = ssl->session != NULL &&
+ !ssl->s3->initial_handshake_complete;
+
+ CBB child;
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
+ !CBB_add_u16(&cbb, ssl->client_version) ||
+ !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ (has_session &&
+ !CBB_add_bytes(&child, ssl->session->session_id,
+ ssl->session->session_id_length))) {
+ goto err;
+ }
+
+ if (SSL_IS_DTLS(ssl)) {
+ if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) {
+ goto err;
+ }
+ }
+
+ size_t length;
+ if (!ssl3_write_client_cipher_list(ssl, &cbb) ||
+ !CBB_add_u8(&cbb, 1 /* one compression method */) ||
+ !CBB_add_u8(&cbb, 0 /* null compression */) ||
+ !ssl_add_clienthello_tlsext(ssl, &cbb,
+ CBB_len(&cbb) + SSL_HM_HEADER_LENGTH(ssl)) ||
+ !CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_HELLO, length)) {
+ goto err;
+ }
+
+ ssl->state = SSL3_ST_CW_CLNT_HELLO_B;
+ return ssl_do_write(ssl);
+
+err:
+ CBB_cleanup(&cbb);
+ return -1;
+}
+
+static int dtls1_get_hello_verify(SSL *ssl) {
+ long n;
+ int al, ok = 0;
+ CBS hello_verify_request, cookie;
+ uint16_t server_version;
+
+ n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ if (ssl->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ ssl->d1->send_cookie = 0;
+ ssl->s3->tmp.reuse_message = 1;
+ return 1;
+ }
+
+ CBS_init(&hello_verify_request, ssl->init_msg, n);
+
+ if (!CBS_get_u16(&hello_verify_request, &server_version) ||
+ !CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
+ CBS_len(&hello_verify_request) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (CBS_len(&cookie) > sizeof(ssl->d1->cookie)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto f_err;
+ }
+
+ memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
+ ssl->d1->cookie_len = CBS_len(&cookie);
+
+ ssl->d1->send_cookie = 1;
+ return 1;
+
+f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ return -1;
+}
+
+static int ssl3_get_server_hello(SSL *ssl) {
+ STACK_OF(SSL_CIPHER) *sk;
+ const SSL_CIPHER *c;
+ CERT *ct = ssl->cert;
+ int al = SSL_AD_INTERNAL_ERROR, ok;
+ long n;
+ CBS server_hello, server_random, session_id;
+ uint16_t server_version, cipher_suite;
+ uint8_t compression_method;
+
+ n = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_HELLO, ssl_hash_message,
+ &ok);
+
+ if (!ok) {
+ uint32_t err = ERR_peek_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
+ ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) {
+ /* Add a dedicated error code to the queue for a handshake_failure alert
+ * in response to ClientHello. This matches NSS's client behavior and
+ * gives a better error on a (probable) failure to negotiate initial
+ * parameters. Note: this error code comes after the original one.
+ *
+ * See https://crbug.com/446505. */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO);
+ }
+ return n;
+ }
+
+ CBS_init(&server_hello, ssl->init_msg, n);
+
+ if (!CBS_get_u16(&server_hello, &server_version) ||
+ !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
+ !CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
+ CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
+ !CBS_get_u16(&server_hello, &cipher_suite) ||
+ !CBS_get_u8(&server_hello, &compression_method)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete);
+ if (!ssl->s3->have_version) {
+ if (!ssl3_is_version_enabled(ssl, server_version)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
+ ssl->version = server_version;
+ /* Mark the version as fixed so the record-layer version is not clamped
+ * to TLS 1.0. */
+ ssl->s3->have_version = 1;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ ssl->version = server_version;
+ ssl->s3->enc_method = ssl3_get_enc_method(server_version);
+ assert(ssl->s3->enc_method != NULL);
+ /* At this point, the connection's version is known and ssl->version is
+ * fixed. Begin enforcing the record-layer version. */
+ ssl->s3->have_version = 1;
+ } else if (server_version != ssl->version) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+
+ /* Copy over the server random. */
+ memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
+
+ assert(ssl->session == NULL || ssl->session->session_id_length > 0);
+ if (!ssl->s3->initial_handshake_complete && ssl->session != NULL &&
+ CBS_mem_equal(&session_id, ssl->session->session_id,
+ ssl->session->session_id_length)) {
+ if (ssl->sid_ctx_length != ssl->session->sid_ctx_length ||
+ memcmp(ssl->session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length)) {
+ /* actually a client application bug */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL,
+ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+ goto f_err;
+ }
+ ssl->hit = 1;
+ } else {
+ /* The session wasn't resumed. Create a fresh SSL_SESSION to
+ * fill out. */
+ ssl->hit = 0;
+ if (!ssl_get_new_session(ssl, 0 /* client */)) {
+ goto f_err;
+ }
+ /* Note: session_id could be empty. */
+ ssl->session->session_id_length = CBS_len(&session_id);
+ memcpy(ssl->session->session_id, CBS_data(&session_id),
+ CBS_len(&session_id));
+ }
+
+ c = SSL_get_cipher_by_value(cipher_suite);
+ if (c == NULL) {
+ /* unknown cipher */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
+ goto f_err;
+ }
+ /* If the cipher is disabled then we didn't sent it in the ClientHello, so if
+ * the server selected it, it's an error. */
+ if ((c->algorithm_mkey & ct->mask_k) || (c->algorithm_auth & ct->mask_a) ||
+ SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
+
+ sk = ssl_get_ciphers_by_id(ssl);
+ if (!sk_SSL_CIPHER_find(sk, NULL, c)) {
+ /* we did not say we would use this cipher */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
+
+ if (ssl->hit) {
+ if (ssl->session->cipher != c) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+ goto f_err;
+ }
+ if (ssl->session->ssl_version != ssl->version) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED);
+ goto f_err;
+ }
+ } else {
+ ssl->session->cipher = c;
+ }
+ ssl->s3->tmp.new_cipher = c;
+
+ /* Now that the cipher is known, initialize the handshake hash. */
+ if (!ssl3_init_handshake_hash(ssl)) {
+ goto f_err;
+ }
+
+ /* If doing a full handshake with TLS 1.2, the server may request a client
+ * certificate which requires hashing the handshake transcript under a
+ * different hash. Otherwise, the handshake buffer may be released. */
+ if (ssl->hit || ssl3_protocol_version(ssl) < TLS1_2_VERSION ||
+ !ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ ssl3_free_handshake_buffer(ssl);
+ }
+
+ /* Only the NULL compression algorithm is supported. */
+ if (compression_method != 0) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ goto f_err;
+ }
+
+ /* TLS extensions */
+ if (!ssl_parse_serverhello_tlsext(ssl, &server_hello)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+ goto err;
+ }
+
+ /* There should be nothing left over in the record. */
+ if (CBS_len(&server_hello) != 0) {
+ /* wrong packet length */
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
+ goto f_err;
+ }
+
+ if (ssl->hit &&
+ ssl->s3->tmp.extended_master_secret !=
+ ssl->session->extended_master_secret) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ if (ssl->session->extended_master_secret) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION);
+ }
+ goto f_err;
+ }
+
+ return 1;
+
+f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+ return -1;
+}
+
+/* ssl3_check_leaf_certificate returns one if |leaf| is a suitable leaf server
+ * certificate for |ssl|. Otherwise, it returns zero and pushes an error on the
+ * error queue. */
+static int ssl3_check_leaf_certificate(SSL *ssl, X509 *leaf) {
+ int ret = 0;
+ EVP_PKEY *pkey = X509_get_pubkey(leaf);
+ if (pkey == NULL) {
+ goto err;
+ }
+
+ /* Check the certificate's type matches the cipher. */
+ const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher;
+ int expected_type = ssl_cipher_get_key_type(cipher);
+ assert(expected_type != EVP_PKEY_NONE);
+ if (pkey->type != expected_type) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE);
+ goto err;
+ }
+
+ if (cipher->algorithm_auth & SSL_aECDSA) {
+ /* TODO(davidben): This behavior is preserved from upstream. Should key
+ * usages be checked in other cases as well? */
+ /* This call populates the ex_flags field correctly */
+ X509_check_purpose(leaf, -1, 0);
+ if ((leaf->ex_flags & EXFLAG_KUSAGE) &&
+ !(leaf->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+ goto err;
+ }
+
+ if (!tls1_check_ec_cert(ssl, leaf)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
+ goto err;
+ }
+ }
+
+ ret = 1;
+
+err:
+ EVP_PKEY_free(pkey);
+ return ret;
+}
+
+static int ssl3_get_server_certificate(SSL *ssl) {
+ int al, ok, ret = -1;
+ unsigned long n;
+ X509 *x = NULL;
+ STACK_OF(X509) *sk = NULL;
+ EVP_PKEY *pkey = NULL;
+ CBS cbs, certificate_list;
+ const uint8_t *data;
+
+ n = ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE, ssl_hash_message,
+ &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ CBS_init(&cbs, ssl->init_msg, n);
+
+ sk = sk_X509_new_null();
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) ||
+ CBS_len(&certificate_list) == 0 ||
+ CBS_len(&cbs) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ while (CBS_len(&certificate_list) > 0) {
+ CBS certificate;
+ if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ /* A u24 length cannot overflow a long. */
+ data = CBS_data(&certificate);
+ x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
+ if (x == NULL) {
+ al = SSL_AD_BAD_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+ goto f_err;
+ }
+ if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (!sk_X509_push(sk, x)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
+
+ X509 *leaf = sk_X509_value(sk, 0);
+ if (!ssl3_check_leaf_certificate(ssl, leaf)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto f_err;
+ }
+
+ /* NOTE: Unlike the server half, the client's copy of |cert_chain| includes
+ * the leaf. */
+ sk_X509_pop_free(ssl->session->cert_chain, X509_free);
+ ssl->session->cert_chain = sk;
+ sk = NULL;
+
+ X509_free(ssl->session->peer);
+ ssl->session->peer = X509_up_ref(leaf);
+
+ ssl->session->verify_result = ssl->verify_result;
+
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ }
+
+err:
+ EVP_PKEY_free(pkey);
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+static int ssl3_get_cert_status(SSL *ssl) {
+ int ok, al;
+ long n;
+ CBS certificate_status, ocsp_response;
+ uint8_t status_type;
+
+ n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
+ /* A server may send status_request in ServerHello and then change
+ * its mind about sending CertificateStatus. */
+ ssl->s3->tmp.reuse_message = 1;
+ return 1;
+ }
+
+ CBS_init(&certificate_status, ssl->init_msg, n);
+ if (!CBS_get_u8(&certificate_status, &status_type) ||
+ status_type != TLSEXT_STATUSTYPE_ocsp ||
+ !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
+ CBS_len(&ocsp_response) == 0 ||
+ CBS_len(&certificate_status) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (!CBS_stow(&ocsp_response, &ssl->session->ocsp_response,
+ &ssl->session->ocsp_response_length)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ return 1;
+
+f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ return -1;
+}
+
+static int ssl3_verify_server_cert(SSL *ssl) {
+ int ret = ssl_verify_cert_chain(ssl, ssl->session->cert_chain);
+ if (ssl->verify_mode != SSL_VERIFY_NONE && ret <= 0) {
+ int al = ssl_verify_alarm_type(ssl->verify_result);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ } else {
+ ret = 1;
+ ERR_clear_error(); /* but we keep ssl->verify_result */
+ }
+
+ return ret;
+}
+
+static int ssl3_get_server_key_exchange(SSL *ssl) {
+ EVP_MD_CTX md_ctx;
+ int al, ok;
+ EVP_PKEY *pkey = NULL;
+ DH *dh = NULL;
+ EC_KEY *ecdh = NULL;
+ EC_POINT *srvr_ecpoint = NULL;
+
+ long n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);
+ if (!ok) {
+ return n;
+ }
+
+ if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
+ if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ /* In plain PSK ciphersuite, ServerKeyExchange may be omitted to send no
+ * identity hint. */
+ if (ssl->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) {
+ /* TODO(davidben): This should be reset in one place with the rest of the
+ * handshake state. */
+ OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint);
+ ssl->s3->tmp.peer_psk_identity_hint = NULL;
+ }
+ ssl->s3->tmp.reuse_message = 1;
+ return 1;
+ }
+
+ /* Retain a copy of the original CBS to compute the signature over. */
+ CBS server_key_exchange;
+ CBS_init(&server_key_exchange, ssl->init_msg, n);
+ CBS server_key_exchange_orig = server_key_exchange;
+
+ uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+ uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+ EVP_MD_CTX_init(&md_ctx);
+
+ if (alg_a & SSL_aPSK) {
+ CBS psk_identity_hint;
+
+ /* Each of the PSK key exchanges begins with a psk_identity_hint. */
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange,
+ &psk_identity_hint)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* Store PSK identity hint for later use, hint is used in
+ * ssl3_send_client_key_exchange. Assume that the maximum length of a PSK
+ * identity hint can be as long as the maximum length of a PSK identity.
+ * Also do not allow NULL characters; identities are saved as C strings.
+ *
+ * TODO(davidben): Should invalid hints be ignored? It's a hint rather than
+ * a specific identity. */
+ if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
+ CBS_contains_zero_byte(&psk_identity_hint)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* Save the identity hint as a C string. */
+ if (!CBS_strdup(&psk_identity_hint, &ssl->s3->tmp.peer_psk_identity_hint)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ }
+
+ if (alg_k & SSL_kDHE) {
+ CBS dh_p, dh_g, dh_Ys;
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
+ CBS_len(&dh_p) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
+ CBS_len(&dh_g) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
+ CBS_len(&dh_Ys) == 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ dh = DH_new();
+ if (dh == NULL) {
+ goto err;
+ }
+
+ dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL);
+ dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL);
+ if (dh->p == NULL || dh->g == NULL) {
+ goto err;
+ }
+
+ ssl->session->key_exchange_info = DH_num_bits(dh);
+ if (ssl->session->key_exchange_info < 1024) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH);
+ goto err;
+ } else if (ssl->session->key_exchange_info > 4096) {
+ /* Overly large DHE groups are prohibitively expensive, so enforce a limit
+ * to prevent a server from causing us to perform too expensive of a
+ * computation. */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DH_P_TOO_LONG);
+ goto err;
+ }
+
+ SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
+ dh = NULL;
+
+ /* Save the peer public key for later. */
+ size_t peer_key_len;
+ if (!CBS_stow(&dh_Ys, &ssl->s3->tmp.peer_key, &peer_key_len)) {
+ goto err;
+ }
+ /* |dh_Ys| was initialized with CBS_get_u16_length_prefixed, so peer_key_len
+ * fits in a uint16_t. */
+ assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
+ ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
+ } else if (alg_k & SSL_kECDHE) {
+ /* Parse the server parameters. */
+ uint8_t group_type;
+ uint16_t group_id;
+ CBS point;
+ if (!CBS_get_u8(&server_key_exchange, &group_type) ||
+ group_type != NAMED_CURVE_TYPE ||
+ !CBS_get_u16(&server_key_exchange, &group_id) ||
+ !CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+ ssl->session->key_exchange_info = group_id;
+
+ /* Ensure the group is consistent with preferences. */
+ if (!tls1_check_group_id(ssl, group_id)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+ goto f_err;
+ }
+
+ /* Initialize ECDH and save the peer public key for later. */
+ size_t peer_key_len;
+ if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) ||
+ !CBS_stow(&point, &ssl->s3->tmp.peer_key, &peer_key_len)) {
+ goto err;
+ }
+ /* |point| was initialized with CBS_get_u8_length_prefixed, so peer_key_len
+ * fits in a uint16_t. */
+ assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
+ ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
+ } else if (alg_k & SSL_kCECPQ1) {
+ if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, SSL_GROUP_CECPQ1)) {
+ goto err;
+ }
+ CBS key;
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &key)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ size_t peer_key_len;
+ if (!CBS_stow(&key, &ssl->s3->tmp.peer_key, &peer_key_len)) {
+ goto err;
+ }
+ /* |key| was initialized with CBS_get_u16_length_prefixed, so peer_key_len
+ * fits in a uint16_t. */
+ assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
+ ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
+ } else if (!(alg_k & SSL_kPSK)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /* At this point, |server_key_exchange| contains the signature, if any, while
+ * |server_key_exchange_orig| contains the entire message. From that, derive
+ * a CBS containing just the parameter. */
+ CBS parameter;
+ CBS_init(&parameter, CBS_data(&server_key_exchange_orig),
+ CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange));
+
+ /* ServerKeyExchange should be signed by the server's public key. */
+ if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ pkey = X509_get_pubkey(ssl->session->peer);
+ if (pkey == NULL) {
+ goto err;
+ }
+
+ const EVP_MD *md = NULL;
+ if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+ uint8_t hash, signature;
+ if (!CBS_get_u8(&server_key_exchange, &hash) ||
+ !CBS_get_u8(&server_key_exchange, &signature)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+ if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature, pkey)) {
+ goto f_err;
+ }
+ ssl->s3->tmp.server_key_exchange_hash = hash;
+ } else if (pkey->type == EVP_PKEY_RSA) {
+ md = EVP_md5_sha1();
+ } else {
+ md = EVP_sha1();
+ }
+
+ /* The last field in |server_key_exchange| is the signature. */
+ CBS signature;
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
+ CBS_len(&server_key_exchange) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ int sig_ok = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
+ EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->client_random,
+ SSL3_RANDOM_SIZE) &&
+ EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE) &&
+ EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&parameter),
+ CBS_len(&parameter)) &&
+ EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
+ CBS_len(&signature));
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+ sig_ok = 1;
+ ERR_clear_error();
+#endif
+ if (!sig_ok) {
+ /* bad signature */
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+ } else {
+ /* PSK ciphers are the only supported certificate-less ciphers. */
+ assert(alg_a == SSL_aPSK);
+
+ if (CBS_len(&server_key_exchange) > 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE);
+ goto f_err;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 1;
+
+f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+ EVP_PKEY_free(pkey);
+ DH_free(dh);
+ EC_POINT_free(srvr_ecpoint);
+ EC_KEY_free(ecdh);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return -1;
+}
+
+static int ca_dn_cmp(const X509_NAME **a, const X509_NAME **b) {
+ return X509_NAME_cmp(*a, *b);
+}
+
+static int ssl3_get_certificate_request(SSL *ssl) {
+ int ok, ret = 0;
+ X509_NAME *xn = NULL;
+ STACK_OF(X509_NAME) *ca_sk = NULL;
+
+ long n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ ssl->s3->tmp.cert_req = 0;
+
+ if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_HELLO_DONE) {
+ ssl->s3->tmp.reuse_message = 1;
+ /* If we get here we don't need the handshake buffer as we won't be doing
+ * client auth. */
+ ssl3_free_handshake_buffer(ssl);
+ return 1;
+ }
+
+ if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
+ CBS cbs;
+ CBS_init(&cbs, ssl->init_msg, n);
+
+ ca_sk = sk_X509_NAME_new(ca_dn_cmp);
+ if (ca_sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* get the certificate types */
+ CBS certificate_types;
+ if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto err;
+ }
+
+ if (!CBS_stow(&certificate_types, &ssl->s3->tmp.certificate_types,
+ &ssl->s3->tmp.num_certificate_types)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+ CBS supported_signature_algorithms;
+ if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
+ !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto err;
+ }
+ }
+
+ /* get the CA RDNs */
+ CBS certificate_authorities;
+ if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ while (CBS_len(&certificate_authorities) > 0) {
+ CBS distinguished_name;
+ if (!CBS_get_u16_length_prefixed(&certificate_authorities,
+ &distinguished_name)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG);
+ goto err;
+ }
+
+ const uint8_t *data = CBS_data(&distinguished_name);
+ /* A u16 length cannot overflow a long. */
+ xn = d2i_X509_NAME(NULL, &data, (long)CBS_len(&distinguished_name));
+ if (xn == NULL ||
+ data != CBS_data(&distinguished_name) + CBS_len(&distinguished_name)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto err;
+ }
+
+ if (!sk_X509_NAME_push(ca_sk, xn)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ xn = NULL;
+ }
+
+ /* we should setup a certificate to return.... */
+ ssl->s3->tmp.cert_req = 1;
+ sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
+ ssl->s3->tmp.ca_names = ca_sk;
+ ca_sk = NULL;
+
+ ret = 1;
+
+err:
+ X509_NAME_free(xn);
+ sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
+ return ret;
+}
+
+static int ssl3_get_server_hello_done(SSL *ssl) {
+ int ok;
+ long n;
+
+ n = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_HELLO_DONE,
+ ssl_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ if (n > 0) {
+ /* should contain no data */
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
+ return -1;
+ }
+
+ return 1;
+}
+
+/* ssl3_has_client_certificate returns true if a client certificate is
+ * configured. */
+static int ssl3_has_client_certificate(SSL *ssl) {
+ return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl);
+}
+
+static int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509,
+ EVP_PKEY **out_pkey) {
+ if (ssl->ctx->client_cert_cb == NULL) {
+ return 0;
+ }
+
+ int ret = ssl->ctx->client_cert_cb(ssl, out_x509, out_pkey);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ assert(*out_x509 != NULL);
+ assert(*out_pkey != NULL);
+ return 1;
+}
+
+static int ssl3_send_client_certificate(SSL *ssl) {
+ if (ssl->state == SSL3_ST_CW_CERT_A) {
+ /* Call cert_cb to update the certificate. */
+ if (ssl->cert->cert_cb) {
+ int ret = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
+ if (ret < 0) {
+ ssl->rwstate = SSL_X509_LOOKUP;
+ return -1;
+ }
+ if (ret == 0) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return -1;
+ }
+ }
+
+ if (ssl3_has_client_certificate(ssl)) {
+ ssl->state = SSL3_ST_CW_CERT_C;
+ } else {
+ ssl->state = SSL3_ST_CW_CERT_B;
+ }
+ }
+
+ if (ssl->state == SSL3_ST_CW_CERT_B) {
+ /* Call client_cert_cb to update the certificate. */
+ X509 *x509 = NULL;
+ EVP_PKEY *pkey = NULL;
+ int ret = ssl_do_client_cert_cb(ssl, &x509, &pkey);
+ if (ret < 0) {
+ ssl->rwstate = SSL_X509_LOOKUP;
+ return -1;
+ }
+
+ int setup_error = ret == 1 && (!SSL_use_certificate(ssl, x509) ||
+ !SSL_use_PrivateKey(ssl, pkey));
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+ if (setup_error) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return -1;
+ }
+
+ ssl->state = SSL3_ST_CW_CERT_C;
+ }
+
+ if (ssl->state == SSL3_ST_CW_CERT_C) {
+ if (!ssl3_has_client_certificate(ssl)) {
+ /* Without a client certificate, the handshake buffer may be released. */
+ ssl3_free_handshake_buffer(ssl);
+
+ if (ssl->version == SSL3_VERSION) {
+ /* In SSL 3.0, send no certificate by skipping both messages. */
+ ssl->s3->tmp.cert_req = 0;
+ ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
+ return 1;
+ }
+
+ /* In TLS, send an empty Certificate message. */
+ ssl->s3->tmp.cert_req = 2;
+ uint8_t *p = ssl_handshake_start(ssl);
+ l2n3(0, p);
+ if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, 3)) {
+ return -1;
+ }
+ } else if (!ssl3_output_cert_chain(ssl)) {
+ return -1;
+ }
+ ssl->state = SSL3_ST_CW_CERT_D;
+ }
+
+ assert(ssl->state == SSL3_ST_CW_CERT_D);
+ return ssl_do_write(ssl);
+}
+
+OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
+ SIZE_T_IS_SMALLER_THAN_UNSIGNED);
+
+static int ssl3_send_client_key_exchange(SSL *ssl) {
+ if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) {
+ return ssl_do_write(ssl);
+ }
+ assert(ssl->state == SSL3_ST_CW_KEY_EXCH_A);
+
+ uint8_t *pms = NULL;
+ size_t pms_len = 0;
+ CBB cbb;
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
+ goto err;
+ }
+
+ uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+ uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+
+ /* If using a PSK key exchange, prepare the pre-shared key. */
+ unsigned psk_len = 0;
+ uint8_t psk[PSK_MAX_PSK_LEN];
+ if (alg_a & SSL_aPSK) {
+ if (ssl->psk_client_callback == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
+ goto err;
+ }
+
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ memset(identity, 0, sizeof(identity));
+ psk_len = ssl->psk_client_callback(
+ ssl, ssl->s3->tmp.peer_psk_identity_hint, identity, sizeof(identity),
+ psk, sizeof(psk));
+ if (psk_len == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
+ assert(psk_len <= PSK_MAX_PSK_LEN);
+
+ OPENSSL_free(ssl->session->psk_identity);
+ ssl->session->psk_identity = BUF_strdup(identity);
+ if (ssl->session->psk_identity == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Write out psk_identity. */
+ CBB child;
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, (const uint8_t *)identity,
+ OPENSSL_strnlen(identity, sizeof(identity))) ||
+ !CBB_flush(&cbb)) {
+ goto err;
+ }
+ }
+
+ /* Depending on the key exchange method, compute |pms| and |pms_len|. */
+ if (alg_k & SSL_kRSA) {
+ pms_len = SSL_MAX_MASTER_KEY_LENGTH;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ EVP_PKEY *pkey = X509_get_pubkey(ssl->session->peer);
+ if (pkey == NULL) {
+ goto err;
+ }
+
+ RSA *rsa = EVP_PKEY_get0_RSA(pkey);
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(pkey);
+ goto err;
+ }
+
+ ssl->session->key_exchange_info = EVP_PKEY_bits(pkey);
+ EVP_PKEY_free(pkey);
+
+ pms[0] = ssl->client_version >> 8;
+ pms[1] = ssl->client_version & 0xff;
+ if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
+ goto err;
+ }
+
+ CBB child, *enc_pms = &cbb;
+ size_t enc_pms_len;
+ /* In TLS, there is a length prefix. */
+ if (ssl->version > SSL3_VERSION) {
+ if (!CBB_add_u16_length_prefixed(&cbb, &child)) {
+ goto err;
+ }
+ enc_pms = &child;
+ }
+
+ uint8_t *ptr;
+ if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) ||
+ !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len,
+ RSA_PKCS1_PADDING) ||
+ /* Log the premaster secret, if logging is enabled. */
+ !ssl_log_rsa_client_key_exchange(ssl, ptr, enc_pms_len, pms, pms_len) ||
+ !CBB_did_write(enc_pms, enc_pms_len) ||
+ !CBB_flush(&cbb)) {
+ goto err;
+ }
+ } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
+ /* Generate a keypair and serialize the public half. */
+ CBB child;
+ if (!SSL_ECDH_CTX_add_key(&ssl->s3->tmp.ecdh_ctx, &cbb, &child)) {
+ goto err;
+ }
+
+ /* Compute the premaster. */
+ uint8_t alert;
+ if (!SSL_ECDH_CTX_accept(&ssl->s3->tmp.ecdh_ctx, &child, &pms, &pms_len,
+ &alert, ssl->s3->tmp.peer_key,
+ ssl->s3->tmp.peer_key_len)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ goto err;
+ }
+ if (!CBB_flush(&cbb)) {
+ goto err;
+ }
+
+ /* The key exchange state may now be discarded. */
+ SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
+ OPENSSL_free(ssl->s3->tmp.peer_key);
+ ssl->s3->tmp.peer_key = NULL;
+ } else if (alg_k & SSL_kPSK) {
+ /* For plain PSK, other_secret is a block of 0s with the same length as
+ * the pre-shared key. */
+ pms_len = psk_len;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(pms, 0, pms_len);
+ } else {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* For a PSK cipher suite, other_secret is combined with the pre-shared
+ * key. */
+ if (alg_a & SSL_aPSK) {
+ CBB pms_cbb, child;
+ uint8_t *new_pms;
+ size_t new_pms_len;
+
+ CBB_zero(&pms_cbb);
+ if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) ||
+ !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+ !CBB_add_bytes(&child, pms, pms_len) ||
+ !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+ !CBB_add_bytes(&child, psk, psk_len) ||
+ !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) {
+ CBB_cleanup(&pms_cbb);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ pms = new_pms;
+ pms_len = new_pms_len;
+ }
+
+ /* The message must be added to the finished hash before calculating the
+ * master secret. */
+ size_t length;
+ if (!CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE, length)) {
+ goto err;
+ }
+ ssl->state = SSL3_ST_CW_KEY_EXCH_B;
+
+ ssl->session->master_key_length =
+ tls1_generate_master_secret(ssl, ssl->session->master_key, pms, pms_len);
+ if (ssl->session->master_key_length == 0) {
+ goto err;
+ }
+ ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+
+ /* SSL3_ST_CW_KEY_EXCH_B */
+ return ssl_do_write(ssl);
+
+err:
+ CBB_cleanup(&cbb);
+ if (pms != NULL) {
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ }
+ return -1;
+}
+
+static int ssl3_send_cert_verify(SSL *ssl) {
+ if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) {
+ return ssl_do_write(ssl);
+ }
+
+ CBB cbb, child;
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
+ goto err;
+ }
+
+ assert(ssl_has_private_key(ssl));
+
+ const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
+ size_t sig_len;
+ enum ssl_private_key_result_t sign_result;
+ if (ssl->state == SSL3_ST_CW_CERT_VRFY_A) {
+ /* Select and write out the digest type in TLS 1.2. */
+ const EVP_MD *md = NULL;
+ if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+ md = tls1_choose_signing_digest(ssl);
+ if (!tls12_add_sigandhash(ssl, &cbb, md)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ /* Compute the digest. In TLS 1.1 and below, the digest type is also
+ * selected here. */
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_len;
+ if (!ssl3_cert_verify_hash(ssl, digest, &digest_len, &md,
+ ssl_private_key_type(ssl))) {
+ goto err;
+ }
+
+ /* The handshake buffer is no longer necessary. */
+ ssl3_free_handshake_buffer(ssl);
+
+ /* Sign the digest. */
+ uint8_t *ptr;
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_reserve(&child, &ptr, max_sig_len)) {
+ goto err;
+ }
+ sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md,
+ digest, digest_len);
+ } else {
+ assert(ssl->state == SSL3_ST_CW_CERT_VRFY_B);
+
+ /* Skip over the already written signature algorithm and retry the
+ * signature. */
+ uint8_t *ptr;
+ if ((ssl3_protocol_version(ssl) >= TLS1_2_VERSION &&
+ !CBB_did_write(&cbb, 2)) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_reserve(&child, &ptr, max_sig_len)) {
+ goto err;
+ }
+ sign_result =
+ ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len);
+ }
+
+ switch (sign_result) {
+ case ssl_private_key_success:
+ break;
+ case ssl_private_key_failure:
+ goto err;
+ case ssl_private_key_retry:
+ ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+ ssl->state = SSL3_ST_CW_CERT_VRFY_B;
+ goto err;
+ }
+
+ size_t length;
+ if (!CBB_did_write(&child, sig_len) ||
+ !CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_VERIFY, length)) {
+ goto err;
+ }
+
+ ssl->state = SSL3_ST_CW_CERT_VRFY_C;
+ return ssl_do_write(ssl);
+
+err:
+ CBB_cleanup(&cbb);
+ return -1;
+}
+
+static int ssl3_send_next_proto(SSL *ssl) {
+ if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) {
+ return ssl_do_write(ssl);
+ }
+
+ assert(ssl->state == SSL3_ST_CW_NEXT_PROTO_A);
+
+ static const uint8_t kZero[32] = {0};
+ size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32);
+
+ CBB cbb, child;
+ size_t length;
+ CBB_zero(&cbb);
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
+ !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, ssl->s3->next_proto_negotiated,
+ ssl->s3->next_proto_negotiated_len) ||
+ !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, kZero, padding_len) ||
+ !CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_NEXT_PROTO, length)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+
+ ssl->state = SSL3_ST_CW_NEXT_PROTO_B;
+ return ssl_do_write(ssl);
+}
+
+static int ssl3_send_channel_id(SSL *ssl) {
+ if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) {
+ return ssl_do_write(ssl);
+ }
+
+ assert(ssl->state == SSL3_ST_CW_CHANNEL_ID_A);
+
+ if (ssl->tlsext_channel_id_private == NULL &&
+ ssl->ctx->channel_id_cb != NULL) {
+ EVP_PKEY *key = NULL;
+ ssl->ctx->channel_id_cb(ssl, &key);
+ if (key != NULL &&
+ !SSL_set1_tls_channel_id(ssl, key)) {
+ EVP_PKEY_free(key);
+ return -1;
+ }
+ EVP_PKEY_free(key);
+ }
+
+ if (ssl->tlsext_channel_id_private == NULL) {
+ ssl->rwstate = SSL_CHANNEL_ID_LOOKUP;
+ return -1;
+ }
+
+ EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->tlsext_channel_id_private);
+ if (ec_key == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ int ret = -1;
+ BIGNUM *x = BN_new();
+ BIGNUM *y = BN_new();
+ ECDSA_SIG *sig = NULL;
+ if (x == NULL || y == NULL ||
+ !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
+ EC_KEY_get0_public_key(ec_key),
+ x, y, NULL)) {
+ goto err;
+ }
+
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_len;
+ if (!tls1_channel_id_hash(ssl, digest, &digest_len)) {
+ goto err;
+ }
+
+ sig = ECDSA_do_sign(digest, digest_len, ec_key);
+ if (sig == NULL) {
+ goto err;
+ }
+
+ CBB cbb, child;
+ size_t length;
+ CBB_zero(&cbb);
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
+ !CBB_add_u16(&cbb, TLSEXT_TYPE_channel_id) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !BN_bn2cbb_padded(&child, 32, x) ||
+ !BN_bn2cbb_padded(&child, 32, y) ||
+ !BN_bn2cbb_padded(&child, 32, sig->r) ||
+ !BN_bn2cbb_padded(&child, 32, sig->s) ||
+ !CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS,
+ length)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ CBB_cleanup(&cbb);
+ goto err;
+ }
+
+ ssl->state = SSL3_ST_CW_CHANNEL_ID_B;
+ ret = ssl_do_write(ssl);
+
+err:
+ BN_free(x);
+ BN_free(y);
+ ECDSA_SIG_free(sig);
+ return ret;
+}
+
+static int ssl3_get_new_session_ticket(SSL *ssl) {
+ int ok, al;
+ long n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEW_SESSION_TICKET,
+ ssl_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ CBS new_session_ticket, ticket;
+ uint32_t ticket_lifetime_hint;
+ CBS_init(&new_session_ticket, ssl->init_msg, n);
+ if (!CBS_get_u32(&new_session_ticket, &ticket_lifetime_hint) ||
+ !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
+ CBS_len(&new_session_ticket) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (CBS_len(&ticket) == 0) {
+ /* RFC 5077 allows a server to change its mind and send no ticket after
+ * negotiating the extension. The value of |tlsext_ticket_expected| is
+ * checked in |ssl_update_cache| so is cleared here to avoid an unnecessary
+ * update. */
+ ssl->tlsext_ticket_expected = 0;
+ return 1;
+ }
+
+ if (ssl->hit) {
+ /* The server is sending a new ticket for an existing session. Sessions are
+ * immutable once established, so duplicate all but the ticket of the
+ * existing session. */
+ uint8_t *bytes;
+ size_t bytes_len;
+ if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &bytes, &bytes_len)) {
+ goto err;
+ }
+ SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len);
+ OPENSSL_free(bytes);
+ if (new_session == NULL) {
+ /* This should never happen. */
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ SSL_SESSION_free(ssl->session);
+ ssl->session = new_session;
+ }
+
+ if (!CBS_stow(&ticket, &ssl->session->tlsext_tick,
+ &ssl->session->tlsext_ticklen)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ssl->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
+
+ /* Generate a session ID for this session based on the session ticket. We use
+ * the session ID mechanism for detecting ticket resumption. This also fits in
+ * with assumptions elsewhere in OpenSSL.*/
+ if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), ssl->session->session_id,
+ &ssl->session->session_id_length, EVP_sha256(), NULL)) {
+ goto err;
+ }
+
+ return 1;
+
+f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+ return -1;
+}
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
new file mode 100644
index 00000000..68a013eb
--- /dev/null
+++ b/ssl/handshake_server.c
@@ -0,0 +1,2225 @@
+/* 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.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 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
+ * openssl-core@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).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/cipher.h>
+#include <openssl/dh.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/nid.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+#include "../crypto/internal.h"
+#include "../crypto/dh/internal.h"
+
+
+static int ssl3_get_initial_bytes(SSL *ssl);
+static int ssl3_get_v2_client_hello(SSL *ssl);
+static int ssl3_get_client_hello(SSL *ssl);
+static int ssl3_send_server_hello(SSL *ssl);
+static int ssl3_send_server_certificate(SSL *ssl);
+static int ssl3_send_certificate_status(SSL *ssl);
+static int ssl3_send_server_key_exchange(SSL *ssl);
+static int ssl3_send_certificate_request(SSL *ssl);
+static int ssl3_send_server_hello_done(SSL *ssl);
+static int ssl3_get_client_certificate(SSL *ssl);
+static int ssl3_get_client_key_exchange(SSL *ssl);
+static int ssl3_get_cert_verify(SSL *ssl);
+static int ssl3_get_next_proto(SSL *ssl);
+static int ssl3_get_channel_id(SSL *ssl);
+static int ssl3_send_new_session_ticket(SSL *ssl);
+
+int ssl3_accept(SSL *ssl) {
+ BUF_MEM *buf = NULL;
+ uint32_t alg_a;
+ int ret = -1;
+ int state, skip = 0;
+
+ assert(ssl->handshake_func == ssl3_accept);
+ assert(ssl->server);
+
+ for (;;) {
+ state = ssl->state;
+
+ switch (ssl->state) {
+ case SSL_ST_ACCEPT:
+ ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
+
+ if (ssl->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (!buf || !BUF_MEM_reserve(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+ ssl->init_buf = buf;
+ buf = NULL;
+ }
+ ssl->init_num = 0;
+
+ /* Enable a write buffer. This groups handshake messages within a flight
+ * into a single write. */
+ if (!ssl_init_wbio_buffer(ssl)) {
+ ret = -1;
+ goto end;
+ }
+
+ if (!ssl3_init_handshake_buffer(ssl)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+
+ if (!ssl->s3->have_version && !SSL_IS_DTLS(ssl)) {
+ ssl->state = SSL3_ST_SR_INITIAL_BYTES;
+ } else {
+ ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
+ }
+ break;
+
+ case SSL3_ST_SR_INITIAL_BYTES:
+ assert(!SSL_IS_DTLS(ssl));
+ ret = ssl3_get_initial_bytes(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ /* ssl3_get_initial_bytes sets ssl->state to one of
+ * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A on success. */
+ break;
+
+ case SSL3_ST_SR_V2_CLIENT_HELLO:
+ assert(!SSL_IS_DTLS(ssl));
+ ret = ssl3_get_v2_client_hello(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
+ break;
+
+ case SSL3_ST_SR_CLNT_HELLO_A:
+ case SSL3_ST_SR_CLNT_HELLO_B:
+ case SSL3_ST_SR_CLNT_HELLO_C:
+ ret = ssl3_get_client_hello(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->method->received_flight(ssl);
+ ssl->state = SSL3_ST_SW_SRVR_HELLO_A;
+ break;
+
+ case SSL3_ST_SW_SRVR_HELLO_A:
+ case SSL3_ST_SW_SRVR_HELLO_B:
+ ret = ssl3_send_server_hello(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (ssl->hit) {
+ if (ssl->tlsext_ticket_expected) {
+ ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
+ } else {
+ ssl->state = SSL3_ST_SW_CHANGE_A;
+ }
+ } else {
+ ssl->state = SSL3_ST_SW_CERT_A;
+ }
+ break;
+
+ case SSL3_ST_SW_CERT_A:
+ case SSL3_ST_SW_CERT_B:
+ if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ ret = ssl3_send_server_certificate(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (ssl->s3->tmp.certificate_status_expected) {
+ ssl->state = SSL3_ST_SW_CERT_STATUS_A;
+ } else {
+ ssl->state = SSL3_ST_SW_KEY_EXCH_A;
+ }
+ } else {
+ skip = 1;
+ ssl->state = SSL3_ST_SW_KEY_EXCH_A;
+ }
+ break;
+
+ case SSL3_ST_SW_CERT_STATUS_A:
+ case SSL3_ST_SW_CERT_STATUS_B:
+ ret = ssl3_send_certificate_status(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_SW_KEY_EXCH_A;
+ break;
+
+ case SSL3_ST_SW_KEY_EXCH_A:
+ case SSL3_ST_SW_KEY_EXCH_B:
+ case SSL3_ST_SW_KEY_EXCH_C:
+ alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+
+ /* PSK ciphers send ServerKeyExchange if there is an identity hint. */
+ if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
+ ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
+ ret = ssl3_send_server_key_exchange(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ } else {
+ skip = 1;
+ }
+
+ ssl->state = SSL3_ST_SW_CERT_REQ_A;
+ break;
+
+ case SSL3_ST_SW_CERT_REQ_A:
+ case SSL3_ST_SW_CERT_REQ_B:
+ if (ssl->s3->tmp.cert_request) {
+ ret = ssl3_send_certificate_request(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ } else {
+ skip = 1;
+ }
+ ssl->state = SSL3_ST_SW_SRVR_DONE_A;
+ break;
+
+ case SSL3_ST_SW_SRVR_DONE_A:
+ case SSL3_ST_SW_SRVR_DONE_B:
+ ret = ssl3_send_server_hello_done(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
+ ssl->state = SSL3_ST_SW_FLUSH;
+ break;
+
+ case SSL3_ST_SR_CERT_A:
+ if (ssl->s3->tmp.cert_request) {
+ ret = ssl3_get_client_certificate(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ }
+ ssl->state = SSL3_ST_SR_KEY_EXCH_A;
+ break;
+
+ case SSL3_ST_SR_KEY_EXCH_A:
+ case SSL3_ST_SR_KEY_EXCH_B:
+ ret = ssl3_get_client_key_exchange(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_SR_CERT_VRFY_A;
+ break;
+
+ case SSL3_ST_SR_CERT_VRFY_A:
+ ret = ssl3_get_cert_verify(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ ssl->state = SSL3_ST_SR_CHANGE;
+ break;
+
+ case SSL3_ST_SR_CHANGE:
+ ret = ssl->method->ssl_read_change_cipher_spec(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ ret = -1;
+ goto end;
+ }
+
+ if (ssl->s3->next_proto_neg_seen) {
+ ssl->state = SSL3_ST_SR_NEXT_PROTO_A;
+ } else if (ssl->s3->tlsext_channel_id_valid) {
+ ssl->state = SSL3_ST_SR_CHANNEL_ID_A;
+ } else {
+ ssl->state = SSL3_ST_SR_FINISHED_A;
+ }
+ break;
+
+ case SSL3_ST_SR_NEXT_PROTO_A:
+ ret = ssl3_get_next_proto(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (ssl->s3->tlsext_channel_id_valid) {
+ ssl->state = SSL3_ST_SR_CHANNEL_ID_A;
+ } else {
+ ssl->state = SSL3_ST_SR_FINISHED_A;
+ }
+ break;
+
+ case SSL3_ST_SR_CHANNEL_ID_A:
+ ret = ssl3_get_channel_id(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_SR_FINISHED_A;
+ break;
+
+ case SSL3_ST_SR_FINISHED_A:
+ ret = ssl3_get_finished(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ ssl->method->received_flight(ssl);
+ if (ssl->hit) {
+ ssl->state = SSL_ST_OK;
+ } else if (ssl->tlsext_ticket_expected) {
+ ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
+ } else {
+ ssl->state = SSL3_ST_SW_CHANGE_A;
+ }
+
+ /* If this is a full handshake with ChannelID then record the hashshake
+ * hashes in |ssl->session| in case we need them to verify a ChannelID
+ * signature on a resumption of this session in the future. */
+ if (!ssl->hit && ssl->s3->tlsext_channel_id_valid) {
+ ret = tls1_record_handshake_hashes_for_channel_id(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ }
+ break;
+
+ case SSL3_ST_SW_SESSION_TICKET_A:
+ case SSL3_ST_SW_SESSION_TICKET_B:
+ ret = ssl3_send_new_session_ticket(ssl);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_SW_CHANGE_A;
+ break;
+
+ case SSL3_ST_SW_CHANGE_A:
+ case SSL3_ST_SW_CHANGE_B:
+ ret = ssl->method->send_change_cipher_spec(ssl, SSL3_ST_SW_CHANGE_A,
+ SSL3_ST_SW_CHANGE_B);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_SW_FINISHED_A;
+
+ if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
+ ret = -1;
+ goto end;
+ }
+ break;
+
+ case SSL3_ST_SW_FINISHED_A:
+ case SSL3_ST_SW_FINISHED_B:
+ ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
+ SSL3_ST_SW_FINISHED_B);
+ if (ret <= 0) {
+ goto end;
+ }
+ ssl->state = SSL3_ST_SW_FLUSH;
+ if (ssl->hit) {
+ ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
+ } else {
+ ssl->s3->tmp.next_state = SSL_ST_OK;
+ }
+ break;
+
+ case SSL3_ST_SW_FLUSH:
+ if (BIO_flush(ssl->wbio) <= 0) {
+ ssl->rwstate = SSL_WRITING;
+ ret = -1;
+ goto end;
+ }
+
+ ssl->state = ssl->s3->tmp.next_state;
+ if (ssl->state != SSL_ST_OK) {
+ ssl->method->expect_flight(ssl);
+ }
+ break;
+
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(ssl);
+
+ /* In DTLS, |init_buf| cannot be released because post-handshake
+ * retransmit relies on that buffer being available as scratch space.
+ *
+ * TODO(davidben): Fix this. */
+ if (!SSL_IS_DTLS(ssl)) {
+ BUF_MEM_free(ssl->init_buf);
+ ssl->init_buf = NULL;
+ ssl->init_num = 0;
+ }
+
+ /* remove buffering on output */
+ ssl_free_wbio_buffer(ssl);
+
+ /* If we aren't retaining peer certificates then we can discard it
+ * now. */
+ if (ssl->ctx->retain_only_sha256_of_client_certs) {
+ X509_free(ssl->session->peer);
+ ssl->session->peer = NULL;
+ sk_X509_pop_free(ssl->session->cert_chain, X509_free);
+ ssl->session->cert_chain = NULL;
+ }
+
+ if (SSL_IS_DTLS(ssl)) {
+ ssl->d1->handshake_read_seq = 0;
+ ssl->d1->handshake_write_seq = 0;
+ ssl->d1->next_handshake_write_seq = 0;
+ }
+
+ ssl->s3->initial_handshake_complete = 1;
+
+ ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
+
+ ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
+
+ ret = 1;
+ goto end;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ }
+
+ if (!ssl->s3->tmp.reuse_message && !skip && ssl->state != state) {
+ int new_state = ssl->state;
+ ssl->state = state;
+ ssl_do_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 1);
+ ssl->state = new_state;
+ }
+ skip = 0;
+ }
+
+end:
+ BUF_MEM_free(buf);
+ ssl_do_info_callback(ssl, SSL_CB_ACCEPT_EXIT, ret);
+ return ret;
+}
+
+static int ssl3_get_initial_bytes(SSL *ssl) {
+ /* Read the first 5 bytes, the size of the TLS record header. This is
+ * sufficient to detect a V2ClientHello and ensures that we never read beyond
+ * the first record. */
+ int ret = ssl_read_buffer_extend_to(ssl, SSL3_RT_HEADER_LENGTH);
+ if (ret <= 0) {
+ return ret;
+ }
+ assert(ssl_read_buffer_len(ssl) == SSL3_RT_HEADER_LENGTH);
+ const uint8_t *p = ssl_read_buffer(ssl);
+
+ /* Some dedicated error codes for protocol mixups should the application wish
+ * to interpret them differently. (These do not overlap with ClientHello or
+ * V2ClientHello.) */
+ if (strncmp("GET ", (const char *)p, 4) == 0 ||
+ strncmp("POST ", (const char *)p, 5) == 0 ||
+ strncmp("HEAD ", (const char *)p, 5) == 0 ||
+ strncmp("PUT ", (const char *)p, 4) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_HTTP_REQUEST);
+ return -1;
+ }
+ if (strncmp("CONNE", (const char *)p, 5) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_HTTPS_PROXY_REQUEST);
+ return -1;
+ }
+
+ /* Determine if this is a V2ClientHello. */
+ if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO &&
+ p[3] >= SSL3_VERSION_MAJOR) {
+ /* This is a V2ClientHello. */
+ ssl->state = SSL3_ST_SR_V2_CLIENT_HELLO;
+ return 1;
+ }
+
+ /* Fall through to the standard logic. */
+ ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
+ return 1;
+}
+
+static int ssl3_get_v2_client_hello(SSL *ssl) {
+ const uint8_t *p;
+ int ret;
+ CBS v2_client_hello, cipher_specs, session_id, challenge;
+ size_t msg_length, rand_len;
+ uint8_t msg_type;
+ uint16_t version, cipher_spec_length, session_id_length, challenge_length;
+ CBB client_hello, hello_body, cipher_suites;
+ uint8_t random[SSL3_RANDOM_SIZE];
+
+ /* Determine the length of the V2ClientHello. */
+ assert(ssl_read_buffer_len(ssl) >= SSL3_RT_HEADER_LENGTH);
+ p = ssl_read_buffer(ssl);
+ msg_length = ((p[0] & 0x7f) << 8) | p[1];
+ if (msg_length > (1024 * 4)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE);
+ return -1;
+ }
+ if (msg_length < SSL3_RT_HEADER_LENGTH - 2) {
+ /* Reject lengths that are too short early. We have already read
+ * |SSL3_RT_HEADER_LENGTH| bytes, so we should not attempt to process an
+ * (invalid) V2ClientHello which would be shorter than that. */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_LENGTH_MISMATCH);
+ return -1;
+ }
+
+ /* Read the remainder of the V2ClientHello. */
+ ret = ssl_read_buffer_extend_to(ssl, 2 + msg_length);
+ if (ret <= 0) {
+ return ret;
+ }
+ assert(ssl_read_buffer_len(ssl) == msg_length + 2);
+ CBS_init(&v2_client_hello, ssl_read_buffer(ssl) + 2, msg_length);
+
+ /* The V2ClientHello without the length is incorporated into the handshake
+ * hash. */
+ if (!ssl3_update_handshake_hash(ssl, CBS_data(&v2_client_hello),
+ CBS_len(&v2_client_hello))) {
+ return -1;
+ }
+
+ ssl_do_msg_callback(ssl, 0 /* read */, SSL2_VERSION, 0,
+ CBS_data(&v2_client_hello), CBS_len(&v2_client_hello));
+
+ if (!CBS_get_u8(&v2_client_hello, &msg_type) ||
+ !CBS_get_u16(&v2_client_hello, &version) ||
+ !CBS_get_u16(&v2_client_hello, &cipher_spec_length) ||
+ !CBS_get_u16(&v2_client_hello, &session_id_length) ||
+ !CBS_get_u16(&v2_client_hello, &challenge_length) ||
+ !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) ||
+ !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) ||
+ !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) ||
+ CBS_len(&v2_client_hello) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ return -1;
+ }
+
+ /* msg_type has already been checked. */
+ assert(msg_type == SSL2_MT_CLIENT_HELLO);
+
+ /* The client_random is the V2ClientHello challenge. Truncate or
+ * left-pad with zeros as needed. */
+ memset(random, 0, SSL3_RANDOM_SIZE);
+ rand_len = CBS_len(&challenge);
+ if (rand_len > SSL3_RANDOM_SIZE) {
+ rand_len = SSL3_RANDOM_SIZE;
+ }
+ memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
+ rand_len);
+
+ /* Write out an equivalent SSLv3 ClientHello. */
+ CBB_zero(&client_hello);
+ if (!CBB_init_fixed(&client_hello, (uint8_t *)ssl->init_buf->data,
+ ssl->init_buf->max) ||
+ !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
+ !CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
+ !CBB_add_u16(&hello_body, version) ||
+ !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
+ /* No session id. */
+ !CBB_add_u8(&hello_body, 0) ||
+ !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+
+ /* Copy the cipher suites. */
+ while (CBS_len(&cipher_specs) > 0) {
+ uint32_t cipher_spec;
+ if (!CBS_get_u24(&cipher_specs, &cipher_spec)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ return -1;
+ }
+
+ /* Skip SSLv2 ciphers. */
+ if ((cipher_spec & 0xff0000) != 0) {
+ continue;
+ }
+ if (!CBB_add_u16(&cipher_suites, cipher_spec)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ }
+
+ /* Add the null compression scheme and finish. */
+ if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) ||
+ !CBB_finish(&client_hello, NULL, &ssl->init_buf->length)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /* Mark the message for "re"-use by the version-specific method. */
+ ssl->s3->tmp.reuse_message = 1;
+ ssl->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO;
+ ssl->s3->tmp.message_complete = 1;
+
+ /* Consume and discard the V2ClientHello. */
+ ssl_read_buffer_consume(ssl, 2 + msg_length);
+ ssl_read_buffer_discard(ssl);
+
+ return 1;
+}
+
+static int ssl3_get_client_hello(SSL *ssl) {
+ int ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
+ long n;
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) *ciphers = NULL;
+ struct ssl_early_callback_ctx early_ctx;
+ CBS client_hello;
+ uint16_t client_version;
+ CBS client_random, session_id, cipher_suites, compression_methods;
+ SSL_SESSION *session = NULL;
+
+ /* We do this so that we will respond with our native type. If we are TLSv1
+ * and we get SSLv3, we will respond with TLSv1, This down switching should
+ * be handled by a different method. If we are SSLv3, we will respond with
+ * SSLv3, even if prompted with TLSv1. */
+ switch (ssl->state) {
+ case SSL3_ST_SR_CLNT_HELLO_A:
+ n = ssl->method->ssl_get_message(ssl, SSL3_MT_CLIENT_HELLO,
+ ssl_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ ssl->state = SSL3_ST_SR_CLNT_HELLO_B;
+ /* fallthrough */
+ case SSL3_ST_SR_CLNT_HELLO_B:
+ case SSL3_ST_SR_CLNT_HELLO_C:
+ /* We have previously parsed the ClientHello message, and can't call
+ * ssl_get_message again without hashing the message into the Finished
+ * digest again. */
+ n = ssl->init_num;
+
+ memset(&early_ctx, 0, sizeof(early_ctx));
+ early_ctx.ssl = ssl;
+ early_ctx.client_hello = ssl->init_msg;
+ early_ctx.client_hello_len = n;
+ if (!ssl_early_callback_init(&early_ctx)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
+ goto f_err;
+ }
+
+ if (ssl->state == SSL3_ST_SR_CLNT_HELLO_B &&
+ ssl->ctx->select_certificate_cb != NULL) {
+ ssl->state = SSL3_ST_SR_CLNT_HELLO_C;
+ switch (ssl->ctx->select_certificate_cb(&early_ctx)) {
+ case 0:
+ ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
+ goto err;
+
+ case -1:
+ /* Connection rejected. */
+ al = SSL_AD_ACCESS_DENIED;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
+ goto f_err;
+
+ default:
+ /* fallthrough */;
+ }
+ }
+ ssl->state = SSL3_ST_SR_CLNT_HELLO_C;
+ break;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
+ return -1;
+ }
+
+ CBS_init(&client_hello, ssl->init_msg, n);
+ if (!CBS_get_u16(&client_hello, &client_version) ||
+ !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) ||
+ !CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
+ CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* use version from inside client hello, not from record header (may differ:
+ * see RFC 2246, Appendix E, second paragraph) */
+ ssl->client_version = client_version;
+
+ /* Load the client random. */
+ memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
+
+ if (SSL_IS_DTLS(ssl)) {
+ CBS cookie;
+
+ if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
+ CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+ }
+
+ /* Note: This codepath may run twice if |ssl_get_prev_session| completes
+ * asynchronously.
+ *
+ * TODO(davidben): Clean up the order of events around ClientHello
+ * processing. */
+ if (!ssl->s3->have_version) {
+ /* Select version to use */
+ uint16_t version = ssl3_get_mutual_version(ssl, client_version);
+ if (version == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
+ ssl->version = ssl->client_version;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ ssl->version = version;
+ ssl->s3->enc_method = ssl3_get_enc_method(version);
+ assert(ssl->s3->enc_method != NULL);
+ /* At this point, the connection's version is known and |ssl->version| is
+ * fixed. Begin enforcing the record-layer version. */
+ ssl->s3->have_version = 1;
+ } else if (SSL_IS_DTLS(ssl) ? (ssl->client_version > ssl->version)
+ : (ssl->client_version < ssl->version)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+
+ ssl->hit = 0;
+ int send_new_ticket = 0;
+ switch (ssl_get_prev_session(ssl, &session, &send_new_ticket, &early_ctx)) {
+ case ssl_session_success:
+ break;
+ case ssl_session_error:
+ goto err;
+ case ssl_session_retry:
+ ssl->rwstate = SSL_PENDING_SESSION;
+ goto err;
+ }
+ ssl->tlsext_ticket_expected = send_new_ticket;
+
+ /* The EMS state is needed when making the resumption decision, but
+ * extensions are not normally parsed until later. This detects the EMS
+ * extension for the resumption decision and it's checked against the result
+ * of the normal parse later in this function. */
+ const uint8_t *ems_data;
+ size_t ems_len;
+ int have_extended_master_secret =
+ ssl->version != SSL3_VERSION &&
+ SSL_early_callback_ctx_extension_get(&early_ctx,
+ TLSEXT_TYPE_extended_master_secret,
+ &ems_data, &ems_len) &&
+ ems_len == 0;
+
+ if (session != NULL) {
+ if (session->extended_master_secret &&
+ !have_extended_master_secret) {
+ /* A ClientHello without EMS that attempts to resume a session with EMS
+ * is fatal to the connection. */
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
+ goto f_err;
+ }
+
+ ssl->hit =
+ /* Only resume if the session's version matches the negotiated version:
+ * most clients do not accept a mismatch. */
+ ssl->version == session->ssl_version &&
+ /* If the client offers the EMS extension, but the previous session
+ * didn't use it, then negotiate a new session. */
+ have_extended_master_secret == session->extended_master_secret;
+ }
+
+ if (ssl->hit) {
+ /* Use the new session. */
+ SSL_SESSION_free(ssl->session);
+ ssl->session = session;
+ session = NULL;
+
+ ssl->verify_result = ssl->session->verify_result;
+ } else {
+ if (!ssl_get_new_session(ssl, 1 /* server */)) {
+ goto err;
+ }
+
+ /* Clear the session ID if we want the session to be single-use. */
+ if (!(ssl->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) {
+ ssl->session->session_id_length = 0;
+ }
+ }
+
+ if (ssl->ctx->dos_protection_cb != NULL &&
+ ssl->ctx->dos_protection_cb(&early_ctx) == 0) {
+ /* Connection rejected for DOS reasons. */
+ al = SSL_AD_ACCESS_DENIED;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
+ goto f_err;
+ }
+
+ if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) ||
+ CBS_len(&cipher_suites) == 0 ||
+ CBS_len(&cipher_suites) % 2 != 0 ||
+ !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) ||
+ CBS_len(&compression_methods) == 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ ciphers = ssl_bytes_to_cipher_list(ssl, &cipher_suites);
+ if (ciphers == NULL) {
+ goto err;
+ }
+
+ /* If it is a hit, check that the cipher is in the list. */
+ if (ssl->hit) {
+ size_t j;
+ int found_cipher = 0;
+ uint32_t id = ssl->session->cipher->id;
+
+ for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
+ c = sk_SSL_CIPHER_value(ciphers, j);
+ if (c->id == id) {
+ found_cipher = 1;
+ break;
+ }
+ }
+
+ if (!found_cipher) {
+ /* we need to have the cipher in the cipher list if we are asked to reuse
+ * it */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_REQUIRED_CIPHER_MISSING);
+ goto f_err;
+ }
+ }
+
+ /* Only null compression is supported. */
+ if (memchr(CBS_data(&compression_methods), 0,
+ CBS_len(&compression_methods)) == NULL) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMPRESSION_SPECIFIED);
+ goto f_err;
+ }
+
+ /* TLS extensions. */
+ if (ssl->version >= SSL3_VERSION &&
+ !ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+ goto err;
+ }
+
+ /* There should be nothing left over in the record. */
+ if (CBS_len(&client_hello) != 0) {
+ /* wrong packet length */
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
+ goto f_err;
+ }
+
+ if (have_extended_master_secret != ssl->s3->tmp.extended_master_secret) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_EMS_STATE_INCONSISTENT);
+ goto f_err;
+ }
+
+ /* Given ciphers and SSL_get_ciphers, we must pick a cipher */
+ if (!ssl->hit) {
+ if (ciphers == NULL) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_PASSED);
+ goto f_err;
+ }
+
+ /* Let cert callback update server certificates if required */
+ if (ssl->cert->cert_cb) {
+ int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
+ if (rv == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
+ goto f_err;
+ }
+ if (rv < 0) {
+ ssl->rwstate = SSL_X509_LOOKUP;
+ goto err;
+ }
+ }
+ c = ssl3_choose_cipher(ssl, ciphers, ssl_get_cipher_preferences(ssl));
+
+ if (c == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+ ssl->session->cipher = c;
+ ssl->s3->tmp.new_cipher = c;
+
+ /* Determine whether to request a client certificate. */
+ ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+ /* Only request a certificate if Channel ID isn't negotiated. */
+ if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
+ ssl->s3->tlsext_channel_id_valid) {
+ ssl->s3->tmp.cert_request = 0;
+ }
+ /* CertificateRequest may only be sent in certificate-based ciphers. */
+ if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ ssl->s3->tmp.cert_request = 0;
+ }
+ } else {
+ /* Session-id reuse */
+ ssl->s3->tmp.new_cipher = ssl->session->cipher;
+ ssl->s3->tmp.cert_request = 0;
+ }
+
+ /* Now that the cipher is known, initialize the handshake hash. */
+ if (!ssl3_init_handshake_hash(ssl)) {
+ goto f_err;
+ }
+
+ /* In TLS 1.2, client authentication requires hashing the handshake transcript
+ * under a different hash. Otherwise, release the handshake buffer. */
+ if (!ssl->s3->tmp.cert_request ||
+ ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
+ ssl3_free_handshake_buffer(ssl);
+ }
+
+ /* we now have the following setup;
+ * client_random
+ * cipher_list - our prefered list of ciphers
+ * ciphers - the clients prefered list of ciphers
+ * compression - basically ignored right now
+ * ssl version is set - sslv3
+ * ssl->session - The ssl session has been setup.
+ * ssl->hit - session reuse flag
+ * ssl->tmp.new_cipher - the new cipher to use. */
+
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ }
+
+err:
+ sk_SSL_CIPHER_free(ciphers);
+ SSL_SESSION_free(session);
+ return ret;
+}
+
+static int ssl3_send_server_hello(SSL *ssl) {
+ if (ssl->state == SSL3_ST_SW_SRVR_HELLO_B) {
+ return ssl_do_write(ssl);
+ }
+
+ assert(ssl->state == SSL3_ST_SW_SRVR_HELLO_A);
+
+ /* We only accept ChannelIDs on connections with ECDHE in order to avoid a
+ * known attack while we fix ChannelID itself. */
+ if (ssl->s3->tlsext_channel_id_valid &&
+ (ssl->s3->tmp.new_cipher->algorithm_mkey & SSL_kECDHE) == 0) {
+ ssl->s3->tlsext_channel_id_valid = 0;
+ }
+
+ /* If this is a resumption and the original handshake didn't support
+ * ChannelID then we didn't record the original handshake hashes in the
+ * session and so cannot resume with ChannelIDs. */
+ if (ssl->hit && ssl->session->original_handshake_hash_len == 0) {
+ ssl->s3->tlsext_channel_id_valid = 0;
+ }
+
+ if (!ssl_fill_hello_random(ssl->s3->server_random, SSL3_RANDOM_SIZE,
+ 1 /* server */)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ CBB cbb, session_id;
+ size_t length;
+ CBB_zero(&cbb);
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
+ !CBB_add_u16(&cbb, ssl->version) ||
+ !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_u8_length_prefixed(&cbb, &session_id) ||
+ !CBB_add_bytes(&session_id, ssl->session->session_id,
+ ssl->session->session_id_length) ||
+ !CBB_add_u16(&cbb, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
+ !CBB_add_u8(&cbb, 0 /* no compression */) ||
+ !ssl_add_serverhello_tlsext(ssl, &cbb) ||
+ !CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_HELLO, length)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ CBB_cleanup(&cbb);
+ return -1;
+ }
+
+ ssl->state = SSL3_ST_SW_SRVR_HELLO_B;
+ return ssl_do_write(ssl);
+}
+
+static int ssl3_send_server_certificate(SSL *ssl) {
+ if (ssl->state == SSL3_ST_SW_CERT_A) {
+ if (!ssl3_output_cert_chain(ssl)) {
+ return 0;
+ }
+ ssl->state = SSL3_ST_SW_CERT_B;
+ }
+
+ /* SSL3_ST_SW_CERT_B */
+ return ssl_do_write(ssl);
+}
+
+static int ssl3_send_certificate_status(SSL *ssl) {
+ if (ssl->state == SSL3_ST_SW_CERT_STATUS_A) {
+ CBB out, ocsp_response;
+ size_t length;
+
+ CBB_zero(&out);
+ if (!CBB_init_fixed(&out, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
+ !CBB_add_u8(&out, TLSEXT_STATUSTYPE_ocsp) ||
+ !CBB_add_u24_length_prefixed(&out, &ocsp_response) ||
+ !CBB_add_bytes(&ocsp_response, ssl->ctx->ocsp_response,
+ ssl->ctx->ocsp_response_length) ||
+ !CBB_finish(&out, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_STATUS, length)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ CBB_cleanup(&out);
+ return -1;
+ }
+
+ ssl->state = SSL3_ST_SW_CERT_STATUS_B;
+ }
+
+ /* SSL3_ST_SW_CERT_STATUS_B */
+ return ssl_do_write(ssl);
+}
+
+static int ssl3_send_server_key_exchange(SSL *ssl) {
+ if (ssl->state == SSL3_ST_SW_KEY_EXCH_C) {
+ return ssl_do_write(ssl);
+ }
+
+ CBB cbb, child;
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
+ goto err;
+ }
+
+ if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
+ /* This is the first iteration, so write parameters. */
+ uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+ uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+
+ /* PSK ciphers begin with an identity hint. */
+ if (alg_a & SSL_aPSK) {
+ size_t len =
+ (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint);
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint,
+ len)) {
+ goto err;
+ }
+ }
+
+ if (alg_k & SSL_kDHE) {
+ /* Determine the group to use. */
+ DH *params = ssl->cert->dh_tmp;
+ if (params == NULL && ssl->cert->dh_tmp_cb != NULL) {
+ params = ssl->cert->dh_tmp_cb(ssl, 0, 1024);
+ }
+ if (params == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_DH_KEY);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
+ ssl->session->key_exchange_info = DH_num_bits(params);
+
+ /* Set up DH, generate a key, and emit the public half. */
+ DH *dh = DHparams_dup(params);
+ if (dh == NULL) {
+ goto err;
+ }
+
+ SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
+ goto err;
+ }
+ } else if (alg_k & SSL_kECDHE) {
+ /* Determine the group to use. */
+ uint16_t group_id;
+ if (!tls1_get_shared_group(ssl, &group_id)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_ECDH_KEY);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
+ ssl->session->key_exchange_info = group_id;
+
+ /* Set up ECDH, generate a key, and emit the public half. */
+ if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) ||
+ !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
+ !CBB_add_u16(&cbb, group_id) ||
+ !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
+ goto err;
+ }
+ } else if (alg_k & SSL_kCECPQ1) {
+ if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, SSL_GROUP_CECPQ1) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
+ goto err;
+ }
+ } else {
+ assert(alg_k & SSL_kPSK);
+ }
+
+ /* Otherwise, restore |cbb| from the previous iteration.
+ * TODO(davidben): When |ssl->init_buf| is gone, come up with a simpler
+ * pattern. Probably keep the |CBB| around in the handshake state. */
+ } else if (!CBB_did_write(&cbb, ssl->init_num - SSL_HM_HEADER_LENGTH(ssl))) {
+ goto err;
+ }
+
+ /* Add a signature. */
+ if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ if (!ssl_has_private_key(ssl)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+
+ const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
+ size_t sig_len;
+ enum ssl_private_key_result_t sign_result;
+ if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
+ /* This is the first iteration, so set up the signature. Sample the
+ * parameter length before adding a signature algorithm. */
+ if (!CBB_flush(&cbb)) {
+ goto err;
+ }
+ size_t params_len = CBB_len(&cbb);
+
+ /* Determine signature algorithm. */
+ const EVP_MD *md;
+ if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+ md = tls1_choose_signing_digest(ssl);
+ if (!tls12_add_sigandhash(ssl, &cbb, md)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+ } else if (ssl_private_key_type(ssl) == EVP_PKEY_RSA) {
+ md = EVP_md5_sha1();
+ } else {
+ md = EVP_sha1();
+ }
+
+ /* Compute the digest and sign it. */
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned digest_len = 0;
+ EVP_MD_CTX md_ctx;
+ EVP_MD_CTX_init(&md_ctx);
+ int digest_ret =
+ EVP_DigestInit_ex(&md_ctx, md, NULL) &&
+ EVP_DigestUpdate(&md_ctx, ssl->s3->client_random, SSL3_RANDOM_SIZE) &&
+ EVP_DigestUpdate(&md_ctx, ssl->s3->server_random, SSL3_RANDOM_SIZE) &&
+ EVP_DigestUpdate(&md_ctx, CBB_data(&cbb), params_len) &&
+ EVP_DigestFinal_ex(&md_ctx, digest, &digest_len);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ uint8_t *ptr;
+ if (!digest_ret ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_reserve(&child, &ptr, max_sig_len)) {
+ goto err;
+ }
+ sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md,
+ digest, digest_len);
+ } else {
+ assert(ssl->state == SSL3_ST_SW_KEY_EXCH_B);
+
+ /* Retry the signature. */
+ uint8_t *ptr;
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_reserve(&child, &ptr, max_sig_len)) {
+ goto err;
+ }
+ sign_result =
+ ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len);
+ }
+
+ switch (sign_result) {
+ case ssl_private_key_success:
+ if (!CBB_did_write(&child, sig_len)) {
+ goto err;
+ }
+ break;
+ case ssl_private_key_failure:
+ goto err;
+ case ssl_private_key_retry:
+ /* Discard the unfinished signature and save the state of |cbb| for the
+ * next iteration. */
+ CBB_discard_child(&cbb);
+ ssl->init_num = SSL_HM_HEADER_LENGTH(ssl) + CBB_len(&cbb);
+ ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+ ssl->state = SSL3_ST_SW_KEY_EXCH_B;
+ goto err;
+ }
+ }
+
+ size_t length;
+ if (!CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_KEY_EXCHANGE, length)) {
+ goto err;
+ }
+ ssl->state = SSL3_ST_SW_KEY_EXCH_C;
+ return ssl_do_write(ssl);
+
+err:
+ CBB_cleanup(&cbb);
+ return -1;
+}
+
+static int ssl3_send_certificate_request(SSL *ssl) {
+ uint8_t *p, *d;
+ size_t i;
+ int j, nl, off, n;
+ STACK_OF(X509_NAME) *sk = NULL;
+ X509_NAME *name;
+ BUF_MEM *buf;
+
+ if (ssl->state == SSL3_ST_SW_CERT_REQ_A) {
+ buf = ssl->init_buf;
+
+ d = p = ssl_handshake_start(ssl);
+
+ /* get the list of acceptable cert types */
+ p++;
+ n = ssl3_get_req_cert_type(ssl, p);
+ d[0] = n;
+ p += n;
+ n++;
+
+ if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+ const uint8_t *psigs;
+ nl = tls12_get_psigalgs(ssl, &psigs);
+ s2n(nl, p);
+ memcpy(p, psigs, nl);
+ p += nl;
+ n += nl + 2;
+ }
+
+ off = n;
+ p += 2;
+ n += 2;
+
+ sk = SSL_get_client_CA_list(ssl);
+ nl = 0;
+ if (sk != NULL) {
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ name = sk_X509_NAME_value(sk, i);
+ j = i2d_X509_NAME(name, NULL);
+ if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(ssl) + n + j + 2)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
+ goto err;
+ }
+ p = ssl_handshake_start(ssl) + n;
+ s2n(j, p);
+ i2d_X509_NAME(name, &p);
+ n += 2 + j;
+ nl += 2 + j;
+ }
+ }
+
+ /* else no CA names */
+ p = ssl_handshake_start(ssl) + off;
+ s2n(nl, p);
+
+ if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_REQUEST, n)) {
+ goto err;
+ }
+ ssl->state = SSL3_ST_SW_CERT_REQ_B;
+ }
+
+ /* SSL3_ST_SW_CERT_REQ_B */
+ return ssl_do_write(ssl);
+
+err:
+ return -1;
+}
+
+static int ssl3_send_server_hello_done(SSL *ssl) {
+ if (ssl->state == SSL3_ST_SW_SRVR_DONE_A) {
+ if (!ssl_set_handshake_header(ssl, SSL3_MT_SERVER_HELLO_DONE, 0)) {
+ return -1;
+ }
+ ssl->state = SSL3_ST_SW_SRVR_DONE_B;
+ }
+
+ /* SSL3_ST_SW_SRVR_DONE_B */
+ return ssl_do_write(ssl);
+}
+
+static int ssl3_get_client_certificate(SSL *ssl) {
+ int ok, al, ret = -1;
+ X509 *x = NULL;
+ unsigned long n;
+ STACK_OF(X509) *sk = NULL;
+ SHA256_CTX sha256;
+ CBS certificate_msg, certificate_list;
+ int is_first_certificate = 1;
+
+ assert(ssl->s3->tmp.cert_request);
+ n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
+ if (ssl->version == SSL3_VERSION &&
+ ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
+ /* In SSL 3.0, the Certificate message is omitted to signal no certificate. */
+ if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
+ (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_err;
+ }
+
+ ssl->s3->tmp.reuse_message = 1;
+ return 1;
+ }
+
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ CBS_init(&certificate_msg, ssl->init_msg, n);
+
+ sk = sk_X509_new_null();
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) ||
+ CBS_len(&certificate_msg) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ while (CBS_len(&certificate_list) > 0) {
+ CBS certificate;
+ const uint8_t *data;
+
+ if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (is_first_certificate && ssl->ctx->retain_only_sha256_of_client_certs) {
+ /* If this is the first certificate, and we don't want to keep peer
+ * certificates in memory, then we hash it right away. */
+ SHA256_Init(&sha256);
+ SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate));
+ SHA256_Final(ssl->session->peer_sha256, &sha256);
+ ssl->session->peer_sha256_valid = 1;
+ }
+ is_first_certificate = 0;
+
+ /* A u24 length cannot overflow a long. */
+ data = CBS_data(&certificate);
+ x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
+ if (x == NULL) {
+ al = SSL_AD_BAD_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+ goto f_err;
+ }
+ if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (!sk_X509_push(sk, x)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
+
+ if (sk_X509_num(sk) <= 0) {
+ /* No client certificate so the handshake buffer may be discarded. */
+ ssl3_free_handshake_buffer(ssl);
+
+ /* TLS does not mind 0 certs returned */
+ if (ssl->version == SSL3_VERSION) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
+ goto f_err;
+ } else if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
+ (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
+ /* Fail for TLS only if we required a certificate */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_err;
+ }
+ } else {
+ if (ssl_verify_cert_chain(ssl, sk) <= 0) {
+ al = ssl_verify_alarm_type(ssl->verify_result);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto f_err;
+ }
+ }
+
+ X509_free(ssl->session->peer);
+ ssl->session->peer = sk_X509_shift(sk);
+ ssl->session->verify_result = ssl->verify_result;
+
+ sk_X509_pop_free(ssl->session->cert_chain, X509_free);
+ ssl->session->cert_chain = sk;
+ /* Inconsistency alert: cert_chain does *not* include the peer's own
+ * certificate, while we do include it in s3_clnt.c */
+
+ sk = NULL;
+
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ }
+
+err:
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+static int ssl3_get_client_key_exchange(SSL *ssl) {
+ int al;
+ CBS client_key_exchange;
+ uint32_t alg_k;
+ uint32_t alg_a;
+ uint8_t *premaster_secret = NULL;
+ size_t premaster_secret_len = 0;
+ uint8_t *decrypt_buf = NULL;
+
+ unsigned psk_len = 0;
+ uint8_t psk[PSK_MAX_PSK_LEN];
+
+ if (ssl->state == SSL3_ST_SR_KEY_EXCH_A) {
+ int ok;
+ const long n = ssl->method->ssl_get_message(
+ ssl, SSL3_MT_CLIENT_KEY_EXCHANGE, ssl_hash_message, &ok);
+ if (!ok) {
+ return n;
+ }
+ }
+
+ CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
+ alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+
+ /* If using a PSK key exchange, prepare the pre-shared key. */
+ if (alg_a & SSL_aPSK) {
+ CBS psk_identity;
+
+ /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK,
+ * then this is the only field in the message. */
+ if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) ||
+ ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ if (ssl->psk_server_callback == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
+ CBS_contains_zero_byte(&psk_identity)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto f_err;
+ }
+
+ if (!CBS_strdup(&psk_identity, &ssl->session->psk_identity)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ /* Look up the key for the identity. */
+ psk_len = ssl->psk_server_callback(ssl, ssl->session->psk_identity, psk,
+ sizeof(psk));
+ if (psk_len > PSK_MAX_PSK_LEN) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ } else if (psk_len == 0) {
+ /* PSK related to the given identity not found */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
+ al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ goto f_err;
+ }
+ }
+
+ /* Depending on the key exchange method, compute |premaster_secret| and
+ * |premaster_secret_len|. */
+ if (alg_k & SSL_kRSA) {
+ /* Allocate a buffer large enough for an RSA decryption. */
+ const size_t rsa_size = ssl_private_key_max_signature_len(ssl);
+ decrypt_buf = OPENSSL_malloc(rsa_size);
+ if (decrypt_buf == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ enum ssl_private_key_result_t decrypt_result;
+ size_t decrypt_len;
+ if (ssl->state == SSL3_ST_SR_KEY_EXCH_A) {
+ if (!ssl_has_private_key(ssl) ||
+ ssl_private_key_type(ssl) != EVP_PKEY_RSA) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE);
+ goto f_err;
+ }
+ CBS encrypted_premaster_secret;
+ if (ssl->version > SSL3_VERSION) {
+ if (!CBS_get_u16_length_prefixed(&client_key_exchange,
+ &encrypted_premaster_secret) ||
+ CBS_len(&client_key_exchange) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL,
+ SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
+ goto f_err;
+ }
+ } else {
+ encrypted_premaster_secret = client_key_exchange;
+ }
+
+ /* Decrypt with no padding. PKCS#1 padding will be removed as part of the
+ * timing-sensitive code below. */
+ decrypt_result = ssl_private_key_decrypt(
+ ssl, decrypt_buf, &decrypt_len, rsa_size,
+ CBS_data(&encrypted_premaster_secret),
+ CBS_len(&encrypted_premaster_secret));
+ } else {
+ assert(ssl->state == SSL3_ST_SR_KEY_EXCH_B);
+ /* Complete async decrypt. */
+ decrypt_result = ssl_private_key_decrypt_complete(
+ ssl, decrypt_buf, &decrypt_len, rsa_size);
+ }
+
+ switch (decrypt_result) {
+ case ssl_private_key_success:
+ break;
+ case ssl_private_key_failure:
+ goto err;
+ case ssl_private_key_retry:
+ ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+ ssl->state = SSL3_ST_SR_KEY_EXCH_B;
+ goto err;
+ }
+
+ if (decrypt_len != rsa_size) {
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
+ goto f_err;
+ }
+
+ /* Prepare a random premaster, to be used on invalid padding. See RFC 5246,
+ * section 7.4.7.1. */
+ premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH;
+ premaster_secret = OPENSSL_malloc(premaster_secret_len);
+ if (premaster_secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!RAND_bytes(premaster_secret, premaster_secret_len)) {
+ goto err;
+ }
+
+ /* The smallest padded premaster is 11 bytes of overhead. Small keys are
+ * publicly invalid. */
+ if (decrypt_len < 11 + premaster_secret_len) {
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
+ goto f_err;
+ }
+
+ /* Check the padding. See RFC 3447, section 7.2.2. */
+ size_t padding_len = decrypt_len - premaster_secret_len;
+ uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) &
+ constant_time_eq_int_8(decrypt_buf[1], 2);
+ size_t i;
+ for (i = 2; i < padding_len - 1; i++) {
+ good &= ~constant_time_is_zero_8(decrypt_buf[i]);
+ }
+ good &= constant_time_is_zero_8(decrypt_buf[padding_len - 1]);
+
+ /* The premaster secret must begin with |client_version|. This too must be
+ * checked in constant time (http://eprint.iacr.org/2003/052/). */
+ good &= constant_time_eq_8(decrypt_buf[padding_len],
+ (unsigned)(ssl->client_version >> 8));
+ good &= constant_time_eq_8(decrypt_buf[padding_len + 1],
+ (unsigned)(ssl->client_version & 0xff));
+
+ /* Select, in constant time, either the decrypted premaster or the random
+ * premaster based on |good|. */
+ for (i = 0; i < premaster_secret_len; i++) {
+ premaster_secret[i] = constant_time_select_8(
+ good, decrypt_buf[padding_len + i], premaster_secret[i]);
+ }
+
+ OPENSSL_free(decrypt_buf);
+ decrypt_buf = NULL;
+ } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
+ /* Parse the ClientKeyExchange. */
+ CBS peer_key;
+ if (!SSL_ECDH_CTX_get_key(&ssl->s3->tmp.ecdh_ctx, &client_key_exchange,
+ &peer_key) ||
+ CBS_len(&client_key_exchange) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* Compute the premaster. */
+ uint8_t alert;
+ if (!SSL_ECDH_CTX_finish(&ssl->s3->tmp.ecdh_ctx, &premaster_secret,
+ &premaster_secret_len, &alert, CBS_data(&peer_key),
+ CBS_len(&peer_key))) {
+ al = alert;
+ goto f_err;
+ }
+
+ /* The key exchange state may now be discarded. */
+ SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
+ } else if (alg_k & SSL_kPSK) {
+ /* For plain PSK, other_secret is a block of 0s with the same length as the
+ * pre-shared key. */
+ premaster_secret_len = psk_len;
+ premaster_secret = OPENSSL_malloc(premaster_secret_len);
+ if (premaster_secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(premaster_secret, 0, premaster_secret_len);
+ } else {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE);
+ goto f_err;
+ }
+
+ /* For a PSK cipher suite, the actual pre-master secret is combined with the
+ * pre-shared key. */
+ if (alg_a & SSL_aPSK) {
+ CBB new_premaster, child;
+ uint8_t *new_data;
+ size_t new_len;
+
+ CBB_zero(&new_premaster);
+ if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
+ !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+ !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
+ !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+ !CBB_add_bytes(&child, psk, psk_len) ||
+ !CBB_finish(&new_premaster, &new_data, &new_len)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ CBB_cleanup(&new_premaster);
+ goto err;
+ }
+
+ OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+ OPENSSL_free(premaster_secret);
+ premaster_secret = new_data;
+ premaster_secret_len = new_len;
+ }
+
+ /* Compute the master secret */
+ ssl->session->master_key_length = tls1_generate_master_secret(
+ ssl, ssl->session->master_key, premaster_secret, premaster_secret_len);
+ if (ssl->session->master_key_length == 0) {
+ goto err;
+ }
+ ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
+
+ OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+ OPENSSL_free(premaster_secret);
+ return 1;
+
+f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+ if (premaster_secret != NULL) {
+ OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+ OPENSSL_free(premaster_secret);
+ }
+ OPENSSL_free(decrypt_buf);
+
+ return -1;
+}
+
+static int ssl3_get_cert_verify(SSL *ssl) {
+ int al, ok, ret = 0;
+ long n;
+ CBS certificate_verify, signature;
+ X509 *peer = ssl->session->peer;
+ EVP_PKEY *pkey = NULL;
+ const EVP_MD *md = NULL;
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_length;
+ EVP_PKEY_CTX *pctx = NULL;
+
+ /* Only RSA and ECDSA client certificates are supported, so a
+ * CertificateVerify is required if and only if there's a client certificate.
+ * */
+ if (peer == NULL) {
+ ssl3_free_handshake_buffer(ssl);
+ return 1;
+ }
+
+ n = ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE_VERIFY,
+ ssl_dont_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ /* Filter out unsupported certificate types. */
+ pkey = X509_get_pubkey(peer);
+ if (pkey == NULL) {
+ goto err;
+ }
+ if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) ||
+ (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) {
+ al = SSL_AD_UNSUPPORTED_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+
+ CBS_init(&certificate_verify, ssl->init_msg, n);
+
+ /* Determine the digest type if needbe. */
+ if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+ uint8_t hash, signature_type;
+ if (!CBS_get_u8(&certificate_verify, &hash) ||
+ !CBS_get_u8(&certificate_verify, &signature_type)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+ if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature_type, pkey)) {
+ goto f_err;
+ }
+ }
+
+ /* Compute the digest. */
+ if (!ssl3_cert_verify_hash(ssl, digest, &digest_length, &md, pkey->type)) {
+ goto err;
+ }
+
+ /* The handshake buffer is no longer necessary, and we may hash the current
+ * message.*/
+ ssl3_free_handshake_buffer(ssl);
+ if (!ssl3_hash_current_message(ssl)) {
+ goto err;
+ }
+
+ /* Parse and verify the signature. */
+ if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
+ CBS_len(&certificate_verify) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (pctx == NULL) {
+ goto err;
+ }
+ int sig_ok = EVP_PKEY_verify_init(pctx) &&
+ EVP_PKEY_CTX_set_signature_md(pctx, md) &&
+ EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
+ digest, digest_length);
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+ sig_ok = 1;
+ ERR_clear_error();
+#endif
+ if (!sig_ok) {
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ }
+
+err:
+ EVP_PKEY_CTX_free(pctx);
+ EVP_PKEY_free(pkey);
+
+ return ret;
+}
+
+/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
+ * sets the next_proto member in s if found */
+static int ssl3_get_next_proto(SSL *ssl) {
+ int ok;
+ long n;
+ CBS next_protocol, selected_protocol, padding;
+
+ /* Clients cannot send a NextProtocol message if we didn't see the extension
+ * in their ClientHello */
+ if (!ssl->s3->next_proto_neg_seen) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
+ return -1;
+ }
+
+ n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEXT_PROTO, ssl_hash_message,
+ &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ CBS_init(&next_protocol, ssl->init_msg, n);
+
+ /* The payload looks like:
+ * uint8 proto_len;
+ * uint8 proto[proto_len];
+ * uint8 padding_len;
+ * uint8 padding[padding_len]; */
+ if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
+ !CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
+ CBS_len(&next_protocol) != 0 ||
+ !CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated,
+ &ssl->s3->next_proto_negotiated_len)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
+static int ssl3_get_channel_id(SSL *ssl) {
+ int ret = -1, ok;
+ long n;
+ uint8_t channel_id_hash[EVP_MAX_MD_SIZE];
+ size_t channel_id_hash_len;
+ const uint8_t *p;
+ uint16_t extension_type;
+ EC_GROUP *p256 = NULL;
+ EC_KEY *key = NULL;
+ EC_POINT *point = NULL;
+ ECDSA_SIG sig;
+ BIGNUM x, y;
+ CBS encrypted_extensions, extension;
+
+ n = ssl->method->ssl_get_message(ssl, SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS,
+ ssl_dont_hash_message, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ /* Before incorporating the EncryptedExtensions message to the handshake
+ * hash, compute the hash that should have been signed. */
+ if (!tls1_channel_id_hash(ssl, channel_id_hash, &channel_id_hash_len)) {
+ return -1;
+ }
+ assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);
+
+ if (!ssl3_hash_current_message(ssl)) {
+ return -1;
+ }
+
+ CBS_init(&encrypted_extensions, ssl->init_msg, n);
+
+ /* EncryptedExtensions could include multiple extensions, but the only
+ * extension that could be negotiated is ChannelID, so there can only be one
+ * entry.
+ *
+ * The payload looks like:
+ * uint16 extension_type
+ * uint16 extension_len;
+ * uint8 x[32];
+ * uint8 y[32];
+ * uint8 r[32];
+ * uint8 s[32]; */
+
+ if (!CBS_get_u16(&encrypted_extensions, &extension_type) ||
+ !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) ||
+ CBS_len(&encrypted_extensions) != 0 ||
+ extension_type != TLSEXT_TYPE_channel_id ||
+ CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_MESSAGE);
+ return -1;
+ }
+
+ p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
+ if (!p256) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
+ return -1;
+ }
+
+ BN_init(&x);
+ BN_init(&y);
+ sig.r = BN_new();
+ sig.s = BN_new();
+ if (sig.r == NULL || sig.s == NULL) {
+ goto err;
+ }
+
+ p = CBS_data(&extension);
+ if (BN_bin2bn(p + 0, 32, &x) == NULL ||
+ BN_bin2bn(p + 32, 32, &y) == NULL ||
+ BN_bin2bn(p + 64, 32, sig.r) == NULL ||
+ BN_bin2bn(p + 96, 32, sig.s) == NULL) {
+ goto err;
+ }
+
+ point = EC_POINT_new(p256);
+ if (!point ||
+ !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) {
+ goto err;
+ }
+
+ key = EC_KEY_new();
+ if (!key || !EC_KEY_set_group(key, p256) ||
+ !EC_KEY_set_public_key(key, point)) {
+ goto err;
+ }
+
+ /* We stored the handshake hash in |tlsext_channel_id| the first time that we
+ * were called. */
+ if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
+ ssl->s3->tlsext_channel_id_valid = 0;
+ goto err;
+ }
+
+ memcpy(ssl->s3->tlsext_channel_id, p, 64);
+ ret = 1;
+
+err:
+ BN_free(&x);
+ BN_free(&y);
+ BN_free(sig.r);
+ BN_free(sig.s);
+ EC_KEY_free(key);
+ EC_POINT_free(point);
+ EC_GROUP_free(p256);
+ return ret;
+}
+
+/* send a new session ticket (not necessarily for a new session) */
+static int ssl3_send_new_session_ticket(SSL *ssl) {
+ int ret = -1;
+ uint8_t *session = NULL;
+ size_t session_len;
+ EVP_CIPHER_CTX ctx;
+ HMAC_CTX hctx;
+
+ EVP_CIPHER_CTX_init(&ctx);
+ HMAC_CTX_init(&hctx);
+
+ if (ssl->state == SSL3_ST_SW_SESSION_TICKET_A) {
+ uint8_t *p, *macstart;
+ int len;
+ unsigned int hlen;
+ SSL_CTX *tctx = ssl->initial_ctx;
+ uint8_t iv[EVP_MAX_IV_LENGTH];
+ uint8_t key_name[16];
+ /* The maximum overhead of encrypting the session is 16 (key name) + IV +
+ * one block of encryption overhead + HMAC. */
+ const size_t max_ticket_overhead =
+ 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
+
+ /* Serialize the SSL_SESSION to be encoded into the ticket. */
+ if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &session,
+ &session_len)) {
+ goto err;
+ }
+
+ /* If the session is too long, emit a dummy value rather than abort the
+ * connection. */
+ if (session_len > 0xFFFF - max_ticket_overhead) {
+ static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
+ const size_t placeholder_len = strlen(kTicketPlaceholder);
+
+ OPENSSL_free(session);
+ session = NULL;
+
+ p = ssl_handshake_start(ssl);
+ /* Emit ticket_lifetime_hint. */
+ l2n(0, p);
+ /* Emit ticket. */
+ s2n(placeholder_len, p);
+ memcpy(p, kTicketPlaceholder, placeholder_len);
+ p += placeholder_len;
+
+ len = p - ssl_handshake_start(ssl);
+ if (!ssl_set_handshake_header(ssl, SSL3_MT_NEW_SESSION_TICKET, len)) {
+ goto err;
+ }
+ ssl->state = SSL3_ST_SW_SESSION_TICKET_B;
+ return ssl_do_write(ssl);
+ }
+
+ /* Grow buffer if need be: the length calculation is as follows:
+ * handshake_header_length + 4 (ticket lifetime hint) + 2 (ticket length) +
+ * max_ticket_overhead + * session_length */
+ if (!BUF_MEM_grow(ssl->init_buf, SSL_HM_HEADER_LENGTH(ssl) + 6 +
+ max_ticket_overhead + session_len)) {
+ goto err;
+ }
+ p = ssl_handshake_start(ssl);
+ /* Initialize HMAC and cipher contexts. If callback present it does all the
+ * work otherwise use generated values from parent ctx. */
+ if (tctx->tlsext_ticket_key_cb) {
+ if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx,
+ 1 /* encrypt */) < 0) {
+ goto err;
+ }
+ } else {
+ if (!RAND_bytes(iv, 16) ||
+ !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ tctx->tlsext_tick_aes_key, iv) ||
+ !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(),
+ NULL)) {
+ goto err;
+ }
+ memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+ }
+
+ /* Ticket lifetime hint (advisory only): We leave this unspecified for
+ * resumed session (for simplicity), and guess that tickets for new
+ * sessions will live as long as their sessions. */
+ l2n(ssl->hit ? 0 : ssl->session->timeout, p);
+
+ /* Skip ticket length for now */
+ p += 2;
+ /* Output key name */
+ macstart = p;
+ memcpy(p, key_name, 16);
+ p += 16;
+ /* output IV */
+ memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+ p += EVP_CIPHER_CTX_iv_length(&ctx);
+ /* Encrypt session data */
+ if (!EVP_EncryptUpdate(&ctx, p, &len, session, session_len)) {
+ goto err;
+ }
+ p += len;
+ if (!EVP_EncryptFinal_ex(&ctx, p, &len)) {
+ goto err;
+ }
+ p += len;
+
+ if (!HMAC_Update(&hctx, macstart, p - macstart) ||
+ !HMAC_Final(&hctx, p, &hlen)) {
+ goto err;
+ }
+
+ p += hlen;
+ /* Now write out lengths: p points to end of data written */
+ /* Total length */
+ len = p - ssl_handshake_start(ssl);
+ /* Skip ticket lifetime hint */
+ p = ssl_handshake_start(ssl) + 4;
+ s2n(len - 6, p);
+ if (!ssl_set_handshake_header(ssl, SSL3_MT_NEW_SESSION_TICKET, len)) {
+ goto err;
+ }
+ ssl->state = SSL3_ST_SW_SESSION_TICKET_B;
+ }
+
+ /* SSL3_ST_SW_SESSION_TICKET_B */
+ ret = ssl_do_write(ssl);
+
+err:
+ OPENSSL_free(session);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&hctx);
+ return ret;
+}
diff --git a/ssl/internal.h b/ssl/internal.h
index 03240613..457a8b42 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -151,9 +151,9 @@
#if defined(OPENSSL_WINDOWS)
/* Windows defines struct timeval in winsock2.h. */
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#else
#include <sys/time.h>
#endif
@@ -167,6 +167,7 @@
#define SSL_kECDHE 0x00000004L
/* SSL_kPSK is only set for plain PSK, not ECDHE_PSK. */
#define SSL_kPSK 0x00000008L
+#define SSL_kCECPQ1 0x00000010L
/* Bits for |algorithm_auth| (server authentication). */
#define SSL_aRSA 0x00000001L
@@ -174,6 +175,8 @@
/* SSL_aPSK is set for both PSK and ECDHE_PSK. */
#define SSL_aPSK 0x00000004L
+#define SSL_aCERT (SSL_aRSA | SSL_aECDSA)
+
/* Bits for |algorithm_enc| (symmetric encryption). */
#define SSL_3DES 0x00000001L
#define SSL_RC4 0x00000002L
@@ -239,17 +242,16 @@ uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher);
* server key used in |cipher| or |EVP_PKEY_NONE| if there is none. */
int ssl_cipher_get_key_type(const SSL_CIPHER *cipher);
-/* ssl_cipher_has_server_public_key returns 1 if |cipher| involves a server
- * public key in the key exchange, sent in a server Certificate message.
- * Otherwise it returns 0. */
-int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher);
+/* ssl_cipher_uses_certificate_auth returns one if |cipher| authenticates the
+ * server and, optionally, the client with a certificate. Otherwise it returns
+ * zero. */
+int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher);
/* ssl_cipher_requires_server_key_exchange returns 1 if |cipher| requires a
* ServerKeyExchange message. Otherwise it returns 0.
*
- * Unlike |ssl_cipher_has_server_public_key|, this function may return zero
- * while still allowing |cipher| an optional ServerKeyExchange. This is the
- * case for plain PSK ciphers. */
+ * This function may return zero while still allowing |cipher| an optional
+ * ServerKeyExchange. This is the case for plain PSK ciphers. */
int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher);
/* ssl_cipher_get_record_split_len, for TLS 1.0 CBC mode ciphers, returns the
@@ -282,6 +284,8 @@ struct ssl_aead_ctx_st {
/* omit_version_in_ad is non-zero if the version should be omitted
* in the AEAD's ad parameter. */
char omit_version_in_ad;
+ /* omit_ad is non-zero if the AEAD's ad parameter should be omitted. */
+ char omit_ad;
/* xor_fixed_nonce is non-zero if the fixed nonce should be XOR'd into the
* variable nonce rather than prepended. */
char xor_fixed_nonce;
@@ -309,21 +313,19 @@ size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *ctx);
* |SSL_AEAD_CTX_seal|. |ctx| may be NULL to denote the null cipher. */
size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *ctx);
-/* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in| and
- * writes the result to |out|. It returns one on success and zero on
- * error. |ctx| may be NULL to denote the null cipher.
- *
- * If |in| and |out| alias then |out| must be <= |in| + |explicit_nonce_len|. */
-int SSL_AEAD_CTX_open(SSL_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
- size_t max_out, uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], const uint8_t *in,
- size_t in_len);
+/* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in|
+ * in-place. On success, it sets |*out| to the plaintext in |in| and returns
+ * one. Otherwise, it returns zero. |ctx| may be NULL to denote the null cipher.
+ * The output will always be |explicit_nonce_len| bytes ahead of |in|. */
+int SSL_AEAD_CTX_open(SSL_AEAD_CTX *ctx, CBS *out, uint8_t type,
+ uint16_t wire_version, const uint8_t seqnum[8],
+ uint8_t *in, size_t in_len);
/* SSL_AEAD_CTX_seal encrypts and authenticates |in_len| bytes from |in| and
* writes the result to |out|. It returns one on success and zero on
* error. |ctx| may be NULL to denote the null cipher.
*
- * If |in| and |out| alias then |out| + |explicit_nonce_len| must be <= |in| */
+ * If |in| and |out| alias then |out| + |explicit_nonce_len| must be == |in|. */
int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out, uint8_t type, uint16_t wire_version,
const uint8_t seqnum[8], const uint8_t *in,
@@ -361,52 +363,60 @@ enum ssl_open_record_t {
ssl_open_record_success,
ssl_open_record_discard,
ssl_open_record_partial,
+ ssl_open_record_close_notify,
+ ssl_open_record_fatal_alert,
ssl_open_record_error,
};
-/* tls_open_record decrypts a record from |in|.
- *
- * On success, it returns |ssl_open_record_success|. It sets |*out_type| to the
- * record type, |*out_len| to the plaintext length, and writes the record body
- * to |out|. It sets |*out_consumed| to the number of bytes of |in| consumed.
- * Note that |*out_len| may be zero.
- *
- * If a record was successfully processed but should be discarded, it returns
- * |ssl_open_record_discard| and sets |*out_consumed| to the number of bytes
- * consumed.
+/* tls_open_record decrypts a record from |in| in-place.
*
* If the input did not contain a complete record, it returns
* |ssl_open_record_partial|. It sets |*out_consumed| to the total number of
* bytes necessary. It is guaranteed that a successful call to |tls_open_record|
* will consume at least that many bytes.
*
- * On failure, it returns |ssl_open_record_error| and sets |*out_alert| to an
- * alert to emit.
+ * Otherwise, it sets |*out_consumed| to the number of bytes of input
+ * consumed. Note that input may be consumed on all return codes if a record was
+ * decrypted.
*
- * If |in| and |out| alias, |out| must be <= |in| + |ssl_record_prefix_len|. */
-enum ssl_open_record_t tls_open_record(
- SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
- size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
- size_t in_len);
+ * On success, it returns |ssl_open_record_success|. It sets |*out_type| to the
+ * record type and |*out| to the record body in |in|. Note that |*out| may be
+ * empty.
+ *
+ * If a record was successfully processed but should be discarded, it returns
+ * |ssl_open_record_discard|.
+ *
+ * If a record was successfully processed but is a close_notify or fatal alert,
+ * it returns |ssl_open_record_close_notify| or |ssl_open_record_fatal_alert|.
+ *
+ * On failure, it returns |ssl_open_record_error| and sets |*out_alert| to an
+ * alert to emit. */
+enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+ size_t *out_consumed, uint8_t *out_alert,
+ uint8_t *in, size_t in_len);
/* dtls_open_record implements |tls_open_record| for DTLS. It never returns
* |ssl_open_record_partial| but otherwise behaves analogously. */
-enum ssl_open_record_t dtls_open_record(
- SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
- size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
- size_t in_len);
-
-/* ssl_seal_prefix_len returns the length of the prefix before the ciphertext
- * when sealing a record with |ssl|. Note that this value may differ from
- * |ssl_record_prefix_len| when TLS 1.0 CBC record-splitting is enabled. Sealing
- * a small record may also result in a smaller output than this value.
+enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+ size_t *out_consumed,
+ uint8_t *out_alert, uint8_t *in,
+ size_t in_len);
+
+/* ssl_seal_align_prefix_len returns the length of the prefix before the start
+ * of the bulk of the ciphertext when sealing a record with |ssl|. Callers may
+ * use this to align buffers.
+ *
+ * Note when TLS 1.0 CBC record-splitting is enabled, this includes the one byte
+ * record and is the offset into second record's ciphertext. Thus this value may
+ * differ from |ssl_record_prefix_len| and sealing a small record may result in
+ * a smaller output than this value.
*
* TODO(davidben): Expose this as part of public API once the high-level
* buffer-free APIs are available. */
-size_t ssl_seal_prefix_len(const SSL *ssl);
+size_t ssl_seal_align_prefix_len(const SSL *ssl);
/* ssl_max_seal_overhead returns the maximum overhead of sealing a record with
- * |ssl|. This includes |ssl_seal_prefix_len|.
+ * |ssl|.
*
* TODO(davidben): Expose this as part of public API once the high-level
* buffer-free APIs are available. */
@@ -417,11 +427,12 @@ size_t ssl_max_seal_overhead(const SSL *ssl);
* and zero on error. If enabled, |tls_seal_record| implements TLS 1.0 CBC 1/n-1
* record splitting and may write two records concatenated.
*
- * For a large record, the ciphertext will begin |ssl_seal_prefix_len| bytes
- * into out. Aligning |out| appropriately may improve performance. It writes at
- * most |in_len| + |ssl_max_seal_overhead| bytes to |out|.
+ * For a large record, the bulk of the ciphertext will begin
+ * |ssl_seal_align_prefix_len| bytes into out. Aligning |out| appropriately may
+ * improve performance. It writes at most |in_len| + |ssl_max_seal_overhead|
+ * bytes to |out|.
*
- * If |in| and |out| alias, |out| + |ssl_seal_prefix_len| must be <= |in|. */
+ * |in| and |out| may not alias. */
int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
uint8_t type, const uint8_t *in, size_t in_len);
@@ -444,6 +455,13 @@ void ssl_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
* ownership of |aead_ctx|. */
void ssl_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
+/* ssl_process_alert processes |in| as an alert and updates |ssl|'s shutdown
+ * state. It returns one of |ssl_open_record_discard|, |ssl_open_record_error|,
+ * |ssl_open_record_close_notify|, or |ssl_open_record_fatal_alert| as
+ * appropriate. */
+enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
+ const uint8_t *in, size_t in_len);
+
/* Private key operations. */
@@ -526,45 +544,66 @@ void ssl3_free_handshake_hash(SSL *ssl);
int ssl3_update_handshake_hash(SSL *ssl, const uint8_t *in, size_t in_len);
-/* ECDH curves. */
+/* ECDH groups. */
-#define SSL_CURVE_SECP256R1 23
-#define SSL_CURVE_SECP384R1 24
-#define SSL_CURVE_SECP521R1 25
-#define SSL_CURVE_X25519 29
+#define SSL_GROUP_SECP256R1 23
+#define SSL_GROUP_SECP384R1 24
+#define SSL_GROUP_SECP521R1 25
+#define SSL_GROUP_X25519 29
+#define SSL_GROUP_CECPQ1 65165
/* An SSL_ECDH_METHOD is an implementation of ECDH-like key exchanges for
* TLS. */
struct ssl_ecdh_method_st {
int nid;
- uint16_t curve_id;
+ uint16_t group_id;
const char name[8];
/* cleanup releases state in |ctx|. */
void (*cleanup)(SSL_ECDH_CTX *ctx);
- /* generate_keypair generates a keypair and writes the public value to
+ /* offer generates a keypair and writes the public value to
* |out_public_key|. It returns one on success and zero on error. */
- int (*generate_keypair)(SSL_ECDH_CTX *ctx, CBB *out_public_key);
-
- /* compute_secret performs a key exchange against |peer_key| and, on
- * success, returns one and sets |*out_secret| and |*out_secret_len| to
- * a newly-allocated buffer containing the shared secret. The caller must
- * release this buffer with |OPENSSL_free|. Otherwise, it returns zero and
- * sets |*out_alert| to an alert to send to the peer. */
- int (*compute_secret)(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len);
+ int (*offer)(SSL_ECDH_CTX *ctx, CBB *out_public_key);
+
+ /* accept performs a key exchange against the |peer_key| generated by |offer|.
+ * On success, it returns one, writes the public value to |out_public_key|,
+ * and sets |*out_secret| and |*out_secret_len| to a newly-allocated buffer
+ * containing the shared secret. The caller must release this buffer with
+ * |OPENSSL_free|. On failure, it returns zero and sets |*out_alert| to an
+ * alert to send to the peer. */
+ int (*accept)(SSL_ECDH_CTX *ctx, CBB *out_public_key, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len);
+
+ /* finish performs a key exchange against the |peer_key| generated by
+ * |accept|. On success, it returns one and sets |*out_secret| and
+ * |*out_secret_len| to a newly-allocated buffer containing the shared
+ * secret. The caller must release this buffer with |OPENSSL_free|. On
+ * failure, it returns zero and sets |*out_alert| to an alert to send to the
+ * peer. */
+ int (*finish)(SSL_ECDH_CTX *ctx, uint8_t **out_secret, size_t *out_secret_len,
+ uint8_t *out_alert, const uint8_t *peer_key,
+ size_t peer_key_len);
+
+ /* get_key initializes |out| with a length-prefixed key from |cbs|. It returns
+ * one on success and zero on error. */
+ int (*get_key)(CBS *cbs, CBS *out);
+
+ /* add_key initializes |out_contents| to receive a key. Typically it will then
+ * be passed to |offer| or |accept|. It returns one on success and zero on
+ * error. */
+ int (*add_key)(CBB *cbb, CBB *out_contents);
} /* SSL_ECDH_METHOD */;
-/* ssl_nid_to_curve_id looks up the curve corresponding to |nid|. On success, it
- * sets |*out_curve_id| to the curve ID and returns one. Otherwise, it returns
+/* ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it
+ * sets |*out_group_id| to the group ID and returns one. Otherwise, it returns
* zero. */
-int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid);
+int ssl_nid_to_group_id(uint16_t *out_group_id, int nid);
-/* SSL_ECDH_CTX_init sets up |ctx| for use with curve |curve_id|. It returns one
+/* SSL_ECDH_CTX_init sets up |ctx| for use with curve |group_id|. It returns one
* on success and zero on error. */
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id);
+int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id);
/* SSL_ECDH_CTX_init_for_dhe sets up |ctx| for use with legacy DHE-based ciphers
* where the server specifies a group. It takes ownership of |params|. */
@@ -574,12 +613,41 @@ void SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX *ctx, DH *params);
* call it in the zero state. */
void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx);
-/* The following functions call the corresponding method of
- * |SSL_ECDH_METHOD|. */
-int SSL_ECDH_CTX_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out_public_key);
-int SSL_ECDH_CTX_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len);
+/* SSL_ECDH_CTX_get_key calls the |get_key| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out);
+
+/* SSL_ECDH_CTX_add_key calls the |add_key| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents);
+
+/* SSL_ECDH_CTX_offer calls the |offer| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key);
+
+/* SSL_ECDH_CTX_accept calls the |accept| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+ uint8_t **out_secret, size_t *out_secret_len,
+ uint8_t *out_alert, const uint8_t *peer_key,
+ size_t peer_key_len);
+
+/* SSL_ECDH_CTX_finish the |finish| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len);
+
+/* Handshake messages. */
+
+/* ssl_max_handshake_message_len returns the maximum number of bytes permitted
+ * in a handshake message for |ssl|. */
+size_t ssl_max_handshake_message_len(const SSL *ssl);
+
+
+/* Callbacks. */
+
+/* ssl_do_info_callback calls |ssl|'s info callback, if set. */
+void ssl_do_info_callback(const SSL *ssl, int type, int value);
+
+/* ssl_do_msg_callback calls |ssl|'s message callback, if set. */
+void ssl_do_msg_callback(SSL *ssl, int is_write, int version, int content_type,
+ const void *buf, size_t len);
/* Transport buffers. */
@@ -641,100 +709,17 @@ void ssl_write_buffer_clear(SSL *ssl);
*
* Functions below here haven't been touched up and may be underdocumented. */
-#define c2l(c, l) \
- (l = ((unsigned long)(*((c)++))), l |= (((unsigned long)(*((c)++))) << 8), \
- l |= (((unsigned long)(*((c)++))) << 16), \
- l |= (((unsigned long)(*((c)++))) << 24))
-
-/* NOTE - c is not incremented as per c2l */
-#define c2ln(c, l1, l2, n) \
- { \
- c += n; \
- l1 = l2 = 0; \
- switch (n) { \
- case 8: \
- l2 = ((unsigned long)(*(--(c)))) << 24; \
- case 7: \
- l2 |= ((unsigned long)(*(--(c)))) << 16; \
- case 6: \
- l2 |= ((unsigned long)(*(--(c)))) << 8; \
- case 5: \
- l2 |= ((unsigned long)(*(--(c)))); \
- case 4: \
- l1 = ((unsigned long)(*(--(c)))) << 24; \
- case 3: \
- l1 |= ((unsigned long)(*(--(c)))) << 16; \
- case 2: \
- l1 |= ((unsigned long)(*(--(c)))) << 8; \
- case 1: \
- l1 |= ((unsigned long)(*(--(c)))); \
- } \
- }
-
-#define l2c(l, c) \
- (*((c)++) = (uint8_t)(((l)) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 24) & 0xff))
-
-#define n2l(c, l) \
- (l = ((unsigned long)(*((c)++))) << 24, \
- l |= ((unsigned long)(*((c)++))) << 16, \
- l |= ((unsigned long)(*((c)++))) << 8, l |= ((unsigned long)(*((c)++))))
-
#define l2n(l, c) \
(*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
*((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
*((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
*((c)++) = (uint8_t)(((l)) & 0xff))
-#define l2n8(l, c) \
- (*((c)++) = (uint8_t)(((l) >> 56) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 48) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 40) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 32) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
- *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
- *((c)++) = (uint8_t)(((l)) & 0xff))
-
-/* NOTE - c is not incremented as per l2c */
-#define l2cn(l1, l2, c, n) \
- { \
- c += n; \
- switch (n) { \
- case 8: \
- *(--(c)) = (uint8_t)(((l2) >> 24) & 0xff); \
- case 7: \
- *(--(c)) = (uint8_t)(((l2) >> 16) & 0xff); \
- case 6: \
- *(--(c)) = (uint8_t)(((l2) >> 8) & 0xff); \
- case 5: \
- *(--(c)) = (uint8_t)(((l2)) & 0xff); \
- case 4: \
- *(--(c)) = (uint8_t)(((l1) >> 24) & 0xff); \
- case 3: \
- *(--(c)) = (uint8_t)(((l1) >> 16) & 0xff); \
- case 2: \
- *(--(c)) = (uint8_t)(((l1) >> 8) & 0xff); \
- case 1: \
- *(--(c)) = (uint8_t)(((l1)) & 0xff); \
- } \
- }
-
-#define n2s(c, s) \
- ((s = (((unsigned int)(c[0])) << 8) | (((unsigned int)(c[1])))), c += 2)
-
#define s2n(s, c) \
((c[0] = (uint8_t)(((s) >> 8) & 0xff), \
c[1] = (uint8_t)(((s)) & 0xff)), \
c += 2)
-#define n2l3(c, l) \
- ((l = (((unsigned long)(c[0])) << 16) | (((unsigned long)(c[1])) << 8) | \
- (((unsigned long)(c[2])))), \
- c += 3)
-
#define l2n3(l, c) \
((c[0] = (uint8_t)(((l) >> 16) & 0xff), \
c[1] = (uint8_t)(((l) >> 8) & 0xff), \
@@ -803,6 +788,10 @@ typedef struct cert_st {
* supported signature algorithms or curves. */
int (*cert_cb)(SSL *ssl, void *arg);
void *cert_cb_arg;
+
+ /* Optional X509_STORE for certificate validation. If NULL the parent SSL_CTX
+ * store is used instead. */
+ X509_STORE *verify_store;
} CERT;
/* SSL_METHOD is a compatibility structure to support the legacy version-locked
@@ -822,10 +811,7 @@ struct ssl_protocol_method_st {
char is_dtls;
int (*ssl_new)(SSL *ssl);
void (*ssl_free)(SSL *ssl);
- int (*ssl_accept)(SSL *ssl);
- int (*ssl_connect)(SSL *ssl);
- long (*ssl_get_message)(SSL *ssl, int header_state, int body_state,
- int msg_type, long max,
+ long (*ssl_get_message)(SSL *ssl, int msg_type,
enum ssl_hash_message_t hash_message, int *ok);
int (*ssl_read_app_data)(SSL *ssl, uint8_t *buf, int len, int peek);
int (*ssl_read_change_cipher_spec)(SSL *ssl);
@@ -841,6 +827,14 @@ struct ssl_protocol_method_st {
int (*set_handshake_header)(SSL *ssl, int type, unsigned long len);
/* Write out handshake message */
int (*do_write)(SSL *ssl);
+ /* send_change_cipher_spec sends a ChangeCipherSpec message. */
+ int (*send_change_cipher_spec)(SSL *ssl, int a, int b);
+ /* expect_flight is called when the handshake expects a flight of messages from
+ * the peer. */
+ void (*expect_flight)(SSL *ssl);
+ /* received_flight is called when the handshake has received a flight of
+ * messages from the peer. */
+ void (*received_flight)(SSL *ssl);
};
/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit
@@ -952,13 +946,12 @@ typedef struct dtls1_state_st {
* timeout. */
struct timeval next_timeout;
- /* Timeout duration */
- unsigned short timeout_duration;
+ /* timeout_duration_ms is the timeout duration in milliseconds. */
+ unsigned timeout_duration_ms;
} DTLS1_STATE;
extern const SSL3_ENC_METHOD TLSv1_enc_data;
extern const SSL3_ENC_METHOD SSLv3_enc_data;
-extern const SRTP_PROTECTION_PROFILE kSRTPProfiles[];
int ssl_clear_bad_session(SSL *ssl);
CERT *ssl_cert_new(void);
@@ -1013,17 +1006,14 @@ int ssl_verify_alarm_type(long type);
* |len|. It returns one on success and zero on failure. */
int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server);
-int ssl3_send_server_certificate(SSL *ssl);
-int ssl3_send_new_session_ticket(SSL *ssl);
-int ssl3_send_certificate_status(SSL *ssl);
-int ssl3_get_finished(SSL *ssl, int state_a, int state_b);
+int ssl3_get_finished(SSL *ssl);
int ssl3_send_change_cipher_spec(SSL *ssl, int state_a, int state_b);
void ssl3_cleanup_key_block(SSL *ssl);
int ssl3_do_write(SSL *ssl, int type);
int ssl3_send_alert(SSL *ssl, int level, int desc);
int ssl3_get_req_cert_type(SSL *ssl, uint8_t *p);
-long ssl3_get_message(SSL *ssl, int header_state, int body_state, int msg_type,
- long max, enum ssl_hash_message_t hash_message, int *ok);
+long ssl3_get_message(SSL *ssl, int msg_type,
+ enum ssl_hash_message_t hash_message, int *ok);
/* ssl3_hash_current_message incorporates the current handshake message into the
* handshake hash. It returns one on success and zero on allocation failure. */
@@ -1059,30 +1049,42 @@ int ssl3_connect(SSL *ssl);
int ssl3_set_handshake_header(SSL *ssl, int htype, unsigned long len);
int ssl3_handshake_write(SSL *ssl);
+void ssl3_expect_flight(SSL *ssl);
+void ssl3_received_flight(SSL *ssl);
int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch);
+
+/* dtls1_get_record reads a new input record. On success, it places it in
+ * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
+ * more data is needed. */
+int dtls1_get_record(SSL *ssl);
+
int dtls1_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek);
int dtls1_read_change_cipher_spec(SSL *ssl);
void dtls1_read_close_notify(SSL *ssl);
-int dtls1_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek);
void dtls1_set_message_header(SSL *ssl, uint8_t mt, unsigned long len,
unsigned short seq_num, unsigned long frag_off,
unsigned long frag_len);
int dtls1_write_app_data(SSL *ssl, const void *buf, int len);
-int dtls1_write_bytes(SSL *ssl, int type, const void *buf, int len,
- enum dtls1_use_epoch_t use_epoch);
+
+/* dtls1_write_record sends a record. It returns one on success and <= 0 on
+ * error. */
+int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len,
+ enum dtls1_use_epoch_t use_epoch);
int dtls1_send_change_cipher_spec(SSL *ssl, int a, int b);
int dtls1_send_finished(SSL *ssl, int a, int b, const char *sender, int slen);
-int dtls1_read_failed(SSL *ssl, int code);
int dtls1_buffer_message(SSL *ssl);
int dtls1_retransmit_buffered_messages(SSL *ssl);
void dtls1_clear_record_buffer(SSL *ssl);
-void dtls1_get_message_header(uint8_t *data, struct hm_header_st *msg_hdr);
+int dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr,
+ CBS *out_body);
int dtls1_check_timeout_num(SSL *ssl);
int dtls1_set_handshake_header(SSL *ssl, int type, unsigned long len);
int dtls1_handshake_write(SSL *ssl);
+void dtls1_expect_flight(SSL *ssl);
+void dtls1_received_flight(SSL *ssl);
int dtls1_supports_cipher(const SSL_CIPHER *cipher);
void dtls1_start_timer(SSL *ssl);
@@ -1092,47 +1094,20 @@ void dtls1_double_timeout(SSL *ssl);
unsigned int dtls1_min_mtu(void);
void dtls1_hm_fragment_free(hm_fragment *frag);
-/* some client-only functions */
-int ssl3_send_client_hello(SSL *ssl);
-int ssl3_get_server_hello(SSL *ssl);
-int ssl3_get_certificate_request(SSL *ssl);
-int ssl3_get_new_session_ticket(SSL *ssl);
-int ssl3_get_cert_status(SSL *ssl);
-int ssl3_get_server_done(SSL *ssl);
-int ssl3_send_cert_verify(SSL *ssl);
-int ssl3_send_client_certificate(SSL *ssl);
-int ssl_do_client_cert_cb(SSL *ssl, X509 **px509, EVP_PKEY **ppkey);
-int ssl3_send_client_key_exchange(SSL *ssl);
-int ssl3_get_server_key_exchange(SSL *ssl);
-int ssl3_get_server_certificate(SSL *ssl);
-int ssl3_send_next_proto(SSL *ssl);
-int ssl3_send_channel_id(SSL *ssl);
-int ssl3_verify_server_cert(SSL *ssl);
-
-/* some server-only functions */
-int ssl3_get_initial_bytes(SSL *ssl);
-int ssl3_get_v2_client_hello(SSL *ssl);
-int ssl3_get_client_hello(SSL *ssl);
-int ssl3_send_server_hello(SSL *ssl);
-int ssl3_send_server_key_exchange(SSL *ssl);
-int ssl3_send_certificate_request(SSL *ssl);
-int ssl3_send_server_done(SSL *ssl);
-int ssl3_get_client_certificate(SSL *ssl);
-int ssl3_get_client_key_exchange(SSL *ssl);
-int ssl3_get_cert_verify(SSL *ssl);
-int ssl3_get_next_proto(SSL *ssl);
-int ssl3_get_channel_id(SSL *ssl);
-
int dtls1_new(SSL *ssl);
int dtls1_accept(SSL *ssl);
int dtls1_connect(SSL *ssl);
void dtls1_free(SSL *ssl);
-long dtls1_get_message(SSL *ssl, int st1, int stn, int mt, long max,
- enum ssl_hash_message_t hash_message, int *ok);
+long dtls1_get_message(SSL *ssl, int mt, enum ssl_hash_message_t hash_message,
+ int *ok);
int dtls1_dispatch_alert(SSL *ssl);
-int ssl_init_wbio_buffer(SSL *ssl, int push);
+/* ssl_is_wbio_buffered returns one if |ssl|'s write BIO is buffered and zero
+ * otherwise. */
+int ssl_is_wbio_buffered(const SSL *ssl);
+
+int ssl_init_wbio_buffer(SSL *ssl);
void ssl_free_wbio_buffer(SSL *ssl);
int tls1_change_cipher_state(SSL *ssl, int which);
@@ -1143,21 +1118,21 @@ int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster
char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx);
-/* tls1_check_curve_id returns one if |curve_id| is consistent with both our
- * and the peer's curve preferences. Note: if called as the client, only our
+/* tls1_check_group_id returns one if |group_id| is consistent with both our
+ * and the peer's group preferences. Note: if called as the client, only our
* preferences are checked; the peer (the server) does not send preferences. */
-int tls1_check_curve_id(SSL *ssl, uint16_t curve_id);
+int tls1_check_group_id(SSL *ssl, uint16_t group_id);
-/* tls1_get_shared_curve sets |*out_curve_id| to the first preferred shared
- * curve between client and server preferences and returns one. If none may be
+/* tls1_get_shared_group sets |*out_group_id| to the first preferred shared
+ * group between client and server preferences and returns one. If none may be
* found, it returns zero. */
-int tls1_get_shared_curve(SSL *ssl, uint16_t *out_curve_id);
+int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id);
/* tls1_set_curves converts the array of |ncurves| NIDs pointed to by |curves|
- * into a newly allocated array of TLS curve IDs. On success, the function
- * returns one and writes the array to |*out_curve_ids| and its size to
- * |*out_curve_ids_len|. Otherwise, it returns zero. */
-int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+ * into a newly allocated array of TLS group IDs. On success, the function
+ * returns one and writes the array to |*out_group_ids| and its size to
+ * |*out_group_ids_len|. Otherwise, it returns zero. */
+int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
const int *curves, size_t ncurves);
/* tls1_check_ec_cert returns one if |x| is an ECC certificate with curve and
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 725c4f53..f081066b 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -114,7 +114,6 @@
#include <assert.h>
#include <limits.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
@@ -122,7 +121,7 @@
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/md5.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/x509.h>
@@ -131,29 +130,20 @@
/* ssl3_do_write sends |ssl->init_buf| in records of type 'type'
- * (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC). It returns -1 on error, 1
- * on success or zero if the transmission is still incomplete. */
+ * (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC). It returns 1 on success
+ * and <= 0 on error. */
int ssl3_do_write(SSL *ssl, int type) {
- int n;
-
- n = ssl3_write_bytes(ssl, type, &ssl->init_buf->data[ssl->init_off],
- ssl->init_num);
- if (n < 0) {
- return -1;
- }
-
- if (n == ssl->init_num) {
- if (ssl->msg_callback) {
- ssl->msg_callback(1, ssl->version, type, ssl->init_buf->data,
- (size_t)(ssl->init_off + ssl->init_num), ssl,
- ssl->msg_callback_arg);
- }
- return 1;
+ int ret = ssl3_write_bytes(ssl, type, ssl->init_buf->data, ssl->init_num);
+ if (ret <= 0) {
+ return ret;
}
- ssl->init_off += n;
- ssl->init_num -= n;
- return 0;
+ /* ssl3_write_bytes writes the data in its entirety. */
+ assert(ret == ssl->init_num);
+ ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, type,
+ ssl->init_buf->data, (size_t)ssl->init_num);
+ ssl->init_num = 0;
+ return 1;
}
int ssl3_send_finished(SSL *ssl, int a, int b) {
@@ -212,13 +202,13 @@ static void ssl3_take_mac(SSL *ssl) {
ssl, !ssl->server, ssl->s3->tmp.peer_finish_md);
}
-int ssl3_get_finished(SSL *ssl, int a, int b) {
+int ssl3_get_finished(SSL *ssl) {
int al, finished_len, ok;
long message_len;
uint8_t *p;
- message_len = ssl->method->ssl_get_message(
- ssl, a, b, SSL3_MT_FINISHED, EVP_MAX_MD_SIZE, ssl_dont_hash_message, &ok);
+ message_len = ssl->method->ssl_get_message(ssl, SSL3_MT_FINISHED,
+ ssl_dont_hash_message, &ok);
if (!ok) {
return message_len;
@@ -239,7 +229,12 @@ int ssl3_get_finished(SSL *ssl, int a, int b) {
goto f_err;
}
- if (CRYPTO_memcmp(p, ssl->s3->tmp.peer_finish_md, finished_len) != 0) {
+ int finished_ret =
+ CRYPTO_memcmp(p, ssl->s3->tmp.peer_finish_md, finished_len);
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+ finished_ret = 0;
+#endif
+ if (finished_ret != 0) {
al = SSL_AD_DECRYPT_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
goto f_err;
@@ -270,7 +265,6 @@ int ssl3_send_change_cipher_spec(SSL *ssl, int a, int b) {
if (ssl->state == a) {
*((uint8_t *)ssl->init_buf->data) = SSL3_MT_CCS;
ssl->init_num = 1;
- ssl->init_off = 0;
ssl->state = b;
}
@@ -294,126 +288,120 @@ int ssl3_output_cert_chain(SSL *ssl) {
return ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, l);
}
-/* Obtain handshake message of message type |msg_type| (any if |msg_type| == -1),
- * maximum acceptable body length |max|. The first four bytes (msg_type and
- * length) are read in state |header_state|, the body is read in state
- * |body_state|. */
-long ssl3_get_message(SSL *ssl, int header_state, int body_state, int msg_type,
- long max, enum ssl_hash_message_t hash_message, int *ok) {
- uint8_t *p;
- unsigned long l;
- long n;
- int al;
+size_t ssl_max_handshake_message_len(const SSL *ssl) {
+ /* kMaxMessageLen is the default maximum message size for handshakes which do
+ * not accept peer certificate chains. */
+ static const size_t kMaxMessageLen = 16384;
+
+ if ((!ssl->server || (ssl->verify_mode & SSL_VERIFY_PEER)) &&
+ kMaxMessageLen < ssl->max_cert_list) {
+ return ssl->max_cert_list;
+ }
+ return kMaxMessageLen;
+}
+
+static int extend_handshake_buffer(SSL *ssl, size_t length) {
+ if (!BUF_MEM_reserve(ssl->init_buf, length)) {
+ return -1;
+ }
+ while (ssl->init_buf->length < length) {
+ int ret =
+ ssl3_read_bytes(ssl, SSL3_RT_HANDSHAKE,
+ (uint8_t *)ssl->init_buf->data + ssl->init_buf->length,
+ length - ssl->init_buf->length, 0);
+ if (ret <= 0) {
+ return ret;
+ }
+ ssl->init_buf->length += (size_t)ret;
+ }
+ return 1;
+}
+
+/* Obtain handshake message of message type |msg_type| (any if |msg_type| ==
+ * -1). */
+long ssl3_get_message(SSL *ssl, int msg_type,
+ enum ssl_hash_message_t hash_message, int *ok) {
+ *ok = 0;
if (ssl->s3->tmp.reuse_message) {
/* A ssl_dont_hash_message call cannot be combined with reuse_message; the
* ssl_dont_hash_message would have to have been applied to the previous
* call. */
assert(hash_message == ssl_hash_message);
+ assert(ssl->s3->tmp.message_complete);
ssl->s3->tmp.reuse_message = 0;
if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
+ return -1;
}
*ok = 1;
- ssl->state = body_state;
+ assert(ssl->init_buf->length >= 4);
ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
- ssl->init_num = (int)ssl->s3->tmp.message_size;
+ ssl->init_num = (int)ssl->init_buf->length - 4;
return ssl->init_num;
}
- p = (uint8_t *)ssl->init_buf->data;
-
- if (ssl->state == header_state) {
- assert(ssl->init_num < 4);
-
- for (;;) {
- while (ssl->init_num < 4) {
- int bytes_read = ssl3_read_bytes(
- ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], 4 - ssl->init_num, 0);
- if (bytes_read <= 0) {
- *ok = 0;
- return bytes_read;
- }
- ssl->init_num += bytes_read;
- }
-
- static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
- if (ssl->server || memcmp(p, kHelloRequest, sizeof(kHelloRequest)) != 0) {
- break;
- }
-
- /* The server may always send 'Hello Request' messages -- we are doing
- * a handshake anyway now, so ignore them if their format is correct.
- * Does not count for 'Finished' MAC. */
- ssl->init_num = 0;
-
- if (ssl->msg_callback) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, p, 4, ssl,
- ssl->msg_callback_arg);
- }
- }
-
- /* ssl->init_num == 4 */
+again:
+ if (ssl->s3->tmp.message_complete) {
+ ssl->s3->tmp.message_complete = 0;
+ ssl->init_buf->length = 0;
+ }
- if (msg_type >= 0 && *p != msg_type) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
- ssl->s3->tmp.message_type = *(p++);
+ /* Read the message header, if we haven't yet. */
+ int ret = extend_handshake_buffer(ssl, 4);
+ if (ret <= 0) {
+ return ret;
+ }
- n2l3(p, l);
- if (l > (unsigned long)max) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
- goto f_err;
- }
+ /* Parse out the length. Cap it so the peer cannot force us to buffer up to
+ * 2^24 bytes. */
+ const uint8_t *p = (uint8_t *)ssl->init_buf->data;
+ size_t msg_len = (((uint32_t)p[1]) << 16) | (((uint32_t)p[2]) << 8) | p[3];
+ if (msg_len > ssl_max_handshake_message_len(ssl)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return -1;
+ }
- if (l && !BUF_MEM_grow_clean(ssl->init_buf, l + 4)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
- goto err;
- }
- ssl->s3->tmp.message_size = l;
- ssl->state = body_state;
+ /* Read the message body, if we haven't yet. */
+ ret = extend_handshake_buffer(ssl, 4 + msg_len);
+ if (ret <= 0) {
+ return ret;
+ }
- ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
- ssl->init_num = 0;
+ /* We have now received a complete message. */
+ ssl->s3->tmp.message_complete = 1;
+ ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
+ ssl->init_buf->data, ssl->init_buf->length);
+
+ static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
+ if (!ssl->server && ssl->init_buf->length == sizeof(kHelloRequest) &&
+ memcmp(kHelloRequest, ssl->init_buf->data, sizeof(kHelloRequest)) == 0) {
+ /* The server may always send 'Hello Request' messages -- we are doing a
+ * handshake anyway now, so ignore them if their format is correct. Does
+ * not count for 'Finished' MAC. */
+ goto again;
}
- /* next state (body_state) */
- p = ssl->init_msg;
- n = ssl->s3->tmp.message_size - ssl->init_num;
- while (n > 0) {
- int bytes_read =
- ssl3_read_bytes(ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], n, 0);
- if (bytes_read <= 0) {
- ssl->rwstate = SSL_READING;
- *ok = 0;
- return bytes_read;
- }
- ssl->init_num += bytes_read;
- n -= bytes_read;
+ uint8_t actual_type = ((const uint8_t *)ssl->init_buf->data)[0];
+ if (msg_type >= 0 && actual_type != msg_type) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+ return -1;
}
+ ssl->s3->tmp.message_type = actual_type;
+
+ ssl->init_msg = (uint8_t*)ssl->init_buf->data + 4;
+ ssl->init_num = ssl->init_buf->length - 4;
/* Feed this message into MAC computation. */
if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
- goto err;
- }
- if (ssl->msg_callback) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
- (size_t)ssl->init_num + 4, ssl, ssl->msg_callback_arg);
+ return -1;
}
+
*ok = 1;
return ssl->init_num;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-
-err:
- *ok = 0;
- return -1;
}
int ssl3_hash_current_message(SSL *ssl) {
@@ -491,6 +479,9 @@ int ssl_verify_alarm_type(long type) {
case X509_V_ERR_CRL_NOT_YET_VALID:
case X509_V_ERR_CERT_UNTRUSTED:
case X509_V_ERR_CERT_REJECTED:
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ case X509_V_ERR_EMAIL_MISMATCH:
+ case X509_V_ERR_IP_ADDRESS_MISMATCH:
al = SSL_AD_BAD_CERTIFICATE;
break;
@@ -508,7 +499,10 @@ int ssl_verify_alarm_type(long type) {
al = SSL_AD_CERTIFICATE_REVOKED;
break;
+ case X509_V_ERR_UNSPECIFIED:
case X509_V_ERR_OUT_OF_MEM:
+ case X509_V_ERR_INVALID_CALL:
+ case X509_V_ERR_STORE_LOOKUP:
al = SSL_AD_INTERNAL_ERROR;
break;
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
deleted file mode 100644
index 09e527a0..00000000
--- a/ssl/s3_clnt.c
+++ /dev/null
@@ -1,2090 +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.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2007 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
- * openssl-core@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).
- *
- */
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * ECC cipher suite support in OpenSSL originally written by
- * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
- *
- */
-/* ====================================================================
- * Copyright 2005 Nokia. All rights reserved.
- *
- * The portions of the attached software ("Contribution") is developed by
- * Nokia Corporation and is licensed pursuant to the OpenSSL open source
- * license.
- *
- * The Contribution, originally written by Mika Kousa and Pasi Eronen of
- * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
- * support (see RFC 4279) to OpenSSL.
- *
- * No patent licenses or other rights except those expressly stated in
- * the OpenSSL open source license shall be deemed granted or received
- * expressly, by implication, estoppel, or otherwise.
- *
- * No assurances are provided by Nokia that the Contribution does not
- * infringe the patent or other intellectual property rights of any third
- * party or that the license provides you with all the necessary rights
- * to make use of the Contribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
- * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
- * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
- * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
- * OTHERWISE.
- */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/bytestring.h>
-#include <openssl/dh.h>
-#include <openssl/ec_key.h>
-#include <openssl/ecdsa.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/md5.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "internal.h"
-#include "../crypto/dh/internal.h"
-
-
-int ssl3_connect(SSL *ssl) {
- BUF_MEM *buf = NULL;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
- int ret = -1;
- int new_state, state, skip = 0;
-
- assert(ssl->handshake_func == ssl3_connect);
- assert(!ssl->server);
- assert(!SSL_IS_DTLS(ssl));
-
- ERR_clear_error();
- ERR_clear_system_error();
-
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
-
- ssl->in_handshake++;
-
- for (;;) {
- state = ssl->state;
-
- switch (ssl->state) {
- case SSL_ST_CONNECT:
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_START, 1);
- }
-
- if (ssl->init_buf == NULL) {
- buf = BUF_MEM_new();
- if (buf == NULL ||
- !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
- ret = -1;
- goto end;
- }
-
- ssl->init_buf = buf;
- buf = NULL;
- }
-
- if (!ssl_init_wbio_buffer(ssl, 0)) {
- ret = -1;
- goto end;
- }
-
- /* don't push the buffering BIO quite yet */
-
- if (!ssl3_init_handshake_buffer(ssl)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- ret = -1;
- goto end;
- }
-
- ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_CLNT_HELLO_A:
- case SSL3_ST_CW_CLNT_HELLO_B:
- ssl->shutdown = 0;
- ret = ssl3_send_client_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CR_SRVR_HELLO_A;
- ssl->init_num = 0;
-
- /* turn on buffering for the next lot of output */
- if (ssl->bbio != ssl->wbio) {
- ssl->wbio = BIO_push(ssl->bbio, ssl->wbio);
- }
-
- break;
-
- case SSL3_ST_CR_SRVR_HELLO_A:
- case SSL3_ST_CR_SRVR_HELLO_B:
- ret = ssl3_get_server_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (ssl->hit) {
- ssl->state = SSL3_ST_CR_CHANGE;
- if (ssl->tlsext_ticket_expected) {
- /* receive renewed session ticket */
- ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
- }
- } else {
- ssl->state = SSL3_ST_CR_CERT_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CERT_A:
- case SSL3_ST_CR_CERT_B:
- if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
- ret = ssl3_get_server_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- if (ssl->s3->tmp.certificate_status_expected) {
- ssl->state = SSL3_ST_CR_CERT_STATUS_A;
- } else {
- ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
- }
- } else {
- skip = 1;
- ssl->state = SSL3_ST_CR_KEY_EXCH_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_VERIFY_SERVER_CERT:
- ret = ssl3_verify_server_cert(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- ssl->state = SSL3_ST_CR_KEY_EXCH_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_KEY_EXCH_A:
- case SSL3_ST_CR_KEY_EXCH_B:
- ret = ssl3_get_server_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CR_CERT_REQ_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CERT_REQ_A:
- case SSL3_ST_CR_CERT_REQ_B:
- ret = ssl3_get_certificate_request(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CR_SRVR_DONE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_SRVR_DONE_A:
- case SSL3_ST_CR_SRVR_DONE_B:
- ret = ssl3_get_server_done(ssl);
- if (ret <= 0) {
- goto end;
- }
- if (ssl->s3->tmp.cert_req) {
- ssl->state = SSL3_ST_CW_CERT_A;
- } else {
- ssl->state = SSL3_ST_CW_KEY_EXCH_A;
- }
- ssl->init_num = 0;
-
- break;
-
- case SSL3_ST_CW_CERT_A:
- case SSL3_ST_CW_CERT_B:
- case SSL3_ST_CW_CERT_C:
- case SSL3_ST_CW_CERT_D:
- ret = ssl3_send_client_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CW_KEY_EXCH_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_KEY_EXCH_A:
- case SSL3_ST_CW_KEY_EXCH_B:
- ret = ssl3_send_client_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- /* For TLS, cert_req is set to 2, so a cert chain
- * of nothing is sent, but no verify packet is sent */
- if (ssl->s3->tmp.cert_req == 1) {
- ssl->state = SSL3_ST_CW_CERT_VRFY_A;
- } else {
- ssl->state = SSL3_ST_CW_CHANGE_A;
- }
-
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_CERT_VRFY_A:
- case SSL3_ST_CW_CERT_VRFY_B:
- case SSL3_ST_CW_CERT_VRFY_C:
- ret = ssl3_send_cert_verify(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CW_CHANGE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_CHANGE_A:
- case SSL3_ST_CW_CHANGE_B:
- ret = ssl3_send_change_cipher_spec(ssl, SSL3_ST_CW_CHANGE_A,
- SSL3_ST_CW_CHANGE_B);
- if (ret <= 0) {
- goto end;
- }
-
- ssl->state = SSL3_ST_CW_FINISHED_A;
- if (ssl->s3->tlsext_channel_id_valid) {
- ssl->state = SSL3_ST_CW_CHANNEL_ID_A;
- }
- if (ssl->s3->next_proto_neg_seen) {
- ssl->state = SSL3_ST_CW_NEXT_PROTO_A;
- }
- ssl->init_num = 0;
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
- ret = -1;
- goto end;
- }
-
- break;
-
- case SSL3_ST_CW_NEXT_PROTO_A:
- case SSL3_ST_CW_NEXT_PROTO_B:
- ret = ssl3_send_next_proto(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (ssl->s3->tlsext_channel_id_valid) {
- ssl->state = SSL3_ST_CW_CHANNEL_ID_A;
- } else {
- ssl->state = SSL3_ST_CW_FINISHED_A;
- }
- break;
-
- case SSL3_ST_CW_CHANNEL_ID_A:
- case SSL3_ST_CW_CHANNEL_ID_B:
- ret = ssl3_send_channel_id(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CW_FINISHED_A;
- break;
-
- case SSL3_ST_CW_FINISHED_A:
- case SSL3_ST_CW_FINISHED_B:
- ret = ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A,
- SSL3_ST_CW_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CW_FLUSH;
-
- if (ssl->hit) {
- ssl->s3->tmp.next_state = SSL_ST_OK;
- } else {
- /* This is a non-resumption handshake. If it involves ChannelID, then
- * record the handshake hashes at this point in the session so that
- * any resumption of this session with ChannelID can sign those
- * hashes. */
- ret = tls1_record_handshake_hashes_for_channel_id(ssl);
- if (ret <= 0) {
- goto end;
- }
- if ((SSL_get_mode(ssl) & SSL_MODE_ENABLE_FALSE_START) &&
- ssl3_can_false_start(ssl) &&
- /* No False Start on renegotiation (would complicate the state
- * machine). */
- !ssl->s3->initial_handshake_complete) {
- ssl->s3->tmp.next_state = SSL3_ST_FALSE_START;
- } else {
- /* Allow NewSessionTicket if ticket expected */
- if (ssl->tlsext_ticket_expected) {
- ssl->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
- } else {
- ssl->s3->tmp.next_state = SSL3_ST_CR_CHANGE;
- }
- }
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_SESSION_TICKET_A:
- case SSL3_ST_CR_SESSION_TICKET_B:
- ret = ssl3_get_new_session_ticket(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_CR_CHANGE;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CERT_STATUS_A:
- case SSL3_ST_CR_CERT_STATUS_B:
- ret = ssl3_get_cert_status(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CR_CHANGE:
- ret = ssl->method->ssl_read_change_cipher_spec(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_READ)) {
- ret = -1;
- goto end;
- }
- ssl->state = SSL3_ST_CR_FINISHED_A;
- break;
-
- case SSL3_ST_CR_FINISHED_A:
- case SSL3_ST_CR_FINISHED_B:
- ret = ssl3_get_finished(ssl, SSL3_ST_CR_FINISHED_A,
- SSL3_ST_CR_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
-
- if (ssl->hit) {
- ssl->state = SSL3_ST_CW_CHANGE_A;
- } else {
- ssl->state = SSL_ST_OK;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_CW_FLUSH:
- ssl->rwstate = SSL_WRITING;
- if (BIO_flush(ssl->wbio) <= 0) {
- ret = -1;
- goto end;
- }
- ssl->rwstate = SSL_NOTHING;
- ssl->state = ssl->s3->tmp.next_state;
- break;
-
- case SSL3_ST_FALSE_START:
- /* Allow NewSessionTicket if ticket expected */
- if (ssl->tlsext_ticket_expected) {
- ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
- } else {
- ssl->state = SSL3_ST_CR_CHANGE;
- }
- ssl->s3->tmp.in_false_start = 1;
-
- ssl_free_wbio_buffer(ssl);
- ret = 1;
- goto end;
-
- case SSL_ST_OK:
- /* clean a few things up */
- ssl3_cleanup_key_block(ssl);
-
- BUF_MEM_free(ssl->init_buf);
- ssl->init_buf = NULL;
-
- /* Remove write buffering now. */
- ssl_free_wbio_buffer(ssl);
-
- const int is_initial_handshake = !ssl->s3->initial_handshake_complete;
-
- ssl->init_num = 0;
- ssl->s3->tmp.in_false_start = 0;
- ssl->s3->initial_handshake_complete = 1;
-
- if (is_initial_handshake) {
- /* Renegotiations do not participate in session resumption. */
- ssl_update_cache(ssl, SSL_SESS_CACHE_CLIENT);
- }
-
- ret = 1;
- /* ssl->server=0; */
-
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
- }
-
- goto end;
-
- default:
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
- ret = -1;
- goto end;
- }
-
- if (!ssl->s3->tmp.reuse_message && !skip) {
- if (cb != NULL && ssl->state != state) {
- new_state = ssl->state;
- ssl->state = state;
- cb(ssl, SSL_CB_CONNECT_LOOP, 1);
- ssl->state = new_state;
- }
- }
- skip = 0;
- }
-
-end:
- ssl->in_handshake--;
- BUF_MEM_free(buf);
- if (cb != NULL) {
- cb(ssl, SSL_CB_CONNECT_EXIT, ret);
- }
- return ret;
-}
-
-static int ssl3_write_client_cipher_list(SSL *ssl, CBB *out) {
- /* Prepare disabled cipher masks. */
- ssl_set_client_disabled(ssl);
-
- CBB child;
- if (!CBB_add_u16_length_prefixed(out, &child)) {
- return 0;
- }
-
- STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
-
- int any_enabled = 0;
- size_t i;
- for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
- /* Skip disabled ciphers */
- if ((cipher->algorithm_mkey & ssl->cert->mask_k) ||
- (cipher->algorithm_auth & ssl->cert->mask_a)) {
- continue;
- }
- if (SSL_CIPHER_get_min_version(cipher) >
- ssl3_version_from_wire(ssl, ssl->client_version)) {
- continue;
- }
- any_enabled = 1;
- if (!CBB_add_u16(&child, ssl_cipher_get_value(cipher))) {
- return 0;
- }
- }
-
- /* If all ciphers were disabled, return the error to the caller. */
- if (!any_enabled) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_AVAILABLE);
- return 0;
- }
-
- /* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is
- * added. */
- if (ssl->client_version == SSL3_VERSION &&
- !ssl->s3->initial_handshake_complete) {
- if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) {
- return 0;
- }
- /* The renegotiation extension is required to be at index zero. */
- ssl->s3->tmp.extensions.sent |= (1u << 0);
- }
-
- if ((ssl->mode & SSL_MODE_SEND_FALLBACK_SCSV) &&
- !CBB_add_u16(&child, SSL3_CK_FALLBACK_SCSV & 0xffff)) {
- return 0;
- }
-
- return CBB_flush(out);
-}
-
-int ssl3_send_client_hello(SSL *ssl) {
- if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) {
- return ssl_do_write(ssl);
- }
-
- /* In DTLS, reset the handshake buffer each time a new ClientHello is
- * assembled. We may send multiple if we receive HelloVerifyRequest. */
- if (SSL_IS_DTLS(ssl) && !ssl3_init_handshake_buffer(ssl)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
- CBB cbb;
- CBB_zero(&cbb);
-
- assert(ssl->state == SSL3_ST_CW_CLNT_HELLO_A);
- if (!ssl->s3->have_version) {
- uint16_t max_version = ssl3_get_max_client_version(ssl);
- /* Disabling all versions is silly: return an error. */
- if (max_version == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
- goto err;
- }
-
- ssl->version = max_version;
- /* Only set |ssl->client_version| on the initial handshake. Renegotiations,
- * although locked to a version, reuse the value. When using the plain RSA
- * key exchange, the ClientHello version is checked in the premaster secret.
- * Some servers fail when this value changes. */
- ssl->client_version = max_version;
- }
-
- /* If the configured session has expired or was created at a version higher
- * than our maximum version, drop it. */
- if (ssl->session != NULL &&
- (ssl->session->session_id_length == 0 || ssl->session->not_resumable ||
- ssl->session->timeout < (long)(time(NULL) - ssl->session->time) ||
- (!SSL_IS_DTLS(ssl) && ssl->session->ssl_version > ssl->version) ||
- (SSL_IS_DTLS(ssl) && ssl->session->ssl_version < ssl->version))) {
- SSL_set_session(ssl, NULL);
- }
-
- /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't
- * renegerate the client_random. The random must be reused. */
- if ((!SSL_IS_DTLS(ssl) || !ssl->d1->send_cookie) &&
- !ssl_fill_hello_random(ssl->s3->client_random,
- sizeof(ssl->s3->client_random), 0 /* client */)) {
- goto err;
- }
-
- /* Renegotiations do not participate in session resumption. */
- int has_session = ssl->session != NULL &&
- !ssl->s3->initial_handshake_complete;
-
- CBB child;
- if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
- !CBB_add_u16(&cbb, ssl->client_version) ||
- !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
- (has_session &&
- !CBB_add_bytes(&child, ssl->session->session_id,
- ssl->session->session_id_length))) {
- goto err;
- }
-
- if (SSL_IS_DTLS(ssl)) {
- if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) {
- goto err;
- }
- }
-
- size_t length;
- if (!ssl3_write_client_cipher_list(ssl, &cbb) ||
- !CBB_add_u8(&cbb, 1 /* one compression method */) ||
- !CBB_add_u8(&cbb, 0 /* null compression */) ||
- !ssl_add_clienthello_tlsext(ssl, &cbb,
- CBB_len(&cbb) + SSL_HM_HEADER_LENGTH(ssl)) ||
- !CBB_finish(&cbb, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_HELLO, length)) {
- goto err;
- }
-
- ssl->state = SSL3_ST_CW_CLNT_HELLO_B;
- return ssl_do_write(ssl);
-
-err:
- CBB_cleanup(&cbb);
- return -1;
-}
-
-int ssl3_get_server_hello(SSL *ssl) {
- STACK_OF(SSL_CIPHER) *sk;
- const SSL_CIPHER *c;
- CERT *ct = ssl->cert;
- int al = SSL_AD_INTERNAL_ERROR, ok;
- long n;
- CBS server_hello, server_random, session_id;
- uint16_t server_version, cipher_suite;
- uint8_t compression_method;
-
- n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_SRVR_HELLO_A,
- SSL3_ST_CR_SRVR_HELLO_B, SSL3_MT_SERVER_HELLO,
- 20000, /* ?? */
- ssl_hash_message, &ok);
-
- if (!ok) {
- uint32_t err = ERR_peek_error();
- if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
- ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) {
- /* Add a dedicated error code to the queue for a handshake_failure alert
- * in response to ClientHello. This matches NSS's client behavior and
- * gives a better error on a (probable) failure to negotiate initial
- * parameters. Note: this error code comes after the original one.
- *
- * See https://crbug.com/446505. */
- OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO);
- }
- return n;
- }
-
- CBS_init(&server_hello, ssl->init_msg, n);
-
- if (!CBS_get_u16(&server_hello, &server_version) ||
- !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
- !CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
- CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
- !CBS_get_u16(&server_hello, &cipher_suite) ||
- !CBS_get_u8(&server_hello, &compression_method)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete);
- if (!ssl->s3->have_version) {
- if (!ssl3_is_version_enabled(ssl, server_version)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
- ssl->version = server_version;
- /* Mark the version as fixed so the record-layer version is not clamped
- * to TLS 1.0. */
- ssl->s3->have_version = 1;
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
- }
- ssl->version = server_version;
- ssl->s3->enc_method = ssl3_get_enc_method(server_version);
- assert(ssl->s3->enc_method != NULL);
- /* At this point, the connection's version is known and ssl->version is
- * fixed. Begin enforcing the record-layer version. */
- ssl->s3->have_version = 1;
- } else if (server_version != ssl->version) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
- }
-
- /* Copy over the server random. */
- memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
-
- assert(ssl->session == NULL || ssl->session->session_id_length > 0);
- if (!ssl->s3->initial_handshake_complete && ssl->session != NULL &&
- CBS_mem_equal(&session_id, ssl->session->session_id,
- ssl->session->session_id_length)) {
- if (ssl->sid_ctx_length != ssl->session->sid_ctx_length ||
- memcmp(ssl->session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length)) {
- /* actually a client application bug */
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL,
- SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
- goto f_err;
- }
- ssl->hit = 1;
- } else {
- /* The session wasn't resumed. Create a fresh SSL_SESSION to
- * fill out. */
- ssl->hit = 0;
- if (!ssl_get_new_session(ssl, 0 /* client */)) {
- goto f_err;
- }
- /* Note: session_id could be empty. */
- ssl->session->session_id_length = CBS_len(&session_id);
- memcpy(ssl->session->session_id, CBS_data(&session_id),
- CBS_len(&session_id));
- }
-
- c = SSL_get_cipher_by_value(cipher_suite);
- if (c == NULL) {
- /* unknown cipher */
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
- goto f_err;
- }
- /* If the cipher is disabled then we didn't sent it in the ClientHello, so if
- * the server selected it, it's an error. */
- if ((c->algorithm_mkey & ct->mask_k) || (c->algorithm_auth & ct->mask_a) ||
- SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
- goto f_err;
- }
-
- sk = ssl_get_ciphers_by_id(ssl);
- if (!sk_SSL_CIPHER_find(sk, NULL, c)) {
- /* we did not say we would use this cipher */
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
- goto f_err;
- }
-
- if (ssl->hit) {
- if (ssl->session->cipher != c) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
- goto f_err;
- }
- if (ssl->session->ssl_version != ssl->version) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED);
- goto f_err;
- }
- } else {
- ssl->session->cipher = c;
- }
- ssl->s3->tmp.new_cipher = c;
-
- /* Now that the cipher is known, initialize the handshake hash. */
- if (!ssl3_init_handshake_hash(ssl)) {
- goto f_err;
- }
-
- /* If doing a full handshake with TLS 1.2, the server may request a client
- * certificate which requires hashing the handshake transcript under a
- * different hash. Otherwise, the handshake buffer may be released. */
- if (ssl->hit || ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
- ssl3_free_handshake_buffer(ssl);
- }
-
- /* Only the NULL compression algorithm is supported. */
- if (compression_method != 0) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
- goto f_err;
- }
-
- /* TLS extensions */
- if (!ssl_parse_serverhello_tlsext(ssl, &server_hello)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
- goto err;
- }
-
- /* There should be nothing left over in the record. */
- if (CBS_len(&server_hello) != 0) {
- /* wrong packet length */
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
- goto f_err;
- }
-
- if (ssl->hit &&
- ssl->s3->tmp.extended_master_secret !=
- ssl->session->extended_master_secret) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- if (ssl->session->extended_master_secret) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
- } else {
- OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION);
- }
- goto f_err;
- }
-
- return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
- return -1;
-}
-
-/* ssl3_check_leaf_certificate returns one if |leaf| is a suitable leaf server
- * certificate for |ssl|. Otherwise, it returns zero and pushes an error on the
- * error queue. */
-static int ssl3_check_leaf_certificate(SSL *ssl, X509 *leaf) {
- int ret = 0;
- EVP_PKEY *pkey = X509_get_pubkey(leaf);
- if (pkey == NULL) {
- goto err;
- }
-
- /* Check the certificate's type matches the cipher. */
- const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher;
- int expected_type = ssl_cipher_get_key_type(cipher);
- assert(expected_type != EVP_PKEY_NONE);
- if (pkey->type != expected_type) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE);
- goto err;
- }
-
- if (cipher->algorithm_auth & SSL_aECDSA) {
- /* TODO(davidben): This behavior is preserved from upstream. Should key
- * usages be checked in other cases as well? */
- /* This call populates the ex_flags field correctly */
- X509_check_purpose(leaf, -1, 0);
- if ((leaf->ex_flags & EXFLAG_KUSAGE) &&
- !(leaf->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
- goto err;
- }
-
- if (!tls1_check_ec_cert(ssl, leaf)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
- goto err;
- }
- }
-
- ret = 1;
-
-err:
- EVP_PKEY_free(pkey);
- return ret;
-}
-
-int ssl3_get_server_certificate(SSL *ssl) {
- int al, ok, ret = -1;
- unsigned long n;
- X509 *x = NULL;
- STACK_OF(X509) *sk = NULL;
- EVP_PKEY *pkey = NULL;
- CBS cbs, certificate_list;
- const uint8_t *data;
-
- n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_CERT_A, SSL3_ST_CR_CERT_B,
- SSL3_MT_CERTIFICATE, (long)ssl->max_cert_list,
- ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- CBS_init(&cbs, ssl->init_msg, n);
-
- sk = sk_X509_new_null();
- if (sk == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) ||
- CBS_len(&certificate_list) == 0 ||
- CBS_len(&cbs) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- while (CBS_len(&certificate_list) > 0) {
- CBS certificate;
- if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
- goto f_err;
- }
- /* A u24 length cannot overflow a long. */
- data = CBS_data(&certificate);
- x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
- if (x == NULL) {
- al = SSL_AD_BAD_CERTIFICATE;
- OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
- goto f_err;
- }
- if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
- goto f_err;
- }
- if (!sk_X509_push(sk, x)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- x = NULL;
- }
-
- X509 *leaf = sk_X509_value(sk, 0);
- if (!ssl3_check_leaf_certificate(ssl, leaf)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- goto f_err;
- }
-
- /* NOTE: Unlike the server half, the client's copy of |cert_chain| includes
- * the leaf. */
- sk_X509_pop_free(ssl->session->cert_chain, X509_free);
- ssl->session->cert_chain = sk;
- sk = NULL;
-
- X509_free(ssl->session->peer);
- ssl->session->peer = X509_up_ref(leaf);
-
- ssl->session->verify_result = ssl->verify_result;
-
- ret = 1;
-
- if (0) {
- f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- }
-
-err:
- EVP_PKEY_free(pkey);
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return ret;
-}
-
-int ssl3_get_server_key_exchange(SSL *ssl) {
- EVP_MD_CTX md_ctx;
- int al, ok;
- EVP_PKEY *pkey = NULL;
- DH *dh = NULL;
- EC_KEY *ecdh = NULL;
- EC_POINT *srvr_ecpoint = NULL;
-
- /* use same message size as in ssl3_get_certificate_request() as
- * ServerKeyExchange message may be skipped */
- long n = ssl->method->ssl_get_message(
- ssl, SSL3_ST_CR_KEY_EXCH_A, SSL3_ST_CR_KEY_EXCH_B, -1, ssl->max_cert_list,
- ssl_hash_message, &ok);
- if (!ok) {
- return n;
- }
-
- if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
- if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
- return -1;
- }
-
- /* In plain PSK ciphersuite, ServerKeyExchange may be omitted to send no
- * identity hint. */
- if (ssl->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) {
- /* TODO(davidben): This should be reset in one place with the rest of the
- * handshake state. */
- OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint);
- ssl->s3->tmp.peer_psk_identity_hint = NULL;
- }
- ssl->s3->tmp.reuse_message = 1;
- return 1;
- }
-
- /* Retain a copy of the original CBS to compute the signature over. */
- CBS server_key_exchange;
- CBS_init(&server_key_exchange, ssl->init_msg, n);
- CBS server_key_exchange_orig = server_key_exchange;
-
- uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
- uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
- EVP_MD_CTX_init(&md_ctx);
-
- if (alg_a & SSL_aPSK) {
- CBS psk_identity_hint;
-
- /* Each of the PSK key exchanges begins with a psk_identity_hint. */
- if (!CBS_get_u16_length_prefixed(&server_key_exchange,
- &psk_identity_hint)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- /* Store PSK identity hint for later use, hint is used in
- * ssl3_send_client_key_exchange. Assume that the maximum length of a PSK
- * identity hint can be as long as the maximum length of a PSK identity.
- * Also do not allow NULL characters; identities are saved as C strings.
- *
- * TODO(davidben): Should invalid hints be ignored? It's a hint rather than
- * a specific identity. */
- if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
- CBS_contains_zero_byte(&psk_identity_hint)) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
- goto f_err;
- }
-
- /* Save the identity hint as a C string. */
- if (!CBS_strdup(&psk_identity_hint, &ssl->s3->tmp.peer_psk_identity_hint)) {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- }
-
- if (alg_k & SSL_kDHE) {
- CBS dh_p, dh_g, dh_Ys;
- if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
- CBS_len(&dh_p) == 0 ||
- !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
- CBS_len(&dh_g) == 0 ||
- !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
- CBS_len(&dh_Ys) == 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- dh = DH_new();
- if (dh == NULL) {
- goto err;
- }
-
- dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL);
- dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL);
- if (dh->p == NULL || dh->g == NULL) {
- goto err;
- }
-
- ssl->session->key_exchange_info = DH_num_bits(dh);
- if (ssl->session->key_exchange_info < 1024) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH);
- goto err;
- } else if (ssl->session->key_exchange_info > 4096) {
- /* Overly large DHE groups are prohibitively expensive, so enforce a limit
- * to prevent a server from causing us to perform too expensive of a
- * computation. */
- OPENSSL_PUT_ERROR(SSL, SSL_R_DH_P_TOO_LONG);
- goto err;
- }
-
- SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
- dh = NULL;
-
- /* Save the peer public key for later. */
- size_t peer_key_len;
- if (!CBS_stow(&dh_Ys, &ssl->s3->tmp.peer_key, &peer_key_len)) {
- goto err;
- }
- /* |dh_Ys| has a u16 length prefix, so this fits in a |uint16_t|. */
- assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
- ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
- } else if (alg_k & SSL_kECDHE) {
- /* Parse the server parameters. */
- uint8_t curve_type;
- uint16_t curve_id;
- CBS point;
- if (!CBS_get_u8(&server_key_exchange, &curve_type) ||
- curve_type != NAMED_CURVE_TYPE ||
- !CBS_get_u16(&server_key_exchange, &curve_id) ||
- !CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
- ssl->session->key_exchange_info = curve_id;
-
- /* Ensure the curve is consistent with preferences. */
- if (!tls1_check_curve_id(ssl, curve_id)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
- goto f_err;
- }
-
- /* Initialize ECDH and save the peer public key for later. */
- size_t peer_key_len;
- if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, curve_id) ||
- !CBS_stow(&point, &ssl->s3->tmp.peer_key, &peer_key_len)) {
- goto err;
- }
- /* |point| has a u8 length prefix, so this fits in a |uint16_t|. */
- assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
- ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
- } else if (!(alg_k & SSL_kPSK)) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
-
- /* At this point, |server_key_exchange| contains the signature, if any, while
- * |server_key_exchange_orig| contains the entire message. From that, derive
- * a CBS containing just the parameter. */
- CBS parameter;
- CBS_init(&parameter, CBS_data(&server_key_exchange_orig),
- CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange));
-
- /* ServerKeyExchange should be signed by the server's public key. */
- if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
- pkey = X509_get_pubkey(ssl->session->peer);
- if (pkey == NULL) {
- goto err;
- }
-
- const EVP_MD *md = NULL;
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- uint8_t hash, signature;
- if (!CBS_get_u8(&server_key_exchange, &hash) ||
- !CBS_get_u8(&server_key_exchange, &signature)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
- if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature, pkey)) {
- goto f_err;
- }
- ssl->s3->tmp.server_key_exchange_hash = hash;
- } else if (pkey->type == EVP_PKEY_RSA) {
- md = EVP_md5_sha1();
- } else {
- md = EVP_sha1();
- }
-
- /* The last field in |server_key_exchange| is the signature. */
- CBS signature;
- if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
- CBS_len(&server_key_exchange) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
- !EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->client_random,
- SSL3_RANDOM_SIZE) ||
- !EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->server_random,
- SSL3_RANDOM_SIZE) ||
- !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&parameter),
- CBS_len(&parameter)) ||
- !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
- CBS_len(&signature))) {
- /* bad signature */
- al = SSL_AD_DECRYPT_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
- goto f_err;
- }
- } else {
- /* PSK ciphers are the only supported certificate-less ciphers. */
- assert(alg_a == SSL_aPSK);
-
- if (CBS_len(&server_key_exchange) > 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE);
- goto f_err;
- }
- }
- EVP_PKEY_free(pkey);
- EVP_MD_CTX_cleanup(&md_ctx);
- return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
- EVP_PKEY_free(pkey);
- DH_free(dh);
- EC_POINT_free(srvr_ecpoint);
- EC_KEY_free(ecdh);
- EVP_MD_CTX_cleanup(&md_ctx);
- return -1;
-}
-
-static int ca_dn_cmp(const X509_NAME **a, const X509_NAME **b) {
- return X509_NAME_cmp(*a, *b);
-}
-
-int ssl3_get_certificate_request(SSL *ssl) {
- int ok, ret = 0;
- unsigned long n;
- X509_NAME *xn = NULL;
- STACK_OF(X509_NAME) *ca_sk = NULL;
- CBS cbs;
- CBS certificate_types;
- CBS certificate_authorities;
- const uint8_t *data;
-
- n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_CERT_REQ_A,
- SSL3_ST_CR_CERT_REQ_B, -1, ssl->max_cert_list,
- ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- ssl->s3->tmp.cert_req = 0;
-
- if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_DONE) {
- ssl->s3->tmp.reuse_message = 1;
- /* If we get here we don't need the handshake buffer as we won't be doing
- * client auth. */
- ssl3_free_handshake_buffer(ssl);
- return 1;
- }
-
- if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_MESSAGE_TYPE);
- goto err;
- }
-
- CBS_init(&cbs, ssl->init_msg, n);
-
- ca_sk = sk_X509_NAME_new(ca_dn_cmp);
- if (ca_sk == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* get the certificate types */
- if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto err;
- }
-
- if (!CBS_stow(&certificate_types, &ssl->s3->tmp.certificate_types,
- &ssl->s3->tmp.num_certificate_types)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
-
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- CBS supported_signature_algorithms;
- if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
- !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto err;
- }
- }
-
- /* get the CA RDNs */
- if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- while (CBS_len(&certificate_authorities) > 0) {
- CBS distinguished_name;
- if (!CBS_get_u16_length_prefixed(&certificate_authorities,
- &distinguished_name)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG);
- goto err;
- }
-
- data = CBS_data(&distinguished_name);
-
- /* A u16 length cannot overflow a long. */
- xn = d2i_X509_NAME(NULL, &data, (long)CBS_len(&distinguished_name));
- if (xn == NULL) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
- goto err;
- }
-
- if (!CBS_skip(&distinguished_name, data - CBS_data(&distinguished_name))) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (CBS_len(&distinguished_name) != 0) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!sk_X509_NAME_push(ca_sk, xn)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- /* we should setup a certificate to return.... */
- ssl->s3->tmp.cert_req = 1;
- sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
- ssl->s3->tmp.ca_names = ca_sk;
- ca_sk = NULL;
-
- ret = 1;
-
-err:
- sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
- return ret;
-}
-
-int ssl3_get_new_session_ticket(SSL *ssl) {
- int ok, al;
- long n = ssl->method->ssl_get_message(
- ssl, SSL3_ST_CR_SESSION_TICKET_A, SSL3_ST_CR_SESSION_TICKET_B,
- SSL3_MT_NEWSESSION_TICKET, 16384, ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- CBS new_session_ticket, ticket;
- uint32_t ticket_lifetime_hint;
- CBS_init(&new_session_ticket, ssl->init_msg, n);
- if (!CBS_get_u32(&new_session_ticket, &ticket_lifetime_hint) ||
- !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
- CBS_len(&new_session_ticket) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (CBS_len(&ticket) == 0) {
- /* RFC 5077 allows a server to change its mind and send no ticket after
- * negotiating the extension. The value of |tlsext_ticket_expected| is
- * checked in |ssl_update_cache| so is cleared here to avoid an unnecessary
- * update. */
- ssl->tlsext_ticket_expected = 0;
- return 1;
- }
-
- if (ssl->hit) {
- /* The server is sending a new ticket for an existing session. Sessions are
- * immutable once established, so duplicate all but the ticket of the
- * existing session. */
- uint8_t *bytes;
- size_t bytes_len;
- if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &bytes, &bytes_len)) {
- goto err;
- }
- SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len);
- OPENSSL_free(bytes);
- if (new_session == NULL) {
- /* This should never happen. */
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- SSL_SESSION_free(ssl->session);
- ssl->session = new_session;
- }
-
- if (!CBS_stow(&ticket, &ssl->session->tlsext_tick,
- &ssl->session->tlsext_ticklen)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ssl->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
-
- /* Generate a session ID for this session based on the session ticket. We use
- * the session ID mechanism for detecting ticket resumption. This also fits in
- * with assumptions elsewhere in OpenSSL.*/
- if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), ssl->session->session_id,
- &ssl->session->session_id_length, EVP_sha256(), NULL)) {
- goto err;
- }
-
- return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
- return -1;
-}
-
-int ssl3_get_cert_status(SSL *ssl) {
- int ok, al;
- long n;
- CBS certificate_status, ocsp_response;
- uint8_t status_type;
-
- n = ssl->method->ssl_get_message(
- ssl, SSL3_ST_CR_CERT_STATUS_A, SSL3_ST_CR_CERT_STATUS_B,
- -1, 16384, ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
- /* A server may send status_request in ServerHello and then change
- * its mind about sending CertificateStatus. */
- ssl->s3->tmp.reuse_message = 1;
- return 1;
- }
-
- CBS_init(&certificate_status, ssl->init_msg, n);
- if (!CBS_get_u8(&certificate_status, &status_type) ||
- status_type != TLSEXT_STATUSTYPE_ocsp ||
- !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
- CBS_len(&ocsp_response) == 0 ||
- CBS_len(&certificate_status) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (!CBS_stow(&ocsp_response, &ssl->session->ocsp_response,
- &ssl->session->ocsp_response_length)) {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- return -1;
-}
-
-int ssl3_get_server_done(SSL *ssl) {
- int ok;
- long n;
-
- n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_SRVR_DONE_A,
- SSL3_ST_CR_SRVR_DONE_B, SSL3_MT_SERVER_DONE,
- 30, /* should be very small, like 0 :-) */
- ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- if (n > 0) {
- /* should contain no data */
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
- return -1;
- }
-
- return 1;
-}
-
-OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
- SIZE_T_IS_SMALLER_THAN_UNSIGNED);
-
-int ssl3_send_client_key_exchange(SSL *ssl) {
- if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) {
- return ssl_do_write(ssl);
- }
- assert(ssl->state == SSL3_ST_CW_KEY_EXCH_A);
-
- uint8_t *pms = NULL;
- size_t pms_len = 0;
- CBB cbb;
- if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
- goto err;
- }
-
- uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
- uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
- /* If using a PSK key exchange, prepare the pre-shared key. */
- unsigned psk_len = 0;
- uint8_t psk[PSK_MAX_PSK_LEN];
- if (alg_a & SSL_aPSK) {
- if (ssl->psk_client_callback == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
- goto err;
- }
-
- char identity[PSK_MAX_IDENTITY_LEN + 1];
- memset(identity, 0, sizeof(identity));
- psk_len = ssl->psk_client_callback(
- ssl, ssl->s3->tmp.peer_psk_identity_hint, identity, sizeof(identity),
- psk, sizeof(psk));
- if (psk_len == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
- }
- assert(psk_len <= PSK_MAX_PSK_LEN);
-
- OPENSSL_free(ssl->session->psk_identity);
- ssl->session->psk_identity = BUF_strdup(identity);
- if (ssl->session->psk_identity == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Write out psk_identity. */
- CBB child;
- if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, (const uint8_t *)identity,
- OPENSSL_strnlen(identity, sizeof(identity))) ||
- !CBB_flush(&cbb)) {
- goto err;
- }
- }
-
- /* Depending on the key exchange method, compute |pms| and |pms_len|. */
- if (alg_k & SSL_kRSA) {
- pms_len = SSL_MAX_MASTER_KEY_LENGTH;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- EVP_PKEY *pkey = X509_get_pubkey(ssl->session->peer);
- if (pkey == NULL) {
- goto err;
- }
-
- RSA *rsa = EVP_PKEY_get0_RSA(pkey);
- if (rsa == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- EVP_PKEY_free(pkey);
- goto err;
- }
-
- ssl->session->key_exchange_info = EVP_PKEY_bits(pkey);
- EVP_PKEY_free(pkey);
-
- pms[0] = ssl->client_version >> 8;
- pms[1] = ssl->client_version & 0xff;
- if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
- goto err;
- }
-
- CBB child, *enc_pms = &cbb;
- size_t enc_pms_len;
- /* In TLS, there is a length prefix. */
- if (ssl->version > SSL3_VERSION) {
- if (!CBB_add_u16_length_prefixed(&cbb, &child)) {
- goto err;
- }
- enc_pms = &child;
- }
-
- uint8_t *ptr;
- if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) ||
- !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len,
- RSA_PKCS1_PADDING) ||
- /* Log the premaster secret, if logging is enabled. */
- !ssl_log_rsa_client_key_exchange(ssl, ptr, enc_pms_len, pms, pms_len) ||
- !CBB_did_write(enc_pms, enc_pms_len) ||
- !CBB_flush(&cbb)) {
- goto err;
- }
- } else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
- /* Generate a keypair and serialize the public half. ECDHE uses a u8 length
- * prefix while DHE uses u16. */
- CBB child;
- int child_ok;
- if (alg_k & SSL_kECDHE) {
- child_ok = CBB_add_u8_length_prefixed(&cbb, &child);
- } else {
- child_ok = CBB_add_u16_length_prefixed(&cbb, &child);
- }
-
- if (!child_ok ||
- !SSL_ECDH_CTX_generate_keypair(&ssl->s3->tmp.ecdh_ctx, &child) ||
- !CBB_flush(&cbb)) {
- goto err;
- }
-
- /* Compute the premaster. */
- uint8_t alert;
- if (!SSL_ECDH_CTX_compute_secret(&ssl->s3->tmp.ecdh_ctx, &pms, &pms_len,
- &alert, ssl->s3->tmp.peer_key,
- ssl->s3->tmp.peer_key_len)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- goto err;
- }
-
- /* The key exchange state may now be discarded. */
- SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
- OPENSSL_free(ssl->s3->tmp.peer_key);
- ssl->s3->tmp.peer_key = NULL;
- } else if (alg_k & SSL_kPSK) {
- /* For plain PSK, other_secret is a block of 0s with the same length as
- * the pre-shared key. */
- pms_len = psk_len;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memset(pms, 0, pms_len);
- } else {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* For a PSK cipher suite, other_secret is combined with the pre-shared
- * key. */
- if (alg_a & SSL_aPSK) {
- CBB pms_cbb, child;
- uint8_t *new_pms;
- size_t new_pms_len;
-
- CBB_zero(&pms_cbb);
- if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) ||
- !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
- !CBB_add_bytes(&child, pms, pms_len) ||
- !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
- !CBB_add_bytes(&child, psk, psk_len) ||
- !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) {
- CBB_cleanup(&pms_cbb);
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
- pms = new_pms;
- pms_len = new_pms_len;
- }
-
- /* The message must be added to the finished hash before calculating the
- * master secret. */
- size_t length;
- if (!CBB_finish(&cbb, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE, length)) {
- goto err;
- }
- ssl->state = SSL3_ST_CW_KEY_EXCH_B;
-
- ssl->session->master_key_length =
- tls1_generate_master_secret(ssl, ssl->session->master_key, pms, pms_len);
- if (ssl->session->master_key_length == 0) {
- goto err;
- }
- ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
-
- /* SSL3_ST_CW_KEY_EXCH_B */
- return ssl_do_write(ssl);
-
-err:
- if (pms != NULL) {
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
- }
- return -1;
-}
-
-int ssl3_send_cert_verify(SSL *ssl) {
- if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) {
- return ssl_do_write(ssl);
- }
-
- CBB cbb, child;
- if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
- goto err;
- }
-
- assert(ssl_has_private_key(ssl));
-
- const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
- size_t sig_len;
- enum ssl_private_key_result_t sign_result;
- if (ssl->state == SSL3_ST_CW_CERT_VRFY_A) {
- /* Select and write out the digest type in TLS 1.2. */
- const EVP_MD *md = NULL;
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- md = tls1_choose_signing_digest(ssl);
- if (!tls12_add_sigandhash(ssl, &cbb, md)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
- /* Compute the digest. In TLS 1.1 and below, the digest type is also
- * selected here. */
- uint8_t digest[EVP_MAX_MD_SIZE];
- size_t digest_len;
- if (!ssl3_cert_verify_hash(ssl, digest, &digest_len, &md,
- ssl_private_key_type(ssl))) {
- goto err;
- }
-
- /* The handshake buffer is no longer necessary. */
- ssl3_free_handshake_buffer(ssl);
-
- /* Sign the digest. */
- uint8_t *ptr;
- if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_reserve(&child, &ptr, max_sig_len)) {
- goto err;
- }
- sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md,
- digest, digest_len);
- } else {
- assert(ssl->state == SSL3_ST_CW_CERT_VRFY_B);
-
- /* Skip over the already written signature algorithm and retry the
- * signature. */
- uint8_t *ptr;
- if ((ssl3_protocol_version(ssl) >= TLS1_2_VERSION &&
- !CBB_did_write(&cbb, 2)) ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_reserve(&child, &ptr, max_sig_len)) {
- goto err;
- }
- sign_result =
- ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len);
- }
-
- switch (sign_result) {
- case ssl_private_key_success:
- ssl->rwstate = SSL_NOTHING;
- break;
- case ssl_private_key_failure:
- ssl->rwstate = SSL_NOTHING;
- goto err;
- case ssl_private_key_retry:
- ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
- ssl->state = SSL3_ST_CW_CERT_VRFY_B;
- goto err;
- }
-
- size_t length;
- if (!CBB_did_write(&child, sig_len) ||
- !CBB_finish(&cbb, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_VERIFY, length)) {
- goto err;
- }
-
- ssl->state = SSL3_ST_CW_CERT_VRFY_C;
- return ssl_do_write(ssl);
-
-err:
- CBB_cleanup(&cbb);
- return -1;
-}
-
-/* ssl3_has_client_certificate returns true if a client certificate is
- * configured. */
-static int ssl3_has_client_certificate(SSL *ssl) {
- return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl);
-}
-
-int ssl3_send_client_certificate(SSL *ssl) {
- X509 *x509 = NULL;
- EVP_PKEY *pkey = NULL;
- int i;
-
- if (ssl->state == SSL3_ST_CW_CERT_A) {
- /* Let cert callback update client certificates if required */
- if (ssl->cert->cert_cb) {
- i = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
- if (i < 0) {
- ssl->rwstate = SSL_X509_LOOKUP;
- return -1;
- }
- if (i == 0) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- return 0;
- }
- ssl->rwstate = SSL_NOTHING;
- }
-
- if (ssl3_has_client_certificate(ssl)) {
- ssl->state = SSL3_ST_CW_CERT_C;
- } else {
- ssl->state = SSL3_ST_CW_CERT_B;
- }
- }
-
- /* We need to get a client cert */
- if (ssl->state == SSL3_ST_CW_CERT_B) {
- /* If we get an error, we need to:
- * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
- * We then get retried later */
- i = ssl_do_client_cert_cb(ssl, &x509, &pkey);
- if (i < 0) {
- ssl->rwstate = SSL_X509_LOOKUP;
- return -1;
- }
- ssl->rwstate = SSL_NOTHING;
- if (i == 1 && pkey != NULL && x509 != NULL) {
- ssl->state = SSL3_ST_CW_CERT_B;
- if (!SSL_use_certificate(ssl, x509) || !SSL_use_PrivateKey(ssl, pkey)) {
- i = 0;
- }
- } else if (i == 1) {
- i = 0;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
- }
-
- X509_free(x509);
- EVP_PKEY_free(pkey);
- if (i && !ssl3_has_client_certificate(ssl)) {
- i = 0;
- }
- if (i == 0) {
- if (ssl->version == SSL3_VERSION) {
- ssl->s3->tmp.cert_req = 0;
- ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
- return 1;
- } else {
- ssl->s3->tmp.cert_req = 2;
- /* There is no client certificate, so the handshake buffer may be
- * released. */
- ssl3_free_handshake_buffer(ssl);
- }
- }
-
- /* Ok, we have a cert */
- ssl->state = SSL3_ST_CW_CERT_C;
- }
-
- if (ssl->state == SSL3_ST_CW_CERT_C) {
- if (ssl->s3->tmp.cert_req == 2) {
- /* Send an empty Certificate message. */
- uint8_t *p = ssl_handshake_start(ssl);
- l2n3(0, p);
- if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, 3)) {
- return -1;
- }
- } else if (!ssl3_output_cert_chain(ssl)) {
- return -1;
- }
- ssl->state = SSL3_ST_CW_CERT_D;
- }
-
- /* SSL3_ST_CW_CERT_D */
- return ssl_do_write(ssl);
-}
-
-int ssl3_send_next_proto(SSL *ssl) {
- if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) {
- return ssl_do_write(ssl);
- }
-
- assert(ssl->state == SSL3_ST_CW_NEXT_PROTO_A);
-
- static const uint8_t kZero[32] = {0};
- size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32);
-
- CBB cbb, child;
- size_t length;
- CBB_zero(&cbb);
- if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, ssl->s3->next_proto_negotiated,
- ssl->s3->next_proto_negotiated_len) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, kZero, padding_len) ||
- !CBB_finish(&cbb, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_NEXT_PROTO, length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
- return -1;
- }
-
- ssl->state = SSL3_ST_CW_NEXT_PROTO_B;
- return ssl_do_write(ssl);
-}
-
-int ssl3_send_channel_id(SSL *ssl) {
- if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) {
- return ssl_do_write(ssl);
- }
-
- assert(ssl->state == SSL3_ST_CW_CHANNEL_ID_A);
-
- if (ssl->tlsext_channel_id_private == NULL &&
- ssl->ctx->channel_id_cb != NULL) {
- EVP_PKEY *key = NULL;
- ssl->ctx->channel_id_cb(ssl, &key);
- if (key != NULL &&
- !SSL_set1_tls_channel_id(ssl, key)) {
- EVP_PKEY_free(key);
- return -1;
- }
- EVP_PKEY_free(key);
- }
-
- if (ssl->tlsext_channel_id_private == NULL) {
- ssl->rwstate = SSL_CHANNEL_ID_LOOKUP;
- return -1;
- }
- ssl->rwstate = SSL_NOTHING;
-
- EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->tlsext_channel_id_private);
- if (ec_key == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
- int ret = -1;
- BIGNUM *x = BN_new();
- BIGNUM *y = BN_new();
- ECDSA_SIG *sig = NULL;
- if (x == NULL || y == NULL ||
- !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
- EC_KEY_get0_public_key(ec_key),
- x, y, NULL)) {
- goto err;
- }
-
- uint8_t digest[EVP_MAX_MD_SIZE];
- size_t digest_len;
- if (!tls1_channel_id_hash(ssl, digest, &digest_len)) {
- goto err;
- }
-
- sig = ECDSA_do_sign(digest, digest_len, ec_key);
- if (sig == NULL) {
- goto err;
- }
-
- CBB cbb, child;
- size_t length;
- CBB_zero(&cbb);
- if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
- !CBB_add_u16(&cbb, TLSEXT_TYPE_channel_id) ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !BN_bn2cbb_padded(&child, 32, x) ||
- !BN_bn2cbb_padded(&child, 32, y) ||
- !BN_bn2cbb_padded(&child, 32, sig->r) ||
- !BN_bn2cbb_padded(&child, 32, sig->s) ||
- !CBB_finish(&cbb, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS, length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
- goto err;
- }
-
- ssl->state = SSL3_ST_CW_CHANNEL_ID_B;
- ret = ssl_do_write(ssl);
-
-err:
- BN_free(x);
- BN_free(y);
- ECDSA_SIG_free(sig);
- return ret;
-}
-
-int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey) {
- if (ssl->ctx->client_cert_cb == NULL) {
- return 0;
- }
- return ssl->ctx->client_cert_cb(ssl, out_x509, out_pkey);
-}
-
-int ssl3_verify_server_cert(SSL *ssl) {
- int ret = ssl_verify_cert_chain(ssl, ssl->session->cert_chain);
- if (ssl->verify_mode != SSL_VERIFY_NONE && ret <= 0) {
- int al = ssl_verify_alarm_type(ssl->verify_result);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
- } else {
- ret = 1;
- ERR_clear_error(); /* but we keep ssl->verify_result */
- }
-
- return ret;
-}
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index a25877ca..04aa08c9 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -136,14 +136,13 @@
#include <openssl/ssl.h>
#include <assert.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/md5.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index b036b641..43dcb020 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -149,7 +149,6 @@
#include <openssl/ssl.h>
#include <assert.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
@@ -158,7 +157,7 @@
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include "internal.h"
@@ -172,7 +171,6 @@ int ssl3_set_handshake_header(SSL *ssl, int htype, unsigned long len) {
*(p++) = htype;
l2n3(len, p);
ssl->init_num = (int)len + SSL3_HM_HEADER_LENGTH;
- ssl->init_off = 0;
/* Add the message to the handshake hash. */
return ssl3_update_handshake_hash(ssl, (uint8_t *)ssl->init_buf->data,
@@ -183,6 +181,10 @@ int ssl3_handshake_write(SSL *ssl) {
return ssl3_do_write(ssl, SSL3_RT_HANDSHAKE);
}
+void ssl3_expect_flight(SSL *ssl) {}
+
+void ssl3_received_flight(SSL *ssl) {}
+
int ssl3_new(SSL *ssl) {
SSL3_STATE *s3;
@@ -221,7 +223,7 @@ void ssl3_free(SSL *ssl) {
sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
OPENSSL_free(ssl->s3->tmp.certificate_types);
- OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
+ OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint);
ssl3_free_handshake_buffer(ssl);
ssl3_free_handshake_hash(ssl);
@@ -235,228 +237,20 @@ void ssl3_free(SSL *ssl) {
ssl->s3 = NULL;
}
-int SSL_session_reused(const SSL *ssl) {
- return ssl->hit;
-}
-
-int SSL_total_renegotiations(const SSL *ssl) {
- return ssl->s3->total_renegotiations;
-}
-
-int SSL_num_renegotiations(const SSL *ssl) {
- return SSL_total_renegotiations(ssl);
-}
-
-int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx) {
- return 0;
-}
-
-int SSL_need_rsa(const SSL *ssl) {
- return 0;
-}
-
-int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa) {
- return 1;
-}
-
-int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa) {
- return 1;
-}
-
-int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) {
- DH_free(ctx->cert->dh_tmp);
- ctx->cert->dh_tmp = DHparams_dup(dh);
- if (ctx->cert->dh_tmp == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
- return 0;
- }
- return 1;
-}
-
-int SSL_set_tmp_dh(SSL *ssl, const DH *dh) {
- DH_free(ssl->cert->dh_tmp);
- ssl->cert->dh_tmp = DHparams_dup(dh);
- if (ssl->cert->dh_tmp == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
- return 0;
- }
- return 1;
-}
-
-int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key) {
- if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
- int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
- return SSL_CTX_set1_curves(ctx, &nid, 1);
-}
-
-int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key) {
- if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
- int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
- return SSL_set1_curves(ssl, &nid, 1);
-}
-
-int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx) {
- ctx->tlsext_channel_id_enabled = 1;
- return 1;
-}
-
-int SSL_enable_tls_channel_id(SSL *ssl) {
- ssl->tlsext_channel_id_enabled = 1;
- return 1;
-}
-
-static int is_p256_key(EVP_PKEY *private_key) {
- const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(private_key);
- return ec_key != NULL &&
- EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) ==
- NID_X9_62_prime256v1;
-}
-
-int SSL_CTX_set1_tls_channel_id(SSL_CTX *ctx, EVP_PKEY *private_key) {
- if (!is_p256_key(private_key)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
- return 0;
- }
-
- EVP_PKEY_free(ctx->tlsext_channel_id_private);
- ctx->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key);
- ctx->tlsext_channel_id_enabled = 1;
-
- return 1;
-}
-
-int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key) {
- if (!is_p256_key(private_key)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
- return 0;
- }
-
- EVP_PKEY_free(ssl->tlsext_channel_id_private);
- ssl->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key);
- ssl->tlsext_channel_id_enabled = 1;
-
- return 1;
-}
-
-size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) {
- if (!ssl->s3->tlsext_channel_id_valid) {
- return 0;
- }
- memcpy(out, ssl->s3->tlsext_channel_id, (max_out < 64) ? max_out : 64);
- return 64;
-}
-
-int SSL_set_tlsext_host_name(SSL *ssl, const char *name) {
- OPENSSL_free(ssl->tlsext_hostname);
- ssl->tlsext_hostname = NULL;
-
- if (name == NULL) {
- return 1;
- }
- if (strlen(name) > TLSEXT_MAXLEN_host_name) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
- return 0;
- }
- ssl->tlsext_hostname = BUF_strdup(name);
- if (ssl->tlsext_hostname == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
-}
-
-size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
- if (ssl->server || !ssl->s3->tmp.cert_req) {
- *out_types = NULL;
- return 0;
- }
- *out_types = ssl->s3->tmp.certificate_types;
- return ssl->s3->tmp.num_certificate_types;
-}
-
-int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, size_t curves_len) {
- return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
- &ctx->tlsext_ellipticcurvelist_length, curves,
- curves_len);
-}
-
-int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) {
- return tls1_set_curves(&ssl->tlsext_ellipticcurvelist,
- &ssl->tlsext_ellipticcurvelist_length, curves,
- curves_len);
-}
-
-int SSL_CTX_set_tlsext_servername_callback(
- SSL_CTX *ctx, int (*callback)(SSL *ssl, int *out_alert, void *arg)) {
- ctx->tlsext_servername_callback = callback;
- return 1;
-}
-
-int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) {
- ctx->tlsext_servername_arg = arg;
- return 1;
-}
-
-int SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, void *out, size_t len) {
- if (out == NULL) {
- return 48;
- }
- if (len != 48) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
- return 0;
- }
- uint8_t *out_bytes = out;
- memcpy(out_bytes, ctx->tlsext_tick_key_name, 16);
- memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16);
- memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16);
- return 1;
-}
-
-int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, size_t len) {
- if (in == NULL) {
- return 48;
- }
- if (len != 48) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
- return 0;
- }
- const uint8_t *in_bytes = in;
- memcpy(ctx->tlsext_tick_key_name, in_bytes, 16);
- memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16);
- memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16);
- return 1;
-}
-
-int SSL_CTX_set_tlsext_ticket_key_cb(
- SSL_CTX *ctx, int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv,
- EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
- int encrypt)) {
- ctx->tlsext_ticket_key_cb = callback;
- return 1;
-}
-
struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *ssl) {
if (ssl->cipher_list != NULL) {
return ssl->cipher_list;
}
- if (ssl->version >= TLS1_1_VERSION && ssl->ctx != NULL &&
- ssl->ctx->cipher_list_tls11 != NULL) {
+ if (ssl->version >= TLS1_1_VERSION && ssl->ctx->cipher_list_tls11 != NULL) {
return ssl->ctx->cipher_list_tls11;
}
- if (ssl->version >= TLS1_VERSION && ssl->ctx != NULL &&
- ssl->ctx->cipher_list_tls10 != NULL) {
+ if (ssl->version >= TLS1_VERSION && ssl->ctx->cipher_list_tls10 != NULL) {
return ssl->ctx->cipher_list_tls10;
}
- if (ssl->ctx != NULL && ssl->ctx->cipher_list != NULL) {
+ if (ssl->ctx->cipher_list != NULL) {
return ssl->ctx->cipher_list;
}
diff --git a/ssl/s3_meth.c b/ssl/s3_meth.c
index b60b5f2c..8370f23f 100644
--- a/ssl/s3_meth.c
+++ b/ssl/s3_meth.c
@@ -63,8 +63,6 @@ static const SSL_PROTOCOL_METHOD TLS_protocol_method = {
0 /* is_dtls */,
ssl3_new,
ssl3_free,
- ssl3_accept,
- ssl3_connect,
ssl3_get_message,
ssl3_read_app_data,
ssl3_read_change_cipher_spec,
@@ -75,6 +73,9 @@ static const SSL_PROTOCOL_METHOD TLS_protocol_method = {
SSL3_HM_HEADER_LENGTH,
ssl3_set_handshake_header,
ssl3_handshake_write,
+ ssl3_send_change_cipher_spec,
+ ssl3_expect_flight,
+ ssl3_received_flight,
};
const SSL_METHOD *TLS_method(void) {
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 81d163e8..2396a7fd 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -110,7 +110,6 @@
#include <assert.h>
#include <limits.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
@@ -124,54 +123,60 @@
static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len);
-/* kMaxWarningAlerts is the number of consecutive warning alerts that will be
- * processed. */
-static const uint8_t kMaxWarningAlerts = 4;
-
/* ssl3_get_record reads a new input record. On success, it places it in
* |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
* more data is needed. */
static int ssl3_get_record(SSL *ssl) {
- int ret;
again:
- /* Ensure the buffer is large enough to decrypt in-place. */
- ret = ssl_read_buffer_extend_to(ssl, ssl_record_prefix_len(ssl));
- if (ret <= 0) {
- return ret;
+ switch (ssl->s3->recv_shutdown) {
+ case ssl_shutdown_none:
+ break;
+ case ssl_shutdown_fatal_alert:
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ return -1;
+ case ssl_shutdown_close_notify:
+ return 0;
}
- assert(ssl_read_buffer_len(ssl) >= ssl_record_prefix_len(ssl));
- uint8_t *out = ssl_read_buffer(ssl) + ssl_record_prefix_len(ssl);
- size_t max_out = ssl_read_buffer_len(ssl) - ssl_record_prefix_len(ssl);
+ CBS body;
uint8_t type, alert;
- size_t len, consumed;
- switch (tls_open_record(ssl, &type, out, &len, &consumed, &alert, max_out,
- ssl_read_buffer(ssl), ssl_read_buffer_len(ssl))) {
- case ssl_open_record_success:
- ssl_read_buffer_consume(ssl, consumed);
+ size_t consumed;
+ enum ssl_open_record_t open_ret =
+ tls_open_record(ssl, &type, &body, &consumed, &alert,
+ ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
+ if (open_ret != ssl_open_record_partial) {
+ ssl_read_buffer_consume(ssl, consumed);
+ }
+ switch (open_ret) {
+ case ssl_open_record_partial: {
+ int read_ret = ssl_read_buffer_extend_to(ssl, consumed);
+ if (read_ret <= 0) {
+ return read_ret;
+ }
+ goto again;
+ }
- if (len > 0xffff) {
+ case ssl_open_record_success:
+ if (CBS_len(&body) > 0xffff) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return -1;
}
SSL3_RECORD *rr = &ssl->s3->rrec;
rr->type = type;
- rr->length = (uint16_t)len;
- rr->data = out;
+ rr->length = (uint16_t)CBS_len(&body);
+ rr->data = (uint8_t *)CBS_data(&body);
return 1;
- case ssl_open_record_partial:
- ret = ssl_read_buffer_extend_to(ssl, consumed);
- if (ret <= 0) {
- return ret;
- }
- goto again;
-
case ssl_open_record_discard:
- ssl_read_buffer_consume(ssl, consumed);
goto again;
+ case ssl_open_record_close_notify:
+ return 0;
+
+ case ssl_open_record_fatal_alert:
+ return -1;
+
case ssl_open_record_error:
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
@@ -183,6 +188,8 @@ again:
}
int ssl3_write_app_data(SSL *ssl, const void *buf, int len) {
+ assert(!SSL_in_init(ssl) || SSL_in_false_start(ssl));
+
return ssl3_write_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len);
}
@@ -190,25 +197,12 @@ int ssl3_write_app_data(SSL *ssl, const void *buf, int len) {
* not all data has been sent or non-blocking IO. */
int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, int len) {
const uint8_t *buf = buf_;
- unsigned int tot, n, nw;
- int i;
+ unsigned tot, n, nw;
- ssl->rwstate = SSL_NOTHING;
assert(ssl->s3->wnum <= INT_MAX);
tot = ssl->s3->wnum;
ssl->s3->wnum = 0;
- if (!ssl->in_handshake && SSL_in_init(ssl) && !SSL_in_false_start(ssl)) {
- i = ssl->handshake_func(ssl);
- if (i < 0) {
- return i;
- }
- if (i == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
- return -1;
- }
- }
-
/* Ensure that if we end up with a smaller value of data to write out than
* the the original len from a write which didn't complete for non-blocking
* I/O and also somehow ended up avoiding the check for this in
@@ -232,19 +226,19 @@ int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, int len) {
nw = n;
}
- i = do_ssl3_write(ssl, type, &buf[tot], nw);
- if (i <= 0) {
+ int ret = do_ssl3_write(ssl, type, &buf[tot], nw);
+ if (ret <= 0) {
ssl->s3->wnum = tot;
- return i;
+ return ret;
}
- if (i == (int)n || (type == SSL3_RT_APPLICATION_DATA &&
- (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) {
- return tot + i;
+ if (ret == (int)n || (type == SSL3_RT_APPLICATION_DATA &&
+ (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) {
+ return tot + ret;
}
- n -= i;
- tot += i;
+ n -= ret;
+ tot += ret;
}
}
@@ -315,34 +309,47 @@ static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) {
}
int ssl3_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek) {
+ assert(!SSL_in_init(ssl));
+ assert(ssl->s3->initial_handshake_complete);
+
return ssl3_read_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len, peek);
}
int ssl3_read_change_cipher_spec(SSL *ssl) {
- uint8_t byte;
- int ret = ssl3_read_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1 /* len */,
- 0 /* no peek */);
- if (ret <= 0) {
- return ret;
+ SSL3_RECORD *rr = &ssl->s3->rrec;
+
+ if (rr->length == 0) {
+ int ret = ssl3_get_record(ssl);
+ if (ret <= 0) {
+ return ret;
+ }
}
- assert(ret == 1);
- if (ssl->s3->rrec.length != 0 || byte != SSL3_MT_CCS) {
+ if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+ return -1;
+ }
+
+ if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return -1;
}
- if (ssl->msg_callback != NULL) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1,
- ssl, ssl->msg_callback_arg);
- }
+ ssl_do_msg_callback(ssl, 0 /* read */, ssl->version,
+ SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, rr->length);
+ rr->length = 0;
+ ssl_read_buffer_discard(ssl);
return 1;
}
void ssl3_read_close_notify(SSL *ssl) {
- ssl3_read_bytes(ssl, 0, NULL, 0, 0);
+ /* Read records until an error or close_notify. */
+ while (ssl3_get_record(ssl) > 0) {
+ ;
+ }
}
static int ssl3_can_renegotiate(SSL *ssl) {
@@ -365,9 +372,7 @@ static int ssl3_can_renegotiate(SSL *ssl) {
* 'type' is one of the following:
*
* - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
- * - SSL3_RT_CHANGE_CIPHER_SPEC (when ssl3_read_change_cipher_spec calls us)
* - SSL3_RT_APPLICATION_DATA (when ssl3_read_app_data calls us)
- * - 0 (during a shutdown, no data has to be returned)
*
* If we don't have stored data to work from, read a SSL/TLS record first
* (possibly multiple records if we still don't have anything to return).
@@ -378,35 +383,14 @@ int ssl3_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek) {
int al, i, ret;
unsigned int n;
SSL3_RECORD *rr;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
- if ((type && type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE &&
- type != SSL3_RT_CHANGE_CIPHER_SPEC) ||
+ if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) ||
(peek && type != SSL3_RT_APPLICATION_DATA)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
- /* This may require multiple iterations. False Start will cause
- * |ssl->handshake_func| to signal success one step early, but the handshake
- * must be completely finished before other modes are accepted.
- *
- * TODO(davidben): Move this check up to a higher level. */
- while (!ssl->in_handshake && SSL_in_init(ssl)) {
- assert(type == SSL3_RT_APPLICATION_DATA);
- i = ssl->handshake_func(ssl);
- if (i < 0) {
- return i;
- }
- if (i == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
- return -1;
- }
- }
-
start:
- ssl->rwstate = SSL_NOTHING;
-
/* ssl->s3->rrec.type - is the type of record
* ssl->s3->rrec.data - data
* ssl->s3->rrec.off - offset into 'data' for next read
@@ -423,28 +407,7 @@ start:
/* we now have a packet which can be read and processed */
- /* If the other end has shut down, throw anything we read away (even in
- * 'peek' mode) */
- if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
- rr->length = 0;
- ssl->rwstate = SSL_NOTHING;
- return 0;
- }
-
- if (type != 0 && type == rr->type) {
- ssl->s3->warning_alert_count = 0;
-
- /* Make sure that we are not getting application data when we are doing a
- * handshake for the first time. */
- if (SSL_in_init(ssl) && type == SSL3_RT_APPLICATION_DATA &&
- ssl->s3->aead_read_ctx == NULL) {
- /* TODO(davidben): Is this check redundant with the handshake_func
- * check? */
- al = SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_APP_DATA_IN_HANDSHAKE);
- goto f_err;
- }
-
+ if (type == rr->type) {
/* Discard empty records. */
if (rr->length == 0) {
goto start;
@@ -503,18 +466,8 @@ start:
}
ssl->s3->hello_request_len = 0;
- if (ssl->msg_callback) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, kHelloRequest,
- sizeof(kHelloRequest), ssl, ssl->msg_callback_arg);
- }
-
- if (!SSL_is_init_finished(ssl) || !ssl->s3->initial_handshake_complete) {
- /* This cannot happen. If a handshake is in progress, |type| must be
- * |SSL3_RT_HANDSHAKE|. */
- assert(0);
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
+ ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
+ kHelloRequest, sizeof(kHelloRequest));
if (ssl->renegotiate_mode == ssl_renegotiate_ignore) {
goto start;
@@ -546,101 +499,28 @@ start:
goto start;
}
- /* If an alert record, process one alert out of the record. Note that we allow
- * a single record to contain multiple alerts. */
- if (rr->type == SSL3_RT_ALERT) {
- /* Alerts may not be fragmented. */
- if (rr->length < 2) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
- goto f_err;
- }
-
- if (ssl->msg_callback) {
- ssl->msg_callback(0, ssl->version, SSL3_RT_ALERT, rr->data, 2, ssl,
- ssl->msg_callback_arg);
- }
- const uint8_t alert_level = rr->data[0];
- const uint8_t alert_descr = rr->data[1];
- rr->length -= 2;
- rr->data += 2;
-
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
-
- if (cb != NULL) {
- uint16_t alert = (alert_level << 8) | alert_descr;
- cb(ssl, SSL_CB_READ_ALERT, alert);
- }
-
- if (alert_level == SSL3_AL_WARNING) {
- ssl->s3->warn_alert = alert_descr;
- if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
- ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
- return 0;
- }
-
- /* This is a warning but we receive it if we requested renegotiation and
- * the peer denied it. Terminate with a fatal alert because if
- * application tried to renegotiatie it presumably had a good reason and
- * expects it to succeed.
- *
- * In future we might have a renegotiation where we don't care if the
- * peer refused it where we carry on. */
- else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
- goto f_err;
- }
-
- ssl->s3->warning_alert_count++;
- if (ssl->s3->warning_alert_count > kMaxWarningAlerts) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS);
- goto f_err;
- }
- } else if (alert_level == SSL3_AL_FATAL) {
- char tmp[16];
-
- ssl->rwstate = SSL_NOTHING;
- ssl->s3->fatal_alert = alert_descr;
- OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
- BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
- ERR_add_error_data(2, "SSL alert number ", tmp);
- ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
- SSL_CTX_remove_session(ssl->ctx, ssl->session);
- return 0;
- } else {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
- goto f_err;
- }
-
- goto start;
- }
-
- if (ssl->shutdown & SSL_SENT_SHUTDOWN) {
- /* close_notify has been sent, so discard all records other than alerts. */
- rr->length = 0;
- goto start;
- }
-
al = SSL_AD_UNEXPECTED_MESSAGE;
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
f_err:
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
return -1;
}
int ssl3_send_alert(SSL *ssl, int level, int desc) {
- /* If a fatal one, remove from cache */
- if (level == 2 && ssl->session != NULL) {
- SSL_CTX_remove_session(ssl->ctx, ssl->session);
+ /* It is illegal to send an alert when we've already sent a closing one. */
+ if (ssl->s3->send_shutdown != ssl_shutdown_none) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ return -1;
+ }
+
+ if (level == SSL3_AL_FATAL) {
+ if (ssl->session != NULL) {
+ SSL_CTX_remove_session(ssl->ctx, ssl->session);
+ }
+ ssl->s3->send_shutdown = ssl_shutdown_fatal_alert;
+ } else if (level == SSL3_AL_WARNING && desc == SSL_AD_CLOSE_NOTIFY) {
+ ssl->s3->send_shutdown = ssl_shutdown_close_notify;
}
ssl->s3->alert_dispatch = 1;
@@ -652,42 +532,28 @@ int ssl3_send_alert(SSL *ssl, int level, int desc) {
return ssl->method->ssl_dispatch_alert(ssl);
}
- /* else data is still being written out, we will get written some time in the
- * future */
+ /* The alert will be dispatched later. */
return -1;
}
int ssl3_dispatch_alert(SSL *ssl) {
- int i, j;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
-
ssl->s3->alert_dispatch = 0;
- i = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
- if (i <= 0) {
+ int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
+ if (ret <= 0) {
ssl->s3->alert_dispatch = 1;
- } else {
- /* Alert sent to BIO. If it is important, flush it now. If the message
- * does not get sent due to non-blocking IO, we will not worry too much. */
- if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
- BIO_flush(ssl->wbio);
- }
+ return ret;
+ }
- if (ssl->msg_callback) {
- ssl->msg_callback(1, ssl->version, SSL3_RT_ALERT, ssl->s3->send_alert, 2,
- ssl, ssl->msg_callback_arg);
- }
+ /* If the alert is fatal, flush the BIO now. */
+ if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
+ BIO_flush(ssl->wbio);
+ }
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
+ ssl_do_msg_callback(ssl, 1 /* write */, ssl->version, SSL3_RT_ALERT,
+ ssl->s3->send_alert, 2);
- if (cb != NULL) {
- j = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
- cb(ssl, SSL_CB_WRITE_ALERT, j);
- }
- }
+ int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
+ ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
- return i;
+ return 1;
}
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
deleted file mode 100644
index ae709dc3..00000000
--- a/ssl/s3_srvr.c
+++ /dev/null
@@ -1,2272 +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.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2007 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
- * openssl-core@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).
- *
- */
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * ECC cipher suite support in OpenSSL originally written by
- * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
- *
- */
-/* ====================================================================
- * Copyright 2005 Nokia. All rights reserved.
- *
- * The portions of the attached software ("Contribution") is developed by
- * Nokia Corporation and is licensed pursuant to the OpenSSL open source
- * license.
- *
- * The Contribution, originally written by Mika Kousa and Pasi Eronen of
- * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
- * support (see RFC 4279) to OpenSSL.
- *
- * No patent licenses or other rights except those expressly stated in
- * the OpenSSL open source license shall be deemed granted or received
- * expressly, by implication, estoppel, or otherwise.
- *
- * No assurances are provided by Nokia that the Contribution does not
- * infringe the patent or other intellectual property rights of any third
- * party or that the license provides you with all the necessary rights
- * to make use of the Contribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
- * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
- * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
- * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
- * OTHERWISE. */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/bytestring.h>
-#include <openssl/cipher.h>
-#include <openssl/dh.h>
-#include <openssl/ec.h>
-#include <openssl/ecdsa.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/md5.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-#include <openssl/sha.h>
-#include <openssl/x509.h>
-
-#include "internal.h"
-#include "../crypto/internal.h"
-#include "../crypto/dh/internal.h"
-
-
-int ssl3_accept(SSL *ssl) {
- BUF_MEM *buf = NULL;
- uint32_t alg_a;
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
- int ret = -1;
- int new_state, state, skip = 0;
-
- assert(ssl->handshake_func == ssl3_accept);
- assert(ssl->server);
- assert(!SSL_IS_DTLS(ssl));
-
- ERR_clear_error();
- ERR_clear_system_error();
-
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
-
- ssl->in_handshake++;
-
- if (ssl->cert == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
- return -1;
- }
-
- for (;;) {
- state = ssl->state;
-
- switch (ssl->state) {
- case SSL_ST_ACCEPT:
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_START, 1);
- }
-
- if (ssl->init_buf == NULL) {
- buf = BUF_MEM_new();
- if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
- ret = -1;
- goto end;
- }
- ssl->init_buf = buf;
- buf = NULL;
- }
- ssl->init_num = 0;
-
- /* Enable a write buffer. This groups handshake messages within a flight
- * into a single write. */
- if (!ssl_init_wbio_buffer(ssl, 1)) {
- ret = -1;
- goto end;
- }
-
- if (!ssl3_init_handshake_buffer(ssl)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- ret = -1;
- goto end;
- }
-
- if (!ssl->s3->have_version) {
- ssl->state = SSL3_ST_SR_INITIAL_BYTES;
- } else {
- ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
- }
- break;
-
- case SSL3_ST_SR_INITIAL_BYTES:
- ret = ssl3_get_initial_bytes(ssl);
- if (ret <= 0) {
- goto end;
- }
- /* ssl3_get_initial_bytes sets ssl->state to one of
- * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A on success. */
- break;
-
- case SSL3_ST_SR_V2_CLIENT_HELLO:
- ret = ssl3_get_v2_client_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
- break;
-
- case SSL3_ST_SR_CLNT_HELLO_A:
- case SSL3_ST_SR_CLNT_HELLO_B:
- case SSL3_ST_SR_CLNT_HELLO_C:
- case SSL3_ST_SR_CLNT_HELLO_D:
- ssl->shutdown = 0;
- ret = ssl3_get_client_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_SRVR_HELLO_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_SRVR_HELLO_A:
- case SSL3_ST_SW_SRVR_HELLO_B:
- ret = ssl3_send_server_hello(ssl);
- if (ret <= 0) {
- goto end;
- }
- if (ssl->hit) {
- if (ssl->tlsext_ticket_expected) {
- ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
- } else {
- ssl->state = SSL3_ST_SW_CHANGE_A;
- }
- } else {
- ssl->state = SSL3_ST_SW_CERT_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CERT_A:
- case SSL3_ST_SW_CERT_B:
- if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
- ret = ssl3_send_server_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- if (ssl->s3->tmp.certificate_status_expected) {
- ssl->state = SSL3_ST_SW_CERT_STATUS_A;
- } else {
- ssl->state = SSL3_ST_SW_KEY_EXCH_A;
- }
- } else {
- skip = 1;
- ssl->state = SSL3_ST_SW_KEY_EXCH_A;
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CERT_STATUS_A:
- case SSL3_ST_SW_CERT_STATUS_B:
- ret = ssl3_send_certificate_status(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_KEY_EXCH_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_KEY_EXCH_A:
- case SSL3_ST_SW_KEY_EXCH_B:
- case SSL3_ST_SW_KEY_EXCH_C:
- alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
- /* Send a ServerKeyExchange message if:
- * - The key exchange is ephemeral or anonymous
- * Diffie-Hellman.
- * - There is a PSK identity hint.
- *
- * TODO(davidben): This logic is currently duplicated in d1_srvr.c. Fix
- * this. In the meantime, keep them in sync. */
- if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
- ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
- ret = ssl3_send_server_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- } else {
- skip = 1;
- }
-
- ssl->state = SSL3_ST_SW_CERT_REQ_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CERT_REQ_A:
- case SSL3_ST_SW_CERT_REQ_B:
- if (ssl->s3->tmp.cert_request) {
- ret = ssl3_send_certificate_request(ssl);
- if (ret <= 0) {
- goto end;
- }
- } else {
- skip = 1;
- }
- ssl->state = SSL3_ST_SW_SRVR_DONE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_SRVR_DONE_A:
- case SSL3_ST_SW_SRVR_DONE_B:
- ret = ssl3_send_server_done(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
- ssl->state = SSL3_ST_SW_FLUSH;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_FLUSH:
- /* This code originally checked to see if any data was pending using
- * BIO_CTRL_INFO and then flushed. This caused problems as documented
- * in PR#1939. The proposed fix doesn't completely resolve this issue
- * as buggy implementations of BIO_CTRL_PENDING still exist. So instead
- * we just flush unconditionally. */
- ssl->rwstate = SSL_WRITING;
- if (BIO_flush(ssl->wbio) <= 0) {
- ret = -1;
- goto end;
- }
- ssl->rwstate = SSL_NOTHING;
-
- ssl->state = ssl->s3->tmp.next_state;
- break;
-
- case SSL3_ST_SR_CERT_A:
- case SSL3_ST_SR_CERT_B:
- if (ssl->s3->tmp.cert_request) {
- ret = ssl3_get_client_certificate(ssl);
- if (ret <= 0) {
- goto end;
- }
- }
- ssl->init_num = 0;
- ssl->state = SSL3_ST_SR_KEY_EXCH_A;
- break;
-
- case SSL3_ST_SR_KEY_EXCH_A:
- case SSL3_ST_SR_KEY_EXCH_B:
- case SSL3_ST_SR_KEY_EXCH_C:
- ret = ssl3_get_client_key_exchange(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SR_CERT_VRFY_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SR_CERT_VRFY_A:
- case SSL3_ST_SR_CERT_VRFY_B:
- ret = ssl3_get_cert_verify(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- ssl->state = SSL3_ST_SR_CHANGE;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SR_CHANGE:
- ret = ssl->method->ssl_read_change_cipher_spec(ssl);
- if (ret <= 0) {
- goto end;
- }
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_READ)) {
- ret = -1;
- goto end;
- }
-
- if (ssl->s3->next_proto_neg_seen) {
- ssl->state = SSL3_ST_SR_NEXT_PROTO_A;
- } else if (ssl->s3->tlsext_channel_id_valid) {
- ssl->state = SSL3_ST_SR_CHANNEL_ID_A;
- } else {
- ssl->state = SSL3_ST_SR_FINISHED_A;
- }
- break;
-
- case SSL3_ST_SR_NEXT_PROTO_A:
- case SSL3_ST_SR_NEXT_PROTO_B:
- ret = ssl3_get_next_proto(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->init_num = 0;
- if (ssl->s3->tlsext_channel_id_valid) {
- ssl->state = SSL3_ST_SR_CHANNEL_ID_A;
- } else {
- ssl->state = SSL3_ST_SR_FINISHED_A;
- }
- break;
-
- case SSL3_ST_SR_CHANNEL_ID_A:
- case SSL3_ST_SR_CHANNEL_ID_B:
- ret = ssl3_get_channel_id(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->init_num = 0;
- ssl->state = SSL3_ST_SR_FINISHED_A;
- break;
-
- case SSL3_ST_SR_FINISHED_A:
- case SSL3_ST_SR_FINISHED_B:
- ret = ssl3_get_finished(ssl, SSL3_ST_SR_FINISHED_A,
- SSL3_ST_SR_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
-
- if (ssl->hit) {
- ssl->state = SSL_ST_OK;
- } else if (ssl->tlsext_ticket_expected) {
- ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
- } else {
- ssl->state = SSL3_ST_SW_CHANGE_A;
- }
- /* If this is a full handshake with ChannelID then record the hashshake
- * hashes in |ssl->session| in case we need them to verify a ChannelID
- * signature on a resumption of this session in the future. */
- if (!ssl->hit && ssl->s3->tlsext_channel_id_valid) {
- ret = tls1_record_handshake_hashes_for_channel_id(ssl);
- if (ret <= 0) {
- goto end;
- }
- }
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_SESSION_TICKET_A:
- case SSL3_ST_SW_SESSION_TICKET_B:
- ret = ssl3_send_new_session_ticket(ssl);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_CHANGE_A;
- ssl->init_num = 0;
- break;
-
- case SSL3_ST_SW_CHANGE_A:
- case SSL3_ST_SW_CHANGE_B:
- ret = ssl3_send_change_cipher_spec(ssl, SSL3_ST_SW_CHANGE_A,
- SSL3_ST_SW_CHANGE_B);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_FINISHED_A;
- ssl->init_num = 0;
-
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
- ret = -1;
- goto end;
- }
- break;
-
- case SSL3_ST_SW_FINISHED_A:
- case SSL3_ST_SW_FINISHED_B:
- ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
- SSL3_ST_SW_FINISHED_B);
- if (ret <= 0) {
- goto end;
- }
- ssl->state = SSL3_ST_SW_FLUSH;
- if (ssl->hit) {
- ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
- } else {
- ssl->s3->tmp.next_state = SSL_ST_OK;
- }
- ssl->init_num = 0;
- break;
-
- case SSL_ST_OK:
- /* clean a few things up */
- ssl3_cleanup_key_block(ssl);
-
- BUF_MEM_free(ssl->init_buf);
- ssl->init_buf = NULL;
-
- /* remove buffering on output */
- ssl_free_wbio_buffer(ssl);
-
- ssl->init_num = 0;
-
- /* If we aren't retaining peer certificates then we can discard it
- * now. */
- if (ssl->ctx->retain_only_sha256_of_client_certs) {
- X509_free(ssl->session->peer);
- ssl->session->peer = NULL;
- sk_X509_pop_free(ssl->session->cert_chain, X509_free);
- ssl->session->cert_chain = NULL;
- }
-
- ssl->s3->initial_handshake_complete = 1;
-
- ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
-
- if (cb != NULL) {
- cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
- }
-
- ret = 1;
- goto end;
-
- default:
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
- ret = -1;
- goto end;
- }
-
- if (!ssl->s3->tmp.reuse_message && !skip && cb != NULL &&
- ssl->state != state) {
- new_state = ssl->state;
- ssl->state = state;
- cb(ssl, SSL_CB_ACCEPT_LOOP, 1);
- ssl->state = new_state;
- }
- skip = 0;
- }
-
-end:
- ssl->in_handshake--;
- BUF_MEM_free(buf);
- if (cb != NULL) {
- cb(ssl, SSL_CB_ACCEPT_EXIT, ret);
- }
- return ret;
-}
-
-int ssl3_get_initial_bytes(SSL *ssl) {
- /* Read the first 5 bytes, the size of the TLS record header. This is
- * sufficient to detect a V2ClientHello and ensures that we never read beyond
- * the first record. */
- int ret = ssl_read_buffer_extend_to(ssl, SSL3_RT_HEADER_LENGTH);
- if (ret <= 0) {
- return ret;
- }
- assert(ssl_read_buffer_len(ssl) == SSL3_RT_HEADER_LENGTH);
- const uint8_t *p = ssl_read_buffer(ssl);
-
- /* Some dedicated error codes for protocol mixups should the application wish
- * to interpret them differently. (These do not overlap with ClientHello or
- * V2ClientHello.) */
- if (strncmp("GET ", (const char *)p, 4) == 0 ||
- strncmp("POST ", (const char *)p, 5) == 0 ||
- strncmp("HEAD ", (const char *)p, 5) == 0 ||
- strncmp("PUT ", (const char *)p, 4) == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_HTTP_REQUEST);
- return -1;
- }
- if (strncmp("CONNE", (const char *)p, 5) == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_HTTPS_PROXY_REQUEST);
- return -1;
- }
-
- /* Determine if this is a V2ClientHello. */
- if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO &&
- p[3] >= SSL3_VERSION_MAJOR) {
- /* This is a V2ClientHello. */
- ssl->state = SSL3_ST_SR_V2_CLIENT_HELLO;
- return 1;
- }
-
- /* Fall through to the standard logic. */
- ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
- return 1;
-}
-
-int ssl3_get_v2_client_hello(SSL *ssl) {
- const uint8_t *p;
- int ret;
- CBS v2_client_hello, cipher_specs, session_id, challenge;
- size_t msg_length, rand_len, len;
- uint8_t msg_type;
- uint16_t version, cipher_spec_length, session_id_length, challenge_length;
- CBB client_hello, hello_body, cipher_suites;
- uint8_t random[SSL3_RANDOM_SIZE];
-
- /* Determine the length of the V2ClientHello. */
- assert(ssl_read_buffer_len(ssl) >= SSL3_RT_HEADER_LENGTH);
- p = ssl_read_buffer(ssl);
- msg_length = ((p[0] & 0x7f) << 8) | p[1];
- if (msg_length > (1024 * 4)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE);
- return -1;
- }
- if (msg_length < SSL3_RT_HEADER_LENGTH - 2) {
- /* Reject lengths that are too short early. We have already read
- * |SSL3_RT_HEADER_LENGTH| bytes, so we should not attempt to process an
- * (invalid) V2ClientHello which would be shorter than that. */
- OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_LENGTH_MISMATCH);
- return -1;
- }
-
- /* Read the remainder of the V2ClientHello. */
- ret = ssl_read_buffer_extend_to(ssl, 2 + msg_length);
- if (ret <= 0) {
- return ret;
- }
- assert(ssl_read_buffer_len(ssl) == msg_length + 2);
- CBS_init(&v2_client_hello, ssl_read_buffer(ssl) + 2, msg_length);
-
- /* The V2ClientHello without the length is incorporated into the handshake
- * hash. */
- if (!ssl3_update_handshake_hash(ssl, CBS_data(&v2_client_hello),
- CBS_len(&v2_client_hello))) {
- return -1;
- }
- if (ssl->msg_callback) {
- ssl->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello),
- CBS_len(&v2_client_hello), ssl, ssl->msg_callback_arg);
- }
-
- if (!CBS_get_u8(&v2_client_hello, &msg_type) ||
- !CBS_get_u16(&v2_client_hello, &version) ||
- !CBS_get_u16(&v2_client_hello, &cipher_spec_length) ||
- !CBS_get_u16(&v2_client_hello, &session_id_length) ||
- !CBS_get_u16(&v2_client_hello, &challenge_length) ||
- !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) ||
- !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) ||
- !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) ||
- CBS_len(&v2_client_hello) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- return -1;
- }
-
- /* msg_type has already been checked. */
- assert(msg_type == SSL2_MT_CLIENT_HELLO);
-
- /* The client_random is the V2ClientHello challenge. Truncate or
- * left-pad with zeros as needed. */
- memset(random, 0, SSL3_RANDOM_SIZE);
- rand_len = CBS_len(&challenge);
- if (rand_len > SSL3_RANDOM_SIZE) {
- rand_len = SSL3_RANDOM_SIZE;
- }
- memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
- rand_len);
-
- /* Write out an equivalent SSLv3 ClientHello. */
- CBB_zero(&client_hello);
- if (!CBB_init_fixed(&client_hello, (uint8_t *)ssl->init_buf->data,
- ssl->init_buf->max) ||
- !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
- !CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
- !CBB_add_u16(&hello_body, version) ||
- !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
- /* No session id. */
- !CBB_add_u8(&hello_body, 0) ||
- !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
- CBB_cleanup(&client_hello);
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return -1;
- }
-
- /* Copy the cipher suites. */
- while (CBS_len(&cipher_specs) > 0) {
- uint32_t cipher_spec;
- if (!CBS_get_u24(&cipher_specs, &cipher_spec)) {
- CBB_cleanup(&client_hello);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- return -1;
- }
-
- /* Skip SSLv2 ciphers. */
- if ((cipher_spec & 0xff0000) != 0) {
- continue;
- }
- if (!CBB_add_u16(&cipher_suites, cipher_spec)) {
- CBB_cleanup(&client_hello);
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- }
-
- /* Add the null compression scheme and finish. */
- if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) ||
- !CBB_finish(&client_hello, NULL, &len)) {
- CBB_cleanup(&client_hello);
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
- /* Mark the message for "re"-use by the version-specific method. */
- ssl->s3->tmp.reuse_message = 1;
- ssl->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO;
- /* The handshake message header is 4 bytes. */
- ssl->s3->tmp.message_size = len - 4;
-
- /* Consume and discard the V2ClientHello. */
- ssl_read_buffer_consume(ssl, 2 + msg_length);
- ssl_read_buffer_discard(ssl);
-
- return 1;
-}
-
-int ssl3_get_client_hello(SSL *ssl) {
- int ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
- long n;
- const SSL_CIPHER *c;
- STACK_OF(SSL_CIPHER) *ciphers = NULL;
- struct ssl_early_callback_ctx early_ctx;
- CBS client_hello;
- uint16_t client_version;
- CBS client_random, session_id, cipher_suites, compression_methods;
- SSL_SESSION *session = NULL;
-
- /* We do this so that we will respond with our native type. If we are TLSv1
- * and we get SSLv3, we will respond with TLSv1, This down switching should
- * be handled by a different method. If we are SSLv3, we will respond with
- * SSLv3, even if prompted with TLSv1. */
- switch (ssl->state) {
- case SSL3_ST_SR_CLNT_HELLO_A:
- case SSL3_ST_SR_CLNT_HELLO_B:
- n = ssl->method->ssl_get_message(
- ssl, SSL3_ST_SR_CLNT_HELLO_A, SSL3_ST_SR_CLNT_HELLO_B,
- SSL3_MT_CLIENT_HELLO, SSL3_RT_MAX_PLAIN_LENGTH,
- ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- ssl->state = SSL3_ST_SR_CLNT_HELLO_C;
- /* fallthrough */
- case SSL3_ST_SR_CLNT_HELLO_C:
- case SSL3_ST_SR_CLNT_HELLO_D:
- /* We have previously parsed the ClientHello message, and can't call
- * ssl_get_message again without hashing the message into the Finished
- * digest again. */
- n = ssl->init_num;
-
- memset(&early_ctx, 0, sizeof(early_ctx));
- early_ctx.ssl = ssl;
- early_ctx.client_hello = ssl->init_msg;
- early_ctx.client_hello_len = n;
- if (!ssl_early_callback_init(&early_ctx)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
- goto f_err;
- }
-
- if (ssl->state == SSL3_ST_SR_CLNT_HELLO_C &&
- ssl->ctx->select_certificate_cb != NULL) {
- ssl->state = SSL3_ST_SR_CLNT_HELLO_D;
- switch (ssl->ctx->select_certificate_cb(&early_ctx)) {
- case 0:
- ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
- goto err;
-
- case -1:
- /* Connection rejected. */
- al = SSL_AD_ACCESS_DENIED;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
- goto f_err;
-
- default:
- /* fallthrough */;
- }
- }
- ssl->state = SSL3_ST_SR_CLNT_HELLO_D;
- break;
-
- default:
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
- return -1;
- }
-
- CBS_init(&client_hello, ssl->init_msg, n);
- if (!CBS_get_u16(&client_hello, &client_version) ||
- !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) ||
- !CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
- CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- /* use version from inside client hello, not from record header (may differ:
- * see RFC 2246, Appendix E, second paragraph) */
- ssl->client_version = client_version;
-
- /* Load the client random. */
- memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
-
- if (SSL_IS_DTLS(ssl)) {
- CBS cookie;
-
- if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
- CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
- }
-
- /* Note: This codepath may run twice if |ssl_get_prev_session| completes
- * asynchronously.
- *
- * TODO(davidben): Clean up the order of events around ClientHello
- * processing. */
- if (!ssl->s3->have_version) {
- /* Select version to use */
- uint16_t version = ssl3_get_mutual_version(ssl, client_version);
- if (version == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
- ssl->version = ssl->client_version;
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
- }
- ssl->version = version;
- ssl->s3->enc_method = ssl3_get_enc_method(version);
- assert(ssl->s3->enc_method != NULL);
- /* At this point, the connection's version is known and |ssl->version| is
- * fixed. Begin enforcing the record-layer version. */
- ssl->s3->have_version = 1;
- } else if (SSL_IS_DTLS(ssl) ? (ssl->client_version > ssl->version)
- : (ssl->client_version < ssl->version)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
- }
-
- ssl->hit = 0;
- int send_new_ticket = 0;
- switch (ssl_get_prev_session(ssl, &session, &send_new_ticket, &early_ctx)) {
- case ssl_session_success:
- break;
- case ssl_session_error:
- goto err;
- case ssl_session_retry:
- ssl->rwstate = SSL_PENDING_SESSION;
- goto err;
- }
- ssl->tlsext_ticket_expected = send_new_ticket;
-
- /* The EMS state is needed when making the resumption decision, but
- * extensions are not normally parsed until later. This detects the EMS
- * extension for the resumption decision and it's checked against the result
- * of the normal parse later in this function. */
- const uint8_t *ems_data;
- size_t ems_len;
- int have_extended_master_secret =
- ssl->version != SSL3_VERSION &&
- SSL_early_callback_ctx_extension_get(&early_ctx,
- TLSEXT_TYPE_extended_master_secret,
- &ems_data, &ems_len) &&
- ems_len == 0;
-
- if (session != NULL) {
- if (session->extended_master_secret &&
- !have_extended_master_secret) {
- /* A ClientHello without EMS that attempts to resume a session with EMS
- * is fatal to the connection. */
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
- goto f_err;
- }
-
- ssl->hit =
- /* Only resume if the session's version matches the negotiated version:
- * most clients do not accept a mismatch. */
- ssl->version == session->ssl_version &&
- /* If the client offers the EMS extension, but the previous session
- * didn't use it, then negotiate a new session. */
- have_extended_master_secret == session->extended_master_secret;
- }
-
- if (ssl->hit) {
- /* Use the new session. */
- SSL_SESSION_free(ssl->session);
- ssl->session = session;
- session = NULL;
-
- ssl->verify_result = ssl->session->verify_result;
- } else {
- if (!ssl_get_new_session(ssl, 1 /* server */)) {
- goto err;
- }
-
- /* Clear the session ID if we want the session to be single-use. */
- if (!(ssl->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) {
- ssl->session->session_id_length = 0;
- }
- }
-
- if (ssl->ctx->dos_protection_cb != NULL &&
- ssl->ctx->dos_protection_cb(&early_ctx) == 0) {
- /* Connection rejected for DOS reasons. */
- al = SSL_AD_ACCESS_DENIED;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
- goto f_err;
- }
-
- if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) ||
- CBS_len(&cipher_suites) == 0 ||
- CBS_len(&cipher_suites) % 2 != 0 ||
- !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) ||
- CBS_len(&compression_methods) == 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- ciphers = ssl_bytes_to_cipher_list(ssl, &cipher_suites);
- if (ciphers == NULL) {
- goto err;
- }
-
- /* If it is a hit, check that the cipher is in the list. */
- if (ssl->hit) {
- size_t j;
- int found_cipher = 0;
- uint32_t id = ssl->session->cipher->id;
-
- for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
- c = sk_SSL_CIPHER_value(ciphers, j);
- if (c->id == id) {
- found_cipher = 1;
- break;
- }
- }
-
- if (!found_cipher) {
- /* we need to have the cipher in the cipher list if we are asked to reuse
- * it */
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_REQUIRED_CIPHER_MISSING);
- goto f_err;
- }
- }
-
- /* Only null compression is supported. */
- if (memchr(CBS_data(&compression_methods), 0,
- CBS_len(&compression_methods)) == NULL) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMPRESSION_SPECIFIED);
- goto f_err;
- }
-
- /* TLS extensions. */
- if (ssl->version >= SSL3_VERSION &&
- !ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
- goto err;
- }
-
- /* There should be nothing left over in the record. */
- if (CBS_len(&client_hello) != 0) {
- /* wrong packet length */
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
- goto f_err;
- }
-
- if (have_extended_master_secret != ssl->s3->tmp.extended_master_secret) {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_EMS_STATE_INCONSISTENT);
- goto f_err;
- }
-
- /* Given ciphers and SSL_get_ciphers, we must pick a cipher */
- if (!ssl->hit) {
- if (ciphers == NULL) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_PASSED);
- goto f_err;
- }
-
- /* Let cert callback update server certificates if required */
- if (ssl->cert->cert_cb) {
- int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
- if (rv == 0) {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
- goto f_err;
- }
- if (rv < 0) {
- ssl->rwstate = SSL_X509_LOOKUP;
- goto err;
- }
- ssl->rwstate = SSL_NOTHING;
- }
- c = ssl3_choose_cipher(ssl, ciphers, ssl_get_cipher_preferences(ssl));
-
- if (c == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
- goto f_err;
- }
- ssl->session->cipher = c;
- ssl->s3->tmp.new_cipher = c;
-
- /* Determine whether to request a client certificate. */
- ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
- /* Only request a certificate if Channel ID isn't negotiated. */
- if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
- ssl->s3->tlsext_channel_id_valid) {
- ssl->s3->tmp.cert_request = 0;
- }
- /* Plain PSK forbids Certificate and CertificateRequest. */
- if (ssl->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) {
- ssl->s3->tmp.cert_request = 0;
- }
- } else {
- /* Session-id reuse */
- ssl->s3->tmp.new_cipher = ssl->session->cipher;
- ssl->s3->tmp.cert_request = 0;
- }
-
- /* Now that the cipher is known, initialize the handshake hash. */
- if (!ssl3_init_handshake_hash(ssl)) {
- goto f_err;
- }
-
- /* In TLS 1.2, client authentication requires hashing the handshake transcript
- * under a different hash. Otherwise, release the handshake buffer. */
- if (!ssl->s3->tmp.cert_request ||
- ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
- ssl3_free_handshake_buffer(ssl);
- }
-
- /* we now have the following setup;
- * client_random
- * cipher_list - our prefered list of ciphers
- * ciphers - the clients prefered list of ciphers
- * compression - basically ignored right now
- * ssl version is set - sslv3
- * ssl->session - The ssl session has been setup.
- * ssl->hit - session reuse flag
- * ssl->tmp.new_cipher - the new cipher to use. */
-
- ret = 1;
-
- if (0) {
- f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- }
-
-err:
- sk_SSL_CIPHER_free(ciphers);
- SSL_SESSION_free(session);
- return ret;
-}
-
-int ssl3_send_server_hello(SSL *ssl) {
- if (ssl->state == SSL3_ST_SW_SRVR_HELLO_B) {
- return ssl_do_write(ssl);
- }
-
- assert(ssl->state == SSL3_ST_SW_SRVR_HELLO_A);
-
- /* We only accept ChannelIDs on connections with ECDHE in order to avoid a
- * known attack while we fix ChannelID itself. */
- if (ssl->s3->tlsext_channel_id_valid &&
- (ssl->s3->tmp.new_cipher->algorithm_mkey & SSL_kECDHE) == 0) {
- ssl->s3->tlsext_channel_id_valid = 0;
- }
-
- /* If this is a resumption and the original handshake didn't support
- * ChannelID then we didn't record the original handshake hashes in the
- * session and so cannot resume with ChannelIDs. */
- if (ssl->hit && ssl->session->original_handshake_hash_len == 0) {
- ssl->s3->tlsext_channel_id_valid = 0;
- }
-
- if (!ssl_fill_hello_random(ssl->s3->server_random, SSL3_RANDOM_SIZE,
- 1 /* server */)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
- CBB cbb, session_id;
- size_t length;
- CBB_zero(&cbb);
- if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
- !CBB_add_u16(&cbb, ssl->version) ||
- !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
- !CBB_add_u8_length_prefixed(&cbb, &session_id) ||
- !CBB_add_bytes(&session_id, ssl->session->session_id,
- ssl->session->session_id_length) ||
- !CBB_add_u16(&cbb, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
- !CBB_add_u8(&cbb, 0 /* no compression */) ||
- !ssl_add_serverhello_tlsext(ssl, &cbb) ||
- !CBB_finish(&cbb, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_HELLO, length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
- return -1;
- }
-
- ssl->state = SSL3_ST_SW_SRVR_HELLO_B;
- return ssl_do_write(ssl);
-}
-
-int ssl3_send_certificate_status(SSL *ssl) {
- if (ssl->state == SSL3_ST_SW_CERT_STATUS_A) {
- CBB out, ocsp_response;
- size_t length;
-
- CBB_zero(&out);
- if (!CBB_init_fixed(&out, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
- !CBB_add_u8(&out, TLSEXT_STATUSTYPE_ocsp) ||
- !CBB_add_u24_length_prefixed(&out, &ocsp_response) ||
- !CBB_add_bytes(&ocsp_response, ssl->ctx->ocsp_response,
- ssl->ctx->ocsp_response_length) ||
- !CBB_finish(&out, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_STATUS, length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&out);
- return -1;
- }
-
- ssl->state = SSL3_ST_SW_CERT_STATUS_B;
- }
-
- /* SSL3_ST_SW_CERT_STATUS_B */
- return ssl_do_write(ssl);
-}
-
-int ssl3_send_server_done(SSL *ssl) {
- if (ssl->state == SSL3_ST_SW_SRVR_DONE_A) {
- if (!ssl_set_handshake_header(ssl, SSL3_MT_SERVER_DONE, 0)) {
- return -1;
- }
- ssl->state = SSL3_ST_SW_SRVR_DONE_B;
- }
-
- /* SSL3_ST_SW_SRVR_DONE_B */
- return ssl_do_write(ssl);
-}
-
-int ssl3_send_server_key_exchange(SSL *ssl) {
- if (ssl->state == SSL3_ST_SW_KEY_EXCH_C) {
- return ssl_do_write(ssl);
- }
-
- CBB cbb, child;
- if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
- ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
- goto err;
- }
-
- if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
- /* This is the first iteration, so write parameters. */
- uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
- uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
- /* PSK ciphers begin with an identity hint. */
- if (alg_a & SSL_aPSK) {
- size_t len =
- (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint);
- if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint,
- len)) {
- goto err;
- }
- }
-
- if (alg_k & SSL_kDHE) {
- /* Determine the group to use. */
- DH *params = ssl->cert->dh_tmp;
- if (params == NULL && ssl->cert->dh_tmp_cb != NULL) {
- params = ssl->cert->dh_tmp_cb(ssl, 0, 1024);
- }
- if (params == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_DH_KEY);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
- }
- ssl->session->key_exchange_info = DH_num_bits(params);
-
- /* Set up DH, generate a key, and emit the public half. */
- DH *dh = DHparams_dup(params);
- if (dh == NULL) {
- goto err;
- }
-
- SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
- if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !SSL_ECDH_CTX_generate_keypair(&ssl->s3->tmp.ecdh_ctx, &child)) {
- goto err;
- }
- } else if (alg_k & SSL_kECDHE) {
- /* Determine the curve to use. */
- uint16_t curve_id;
- if (!tls1_get_shared_curve(ssl, &curve_id)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_ECDH_KEY);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
- }
- ssl->session->key_exchange_info = curve_id;
-
- /* Set up ECDH, generate a key, and emit the public half. */
- if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, curve_id) ||
- !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
- !CBB_add_u16(&cbb, curve_id) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
- !SSL_ECDH_CTX_generate_keypair(&ssl->s3->tmp.ecdh_ctx, &child)) {
- goto err;
- }
- } else {
- assert(alg_k & SSL_kPSK);
- }
-
- /* Otherwise, restore |cbb| from the previous iteration.
- * TODO(davidben): When |ssl->init_buf| is gone, come up with a simpler
- * pattern. Probably keep the |CBB| around in the handshake state. */
- } else if (!CBB_did_write(&cbb, ssl->init_num - SSL_HM_HEADER_LENGTH(ssl))) {
- goto err;
- }
-
- /* Add a signature. */
- if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
- if (!ssl_has_private_key(ssl)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
-
- const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
- size_t sig_len;
- enum ssl_private_key_result_t sign_result;
- if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
- /* This is the first iteration, so set up the signature. Sample the
- * parameter length before adding a signature algorithm. */
- if (!CBB_flush(&cbb)) {
- goto err;
- }
- size_t params_len = CBB_len(&cbb);
-
- /* Determine signature algorithm. */
- const EVP_MD *md;
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- md = tls1_choose_signing_digest(ssl);
- if (!tls12_add_sigandhash(ssl, &cbb, md)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
- } else if (ssl_private_key_type(ssl) == EVP_PKEY_RSA) {
- md = EVP_md5_sha1();
- } else {
- md = EVP_sha1();
- }
-
- /* Compute the digest and sign it. */
- uint8_t digest[EVP_MAX_MD_SIZE];
- unsigned digest_len = 0;
- EVP_MD_CTX md_ctx;
- EVP_MD_CTX_init(&md_ctx);
- int digest_ret =
- EVP_DigestInit_ex(&md_ctx, md, NULL) &&
- EVP_DigestUpdate(&md_ctx, ssl->s3->client_random, SSL3_RANDOM_SIZE) &&
- EVP_DigestUpdate(&md_ctx, ssl->s3->server_random, SSL3_RANDOM_SIZE) &&
- EVP_DigestUpdate(&md_ctx, CBB_data(&cbb), params_len) &&
- EVP_DigestFinal_ex(&md_ctx, digest, &digest_len);
- EVP_MD_CTX_cleanup(&md_ctx);
- uint8_t *ptr;
- if (!digest_ret ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_reserve(&child, &ptr, max_sig_len)) {
- goto err;
- }
- sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md,
- digest, digest_len);
- } else {
- assert(ssl->state == SSL3_ST_SW_KEY_EXCH_B);
-
- /* Retry the signature. */
- uint8_t *ptr;
- if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_reserve(&child, &ptr, max_sig_len)) {
- goto err;
- }
- sign_result =
- ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len);
- }
-
- switch (sign_result) {
- case ssl_private_key_success:
- ssl->rwstate = SSL_NOTHING;
- if (!CBB_did_write(&child, sig_len)) {
- goto err;
- }
- break;
- case ssl_private_key_failure:
- ssl->rwstate = SSL_NOTHING;
- goto err;
- case ssl_private_key_retry:
- /* Discard the unfinished signature and save the state of |cbb| for the
- * next iteration. */
- CBB_discard_child(&cbb);
- ssl->init_num = SSL_HM_HEADER_LENGTH(ssl) + CBB_len(&cbb);
- ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
- ssl->state = SSL3_ST_SW_KEY_EXCH_B;
- goto err;
- }
- }
-
- size_t length;
- if (!CBB_finish(&cbb, NULL, &length) ||
- !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_KEY_EXCHANGE, length)) {
- goto err;
- }
- ssl->state = SSL3_ST_SW_KEY_EXCH_C;
- return ssl_do_write(ssl);
-
-err:
- CBB_cleanup(&cbb);
- return -1;
-}
-
-int ssl3_send_certificate_request(SSL *ssl) {
- uint8_t *p, *d;
- size_t i;
- int j, nl, off, n;
- STACK_OF(X509_NAME) *sk = NULL;
- X509_NAME *name;
- BUF_MEM *buf;
-
- if (ssl->state == SSL3_ST_SW_CERT_REQ_A) {
- buf = ssl->init_buf;
-
- d = p = ssl_handshake_start(ssl);
-
- /* get the list of acceptable cert types */
- p++;
- n = ssl3_get_req_cert_type(ssl, p);
- d[0] = n;
- p += n;
- n++;
-
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- const uint8_t *psigs;
- nl = tls12_get_psigalgs(ssl, &psigs);
- s2n(nl, p);
- memcpy(p, psigs, nl);
- p += nl;
- n += nl + 2;
- }
-
- off = n;
- p += 2;
- n += 2;
-
- sk = SSL_get_client_CA_list(ssl);
- nl = 0;
- if (sk != NULL) {
- for (i = 0; i < sk_X509_NAME_num(sk); i++) {
- name = sk_X509_NAME_value(sk, i);
- j = i2d_X509_NAME(name, NULL);
- if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(ssl) + n + j + 2)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
- goto err;
- }
- p = ssl_handshake_start(ssl) + n;
- s2n(j, p);
- i2d_X509_NAME(name, &p);
- n += 2 + j;
- nl += 2 + j;
- }
- }
-
- /* else no CA names */
- p = ssl_handshake_start(ssl) + off;
- s2n(nl, p);
-
- if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_REQUEST, n)) {
- goto err;
- }
- ssl->state = SSL3_ST_SW_CERT_REQ_B;
- }
-
- /* SSL3_ST_SW_CERT_REQ_B */
- return ssl_do_write(ssl);
-
-err:
- return -1;
-}
-
-int ssl3_get_client_key_exchange(SSL *ssl) {
- int al;
- CBS client_key_exchange;
- uint32_t alg_k;
- uint32_t alg_a;
- uint8_t *premaster_secret = NULL;
- size_t premaster_secret_len = 0;
- uint8_t *decrypt_buf = NULL;
-
- unsigned psk_len = 0;
- uint8_t psk[PSK_MAX_PSK_LEN];
-
- if (ssl->state == SSL3_ST_SR_KEY_EXCH_A ||
- ssl->state == SSL3_ST_SR_KEY_EXCH_B) {
- int ok;
- const long n = ssl->method->ssl_get_message(
- ssl, SSL3_ST_SR_KEY_EXCH_A, SSL3_ST_SR_KEY_EXCH_B,
- SSL3_MT_CLIENT_KEY_EXCHANGE, 2048 /* ??? */, ssl_hash_message, &ok);
- if (!ok) {
- return n;
- }
- }
-
- CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
- alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
- /* If using a PSK key exchange, prepare the pre-shared key. */
- if (alg_a & SSL_aPSK) {
- CBS psk_identity;
-
- /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK,
- * then this is the only field in the message. */
- if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) ||
- ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- al = SSL_AD_DECODE_ERROR;
- goto f_err;
- }
-
- if (ssl->psk_server_callback == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
- al = SSL_AD_INTERNAL_ERROR;
- goto f_err;
- }
-
- if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
- CBS_contains_zero_byte(&psk_identity)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
- al = SSL_AD_ILLEGAL_PARAMETER;
- goto f_err;
- }
-
- if (!CBS_strdup(&psk_identity, &ssl->session->psk_identity)) {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
-
- /* Look up the key for the identity. */
- psk_len = ssl->psk_server_callback(ssl, ssl->session->psk_identity, psk,
- sizeof(psk));
- if (psk_len > PSK_MAX_PSK_LEN) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- al = SSL_AD_INTERNAL_ERROR;
- goto f_err;
- } else if (psk_len == 0) {
- /* PSK related to the given identity not found */
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
- al = SSL_AD_UNKNOWN_PSK_IDENTITY;
- goto f_err;
- }
- }
-
- /* Depending on the key exchange method, compute |premaster_secret| and
- * |premaster_secret_len|. */
- if (alg_k & SSL_kRSA) {
- /* Allocate a buffer large enough for an RSA decryption. */
- const size_t rsa_size = ssl_private_key_max_signature_len(ssl);
- decrypt_buf = OPENSSL_malloc(rsa_size);
- if (decrypt_buf == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- enum ssl_private_key_result_t decrypt_result;
- size_t decrypt_len;
- if (ssl->state == SSL3_ST_SR_KEY_EXCH_B) {
- if (!ssl_has_private_key(ssl) ||
- ssl_private_key_type(ssl) != EVP_PKEY_RSA) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE);
- goto f_err;
- }
- CBS encrypted_premaster_secret;
- if (ssl->version > SSL3_VERSION) {
- if (!CBS_get_u16_length_prefixed(&client_key_exchange,
- &encrypted_premaster_secret) ||
- CBS_len(&client_key_exchange) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL,
- SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
- goto f_err;
- }
- } else {
- encrypted_premaster_secret = client_key_exchange;
- }
-
- /* Decrypt with no padding. PKCS#1 padding will be removed as part of the
- * timing-sensitive code below. */
- decrypt_result = ssl_private_key_decrypt(
- ssl, decrypt_buf, &decrypt_len, rsa_size,
- CBS_data(&encrypted_premaster_secret),
- CBS_len(&encrypted_premaster_secret));
- } else {
- assert(ssl->state == SSL3_ST_SR_KEY_EXCH_C);
- /* Complete async decrypt. */
- decrypt_result = ssl_private_key_decrypt_complete(
- ssl, decrypt_buf, &decrypt_len, rsa_size);
- }
-
- switch (decrypt_result) {
- case ssl_private_key_success:
- ssl->rwstate = SSL_NOTHING;
- break;
- case ssl_private_key_failure:
- ssl->rwstate = SSL_NOTHING;
- goto err;
- case ssl_private_key_retry:
- ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
- ssl->state = SSL3_ST_SR_KEY_EXCH_C;
- goto err;
- }
-
- assert(decrypt_len == rsa_size);
-
- /* Prepare a random premaster, to be used on invalid padding. See RFC 5246,
- * section 7.4.7.1. */
- premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH;
- premaster_secret = OPENSSL_malloc(premaster_secret_len);
- if (premaster_secret == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!RAND_bytes(premaster_secret, premaster_secret_len)) {
- goto err;
- }
-
- /* The smallest padded premaster is 11 bytes of overhead. Small keys are
- * publicly invalid. */
- if (decrypt_len < 11 + premaster_secret_len) {
- al = SSL_AD_DECRYPT_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
- goto f_err;
- }
-
- /* Check the padding. See RFC 3447, section 7.2.2. */
- size_t padding_len = decrypt_len - premaster_secret_len;
- uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) &
- constant_time_eq_int_8(decrypt_buf[1], 2);
- size_t i;
- for (i = 2; i < padding_len - 1; i++) {
- good &= ~constant_time_is_zero_8(decrypt_buf[i]);
- }
- good &= constant_time_is_zero_8(decrypt_buf[padding_len - 1]);
-
- /* The premaster secret must begin with |client_version|. This too must be
- * checked in constant time (http://eprint.iacr.org/2003/052/). */
- good &= constant_time_eq_8(decrypt_buf[padding_len],
- (unsigned)(ssl->client_version >> 8));
- good &= constant_time_eq_8(decrypt_buf[padding_len + 1],
- (unsigned)(ssl->client_version & 0xff));
-
- /* Select, in constant time, either the decrypted premaster or the random
- * premaster based on |good|. */
- for (i = 0; i < premaster_secret_len; i++) {
- premaster_secret[i] = constant_time_select_8(
- good, decrypt_buf[padding_len + i], premaster_secret[i]);
- }
-
- OPENSSL_free(decrypt_buf);
- decrypt_buf = NULL;
- } else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
- /* Parse the ClientKeyExchange. ECDHE uses a u8 length prefix while DHE uses
- * u16. */
- CBS peer_key;
- int peer_key_ok;
- if (alg_k & SSL_kECDHE) {
- peer_key_ok = CBS_get_u8_length_prefixed(&client_key_exchange, &peer_key);
- } else {
- peer_key_ok =
- CBS_get_u16_length_prefixed(&client_key_exchange, &peer_key);
- }
-
- if (!peer_key_ok || CBS_len(&client_key_exchange) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- /* Compute the premaster. */
- uint8_t alert;
- if (!SSL_ECDH_CTX_compute_secret(&ssl->s3->tmp.ecdh_ctx, &premaster_secret,
- &premaster_secret_len, &alert,
- CBS_data(&peer_key), CBS_len(&peer_key))) {
- al = alert;
- goto f_err;
- }
-
- /* The key exchange state may now be discarded. */
- SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
- } else if (alg_k & SSL_kPSK) {
- /* For plain PSK, other_secret is a block of 0s with the same length as the
- * pre-shared key. */
- premaster_secret_len = psk_len;
- premaster_secret = OPENSSL_malloc(premaster_secret_len);
- if (premaster_secret == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memset(premaster_secret, 0, premaster_secret_len);
- } else {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE);
- goto f_err;
- }
-
- /* For a PSK cipher suite, the actual pre-master secret is combined with the
- * pre-shared key. */
- if (alg_a & SSL_aPSK) {
- CBB new_premaster, child;
- uint8_t *new_data;
- size_t new_len;
-
- CBB_zero(&new_premaster);
- if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
- !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
- !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
- !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
- !CBB_add_bytes(&child, psk, psk_len) ||
- !CBB_finish(&new_premaster, &new_data, &new_len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- CBB_cleanup(&new_premaster);
- goto err;
- }
-
- OPENSSL_cleanse(premaster_secret, premaster_secret_len);
- OPENSSL_free(premaster_secret);
- premaster_secret = new_data;
- premaster_secret_len = new_len;
- }
-
- /* Compute the master secret */
- ssl->session->master_key_length = tls1_generate_master_secret(
- ssl, ssl->session->master_key, premaster_secret, premaster_secret_len);
- if (ssl->session->master_key_length == 0) {
- goto err;
- }
- ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
-
- OPENSSL_cleanse(premaster_secret, premaster_secret_len);
- OPENSSL_free(premaster_secret);
- return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
- if (premaster_secret != NULL) {
- OPENSSL_cleanse(premaster_secret, premaster_secret_len);
- OPENSSL_free(premaster_secret);
- }
- OPENSSL_free(decrypt_buf);
-
- return -1;
-}
-
-int ssl3_get_cert_verify(SSL *ssl) {
- int al, ok, ret = 0;
- long n;
- CBS certificate_verify, signature;
- X509 *peer = ssl->session->peer;
- EVP_PKEY *pkey = NULL;
- const EVP_MD *md = NULL;
- uint8_t digest[EVP_MAX_MD_SIZE];
- size_t digest_length;
- EVP_PKEY_CTX *pctx = NULL;
-
- /* Only RSA and ECDSA client certificates are supported, so a
- * CertificateVerify is required if and only if there's a client certificate.
- * */
- if (peer == NULL) {
- ssl3_free_handshake_buffer(ssl);
- return 1;
- }
-
- n = ssl->method->ssl_get_message(
- ssl, SSL3_ST_SR_CERT_VRFY_A, SSL3_ST_SR_CERT_VRFY_B,
- SSL3_MT_CERTIFICATE_VERIFY, SSL3_RT_MAX_PLAIN_LENGTH,
- ssl_dont_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- /* Filter out unsupported certificate types. */
- pkey = X509_get_pubkey(peer);
- if (pkey == NULL) {
- goto err;
- }
- if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) ||
- (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) {
- al = SSL_AD_UNSUPPORTED_CERTIFICATE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
- goto f_err;
- }
-
- CBS_init(&certificate_verify, ssl->init_msg, n);
-
- /* Determine the digest type if needbe. */
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- uint8_t hash, signature_type;
- if (!CBS_get_u8(&certificate_verify, &hash) ||
- !CBS_get_u8(&certificate_verify, &signature_type)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
- if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature_type, pkey)) {
- goto f_err;
- }
- }
-
- /* Compute the digest. */
- if (!ssl3_cert_verify_hash(ssl, digest, &digest_length, &md, pkey->type)) {
- goto err;
- }
-
- /* The handshake buffer is no longer necessary, and we may hash the current
- * message.*/
- ssl3_free_handshake_buffer(ssl);
- if (!ssl3_hash_current_message(ssl)) {
- goto err;
- }
-
- /* Parse and verify the signature. */
- if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
- CBS_len(&certificate_verify) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (pctx == NULL) {
- goto err;
- }
- if (!EVP_PKEY_verify_init(pctx) ||
- !EVP_PKEY_CTX_set_signature_md(pctx, md) ||
- !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), digest,
- digest_length)) {
- al = SSL_AD_DECRYPT_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
- goto f_err;
- }
-
- ret = 1;
-
- if (0) {
- f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- }
-
-err:
- EVP_PKEY_CTX_free(pctx);
- EVP_PKEY_free(pkey);
-
- return ret;
-}
-
-int ssl3_get_client_certificate(SSL *ssl) {
- int i, ok, al, ret = -1;
- X509 *x = NULL;
- unsigned long n;
- STACK_OF(X509) *sk = NULL;
- SHA256_CTX sha256;
- CBS certificate_msg, certificate_list;
- int is_first_certificate = 1;
-
- n = ssl->method->ssl_get_message(ssl, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B,
- -1, (long)ssl->max_cert_list,
- ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- if (ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
- if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
- (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
- al = SSL_AD_HANDSHAKE_FAILURE;
- goto f_err;
- }
-
- /* If tls asked for a client cert, the client must return a 0 list */
- if (ssl->version > SSL3_VERSION && ssl->s3->tmp.cert_request) {
- OPENSSL_PUT_ERROR(SSL,
- SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
- al = SSL_AD_UNEXPECTED_MESSAGE;
- goto f_err;
- }
- ssl->s3->tmp.reuse_message = 1;
-
- return 1;
- }
-
- if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_MESSAGE_TYPE);
- goto f_err;
- }
-
- CBS_init(&certificate_msg, ssl->init_msg, n);
-
- sk = sk_X509_new_null();
- if (sk == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) ||
- CBS_len(&certificate_msg) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- while (CBS_len(&certificate_list) > 0) {
- CBS certificate;
- const uint8_t *data;
-
- if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (is_first_certificate && ssl->ctx->retain_only_sha256_of_client_certs) {
- /* If this is the first certificate, and we don't want to keep peer
- * certificates in memory, then we hash it right away. */
- SHA256_Init(&sha256);
- SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate));
- SHA256_Final(ssl->session->peer_sha256, &sha256);
- ssl->session->peer_sha256_valid = 1;
- }
- is_first_certificate = 0;
-
- /* A u24 length cannot overflow a long. */
- data = CBS_data(&certificate);
- x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
- if (x == NULL) {
- al = SSL_AD_BAD_CERTIFICATE;
- OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
- goto f_err;
- }
- if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
- goto f_err;
- }
- if (!sk_X509_push(sk, x)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- x = NULL;
- }
-
- if (sk_X509_num(sk) <= 0) {
- /* No client certificate so the handshake buffer may be discarded. */
- ssl3_free_handshake_buffer(ssl);
-
- /* TLS does not mind 0 certs returned */
- if (ssl->version == SSL3_VERSION) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
- goto f_err;
- } else if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
- (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
- /* Fail for TLS only if we required a certificate */
- OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
- al = SSL_AD_HANDSHAKE_FAILURE;
- goto f_err;
- }
- } else {
- i = ssl_verify_cert_chain(ssl, sk);
- if (i <= 0) {
- al = ssl_verify_alarm_type(ssl->verify_result);
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
- goto f_err;
- }
- }
-
- X509_free(ssl->session->peer);
- ssl->session->peer = sk_X509_shift(sk);
- ssl->session->verify_result = ssl->verify_result;
-
- sk_X509_pop_free(ssl->session->cert_chain, X509_free);
- ssl->session->cert_chain = sk;
- /* Inconsistency alert: cert_chain does *not* include the peer's own
- * certificate, while we do include it in s3_clnt.c */
-
- sk = NULL;
-
- ret = 1;
-
- if (0) {
- f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- }
-
-err:
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return ret;
-}
-
-int ssl3_send_server_certificate(SSL *ssl) {
- if (ssl->state == SSL3_ST_SW_CERT_A) {
- if (!ssl3_output_cert_chain(ssl)) {
- return 0;
- }
- ssl->state = SSL3_ST_SW_CERT_B;
- }
-
- /* SSL3_ST_SW_CERT_B */
- return ssl_do_write(ssl);
-}
-
-/* send a new session ticket (not necessarily for a new session) */
-int ssl3_send_new_session_ticket(SSL *ssl) {
- int ret = -1;
- uint8_t *session = NULL;
- size_t session_len;
- EVP_CIPHER_CTX ctx;
- HMAC_CTX hctx;
-
- EVP_CIPHER_CTX_init(&ctx);
- HMAC_CTX_init(&hctx);
-
- if (ssl->state == SSL3_ST_SW_SESSION_TICKET_A) {
- uint8_t *p, *macstart;
- int len;
- unsigned int hlen;
- SSL_CTX *tctx = ssl->initial_ctx;
- uint8_t iv[EVP_MAX_IV_LENGTH];
- uint8_t key_name[16];
- /* The maximum overhead of encrypting the session is 16 (key name) + IV +
- * one block of encryption overhead + HMAC. */
- const size_t max_ticket_overhead =
- 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
-
- /* Serialize the SSL_SESSION to be encoded into the ticket. */
- if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &session,
- &session_len)) {
- goto err;
- }
-
- /* If the session is too long, emit a dummy value rather than abort the
- * connection. */
- if (session_len > 0xFFFF - max_ticket_overhead) {
- static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
- const size_t placeholder_len = strlen(kTicketPlaceholder);
-
- OPENSSL_free(session);
- session = NULL;
-
- p = ssl_handshake_start(ssl);
- /* Emit ticket_lifetime_hint. */
- l2n(0, p);
- /* Emit ticket. */
- s2n(placeholder_len, p);
- memcpy(p, kTicketPlaceholder, placeholder_len);
- p += placeholder_len;
-
- len = p - ssl_handshake_start(ssl);
- if (!ssl_set_handshake_header(ssl, SSL3_MT_NEWSESSION_TICKET, len)) {
- goto err;
- }
- ssl->state = SSL3_ST_SW_SESSION_TICKET_B;
- return ssl_do_write(ssl);
- }
-
- /* Grow buffer if need be: the length calculation is as follows:
- * handshake_header_length + 4 (ticket lifetime hint) + 2 (ticket length) +
- * max_ticket_overhead + * session_length */
- if (!BUF_MEM_grow(ssl->init_buf, SSL_HM_HEADER_LENGTH(ssl) + 6 +
- max_ticket_overhead + session_len)) {
- goto err;
- }
- p = ssl_handshake_start(ssl);
- /* Initialize HMAC and cipher contexts. If callback present it does all the
- * work otherwise use generated values from parent ctx. */
- if (tctx->tlsext_ticket_key_cb) {
- if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx,
- 1 /* encrypt */) < 0) {
- goto err;
- }
- } else {
- if (!RAND_bytes(iv, 16) ||
- !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
- tctx->tlsext_tick_aes_key, iv) ||
- !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(),
- NULL)) {
- goto err;
- }
- memcpy(key_name, tctx->tlsext_tick_key_name, 16);
- }
-
- /* Ticket lifetime hint (advisory only): We leave this unspecified for
- * resumed session (for simplicity), and guess that tickets for new
- * sessions will live as long as their sessions. */
- l2n(ssl->hit ? 0 : ssl->session->timeout, p);
-
- /* Skip ticket length for now */
- p += 2;
- /* Output key name */
- macstart = p;
- memcpy(p, key_name, 16);
- p += 16;
- /* output IV */
- memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
- p += EVP_CIPHER_CTX_iv_length(&ctx);
- /* Encrypt session data */
- if (!EVP_EncryptUpdate(&ctx, p, &len, session, session_len)) {
- goto err;
- }
- p += len;
- if (!EVP_EncryptFinal_ex(&ctx, p, &len)) {
- goto err;
- }
- p += len;
-
- if (!HMAC_Update(&hctx, macstart, p - macstart) ||
- !HMAC_Final(&hctx, p, &hlen)) {
- goto err;
- }
-
- p += hlen;
- /* Now write out lengths: p points to end of data written */
- /* Total length */
- len = p - ssl_handshake_start(ssl);
- /* Skip ticket lifetime hint */
- p = ssl_handshake_start(ssl) + 4;
- s2n(len - 6, p);
- if (!ssl_set_handshake_header(ssl, SSL3_MT_NEWSESSION_TICKET, len)) {
- goto err;
- }
- ssl->state = SSL3_ST_SW_SESSION_TICKET_B;
- }
-
- /* SSL3_ST_SW_SESSION_TICKET_B */
- ret = ssl_do_write(ssl);
-
-err:
- OPENSSL_free(session);
- EVP_CIPHER_CTX_cleanup(&ctx);
- HMAC_CTX_cleanup(&hctx);
- return ret;
-}
-
-/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
- * sets the next_proto member in s if found */
-int ssl3_get_next_proto(SSL *ssl) {
- int ok;
- long n;
- CBS next_protocol, selected_protocol, padding;
-
- /* Clients cannot send a NextProtocol message if we didn't see the extension
- * in their ClientHello */
- if (!ssl->s3->next_proto_neg_seen) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
- return -1;
- }
-
- n = ssl->method->ssl_get_message(ssl, SSL3_ST_SR_NEXT_PROTO_A,
- SSL3_ST_SR_NEXT_PROTO_B, SSL3_MT_NEXT_PROTO,
- 514, /* See the payload format below */
- ssl_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- CBS_init(&next_protocol, ssl->init_msg, n);
-
- /* The payload looks like:
- * uint8 proto_len;
- * uint8 proto[proto_len];
- * uint8 padding_len;
- * uint8 padding[padding_len]; */
- if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
- !CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
- CBS_len(&next_protocol) != 0 ||
- !CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated,
- &ssl->s3->next_proto_negotiated_len)) {
- return 0;
- }
-
- return 1;
-}
-
-/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
-int ssl3_get_channel_id(SSL *ssl) {
- int ret = -1, ok;
- long n;
- uint8_t channel_id_hash[EVP_MAX_MD_SIZE];
- size_t channel_id_hash_len;
- const uint8_t *p;
- uint16_t extension_type;
- EC_GROUP *p256 = NULL;
- EC_KEY *key = NULL;
- EC_POINT *point = NULL;
- ECDSA_SIG sig;
- BIGNUM x, y;
- CBS encrypted_extensions, extension;
-
- n = ssl->method->ssl_get_message(
- ssl, SSL3_ST_SR_CHANNEL_ID_A, SSL3_ST_SR_CHANNEL_ID_B,
- SSL3_MT_ENCRYPTED_EXTENSIONS, 2 + 2 + TLSEXT_CHANNEL_ID_SIZE,
- ssl_dont_hash_message, &ok);
-
- if (!ok) {
- return n;
- }
-
- /* Before incorporating the EncryptedExtensions message to the handshake
- * hash, compute the hash that should have been signed. */
- if (!tls1_channel_id_hash(ssl, channel_id_hash, &channel_id_hash_len)) {
- return -1;
- }
- assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);
-
- if (!ssl3_hash_current_message(ssl)) {
- return -1;
- }
-
- CBS_init(&encrypted_extensions, ssl->init_msg, n);
-
- /* EncryptedExtensions could include multiple extensions, but the only
- * extension that could be negotiated is ChannelID, so there can only be one
- * entry.
- *
- * The payload looks like:
- * uint16 extension_type
- * uint16 extension_len;
- * uint8 x[32];
- * uint8 y[32];
- * uint8 r[32];
- * uint8 s[32]; */
-
- if (!CBS_get_u16(&encrypted_extensions, &extension_type) ||
- !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) ||
- CBS_len(&encrypted_extensions) != 0 ||
- extension_type != TLSEXT_TYPE_channel_id ||
- CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_MESSAGE);
- return -1;
- }
-
- p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
- if (!p256) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
- return -1;
- }
-
- BN_init(&x);
- BN_init(&y);
- sig.r = BN_new();
- sig.s = BN_new();
- if (sig.r == NULL || sig.s == NULL) {
- goto err;
- }
-
- p = CBS_data(&extension);
- if (BN_bin2bn(p + 0, 32, &x) == NULL ||
- BN_bin2bn(p + 32, 32, &y) == NULL ||
- BN_bin2bn(p + 64, 32, sig.r) == NULL ||
- BN_bin2bn(p + 96, 32, sig.s) == NULL) {
- goto err;
- }
-
- point = EC_POINT_new(p256);
- if (!point ||
- !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) {
- goto err;
- }
-
- key = EC_KEY_new();
- if (!key || !EC_KEY_set_group(key, p256) ||
- !EC_KEY_set_public_key(key, point)) {
- goto err;
- }
-
- /* We stored the handshake hash in |tlsext_channel_id| the first time that we
- * were called. */
- if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
- ssl->s3->tlsext_channel_id_valid = 0;
- goto err;
- }
-
- memcpy(ssl->s3->tlsext_channel_id, p, 64);
- ret = 1;
-
-err:
- BN_free(&x);
- BN_free(&y);
- BN_free(sig.r);
- BN_free(sig.s);
- EC_KEY_free(key);
- EC_POINT_free(point);
- EC_GROUP_free(p256);
- return ret;
-}
diff --git a/ssl/ssl_aead_ctx.c b/ssl/ssl_aead_ctx.c
index ea44a6cb..e5bfe86a 100644
--- a/ssl/ssl_aead_ctx.c
+++ b/ssl/ssl_aead_ctx.c
@@ -92,7 +92,18 @@ SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) {
aead_ctx->variable_nonce_included_in_record = 1;
}
+
+ /* The TLS 1.3 construction XORs the fixed nonce into the sequence number
+ * and omits the additional data. */
+ if (version >= TLS1_3_VERSION) {
+ aead_ctx->xor_fixed_nonce = 1;
+ aead_ctx->variable_nonce_len = 8;
+ aead_ctx->variable_nonce_included_in_record = 0;
+ aead_ctx->omit_ad = 1;
+ assert(fixed_iv_len >= aead_ctx->variable_nonce_len);
+ }
} else {
+ assert(version < TLS1_3_VERSION);
aead_ctx->variable_nonce_included_in_record = 1;
aead_ctx->random_variable_nonce = 1;
aead_ctx->omit_length_in_ad = 1;
@@ -111,6 +122,10 @@ void SSL_AEAD_CTX_free(SSL_AEAD_CTX *aead) {
}
size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *aead) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+ aead = NULL;
+#endif
+
if (aead != NULL && aead->variable_nonce_included_in_record) {
return aead->variable_nonce_len;
}
@@ -118,11 +133,15 @@ size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *aead) {
}
size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *aead) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+ aead = NULL;
+#endif
+
if (aead == NULL) {
return 0;
}
return EVP_AEAD_max_overhead(aead->ctx.aead) +
- SSL_AEAD_CTX_explicit_nonce_len(aead);
+ SSL_AEAD_CTX_explicit_nonce_len(aead);
}
/* ssl_aead_ctx_get_ad writes the additional data for |aead| into |out| and
@@ -131,6 +150,10 @@ static size_t ssl_aead_ctx_get_ad(SSL_AEAD_CTX *aead, uint8_t out[13],
uint8_t type, uint16_t wire_version,
const uint8_t seqnum[8],
size_t plaintext_len) {
+ if (aead->omit_ad) {
+ return 0;
+ }
+
memcpy(out, seqnum, 8);
size_t len = 8;
out[len++] = type;
@@ -145,18 +168,16 @@ static size_t ssl_aead_ctx_get_ad(SSL_AEAD_CTX *aead, uint8_t out[13],
return len;
}
-int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
- size_t max_out, uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], const uint8_t *in,
- size_t in_len) {
+int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, CBS *out, uint8_t type,
+ uint16_t wire_version, const uint8_t seqnum[8],
+ uint8_t *in, size_t in_len) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+ aead = NULL;
+#endif
+
if (aead == NULL) {
/* Handle the initial NULL cipher. */
- if (in_len > max_out) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
- return 0;
- }
- memmove(out, in, in_len);
- *out_len = in_len;
+ CBS_init(out, in, in_len);
return 1;
}
@@ -214,14 +235,24 @@ int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
}
}
- return EVP_AEAD_CTX_open(&aead->ctx, out, out_len, max_out, nonce, nonce_len,
- in, in_len, ad, ad_len);
+ /* Decrypt in-place. */
+ size_t len;
+ if (!EVP_AEAD_CTX_open(&aead->ctx, in, &len, in_len, nonce, nonce_len,
+ in, in_len, ad, ad_len)) {
+ return 0;
+ }
+ CBS_init(out, in, len);
+ return 1;
}
int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
size_t max_out, uint8_t type, uint16_t wire_version,
const uint8_t seqnum[8], const uint8_t *in,
size_t in_len) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+ aead = NULL;
+#endif
+
if (aead == NULL) {
/* Handle the initial NULL cipher. */
if (in_len > max_out) {
diff --git a/ssl/ssl_buffer.c b/ssl/ssl_buffer.c
index 7fd74e48..a3cf360b 100644
--- a/ssl/ssl_buffer.c
+++ b/ssl/ssl_buffer.c
@@ -113,12 +113,11 @@ static int dtls_read_buffer_next_packet(SSL *ssl) {
}
/* Read a single packet from |ssl->rbio|. |buf->cap| must fit in an int. */
- ssl->rwstate = SSL_READING;
int ret = BIO_read(ssl->rbio, buf->buf + buf->offset, (int)buf->cap);
if (ret <= 0) {
+ ssl->rwstate = SSL_READING;
return ret;
}
- ssl->rwstate = SSL_NOTHING;
/* |BIO_read| was bound by |buf->cap|, so this cannot overflow. */
buf->len = (uint16_t)ret;
return 1;
@@ -136,13 +135,12 @@ static int tls_read_buffer_extend_to(SSL *ssl, size_t len) {
while (buf->len < len) {
/* The amount of data to read is bounded by |buf->cap|, which must fit in an
* int. */
- ssl->rwstate = SSL_READING;
int ret = BIO_read(ssl->rbio, buf->buf + buf->offset + buf->len,
(int)(len - buf->len));
if (ret <= 0) {
+ ssl->rwstate = SSL_READING;
return ret;
}
- ssl->rwstate = SSL_NOTHING;
/* |BIO_read| was bound by |buf->cap - buf->len|, so this cannot
* overflow. */
buf->len += (uint16_t)ret;
@@ -164,8 +162,6 @@ int ssl_read_buffer_extend_to(SSL *ssl, size_t len) {
return -1;
}
- ERR_clear_system_error();
-
int ret;
if (SSL_IS_DTLS(ssl)) {
/* |len| is ignored for a datagram transport. */
@@ -186,14 +182,13 @@ void ssl_read_buffer_consume(SSL *ssl, size_t len) {
SSL3_BUFFER *buf = &ssl->s3->read_buffer;
consume_buffer(buf, len);
- if (!SSL_IS_DTLS(ssl)) {
- /* The TLS stack never reads beyond the current record, so there will never
- * be unconsumed data. If read-ahead is ever reimplemented,
- * |ssl_read_buffer_discard| will require a |memcpy| to shift the excess
- * back to the front of the buffer, to ensure there is enough space for the
- * next record. */
- assert(buf->len == 0);
- }
+
+ /* The TLS stack never reads beyond the current record, so there will never be
+ * unconsumed data. If read-ahead is ever reimplemented,
+ * |ssl_read_buffer_discard| will require a |memcpy| to shift the excess back
+ * to the front of the buffer, to ensure there is enough space for the next
+ * record. */
+ assert(SSL_IS_DTLS(ssl) || len == 0 || buf->len == 0);
}
void ssl_read_buffer_discard(SSL *ssl) {
@@ -229,7 +224,7 @@ int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) {
return 0;
}
- size_t header_len = ssl_seal_prefix_len(ssl);
+ size_t header_len = ssl_seal_align_prefix_len(ssl);
/* TODO(davidben): This matches the original behavior in keeping the malloc
* size consistent. Does this matter? |cap| could just be |max_len|. */
@@ -268,12 +263,11 @@ static int tls_write_buffer_flush(SSL *ssl) {
SSL3_BUFFER *buf = &ssl->s3->write_buffer;
while (buf->len > 0) {
- ssl->rwstate = SSL_WRITING;
int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
if (ret <= 0) {
+ ssl->rwstate = SSL_WRITING;
return ret;
}
- ssl->rwstate = SSL_NOTHING;
consume_buffer(buf, (size_t)ret);
}
ssl_write_buffer_clear(ssl);
@@ -286,16 +280,15 @@ static int dtls_write_buffer_flush(SSL *ssl) {
return 1;
}
- ssl->rwstate = SSL_WRITING;
int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
if (ret <= 0) {
+ ssl->rwstate = SSL_WRITING;
/* If the write failed, drop the write buffer anyway. Datagram transports
* can't write half a packet, so the caller is expected to retry from the
* top. */
ssl_write_buffer_clear(ssl);
return ret;
}
- ssl->rwstate = SSL_NOTHING;
ssl_write_buffer_clear(ssl);
return 1;
}
@@ -305,7 +298,6 @@ int ssl_write_buffer_flush(SSL *ssl) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
return -1;
}
- ERR_clear_system_error();
if (SSL_IS_DTLS(ssl)) {
return dtls_write_buffer_flush(ssl);
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 983e1a7b..0eb0d8bf 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -185,9 +185,16 @@ CERT *ssl_cert_dup(CERT *cert) {
}
}
+ ret->key_method = cert->key_method;
+
ret->cert_cb = cert->cert_cb;
ret->cert_cb_arg = cert->cert_cb_arg;
+ if (cert->verify_store != NULL) {
+ X509_STORE_up_ref(cert->verify_store);
+ ret->verify_store = cert->verify_store;
+ }
+
return ret;
err:
@@ -220,6 +227,7 @@ void ssl_cert_free(CERT *c) {
ssl_cert_clear_certs(c);
OPENSSL_free(c->peer_sigalgs);
OPENSSL_free(c->digest_nids);
+ X509_STORE_free(c->verify_store);
OPENSSL_free(c);
}
@@ -279,10 +287,15 @@ int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain) {
return 0;
}
+ X509_STORE *verify_store = ssl->ctx->cert_store;
+ if (ssl->cert->verify_store != NULL) {
+ verify_store = ssl->cert->verify_store;
+ }
+
X509 *leaf = sk_X509_value(cert_chain, 0);
int ret = 0;
X509_STORE_CTX ctx;
- if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, leaf, cert_chain)) {
+ if (!X509_STORE_CTX_init(&ctx, verify_store, leaf, cert_chain)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
return 0;
}
@@ -409,13 +422,18 @@ static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) {
uint8_t *p;
n = i2d_X509(x, NULL);
- if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
+ if (n < 0 || !BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
return 0;
}
p = (uint8_t *)&(buf->data[*l]);
l2n3(n, p);
- i2d_X509(x, &p);
+ n = i2d_X509(x, &p);
+ if (n < 0) {
+ /* This shouldn't happen. */
+ OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
+ return 0;
+ }
*l += n + 3;
return 1;
@@ -475,6 +493,33 @@ int ssl_add_cert_chain(SSL *ssl, unsigned long *l) {
return 1;
}
+static int set_cert_store(X509_STORE **store_ptr, X509_STORE *new_store, int take_ref) {
+ X509_STORE_free(*store_ptr);
+ *store_ptr = new_store;
+
+ if (new_store != NULL && take_ref) {
+ X509_STORE_up_ref(new_store);
+ }
+
+ return 1;
+}
+
+int SSL_CTX_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+ return set_cert_store(&ctx->cert->verify_store, store, 0);
+}
+
+int SSL_CTX_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+ return set_cert_store(&ctx->cert->verify_store, store, 1);
+}
+
+int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store) {
+ return set_cert_store(&ssl->cert->verify_store, store, 0);
+}
+
+int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store) {
+ return set_cert_store(&ssl->cert->verify_store, store, 1);
+}
+
int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
return ssl_cert_set0_chain(ctx->cert, chain);
}
diff --git a/ssl/ssl_cipher.c b/ssl/ssl_cipher.c
index 4ff9f5c2..1aad8c48 100644
--- a/ssl/ssl_cipher.c
+++ b/ssl/ssl_cipher.c
@@ -141,7 +141,6 @@
#include <openssl/ssl.h>
#include <assert.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
@@ -376,6 +375,52 @@ static const SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_SHA384,
},
+ /* CECPQ1 (combined elliptic curve + post-quantum) suites. */
+
+ /* Cipher 16B7 */
+ {
+ TLS1_TXT_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ TLS1_CK_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ SSL_kCECPQ1,
+ SSL_aRSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ /* Cipher 16B8 */
+ {
+ TLS1_TXT_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ TLS1_CK_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ SSL_kCECPQ1,
+ SSL_aECDSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ /* Cipher 16B9 */
+ {
+ TLS1_TXT_CECPQ1_RSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_CECPQ1_RSA_WITH_AES_256_GCM_SHA384,
+ SSL_kCECPQ1,
+ SSL_aRSA,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA384,
+ },
+
+ /* Cipher 16BA */
+ {
+ TLS1_TXT_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384,
+ SSL_kCECPQ1,
+ SSL_aECDSA,
+ SSL_AES256GCM,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA384,
+ },
+
/* Cipher C007 */
{
TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
@@ -616,6 +661,29 @@ static const SSL_CIPHER kCiphers[] = {
SSL_AEAD,
SSL_HANDSHAKE_MAC_SHA256,
},
+
+ /* Cipher D001 */
+ {
+ TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+ SSL_kECDHE,
+ SSL_aPSK,
+ SSL_AES128GCM,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ /* Cipher D002 */
+ {
+ TLS1_TXT_ECDHE_PSK_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_ECDHE_PSK_WITH_AES_256_GCM_SHA384,
+ SSL_kECDHE,
+ SSL_aPSK,
+ SSL_AES256GCM,
+ SSL_SHA384,
+ SSL_HANDSHAKE_MAC_SHA384,
+ },
+
};
static const size_t kCiphersLen = sizeof(kCiphers) / sizeof(kCiphers[0]);
@@ -652,8 +720,9 @@ typedef struct cipher_alias_st {
} CIPHER_ALIAS;
static const CIPHER_ALIAS kCipherAliases[] = {
- /* "ALL" doesn't include eNULL (must be specifically enabled) */
- {"ALL", ~0u, ~0u, ~SSL_eNULL, ~0u, 0},
+ /* "ALL" doesn't include eNULL nor kCECPQ1. These must be explicitly
+ * enabled. */
+ {"ALL", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, 0},
/* The "COMPLEMENTOFDEFAULT" rule is omitted. It matches nothing. */
@@ -668,15 +737,16 @@ static const CIPHER_ALIAS kCipherAliases[] = {
{"DH", SSL_kDHE, ~0u, ~0u, ~0u, 0},
{"kECDHE", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
+ {"kCECPQ1", SSL_kCECPQ1, ~0u, ~0u, ~0u, 0},
{"kEECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
{"ECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
{"kPSK", SSL_kPSK, ~0u, ~0u, ~0u, 0},
/* server authentication aliases */
- {"aRSA", ~0u, SSL_aRSA, ~SSL_eNULL, ~0u, 0},
- {"aECDSA", ~0u, SSL_aECDSA, ~0u, ~0u, 0},
- {"ECDSA", ~0u, SSL_aECDSA, ~0u, ~0u, 0},
+ {"aRSA", ~SSL_kCECPQ1, SSL_aRSA, ~SSL_eNULL, ~0u, 0},
+ {"aECDSA", ~SSL_kCECPQ1, SSL_aECDSA, ~0u, ~0u, 0},
+ {"ECDSA", ~SSL_kCECPQ1, SSL_aECDSA, ~0u, ~0u, 0},
{"aPSK", ~0u, SSL_aPSK, ~0u, ~0u, 0},
/* aliases combining key exchange and server authentication */
@@ -691,29 +761,29 @@ static const CIPHER_ALIAS kCipherAliases[] = {
{"3DES", ~0u, ~0u, SSL_3DES, ~0u, 0},
{"RC4", ~0u, ~0u, SSL_RC4, ~0u, 0},
{"AES128", ~0u, ~0u, SSL_AES128 | SSL_AES128GCM, ~0u, 0},
- {"AES256", ~0u, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, 0},
- {"AES", ~0u, ~0u, SSL_AES, ~0u, 0},
- {"AESGCM", ~0u, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, 0},
- {"CHACHA20", ~0u, ~0u, SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD, ~0u,
+ {"AES256", ~SSL_kCECPQ1, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, 0},
+ {"AES", ~SSL_kCECPQ1, ~0u, SSL_AES, ~0u, 0},
+ {"AESGCM", ~SSL_kCECPQ1, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, 0},
+ {"CHACHA20", ~SSL_kCECPQ1, ~0u, SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD, ~0u,
0},
/* MAC aliases */
{"MD5", ~0u, ~0u, ~0u, SSL_MD5, 0},
{"SHA1", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0},
{"SHA", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0},
- {"SHA256", ~0u, ~0u, ~0u, SSL_SHA256, 0},
- {"SHA384", ~0u, ~0u, ~0u, SSL_SHA384, 0},
+ {"SHA256", ~SSL_kCECPQ1, ~0u, ~0u, SSL_SHA256, 0},
+ {"SHA384", ~SSL_kCECPQ1, ~0u, ~0u, SSL_SHA384, 0},
/* Legacy protocol minimum version aliases. "TLSv1" is intentionally the
* same as "SSLv3". */
- {"SSLv3", ~0u, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
- {"TLSv1", ~0u, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
- {"TLSv1.2", ~0u, ~0u, ~SSL_eNULL, ~0u, TLS1_2_VERSION},
+ {"SSLv3", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
+ {"TLSv1", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
+ {"TLSv1.2", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, TLS1_2_VERSION},
/* Legacy strength classes. */
{"MEDIUM", ~0u, ~0u, SSL_RC4, ~0u, 0},
- {"HIGH", ~0u, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
- {"FIPS", ~0u, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
+ {"HIGH", ~SSL_kCECPQ1, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
+ {"FIPS", ~SSL_kCECPQ1, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
};
static const size_t kCipherAliasesLen =
@@ -756,24 +826,24 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
case SSL_AES128GCM:
*out_aead = EVP_aead_aes_128_gcm();
*out_fixed_iv_len = 4;
- return 1;
+ break;
case SSL_AES256GCM:
*out_aead = EVP_aead_aes_256_gcm();
*out_fixed_iv_len = 4;
- return 1;
+ break;
#if !defined(BORINGSSL_ANDROID_SYSTEM)
case SSL_CHACHA20POLY1305_OLD:
*out_aead = EVP_aead_chacha20_poly1305_old();
*out_fixed_iv_len = 0;
- return 1;
+ break;
#endif
case SSL_CHACHA20POLY1305:
*out_aead = EVP_aead_chacha20_poly1305();
*out_fixed_iv_len = 12;
- return 1;
+ break;
case SSL_RC4:
switch (cipher->algorithm_mac) {
@@ -784,7 +854,7 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
*out_aead = EVP_aead_rc4_md5_tls();
}
*out_mac_secret_len = MD5_DIGEST_LENGTH;
- return 1;
+ break;
case SSL_SHA1:
if (version == SSL3_VERSION) {
*out_aead = EVP_aead_rc4_sha1_ssl3();
@@ -792,10 +862,11 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
*out_aead = EVP_aead_rc4_sha1_tls();
}
*out_mac_secret_len = SHA_DIGEST_LENGTH;
- return 1;
+ break;
default:
return 0;
}
+ break;
case SSL_AES128:
switch (cipher->algorithm_mac) {
@@ -810,14 +881,15 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
*out_aead = EVP_aead_aes_128_cbc_sha1_tls();
}
*out_mac_secret_len = SHA_DIGEST_LENGTH;
- return 1;
+ break;
case SSL_SHA256:
*out_aead = EVP_aead_aes_128_cbc_sha256_tls();
*out_mac_secret_len = SHA256_DIGEST_LENGTH;
- return 1;
+ break;
default:
return 0;
}
+ break;
case SSL_AES256:
switch (cipher->algorithm_mac) {
@@ -832,18 +904,19 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
*out_aead = EVP_aead_aes_256_cbc_sha1_tls();
}
*out_mac_secret_len = SHA_DIGEST_LENGTH;
- return 1;
+ break;
case SSL_SHA256:
*out_aead = EVP_aead_aes_256_cbc_sha256_tls();
*out_mac_secret_len = SHA256_DIGEST_LENGTH;
- return 1;
+ break;
case SSL_SHA384:
*out_aead = EVP_aead_aes_256_cbc_sha384_tls();
*out_mac_secret_len = SHA384_DIGEST_LENGTH;
- return 1;
+ break;
default:
return 0;
}
+ break;
case SSL_3DES:
switch (cipher->algorithm_mac) {
@@ -858,10 +931,11 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
*out_aead = EVP_aead_des_ede3_cbc_sha1_tls();
}
*out_mac_secret_len = SHA_DIGEST_LENGTH;
- return 1;
+ break;
default:
return 0;
}
+ break;
case SSL_eNULL:
switch (cipher->algorithm_mac) {
@@ -872,14 +946,25 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
*out_aead = EVP_aead_null_sha1_tls();
}
*out_mac_secret_len = SHA_DIGEST_LENGTH;
- return 1;
+ break;
default:
return 0;
}
+ break;
default:
return 0;
}
+
+ /* In TLS 1.3, the iv_len is equal to the AEAD nonce length whereas the code
+ * above computes the TLS 1.2 construction.
+ *
+ * TODO(davidben,svaldez): Avoid computing the wrong value and fixing it. */
+ if (version >= TLS1_3_VERSION) {
+ *out_fixed_iv_len = EVP_AEAD_nonce_length(*out_aead);
+ assert(*out_fixed_iv_len >= 8);
+ }
+ return 1;
}
const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf) {
@@ -1405,6 +1490,7 @@ ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
/* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other
* key exchange mechanisms */
+
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, ~0u, ~0u, 0, CIPHER_ADD, -1,
0, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, 0,
@@ -1417,10 +1503,10 @@ ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
* AES_GCM. Of the two CHACHA20 variants, the new one is preferred over the
* old one. */
if (EVP_has_aes_hardware()) {
- ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
- &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1, 0,
&head, &tail);
+ ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD,
-1, 0, &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0,
@@ -1430,24 +1516,24 @@ ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
-1, 0, &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0,
CIPHER_ADD, -1, 0, &head, &tail);
- ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
- &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1, 0,
&head, &tail);
+ ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
}
- /* Then the legacy non-AEAD ciphers: AES_256_CBC, AES-128_CBC, RC4_128_SHA,
- * RC4_128_MD5, 3DES_EDE_CBC_SHA. */
- ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256, ~0u, 0, CIPHER_ADD, -1, 0,
- &head, &tail);
+ /* Then the legacy non-AEAD ciphers: AES_128_CBC, AES_256_CBC,
+ * 3DES_EDE_CBC_SHA, RC4_128_SHA, RC4_128_MD5. */
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128, ~0u, 0, CIPHER_ADD, -1, 0,
&head, &tail);
+ ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256, ~0u, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_3DES, ~0u, 0, CIPHER_ADD, -1, 0, &head,
+ &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_RC4, ~SSL_MD5, 0, CIPHER_ADD, -1, 0,
&head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_RC4, SSL_MD5, 0, CIPHER_ADD, -1, 0,
&head, &tail);
- ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_3DES, ~0u, 0, CIPHER_ADD, -1, 0, &head,
- &tail);
/* Temporarily enable everything else for sorting */
ssl_cipher_apply_rule(0, ~0u, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, 0, &head,
@@ -1577,6 +1663,10 @@ int SSL_CIPHER_has_SHA1_HMAC(const SSL_CIPHER *cipher) {
return (cipher->algorithm_mac & SSL_SHA1) != 0;
}
+int SSL_CIPHER_has_SHA256_HMAC(const SSL_CIPHER *cipher) {
+ return (cipher->algorithm_mac & SSL_SHA256) != 0;
+}
+
int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher) {
return (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) != 0;
}
@@ -1616,10 +1706,18 @@ int SSL_CIPHER_is_ECDSA(const SSL_CIPHER *cipher) {
return (cipher->algorithm_auth & SSL_aECDSA) != 0;
}
+int SSL_CIPHER_is_DHE(const SSL_CIPHER *cipher) {
+ return (cipher->algorithm_mkey & SSL_kDHE) != 0;
+}
+
int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher) {
return (cipher->algorithm_mkey & SSL_kECDHE) != 0;
}
+int SSL_CIPHER_is_CECPQ1(const SSL_CIPHER *cipher) {
+ return (cipher->algorithm_mkey & SSL_kCECPQ1) != 0;
+}
+
uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher) {
if (cipher->algorithm_prf != SSL_HANDSHAKE_MAC_DEFAULT) {
/* Cipher suites before TLS 1.2 use the default PRF, while all those added
@@ -1669,6 +1767,17 @@ const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) {
return "UNKNOWN";
}
+ case SSL_kCECPQ1:
+ switch (cipher->algorithm_auth) {
+ case SSL_aECDSA:
+ return "CECPQ1_ECDSA";
+ case SSL_aRSA:
+ return "CECPQ1_RSA";
+ default:
+ assert(0);
+ return "UNKNOWN";
+ }
+
case SSL_kPSK:
assert(cipher->algorithm_auth == SSL_aPSK);
return "PSK";
@@ -1823,6 +1932,10 @@ const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf,
kx = "ECDH";
break;
+ case SSL_kCECPQ1:
+ kx = "CECPQ1";
+ break;
+
case SSL_kPSK:
kx = "PSK";
break;
@@ -1954,20 +2067,15 @@ int ssl_cipher_get_key_type(const SSL_CIPHER *cipher) {
return EVP_PKEY_NONE;
}
-int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher) {
- /* PSK-authenticated ciphers do not use a certificate. (RSA_PSK is not
- * supported.) */
- if (cipher->algorithm_auth & SSL_aPSK) {
- return 0;
- }
-
- /* All other ciphers include it. */
- return 1;
+int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) {
+ return (cipher->algorithm_auth & SSL_aCERT) != 0;
}
int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
/* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
- if (cipher->algorithm_mkey & SSL_kDHE || cipher->algorithm_mkey & SSL_kECDHE) {
+ if (cipher->algorithm_mkey & SSL_kDHE ||
+ cipher->algorithm_mkey & SSL_kECDHE ||
+ cipher->algorithm_mkey & SSL_kCECPQ1) {
return 1;
}
diff --git a/ssl/ssl_ecdh.c b/ssl/ssl_ecdh.c
index 700d9471..1236cd39 100644
--- a/ssl/ssl_ecdh.c
+++ b/ssl/ssl_ecdh.c
@@ -23,7 +23,8 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/newhope.h>
+#include <openssl/nid.h>
#include "internal.h"
@@ -35,7 +36,7 @@ static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) {
BN_clear_free(private_key);
}
-static int ssl_ec_point_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
+static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
assert(ctx->data == NULL);
BIGNUM *private_key = BN_new();
if (private_key == NULL) {
@@ -84,9 +85,9 @@ err:
return ret;
}
-int ssl_ec_point_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) {
+static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) {
BIGNUM *private_key = (BIGNUM *)ctx->data;
assert(private_key != NULL);
*out_alert = SSL_AD_INTERNAL_ERROR;
@@ -147,6 +148,18 @@ err:
return ret;
}
+static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+ uint8_t **out_secret, size_t *out_secret_len,
+ uint8_t *out_alert, const uint8_t *peer_key,
+ size_t peer_key_len) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ if (!ssl_ec_point_offer(ctx, out_public_key) ||
+ !ssl_ec_point_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
+ peer_key_len)) {
+ return 0;
+ }
+ return 1;
+}
/* X25119 implementation. */
@@ -158,7 +171,7 @@ static void ssl_x25519_cleanup(SSL_ECDH_CTX *ctx) {
OPENSSL_free(ctx->data);
}
-static int ssl_x25519_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
+static int ssl_x25519_offer(SSL_ECDH_CTX *ctx, CBB *out) {
assert(ctx->data == NULL);
ctx->data = OPENSSL_malloc(32);
@@ -171,10 +184,9 @@ static int ssl_x25519_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
return CBB_add_bytes(out, public_key, sizeof(public_key));
}
-static int ssl_x25519_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key,
- size_t peer_key_len) {
+static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) {
assert(ctx->data != NULL);
*out_alert = SSL_AD_INTERNAL_ERROR;
@@ -196,6 +208,166 @@ static int ssl_x25519_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
return 1;
}
+static int ssl_x25519_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+ uint8_t **out_secret, size_t *out_secret_len,
+ uint8_t *out_alert, const uint8_t *peer_key,
+ size_t peer_key_len) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ if (!ssl_x25519_offer(ctx, out_public_key) ||
+ !ssl_x25519_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
+ peer_key_len)) {
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Combined X25119 + New Hope (post-quantum) implementation. */
+
+typedef struct {
+ uint8_t x25519_key[32];
+ NEWHOPE_POLY *newhope_sk;
+} cecpq1_data;
+
+#define CECPQ1_OFFERMSG_LENGTH (32 + NEWHOPE_OFFERMSG_LENGTH)
+#define CECPQ1_ACCEPTMSG_LENGTH (32 + NEWHOPE_ACCEPTMSG_LENGTH)
+#define CECPQ1_SECRET_LENGTH (32 + SHA256_DIGEST_LENGTH)
+
+static void ssl_cecpq1_cleanup(SSL_ECDH_CTX *ctx) {
+ if (ctx->data == NULL) {
+ return;
+ }
+ cecpq1_data *data = ctx->data;
+ NEWHOPE_POLY_free(data->newhope_sk);
+ OPENSSL_cleanse(data, sizeof(cecpq1_data));
+ OPENSSL_free(data);
+}
+
+static int ssl_cecpq1_offer(SSL_ECDH_CTX *ctx, CBB *out) {
+ assert(ctx->data == NULL);
+ cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data));
+ if (data == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ctx->data = data;
+ data->newhope_sk = NEWHOPE_POLY_new();
+ if (data->newhope_sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ uint8_t x25519_public_key[32];
+ X25519_keypair(x25519_public_key, data->x25519_key);
+
+ uint8_t newhope_offermsg[NEWHOPE_OFFERMSG_LENGTH];
+ NEWHOPE_offer(newhope_offermsg, data->newhope_sk);
+
+ if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
+ !CBB_add_bytes(out, newhope_offermsg, sizeof(newhope_offermsg))) {
+ return 0;
+ }
+ return 1;
+}
+
+static int ssl_cecpq1_accept(SSL_ECDH_CTX *ctx, CBB *cbb, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) {
+ if (peer_key_len != CECPQ1_OFFERMSG_LENGTH) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+
+ assert(ctx->data == NULL);
+ cecpq1_data *data = OPENSSL_malloc(sizeof(cecpq1_data));
+ if (data == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ data->newhope_sk = NULL;
+ ctx->data = data;
+
+ uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH);
+ if (secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* Generate message to server, and secret key, at once. */
+
+ uint8_t x25519_public_key[32];
+ X25519_keypair(x25519_public_key, data->x25519_key);
+ if (!X25519(secret, data->x25519_key, peer_key)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
+ goto err;
+ }
+
+ uint8_t newhope_acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH];
+ if (!NEWHOPE_accept(secret + 32, newhope_acceptmsg, peer_key + 32,
+ NEWHOPE_OFFERMSG_LENGTH)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ goto err;
+ }
+
+ if (!CBB_add_bytes(cbb, x25519_public_key, sizeof(x25519_public_key)) ||
+ !CBB_add_bytes(cbb, newhope_acceptmsg, sizeof(newhope_acceptmsg))) {
+ goto err;
+ }
+
+ *out_secret = secret;
+ *out_secret_len = CECPQ1_SECRET_LENGTH;
+ return 1;
+
+ err:
+ OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH);
+ OPENSSL_free(secret);
+ return 0;
+}
+
+static int ssl_cecpq1_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) {
+ if (peer_key_len != CECPQ1_ACCEPTMSG_LENGTH) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+
+ assert(ctx->data != NULL);
+ cecpq1_data *data = ctx->data;
+
+ uint8_t *secret = OPENSSL_malloc(CECPQ1_SECRET_LENGTH);
+ if (secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!X25519(secret, data->x25519_key, peer_key)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
+ goto err;
+ }
+
+ if (!NEWHOPE_finish(secret + 32, data->newhope_sk, peer_key + 32,
+ NEWHOPE_ACCEPTMSG_LENGTH)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ goto err;
+ }
+
+ *out_secret = secret;
+ *out_secret_len = CECPQ1_SECRET_LENGTH;
+ return 1;
+
+ err:
+ OPENSSL_cleanse(secret, CECPQ1_SECRET_LENGTH);
+ OPENSSL_free(secret);
+ return 0;
+}
+
/* Legacy DHE-based implementation. */
@@ -203,7 +375,7 @@ static void ssl_dhe_cleanup(SSL_ECDH_CTX *ctx) {
DH_free((DH *)ctx->data);
}
-static int ssl_dhe_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
+static int ssl_dhe_offer(SSL_ECDH_CTX *ctx, CBB *out) {
DH *dh = (DH *)ctx->data;
/* The group must have been initialized already, but not the key. */
assert(dh != NULL);
@@ -215,10 +387,9 @@ static int ssl_dhe_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
BN_bn2cbb_padded(out, BN_num_bytes(dh->p), dh->pub_key);
}
-static int ssl_dhe_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key,
- size_t peer_key_len) {
+static int ssl_dhe_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) {
DH *dh = (DH *)ctx->data;
assert(dh != NULL);
assert(dh->priv_key != NULL);
@@ -254,53 +425,91 @@ err:
return 0;
}
+static int ssl_dhe_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+ uint8_t **out_secret, size_t *out_secret_len,
+ uint8_t *out_alert, const uint8_t *peer_key,
+ size_t peer_key_len) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ if (!ssl_dhe_offer(ctx, out_public_key) ||
+ !ssl_dhe_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
+ peer_key_len)) {
+ return 0;
+ }
+ return 1;
+}
+
static const SSL_ECDH_METHOD kDHEMethod = {
NID_undef, 0, "",
ssl_dhe_cleanup,
- ssl_dhe_generate_keypair,
- ssl_dhe_compute_secret,
+ ssl_dhe_offer,
+ ssl_dhe_accept,
+ ssl_dhe_finish,
+ CBS_get_u16_length_prefixed,
+ CBB_add_u16_length_prefixed,
};
-
static const SSL_ECDH_METHOD kMethods[] = {
{
NID_X9_62_prime256v1,
- SSL_CURVE_SECP256R1,
+ SSL_GROUP_SECP256R1,
"P-256",
ssl_ec_point_cleanup,
- ssl_ec_point_generate_keypair,
- ssl_ec_point_compute_secret,
+ ssl_ec_point_offer,
+ ssl_ec_point_accept,
+ ssl_ec_point_finish,
+ CBS_get_u8_length_prefixed,
+ CBB_add_u8_length_prefixed,
},
{
NID_secp384r1,
- SSL_CURVE_SECP384R1,
+ SSL_GROUP_SECP384R1,
"P-384",
ssl_ec_point_cleanup,
- ssl_ec_point_generate_keypair,
- ssl_ec_point_compute_secret,
+ ssl_ec_point_offer,
+ ssl_ec_point_accept,
+ ssl_ec_point_finish,
+ CBS_get_u8_length_prefixed,
+ CBB_add_u8_length_prefixed,
},
{
NID_secp521r1,
- SSL_CURVE_SECP521R1,
+ SSL_GROUP_SECP521R1,
"P-521",
ssl_ec_point_cleanup,
- ssl_ec_point_generate_keypair,
- ssl_ec_point_compute_secret,
+ ssl_ec_point_offer,
+ ssl_ec_point_accept,
+ ssl_ec_point_finish,
+ CBS_get_u8_length_prefixed,
+ CBB_add_u8_length_prefixed,
},
{
- NID_x25519,
- SSL_CURVE_X25519,
+ NID_X25519,
+ SSL_GROUP_X25519,
"X25519",
ssl_x25519_cleanup,
- ssl_x25519_generate_keypair,
- ssl_x25519_compute_secret,
+ ssl_x25519_offer,
+ ssl_x25519_accept,
+ ssl_x25519_finish,
+ CBS_get_u8_length_prefixed,
+ CBB_add_u8_length_prefixed,
+ },
+ {
+ NID_cecpq1,
+ SSL_GROUP_CECPQ1,
+ "CECPQ1",
+ ssl_cecpq1_cleanup,
+ ssl_cecpq1_offer,
+ ssl_cecpq1_accept,
+ ssl_cecpq1_finish,
+ CBS_get_u16_length_prefixed,
+ CBB_add_u16_length_prefixed,
},
};
-static const SSL_ECDH_METHOD *method_from_curve_id(uint16_t curve_id) {
+static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) {
size_t i;
for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
- if (kMethods[i].curve_id == curve_id) {
+ if (kMethods[i].group_id == group_id) {
return &kMethods[i];
}
}
@@ -317,27 +526,27 @@ static const SSL_ECDH_METHOD *method_from_nid(int nid) {
return NULL;
}
-const char* SSL_get_curve_name(uint16_t curve_id) {
- const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
+const char* SSL_get_curve_name(uint16_t group_id) {
+ const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
if (method == NULL) {
return NULL;
}
return method->name;
}
-int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid) {
+int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
const SSL_ECDH_METHOD *method = method_from_nid(nid);
if (method == NULL) {
return 0;
}
- *out_curve_id = method->curve_id;
+ *out_group_id = method->group_id;
return 1;
}
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id) {
+int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id) {
SSL_ECDH_CTX_cleanup(ctx);
- const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
+ const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
if (method == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
return 0;
@@ -353,6 +562,20 @@ void SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX *ctx, DH *params) {
ctx->data = params;
}
+int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out) {
+ if (ctx->method == NULL) {
+ return 0;
+ }
+ return ctx->method->get_key(cbs, out);
+}
+
+int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents) {
+ if (ctx->method == NULL) {
+ return 0;
+ }
+ return ctx->method->add_key(cbb, out_contents);
+}
+
void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
if (ctx->method == NULL) {
return;
@@ -362,13 +585,21 @@ void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
ctx->data = NULL;
}
-int SSL_ECDH_CTX_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
- return ctx->method->generate_keypair(ctx, out_public_key);
+int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
+ return ctx->method->offer(ctx, out_public_key);
+}
+
+int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+ uint8_t **out_secret, size_t *out_secret_len,
+ uint8_t *out_alert, const uint8_t *peer_key,
+ size_t peer_key_len) {
+ return ctx->method->accept(ctx, out_public_key, out_secret, out_secret_len,
+ out_alert, peer_key, peer_key_len);
}
-int SSL_ECDH_CTX_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) {
- return ctx->method->compute_secret(ctx, out_secret, out_secret_len, out_alert,
- peer_key, peer_key_len);
+int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) {
+ return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert,
+ peer_key, peer_key_len);
}
diff --git a/ssl/ssl_file.c b/ssl/ssl_file.c
index 42cf800c..748d50ca 100644
--- a/ssl/ssl_file.c
+++ b/ssl/ssl_file.c
@@ -121,7 +121,6 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
-#include "../crypto/directory.h"
#include "internal.h"
@@ -247,53 +246,6 @@ int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
return ret;
}
-/* Add a directory of certs to a stack.
- *
- * \param stack the stack to append to.
- * \param dir the directory to append from. All files in this directory will be
- * examined as potential certs. Any that are acceptable to
- * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will
- * be included.
- * \return 1 for success, 0 for failure. Note that in the case of failure some
- * certs may have been added to \c stack. */
-int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
- const char *dir) {
- OPENSSL_DIR_CTX *d = NULL;
- const char *filename;
- int ret = 0;
-
- /* Note that a side effect is that the CAs will be sorted by name */
- while ((filename = OPENSSL_DIR_read(&d, dir))) {
- char buf[1024];
- int r;
-
- if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PATH_TOO_LONG);
- goto err;
- }
-
- r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename);
- if (r <= 0 || r >= (int)sizeof(buf) ||
- !SSL_add_file_cert_subjects_to_stack(stack, buf)) {
- goto err;
- }
- }
-
- if (errno) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
- ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
- goto err;
- }
-
- ret = 1;
-
-err:
- if (d) {
- OPENSSL_DIR_end(&d);
- }
- return ret;
-}
-
int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
int reason_code;
BIO *in;
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index b7260117..0d956950 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -141,7 +141,6 @@
#include <openssl/ssl.h>
#include <assert.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/bytestring.h>
@@ -150,7 +149,6 @@
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <openssl/rand.h>
#include <openssl/x509v3.h>
@@ -299,6 +297,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
if (method->version != 0) {
SSL_CTX_set_max_version(ret, method->version);
SSL_CTX_set_min_version(ret, method->version);
+ } else if (!method->method->is_dtls) {
+ /* TODO(svaldez): Enable TLS 1.3 once implemented. */
+ SSL_CTX_set_max_version(ret, TLS1_2_VERSION);
}
return ret;
@@ -343,7 +344,7 @@ void SSL_CTX_free(SSL_CTX *ctx) {
sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free);
sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles);
OPENSSL_free(ctx->psk_identity_hint);
- OPENSSL_free(ctx->tlsext_ellipticcurvelist);
+ OPENSSL_free(ctx->supported_group_list);
OPENSSL_free(ctx->alpn_client_proto_list);
OPENSSL_free(ctx->ocsp_response);
OPENSSL_free(ctx->signed_cert_timestamp_list);
@@ -371,6 +372,10 @@ SSL *SSL_new(SSL_CTX *ctx) {
ssl->min_version = ctx->min_version;
ssl->max_version = ctx->max_version;
+ /* RFC 6347 states that implementations SHOULD use an initial timer value of
+ * 1 second. */
+ ssl->initial_timeout_duration_ms = 1000;
+
ssl->options = ctx->options;
ssl->mode = ctx->mode;
ssl->max_cert_list = ctx->max_cert_list;
@@ -401,14 +406,14 @@ SSL *SSL_new(SSL_CTX *ctx) {
CRYPTO_refcount_inc(&ctx->references);
ssl->initial_ctx = ctx;
- if (ctx->tlsext_ellipticcurvelist) {
- ssl->tlsext_ellipticcurvelist =
- BUF_memdup(ctx->tlsext_ellipticcurvelist,
- ctx->tlsext_ellipticcurvelist_length * 2);
- if (!ssl->tlsext_ellipticcurvelist) {
+ if (ctx->supported_group_list) {
+ ssl->supported_group_list =
+ BUF_memdup(ctx->supported_group_list,
+ ctx->supported_group_list_len * 2);
+ if (!ssl->supported_group_list) {
goto err;
}
- ssl->tlsext_ellipticcurvelist_length = ctx->tlsext_ellipticcurvelist_length;
+ ssl->supported_group_list_len = ctx->supported_group_list_len;
}
if (ssl->ctx->alpn_client_proto_list) {
@@ -469,20 +474,11 @@ void SSL_free(SSL *ssl) {
CRYPTO_free_ex_data(&g_ex_data_class_ssl, ssl, &ssl->ex_data);
- if (ssl->bbio != NULL) {
- /* If the buffering BIO is in place, pop it off */
- if (ssl->bbio == ssl->wbio) {
- ssl->wbio = BIO_pop(ssl->wbio);
- }
- BIO_free(ssl->bbio);
- ssl->bbio = NULL;
- }
+ ssl_free_wbio_buffer(ssl);
+ assert(ssl->bbio == NULL);
- int free_wbio = ssl->wbio != ssl->rbio;
BIO_free_all(ssl->rbio);
- if (free_wbio) {
- BIO_free_all(ssl->wbio);
- }
+ BIO_free_all(ssl->wbio);
BUF_MEM_free(ssl->init_buf);
@@ -497,7 +493,7 @@ void SSL_free(SSL *ssl) {
OPENSSL_free(ssl->tlsext_hostname);
SSL_CTX_free(ssl->initial_ctx);
- OPENSSL_free(ssl->tlsext_ellipticcurvelist);
+ OPENSSL_free(ssl->supported_group_list);
OPENSSL_free(ssl->alpn_client_proto_list);
EVP_PKEY_free(ssl->tlsext_channel_id_private);
OPENSSL_free(ssl->psk_identity_hint);
@@ -514,42 +510,78 @@ void SSL_free(SSL *ssl) {
void SSL_set_connect_state(SSL *ssl) {
ssl->server = 0;
- ssl->shutdown = 0;
ssl->state = SSL_ST_CONNECT;
- ssl->handshake_func = ssl->method->ssl_connect;
+ ssl->handshake_func = ssl3_connect;
}
void SSL_set_accept_state(SSL *ssl) {
ssl->server = 1;
- ssl->shutdown = 0;
ssl->state = SSL_ST_ACCEPT;
- ssl->handshake_func = ssl->method->ssl_accept;
+ ssl->handshake_func = ssl3_accept;
}
-void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio) {
+static void ssl_set_rbio(SSL *ssl, BIO *rbio) {
+ BIO_free_all(ssl->rbio);
+ ssl->rbio = rbio;
+}
+
+static void ssl_set_wbio(SSL *ssl, BIO *wbio) {
/* If the output buffering BIO is still in place, remove it. */
if (ssl->bbio != NULL) {
- if (ssl->wbio == ssl->bbio) {
- ssl->wbio = ssl->wbio->next_bio;
- ssl->bbio->next_bio = NULL;
- }
+ ssl->wbio = BIO_pop(ssl->wbio);
+ }
+
+ BIO_free_all(ssl->wbio);
+ ssl->wbio = wbio;
+
+ /* Re-attach |bbio| to the new |wbio|. */
+ if (ssl->bbio != NULL) {
+ ssl->wbio = BIO_push(ssl->bbio, ssl->wbio);
}
+}
+
+void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio) {
+ /* For historical reasons, this function has many different cases in ownership
+ * handling. */
- if (ssl->rbio != rbio) {
- BIO_free_all(ssl->rbio);
+ /* If the two arguments are equal, one fewer reference is granted than
+ * taken. */
+ if (rbio != NULL && rbio == wbio) {
+ BIO_up_ref(rbio);
}
- if (ssl->wbio != wbio && ssl->rbio != ssl->wbio) {
- BIO_free_all(ssl->wbio);
+
+ /* If at most one of rbio or wbio is changed, only adopt one reference. */
+ if (rbio == SSL_get_rbio(ssl)) {
+ ssl_set_wbio(ssl, wbio);
+ return;
}
- ssl->rbio = rbio;
- ssl->wbio = wbio;
+ if (wbio == SSL_get_wbio(ssl)) {
+ ssl_set_rbio(ssl, rbio);
+ return;
+ }
+
+ /* Otherwise, adopt both references. */
+ ssl_set_rbio(ssl, rbio);
+ ssl_set_wbio(ssl, wbio);
}
BIO *SSL_get_rbio(const SSL *ssl) { return ssl->rbio; }
-BIO *SSL_get_wbio(const SSL *ssl) { return ssl->wbio; }
+BIO *SSL_get_wbio(const SSL *ssl) {
+ if (ssl->bbio != NULL) {
+ /* If |bbio| is active, the true caller-configured BIO is its |next_bio|. */
+ assert(ssl->bbio == ssl->wbio);
+ return ssl->bbio->next_bio;
+ }
+ return ssl->wbio;
+}
int SSL_do_handshake(SSL *ssl) {
+ ssl->rwstate = SSL_NOTHING;
+ /* Functions which use SSL_get_error must clear the error queue on entry. */
+ ERR_clear_error();
+ ERR_clear_system_error();
+
if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_TYPE_NOT_SET);
return -1;
@@ -563,131 +595,138 @@ int SSL_do_handshake(SSL *ssl) {
}
int SSL_connect(SSL *ssl) {
- if (ssl->handshake_func == 0) {
+ if (ssl->handshake_func == NULL) {
/* Not properly initialized yet */
SSL_set_connect_state(ssl);
}
- if (ssl->handshake_func != ssl->method->ssl_connect) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
- return ssl->handshake_func(ssl);
+ return SSL_do_handshake(ssl);
}
int SSL_accept(SSL *ssl) {
- if (ssl->handshake_func == 0) {
+ if (ssl->handshake_func == NULL) {
/* Not properly initialized yet */
SSL_set_accept_state(ssl);
}
- if (ssl->handshake_func != ssl->method->ssl_accept) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
- return ssl->handshake_func(ssl);
+ return SSL_do_handshake(ssl);
}
-int SSL_read(SSL *ssl, void *buf, int num) {
- if (ssl->handshake_func == 0) {
+static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) {
+ ssl->rwstate = SSL_NOTHING;
+ /* Functions which use SSL_get_error must clear the error queue on entry. */
+ ERR_clear_error();
+ ERR_clear_system_error();
+
+ if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
return -1;
}
- if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
- ssl->rwstate = SSL_NOTHING;
- return 0;
+ /* This may require multiple iterations. False Start will cause
+ * |ssl->handshake_func| to signal success one step early, but the handshake
+ * must be completely finished before other modes are accepted. */
+ while (SSL_in_init(ssl)) {
+ int ret = SSL_do_handshake(ssl);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
}
- ERR_clear_system_error();
- return ssl->method->ssl_read_app_data(ssl, buf, num, 0);
+ return ssl->method->ssl_read_app_data(ssl, buf, num, peek);
}
-int SSL_peek(SSL *ssl, void *buf, int num) {
- if (ssl->handshake_func == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
- return -1;
- }
-
- if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
- return 0;
- }
+int SSL_read(SSL *ssl, void *buf, int num) {
+ return ssl_read_impl(ssl, buf, num, 0 /* consume bytes */);
+}
- ERR_clear_system_error();
- return ssl->method->ssl_read_app_data(ssl, buf, num, 1);
+int SSL_peek(SSL *ssl, void *buf, int num) {
+ return ssl_read_impl(ssl, buf, num, 1 /* peek */);
}
int SSL_write(SSL *ssl, const void *buf, int num) {
- if (ssl->handshake_func == 0) {
+ ssl->rwstate = SSL_NOTHING;
+ /* Functions which use SSL_get_error must clear the error queue on entry. */
+ ERR_clear_error();
+ ERR_clear_system_error();
+
+ if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
return -1;
}
- if (ssl->shutdown & SSL_SENT_SHUTDOWN) {
- ssl->rwstate = SSL_NOTHING;
+ if (ssl->s3->send_shutdown != ssl_shutdown_none) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
return -1;
}
- ERR_clear_system_error();
+ /* If necessary, complete the handshake implicitly. */
+ if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) {
+ int ret = SSL_do_handshake(ssl);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
return ssl->method->ssl_write_app_data(ssl, buf, num);
}
int SSL_shutdown(SSL *ssl) {
- /* Note that this function behaves differently from what one might expect.
- * Return values are 0 for no success (yet), 1 for success; but calling it
- * once is usually not enough, even if blocking I/O is used (see
- * ssl3_shutdown). */
+ ssl->rwstate = SSL_NOTHING;
+ /* Functions which use SSL_get_error must clear the error queue on entry. */
+ ERR_clear_error();
+ ERR_clear_system_error();
- if (ssl->handshake_func == 0) {
+ if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
return -1;
}
+ /* We can't shutdown properly if we are in the middle of a handshake. */
if (SSL_in_init(ssl)) {
- return 1;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_SHUTDOWN_WHILE_IN_INIT);
+ return -1;
}
- /* Do nothing if configured not to send a close_notify. */
if (ssl->quiet_shutdown) {
- ssl->shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN;
+ /* Do nothing if configured not to send a close_notify. */
+ ssl->s3->send_shutdown = ssl_shutdown_close_notify;
+ ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
return 1;
}
- if (!(ssl->shutdown & SSL_SENT_SHUTDOWN)) {
- ssl->shutdown |= SSL_SENT_SHUTDOWN;
- ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY);
+ /* This function completes in two stages. It sends a close_notify and then it
+ * waits for a close_notify to come in. Perform exactly one action and return
+ * whether or not it succeeds. */
- /* our shutdown alert has been sent now, and if it still needs to be
- * written, ssl->s3->alert_dispatch will be true */
- if (ssl->s3->alert_dispatch) {
- return -1; /* return WANT_WRITE */
+ if (ssl->s3->send_shutdown != ssl_shutdown_close_notify) {
+ /* Send a close_notify. */
+ if (ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY) <= 0) {
+ return -1;
}
} else if (ssl->s3->alert_dispatch) {
- /* resend it if not sent */
- int ret = ssl->method->ssl_dispatch_alert(ssl);
- if (ret == -1) {
- /* we only get to return -1 here the 2nd/Nth invocation, we must have
- * already signalled return 0 upon a previous invoation, return
- * WANT_WRITE */
- return ret;
+ /* Finish sending the close_notify. */
+ if (ssl->method->ssl_dispatch_alert(ssl) <= 0) {
+ return -1;
}
- } else if (!(ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) {
- /* If we are waiting for a close from our peer, we are closed */
+ } else if (ssl->s3->recv_shutdown != ssl_shutdown_close_notify) {
+ /* Wait for the peer's close_notify. */
ssl->method->ssl_read_close_notify(ssl);
- if (!(ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) {
- return -1; /* return WANT_READ */
+ if (ssl->s3->recv_shutdown != ssl_shutdown_close_notify) {
+ return -1;
}
}
- if (ssl->shutdown == (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN) &&
- !ssl->s3->alert_dispatch) {
- return 1;
- } else {
- return 0;
- }
+ /* Return 0 for unidirectional shutdown and 1 for bidirectional shutdown. */
+ return ssl->s3->recv_shutdown == ssl_shutdown_close_notify;
}
int SSL_get_error(const SSL *ssl, int ret_code) {
@@ -710,9 +749,7 @@ int SSL_get_error(const SSL *ssl, int ret_code) {
}
if (ret_code == 0) {
- if ((ssl->shutdown & SSL_RECEIVED_SHUTDOWN) &&
- (ssl->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) {
- /* The socket was cleanly shut down with a close_notify. */
+ if (ssl->s3->recv_shutdown == ssl_shutdown_close_notify) {
return SSL_ERROR_ZERO_RETURN;
}
/* An EOF was observed which violates the protocol, and the underlying
@@ -997,7 +1034,7 @@ int SSL_get_wfd(const SSL *ssl) {
}
int SSL_set_fd(SSL *ssl, int fd) {
- BIO *bio = BIO_new(BIO_s_fd());
+ BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
return 0;
@@ -1008,35 +1045,36 @@ int SSL_set_fd(SSL *ssl, int fd) {
}
int SSL_set_wfd(SSL *ssl, int fd) {
- if (ssl->rbio == NULL ||
- BIO_method_type(ssl->rbio) != BIO_TYPE_FD ||
- BIO_get_fd(ssl->rbio, NULL) != fd) {
- BIO *bio = BIO_new(BIO_s_fd());
+ BIO *rbio = SSL_get_rbio(ssl);
+ if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET ||
+ BIO_get_fd(rbio, NULL) != fd) {
+ BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
- SSL_set_bio(ssl, SSL_get_rbio(ssl), bio);
+ SSL_set_bio(ssl, rbio, bio);
} else {
- SSL_set_bio(ssl, SSL_get_rbio(ssl), SSL_get_rbio(ssl));
+ SSL_set_bio(ssl, rbio, rbio);
}
return 1;
}
int SSL_set_rfd(SSL *ssl, int fd) {
- if (ssl->wbio == NULL || BIO_method_type(ssl->wbio) != BIO_TYPE_FD ||
- BIO_get_fd(ssl->wbio, NULL) != fd) {
- BIO *bio = BIO_new(BIO_s_fd());
+ BIO *wbio = SSL_get_wbio(ssl);
+ if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET ||
+ BIO_get_fd(wbio, NULL) != fd) {
+ BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
- SSL_set_bio(ssl, bio, SSL_get_wbio(ssl));
+ SSL_set_bio(ssl, bio, wbio);
} else {
- SSL_set_bio(ssl, SSL_get_wbio(ssl), SSL_get_wbio(ssl));
+ SSL_set_bio(ssl, wbio, wbio);
}
return 1;
}
@@ -1165,6 +1203,10 @@ int SSL_renegotiate_pending(SSL *ssl) {
return SSL_in_init(ssl) && ssl->s3->initial_handshake_complete;
}
+int SSL_total_renegotiations(const SSL *ssl) {
+ return ssl->s3->total_renegotiations;
+}
+
size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx) {
return ctx->max_cert_list;
}
@@ -1249,6 +1291,77 @@ int SSL_CTX_get_session_cache_mode(const SSL_CTX *ctx) {
return ctx->session_cache_mode;
}
+
+int SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, void *out, size_t len) {
+ if (out == NULL) {
+ return 48;
+ }
+ if (len != 48) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+ return 0;
+ }
+ uint8_t *out_bytes = out;
+ memcpy(out_bytes, ctx->tlsext_tick_key_name, 16);
+ memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16);
+ memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16);
+ return 1;
+}
+
+int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, size_t len) {
+ if (in == NULL) {
+ return 48;
+ }
+ if (len != 48) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+ return 0;
+ }
+ const uint8_t *in_bytes = in;
+ memcpy(ctx->tlsext_tick_key_name, in_bytes, 16);
+ memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16);
+ memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16);
+ return 1;
+}
+
+int SSL_CTX_set_tlsext_ticket_key_cb(
+ SSL_CTX *ctx, int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv,
+ EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
+ int encrypt)) {
+ ctx->tlsext_ticket_key_cb = callback;
+ return 1;
+}
+
+int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, size_t curves_len) {
+ return tls1_set_curves(&ctx->supported_group_list,
+ &ctx->supported_group_list_len, curves,
+ curves_len);
+}
+
+int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) {
+ return tls1_set_curves(&ssl->supported_group_list,
+ &ssl->supported_group_list_len, curves,
+ curves_len);
+}
+
+int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) {
+ DH_free(ctx->cert->dh_tmp);
+ ctx->cert->dh_tmp = DHparams_dup(dh);
+ if (ctx->cert->dh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
+ return 0;
+ }
+ return 1;
+}
+
+int SSL_set_tmp_dh(SSL *ssl, const DH *dh) {
+ DH_free(ssl->cert->dh_tmp);
+ ssl->cert->dh_tmp = DHparams_dup(dh);
+ if (ssl->cert->dh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
+ return 0;
+ }
+ return 1;
+}
+
STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl) {
if (ssl == NULL) {
return NULL;
@@ -1258,17 +1371,15 @@ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl) {
return ssl->cipher_list->ciphers;
}
- if (ssl->version >= TLS1_1_VERSION && ssl->ctx != NULL &&
- ssl->ctx->cipher_list_tls11 != NULL) {
+ if (ssl->version >= TLS1_1_VERSION && ssl->ctx->cipher_list_tls11 != NULL) {
return ssl->ctx->cipher_list_tls11->ciphers;
}
- if (ssl->version >= TLS1_VERSION && ssl->ctx != NULL &&
- ssl->ctx->cipher_list_tls10 != NULL) {
+ if (ssl->version >= TLS1_VERSION && ssl->ctx->cipher_list_tls10 != NULL) {
return ssl->ctx->cipher_list_tls10->ciphers;
}
- if (ssl->ctx != NULL && ssl->ctx->cipher_list != NULL) {
+ if (ssl->ctx->cipher_list != NULL) {
return ssl->ctx->cipher_list->ciphers;
}
@@ -1286,7 +1397,7 @@ STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl) {
return ssl->cipher_list_by_id;
}
- if (ssl->ctx != NULL && ssl->ctx->cipher_list_by_id != NULL) {
+ if (ssl->ctx->cipher_list_by_id != NULL) {
return ssl->ctx->cipher_list_by_id;
}
@@ -1542,6 +1653,38 @@ int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response,
return 1;
}
+int SSL_set_tlsext_host_name(SSL *ssl, const char *name) {
+ OPENSSL_free(ssl->tlsext_hostname);
+ ssl->tlsext_hostname = NULL;
+
+ if (name == NULL) {
+ return 1;
+ }
+
+ size_t len = strlen(name);
+ if (len == 0 || len > TLSEXT_MAXLEN_host_name) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
+ return 0;
+ }
+ ssl->tlsext_hostname = BUF_strdup(name);
+ if (ssl->tlsext_hostname == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+}
+
+int SSL_CTX_set_tlsext_servername_callback(
+ SSL_CTX *ctx, int (*callback)(SSL *ssl, int *out_alert, void *arg)) {
+ ctx->tlsext_servername_callback = callback;
+ return 1;
+}
+
+int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) {
+ ctx->tlsext_servername_arg = arg;
+ return 1;
+}
+
int SSL_select_next_proto(uint8_t **out, uint8_t *out_len,
const uint8_t *server, unsigned server_len,
const uint8_t *client, unsigned client_len) {
@@ -1647,6 +1790,58 @@ void SSL_get0_alpn_selected(const SSL *ssl, const uint8_t **out_data,
}
}
+
+int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx) {
+ ctx->tlsext_channel_id_enabled = 1;
+ return 1;
+}
+
+int SSL_enable_tls_channel_id(SSL *ssl) {
+ ssl->tlsext_channel_id_enabled = 1;
+ return 1;
+}
+
+static int is_p256_key(EVP_PKEY *private_key) {
+ const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(private_key);
+ return ec_key != NULL &&
+ EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) ==
+ NID_X9_62_prime256v1;
+}
+
+int SSL_CTX_set1_tls_channel_id(SSL_CTX *ctx, EVP_PKEY *private_key) {
+ if (!is_p256_key(private_key)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
+ return 0;
+ }
+
+ EVP_PKEY_free(ctx->tlsext_channel_id_private);
+ ctx->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key);
+ ctx->tlsext_channel_id_enabled = 1;
+
+ return 1;
+}
+
+int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key) {
+ if (!is_p256_key(private_key)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
+ return 0;
+ }
+
+ EVP_PKEY_free(ssl->tlsext_channel_id_private);
+ ssl->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key);
+ ssl->tlsext_channel_id_enabled = 1;
+
+ return 1;
+}
+
+size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) {
+ if (!ssl->s3->tlsext_channel_id_valid) {
+ return 0;
+ }
+ memcpy(out, ssl->s3->tlsext_channel_id, (max_out < 64) ? max_out : 64);
+ return 64;
+}
+
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
int (*cb)(X509_STORE_CTX *store_ctx,
void *arg),
@@ -1674,59 +1869,52 @@ void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
ssl_cert_set_cert_cb(ssl->cert, cb, arg);
}
+size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
+ if (ssl->server || !ssl->s3->tmp.cert_req) {
+ *out_types = NULL;
+ return 0;
+ }
+ *out_types = ssl->s3->tmp.certificate_types;
+ return ssl->s3->tmp.num_certificate_types;
+}
+
void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
uint32_t *out_mask_a) {
- CERT *c = ssl->cert;
- int have_rsa_cert = 0, dh_tmp;
- uint32_t mask_k, mask_a;
- int have_ecc_cert = 0, ecdsa_ok;
- X509 *x;
-
- dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
+ uint32_t mask_k = 0;
+ uint32_t mask_a = 0;
if (ssl->cert->x509 != NULL && ssl_has_private_key(ssl)) {
if (ssl_private_key_type(ssl) == EVP_PKEY_RSA) {
- have_rsa_cert = 1;
+ mask_k |= SSL_kRSA;
+ mask_a |= SSL_aRSA;
} else if (ssl_private_key_type(ssl) == EVP_PKEY_EC) {
- have_ecc_cert = 1;
+ /* An ECC certificate may be usable for ECDSA cipher suites depending on
+ * the key usage extension and on the client's group preferences. */
+ X509 *x = ssl->cert->x509;
+ /* This call populates extension flags (ex_flags). */
+ X509_check_purpose(x, -1, 0);
+ int ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE)
+ ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)
+ : 1;
+ if (ecdsa_ok && tls1_check_ec_cert(ssl, x)) {
+ mask_a |= SSL_aECDSA;
+ }
}
}
- mask_k = 0;
- mask_a = 0;
-
- if (dh_tmp) {
+ if (ssl->cert->dh_tmp != NULL || ssl->cert->dh_tmp_cb != NULL) {
mask_k |= SSL_kDHE;
}
- if (have_rsa_cert) {
- mask_k |= SSL_kRSA;
- mask_a |= SSL_aRSA;
- }
-
- /* An ECC certificate may be usable for ECDSA cipher suites depending on the
- * key usage extension and on the client's curve preferences. */
- if (have_ecc_cert) {
- x = c->x509;
- /* This call populates extension flags (ex_flags). */
- X509_check_purpose(x, -1, 0);
- ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE)
- ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)
- : 1;
- if (!tls1_check_ec_cert(ssl, x)) {
- ecdsa_ok = 0;
- }
- if (ecdsa_ok) {
- mask_a |= SSL_aECDSA;
- }
- }
- /* If we are considering an ECC cipher suite that uses an ephemeral EC
- * key, check for a shared curve. */
+ /* Check for a shared group to consider ECDHE ciphers. */
uint16_t unused;
- if (tls1_get_shared_curve(ssl, &unused)) {
+ if (tls1_get_shared_group(ssl, &unused)) {
mask_k |= SSL_kECDHE;
}
+ /* CECPQ1 ciphers are always acceptable if supported by both sides. */
+ mask_k |= SSL_kCECPQ1;
+
/* PSK requires a server callback. */
if (ssl->psk_server_callback != NULL) {
mask_k |= SSL_kPSK;
@@ -1773,7 +1961,7 @@ void ssl_update_cache(SSL *ssl, int mode) {
flush_cache = 1;
ctx->handshakes_since_cache_flush = 0;
}
- CRYPTO_MUTEX_unlock(&ctx->lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
if (flush_cache) {
SSL_CTX_flush_sessions(ctx, (unsigned long)time(NULL));
@@ -1783,6 +1971,9 @@ void ssl_update_cache(SSL *ssl, int mode) {
static const char *ssl_get_version(int version) {
switch (version) {
+ case TLS1_3_VERSION:
+ return "TLSv1.3";
+
case TLS1_2_VERSION:
return "TLSv1.2";
@@ -1853,42 +2044,36 @@ const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl) {
return ssl->s3->aead_write_ctx->cipher;
}
+int SSL_session_reused(const SSL *ssl) {
+ return ssl->hit;
+}
+
const COMP_METHOD *SSL_get_current_compression(SSL *ssl) { return NULL; }
const COMP_METHOD *SSL_get_current_expansion(SSL *ssl) { return NULL; }
-int ssl_init_wbio_buffer(SSL *ssl, int push) {
- BIO *bbio;
+int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key) { return 0; }
- if (ssl->bbio == NULL) {
- bbio = BIO_new(BIO_f_buffer());
- if (bbio == NULL) {
- return 0;
- }
- ssl->bbio = bbio;
- } else {
- bbio = ssl->bbio;
- if (ssl->bbio == ssl->wbio) {
- ssl->wbio = BIO_pop(ssl->wbio);
- }
- }
+int ssl_is_wbio_buffered(const SSL *ssl) {
+ return ssl->bbio != NULL;
+}
- BIO_reset(bbio);
- if (!BIO_set_read_buffer_size(bbio, 1)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
- return 0;
+int ssl_init_wbio_buffer(SSL *ssl) {
+ if (ssl->bbio != NULL) {
+ /* Already buffered. */
+ assert(ssl->bbio == ssl->wbio);
+ return 1;
}
- if (push) {
- if (ssl->wbio != bbio) {
- ssl->wbio = BIO_push(bbio, ssl->wbio);
- }
- } else {
- if (ssl->wbio == bbio) {
- ssl->wbio = BIO_pop(bbio);
- }
+ BIO *bbio = BIO_new(BIO_f_buffer());
+ if (bbio == NULL ||
+ !BIO_set_read_buffer_size(bbio, 1)) {
+ BIO_free(bbio);
+ return 0;
}
+ ssl->bbio = bbio;
+ ssl->wbio = BIO_push(bbio, ssl->wbio);
return 1;
}
@@ -1897,11 +2082,9 @@ void ssl_free_wbio_buffer(SSL *ssl) {
return;
}
- if (ssl->bbio == ssl->wbio) {
- /* remove buffering */
- ssl->wbio = BIO_pop(ssl->wbio);
- }
+ assert(ssl->bbio == ssl->wbio);
+ ssl->wbio = BIO_pop(ssl->wbio);
BIO_free(ssl->bbio);
ssl->bbio = NULL;
}
@@ -1923,12 +2106,32 @@ int SSL_get_quiet_shutdown(const SSL *ssl) { return ssl->quiet_shutdown; }
void SSL_set_shutdown(SSL *ssl, int mode) {
/* It is an error to clear any bits that have already been set. (We can't try
* to get a second close_notify or send two.) */
- assert((ssl->shutdown & mode) == ssl->shutdown);
+ assert((SSL_get_shutdown(ssl) & mode) == SSL_get_shutdown(ssl));
+
+ if (mode & SSL_RECEIVED_SHUTDOWN &&
+ ssl->s3->recv_shutdown == ssl_shutdown_none) {
+ ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
+ }
- ssl->shutdown |= mode;
+ if (mode & SSL_SENT_SHUTDOWN &&
+ ssl->s3->send_shutdown == ssl_shutdown_none) {
+ ssl->s3->send_shutdown = ssl_shutdown_close_notify;
+ }
}
-int SSL_get_shutdown(const SSL *ssl) { return ssl->shutdown; }
+int SSL_get_shutdown(const SSL *ssl) {
+ int ret = 0;
+ if (ssl->s3->recv_shutdown != ssl_shutdown_none) {
+ /* Historically, OpenSSL set |SSL_RECEIVED_SHUTDOWN| on both close_notify
+ * and fatal alert. */
+ ret |= SSL_RECEIVED_SHUTDOWN;
+ }
+ if (ssl->s3->send_shutdown == ssl_shutdown_close_notify) {
+ /* Historically, OpenSSL set |SSL_SENT_SHUTDOWN| on only close_notify. */
+ ret |= SSL_SENT_SHUTDOWN;
+ }
+ return ret;
+}
int SSL_version(const SSL *ssl) { return ssl->version; }
@@ -1980,6 +2183,14 @@ int SSL_state(const SSL *ssl) { return ssl->state; }
void SSL_set_state(SSL *ssl, int state) { }
+char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len) {
+ if (len <= 0) {
+ return NULL;
+ }
+ buf[0] = '\0';
+ return buf;
+}
+
void SSL_set_verify_result(SSL *ssl, long result) {
ssl->verify_result = result;
}
@@ -2166,6 +2377,12 @@ void SSL_CTX_set_keylog_callback(SSL_CTX *ctx,
ctx->keylog_callback = cb;
}
+void SSL_CTX_set_current_time_cb(SSL_CTX *ctx,
+ void (*cb)(const SSL *ssl,
+ struct timeval *out_clock)) {
+ ctx->current_time_cb = cb;
+}
+
static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
static const char hextable[] = "0123456789abcdef";
uint8_t *out;
@@ -2277,7 +2494,7 @@ int ssl3_can_false_start(const SSL *ssl) {
/* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */
return !SSL_IS_DTLS(ssl) &&
- SSL_version(ssl) >= TLS1_2_VERSION &&
+ SSL_version(ssl) == TLS1_2_VERSION &&
(ssl->s3->alpn_selected || ssl->s3->next_proto_neg_seen) &&
cipher != NULL &&
cipher->algorithm_mkey == SSL_kECDHE &&
@@ -2292,6 +2509,7 @@ const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) {
case TLS1_VERSION:
case TLS1_1_VERSION:
case TLS1_2_VERSION:
+ case TLS1_3_VERSION:
case DTLS1_VERSION:
case DTLS1_2_VERSION:
return &TLSv1_enc_data;
@@ -2316,7 +2534,10 @@ uint16_t ssl3_get_max_server_version(const SSL *ssl) {
return 0;
}
- max_version = (ssl->max_version != 0) ? ssl->max_version : TLS1_2_VERSION;
+ max_version = (ssl->max_version != 0) ? ssl->max_version : TLS1_3_VERSION;
+ if (!(ssl->options & SSL_OP_NO_TLSv1_3) && TLS1_3_VERSION <= max_version) {
+ return TLS1_3_VERSION;
+ }
if (!(ssl->options & SSL_OP_NO_TLSv1_2) && TLS1_2_VERSION <= max_version) {
return TLS1_2_VERSION;
}
@@ -2360,8 +2581,11 @@ uint16_t ssl3_get_mutual_version(SSL *ssl, uint16_t client_version) {
client_version = ssl->max_version;
}
- if (client_version >= TLS1_2_VERSION &&
- !(ssl->options & SSL_OP_NO_TLSv1_2)) {
+ if (client_version >= TLS1_3_VERSION &&
+ !(ssl->options & SSL_OP_NO_TLSv1_3)) {
+ version = TLS1_3_VERSION;
+ } else if (client_version >= TLS1_2_VERSION &&
+ !(ssl->options & SSL_OP_NO_TLSv1_2)) {
version = TLS1_2_VERSION;
} else if (client_version >= TLS1_1_VERSION &&
!(ssl->options & SSL_OP_NO_TLSv1_1)) {
@@ -2410,7 +2634,10 @@ uint16_t ssl3_get_max_client_version(SSL *ssl) {
version = ssl->max_version;
}
} else {
- if (!(options & SSL_OP_NO_TLSv1_2)) {
+ if (!(options & SSL_OP_NO_TLSv1_3)) {
+ version = TLS1_3_VERSION;
+ }
+ if (!(options & SSL_OP_NO_TLSv1_2) && (options & SSL_OP_NO_TLSv1_3)) {
version = TLS1_2_VERSION;
}
if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2)) {
@@ -2470,6 +2697,9 @@ int ssl3_is_version_enabled(SSL *ssl, uint16_t version) {
case TLS1_2_VERSION:
return !(ssl->options & SSL_OP_NO_TLSv1_2);
+ case TLS1_3_VERSION:
+ return !(ssl->options & SSL_OP_NO_TLSv1_3);
+
default:
return 0;
}
@@ -2502,8 +2732,6 @@ uint16_t ssl3_protocol_version(const SSL *ssl) {
return ssl3_version_from_wire(ssl, ssl->version);
}
-int SSL_cache_hit(SSL *ssl) { return SSL_session_reused(ssl); }
-
int SSL_is_server(SSL *ssl) { return ssl->server; }
void SSL_CTX_set_select_certificate_cb(
@@ -2628,7 +2856,6 @@ int SSL_clear(SSL *ssl) {
}
ssl->hit = 0;
- ssl->shutdown = 0;
/* SSL_clear may be called before or after the |ssl| is initialized in either
* accept or connect state. In the latter case, SSL_clear should preserve the
@@ -2677,6 +2904,27 @@ int SSL_clear(SSL *ssl) {
return 1;
}
+void ssl_do_info_callback(const SSL *ssl, int type, int value) {
+ void (*cb)(const SSL *ssl, int type, int value) = NULL;
+ if (ssl->info_callback != NULL) {
+ cb = ssl->info_callback;
+ } else if (ssl->ctx->info_callback != NULL) {
+ cb = ssl->ctx->info_callback;
+ }
+
+ if (cb != NULL) {
+ cb(ssl, type, value);
+ }
+}
+
+void ssl_do_msg_callback(SSL *ssl, int is_write, int version, int content_type,
+ const void *buf, size_t len) {
+ if (ssl->msg_callback != NULL) {
+ ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
+ ssl->msg_callback_arg);
+ }
+}
+
int SSL_CTX_sess_connect(const SSL_CTX *ctx) { return 0; }
int SSL_CTX_sess_connect_good(const SSL_CTX *ctx) { return 0; }
int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx) { return 0; }
@@ -2688,5 +2936,33 @@ int SSL_CTX_sess_cb_hits(const SSL_CTX *ctx) { return 0; }
int SSL_CTX_sess_misses(const SSL_CTX *ctx) { return 0; }
int SSL_CTX_sess_timeouts(const SSL_CTX *ctx) { return 0; }
int SSL_CTX_sess_cache_full(const SSL_CTX *ctx) { return 0; }
+
+int SSL_num_renegotiations(const SSL *ssl) {
+ return SSL_total_renegotiations(ssl);
+}
+
+int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx) { return 0; }
+int SSL_need_tmp_RSA(const SSL *ssl) { return 0; }
+int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa) { return 1; }
+int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa) { return 1; }
void ERR_load_SSL_strings(void) {}
void SSL_load_error_strings(void) {}
+int SSL_cache_hit(SSL *ssl) { return SSL_session_reused(ssl); }
+
+int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key) {
+ if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
+ return SSL_CTX_set1_curves(ctx, &nid, 1);
+}
+
+int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key) {
+ if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
+ return SSL_set1_curves(ssl, &nid, 1);
+}
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 990979b1..c17d2da4 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -326,6 +326,11 @@ void SSL_set_private_key_method(SSL *ssl,
ssl->cert->key_method = key_method;
}
+void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
+ const SSL_PRIVATE_KEY_METHOD *key_method) {
+ ctx->cert->key_method = key_method;
+}
+
int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
size_t num_digests) {
OPENSSL_free(ssl->cert->digest_nids);
diff --git a/ssl/ssl_session.c b/ssl/ssl_session.c
index 804a04f6..8e51a6a2 100644
--- a/ssl/ssl_session.c
+++ b/ssl/ssl_session.c
@@ -136,7 +136,6 @@
#include <openssl/ssl.h>
#include <assert.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
@@ -232,6 +231,19 @@ X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
return session->peer;
}
+size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
+ size_t max_out) {
+ /* TODO(davidben): Fix master_key_length's type and remove these casts. */
+ if (max_out == 0) {
+ return (size_t)session->master_key_length;
+ }
+ if (max_out > (size_t)session->master_key_length) {
+ max_out = (size_t)session->master_key_length;
+ }
+ memcpy(out, session->master_key, max_out);
+ return max_out;
+}
+
long SSL_SESSION_set_time(SSL_SESSION *session, long time) {
if (session == NULL) {
return 0;
@@ -384,7 +396,7 @@ static enum ssl_session_result_t ssl_lookup_session(
SSL_SESSION_up_ref(session);
}
/* TODO(davidben): This should probably move it to the front of the list. */
- CRYPTO_MUTEX_unlock(&ssl->initial_ctx->lock);
+ CRYPTO_MUTEX_unlock_read(&ssl->initial_ctx->lock);
if (session != NULL) {
*out_session = session;
@@ -505,7 +517,7 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
SSL_SESSION *old_session;
CRYPTO_MUTEX_lock_write(&ctx->lock);
if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
- CRYPTO_MUTEX_unlock(&ctx->lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
SSL_SESSION_free(session);
return 0;
}
@@ -513,7 +525,7 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
if (old_session != NULL) {
if (old_session == session) {
/* |session| was already in the cache. */
- CRYPTO_MUTEX_unlock(&ctx->lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
SSL_SESSION_free(old_session);
return 0;
}
@@ -535,7 +547,7 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
}
}
- CRYPTO_MUTEX_unlock(&ctx->lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
return 1;
}
@@ -559,7 +571,7 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
}
if (lock) {
- CRYPTO_MUTEX_unlock(&ctx->lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
}
if (ret) {
@@ -642,11 +654,12 @@ void SSL_CTX_flush_sessions(SSL_CTX *ctx, long time) {
tp.time = time;
CRYPTO_MUTEX_lock_write(&ctx->lock);
lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
- CRYPTO_MUTEX_unlock(&ctx->lock);
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
}
int ssl_clear_bad_session(SSL *ssl) {
- if (ssl->session != NULL && !(ssl->shutdown & SSL_SENT_SHUTDOWN) &&
+ if (ssl->session != NULL &&
+ ssl->s3->send_shutdown != ssl_shutdown_close_notify &&
!SSL_in_init(ssl)) {
SSL_CTX_remove_session(ssl->ctx, ssl->session);
return 1;
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index 8fa197d5..15d1270b 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -110,39 +110,21 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_CR_SRVR_HELLO_A:
return "SSLv3 read server hello A";
- case SSL3_ST_CR_SRVR_HELLO_B:
- return "SSLv3 read server hello B";
-
case SSL3_ST_CR_CERT_A:
return "SSLv3 read server certificate A";
- case SSL3_ST_CR_CERT_B:
- return "SSLv3 read server certificate B";
-
case SSL3_ST_CR_KEY_EXCH_A:
return "SSLv3 read server key exchange A";
- case SSL3_ST_CR_KEY_EXCH_B:
- return "SSLv3 read server key exchange B";
-
case SSL3_ST_CR_CERT_REQ_A:
return "SSLv3 read server certificate request A";
- case SSL3_ST_CR_CERT_REQ_B:
- return "SSLv3 read server certificate request B";
-
case SSL3_ST_CR_SESSION_TICKET_A:
return "SSLv3 read server session ticket A";
- case SSL3_ST_CR_SESSION_TICKET_B:
- return "SSLv3 read server session ticket B";
-
case SSL3_ST_CR_SRVR_DONE_A:
return "SSLv3 read server done A";
- case SSL3_ST_CR_SRVR_DONE_B:
- return "SSLv3 read server done B";
-
case SSL3_ST_CW_CERT_A:
return "SSLv3 write client certificate A";
@@ -191,10 +173,6 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_SR_FINISHED_A:
return "SSLv3 read finished A";
- case SSL3_ST_CR_FINISHED_B:
- case SSL3_ST_SR_FINISHED_B:
- return "SSLv3 read finished B";
-
case SSL3_ST_CW_FLUSH:
case SSL3_ST_SW_FLUSH:
return "SSLv3 flush data";
@@ -208,9 +186,6 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_SR_CLNT_HELLO_C:
return "SSLv3 read client hello C";
- case SSL3_ST_SR_CLNT_HELLO_D:
- return "SSLv3 read client hello D";
-
case SSL3_ST_SW_HELLO_REQ_A:
return "SSLv3 write hello request A";
@@ -259,9 +234,6 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_SR_CERT_A:
return "SSLv3 read client certificate A";
- case SSL3_ST_SR_CERT_B:
- return "SSLv3 read client certificate B";
-
case SSL3_ST_SR_KEY_EXCH_A:
return "SSLv3 read client key exchange A";
@@ -271,16 +243,10 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_SR_CERT_VRFY_A:
return "SSLv3 read certificate verify A";
- case SSL3_ST_SR_CERT_VRFY_B:
- return "SSLv3 read certificate verify B";
-
/* DTLS */
case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
return "DTLS1 read hello verify request A";
- case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
- return "DTLS1 read hello verify request B";
-
default:
return "unknown state";
}
@@ -311,33 +277,18 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_CR_SRVR_HELLO_A:
return "3RSH_A";
- case SSL3_ST_CR_SRVR_HELLO_B:
- return "3RSH_B";
-
case SSL3_ST_CR_CERT_A:
return "3RSC_A";
- case SSL3_ST_CR_CERT_B:
- return "3RSC_B";
-
case SSL3_ST_CR_KEY_EXCH_A:
return "3RSKEA";
- case SSL3_ST_CR_KEY_EXCH_B:
- return "3RSKEB";
-
case SSL3_ST_CR_CERT_REQ_A:
return "3RCR_A";
- case SSL3_ST_CR_CERT_REQ_B:
- return "3RCR_B";
-
case SSL3_ST_CR_SRVR_DONE_A:
return "3RSD_A";
- case SSL3_ST_CR_SRVR_DONE_B:
- return "3RSD_B";
-
case SSL3_ST_CW_CERT_A:
return "3WCC_A";
@@ -386,10 +337,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_CR_FINISHED_A:
return "3RFINA";
- case SSL3_ST_SR_FINISHED_B:
- case SSL3_ST_CR_FINISHED_B:
- return "3RFINB";
-
case SSL3_ST_SW_HELLO_REQ_A:
return "3WHR_A";
@@ -408,9 +355,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_SR_CLNT_HELLO_C:
return "3RCH_C";
- case SSL3_ST_SR_CLNT_HELLO_D:
- return "3RCH_D";
-
case SSL3_ST_SW_SRVR_HELLO_A:
return "3WSH_A";
@@ -444,28 +388,16 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_SR_CERT_A:
return "3RCC_A";
- case SSL3_ST_SR_CERT_B:
- return "3RCC_B";
-
case SSL3_ST_SR_KEY_EXCH_A:
return "3RCKEA";
- case SSL3_ST_SR_KEY_EXCH_B:
- return "3RCKEB";
-
case SSL3_ST_SR_CERT_VRFY_A:
return "3RCV_A";
- case SSL3_ST_SR_CERT_VRFY_B:
- return "3RCV_B";
-
/* DTLS */
case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
return "DRCHVA";
- case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
- return "DRCHVB";
-
default:
return "UNKWN ";
}
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index ed1d3c7d..3e9cd1ed 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -254,6 +254,31 @@ static const char *kMustNotIncludeNull[] = {
"TLSv1.2",
};
+static const char *kMustNotIncludeCECPQ1[] = {
+ "ALL",
+ "DEFAULT",
+ "MEDIUM",
+ "HIGH",
+ "FIPS",
+ "SHA",
+ "SHA1",
+ "SHA256",
+ "SHA384",
+ "RSA",
+ "SSLv3",
+ "TLSv1",
+ "TLSv1.2",
+ "aRSA",
+ "RSA",
+ "aECDSA",
+ "ECDSA",
+ "AES",
+ "AES128",
+ "AES256",
+ "AESGCM",
+ "CHACHA20",
+};
+
static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) {
bool in_group = false;
for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
@@ -324,6 +349,24 @@ static bool TestRuleDoesNotIncludeNull(const char *rule) {
return true;
}
+static bool TestRuleDoesNotIncludeCECPQ1(const char *rule) {
+ ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
+ if (!ctx) {
+ return false;
+ }
+ if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
+ fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
+ return false;
+ }
+ for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
+ if (SSL_CIPHER_is_CECPQ1(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
+ fprintf(stderr, "Error: cipher rule '%s' includes CECPQ1\n",rule);
+ return false;
+ }
+ }
+ return true;
+}
+
static bool TestCipherRules() {
for (const CipherTest &test : kCipherTests) {
if (!TestCipherRule(test)) {
@@ -349,6 +392,12 @@ static bool TestCipherRules() {
}
}
+ for (const char *rule : kMustNotIncludeCECPQ1) {
+ if (!TestRuleDoesNotIncludeCECPQ1(rule)) {
+ return false;
+ }
+ }
+
return true;
}
@@ -646,7 +695,10 @@ static bool TestDefaultVersion(uint16_t version,
if (!ctx) {
return false;
}
- return ctx->min_version == version && ctx->max_version == version;
+ // TODO(svaldez): Remove TLS1_2_VERSION fallback upon implementing TLS 1.3.
+ return ctx->min_version == version &&
+ (ctx->max_version == version ||
+ (version == 0 && ctx->max_version == TLS1_2_VERSION));
}
static bool CipherGetRFCName(std::string *out, uint16_t value) {
@@ -1001,8 +1053,7 @@ static ScopedX509 GetTestCertificate() {
"T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f\n"
"j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n"
"-----END CERTIFICATE-----\n";
- ScopedBIO bio(
- BIO_new_mem_buf(const_cast<char *>(kCertPEM), strlen(kCertPEM)));
+ ScopedBIO bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
}
@@ -1023,28 +1074,14 @@ static ScopedEVP_PKEY GetTestKey() {
"tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
"moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
"-----END RSA PRIVATE KEY-----\n";
- ScopedBIO bio(BIO_new_mem_buf(const_cast<char *>(kKeyPEM), strlen(kKeyPEM)));
+ ScopedBIO bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
return ScopedEVP_PKEY(
PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
}
-static bool TestSequenceNumber(bool dtls) {
- ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
- ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
- if (!client_ctx || !server_ctx) {
- return false;
- }
-
- ScopedX509 cert = GetTestCertificate();
- ScopedEVP_PKEY key = GetTestKey();
- if (!cert || !key ||
- !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
- !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
- return false;
- }
-
- // Create a client and server connected to each other.
- ScopedSSL client(SSL_new(client_ctx.get())), server(SSL_new(server_ctx.get()));
+static bool ConnectClientAndServer(ScopedSSL *out_client, ScopedSSL *out_server,
+ SSL_CTX *client_ctx, SSL_CTX *server_ctx) {
+ ScopedSSL client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
if (!client || !server) {
return false;
}
@@ -1084,6 +1121,32 @@ static bool TestSequenceNumber(bool dtls) {
}
}
+ *out_client = std::move(client);
+ *out_server = std::move(server);
+ return true;
+}
+
+static bool TestSequenceNumber(bool dtls) {
+ ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
+ ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
+ if (!client_ctx || !server_ctx) {
+ return false;
+ }
+
+ ScopedX509 cert = GetTestCertificate();
+ ScopedEVP_PKEY key = GetTestKey();
+ if (!cert || !key ||
+ !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+ !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
+ return false;
+ }
+
+ ScopedSSL client, server;
+ if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get())) {
+ return false;
+ }
+
uint64_t client_read_seq = SSL_get_read_sequence(client.get());
uint64_t client_write_seq = SSL_get_write_sequence(client.get());
uint64_t server_read_seq = SSL_get_read_sequence(server.get());
@@ -1132,6 +1195,162 @@ static bool TestSequenceNumber(bool dtls) {
return true;
}
+static bool TestOneSidedShutdown() {
+ ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
+ ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
+ if (!client_ctx || !server_ctx) {
+ return false;
+ }
+
+ ScopedX509 cert = GetTestCertificate();
+ ScopedEVP_PKEY key = GetTestKey();
+ if (!cert || !key ||
+ !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+ !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
+ return false;
+ }
+
+ ScopedSSL client, server;
+ if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get())) {
+ return false;
+ }
+
+ // Shut down half the connection. SSL_shutdown will return 0 to signal only
+ // one side has shut down.
+ if (SSL_shutdown(client.get()) != 0) {
+ fprintf(stderr, "Could not shutdown.\n");
+ return false;
+ }
+
+ // Reading from the server should consume the EOF.
+ uint8_t byte;
+ if (SSL_read(server.get(), &byte, 1) != 0 ||
+ SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) {
+ fprintf(stderr, "Connection was not shut down cleanly.\n");
+ return false;
+ }
+
+ // However, the server may continue to write data and then shut down the
+ // connection.
+ byte = 42;
+ if (SSL_write(server.get(), &byte, 1) != 1 ||
+ SSL_read(client.get(), &byte, 1) != 1 ||
+ byte != 42) {
+ fprintf(stderr, "Could not send byte.\n");
+ return false;
+ }
+
+ // The server may then shutdown the connection.
+ if (SSL_shutdown(server.get()) != 1 ||
+ SSL_shutdown(client.get()) != 1) {
+ fprintf(stderr, "Could not complete shutdown.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) {
+ if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) {
+ fprintf(stderr, "Got fds %d and %d, wanted %d and %d.\n", SSL_get_rfd(ssl),
+ SSL_get_wfd(ssl), rfd, wfd);
+ return false;
+ }
+
+ // The wrapper BIOs are always equal when fds are equal, even if set
+ // individually.
+ if (rfd == wfd && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) {
+ fprintf(stderr, "rbio and wbio did not match.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestSetFD() {
+ ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
+ if (!ctx) {
+ return false;
+ }
+
+ // Test setting different read and write FDs.
+ ScopedSSL ssl(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_rfd(ssl.get(), 1) ||
+ !SSL_set_wfd(ssl.get(), 2) ||
+ !ExpectFDs(ssl.get(), 1, 2)) {
+ return false;
+ }
+
+ // Test setting the same FD.
+ ssl.reset(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_fd(ssl.get(), 1) ||
+ !ExpectFDs(ssl.get(), 1, 1)) {
+ return false;
+ }
+
+ // Test setting the same FD one side at a time.
+ ssl.reset(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_rfd(ssl.get(), 1) ||
+ !SSL_set_wfd(ssl.get(), 1) ||
+ !ExpectFDs(ssl.get(), 1, 1)) {
+ return false;
+ }
+
+ // Test setting the same FD in the other order.
+ ssl.reset(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_wfd(ssl.get(), 1) ||
+ !SSL_set_rfd(ssl.get(), 1) ||
+ !ExpectFDs(ssl.get(), 1, 1)) {
+ return false;
+ }
+
+ // Test changing the read FD partway through.
+ ssl.reset(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_fd(ssl.get(), 1) ||
+ !SSL_set_rfd(ssl.get(), 2) ||
+ !ExpectFDs(ssl.get(), 2, 1)) {
+ return false;
+ }
+
+ // Test changing the write FD partway through.
+ ssl.reset(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_fd(ssl.get(), 1) ||
+ !SSL_set_wfd(ssl.get(), 2) ||
+ !ExpectFDs(ssl.get(), 1, 2)) {
+ return false;
+ }
+
+ // Test a no-op change to the read FD partway through.
+ ssl.reset(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_fd(ssl.get(), 1) ||
+ !SSL_set_rfd(ssl.get(), 1) ||
+ !ExpectFDs(ssl.get(), 1, 1)) {
+ return false;
+ }
+
+ // Test a no-op change to the write FD partway through.
+ ssl.reset(SSL_new(ctx.get()));
+ if (!ssl ||
+ !SSL_set_fd(ssl.get(), 1) ||
+ !SSL_set_wfd(ssl.get(), 1) ||
+ !ExpectFDs(ssl.get(), 1, 1)) {
+ return false;
+ }
+
+ // ASan builds will implicitly test that the internal |BIO| reference-counting
+ // is correct.
+
+ return true;
+}
+
int main() {
CRYPTO_library_init();
@@ -1155,7 +1374,9 @@ int main() {
!TestClientCAList() ||
!TestInternalSessionCache() ||
!TestSequenceNumber(false /* TLS */) ||
- !TestSequenceNumber(true /* DTLS */)) {
+ !TestSequenceNumber(true /* DTLS */) ||
+ !TestOneSidedShutdown() ||
+ !TestSetFD()) {
ERR_print_errors_fp(stderr);
return 1;
}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 216514dc..b5992077 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -136,7 +136,6 @@
#include <openssl/ssl.h>
#include <assert.h>
-#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
@@ -144,7 +143,7 @@
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include "internal.h"
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 434286bf..16cac15e 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -110,7 +110,6 @@
#include <assert.h>
#include <limits.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -120,7 +119,7 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/type_check.h>
@@ -292,77 +291,77 @@ int SSL_early_callback_ctx_extension_get(
return 0;
}
-static const uint16_t eccurves_default[] = {
- SSL_CURVE_X25519,
- SSL_CURVE_SECP256R1,
- SSL_CURVE_SECP384R1,
+static const uint16_t kDefaultGroups[] = {
+ SSL_GROUP_X25519,
+ SSL_GROUP_SECP256R1,
+ SSL_GROUP_SECP384R1,
#if defined(BORINGSSL_ANDROID_SYSTEM)
- SSL_CURVE_SECP521R1,
+ SSL_GROUP_SECP521R1,
#endif
};
-/* tls1_get_curvelist sets |*out_curve_ids| and |*out_curve_ids_len| to the
- * list of allowed curve IDs. If |get_peer_curves| is non-zero, return the
- * peer's curve list. Otherwise, return the preferred list. */
-static void tls1_get_curvelist(SSL *ssl, int get_peer_curves,
- const uint16_t **out_curve_ids,
- size_t *out_curve_ids_len) {
- if (get_peer_curves) {
- /* Only clients send a curve list, so this function is only called
- * on the server. */
+/* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
+ * list of allowed group IDs. If |get_peer_groups| is non-zero, return the
+ * peer's group list. Otherwise, return the preferred list. */
+static void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
+ const uint16_t **out_group_ids,
+ size_t *out_group_ids_len) {
+ if (get_peer_groups) {
+ /* Only clients send a supported group list, so this function is only
+ * called on the server. */
assert(ssl->server);
- *out_curve_ids = ssl->s3->tmp.peer_ellipticcurvelist;
- *out_curve_ids_len = ssl->s3->tmp.peer_ellipticcurvelist_length;
+ *out_group_ids = ssl->s3->tmp.peer_supported_group_list;
+ *out_group_ids_len = ssl->s3->tmp.peer_supported_group_list_len;
return;
}
- *out_curve_ids = ssl->tlsext_ellipticcurvelist;
- *out_curve_ids_len = ssl->tlsext_ellipticcurvelist_length;
- if (!*out_curve_ids) {
- *out_curve_ids = eccurves_default;
- *out_curve_ids_len = sizeof(eccurves_default) / sizeof(eccurves_default[0]);
+ *out_group_ids = ssl->supported_group_list;
+ *out_group_ids_len = ssl->supported_group_list_len;
+ if (!*out_group_ids) {
+ *out_group_ids = kDefaultGroups;
+ *out_group_ids_len = sizeof(kDefaultGroups) / sizeof(kDefaultGroups[0]);
}
}
-int tls1_get_shared_curve(SSL *ssl, uint16_t *out_curve_id) {
- const uint16_t *curves, *peer_curves, *pref, *supp;
- size_t curves_len, peer_curves_len, pref_len, supp_len, i, j;
+int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id) {
+ const uint16_t *groups, *peer_groups, *pref, *supp;
+ size_t groups_len, peer_groups_len, pref_len, supp_len, i, j;
/* Can't do anything on client side */
if (ssl->server == 0) {
return 0;
}
- tls1_get_curvelist(ssl, 0 /* local curves */, &curves, &curves_len);
- tls1_get_curvelist(ssl, 1 /* peer curves */, &peer_curves, &peer_curves_len);
+ tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
+ tls1_get_grouplist(ssl, 1 /* peer groups */, &peer_groups, &peer_groups_len);
- if (peer_curves_len == 0) {
- /* Clients are not required to send a supported_curves extension. In this
- * case, the server is free to pick any curve it likes. See RFC 4492,
+ if (peer_groups_len == 0) {
+ /* Clients are not required to send a supported_groups extension. In this
+ * case, the server is free to pick any group it likes. See RFC 4492,
* section 4, paragraph 3.
*
* However, in the interests of compatibility, we will skip ECDH if the
* client didn't send an extension because we can't be sure that they'll
- * support our favoured curve. */
+ * support our favoured group. */
return 0;
}
if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
- pref = curves;
- pref_len = curves_len;
- supp = peer_curves;
- supp_len = peer_curves_len;
+ pref = groups;
+ pref_len = groups_len;
+ supp = peer_groups;
+ supp_len = peer_groups_len;
} else {
- pref = peer_curves;
- pref_len = peer_curves_len;
- supp = curves;
- supp_len = curves_len;
+ pref = peer_groups;
+ pref_len = peer_groups_len;
+ supp = groups;
+ supp_len = groups_len;
}
for (i = 0; i < pref_len; i++) {
for (j = 0; j < supp_len; j++) {
if (pref[i] == supp[j]) {
- *out_curve_id = pref[i];
+ *out_group_id = pref[i];
return 1;
}
}
@@ -371,34 +370,34 @@ int tls1_get_shared_curve(SSL *ssl, uint16_t *out_curve_id) {
return 0;
}
-int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
const int *curves, size_t ncurves) {
- uint16_t *curve_ids;
+ uint16_t *group_ids;
size_t i;
- curve_ids = OPENSSL_malloc(ncurves * sizeof(uint16_t));
- if (curve_ids == NULL) {
+ group_ids = OPENSSL_malloc(ncurves * sizeof(uint16_t));
+ if (group_ids == NULL) {
return 0;
}
for (i = 0; i < ncurves; i++) {
- if (!ssl_nid_to_curve_id(&curve_ids[i], curves[i])) {
- OPENSSL_free(curve_ids);
+ if (!ssl_nid_to_group_id(&group_ids[i], curves[i])) {
+ OPENSSL_free(group_ids);
return 0;
}
}
- OPENSSL_free(*out_curve_ids);
- *out_curve_ids = curve_ids;
- *out_curve_ids_len = ncurves;
+ OPENSSL_free(*out_group_ids);
+ *out_group_ids = group_ids;
+ *out_group_ids_len = ncurves;
return 1;
}
-/* tls1_curve_params_from_ec_key sets |*out_curve_id| and |*out_comp_id| to the
- * TLS curve ID and point format, respectively, for |ec|. It returns one on
+/* tls1_curve_params_from_ec_key sets |*out_group_id| and |*out_comp_id| to the
+ * TLS group ID and point format, respectively, for |ec|. It returns one on
* success and zero on failure. */
-static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id,
+static int tls1_curve_params_from_ec_key(uint16_t *out_group_id,
uint8_t *out_comp_id, EC_KEY *ec) {
int nid;
uint16_t id;
@@ -413,14 +412,14 @@ static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id,
return 0;
}
- /* Determine curve ID */
+ /* Determine group ID */
nid = EC_GROUP_get_curve_name(grp);
- if (!ssl_nid_to_curve_id(&id, nid)) {
+ if (!ssl_nid_to_group_id(&id, nid)) {
return 0;
}
- /* Set the named curve ID. Arbitrary explicit curves are not supported. */
- *out_curve_id = id;
+ /* Set the named group ID. Arbitrary explicit groups are not supported. */
+ *out_group_id = id;
if (out_comp_id) {
if (EC_KEY_get0_public_key(ec) == NULL) {
@@ -436,35 +435,35 @@ static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id,
return 1;
}
-/* tls1_check_curve_id returns one if |curve_id| is consistent with both our
- * and the peer's curve preferences. Note: if called as the client, only our
+/* tls1_check_group_id returns one if |group_id| is consistent with both our
+ * and the peer's group preferences. Note: if called as the client, only our
* preferences are checked; the peer (the server) does not send preferences. */
-int tls1_check_curve_id(SSL *ssl, uint16_t curve_id) {
- const uint16_t *curves;
- size_t curves_len, i, get_peer_curves;
+int tls1_check_group_id(SSL *ssl, uint16_t group_id) {
+ const uint16_t *groups;
+ size_t groups_len, i, get_peer_groups;
/* Check against our list, then the peer's list. */
- for (get_peer_curves = 0; get_peer_curves <= 1; get_peer_curves++) {
- if (get_peer_curves && !ssl->server) {
+ for (get_peer_groups = 0; get_peer_groups <= 1; get_peer_groups++) {
+ if (get_peer_groups && !ssl->server) {
/* Servers do not present a preference list so, if we are a client, only
* check our list. */
continue;
}
- tls1_get_curvelist(ssl, get_peer_curves, &curves, &curves_len);
- if (get_peer_curves && curves_len == 0) {
- /* Clients are not required to send a supported_curves extension. In this
- * case, the server is free to pick any curve it likes. See RFC 4492,
+ tls1_get_grouplist(ssl, get_peer_groups, &groups, &groups_len);
+ if (get_peer_groups && groups_len == 0) {
+ /* Clients are not required to send a supported_groups extension. In this
+ * case, the server is free to pick any group it likes. See RFC 4492,
* section 4, paragraph 3. */
continue;
}
- for (i = 0; i < curves_len; i++) {
- if (curves[i] == curve_id) {
+ for (i = 0; i < groups_len; i++) {
+ if (groups[i] == group_id) {
break;
}
}
- if (i == curves_len) {
+ if (i == groups_len) {
return 0;
}
}
@@ -475,7 +474,7 @@ int tls1_check_curve_id(SSL *ssl, uint16_t curve_id) {
int tls1_check_ec_cert(SSL *ssl, X509 *x) {
int ret = 0;
EVP_PKEY *pkey = X509_get_pubkey(x);
- uint16_t curve_id;
+ uint16_t group_id;
uint8_t comp_id;
if (!pkey) {
@@ -483,8 +482,8 @@ int tls1_check_ec_cert(SSL *ssl, X509 *x) {
}
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (ec_key == NULL ||
- !tls1_curve_params_from_ec_key(&curve_id, &comp_id, ec_key) ||
- !tls1_check_curve_id(ssl, curve_id) ||
+ !tls1_curve_params_from_ec_key(&group_id, &comp_id, ec_key) ||
+ !tls1_check_group_id(ssl, group_id) ||
comp_id != TLSEXT_ECPOINTFORMAT_uncompressed) {
goto done;
}
@@ -688,82 +687,44 @@ static int ext_sni_parse_clienthello(SSL *ssl, uint8_t *out_alert,
return 1;
}
- /* The servername extension is treated as follows:
- *
- * - Only the hostname type is supported with a maximum length of 255.
- * - The servername is rejected if too long or if it contains zeros, in
- * which case an fatal alert is generated.
- * - The servername field is maintained together with the session cache.
- * - When a session is resumed, the servername callback is invoked in order
- * to allow the application to position itself to the right context.
- * - The servername is acknowledged if it is new for a session or when
- * it is identical to a previously used for the same session.
- * Applications can control the behaviour. They can at any time
- * set a 'desirable' servername for a new SSL object. This can be the
- * case for example with HTTPS when a Host: header field is received and
- * a renegotiation is requested. In this case, a possible servername
- * presented in the new client hello is only acknowledged if it matches
- * the value of the Host: field.
- * - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
- * if they provide for changing an explicit servername context for the
- * session,
- * i.e. when the session has been established with a servername extension.
- */
-
- CBS server_name_list;
- char have_seen_host_name = 0;
-
+ CBS server_name_list, host_name;
+ uint8_t name_type;
if (!CBS_get_u16_length_prefixed(contents, &server_name_list) ||
- CBS_len(&server_name_list) == 0 ||
+ !CBS_get_u8(&server_name_list, &name_type) ||
+ /* Although the server_name extension was intended to be extensible to
+ * new name types and multiple names, OpenSSL 1.0.x had a bug which meant
+ * different name types will cause an error. Further, RFC 4366 originally
+ * defined syntax inextensibly. RFC 6066 corrected this mistake, but
+ * adding new name types is no longer feasible.
+ *
+ * Act as if the extensibility does not exist to simplify parsing. */
+ !CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
+ CBS_len(&server_name_list) != 0 ||
CBS_len(contents) != 0) {
return 0;
}
- /* Decode each ServerName in the extension. */
- while (CBS_len(&server_name_list) > 0) {
- uint8_t name_type;
- CBS host_name;
-
- if (!CBS_get_u8(&server_name_list, &name_type) ||
- !CBS_get_u16_length_prefixed(&server_name_list, &host_name)) {
- return 0;
- }
-
- /* Only host_name is supported. */
- if (name_type != TLSEXT_NAMETYPE_host_name) {
- continue;
- }
-
- if (have_seen_host_name) {
- /* The ServerNameList MUST NOT contain more than one name of the same
- * name_type. */
- return 0;
- }
+ if (name_type != TLSEXT_NAMETYPE_host_name ||
+ CBS_len(&host_name) == 0 ||
+ CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
+ CBS_contains_zero_byte(&host_name)) {
+ *out_alert = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
- have_seen_host_name = 1;
+ /* TODO(davidben): SNI should be resolved before resumption. We have the
+ * early callback as a replacement, but we should fix the current callback
+ * and avoid the need for |SSL_CTX_set_session_id_context|. */
+ if (!ssl->hit) {
+ assert(ssl->session->tlsext_hostname == NULL);
- if (CBS_len(&host_name) == 0 ||
- CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
- CBS_contains_zero_byte(&host_name)) {
- *out_alert = SSL_AD_UNRECOGNIZED_NAME;
+ /* Copy the hostname as a string. */
+ if (!CBS_strdup(&host_name, &ssl->session->tlsext_hostname)) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
- if (!ssl->hit) {
- assert(ssl->session->tlsext_hostname == NULL);
- if (ssl->session->tlsext_hostname) {
- /* This should be impossible. */
- return 0;
- }
-
- /* Copy the hostname as a string. */
- if (!CBS_strdup(&host_name, &ssl->session->tlsext_hostname)) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
-
- ssl->s3->tmp.should_ack_sni = 1;
- }
+ ssl->s3->tmp.should_ack_sni = 1;
}
return 1;
@@ -1848,35 +1809,36 @@ static int ext_ec_point_add_serverhello(SSL *ssl, CBB *out) {
}
-/* EC supported curves.
+/* Negotiated Groups
*
- * https://tools.ietf.org/html/rfc4492#section-5.1.2 */
+ * https://tools.ietf.org/html/rfc4492#section-5.1.2
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-12#section-6.3.2.2 */
-static void ext_ec_curves_init(SSL *ssl) {
- OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
- ssl->s3->tmp.peer_ellipticcurvelist = NULL;
- ssl->s3->tmp.peer_ellipticcurvelist_length = 0;
+static void ext_supported_groups_init(SSL *ssl) {
+ OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
+ ssl->s3->tmp.peer_supported_group_list = NULL;
+ ssl->s3->tmp.peer_supported_group_list_len = 0;
}
-static int ext_ec_curves_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_supported_groups_add_clienthello(SSL *ssl, CBB *out) {
if (!ssl_any_ec_cipher_suites_enabled(ssl)) {
return 1;
}
- CBB contents, curves_bytes;
- if (!CBB_add_u16(out, TLSEXT_TYPE_elliptic_curves) ||
+ CBB contents, groups_bytes;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_supported_groups) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
- !CBB_add_u16_length_prefixed(&contents, &curves_bytes)) {
+ !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) {
return 0;
}
- const uint16_t *curves;
- size_t curves_len;
- tls1_get_curvelist(ssl, 0, &curves, &curves_len);
+ const uint16_t *groups;
+ size_t groups_len;
+ tls1_get_grouplist(ssl, 0, &groups, &groups_len);
size_t i;
- for (i = 0; i < curves_len; i++) {
- if (!CBB_add_u16(&curves_bytes, curves[i])) {
+ for (i = 0; i < groups_len; i++) {
+ if (!CBB_add_u16(&groups_bytes, groups[i])) {
return 0;
}
}
@@ -1884,54 +1846,55 @@ static int ext_ec_curves_add_clienthello(SSL *ssl, CBB *out) {
return CBB_flush(out);
}
-static int ext_ec_curves_parse_serverhello(SSL *ssl, uint8_t *out_alert,
- CBS *contents) {
+static int ext_supported_groups_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+ CBS *contents) {
/* This extension is not expected to be echoed by servers and is ignored. */
return 1;
}
-static int ext_ec_curves_parse_clienthello(SSL *ssl, uint8_t *out_alert,
- CBS *contents) {
+static int ext_supported_groups_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+ CBS *contents) {
if (contents == NULL) {
return 1;
}
- CBS elliptic_curve_list;
- if (!CBS_get_u16_length_prefixed(contents, &elliptic_curve_list) ||
- CBS_len(&elliptic_curve_list) == 0 ||
- (CBS_len(&elliptic_curve_list) & 1) != 0 ||
+ CBS supported_group_list;
+ if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
+ CBS_len(&supported_group_list) == 0 ||
+ (CBS_len(&supported_group_list) & 1) != 0 ||
CBS_len(contents) != 0) {
return 0;
}
- ssl->s3->tmp.peer_ellipticcurvelist = OPENSSL_malloc(CBS_len(&elliptic_curve_list));
- if (ssl->s3->tmp.peer_ellipticcurvelist == NULL) {
+ ssl->s3->tmp.peer_supported_group_list = OPENSSL_malloc(
+ CBS_len(&supported_group_list));
+ if (ssl->s3->tmp.peer_supported_group_list == NULL) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
- const size_t num_curves = CBS_len(&elliptic_curve_list) / 2;
+ const size_t num_groups = CBS_len(&supported_group_list) / 2;
size_t i;
- for (i = 0; i < num_curves; i++) {
- if (!CBS_get_u16(&elliptic_curve_list,
- &ssl->s3->tmp.peer_ellipticcurvelist[i])) {
+ for (i = 0; i < num_groups; i++) {
+ if (!CBS_get_u16(&supported_group_list,
+ &ssl->s3->tmp.peer_supported_group_list[i])) {
goto err;
}
}
- assert(CBS_len(&elliptic_curve_list) == 0);
- ssl->s3->tmp.peer_ellipticcurvelist_length = num_curves;
+ assert(CBS_len(&supported_group_list) == 0);
+ ssl->s3->tmp.peer_supported_group_list_len = num_groups;
return 1;
err:
- OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
- ssl->s3->tmp.peer_ellipticcurvelist = NULL;
+ OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
+ ssl->s3->tmp.peer_supported_group_list = NULL;
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
-static int ext_ec_curves_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_supported_groups_add_serverhello(SSL *ssl, CBB *out) {
/* Servers don't echo this extension. */
return 1;
}
@@ -2038,13 +2001,16 @@ static const struct tls_extension kExtensions[] = {
ext_ec_point_parse_clienthello,
ext_ec_point_add_serverhello,
},
+ /* The final extension must be non-empty. WebSphere Application Server 7.0 is
+ * intolerant to the last extension being zero-length. See
+ * https://crbug.com/363583. */
{
- TLSEXT_TYPE_elliptic_curves,
- ext_ec_curves_init,
- ext_ec_curves_add_clienthello,
- ext_ec_curves_parse_serverhello,
- ext_ec_curves_parse_clienthello,
- ext_ec_curves_add_serverhello,
+ TLSEXT_TYPE_supported_groups,
+ ext_supported_groups_init,
+ ext_supported_groups_add_clienthello,
+ ext_supported_groups_parse_serverhello,
+ ext_supported_groups_parse_clienthello,
+ ext_supported_groups_add_serverhello,
},
};
@@ -2124,9 +2090,10 @@ int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len) {
* NB: because this code works out the length of all existing extensions
* it MUST always appear last. */
size_t padding_len = 0x200 - header_len;
- /* Extensions take at least four bytes to encode. Always include least
+ /* Extensions take at least four bytes to encode. Always include at least
* one byte of data if including the extension. WebSphere Application
- * Server 7.0 is intolerant to the last extension being zero-length. */
+ * Server 7.0 is intolerant to the last extension being zero-length. See
+ * https://crbug.com/363583. */
if (padding_len >= 4 + 1) {
padding_len -= 4;
} else {
@@ -2368,14 +2335,10 @@ static int ssl_check_clienthello_tlsext(SSL *ssl) {
int ret = SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
- /* The handling of the ECPointFormats extension is done elsewhere, namely in
- * ssl3_choose_cipher in s3_lib.c. */
-
- if (ssl->ctx != NULL && ssl->ctx->tlsext_servername_callback != 0) {
+ if (ssl->ctx->tlsext_servername_callback != 0) {
ret = ssl->ctx->tlsext_servername_callback(ssl, &al,
- ssl->ctx->tlsext_servername_arg);
- } else if (ssl->initial_ctx != NULL &&
- ssl->initial_ctx->tlsext_servername_callback != 0) {
+ ssl->ctx->tlsext_servername_arg);
+ } else if (ssl->initial_ctx->tlsext_servername_callback != 0) {
ret = ssl->initial_ctx->tlsext_servername_callback(
ssl, &al, ssl->initial_ctx->tlsext_servername_arg);
}
@@ -2402,11 +2365,10 @@ static int ssl_check_serverhello_tlsext(SSL *ssl) {
int ret = SSL_TLSEXT_ERR_OK;
int al = SSL_AD_UNRECOGNIZED_NAME;
- if (ssl->ctx != NULL && ssl->ctx->tlsext_servername_callback != 0) {
+ if (ssl->ctx->tlsext_servername_callback != 0) {
ret = ssl->ctx->tlsext_servername_callback(ssl, &al,
- ssl->ctx->tlsext_servername_arg);
- } else if (ssl->initial_ctx != NULL &&
- ssl->initial_ctx->tlsext_servername_callback != 0) {
+ ssl->ctx->tlsext_servername_arg);
+ } else if (ssl->initial_ctx->tlsext_servername_callback != 0) {
ret = ssl->initial_ctx->tlsext_servername_callback(
ssl, &al, ssl->initial_ctx->tlsext_servername_arg);
}
diff --git a/ssl/test/README.md b/ssl/test/README.md
new file mode 100644
index 00000000..7a46c323
--- /dev/null
+++ b/ssl/test/README.md
@@ -0,0 +1,35 @@
+# BoringSSL SSL Tests
+
+This directory contains BoringSSL's protocol-level test suite.
+
+Testing a TLS implementation can be difficult. We need to produce invalid but
+sufficiently correct handshakes to get our implementation close to its edge
+cases. TLS's cryptographic steps mean we cannot use a transcript and effectively
+need a TLS implementation on the other end. But we do not wish to litter
+BoringSSL with options for bugs to test against.
+
+Instead, we use a fork of the Go `crypto/tls` package, heavily patched with
+configurable bugs. This code, along with a test suite and harness written in Go,
+lives in the `runner` directory. The harness runs BoringSSL via a C/C++ shim
+binary which lives in this directory. All communication with the shim binary
+occurs with command-line flags, sockets, and standard I/O.
+
+This strategy also ensures we always test against a second implementation. All
+features should be implemented twice, once in C for BoringSSL and once in Go for
+testing. If possible, the Go code should be suitable for potentially
+upstreaming. However, sometimes test code has different needs. For example, our
+test DTLS code enforces strict ordering on sequence numbers and has controlled
+packet drop simulation.
+
+To run the tests manually, run `go test` from the `runner` directory. It takes
+command-line flags found at the top of `runner/runner.go`. The `-help` option
+also works after using `go test -c` to make a `runner.test` binary first.
+
+If adding a new test, these files may be a good starting point:
+
+ * `runner/runner.go`: the test harness and all the individual tests.
+ * `runner/common.go`: contains the `Config` and `ProtocolBugs` struct which
+ control the Go TLS implementation's behavior.
+ * `test_config.h`, `test_config.cc`: the command-line flags which control the
+ shim's behavior.
+ * `bssl_shim.cc`: the shim binary itself.
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index dde25b44..ef759d9f 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -28,14 +28,15 @@
#include <unistd.h>
#else
#include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#pragma comment(lib, "Ws2_32.lib")
#endif
+#include <assert.h>
#include <inttypes.h>
#include <string.h>
@@ -46,7 +47,7 @@
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
@@ -81,19 +82,10 @@ static int Usage(const char *program) {
}
struct TestState {
- TestState() {
- // MSVC cannot initialize these inline.
- memset(&clock, 0, sizeof(clock));
- memset(&clock_delta, 0, sizeof(clock_delta));
- }
-
// async_bio is async BIO which pauses reads and writes.
BIO *async_bio = nullptr;
- // clock is the current time for the SSL connection.
- timeval clock;
- // clock_delta is how far the clock advanced in the most recent failed
- // |BIO_read|.
- timeval clock_delta;
+ // packeted_bio is the packeted BIO which simulates read timeouts.
+ BIO *packeted_bio = nullptr;
ScopedEVP_PKEY channel_id;
bool cert_ready = false;
ScopedSSL_SESSION session;
@@ -117,11 +109,11 @@ static void TestStateExFree(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
static int g_config_index = 0;
static int g_state_index = 0;
-static bool SetConfigPtr(SSL *ssl, const TestConfig *config) {
+static bool SetTestConfig(SSL *ssl, const TestConfig *config) {
return SSL_set_ex_data(ssl, g_config_index, (void *)config) == 1;
}
-static const TestConfig *GetConfigPtr(const SSL *ssl) {
+static const TestConfig *GetTestConfig(const SSL *ssl) {
return (const TestConfig *)SSL_get_ex_data(ssl, g_config_index);
}
@@ -138,13 +130,20 @@ static TestState *GetTestState(const SSL *ssl) {
return (TestState *)SSL_get_ex_data(ssl, g_state_index);
}
+static ScopedX509 LoadCertificate(const std::string &file) {
+ ScopedBIO bio(BIO_new(BIO_s_file()));
+ if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
+ return nullptr;
+ }
+ return ScopedX509(PEM_read_bio_X509(bio.get(), NULL, NULL, NULL));
+}
+
static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) {
ScopedBIO bio(BIO_new(BIO_s_file()));
if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
return nullptr;
}
- ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL));
- return pkey;
+ return ScopedEVP_PKEY(PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL));
}
static int AsyncPrivateKeyType(SSL *ssl) {
@@ -291,9 +290,9 @@ struct Free {
}
};
-static bool InstallCertificate(SSL *ssl) {
- const TestConfig *config = GetConfigPtr(ssl);
- TestState *test_state = GetTestState(ssl);
+static bool GetCertificate(SSL *ssl, ScopedX509 *out_x509,
+ ScopedEVP_PKEY *out_pkey) {
+ const TestConfig *config = GetTestConfig(ssl);
if (!config->digest_prefs.empty()) {
std::unique_ptr<char, Free<char>> digest_prefs(
@@ -317,21 +316,16 @@ static bool InstallCertificate(SSL *ssl) {
}
if (!config->key_file.empty()) {
- if (config->async) {
- test_state->private_key = LoadPrivateKey(config->key_file.c_str());
- if (!test_state->private_key) {
- return false;
- }
- SSL_set_private_key_method(ssl, &g_async_private_key_method);
- } else if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(),
- SSL_FILETYPE_PEM)) {
+ *out_pkey = LoadPrivateKey(config->key_file.c_str());
+ if (!*out_pkey) {
return false;
}
}
- if (!config->cert_file.empty() &&
- !SSL_use_certificate_file(ssl, config->cert_file.c_str(),
- SSL_FILETYPE_PEM)) {
- return false;
+ if (!config->cert_file.empty()) {
+ *out_x509 = LoadCertificate(config->cert_file.c_str());
+ if (!*out_x509) {
+ return false;
+ }
}
if (!config->ocsp_response.empty() &&
!SSL_CTX_set_ocsp_response(ssl->ctx,
@@ -342,8 +336,33 @@ static bool InstallCertificate(SSL *ssl) {
return true;
}
+static bool InstallCertificate(SSL *ssl) {
+ ScopedX509 x509;
+ ScopedEVP_PKEY pkey;
+ if (!GetCertificate(ssl, &x509, &pkey)) {
+ return false;
+ }
+
+ if (pkey) {
+ TestState *test_state = GetTestState(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
+ if (config->async) {
+ test_state->private_key = std::move(pkey);
+ SSL_set_private_key_method(ssl, &g_async_private_key_method);
+ } else if (!SSL_use_PrivateKey(ssl, pkey.get())) {
+ return false;
+ }
+ }
+
+ if (x509 && !SSL_use_certificate(ssl, x509.get())) {
+ return false;
+ }
+
+ return true;
+}
+
static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) {
- const TestConfig *config = GetConfigPtr(ctx->ssl);
+ const TestConfig *config = GetTestConfig(ctx->ssl);
GetTestState(ctx->ssl)->early_callback_called = true;
if (!config->expected_server_name.empty()) {
@@ -394,10 +413,32 @@ static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) {
return 1;
}
+static int ClientCertCallback(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey) {
+ if (GetTestConfig(ssl)->async && !GetTestState(ssl)->cert_ready) {
+ return -1;
+ }
+
+ ScopedX509 x509;
+ ScopedEVP_PKEY pkey;
+ if (!GetCertificate(ssl, &x509, &pkey)) {
+ return -1;
+ }
+
+ // Return zero for no certificate.
+ if (!x509) {
+ return 0;
+ }
+
+ // Asynchronous private keys are not supported with client_cert_cb.
+ *out_x509 = x509.release();
+ *out_pkey = pkey.release();
+ return 1;
+}
+
static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) {
SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
SSL_get_ex_data_X509_STORE_CTX_idx());
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
if (!config->expected_ocsp_response.empty()) {
const uint8_t *data;
@@ -419,7 +460,7 @@ static int VerifyFail(X509_STORE_CTX *store_ctx, void *arg) {
static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
unsigned int *out_len, void *arg) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
if (config->advertise_npn.empty()) {
return SSL_TLSEXT_ERR_NOACK;
}
@@ -431,7 +472,7 @@ static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen,
const uint8_t* in, unsigned inlen, void* arg) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
if (config->select_next_proto.empty()) {
return SSL_TLSEXT_ERR_NOACK;
}
@@ -443,8 +484,8 @@ static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen,
static int AlpnSelectCallback(SSL* ssl, const uint8_t** out, uint8_t* outlen,
const uint8_t* in, unsigned inlen, void* arg) {
- const TestConfig *config = GetConfigPtr(ssl);
- if (config->select_alpn.empty()) {
+ const TestConfig *config = GetTestConfig(ssl);
+ if (config->decline_alpn) {
return SSL_TLSEXT_ERR_NOACK;
}
@@ -465,7 +506,7 @@ static unsigned PskClientCallback(SSL *ssl, const char *hint,
char *out_identity,
unsigned max_identity_len,
uint8_t *out_psk, unsigned max_psk_len) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
if (strcmp(hint ? hint : "", config->psk_identity.c_str()) != 0) {
fprintf(stderr, "Server PSK hint did not match.\n");
@@ -487,7 +528,7 @@ static unsigned PskClientCallback(SSL *ssl, const char *hint,
static unsigned PskServerCallback(SSL *ssl, const char *identity,
uint8_t *out_psk, unsigned max_psk_len) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
if (strcmp(identity, config->psk_identity.c_str()) != 0) {
fprintf(stderr, "Client PSK identity did not match.\n");
@@ -504,7 +545,7 @@ static unsigned PskServerCallback(SSL *ssl, const char *identity,
}
static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
- *out_clock = GetTestState(ssl)->clock;
+ *out_clock = PacketedBioGetClock(GetTestState(ssl)->packeted_bio);
}
static void ChannelIdCallback(SSL *ssl, EVP_PKEY **out_pkey) {
@@ -535,7 +576,7 @@ static SSL_SESSION *GetSessionCallback(SSL *ssl, uint8_t *data, int len,
}
static int DDoSCallback(const struct ssl_early_callback_ctx *early_context) {
- const TestConfig *config = GetConfigPtr(early_context->ssl);
+ const TestConfig *config = GetTestConfig(early_context->ssl);
static int callback_num = 0;
callback_num++;
@@ -548,7 +589,7 @@ static int DDoSCallback(const struct ssl_early_callback_ctx *early_context) {
static void InfoCallback(const SSL *ssl, int type, int val) {
if (type == SSL_CB_HANDSHAKE_DONE) {
- if (GetConfigPtr(ssl)->handshake_never_done) {
+ if (GetTestConfig(ssl)->handshake_never_done) {
fprintf(stderr, "handshake completed\n");
// Abort before any expected error code is printed, to ensure the overall
// test fails.
@@ -584,7 +625,7 @@ static int TicketKeyCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
}
if (!encrypt) {
- return GetConfigPtr(ssl)->renew_ticket ? 2 : 1;
+ return GetTestConfig(ssl)->renew_ticket ? 2 : 1;
}
return 1;
}
@@ -606,10 +647,10 @@ static int CustomExtensionAddCallback(SSL *ssl, unsigned extension_value,
abort();
}
- if (GetConfigPtr(ssl)->custom_extension_skip) {
+ if (GetTestConfig(ssl)->custom_extension_skip) {
return 0;
}
- if (GetConfigPtr(ssl)->custom_extension_fail_add) {
+ if (GetTestConfig(ssl)->custom_extension_fail_add) {
return -1;
}
@@ -732,6 +773,9 @@ static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
}
ScopedDH dh(DH_get_2048_256(NULL));
+ if (!dh) {
+ return nullptr;
+ }
if (config->use_sparse_dh_prime) {
// This prime number is 2^1024 + 643 – a value just above a power of two.
@@ -752,7 +796,7 @@ static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
dh->priv_length = 0;
}
- if (!dh || !SSL_CTX_set_tmp_dh(ssl_ctx.get(), dh.get())) {
+ if (!SSL_CTX_set_tmp_dh(ssl_ctx.get(), dh.get())) {
return nullptr;
}
@@ -768,6 +812,10 @@ static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
SSL_CTX_set_select_certificate_cb(ssl_ctx.get(), SelectCertificateCallback);
+ if (config->use_old_client_cert_callback) {
+ SSL_CTX_set_client_cert_cb(ssl_ctx.get(), ClientCertCallback);
+ }
+
SSL_CTX_set_next_protos_advertised_cb(
ssl_ctx.get(), NextProtosAdvertisedCallback, NULL);
if (!config->select_next_proto.empty()) {
@@ -775,14 +823,14 @@ static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
NULL);
}
- if (!config->select_alpn.empty()) {
+ if (!config->select_alpn.empty() || config->decline_alpn) {
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL);
}
SSL_CTX_enable_tls_channel_id(ssl_ctx.get());
SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback);
- ssl_ctx->current_time_cb = CurrentTimeCallback;
+ SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback);
SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback);
SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
@@ -832,26 +880,16 @@ static bool RetryAsync(SSL *ssl, int ret) {
return false;
}
- const TestConfig *config = GetConfigPtr(ssl);
TestState *test_state = GetTestState(ssl);
- if (test_state->clock_delta.tv_usec != 0 ||
- test_state->clock_delta.tv_sec != 0) {
- // Process the timeout and retry.
- test_state->clock.tv_usec += test_state->clock_delta.tv_usec;
- test_state->clock.tv_sec += test_state->clock.tv_usec / 1000000;
- test_state->clock.tv_usec %= 1000000;
- test_state->clock.tv_sec += test_state->clock_delta.tv_sec;
- memset(&test_state->clock_delta, 0, sizeof(test_state->clock_delta));
+ assert(GetTestConfig(ssl)->async);
+ if (test_state->packeted_bio != nullptr &&
+ PacketedBioAdvanceClock(test_state->packeted_bio)) {
// The DTLS retransmit logic silently ignores write failures. So the test
// may progress, allow writes through synchronously.
- if (config->async) {
- AsyncBioEnforceWriteQuota(test_state->async_bio, false);
- }
+ AsyncBioEnforceWriteQuota(test_state->async_bio, false);
int timeout_ret = DTLSv1_handle_timeout(ssl);
- if (config->async) {
- AsyncBioEnforceWriteQuota(test_state->async_bio, true);
- }
+ AsyncBioEnforceWriteQuota(test_state->async_bio, true);
if (timeout_ret < 0) {
fprintf(stderr, "Error retransmitting.\n");
@@ -870,7 +908,7 @@ static bool RetryAsync(SSL *ssl, int ret) {
AsyncBioAllowWrite(test_state->async_bio, 1);
return true;
case SSL_ERROR_WANT_CHANNEL_ID_LOOKUP: {
- ScopedEVP_PKEY pkey = LoadPrivateKey(GetConfigPtr(ssl)->send_channel_id);
+ ScopedEVP_PKEY pkey = LoadPrivateKey(GetTestConfig(ssl)->send_channel_id);
if (!pkey) {
return false;
}
@@ -897,7 +935,7 @@ static bool RetryAsync(SSL *ssl, int ret) {
// DoRead reads from |ssl|, resolving any asynchronous operations. It returns
// the result value of the final |SSL_read| call.
static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
TestState *test_state = GetTestState(ssl);
int ret;
do {
@@ -918,7 +956,7 @@ static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) {
// WriteAll writes |in_len| bytes from |in| to |ssl|, resolving any asynchronous
// operations. It returns the result of the final |SSL_write| call.
static int WriteAll(SSL *ssl, const uint8_t *in, size_t in_len) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
int ret;
do {
ret = SSL_write(ssl, in, in_len);
@@ -933,7 +971,7 @@ static int WriteAll(SSL *ssl, const uint8_t *in, size_t in_len) {
// DoShutdown calls |SSL_shutdown|, resolving any asynchronous operations. It
// returns the result of the final |SSL_shutdown| call.
static int DoShutdown(SSL *ssl) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
int ret;
do {
ret = SSL_shutdown(ssl);
@@ -945,7 +983,7 @@ static int DoShutdown(SSL *ssl) {
// initial handshake (or False Starts), whether all the properties are
// consistent with the test configuration and invariants.
static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
- const TestConfig *config = GetConfigPtr(ssl);
+ const TestConfig *config = GetTestConfig(ssl);
if (SSL_get_current_cipher(ssl) == nullptr) {
fprintf(stderr, "null cipher after handshake\n");
@@ -1131,7 +1169,7 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
return false;
}
- if (!SetConfigPtr(ssl.get(), config) ||
+ if (!SetTestConfig(ssl.get(), config) ||
!SetTestState(ssl.get(), std::unique_ptr<TestState>(new TestState))) {
return false;
}
@@ -1140,9 +1178,8 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
!SSL_set_mode(ssl.get(), SSL_MODE_SEND_FALLBACK_SCSV)) {
return false;
}
- if (!config->use_early_callback) {
+ if (!config->use_early_callback && !config->use_old_client_cert_callback) {
if (config->async) {
- // TODO(davidben): Also test |s->ctx->client_cert_cb| on the client.
SSL_set_cert_cb(ssl.get(), CertCallback, NULL);
} else if (!InstallCertificate(ssl.get())) {
return false;
@@ -1164,6 +1201,9 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
if (config->partial_write) {
SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_PARTIAL_WRITE);
}
+ if (config->no_tls13) {
+ SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_3);
+ }
if (config->no_tls12) {
SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_2);
}
@@ -1255,13 +1295,17 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
}
if (config->enable_all_curves) {
static const int kAllCurves[] = {
- NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_x25519,
+ NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_X25519,
};
if (!SSL_set1_curves(ssl.get(), kAllCurves,
sizeof(kAllCurves) / sizeof(kAllCurves[0]))) {
return false;
}
}
+ if (config->initial_timeout_duration_ms > 0) {
+ DTLSv1_set_initial_timeout_duration(ssl.get(),
+ config->initial_timeout_duration_ms);
+ }
int sock = Connect(config->port);
if (sock == -1) {
@@ -1274,14 +1318,20 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
return false;
}
if (config->is_dtls) {
- ScopedBIO packeted =
- PacketedBioCreate(&GetTestState(ssl.get())->clock_delta);
+ ScopedBIO packeted = PacketedBioCreate(!config->async);
+ if (!packeted) {
+ return false;
+ }
+ GetTestState(ssl.get())->packeted_bio = packeted.get();
BIO_push(packeted.get(), bio.release());
bio = std::move(packeted);
}
if (config->async) {
ScopedBIO async_scoped =
config->is_dtls ? AsyncBioCreateDatagram() : AsyncBioCreate();
+ if (!async_scoped) {
+ return false;
+ }
BIO_push(async_scoped.get(), bio.release());
GetTestState(ssl.get())->async_bio = async_scoped.get();
bio = std::move(async_scoped);
@@ -1485,7 +1535,16 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
return true;
}
+class StderrDelimiter {
+ public:
+ ~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); }
+};
+
int main(int argc, char **argv) {
+ // To distinguish ASan's output from ours, add a trailing message to stderr.
+ // Anything following this line will be considered an error.
+ StderrDelimiter delimiter;
+
#if defined(OPENSSL_WINDOWS)
/* Initialize Winsock. */
WORD wsa_version = MAKEWORD(2, 2);
diff --git a/ssl/test/packeted_bio.cc b/ssl/test/packeted_bio.cc
index e831082a..b0982b07 100644
--- a/ssl/test/packeted_bio.cc
+++ b/ssl/test/packeted_bio.cc
@@ -30,6 +30,46 @@ const uint8_t kOpcodePacket = 'P';
const uint8_t kOpcodeTimeout = 'T';
const uint8_t kOpcodeTimeoutAck = 't';
+struct PacketedBio {
+ explicit PacketedBio(bool advance_clock_arg)
+ : advance_clock(advance_clock_arg) {
+ memset(&timeout, 0, sizeof(timeout));
+ memset(&clock, 0, sizeof(clock));
+ memset(&read_deadline, 0, sizeof(read_deadline));
+ }
+
+ bool HasTimeout() const {
+ return timeout.tv_sec != 0 || timeout.tv_usec != 0;
+ }
+
+ bool CanRead() const {
+ if (read_deadline.tv_sec == 0 && read_deadline.tv_usec == 0) {
+ return true;
+ }
+
+ if (clock.tv_sec == read_deadline.tv_sec) {
+ return clock.tv_usec < read_deadline.tv_usec;
+ }
+ return clock.tv_sec < read_deadline.tv_sec;
+ }
+
+ timeval timeout;
+ timeval clock;
+ timeval read_deadline;
+ bool advance_clock;
+};
+
+PacketedBio *GetData(BIO *bio) {
+ if (bio->method != &g_packeted_bio_method) {
+ return NULL;
+ }
+ return (PacketedBio *)bio->ptr;
+}
+
+const PacketedBio *GetData(const BIO *bio) {
+ return GetData(const_cast<BIO*>(bio));
+}
+
// ReadAll reads |len| bytes from |bio| into |out|. It returns 1 on success and
// 0 or -1 on error.
static int ReadAll(BIO *bio, uint8_t *out, size_t len) {
@@ -79,90 +119,113 @@ static int PacketedWrite(BIO *bio, const char *in, int inl) {
}
static int PacketedRead(BIO *bio, char *out, int outl) {
+ PacketedBio *data = GetData(bio);
if (bio->next_bio == NULL) {
return 0;
}
BIO_clear_retry_flags(bio);
- // Read the opcode.
- uint8_t opcode;
- int ret = ReadAll(bio->next_bio, &opcode, sizeof(opcode));
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- return ret;
- }
+ for (;;) {
+ // Check if the read deadline has passed.
+ if (!data->CanRead()) {
+ BIO_set_retry_read(bio);
+ return -1;
+ }
- if (opcode == kOpcodeTimeout) {
- // Process the timeout.
- uint8_t buf[8];
- ret = ReadAll(bio->next_bio, buf, sizeof(buf));
+ // Read the opcode.
+ uint8_t opcode;
+ int ret = ReadAll(bio->next_bio, &opcode, sizeof(opcode));
if (ret <= 0) {
BIO_copy_next_retry(bio);
return ret;
}
- uint64_t timeout = (static_cast<uint64_t>(buf[0]) << 56) |
- (static_cast<uint64_t>(buf[1]) << 48) |
- (static_cast<uint64_t>(buf[2]) << 40) |
- (static_cast<uint64_t>(buf[3]) << 32) |
- (static_cast<uint64_t>(buf[4]) << 24) |
- (static_cast<uint64_t>(buf[5]) << 16) |
- (static_cast<uint64_t>(buf[6]) << 8) |
- static_cast<uint64_t>(buf[7]);
- timeout /= 1000; // Convert nanoseconds to microseconds.
- timeval *out_timeout = reinterpret_cast<timeval *>(bio->ptr);
- assert(out_timeout->tv_usec == 0);
- assert(out_timeout->tv_sec == 0);
- out_timeout->tv_usec = timeout % 1000000;
- out_timeout->tv_sec = timeout / 1000000;
-
- // Send an ACK to the peer.
- ret = BIO_write(bio->next_bio, &kOpcodeTimeoutAck, 1);
- if (ret <= 0) {
- return ret;
- }
- assert(ret == 1);
- // Signal to the caller to retry the read, after processing the
- // new clock.
- BIO_set_retry_read(bio);
- return -1;
- }
+ if (opcode == kOpcodeTimeout) {
+ // The caller is required to advance any pending timeouts before
+ // continuing.
+ if (data->HasTimeout()) {
+ fprintf(stderr, "Unprocessed timeout!\n");
+ return -1;
+ }
- if (opcode != kOpcodePacket) {
- fprintf(stderr, "Unknown opcode, %u\n", opcode);
- return -1;
- }
+ // Process the timeout.
+ uint8_t buf[8];
+ ret = ReadAll(bio->next_bio, buf, sizeof(buf));
+ if (ret <= 0) {
+ BIO_copy_next_retry(bio);
+ return ret;
+ }
+ uint64_t timeout = (static_cast<uint64_t>(buf[0]) << 56) |
+ (static_cast<uint64_t>(buf[1]) << 48) |
+ (static_cast<uint64_t>(buf[2]) << 40) |
+ (static_cast<uint64_t>(buf[3]) << 32) |
+ (static_cast<uint64_t>(buf[4]) << 24) |
+ (static_cast<uint64_t>(buf[5]) << 16) |
+ (static_cast<uint64_t>(buf[6]) << 8) |
+ static_cast<uint64_t>(buf[7]);
+ timeout /= 1000; // Convert nanoseconds to microseconds.
- // Read the length prefix.
- uint8_t len_bytes[4];
- ret = ReadAll(bio->next_bio, len_bytes, sizeof(len_bytes));
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- return ret;
- }
+ data->timeout.tv_usec = timeout % 1000000;
+ data->timeout.tv_sec = timeout / 1000000;
- uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) |
- (len_bytes[2] << 8) | len_bytes[3];
- uint8_t *buf = (uint8_t *)OPENSSL_malloc(len);
- if (buf == NULL) {
- return -1;
- }
- ret = ReadAll(bio->next_bio, buf, len);
- if (ret <= 0) {
- fprintf(stderr, "Packeted BIO was truncated\n");
- return -1;
- }
+ // Send an ACK to the peer.
+ ret = BIO_write(bio->next_bio, &kOpcodeTimeoutAck, 1);
+ if (ret <= 0) {
+ return ret;
+ }
+ assert(ret == 1);
- if (outl > (int)len) {
- outl = len;
+ if (!data->advance_clock) {
+ // Signal to the caller to retry the read, after advancing the clock.
+ BIO_set_retry_read(bio);
+ return -1;
+ }
+
+ PacketedBioAdvanceClock(bio);
+ continue;
+ }
+
+ if (opcode != kOpcodePacket) {
+ fprintf(stderr, "Unknown opcode, %u\n", opcode);
+ return -1;
+ }
+
+ // Read the length prefix.
+ uint8_t len_bytes[4];
+ ret = ReadAll(bio->next_bio, len_bytes, sizeof(len_bytes));
+ if (ret <= 0) {
+ BIO_copy_next_retry(bio);
+ return ret;
+ }
+
+ uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) |
+ (len_bytes[2] << 8) | len_bytes[3];
+ uint8_t *buf = (uint8_t *)OPENSSL_malloc(len);
+ if (buf == NULL) {
+ return -1;
+ }
+ ret = ReadAll(bio->next_bio, buf, len);
+ if (ret <= 0) {
+ fprintf(stderr, "Packeted BIO was truncated\n");
+ return -1;
+ }
+
+ if (outl > (int)len) {
+ outl = len;
+ }
+ memcpy(out, buf, outl);
+ OPENSSL_free(buf);
+ return outl;
}
- memcpy(out, buf, outl);
- OPENSSL_free(buf);
- return outl;
}
static long PacketedCtrl(BIO *bio, int cmd, long num, void *ptr) {
+ if (cmd == BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT) {
+ memcpy(&GetData(bio)->read_deadline, ptr, sizeof(timeval));
+ return 1;
+ }
+
if (bio->next_bio == NULL) {
return 0;
}
@@ -182,6 +245,7 @@ static int PacketedFree(BIO *bio) {
return 0;
}
+ delete GetData(bio);
bio->init = 0;
return 1;
}
@@ -208,11 +272,33 @@ const BIO_METHOD g_packeted_bio_method = {
} // namespace
-ScopedBIO PacketedBioCreate(timeval *out_timeout) {
+ScopedBIO PacketedBioCreate(bool advance_clock) {
ScopedBIO bio(BIO_new(&g_packeted_bio_method));
if (!bio) {
return nullptr;
}
- bio->ptr = out_timeout;
+ bio->ptr = new PacketedBio(advance_clock);
return bio;
}
+
+timeval PacketedBioGetClock(const BIO *bio) {
+ return GetData(bio)->clock;
+}
+
+bool PacketedBioAdvanceClock(BIO *bio) {
+ PacketedBio *data = GetData(bio);
+ if (data == nullptr) {
+ return false;
+ }
+
+ if (!data->HasTimeout()) {
+ return false;
+ }
+
+ data->clock.tv_usec += data->timeout.tv_usec;
+ data->clock.tv_sec += data->clock.tv_usec / 1000000;
+ data->clock.tv_usec %= 1000000;
+ data->clock.tv_sec += data->timeout.tv_sec;
+ memset(&data->timeout, 0, sizeof(data->timeout));
+ return true;
+}
diff --git a/ssl/test/packeted_bio.h b/ssl/test/packeted_bio.h
index 75cfa13b..9bab635a 100644
--- a/ssl/test/packeted_bio.h
+++ b/ssl/test/packeted_bio.h
@@ -21,24 +21,31 @@
#include "../../crypto/test/scoped_types.h"
#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#else
#include <sys/time.h>
#endif
// PacketedBioCreate creates a filter BIO which implements a reliable in-order
-// blocking datagram socket. The resulting BIO, on |BIO_read|, may simulate a
-// timeout which sets |*out_timeout| to the timeout and fails the read.
-// |*out_timeout| must be zero on entry to |BIO_read|; it is an error to not
-// apply the timeout before the next |BIO_read|.
+// blocking datagram socket. It internally maintains a clock and honors
+// |BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT| based on it.
//
-// Note: The read timeout simulation is intended to be used with the async BIO
-// wrapper. It doesn't simulate BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, used in DTLS's
-// blocking mode.
-ScopedBIO PacketedBioCreate(timeval *out_timeout);
+// During a |BIO_read|, the peer may signal the filter BIO to simulate a
+// timeout. If |advance_clock| is true, it automatically advances the clock and
+// continues reading, subject to the read deadline. Otherwise, it fails
+// immediately. The caller must then call |PacketedBioAdvanceClock| before
+// retrying |BIO_read|.
+ScopedBIO PacketedBioCreate(bool advance_clock);
+
+// PacketedBioGetClock returns the current time for |bio|.
+timeval PacketedBioGetClock(const BIO *bio);
+
+// PacketedBioAdvanceClock advances |bio|'s internal clock and returns true if
+// there is a pending timeout. Otherwise, it returns false.
+bool PacketedBioAdvanceClock(BIO *bio);
#endif // HEADER_PACKETED_BIO
diff --git a/ssl/test/runner/alert.go b/ssl/test/runner/alert.go
index 541216ed..7db68267 100644
--- a/ssl/test/runner/alert.go
+++ b/ssl/test/runner/alert.go
@@ -22,6 +22,7 @@ const (
alertRecordOverflow alert = 22
alertDecompressionFailure alert = 30
alertHandshakeFailure alert = 40
+ alertNoCertficate alert = 41
alertBadCertificate alert = 42
alertUnsupportedCertificate alert = 43
alertCertificateRevoked alert = 44
diff --git a/ssl/test/runner/chacha20_poly1305.go b/ssl/test/runner/chacha20_poly1305.go
index 3c6ad829..8b975459 100644
--- a/ssl/test/runner/chacha20_poly1305.go
+++ b/ssl/test/runner/chacha20_poly1305.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
package runner
import (
diff --git a/ssl/test/runner/chacha20_poly1305_test.go b/ssl/test/runner/chacha20_poly1305_test.go
index 4d19b8ce..8cecb5c8 100644
--- a/ssl/test/runner/chacha20_poly1305_test.go
+++ b/ssl/test/runner/chacha20_poly1305_test.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
package runner
import (
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index bfd31a58..26f51b06 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -43,6 +43,9 @@ const (
// client indicates that it supports ECC with a curve and point format
// that we're happy with.
suiteECDHE = 1 << iota
+ // suiteCECPQ1 indicates that the cipher suite uses the
+ // experimental, temporary, and non-standard CECPQ1 key agreement.
+ suiteCECPQ1
// suiteECDSA indicates that the cipher suite involves an ECDSA
// signature and therefore may only be selected when the server's
// certificate is ECDSA. If this is not set then the cipher suite is
@@ -104,6 +107,10 @@ var cipherSuites = []*cipherSuite{
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+ {TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+ {TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+ {TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
@@ -122,6 +129,8 @@ var cipherSuites = []*cipherSuite{
{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
{TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+ {TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
{TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
@@ -373,6 +382,15 @@ func ecdheECDSAKA(version uint16) keyAgreement {
}
}
+func cecpq1ECDSAKA(version uint16) keyAgreement {
+ return &cecpq1KeyAgreement{
+ auth: &signedKeyAgreement{
+ sigType: signatureECDSA,
+ version: version,
+ },
+ }
+}
+
func ecdheRSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
auth: &signedKeyAgreement{
@@ -382,6 +400,15 @@ func ecdheRSAKA(version uint16) keyAgreement {
}
}
+func cecpq1RSAKA(version uint16) keyAgreement {
+ return &cecpq1KeyAgreement{
+ auth: &signedKeyAgreement{
+ sigType: signatureRSA,
+ version: version,
+ },
+ }
+}
+
func dheRSAKA(version uint16) keyAgreement {
return &dheKeyAgreement{
auth: &signedKeyAgreement{
@@ -472,4 +499,10 @@ const (
const (
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc13
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc14
+ TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0xd001
+ TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0xd002
+ TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0x16b7
+ TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0x16b8
+ TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x16b9
+ TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0x16ba
)
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index f2ef3605..648807fc 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -424,6 +424,10 @@ type ProtocolBugs struct {
// to be wrong.
InvalidSKXCurve bool
+ // InvalidECDHPoint, if true, causes the ECC points in
+ // ServerKeyExchange or ClientKeyExchange messages to be invalid.
+ InvalidECDHPoint bool
+
// BadECDSAR controls ways in which the 'r' value of an ECDSA signature
// can be invalid.
BadECDSAR BadValue
@@ -469,6 +473,10 @@ type ProtocolBugs struct {
// NewSessionTicket message despite promising to in ServerHello.
SkipNewSessionTicket bool
+ // SkipClientCertificate causes the client to skip the Certificate
+ // message.
+ SkipClientCertificate bool
+
// SkipChangeCipherSpec causes the implementation to skip
// sending the ChangeCipherSpec message (and adjusting cipher
// state accordingly for the Finished message).
@@ -517,6 +525,10 @@ type ProtocolBugs struct {
// two records.
FragmentAlert bool
+ // DoubleAlert will cause all alerts to be sent as two copies packed
+ // within one record.
+ DoubleAlert bool
+
// SendSpuriousAlert, if non-zero, will cause an spurious, unwanted
// alert to be sent.
SendSpuriousAlert alert
@@ -775,6 +787,10 @@ type ProtocolBugs struct {
// on connection shutdown.
NoCloseNotify bool
+ // SendAlertOnShutdown, if non-zero, is the alert to send instead of
+ // close_notify on shutdown.
+ SendAlertOnShutdown alert
+
// ExpectCloseNotify, if true, requires a close_notify from the peer on
// shutdown. Records from the peer received after close_notify is sent
// are not discard.
@@ -818,6 +834,22 @@ type ProtocolBugs struct {
// RequireSessionTickets, if true, causes the client to require new
// sessions use session tickets instead of session IDs.
RequireSessionTickets bool
+
+ // NullAllCiphers, if true, causes every cipher to behave like the null
+ // cipher.
+ NullAllCiphers bool
+
+ // SendSCTListOnResume, if not nil, causes the server to send the
+ // supplied SCT list in resumption handshakes.
+ SendSCTListOnResume []byte
+
+ // CECPQ1BadX25519Part corrupts the X25519 part of a CECPQ1 key exchange, as
+ // a trivial proof that it is actually used.
+ CECPQ1BadX25519Part bool
+
+ // CECPQ1BadNewhopePart corrupts the Newhope part of a CECPQ1 key exchange,
+ // as a trivial proof that it is actually used.
+ CECPQ1BadNewhopePart bool
}
func (c *Config) serverInit() {
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index cb60a928..3913995b 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -189,6 +189,11 @@ func (hc *halfConn) changeCipherSpec(config *Config) error {
hc.nextMac = nil
hc.config = config
hc.incEpoch()
+
+ if config.Bugs.NullAllCiphers {
+ hc.cipher = nil
+ hc.mac = nil
+ }
return nil
}
@@ -837,6 +842,9 @@ func (c *Conn) sendAlertLocked(level byte, err alert) error {
if c.config.Bugs.FragmentAlert {
c.writeRecord(recordTypeAlert, c.tmp[0:1])
c.writeRecord(recordTypeAlert, c.tmp[1:2])
+ } else if c.config.Bugs.DoubleAlert {
+ copy(c.tmp[2:4], c.tmp[0:2])
+ c.writeRecord(recordTypeAlert, c.tmp[0:4])
} else {
c.writeRecord(recordTypeAlert, c.tmp[0:2])
}
@@ -851,7 +859,7 @@ func (c *Conn) sendAlertLocked(level byte, err alert) error {
// L < c.out.Mutex.
func (c *Conn) sendAlert(err alert) error {
level := byte(alertLevelError)
- if err == alertNoRenegotiation || err == alertCloseNotify {
+ if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertficate {
level = alertLevelWarning
}
return c.SendAlert(level, err)
@@ -1284,7 +1292,16 @@ func (c *Conn) Close() error {
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
if c.handshakeComplete && !c.config.Bugs.NoCloseNotify {
- alertErr = c.sendAlert(alertCloseNotify)
+ alert := alertCloseNotify
+ if c.config.Bugs.SendAlertOnShutdown != 0 {
+ alert = c.config.Bugs.SendAlertOnShutdown
+ }
+ alertErr = c.sendAlert(alert)
+ // Clear local alerts when sending alerts so we continue to wait
+ // for the peer rather than closing the socket early.
+ if opErr, ok := alertErr.(*net.OpError); ok && opErr.Op == "local error" {
+ alertErr = nil
+ }
}
// Consume a close_notify from the peer if one hasn't been received
diff --git a/ssl/test/runner/deterministic.go b/ssl/test/runner/deterministic.go
new file mode 100644
index 00000000..4a61ee0a
--- /dev/null
+++ b/ssl/test/runner/deterministic.go
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package runner
+
+import (
+ "encoding/binary"
+)
+
+// Use a different key from crypto/rand/deterministic.c.
+var deterministicRandKey = []byte("runner deterministic key 0123456")
+
+type deterministicRand struct {
+ numCalls uint64
+}
+
+func (d *deterministicRand) Read(buf []byte) (int, error) {
+ for i := range buf {
+ buf[i] = 0
+ }
+ var nonce [12]byte
+ binary.LittleEndian.PutUint64(nonce[:8], d.numCalls)
+ chaCha20(buf, buf, deterministicRandKey, nonce[:], 0)
+ d.numCalls++
+ return len(buf), nil
+}
diff --git a/ssl/test/runner/dtls.go b/ssl/test/runner/dtls.go
index c3ee5218..a31dfc00 100644
--- a/ssl/test/runner/dtls.go
+++ b/ssl/test/runner/dtls.go
@@ -46,6 +46,7 @@ func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
b := c.rawInput
// Read a new packet only if the current one is empty.
+ var newPacket bool
if len(b.data) == 0 {
// Pick some absurdly large buffer size.
b.resize(maxCiphertext + recordHeaderLen)
@@ -57,6 +58,7 @@ func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length")
}
c.rawInput.resize(n)
+ newPacket = true
}
// Read out one record.
@@ -108,6 +110,13 @@ func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
c.in.setErrorLocked(c.sendAlert(err))
}
b.off = off
+
+ // Require that ChangeCipherSpec always share a packet with either the
+ // previous or next handshake message.
+ if newPacket && typ == recordTypeChangeCipherSpec && c.rawInput == nil {
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: ChangeCipherSpec not packed together with Finished"))
+ }
+
return typ, b, nil
}
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 1f52dcee..67609fcd 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -564,15 +564,20 @@ func (hs *clientHandshakeState) doFullHandshake() error {
hs.writeServerHash(shd.marshal())
// If the server requested a certificate then we have to send a
- // Certificate message, even if it's empty because we don't have a
- // certificate to send.
+ // Certificate message in TLS, even if it's empty because we don't have
+ // a certificate to send. In SSL 3.0, skip the message and send a
+ // no_certificate warning alert.
if certRequested {
- certMsg := new(certificateMsg)
- if chainToSend != nil {
- certMsg.certificates = chainToSend.Certificate
+ if c.vers == VersionSSL30 && chainToSend == nil {
+ c.sendAlert(alertNoCertficate)
+ } else if !c.config.Bugs.SkipClientCertificate {
+ certMsg := new(certificateMsg)
+ if chainToSend != nil {
+ certMsg.certificates = chainToSend.Certificate
+ }
+ hs.writeClientHash(certMsg.marshal())
+ c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
- hs.writeClientHash(certMsg.marshal())
- c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 0232772f..72d1eb99 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -488,6 +488,10 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
hs.hello.sessionId = hs.clientHello.sessionId
hs.hello.ticketSupported = c.config.Bugs.RenewTicketOnResume
+ if c.config.Bugs.SendSCTListOnResume != nil {
+ hs.hello.sctList = c.config.Bugs.SendSCTListOnResume
+ }
+
hs.finishedHash = newFinishedHash(c.vers, hs.suite)
hs.finishedHash.discardHandshakeBuffer()
hs.writeClientHash(hs.clientHello.marshal())
@@ -626,13 +630,22 @@ func (hs *serverHandshakeState) doFullHandshake() error {
// certificate message, even if it's empty.
if config.ClientAuth >= RequestClientCert {
var certMsg *certificateMsg
- if certMsg, ok = msg.(*certificateMsg); !ok {
+ var certificates [][]byte
+ if certMsg, ok = msg.(*certificateMsg); ok {
+ if c.vers == VersionSSL30 && len(certMsg.certificates) == 0 {
+ return errors.New("tls: empty certificate message in SSL 3.0")
+ }
+
+ hs.writeClientHash(certMsg.marshal())
+ certificates = certMsg.certificates
+ } else if c.vers != VersionSSL30 {
+ // In TLS, the Certificate message is required. In SSL
+ // 3.0, the peer skips it when sending no certificates.
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certMsg, msg)
}
- hs.writeClientHash(certMsg.marshal())
- if len(certMsg.certificates) == 0 {
+ if len(certificates) == 0 {
// The client didn't actually send a certificate
switch config.ClientAuth {
case RequireAnyClientCert, RequireAndVerifyClientCert:
@@ -641,14 +654,16 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
}
- pub, err = hs.processCertsFromClient(certMsg.certificates)
+ pub, err = hs.processCertsFromClient(certificates)
if err != nil {
return err
}
- msg, err = c.readHandshake()
- if err != nil {
- return err
+ if ok {
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
}
}
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 9ecd2e56..5e5d976d 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -21,6 +21,7 @@ import (
"math/big"
"./curve25519"
+ "./newhope"
)
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
@@ -252,13 +253,16 @@ func pickTLS12HashForSignature(sigType uint8, clientList, serverList []signature
// A ecdhCurve is an instance of ECDH-style key agreement for TLS.
type ecdhCurve interface {
- // generateKeypair generates a keypair using rand. It returns the
- // encoded public key.
- generateKeypair(rand io.Reader) (publicKey []byte, err error)
+ // offer generates a keypair using rand. It returns the encoded |publicKey|.
+ offer(rand io.Reader) (publicKey []byte, err error)
- // computeSecret performs a key exchange against peerKey and returns
- // the resulting shared secret.
- computeSecret(peerKey []byte) (preMasterSecret []byte, err error)
+ // accept responds to the |peerKey| generated by |offer| with the acceptor's
+ // |publicKey|, and returns agreed-upon |preMasterSecret| to the acceptor.
+ accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error)
+
+ // finish returns the computed |preMasterSecret|, given the |peerKey|
+ // generated by |accept|.
+ finish(peerKey []byte) (preMasterSecret []byte, err error)
}
// ellipticECDHCurve implements ecdhCurve with an elliptic.Curve.
@@ -267,7 +271,7 @@ type ellipticECDHCurve struct {
privateKey []byte
}
-func (e *ellipticECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err error) {
+func (e *ellipticECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
var x, y *big.Int
e.privateKey, x, y, err = elliptic.GenerateKey(e.curve, rand)
if err != nil {
@@ -276,7 +280,19 @@ func (e *ellipticECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, e
return elliptic.Marshal(e.curve, x, y), nil
}
-func (e *ellipticECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte, err error) {
+func (e *ellipticECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ publicKey, err = e.offer(rand)
+ if err != nil {
+ return nil, nil, err
+ }
+ preMasterSecret, err = e.finish(peerKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ return
+}
+
+func (e *ellipticECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
x, y := elliptic.Unmarshal(e.curve, peerKey)
if x == nil {
return nil, errors.New("tls: invalid peer key")
@@ -294,7 +310,7 @@ type x25519ECDHCurve struct {
privateKey [32]byte
}
-func (e *x25519ECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err error) {
+func (e *x25519ECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
_, err = io.ReadFull(rand, e.privateKey[:])
if err != nil {
return
@@ -304,7 +320,19 @@ func (e *x25519ECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err
return out[:], nil
}
-func (e *x25519ECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte, err error) {
+func (e *x25519ECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ publicKey, err = e.offer(rand)
+ if err != nil {
+ return nil, nil, err
+ }
+ preMasterSecret, err = e.finish(peerKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ return
+}
+
+func (e *x25519ECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
if len(peerKey) != 32 {
return nil, errors.New("tls: invalid peer key")
}
@@ -321,6 +349,66 @@ func (e *x25519ECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte,
return out[:], nil
}
+// cecpq1Curve is combined elliptic curve (X25519) and post-quantum (new hope) key
+// agreement.
+type cecpq1Curve struct {
+ x25519 *x25519ECDHCurve
+ newhope *newhope.Poly
+}
+
+func (e *cecpq1Curve) offer(rand io.Reader) (publicKey []byte, err error) {
+ var x25519OfferMsg, newhopeOfferMsg []byte
+
+ e.x25519 = new(x25519ECDHCurve)
+ if x25519OfferMsg, err = e.x25519.offer(rand); err != nil {
+ return nil, err
+ }
+
+ newhopeOfferMsg, e.newhope = newhope.Offer(rand)
+
+ return append(x25519OfferMsg, newhopeOfferMsg[:]...), nil
+}
+
+func (e *cecpq1Curve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+newhope.OfferMsgLen {
+ return nil, nil, errors.New("cecpq1: invalid offer message")
+ }
+
+ var x25519AcceptMsg, newhopeAcceptMsg []byte
+ var x25519Secret []byte
+ var newhopeSecret newhope.Key
+
+ x25519 := new(x25519ECDHCurve)
+ if x25519AcceptMsg, x25519Secret, err = x25519.accept(rand, peerKey[:32]); err != nil {
+ return nil, nil, err
+ }
+
+ if newhopeSecret, newhopeAcceptMsg, err = newhope.Accept(rand, peerKey[32:]); err != nil {
+ return nil, nil, err
+ }
+
+ return append(x25519AcceptMsg, newhopeAcceptMsg[:]...), append(x25519Secret, newhopeSecret[:]...), nil
+}
+
+func (e *cecpq1Curve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+newhope.AcceptMsgLen {
+ return nil, errors.New("cecpq1: invalid accept message")
+ }
+
+ var x25519Secret []byte
+ var newhopeSecret newhope.Key
+
+ if x25519Secret, err = e.x25519.finish(peerKey[:32]); err != nil {
+ return nil, err
+ }
+
+ if newhopeSecret, err = e.newhope.Finish(peerKey[32:]); err != nil {
+ return nil, err
+ }
+
+ return append(x25519Secret, newhopeSecret[:]...), nil
+}
+
func curveForCurveID(id CurveID) (ecdhCurve, bool) {
switch id {
case CurveP224:
@@ -551,7 +639,7 @@ NextCandidate:
return nil, errors.New("tls: preferredCurves includes unsupported curve")
}
- publicKey, err := ka.curve.generateKeypair(config.rand())
+ publicKey, err := ka.curve.offer(config.rand())
if err != nil {
return nil, err
}
@@ -566,6 +654,9 @@ NextCandidate:
}
serverECDHParams[3] = byte(len(publicKey))
copy(serverECDHParams[4:], publicKey)
+ if config.Bugs.InvalidECDHPoint {
+ serverECDHParams[4] ^= 0xff
+ }
return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
}
@@ -574,7 +665,7 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errClientKeyExchange
}
- return ka.curve.computeSecret(ckx.ciphertext[1:])
+ return ka.curve.finish(ckx.ciphertext[1:])
}
func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
@@ -609,11 +700,7 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
return nil, nil, errors.New("missing ServerKeyExchange message")
}
- publicKey, err := ka.curve.generateKeypair(config.rand())
- if err != nil {
- return nil, nil, err
- }
- preMasterSecret, err := ka.curve.computeSecret(ka.peerKey)
+ publicKey, preMasterSecret, err := ka.curve.accept(config.rand(), ka.peerKey)
if err != nil {
return nil, nil, err
}
@@ -622,6 +709,100 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
ckx.ciphertext = make([]byte, 1+len(publicKey))
ckx.ciphertext[0] = byte(len(publicKey))
copy(ckx.ciphertext[1:], publicKey)
+ if config.Bugs.InvalidECDHPoint {
+ ckx.ciphertext[1] ^= 0xff
+ }
+
+ return preMasterSecret, ckx, nil
+}
+
+// cecpq1RSAKeyAgreement is like an ecdheKeyAgreement, but using the cecpq1Curve
+// pseudo-curve, and without any parameters (e.g. curve name) other than the
+// keys being exchanged. The signature may either be ECDSA or RSA.
+type cecpq1KeyAgreement struct {
+ auth keyAgreementAuthentication
+ curve ecdhCurve
+ peerKey []byte
+}
+
+func (ka *cecpq1KeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ ka.curve = &cecpq1Curve{}
+ publicKey, err := ka.curve.offer(config.rand())
+ if err != nil {
+ return nil, err
+ }
+
+ if config.Bugs.CECPQ1BadX25519Part {
+ publicKey[0] ^= 1
+ }
+ if config.Bugs.CECPQ1BadNewhopePart {
+ publicKey[32] ^= 1
+ publicKey[33] ^= 1
+ publicKey[34] ^= 1
+ publicKey[35] ^= 1
+ }
+
+ var params []byte
+ params = append(params, byte(len(publicKey)>>8))
+ params = append(params, byte(len(publicKey)&0xff))
+ params = append(params, publicKey[:]...)
+
+ return ka.auth.signParameters(config, cert, clientHello, hello, params)
+}
+
+func (ka *cecpq1KeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ if len(ckx.ciphertext) < 2 {
+ return nil, errClientKeyExchange
+ }
+ peerKeyLen := int(ckx.ciphertext[0])<<8 + int(ckx.ciphertext[1])
+ peerKey := ckx.ciphertext[2:]
+ if peerKeyLen != len(peerKey) {
+ return nil, errClientKeyExchange
+ }
+ return ka.curve.finish(peerKey)
+}
+
+func (ka *cecpq1KeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) < 2 {
+ return errServerKeyExchange
+ }
+ peerKeyLen := int(skx.key[0])<<8 + int(skx.key[1])
+ // Save the peer key for later.
+ if len(skx.key) < 2+peerKeyLen {
+ return errServerKeyExchange
+ }
+ ka.peerKey = skx.key[2 : 2+peerKeyLen]
+ if peerKeyLen != len(ka.peerKey) {
+ return errServerKeyExchange
+ }
+
+ // Check the signature.
+ params := skx.key[:2+peerKeyLen]
+ sig := skx.key[2+peerKeyLen:]
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, params, sig)
+}
+
+func (ka *cecpq1KeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ curve := &cecpq1Curve{}
+ publicKey, preMasterSecret, err := curve.accept(config.rand(), ka.peerKey)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if config.Bugs.CECPQ1BadX25519Part {
+ publicKey[0] ^= 1
+ }
+ if config.Bugs.CECPQ1BadNewhopePart {
+ publicKey[32] ^= 1
+ publicKey[33] ^= 1
+ publicKey[34] ^= 1
+ publicKey[35] ^= 1
+ }
+
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)>>8))
+ ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)&0xff))
+ ckx.ciphertext = append(ckx.ciphertext, publicKey[:]...)
return preMasterSecret, ckx, nil
}
diff --git a/ssl/test/runner/newhope/newhope.go b/ssl/test/runner/newhope/newhope.go
new file mode 100644
index 00000000..8f7a5308
--- /dev/null
+++ b/ssl/test/runner/newhope/newhope.go
@@ -0,0 +1,319 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+// package newhope contains a post-quantum key agreement algorithm,
+// reimplemented from the reference implementation at
+// https://github.com/tpoeppelmann/newhope.
+//
+// Note that this package does not interoperate with the reference
+// implementation.
+package newhope
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "errors"
+ "io"
+)
+
+const (
+ // q is the prime that defines the field.
+ q = 12289
+ // n is the number of coefficients in polynomials.
+ n = 1024
+ // k is the width of the noise distribution.
+ k = 16
+
+ // These values are used in the NTT calculation. See the paper for
+ // details about their origins.
+ omega = 49
+ invOmega = 1254
+ sqrtOmega = 7
+ invSqrtOmega = 8778
+ invN = 12277
+
+ // encodedPolyLen is the length, in bytes, of an encoded polynomial. The
+ // encoding uses 14 bits per coefficient.
+ encodedPolyLen = (n * 14) / 8
+
+ // offerMsgLen is the length, in bytes, of the offering (first) message of
+ // the key exchange.
+ OfferMsgLen = encodedPolyLen + 32
+
+ // acceptMsgLen is the length, in bytes, of the accepting (second) message
+ // of the key exchange.
+ AcceptMsgLen = encodedPolyLen + 256
+)
+
+// count16Bits returns the number of '1' bits in v.
+func count16Bits(v uint16) (sum uint16) {
+ for i := 0; i < 16; i++ {
+ sum += v & 1
+ v >>= 1
+ }
+
+ return sum
+}
+
+// Poly is a polynomial of n coefficients.
+type Poly [n]uint16
+
+// Key is the result of a key agreement.
+type Key [32]uint8
+
+// sampleNoise returns a random polynomial where the coefficients are
+// drawn from the noise distribution.
+func sampleNoise(rand io.Reader) *Poly {
+ poly := new(Poly)
+ buf := make([]byte, 4)
+
+ for i := range poly {
+ if _, err := io.ReadFull(rand, buf); err != nil {
+ panic(err)
+ }
+ a := count16Bits(uint16(buf[0])<<8 | uint16(buf[1]))
+ b := count16Bits(uint16(buf[2])<<8 | uint16(buf[3]))
+ poly[i] = (q + a - b) % q
+ }
+
+ return poly
+}
+
+// randomPolynomial returns a random polynomial where the coefficients are
+// drawn uniformly at random from the underlying field.
+func randomPolynomial(rand io.Reader) *Poly {
+ poly := new(Poly)
+
+ buf := make([]byte, 2)
+ for i := range poly {
+ for {
+ if _, err := io.ReadFull(rand, buf); err != nil {
+ panic(err)
+ }
+
+ v := uint16(buf[1])<<8 | uint16(buf[0])
+ v &= 0x3fff
+
+ if v < q {
+ poly[i] = v
+ break
+ }
+ }
+ }
+
+ return poly
+}
+
+type zeroReader struct {
+ io.Reader
+}
+
+func (z *zeroReader) Read(dst []byte) (n int, err error) {
+ for i := range dst {
+ dst[i] = 0
+ }
+ return len(dst), nil
+}
+
+// seedToPolynomial uses AES-CTR to generate a pseudo-random polynomial given a
+// 32-byte seed.
+func seedToPolynomial(seed []byte) *Poly {
+ aes, err := aes.NewCipher(seed[0:16])
+ if err != nil {
+ panic(err)
+ }
+ stream := cipher.NewCTR(aes, seed[16:32])
+ reader := &cipher.StreamReader{S: stream, R: &zeroReader{}}
+ return randomPolynomial(reader)
+}
+
+// forwardNTT converts |in| into the frequency domain.
+func forwardNTT(in *Poly) *Poly {
+ return ntt(in, omega, sqrtOmega, 1, 1)
+}
+
+// inverseNTT converts |in| into the time domain.
+func inverseNTT(in *Poly) *Poly {
+ return ntt(in, invOmega, 1, invSqrtOmega, invN)
+}
+
+// ntt performs the number-theoretic transform (a discrete Fourier transform in
+// a field) on in. Significant magic is in effect here. See the paper for the
+// details of how this works.
+func ntt(in *Poly, omega, preScaleBase, postScaleBase, postScale uint16) *Poly {
+ out := new(Poly)
+ omega_to_the_i := uint64(1)
+
+ for i := range out {
+ omegaToTheIJ := uint64(1)
+ preScale := uint64(1)
+ sum := uint64(0)
+
+ for j := range in {
+ t := (uint64(in[j]) * preScale) % q
+ sum += (t * omegaToTheIJ) % q
+ omegaToTheIJ = (omegaToTheIJ * omega_to_the_i) % q
+ preScale = (uint64(preScaleBase) * preScale) % q
+ }
+
+ out[i] = uint16((sum * uint64(postScale)) % q)
+
+ omega_to_the_i = (omega_to_the_i * uint64(omega)) % q
+ postScale = uint16((uint64(postScale) * uint64(postScaleBase)) % q)
+ }
+
+ return out
+}
+
+// encodeRec encodes the reconciliation data compactly, for use in the accept
+// message.
+func encodeRec(rec *reconciliationData) []byte {
+ var ret [n / 4]byte
+
+ for i := 0; i < n/4; i++ {
+ ret[i] = rec[4*i] | rec[4*i+1]<<2 | rec[4*i+2]<<4 | rec[4*i+3]<<6
+ }
+
+ return ret[:]
+}
+
+// decodeRec decodes reconciliation data from the accept message.
+func decodeRec(message []byte) (rec *reconciliationData) {
+ rec = new(reconciliationData)
+
+ for i, b := range message {
+ rec[4*i] = b & 0x03
+ rec[4*i+1] = (b >> 2) & 0x3
+ rec[4*i+2] = (b >> 4) & 0x3
+ rec[4*i+3] = b >> 6
+ }
+
+ return rec
+}
+
+// encodePoly returns a byte array that encodes a polynomial compactly, with 14
+// bits per coefficient.
+func encodePoly(poly *Poly) []byte {
+ ret := make([]byte, encodedPolyLen)
+
+ for i := 0; i < n/4; i++ {
+ t0 := poly[4*i]
+ t1 := poly[4*i+1]
+ t2 := poly[4*i+2]
+ t3 := poly[4*i+3]
+
+ ret[7*i] = byte(t0)
+ ret[7*i+1] = byte(t0>>8) | byte(t1<<6)
+ ret[7*i+2] = byte(t1 >> 2)
+ ret[7*i+3] = byte(t1>>10) | byte(t2<<4)
+ ret[7*i+4] = byte(t2 >> 4)
+ ret[7*i+5] = byte(t2>>12) | byte(t3<<2)
+ ret[7*i+6] = byte(t3 >> 6)
+ }
+
+ return ret
+}
+
+// decodePoly inverts encodePoly.
+func decodePoly(encoded []byte) *Poly {
+ ret := new(Poly)
+
+ for i := 0; i < n/4; i++ {
+ ret[4*i] = uint16(encoded[7*i]) | uint16(encoded[7*i+1]&0x3f)<<8
+ ret[4*i+1] = uint16(encoded[7*i+1])>>6 | uint16(encoded[7*i+2])<<2 | uint16(encoded[7*i+3]&0x0f)<<10
+ ret[4*i+2] = uint16(encoded[7*i+3])>>4 | uint16(encoded[7*i+4])<<4 | uint16(encoded[7*i+5]&0x03)<<12
+ ret[4*i+3] = uint16(encoded[7*i+5])>>2 | uint16(encoded[7*i+6])<<6
+ }
+
+ return ret
+}
+
+// Offer starts a new key exchange. It returns a message that should be
+// transmitted to the peer, and a polynomial that must be retained in order to
+// complete the exchange.
+func Offer(rand io.Reader) (offerMsg []byte, sFreq *Poly) {
+ seed := make([]byte, 32)
+
+ if _, err := io.ReadFull(rand, seed); err != nil {
+ panic(err)
+ }
+
+ aFreq := seedToPolynomial(seed)
+ sFreq = forwardNTT(sampleNoise(rand))
+ eFreq := forwardNTT(sampleNoise(rand))
+
+ bFreq := new(Poly)
+ for i := range bFreq {
+ bFreq[i] = uint16((uint64(sFreq[i])*uint64(aFreq[i]) + uint64(eFreq[i])) % q)
+ }
+
+ offerMsg = encodePoly(bFreq)
+ offerMsg = append(offerMsg, seed[:]...)
+ return offerMsg, sFreq
+}
+
+// Accept processes a message generated by |Offer| and returns a reply message
+// and the shared key.
+func Accept(rand io.Reader, offerMsg []byte) (sharedKey Key, acceptMsg []byte, err error) {
+ if len(offerMsg) != OfferMsgLen {
+ return sharedKey, nil, errors.New("newhope: offer message has incorrect length")
+ }
+
+ bFreq := decodePoly(offerMsg)
+ seed := offerMsg[encodedPolyLen:]
+
+ aFreq := seedToPolynomial(seed)
+ sPrimeFreq := forwardNTT(sampleNoise(rand))
+ ePrimeFreq := forwardNTT(sampleNoise(rand))
+
+ uFreq := new(Poly)
+ for i := range uFreq {
+ uFreq[i] = uint16((uint64(sPrimeFreq[i])*uint64(aFreq[i]) + uint64(ePrimeFreq[i])) % q)
+ }
+
+ vFreq := new(Poly)
+ for i := range vFreq {
+ vFreq[i] = uint16((uint64(sPrimeFreq[i]) * uint64(bFreq[i])) % q)
+ }
+
+ v := inverseNTT(vFreq)
+ ePrimePrime := sampleNoise(rand)
+ for i := range v {
+ v[i] = uint16((uint64(v[i]) + uint64(ePrimePrime[i])) % q)
+ }
+
+ rec := helprec(rand, v)
+
+ sharedKey = reconcile(v, rec)
+ acceptMsg = encodePoly(uFreq)
+ acceptMsg = append(acceptMsg, encodeRec(rec)[:]...)
+ return sharedKey, acceptMsg, nil
+}
+
+// Finish processes the reply from the peer and returns the shared key.
+func (sk *Poly) Finish(acceptMsg []byte) (sharedKey Key, err error) {
+ if len(acceptMsg) != AcceptMsgLen {
+ return sharedKey, errors.New("newhope: accept message has incorrect length")
+ }
+
+ uFreq := decodePoly(acceptMsg[:encodedPolyLen])
+ rec := decodeRec(acceptMsg[encodedPolyLen:])
+
+ for i, u := range uFreq {
+ uFreq[i] = uint16((uint64(u) * uint64(sk[i])) % q)
+ }
+ u := inverseNTT(uFreq)
+
+ return reconcile(u, rec), nil
+}
diff --git a/ssl/test/runner/newhope/newhope_test.go b/ssl/test/runner/newhope/newhope_test.go
new file mode 100644
index 00000000..31e95c7e
--- /dev/null
+++ b/ssl/test/runner/newhope/newhope_test.go
@@ -0,0 +1,154 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package newhope
+
+import (
+ "bytes"
+ "crypto/rand"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "testing"
+)
+
+func TestNTTRoundTrip(t *testing.T) {
+ var a Poly
+ for i := range a {
+ a[i] = uint16(i)
+ }
+
+ frequency := forwardNTT(&a)
+ original := inverseNTT(frequency)
+
+ for i, v := range a {
+ if v != original[i] {
+ t.Errorf("NTT didn't invert correctly: original[%d] = %d", i, original[i])
+ break
+ }
+ }
+}
+
+func TestNTTInv(t *testing.T) {
+ var a Poly
+ for i := range a {
+ a[i] = uint16(i)
+ }
+
+ result := ntt(&a, invOmega, 1, invSqrtOmega, invN)
+ if result[0] != 6656 || result[1] != 1792 || result[2] != 1234 {
+ t.Errorf("NTT^-1 gave bad result: %v", result[:8])
+ }
+}
+
+func disabledTestNoise(t *testing.T) {
+ var buckets [1 + 2*k]int
+ numSamples := 100
+
+ for i := 0; i < numSamples; i++ {
+ noise := sampleNoise(rand.Reader)
+ for _, v := range noise {
+ value := (int(v) + k) % q
+ buckets[value]++
+ }
+ }
+
+ sum := 0
+ squareSum := 0
+
+ for i, count := range buckets {
+ sum += (i - k) * count
+ squareSum += (i - k) * (i - k) * count
+ }
+
+ mean := float64(sum) / float64(n*numSamples)
+ if mean < -0.5 || 0.5 < mean {
+ t.Errorf("mean out of range: %f", mean)
+ }
+
+ expectedVariance := 0.5 * 0.5 * float64(k*2) // I think?
+ variance := float64(squareSum)/float64(n*numSamples) - mean*mean
+
+ if variance < expectedVariance-1.0 || expectedVariance+1.0 < variance {
+ t.Errorf("variance out of range: got %f, want %f", variance, expectedVariance)
+ }
+
+ file, err := ioutil.TempFile("", "noise")
+ fmt.Printf("writing noise to %s\n", file.Name())
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, count := range buckets {
+ dots := ""
+ for i := 0; i < count/(3*numSamples); i++ {
+ dots += "++"
+ }
+ fmt.Fprintf(file, "%+d\t%d\t%s\n", i-k, count, dots)
+ }
+ file.Close()
+}
+
+func TestSeedToPolynomial(t *testing.T) {
+ seed := make([]byte, 32)
+ seed[0] = 1
+ seed[31] = 2
+
+ poly := seedToPolynomial(seed)
+ if poly[0] != 3313 || poly[1] != 9277 || poly[2] != 11020 {
+ t.Errorf("bad result: %v", poly[:3])
+ }
+}
+
+func TestEncodeDecodePoly(t *testing.T) {
+ poly := randomPolynomial(rand.Reader)
+ poly2 := decodePoly(encodePoly(poly))
+ if *poly != *poly2 {
+ t.Errorf("decodePoly(encodePoly) isn't the identity function")
+ }
+}
+
+func TestEncodeDecodeRec(t *testing.T) {
+ var r reconciliationData
+ if _, err := io.ReadFull(rand.Reader, r[:]); err != nil {
+ panic(err)
+ }
+ for i := range r {
+ r[i] &= 3
+ }
+
+ encoded := encodeRec(&r)
+ decoded := decodeRec(encoded)
+
+ if *decoded != r {
+ t.Errorf("bad decode of rec")
+ }
+}
+
+func TestExchange(t *testing.T) {
+ for count := 0; count < 64; count++ {
+ offerMsg, state := Offer(rand.Reader)
+ sharedKey1, acceptMsg, err := Accept(rand.Reader, offerMsg)
+ if err != nil {
+ t.Errorf("Accept: %v", err)
+ }
+ sharedKey2, err := state.Finish(acceptMsg)
+ if err != nil {
+ t.Fatal("Finish: %v", err)
+ }
+
+ if !bytes.Equal(sharedKey1[:], sharedKey2[:]) {
+ t.Fatalf("keys mismatched on iteration %d: %x vs %x", count, sharedKey1, sharedKey2)
+ }
+ }
+}
diff --git a/ssl/test/runner/newhope/reconciliation.go b/ssl/test/runner/newhope/reconciliation.go
new file mode 100644
index 00000000..07479fe7
--- /dev/null
+++ b/ssl/test/runner/newhope/reconciliation.go
@@ -0,0 +1,132 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package newhope
+
+// This file contains the reconciliation algorithm for NewHope. This is simply a
+// monkey-see-monkey-do version of the reference code, with the exception that
+// the key resulting from reconciliation is whitened with SHA2 rather than SHA3.
+//
+// Thanks to the authors of the reference code for allowing us to release this
+// under the BoringSSL license.
+
+import (
+ "crypto/sha256"
+ "io"
+)
+
+func abs(v int32) int32 {
+ mask := v >> 31
+ return (v ^ mask) - mask
+}
+
+func f(x int32) (v0, v1, k int32) {
+ // Next 6 lines compute t = x/q;
+ b := x * 2730
+ t := b >> 25
+ b = x - t*12289
+ b = 12288 - b
+ b >>= 31
+ t -= b
+
+ r := t & 1
+ xit := (t >> 1)
+ v0 = xit + r // v0 = round(x/(2*q))
+
+ t -= 1
+ r = t & 1
+ v1 = (t >> 1) + r
+
+ k = abs(x - (v0 * 2 * q))
+ return
+}
+
+// reconciliationData is the data needed for reconciliation. There are 2 bits
+// per coefficient; this is the unpacked form.
+type reconciliationData [n]uint8
+
+func helprec(rand io.Reader, v *Poly) *reconciliationData {
+ var randBits [n / (4 * 8)]byte
+ if _, err := io.ReadFull(rand, randBits[:]); err != nil {
+ panic(err)
+ }
+
+ ret := new(reconciliationData)
+
+ for i := uint(0); i < n/4; i++ {
+ rbit := int32((randBits[i>>3] >> (i & 7)) & 1)
+
+ a0, b0, k0 := f(8*int32(v[i]) + 4*rbit)
+ a1, b1, k1 := f(8*int32(v[256+i]) + 4*rbit)
+ a2, b2, k2 := f(8*int32(v[512+i]) + 4*rbit)
+ a3, b3, k3 := f(8*int32(v[768+i]) + 4*rbit)
+
+ k := (2*q - 1 - (k0 + k1 + k2 + k3)) >> 31
+
+ v0 := ((^k) & a0) ^ (k & b0)
+ v1 := ((^k) & a1) ^ (k & b1)
+ v2 := ((^k) & a2) ^ (k & b2)
+ v3 := ((^k) & a3) ^ (k & b3)
+
+ ret[i] = uint8((v0 - v3) & 3)
+ ret[i+256] = uint8((v1 - v3) & 3)
+ ret[i+512] = uint8((v2 - v3) & 3)
+ ret[i+768] = uint8((-k + 2*v3) & 3)
+ }
+
+ return ret
+}
+
+func g(x int32) int32 {
+ // Next 6 lines compute t = x/(4*q);
+ b := x * 2730
+ t := b >> 27
+ b = x - t*49156
+ b = 49155 - b
+ b >>= 31
+ t -= b
+
+ c := t & 1
+ t = (t >> 1) + c // t = round(x/(8*q))
+
+ t *= 8 * q
+
+ return abs(t - x)
+}
+
+func ldDecode(xi0, xi1, xi2, xi3 int32) uint8 {
+ t := g(xi0)
+ t += g(xi1)
+ t += g(xi2)
+ t += g(xi3)
+
+ t -= 8 * q
+ t >>= 31
+ return uint8(t & 1)
+}
+
+func reconcile(v *Poly, reconciliation *reconciliationData) Key {
+ key := new(Key)
+
+ for i := uint(0); i < n/4; i++ {
+ t0 := 16*q + 8*int32(v[i]) - q*(2*int32(reconciliation[i])+int32(reconciliation[i+768]))
+ t1 := 16*q + 8*int32(v[i+256]) - q*(2*int32(reconciliation[256+i])+int32(reconciliation[i+768]))
+ t2 := 16*q + 8*int32(v[i+512]) - q*(2*int32(reconciliation[512+i])+int32(reconciliation[i+768]))
+ t3 := 16*q + 8*int32(v[i+768]) - q*int32(reconciliation[i+768])
+
+ key[i>>3] |= ldDecode(t0, t1, t2, t3) << (i & 7)
+ }
+
+ return sha256.Sum256(key[:])
+}
diff --git a/ssl/test/runner/recordingconn.go b/ssl/test/runner/recordingconn.go
index 39deb194..dfc10c7b 100644
--- a/ssl/test/runner/recordingconn.go
+++ b/ssl/test/runner/recordingconn.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
package runner
import (
@@ -92,6 +106,17 @@ func (r *recordingConn) WriteTo(w io.Writer) {
}
}
+func (r *recordingConn) Transcript() []byte {
+ var ret []byte
+ for _, flow := range r.flows {
+ if flow.flowType != writeFlow {
+ continue
+ }
+ ret = append(ret, flow.data...)
+ }
+ return ret
+}
+
func parseTestData(r io.Reader) (flows [][]byte, err error) {
var currentFlow []byte
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index b74f66bb..9cfba3a7 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
package runner
import (
@@ -37,6 +51,10 @@ var (
numWorkers = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
shimPath = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
resourceDir = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
+ fuzzer = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
+ transcriptDir = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
+ idleTimeout = flag.Duration("idle-timeout", 15*time.Second, "The number of seconds to wait for a read or write to bssl_shim.")
+ deterministic = flag.Bool("deterministic", false, "If true, uses a deterministic PRNG in the runner.")
)
const (
@@ -244,15 +262,68 @@ type testCase struct {
var testCases []testCase
+func writeTranscript(test *testCase, isResume bool, data []byte) {
+ if len(data) == 0 {
+ return
+ }
+
+ protocol := "tls"
+ if test.protocol == dtls {
+ protocol = "dtls"
+ }
+
+ side := "client"
+ if test.testType == serverTest {
+ side = "server"
+ }
+
+ dir := path.Join(*transcriptDir, protocol, side)
+ if err := os.MkdirAll(dir, 0755); err != nil {
+ fmt.Fprintf(os.Stderr, "Error making %s: %s\n", dir, err)
+ return
+ }
+
+ name := test.name
+ if isResume {
+ name += "-Resume"
+ } else {
+ name += "-Normal"
+ }
+
+ if err := ioutil.WriteFile(path.Join(dir, name), data, 0644); err != nil {
+ fmt.Fprintf(os.Stderr, "Error writing %s: %s\n", name, err)
+ }
+}
+
+// A timeoutConn implements an idle timeout on each Read and Write operation.
+type timeoutConn struct {
+ net.Conn
+ timeout time.Duration
+}
+
+func (t *timeoutConn) Read(b []byte) (int, error) {
+ if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
+ return 0, err
+ }
+ return t.Conn.Read(b)
+}
+
+func (t *timeoutConn) Write(b []byte) (int, error) {
+ if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
+ return 0, err
+ }
+ return t.Conn.Write(b)
+}
+
func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
- var connDamage *damageAdaptor
+ conn = &timeoutConn{conn, *idleTimeout}
if test.protocol == dtls {
config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
conn = config.Bugs.PacketAdaptor
}
- if *flagDebug {
+ if *flagDebug || len(*transcriptDir) != 0 {
local, peer := "client", "server"
if test.testType == clientTest {
local, peer = peer, local
@@ -264,9 +335,14 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
peer: peer,
}
conn = connDebug
- defer func() {
- connDebug.WriteTo(os.Stdout)
- }()
+ if *flagDebug {
+ defer connDebug.WriteTo(os.Stdout)
+ }
+ if len(*transcriptDir) != 0 {
+ defer func() {
+ writeTranscript(test, isResume, connDebug.Transcript())
+ }()
+ }
if config.Bugs.PacketAdaptor != nil {
config.Bugs.PacketAdaptor.debug = connDebug
@@ -277,6 +353,7 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
conn = newReplayAdaptor(conn)
}
+ var connDamage *damageAdaptor
if test.damageFirstWrite {
connDamage = newDamageAdaptor(conn)
conn = connDamage
@@ -686,6 +763,12 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
config.ServerName = "test"
}
}
+ if *fuzzer {
+ config.Bugs.NullAllCiphers = true
+ }
+ if *deterministic {
+ config.Rand = &deterministicRand{}
+ }
conn, err := acceptOrWait(listener, waitChan)
if err == nil {
@@ -713,6 +796,10 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
resumeConfig.ClientSessionCache = config.ClientSessionCache
resumeConfig.ServerSessionCache = config.ServerSessionCache
}
+ if *fuzzer {
+ resumeConfig.Bugs.NullAllCiphers = true
+ }
+ resumeConfig.Rand = config.Rand
} else {
resumeConfig = config
}
@@ -736,8 +823,18 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
}
}
- stdout := string(stdoutBuf.Bytes())
- stderr := string(stderrBuf.Bytes())
+ // Account for Windows line endings.
+ stdout := strings.Replace(string(stdoutBuf.Bytes()), "\r\n", "\n", -1)
+ stderr := strings.Replace(string(stderrBuf.Bytes()), "\r\n", "\n", -1)
+
+ // Separate the errors from the shim and those from tools like
+ // AddressSanitizer.
+ var extraStderr string
+ if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
+ stderr = stderrParts[0]
+ extraStderr = stderrParts[1]
+ }
+
failed := err != nil || childErr != nil
correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
localError := "none"
@@ -769,8 +866,8 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr)
}
- if !*useValgrind && !failed && len(stderr) > 0 {
- println(stderr)
+ if !*useValgrind && (len(extraStderr) > 0 || (!failed && len(stderr) > 0)) {
+ return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
}
return nil
@@ -823,11 +920,17 @@ var testCipherSuites = []struct {
{"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
{"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
{"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ {"CECPQ1-RSA-CHACHA20-POLY1305-SHA256", TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256},
+ {"CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256", TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
+ {"CECPQ1-RSA-AES256-GCM-SHA384", TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
+ {"CECPQ1-ECDSA-AES256-GCM-SHA384", TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384},
{"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
{"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
{"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
{"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
{"ECDHE-PSK-CHACHA20-POLY1305", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
+ {"ECDHE-PSK-AES128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
+ {"ECDHE-PSK-AES256-GCM-SHA384", TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384},
{"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
{"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
{"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
@@ -1128,6 +1231,31 @@ func addBasicTests() {
},
{
testType: serverTest,
+ name: "DoubleAlert",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DoubleAlert: true,
+ SendSpuriousAlert: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":BAD_ALERT:",
+ },
+ {
+ protocol: dtls,
+ testType: serverTest,
+ name: "DoubleAlert-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DoubleAlert: true,
+ SendSpuriousAlert: alertRecordOverflow,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":BAD_ALERT:",
+ },
+ {
+ testType: serverTest,
name: "EarlyChangeCipherSpec-server-1",
config: Config{
Bugs: ProtocolBugs{
@@ -1288,7 +1416,7 @@ func addBasicTests() {
},
{
name: "DisableEverything",
- flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
+ flags: []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
shouldFail: true,
expectedError: ":WRONG_SSL_VERSION:",
},
@@ -1649,7 +1777,7 @@ func addBasicTests() {
},
},
shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedError: ":BAD_HANDSHAKE_RECORD:",
},
{
protocol: dtls,
@@ -1660,7 +1788,7 @@ func addBasicTests() {
},
},
shouldFail: true,
- expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+ expectedError: ":BAD_HANDSHAKE_RECORD:",
},
{
protocol: dtls,
@@ -1671,7 +1799,7 @@ func addBasicTests() {
},
},
shouldFail: true,
- expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+ expectedError: ":BAD_HANDSHAKE_RECORD:",
},
{
protocol: dtls,
@@ -1708,7 +1836,18 @@ func addBasicTests() {
expectedError: ":WRONG_CURVE:",
},
{
- name: "BadFinished",
+ name: "BadFinished-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ BadFinished: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DIGEST_CHECK_FAILED:",
+ },
+ {
+ testType: serverTest,
+ name: "BadFinished-Server",
config: Config{
Bugs: ProtocolBugs{
BadFinished: true,
@@ -1947,6 +2086,19 @@ func addBasicTests() {
shimShutsDown: true,
},
{
+ name: "Unclean-Shutdown-Alert",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendAlertOnShutdown: alertDecompressionFailure,
+ ExpectCloseNotify: true,
+ },
+ },
+ shimShutsDown: true,
+ flags: []string{"-check-close-notify"},
+ shouldFail: true,
+ expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
+ },
+ {
name: "LargePlaintext",
config: Config{
Bugs: ProtocolBugs{
@@ -2097,6 +2249,31 @@ func addBasicTests() {
resumeConfig: &Config{},
resumeSession: true,
},
+ {
+ name: "InvalidECDHPoint-Client",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ CurvePreferences: []CurveID{CurveP256},
+ Bugs: ProtocolBugs{
+ InvalidECDHPoint: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":INVALID_ENCODING:",
+ },
+ {
+ testType: serverTest,
+ name: "InvalidECDHPoint-Server",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ CurvePreferences: []CurveID{CurveP256},
+ Bugs: ProtocolBugs{
+ InvalidECDHPoint: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":INVALID_ENCODING:",
+ },
}
testCases = append(testCases, basicTests...)
}
@@ -2129,6 +2306,10 @@ func addCipherSuiteTests() {
// NULL ciphers must be explicitly enabled.
flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
}
+ if hasComponent(suite.name, "CECPQ1") {
+ // CECPQ1 ciphers must be explicitly enabled.
+ flags = append(flags, "-cipher", "DEFAULT:kCECPQ1")
+ }
for _, ver := range tlsVersions {
if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
@@ -2402,7 +2583,7 @@ func addBadECDSASignatureTests() {
},
},
shouldFail: true,
- expectedError: "SIGNATURE",
+ expectedError: ":BAD_SIGNATURE:",
})
}
}
@@ -2428,7 +2609,7 @@ func addCBCPaddingTests() {
},
},
shouldFail: true,
- expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
})
// OpenSSL previously had an issue where the first byte of padding in
// 255 bytes of padding wasn't checked.
@@ -2443,7 +2624,7 @@ func addCBCPaddingTests() {
},
messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
shouldFail: true,
- expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
})
}
@@ -2542,6 +2723,73 @@ func addClientAuthTests() {
})
}
}
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "RequireAnyClientCertificate",
+ flags: []string{"-require-any-client-certificate"},
+ shouldFail: true,
+ expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "RequireAnyClientCertificate-SSL3",
+ config: Config{
+ MaxVersion: VersionSSL30,
+ },
+ flags: []string{"-require-any-client-certificate"},
+ shouldFail: true,
+ expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipClientCertificate",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SkipClientCertificate: true,
+ },
+ },
+ // Setting SSL_VERIFY_PEER allows anonymous clients.
+ flags: []string{"-verify-peer"},
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ })
+
+ // Client auth is only legal in certificate-based ciphers.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ClientAuth-PSK",
+ config: Config{
+ CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+ PreSharedKey: []byte("secret"),
+ ClientAuth: RequireAnyClientCert,
+ },
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-psk", "secret",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ClientAuth-ECDHE_PSK",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
+ PreSharedKey: []byte("secret"),
+ ClientAuth: RequireAnyClientCert,
+ },
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-psk", "secret",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ })
}
func addExtendedMasterSecretTests() {
@@ -2745,6 +2993,46 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
// TLS client auth.
tests = append(tests, testCase{
testType: clientTest,
+ name: "ClientAuth-NoCertificate-Client",
+ config: Config{
+ ClientAuth: RequestClientCert,
+ },
+ })
+ tests = append(tests, testCase{
+ testType: serverTest,
+ name: "ClientAuth-NoCertificate-Server",
+ // Setting SSL_VERIFY_PEER allows anonymous clients.
+ flags: []string{"-verify-peer"},
+ })
+ if protocol == tls {
+ tests = append(tests, testCase{
+ testType: clientTest,
+ name: "ClientAuth-NoCertificate-Client-SSL3",
+ config: Config{
+ MaxVersion: VersionSSL30,
+ ClientAuth: RequestClientCert,
+ },
+ })
+ tests = append(tests, testCase{
+ testType: serverTest,
+ name: "ClientAuth-NoCertificate-Server-SSL3",
+ config: Config{
+ MaxVersion: VersionSSL30,
+ },
+ // Setting SSL_VERIFY_PEER allows anonymous clients.
+ flags: []string{"-verify-peer"},
+ })
+ }
+ tests = append(tests, testCase{
+ testType: clientTest,
+ name: "ClientAuth-NoCertificate-OldCallback",
+ config: Config{
+ ClientAuth: RequestClientCert,
+ },
+ flags: []string{"-use-old-client-cert-callback"},
+ })
+ tests = append(tests, testCase{
+ testType: clientTest,
name: "ClientAuth-RSA-Client",
config: Config{
ClientAuth: RequireAnyClientCert,
@@ -2765,6 +3053,19 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
"-key-file", path.Join(*resourceDir, ecdsaKeyFile),
},
})
+ tests = append(tests, testCase{
+ testType: clientTest,
+ name: "ClientAuth-OldCallback",
+ config: Config{
+ ClientAuth: RequireAnyClientCert,
+ },
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ "-use-old-client-cert-callback",
+ },
+ })
+
if async {
// Test async keys against each key exchange.
tests = append(tests, testCase{
@@ -2912,6 +3213,7 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
NextProtos: []string{"foo"},
},
flags: []string{"-select-next-proto", "foo"},
+ resumeSession: true,
expectedNextProto: "foo",
expectedNextProtoType: npn,
})
@@ -2925,6 +3227,7 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
"-advertise-npn", "\x03foo\x03bar\x03baz",
"-expect-next-proto", "bar",
},
+ resumeSession: true,
expectedNextProto: "bar",
expectedNextProtoType: npn,
})
@@ -3041,6 +3344,42 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
expectChannelID: true,
})
+ // Channel ID and NPN at the same time, to ensure their relative
+ // ordering is correct.
+ tests = append(tests, testCase{
+ name: "ChannelID-NPN-Client",
+ config: Config{
+ RequestChannelID: true,
+ NextProtos: []string{"foo"},
+ },
+ flags: []string{
+ "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+ "-select-next-proto", "foo",
+ },
+ resumeSession: true,
+ expectChannelID: true,
+ expectedNextProto: "foo",
+ expectedNextProtoType: npn,
+ })
+ tests = append(tests, testCase{
+ testType: serverTest,
+ name: "ChannelID-NPN-Server",
+ config: Config{
+ ChannelID: channelIDKey,
+ NextProtos: []string{"bar"},
+ },
+ flags: []string{
+ "-expect-channel-id",
+ base64.StdEncoding.EncodeToString(channelIDBytes),
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ "-expect-next-proto", "bar",
+ },
+ resumeSession: true,
+ expectChannelID: true,
+ expectedNextProto: "bar",
+ expectedNextProtoType: npn,
+ })
+
// Bidirectional shutdown with the runner initiating.
tests = append(tests, testCase{
name: "Shutdown-Runner",
@@ -3403,6 +3742,16 @@ func addExtensionTests() {
expectedNextProtoType: alpn,
resumeSession: true,
})
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Decline",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{"-decline-alpn"},
+ expectNoNextProto: true,
+ resumeSession: true,
+ })
// Test that the server prefers ALPN over NPN.
testCases = append(testCases, testCase{
testType: serverTest,
@@ -3644,6 +3993,20 @@ func addExtensionTests() {
resumeSession: true,
})
testCases = append(testCases, testCase{
+ name: "SendSCTListOnResume",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSCTListOnResume: []byte("bogus"),
+ },
+ },
+ flags: []string{
+ "-enable-signed-cert-timestamps",
+ "-expect-signed-cert-timestamps",
+ base64.StdEncoding.EncodeToString(testSCTList),
+ },
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
name: "SignedCertificateTimestampList-Server",
testType: serverTest,
flags: []string{
@@ -4348,82 +4711,156 @@ var timeouts = []time.Duration{
60 * time.Second,
}
+// shortTimeouts is an alternate set of timeouts which would occur if the
+// initial timeout duration was set to 250ms.
+var shortTimeouts = []time.Duration{
+ 250 * time.Millisecond,
+ 500 * time.Millisecond,
+ 1 * time.Second,
+ 2 * time.Second,
+ 4 * time.Second,
+ 8 * time.Second,
+ 16 * time.Second,
+ 32 * time.Second,
+ 60 * time.Second,
+ 60 * time.Second,
+ 60 * time.Second,
+ 60 * time.Second,
+ 60 * time.Second,
+}
+
func addDTLSRetransmitTests() {
- // Test that this is indeed the timeout schedule. Stress all
- // four patterns of handshake.
- for i := 1; i < len(timeouts); i++ {
- number := strconv.Itoa(i)
- testCases = append(testCases, testCase{
+ // These tests work by coordinating some behavior on both the shim and
+ // the runner.
+ //
+ // TimeoutSchedule configures the runner to send a series of timeout
+ // opcodes to the shim (see packetAdaptor) immediately before reading
+ // each peer handshake flight N. The timeout opcode both simulates a
+ // timeout in the shim and acts as a synchronization point to help the
+ // runner bracket each handshake flight.
+ //
+ // We assume the shim does not read from the channel eagerly. It must
+ // first wait until it has sent flight N and is ready to receive
+ // handshake flight N+1. At this point, it will process the timeout
+ // opcode. It must then immediately respond with a timeout ACK and act
+ // as if the shim was idle for the specified amount of time.
+ //
+ // The runner then drops all packets received before the ACK and
+ // continues waiting for flight N. This ordering results in one attempt
+ // at sending flight N to be dropped. For the test to complete, the
+ // shim must send flight N again, testing that the shim implements DTLS
+ // retransmit on a timeout.
+
+ for _, async := range []bool{true, false} {
+ var tests []testCase
+
+ // Test that this is indeed the timeout schedule. Stress all
+ // four patterns of handshake.
+ for i := 1; i < len(timeouts); i++ {
+ number := strconv.Itoa(i)
+ tests = append(tests, testCase{
+ protocol: dtls,
+ name: "DTLS-Retransmit-Client-" + number,
+ config: Config{
+ Bugs: ProtocolBugs{
+ TimeoutSchedule: timeouts[:i],
+ },
+ },
+ resumeSession: true,
+ })
+ tests = append(tests, testCase{
+ protocol: dtls,
+ testType: serverTest,
+ name: "DTLS-Retransmit-Server-" + number,
+ config: Config{
+ Bugs: ProtocolBugs{
+ TimeoutSchedule: timeouts[:i],
+ },
+ },
+ resumeSession: true,
+ })
+ }
+
+ // Test that exceeding the timeout schedule hits a read
+ // timeout.
+ tests = append(tests, testCase{
protocol: dtls,
- name: "DTLS-Retransmit-Client-" + number,
+ name: "DTLS-Retransmit-Timeout",
config: Config{
Bugs: ProtocolBugs{
- TimeoutSchedule: timeouts[:i],
+ TimeoutSchedule: timeouts,
},
},
resumeSession: true,
- flags: []string{"-async"},
+ shouldFail: true,
+ expectedError: ":READ_TIMEOUT_EXPIRED:",
})
- testCases = append(testCases, testCase{
- protocol: dtls,
+
+ if async {
+ // Test that timeout handling has a fudge factor, due to API
+ // problems.
+ tests = append(tests, testCase{
+ protocol: dtls,
+ name: "DTLS-Retransmit-Fudge",
+ config: Config{
+ Bugs: ProtocolBugs{
+ TimeoutSchedule: []time.Duration{
+ timeouts[0] - 10*time.Millisecond,
+ },
+ },
+ },
+ resumeSession: true,
+ })
+ }
+
+ // Test that the final Finished retransmitting isn't
+ // duplicated if the peer badly fragments everything.
+ tests = append(tests, testCase{
testType: serverTest,
- name: "DTLS-Retransmit-Server-" + number,
+ protocol: dtls,
+ name: "DTLS-Retransmit-Fragmented",
config: Config{
Bugs: ProtocolBugs{
- TimeoutSchedule: timeouts[:i],
+ TimeoutSchedule: []time.Duration{timeouts[0]},
+ MaxHandshakeRecordLength: 2,
},
},
- resumeSession: true,
- flags: []string{"-async"},
})
- }
- // Test that exceeding the timeout schedule hits a read
- // timeout.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Retransmit-Timeout",
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: timeouts,
+ // Test the timeout schedule when a shorter initial timeout duration is set.
+ tests = append(tests, testCase{
+ protocol: dtls,
+ name: "DTLS-Retransmit-Short-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
+ },
},
- },
- resumeSession: true,
- flags: []string{"-async"},
- shouldFail: true,
- expectedError: ":READ_TIMEOUT_EXPIRED:",
- })
-
- // Test that timeout handling has a fudge factor, due to API
- // problems.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Retransmit-Fudge",
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: []time.Duration{
- timeouts[0] - 10*time.Millisecond,
+ resumeSession: true,
+ flags: []string{"-initial-timeout-duration-ms", "250"},
+ })
+ tests = append(tests, testCase{
+ protocol: dtls,
+ testType: serverTest,
+ name: "DTLS-Retransmit-Short-Server",
+ config: Config{
+ Bugs: ProtocolBugs{
+ TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
},
},
- },
- resumeSession: true,
- flags: []string{"-async"},
- })
+ resumeSession: true,
+ flags: []string{"-initial-timeout-duration-ms", "250"},
+ })
- // Test that the final Finished retransmitting isn't
- // duplicated if the peer badly fragments everything.
- testCases = append(testCases, testCase{
- testType: serverTest,
- protocol: dtls,
- name: "DTLS-Retransmit-Fragmented",
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: []time.Duration{timeouts[0]},
- MaxHandshakeRecordLength: 2,
- },
- },
- flags: []string{"-async"},
- })
+ for _, test := range tests {
+ if async {
+ test.name += "-Async"
+ test.flags = append(test.flags, "-async")
+ }
+
+ testCases = append(testCases, test)
+ }
+ }
}
func addExportKeyingMaterialTests() {
@@ -4702,6 +5139,65 @@ func addCurveTests() {
})
}
+func addCECPQ1Tests() {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "CECPQ1-Client-BadX25519Part",
+ config: Config{
+ MinVersion: VersionTLS12,
+ CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
+ Bugs: ProtocolBugs{
+ CECPQ1BadX25519Part: true,
+ },
+ },
+ flags: []string{"-cipher", "kCECPQ1"},
+ shouldFail: true,
+ expectedLocalError: "local error: bad record MAC",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "CECPQ1-Client-BadNewhopePart",
+ config: Config{
+ MinVersion: VersionTLS12,
+ CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
+ Bugs: ProtocolBugs{
+ CECPQ1BadNewhopePart: true,
+ },
+ },
+ flags: []string{"-cipher", "kCECPQ1"},
+ shouldFail: true,
+ expectedLocalError: "local error: bad record MAC",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "CECPQ1-Server-BadX25519Part",
+ config: Config{
+ MinVersion: VersionTLS12,
+ CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
+ Bugs: ProtocolBugs{
+ CECPQ1BadX25519Part: true,
+ },
+ },
+ flags: []string{"-cipher", "kCECPQ1"},
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "CECPQ1-Server-BadNewhopePart",
+ config: Config{
+ MinVersion: VersionTLS12,
+ CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
+ Bugs: ProtocolBugs{
+ CECPQ1BadNewhopePart: true,
+ },
+ },
+ flags: []string{"-cipher", "kCECPQ1"},
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ })
+}
+
func addKeyExchangeInfoTests() {
testCases = append(testCases, testCase{
name: "KeyExchangeInfo-RSA-Client",
@@ -4855,6 +5351,7 @@ func main() {
addCustomExtensionTests()
addRSAClientKeyExchangeTests()
addCurveTests()
+ addCECPQ1Tests()
addKeyExchangeInfoTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
@@ -4877,11 +5374,17 @@ func main() {
go worker(statusChan, testChan, *shimPath, &wg)
}
+ var foundTest bool
for i := range testCases {
if len(*testToRun) == 0 || *testToRun == testCases[i].name {
+ foundTest = true
testChan <- &testCases[i]
}
}
+ if !foundTest {
+ fmt.Fprintf(os.Stderr, "No test named '%s'\n", *testToRun)
+ os.Exit(1)
+ }
close(testChan)
wg.Wait()
diff --git a/ssl/test/runner/runner_test.go b/ssl/test/runner/runner_test.go
index 320ff52e..1ba28e0e 100644
--- a/ssl/test/runner/runner_test.go
+++ b/ssl/test/runner/runner_test.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
package runner
import "testing"
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 1cf316d5..536978b6 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -56,12 +56,14 @@ const Flag<bool> kBoolFlags[] = {
&TestConfig::write_different_record_sizes },
{ "-cbc-record-splitting", &TestConfig::cbc_record_splitting },
{ "-partial-write", &TestConfig::partial_write },
+ { "-no-tls13", &TestConfig::no_tls13 },
{ "-no-tls12", &TestConfig::no_tls12 },
{ "-no-tls11", &TestConfig::no_tls11 },
{ "-no-tls1", &TestConfig::no_tls1 },
{ "-no-ssl3", &TestConfig::no_ssl3 },
{ "-shim-writes-first", &TestConfig::shim_writes_first },
{ "-expect-session-miss", &TestConfig::expect_session_miss },
+ { "-decline-alpn", &TestConfig::decline_alpn },
{ "-expect-extended-master-secret",
&TestConfig::expect_extended_master_secret },
{ "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling },
@@ -98,6 +100,8 @@ const Flag<bool> kBoolFlags[] = {
{ "-p384-only", &TestConfig::p384_only },
{ "-enable-all-curves", &TestConfig::enable_all_curves },
{ "-use-sparse-dh-prime", &TestConfig::use_sparse_dh_prime },
+ { "-use-old-client-cert-callback",
+ &TestConfig::use_old_client_cert_callback },
};
const Flag<std::string> kStringFlags[] = {
@@ -145,6 +149,7 @@ const Flag<int> kIntFlags[] = {
&TestConfig::expect_server_key_exchange_hash },
{ "-expect-key-exchange-info",
&TestConfig::expect_key_exchange_info },
+ { "-initial-timeout-duration-ms", &TestConfig::initial_timeout_duration_ms },
};
} // namespace
@@ -178,12 +183,14 @@ bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
size_t len;
if (!EVP_DecodedLength(&len, strlen(argv[i]))) {
fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+ return false;
}
std::unique_ptr<uint8_t[]> decoded(new uint8_t[len]);
if (!EVP_DecodeBase64(decoded.get(), &len, len,
reinterpret_cast<const uint8_t *>(argv[i]),
strlen(argv[i]))) {
fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+ return false;
}
base64_field->assign(reinterpret_cast<const char *>(decoded.get()), len);
continue;
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 4e0a46ae..aff194ef 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -38,6 +38,7 @@ struct TestConfig {
bool write_different_record_sizes = false;
bool cbc_record_splitting = false;
bool partial_write = false;
+ bool no_tls13 = false;
bool no_tls12 = false;
bool no_tls11 = false;
bool no_tls1 = false;
@@ -50,6 +51,7 @@ struct TestConfig {
std::string expected_alpn;
std::string expected_advertised_alpn;
std::string select_alpn;
+ bool decline_alpn = false;
bool expect_session_miss = false;
bool expect_extended_master_secret = false;
std::string psk;
@@ -102,6 +104,8 @@ struct TestConfig {
bool enable_all_curves = false;
bool use_sparse_dh_prime = false;
int expect_key_exchange_info = 0;
+ bool use_old_client_cert_callback = false;
+ int initial_timeout_duration_ms = 0;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);
diff --git a/ssl/tls_record.c b/ssl/tls_record.c
index d53e1d78..e1553e32 100644
--- a/ssl/tls_record.c
+++ b/ssl/tls_record.c
@@ -113,8 +113,10 @@
#include <openssl/bytestring.h>
#include <openssl/err.h>
+#include <openssl/mem.h>
#include "internal.h"
+#include "../crypto/internal.h"
/* kMaxEmptyRecords is the number of consecutive, empty records that will be
@@ -123,6 +125,10 @@
* forever. */
static const uint8_t kMaxEmptyRecords = 32;
+/* kMaxWarningAlerts is the number of consecutive warning alerts that will be
+ * processed. */
+static const uint8_t kMaxWarningAlerts = 4;
+
/* ssl_needs_record_splitting returns one if |ssl|'s current outgoing cipher
* state needs record-splitting and zero otherwise. */
static int ssl_needs_record_splitting(const SSL *ssl) {
@@ -154,7 +160,7 @@ size_t ssl_record_prefix_len(const SSL *ssl) {
}
}
-size_t ssl_seal_prefix_len(const SSL *ssl) {
+size_t ssl_seal_align_prefix_len(const SSL *ssl) {
if (SSL_IS_DTLS(ssl)) {
return DTLS1_RT_HEADER_LENGTH +
SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
@@ -170,23 +176,28 @@ size_t ssl_seal_prefix_len(const SSL *ssl) {
}
size_t ssl_max_seal_overhead(const SSL *ssl) {
+ size_t ret = SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
if (SSL_IS_DTLS(ssl)) {
- return DTLS1_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
+ ret += DTLS1_RT_HEADER_LENGTH;
} else {
- size_t ret = SSL3_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
- if (ssl_needs_record_splitting(ssl)) {
- ret *= 2;
- }
- return ret;
+ ret += SSL3_RT_HEADER_LENGTH;
+ }
+ /* TLS 1.3 needs an extra byte for the encrypted record type. */
+ if (ssl->s3->have_version &&
+ ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ ret += 1;
}
+ if (!SSL_IS_DTLS(ssl) && ssl_needs_record_splitting(ssl)) {
+ ret *= 2;
+ }
+ return ret;
}
-enum ssl_open_record_t tls_open_record(
- SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
- size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
- size_t in_len) {
+enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+ size_t *out_consumed, uint8_t *out_alert,
+ uint8_t *in, size_t in_len) {
+ *out_consumed = 0;
+
CBS cbs;
CBS_init(&cbs, in, in_len);
@@ -200,9 +211,9 @@ enum ssl_open_record_t tls_open_record(
return ssl_open_record_partial;
}
- /* Check the version. */
- if ((ssl->s3->have_version && version != ssl->version) ||
- (version >> 8) != SSL3_VERSION_MAJOR) {
+ /* Check that the major version in the record matches. As of TLS 1.3, the
+ * minor version is no longer checked. */
+ if ((version >> 8) != SSL3_VERSION_MAJOR) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
*out_alert = SSL_AD_PROTOCOL_VERSION;
return ssl_open_record_error;
@@ -222,34 +233,46 @@ enum ssl_open_record_t tls_open_record(
return ssl_open_record_partial;
}
- if (ssl->msg_callback != NULL) {
- ssl->msg_callback(0 /* read */, 0, SSL3_RT_HEADER, in,
- SSL3_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
- }
+ ssl_do_msg_callback(ssl, 0 /* read */, 0, SSL3_RT_HEADER, in,
+ SSL3_RT_HEADER_LENGTH);
- /* Decrypt the body. */
- size_t plaintext_len;
- if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, &plaintext_len, max_out,
- type, version, ssl->s3->read_sequence, CBS_data(&body),
+ /* Decrypt the body in-place. */
+ if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version,
+ ssl->s3->read_sequence, (uint8_t *)CBS_data(&body),
CBS_len(&body))) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
*out_alert = SSL_AD_BAD_RECORD_MAC;
return ssl_open_record_error;
}
+ *out_consumed = in_len - CBS_len(&cbs);
+
if (!ssl_record_sequence_update(ssl->s3->read_sequence, 8)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return ssl_open_record_error;
}
+ /* TLS 1.3 hides the record type inside the encrypted data. */
+ if (ssl->s3->have_version &&
+ ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+ ssl->s3->aead_read_ctx != NULL) {
+ do {
+ if (!CBS_get_last_u8(out, &type)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ *out_alert = SSL_AD_DECRYPT_ERROR;
+ return ssl_open_record_error;
+ }
+ } while (type == 0);
+ }
+
/* Check the plaintext length. */
- if (plaintext_len > SSL3_RT_MAX_PLAIN_LENGTH) {
+ if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
*out_alert = SSL_AD_RECORD_OVERFLOW;
return ssl_open_record_error;
}
/* Limit the number of consecutive empty records. */
- if (plaintext_len == 0) {
+ if (CBS_len(out) == 0) {
ssl->s3->empty_record_count++;
if (ssl->s3->empty_record_count > kMaxEmptyRecords) {
OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_EMPTY_FRAGMENTS);
@@ -262,9 +285,13 @@ enum ssl_open_record_t tls_open_record(
ssl->s3->empty_record_count = 0;
}
+ if (type == SSL3_RT_ALERT) {
+ return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out));
+ }
+
+ ssl->s3->warning_alert_count = 0;
+
*out_type = type;
- *out_len = plaintext_len;
- *out_consumed = in_len - CBS_len(&cbs);
return ssl_open_record_success;
}
@@ -275,20 +302,25 @@ static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len,
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
return 0;
}
- /* Check the record header does not alias any part of the input.
- * |SSL_AEAD_CTX_seal| will internally enforce other aliasing requirements. */
- if (in < out + SSL3_RT_HEADER_LENGTH && out < in + in_len) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
- return 0;
- }
+
+ /* Either |in| and |out| don't alias or |in| aligns with the
+ * ciphertext. |tls_seal_record| forbids aliasing, but TLS 1.3 aliases them
+ * internally. */
+ assert(!buffers_alias(in, in_len, out, max_out) ||
+ in ==
+ out + SSL3_RT_HEADER_LENGTH +
+ SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx));
out[0] = type;
- /* Some servers hang if initial ClientHello is larger than 256 bytes and
- * record version number > TLS 1.0. */
- uint16_t wire_version = ssl->version;
- if (!ssl->s3->have_version && ssl->version > SSL3_VERSION) {
- wire_version = TLS1_VERSION;
+ /* The TLS record-layer version number is meaningless and, starting in
+ * TLS 1.3, is frozen at TLS 1.0. But for historical reasons, SSL 3.0
+ * ClientHellos should use SSL 3.0 and pre-TLS-1.3 expects the version
+ * to change after version negotiation. */
+ uint16_t wire_version = TLS1_VERSION;
+ if (ssl->version == SSL3_VERSION ||
+ (ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION)) {
+ wire_version = ssl->version;
}
out[1] = wire_version >> 8;
out[2] = wire_version & 0xff;
@@ -311,31 +343,41 @@ static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len,
*out_len = SSL3_RT_HEADER_LENGTH + ciphertext_len;
- if (ssl->msg_callback) {
- ssl->msg_callback(1 /* write */, 0, SSL3_RT_HEADER, out,
- SSL3_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
- }
-
+ ssl_do_msg_callback(ssl, 1 /* write */, 0, SSL3_RT_HEADER, out,
+ SSL3_RT_HEADER_LENGTH);
return 1;
}
int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
uint8_t type, const uint8_t *in, size_t in_len) {
+ if (buffers_alias(in, in_len, out, max_out)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
+ return 0;
+ }
+
size_t frag_len = 0;
- if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
- ssl_needs_record_splitting(ssl)) {
- /* |do_seal_record| will notice if it clobbers |in[0]|, but not if it
- * aliases the rest of |in|. */
- if (in + 1 <= out && out < in + in_len) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
+
+ /* TLS 1.3 hides the actual record type inside the encrypted data. */
+ if (ssl->s3->have_version &&
+ ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+ ssl->s3->aead_read_ctx != NULL) {
+ size_t padding = SSL3_RT_HEADER_LENGTH + 1;
+
+ if (in_len > in_len + padding || max_out < in_len + padding) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
return 0;
}
- /* Ensure |do_seal_record| does not write beyond |in[0]|. */
- size_t frag_max_out = max_out;
- if (out <= in + 1 && in + 1 < out + frag_max_out) {
- frag_max_out = (size_t)(in + 1 - out);
- }
- if (!do_seal_record(ssl, out, &frag_len, frag_max_out, type, in, 1)) {
+
+ memmove(out + SSL3_RT_HEADER_LENGTH, in, in_len);
+ out[SSL3_RT_HEADER_LENGTH + in_len] = type;
+ in = out + SSL3_RT_HEADER_LENGTH;
+ type = SSL3_RT_APPLICATION_DATA;
+ in_len++;
+ }
+
+ if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
+ ssl_needs_record_splitting(ssl)) {
+ if (!do_seal_record(ssl, out, &frag_len, max_out, type, in, 1)) {
return 0;
}
in++;
@@ -343,9 +385,11 @@ int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
out += frag_len;
max_out -= frag_len;
+#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
assert(SSL3_RT_HEADER_LENGTH + ssl_cipher_get_record_split_len(
ssl->s3->aead_write_ctx->cipher) ==
frag_len);
+#endif
}
if (!do_seal_record(ssl, out, out_len, max_out, type, in, in_len)) {
@@ -377,3 +421,51 @@ void ssl_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
ssl->s3->aead_write_ctx = aead_ctx;
}
+
+enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
+ const uint8_t *in, size_t in_len) {
+ /* Alerts records may not contain fragmented or multiple alerts. */
+ if (in_len != 2) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
+ return ssl_open_record_error;
+ }
+
+ ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_ALERT, in, in_len);
+
+ const uint8_t alert_level = in[0];
+ const uint8_t alert_descr = in[1];
+
+ uint16_t alert = (alert_level << 8) | alert_descr;
+ ssl_do_info_callback(ssl, SSL_CB_READ_ALERT, alert);
+
+ if (alert_level == SSL3_AL_WARNING) {
+ if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
+ ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
+ return ssl_open_record_close_notify;
+ }
+
+ ssl->s3->warning_alert_count++;
+ if (ssl->s3->warning_alert_count > kMaxWarningAlerts) {
+ *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS);
+ return ssl_open_record_error;
+ }
+ return ssl_open_record_discard;
+ }
+
+ if (alert_level == SSL3_AL_FATAL) {
+ ssl->s3->recv_shutdown = ssl_shutdown_fatal_alert;
+ SSL_CTX_remove_session(ssl->ctx, ssl->session);
+
+ char tmp[16];
+ OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
+ BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
+ ERR_add_error_data(2, "SSL alert number ", tmp);
+ return ssl_open_record_fatal_alert;
+ }
+
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
+ return ssl_open_record_error;
+}
diff --git a/third_party/android-cmake/AndroidNdkGdb.cmake b/third_party/android-cmake/AndroidNdkGdb.cmake
new file mode 100644
index 00000000..0677dcda
--- /dev/null
+++ b/third_party/android-cmake/AndroidNdkGdb.cmake
@@ -0,0 +1,96 @@
+# Copyright (c) 2014, Pavel Rojtberg
+# 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. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
+
+# ------------------------------------------------------------------------------
+# Usage:
+# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH}
+# 2. inside your project add
+#
+# include(AndroidNdkGdb)
+# android_ndk_gdb_enable()
+# # for each target
+# add_library(MyLibrary ...)
+# android_ndk_gdb_debuggable(MyLibrary)
+
+
+# add gdbserver and general gdb configuration to project
+# also create a mininal NDK skeleton so ndk-gdb finds the paths
+#
+# the optional parameter defines the path to the android project.
+# uses PROJECT_SOURCE_DIR by default.
+macro(android_ndk_gdb_enable)
+ if(ANDROID)
+ # create custom target that depends on the real target so it gets executed afterwards
+ add_custom_target(NDK_GDB ALL)
+
+ if(${ARGC})
+ set(ANDROID_PROJECT_DIR ${ARGV0})
+ else()
+ set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR})
+ endif()
+
+ set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)
+ file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH})
+
+ # 1. generate essential Android Makefiles
+ file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni)
+ if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk)
+ file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
+ endif()
+ if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk)
+ file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
+ endif()
+
+ # 2. generate gdb.setup
+ get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES)
+ string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}")
+ file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n")
+ file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n")
+
+ # 3. copy gdbserver executable
+ file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH})
+ endif()
+endmacro()
+
+# register a target for remote debugging
+# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original
+macro(android_ndk_gdb_debuggable TARGET_NAME)
+ if(ANDROID)
+ get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION)
+
+ # create custom target that depends on the real target so it gets executed afterwards
+ add_dependencies(NDK_GDB ${TARGET_NAME})
+
+ # 4. copy lib to obj
+ add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH})
+
+ # 5. strip symbols
+ add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION})
+ endif()
+endmacro()
diff --git a/third_party/android-cmake/AndroidNdkModules.cmake b/third_party/android-cmake/AndroidNdkModules.cmake
new file mode 100644
index 00000000..64f37fde
--- /dev/null
+++ b/third_party/android-cmake/AndroidNdkModules.cmake
@@ -0,0 +1,58 @@
+# Copyright (c) 2014, Pavel Rojtberg
+# 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. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
+
+macro(android_ndk_import_module_cpufeatures)
+ if(ANDROID)
+ include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
+ add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
+ target_link_libraries(cpufeatures dl)
+ endif()
+endmacro()
+
+macro(android_ndk_import_module_native_app_glue)
+ if(ANDROID)
+ include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
+ add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+ target_link_libraries(native_app_glue log)
+ endif()
+endmacro()
+
+macro(android_ndk_import_module_ndk_helper)
+ if(ANDROID)
+ android_ndk_import_module_cpufeatures()
+ android_ndk_import_module_native_app_glue()
+
+ include_directories(${ANDROID_NDK}/sources/android/ndk_helper)
+ file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c)
+ add_library(ndk_helper ${_NDK_HELPER_SRCS})
+ target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue)
+
+ unset(_NDK_HELPER_SRCS)
+ endif()
+endmacro() \ No newline at end of file
diff --git a/third_party/android-cmake/LICENSE b/third_party/android-cmake/LICENSE
new file mode 100644
index 00000000..a96a3694
--- /dev/null
+++ b/third_party/android-cmake/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2010-2011, Ethan Rublee
+Copyright (c) 2011-2014, Andrey Kamaev
+Copyright (c) 2014, Pavel Rojtberg
+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. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
diff --git a/third_party/android-cmake/README.google b/third_party/android-cmake/README.google
new file mode 100644
index 00000000..b2a0caf6
--- /dev/null
+++ b/third_party/android-cmake/README.google
@@ -0,0 +1,12 @@
+URL: https://github.com/taka-no-me/android-cmake/archive/556cc14296c226f753a3778d99d8b60778b7df4f.zip
+Version: 556cc14296c226f753a3778d99d8b60778b7df4f
+License: BSD
+License File: LICENSE
+
+Description:
+android-cmake is a collection of CMake scripts for building against the Android
+NDK.
+
+Local Modifications:
+LICENSE file has been created for compliance purposes. Not included in original
+distribution.
diff --git a/third_party/android-cmake/README.md b/third_party/android-cmake/README.md
new file mode 100644
index 00000000..ee630212
--- /dev/null
+++ b/third_party/android-cmake/README.md
@@ -0,0 +1,240 @@
+# android-cmake
+
+CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html
+
+Main goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android.
+
+## TL;DR
+
+ cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \
+ -DANDROID_NDK=<ndk_path> \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DANDROID_ABI="armeabi-v7a with NEON" \
+ <source_path>
+ cmake --build .
+
+One-liner:
+
+ cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK=<ndk_path> -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" <source_path> && cmake --build .
+
+_android-cmake_ will search for your NDK install in the following order:
+
+1. Value of `ANDROID_NDK` CMake variable;
+1. Value of `ANDROID_NDK` environment variable;
+1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable;
+1. Search platform specific locations (home folder, Windows "Program Files", etc).
+
+So if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically.
+
+## Getting started
+
+To build a cmake-based C/C++ project for Android you need:
+
+* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html
+* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download
+
+The _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with.
+
+## Difference from traditional CMake
+
+Folowing the _ndk-build_ the _android-cmake_ supports **only two build targets**:
+
+* `-DCMAKE_BUILD_TYPE=Release`
+* `-DCMAKE_BUILD_TYPE=Debug`
+
+So don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default.
+
+## Difference from _ndk-build_
+
+* Latest GCC available in NDK is used as the default compiler;
+* `Release` builds with `-O3` instead of `-Os`;
+* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target);
+* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64;
+* GCC's stack protector is not used neither in `Debug` nor `Release` configurations;
+* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters);
+* No file level Neon via `.neon` suffix;
+
+The following features of _ndk-build_ are not supported by the _android-cmake_ yet:
+
+* `armeabi-v7a-hard` ABI
+* `libc++_static`/`libc++_shared` STL runtime
+
+## Basic options
+
+Similarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D<NAME>=<VALUE>` or as environment variables:
+
+* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations;
+* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are:
+ * `armeabi` - ARMv5TE based CPU with software floating point operations;
+ * **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16);
+ * `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit;
+ * `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit;
+ * `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP;
+ * `x86` - IA-32 instruction set
+ * `mips` - MIPS32 instruction set
+ * `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer
+ * `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer
+ * `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer
+* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI:
+ * `android-8` for ARM;
+ * `android-9` for x86 and MIPS;
+ * `android-21` for 64-bit ABIs.
+
+ Building for `android-L` is possible only when it is explicitly selected.
+* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`.
+
+ Example values are:
+ * `aarch64-linux-android-4.9`
+ * `aarch64-linux-android-clang3.5`
+ * `arm-linux-androideabi-4.8`
+ * `arm-linux-androideabi-4.9`
+ * `arm-linux-androideabi-clang3.5`
+ * `mips64el-linux-android-4.9`
+ * `mipsel-linux-android-4.8`
+ * `x86-4.9`
+ * `x86_64-4.9`
+ * etc.
+* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`.
+ * `none` - do not configure the runtime.
+ * `system` - use the default minimal system C++ runtime library.
+ * Implies `-fno-rtti -fno-exceptions`.
+ * `system_re` - use the default minimal system C++ runtime library.
+ * Implies `-frtti -fexceptions`.
+ * `gabi++_static` - use the GAbi++ runtime as a static library.
+ * Implies `-frtti -fno-exceptions`.
+ * Available for NDK r7 and newer.
+ * `gabi++_shared` - use the GAbi++ runtime as a shared library.
+ * Implies `-frtti -fno-exceptions`.
+ * Available for NDK r7 and newer.
+ * `stlport_static` - use the STLport runtime as a static library.
+ * Implies `-fno-rtti -fno-exceptions` for NDK before r7.
+ * Implies `-frtti -fno-exceptions` for NDK r7 and newer.
+ * `stlport_shared` - use the STLport runtime as a shared library.
+ * Implies `-fno-rtti -fno-exceptions` for NDK before r7.
+ * Implies `-frtti -fno-exceptions` for NDK r7 and newer.
+ * **`gnustl_static`** - use the GNU STL as a static library.
+ * Implies `-frtti -fexceptions`.
+ * `gnustl_shared` - use the GNU STL as a shared library.
+ * Implies `-frtti -fno-exceptions`.
+ * Available for NDK r7b and newer.
+ * Silently degrades to `gnustl_static` if not available.
+* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable.
+
+## Advanced _android-cmake_ options
+
+Normally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues:
+
+* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`;
+* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors;
+* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries;
+ * actually it is turned `ON` by default for NDK older than `r7`
+* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime;
+* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are:
+ * `RELEASE` - public releases from Google;
+ * `LINARO` - NDK from Linaro project;
+ * `ANDROID` - NDK from AOSP.
+* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`);
+* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86);
+* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`);
+* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`);
+* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product/<product_name>/obj/lib/libm.so`) to workaround unresolved `sincos`.
+
+## Fine-tuning `CMakeLists.txt` for _android-cmake_
+
+### Recognizing Android build
+
+_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff:
+
+ if (ANDROID)
+ message(STATUS "Hello from Android build!")
+ endif()
+
+The recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value:
+
+* `armv5te` - for `armeabi` ABI
+* `armv6` - for `armeabi-v6 with VFP` ABI
+* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs
+* `aarch64` - for `arm64-v8a` ABI
+* `i686` - for `x86` ABI
+* `x86_64` - for `x86_64` ABI
+* `mips` - for `mips` ABI
+* `mips64` - for `mips64` ABI
+
+Other variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are:
+
+* `NEON` - set if target ABI supports Neon;
+* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level)
+* `ANDROID_NDK_RELEASE` - version of the Android NDK
+* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform
+* `ANDROID_RTTI` - set if rtti is enabled by the runtime
+* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime
+
+### Finding packages
+
+When crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So
+
+ find_package(ZLIB)
+
+will surely find libz.so within the Android NDK.
+
+However sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`:
+
+ find_host_package(Doxygen)
+ find_host_program(PDFLATEX pdflatex)
+
+However this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command):
+
+ # Search packages for host system instead of packages for target system
+ # in case of cross compilation these macro should be defined by toolchain file
+ if(NOT COMMAND find_host_package)
+ macro(find_host_package)
+ find_package(${ARGN})
+ endmacro()
+ endif()
+ if(NOT COMMAND find_host_program)
+ macro(find_host_program)
+ find_program(${ARGN})
+ endmacro()
+ endif()
+
+### Compiler flags recycling
+
+Make sure to do the following in your scripts:
+
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}")
+
+The flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags.
+
+## Troubleshooting
+
+### Building on Windows
+
+First of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead.
+
+To build with Ninja you need:
+
+* Ensure you are using CMake newer than 2.8.9;
+* Download the latest Ninja from https://github.com/martine/ninja/releases;
+* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable);
+* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`).
+* Enjoy the fast native multithreaded build :)
+
+But if you still want to stick to old make then:
+
+* Get a Windows port of GNU Make:
+ * Android NDK r7 (and newer) already has `make.exe` on board;
+ * `mingw-make` should work as fine;
+ * Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm.
+* Add path to your `make.exe` to system PATH or always use full path;
+* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="<full/path/to/>make.exe"`
+ * It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make.
+* Run `make.exe` or `cmake --build .` for single-threaded build.
+
+### Projects with assembler files
+
+The _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5
+
+## Copying
+
+_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) \ No newline at end of file
diff --git a/third_party/android-cmake/android.toolchain.cmake b/third_party/android-cmake/android.toolchain.cmake
new file mode 100644
index 00000000..ffa26126
--- /dev/null
+++ b/third_party/android-cmake/android.toolchain.cmake
@@ -0,0 +1,1693 @@
+# Copyright (c) 2010-2011, Ethan Rublee
+# Copyright (c) 2011-2014, Andrey Kamaev
+# 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. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
+
+# ------------------------------------------------------------------------------
+# Android CMake toolchain file, for use with the Android NDK r5-r10d
+# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended).
+# See home page: https://github.com/taka-no-me/android-cmake
+#
+# Usage Linux:
+# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk
+# $ mkdir build && cd build
+# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
+# $ make -j8
+#
+# Usage Windows:
+# You need native port of make to build your project.
+# Android NDK r7 (and newer) already has make.exe on board.
+# For older NDK you have to install it separately.
+# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm
+#
+# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk
+# $ mkdir build && cd build
+# $ cmake.exe -G"MinGW Makefiles"
+# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake
+# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" ..
+# $ cmake.exe --build .
+#
+#
+# Options (can be set as cmake parameters: -D<option_name>=<value>):
+# ANDROID_NDK=/opt/android-ndk - path to the NDK root.
+# Can be set as environment variable. Can be set only at first cmake run.
+#
+# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary
+# Interface (ABI). This option nearly matches to the APP_ABI variable
+# used by ndk-build tool from Android NDK.
+#
+# Possible targets are:
+# "armeabi" - ARMv5TE based CPU with software floating point operations
+# "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions
+# this ABI target is used by default
+# "armeabi-v7a with NEON" - same as armeabi-v7a, but
+# sets NEON as floating-point unit
+# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but
+# sets VFPV3 as floating-point unit (has 32 registers instead of 16)
+# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP
+# "x86" - IA-32 instruction set
+# "mips" - MIPS32 instruction set
+#
+# 64-bit ABIs for NDK r10 and newer:
+# "arm64-v8a" - ARMv8 AArch64 instruction set
+# "x86_64" - Intel64 instruction set (r1)
+# "mips64" - MIPS64 instruction set (r6)
+#
+# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for.
+# Option is read-only when standalone toolchain is used.
+# Note: building for "android-L" requires explicit configuration.
+#
+# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler
+# toolchain to be used. The list of possible values depends on the NDK
+# version. For NDK r10c the possible values are:
+#
+# * aarch64-linux-android-4.9
+# * aarch64-linux-android-clang3.4
+# * aarch64-linux-android-clang3.5
+# * arm-linux-androideabi-4.6
+# * arm-linux-androideabi-4.8
+# * arm-linux-androideabi-4.9 (default)
+# * arm-linux-androideabi-clang3.4
+# * arm-linux-androideabi-clang3.5
+# * mips64el-linux-android-4.9
+# * mips64el-linux-android-clang3.4
+# * mips64el-linux-android-clang3.5
+# * mipsel-linux-android-4.6
+# * mipsel-linux-android-4.8
+# * mipsel-linux-android-4.9
+# * mipsel-linux-android-clang3.4
+# * mipsel-linux-android-clang3.5
+# * x86-4.6
+# * x86-4.8
+# * x86-4.9
+# * x86-clang3.4
+# * x86-clang3.5
+# * x86_64-4.9
+# * x86_64-clang3.4
+# * x86_64-clang3.5
+#
+# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions
+# instead of Thumb. Is not available for "armeabi-v6 with VFP"
+# (is forced to be ON) ABI.
+#
+# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker
+# errors even if they are not used.
+#
+# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared
+# libraries. Automatically turned for NDK r5x and r6x due to GLESv2
+# problems.
+#
+# ANDROID_STL=gnustl_static - specify the runtime to use.
+#
+# Possible values are:
+# none -> Do not configure the runtime.
+# system -> Use the default minimal system C++ runtime library.
+# Implies -fno-rtti -fno-exceptions.
+# Is not available for standalone toolchain.
+# system_re -> Use the default minimal system C++ runtime library.
+# Implies -frtti -fexceptions.
+# Is not available for standalone toolchain.
+# gabi++_static -> Use the GAbi++ runtime as a static library.
+# Implies -frtti -fno-exceptions.
+# Available for NDK r7 and newer.
+# Is not available for standalone toolchain.
+# gabi++_shared -> Use the GAbi++ runtime as a shared library.
+# Implies -frtti -fno-exceptions.
+# Available for NDK r7 and newer.
+# Is not available for standalone toolchain.
+# stlport_static -> Use the STLport runtime as a static library.
+# Implies -fno-rtti -fno-exceptions for NDK before r7.
+# Implies -frtti -fno-exceptions for NDK r7 and newer.
+# Is not available for standalone toolchain.
+# stlport_shared -> Use the STLport runtime as a shared library.
+# Implies -fno-rtti -fno-exceptions for NDK before r7.
+# Implies -frtti -fno-exceptions for NDK r7 and newer.
+# Is not available for standalone toolchain.
+# gnustl_static -> Use the GNU STL as a static library.
+# Implies -frtti -fexceptions.
+# gnustl_shared -> Use the GNU STL as a shared library.
+# Implies -frtti -fno-exceptions.
+# Available for NDK r7b and newer.
+# Silently degrades to gnustl_static if not available.
+#
+# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on
+# chosen runtime. If disabled, then the user is responsible for settings
+# these options.
+#
+# What?:
+# android-cmake toolchain searches for NDK/toolchain in the following order:
+# ANDROID_NDK - cmake parameter
+# ANDROID_NDK - environment variable
+# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter
+# ANDROID_STANDALONE_TOOLCHAIN - environment variable
+# ANDROID_NDK - default locations
+# ANDROID_STANDALONE_TOOLCHAIN - default locations
+#
+# Make sure to do the following in your scripts:
+# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" )
+# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" )
+# The flags will be prepopulated with critical flags, so don't loose them.
+# Also be aware that toolchain also sets configuration-specific compiler
+# flags and linker flags.
+#
+# ANDROID and BUILD_ANDROID will be set to true, you may test any of these
+# variables to make necessary Android-specific configuration changes.
+#
+# Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64
+# will be set true, mutually exclusive. NEON option will be set true
+# if VFP is set to NEON.
+#
+# ------------------------------------------------------------------------------
+
+cmake_minimum_required( VERSION 2.6.3 )
+
+if( DEFINED CMAKE_CROSSCOMPILING )
+ # subsequent toolchain loading is not really needed
+ return()
+endif()
+
+if( CMAKE_TOOLCHAIN_FILE )
+ # touch toolchain variable to suppress "unused variable" warning
+endif()
+
+# inherit settings in recursive loads
+get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
+if( _CMAKE_IN_TRY_COMPILE )
+ include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL )
+endif()
+
+# this one is important
+if( CMAKE_VERSION VERSION_GREATER "3.0.99" )
+ set( CMAKE_SYSTEM_NAME Android )
+else()
+ set( CMAKE_SYSTEM_NAME Linux )
+endif()
+
+# this one not so much
+set( CMAKE_SYSTEM_VERSION 1 )
+
+# rpath makes low sense for Android
+set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" )
+set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
+
+# NDK search paths
+set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
+if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS )
+ if( CMAKE_HOST_WIN32 )
+ file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
+ set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" )
+ else()
+ file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS )
+ set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" )
+ endif()
+endif()
+if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
+ set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
+endif()
+
+# known ABIs
+set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" )
+set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" )
+set( ANDROID_SUPPORTED_ABIS_x86 "x86" )
+set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" )
+set( ANDROID_SUPPORTED_ABIS_mips "mips" )
+set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" )
+
+# API level defaults
+set( ANDROID_DEFAULT_NDK_API_LEVEL 8 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 )
+
+
+macro( __LIST_FILTER listvar regex )
+ if( ${listvar} )
+ foreach( __val ${${listvar}} )
+ if( __val MATCHES "${regex}" )
+ list( REMOVE_ITEM ${listvar} "${__val}" )
+ endif()
+ endforeach()
+ endif()
+endmacro()
+
+macro( __INIT_VARIABLE var_name )
+ set( __test_path 0 )
+ foreach( __var ${ARGN} )
+ if( __var STREQUAL "PATH" )
+ set( __test_path 1 )
+ break()
+ endif()
+ endforeach()
+
+ if( __test_path AND NOT EXISTS "${${var_name}}" )
+ unset( ${var_name} CACHE )
+ endif()
+
+ if( " ${${var_name}}" STREQUAL " " )
+ set( __values 0 )
+ foreach( __var ${ARGN} )
+ if( __var STREQUAL "VALUES" )
+ set( __values 1 )
+ elseif( NOT __var STREQUAL "PATH" )
+ if( __var MATCHES "^ENV_.*$" )
+ string( REPLACE "ENV_" "" __var "${__var}" )
+ set( __value "$ENV{${__var}}" )
+ elseif( DEFINED ${__var} )
+ set( __value "${${__var}}" )
+ elseif( __values )
+ set( __value "${__var}" )
+ else()
+ set( __value "" )
+ endif()
+
+ if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") )
+ set( ${var_name} "${__value}" )
+ break()
+ endif()
+ endif()
+ endforeach()
+ unset( __value )
+ unset( __values )
+ endif()
+
+ if( __test_path )
+ file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
+ endif()
+ unset( __test_path )
+endmacro()
+
+macro( __DETECT_NATIVE_API_LEVEL _var _path )
+ set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
+ file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
+ if( NOT __apiFileContent )
+ message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
+ endif()
+ string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
+ unset( __apiFileContent )
+ unset( __ndkApiLevelRegex )
+endmacro()
+
+macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root )
+ if( EXISTS "${_root}" )
+ file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
+ __LIST_FILTER( __gccExePath "^[.].*" )
+ list( LENGTH __gccExePath __gccExePathsCount )
+ if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE )
+ message( WARNING "Could not determine machine name for compiler from ${_root}" )
+ set( ${_var} "" )
+ else()
+ get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
+ string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
+ endif()
+ unset( __gccExePath )
+ unset( __gccExePathsCount )
+ unset( __gccExeName )
+ else()
+ set( ${_var} "" )
+ endif()
+endmacro()
+
+
+# fight against cygwin
+set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools")
+mark_as_advanced( ANDROID_FORBID_SYGWIN )
+if( ANDROID_FORBID_SYGWIN )
+ if( CYGWIN )
+ message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." )
+ endif()
+
+ if( CMAKE_HOST_WIN32 )
+ # remove cygwin from PATH
+ set( __new_path "$ENV{PATH}")
+ __LIST_FILTER( __new_path "cygwin" )
+ set(ENV{PATH} "${__new_path}")
+ unset(__new_path)
+ endif()
+endif()
+
+
+# detect current host platform
+if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) )
+ set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" )
+ mark_as_advanced( ANDROID_NDK_HOST_X64 )
+endif()
+
+set( TOOL_OS_SUFFIX "" )
+if( CMAKE_HOST_APPLE )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" )
+elseif( CMAKE_HOST_WIN32 )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" )
+ set( TOOL_OS_SUFFIX ".exe" )
+elseif( CMAKE_HOST_UNIX )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" )
+else()
+ message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
+endif()
+
+if( NOT ANDROID_NDK_HOST_X64 )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
+endif()
+
+# see if we have path to Android NDK
+if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN )
+ __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
+endif()
+if( NOT ANDROID_NDK )
+ # see if we have path to Android standalone toolchain
+ __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN )
+
+ if( NOT ANDROID_STANDALONE_TOOLCHAIN )
+ #try to find Android NDK in one of the the default locations
+ set( __ndkSearchPaths )
+ foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} )
+ foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} )
+ list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" )
+ endforeach()
+ endforeach()
+ __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} )
+ unset( __ndkSearchPaths )
+
+ if( ANDROID_NDK )
+ message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" )
+ message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" )
+ else()
+ #try to find Android standalone toolchain in one of the the default locations
+ __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
+
+ if( ANDROID_STANDALONE_TOOLCHAIN )
+ message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" )
+ message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" )
+ endif( ANDROID_STANDALONE_TOOLCHAIN )
+ endif( ANDROID_NDK )
+ endif( NOT ANDROID_STANDALONE_TOOLCHAIN )
+endif( NOT ANDROID_NDK )
+
+# remember found paths
+if( ANDROID_NDK )
+ get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
+ set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE )
+ set( BUILD_WITH_ANDROID_NDK True )
+ if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
+ file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" )
+ string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" )
+ else()
+ set( ANDROID_NDK_RELEASE "r1x" )
+ set( ANDROID_NDK_RELEASE_FULL "unreleased" )
+ endif()
+ string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" )
+ string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum )
+ math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" )
+elseif( ANDROID_STANDALONE_TOOLCHAIN )
+ get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
+ # try to detect change
+ if( CMAKE_AR )
+ string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length )
+ string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath )
+ if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN )
+ message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." )
+ endif()
+ unset( __androidStandaloneToolchainPreviousPath )
+ unset( __length )
+ endif()
+ set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE )
+ set( BUILD_WITH_STANDALONE_TOOLCHAIN True )
+else()
+ list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH)
+ message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain.
+ You should either set an environment variable:
+ export ANDROID_NDK=~/my-android-ndk
+ or
+ export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain
+ or put the toolchain or NDK in the default path:
+ sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk
+ sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
+endif()
+
+# android NDK layout
+if( BUILD_WITH_ANDROID_NDK )
+ if( NOT DEFINED ANDROID_NDK_LAYOUT )
+ # try to automatically detect the layout
+ if( EXISTS "${ANDROID_NDK}/RELEASE.TXT")
+ set( ANDROID_NDK_LAYOUT "RELEASE" )
+ elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" )
+ set( ANDROID_NDK_LAYOUT "LINARO" )
+ elseif( EXISTS "${ANDROID_NDK}/../../gcc/" )
+ set( ANDROID_NDK_LAYOUT "ANDROID" )
+ endif()
+ endif()
+ set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" )
+ mark_as_advanced( ANDROID_NDK_LAYOUT )
+ if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+ set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+ set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE"
+ set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" )
+ endif()
+ get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE )
+
+ # try to detect change of NDK
+ if( CMAKE_AR )
+ string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length )
+ string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
+ if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH )
+ message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first.
+ " )
+ endif()
+ unset( __androidNdkPreviousPath )
+ unset( __length )
+ endif()
+endif()
+
+
+# get all the details about standalone toolchain
+if( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" )
+ set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ set( __availableToolchains "standalone" )
+ __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ if( NOT __availableToolchainMachines )
+ message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." )
+ endif()
+ if( __availableToolchainMachines MATCHES x86_64 )
+ set( __availableToolchainArchs "x86_64" )
+ elseif( __availableToolchainMachines MATCHES i686 )
+ set( __availableToolchainArchs "x86" )
+ elseif( __availableToolchainMachines MATCHES aarch64 )
+ set( __availableToolchainArchs "arm64" )
+ elseif( __availableToolchainMachines MATCHES arm )
+ set( __availableToolchainArchs "arm" )
+ elseif( __availableToolchainMachines MATCHES mips64el )
+ set( __availableToolchainArchs "mips64" )
+ elseif( __availableToolchainMachines MATCHES mipsel )
+ set( __availableToolchainArchs "mips" )
+ endif()
+ execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion
+ OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE )
+ string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" )
+ if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" )
+ list( APPEND __availableToolchains "standalone-clang" )
+ list( APPEND __availableToolchainMachines ${__availableToolchainMachines} )
+ list( APPEND __availableToolchainArchs ${__availableToolchainArchs} )
+ list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} )
+ endif()
+endif()
+
+macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
+ foreach( __toolchain ${${__availableToolchainsLst}} )
+ if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
+ SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" )
+ FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" )
+ if( __toolchainVersionStr )
+ string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" )
+ string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" )
+ else()
+ string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
+ endif()
+ unset( __toolchainVersionStr )
+ unset( __toolchainVersionRegex )
+ else()
+ set( __gcc_toolchain "${__toolchain}" )
+ endif()
+ __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" )
+ if( __machine )
+ string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" )
+ if( __machine MATCHES x86_64 )
+ set( __arch "x86_64" )
+ elseif( __machine MATCHES i686 )
+ set( __arch "x86" )
+ elseif( __machine MATCHES aarch64 )
+ set( __arch "arm64" )
+ elseif( __machine MATCHES arm )
+ set( __arch "arm" )
+ elseif( __machine MATCHES mips64el )
+ set( __arch "mips64" )
+ elseif( __machine MATCHES mipsel )
+ set( __arch "mips" )
+ else()
+ set( __arch "" )
+ endif()
+ #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n")
+ if (__arch)
+ list( APPEND __availableToolchainMachines "${__machine}" )
+ list( APPEND __availableToolchainArchs "${__arch}" )
+ list( APPEND __availableToolchainCompilerVersions "${__version}" )
+ list( APPEND ${__availableToolchainsVar} "${__toolchain}" )
+ endif()
+ endif()
+ unset( __gcc_toolchain )
+ endforeach()
+endmacro()
+
+# get all the details about NDK
+if( BUILD_WITH_ANDROID_NDK )
+ file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" )
+ string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" )
+ set( __availableToolchains "" )
+ set( __availableToolchainMachines "" )
+ set( __availableToolchainArchs "" )
+ set( __availableToolchainCompilerVersions "" )
+ if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
+ # do not go through all toolchains if we know the name
+ set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+ if( __availableToolchains )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+ endif()
+ endif()
+ endif()
+ if( NOT __availableToolchains )
+ file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
+ if( __availableToolchainsLst )
+ list(SORT __availableToolchainsLst) # we need clang to go after gcc
+ endif()
+ __LIST_FILTER( __availableToolchainsLst "^[.]" )
+ __LIST_FILTER( __availableToolchainsLst "llvm" )
+ __LIST_FILTER( __availableToolchainsLst "renderscript" )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+ if( __availableToolchains )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+ endif()
+ endif()
+ endif()
+ if( NOT __availableToolchains )
+ message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." )
+ endif()
+endif()
+
+# build list of available ABIs
+set( ANDROID_SUPPORTED_ABIS "" )
+set( __uniqToolchainArchNames ${__availableToolchainArchs} )
+list( REMOVE_DUPLICATES __uniqToolchainArchNames )
+list( SORT __uniqToolchainArchNames )
+foreach( __arch ${__uniqToolchainArchNames} )
+ list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} )
+endforeach()
+unset( __uniqToolchainArchNames )
+if( NOT ANDROID_SUPPORTED_ABIS )
+ message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." )
+endif()
+
+# choose target ABI
+__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} )
+# verify that target ABI is supported
+list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
+if( __androidAbiIdx EQUAL -1 )
+ string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" )
+ message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain.
+ Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\"
+ " )
+endif()
+unset( __androidAbiIdx )
+
+# set target ABI options
+if( ANDROID_ABI STREQUAL "x86" )
+ set( X86 true )
+ set( ANDROID_NDK_ABI_NAME "x86" )
+ set( ANDROID_ARCH_NAME "x86" )
+ set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "i686" )
+elseif( ANDROID_ABI STREQUAL "x86_64" )
+ set( X86 true )
+ set( X86_64 true )
+ set( ANDROID_NDK_ABI_NAME "x86_64" )
+ set( ANDROID_ARCH_NAME "x86_64" )
+ set( CMAKE_SYSTEM_PROCESSOR "x86_64" )
+ set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" )
+elseif( ANDROID_ABI STREQUAL "mips64" )
+ set( MIPS64 true )
+ set( ANDROID_NDK_ABI_NAME "mips64" )
+ set( ANDROID_ARCH_NAME "mips64" )
+ set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "mips64" )
+elseif( ANDROID_ABI STREQUAL "mips" )
+ set( MIPS true )
+ set( ANDROID_NDK_ABI_NAME "mips" )
+ set( ANDROID_ARCH_NAME "mips" )
+ set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "mips" )
+elseif( ANDROID_ABI STREQUAL "arm64-v8a" )
+ set( ARM64_V8A true )
+ set( ANDROID_NDK_ABI_NAME "arm64-v8a" )
+ set( ANDROID_ARCH_NAME "arm64" )
+ set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "aarch64" )
+ set( VFPV3 true )
+ set( NEON true )
+elseif( ANDROID_ABI STREQUAL "armeabi" )
+ set( ARMEABI true )
+ set( ANDROID_NDK_ABI_NAME "armeabi" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv5te" )
+elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" )
+ set( ARMEABI_V6 true )
+ set( ANDROID_NDK_ABI_NAME "armeabi" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv6" )
+ # need always fallback to older platform
+ set( ARMEABI true )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a")
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" )
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+ set( VFPV3 true )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" )
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+ set( VFPV3 true )
+ set( NEON true )
+else()
+ message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." )
+endif()
+
+if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" )
+ # really dirty hack
+ # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run...
+ file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" )
+endif()
+
+if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
+ __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF )
+ set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE )
+ mark_as_advanced( ANDROID_FORCE_ARM_BUILD )
+else()
+ unset( ANDROID_FORCE_ARM_BUILD CACHE )
+endif()
+
+# choose toolchain
+if( ANDROID_TOOLCHAIN_NAME )
+ list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx )
+ if( __toolchainIdx EQUAL -1 )
+ list( SORT __availableToolchains )
+ string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" )
+ set( toolchains_list " * ${toolchains_list}")
+ message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain.
+To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" )
+ endif()
+ list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch )
+ if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+ message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." )
+ endif()
+else()
+ set( __toolchainIdx -1 )
+ set( __applicableToolchains "" )
+ set( __toolchainMaxVersion "0.0.0" )
+ list( LENGTH __availableToolchains __availableToolchainsCount )
+ math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" )
+ foreach( __idx RANGE ${__availableToolchainsCount} )
+ list( GET __availableToolchainArchs ${__idx} __toolchainArch )
+ if( __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+ list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion )
+ string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}")
+ if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion )
+ set( __toolchainMaxVersion "${__toolchainVersion}" )
+ set( __toolchainIdx ${__idx} )
+ endif()
+ endif()
+ endforeach()
+ unset( __availableToolchainsCount )
+ unset( __toolchainMaxVersion )
+ unset( __toolchainVersion )
+endif()
+unset( __toolchainArch )
+if( __toolchainIdx EQUAL -1 )
+ message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." )
+endif()
+list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME )
+list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME )
+list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION )
+
+unset( __toolchainIdx )
+unset( __availableToolchains )
+unset( __availableToolchainMachines )
+unset( __availableToolchainArchs )
+unset( __availableToolchainCompilerVersions )
+
+# choose native API level
+__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )
+string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" )
+string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL )
+# adjust API level
+set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} )
+foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level )
+ set( __real_api_level ${__level} )
+ endif()
+endforeach()
+if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level )
+ message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'")
+ set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} )
+endif()
+unset(__real_api_level)
+# validate
+list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx )
+if( __levelIdx EQUAL -1 )
+ message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." )
+else()
+ if( BUILD_WITH_ANDROID_NDK )
+ __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" )
+ if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 )
+ message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." )
+ endif()
+ unset( __realApiLevel )
+ endif()
+ set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE )
+ set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} )
+ if( CMAKE_VERSION VERSION_GREATER "2.8" )
+ list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
+ set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ endif()
+endif()
+unset( __levelIdx )
+
+
+# remember target ABI
+set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE )
+if( CMAKE_VERSION VERSION_GREATER "2.8" )
+ list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} )
+ set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} )
+endif()
+
+
+# runtime choice (STL, rtti, exceptions)
+if( NOT ANDROID_STL )
+ set( ANDROID_STL gnustl_static )
+endif()
+set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" )
+set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" )
+mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES )
+
+if( BUILD_WITH_ANDROID_NDK )
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$")
+ message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
+The possible values are:
+ none -> Do not configure the runtime.
+ system -> Use the default minimal system C++ runtime library.
+ system_re -> Same as system but with rtti and exceptions.
+ gabi++_static -> Use the GAbi++ runtime as a static library.
+ gabi++_shared -> Use the GAbi++ runtime as a shared library.
+ stlport_static -> Use the STLport runtime as a static library.
+ stlport_shared -> Use the STLport runtime as a shared library.
+ gnustl_static -> (default) Use the GNU STL as a static library.
+ gnustl_shared -> Use the GNU STL as a shared library.
+" )
+ endif()
+elseif( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$")
+ message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
+The possible values are:
+ none -> Do not configure the runtime.
+ gnustl_static -> (default) Use the GNU STL as a static library.
+ gnustl_shared -> Use the GNU STL as a shared library.
+" )
+ endif()
+endif()
+
+unset( ANDROID_RTTI )
+unset( ANDROID_EXCEPTIONS )
+unset( ANDROID_STL_INCLUDE_DIRS )
+unset( __libstl )
+unset( __libsupcxx )
+
+if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" )
+ message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf).
+You are strongly recommended to switch to another NDK release.
+" )
+endif()
+
+if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" )
+ message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header:
+See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2
+ diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+ index 5e28c64..65892a1 100644
+ --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+ +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+ @@ -51,7 +51,11 @@ typedef long int ssize_t;
+ #endif
+ #ifndef _PTRDIFF_T
+ #define _PTRDIFF_T
+ -typedef long ptrdiff_t;
+ +# ifdef __ANDROID__
+ + typedef int ptrdiff_t;
+ +# else
+ + typedef long ptrdiff_t;
+ +# endif
+ #endif
+" )
+endif()
+
+
+# setup paths and STL for standalone toolchain
+if( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" )
+
+ if( NOT ANDROID_STL STREQUAL "none" )
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" )
+ if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" )
+ # old location ( pre r8c )
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" )
+ endif()
+ if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" )
+ list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" )
+ elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" )
+ list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" )
+ else()
+ list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" )
+ endif()
+ # always search static GNU STL to get the location of libsupc++.a
+ if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" )
+ set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" )
+ elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" )
+ set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" )
+ elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" )
+ set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" )
+ elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" )
+ set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" )
+ endif()
+ if( __libstl )
+ set( __libsupcxx "${__libstl}/libsupc++.a" )
+ set( __libstl "${__libstl}/libstdc++.a" )
+ endif()
+ if( NOT EXISTS "${__libsupcxx}" )
+ message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain.
+ Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c.
+ You need to either upgrade to newer NDK or manually copy
+ $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a
+ to
+ ${__libsupcxx}
+ " )
+ endif()
+ if( ANDROID_STL STREQUAL "gnustl_shared" )
+ if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
+ set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
+ elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
+ set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
+ elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
+ set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
+ endif()
+ endif()
+ endif()
+endif()
+
+# clang
+if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
+ set( ANDROID_COMPILER_IS_CLANG 1 )
+ execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
+ string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}")
+elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
+ string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
+ string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
+ if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
+ message( FATAL_ERROR "Could not find the Clang compiler driver" )
+ endif()
+ set( ANDROID_COMPILER_IS_CLANG 1 )
+ set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+else()
+ set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
+ unset( ANDROID_COMPILER_IS_CLANG CACHE )
+endif()
+
+string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" )
+if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" )
+ set( _clang_name "clang" )
+endif()
+
+
+# setup paths and STL for NDK
+if( BUILD_WITH_ANDROID_NDK )
+ set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" )
+
+ if( ANDROID_STL STREQUAL "none" )
+ # do nothing
+ elseif( ANDROID_STL STREQUAL "system" )
+ set( ANDROID_RTTI OFF )
+ set( ANDROID_EXCEPTIONS OFF )
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
+ elseif( ANDROID_STL STREQUAL "system_re" )
+ set( ANDROID_RTTI ON )
+ set( ANDROID_EXCEPTIONS ON )
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
+ elseif( ANDROID_STL MATCHES "gabi" )
+ if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+ message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
+ endif()
+ set( ANDROID_RTTI ON )
+ set( ANDROID_EXCEPTIONS OFF )
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" )
+ set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" )
+ elseif( ANDROID_STL MATCHES "stlport" )
+ if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d
+ set( ANDROID_EXCEPTIONS ON )
+ else()
+ set( ANDROID_EXCEPTIONS OFF )
+ endif()
+ if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+ set( ANDROID_RTTI OFF )
+ else()
+ set( ANDROID_RTTI ON )
+ endif()
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" )
+ set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" )
+ elseif( ANDROID_STL MATCHES "gnustl" )
+ set( ANDROID_EXCEPTIONS ON )
+ set( ANDROID_RTTI ON )
+ if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
+ if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" )
+ # gnustl binary for 4.7 compiler is buggy :(
+ # TODO: look for right fix
+ set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" )
+ else()
+ set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
+ endif()
+ else()
+ set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" )
+ endif()
+ set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" )
+ if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
+ set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
+ else()
+ set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
+ endif()
+ else()
+ message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" )
+ endif()
+ # find libsupc++.a - rtti & exceptions
+ if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" )
+ set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer
+ if( NOT EXISTS "${__libsupcxx}" )
+ set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8
+ endif()
+ if( NOT EXISTS "${__libsupcxx}" ) # before r7
+ if( ARMEABI_V7A )
+ if( ANDROID_FORCE_ARM_BUILD )
+ set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" )
+ else()
+ set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" )
+ endif()
+ elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD )
+ set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" )
+ else()
+ set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" )
+ endif()
+ endif()
+ if( NOT EXISTS "${__libsupcxx}")
+ message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.")
+ endif()
+ endif()
+endif()
+
+
+# case of shared STL linkage
+if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl )
+ string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" )
+ # TODO: check if .so file exists before the renaming
+endif()
+
+
+# ccache support
+__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE )
+if( _ndk_ccache )
+ if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE )
+ unset( NDK_CCACHE CACHE )
+ endif()
+ find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary")
+else()
+ unset( NDK_CCACHE CACHE )
+endif()
+unset( _ndk_ccache )
+
+
+# setup the cross-compiler
+if( NOT CMAKE_C_COMPILER )
+ if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
+ set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" )
+ set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" )
+ if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
+ set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+ else()
+ set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
+ set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+ endif()
+ else()
+ if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
+ set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+ else()
+ set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" )
+ set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" )
+ endif()
+ endif()
+ set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" )
+ set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" )
+ if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" )
+ # Use gcc-ar if we have it for better LTO support.
+ set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
+ else()
+ set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
+ endif()
+ set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" )
+ set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" )
+ set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
+ set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" )
+ set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" )
+endif()
+
+set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" )
+if( CMAKE_VERSION VERSION_LESS 2.8.5 )
+ set( CMAKE_ASM_COMPILER_ARG1 "-c" )
+endif()
+if( APPLE )
+ find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
+ if( NOT CMAKE_INSTALL_NAME_TOOL )
+ message( FATAL_ERROR "Could not find install_name_tool, please check your installation." )
+ endif()
+ mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
+endif()
+
+# Force set compilers because standard identification works badly for us
+include( CMakeForceCompiler )
+CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
+if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_C_COMPILER_ID Clang )
+endif()
+set( CMAKE_C_PLATFORM_ID Linux )
+if( X86_64 OR MIPS64 OR ARM64_V8A )
+ set( CMAKE_C_SIZEOF_DATA_PTR 8 )
+else()
+ set( CMAKE_C_SIZEOF_DATA_PTR 4 )
+endif()
+set( CMAKE_C_HAS_ISYSROOT 1 )
+set( CMAKE_C_COMPILER_ABI ELF )
+CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU )
+if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_CXX_COMPILER_ID Clang)
+endif()
+set( CMAKE_CXX_PLATFORM_ID Linux )
+set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} )
+set( CMAKE_CXX_HAS_ISYSROOT 1 )
+set( CMAKE_CXX_COMPILER_ABI ELF )
+set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C )
+# force ASM compiler (required for CMake < 2.8.5)
+set( CMAKE_ASM_COMPILER_ID_RUN TRUE )
+set( CMAKE_ASM_COMPILER_ID GNU )
+set( CMAKE_ASM_COMPILER_WORKS TRUE )
+set( CMAKE_ASM_COMPILER_FORCED TRUE )
+set( CMAKE_COMPILER_IS_GNUASM 1)
+set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
+
+foreach( lang C CXX ASM )
+ if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} )
+ else()
+ set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} )
+ endif()
+endforeach()
+
+# flags and definitions
+remove_definitions( -DANDROID )
+add_definitions( -DANDROID )
+
+if( ANDROID_SYSROOT MATCHES "[ ;\"]" )
+ if( CMAKE_HOST_WIN32 )
+ # try to convert path to 8.3 form
+ file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" )
+ execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}"
+ OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE __result ERROR_QUIET )
+ if( __result EQUAL 0 )
+ file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT )
+ set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
+ else()
+ set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
+ endif()
+ else()
+ set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" )
+ endif()
+ if( NOT _CMAKE_IN_TRY_COMPILE )
+ # quotes can break try_compile and compiler identification
+ message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n")
+ endif()
+else()
+ set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
+endif()
+
+# NDK flags
+if (ARM64_V8A )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
+ endif()
+elseif( ARMEABI OR ARMEABI_V7A)
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
+ set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" )
+ endif()
+ else()
+ # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI
+ set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+ endif()
+ endif()
+elseif( X86 OR X86_64 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+ endif()
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
+elseif( MIPS OR MIPS64 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
+ set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
+ endif()
+elseif()
+ set( ANDROID_CXX_FLAGS_RELEASE "" )
+ set( ANDROID_CXX_FLAGS_DEBUG "" )
+endif()
+
+set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries
+
+if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" )
+endif()
+
+if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/
+endif()
+
+# ABI-specific flags
+if( ARMEABI_V7A )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" )
+ if( NEON )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" )
+ elseif( VFPV3 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" )
+ else()
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" )
+ endif()
+elseif( ARMEABI_V6 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2
+elseif( ARMEABI )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" )
+endif()
+
+if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+else()
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+endif()
+
+# STL
+if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
+ if( EXISTS "${__libstl}" )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" )
+ set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" )
+ endif()
+ if( EXISTS "${__libsupcxx}" )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
+ set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
+ # C objects:
+ set( CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_C_CREATE_SHARED_MODULE "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+ set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
+ set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
+ set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
+ endif()
+ if( ANDROID_STL MATCHES "gnustl" )
+ if( NOT EXISTS "${ANDROID_LIBM_PATH}" )
+ set( ANDROID_LIBM_PATH -lm )
+ endif()
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" )
+ set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" )
+ endif()
+endif()
+
+# variables controlling optional build flags
+if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+ # libGLESv2.so in NDK's prior to r7 refers to missing external symbols.
+ # So this flag option is required for all projects using OpenGL from native.
+ __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON )
+else()
+ __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF )
+endif()
+__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON )
+__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON )
+__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON )
+__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON )
+__INIT_VARIABLE( ANDROID_RELRO VALUES ON )
+
+set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" )
+set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
+set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" )
+set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" )
+set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
+set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" )
+mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO )
+
+# linker flags
+set( ANDROID_LINKER_FLAGS "" )
+
+if( ARMEABI_V7A )
+ # this is *required* to use the following linker flags that routes around
+ # a CPU bug in some Cortex-A8 implementations:
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" )
+endif()
+
+if( ANDROID_NO_UNDEFINED )
+ if( MIPS )
+ # there is some sysroot-related problem in mips linker...
+ if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" )
+ endif()
+ else()
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" )
+ endif()
+endif()
+
+if( ANDROID_SO_UNDEFINED )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" )
+endif()
+
+if( ANDROID_FUNCTION_LEVEL_LINKING )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" )
+endif()
+
+if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" )
+ if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" )
+ elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" )
+ elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE )
+ message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342
+ On Linux and OS X host platform you can workaround this problem using gold linker (default).
+ Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems.
+" )
+ endif()
+endif() # version 4.6
+
+if( ANDROID_NOEXECSTACK )
+ if( ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" )
+ else()
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" )
+ endif()
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" )
+endif()
+
+if( ANDROID_RELRO )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" )
+endif()
+
+if( ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" )
+ if( BUILD_WITH_ANDROID_NDK )
+ set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" )
+ endif()
+endif()
+
+# cache flags
+set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" )
+set( CMAKE_C_FLAGS "" CACHE STRING "c flags" )
+set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" )
+set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" )
+set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" )
+set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" )
+set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" )
+set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" )
+set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" )
+
+# put flags to cache (for debug purpose only)
+set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" )
+set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" )
+set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" )
+set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" )
+
+# finish flags
+set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
+set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
+set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" )
+set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" )
+set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" )
+set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" )
+set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" )
+set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" )
+set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
+
+if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
+ set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" )
+ set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" )
+ set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
+endif()
+
+# pie/pic
+if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) )
+ set( CMAKE_POSITION_INDEPENDENT_CODE TRUE )
+ set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
+else()
+ set( CMAKE_POSITION_INDEPENDENT_CODE FALSE )
+ set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" )
+ set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" )
+endif()
+
+# configure rtti
+if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES )
+ if( ANDROID_RTTI )
+ set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" )
+ else()
+ set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" )
+ endif()
+endif()
+
+# configure exceptios
+if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES )
+ if( ANDROID_EXCEPTIONS )
+ set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" )
+ set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" )
+ else()
+ set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" )
+ set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" )
+ endif()
+endif()
+
+# global includes and link directories
+include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} )
+get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning
+link_directories( "${__android_install_path}" )
+
+# detect if need link crtbegin_so.o explicitly
+if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK )
+ set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" )
+ string( REPLACE "<CMAKE_CXX_COMPILER>" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_C_COMPILER>" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_CXX_FLAGS>" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "<LANGUAGE_COMPILE_FLAGS>" "" __cmd "${__cmd}" )
+ string( REPLACE "<LINK_FLAGS>" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS>" "-shared" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG>" "" __cmd "${__cmd}" )
+ string( REPLACE "<TARGET_SONAME>" "" __cmd "${__cmd}" )
+ string( REPLACE "<TARGET>" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" )
+ string( REPLACE "<OBJECTS>" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" )
+ string( REPLACE "<LINK_LIBRARIES>" "" __cmd "${__cmd}" )
+ separate_arguments( __cmd )
+ foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN )
+ if( ${__var} )
+ set( __tmp "${${__var}}" )
+ separate_arguments( __tmp )
+ string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}")
+ endif()
+ endforeach()
+ string( REPLACE "'" "" __cmd "${__cmd}" )
+ string( REPLACE "\"" "" __cmd "${__cmd}" )
+ execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET )
+ if( __cmd_result EQUAL 0 )
+ set( ANDROID_EXPLICIT_CRT_LINK ON )
+ else()
+ set( ANDROID_EXPLICIT_CRT_LINK OFF )
+ endif()
+endif()
+
+if( ANDROID_EXPLICIT_CRT_LINK )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+endif()
+
+# setup output directories
+set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
+
+if( DEFINED LIBRARY_OUTPUT_PATH_ROOT
+ OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml"
+ OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") )
+ set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" )
+ if( NOT _CMAKE_IN_TRY_COMPILE )
+ if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
+ set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
+ else()
+ set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
+ endif()
+ set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" )
+ endif()
+endif()
+
+# copy shaed stl library to build directory
+if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH )
+ get_filename_component( __libstlname "${__libstl}" NAME )
+ execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
+ if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}")
+ message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" )
+ endif()
+ unset( __fileCopyProcess )
+ unset( __libstlname )
+endif()
+
+
+# set these global flags for cmake client scripts to change behavior
+set( ANDROID True )
+set( BUILD_ANDROID True )
+
+# where is the target environment
+set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" )
+
+# only search for libraries and includes in the ndk toolchain
+set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+
+
+# macro to find packages on the host OS
+macro( find_host_package )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
+ if( CMAKE_HOST_WIN32 )
+ SET( WIN32 1 )
+ SET( UNIX )
+ elseif( CMAKE_HOST_APPLE )
+ SET( APPLE 1 )
+ SET( UNIX )
+ endif()
+ find_package( ${ARGN} )
+ SET( WIN32 )
+ SET( APPLE )
+ SET( UNIX 1 )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+endmacro()
+
+
+# macro to find programs on the host OS
+macro( find_host_program )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
+ if( CMAKE_HOST_WIN32 )
+ SET( WIN32 1 )
+ SET( UNIX )
+ elseif( CMAKE_HOST_APPLE )
+ SET( APPLE 1 )
+ SET( UNIX )
+ endif()
+ find_program( ${ARGN} )
+ SET( WIN32 )
+ SET( APPLE )
+ SET( UNIX 1 )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+endmacro()
+
+
+# export toolchain settings for the try_compile() command
+if( NOT _CMAKE_IN_TRY_COMPILE )
+ set( __toolchain_config "")
+ foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN
+ ANDROID_NDK_HOST_X64
+ ANDROID_NDK
+ ANDROID_NDK_LAYOUT
+ ANDROID_STANDALONE_TOOLCHAIN
+ ANDROID_TOOLCHAIN_NAME
+ ANDROID_ABI
+ ANDROID_NATIVE_API_LEVEL
+ ANDROID_STL
+ ANDROID_STL_FORCE_FEATURES
+ ANDROID_FORCE_ARM_BUILD
+ ANDROID_NO_UNDEFINED
+ ANDROID_SO_UNDEFINED
+ ANDROID_FUNCTION_LEVEL_LINKING
+ ANDROID_GOLD_LINKER
+ ANDROID_NOEXECSTACK
+ ANDROID_RELRO
+ ANDROID_LIBM_PATH
+ ANDROID_EXPLICIT_CRT_LINK
+ ANDROID_APP_PIE
+ )
+ if( DEFINED ${__var} )
+ if( ${__var} MATCHES " ")
+ set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" )
+ else()
+ set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" )
+ endif()
+ endif()
+ endforeach()
+ file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" )
+ unset( __toolchain_config )
+endif()
+
+
+# force cmake to produce / instead of \ in build commands for Ninja generator
+if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 )
+ # it is a bad hack after all
+ # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW
+ set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW
+ set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion
+ enable_language( C )
+ enable_language( CXX )
+ # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it
+ unset( MINGW )
+endif()
+
+
+# Variables controlling behavior or set by cmake toolchain:
+# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64"
+# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version)
+# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none
+# ANDROID_FORBID_SYGWIN : ON/OFF
+# ANDROID_NO_UNDEFINED : ON/OFF
+# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version)
+# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF
+# ANDROID_GOLD_LINKER : ON/OFF
+# ANDROID_NOEXECSTACK : ON/OFF
+# ANDROID_RELRO : ON/OFF
+# ANDROID_FORCE_ARM_BUILD : ON/OFF
+# ANDROID_STL_FORCE_FEATURES : ON/OFF
+# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
+# Can be set only at the first run:
+# ANDROID_NDK : path to your NDK install
+# NDK_CCACHE : path to your ccache executable
+# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
+# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
+# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
+# LIBRARY_OUTPUT_PATH_ROOT : <any valid path>
+# ANDROID_STANDALONE_TOOLCHAIN
+#
+# Primary read-only variables:
+# ANDROID : always TRUE
+# ARMEABI : TRUE for arm v6 and older devices
+# ARMEABI_V6 : TRUE for arm v6
+# ARMEABI_V7A : TRUE for arm v7a
+# ARM64_V8A : TRUE for arm64-v8a
+# NEON : TRUE if NEON unit is enabled
+# VFPV3 : TRUE if VFP version 3 is enabled
+# X86 : TRUE if configured for x86
+# X86_64 : TRUE if configured for x86_64
+# MIPS : TRUE if configured for mips
+# MIPS64 : TRUE if configured for mips64
+# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
+# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
+# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
+# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI
+# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK
+# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor)
+# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI
+# ANDROID_SYSROOT : path to the compiler sysroot
+# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
+# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used
+#
+# Secondary (less stable) read-only variables:
+# ANDROID_COMPILER_VERSION : GCC version used (not Clang version)
+# ANDROID_CLANG_VERSION : version of clang compiler if clang is used
+# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform
+# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI
+# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux"
+# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK)
+# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools
+# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK
+# ANDROID_STL_INCLUDE_DIRS : stl include paths
+# ANDROID_RTTI : if rtti is enabled by the runtime
+# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
+# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
+#
+# Defaults:
+# ANDROID_DEFAULT_NDK_API_LEVEL
+# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
+# ANDROID_NDK_SEARCH_PATHS
+# ANDROID_SUPPORTED_ABIS_${ARCH}
+# ANDROID_SUPPORTED_NDK_VERSIONS
diff --git a/third_party/android-cmake/ndk_links.md b/third_party/android-cmake/ndk_links.md
new file mode 100644
index 00000000..6d93d61d
--- /dev/null
+++ b/third_party/android-cmake/ndk_links.md
@@ -0,0 +1,211 @@
+
+============== r1 ============== (dead links)
+
+* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip
+
+============== r2 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip
+
+============== r3 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip
+
+============== r4 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip
+
+============== r4b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip
+
+============== r5 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2
+
+============== r5b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2
+
+============== r5c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2
+
+============== r6 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2
+
+============== r6b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2
+
+============== r7 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2
+
+============== r7b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2
+
+============== r7c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2
+
+============== r8 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2
+
+============== r8b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2
+
+============== r8c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2
+
+============== r8d ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2
+
+============== r8e ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2
+
+============== r9 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2
+
+============== r9b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2
+
+============== r9c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip
+
+============== r9d ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip
+
+============== r10 ==============
+
+* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip
+
+============== r10b ==============
+
+* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip
+
+============== r10c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe
+* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe
+* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86_64.bin
+* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin
+
+============== r10d ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe
+* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe
+* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin
+* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin
diff --git a/tool/digest.cc b/tool/digest.cc
index 7cd88278..2e3e6085 100644
--- a/tool/digest.cc
+++ b/tool/digest.cc
@@ -31,9 +31,9 @@
#define O_BINARY 0
#endif
#else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#include <io.h>
#define PATH_MAX MAX_PATH
typedef int ssize_t;
@@ -41,10 +41,12 @@ typedef int ssize_t;
#include <openssl/digest.h>
+#include "internal.h"
+
struct close_delete {
void operator()(int *fd) {
- close(*fd);
+ BORINGSSL_CLOSE(*fd);
}
};
@@ -81,7 +83,7 @@ static const char kStdinName[] = "standard input";
static bool OpenFile(int *out_fd, const std::string &filename) {
*out_fd = -1;
- int fd = open(filename.c_str(), O_RDONLY | O_BINARY);
+ int fd = BORINGSSL_OPEN(filename.c_str(), O_RDONLY | O_BINARY);
if (fd < 0) {
fprintf(stderr, "Failed to open input file '%s': %s\n", filename.c_str(),
strerror(errno));
@@ -144,7 +146,7 @@ static bool SumFile(std::string *out_hex, const EVP_MD *md,
ssize_t n;
do {
- n = read(fd, buf.get(), kBufSize);
+ n = BORINGSSL_READ(fd, buf.get(), kBufSize);
} while (n == -1 && errno == EINTR);
if (n == 0) {
@@ -232,10 +234,10 @@ static bool Check(const CheckModeArguments &args, const EVP_MD *md,
return false;
}
- file = fdopen(fd, "rb");
+ file = BORINGSSL_FDOPEN(fd, "rb");
if (!file) {
perror("fdopen");
- close(fd);
+ BORINGSSL_CLOSE(fd);
return false;
}
diff --git a/tool/internal.h b/tool/internal.h
index 84f8c4d4..fd66e00f 100644
--- a/tool/internal.h
+++ b/tool/internal.h
@@ -20,18 +20,28 @@
#include <string>
#include <vector>
-#if defined(_MSC_VER)
-#pragma warning(push)
+OPENSSL_MSVC_PRAGMA(warning(push))
// MSVC issues warning C4702 for unreachable code in its xtree header when
// compiling with -D_HAS_EXCEPTIONS=0. See
// https://connect.microsoft.com/VisualStudio/feedback/details/809962
-#pragma warning(disable: 4702)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
#include <map>
-#if defined(_MSC_VER)
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
+
+#if defined(OPENSSL_WINDOWS)
+ #define BORINGSSL_OPEN _open
+ #define BORINGSSL_FDOPEN _fdopen
+ #define BORINGSSL_CLOSE _close
+ #define BORINGSSL_READ _read
+ #define BORINGSSL_WRITE _write
+#else
+ #define BORINGSSL_OPEN open
+ #define BORINGSSL_FDOPEN fdopen
+ #define BORINGSSL_CLOSE close
+ #define BORINGSSL_READ read
+ #define BORINGSSL_WRITE write
#endif
enum ArgumentType {
@@ -55,6 +65,21 @@ bool GetUnsigned(unsigned *out, const std::string &arg_name,
unsigned default_value,
const std::map<std::string, std::string> &args);
+bool Ciphers(const std::vector<std::string> &args);
+bool Client(const std::vector<std::string> &args);
+bool DoPKCS12(const std::vector<std::string> &args);
+bool GenerateEd25519Key(const std::vector<std::string> &args);
+bool GenerateRSAKey(const std::vector<std::string> &args);
+bool MD5Sum(const std::vector<std::string> &args);
+bool Rand(const std::vector<std::string> &args);
+bool SHA1Sum(const std::vector<std::string> &args);
+bool SHA224Sum(const std::vector<std::string> &args);
+bool SHA256Sum(const std::vector<std::string> &args);
+bool SHA384Sum(const std::vector<std::string> &args);
+bool SHA512Sum(const std::vector<std::string> &args);
+bool Server(const std::vector<std::string> &args);
+bool Speed(const std::vector<std::string> &args);
+
// These values are DER encoded, RSA private keys.
extern const uint8_t kDERRSAPrivate2048[];
extern const size_t kDERRSAPrivate2048Len;
diff --git a/tool/pkcs12.cc b/tool/pkcs12.cc
index fe830d66..15e32d3d 100644
--- a/tool/pkcs12.cc
+++ b/tool/pkcs12.cc
@@ -64,7 +64,7 @@ bool DoPKCS12(const std::vector<std::string> &args) {
return false;
}
- int fd = open(args_map["-dump"].c_str(), O_RDONLY);
+ int fd = BORINGSSL_OPEN(args_map["-dump"].c_str(), O_RDONLY);
if (fd < 0) {
perror("open");
return false;
@@ -73,7 +73,7 @@ bool DoPKCS12(const std::vector<std::string> &args) {
struct stat st;
if (fstat(fd, &st)) {
perror("fstat");
- close(fd);
+ BORINGSSL_CLOSE(fd);
return false;
}
const size_t size = st.st_size;
@@ -82,7 +82,7 @@ bool DoPKCS12(const std::vector<std::string> &args) {
read_result_t n;
size_t off = 0;
do {
- n = read(fd, &contents[off], size - off);
+ n = BORINGSSL_READ(fd, &contents[off], size - off);
if (n >= 0) {
off += static_cast<size_t>(n);
}
@@ -90,11 +90,11 @@ bool DoPKCS12(const std::vector<std::string> &args) {
if (off != size) {
perror("read");
- close(fd);
+ BORINGSSL_CLOSE(fd);
return false;
}
- close(fd);
+ BORINGSSL_CLOSE(fd);
printf("Enter password: ");
fflush(stdout);
@@ -102,7 +102,7 @@ bool DoPKCS12(const std::vector<std::string> &args) {
char password[256];
off = 0;
do {
- n = read(0, &password[off], sizeof(password) - 1 - off);
+ n = BORINGSSL_READ(0, &password[off], sizeof(password) - 1 - off);
if (n >= 0) {
off += static_cast<size_t>(n);
}
diff --git a/tool/rand.cc b/tool/rand.cc
index 10078e22..3701748c 100644
--- a/tool/rand.cc
+++ b/tool/rand.cc
@@ -71,7 +71,7 @@ bool Rand(const std::vector<std::string> &args) {
}
RAND_bytes(buf, todo);
if (hex) {
- static const char hextable[] = "0123456789abdef";
+ static const char hextable[16 + 1] = "0123456789abcdef";
for (unsigned i = 0; i < todo; i++) {
hex_buf[i*2] = hextable[buf[i] >> 4];
hex_buf[i*2 + 1] = hextable[buf[i] & 0xf];
diff --git a/tool/speed.cc b/tool/speed.cc
index db7c5fa7..a8eb8bfa 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -24,14 +24,15 @@
#include <openssl/curve25519.h>
#include <openssl/digest.h>
#include <openssl/err.h>
-#include <openssl/obj.h>
+#include <openssl/newhope.h>
+#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
#elif defined(OPENSSL_APPLE)
#include <sys/time.h>
#endif
@@ -467,6 +468,81 @@ static bool Speed25519(const std::string &selected) {
return true;
}
+static bool SpeedSPAKE2(const std::string &selected) {
+ if (!selected.empty() && selected.find("SPAKE2") == std::string::npos) {
+ return true;
+ }
+
+ TimeResults results;
+
+ static const uint8_t kAliceName[] = {'A'};
+ static const uint8_t kBobName[] = {'B'};
+ static const uint8_t kPassword[] = "password";
+ ScopedSPAKE2_CTX alice(SPAKE2_CTX_new(spake2_role_alice, kAliceName,
+ sizeof(kAliceName), kBobName,
+ sizeof(kBobName)));
+ uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
+ size_t alice_msg_len;
+
+ if (!SPAKE2_generate_msg(alice.get(), alice_msg, &alice_msg_len,
+ sizeof(alice_msg),
+ kPassword, sizeof(kPassword))) {
+ fprintf(stderr, "SPAKE2_generate_msg failed.\n");
+ return false;
+ }
+
+ if (!TimeFunction(&results, [&alice_msg, alice_msg_len]() -> bool {
+ ScopedSPAKE2_CTX bob(SPAKE2_CTX_new(spake2_role_bob, kBobName,
+ sizeof(kBobName), kAliceName,
+ sizeof(kAliceName)));
+ uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE], bob_key[64];
+ size_t bob_msg_len, bob_key_len;
+ if (!SPAKE2_generate_msg(bob.get(), bob_msg, &bob_msg_len,
+ sizeof(bob_msg), kPassword,
+ sizeof(kPassword)) ||
+ !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len,
+ sizeof(bob_key), alice_msg, alice_msg_len)) {
+ return false;
+ }
+
+ return true;
+ })) {
+ fprintf(stderr, "SPAKE2 failed.\n");
+ }
+
+ results.Print("SPAKE2 over Ed25519");
+
+ return true;
+}
+
+static bool SpeedNewHope(const std::string &selected) {
+ if (!selected.empty() && selected.find("newhope") == std::string::npos) {
+ return true;
+ }
+
+ TimeResults results;
+ NEWHOPE_POLY *sk = NEWHOPE_POLY_new();
+ uint8_t acceptmsg[NEWHOPE_ACCEPTMSG_LENGTH];
+ RAND_bytes(acceptmsg, sizeof(acceptmsg));
+
+ if (!TimeFunction(&results, [sk, &acceptmsg]() -> bool {
+ uint8_t key[SHA256_DIGEST_LENGTH];
+ uint8_t offermsg[NEWHOPE_OFFERMSG_LENGTH];
+ NEWHOPE_offer(offermsg, sk);
+ if (!NEWHOPE_finish(key, sk, acceptmsg, NEWHOPE_ACCEPTMSG_LENGTH)) {
+ return false;
+ }
+ return true;
+ })) {
+ fprintf(stderr, "failed to exchange key.\n");
+ return false;
+ }
+
+ NEWHOPE_POLY_free(sk);
+ results.Print("newhope key exchange");
+ return true;
+}
+
bool Speed(const std::vector<std::string> &args) {
std::string selected;
if (args.size() > 1) {
@@ -546,7 +622,9 @@ bool Speed(const std::vector<std::string> &args) {
!SpeedRandom(selected) ||
!SpeedECDH(selected) ||
!SpeedECDSA(selected) ||
- !Speed25519(selected)) {
+ !Speed25519(selected) ||
+ !SpeedSPAKE2(selected) ||
+ !SpeedNewHope(selected)) {
return false;
}
diff --git a/tool/tool.cc b/tool/tool.cc
index b8250089..34851b47 100644
--- a/tool/tool.cc
+++ b/tool/tool.cc
@@ -26,21 +26,8 @@
#include <libgen.h>
#endif
+#include "internal.h"
-bool Ciphers(const std::vector<std::string> &args);
-bool Client(const std::vector<std::string> &args);
-bool DoPKCS12(const std::vector<std::string> &args);
-bool GenerateEd25519Key(const std::vector<std::string> &args);
-bool GenerateRSAKey(const std::vector<std::string> &args);
-bool MD5Sum(const std::vector<std::string> &args);
-bool Rand(const std::vector<std::string> &args);
-bool SHA1Sum(const std::vector<std::string> &args);
-bool SHA224Sum(const std::vector<std::string> &args);
-bool SHA256Sum(const std::vector<std::string> &args);
-bool SHA384Sum(const std::vector<std::string> &args);
-bool SHA512Sum(const std::vector<std::string> &args);
-bool Server(const std::vector<std::string> &args);
-bool Speed(const std::vector<std::string> &args);
typedef bool (*tool_func_t)(const std::vector<std::string> &args);
@@ -83,7 +70,7 @@ static void usage(const char *name) {
}
}
-tool_func_t FindTool(const std::string &name) {
+static tool_func_t FindTool(const std::string &name) {
for (size_t i = 0;; i++) {
const Tool &tool = kTools[i];
if (tool.func == nullptr || name == tool.name) {
diff --git a/tool/transport_common.cc b/tool/transport_common.cc
index 2c15c00b..01fcde4e 100644
--- a/tool/transport_common.cc
+++ b/tool/transport_common.cc
@@ -33,10 +33,10 @@
#include <unistd.h>
#else
#include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
typedef int ssize_t;
#pragma comment(lib, "Ws2_32.lib")
@@ -44,8 +44,10 @@ typedef int ssize_t;
#include <openssl/err.h>
#include <openssl/ssl.h>
+#include <openssl/x509.h>
#include "internal.h"
+#include "transport_common.h"
#if !defined(OPENSSL_WINDOWS)
@@ -179,6 +181,8 @@ void PrintConnectionInfo(const SSL *ssl) {
}
fprintf(stderr, " Secure renegotiation: %s\n",
SSL_get_secure_renegotiation_support(ssl) ? "yes" : "no");
+ fprintf(stderr, " Extended master secret: %s\n",
+ SSL_get_extms_support(ssl) ? "yes" : "no");
const uint8_t *next_proto;
unsigned next_proto_len;
@@ -190,6 +194,19 @@ void PrintConnectionInfo(const SSL *ssl) {
unsigned alpn_len;
SSL_get0_alpn_selected(ssl, &alpn, &alpn_len);
fprintf(stderr, " ALPN protocol: %.*s\n", alpn_len, alpn);
+
+ // Print the server cert subject and issuer names.
+ X509 *peer = SSL_get_peer_certificate(ssl);
+ if (peer != NULL) {
+ fprintf(stderr, " Cert subject: ");
+ X509_NAME_print_ex_fp(stderr, X509_get_subject_name(peer), 0,
+ XN_FLAG_ONELINE);
+ fprintf(stderr, "\n Cert issuer: ");
+ X509_NAME_print_ex_fp(stderr, X509_get_issuer_name(peer), 0,
+ XN_FLAG_ONELINE);
+ fprintf(stderr, "\n");
+ X509_free(peer);
+ }
}
bool SocketSetNonBlocking(int sock, bool is_non_blocking) {
@@ -250,7 +267,7 @@ bool TransferData(SSL *ssl, int sock) {
ssize_t n;
do {
- n = read(0, buffer, sizeof(buffer));
+ n = BORINGSSL_READ(0, buffer, sizeof(buffer));
} while (n == -1 && errno == EINTR);
if (n == 0) {
@@ -304,7 +321,7 @@ bool TransferData(SSL *ssl, int sock) {
ssize_t n;
do {
- n = write(1, buffer, ssl_ret);
+ n = BORINGSSL_WRITE(1, buffer, ssl_ret);
} while (n == -1 && errno == EINTR);
if (n != ssl_ret) {
diff --git a/util/all_tests.go b/util/all_tests.go
index 566c3f70..d361651e 100644
--- a/util/all_tests.go
+++ b/util/all_tests.go
@@ -24,6 +24,7 @@ import (
"path"
"strconv"
"strings"
+ "sync"
"syscall"
"time"
)
@@ -32,8 +33,10 @@ import (
var (
useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
+ useCallgrind = flag.Bool("callgrind", false, "If true, run code under valgrind to generate callgrind traces.")
useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
buildDir = flag.String("build-dir", "build", "The build directory to run the tests from.")
+ numWorkers = flag.Int("num-workers", 1, "Runs the given number of workers when testing.")
jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask each test to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
@@ -41,6 +44,12 @@ var (
type test []string
+type result struct {
+ Test test
+ Passed bool
+ Error error
+}
+
// testOutput is a representation of Chromium's JSON test result format. See
// https://www.chromium.org/developers/the-json-test-results-format
type testOutput struct {
@@ -105,6 +114,14 @@ func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
return exec.Command("valgrind", valgrindArgs...)
}
+func callgrindOf(path string, args ...string) *exec.Cmd {
+ valgrindArgs := []string{"-q", "--tool=callgrind", "--dump-instr=yes", "--collect-jumps=yes", "--callgrind-out-file=" + *buildDir + "/callgrind/callgrind.out.%p"}
+ valgrindArgs = append(valgrindArgs, path)
+ valgrindArgs = append(valgrindArgs, args...)
+
+ return exec.Command("valgrind", valgrindArgs...)
+}
+
func gdbOf(path string, args ...string) *exec.Cmd {
xtermArgs := []string{"-e", "gdb", "--args"}
xtermArgs = append(xtermArgs, path)
@@ -127,6 +144,8 @@ func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) {
var cmd *exec.Cmd
if *useValgrind {
cmd = valgrindOf(false, prog, args...)
+ } else if *useCallgrind {
+ cmd = callgrindOf(prog, args...)
} else if *useGDB {
cmd = gdbOf(prog, args...)
} else {
@@ -225,28 +244,55 @@ func parseTestConfig(filename string) ([]test, error) {
return result, nil
}
+func worker(tests <-chan test, results chan<- result, done *sync.WaitGroup) {
+ defer done.Done()
+ for test := range tests {
+ passed, err := runTest(test)
+ results <- result{test, passed, err}
+ }
+}
+
func main() {
flag.Parse()
setWorkingDirectory()
- tests, err := parseTestConfig("util/all_tests.json")
+ testCases, err := parseTestConfig("util/all_tests.json")
if err != nil {
fmt.Printf("Failed to parse input: %s\n", err)
os.Exit(1)
}
+ var wg sync.WaitGroup
+ tests := make(chan test, *numWorkers)
+ results := make(chan result, *numWorkers)
+
+ for i := 0; i < *numWorkers; i++ {
+ wg.Add(1)
+ go worker(tests, results, &wg)
+ }
+
+ go func() {
+ for _, test := range testCases {
+ tests <- test
+ }
+ close(tests)
+
+ wg.Wait()
+ close(results)
+ }()
+
testOutput := newTestOutput()
var failed []test
- for _, test := range tests {
- fmt.Printf("%s\n", strings.Join([]string(test), " "))
+ for testResult := range results {
+ test := testResult.Test
+ fmt.Printf("%s\n", strings.Join([]string(test), " "))
name := shortTestName(test)
- passed, err := runTest(test)
- if err != nil {
- fmt.Printf("%s failed to complete: %s\n", test[0], err)
+ if testResult.Error != nil {
+ fmt.Printf("%s failed to complete: %s\n", test[0], testResult.Error)
failed = append(failed, test)
testOutput.addResult(name, "CRASHED")
- } else if !passed {
+ } else if !testResult.Passed {
fmt.Printf("%s failed to print PASS on the last line.\n", test[0])
failed = append(failed, test)
testOutput.addResult(name, "FAIL")
@@ -262,7 +308,7 @@ func main() {
}
if len(failed) > 0 {
- fmt.Printf("\n%d of %d tests failed:\n", len(failed), len(tests))
+ fmt.Printf("\n%d of %d tests failed:\n", len(failed), len(testCases))
for _, test := range failed {
fmt.Printf("\t%s\n", strings.Join([]string(test), " "))
}
diff --git a/util/all_tests.json b/util/all_tests.json
index bacee7af..48b540e0 100644
--- a/util/all_tests.json
+++ b/util/all_tests.json
@@ -5,6 +5,7 @@
["crypto/bio/bio_test"],
["crypto/bn/bn_test"],
["crypto/bytestring/bytestring_test"],
+ ["crypto/chacha/chacha_test"],
["crypto/cipher/aead_test", "aes-128-gcm", "crypto/cipher/test/aes_128_gcm_tests.txt"],
["crypto/cipher/aead_test", "aes-128-key-wrap", "crypto/cipher/test/aes_128_key_wrap_tests.txt"],
["crypto/cipher/aead_test", "aes-256-gcm", "crypto/cipher/test/aes_256_gcm_tests.txt"],
@@ -29,11 +30,12 @@
["crypto/cipher/aead_test", "des-ede3-cbc-sha1-ssl3", "crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt"],
["crypto/cipher/aead_test", "aes-128-ctr-hmac-sha256", "crypto/cipher/test/aes_128_ctr_hmac_sha256.txt"],
["crypto/cipher/aead_test", "aes-256-ctr-hmac-sha256", "crypto/cipher/test/aes_256_ctr_hmac_sha256.txt"],
- ["crypto/cipher/cipher_test", "crypto/cipher/test/cipher_test.txt"],
+ ["crypto/cipher/cipher_test", "crypto/cipher/test/cipher_tests.txt"],
["crypto/cmac/cmac_test"],
["crypto/constant_time_test"],
["crypto/curve25519/ed25519_test", "crypto/curve25519/ed25519_tests.txt"],
["crypto/curve25519/x25519_test"],
+ ["crypto/curve25519/spake25519_test"],
["crypto/dh/dh_test"],
["crypto/digest/digest_test"],
["crypto/dsa/dsa_test"],
@@ -48,9 +50,13 @@
["crypto/hmac/hmac_test", "crypto/hmac/hmac_tests.txt"],
["crypto/lhash/lhash_test"],
["crypto/modes/gcm_test"],
- ["crypto/pkcs8/pkcs8_test"],
+ ["crypto/newhope/newhope_test"],
+ ["crypto/newhope/newhope_statistical_test"],
+ ["crypto/newhope/newhope_vectors_test", "crypto/newhope/newhope_tests.txt"],
+ ["crypto/obj/obj_test"],
["crypto/pkcs8/pkcs12_test"],
- ["crypto/poly1305/poly1305_test", "crypto/poly1305/poly1305_test.txt"],
+ ["crypto/pkcs8/pkcs8_test"],
+ ["crypto/poly1305/poly1305_test", "crypto/poly1305/poly1305_tests.txt"],
["crypto/refcount_test"],
["crypto/rsa/rsa_test"],
["crypto/thread_test"],
@@ -58,6 +64,7 @@
["crypto/x509/x509_test"],
["crypto/x509v3/tab_test"],
["crypto/x509v3/v3name_test"],
+ ["decrepit/ripemd/ripemd_test"],
["ssl/pqueue/pqueue_test"],
["ssl/ssl_test"]
]
diff --git a/util/bot/DEPS b/util/bot/DEPS
index 738fbd3d..2a1e01a8 100644
--- a/util/bot/DEPS
+++ b/util/bot/DEPS
@@ -18,7 +18,14 @@ vars = {
deps = {
'boringssl/util/bot/gyp':
- Var('chromium_git') + '/external/gyp.git' + '@' + '4a9b712d5cb4a5ba7a9950128a7219569caf7263',
+ Var('chromium_git') + '/external/gyp.git' + '@' + '4cf07e8d616739f6484e46c9359b2a35196b2585',
+}
+
+deps_os = {
+ 'android': {
+ 'boringssl/util/bot/android_tools':
+ Var('chromium_git') + '/android_tools.git' + '@' + '5b5f2f60b78198eaef25d442ac60f823142a8a6e',
+ },
}
hooks = [
diff --git a/util/bot/UPDATING b/util/bot/UPDATING
new file mode 100644
index 00000000..2007d46f
--- /dev/null
+++ b/util/bot/UPDATING
@@ -0,0 +1,47 @@
+This directory consumes tools from other repositories for use on the
+bots. To update to newer revisions, follow these instructions:
+
+DEPS: Set all revisions to those used in Chromium, found at
+ https://chromium.googlesource.com/chromium/src/+/master/DEPS (Search for the
+ corresponding repository name.)
+
+go/bootstrap.py: Set TOOLSET_VERSION to the latest release of Go, found at
+ https://golang.org/dl/.
+
+update_clang.py: Set CLANG_REVISION and CLANG_SUB_REVISION to the values used in
+ Chromium, found at
+ https://chromium.googlesource.com/chromium/src/+/master/tools/clang/scripts/update.py
+
+vs_toolchain.py: Set the hash in TOOLCHAIN_HASH to the toolchain
+ used in Chromium, found at _GetDesiredVsToolchainHashes
+ https://chromium.googlesource.com/chromium/src/+/master/build/vs_toolchain.py
+ This may require taking other updates to that file. If updating MSVS
+ version, also update TOOLCHAIN_VERSION accordingly.
+
+The .sha1 files correspond to files downloaded from Google Cloud Storage. To
+update, place the updated files in their intended location and run:
+
+ upload_to_google_storage.py -b chromium-tools FILE
+
+cmake-linux64.tar.gz: Download the latest CMake source tarball, found at
+ https://cmake.org/download/. Build it with:
+
+ ./bootstrap --prefix=$PWD/cmake-linux64 && make && make install
+ tar -czf cmake-linux64.tar.gz cmake-linux64/
+
+cmake-mac.tar.gz: Follow the same instructions as above on a Mac, but replace
+ cmake-linux64 with cmake-mac.
+
+cmake-win32.zip: Update to the latest prebuilt release of CMake, found at
+ https://cmake.org/download/. Use the file labeled "Windows ZIP". The
+ download will be named cmake-VERSION-win32-x86.zip.
+
+perl-win32.zip: Update to the latest 32-bit prebuilt "PortableZip" edition of
+ Strawberry Perl, found at http://strawberryperl.com/releases.html. The
+ download will be named strawberry-perl-VERSION-32bit-portable.zip.
+
+yasm-win32.exe: Update to the appropriate release of Yasm. Use the same version
+ as Chromium, found at
+ https://chromium.googlesource.com/chromium/src/+/master/third_party/yasm/README.chromium
+ Use the release at http://yasm.tortall.net/Download.html labeled
+ "Win32 .exe". The download will be named yasm-VERSION-win32.exe.
diff --git a/util/bot/cmake-linux64.tar.gz.sha1 b/util/bot/cmake-linux64.tar.gz.sha1
index 6a8aa1c9..404570f6 100644
--- a/util/bot/cmake-linux64.tar.gz.sha1
+++ b/util/bot/cmake-linux64.tar.gz.sha1
@@ -1 +1 @@
-32cd1d5fe84ae569dbb36f5767650d62efb8be38 \ No newline at end of file
+6ea4ad07a4bab113ea74c45fafb14b8d0b0feab5 \ No newline at end of file
diff --git a/util/bot/cmake-mac.tar.gz.sha1 b/util/bot/cmake-mac.tar.gz.sha1
index cb7251ba..19c9b61f 100644
--- a/util/bot/cmake-mac.tar.gz.sha1
+++ b/util/bot/cmake-mac.tar.gz.sha1
@@ -1 +1 @@
-310df6945ae7f8c9da559d22f5794ee8e578a663 \ No newline at end of file
+f3166dab96234c9516ece56dc2851bf4c8e70fe8 \ No newline at end of file
diff --git a/util/bot/cmake-win32.zip.sha1 b/util/bot/cmake-win32.zip.sha1
index 9196b58c..6bb460eb 100644
--- a/util/bot/cmake-win32.zip.sha1
+++ b/util/bot/cmake-win32.zip.sha1
@@ -1 +1 @@
-e9493171de0edd8879755aa7229a701010a19561 \ No newline at end of file
+ed4e1939d246374b0bae724a1a4200fd60e7efe8 \ No newline at end of file
diff --git a/util/bot/go/bootstrap.py b/util/bot/go/bootstrap.py
index 4a52d9eb..8d08cc32 100755
--- a/util/bot/go/bootstrap.py
+++ b/util/bot/go/bootstrap.py
@@ -45,7 +45,7 @@ WORKSPACE = os.path.join(ROOT, 'go')
EXE_SFX = '.exe' if sys.platform == 'win32' else ''
# Pinned version of Go toolset to download.
-TOOLSET_VERSION = 'go1.5.1'
+TOOLSET_VERSION = 'go1.6.2'
# Platform dependent portion of a download URL. See http://golang.org/dl/.
TOOLSET_VARIANTS = {
diff --git a/util/bot/perl-win32.zip.sha1 b/util/bot/perl-win32.zip.sha1
index a5559d8a..8874fbbb 100644
--- a/util/bot/perl-win32.zip.sha1
+++ b/util/bot/perl-win32.zip.sha1
@@ -1 +1 @@
-ab6e7aee6a915c4d820b86f5227094763b649fce \ No newline at end of file
+3db2b4964d56f6e23cc48ced40a6cee05419a0af \ No newline at end of file
diff --git a/util/bot/update_clang.py b/util/bot/update_clang.py
index 18243934..e48a2871 100644
--- a/util/bot/update_clang.py
+++ b/util/bot/update_clang.py
@@ -22,7 +22,7 @@ import urllib
# CLANG_REVISION and CLANG_SUB_REVISION determine the build of clang
# to use. These should be synced with tools/clang/scripts/update.py in
# Chromium.
-CLANG_REVISION = "233105"
+CLANG_REVISION = "267383"
CLANG_SUB_REVISION = "1"
PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/util/bot/vs_toolchain.py b/util/bot/vs_toolchain.py
index 2a54b9e5..f90bb466 100644
--- a/util/bot/vs_toolchain.py
+++ b/util/bot/vs_toolchain.py
@@ -18,12 +18,16 @@ json_data_file = os.path.join(script_dir, 'win_toolchain.json')
import gyp
+TOOLCHAIN_VERSION = '2015'
+TOOLCHAIN_HASH = '95ddda401ec5678f15eeed01d2bee08fcbc5ee97'
+
+
def SetEnvironmentAndGetRuntimeDllDirs():
"""Sets up os.environ to use the depot_tools VS toolchain with gyp, and
returns the location of the VS runtime DLLs so they can be copied into
the output directory after gyp generation.
"""
- vs2013_runtime_dll_dirs = None
+ vs_runtime_dll_dirs = None
depot_tools_win_toolchain = \
bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
@@ -41,7 +45,7 @@ def SetEnvironmentAndGetRuntimeDllDirs():
# TODO(scottmg): The order unfortunately matters in these. They should be
# split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
# below). http://crbug.com/345992
- vs2013_runtime_dll_dirs = toolchain_data['runtime_dirs']
+ vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
os.environ['GYP_MSVS_VERSION'] = version
@@ -56,16 +60,9 @@ def SetEnvironmentAndGetRuntimeDllDirs():
os.environ['WINDOWSSDKDIR'] = win_sdk
os.environ['WDK_DIR'] = wdk
# Include the VS runtime in the PATH in case it's not machine-installed.
- runtime_path = ';'.join(vs2013_runtime_dll_dirs)
+ runtime_path = ';'.join(vs_runtime_dll_dirs)
os.environ['PATH'] = runtime_path + ';' + os.environ['PATH']
- return vs2013_runtime_dll_dirs
-
-
-def _GetDesiredVsToolchainHashes():
- """Load a list of SHA1s corresponding to the toolchains that we want installed
- to build with."""
- # Use Chromium's VS2013.
- return ['ee7d718ec60c2dc5d255bbe325909c2021a7efef']
+ return vs_runtime_dll_dirs
def FindDepotTools():
@@ -85,13 +82,16 @@ def Update():
bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
depot_tools_path = FindDepotTools()
+ # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
+ # in the correct directory.
+ os.environ['GYP_MSVS_VERSION'] = TOOLCHAIN_VERSION
get_toolchain_args = [
sys.executable,
os.path.join(depot_tools_path,
'win_toolchain',
'get_toolchain_if_necessary.py'),
- '--output-json', json_data_file,
- ] + _GetDesiredVsToolchainHashes()
+ '--output-json', json_data_file, TOOLCHAIN_HASH,
+ ]
subprocess.check_call(get_toolchain_args)
return 0
diff --git a/util/doc.config b/util/doc.config
index cbee5438..e7cfa82d 100644
--- a/util/doc.config
+++ b/util/doc.config
@@ -33,8 +33,10 @@
"include/openssl/ecdh.h",
"include/openssl/ecdsa.h",
"include/openssl/engine.h",
+ "include/openssl/hkdf.h",
"include/openssl/hmac.h",
"include/openssl/md5.h",
+ "include/openssl/newhope.h",
"include/openssl/rc4.h",
"include/openssl/rsa.h",
"include/openssl/sha.h"
diff --git a/util/doc.css b/util/doc.css
index ab653e4e..a868e444 100644
--- a/util/doc.css
+++ b/util/doc.css
@@ -7,12 +7,15 @@
h2 {
font-family: monospace;
- margin-bottom: 2em;
background-color: #b2c9db;
padding: 7px;
border-radius: 7px;
}
+div.title {
+ margin-bottom: 2em;
+}
+
ol {
list-style: none;
margin-bottom: 4em;
diff --git a/util/doc.go b/util/doc.go
index ace7a580..681b8349 100644
--- a/util/doc.go
+++ b/util/doc.go
@@ -274,13 +274,12 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) {
return nil, err
}
- lineNo := 0
+ lineNo := 1
found := false
for i, line := range lines {
- lineNo++
if line == cppGuard {
lines = lines[i+1:]
- lineNo++
+ lineNo += i + 1
found = true
break
}
@@ -302,9 +301,9 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) {
}
for i, line := range lines {
- lineNo++
if len(line) > 0 {
lines = lines[i:]
+ lineNo += i
break
}
}
@@ -390,6 +389,7 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) {
if len(lines) == 0 {
return nil, errors.New("expected decl at EOF")
}
+ declLineNo := lineNo
decl, lines, lineNo, err = extractDecl(lines, lineNo)
if err != nil {
return nil, err
@@ -409,10 +409,12 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) {
// detected by starting with “The” or “These”.
if len(comment) > 0 &&
!strings.HasPrefix(comment[0], name) &&
+ !strings.HasPrefix(comment[0], "A "+name) &&
+ !strings.HasPrefix(comment[0], "An "+name) &&
!strings.HasPrefix(decl, "#define ") &&
!strings.HasPrefix(comment[0], "The ") &&
!strings.HasPrefix(comment[0], "These ") {
- return nil, fmt.Errorf("Comment for %q doesn't seem to match just above %s:%d\n", name, path, lineNo)
+ return nil, fmt.Errorf("Comment for %q doesn't seem to match line %s:%d\n", name, path, declLineNo)
}
anchor := sanitizeAnchor(name)
// TODO(davidben): Enforce uniqueness. This is
@@ -542,7 +544,10 @@ func generate(outPath string, config *Config) (map[string]string, error) {
<body>
<div id="main">
- <h2>{{.Name}}</h2>
+ <div class="title">
+ <h2>{{.Name}}</h2>
+ <a href="headers.html">All headers</a>
+ </div>
{{range .Preamble}}<p>{{. | html | markupPipeWords}}</p>{{end}}
@@ -635,6 +640,9 @@ func generateIndex(outPath string, config *Config, headerDescriptions map[string
<body>
<div id="main">
+ <div class="title">
+ <h2>BoringSSL Headers</h2>
+ </div>
<table>
{{range .Sections}}
<tr class="header"><td colspan="2">{{.Name}}</td></tr>
diff --git a/util/generate-asm-lcov.py b/util/generate-asm-lcov.py
new file mode 100755
index 00000000..257ae841
--- /dev/null
+++ b/util/generate-asm-lcov.py
@@ -0,0 +1,152 @@
+#!/usr/bin/python
+# Copyright (c) 2016, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+import os
+import os.path
+import subprocess
+import sys
+
+# The LCOV output format for each source file is:
+#
+# SF:<filename>
+# DA:<line>,<execution count>
+# ...
+# end_of_record
+#
+# The <execution count> can either be 0 for an unexecuted instruction or a
+# value representing the number of executions. The DA line should be omitted
+# for lines not representing an instruction.
+
+SECTION_SEPERATOR = '-' * 80
+
+def is_asm(l):
+ """Returns whether a line should be considered to be an instruction."""
+ l = l.strip()
+ # Empty lines
+ if l == '':
+ return False
+ # Comments
+ if l.startswith('#'):
+ return False
+ # Assembly Macros
+ if l.startswith('.'):
+ return False
+ # Label
+ if l.endswith(':'):
+ return False
+ return True
+
+def merge(callgrind_files, srcs):
+ """Calls callgrind_annotate over the set of callgrind output
+ |callgrind_files| using the sources |srcs| and merges the results
+ together."""
+ out = ''
+ for file in callgrind_files:
+ data = subprocess.check_output(['callgrind_annotate', file] + srcs)
+ out += '%s\n%s\n' % (data, SECTION_SEPERATOR)
+ return out
+
+def parse(filename, data, current):
+ """Parses an annotated execution flow |data| from callgrind_annotate for
+ source |filename| and updates the current execution counts from |current|."""
+ with open(filename) as f:
+ source = f.read().split('\n')
+
+ out = current
+ if out == None:
+ out = [0 if is_asm(l) else None for l in source]
+
+ # Lines are of the following formats:
+ # -- line: Indicates that analysis continues from a different place.
+ # Ir : Indicates the start of a file.
+ # => : Indicates a call/jump in the control flow.
+ # <Count> <Code>: Indicates that the line has been executed that many times.
+ line = None
+ for l in data:
+ l = l.strip() + ' '
+ if l.startswith('-- line'):
+ line = int(l.split(' ')[2]) - 1
+ elif l.strip() == 'Ir':
+ line = 0
+ elif line != None and l.strip() and '=>' not in l and 'unidentified lines' not in l:
+ count = l.split(' ')[0].replace(',', '').replace('.', '0')
+ instruction = l.split(' ', 1)[1].strip()
+ if count != '0' or is_asm(instruction):
+ if out[line] == None:
+ out[line] = 0
+ out[line] += int(count)
+ line += 1
+
+ return out
+
+
+def generate(data):
+ """Parses the merged callgrind_annotate output |data| and generates execution
+ counts for all annotated files."""
+ out = {}
+ data = [p.strip() for p in data.split(SECTION_SEPERATOR)]
+
+
+ # Most sections are ignored, but a section with:
+ # User-annotated source: <file>
+ # precedes a listing of execution count for that <file>.
+ for i in range(len(data)):
+ if 'User-annotated source' in data[i] and i < len(data) - 1:
+ filename = data[i].split(':', 1)[1].strip()
+ res = data[i + 1]
+ if filename not in out:
+ out[filename] = None
+ if 'No information' in res:
+ res = []
+ else:
+ res = res.split('\n')
+ out[filename] = parse(filename, res, out[filename])
+ return out
+
+def output(data):
+ """Takes a dictionary |data| of filenames and execution counts and generates
+ a LCOV coverage output."""
+ out = ''
+ for filename, counts in data.iteritems():
+ out += 'SF:%s\n' % (os.path.abspath(filename))
+ for line, count in enumerate(counts):
+ if count != None:
+ out += 'DA:%d,%s\n' % (line + 1, count)
+ out += 'end_of_record\n'
+ return out
+
+if __name__ == '__main__':
+ if len(sys.argv) != 3:
+ print '%s <Callgrind Folder> <Build Folder>' % (__file__)
+ sys.exit()
+
+ cg_folder = sys.argv[1]
+ build_folder = sys.argv[2]
+
+ cg_files = []
+ for (cwd, _, files) in os.walk(cg_folder):
+ for f in files:
+ if f.startswith('callgrind.out'):
+ cg_files.append(os.path.abspath(os.path.join(cwd, f)))
+
+ srcs = []
+ for (cwd, _, files) in os.walk(build_folder):
+ for f in files:
+ fn = os.path.join(cwd, f)
+ if fn.endswith('.S'):
+ srcs.append(fn)
+
+ annotated = merge(cg_files, srcs)
+ lcov = generate(annotated)
+ print output(lcov)
diff --git a/util/generate-coverage.sh b/util/generate-coverage.sh
new file mode 100755
index 00000000..2fbe6b83
--- /dev/null
+++ b/util/generate-coverage.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+# Copyright (c) 2016, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+set -xe
+
+SRC=$PWD
+
+BUILD=$(mktemp -d '/tmp/boringssl.XXXXXX')
+BUILD_SRC=$(mktemp -d '/tmp/boringssl-src.XXXXXX')
+LCOV=$(mktemp -d '/tmp/boringssl-lcov.XXXXXX')
+
+if [ -n "$1" ]; then
+ LCOV=$(readlink -f "$1")
+ mkdir -p "$LCOV"
+fi
+
+cd "$BUILD"
+cmake "$SRC" -GNinja -DCMAKE_C_FLAGS='-fprofile-arcs -ftest-coverage' \
+ -DCMAKE_CXX_FLAGS='-fprofile-arcs -ftest-coverage' -DCMAKE_ASM_FLAGS='-Wa,-g'
+ninja
+
+cp -r "$SRC/crypto" "$SRC/decrepit" "$SRC/include" "$SRC/ssl" "$SRC/tool" \
+ "$BUILD_SRC"
+cp -r "$BUILD"/* "$BUILD_SRC"
+mkdir "$BUILD/callgrind/"
+
+cd "$SRC"
+go run "$SRC/util/all_tests.go" -build-dir "$BUILD" -callgrind -num-workers 16
+util/generate-asm-lcov.py "$BUILD/callgrind" "$BUILD" > "$BUILD/asm.info"
+
+go run "util/all_tests.go" -build-dir "$BUILD"
+
+cd "$SRC/ssl/test/runner"
+go test -shim-path "$BUILD/ssl/test/bssl_shim" -num-workers 1
+
+cd "$LCOV"
+lcov -c -d "$BUILD" -b "$BUILD" -o "$BUILD/lcov.info"
+lcov -r "$BUILD/lcov.info" "*_test.c" -o "$BUILD/lcov-1.info"
+lcov -r "$BUILD/lcov-1.info" "*_test.cc" -o "$BUILD/lcov-2.info"
+cat "$BUILD/lcov-2.info" "$BUILD/asm.info" > "$BUILD/final.info"
+sed -i "s;$BUILD;$BUILD_SRC;g" "$BUILD/final.info"
+sed -i "s;$SRC;$BUILD_SRC;g" "$BUILD/final.info"
+genhtml -p "$BUILD_SRC" "$BUILD/final.info"
+
+rm -rf "$BUILD"
+rm -rf "$BUILD_SRC"
+
+xdg-open index.html
diff --git a/util/generate_build_files.py b/util/generate_build_files.py
index acc693af..b3db1480 100644
--- a/util/generate_build_files.py
+++ b/util/generate_build_files.py
@@ -12,10 +12,9 @@
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-"""Enumerates the BoringSSL source in src/ and either generates two gypi files
- (boringssl.gypi and boringssl_tests.gypi) for Chromium, or generates
- source-list files for Android."""
+"""Enumerates source files for consumption by various build systems."""
+import optparse
import os
import subprocess
import sys
@@ -39,85 +38,22 @@ OS_ARCH_COMBOS = [
# perlasm system.
NON_PERL_FILES = {
('linux', 'arm'): [
- 'src/crypto/chacha/chacha_vec_arm.S',
- 'src/crypto/cpu-arm-asm.S',
'src/crypto/curve25519/asm/x25519-asm-arm.S',
'src/crypto/poly1305/poly1305_arm_asm.S',
],
('linux', 'x86_64'): [
'src/crypto/curve25519/asm/x25519-asm-x86_64.S',
],
+ ('mac', 'x86_64'): [
+ 'src/crypto/curve25519/asm/x25519-asm-x86_64.S',
+ ],
}
+PREFIX = None
-class Chromium(object):
-
- def __init__(self):
- self.header = \
-"""# Copyright (c) 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file is created by generate_build_files.py. Do not edit manually.
-
-"""
-
- def PrintVariableSection(self, out, name, files):
- out.write(' \'%s\': [\n' % name)
- for f in sorted(files):
- out.write(' \'%s\',\n' % f)
- out.write(' ],\n')
-
- def WriteFiles(self, files, asm_outputs):
- with open('boringssl.gypi', 'w+') as gypi:
- gypi.write(self.header + '{\n \'variables\': {\n')
-
- self.PrintVariableSection(
- gypi, 'boringssl_ssl_sources', files['ssl'])
- self.PrintVariableSection(
- gypi, 'boringssl_crypto_sources', files['crypto'])
-
- for ((osname, arch), asm_files) in asm_outputs:
- self.PrintVariableSection(gypi, 'boringssl_%s_%s_sources' %
- (osname, arch), asm_files)
-
- gypi.write(' }\n}\n')
-
- with open('boringssl_tests.gypi', 'w+') as test_gypi:
- test_gypi.write(self.header + '{\n \'targets\': [\n')
-
- test_names = []
- for test in sorted(files['test']):
- test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0]
- test_gypi.write(""" {
- 'target_name': '%s',
- 'type': 'executable',
- 'dependencies': [
- 'boringssl.gyp:boringssl',
- ],
- 'sources': [
- '%s',
- '<@(boringssl_test_support_sources)',
- ],
- # TODO(davidben): Fix size_t truncations in BoringSSL.
- # https://crbug.com/429039
- 'msvs_disabled_warnings': [ 4267, ],
- },\n""" % (test_name, test))
- test_names.append(test_name)
-
- test_names.sort()
-
- test_gypi.write(' ],\n \'variables\': {\n')
-
- self.PrintVariableSection(
- test_gypi, 'boringssl_test_support_sources', files['test_support'])
- test_gypi.write(' \'boringssl_test_targets\': [\n')
-
- for test in test_names:
- test_gypi.write(""" '%s',\n""" % test)
-
- test_gypi.write(' ],\n }\n}\n')
+def PathOf(x):
+ return x if not PREFIX else os.path.join(PREFIX, x)
class Android(object):
@@ -190,7 +126,7 @@ class Bazel(object):
out.write('%s = [\n' % name)
for f in sorted(files):
- out.write(' "%s",\n' % f)
+ out.write(' "%s",\n' % PathOf(f))
out.write(']\n')
def WriteFiles(self, files, asm_outputs):
@@ -215,16 +151,16 @@ class Bazel(object):
out.write(self.header)
out.write('test_support_sources = [\n')
- for filename in files['test_support']:
+ for filename in (files['test_support'] +
+ files['crypto_internal_headers'] +
+ files['ssl_internal_headers']):
if os.path.basename(filename) == 'malloc.cc':
continue
- out.write(' "%s",\n' % filename)
+ out.write(' "%s",\n' % PathOf(filename))
out.write(']\n\n')
- out.write('def create_tests(copts):\n')
- out.write(' test_support_sources_complete = test_support_sources + \\\n')
- out.write(' native.glob(["src/crypto/test/*.h"])\n')
+ out.write('def create_tests(copts, crypto, ssl):\n')
name_counts = {}
for test in files['tests']:
name = os.path.basename(test[0])
@@ -254,7 +190,8 @@ class Bazel(object):
out.write(' native.cc_test(\n')
out.write(' name = "%s",\n' % name)
out.write(' size = "small",\n')
- out.write(' srcs = ["%s"] + test_support_sources_complete,\n' % src)
+ out.write(' srcs = ["%s"] + test_support_sources,\n' %
+ PathOf(src))
data_files = []
if len(test) > 1:
@@ -262,7 +199,8 @@ class Bazel(object):
out.write(' args = [\n')
for arg in test[1:]:
if '/' in arg:
- out.write(' "$(location src/%s)",\n' % arg)
+ out.write(' "$(location %s)",\n' %
+ PathOf(os.path.join('src', arg)))
data_files.append('src/%s' % arg)
else:
out.write(' "%s",\n' % arg)
@@ -273,19 +211,164 @@ class Bazel(object):
if len(data_files) > 0:
out.write(' data = [\n')
for filename in data_files:
- out.write(' "%s",\n' % filename)
+ out.write(' "%s",\n' % PathOf(filename))
out.write(' ],\n')
if 'ssl/' in test[0]:
out.write(' deps = [\n')
- out.write(' ":crypto",\n')
- out.write(' ":ssl",\n')
+ out.write(' crypto,\n')
+ out.write(' ssl,\n')
out.write(' ],\n')
else:
- out.write(' deps = [":crypto"],\n')
+ out.write(' deps = [crypto],\n')
out.write(' )\n')
+class GN(object):
+
+ def __init__(self):
+ self.firstSection = True
+ self.header = \
+"""# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is created by generate_build_files.py. Do not edit manually.
+
+"""
+
+ def PrintVariableSection(self, out, name, files):
+ if not self.firstSection:
+ out.write('\n')
+ self.firstSection = False
+
+ out.write('%s = [\n' % name)
+ for f in sorted(files):
+ out.write(' "%s",\n' % f)
+ out.write(']\n')
+
+ def WriteFiles(self, files, asm_outputs):
+ with open('BUILD.generated.gni', 'w+') as out:
+ out.write(self.header)
+
+ self.PrintVariableSection(out, 'crypto_sources', files['crypto'])
+ self.PrintVariableSection(out, 'ssl_sources', files['ssl'])
+
+ for ((osname, arch), asm_files) in asm_outputs:
+ self.PrintVariableSection(
+ out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
+
+ fuzzers = [os.path.splitext(os.path.basename(fuzzer))[0]
+ for fuzzer in files['fuzz']]
+ self.PrintVariableSection(out, 'fuzzers', fuzzers)
+
+ with open('BUILD.generated_tests.gni', 'w+') as out:
+ self.firstSection = True
+ out.write(self.header)
+
+ self.PrintVariableSection(out, '_test_support_sources',
+ files['test_support'])
+ out.write('\n')
+
+ out.write('template("create_tests") {\n')
+
+ all_tests = []
+ for test in sorted(files['test']):
+ test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0]
+ all_tests.append(test_name)
+
+ out.write(' executable("%s") {\n' % test_name)
+ out.write(' sources = [\n')
+ out.write(' "%s",\n' % test)
+ out.write(' ]\n')
+ out.write(' sources += _test_support_sources\n')
+ out.write(' if (defined(invoker.configs_exclude)) {\n')
+ out.write(' configs -= invoker.configs_exclude\n')
+ out.write(' }\n')
+ out.write(' configs += invoker.configs\n')
+ out.write(' deps = invoker.deps\n')
+ out.write(' }\n')
+ out.write('\n')
+
+ out.write(' group(target_name) {\n')
+ out.write(' deps = [\n')
+ for test_name in sorted(all_tests):
+ out.write(' ":%s",\n' % test_name)
+ out.write(' ]\n')
+ out.write(' }\n')
+ out.write('}\n')
+
+
+class GYP(object):
+
+ def __init__(self):
+ self.header = \
+"""# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is created by generate_build_files.py. Do not edit manually.
+
+"""
+
+ def PrintVariableSection(self, out, name, files):
+ out.write(' \'%s\': [\n' % name)
+ for f in sorted(files):
+ out.write(' \'%s\',\n' % f)
+ out.write(' ],\n')
+
+ def WriteFiles(self, files, asm_outputs):
+ with open('boringssl.gypi', 'w+') as gypi:
+ gypi.write(self.header + '{\n \'variables\': {\n')
+
+ self.PrintVariableSection(
+ gypi, 'boringssl_ssl_sources', files['ssl'])
+ self.PrintVariableSection(
+ gypi, 'boringssl_crypto_sources', files['crypto'])
+
+ for ((osname, arch), asm_files) in asm_outputs:
+ self.PrintVariableSection(gypi, 'boringssl_%s_%s_sources' %
+ (osname, arch), asm_files)
+
+ gypi.write(' }\n}\n')
+
+ with open('boringssl_tests.gypi', 'w+') as test_gypi:
+ test_gypi.write(self.header + '{\n \'targets\': [\n')
+
+ test_names = []
+ for test in sorted(files['test']):
+ test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0]
+ test_gypi.write(""" {
+ 'target_name': '%s',
+ 'type': 'executable',
+ 'dependencies': [
+ 'boringssl.gyp:boringssl',
+ ],
+ 'sources': [
+ '%s',
+ '<@(boringssl_test_support_sources)',
+ ],
+ # TODO(davidben): Fix size_t truncations in BoringSSL.
+ # https://crbug.com/429039
+ 'msvs_disabled_warnings': [ 4267, ],
+ },\n""" % (test_name, test))
+ test_names.append(test_name)
+
+ test_names.sort()
+
+ test_gypi.write(' ],\n \'variables\': {\n')
+
+ self.PrintVariableSection(
+ test_gypi, 'boringssl_test_support_sources', files['test_support'])
+
+ test_gypi.write(' \'boringssl_test_targets\': [\n')
+
+ for test in sorted(test_names):
+ test_gypi.write(""" '%s',\n""" % test)
+
+ test_gypi.write(' ],\n }\n}\n')
+
+
def FindCMakeFiles(directory):
"""Returns list of all CMakeLists.txt files recursively in directory."""
cmakefiles = []
@@ -356,6 +439,10 @@ def FindHeaderFiles(directory, filter_func):
continue
hfiles.append(os.path.join(path, filename))
+ for (i, dirname) in enumerate(dirnames):
+ if not filter_func(dirname, True):
+ del dirnames[i]
+
return hfiles
@@ -459,7 +546,7 @@ def WriteAsmFiles(perlasms):
def main(platforms):
crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTests)
ssl_c_files = FindCFiles(os.path.join('src', 'ssl'), NoTests)
- tool_cc_files = FindCFiles(os.path.join('src', 'tool'), NoTests)
+ tool_c_files = FindCFiles(os.path.join('src', 'tool'), NoTests)
# Generate err_data.c
with open('err_data.c', 'w+') as err_data:
@@ -468,12 +555,17 @@ def main(platforms):
stdout=err_data)
crypto_c_files.append('err_data.c')
- test_support_cc_files = FindCFiles(os.path.join('src', 'crypto', 'test'),
- AllFiles)
+ test_support_c_files = FindCFiles(os.path.join('src', 'crypto', 'test'),
+ AllFiles)
+ test_support_h_files = (
+ FindHeaderFiles(os.path.join('src', 'crypto', 'test'), AllFiles) +
+ FindHeaderFiles(os.path.join('src', 'ssl', 'test'), AllFiles))
test_c_files = FindCFiles(os.path.join('src', 'crypto'), OnlyTests)
test_c_files += FindCFiles(os.path.join('src', 'ssl'), OnlyTests)
+ fuzz_c_files = FindCFiles(os.path.join('src', 'fuzz'), NoTests)
+
ssl_h_files = (
FindHeaderFiles(
os.path.join('src', 'include', 'openssl'),
@@ -492,6 +584,8 @@ def main(platforms):
with open('src/util/all_tests.json', 'r') as f:
tests = json.load(f)
+ # Skip tests for libdecrepit. Consumers import that manually.
+ tests = [test for test in tests if not test[0].startswith("decrepit/")]
test_binaries = set([test[0] for test in tests])
test_sources = set([
test.replace('.cc', '').replace('.c', '').replace(
@@ -511,12 +605,13 @@ def main(platforms):
'crypto': crypto_c_files,
'crypto_headers': crypto_h_files,
'crypto_internal_headers': crypto_internal_h_files,
+ 'fuzz': fuzz_c_files,
'ssl': ssl_c_files,
'ssl_headers': ssl_h_files,
'ssl_internal_headers': ssl_internal_h_files,
- 'tool': tool_cc_files,
+ 'tool': tool_c_files,
'test': test_c_files,
- 'test_support': test_support_cc_files,
+ 'test_support': test_support_h_files + test_support_c_files,
'tests': tests,
}
@@ -528,26 +623,32 @@ def main(platforms):
return 0
-def Usage():
- print 'Usage: python %s [chromium|android|android-standalone|bazel]' % sys.argv[0]
- sys.exit(1)
-
-
if __name__ == '__main__':
- if len(sys.argv) < 2:
- Usage()
+ parser = optparse.OptionParser(usage='Usage: %prog [--prefix=<path>]'
+ ' [android|android-standalone|bazel|gn|gyp]')
+ parser.add_option('--prefix', dest='prefix',
+ help='For Bazel, prepend argument to all source files')
+ options, args = parser.parse_args(sys.argv[1:])
+ PREFIX = options.prefix
+
+ if not args:
+ parser.print_help()
+ sys.exit(1)
platforms = []
- for s in sys.argv[1:]:
- if s == 'chromium' or s == 'gyp':
- platforms.append(Chromium())
- elif s == 'android':
+ for s in args:
+ if s == 'android':
platforms.append(Android())
elif s == 'android-standalone':
platforms.append(AndroidStandalone())
elif s == 'bazel':
platforms.append(Bazel())
+ elif s == 'gn':
+ platforms.append(GN())
+ elif s == 'gyp':
+ platforms.append(GYP())
else:
- Usage()
+ parser.print_help()
+ sys.exit(1)
sys.exit(main(platforms))
diff --git a/util/run_android_tests.go b/util/run_android_tests.go
new file mode 100644
index 00000000..6502a166
--- /dev/null
+++ b/util/run_android_tests.go
@@ -0,0 +1,315 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+ "strings"
+)
+
+var (
+ buildDir = flag.String("build-dir", "build", "Specifies the build directory to push.")
+ adbPath = flag.String("adb", "adb", "Specifies the adb binary to use. Defaults to looking in PATH.")
+ device = flag.String("device", "", "Specifies the device or emulator. See adb's -s argument.")
+ aarch64 = flag.Bool("aarch64", false, "Build the test runners for aarch64 instead of arm.")
+ arm = flag.Int("arm", 7, "Which arm revision to build for.")
+ suite = flag.String("suite", "all", "Specifies the test suites to run (all, unit, or ssl).")
+ allTestsArgs = flag.String("all-tests-args", "", "Specifies space-separated arguments to pass to all_tests.go")
+ runnerArgs = flag.String("runner-args", "", "Specifies space-separated arguments to pass to ssl/test/runner")
+ jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
+)
+
+func enableUnitTests() bool {
+ return *suite == "all" || *suite == "unit"
+}
+
+func enableSSLTests() bool {
+ return *suite == "all" || *suite == "ssl"
+}
+
+func adb(args ...string) error {
+ if len(*device) > 0 {
+ args = append([]string{"-s", *device}, args...)
+ }
+ cmd := exec.Command(*adbPath, args...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+}
+
+func adbShell(shellCmd string) (int, error) {
+ var args []string
+ if len(*device) > 0 {
+ args = append([]string{"-s", *device}, args...)
+ }
+ args = append(args, "shell")
+
+ const delimiter = "___EXIT_CODE___"
+
+ // Older versions of adb and Android do not preserve the exit
+ // code, so work around this.
+ // https://code.google.com/p/android/issues/detail?id=3254
+ shellCmd += "; echo " + delimiter + " $?"
+ args = append(args, shellCmd)
+
+ cmd := exec.Command(*adbPath, args...)
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ return 0, err
+ }
+ cmd.Stderr = os.Stderr
+ if err := cmd.Start(); err != nil {
+ return 0, err
+ }
+
+ var stdoutBytes bytes.Buffer
+ for {
+ var buf [1024]byte
+ n, err := stdout.Read(buf[:])
+ stdoutBytes.Write(buf[:n])
+ os.Stdout.Write(buf[:n])
+ if err != nil {
+ break
+ }
+ }
+
+ if err := cmd.Wait(); err != nil {
+ return 0, err
+ }
+
+ stdoutStr := stdoutBytes.String()
+ idx := strings.LastIndex(stdoutStr, delimiter)
+ if idx < 0 {
+ return 0, fmt.Errorf("Could not find delimiter in output.")
+ }
+
+ return strconv.Atoi(strings.TrimSpace(stdoutStr[idx+len(delimiter):]))
+}
+
+func goTool(args ...string) error {
+ cmd := exec.Command("go", args...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+
+ cmd.Env = os.Environ()
+ if *aarch64 {
+ cmd.Env = append(cmd.Env, "GOARCH=arm64")
+ } else {
+ cmd.Env = append(cmd.Env, "GOARCH=arm")
+ cmd.Env = append(cmd.Env, fmt.Sprintf("GOARM=%d", *arm))
+ }
+ return cmd.Run()
+}
+
+// setWorkingDirectory walks up directories as needed until the current working
+// directory is the top of a BoringSSL checkout.
+func setWorkingDirectory() {
+ for i := 0; i < 64; i++ {
+ if _, err := os.Stat("BUILDING.md"); err == nil {
+ return
+ }
+ os.Chdir("..")
+ }
+
+ panic("Couldn't find BUILDING.md in a parent directory!")
+}
+
+type test []string
+
+func parseTestConfig(filename string) ([]test, error) {
+ in, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer in.Close()
+
+ decoder := json.NewDecoder(in)
+ var result []test
+ if err := decoder.Decode(&result); err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func copyFile(dst, src string) error {
+ srcFile, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer srcFile.Close()
+
+ srcInfo, err := srcFile.Stat()
+ if err != nil {
+ return err
+ }
+
+ dir := filepath.Dir(dst)
+ if err := os.MkdirAll(dir, 0777); err != nil {
+ return err
+ }
+
+ dstFile, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, srcInfo.Mode())
+ if err != nil {
+ return err
+ }
+ defer dstFile.Close()
+
+ _, err = io.Copy(dstFile, srcFile)
+ return err
+}
+
+func main() {
+ flag.Parse()
+
+ if *suite == "all" && *jsonOutput != "" {
+ fmt.Printf("To use -json-output flag, select only one test suite with -suite.\n")
+ os.Exit(1)
+ }
+
+ setWorkingDirectory()
+
+ // Clear the target directory.
+ if err := adb("shell", "rm -Rf /data/local/tmp/boringssl-tmp"); err != nil {
+ fmt.Printf("Failed to clear target directory: %s\n", err)
+ os.Exit(1)
+ }
+
+ // Stage everything in a temporary directory.
+ tmpDir, err := ioutil.TempDir("", "boringssl-android")
+ if err != nil {
+ fmt.Printf("Error making temporary directory: %s\n", err)
+ os.Exit(1)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ var binaries, files []string
+
+ if enableUnitTests() {
+ files = append(files,
+ "util/all_tests.json",
+ "BUILDING.md",
+ )
+
+ tests, err := parseTestConfig("util/all_tests.json")
+ if err != nil {
+ fmt.Printf("Failed to parse input: %s\n", err)
+ os.Exit(1)
+ }
+
+ seenBinary := make(map[string]struct{})
+ for _, test := range tests {
+ if _, ok := seenBinary[test[0]]; !ok {
+ binaries = append(binaries, test[0])
+ seenBinary[test[0]] = struct{}{}
+ }
+ for _, arg := range test[1:] {
+ if strings.Contains(arg, "/") {
+ files = append(files, arg)
+ }
+ }
+ }
+
+ fmt.Printf("Building all_tests...\n")
+ if err := goTool("build", "-o", filepath.Join(tmpDir, "util/all_tests"), "util/all_tests.go"); err != nil {
+ fmt.Printf("Error building all_tests.go: %s\n", err)
+ os.Exit(1)
+ }
+ }
+
+ if enableSSLTests() {
+ binaries = append(binaries, "ssl/test/bssl_shim")
+ files = append(files,
+ "BUILDING.md",
+ "util/all_tests.json",
+ "ssl/test/runner/cert.pem",
+ "ssl/test/runner/channel_id_key.pem",
+ "ssl/test/runner/ecdsa_cert.pem",
+ "ssl/test/runner/ecdsa_key.pem",
+ "ssl/test/runner/key.pem",
+ )
+
+ fmt.Printf("Building runner...\n")
+ if err := goTool("test", "-c", "-o", filepath.Join(tmpDir, "ssl/test/runner/runner"), "./ssl/test/runner/"); err != nil {
+ fmt.Printf("Error building runner: %s\n", err)
+ os.Exit(1)
+ }
+ }
+
+ fmt.Printf("Copying test binaries...\n")
+ for _, binary := range binaries {
+ if err := copyFile(filepath.Join(tmpDir, "build", binary), filepath.Join(*buildDir, binary)); err != nil {
+ fmt.Printf("Failed to copy %s: %s\n", binary, err)
+ os.Exit(1)
+ }
+ }
+
+ fmt.Printf("Copying data files...\n")
+ for _, file := range files {
+ if err := copyFile(filepath.Join(tmpDir, file), file); err != nil {
+ fmt.Printf("Failed to copy %s: %s\n", file, err)
+ os.Exit(1)
+ }
+ }
+
+ fmt.Printf("Uploading files...\n")
+ if err := adb("push", "-p", tmpDir, "/data/local/tmp/boringssl-tmp"); err != nil {
+ fmt.Printf("Failed to push runner: %s\n", err)
+ os.Exit(1)
+ }
+
+ var unitTestExit int
+ if enableUnitTests() {
+ fmt.Printf("Running unit tests...\n")
+ unitTestExit, err = adbShell(fmt.Sprintf("cd /data/local/tmp/boringssl-tmp && ./util/all_tests -json-output results.json %s", *allTestsArgs))
+ if err != nil {
+ fmt.Printf("Failed to run unit tests: %s\n", err)
+ os.Exit(1)
+ }
+ }
+
+ var sslTestExit int
+ if enableSSLTests() {
+ fmt.Printf("Running SSL tests...\n")
+ sslTestExit, err = adbShell(fmt.Sprintf("cd /data/local/tmp/boringssl-tmp/ssl/test/runner && ./runner -json-output ../../../results.json %s", *runnerArgs))
+ if err != nil {
+ fmt.Printf("Failed to run SSL tests: %s\n", err)
+ os.Exit(1)
+ }
+ }
+
+ if *jsonOutput != "" {
+ if err := adb("pull", "-p", "/data/local/tmp/boringssl-tmp/results.json", *jsonOutput); err != nil {
+ fmt.Printf("Failed to extract results.json: %s\n", err)
+ os.Exit(1)
+ }
+ }
+
+ if unitTestExit != 0 {
+ os.Exit(unitTestExit)
+ }
+
+ if sslTestExit != 0 {
+ os.Exit(sslTestExit)
+ }
+}