Compare commits

...

318 Commits

Author SHA1 Message Date
Adam Langley 0cd846f24f delocation: large memory model support.
Large memory models on x86-64 allow the code/data of a shared object /
executable to be larger than 2GiB. This is typically impossible because
x86-64 code frequently uses int32 offsets from RIP.

Consider the following program:

    int getpid();

    int main() {
        return getpid();
    }

This is turned into the following assembly under a large memory model:

.L0$pb:
	leaq	.L0$pb(%rip), %rax
	movabsq	$_GLOBAL_OFFSET_TABLE_-.L0$pb, %rcx
	addq	%rax, %rcx
	movabsq	$getpid@GOT, %rdx
	xorl	%eax, %eax
	jmpq	*(%rcx,%rdx)            # TAILCALL

And, with relocations:

   0:	48 8d 05 f9 ff ff ff 	lea    -0x7(%rip),%rax        # 0 <main>
   7:	48 b9 00 00 00 00 00 	movabs $0x0,%rcx
   e:	00 00 00
			9: R_X86_64_GOTPC64	_GLOBAL_OFFSET_TABLE_+0x9
  11:	48 01 c1             	add    %rax,%rcx
  14:	48 ba 00 00 00 00 00 	movabs $0x0,%rdx
  1b:	00 00 00
			16: R_X86_64_GOT64	getpid
  1e:	31 c0                	xor    %eax,%eax
  20:	ff 24 11             	jmpq   *(%rcx,%rdx,1)

We can see that, in the large memory model, function calls involve
loading the address of _GLOBAL_OFFSET_TABLE_ (using `movabs`, which
takes a 64-bit immediate) and then indexing into it. Both cause
relocations.

If we link the binary and disassemble we get:

0000000000001120 <main>:
    1120:	48 8d 05 f9 ff ff ff 	lea    -0x7(%rip),%rax        # 1120 <main>
    1127:	48 b9 e0 2e 00 00 00 	movabs $0x2ee0,%rcx
    112e:	00 00 00
    1131:	48 01 c1             	add    %rax,%rcx
    1134:	48 ba d8 ff ff ff ff 	movabs $0xffffffffffffffd8,%rdx
    113b:	ff ff ff
    113e:	31 c0                	xor    %eax,%eax
    1140:	ff 24 11             	jmpq   *(%rcx,%rdx,1)

Thus the _GLOBAL_OFFSET_TABLE_ symbol is at 0x1120+0x2ee0 = 0x4000.
That's the address of the .got.plt section. But the offset “into” the
table is -0x40, putting it at 0x3fd8, in .got:

Idx Name          Size      VMA               LMA               File off  Algn
 18 .got          00000030  0000000000003fd0  0000000000003fd0  00002fd0  2**3
 19 .got.plt      00000018  0000000000004000  0000000000004000  00003000  2**3

And, indeed, there's a dynamic relocation to setup that address:

OFFSET           TYPE              VALUE
0000000000003fd8 R_X86_64_GLOB_DAT  getpid@GLIBC_2.2.5

Accessing data or BSS works the same: the address of the variable is
stored relative to _GLOBAL_OFFSET_TABLE_.

This is a bit of a pain because we want to delocate the module into a
single .text segment so that it moves through linking unaltered. If we
took the obvious path and built our own offset table then it would need
to contain absolute addresses, but they are only available at runtime
and .text segments aren't supposed to be run-time patched. (That's why
.rela.dyn is a separate segment.) If we use a different segment then
we have the same problem as with the original offset table: the offset
to the segment is unknown when compiling the module.

Trying to pattern match this two-step lookup to do extensive rewriting
seems fragile: I'm sure the compilers will move things around and
interleave other work in time, if they don't already.

So, in order to handle movabs trying to load _GLOBAL_OFFSET_TABLE_ we
define a symbol in the same segment, but outside of the hashed region of
the module, that contains the offset from that position to
_GLOBAL_OFFSET_TABLE_:

.boringssl_got_delta:
    .quad _GLOBAL_OFFSET_TABLE_-.boringssl_got_delta

Then a movabs of $_GLOBAL_OFFSET_TABLE_-.Lfoo turns into:

movq .boringssl_got_delta(%rip), %destreg
addq $.boringssl_got_delta-.Lfoo, %destreg

This works because it's calculating
_GLOBAL_OFFSET_TABLE_ - got_delta + (got_delta - .Lfoo)

When that value is added to .Lfoo, as the original code will do, the
correct address results. Also it doesn't need an extra register because
we know that 32-bit offsets are sufficient for offsets within the
module.

As for the offsets within the offset table, we have to load them from
locations outside of the hashed part of the module to get the
relocations out of the way. Again, no extra registers are needed.

Change-Id: I87b19a2f8886bd9f7ac538fd55754e526bcf3097
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42324
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-08-10 23:46:33 +00:00
Nick Harper 74161f485b Enforce presence of ALPN when QUIC is in use.
Update-Note: If an SSL_QUIC_METHOD is set, connections will now fail if
ALPN is not negotiated. This new behavior can be detected by checking
if the value of BORINGSSL_API_VERSION is greater than 10.

Bug: 294
Change-Id: I42fb80aa09268e77cec4a51e49cdad79bd72fa58
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42304
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-07-30 16:41:06 +00:00
David Benjamin 7d3a24d9db Fix the naming of alert error codes.
Reason codes 1000+N correspond to receiving an alert N from the peer,
rather than observing the corresponding error condition locally. This
has generally been a source of confusion for folks.

They were originally named like SSL_R_TLSV1_ALERT_DECRYPTION_FAILED, but
OpenSSL introduced a few without the "ALERT" token in
739a543ea863682f157e9aa0ee382367eb3d187c.

We then inadvertently carried the mistake over in
SSL_R_TLSV1_UNKNOWN_PSK_IDENTITY and SSL_R_TLSV1_CERTIFICATE_REQUIRED.
Fix all these to include the "ALERT" for consistency and make it
slightly less confusing. (Although perhaps it should have been
RECEIVED_ALERT or so.) Add compatibility #defines for the original
OpenSSL ones and SSL_R_TLSV1_CERTIFICATE_REQUIRED. The latter can be
removed when downstream code is fixed. The OpenSSL ones we'll probably
just leave around.

Update-Note: The renamed alerts will log slightly different strings, but
the constants used by external code are still there.

Bug: 366
Change-Id: I30c299c4ad4b2bed695bd71d0831fbe6755975a7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42384
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-07-29 21:19:25 +00:00
David Benjamin 70fee17204 Use golang.org/x/crypto in runner.
The CI should be set up to retain the Go module and build caches, so
we'll avoid downloading it multiple times. This avoids having to
replicate some code.

Update-Note: The tests now have a golang.org/x/crypto dependency. This
should be fetched transparently with Go modules. Monorepos with
different import path conventions may need to rewrite these imports.

Change-Id: If5ba52e051f180536d72109c2e690bbd13d58e7c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42044
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-07-29 19:27:59 +00:00
Nick Harper 281a8f5ea3 Disable ClientHello padding for QUIC.
Bug: 327
Change-Id: I415deee8e6b2dc4cd5bdfb5e329d889dd3a5baa7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42364
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-07-28 18:16:41 +00:00
David Benjamin db129f3f3f Add X509_SIG_get0 and X509_SIG_getm.
Change-Id: I1bef3ea54f871003f7e4a076c5cfb0dbb7f89f73
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42344
Reviewed-by: Adam Langley <agl@google.com>
2020-07-28 15:36:02 +00:00
Daniel McArdle 8b601c88fb Implement HPKE.
draft-ietf-tls-esni-07 uses HPKE for encryption.

Bug: 275
Change-Id: I4af39be4df534f8c1c991c4df82d38c6adcf2574
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41304
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-07-27 20:08:35 +00:00
Nick Harper cac93924ab Disallow TLS 1.3 compatibility mode in QUIC.
Bug: 335
Change-Id: I3caa780284d4a3e646414d1fd85cc2528ebeceff
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41264
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-07-27 18:51:35 +00:00
David Benjamin 54858b63c1 Switch clang-format IncludeBlocks to Preserve.
clang-format now reorders includes. It used to simply sort within
blocks, but later it added a "regroup" option. The regroup option is a
bit aggressive and does not take into account our project headers being
referenced in <system/header.h> style. (It also won't be able to
recognize the header corresponding to the source file, but perhaps we
should drop that rule.)

For now, just revert it to Preserve.

Change-Id: Ief82b5c3f91c16a8def14f91ef6bf6cde502bb79
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42265
Reviewed-by: Adam Langley <agl@google.com>
2020-07-23 21:55:26 +00:00
David Benjamin d054e1bc61 Fix unterminated clang-format off.
We should probably ponder what to do about clang-format. That we
disagree on chains of && is a little annoying, but peppering the code
with clang-format off seems problematic.

Change-Id: I0547e4e41817e8c0b585d5fabe759ef25ed00cf7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42264
Reviewed-by: Adam Langley <agl@google.com>
2020-07-23 20:52:15 +00:00
Daniel McArdle 1a63507c41 Add line number to doc.go error messages.
Change-Id: I00f35648a6d354abdc908314fef48b3fa573d825
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42224
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-07-20 17:33:03 +00:00
Adam Langley f0558c359c Kick the bots.
This should make them update and generate JSON outputs due to
8c0a6ebfc2.

Change-Id: I7e2fa7ace2ed0216fee6b553c4cf7e16a7d7457d
2020-07-16 14:14:15 -07:00
David Benjamin 8c0a6ebfc2 Add a JSON output to generate_build_files.py.
gRPC are currently importing generate_build_files.py, injecting a
custom printer, and running into problems with the symlinks they set up
to make this work, as well as needing to delete duplicate generated
files.
https://github.com/grpc/grpc/blob/53a5ad34c0b5fca2cc9fd9ec4b354ff79c12948b/src/boringssl/gen_build_yaml.py#L130
https://boringssl-review.googlesource.com/c/boringssl/+/42164

Rather than layer on more hacks, add a JSON output to
generate_build_files.py. This outputs a sources.json file that folks
with especially custom builds can consume. (Looks like gRPC converts to
some home-grown YAML format which I imagine is further processed by some
other generator?) We can then add it to master-with-bazel's output.

Change-Id: I82b4ea0647386ca6c76a977f057b9962f40d41c8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42204
Reviewed-by: Adam Langley <agl@google.com>
2020-07-16 19:32:10 +00:00
Adam Langley 83b74c6a7a Add details of 20190808 FIPS certification.
Change-Id: I4d17e1e6f24b623ee39a844def8f265eb5e6c6cc
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42144
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-07-13 16:59:37 +00:00
David Benjamin 8f88b27d6a Link to ws2_32 more consistently.
This fixes a couple issues:

- Which libraries to use should be based on WIN32, not MSVC.

- Windows libraries can be specified by #pragma comment lines in the
  source or by build dependencies. We specified #pragma lines in
  source, but also have build dependencies in crypto_test, etc. The
  latter was missing bssl.

  The comment line should be sufficient, but being explicit is useful,
  so fill in the missing one. This should help building with MINGW,
  which is missing support for the usual Windows pragma.

Change-Id: Ide9328c7dd306738ebbb0792e47da96948fe12f4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42105
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-07-09 23:43:52 +00:00
David Benjamin de196121b0 Allow explicitly-encoded X.509v1 versions for now.
Sadly, we need to roll this one back for now, at least until we've
cleared all the test failures it causes. This retains the other checks
in https://boringssl-review.googlesource.com/c/boringssl/+/41746. We're
only rolling back enforcement of the DEFAULT v1 encoding.

Bug: 348, 364
Change-Id: I6a290311f5a5714ff4d5add3ae35ec4550398b32
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42104
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-07-09 16:28:02 +00:00
David Benjamin eda849d2e6 Opaquify PKCS8_PRIV_KEY_INFO.
This is partially imported from upstream's
54dbf42398e23349b59f258a3dd60387bbc5ba13 which does something similar.

In doing so, remove the pkcs8->broken field, which is a remnant of some
parsing hacks we long since removed (PKCS8_set_broken). The immediate
motivation is, if this sticks, this would make it easier to detach
i2d_PKCS8_PRIV_KEY_INFO and d2i_PKCS8_PRIV_KEY_INFO from the old ASN.1
code.

Update-Note: Direct accesses of PKCS8_PRIV_KEY_INFO now need to use the
accessors. Code search suggests no one uses the fields. Even the
accessors are virtually unused (the one thing which uses it doesn't need
it).

Bug: chromium:1102458
Change-Id: I57054de3fe412079f7387dc99291250e873b1471
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42006
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-07-08 16:09:11 +00:00
David Benjamin 5d7c2f8b1d Implement i2d_PUBKEY and friends without crypto/asn1.
Code which targets OpenSSL won't use EVP_parse_public_key. X509_PUBKEY
is fairly deeply tied to the old ASN.1 stack, but there's no reason for
i2d_PUBKEY and friends to be. Move them to crypto/evp and reimplement as
wrappers over our functions.

Bug: chromium:1102458
Change-Id: Ic11766acdac797602e4abe1253b0efe33faef298
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42005
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-07-08 15:48:18 +00:00
Steven Valdez d0637e901d Remove TRUST_TOKEN_experiment_v0.
Update-Note: This gets rid of TRUST_TOKEN_experiment_v0. Existing callers
should be updated to call TRUST_TOKEN_experiment_v1.

Change-Id: I8ec9b808cbd35546425690d1548db671ff033e14
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41524
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
2020-07-07 16:26:59 +00:00
David Benjamin b9fbf4069e Clarify in-place rules for low-level AES mode functions.
Change-Id: I9dde27f4a6b492d5a3f49041c8cdcac642c58335
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42004
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-07-06 18:20:21 +00:00
Adam Langley fb0c05cac2 acvp: add CMAC-AES support.
Change by Dan Janni.

Change-Id: I3f059e7b1a822c6f97128ca92a693499a3f7fa8f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41984
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-07-02 20:51:31 +00:00
Adam Langley c655065273 acvp: add SP800-108 KDF support.
Based on a change from Dan Janni.

Change-Id: Ibe00e61cb43819ecad7c1376f8c013aca3667037
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41964
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-07-02 20:29:41 +00:00
David Benjamin 25638f06e3 Remove x509->name.
Every X509 object, when parsed, would pretty-print the subject and stash
the result in x509->name. This field was removed in upstream OpenSSL and
all uses I found have now been fixed. Remove this to reduce unnecessary
work in the X.509 parser.

Update-Note: instead of x509->name, use X509_NAME_oneline and
X509_get_subject_name.

Change-Id: I1d1e69bed7429d59125a8bdea5cbba391cd1028c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41904
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-07-02 20:19:01 +00:00
Adam Langley 939d426f6b Maybe build for AArch64 Windows.
Microsoft lists[1] this define to indicate AArch64, support for which is
requested on https://github.com/grpc/grpc/issues/23310.

More might well be needed, especially if the assembly code is to work,
but maybe this'll work for gRPC.

[1] https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019

Change-Id: Id66d1c8ab7ab161f73c993dd4901e2252198bda8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41945
Reviewed-by: Adam Langley <alangley@gmail.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-07-02 20:06:21 +00:00
Adam Langley e2abade424 sha1-x86_64: fix CFI.
This issue only arises when SHAEXT is enabled, which it isn't (yet).
Will upstream too.

Change-Id: I92de51789d58ba1784b88eb872b1f9eca8eb78d8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41944
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-06-30 16:48:54 +00:00
Brian Smith 5d74463301 Use |crypto_word_t| and |size_t| more consistently in ECC scalar recoding.
Use |crypto_word_t| as the type for secret values in scalar recoding.
Use |size_t| as the type of array indexes in scalar recoding. Use
explicit casts where a larger type is (losslessly) truncated to a
smaller type. With this change, |uint64_t| is no longer used in the
p256.c when building in 32-bit mode, |unsigned| is not used in any of
the affected modules, and |uint8_t| and |char| are no longer used for
secret values in the ECC recoding.

When given the choice of doing non-array-indexing arithmetic (e.g. shifts)
on |size_t| values or |crypto_word_t| values, prefer doing it on
|crypto_word_t| values. More generally, try to use |size_t| only for
sizes and array indexes.

This is part of a bigger project to minimize the use of types other than
|crypto_word_t| for secret values. This is also part of a larger project
make the ECC code more consistent.

Avoid changing the loop indexing in the P-256 scalar multiplication from
|int| to |size_t|. The P-224 code does use |size_t| but it is less clear
than the P-256 code where |i - 1| results in a negative/underflowed
value when |i| is zero.

Change-Id: I78cb404455c2340a4f8c9688d36c0d425bfcc50b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41685
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-30 15:04:06 +00:00
Ilya Tokar 7361ee42cf Enable shaext path for sha1.
This makes sha1 ~2x faster on Amd Rome:

BM_SHA1Hash/2               10.9MB/s ± 1%           14.0MB/s ± 1%  +28.77%        (p=0.000 n=10+10)
BM_SHA1Hash/4               21.9MB/s ± 1%           28.2MB/s ± 1%  +28.56%        (p=0.000 n=10+10)
BM_SHA1Hash/8               43.9MB/s ± 1%           56.3MB/s ± 2%  +28.36%        (p=0.000 n=10+10)
BM_SHA1Hash/16              88.1MB/s ± 1%          114.8MB/s ± 2%  +30.40%         (p=0.000 n=9+10)
BM_SHA1Hash/32               178MB/s ± 1%            229MB/s ± 2%  +28.64%        (p=0.000 n=10+10)
BM_SHA1Hash/64               240MB/s ± 1%            363MB/s ± 2%  +51.57%        (p=0.000 n=10+10)
BM_SHA1Hash/512              629MB/s ± 1%           1129MB/s ± 2%  +79.54%         (p=0.000 n=9+10)
BM_SHA1Hash/4k               794MB/s ± 0%           1538MB/s ± 1%  +93.76%         (p=0.000 n=8+10)
BM_SHA1Hash/32k              820MB/s ± 1%           1610MB/s ± 2%  +96.44%        (p=0.000 n=10+10)
BM_SHA1Hash/256k             822MB/s ± 1%           1624MB/s ± 1%  +97.48%        (p=0.000 n=10+10)
BM_SHA1Hash/1M               822MB/s ± 1%           1625MB/s ± 1%  +97.63%        (p=0.000 n=10+10)
BM_SHA1Hash/2M               824MB/s ± 1%           1626MB/s ± 1%  +97.32%        (p=0.000 n=10+10)
BM_SHA1Hash/4M               826MB/s ± 1%           1631MB/s ± 0%  +97.56%         (p=0.000 n=10+8)
BM_SHA1Hash/8M               824MB/s ± 1%           1625MB/s ± 1%  +97.14%        (p=0.000 n=10+10)
BM_SHA1Hash/16M              823MB/s ± 1%           1625MB/s ± 1%  +97.40%        (p=0.000 n=10+10)

Change-Id: Ic75eb717a71b35d0ca775c309e08396b2ab77641
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41884
Reviewed-by: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-30 14:58:34 +00:00
David Benjamin 5fa22ed85e Avoid relying on SSL_get_session's behavior during the handshake.
Mid-renegotiation, there are a lot of sets of TLS parameters flying
around. We need to be clear which one we want for each operation. There
were a few parts of TLS 1.2 which were relying on SSL_get_session to
abstract between the resumption session and a new session.

Implement that separately as ssl_handshake_session, so we're free to
avoid SSL_get_session returning an incomplete session mid-renegotiation.

This doesn't fixed the linked Chromium bug, but it is necessary to do
so. (I'm trying to separate the SSL_get_session change from the
dependencies within the library.)

Update-Note: SSL_generate_key_block will now fail mid-handshake. It is
ambiguous which key block to use and, in some cases, we may not even be
able to compute the right key block.

Bug: chromium:1010748
Change-Id: I30c8a683bb506310e37adbd05a28e3b8de6e6836
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41865
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-29 16:18:30 +00:00
David Benjamin b3c5ac51d5 Add a -wait-for-debugger flag to runner.
xterm on macOS is surprisingly difficult to get at these days. Instead,
add an option to make bssl_shim SIGSTOP itself so a debugger can resume
it.

Change-Id: Ie3cf02744557f46c8fa08c162276b5ff851a51c7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41864
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-06-29 15:41:10 +00:00
David Benjamin 86f86cbdf7 Add missing OPENSSL_EXPORT to X509_get_X509_PUBKEY.
Thanks to Daniel Stenberg for noticing this.

Change-Id: I4e1e75d879dc8a09a9d077d710a69804b31ad7bd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41924
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-06-29 15:19:03 +00:00
David Benjamin 430a742303 Const-correct various functions in crypto/asn1.
The const ASN1_TIME getters don't work well because some const functions
aren't marked as such. I took a pass over the header and fixed the ones
I noticed.

Change-Id: I7eede530abc14ba0aab5763561c6f2dcf09e9659
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41824
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-06-23 17:57:25 +00:00
Pete Bentley d1d8eee76b Remove uneeded switch statement.
Warnings for switch statements with just a default case are
now fatal with the latest Windows toolchain used by Github
workflows. So indirectly this was breaking Conscrypt's
continuous integration and possibly other projects using
BoringSSL which run CI on Windows.

Example: https://github.com/google/conscrypt/runs/793502854?check_suite_focus=true

Change-Id: Ia09b86f3292299089c6536862a170677a8024984
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41844
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-06-22 14:06:04 +00:00
David Benjamin 33f8d33af0 Convert X.509 accessor macros to proper functions.
We'll need the accessors to be functions if we ever make X509 opaque.
Functions are also type-checked and avoid confusing code search's cross
reference features.

Update-Note: This should be compatible, but it is possible that someone,
e.g., passed in a bssl::UniquePtr<X509> to an accessor and relied on
operator->. Callers may also run afoul of const correctness. I mirrored
OpenSSL 1.1.1's consts, so it should at least be compatible with
third-party code.

Change-Id: I65dadc4e9ac0042576dc4db0f194d2e6b786ccca
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41808
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-19 22:28:52 +00:00
David Benjamin d206a11d48 Remove X509_CINF_get_issuer and X509_CINF_get_extensions.
The X509_CINF_* macros were removed before OpenSSL 1.0.2 was released
but after we forked. X509_CINF_set_modified and X509_CINF_get_signature
have some users to clean up, but these two are unused.

(OpenSSL 1.1.x's new X.509 API effectively no longer exposes X509_CINF
at all. If we could align, that would simplify switching to retaining
the full encoding rather than just TBSCertificate. But I think we'll
need to add some functions to replace a few use cases they missed.)

Update-Note: Two unused macros were removed. If there were uses, the
X509-level accessors can be used instead.

Change-Id: I9b5c7c08196885ee0bccc2658b1ad177bf3100e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41807
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-19 22:13:52 +00:00
David Benjamin beaf594f8b Remove X509_get_signature_type.
This macro dates to SSLeay. It is never used and for good reason: it
doesn't do anything. EVP_PKEY_type returns NID_undef if the NID is not
key type, but it is being passed in a signature algorithm type. This
means that, except for invalid certificates, or the rare algorithms
where the two OIDs match (Ed25519), it always returns NID_undef.

Update-Note: If there are any calls to X509_get_signature_type, remove
them. It more-or-less always returned NID_undef.

Change-Id: I6e2e41f171143c28f2afce2890f029b776cc36b5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41806
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-19 21:46:02 +00:00
David Benjamin 991d31bbf1 clang-format x509.h and run comment converter.
We never updated it to OpenSSL's new indentation style and it's already
pretty difficult to directly apply patches from upstream anyway.

Change-Id: I78f7f644c6d427f27c29f51c4e8ba54476ddeb2b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41805
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-19 21:35:42 +00:00
David Benjamin 9dd9d4fc24 Check AlgorithmIdentifier parameters for RSA and ECDSA signatures.
This aligns with the Chromium certificate verifier, which allows NULL or
empty for RSA and requires empty for ECDSA.

Bug: 342
Change-Id: I34acf68f63b4d133dd47b73144b2f27224c499ee
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41804
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-19 21:30:22 +00:00
David Benjamin a3cc7780e7 Remove some unimplemented prototypes.
We don't have the corresponding functions anyway.

Change-Id: I9771771f011da295db708ed8bc635b4748d0101b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41784
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-06-19 18:26:12 +00:00
David Benjamin dd86e75b24 Check the X.509 version when parsing.
This checks the X.509 version is valid and consistent with fields new to
those versions. These checks are also implemented by Chromium's
certificate verifier and should be compatible.

Update-Note: The X.509 parser is now a bit stricter. This may break some
malformed certificates which were previously incorrectly accepted.

Bug: 348, 351
Change-Id: I56f35d768d5e72948d22a9546fba3d257a75f409
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41746
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-19 18:16:11 +00:00
David Benjamin fd86eaa868 Fix x509v3_cache_extensions error-handling.
This imports https://github.com/openssl/openssl/pull/10756 from upstream
with a number of changes:

- Add tests.

- Rather than blindly return false in cert_self_signed, make that
  function a tri-state return. This gives better error-reporting when the
  leaf certificate has a bad extension and reduces the risk of confusing
  the verifier.

- Give x509v3_cache_extensions a return value rather than expecting
  everyone to check EXFLAG_INVALID. Switch X509_check_purpose calls to
  it when applicable.

- Rather than setting EXFLAG_INVALID on bad CRLs, fail the parse
  altogether. We're already in the d2i callback. (Nothing checks
  EXFLAG_INVALID on CRLs.)

- I've intentionally left the error unchecked in X509_cmp. OpenSSL's
  strategy is to return -2, but that's not a consistent comparison
  and may mess up sorts that depend on transitivity. This retains the
  current behavior where we consider all undigestable certs as equal
  to each other (modulo the opportunistic TBSCertificate double-check
  which should work most of the time). This is terrible, so I've filed
  https://crbug.com/boringssl/355 to track fixes here.

That last fix caught that I misread the spec when I generated
kKnownCriticalCRL and kUnknownCriticalCRL2. This fixes those and uses
the old kKnownCriticalCRL as a test for invalid extensions. (Those CRLs
were assembled by hand, so they don't indicate any software has been
encoding them wrong.)

Update-Note: The X.509 verifier now correctly rejects syntax errors in
important certificate extensions. This may break some malformed
certificates which were incorrectly accepted before.

Bug: 345
Change-Id: Ifb3a98ba62cd296920546bc718fda524bd55c024
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41745
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-19 16:55:51 +00:00
David Benjamin cbac9c3a2d Work around Windows command-line limits in embed_test_data.go.
Change-Id: I020f7c75d2ed160b16a62cb909d2113c318feb3c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41764
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-18 22:48:41 +00:00
David Benjamin 5ddc5b14d9 Move crypto/x509 test data into its own directory.
I'm about to add a lot more of these.

Change-Id: I2556e301dbed3ceb450e7070ffed46dc4d6de2b4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41744
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-18 22:39:51 +00:00
David Benjamin 1b8194715e Test resumability of same, different, and default ticket keys.
If we were to accidentally leave the ticket keys zero-initialized, the
only tests that notice are DefaultTicketKeyInitialization (initial key
is not all zeros) and DefaultTicketKeyRotation (old key is not new key),
by way of querying the keys themselves.

Add some tests which additionally test the effects on resumption itself.

Change-Id: I3bfd3f1e082e3a466105dbdffa18621b81c53d17
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41564
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-06-18 22:09:51 +00:00
Jesko Jochum c179854243 Fixes warning when redefining PATH_MAX when building with MINGW.
Fixes warning thrown when compiling digest.cc with MinGW64, by only defining PATH_MAX, if it has not yet been defined.
Else building with MinGW64, throws the following warning:

<PATH_TO_SOURCE_FOLDER>\boringssl\src\tool\digest.cc:39: warning: "PATH_MAX" redefined
   39 | #define PATH_MAX MAX_PATH
      |
In file included from C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/9.3.0/include-fixed/limits.h:194,
                 from C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/9.3.0/include-fixed/syslimits.h:7,
                 from C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/9.3.0/include-fixed/limits.h:34,
                 from C:/msys64/mingw64/x86_64-w64-mingw32/include/pthread.h:67,
                 from C:/msys64/mingw64/include/c++/9.3.0/x86_64-w64-mingw32/bits/gthr-default.h:35,
                 from C:/msys64/mingw64/include/c++/9.3.0/x86_64-w64-mingw32/bits/gthr.h:148,
                 from C:/msys64/mingw64/include/c++/9.3.0/ext/atomicity.h:35,
                 from C:/msys64/mingw64/include/c++/9.3.0/memory:73,
                 from <PATH_TO_SOURCE_FOLDER>/boringssl/src/include/openssl/base.h:473,
                 from <PATH_TO_SOURCE_FOLDER>\boringssl\src\tool\digest.cc:15:
C:/msys64/mingw64/x86_64-w64-mingw32/include/limits.h:20: note: this is the location of the previous definition
   20 | #define PATH_MAX 260
      |

Change-Id: I29eb33ee8fad9e4e80d9348a0d5e4057dfac620c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41705
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-17 17:22:18 +00:00
David Benjamin 8afdbf04bd Abstract fd operations better in tool.
Windows and POSIX implement very similar fd operations, but differ
slightly:

- ssize_t in POSIX is usually int on Windows.
- POSIX needs EINTR retry loops.
- Windows wants _open rather than open, etc.
- POSIX fds and sockets are the same thing, while Windows sockets are
  HANDLEs and leaves fd as a C runtime construct.

Rather than ad-hoc macros and redefinitions of ssize_t (which reportedly
upset MINGW), add some actual abstractions. While I'm here, add a scoped
file descriptor type.

That still leaves recv/send which are only used in one file, so defined
a socket_result_t for them.

Change-Id: I17fca2a50c77191f573852bfd27553996e3e9c3f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41725
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-06-16 20:48:22 +00:00
David Benjamin 884614c24f Use CMAKE_SIZEOF_VOID_P instead of CMAKE_CL_64
CMake's documentation says this is preferred.
https://cmake.org/cmake/help/latest/variable/CMAKE_CL_64.html

Reportedly, it also works better with MINGW, though we do not currently
support MINGW with the CMake build. See
https://boringssl-review.googlesource.com/c/boringssl/+/41704/

Change-Id: Ie5794306beeeff816b34ee98c7a0f8e0d4f99ec8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41724
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-16 15:20:28 +00:00
David Benjamin cd8f3d36fe Enforce the keyUsage extension in TLS 1.2 client certs.
I've left this independent of SSL_set_enforce_rsa_key_usage because
client certificates in TLS always use the digitalSignature bit, RSA or
otherwise, so it's less likely that someone has messed it up, unlike
TLS 1.2 RSA server certificates.

Update-Note: Client certificates which do not support the
digitalSignature key usage will be rejected. They should either include
that bit or omit the keyUsage extension.

Bug: 349
Change-Id: I97bbf0c8e394f219ff75b686e0c14019f6d8c9a8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41664
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-06-15 16:34:03 +00:00
David Benjamin 72b095d0d4 Reword some comments.
There were a handful of comments that use "blacklist" and "whitelist".
They are easy to fix.

Change-Id: I49a9592393b43fc85e92b4a00a585b504dede75a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41645
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-12 21:17:03 +00:00
Adam Langley 7f90eda55e Add “Z Computation” KAT.
FIPS updates will make this useful / mandatory in the future.

Change-Id: I9921e4f3fc8a8315dc85dc366f331b456572d49e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41644
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-06-12 19:01:37 +00:00
Adam Langley 9c256d1d7f acvptool: handle negative sizeConstraint.
The NIST server has been updated and is now sending a sizeConstraint of
-1 to indicate that the large-upload process isn't needed. However, the
code was trying to put that in a uint64, which caused a parse error.

Change-Id: I9ee16918df13c229b0e889fa1248eb2e0a6a5fb2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41605
Reviewed-by: David Benjamin <davidben@google.com>
2020-06-11 20:41:51 +00:00
Adam Langley 0313b59d5f Let memory hooks override the size prefix.
In order to efficiently track heap operations, the memory hooks may need
to store other information in the prefix area than the size that
BoringSSL uses by default. This change lets them manage the prefix how
they wish.

Change-Id: I5a4d98bed100aff2deaaabb3d23fab02f0be82aa
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41584
Reviewed-by: Adam Langley <alangley@gmail.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-11 18:41:45 +00:00
Adam Langley fbaf1c0546 acvptool: go fmt
Change-Id: If90e35bf4ef75d12cdbddc118611127b74bbafe6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41604
Reviewed-by: Adam Langley <agl@google.com>
2020-06-10 22:15:02 +00:00
David Benjamin 251b5169fd Assert md_size > 0.
md_size is the size of a hash, so it cannot be zero. Add an assert since
it appears to have caused some confusion. The j >= md_size and
j -= md_size logic implicitly assumes md_size > 0. (It's another way to
stick a % md_size elsewhere which, likewise, assumes md_size > 0.)

The bug report itself is a false positive, but locally documenting
assumptions is good.

Bug: chromium:1092697
Change-Id: I3be0992552a300c6786cf1dc5ecfa881173a42e6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41544
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-06-09 17:08:35 +00:00
Adam Langley 88024df121 Remove -enable-ed25519 compat hack.
Change-Id: I2d5843b2dc957f8ae8e4d9a41cecd3268220cc1d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41504
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-06-02 15:46:08 +00:00
Adam Langley 53a17f5524 Add a |SSL_process_tls13_new_session_ticket|.
This API processes a given NewSessionTicket message and returns a resumable
|SSL_SESSION| object that contains the ticket.

(Change by Cesar Ghali.)

Change-Id: I7426933b043865ca54d3cf597f7ecd54d493bf35
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41464
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-05-28 19:39:26 +00:00
David Benjamin 2309f645e5 Use ctr32 optimizations for AES_ctr128_encrypt.
There are a decent number of uses of this function directly. I've
attached this to bug 338. Arguably it makes it worse, though it does
help with aligning on ctr32, if that works out.

Bug: 338
Change-Id: I3dfc1305d359ec0c88d4f298fe1928bef7ec9877
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41426
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-05-26 19:04:16 +00:00
David Benjamin 8819e0be62 Test AES mode wrappers.
AES_ctr128_encrypt, in particular, has a decent number of external
callers but is completely untested. I haven't included
AES_cfb128_encrypt because its EVP_CIPHER counterpart is tested in
decrept_test. But the EVP_CIPHER counterpart simply calls
AES_cfb128_encrypt, so it's tested transitively.

Change-Id: I0133dbd5b13c2b4045a89a04f29240008a279186
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41425
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-05-26 18:03:03 +00:00
David Benjamin 81a998a637 Bump minimum CMake version.
CMake 3.2.1 was released in March 2015, which was over five years ago.

Change-Id: I8b76e1de3dba8732a143f86a3956c83fbb4306a7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41444
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-26 16:37:04 +00:00
Nick Harper 851943277f Modify how QUIC 0-RTT go/no-go decision is made.
The previous implementation was too strict in its byte-for-byte equality
check including Transport Parameters, because the Transport Parameters
contain a field that QUIC requires be different on each connection. This
change still has BoringSSL do a byte-for-byte check, but now it is only
done over the quic_early_data_context. An additional requirement is
imposed that the quic_early_data_context must be set for early data
capable tickets to be issued.

Bug: 295
Change-Id: I5145c10752b41908b6807c3a3c967653b0c13f37
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41427
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-26 16:31:02 +00:00
David Benjamin 9701e84eff Remove RAND_set_urandom_fd.
Also update the documentation for RAND_enable_fork_unsafe_buffering. The
fd parameter is no longer used.

Update-Note: RAND_set_urandom_fd no longer exists. This was only called
by Chromium, which now uses CRYPTO_pre_sandbox_init.

Change-Id: I1659c1cc84a6f1edc01f6105fc07e80856e457fc
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41424
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-20 18:55:59 +00:00
David Benjamin 7b31d69f19 Document that getrandom support must be consistent.
Syscall-filtering sandboxes may make getrandom fail without crashing.
This will sometimes trigger the /dev/urandom fallback and sometimes not.

Change-Id: Ic824e5bfe6fcb99105fd285184243c4620447327
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41404
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-05-20 18:55:29 +00:00
Anna Sarai Rosenberg 8f12996be3 Fix docs link for SSL_CTX_load_verify_locations
Link is outdated; results in 404. Update link to match docs version in other links with redirected path to current link for that version.

Change-Id: I4c9bb2fe48d1b2bbf699773259d5eebad9461ddd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41385
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-18 17:00:25 +00:00
Steven Valdez 78b3337a10 Fix TRUST_TOKEN experiment_v1 SRR map.
Change-Id: I9e5c9b016cc0b3b7926df850d470e6367eb9c0bc
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41364
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-14 19:21:22 +00:00
David Benjamin 3e4dfbb2f8 Add CRYPTO_pre_sandbox_init.
The intent is to replace the logic in [0] and allows Chromium to set up
the MADV_WIPEONFORK page without increasing sandbox syscall surface.
From there we can remove RAND_set_urandom_fd and trim a bit of
complexity from the PRNG logic.

[0] https://source.chromium.org/chromium/chromium/src/+/master:content/app/content_main_runner_impl.cc;l=333-341;drc=975850fa57e140ec696114477e9416a19f06d29f

Change-Id: I9b679e15da551a10302389556c6c77d192be662a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41326
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-05-14 18:17:12 +00:00
David Benjamin 9cf9d3eb06 Still query getauxval if reading /proc/cpuinfo fails.
If BoringSSL is used in a sandbox without /proc/cpuinfo, we will
silently act as if the CPU is missing capabilities, even though
getauxval may be available. We use /proc/cpuinfo to work around a
missing AT_HWCAP2 and ignore a particular broken CPU.

Ignoring the former fails closed, so it's safe to proceed. The latter
fails closed, but it is now vanishingly rare (even missing AT_HWCAP2 has
largely dropped off), so instead proceed with getauxval. This makes the
/proc paths largely optional.

Change-Id: Ib198c4f78ccdae874d55669b6a7508dfbeac0f44
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41325
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-05-14 17:33:22 +00:00
Nick Harper be28dd623f Add missing header to ec/wnaf.c
a810d82 added calls to OPENSSL_malloc in this file, but openssl/mem.h
was missing.

Change-Id: I77e19e61e92b1e73702cb3eb93b9c6e22aca9596
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41344
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-14 00:09:11 +00:00
David Benjamin b7acfff8e7 Fix OPENSSL_TSAN typo.
We weren't actually reducing MAX_BLINDINGS_PER_RSA under TSan.

Change-Id: Ib33dc1a1c0312bd3309a64f2600ec4d6e2ec9ddb
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41324
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-13 17:00:31 +00:00
David Benjamin 49e95dc0f3 Fix p256-x86_64-table.h indentation.
This makes clang-format a no-op. (I would not recommend running
clang-format on that file. It takes a while.)

Change-Id: Ie4bd93340be8fe586e774ce16b5aed1ab626bb0c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41165
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-12 19:40:02 +00:00
Ilya Tokar 1274d1d977 Enable avx2 implementation of sha1.
Before:
Did 19655000 SHA-1 (16 bytes) operations in 2000053us (157.2 MB/sec)
Did 5112000 SHA-1 (256 bytes) operations in 2000126us (654.3 MB/sec)
Did 1280000 SHA-1 (1350 bytes) operations in 2000559us (863.8 MB/sec)
Did 229000 SHA-1 (8192 bytes) operations in 2004784us (935.7 MB/sec)
Did 116000 SHA-1 (16384 bytes) operations in 2008224us (946.4 MB/sec)

After:
Did 20506000 SHA-1 (16 bytes) operations in 2000062us (164.0 MB/sec) [+4.3%]
Did 5659000 SHA-1 (256 bytes) operations in 2000100us (724.3 MB/sec) [+10.7%]
Did 1454000 SHA-1 (1350 bytes) operations in 2000739us (981.1 MB/sec) [+13.6%]
Did 255000 SHA-1 (8192 bytes) operations in 2000733us (1044.1 MB/sec) [+11.6%]
Did 129000 SHA-1 (16384 bytes) operations in 2009483us (1051.8 MB/sec) [+11.1%]

Change-Id: Idaf75e92b2da4d83b597771aca1123f2884d7687
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41284
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-12 19:32:02 +00:00
David Benjamin d4d501c159 Trim Z coordinates from the OPENSSL_SMALL P-256 tables.
The small P-256 tables currently store 2 * 16 points in Jacobian
coordinates, but all the Z values are one, except for the two entries
which store infinity. Instead, store only affine coordinates and omit
the infinity entries. (We can recover infinity with constant-time
selects.)

This trims 1152 bytes from the table. Comparing the sizes of the bssl
tool (stripped, otherwise debug symbols undo the size gain), the binary
is 4096 bytes smaller, but I suspect this is just an artifact of
something rounding to page sizes.

Along the way, I've scripted the table generation and merged it into a
much generalized version of make_p256-x86_64-table.go.

As a bonus, by cutting the size of the table we scan, it's faster!
(ECDSA verify was already not scanning a table, so that one staying the
same is expected.)

Before:
Did 22302 ECDH P-256 operations in 4009795us (5561.9 ops/sec)
Did 62000 ECDSA P-256 signing operations in 4020075us (15422.6 ops/sec)
Did 26544 ECDSA P-256 verify operations in 4056526us (6543.5 ops/sec)

After:
Did 23001 ECDH P-256 operations in 4016544us (5726.6 ops/sec) [+3.0%]
Did 66000 ECDSA P-256 signing operations in 4043083us (16324.2 ops/sec) [+5.8%]
Did 26544 ECDSA P-256 verify operations in 4051220us (6552.1 ops/sec) [+0.1%]

Change-Id: Ie88898fd56e57505e3a325c50bbaf0dc5d42eeb3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41164
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-12 19:24:22 +00:00
David Benjamin a810d82575 Use public multi-scalar mults in Trust Tokens where applicable.
The input points are all public, so we can use a faster multi-scalar
multiplication. This generalizes ec_point_mul_scalar_public to
ec_point_mul_scalar_public_batch. To support the batched DLEQ
construction, this function takes an arbirarily-length array of points
and allocates some temporaries if necessary.

First, to confirm that this doesn't affect the basic ECDSA verify case:
Before:
Did 6324 ECDSA P-384 verify operations in 3069342us (2060.4 ops/sec)
After:
Did 6324 ECDSA P-384 verify operations in 3063355us (2064.4 ops/sec) [+0.2%]

Results for Trust Tokens issue (Exp1) and finish_issuance (both):
Before:
Did 147 TrustToken-Exp0-Batch1 finish_issuance operations in 2059145us (71.4 ops/sec)
Did 14 TrustToken-Exp0-Batch10 finish_issuance operations in 2085888us (6.7 ops/sec)
Did 357 TrustToken-Exp1-Batch1 issue operations in 2068238us (172.6 ops/sec)
Did 286 TrustToken-Exp1-Batch1 finish_issuance operations in 2090932us (136.8 ops/sec)
Did 63 TrustToken-Exp1-Batch10 issue operations in 2068201us (30.5 ops/sec)
Did 56 TrustToken-Exp1-Batch10 finish_issuance operations in 2064796us (27.1 ops/sec)

After:
Did 168 TrustToken-Exp0-Batch1 finish_issuance operations in 2058891us (81.6 ops/sec) [+14.3%]
Did 16 TrustToken-Exp0-Batch10 finish_issuance operations in 2075742us (7.7 ops/sec) [+14.8%]
Did 378 TrustToken-Exp1-Batch1 issue operations in 2067956us (182.8 ops/sec) [+5.9%]
Did 336 TrustToken-Exp1-Batch1 finish_issuance operations in 2097757us (160.2 ops/sec) [+17.1%]
Did 105 TrustToken-Exp1-Batch10 issue operations in 2069934us (50.7 ops/sec) [+66.5%]
Did 88 TrustToken-Exp1-Batch10 finish_issuance operations in 2014621us (43.7 ops/sec) [+61.1%]

(This CL doesn't affect other operations.)

Change-Id: Ie643b06f44990ab52bf892a007732fde61cdffe5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41285
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-12 17:38:55 +00:00
Steven Valdez b55a8c1580 Use batched DLEQ proofs for Trust Token.
Before:
Did 867 TrustToken-Exp1-Batch1 generate_key operations in 1029740us (842.0 ops/sec)
Did 1441 TrustToken-Exp1-Batch1 begin_issuance operations in 1021088us (1411.2 ops/sec)
Did 200 TrustToken-Exp1-Batch1 issue operations in 1003145us (199.4 ops/sec)
Did 154 TrustToken-Exp1-Batch1 finish_issuance operations in 1053858us (146.1 ops/sec)
Did 5128000 TrustToken-Exp1-Batch1 begin_redemption operations in 1000076us (5127610.3 ops/sec)
Did 517 TrustToken-Exp1-Batch1 redeem operations in 1031054us (501.4 ops/sec)
Did 15000 TrustToken-Exp1-Batch1 finish_redemption operations in 1041906us (14396.7 ops/sec)
Did 870 TrustToken-Exp1-Batch10 generate_key operations in 1020929us (852.2 ops/sec)
Did 154 TrustToken-Exp1-Batch10 begin_issuance operations in 1085963us (141.8 ops/sec)
Did 20 TrustToken-Exp1-Batch10 issue operations in 1040995us (19.2 ops/sec)
Did 14 TrustToken-Exp1-Batch10 finish_issuance operations in 1009041us (13.9 ops/sec)
Did 5138000 TrustToken-Exp1-Batch10 begin_redemption operations in 1000114us (5137414.3 ops/sec)
Did 528 TrustToken-Exp1-Batch10 redeem operations in 1026978us (514.1 ops/sec)
Did 15000 TrustToken-Exp1-Batch10 finish_redemption operations in 1016920us (14750.4 ops/sec)

After:
Did 900 TrustToken-Exp1-Batch1 generate_key operations in 1032678us (871.5 ops/sec) [+3.5%]
Did 1410 TrustToken-Exp1-Batch1 begin_issuance operations in 1004439us (1403.8 ops/sec) [-0.5%]
Did 154 TrustToken-Exp1-Batch1 issue operations in 1068370us (144.1 ops/sec) [-27.7%]
Did 121 TrustToken-Exp1-Batch1 finish_issuance operations in 1048767us (115.4 ops/sec) [-21.0%]
Did 5179000 TrustToken-Exp1-Batch1 begin_redemption operations in 1000159us (5178176.7 ops/sec) [+1.0%]
Did 572 TrustToken-Exp1-Batch1 redeem operations in 1093354us (523.2 ops/sec) [+4.3%]
Did 15000 TrustToken-Exp1-Batch1 finish_redemption operations in 1001506us (14977.4 ops/sec) [+4.0%]
Did 913 TrustToken-Exp1-Batch10 generate_key operations in 1027546us (888.5 ops/sec) [+4.3%]
Did 154 TrustToken-Exp1-Batch10 begin_issuance operations in 1051530us (146.5 ops/sec) [+3.3%]
Did 26 TrustToken-Exp1-Batch10 issue operations in 1027599us (25.3 ops/sec) [+31.7%]
Did 24 TrustToken-Exp1-Batch10 finish_issuance operations in 1055615us (22.7 ops/sec) [+63.9%]
Did 5100000 TrustToken-Exp1-Batch10 begin_redemption operations in 1000201us (5098975.1 ops/sec) [-0.7%]
Did 561 TrustToken-Exp1-Batch10 redeem operations in 1072683us (523.0 ops/sec) [+1.7%]
Did 15000 TrustToken-Exp1-Batch10 finish_redemption operations in 1006697us (14900.2 ops/sec) [+1.0%]

Change-Id: Ibdc08f9d63e62dda14a2cd9e9d8be27c8723675b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40865
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-05-12 17:09:54 +00:00
Nick Harper 7c522995d1 Restrict when 0-RTT will be accepted in QUIC.
QUIC imposes additional restrictions on when 0-RTT data can be accepted.
With this change, a QUIC server configured to support 0-RTT will only
accept early data if the transport parameters and application protocol
specific context are a byte-for-byte match from the original connection
to the 0-RTT resumption attempt.

Bug: 295
Change-Id: Ie5d4688d1c9076b49f2131bb66b27c87e2ba041a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41145
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-05-08 15:08:00 +00:00
Nick Harper e32549edf9 Disable TLS 1.3 compatibility mode for QUIC.
Bug: 335
Change-Id: Ic22dafbc4ada3af56260bc7213f0078876e56c3d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41244
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-07 23:25:51 +00:00
David Benjamin d4a97fa65f Use a 5-bit comb for some Trust Tokens multiplications.
Several of the Trust Tokens multiplications use repeated points (G, H,
and the public keys). We can precompute a 5-bit comb for those points
and perform only 1/5th as many doubles in the multiplication.

Before:
Did 483 TrustToken-Exp0-Batch1 generate_key operations in 2017082us (239.5 ops/sec)
Did 1449 TrustToken-Exp0-Batch1 begin_issuance operations in 2086097us (694.6 ops/sec)
Did 176 TrustToken-Exp0-Batch1 issue operations in 2089640us (84.2 ops/sec)
Did 147 TrustToken-Exp0-Batch1 finish_issuance operations in 2027924us (72.5 ops/sec)
Did 12284000 TrustToken-Exp0-Batch1 begin_redemption operations in 2000151us (6141536.3 ops/sec)
Did 483 TrustToken-Exp0-Batch1 redeem operations in 2063241us (234.1 ops/sec)
Did 35000 TrustToken-Exp0-Batch1 finish_redemption operations in 2050694us (17067.4 ops/sec)
Did 483 TrustToken-Exp0-Batch10 generate_key operations in 2003222us (241.1 ops/sec)
Did 138 TrustToken-Exp0-Batch10 begin_issuance operations in 2000845us (69.0 ops/sec)
Did 16 TrustToken-Exp0-Batch10 issue operations in 2010264us (8.0 ops/sec)
Did 14 TrustToken-Exp0-Batch10 finish_issuance operations in 2036137us (6.9 ops/sec)
Did 12106000 TrustToken-Exp0-Batch10 begin_redemption operations in 2000126us (6052618.7 ops/sec)
Did 483 TrustToken-Exp0-Batch10 redeem operations in 2062366us (234.2 ops/sec)
Did 35000 TrustToken-Exp0-Batch10 finish_redemption operations in 2023617us (17295.8 ops/sec)

Did 1254 TrustToken-Exp1-Batch1 generate_key operations in 2086776us (600.9 ops/sec)
Did 3612 TrustToken-Exp1-Batch1 begin_issuance operations in 2052090us (1760.2 ops/sec)
Did 420 TrustToken-Exp1-Batch1 issue operations in 2002421us (209.7 ops/sec)
Did 378 TrustToken-Exp1-Batch1 finish_issuance operations in 2078074us (181.9 ops/sec)
Did 12843000 TrustToken-Exp1-Batch1 begin_redemption operations in 2000068us (6421281.7 ops/sec)
Did 1210 TrustToken-Exp1-Batch1 redeem operations in 2083419us (580.8 ops/sec)
Did 35000 TrustToken-Exp1-Batch1 finish_redemption operations in 2023704us (17295.0 ops/sec)
Did 1239 TrustToken-Exp1-Batch10 generate_key operations in 2060962us (601.2 ops/sec)
Did 357 TrustToken-Exp1-Batch10 begin_issuance operations in 2031131us (175.8 ops/sec)
Did 42 TrustToken-Exp1-Batch10 issue operations in 2045185us (20.5 ops/sec)
Did 36 TrustToken-Exp1-Batch10 finish_issuance operations in 2028604us (17.7 ops/sec)
Did 12435000 TrustToken-Exp1-Batch10 begin_redemption operations in 2000084us (6217238.9 ops/sec)
Did 1176 TrustToken-Exp1-Batch10 redeem operations in 2023934us (581.0 ops/sec)
Did 35000 TrustToken-Exp1-Batch10 finish_redemption operations in 2002899us (17474.7 ops/sec)

After:
Did 875 TrustToken-Exp0-Batch1 generate_key operations in 2028222us (431.4 ops/sec) [+80.2%]
Did 1449 TrustToken-Exp0-Batch1 begin_issuance operations in 2097298us (690.9 ops/sec) [-0.5%]
Did 207 TrustToken-Exp0-Batch1 issue operations in 2083578us (99.3 ops/sec) [+18.0%]
Did 147 TrustToken-Exp0-Batch1 finish_issuance operations in 2018783us (72.8 ops/sec) [+0.5%]
Did 12020250 TrustToken-Exp0-Batch1 begin_redemption operations in 2000036us (6010016.8 ops/sec) [-2.1%]
Did 525 TrustToken-Exp0-Batch1 redeem operations in 2077137us (252.8 ops/sec) [+8.0%]
Did 35000 TrustToken-Exp0-Batch1 finish_redemption operations in 2006257us (17445.4 ops/sec) [+2.2%]
Did 903 TrustToken-Exp0-Batch10 generate_key operations in 2091846us (431.7 ops/sec) [+79.0%]
Did 138 TrustToken-Exp0-Batch10 begin_issuance operations in 2006432us (68.8 ops/sec) [-0.3%]
Did 19 TrustToken-Exp0-Batch10 issue operations in 2000665us (9.5 ops/sec) [+19.3%]
Did 14 TrustToken-Exp0-Batch10 finish_issuance operations in 2045846us (6.8 ops/sec) [-0.5%]
Did 12124000 TrustToken-Exp0-Batch10 begin_redemption operations in 2000055us (6061833.3 ops/sec) [+0.2%]
Did 525 TrustToken-Exp0-Batch10 redeem operations in 2076637us (252.8 ops/sec) [+7.9%]
Did 35000 TrustToken-Exp0-Batch10 finish_redemption operations in 2000072us (17499.4 ops/sec) [+1.2%]

Did 2142 TrustToken-Exp1-Batch1 generate_key operations in 2031447us (1054.4 ops/sec) [+75.5%]
Did 3633 TrustToken-Exp1-Batch1 begin_issuance operations in 2073265us (1752.3 ops/sec) [-0.4%]
Did 504 TrustToken-Exp1-Batch1 issue operations in 2043677us (246.6 ops/sec) [+17.6%]
Did 378 TrustToken-Exp1-Batch1 finish_issuance operations in 2086624us (181.2 ops/sec) [-0.4%]
Did 12548250 TrustToken-Exp1-Batch1 begin_redemption operations in 2000020us (6274062.3 ops/sec) [-2.3%]
Did 1281 TrustToken-Exp1-Batch1 redeem operations in 2067790us (619.5 ops/sec) [+6.7%]
Did 35000 TrustToken-Exp1-Batch1 finish_redemption operations in 2012117us (17394.6 ops/sec) [+0.6%]
Did 2184 TrustToken-Exp1-Batch10 generate_key operations in 2069977us (1055.1 ops/sec) [+75.5%]
Did 357 TrustToken-Exp1-Batch10 begin_issuance operations in 2041930us (174.8 ops/sec) [-0.5%]
Did 50 TrustToken-Exp1-Batch10 issue operations in 2063927us (24.2 ops/sec) [+18.0%]
Did 36 TrustToken-Exp1-Batch10 finish_issuance operations in 2038115us (17.7 ops/sec) [-0.5%]
Did 12693000 TrustToken-Exp1-Batch10 begin_redemption operations in 2000070us (6346277.9 ops/sec) [+2.1%]
Did 1281 TrustToken-Exp1-Batch10 redeem operations in 2066940us (619.8 ops/sec) [+6.7%]
Did 35000 TrustToken-Exp1-Batch10 finish_redemption operations in 2020506us (17322.4 ops/sec) [-0.9%]

Change-Id: Id26600c07401d6567275155aa389839ac0e87013
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41124
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-07 18:16:27 +00:00
David Benjamin 5f43b12d52 Use a (mostly) constant-time multi-scalar mult for Trust Tokens.
With multi-scalar multiplication, we're stuck pondering the doubling
case. But it's fine for trust tokens, because the points are independent
and the scalars are uniformly generated and not under attacker control.
That means the probability of hitting a double is negligible. (It's
equivalent to accidentally finding the discrete log of two independent
points.)

Before:
Did 306 TrustToken-Exp0-Batch1 generate_key operations in 2000725us (152.9 ops/sec)
Did 1428 TrustToken-Exp0-Batch1 begin_issuance operations in 2080325us (686.4 ops/sec)
Did 105 TrustToken-Exp0-Batch1 issue operations in 2070658us (50.7 ops/sec)
Did 88 TrustToken-Exp0-Batch1 finish_issuance operations in 2023864us (43.5 ops/sec)
Did 12283000 TrustToken-Exp0-Batch1 begin_redemption operations in 2000063us (6141306.5 ops/sec)
Did 315 TrustToken-Exp0-Batch1 redeem operations in 2084451us (151.1 ops/sec)
Did 35000 TrustToken-Exp0-Batch1 finish_redemption operations in 2024388us (17289.2 ops/sec)
Did 315 TrustToken-Exp0-Batch10 generate_key operations in 2045481us (154.0 ops/sec)
Did 138 TrustToken-Exp0-Batch10 begin_issuance operations in 2022158us (68.2 ops/sec)
Did 10 TrustToken-Exp0-Batch10 issue operations in 2148640us (4.7 ops/sec)
Did 8 TrustToken-Exp0-Batch10 finish_issuance operations in 2047452us (3.9 ops/sec)
Did 12167000 TrustToken-Exp0-Batch10 begin_redemption operations in 2000118us (6083141.1 ops/sec)
Did 315 TrustToken-Exp0-Batch10 redeem operations in 2084853us (151.1 ops/sec)
Did 35000 TrustToken-Exp0-Batch10 finish_redemption operations in 2014997us (17369.8 ops/sec)

Did 777 TrustToken-Exp1-Batch1 generate_key operations in 2034967us (381.8 ops/sec)
Did 3612 TrustToken-Exp1-Batch1 begin_issuance operations in 2052618us (1759.7 ops/sec)
Did 264 TrustToken-Exp1-Batch1 issue operations in 2084327us (126.7 ops/sec)
Did 220 TrustToken-Exp1-Batch1 finish_issuance operations in 2024603us (108.7 ops/sec)
Did 12691000 TrustToken-Exp1-Batch1 begin_redemption operations in 2000111us (6345147.8 ops/sec)
Did 777 TrustToken-Exp1-Batch1 redeem operations in 2070867us (375.2 ops/sec)
Did 35000 TrustToken-Exp1-Batch1 finish_redemption operations in 2019118us (17334.3 ops/sec)
Did 798 TrustToken-Exp1-Batch10 generate_key operations in 2090816us (381.7 ops/sec)
Did 357 TrustToken-Exp1-Batch10 begin_issuance operations in 2032751us (175.6 ops/sec)
Did 25 TrustToken-Exp1-Batch10 issue operations in 2046353us (12.2 ops/sec)
Did 21 TrustToken-Exp1-Batch10 finish_issuance operations in 2015579us (10.4 ops/sec)
Did 12695000 TrustToken-Exp1-Batch10 begin_redemption operations in 2000126us (6347100.1 ops/sec)
Did 740 TrustToken-Exp1-Batch10 redeem operations in 2032413us (364.1 ops/sec)
Did 35000 TrustToken-Exp1-Batch10 finish_redemption operations in 2011564us (17399.4 ops/sec)

After:
Did 483 TrustToken-Exp0-Batch1 generate_key operations in 2003131us (241.1 ops/sec) [+57.7%]
Did 1449 TrustToken-Exp0-Batch1 begin_issuance operations in 2089317us (693.5 ops/sec) [+1.0%]
Did 176 TrustToken-Exp0-Batch1 issue operations in 2094210us (84.0 ops/sec) [+65.7%]
Did 147 TrustToken-Exp0-Batch1 finish_issuance operations in 2006750us (73.3 ops/sec) [+68.5%]
Did 12217000 TrustToken-Exp0-Batch1 begin_redemption operations in 2000094us (6108212.9 ops/sec) [-0.5%]
Did 483 TrustToken-Exp0-Batch1 redeem operations in 2058132us (234.7 ops/sec) [+55.3%]
Did 35000 TrustToken-Exp0-Batch1 finish_redemption operations in 2026970us (17267.2 ops/sec) [-0.1%]
Did 504 TrustToken-Exp0-Batch10 generate_key operations in 2086204us (241.6 ops/sec) [+56.9%]
Did 144 TrustToken-Exp0-Batch10 begin_issuance operations in 2084670us (69.1 ops/sec) [+1.2%]
Did 16 TrustToken-Exp0-Batch10 issue operations in 2008793us (8.0 ops/sec) [+71.1%]
Did 14 TrustToken-Exp0-Batch10 finish_issuance operations in 2033577us (6.9 ops/sec) [+76.2%]
Did 12026000 TrustToken-Exp0-Batch10 begin_redemption operations in 2000018us (6012945.9 ops/sec) [-1.2%]
Did 483 TrustToken-Exp0-Batch10 redeem operations in 2056418us (234.9 ops/sec) [+55.5%]
Did 35000 TrustToken-Exp0-Batch10 finish_redemption operations in 2046766us (17100.1 ops/sec) [-1.6%]

Did 1239 TrustToken-Exp1-Batch1 generate_key operations in 2060737us (601.2 ops/sec) [+57.5%]
Did 3675 TrustToken-Exp1-Batch1 begin_issuance operations in 2085293us (1762.3 ops/sec) [+0.1%]
Did 420 TrustToken-Exp1-Batch1 issue operations in 2008121us (209.2 ops/sec) [+65.1%]
Did 378 TrustToken-Exp1-Batch1 finish_issuance operations in 2077226us (182.0 ops/sec) [+67.5%]
Did 12783000 TrustToken-Exp1-Batch1 begin_redemption operations in 2000134us (6391071.8 ops/sec) [+0.7%]
Did 1197 TrustToken-Exp1-Batch1 redeem operations in 2056802us (582.0 ops/sec) [+55.1%]
Did 35000 TrustToken-Exp1-Batch1 finish_redemption operations in 2030955us (17233.3 ops/sec) [-0.6%]
Did 1260 TrustToken-Exp1-Batch10 generate_key operations in 2095507us (601.3 ops/sec) [+57.5%]
Did 357 TrustToken-Exp1-Batch10 begin_issuance operations in 2029693us (175.9 ops/sec) [+0.2%]
Did 42 TrustToken-Exp1-Batch10 issue operations in 2050856us (20.5 ops/sec) [+67.6%]
Did 36 TrustToken-Exp1-Batch10 finish_issuance operations in 2027488us (17.8 ops/sec) [+70.4%]
Did 12140000 TrustToken-Exp1-Batch10 begin_redemption operations in 2000070us (6069787.6 ops/sec) [-4.4%]
Did 1210 TrustToken-Exp1-Batch10 redeem operations in 2079615us (581.8 ops/sec) [+59.8%]
Did 34000 TrustToken-Exp1-Batch10 finish_redemption operations in 2052918us (16561.8 ops/sec) [-4.8%]

Change-Id: Idd51d7e1d18f3b94edc4105e68fd50b5f44d87cd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41104
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-07 17:10:36 +00:00
David Benjamin ce1665b825 Batch inversions in Trust Tokens.
The DLEQ and DLEQOR proofs require converting many Jacobian points to
affine, some multiple times. The inversions involved can be batched.

This buys us a +5-8% improvement in token issuance speed. issue and
finish_issue should each only perform two inversions per token now. We
could save an inversion per token by changing the dleq_generate and
dleq_verify function signatures, but that would complicate the likely
more valuable batched DLEQ(OR) optimization, so I've left those alone.

Before:
Did 300 TrustToken-Exp0-Batch1 generate_key operations in 2031798us (147.7 ops/sec)
Did 1449 TrustToken-Exp0-Batch1 begin_issuance operations in 2093639us (692.1 ops/sec)
Did 96 TrustToken-Exp0-Batch1 issue operations in 2044310us (47.0 ops/sec)
Did 84 TrustToken-Exp0-Batch1 finish_issuance operations in 2072137us (40.5 ops/sec)
Did 12170000 TrustToken-Exp0-Batch1 begin_redemption operations in 2000098us (6084701.8 ops/sec)
Did 315 TrustToken-Exp0-Batch1 redeem operations in 2091938us (150.6 ops/sec)
Did 35000 TrustToken-Exp0-Batch1 finish_redemption operations in 2004900us (17457.2 ops/sec)
Did 308 TrustToken-Exp0-Batch10 generate_key operations in 2067860us (148.9 ops/sec)
Did 138 TrustToken-Exp0-Batch10 begin_issuance operations in 2005706us (68.8 ops/sec)
Did 9 TrustToken-Exp0-Batch10 issue operations in 2107753us (4.3 ops/sec)
Did 8 TrustToken-Exp0-Batch10 finish_issuance operations in 2193489us (3.6 ops/sec)
Did 12046750 TrustToken-Exp0-Batch10 begin_redemption operations in 2000025us (6023299.7 ops/sec)
Did 315 TrustToken-Exp0-Batch10 redeem operations in 2091940us (150.6 ops/sec)
Did 35000 TrustToken-Exp0-Batch10 finish_redemption operations in 2008851us (17422.9 ops/sec)

Did 756 TrustToken-Exp1-Batch1 generate_key operations in 2051005us (368.6 ops/sec)
Did 3633 TrustToken-Exp1-Batch1 begin_issuance operations in 2072577us (1752.9 ops/sec)
Did 242 TrustToken-Exp1-Batch1 issue operations in 2052091us (117.9 ops/sec)
Did 210 TrustToken-Exp1-Batch1 finish_issuance operations in 2058740us (102.0 ops/sec)
Did 12477000 TrustToken-Exp1-Batch1 begin_redemption operations in 2000004us (6238487.5 ops/sec)
Did 777 TrustToken-Exp1-Batch1 redeem operations in 2084953us (372.7 ops/sec)
Did 35000 TrustToken-Exp1-Batch1 finish_redemption operations in 2028286us (17255.9 ops/sec)
Did 756 TrustToken-Exp1-Batch10 generate_key operations in 2051178us (368.6 ops/sec)
Did 357 TrustToken-Exp1-Batch10 begin_issuance operations in 2041875us (174.8 ops/sec)
Did 23 TrustToken-Exp1-Batch10 issue operations in 2026494us (11.3 ops/sec)
Did 20 TrustToken-Exp1-Batch10 finish_issuance operations in 2048478us (9.8 ops/sec)
Did 12492000 TrustToken-Exp1-Batch10 begin_redemption operations in 2000053us (6245834.5 ops/sec)
Did 777 TrustToken-Exp1-Batch10 redeem operations in 2084956us (372.7 ops/sec)
Did 36000 TrustToken-Exp1-Batch10 finish_redemption operations in 2021991us (17804.2 ops/sec)

After:
Did 315 TrustToken-Exp0-Batch1 generate_key operations in 2046638us (153.9 ops/sec) [+4.2%]
Did 1449 TrustToken-Exp0-Batch1 begin_issuance operations in 2087930us (694.0 ops/sec) [+0.3%]
Did 105 TrustToken-Exp0-Batch1 issue operations in 2071104us (50.7 ops/sec) [+8.0%]
Did 88 TrustToken-Exp0-Batch1 finish_issuance operations in 2023502us (43.5 ops/sec) [+7.3%]
Did 11847000 TrustToken-Exp0-Batch1 begin_redemption operations in 2000041us (5923378.6 ops/sec) [-2.7%]
Did 315 TrustToken-Exp0-Batch1 redeem operations in 2084116us (151.1 ops/sec) [+0.4%]
Did 35000 TrustToken-Exp0-Batch1 finish_redemption operations in 2003732us (17467.4 ops/sec) [+0.1%]
Did 315 TrustToken-Exp0-Batch10 generate_key operations in 2046863us (153.9 ops/sec) [+3.3%]
Did 138 TrustToken-Exp0-Batch10 begin_issuance operations in 2000108us (69.0 ops/sec) [+0.3%]
Did 10 TrustToken-Exp0-Batch10 issue operations in 2149283us (4.7 ops/sec) [+9.0%]
Did 8 TrustToken-Exp0-Batch10 finish_issuance operations in 2046416us (3.9 ops/sec) [+7.2%]
Did 12112000 TrustToken-Exp0-Batch10 begin_redemption operations in 2000077us (6055766.9 ops/sec) [+0.5%]
Did 315 TrustToken-Exp0-Batch10 redeem operations in 2084427us (151.1 ops/sec) [+0.4%]
Did 35000 TrustToken-Exp0-Batch10 finish_redemption operations in 2015111us (17368.8 ops/sec) [-0.3%]

Did 777 TrustToken-Exp1-Batch1 generate_key operations in 2029777us (382.8 ops/sec) [+3.9%]
Did 3654 TrustToken-Exp1-Batch1 begin_issuance operations in 2093484us (1745.4 ops/sec) [-0.4%]
Did 252 TrustToken-Exp1-Batch1 issue operations in 2024557us (124.5 ops/sec) [+5.5%]
Did 220 TrustToken-Exp1-Batch1 finish_issuance operations in 2034633us (108.1 ops/sec) [+6.0%]
Did 12659000 TrustToken-Exp1-Batch1 begin_redemption operations in 2000112us (6329145.6 ops/sec) [+1.5%]
Did 777 TrustToken-Exp1-Batch1 redeem operations in 2073783us (374.7 ops/sec) [+0.5%]
Did 35000 TrustToken-Exp1-Batch1 finish_redemption operations in 2050371us (17070.1 ops/sec) [-1.1%]
Did 768 TrustToken-Exp1-Batch10 generate_key operations in 2025482us (379.2 ops/sec) [+2.9%]
Did 357 TrustToken-Exp1-Batch10 begin_issuance operations in 2034429us (175.5 ops/sec) [+0.4%]
Did 25 TrustToken-Exp1-Batch10 issue operations in 2049293us (12.2 ops/sec) [+7.5%]
Did 21 TrustToken-Exp1-Batch10 finish_issuance operations in 2022256us (10.4 ops/sec) [+6.4%]
Did 12702000 TrustToken-Exp1-Batch10 begin_redemption operations in 2000015us (6350952.4 ops/sec) [+1.7%]
Did 777 TrustToken-Exp1-Batch10 redeem operations in 2072048us (375.0 ops/sec) [+0.6%]
Did 35000 TrustToken-Exp1-Batch10 finish_redemption operations in 2024580us (17287.5 ops/sec) [-2.9%]

Change-Id: Ia1b09cd14aa8ce0935d18033fb4bd75666a258e9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41086
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-07 16:45:06 +00:00
David Benjamin 54a59c68b7 Rearrange the DLEQ logic slightly.
The DLEQ logic needs to convert many points to affine coordinates at the
Hc computations. Rearrange things so the two happen concurrently, which
will allow us to batch the inversions.

Change-Id: I09bb053788f1555547272bf9af19b54e0fe7c325
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41085
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-05 18:55:28 +00:00
Steven Valdez 54304734eb Use token hash to encode private metadata for Trust Token Experiment V1.
Bug: 328
Change-Id: Iaf3ff1bbe2f21c622b974081281848c60a01f142
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40764
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-05-05 18:37:58 +00:00
David Benjamin 802523aa5f Introduce an EC_AFFINE abstraction.
PMBTokens ends up converting the same point to affine coordinates
repeatedly. Additionally, it converts many affine coordinates at once,
which we can batch. Introduce an EC_AFFINE type to store affine points
and move the inversion to the Jacobian -> affine conversion.

This does mean we lose the (negligible) Montgomery reduction
optimization in EC_GFp_mont. point_get_affine_coordinates no longer
breaks the EC_FELEM abstraction around Montgomery form.

Unfortunately, this complicates hardening of the callers not checking
return values because EC_AFFINE cannot represent the point at infinity
and, due to OpenSSL's API limitations, groups may not have generators
available and the generator is not affine at the type level. (EC_AFFINE
cannot represent the point at infinity.) Thus this CL:

- Tidies up some duplicate code in setting up the generator and ensures
  it always has Z = 1.
- ec_point_set_affine_coordinates hardens against unused results if the
  generator is configured. But this is ultimately an internal function.
- Retains the hardening on the public APIs by adding calls to
  ec_set_to_safe_point in two places.

This CL does not apply the optimization to Trust Tokens, only introduces
the EC_AFFINE abstraction. It additionally continues to store EC_POINTs
(used in ECDH and ECDSA) in Jacobian form. See
https://crbug.com/boringssl/326#c4 for a discussion on why this is
tricky. Those protocols are hopefully simple enough that they don't need
complexity around inversions.

Having an EC_AFFINE type will also be useful for computing custom tables
for Trust Token public keys, which gives a nice speedup.

Bug: 326
Change-Id: I11b010a33f36a15bac9939351df5205bd35cc665
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41084
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-05 16:55:18 +00:00
David Benjamin 73e0401e3d Make the fuzzer PRNG thread-safe.
We run some unit tests with multiple threads now. While that makes it no
longer deterministic, we should at least be thread-safe.

Change-Id: I5d75f2ff1ce76d0b7914cd6ea61bcf640aa085ab
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41184
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-04 18:27:17 +00:00
Adam Langley cccfb9bcf2 Disable fork-detect tests under TSAN.
TSAN can't cope with the pattern of forking and threading here and
exits with an error.

Change-Id: I3673004b62a45c5e910a4597f89764682a0b8d0a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41224
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-05-04 15:19:06 +00:00
David Benjamin aa764c46eb Introduce TRUST_TOKENS_experiment_v1.
This starts a new branch of the protocol using P-384 and draft-07 of
hash-to-curve. Mark it unstable for now as we aim to add batching and
other fixes.

Did 154 TrustToken-Exp0-Batch1 generate_key operations in 1033312us (149.0 ops/sec)
Did 748 TrustToken-Exp0-Batch1 begin_issuance operations in 1078707us (693.4 ops/sec)
Did 48 TrustToken-Exp0-Batch1 issue operations in 1030056us (46.6 ops/sec)
Did 44 TrustToken-Exp0-Batch1 finish_issuance operations in 1092816us (40.3 ops/sec)
Did 6040750 TrustToken-Exp0-Batch1 begin_redemption operations in 1000009us (6040695.6 ops/sec)
Did 154 TrustToken-Exp0-Batch1 redeem operations in 1023722us (150.4 ops/sec)
Did 18000 TrustToken-Exp0-Batch1 finish_redemption operations in 1021087us (17628.3 ops/sec)
Did 154 TrustToken-Exp0-Batch10 generate_key operations in 1032878us (149.1 ops/sec)
Did 72 TrustToken-Exp0-Batch10 begin_issuance operations in 1050908us (68.5 ops/sec)
Did 4 TrustToken-Exp0-Batch10 issue operations in 1051989us (3.8 ops/sec)
Did 4 TrustToken-Exp0-Batch10 finish_issuance operations in 1214996us (3.3 ops/sec)
Did 5987000 TrustToken-Exp0-Batch10 begin_redemption operations in 1000068us (5986592.9 ops/sec)
Did 154 TrustToken-Exp0-Batch10 redeem operations in 1037898us (148.4 ops/sec)
Did 18000 TrustToken-Exp0-Batch10 finish_redemption operations in 1024788us (17564.6 ops/sec)

Did 396 TrustToken-Exp1-Batch1 generate_key operations in 1060955us (373.2 ops/sec)
Did 1925 TrustToken-Exp1-Batch1 begin_issuance operations in 1093039us (1761.1 ops/sec)
Did 121 TrustToken-Exp1-Batch1 issue operations in 1022292us (118.4 ops/sec)
Did 110 TrustToken-Exp1-Batch1 finish_issuance operations in 1076011us (102.2 ops/sec)
Did 6322000 TrustToken-Exp1-Batch1 begin_redemption operations in 1000144us (6321089.8 ops/sec)
Did 407 TrustToken-Exp1-Batch1 redeem operations in 1087774us (374.2 ops/sec)
Did 18000 TrustToken-Exp1-Batch1 finish_redemption operations in 1031736us (17446.3 ops/sec)
Did 407 TrustToken-Exp1-Batch10 generate_key operations in 1090415us (373.3 ops/sec)
Did 187 TrustToken-Exp1-Batch10 begin_issuance operations in 1065754us (175.5 ops/sec)
Did 11 TrustToken-Exp1-Batch10 issue operations in 1005738us (10.9 ops/sec)
Did 10 TrustToken-Exp1-Batch10 finish_issuance operations in 1066494us (9.4 ops/sec)
Did 6302000 TrustToken-Exp1-Batch10 begin_redemption operations in 1000029us (6301817.2 ops/sec)
Did 407 TrustToken-Exp1-Batch10 redeem operations in 1087692us (374.2 ops/sec)
Did 18000 TrustToken-Exp1-Batch10 finish_redemption operations in 1014611us (17740.8 ops/sec)

Change-Id: I7ea9a8ab8ad48acfbf50026e251cc6e1d5b8ba7f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41069
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
2020-05-04 14:20:47 +00:00
David Benjamin 69402f33f3 Route PMBToken calls through TRUST_TOKEN_METHOD.
Change-Id: I8b87484ea94cf1f931fa66216aab4654abe26bd3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41068
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-04 13:40:46 +00:00
David Benjamin 239634da1b Introduce a TRUST_TOKEN_METHOD hook to select TRUST_TOKEN variations.
For now, it does nothing. This will make it easier to transition between
versions of the experiment while the protocol evolves.

Update-Note: Pass TRUST_TOKEN_experiment_v0() into any existing code
that now needs a TRUST_TOKEN_METHOD.

Change-Id: I434e18c794ab30545e367eb902e434e6311b7497
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41066
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-01 20:21:02 +00:00
Adam Langley ad5582985c fork_detect: be robust to qemu.
fork_detect needs to know whether |MADV_WIPEONFORK| is supported by the
kernel or not. However, current versions of qemu ignore madvise calls
and just return zero, making it seems like it's supported when it's
actually not. Therefore, try an madvise with -1 to ensure that clearly
bogus values actually produce and error before trusting the result of
calling with |MADV_WIPEONFORK|.

Change-Id: I7f72714d5794274acabd0bee0b0ac470e1933774
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41024
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-05-01 18:35:42 +00:00
David Benjamin 90bb72c6a6 Move serialization of points inside pmbtoken.c.
This reduces the number of places that know about the group and allows
us to abstract between different PMBTokens variations. Although the
abstraction isn't quite clean with the key_id in the TRUST_TOKEN
serialization, so we may need to ponder this.

Change-Id: Ia892340057025794aaf7c44a64c4d195a969715f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41065
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-01 18:16:12 +00:00
David Benjamin 090ee96bf6 Introduce PMBTOKENS key abstractions.
Start tidying up the TRUST_TOKENS/PMBTOKENS split.

Change-Id: Iabcbc864f4016dfcb22438387446b04d31b64beb
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41064
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
2020-05-01 17:52:31 +00:00
David Benjamin 17078f21a5 Fix the types used in token counts.
The number of tokens is inconsistent throughout the API. max_batchsize
is a uint16_t. max_issuance is a size_t. out_tokens_issued is a
uint8_t*. The serialization only supports up to uint16_t.

Standardize on size_t. The natural size for a count of elements is
size_t. Protocol limitations can be handled within the implementation.
Additionally, it is best not to use small types for counters in public
APIs in C/C++ because the language has implicit truncating conversions.
(Whereas code points or other enum-like values are fine because the
caller won't managed to get a 32-bit cipher suite.)

Update-Note: Fix callers of TRUST_TOKEN_ISSUER_issue to use size_t
instead of uint8_t. The max_batchsize changes should go through without
changes to the caller.

Change-Id: I9be5dd8f61abdbe5a1dbe70b8dc72d06114b1022
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41044
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-05-01 17:29:22 +00:00
David Benjamin dc06e320d8 Remove unused code from ghash-x86_64.pl.
Thanks to Brian Smith for pointing these out in
https://boringssl-review.googlesource.com/c/boringssl/+/38724.

Change-Id: I715da0778346fcc45aab19855050e18fe95a9185
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41144
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-05-01 16:01:21 +00:00
David Benjamin eeb5bb3561 Switch the P-384 hash-to-curve to draft-07.
Leave the P-521 one alone as it's part of the current trust token
experiment. But suffix all the functions by their draft until everything
stabilizes. Also remove the ref_for_testing function since we can cite
the fixed test vectors from the upstream PR.

Change-Id: Ied89d26848c8ec1f6e8414a2385d9f3e491d7fb2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41067
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-04-30 20:23:27 +00:00
Steven Valdez 6a7184066f Add hash-to-curve code for P384.
Change-Id: I34c3609641c23aed14f2324c6887250369ae8b5f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40944
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-29 17:16:17 +00:00
David Benjamin b36f52d187 Write down the expressions for all the NIST primes.
I find myself needing to look them up frequently and this is easier than
digging through https://www.secg.org/SEC2-Ver-1.0.pdf each time.

Change-Id: I4aa7cdf2c8f114a0f2ba8b9bd7ee394d3201d731
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40984
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-27 17:27:49 +00:00
Adam Langley 21aede9179 Move fork_detect files into rand/
Files in the top-level of fipsmodule/ are considered be FIPS-support
files by generate_build_files.py. However, fork_detect is different.
Rather than have more special cases in the support scripts, this change
moves fork_detect into fipsmodule/rand. It's not a perfect fit, and
maybe it could have been its own directory, but it's not bad and fixes
the build for now.

Change-Id: I875088dd458069190dade870e085865e1306f55a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40964
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-04-26 21:38:36 +00:00
David Benjamin b1086cdb12 Harden against fork via MADV_WIPEONFORK.
Linux 4.14 and up support MADV_WIPEONFORK, which can be used to reliably
and efficiently detect forks. Use it to harden the PRNG and RSA blinding
caches.

On the RSA side, we currently cache blinding values. (Alas, removing the cache
gives a *very* noticeable perf hit. There is some low-hanging fruit to trim a
few Montgomery reductions, but it didn't offset much last I toyed with it.)
Now, on Linux 4.14 and up, this cache is fork-safe.

Since not all platforms that support fork also support fork detection,
this should only be used as a hardening measure. Now, when detection is
present, BoringSSL will skip doing per-call entropy draws from the
kernel. (This might regress protection against VM cloning when no fast
RDRAND is available. However, we need to do something for AMD machines.
Hypervisors that clone VMs are going to need to signal the kernel to
wipe WIPEONFORK pages.)

Upgrade-Note: BoringSSL now calls some more syscalls on Linux. If this offends
sandboxes, let us know. We can loosen the sandbox or add a mechanism to prime
the MADV_WIPEONFORK page before entering it.

Change-Id: I6ba43951aeaa2b9b81f74f9e5a7a0ce2de0438a4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/34745
Reviewed-by: Adam Langley <alangley@gmail.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-04-26 18:31:56 +00:00
David Benjamin 14d192e930 Fix typo in comment.
Change-Id: I67a012a54a2818ec12c1829a746e2d7f796616d6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40924
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-04-24 16:01:58 +00:00
David Benjamin 21f694210c Use faster addition chains for P-256 field inversion.
Switch to the addition chains by Brian Smith in
https://briansmith.org/ecc-inversion-addition-chains-01#p256_field_inversion

The new addition chains are a bit faster when measured independently.
They aren't, however, noticeable when measured with everything else in
ECDH. Rather, the motivation is just to align fiat_p256, nistz256, and a
possible future fiat_p384 import.

Since it's free, I've included the (negligible) z^-2 optimization, but
if we ever want a z^-1 abstraction, it doesn't actually matter. In the
meantime, it replaces the (even more negligible) Montgomery conversion
optimization which is a bit less odd on the EC_FELEM abstraction. (I'm
pondering whether we want an EC_AFFINE abstraction given how the Trust
Tokens DLEQ proofs work.)

fiat_p256 (64-bit):
Before:
Did 539000 P-256 get x operations in 5007148us (107646.1 ops/sec)
Did 532000 P-256 get x and y operations in 5008736us (106214.4 ops/sec)
After:
Did 607000 P-256 get x operations in 5005225us (121273.3 ops/sec)
Did 594000 P-256 get x and y operations in 5001251us (118770.3 ops/sec)

nistz256:
Before:
Did 1472000 P-256 get x operations in 5003286us (294206.6 ops/sec)
Did 1445000 P-256 get x and y operations in 5002052us (288881.4 ops/sec)
After:
Did 1491000 P-256 get x operations in 5002524us (298049.5 ops/sec)
Did 1452000 P-256 get x and y operations in 5003193us (290214.7 ops/sec)

I haven't bothered checking in the benchmarks as those operations
standalone are largely artificial. They're a consequence of using the
same type for affine and Jacobian points.

Change-Id: I71e0d50a8712198f9cb8f68d50894d14a6091635
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40867
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-23 21:31:07 +00:00
David Benjamin 47b1e39042 Tidy up third_party/fiat.
Originally, when we imported fiat-crypto field operations, the pipeline
was in early stages and the generated code had to be manually integrated
with the rest of the curve implementation, so we moved all our
supporting code to third_party/fiat for simplicity. Over time more
supporting code, like the table generators, landed there to be next to
its callers.

fiat-crypto now generates standalone files which we #include into the
supporting code. This moves the supporting code back to the usual
location. It also updates the README.md file to reflect the new
pipeline. (Most of it was a documentation of the old pipeline, which was
much more manual.)

Change-Id: I64db7235feb6566f0d3cd4db3a7146050edaf25a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40904
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-23 19:50:07 +00:00
David Benjamin 25ab623a86 Prefix g_pre_comp in p256.c as well.
I missed a symbol.

Change-Id: I83c6828620a54eaab26cad08b1714402a2758fc0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40905
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-23 19:05:07 +00:00
David Benjamin 8bbc5e9a61 Add missing curve check to ec_hash_to_scalar_p521_xmd_sha512.
The bounds on k make this a little tricky to test, so stick an assert(0)
as that codepath should be impossible.

Change-Id: I03958ed36bff4f0b420a446c6d49eca944f45da2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40885
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-04-23 17:44:57 +00:00
David Benjamin 1d8ef2c666 Add a tool to compare the output of bssl speed.
I've been doing it by hand this whole time.

Change-Id: Ib64dcca81c33ebe7b81cd8e3d579b9fca02e1096
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40745
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-23 17:15:27 +00:00
David Benjamin 21712d52c4 Benchmark ECDH slightly more accurately.
We really need a better ECDH API in the first place, but ECDH would not
extract the y-coordinate which saves a couple multiplications. (This is
entirely unnoticeable between everything else going on in ECDH.)

Change-Id: I663554577b0cfc373067f9db4d2116a3dfbf1478
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40866
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-04-23 16:52:47 +00:00
David Benjamin c878b651ce Align remaining Intel copyright notice.
https://boringssl-review.googlesource.com/c/boringssl/+/25588/ missed
one of the files.

Change-Id: Iba3aa37f5ecd69fd35054c44cbd5f8988a05f76e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40868
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-23 15:59:37 +00:00
David Benjamin e2af857ddc Don't retain T in PMBTOKEN_PRETOKEN.
We only need r, t, and T'.

Change-Id: I736c5638c73e80c99036182fa3cd30397c33d923
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40884
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-04-23 15:17:47 +00:00
David Benjamin cbe128b3e3 Check for trailing data in TRUST_TOKEN_CLIENT_finish_issuance.
Change-Id: I2dec3ca3651c81e25370dfd7d10bd27c1803cc38
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40847
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-22 20:15:36 +00:00
David Benjamin 13d09f0527 Properly namespace everything in third_party/fiat/p256.c.
This file gets #included into other files, so we shouldn't use generic
names like 'fe'. This will let us import other fiat-crypto curves in the
future, if we want them.

Change-Id: Ie4e222729bde7e4ccd368b86fb9048a2ea4a58ac
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40824
Reviewed-by: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-22 20:04:56 +00:00
David Benjamin baca5b4fa0 Update fiat-crypto.
This pulls in the latest upstream files and reapplies our value_barrier patch.
In particular, https://github.com/mit-plv/fiat-crypto/pull/723 made 64-bit
P-256 faster!

32-bit x86, gcc
Before:
Did 3150 ECDH P-256 operations in 4027477us (782.1 ops/sec)
Did 9912 ECDSA P-256 signing operations in 4067212us (2437.1 ops/sec)
Did 3772 ECDSA P-256 verify operations in 4059197us (929.2 ops/sec)
Did 74800 Ed25519 key generation operations in 4020883us (18602.9 ops/sec)
Did 74000 Ed25519 signing operations in 4001827us (18491.6 ops/sec)
Did 21371 Ed25519 verify operations in 4024606us (5310.1 ops/sec)
Did 78000 Curve25519 base-point multiplication operations in 4051574us (19251.8 ops/sec)
Did 25133 Curve25519 arbitrary point multiplication operations in 4063280us (6185.4 ops/sec)
After:
Did 3250 ECDH P-256 operations in 4025179us (807.4 ops/sec) [+3.2%]
Did 10277 ECDSA P-256 signing operations in 4084926us (2515.8 ops/sec) [+3.2%]
Did 3895 ECDSA P-256 verify operations in 4048734us (962.0 ops/sec) [+3.5%]
Did 74480 Ed25519 key generation operations in 4002460us (18608.6 ops/sec) [+0.0%]
Did 74000 Ed25519 signing operations in 4004425us (18479.6 ops/sec) [-0.1%]
Did 21756 Ed25519 verify operations in 4038856us (5386.7 ops/sec) [+1.4%]
Did 78000 Curve25519 base-point multiplication operations in 4031991us (19345.3 ops/sec) [+0.5%]
Did 25133 Curve25519 arbitrary point multiplication operations in 4064925us (6182.9 ops/sec) [-0.0%]

x86_64, clang, OPENSSL_SMALL
Before:
Did 20090 ECDH P-256 operations in 4019408us (4998.2 ops/sec)
Did 56000 ECDSA P-256 signing operations in 4004370us (13984.7 ops/sec)
Did 23562 ECDSA P-256 verify operations in 4062283us (5800.2 ops/sec)
Did 127000 Ed25519 key generation operations in 4005053us (31709.9 ops/sec)
Did 128000 Ed25519 signing operations in 4021902us (31825.7 ops/sec)
Did 71000 Ed25519 verify operations in 4036015us (17591.6 ops/sec)
Did 132000 Curve25519 base-point multiplication operations in 4002101us (32982.7 ops/sec)
Did 93000 Curve25519 arbitrary point multiplication operations in 4023827us (23112.3 ops/sec)
After:
Did 22263 ECDH P-256 operations in 4005099us (5558.7 ops/sec) [+11.2%]
Did 61000 ECDSA P-256 signing operations in 4024810us (15156.0 ops/sec) [+8.4%]
Did 27426 ECDSA P-256 verify operations in 4038547us (6791.1 ops/sec) [+17.1%]
Did 128000 Ed25519 key generation operations in 4015033us (31880.2 ops/sec) [+0.5%]
Did 127000 Ed25519 signing operations in 4003894us (31719.1 ops/sec) [-0.3%]
Did 70000 Ed25519 verify operations in 4017446us (17424.0 ops/sec) [-1.0%]
Did 132000 Curve25519 base-point multiplication operations in 4006282us (32948.3 ops/sec) [-0.1%]
Did 93000 Curve25519 arbitrary point multiplication operations in 4025190us (23104.5 ops/sec) [-0.0%]

Change-Id: I2f705772899c701480ca0e0885e6b75dd1bb1f5d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40746
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-22 19:06:26 +00:00
David Benjamin a27ed585fa Add missing ERR_LIB_TRUST_TOKEN constants.
Also fix the numbering. ERR_LIB_USER probably ought to be last.

Change-Id: I2eb94dc129aa40b36711a7c20a9dfedf9944fc21
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40846
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-22 15:07:24 +00:00
Steven Valdez 188b65a791 Add bssl speed support for hashtocurve and trusttoken.
Change-Id: I74bee1855c593131bf1451553de6a56b4e0e8a54
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40804
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-22 03:20:44 +00:00
Steven Valdez 78987bb7bb Implement DLEQ checks for Trust Token.
Change-Id: I6f263b775aafad6616b31af59096c3b4229fe3e1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40684
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-21 13:42:50 +00:00
David Benjamin 367d64f84c Fix error-handling in EVP_BytesToKey.
This only matters on malloc failure and I think, even then,
EVP_DigestInit_ex will only fail the first time around the loop so it
wouldn't actually leak anything. Nonetheless, that should be a goto err.

Change-Id: Ieea9db387f9c16915c3a0026c6fd48036da2cfef
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40748
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-17 18:40:28 +00:00
Steven Valdez 8f3019e849 Fix Trust Token CBOR.
CBOR requires map keys to be sorted by length followed by alphabet,
but only some parsers enforce this requirement.

Change-Id: I63cad4ec27f1509704be7a755b5486b0f4baa800
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40747
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-17 16:42:58 +00:00
David Benjamin 7853619553 Match parameter names between header and source.
clang-tidy flagged this in a diff. Running a full clang-tidy would
probably reveal others, but ah well.

Change-Id: Ib004f7df4fd53b326686810c314869b35b35e547
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40749
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-17 16:37:18 +00:00
Steven Valdez 538a124d70 Trust Token Implementation.
Trust Token implementation based on PrivacyPass using the PMBToken construction.
This implementation currently omits the DLEQ proofs.

https://github.com/alxdavids/privacy-pass-ietf/blob/master/draft-davidson-pp-protocol.md
https://eprint.iacr.org/2020/072.pdf

Change-Id: If236cc8beaf33a80bdad2991c3163f9dd0cb7571
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39244
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-17 01:41:02 +00:00
Adam Langley f37eb8d6a8 Include mem.h for |CRYPTO_memcmp|
Change-Id: I3009326a5fa0c28bd3d214254e9beda4ea779833
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40744
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-04-16 21:10:07 +00:00
Adam Langley 9a798eb531 acvptool: add subprocess tests.
(Written by Dan Janni.)

Change-Id: Ice03bb3e717b361af367cce7425f43d65e79cadc
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40724
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-16 17:00:17 +00:00
Adam Langley 3c11bf53e9 Add SHA-512-256.
(Not wired up into all the signature verifiers because we don't need or
recommend that.)

Change-Id: Ia212a1f0e1c389a31d303e00a6fafb0ec3db7c71
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40704
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-15 21:23:37 +00:00
David Benjamin 9fc31378f0 Make ec_GFp_simple_cmp constant-time.
We need a constant-time point equality for two reasons. First, although
multiplication results are usually public, their Jacobian Z coordinates
may be secret, or at least are not obviously public. Second, more
complex protocols will sometimes manipulate secret points, notably
PMBTokens.

While here I've renamed the inner function to points_equal without the
flipped return value, to be less confusing.

Update-Note: This does mean that we pay a 6M+2S Jacobian comparison
where comparing two publicly affine points should cost no field
operations at all. Code which compares two EC public keys for equality
will be slightly slower. I wouldn't expect this to matter (if you
actually use the public keys, you'll pay much much more) If it does, we
can restore this optimization by keeping better track of affine vs.
Jacobian forms. See https://crbug.com/boringssl/326.

Bug: 326, chromium:1014199
Change-Id: I67c9a56bc9b66f30c0b500a29e8bf90427d89061
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40665
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-13 21:33:44 +00:00
David Benjamin f883b98cfd Tidy up CRYPTO_sysrand variants.
We can extend the inline function trick to avoid needing to add extra
wrappers to the fuzzer PRNG.

Change-Id: Ie007a4ccaf0e2d703a3710e4298a774af861d514
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40624
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-13 19:15:28 +00:00
David Benjamin 3d22c8260a Do a better job testing EC_POINT_cmp.
If EC_POINT_cmp always returns points are equal, our tests barely
notice.

Change-Id: I1a78d95af2fad3d97c2db013468d34159807ff21
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40664
Reviewed-by: Adam Langley <agl@google.com>
2020-04-13 19:02:38 +00:00
David Benjamin 2a8e294b70 Follow-up comments to hash_to_scalar.
See
https://boringssl-review.googlesource.com/c/boringssl/+/40646/3#message-ee607e82b0c62dd73a1b8a81f03acd9329cbbf02

Additionally, to be consistent with hash_to_field, we ought to use a
big-endian value. It's also probably time to have some common functions
for dealing with converting BN_ULONG[]s to and from big-endian bytes.
Coding all those free-handed is a little tedious and error-prone.

Change-Id: I6bdcd9362cee60e160e5a8eca25206b052206e1f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40647
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-10 18:35:25 +00:00
David Benjamin 28987cf081 Add a hash_to_scalar variation of P-521's hash_to_field.
DLEQ proofs for PMBTokens need a random oracle over scalars as well as
field elements. (Interestingly, draft-irtf-cfrg-voprf-03 section 5.1
does not specify as strong of requirements, but then their reference
implementation does rejection sampling, so it's unclear.)

Reusing the hash_to_field operation so hash calls use the domain
separation tag consistently with other hash-to-curve operations seems
prudent, so implement a companion function until the actual construction
solidifies.

Change-Id: I92d807bfddcca26db690cce0a3da551143c25ff3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40646
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
2020-04-10 15:37:52 +00:00
David Benjamin f9e0cda2d8 Add SSL_SESSION_copy_without_early_data.
While we could store an extra boolean along with each session in the
session cache and then disable early data on a per-socket level, that
causes SSL_early_data_reason to report confusing values. Clearing it
at the session seems simpler. Since sessions are intended to be
mutable, do this as a copy operation.

Bug: chromium:1066623
Change-Id: I599b1559b696805e330ab5c2d61e4158440daef8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40464
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-09 18:50:29 +00:00
David Benjamin 5902657734 Double-check secret EC point multiplications.
Doing a Jacobian point-on-curve check has negligible cost compared to
the point operations. We may as well perform one to add some defense
against potential bugs and such. (We already double-check RSA
operations.)

Before:
Did 40000 ECDH P-224 operations in 3014872us (13267.6 ops/sec)
Did 55000 ECDH P-256 operations in 3026351us (18173.7 ops/sec)
Did 3410 ECDH P-384 operations in 3053181us (1116.9 ops/sec)
Did 1364 ECDH P-521 operations in 3079656us (442.9 ops/sec)
Did 83000 ECDSA P-224 signing operations in 3013476us (27542.9 ops/sec)
Did 41000 ECDSA P-224 verify operations in 3073530us (13339.7 ops/sec)
Did 168000 ECDSA P-256 signing operations in 3008562us (55840.6 ops/sec)
Did 60000 ECDSA P-256 verify operations in 3038517us (19746.5 ops/sec)
Did 6169 ECDSA P-384 signing operations in 3066741us (2011.6 ops/sec)
Did 6231 ECDSA P-384 verify operations in 3054468us (2040.0 ops/sec)
Did 2418 ECDSA P-521 signing operations in 3058901us (790.5 ops/sec)
Did 2418 ECDSA P-521 verify operations in 3048765us (793.1 ops/sec)

After:
Did 39600 ECDH P-224 operations in 3001966us (13191.4 ops/sec)
Did 55000 ECDH P-256 operations in 3033098us (18133.3 ops/sec)
Did 3441 ECDH P-384 operations in 3088436us (1114.2 ops/sec)
Did 1364 ECDH P-521 operations in 3087711us (441.8 ops/sec)
Did 83000 ECDSA P-224 signing operations in 3029486us (27397.4 ops/sec)
Did 40000 ECDSA P-224 verify operations in 3005452us (13309.1 ops/sec)
Did 168000 ECDSA P-256 signing operations in 3011387us (55788.2 ops/sec)
Did 60000 ECDSA P-256 verify operations in 3030343us (19799.7 ops/sec)
Did 6076 ECDSA P-384 signing operations in 3023469us (2009.6 ops/sec)
Did 6231 ECDSA P-384 verify operations in 3056138us (2038.8 ops/sec)
Did 2418 ECDSA P-521 signing operations in 3057375us (790.9 ops/sec)
Did 2449 ECDSA P-521 verify operations in 3083418us (794.2 ops/sec)

Change-Id: Icedc51e340c8f3a21f96a535395814575e0c89b2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40592
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-09 18:11:29 +00:00
David Benjamin d2c5b7da2f Make ec_felem_equal constant-time.
This doesn't fix any particular issue, but we may as well use
the constant-time comparison to be more robust.

Change-Id: I96dffce7fe153a7dd4eec226a6b42dcea240c3f1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40591
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-09 15:45:09 +00:00
David Benjamin 0f86c142a7 Fix hash-to-curve comment.
511S + 3M isn't even enough operations to get up to 2^519-1. I dropped a
a bunch of terms. (We can get up to 2^512-1 with 511S + 9M. Then an
additional 7S + 3M finishes it up.)

Change-Id: Ibb1bc3491dfb09ab8a917498e99deb66e4894cf0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40644
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-09 15:32:38 +00:00
David Benjamin f20772cc0a Make ec_GFp_simple_is_on_curve constant-time.
This function (by way of EC_POINT_is_on_curve) is used by callers in two
places:

- To check the affine result of decoding a point. (This is no longer
  necessary because we'll always do it internally, but folks still do
  it.)

- To check the Jacobian result of a multiplication as fault protection.
  (Tink does this. We should probably do it in the library.)

That function's implementations of affine and Jacobian checks are mostly
constant-time, but branching between the two isn't. Since the difference
is small (2S + 1M vs 2S + 3M) compared to what one would be doing with
an affine point (point multiplication), this probably isn't worth
worrying about. Conservatively do the Jacobian check so folks like Tink
aren't accidentally introducing side channels.

Change-Id: I3140167868e027004906293df547add43ae40552
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40590
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-09 15:03:48 +00:00
David Benjamin a49c617197 Implement draft-irtf-cfrg-hash-to-curve-06.
This implements hash-to-curve for P-521, which is needed by the
PMBTokens construction in https://eprint.iacr.org/2020/072.pdf. It is
only an internal function for now, operating on EC_RAW_POINT, so that
PMBTokens can avoid allocating EC_POINTs everywhere. If we ever have a
need to expose this outside, we can add an EC_POINT wrapper (hopefully
by then the draft will be stable).

Note this implements two versions of the function due to a spec issue in
P521_XMD:SHA-512_SSWU_RO_. One of them only exists to test against the
original test vectors. See
https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/issues/237

Bug: chromium:1014199
Change-Id: I7207d1bcb8b20f7111c2ffb40e2794ad2d3d0000
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40589
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-08 22:18:51 +00:00
Adam Langley 4143943085 Update list of tested SDE configurations.
This is taken from the help output of the current version of SDE.

Change-Id: I0513088a52d6692dd419f323b72411e107ed9636
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40584
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-08 18:45:11 +00:00
Adam Langley 7a22a65098 Only draw from RDRAND for additional_data if it's fast.
We seek to incorporate entropy into every |RAND_bytes| call to avoid
problems with fork() and VM cloning. However, on some chips, RDRAND is
significantly slower than a system call thus crushing the performance of
|RAND_bytes|.

This change disables use of RDRAND for this opportunistic draw for
non-Intel chips. BoringSSL will then fall back to either the OS, or
nothing (if fork-unsafe mode has been set).

RDRAND is still used for seeding the PRNG whenever it is available.

This now adds a new blocking case: RDRAND may be used for seeding, but
the syscall to get additional_data was still blocking. Previously that
didn't matter because, if a syscall was used to get additional_data,
then a blocking one had already been used to seed. Thus the syscall for
additional_data is now non-blocking.

Also, we had both |hwrand| and |rdrand| names hanging around. We don't
support entropy instructions other than RDRAND, so unify around |rdrand|
naming. If we ever do add support for more we can properly abstract at
that time.

Change-Id: I91121b270a2ebc667543dad1324f37285daad893
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40565
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-08 18:29:21 +00:00
David Benjamin ea53011c6e Generalize bn_from_montgomery_small.
Montgomery reduction works when the input is at most N*R (N^2 is a
tighter bound that's easier to describe and usually suffices). This is
useful when reducing product-sized values. In particular,
hash-to-curve's hash_to_field function requires a reduction. Generalize
this so we can implement it with Montgomery reduction.

Bug: chromium:1014199
Change-Id: I1a07f9b94823742384a98c0c6fecdedfe5240b7b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40588
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-08 00:40:10 +00:00
David Benjamin ad5e3e3597 Remove BIGNUM from uncompressed coordinate parsing.
Compressed coordinates still use BIGNUM. I've moved the curve check to
an EC_FELEM-based ec_point_set_affine_coordinates and implemented a
tighter one than ec_GFp_simple_is_on_curve, which currently needs to
branch on Jacobian vs. affine and potentially leaks information. (A
later CL will make it conservatively always perform a Jacobian check.)

The Trust Tokens implementation will eventually need to deserialize
points, so this avoids needing to allocate EC_POINTs everywhere.
Likewise if we ever get around to adding a better ECDH, this will let us
avoid pulling in BIGNUMs.

Bug: chromium:1014199, 242
Change-Id: I93162ba3680d38cb3c0eacff1eb8f42a445246ea
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40587
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-07 23:46:10 +00:00
David Benjamin 58add794d9 Add EC_RAW_POINT serialization function.
This avoids some unnecessary EC_POINT allocations in the in-progress Trust
Tokens implementation.

Bug: chromium:1014199
Change-Id: I64e1fca61d111eacec02648e68972be30fd5a48f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40586
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-07 23:14:30 +00:00
David Benjamin 1d43e57c30 Base EC_FELEM conversions on bytes rather than BIGNUMs.
It is tricky to create EC_FELEMs right now. This will simplify making them.

Change-Id: Icde518efed61381004e2e5569a45d653af48ca2a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40585
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-07 23:10:10 +00:00
David Benjamin 47a6f5b4bf runner: Replace supportsVersions calls with allVersions.
Save a few lines.

Change-Id: I9e3bdd00e31d5c832c29df68be0207e13a36fc8e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40604
Reviewed-by: Nick Harper <nharper@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-07 23:06:10 +00:00
Nick Harper e8434d304c Enable QUIC for some perMessageTest runner tests
Change-Id: I7b944a5456e04a2fb1b0248a020d288065064043
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40304
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-07 22:51:10 +00:00
David Benjamin b65e630ec0 Move BN_nnmod calls out of low-level group_set_curve.
group_set_curve is called when instantiating the built-in curves and
when creating arbitrary curves. The former has non-NULL BN_CTXs and
fully reduced inputs. Move the logic for this to the deprecated
EC_GROUP_new_curve_GFp function so it can be dropped from most binaries.

Change-Id: I5ff60d6d51acb79fbcb32588e6324a5b2627b6d2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40544
Reviewed-by: Adam Langley <agl@google.com>
2020-04-07 20:54:45 +00:00
David Benjamin bd1fa86feb Clean up various EC inversion functions.
This fixes two issues. First, we have been lax about whether the
low-level inversion functions fail on zero input or output zero. Fix the
documentation and call the latter inv0 or inverse0 to match the
terminology used in draft-irtf-cfrg-hash-to-curve. (Although we may not
actually need inv0 given the optimization in D.2.)

This has no actual effect because the functions were only used in
contexts where the inputs were already guaranteed to be non-zero. Still,
we should be consistent here.

Second, ec_scalar_inv_montgomery and ec_scalar_inv_montgomery_vartime
claim to perform the same operation, but they do not. First, one
computed inv0 and the other computed inv (except only in some
implementations, so fix it to be consistent). Second, the former
computes inverses in the Montgomery domain, while the latter converts to
the Montgomery domain and then inverts. Rename it to
ec_scalar_to_montgomery_inv_vartime, which is... questionably
understandable but at least looks different.

Change-Id: I9b4829ce5013bdb9528078a093f41b1b158df265
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40526
Reviewed-by: Adam Langley <agl@google.com>
2020-04-07 20:28:59 +00:00
David Benjamin 243a29241c Start to organize ec/internal.h a little.
Change-Id: I1de8ca164641d1e3d1fc36246205a7c0e60e0034
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40525
Reviewed-by: Adam Langley <agl@google.com>
2020-04-07 19:34:55 +00:00
Adam Langley 12840915a1 Fix CFI for AVX2 ChaCha20-Poly1305.
When running ABI tests on an AVX2-enabled system, they flag the
ChaCha20-Poly1305 assembly. The issue appears pretty simple: the code
has chunks of code after the mainline `ret` instruction the there's a
CFI directive that undoes the adjustments for restoring registers, but
it only accounts for six saved registers and there are actually seven.

At least, with this, the ABI tests are happy.

Change-Id: Ia6d1d89f564148db43852b245916a8c2cdfb1e6b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40564
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-07 19:33:30 +00:00
David Benjamin 300ef4767d Remove unused function prototype.
This function was removed in
https://boringssl-review.googlesource.com/c/boringssl/+/33065.

Change-Id: Ib8adefeabafa58e22e1b0fdd406f73c234c2e5e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40524
Reviewed-by: Adam Langley <agl@google.com>
2020-04-07 19:17:12 +00:00
Nick Harper af6bfbee47 Enable more runner tests for QUIC
Change-Id: Id1922197c5218460210e6404ad60b60afc591984
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40284
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-04-06 18:51:17 +00:00
Nick Harper 72cff81939 Require QUIC method with Transport Parameters and vice versa
Bug: 296, 322

Change-Id: I297f53674ee7177f61d75695f47b5caeed78bd17
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40384
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-03 21:52:34 +00:00
Adam Langley ee2660203b acvptool: support non-interactive mode.
Most people won't need the interactive mode and it's use of x/crypto can
be problematic in some contexts.

Change-Id: I33e0178726ee485f3967c0b71c9d538524af9286
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40504
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-02 17:00:33 +00:00
Nick Harper 6bfd25c755 Add is_quic bit to SSL_SESSION
This bit is used to prevent cross-protocol resumption between QUIC and
TLS-over-TCP.

Bug: 221
Change-Id: I8ab5341f00ae96c0a5f7ac3999f61edc7cbeca1c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40444
Commit-Queue: Nick Harper <nharper@chromium.org>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-01 21:38:22 +00:00
David Benjamin d5aae81fb7 Update SDE.
Change-Id: I7f5209dff570b1b2efd8d1d53ece818219bbf98c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40470
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-01 18:43:51 +00:00
David Benjamin 7c719d1246 Update tools.
This skips vs_toolchain.py because Chromium is now using VS2019, but we're
still testing 2015 and 2017.

Change-Id: Ib46eba76c8a3309d82be6e88e2baa4d8a93d222a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40469
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-01 18:21:41 +00:00
David Benjamin cdc5c184b3 Add simpler getters for DH and DSA.
These come from OpenSSL 1.1.1. I don't think any third-party code is
using them yet, but OpenSSL 1.1.0 is EOL, so newer code may use them and
they're much more convenient when porting over existing uses of DH and
DSA.

Bug: 325
Change-Id: I767496da4b458a3871dea23a1405b1e7e40b3de5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40484
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-04-01 18:01:12 +00:00
Adam Langley 0cf14d3ec8 Don't define default implementations for weak symbols.
See https://github.com/facebook/folly/blob/d72b38e4aa7a42d9ff49705020e0916851d0e3cc/folly/memory/Malloc.h#L89-L97

This should work as well and be more robust to the pattern used in
Folly. The branch-predictor in modern CPUs probably makes it equally
fast.

Change-Id: I65b115c16d103b8a5492354411b55f3ef906b097
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40405
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-01 16:18:51 +00:00
Adam Langley 732b70ee20 Don't automatically run all tests for ABI testing.
We have good coverage for individual functions now and this makes
running tests when building for shared libraries more complex.

Change-Id: Ie69d234e1eed04e341b5192e174c4dae553c8706
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40404
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-01 15:20:21 +00:00
Adam Langley 577eadc424 Fix test build with recent Clang.
Some configurations of Clang hate not using a reference in a C++
range-for loop.

Change-Id: I90abf99625df4bbb67e835411bd85d995252beae
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40471
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-04-01 14:49:21 +00:00
David Benjamin 141062fe7f Remove LCM dependency from RSA_check_key.
Instead of checking d * e = 1 (mod lcm(p-1, q-1)), we can separately
check d * e = 1 (mod p-1) and d * e = 1 (mod q-1). This drops an LCM
dependency from key import and is 2x faster.

(Our constant-time LCM implementation can probably be faster if we
tried, but now it's only used in RSA keygen, so it doesn't matter much.
It's also using the unoptimized constant-time division, which is
probably the next target if we decide we care about speeding this up.)

Before:
Did 6768 RSA 2048 checking operations in 3015824us (2244.2 ops/sec)
Did 5610 RSA 2048 signing operations in 3033396us (1849.4 ops/sec)
Did 1953 RSA 4096 checking operations in 3060828us (638.1 ops/sec)
Did 817 RSA 4096 signing operations in 3021092us (270.4 ops/sec)
After:
Did 13175 RSA 2048 checking operations in 3090576us (4263.0 ops/sec)
Did 5610 RSA 2048 signing operations in 3032966us (1849.7 ops/sec)
Did 3720 RSA 4096 checking operations in 3085971us (1205.5 ops/sec)
Did 820 RSA 4096 signing operations in 3027312us (270.9 ops/sec)

Bug: 316
Change-Id: Ie29554c02d31f586dd0f8bdee03a227f1d5dc916
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40146
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-03-31 23:11:26 +00:00
David Benjamin ce9b8737cb Simplify bn_sub_part_words.
This function does not need to be so complex. The bulk of
the work is done by bn_sub_words. The unrolled loop is only used when
bn_sub_part_words is called in different-length inputs.

bn_sub_part_words is itself only called from bn_abs_sub_consttime and
bn_mul_part_recursive. bn_abs_sub_consttime is used to compute p - q in
RSA key generation so it never sees different-width inputs.
bn_mul_part_recursive is called from bn_mul_impl if all of the following
are true:

- Both inputs are at least 16 words long (1024 bits on 64-bit platforms
  and 512 bits on 32-bit).

- The two inputs are within one word from each other.

- The length of the larger input is one more than a power of two.

The first condition rules out all EC configurations except P-521 on
32-bit platforms. The EC code uses bn_mul_mont assembly if available, so
this only affects non-x86 and non-ARM 32-bit architectures. Building for
32-bit x86 without assembly shows no significant change:

Before:
Did 88 ECDH P-521 operations in 1014591us (86.7 ops/sec)
Did 165 ECDSA P-521 signing operations in 1066428us (154.7 ops/sec)
Did 150 ECDSA P-521 verify operations in 1001749us (149.7 ops/sec)
After:
Did 90 ECDH P-521 operations in 1045905us (86.0 ops/sec)
Did 165 ECDSA P-521 signing operations in 1071189us (154.0 ops/sec)
Did 154 ECDSA P-521 verify operations in 1050509us (146.6 ops/sec)

RSA does meet the first condition, but the third condition rules out all
common RSA sizes, with one quirk: RSA_check_key uses the non-normalized
BIGNUMs, but RSA_check_key is not called as part of private key
operations. (https://crbug.com/boringssl/316 discusses what to do about
RSA longer term. It's kind of a mess right now.)

Bug: 314
Change-Id: I0bd604e2cd6a75c266f64476c23a730ca1721ea6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40145
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-03-31 22:56:39 +00:00
David Benjamin 8b4fa1b6b5 No-op commit to test Windows SDE bots.
Change-Id: I10210ed7f4a40925f68383d16ec619a2cf43308f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40468
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-03-31 22:27:03 +00:00
Adam Langley 6c17797205 ABI-test each AEAD.
This keeps coverage for some assembly once we stop ABI testing by
default.

Change-Id: I2937a2961c19de560cb63e180646eb0e7d59d4ec
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40424
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-03-31 16:16:44 +00:00
Wiktor Garbacz 9ae40ce9ad Add memory tracking and sanitization hooks
Intended use is sanitization of BoringSSL allocations.

Change-Id: Ia577f944d19e5b0b77373fedd0970e2c0c97cd21
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39824
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-03-25 17:45:13 +00:00
David Benjamin 5cd0724ecb Add X509_STORE_CTX_get0_chain.
In OpenSSL 1.1.x, the preferred spelling of X509_STORE_CTX_get_chain is
X509_STORE_CTX_get0_chain.

Change-Id: I20281c7ae86371a72ac70fb9a8719f4810e0747c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40366
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-03-24 01:51:30 +00:00
David Benjamin 0064c290d1 Add DH_set_length.
OpenSSH uses this function.

Change-Id: I73c4c1647f61824f771022606f95bff7f6d3d77a
Update-Note: Set HAVE_DH_SET_LENGTH in OpenSSH.
Bug: 325
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40365
Reviewed-by: Adam Langley <agl@google.com>
2020-03-23 23:30:01 +00:00
David Benjamin dea1d44988 Static assert that CRYPTO_MUTEX is sufficiently aligned.
Bug: 325

Change-Id: I55d4d7fcb91602c8d2a371be5011e1a5df157819
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40364
Reviewed-by: Adam Langley <agl@google.com>
2020-03-23 23:28:24 +00:00
Yannic Bonenberger 7fe639cc2d [bazel] Format toplevel BUILD file with buildifier
This change was generated with
  buildifier -type build -lint=fix -warnings=all util/BUILD.toplevel

Change-Id: I4200fb484ec205c37abcb9b657c4ce74796a411c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40324
Reviewed-by: Adam Langley <agl@google.com>
2020-03-23 14:51:06 +00:00
Adam Langley 964256d066 Add |SSL_CTX_get0_chain|.
This is the getter counterpart to |SSL_CTX_set_chain_and_key|. There's
no |SSL*| because a) we didn't need it and b) then you have to worry
about config discarding and it doesn't end up being very useful.

Change-Id: Iba75d0165d7e555d0f793687b1f5e1e6c6f7c738
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40264
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-03-19 22:53:55 +00:00
David Benjamin 5298ef99bf Configure QUIC secrets inside set_{read,write}_state.
set_write_state flushes buffered handshake data, and we should finish
writing to a level before moving on to the next one.

I've moved the callback into set_{read,write}_state to ensure we still
update read_level and write_level after installing secrets, since that's
how we decide what level to write things and we should never write
alerts with keys we don't have. (I believe the only way this can come up
is if the QUIC callback itself fails, but it still seems prudent to
defer updating the levels.)

This does unfortunately mean a goofy secret_for_quic parameter, though
it is arguably more "correct" in that QUIC would ideally be a third
SSL_PROTOCOL_METHOD, rather than escape hatches over TLS. Probably a
cleaner abstraction would be for set_read_state and set_write_state to
take the secret and derive an SSLAEADContext internally.

Update-Note: See b/151142920#comment9
Change-Id: I4bbb76e15b5d95615ea643bccf796db87fae4989
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40244
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-03-16 16:45:10 +00:00
Nick Harper 80ddfc7d1b Allow setting QUIC transport parameters after parsing the client's
Our server code (unfortunately) conditions its transport parameters
based on the client's transport parameters. Instead of using
hs->config->quic_transport_params to check whether QUIC is in use, this
replaces it with ssl->quic_method.

Change-Id: I6817e9f674a70f4568b0c469c96dfdf1c1c91709
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40224
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-03-13 20:04:56 +00:00
Adam Langley 959c76d928 Fix comment for |BORINGSSL_self_test|.
The hash-based omission of the self tests for Android was moved around,
but the comment wasn't updated to match.

Change-Id: I66c3b4e9b48df00e8134cee3feb72469f92d51a4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40184
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-03-11 18:23:46 +00:00
Steven Valdez 0b710a305b Trust Token Key Generation.
Trust Token is a new protocol to issue and redeem provably anonymized
tokens. To allow for development of key storage/management for Trust
Token, this CL provides the function to generate Trust Token keys.

Bug: chromium:1014199
Change-Id: If764e027b202f07be13c64f7be66dfaff71c45e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40064
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-03-04 21:16:08 +00:00
David Benjamin 1e859054c3 Revise QUIC encryption secret APIs.
The original API separated when keys were exported to QUIC from when
they were "active". This means the obligations on QUIC are unclear. For
instance we added SSL_quic_read_level and SSL_quic_write_level to
capture when keys were active, yet QUICHE never used them anyway. It
would be better to defer releasing keys to when they are needed.

In particular, we should align our API with the guidelines in
https://github.com/quicwg/base-drafts/issues/3173.

This means we need separate read and write callbacks, which
unfortunately means the invariants around ACKs must now be covered in
prose.

We'll likely remove SSL_quic_read_level and SSL_quic_write_level in a
later CL as QUIC has no need to know this anymore. (It should simply
feed handshake data to BoringSSL as it sees it and, if we reject it,
report a suitably error.) The notion of a "current" encryption level is
a little odd given the interaction between 0-RTT and
ServerHello..Finished ACKs.

Update-Note: This is an incompatible change to SSL_QUIC_METHOD.
BORINGSSL_API_VERSION can be used to distinguish the two revisions.

Bug: 303
Change-Id: I6c9dca1ae156d26a80c366a4ba969dcb04e65349
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40127
Reviewed-by: Nick Harper <nharper@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-03-03 17:15:15 +00:00
David Benjamin bfe527fa35 Fix ec_point_mul_scalar_public's documentation.
At the time the comment was written, the secret multiplication operation
hadn't been split yet.

Change-Id: Idd283461c357b47e91b73fac489d1828c4ce2a0c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40065
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-03-03 17:09:35 +00:00
David Benjamin 2fb729d4f3 Don't infinite loop when QUIC tests fail.
Change-Id: I33714c68ab8ba841c614afd2ea9a57a6e9b8c27a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40126
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2020-03-02 18:57:19 +00:00
David Benjamin 44099d5925 Tidy up transitions out of 0-RTT keys on the client.
This change does two things. First, it funnels the transition out of
0-RTT into one function so that, later, when QUIC releases keys in
set_(read|write)_state, we can handle the QUIC quirks better.

Second, it switches to handshake (or initial) keys as soon as 0-RTT is
closed. In particular, if EncryptedExtensions reports a 0-RTT reject, we
switch keys before processing Certificate. This way, if we then reject
the server certificate, we send the alert with keys the server can read.

If there is an error in EncryptedExtensions or earlier, we do not know
whether the server is expecting 0-RTT-encrypted alerts or
handshake-encrypted alerts, so we cannot reliably send an alert. This is
fine because all such error cases are server implementation bugs and
alerts are purely a debugging courtesy. However, after a 0-RTT reject,
we may reject the Certificate message due to local policy, in which case
the certificate error alerts make more sense.

Bug: 303
Change-Id: I4c4bc9c8ab2c2ecb89e20141518e1b7ea7b39af3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40125
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-03-02 18:29:59 +00:00
David Benjamin 3280287c06 Remove bn_sub_part_words assembly.
The assembly only existed for 32-bit x86, which is much less relevant
these days. It's also just a pile of ADDs, ADCs, etc., which compilers
should be able to figure out by now.

This frees us up to clean up that function, including the weird cl/dl
calling convention. No noticeable difference in RSA benchmarks:

Before:
Did 224 RSA 2048 signing operations in 1006100us (222.6 ops/sec)
Did 9240 RSA 2048 verify (same key) operations in 1078563us (8567.0 ops/sec)
Did 8541 RSA 2048 verify (fresh key) operations in 1064996us (8019.7 ops/sec)
Did 32 RSA 4096 signing operations in 1052851us (30.4 ops/sec)
Did 2365 RSA 4096 verify (same key) operations in 1093337us (2163.1 ops/sec)
Did 2222 RSA 4096 verify (fresh key) operations in 1090037us (2038.5 ops/sec)

After:
Did 231 RSA 2048 signing operations in 1018908us (226.7 ops/sec)
Did 9394 RSA 2048 verify (same key) operations in 1095548us (8574.7 ops/sec)
Did 8525 RSA 2048 verify (fresh key) operations in 1062449us (8023.9 ops/sec)
Did 32 RSA 4096 signing operations in 1050236us (30.5 ops/sec)
Did 2376 RSA 4096 verify (same key) operations in 1098509us (2162.9 ops/sec)
Did 2233 RSA 4096 verify (fresh key) operations in 1094724us (2039.8 ops/sec)

Bug: 314
Change-Id: I86a27b2550ab8bec2a9930cc509f4c29d6036b35
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40144
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-02-28 17:56:19 +00:00
David Benjamin b092192965 Keep the encryption state and encryption level in sync.
This is a little bit of internal cleanup. The original intent was so
QUIC could install secrets in set_(read|write)_state, but that was
somewhat annoying, so I've left it just before the call for now.

There is one TLS 1.3 state transition which doesn't carry an encryption
level: switching from 0-RTT keys back to unencrypted on an HRR-based
0-RTT reject. The TCP code doesn't care about write_level and the QUIC
code is currently fine because we never "install" the 0-RTT keys. But we
should get this correct.

This also opens the door for DTLS 1.3, if we ever implement it, because
DTLS 1.3 will need to know which level it is to handle 0-RTT keys funny.
(Clients sending 0-RTT will briefly have handshake and 0-RTT write keys
active simultaneously.)

QUIC has the same property, but we can fudge it because only the caller
is aware of this.

Change-Id: Ia76d787e1b96a058d9818948b6d9a051e8592207
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40124
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-02-24 22:16:24 +00:00
Shelley Vohr 6432bb46ab Add ECDSA_SIG_get0_r and ECDSA_SIG_get0_s.
OpenSSL 1.1.1 added some more convenient versions of ECDSA_SIG_get0.
Node.js uses them.

Change-Id: I425e8a0c2e43c34130f30d902090b839f1a67186
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40044
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-18 22:08:35 +00:00
Adam Langley 472d91c39c Fix a couple of comment typos.
Thanks to Tobias Thierer for pointing these out.

(No semantic change.)

Change-Id: Ia191da6353a11b090201adf813e2ca271acaff2e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40104
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-18 20:36:28 +00:00
David Benjamin a12a2497ff Const-correct various X509_NAME APIs.
Half of them were marked const and half weren't.

Change-Id: Ia9135f743b06f07aafac8655ded84d01e59cf481
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39764
Reviewed-by: Adam Langley <agl@google.com>
2020-02-17 17:46:12 +00:00
Adam Langley 7940ed1f30 Ignore old -enable-ed25519 flag.
Change 1766935f76 removed this flag but it's useful if bssl_shim ignores
it to reduce noise in cross-version testing. This can be dropped in
three months once the old versions have aged out.

Change-Id: I73f2bebeb5e8c178253fbb6915026e06b6ad58bc
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40084
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-14 23:50:28 +00:00
Adam Langley f1efbc8f8b Provide __NR_getrandom fillins in urandom test too.
The urandom test added in 3e502c84f0 assumed that __NR_getrandom was
defined by the system's headers, but urandom.c doesn't. This change
pulls the fills for that system call into a common header that's used by
both.

Change-Id: I71c3b9bfa69c34b320e724a4c977cd63163cbdec
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40067
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-02-14 19:14:38 +00:00
David Benjamin aadb46369a Skip RSATest.DISABLED_BlindingCacheConcurrency in SDE.
The SDE bot has started developing flakes with that many threads.
(Unclear if it is due to SDE or running too many copies of the test
in parallel.)

Change-Id: I0081b6d75882b946bdccee5405dc688d0035d565
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40066
Reviewed-by: Adam Langley <agl@google.com>
2020-02-14 18:39:56 +00:00
David Benjamin 754d4c99c8 Fix client handling of 0-RTT rejects with cipher mismatch.
Servers can only accept 0-RTT if the ciphers match. If they reject
0-RTT, however, they may change the cipher suite and even the PRF hash.
This is tricky, however, because the 0-RTT accept or reject signal comes
in EncryptedExtensions, which is *after* the new cipher suite is
installed. (Although a client could infer 0-RTT is rejected based on the
cipher suite if it wanted.)

While we correctly handled the PRF hash switch, we get the cipher suite
mixed up due to dependency on SSL_get_session and incorrectly decrypt
EncryptedExtensions. Fix this and add some tests.

Change-Id: Ia20f2ed665cf601d30a38f0c8d4786c4c111019f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40005
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-02-14 17:20:17 +00:00
David Benjamin 83ea777db5 runner: Tidy up 0-RTT support.
earlyCipherSuite is a remnant of early exporters, which we've since
removed. Also runner should perform the cipher suite matching check for
0-RTT.

Change-Id: Ia6dc2ff6cf7072d94820e8755acd555037c557f1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40004
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-02-14 16:44:37 +00:00
David Benjamin 0dc70e462c Add X509_getm_notBefore and X509_getm_notAfter.
This functions were added in OpenSSL 1.1.0.

Change-Id: I1ee78ba124534d6e3e47edf75c0b4fed51388a6e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40024
Reviewed-by: Adam Langley <agl@google.com>
2020-02-14 16:06:40 +00:00
David Benjamin 0c30649ba6 Clean up TLS 1.3 handback logic.
There's no need to treat the 1-RTT and 0-RTT handback flows differently.
This aligns the 1-RTT handback with the 0-RTT point. This consistently
installs the decryption keys in the state machine after handback rather
than while applying the handback.

Update-Note: This changes the serialization format for TLS 1.3 split
handshakes, which were only just added.

Change-Id: I0e109cb8d9ecd3c8658dfa26059cbe0139f82eed
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39988
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Matt Braithwaite <mab@google.com>
2020-02-13 19:57:57 +00:00
David Benjamin f9cc26f9c1 Require handshake flights end at record boundaries.
The TLS handshake runs over a sequence of messages, serialized onto a
stream, which is then packetized into records, with no correlation to
message boundaries.

TLS messages may span records, so a TLS implementation will buffer up
excess data in a record for the next message. If not checked, that next
message may a round-trip or even a key change later. Carrying data
across a key change has security consequences, so we reject any excess
data across key changes (see ChangeCipherSpec synchronization tests and
(d)tls_set_read_state). However, we do not currently check it across
network round trips that do not change keys.

For instance, a TLS 1.2 client may pack part of ClientKeyExchange (the
first byte, at least, is deterministic) into the ClientHello record,
before even receiving ServerHello. Most TLS implementations will accept
this.

However, the handback logic does *not* serialize excess data in hs_buf.
There shouldn't be any, but if the peer is doing strange things as
above, that data will get silently dropped. The way TLS 1.3 0-RTT
handback logic works (the key isn't installed until after handback),
this data is even silently dropped though there is a key change.

To keep all our behavior consistent, check for unprocessed handshake
data at the end of each flight and reject it. Add a bunch of tests.

Update-Note: If the peer packs data across handshake flights, or packs
HelloRequest into the same record as Finished, this will now be an
error. (The former is pathologically odd behavior. The latter is also
rejected by Schannel and also odd.)

Change-Id: I9412bbdea09ee7fdcfeb78d3456329505a190641
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39987
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-02-13 19:30:40 +00:00
David Benjamin 21a879a78a Delete unreachable DTLS check.
It is impossible for us to have an unconsumed ChangeCipherSpec message
in dtls_has_unprocessed_handshake_data.
dtls_has_unprocessed_handshake_data is only called in
dtls1_set_read_state and, in DTLS 1.2 and earlier, we only ever switch
the cipher state immediately after consuming ChangeCipherSpec.

Remove this because later commits will check
has_unprocessed_handshake_data in more places and we have a test
(StrayChangeCipherSpec) which asserts we do tolerate arbitrarily early
ChangeCipherSpecs messages.

There may be something to be said for rejecting this (the peer would
have to be doing something weird and sending ChangeCipherSpec in the
wrong flight), but ChangeCipherSpec in DTLS is predictable and
informationless, so this is probably not worth worrying about.

Change-Id: I1bc2952c0ba5231a7f962b9f7ca4c63271ec079f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39986
Reviewed-by: Adam Langley <agl@google.com>
2020-02-11 21:47:07 +00:00
David Benjamin 82a4b2234e Rename TLS-specific functions to tls_foo from ssl3_foo.
Some of the TLS-specific functions begin with ssl3_, otherwise with
tls_. Align on tls_ since we don't implement SSL 3.0 anymore. (Plain ssl_
means common to TLS and DTLS, which is an odd backronym, but SSL_foo for
the APIs are thoroughly stuck.)

Change-Id: Ib7acffd21ee370bb9bed46789fb511d00fac24ca
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39985
Reviewed-by: Adam Langley <agl@google.com>
2020-02-11 21:38:53 +00:00
David Benjamin f6cc8ddf52 Rename ssl3_choose_cipher.
We don't support SSL 3.0 anymore. It's also file-local, so it can be
choose_cipher.

Change-Id: Idab96496eda69c7fd906aa788ac26e8d30c317d5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39984
Reviewed-by: Adam Langley <agl@google.com>
2020-02-11 21:37:39 +00:00
Matthew Braithwaite 8f299d5e03 SSL_apply_handback: don't choke on trailing data.
It may be useful for future extensibility.

Change-Id: I415095140367a44a2c8dd636998721399232c400
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39964
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-02-11 01:14:36 +00:00
Matthew Braithwaite 4f3e8212ea ssl_test: test early data with split handshakes.
This helps to clarify where SSL_set_early_data_enabled() needs to be
called: in the shim tests it was being set everywhere, which concealed
the fact that the |enable_early_data| bit was not being set by
SSL_apply_handback().

Change-Id: I35bfdc6dd43f4fa07ef79eb02e4624b59fcdda5e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39385
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-10 21:19:46 +00:00
Adam Langley 7964a1d676 Check for overflow in massive mallocs.
Hopefully it never happens, but a malloc of nearly the whole address
space should fail cleanly.

Change-Id: I82499e3236a1a485f5518b1c048899b1df3e8488
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39864
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-10 17:43:35 +00:00
David Benjamin 7e43e2e8ee Add more convenient RSA getters.
OpenSSL 1.1.0's RSA getters can be inconvenient because they return a number of
fields via output parameters. OpenSSL 1.1.1 adds individual getters for each of
the fields, which is a bit simpler. Align with them.

Note our OPENSSL_VERSION_NUMBER is still 1.1.0. Adding these functions may
cause friction with third-party packages which polyfill these functions based
on OPENSSL_VERSION_NUMBER, though none appear to be doing this right now.
Between this and TLS 1.3, we probably should switch the version to 1.1.1 at
some point anyway.

Change-Id: Iada5a0315c403cc221688af53fc4ba165d65e99c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39944
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-02-07 19:36:22 +00:00
David Benjamin 1766935f76 Remove SSL_CTX_set_ed25519_enabled.
We never ended up using this, and callers can still configure
SSL_CTX_set_verify_algorithm_prefs to enable Ed25519 on the receiving
side. (On the sending side, this API was never needed because it's a
function of what certificate you configure.) This was just a way to
tweak the default without requiring callers restate the order.

Change-Id: I38d7f91d85430f37fc7e278d77466e78a0cbfa0d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39848
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-02-06 23:54:44 +00:00
David Benjamin 6ab75bf21f Improve signature algorithm tests.
ecdsa_sha1 and ecdsa_secp521_sha512 are disabled by default but a caller
could still enable them by configuring the verify preferences. Improve
the tests to distinguish these cases better. Also, as this is getting
unwieldy, cut down on duplicated code between the client and server
signatures.

Change-Id: I1530f4cb43d8e9d675f7fdc4693034287fcac153
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39847
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-02-06 20:02:23 +00:00
Adam Langley 2a4ce17243 bazel: explicitly load C++ rules
Starting with Bazel 3.0, C++ rules will require loads. See
https://github.com/bazelbuild/bazel/issues/8743

Thanks to Yannic Bonenberger for noting this in
https://boringssl-review.googlesource.com/c/boringssl/+/39825

Change-Id: I8e274c82ade6c7ec569989026190f6a0a88b47ed
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39924
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-06 19:15:03 +00:00
Adam Langley fbea9de163 Check enum values in handoff.
Casting an out-of-range value to an enum is undefined behaviour in C.

Bug: oss-fuzz:20546
Change-Id: I11c6bc533b898430bd791e3cdcb271943b95c101
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39904
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-06 18:24:43 +00:00
David Benjamin 921bb9e224 Restore fuzz/cert_corpus.
This was accidentally deleted in https://boringssl-review.googlesource.com/c/boringssl/+/39805

Change-Id: Iba1ee7b03e0e531a4aa86ec6c048523d87bd2c72
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39884
Reviewed-by: Adam Langley <agl@google.com>
2020-02-06 17:55:42 +00:00
David Benjamin bf17f4f6f1 Add a -sigalgs option to bssl client.
Change-Id: I6247e02c6a9a9cc6ff5005eafe96f89f864cb12c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39846
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-02-06 00:53:13 +00:00
David Benjamin f0a815cce5 Add SSL_set_verify_algorithm_prefs.
We already had the state for it, but no API. This will allow us to
configure the signature preferences individually per socket in Chromium
and get a better measurement for how often SHA-1 in TLS 1.2 is still
needed. See associated bug for details.

Bug: chromium:658905
Change-Id: Id6198afc91f8275492995992e03d75a7ff328909
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39845
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-02-06 00:43:12 +00:00
David Benjamin ebad508ef1 Switch verify sigalg pref functions to SSL_HANDSHAKE.
Functions that take SSL* do not necessarily have an ssl->config
available because it is released post-handshake, whereas hs->config can
be accessed without a null check.

Change-Id: I3d9f3838c1f2d79f92beac363a90fb6046671053
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39844
Reviewed-by: Adam Langley <agl@google.com>
2020-02-05 23:21:08 +00:00
David Schinazi 10165d82c1 Add SSL_AD_NO_APPLICATION_PROTOCOL
This is based on AGL's comment on
https://boringssl-review.googlesource.com/c/boringssl/+/39784

Change-Id: I3204a64084288a2c025bc3e4c769a153126a1f9f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39785
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-02-05 14:36:02 +00:00
Matthew Braithwaite 3d53d1ffe6 Refresh corpora due to TLS 1.3 changes in handoff serialization.
Along the way, update |refresh_ssl_corpora.sh| to use the right
handshaker path.

How to:

(rm -rf build-fuzz && mkdir build-fuzz && cd build-fuzz && CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 .. && ninja all)

(rm -rf build-no-fuzzer-mode && mkdir build-no-fuzzer-mode && cd build-no-fuzzer-mode && CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 -DNO_FUZZER_MODE=1 .. && ninja all)

(cd ~/boringssl/fuzz && ../fuzz/refresh_ssl_corpora.sh ../build-fuzz ../build-no-fuzzer-mode ) 2>&1 | tee /tmp/refresh-log

Change-Id: I1115dfe45d25bd74ace1048c80d614afb26223ee
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39805
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Matt Braithwaite <mab@google.com>
2020-02-05 00:34:02 +00:00
Matthew Braithwaite 9e23361aa0 handoff: set |enable_early_data| as part of handback.
This doesn't change the serialization: it just adds
|enable_early_data| to the list of early data fields that get updated
by SSL_apply_handback().

This is needed because, for example, add_new_session_tickets(), which
runs after handback, performs certain actions iff |enable_early_data|
is set.  Plus it just seems cleaner.

Change-Id: Ibcdb745ff9bcbeb2af2475f69f9f798937e7ee63
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39804
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Matt Braithwaite <mab@google.com>
2020-02-04 22:14:27 +00:00
David Schinazi 032fc660bc Add 109 and 120 to SSL_alert_desc_string_long
Change-Id: Ie50fcbabec73bf14895c4eaba134409e010679c4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39784
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-04 16:41:56 +00:00
Matthew Braithwaite 6192ccbbfd runner: enable split handshake tests for TLS 1.3.
Although the new tests are enabled by default, there is a flag to
(continue to) skip them.  This is to allow for inter-version
compatibility testing to be performed without a monstrous number of
failures from old versions that don't yet have TLS 1.3 support.

Change-Id: I9f5e201a21f775442859e127c906b5f77ad8755b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39388
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-04 00:02:33 +00:00
Matthew Braithwaite f3c98ce9b7 Make TLS 1.3 split handshakes work with early data.
Change-Id: Ib051447a4bdde4e08e84e54ec619d47535bb472c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39384
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-02-03 22:54:43 +00:00
Matthew Braithwaite 093a823923 Split half-RTT tickets out into a separate TLS 1.3 state.
This is prefactoring to allow a split handshake to be handed back
prior to sending the half-RTT ticket.

Change-Id: Ib5c335b3109a024391c2ec2cab0749eae43f4646
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39744
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-29 20:40:05 +00:00
Augusto Righetto bc7e2cb92d Use BCryptGenRandom when building as Windows UWP app.
RtlGenRandom is a legacy API that might be altered and is unavailable
for UWP apps. BCryptGenRandom is the recommended API for generating
random numbers on UWP.

This change causes BCryptGenRandom to be used for UWP apps and
RtlGenRandom to be used on non-UWP apps (i.e. desktop apps). For non-UWP
configurations, RtlGenRandom is used instead of BCryptGenRandom to avoid
accessing resources that may be unavailable inside the Chromium sandbox.

Bug: 307
Change-Id: I49f445198b7b4f300a752f45e221a2875d17099e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39584
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-01-28 16:27:53 +00:00
David Benjamin 1cc95ac07c Define EVP compatibility constants for X448 and Ed448.
We do not support these, but Node expects the constants to be there, so
define them. Also fill in X25519's OID. Now that we can wrap it in
EVP_PKEY, we should have the OID there. (Our serializers don't use the
giant OID table, which is why it didn't matter.)

Change-Id: Ie0637f0e525c5704a9354c743075c027ace2f631
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39724
Reviewed-by: Adam Langley <agl@google.com>
2020-01-22 23:03:16 +00:00
Adam Langley a0cdbf989c Allow shared libraries in the external CMake build.
It's trivial to add and someone requested it. Although we don't
generally take external requests, I suspect that gRPC will ask for it
soon enough so worth doing.

BUG=309

Change-Id: I59d6b4f8b26841a95ccf09c753e2afc28e13722b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39664
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-21 17:31:57 +00:00
Adam Langley a965a25952 Add a few little-endian functions to CBS/CBB.
Change-Id: Idf962d587f031c1feed541a43be55dc9a65ca444
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39607
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-17 19:13:18 +00:00
Adam Langley 89730072b8 Move iOS asm tricks up in external CMake build.
This block needs to come before enable_language in order to have the
correct effect.

Change-Id: I2c0e3332c055828381694305e14f2f54b50bb06b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39644
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-17 16:39:30 +00:00
David Benjamin f22e5fbaba Try again to deal with expensive tests.
BlindingCacheConcurrency is crashing on older macOS in Chromium and
Wycheproof primality tests are timing out on Windows. Just disable them
both by default and reenable only when running tests standalone.

Bug: chromium:1042657
Change-Id: Ib3151e883269d1c03154560c2c6f89467cc0113c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39625
Reviewed-by: Adam Langley <agl@google.com>
2020-01-17 01:21:15 +00:00
David Benjamin e1148bdf89 Restore ARM CPU variation tests on builders.
After
https://boringssl.googlesource.com/boringssl/+/9351266ba520336aa082fd256386a46bd1382558,
all_tests.go now sees runtime.GOOS == "android".

Change-Id: If7c5ec448c2ea4bc7efff79acf9aaa55690eda04
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39626
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-01-17 00:25:00 +00:00
David Benjamin f249840c94 Remove SSL_CTX_set_rsa_pss_rsae_certs_enabled.
We never ended up using this, and it'll only become less relevant over
time.

Change-Id: I44c750aee24df8e9eecc28b46540d8b3139004ff
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39608
Reviewed-by: Adam Langley <agl@google.com>
2020-01-16 23:39:20 +00:00
David Benjamin 986afedaa7 Work around another NULL/0 C language bug.
memchr should be OPENSSL_memchr to avoid tripping the memchr variant
of the memcpy(NULL, NULL, 0) language flaw.

Change-Id: I5c945fa6df026d56073f3c5839c0d19cecaf1aa0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39624
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-16 22:22:59 +00:00
David Benjamin 0416e8c305 Use the MAYBE/DISABLED pattern in RSATest.BlindingCacheConcurrency.
Change-Id: Ia3565c117eb952a106bc5f1ab7d5231708854483
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39606
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-15 22:31:48 +00:00
David Benjamin 31e64a295e Switch an #if-0-gated test to DISABLED_Foo.
This is still runnable with --gtest_also_run_disabled_tests and ensures
it keeps compiling at least.

Change-Id: I15bdcb97e74574c04c1119da3945dd6c0350beea
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39605
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-01-15 22:30:08 +00:00
Matthew Braithwaite 98b4cdba1e Proxy: send whole SSL records through the handshaker.
In split handshake tests, it is already the case that the handshaker
must signal the proxy when it wants to read more data.  But there was
not a lot of specificity about exactly how much data would be read.

The case of rejecting early data sent with a second ClientHello,
following a HelloRetryRequest,[1] requires this to be nailed down, in
order that the handshaker should not process the early data.

This commit changes the handshaker to read exactly one SSL record and
then stop, when it is asked to read.  The pattern of I/O operations
remains undefined.

[1] See SkipEarlyData-SecondClientHelloEarlyData-TLS13-Split.

Change-Id: I30f58e57fc5ebff3f7c7ef8482cc629e42fef6a4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39524
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-15 21:36:18 +00:00
David Benjamin 0dcc6e231d Disable Wycheproof primality test cases on non-x86 (too slow)
I had hoped outputting regularly would solve things, but one of
Chromium's Android builders is still timing out. Limit it to x86 and
x86_64, which typically is correlated with a more powerful CPU in
downstream CIs.

This isn't great, but we still run non-Wycheproof primality tests and
primality testing doesn't have any dedicated platform-specific assembly.
It does run platform-specific assembly by way of lower-level BIGNUM
operations, but those are also tested elsewhere. bn_mod_u16_consttime
depends on 32-bit vs 64-bit, but that is covered by running on both
32-bit and 64-bit x86.

Use the GTest DISABLED_Foo mechanism so they may still be run manually
with --gtest_also_run_disabled_tests.

Change-Id: Ie422096db5bb4186145532f4fd2d4063372b8988
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39604
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-15 21:08:58 +00:00
Matthew Braithwaite f06254c739 test_state.cc: serialize the test clock.
This is needed for some TLS 1.3 split-handshake tests.  Because
TestState::Deserialize doesn't check for CBS_len() == 0, it should be
a compatible change to tack additional data onto the end of the
serialized test state.

Change-Id: I16464b6e27ab2e9afd0d505719095b4895e652a4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39546
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-15 20:38:44 +00:00
David Benjamin 8e8759f0d3 Output after every Wycheproof primality test.
Running that many primality tests, particularly on large numbers, in a
single test case is slow and timing out Chromium's test runner.

Change-Id: I07363744970545b2b4fcd7be264e20c338765dea
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39564
Reviewed-by: Adam Langley <agl@google.com>
2020-01-15 17:12:02 +00:00
Adam Langley ff631133c4 Maybe fix generated-CMake build on Android and iOS.
Based on reports, these changes seem like good suspects for build
failures reported, while using the generated CMake build, on iOS and
Android. By checking this in, this change will appear in the
master-with-bazel branch, making it easier for consumers to test.

Change-Id: Icbcebe85f10fad76e3224333c769d0818ae45244
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39545
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-15 16:59:50 +00:00
David Benjamin f50a8a77bd Detect the NDK path from CMAKE_TOOLCHAIN_FILE.
The NDK toolchain file uses either ANDROID_NDK or CMAKE_TOOLCHAIN_FILE,
so look at both. In particular, our builders don't pass in ANDROID_NDK.

Change-Id: Ic7fabdbd16adc3d38389d338b38839b67dde6523
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39544
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-13 23:50:48 +00:00
David Benjamin 9351266ba5 Tell Go to build for GOOS=android when running on Android.
This is a speculative fix for the CI flakiness on Android. It seems
Android and Linux ARM ABIs may differ slightly in handling of thread
locals, so we should build for GOOS=android. That requires cgo and
pointing CC at a suitable target-specific compiler from the NDK. Detect
those values from CMakeCache.txt.

Change-Id: I2da75bf9ca6df3e5e677c2151ece8c5e20740fc3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39504
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-13 19:54:08 +00:00
David Benjamin c556d87ddf Reland bitsliced aes_nohw implementation.
This relands
https://boringssl-review.googlesource.com/c/boringssl/+/39206. See that
CL description for details on the change.

The CL was originally reverted due to a number of ARM-only test
failures. First, there was a test-only issue, resolved in
https://boringssl-review.googlesource.com/c/boringssl/+/39306.

Second, the implementation did not work in unoptimized Android Thumb2
builds. This was caused by a clang bug introduced in
https://reviews.llvm.org/rL340261 and fixed in
https://reviews.llvm.org/rL351310. aes_nohw_(un)compact_block have
been rewritten in an attempt to dodge the bug. Performance of optimized
builds with clang and gcc do not appear to be affected by the rewrite.
See the delta from patch set 1.

(I had hoped to improve precommit CQ coverage before landing this, but
both failures turned out to be ARM-only. Either way, there are now
32-bit and 64-bit SSE2-less configurations so the 32-bit and 64-bit
implementations have CQ coverage.)

Change-Id: If5f9f5ea570686a15258ecd7cf49bdbc12dc34c5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39444
Reviewed-by: Adam Langley <agl@google.com>
2020-01-13 19:14:52 +00:00
Pete Bentley 3e96cd4b76 Add bssl client option to load a hashed directory of cacerts.
Useful for debugging TLS issues on Android.

Change-Id: Ibdf9233b30e297dbab6be86a4f6b1a9eab593dbf
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39464
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-01-10 16:38:49 +00:00
David Benjamin b0d449aea2 No-op change to run the new NO_SSE2 builders.
Change-Id: Ie54d4faf911d1106f27aa7e8f0be341cf1ed8a62
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39424
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-01-09 20:34:48 +00:00
David Benjamin 0deb91ab3f Clarify that we perform the point-on-curve check.
Points not on the curve are invalid inputs to EC functions, so EC
implementations should check the curve equation whenever importing
points from the caller. Sadly, a number of implementations, including
older OpenSSLs, miss this important check, so careful callers want this
clarified in the documentation.

Also update the note about OpenSSL to reflect the current behavior.

While I'm here, const-correct EC_KEY_key2buf.

Change-Id: I6fde5c823c4f3f6b141ba1566f427d96cd5881df
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39364
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-07 17:04:27 +00:00
Adam Langley 604320f8a3 Reduce size of BlindingCacheConcurrency test under TSAN.
When building with TSAN, having 2048 threads causes crypto_test to run
for more than 20 minutes (when I gave up), vs about two minutes
normally. This will remove our TSAN coverage (due to timeouts) unless we
trim the size of the test.

Change-Id: I381c77a8e9e09c49f3476c38993db40ffdac60d6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39346
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2020-01-06 20:17:02 +00:00
David Benjamin 2feab0c085 Compare vpaes/bsaes conversions against a reference implementation.
We no longer pair bsaes with aes_nohw and
https://boringssl-review.googlesource.com/c/boringssl/+/39206 aimed to
replace it with a different implementation. This fixes an ARM test
failure when relanding
https://boringssl-review.googlesource.com/c/boringssl/+/39206.

Change-Id: I8c9553f75470cf571ecab279c9451d7228a86485
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39306
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-06 19:26:52 +00:00
David Benjamin 63d06626d3 Enable the SSE2 Poly1305 implementation on clang-cl.
poly1305_vec.c requires SSE2 intrinsics and uint128_t. Unlike MSVC, clang-cl
supports uint128_t just fine (as long as we do not do division). This makes
ChaCha20-Poly1305 much faster on Windows when built with clang-cl.

Before:
Did 2219000 ChaCha20-Poly1305 (16 bytes) seal operations in 1016000us (2184055.1 ops/sec): 34.9 MB/s
Did 1279500 ChaCha20-Poly1305 (256 bytes) seal operations in 1016000us (1259350.4 ops/sec): 322.4 MB/s
Did 428250 ChaCha20-Poly1305 (1350 bytes) seal operations in 1015000us (421921.2 ops/sec): 569.6 MB/s
Did 84000 ChaCha20-Poly1305 (8192 bytes) seal operations in 1016000us (82677.2 ops/sec): 677.3 MB/s
Did 39750 ChaCha20-Poly1305 (16384 bytes) seal operations in 1015000us (39162.6 ops/sec): 641.6 MB/s

After:
Did 2096250 ChaCha20-Poly1305 (16 bytes) seal operations in 1015000us (2065270.9 ops/sec): 33.0 MB/s
Did 1453250 ChaCha20-Poly1305 (256 bytes) seal operations in 1016000us (1430364.2 ops/sec): 366.2 MB/s
Did 642500 ChaCha20-Poly1305 (1350 bytes) seal operations in 1015000us (633004.9 ops/sec): 854.6 MB/s
Did 136250 ChaCha20-Poly1305 (8192 bytes) seal operations in 1016000us (134104.3 ops/sec): 1098.6 MB/s
Did 69750 ChaCha20-Poly1305 (16384 bytes) seal operations in 1016000us (68651.6 ops/sec): 1124.8 MB/s

(Benchmarks gathered in VM, but this is a significant difference.)

Change-Id: Ia0a856e75995623c5621d2e48d61d945c41b17de
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39345
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-06 19:15:52 +00:00
David Benjamin 056035edcc Remove alignment requirement on CRYPTO_poly1305_finish.
This dates to https://boringssl-review.googlesource.com/2850, which was
done in response to an ARM crash. I assume the ARM crash was due to
poly1305_arm.c casting pointers around, which is technically UB, even on
x86 since C says it is UB to cast pointers if the value would be
unaligned. (Also I believe it's a strict aliasing violation, though the
compilers really ought to give us a sanitizer for it if they're excited
about that optimization.)

Replace with memcpy, which any reasonable compiler would compile the
same on platforms that support unaligned access. ARM does support it
these days, so perhaps the crash came from an older ARM?

Benchmarks showed no difference with this CL.

Change-Id: I022bdb84f95e45c143ad19359f646ee1416d5ae9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39344
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-06 19:10:12 +00:00
Adam Langley 2c58c2fda1 Fix double-free under load.
The BN_BLINDING cache, when 1024 threads are performing concurrent
private operations on one RSA key, can race to append a BN_BLINDING to a
cache which is just short of the maximum length. The cache ends up one
(or more) elements longer than the maximum length. That causes the index
of one of the cache elements to _be_ the supposed maximum length, but
that index is treated as a magic number that indicates that a
BN_BLINDING isn't from the cache and thus needs to be freed after use.
That BN_BLINDING is then double-freed when the cache itself is freed.

See internal bug b/147126942.

Since the fact that someone hit this means that 1024 threads working on
a single RSA key is a thing that's happening, take the opportunity to
grow the cache by doubling rather than by single elements at a time.
Once the number of extensions is so reduced, the trick of unlocking to
keep a few allocations outside of the lock (which caused the problem)
can be discarded.

Change-Id: I32dd16d825b702b31ee9b776414c4e6afe883724
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39324
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2020-01-06 17:34:02 +00:00
David Benjamin aaa1a84d63 Add some XTS tests.
For some reason, these also fail with the reverted aes_nohw on 32-bit
Android. (Still trying to figure out why that happens.)

Change-Id: Ia9ef34e97b473585424120620b1d937220cd2c31
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39305
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-03 23:14:49 +00:00
David Benjamin 8959a49cc1 Add EncodeHex and DecodeHex functions to test_util.h.
We have enough copies of these.

Change-Id: I1ff8915b8ca781dc070e802e634d1dc12832e272
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39304
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-03 23:10:49 +00:00
David Benjamin 6c95434cc9 Revert "Replace aes_nohw with a bitsliced implementation."
This reverts commit b3ac6bb39a.

Reason for revert: 32-bit version seems to be broken. I'll debug this
and improve pre-commit CQ coverage before relanding.

Original change's description:
> Replace aes_nohw with a bitsliced implementation.
> 
> aes_nohw is currently one of several variable-time table-based
> implementations in C or assembly (armv4, x86, and x86_64). Replace all
> of these with a C bitsliced implementation, with 32-bit, 64-bit, and
> 128-bit (SSE2) variants. This is based on the algorithms described in:
> 
> https://bearssl.org/constanttime.html#aes
> https://eprint.iacr.org/2009/129.pdf
> https://eprint.iacr.org/2009/191.pdf
> 
> This makes our AES implementation constant-time in all build
> configurations!
> 
> There were far too many benchmarks to put in the commit message.
> Instead, please refer to this fancy spreadsheet:
> https://docs.google.com/spreadsheets/d/1wDCzfkPl7brfjWJKq55awQjwCPhOYI8O7zSQZuEc2Xg/edit?usp=sharing
> 
> Parallel modes on x86 and x86_64 do fine due to the SSE2 code. AES-GCM
> actually gets faster. The 64-bit (4x) bitsliced implementation is less
> effective at speeding parallel modes but still helps. The 32-bit (2x)
> bitsliced implementation even less.
> 
> Non-parallel modes, sadly, take a *dramatic* performance hit. I tried a
> constant-time table lookup for comparison, but bitslicing was still
> better. This implementation performs comparably to the table in
> BearSSL's documentation, which suggests I didn't do anything obviously
> wrong. (Note BearSSL's table for 'ct' corresponds to a 32-bit bitsliced
> implementation compiled for 64-bit. Compiling this implementation for
> 64-bit matches, but compiling it for 32-bit seems to be considerably
> slower.)
> 
> Assumptions that may make this palatable:
> 
> - AES-GCM is by far the most important AES mode, and we perform okay
>   with it. Modern things aren't built out of CBC.
> 
> - A nontrivial chunk of Chrome users on Windows don't have SSSE3 and
>   would be affected by this change. They would get the SSE2 version
>   which performs well for AES-GCM *and* is constant-time.
> 
> - ARM devices are primarily mobile which cycles hardware much faster.
>   Chrome for Android has required NEON for several years now, so it
>   would not run this code. (Aside from https://crbug.com/341598.)
> 
> - aarch64 mandates NEON, so it would not run this code.
> 
> - QUIC packet number encryption does use a one-off block operation, but
>   only once per packet.
> 
> - Arguably this is undoing a performance gain that we never earned. That
>   said, it was a dramatic performance gain in places.
> 
> As an alternative, we could just check in the SSE2 version and drop the
> x86 and x86_64 table-based assembly, but this still leaves the generic
> code with cache-timing side channels.
> 
> Change-Id: I0f4b4467a49790509503c529d7c0940318096a00
> Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39206
> Commit-Queue: Adam Langley <agl@google.com>
> Reviewed-by: Adam Langley <agl@google.com>

TBR=agl@google.com,davidben@google.com

Change-Id: Iffaf01a98ab40bbfa009c451aa20ba3eb923eab9
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39285
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2020-01-03 17:47:29 +00:00
David Benjamin b3ac6bb39a Replace aes_nohw with a bitsliced implementation.
aes_nohw is currently one of several variable-time table-based
implementations in C or assembly (armv4, x86, and x86_64). Replace all
of these with a C bitsliced implementation, with 32-bit, 64-bit, and
128-bit (SSE2) variants. This is based on the algorithms described in:

https://bearssl.org/constanttime.html#aes
https://eprint.iacr.org/2009/129.pdf
https://eprint.iacr.org/2009/191.pdf

This makes our AES implementation constant-time in all build
configurations!

There were far too many benchmarks to put in the commit message.
Instead, please refer to this fancy spreadsheet:
https://docs.google.com/spreadsheets/d/1wDCzfkPl7brfjWJKq55awQjwCPhOYI8O7zSQZuEc2Xg/edit?usp=sharing

Parallel modes on x86 and x86_64 do fine due to the SSE2 code. AES-GCM
actually gets faster. The 64-bit (4x) bitsliced implementation is less
effective at speeding parallel modes but still helps. The 32-bit (2x)
bitsliced implementation even less.

Non-parallel modes, sadly, take a *dramatic* performance hit. I tried a
constant-time table lookup for comparison, but bitslicing was still
better. This implementation performs comparably to the table in
BearSSL's documentation, which suggests I didn't do anything obviously
wrong. (Note BearSSL's table for 'ct' corresponds to a 32-bit bitsliced
implementation compiled for 64-bit. Compiling this implementation for
64-bit matches, but compiling it for 32-bit seems to be considerably
slower.)

Assumptions that may make this palatable:

- AES-GCM is by far the most important AES mode, and we perform okay
  with it. Modern things aren't built out of CBC.

- A nontrivial chunk of Chrome users on Windows don't have SSSE3 and
  would be affected by this change. They would get the SSE2 version
  which performs well for AES-GCM *and* is constant-time.

- ARM devices are primarily mobile which cycles hardware much faster.
  Chrome for Android has required NEON for several years now, so it
  would not run this code. (Aside from https://crbug.com/341598.)

- aarch64 mandates NEON, so it would not run this code.

- QUIC packet number encryption does use a one-off block operation, but
  only once per packet.

- Arguably this is undoing a performance gain that we never earned. That
  said, it was a dramatic performance gain in places.

As an alternative, we could just check in the SSE2 version and drop the
x86 and x86_64 table-based assembly, but this still leaves the generic
code with cache-timing side channels.

Change-Id: I0f4b4467a49790509503c529d7c0940318096a00
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39206
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2020-01-03 16:41:59 +00:00
Adam Langley cbae965ca0 Switch HRSS inversion algorithm.
This algorithm is much simplier and more obvious than the one from the
HRSS paper. Unfortunately it's not immediately any faster (roughly a
no-op on most platforms, +5% on ARM) but it does allow a bunch of
constant-time rotation code to be deleted.

Since it's simplier, however, it's easier to speed-up a little with
future changes.

Change-Id: Ic0e92c77c44ea9aeb6fe35940af9767084fe5f58
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39084
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-12-20 21:54:43 +00:00
David Benjamin 6c5e4a4bc9 Run EVP_CIPHER tests in-place.
I had a bug that was only caught in ssl_test. This would have caught it
in crypto_test (although only via Wycheproof test vectors; our
EVP_CIPHER CBC test vectors are all short.)

Change-Id: I8dc1457796cb6a8c0be808639657ce74967225ad
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39205
Reviewed-by: Adam Langley <agl@google.com>
2019-12-20 18:32:27 +00:00
David Benjamin 6887d5e81b Add an option to disable SSE2 intrinsics for testing.
We have some code which uses SSE2 intrinsics which, since they don't
have complicated build requirements, is enabled even with
OPENSSL_NO_ASM. x86_64 mandates SSE2 and people building for x86 tend to
mandate it anyway these days. This is great, but we still have generic
32-bit and 64-bit code configurations for other platforms.

32-bit generic code is covered by testing 32-bit ARM with NEON disabled.
However, 64-bit ARM always has NEON available, so we have no SIMD-less
64-bit platforms in our CI.

The immediate motivation is some bitsliced AES code I'm working on,
however I believe this also applies to the existing HRSS code. This also
fixes the HRSS feature checks to only look at __SSE2__, not __SSE__.
__SSE__ isn't sufficient and we don't compile if GCC or Clang is told
-msse -mno-sse2.

Change-Id: Iebb23f1664a2f62e0b4333e0e99f7d5f6c7f384d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39204
Reviewed-by: Adam Langley <agl@google.com>
2019-12-20 18:29:26 +00:00
Adam Langley 522e2df089 Dummy change to trigger master-with-bazel builder.
Change-Id: I0ac60d7b67f8f680a8faaba736eb85aa6a94b6a2
2019-12-18 12:06:18 -08:00
Adam Langley c58a85f8ca Drop use of alignas(64) in aead_test.cc
Reportedly, GCC 8 and 9, on aarch64, rejects this with:

  crypto/cipher_extra/aead_test.cc:545:54: error: requested alignment 64 is larger than 16 [-Werror=attributes]

The only other uses of alignas(x), with x > 16, are in x86-64-only code.

Change-Id: I1c93732cb40a783c2ef7271b1df9baae644b4305
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39224
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-12-18 18:26:40 +00:00
Adam Langley cfd80a9b24 Add standalone CMake build to generate_build_files.py
This change adds a 'cmake' build type to generate_build_files.py, which
creates a standalone, CMake build without (most) of the complexities of
the full development CMake build.

(This is just a sketch for now. Some deduplication of the CMake is
called for before landing, presuming that this is useful.)

Change-Id: I1f91a8905cabaedf8f9ec588da5784edd67bfed0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38744
Reviewed-by: Adam Langley <agl@google.com>
2019-12-17 22:00:50 +00:00
Matthew Braithwaite cc0c28654a TLS 1.3 split handshake initial support.
This does not change the wire format for any existing (TLS 1.2 and
lower) cases, which means it should not affect interoperability of
anything that exists.

Most tests pass, but I'll land those in a separate commit, after
nailing down some loose ends, and in order to have more time to reason
about interoperability effects.

Some features are not supported yet, e.g early data.

Change-Id: I7bb377017324cb3d98df75c5d6ed4757c6901ed7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38926
Reviewed-by: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Matt Braithwaite <mab@google.com>
2019-12-16 23:05:32 +00:00
David Benjamin be1d14b789 Import Wycheproof primality tests.
Change-Id: I885fb8f282b6339bdb061fde1c8d3d74706de5b5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39196
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 22:20:51 +00:00
David Benjamin 0df6edff4f Split BN_prime_checks into two constants for generation and validation.
Although (somewhat) documented in prose, it is not obvious from the name
that BN_prime_checks only works for randomly-selected candidate primes.
Split into BN_prime_checks_for_generation and
BN_prime_checks_for_validation. Fix internal call sites. Notably,
DH_check now uses more iterations.

Consistently call the parameter 'checks' rather than 'iterations', to
match BN_prime_checks.

This is in preparation for importing the Wycheproof primality testing
vectors, some of which include Miller-Rabin worst case values.
(Realistically the blinding mechanism meant, even for those inputs, our
false positive rate was at most ~2^-64 anyway, but best to keep the use
cases clear.)

Update-Note: DH_check may be slower after this change.
Change-Id: Ic13d03d8631e74bf2958979ee5ef45a69e603f46
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39195
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 22:20:22 +00:00
David Benjamin 9511ca4c03 Add some Miller-Rabin tests from Wycheproof.
Wycheproof's primality testing vectors include worst case values where
1/4 of witnesses are false. Add some test cases for true and false
witnesses.

Change-Id: I66050fd34694ca1cc145f950500d110c22d8bd42
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39194
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:26:32 +00:00
David Benjamin a165168277 Import Wycheproof PKCS#1 decrypt tests.
Change-Id: I2f9bca4233b42ff5604e1516ad482142470467dd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39193
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:25:35 +00:00
David Benjamin 355828a2f7 Import Wycheproof OAEP tests.
Change-Id: I49fb836e92ee6c0b668b3921f6f873b8f79e793d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39192
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:24:27 +00:00
David Benjamin e5905d01c3 Import Wycheproof PKCS#1 signing tests.
In doing so, add an IgnoreAllInstructions option for FileTest. FileTest
tracks unused fields so test drivers don't accidentally miss a portion
of the test. Wycheproof tests, however, have many different key formats
in instructions. These are tedious to list out, so add an option to
ignore them, on the assumption that checking attributes is more useful
than instructions.

Change-Id: I01cc9f3a95577d576c8c2dd68f5092fceb3215b1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39191
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:21:41 +00:00
David Benjamin 305a03a8b0 Skip JWK keys when converting Wycheproof tests.
We expand the dictionaries, which is no longer JWK anyway.

Change-Id: I26f0b8beedf82a7efe40a536171eab940c0ec7d5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39190
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:19:46 +00:00
David Benjamin 55ed2a60d3 Import Wycheproof's size-specific RSA PKCS#1 verifying tests.
It's unclear to me whether the normal rsa_signature_test.txt file is
still needed with these, but I've left it in for now.

Change-Id: I6db9c9556820263c2b0bc37d144e6403b9a7a178
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39189
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:18:35 +00:00
David Benjamin 906bbef001 Handle "acceptable" Wycheproof inputs unambiguously.
This CL updates the JSON conversion to preserve the flags. A
WycheproofResult now captures both "result" and "flags". An "acceptable"
test case's validity is determined by its flags. By default, we consider
an "acceptable" case as invalid, but a test driver may mark some of them
as valid by listing the flags as a parameter.

Previously, some Wycheproof tests (I think it was x25519_tests.txt?) did
not contain enough information to resolve this unambiguously. This has
since been fixed.

This also makes the converted files smaller because we no longer expand the
flags into comments.

Change-Id: I2ca02d7f1b95f250409e8b23c4ad7bb595d77fdf
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39188
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:17:51 +00:00
David Benjamin 62f662dbeb Import Wycheproof XChaCha20-Poly1305 tests.
Change-Id: Iaa10ebfc61aa2f928f057a62737d5d97743d6305
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39187
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:17:00 +00:00
David Benjamin b19efcc1cf Import Wycheproof HMAC tests.
Change-Id: I712ac83efc3bf1edfd4485cb0e822f5719629293
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39186
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 20:14:01 +00:00
David Benjamin 8e71fe9ca8 Import Wycheproof HKDF tests.
Change-Id: Iece24241327778eb092a069fd1a0784c9d2a7363
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39185
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 18:58:12 +00:00
Matthew Braithwaite 82dbb53f77 bytestring: add methods for int64.
I guess there's a first time for everything.  Today, it's negative
ASN.1 INTEGERs.  This benefits TLS 1.3 split handshakes.

Change-Id: I886bc513d644dde756db11488d09f450032e464b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39124
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 18:55:32 +00:00
David Benjamin 15cd8bf433 Update Wycheproof test vectors.
Wycheproof have added many more tests. They'll be imported in subsequent
CLs.

Change-Id: I69d8e09328b08edbd0a96757db26b380d7a7c7ee
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39184
Reviewed-by: Adam Langley <agl@google.com>
2019-12-16 18:53:44 +00:00
Nick Harper b14530e636 Add mock QUIC transport to runner
The mock QUIC transport used has a very simple record layer: A record
starts with a single byte (either 'H' or 'A') identifying the record to
be handshake or application data, then a 4-byte network order integer
indicating the length of the payload, followed by the encryption secret
that would be used for protecting that payload, followed by the payload
itself. The encoded length is only the length of the payload, not that
of the payload and secret (or the whole record).

Bug: 293
Change-Id: Icb706a94ef1ad77e86ef8728b73db8832ee65e1b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39144
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-12-13 21:49:40 +00:00
David Benjamin cb3f04f584 Add test vectors for CVE-2019-1551 (not affected).
This was a bug in the 512-bit RSAZ code, which we removed in
https://boringssl-review.googlesource.com/12841. Import the test vectors
anyway.

(Imported from upstream's 08fb832377cd90c08a2d233b3230b95a9b9f6e24.)

Change-Id: Ie057c54e6e77ac943805dafd74afcb84cf67e918
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39064
Reviewed-by: Adam Langley <agl@google.com>
2019-12-06 17:17:57 +00:00
David Benjamin b63123ca02 Fix check_bn_tests.go.
Go and OpenSSL disagree on 0^-1 (mod 1). Also if the input is ill-formed
and there is no inverse, report an error rather than crashing.

Change-Id: Id5b0b70cd7498e0c7526ec6a7bc5480cd9718f41
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39044
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2019-12-05 18:11:57 +00:00
David Benjamin 243b5cc9e3 Fix MSan error in SSLTest.Handoff test.
Apparently I forgot to put MSan on the CQ, just CI.

Change-Id: I1f47c3bd92f6db6a67e0a4ecc113a6ea214f642f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39024
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-04 16:49:42 +00:00
Matthew Braithwaite 134fb89c4f SSLTest.Handoff: extend to include a session resumption.
This was a tricky thing to get right for both TLS 1.2 and TLS 1.3, and
having this test around made it easier.

Change-Id: I47f55160c7e267d122f310165a17a1f9402dadd7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38925
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-12-04 00:00:14 +00:00
Jooyung Han 9ad9cda088 inject_hash preserves filemode
Previously, inject_hash writes output file with 0644 regardless of
input file.

Now it preserves filemode of input when writing output file.

Change-Id: I00db775e1b28f6d9a72986276e32a9b944317949
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38844
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2019-12-03 18:57:23 +00:00
Matthew Braithwaite 08e1fe05e6 Move TLS 1.3 state machine constants to internal.h.
This benefits TLS 1.3 split handshakes, which need the constants to
put an |SSL| into the correct state after SSL_apply_handback().

Change-Id: I2dc5b108d7393fb30708b89c53adcc73056d4f0b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38924
Commit-Queue: Matt Braithwaite <mab@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-12-03 00:59:11 +00:00
David Benjamin 31db68195b Add a ppc64le ABI tester.
Now we have ABI tests for every architecture where we have assembly.

Change-Id: I59bc2d0f72f2325e9f294b1fc08287bb93fc9cd2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39008
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-02 23:12:31 +00:00
David Benjamin c73375467c Allocate small TLS read buffers inline.
Our TLS read patterns are always read(5); read(record_size); read(5);
read(record_size); ...;. Allocate the 5-byte reads inline in SSLBuffer.
This avoids bouncing on a 5-byte malloc to learn a socket is idle and
avoids calling malloc twice on each record.

This costs a few bytes but means we malloc once per record, rather than
twice per record + once each time the state machine is run while idle.

Change-Id: I4f6dafe4141cbb890b921a5fa8d528c1fb98a0b4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39004
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-02 22:14:18 +00:00
David Benjamin b8b0e9f485 Remove unused labels from ARM ABI test assembly.
I think these were copied over from the x86_64 one on accident.

Change-Id: I0a8bb28bb0b9e94739f4696146e2418e84cb2b87
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39007
Reviewed-by: Adam Langley <agl@google.com>
2019-12-02 21:48:35 +00:00
David Benjamin 469446c736 Update AAPCS and AAPCS64 links.
The old ones disappeared. Switch to the developer.arm.com pointers.
Hopefully they are more stable. (Interestingly, the "Download PDF" link
for AAPCS64 now points to a GitHub repo.)

Change-Id: Ifa81e95978285409a6323f007d041515d4f270ee
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39006
Reviewed-by: Adam Langley <agl@google.com>
2019-12-02 21:48:27 +00:00
David Benjamin 5746add69c Fix EVP_has_aes_hardware on ppc64le.
Change-Id: I5e0bc02e591b86ccc30d35eeed2c7065910dd24a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39005
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-02 21:48:21 +00:00
David Benjamin 98ba3bd6e7 Remove remnants of end_of_early_data alert from tests.
It changed from an alert to a handshake message in the
standardization process.

Change-Id: Ib3e5b29ccf83b72d78a714f604957ca55594d5e3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38604
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-12-02 20:07:53 +00:00
David Benjamin f8fcab9d81 Add a test for ERR_error_string_n.
The truncation logic has some non-trivial bits around preserving colon
separators which we ought to test.

Change-Id: Id2784546f6578ebd85ba6bf1010c575cc371ef1b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38965
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-12-02 17:52:12 +00:00
David Benjamin e0d95adb24 Remove post-quantum experiment signal extension.
The experiment has concluded, so we don't need this anymore.

Change-Id: Id99722394d5d0525f536bddea5df6cde8bb44c94
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38944
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-12-02 17:40:22 +00:00
David Benjamin 35c1075e83 Give ERR_error_string_n a return value for convenience.
ERR_error_string_n needs to be called in a separate statement, compared
to ERR_error_string(err, NULL), which returns a buffer and is very
convenient to use in an expression. This is unfortunate because it is
not thread-safe.

Give ERR_error_string_n a return value to align. Fixing callers still
requires allocating a buffer somewhere, but the rest of the expression
can remain relatively unperturbed.

Change-Id: I273c9df97f0bb113cdc57cf3896c42195910c67a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38964
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-12-02 16:53:32 +00:00
David Benjamin ee0716f386 Defer early keys to QUIC clients to after certificate reverification.
On a client using SSL_CTX_set_reverify_on_resume, we currently release
the early data keys before reverification rather than afterwards. This
means the QUIC implementation needs to watch for SSL_do_handshake's
return value before using the keys we've released. It is better to be
robust, so defer releasing the keys in the first place.

To avoid oddities around TCP and QUIC differences, tweak the 0-RTT cert
reverification to not send an alert on error. Sending such an alert
under early data is somewhat questionable given the server may not be
able to read it anyway.

Bug: 303
Change-Id: I42c16f9f046322d0b03cb0b425e11471f2fbe52a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38885
Reviewed-by: Nick Harper <nharper@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-11-27 15:49:42 +00:00
David Benjamin fd32089f47 Defer releasing early secrets to QUIC servers.
We want the QUIC/TLS interface to never release a read key without the
corresponding write key for ACKs. This is mostly done by shipping both keys
simultaneously, but 0-RTT is weird because it is ACKed by 1-RTT.

Note this means we actually release 0-RTT keys to the server *after* the 1-RTT
keys. This is kinda weird but more directly maintains our invariant.

(We may want to revisit the key configuring API in light of
https://github.com/quicwg/base-drafts/issues/3159 and
https://github.com/quicwg/base-drafts/issues/3173, but start with this more
local tweak.)

Bug: 303
Change-Id: I317fe6ae8150533738373c219f19d3034bb040ad
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38884
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Nick Harper <nharper@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
2019-11-27 14:15:33 +00:00
David Benjamin 75148d7abf Halve the size of the kNIDsIn* constants
We have not and are unlikely to ever allocate 65K NIDs, so these ables can use
uint16_t and halve their size.

Bug: 300
Change-Id: I5c69a366588f26df75b7b642bee6dd12ad8cc661
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38904
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-11-20 15:09:27 +00:00
Adam Langley 6ba98ff601 modulewrapper: manage buffer with |unique_ptr|.
This doesn't actually matter, but ASan otherwise complains about the
memory leak on process exit.

Change-Id: Ic7cf591b7687f10c3a5bc304e1321f4deecdcb10
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38804
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2019-11-12 23:49:31 +00:00
David Benjamin af609d885b Add missing boringssl_prefix_symbols_asm.h include.
This file probably should be switched to perlasm, but this is an easier fix for
now. It touches ymm registers, so Windows will be a little fussy.

Change-Id: I7b89435cb5c3e908b3bc784d7c305f115e707358
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38864
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-11-12 23:34:21 +00:00
Gurleen Grewal 913a240c28 acvptool: add support for ECDSA
Change-Id: I0c643de16d5215a20bb21e8523efccd5555098eb
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38764
Reviewed-by: Gurleen Grewal <gurleengrewal@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-11-12 23:13:24 +00:00
David Benjamin 5d62952b2a Inline gcm_init_4bit into gcm_init_ssse3.
In doing so, convert an unnecessary macro into an inline function and
avoid needing to fix up the word order. gcm.c likes to store things with
the words byteswapped and the words unswapped.

Change-Id: Ifa4cbe9ceaaf2d4cd3b6133d442603343b409cc3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38785
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-11-12 05:59:55 +00:00
David Benjamin a2518dd077 Vectorize gcm_mul32_nohw and replace gcm_gmult_4bit_mmx.
This shrinks the perf gap between nohw and 4bit_mmx. Replace 4bit_mmx
and fix the last remaining variable-time GHASH implementation, covering
32-bit x86 without SSSE3.

Before:
Did 2065000 AES-128-GCM (16 bytes) seal operations in 1000154us (2064682.0 ops/sec): 33.0 MB/s
Did 368000 AES-128-GCM (256 bytes) seal operations in 1002435us (367106.1 ops/sec): 94.0 MB/s
Did 77000 AES-128-GCM (1350 bytes) seal operations in 1001225us (76905.8 ops/sec): 103.8 MB/s
Did 14000 AES-128-GCM (8192 bytes) seal operations in 1067523us (13114.5 ops/sec): 107.4 MB/s
Did 6572 AES-128-GCM (16384 bytes) seal operations in 1015976us (6468.7 ops/sec): 106.0 MB/s
After:
Did 1995000 AES-128-GCM (16 bytes) seal operations in 1000374us (1994254.1 ops/sec): 31.9 MB/s
Did 319000 AES-128-GCM (256 bytes) seal operations in 1000196us (318937.5 ops/sec): 81.6 MB/s
Did 66000 AES-128-GCM (1350 bytes) seal operations in 1002823us (65814.2 ops/sec): 88.8 MB/s
Did 12000 AES-128-GCM (8192 bytes) seal operations in 1079294us (11118.4 ops/sec): 91.1 MB/s
Did 5511 AES-128-GCM (16384 bytes) seal operations in 1006218us (5476.9 ops/sec): 89.7 MB/s
(Note fallback AES is dampening the perf hit. Pairing with AESNI to
roughly isolate GHASH shows a 40% hit.)

That just leaves aes_nohw...

Change-Id: I7d842806c54a5a057895fa2e7665633330e34b72
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38784
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-11-12 01:01:38 +00:00
David Benjamin 9855c1c59a Add a constant-time fallback GHASH implementation.
We have several variable-time table-based GHASH implementations, called
"4bit" in the code. We have a fallback one in C and assembly
implementations for x86, x86_64, and armv4. This are used if assembly is
off or if the hardware lacks NEON or SSSE3.

Note these benchmarks are all on hardware several generations beyond
what would actually run this code, so it's a bit artificial.

Implement a constant-time implementation of GHASH based on the notes in
https://bearssl.org/constanttime.html#ghash-for-gcm, as well as the
reduction algorithm described in
https://crypto.stanford.edu/RealWorldCrypto/slides/gueron.pdf.

This new implementation is actually faster than the fallback C code for
both 32-bit and 64-bit. It is slower than the assembly implementations,
particularly for 32-bit. I've left 32-bit x86 alone but replaced the
x86_64 and armv4 ones.  The perf hit on x86_64 is smaller and affects a
small percentage of 64-bit Chrome on Windows users. ARM chips without
NEON is rare (Chrome for Android requires it), so replace that too.

The answer for 32-bit x86 is unclear. More 32-bit Chrome on Windows
users lack SSSE3, and the perf hit is dramatic. gcm_gmult_4bit_mmx uses
SSE2, so perhaps we can close the gap with an SSE2 version of this
strategy, or perhaps we can decide this perf hit is worth fixing the
timing leaks.

32-bit x86 with OPENSSL_NO_ASM
Before: (4bit C)
Did 1136000 AES-128-GCM (16 bytes) seal operations in 1000762us (1135135.0 ops/sec): 18.2 MB/s
Did 190000 AES-128-GCM (256 bytes) seal operations in 1003533us (189331.1 ops/sec): 48.5 MB/s
Did 40000 AES-128-GCM (1350 bytes) seal operations in 1022114us (39134.6 ops/sec): 52.8 MB/s
Did 7282 AES-128-GCM (8192 bytes) seal operations in 1117575us (6515.9 ops/sec): 53.4 MB/s
Did 3663 AES-128-GCM (16384 bytes) seal operations in 1098538us (3334.4 ops/sec): 54.6 MB/s
After:
Did 1503000 AES-128-GCM (16 bytes) seal operations in 1000054us (1502918.8 ops/sec): 24.0 MB/s
Did 252000 AES-128-GCM (256 bytes) seal operations in 1001173us (251704.8 ops/sec): 64.4 MB/s
Did 53000 AES-128-GCM (1350 bytes) seal operations in 1016983us (52114.9 ops/sec): 70.4 MB/s
Did 9317 AES-128-GCM (8192 bytes) seal operations in 1056367us (8819.9 ops/sec): 72.3 MB/s
Did 4356 AES-128-GCM (16384 bytes) seal operations in 1000445us (4354.1 ops/sec): 71.3 MB/s

64-bit x86 with OPENSSL_NO_ASM
Before: (4bit C)
Did 2976000 AES-128-GCM (16 bytes) seal operations in 1000258us (2975232.4 ops/sec): 47.6 MB/s
Did 510000 AES-128-GCM (256 bytes) seal operations in 1000295us (509849.6 ops/sec): 130.5 MB/s
Did 106000 AES-128-GCM (1350 bytes) seal operations in 1001573us (105833.5 ops/sec): 142.9 MB/s
Did 18000 AES-128-GCM (8192 bytes) seal operations in 1003895us (17930.2 ops/sec): 146.9 MB/s
Did 9000 AES-128-GCM (16384 bytes) seal operations in 1003352us (8969.9 ops/sec): 147.0 MB/s
After:
Did 2972000 AES-128-GCM (16 bytes) seal operations in 1000178us (2971471.1 ops/sec): 47.5 MB/s
Did 515000 AES-128-GCM (256 bytes) seal operations in 1001850us (514049.0 ops/sec): 131.6 MB/s
Did 108000 AES-128-GCM (1350 bytes) seal operations in 1004941us (107469.0 ops/sec): 145.1 MB/s
Did 19000 AES-128-GCM (8192 bytes) seal operations in 1034966us (18358.1 ops/sec): 150.4 MB/s
Did 9250 AES-128-GCM (16384 bytes) seal operations in 1005269us (9201.5 ops/sec): 150.8 MB/s

32-bit ARM without NEON
Before: (4bit armv4 asm)
Did 952000 AES-128-GCM (16 bytes) seal operations in 1001009us (951040.4 ops/sec): 15.2 MB/s
Did 152000 AES-128-GCM (256 bytes) seal operations in 1005576us (151157.1 ops/sec): 38.7 MB/s
Did 32000 AES-128-GCM (1350 bytes) seal operations in 1024522us (31234.1 ops/sec): 42.2 MB/s
Did 5290 AES-128-GCM (8192 bytes) seal operations in 1005335us (5261.9 ops/sec): 43.1 MB/s
Did 2650 AES-128-GCM (16384 bytes) seal operations in 1004396us (2638.4 ops/sec): 43.2 MB/s
After:
Did 540000 AES-128-GCM (16 bytes) seal operations in 1000009us (539995.1 ops/sec): 8.6 MB/s
Did 90000 AES-128-GCM (256 bytes) seal operations in 1000028us (89997.5 ops/sec): 23.0 MB/s
Did 19000 AES-128-GCM (1350 bytes) seal operations in 1022041us (18590.3 ops/sec): 25.1 MB/s
Did 3150 AES-128-GCM (8192 bytes) seal operations in 1003199us (3140.0 ops/sec): 25.7 MB/s
Did 1694 AES-128-GCM (16384 bytes) seal operations in 1076156us (1574.1 ops/sec): 25.8 MB/s
(Note fallback AES is dampening the perf hit.)

64-bit x86 with OPENSSL_ia32cap=0
Before: (4bit x86_64 asm)
Did 2615000 AES-128-GCM (16 bytes) seal operations in 1000220us (2614424.8 ops/sec): 41.8 MB/s
Did 431000 AES-128-GCM (256 bytes) seal operations in 1001250us (430461.9 ops/sec): 110.2 MB/s
Did 89000 AES-128-GCM (1350 bytes) seal operations in 1002209us (88803.8 ops/sec): 119.9 MB/s
Did 16000 AES-128-GCM (8192 bytes) seal operations in 1064535us (15030.0 ops/sec): 123.1 MB/s
Did 8261 AES-128-GCM (16384 bytes) seal operations in 1096787us (7532.0 ops/sec): 123.4 MB/s
After:
Did 2355000 AES-128-GCM (16 bytes) seal operations in 1000096us (2354773.9 ops/sec): 37.7 MB/s
Did 373000 AES-128-GCM (256 bytes) seal operations in 1000981us (372634.4 ops/sec): 95.4 MB/s
Did 77000 AES-128-GCM (1350 bytes) seal operations in 1003557us (76727.1 ops/sec): 103.6 MB/s
Did 13000 AES-128-GCM (8192 bytes) seal operations in 1003058us (12960.4 ops/sec): 106.2 MB/s
Did 7139 AES-128-GCM (16384 bytes) seal operations in 1099576us (6492.5 ops/sec): 106.4 MB/s
(Note fallback AES is dampening the perf hit. Pairing with AESNI to roughly
isolate GHASH shows a 40% hit.)

For comparison, this is what removing gcm_gmult_4bit_mmx would do.
32-bit x86 with OPENSSL_ia32cap=0
Before:
Did 2014000 AES-128-GCM (16 bytes) seal operations in 1000026us (2013947.6 ops/sec): 32.2 MB/s
Did 367000 AES-128-GCM (256 bytes) seal operations in 1000097us (366964.4 ops/sec): 93.9 MB/s
Did 77000 AES-128-GCM (1350 bytes) seal operations in 1002135us (76836.0 ops/sec): 103.7 MB/s
Did 13000 AES-128-GCM (8192 bytes) seal operations in 1011394us (12853.5 ops/sec): 105.3 MB/s
Did 7227 AES-128-GCM (16384 bytes) seal operations in 1099409us (6573.5 ops/sec): 107.7 MB/s
If gcm_gmult_4bit_mmx were replaced:
Did 1350000 AES-128-GCM (16 bytes) seal operations in 1000128us (1349827.2 ops/sec): 21.6 MB/s
Did 219000 AES-128-GCM (256 bytes) seal operations in 1000090us (218980.3 ops/sec): 56.1 MB/s
Did 46000 AES-128-GCM (1350 bytes) seal operations in 1017365us (45214.8 ops/sec): 61.0 MB/s
Did 8393 AES-128-GCM (8192 bytes) seal operations in 1115579us (7523.4 ops/sec): 61.6 MB/s
Did 3840 AES-128-GCM (16384 bytes) seal operations in 1001928us (3832.6 ops/sec): 62.8 MB/s
(Note fallback AES is dampening the perf hit. Pairing with AESNI to roughly
isolate GHASH shows a 73% hit. gcm_gmult_4bit_mmx is almost 4x as faster.)

Change-Id: Ib28c981e92e200b17fb9ddc89aef695ac6733a43
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38724
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-11-12 00:27:02 +00:00
Pete Bentley 98f969491c Conditionally define PTRACE_O_EXITKILL in urandom_test.cc
On older Linux distributions (e.g. Centos 7 which we still use for
Conscrypt releases) PTRACE_O_EXITKILL is defined in <linux/ptrace.h>
but this can't be included alongside <sys/ptrace.h> due to conflicting
defines, so this is the path of least resistance for portability.

Could also define this as 0 if undefined, but all distributions seem
to use 1<<20, and Centos 7 kernels should have support as they are 3.10
and later and PTRACE_O_EXITKILL was introduced around 3.8.

Change-Id: Ib8a6e0dbc62613e30c38a6cc09522c2d7b92577b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38704
Reviewed-by: Adam Langley <agl@google.com>
2019-11-08 15:49:37 +00:00
David Benjamin 43890dbd69 Fix build warning if _SCL_SECURE_NO_WARNINGS is defined globally
Thanks to shohei.yoshida@dena.jp for reporting the issue and providing
a patch.

Bug: 302
Change-Id: I1200a917ef4b791822712feafece19cb21988d55
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38684
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-11-07 16:09:13 +00:00
Adam Langley 279740ed8d modulewrapper: use a raw string.
The quoting in the JSON configuration string was getting a little out of
hand. Use a C++ raw string instead.

Change-Id: I568672480e967361f8269382f73e3c41bc71a0b7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38665
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-11-05 20:19:12 +00:00
Adam Langley d709b0d892 acvptool: add license headers.
Change-Id: I0da3e2a89cc502563d74dbbbdb0dddacfaaf5f9c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38664
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-11-05 20:01:21 +00:00
Matthew Braithwaite 58d56f4c59 Enable TLS 1.3 by default.
Update-Note: If calling code does not work with TLS 1.3, the simplest
fix is to call SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION).

Change-Id: Ic99861753dac117c52aea1988a6c4227a32984ca
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38624
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-11-05 19:44:12 +00:00
Gurleen Grewal 9294306578 acvptool: Add support for DRBG
Change-Id: Ia9dda0826787aea4d63536524074e343ff6c87d9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38644
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: Gurleen Grewal <gurleengrewal@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2019-11-05 19:29:15 +00:00
David Benjamin f0bdf5c9a1 Discard user_canceled alerts in TLS 1.3.
Warning alerts do not exist in TLS 1.3, but RFC 8446 section 6.1
continues to define user_canceled as a signal to cancel the handshake,
without specifying how to handle it. JDK11 misuses it to signal
full-duplex connection close after the handshake. As a workaround, skip
user_canceled as in TLS 1.2. This matches NSS and OpenSSL.

Bug: b/135941563
Change-Id: I7ef546f1f166741b9f112686c75e6757331948f0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38605
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-31 19:20:03 +00:00
David Benjamin 6be491b7bb Work around more C language bugs with empty spans.
C's specification text around pointer arithmetic is buggy and fails to
account for empty spans. Empty spans are typically represented as
ptr=NULL and len=0, so (T*)NULL + 0 must be defined for ptr + len to
reliably work. C++ does not have this bug and specifies this correctly.
See https://crbug.com/1019588.

This language bug has made its way over to newer versions of UBSan,
which enforce this. In the short term, add bogus length checks as a
workaround. However, unlike the memcpy language bug, we cannot address
this systematically. In the long term, we need to switch libcrypto to
building as C++ for a real fix.

To test this, update our clang revision to that in
https://chromium-review.googlesource.com/c/chromium/src/+/1879890. Note
that clang revision was later reverted in Chromium for seemingly
unrelated reasons.

This newer UBSan also catches a memcpy/OPENSSL_memcpy issue in
siphash.c, from the earlier C NULL bug we'd been working around.

Bug: chromium:1019588, chromium:1019644
Change-Id: I460e547c8cd740db68da8cc2a3a970276ec92e90
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38584
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2019-10-30 17:02:32 +00:00
David Benjamin bf7b331d1b No-op commit to test the new builder.
Change-Id: I9f29265715a784e0213425935421639d705cbe31
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38565
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-29 17:56:33 +00:00
Gurleen Grewal 2085c7c2c6 acvptool: Add support for HMAC
Change-Id: Ie3e3748cc1eb0e2f66ef052847179deaf0de239b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38544
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-28 18:45:59 +00:00
Shelley Vohr 706da620b2 Add stub functions for RSA-PSS keygen parameters.
These functions are used by Node.js in
https://github.com/nodejs/node/pull/26960. BoringSSL does not
support EVP_PKEY_RSA_PSS keys, so they always fail.

This simplifies building Node with BoringSSL.

Change-Id: I81c4cdba8791a60d965bc176d09e5c818153860c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38524
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-10-23 22:38:19 +00:00
Kris Kwiatkowski b11902a385 HelloRetryRequest getter
Adds getter indicating whether HelloRetryRequest was triggered
during TLSv1.3 handshake.

Change-Id: I84922188ded81ec89259b5f333c80494426759f8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/37304
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-10-23 21:26:29 +00:00
Adam Langley fe37af11a6 Add break-tests-android.sh script.
This addition duplicates the existing break-tests.sh script, but for the
Android context.

Change-Id: I54d0881e11231770978633f03af4bf9dc228611b
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38465
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-23 19:46:15 +00:00
Shelley Vohr 3ab3b1283f Add compatibility functions for sigalgs
Node.js recently added an option to override signature algorithms in https://github.com/nodejs/node/pull/29598
which make use of several NIDs and SSL_get_shared_sigalgs. This CL adds
NIDs for Ed448 (but does not implement it) and a shim function for
SSL_get_shared_sigalgs that simply returns 0. This enables Electron to
reduce its patch surface.

Change-Id: I833d30b0248ca68ebce4767dd58d5f087fd1e18e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38404
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-10-22 16:58:58 +00:00
Adam Langley de1d2881ae Run AES-192-GCM in CAVP tests.
Change-Id: I8fbba51ac650c648893fcd21da5c3018cd7810be
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38426
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-22 16:15:18 +00:00
David Benjamin 3ba9586bc0 Rename a number of BUF_* functions to OPENSSL_*.
Upstream did this in 7644a9aef8932ed4d1c3f25ed776c997702982be, so align
with them. Add the new OPENSSL_* names and switch all callers witihn the
library to match. Keep the old BUF_* names around for compatibility.

Note there were two functions where we already had an OPENSSL_* version:
OPENSSL_strdup and OPENSSL_strnlen. The former now gains a NULL check to
align with BUF_strdup. The latter gets deduplicated; we had two
implementations.

Change-Id: Ia1cd4527a752fcd62e142ed1e1d7768d323279ba
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38425
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-10-21 21:06:07 +00:00
Adam Langley 31f94b0bf7 List bn_div fuzzer in documentation.
c951e5560b added it back in the build, but it should be listed in
documentation too. Picked 384 bytes on the assumption that the largest
specialisation that we're likely to have is 1024-bit for RSA 2048.

Change-Id: I13fb46dceedb7a62616db6a2b39634a0b6fed508
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38444
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-21 16:29:53 +00:00
David Van Cleve c951e5560b Reenable bn_div fuzzer.
It looks like the bn_div fuzzer was inadvertently removed from
fuzz/'s CMakeLists during an earlier refactor [1]. This change
adds it back.

[1]: https://boringssl-review.googlesource.com/c/boringssl/+/31324/

Change-Id: I8bb4b224eedff60cc5cd6df7fa39d9c39d499a56
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38424
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-21 15:46:02 +00:00
Adam Langley 7f02881e96 Drop CECPQ2b code.
The experiment which motivated CECPQ2b has concluded (although the
results haven't been published yet) and the SIKE code is causing some
issues for gRPC in gprc/grpc#20100. Also, this is code size that takes
up space in Android etc.

Change-Id: I43b0b8c420f236c0fe9b40bf2517d2fde98495d5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38384
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-10-18 22:33:00 +00:00
Adam Langley 7de9498a88 Add urandom_test to all_tests.json
Change-Id: I4e30bc8b8c1bd1215f516a6c89735782cfbf8ef5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38284
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2019-10-18 21:44:29 +00:00
David Benjamin e481d94a6f Fix the standalone Android FIPS build.
Change-Id: Idce6c93f5a37e1f05afaa6fb928e15b92d75e911
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38365
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-18 21:21:29 +00:00
Adam Langley da8caf5b10 Add sanity checks to FIPS module construction.
If -ffunction-sections or -fdata-sections is enabled when doing a FIPS
shared build, the linker script won't do what's expected and will
silently end up including very little (or nothing) in the integrity
check.

This changes alters the linker script to discard any text or data
sections other than the main one, which should make this failure much
more obvious.

Also, add assertions (that are always enabled) in the module to check
that a few obvious things that should be inside the module boundaries
actually are.

Change-Id: I91178e213a28a7c0c4a38155974e452cd9d558d1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38324
Reviewed-by: Adam Langley <agl@google.com>
2019-10-18 20:37:54 +00:00
Adam Langley 20ae5e6f6c Correct relative path.
This path has always had one-too-few “..” elements since the file first
appeared, but everyone seems to have lived with it, presumably because
/include is in the search path and the compiler tries relative to that.

Change-Id: I30006209ad74d064ded5dd2cd34b1f14806dcffe
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38344
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2019-10-18 17:49:29 +00:00
Adam Langley 3e502c84f0 Add test for urandom.c
This change adds a test to try and prevent errors like b8f760191e. Since
it's challenging to test this code, it uses ptrace to capture a trace of
the PRNG behaviour and checks that the observed behaviour matches a much
smaller model of the code. The model is hopefully easier to read and
believe correct.

Change-Id: I00b811dc5692e2fbe3dcc16c622d4eb706f16ce0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38265
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-17 21:38:38 +00:00
Pete Bentley 76918d0164 break-hash.go: Search ELF dynamic symbols if symbols not found.
Allows the utility to work on shared libraries.

Also, don't printf the output from hex.Dump() as it may contain
formatting chars such as %.

Change-Id: I3c091436271c132417fd0212955a6575ef57af50
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38244
Reviewed-by: Adam Langley <agl@google.com>
2019-10-17 15:12:28 +00:00
Adam Langley 9709ad52eb Fix $OPENSSL_ia32cap handling.
The comment says that an "0x" prefix indicates a hex value. However we
always passed PRIu64 as the format specifier for |sscanf|, and |sscanf|
isn't documented to handle an 0x prefix expect for "i"-family format
specifiers. With |PRIu64|, |sscanf| reads any leading "0x" as just zero.

Instead, check for "0x" ourselves and use |PRIx64| if found to parse hex
values.

Change-Id: Id5ed7009d30902022e5ee640e8931bf1431dedc0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38264
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-16 21:25:03 +00:00
David Benjamin eec840da62 Switch probable_prime to rejection sampling.
This is much more straightforward, and aligns better with what our
actual RSA key generation logic does.

Change-Id: I45f368b10f42558b91c2d022847505ddab2f7094
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38170
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-15 22:06:37 +00:00
David Benjamin a93bebafb8 Rename the last remnants of the early_data_info extension.
The extension was renamed to just 'early_data' at some point in TLS
1.3's development.

Change-Id: I9d1de10aaeb347237b52a226e9533307f5c269ce
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38224
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
2019-10-15 21:24:17 +00:00
David Benjamin 31302a473a Fix up BN_GENCB_call calls.
Use the constants when defined. Also OpenSSL uses 0-indexed iteration
counts rather than 1-indexed. This likely changed when we tried to align
with the 1-indexed FIPS 186-4 algorithm.

Also fix the safe prime call. BN_GENCB_call(cb, i, c1 - 1) doesn't make
sense since the first parameter should be an event constant. OpenSSL
does BN_GENCB_call(cb, 2, c1 - 1).

This also doesn't make sense. OpenSSL documents 2 as meaning the prime
has been found. That function is interleaving the p and (p-1)/2 checks
to save the full iteration count on p if (p-1)/2 is composite anyway.

That also doesn't work because the blinding mechanism runs even if the
iteration count is 1, so we're actually paying for the blinding four
times. Add a TODO to address this.

(I can only assume we just never try to generate safe primes. Moreover,
we don't even use BN_generate_prime_ex in RSA keygen. Still, that
function needs work.)

Change-Id: I6f0b7cd10da28484362c92db0c806c1c3045d415
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38169
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-15 20:50:47 +00:00
David Benjamin a7a75f208c Do fewer trial divisions for larger RSA keygens.
Now that Miller-Rabin can reject composites faster, we can do fewer
trial divisions. Halving the table seems to improve things for RSA-3072
and RSA-4096. I left RSA-2048 alone since measurements with it halved
were a bit more of a wash.

(Although now that I've left it alone, it's gotten faster, so these
numbers are generally noisy.)

Before:
Did 320 RSA 2048 key-gen operations in 30132984us (10.6 ops/sec)
  min: 27703us, median: 81774us, max: 375687us
Did 84 RSA 3072 key-gen operations in 30166627us (2.8 ops/sec)
  min: 86961us, median: 322184us, max: 1170392us
Did 30 RSA 4096 key-gen operations in 30644802us (1.0 ops/sec)
  min: 260916us, median: 772364us, max: 2743435us

After:
Did 345 RSA 2048 key-gen operations in 30103781us (11.5 ops/sec)
  min: 23359us, median: 75033us, max: 267159us
Did 91 RSA 3072 key-gen operations in 30185495us (3.0 ops/sec)
  min: 72531us, median: 267385us, max: 1119039us
Did 38 RSA 4096 key-gen operations in 30473203us (1.2 ops/sec)
  min: 228529us, median: 720027us, max: 2039681us

Change-Id: I52d431347a70572034ced5b7778a2edac8f15173
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38168
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-15 20:29:17 +00:00
Adam Langley f3bd757ee5 Fix GRND_NONBLOCK flag when calling getrandom.
I screwed up in 56b6c714c9 and got the direction of this condition
backwards. This doesn't cause a security problem because:
  a) wait_for_entropy will ensure that the pool is initialised.
  b) if GRNG_NONBLOCK is set when not expected, any EAGAIN will
     cause an abort anyway.

However, when coupled with opportunistic entropy collection on platforms
with RDRAND, this could cause an unexpected blocking getrandom call.

This this change, `strace -e getrandom bssl rand 1` shows two getrandom
calls with GRNG_NONBLOCK set, as expected. (The first being the probe to
check whether the kernel supports getrandom, and the second being the
opportunistic entropy gathering to augment RDRAND.)

Change-Id: I98ed1cef90df510f24cf2df1fba9b886fcbf3355
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38204
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-15 20:00:07 +00:00
David Benjamin 642664838a Simplify bn_miller_rabin_iteration slightly.
We don't need both mask variables. If we know we have a composite
witness, we return immediately, so the only time we mask off
instructions is when we know we have a nonwitness.

Change-Id: I2b99f3114a79ce2dc1a37706835d2abfe93a716e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38167
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-15 19:34:44 +00:00
David Benjamin 841a40a276 Add some notes on RSA key generation performance.
Change-Id: I8c0cadddcfc7d8b14adbc3ed3b75332859deea42
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38166
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-15 18:56:16 +00:00
David Benjamin fba30c389c Break early on composites in the primality test.
|a| is usually much smaller than |w_bits|. We only need to loop up to
|w_bits| and hide |a| when the value is possibly composite. If
Miller-Rabin has not hit -1 by then, break early.

This speeds up RSA keygen by a bit.

Before:
Did 248 RSA 2048 key-gen operations in 30041496us (8.3 ops/sec)
  min: 31690us, median: 109097us, max: 373911us
Did 71 RSA 3072 key-gen operations in 30096719us (2.4 ops/sec)
  min: 108650us, median: 370844us, max: 1768070us
Did 27 RSA 4096 key-gen operations in 32829007us (0.8 ops/sec)
  min: 205485us, median: 1107051us, max: 4035040us

After:
Did 340 RSA 2048 key-gen operations in 30026342us (11.3 ops/sec)
  min: 24681us, median: 77749us, max: 350477us
Did 67 RSA 3072 key-gen operations in 30089075us (2.2 ops/sec)
  min: 75070us, median: 394220us, max: 1101562us
Did 38 RSA 4096 key-gen operations in 30283788us (1.3 ops/sec)
  min: 284947us, median: 742688us, max: 1970468us

Change-Id: If1b48e9306c3fe1be56c304143e206c3bdb3301d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38165
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-15 18:41:56 +00:00
David Benjamin 18d145e651 Extract and test the deterministic part of Miller-Rabin.
This way we test not only that we match expectations for primes and
composites but that the core test correctly reports false witnesses. I
made an initial attempt to gather some interesting test input, but
probably one can do better.

Change-Id: I7c29afb534bd6980ef42a893e86d86bd44af8349
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38164
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-15 18:31:36 +00:00
Adam Langley 5cf3298140 Fix the FIPS + fuzzing build.
Recent changes to the PRNG seeding in FIPS mode broke the build when
trying to build with both FIPS and fuzzing enabled.

Change-Id: I069b4af1fdd4efaef96e3e3b3a1e0197faabe2e1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38184
Reviewed-by: Matt Braithwaite <mab@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2019-10-14 21:32:23 +00:00
Adam Langley 2865bce1b2 FIPS.md: document some recent Android changes.
Change-Id: I48cc5fc6211a1a557cfeb1aad5688753bc7b5dfd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38124
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
2019-10-11 22:34:25 +00:00
1190 changed files with 498214 additions and 113511 deletions
+4
View File
@@ -4,4 +4,8 @@ AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
DerivePointerAlignment: false
PointerAlignment: Right
# TODO(davidben): The default for Google style is now Regroup, but the default
# IncludeCategories does not recognize <openssl/header.h>. We should
# reconfigure IncludeCategories to match. For now, keep it at Preserve.
IncludeBlocks: Preserve
+28 -10
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.3)
# Defer enabling C and CXX languages.
project(BoringSSL NONE)
@@ -387,6 +387,14 @@ if(FIPS)
set(FIPS_DELOCATE "1")
endif()
endif()
if(FIPS_SHARED)
# The Android CMake files set -ffunction-sections and -fdata-sections,
# which is incompatible with FIPS_SHARED.
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -fno-function-sections -fno-data-sections")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fno-function-sections -fno-data-sections")
endif()
endif()
if(OPENSSL_SMALL)
@@ -450,6 +458,10 @@ if(NOT OPENSSL_NO_ASM AND CMAKE_OSX_ARCHITECTURES)
list(GET CMAKE_OSX_ARCHITECTURES 0 CMAKE_SYSTEM_PROCESSOR)
endif()
if(OPENSSL_NO_SSE2_FOR_TESTING)
add_definitions(-DOPENSSL_NO_SSE2_FOR_TESTING)
endif()
if(OPENSSL_NO_ASM)
add_definitions(-DOPENSSL_NO_ASM)
set(ARCH "generic")
@@ -459,7 +471,7 @@ elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64")
set(ARCH "x86_64")
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
# cmake reports AMD64 on Windows, but we might be building for 32-bit.
if(CMAKE_CL_64)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH "x86_64")
else()
set(ARCH "x86")
@@ -561,10 +573,21 @@ include_directories(third_party/googletest/include)
# themselves as dependencies next to the target definition.
add_custom_target(all_tests)
# On Windows, CRYPTO_TEST_DATA is too long to fit in command-line limits.
# TODO(davidben): CMake 3.12 has a list(JOIN) command. Use that when we've
# updated the minimum version.
set(EMBED_TEST_DATA_ARGS "")
foreach(arg ${CRYPTO_TEST_DATA})
set(EMBED_TEST_DATA_ARGS "${EMBED_TEST_DATA_ARGS}${arg}\n")
endforeach()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/embed_test_data_args.txt"
"${EMBED_TEST_DATA_ARGS}")
add_custom_command(
OUTPUT crypto_test_data.cc
COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go ${CRYPTO_TEST_DATA} >
${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc
COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go -file-list
"${CMAKE_CURRENT_BINARY_DIR}/embed_test_data_args.txt" >
"${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc"
DEPENDS util/embed_test_data.go ${CRYPTO_TEST_DATA}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
@@ -590,11 +613,6 @@ if(FUZZ)
add_subdirectory(fuzz)
endif()
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.2")
# USES_TERMINAL is only available in CMake 3.2 or later.
set(MAYBE_USES_TERMINAL USES_TERMINAL)
endif()
if(UNIX AND NOT APPLE AND NOT ANDROID)
set(HANDSHAKER_ARGS "-handshaker-path" $<TARGET_FILE:handshaker>)
endif()
@@ -608,4 +626,4 @@ add_custom_target(
${HANDSHAKER_ARGS} ${RUNNER_ARGS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
DEPENDS all_tests bssl_shim handshaker
${MAYBE_USES_TERMINAL})
USES_TERMINAL)
+1
View File
@@ -26,6 +26,7 @@ The recommended values of `max_len` for each test are:
| Test | `max_len` value |
|---------------|-----------------|
| `bn_div` | 384 |
| `bn_mod_exp` | 4096 |
| `cert` | 10000 |
| `client` | 20000 |
-23
View File
@@ -181,29 +181,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The code in third_party/sike also carries the MIT license:
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
Licenses for support code
-------------------------
+1
View File
@@ -39,3 +39,4 @@ There are other files in this directory which might be helpful:
* [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
* [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL.
* [BREAKING-CHANGES.md](/BREAKING-CHANGES.md): notes on potentially-breaking changes.
* [SANDBOXING.md](/SANDBOXING.md): notes on using BoringSSL in a sandboxed environment.
+138
View File
@@ -0,0 +1,138 @@
# Using BoringSSL in a Sandbox
Sandboxes are a valuable tool for securing applications, so BoringSSL aims to
support them. However, it is difficult to make concrete API guarantees with
sandboxes. Sandboxes remove low-level OS resources and system calls, which
breaks platform abstractions. A syscall-filtering sandbox may, for instance, be
sensitive to otherwise non-breaking changes to use newer syscalls
in either BoringSSL or the C library.
Some functions in BoringSSL, such as `BIO_new_file`, inherently need OS
resources like the filesystem. We assume that sandboxed consumers either avoid
those functions or make necessary resources available. Other functions like
`RSA_sign` are purely computational, but still have some baseline OS
dependencies.
Sandboxes which drop privileges partway through a process's lifetime are
additionally sensitive to OS resources retained across the transitions. For
instance, if a library function internally opened and retained a handle to the
user's home directory, and then the application called `chroot`, that handle
would be a sandbox escape.
This document attempts to describe these baseline OS dependencies and long-lived
internal resources. These dependencies may change over time, but we aim to
[work with sandboxed consumers](/BREAKING-CHANGES.md) when they do. However,
each sandbox imposes different constraints, so, above all, sandboxed consumers
must have ample test coverage to detect issues as they arise.
## Baseline dependencies
Callers must assume that any BoringSSL function may perform one of the following
operations:
### Memory allocation
Any BoringSSL function may allocate memory via `malloc` and related functions.
### Thread synchronization
Any BoringSSL function may call into the platform's thread synchronization
primitives, including read/write locks and the equivalent of `pthread_once`.
These must succeed, or BoringSSL will abort the process. Callers, however, can
assume that BoringSSL functions will not spawn internal threads, unless
otherwise documented.
Syscall-filtering sandboxes should note that BoringSSL uses `pthread_rwlock_t`
on POSIX systems, which is less common and may not be part of other libraries'
syscall surface. Additionally, thread synchronization primitives usually have an
atomics-based fast path. If a sandbox blocks a necessary pthreads syscall, it
may not show up in testing without lock contention.
### Standard error
Any BoringSSL function may write to `stderr` or file descriptor
`STDERR_FILENO` (2), either via `FILE` APIs or low-level functions like `write`.
Writes to `stderr` may fail, but there must some file at `STDERR_FILENO` which
will tolerate error messages from BoringSSL. (The file descriptor must be
allocated so calls to `open` do not accidentally open something else there.)
Note some C standard library implementations also log to `stderr`, so callers
should ensure this regardless.
### Entropy
Any BoringSSL function may draw entropy from the OS. On Windows, this uses
`RtlGenRandom` and, on POSIX systems, this uses `getrandom`, `getentropy`, or a
`read` from a file descriptor to `/dev/urandom`. These operations must succeed
or BoringSSL will abort the process. BoringSSL only probes for `getrandom`
support once and assumes support is consistent for the lifetime of the address
space (and any copies made via `fork`). If a syscall-filtering sandbox is
enabled partway through this lifetime and changes whether `getrandom` works,
BoringSSL may abort the process. Sandboxes are recommended to allow
`getrandom`.
Note even deterministic algorithms may require OS entropy. For example,
RSASSA-PKCS1-v1_5 is deterministic, but BoringSSL draws entropy to implement
RSA blinding.
Entropy gathering additionally has some initialization dependencies described in
the following section.
## Initialization
BoringSSL has some uncommon OS dependencies which are only used once to
initialize some state. Sandboxes which drop privileges after some setup work may
use `CRYPTO_pre_sandbox_init` to initialize this state ahead of time. Otherwise,
callers must assume any BoringSSL function may depend on these resources, in
addition to the operations above.
### CPU capabilities
On Linux ARM platforms, BoringSSL depends on OS APIs to query CPU capabilities.
32-bit and 64-bit ARM both depend on the `getauxval` function. 32-bit ARM, to
work around bugs in older Android devices, may additionally read `/proc/cpuinfo`
and `/proc/self/auxv`.
If querying CPU capabilities fails, BoringSSL will still function, but may not
perform as well.
### Entropy
On Linux systems without a working `getrandom`, drawing entropy from the OS
additionally requires opening `/dev/urandom`. If this fails, BoringSSL will
abort the process. BoringSSL retains the resulting file descriptor, even across
privilege transitions.
### Fork protection
On Linux, BoringSSL allocates a page and calls `madvise` with `MADV_WIPEONFORK`
to protect single-use state from `fork`. This operation must not crash, but if
it fails, BoringSSL will use alternate fork-safety strategies, potentially at a
performance cost. If it succeeds, BoringSSL assumes `MADV_WIPEONFORK` is
functional and relies on it for fork-safety. Sandboxes must not report success
if they ignore the `MADV_WIPEONFORK` flag. As of writing, QEMU will ignore
`madvise` calls and report success, so BoringSSL detects this by calling
`madvise` with -1. Sandboxes must cleanly report an error instead of crashing.
Once initialized, this mechanism does not require system calls in the steady
state, though note the configured page will be inherited across privilege
transitions.
## C and C++ standard library
BoringSSL depends on the C and C++ standard libraries which, themselves, do not
make any guarantees about sandboxes. If it produces the correct answer and has
no observable invalid side effects, it is possible, though unreasonable, for
`memcmp` to create and close a socket.
BoringSSL assumes that functions in the C and C++ library only have the platform
dependencies which would be "reasonable". For instance, a function in BoringSSL
which aims not to open files will still freely call any libc memory and
string functions.
Note some C functions, such as `strerror`, may read files relating to the user's
locale. BoringSSL may trigger these paths and assumes the sandbox environment
will tolerate this. BoringSSL additionally cannot make guarantees about which
system calls are used by standard library's syscall wrappers. In some cases, the
compiler may add dependencies. (Some C++ language features emit locking code.)
Syscall-filtering sandboxes may need updates as these dependencies change.
+33 -12
View File
@@ -115,7 +115,14 @@ if(${ARCH} STREQUAL "aarch64")
chacha/chacha-armv8.${ASM_EXT}
test/trampoline-armv8.${ASM_EXT}
third_party/sike/asm/fp-armv8.${ASM_EXT}
)
endif()
if(${ARCH} STREQUAL "ppc64le")
set(
CRYPTO_ARCH_SOURCES
test/trampoline-ppc.${ASM_EXT}
)
endif()
@@ -137,7 +144,6 @@ if(${ARCH} STREQUAL "x86_64")
cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT}
hrss/asm/poly_rq_mul.S
test/trampoline-x86_64.${ASM_EXT}
third_party/sike/asm/fp-x86_64.${ASM_EXT}
)
endif()
@@ -147,10 +153,9 @@ perlasm(chacha/chacha-x86.${ASM_EXT} chacha/asm/chacha-x86.pl)
perlasm(chacha/chacha-x86_64.${ASM_EXT} chacha/asm/chacha-x86_64.pl)
perlasm(cipher_extra/aes128gcmsiv-x86_64.${ASM_EXT} cipher_extra/asm/aes128gcmsiv-x86_64.pl)
perlasm(cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT} cipher_extra/asm/chacha20_poly1305_x86_64.pl)
perlasm(third_party/sike/asm/fp-x86_64.${ASM_EXT} ../third_party/sike/asm/fp-x86_64.pl)
perlasm(third_party/sike/asm/fp-armv8.${ASM_EXT} ../third_party/sike/asm/fp-armv8.pl)
perlasm(test/trampoline-armv4.${ASM_EXT} test/asm/trampoline-armv4.pl)
perlasm(test/trampoline-armv8.${ASM_EXT} test/asm/trampoline-armv8.pl)
perlasm(test/trampoline-ppc.${ASM_EXT} test/asm/trampoline-ppc.pl)
perlasm(test/trampoline-x86.${ASM_EXT} test/asm/trampoline-x86.pl)
perlasm(test/trampoline-x86_64.${ASM_EXT} test/asm/trampoline-x86_64.pl)
@@ -179,6 +184,7 @@ add_custom_command(
err/pkcs8.errordata
err/rsa.errordata
err/ssl.errordata
err/trust_token.errordata
err/x509.errordata
err/x509v3.errordata
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/err
@@ -257,6 +263,7 @@ add_library(
cpu-intel.c
cpu-ppc64le.c
crypto.c
curve25519/curve25519.c
curve25519/spake25519.c
dh/dh.c
dh/params.c
@@ -269,6 +276,7 @@ add_library(
ecdsa_extra/ecdsa_asn1.c
ec_extra/ec_asn1.c
ec_extra/ec_derive.c
ec_extra/hash_to_curve.c
err/err.c
err_data.c
engine/engine.c
@@ -291,6 +299,7 @@ add_library(
evp/sign.c
ex_data.c
hkdf/hkdf.c
hpke/hpke.c
hrss/hrss.c
lhash/lhash.c
mem.c
@@ -329,6 +338,8 @@ add_library(
thread_none.c
thread_pthread.c
thread_win.c
trust_token/pmbtoken.c
trust_token/trust_token.c
x509/a_digest.c
x509/a_sign.c
x509/a_strex.c
@@ -411,12 +422,6 @@ add_library(
x509v3/v3_skey.c
x509v3/v3_sxnet.c
x509v3/v3_utl.c
../third_party/fiat/curve25519.c
../third_party/sike/fpx.c
../third_party/sike/isogeny.c
../third_party/sike/curve_params.c
../third_party/sike/sike.c
../third_party/sike/asm/fp_generic.c
$<TARGET_OBJECTS:fipsmodule>
@@ -452,7 +457,7 @@ endif()
SET_TARGET_PROPERTIES(crypto PROPERTIES LINKER_LANGUAGE C)
if(NOT MSVC AND NOT ANDROID)
if(NOT WIN32 AND NOT ANDROID)
target_link_libraries(crypto pthread)
endif()
@@ -462,6 +467,20 @@ if(USE_CUSTOM_LIBCXX)
target_link_libraries(crypto libcxx)
endif()
# urandom_test is a separate binary because it needs to be able to observe the
# PRNG initialisation, which means that it can't have other tests running before
# it does.
add_executable(
urandom_test
fipsmodule/rand/urandom_test.cc
)
target_link_libraries(urandom_test test_support_lib boringssl_gtest crypto)
add_dependencies(urandom_test global_target)
add_dependencies(all_tests urandom_test)
add_executable(
crypto_test
@@ -498,8 +517,10 @@ add_executable(
fipsmodule/md5/md5_test.cc
fipsmodule/modes/gcm_test.cc
fipsmodule/rand/ctrdrbg_test.cc
fipsmodule/rand/fork_detect_test.cc
fipsmodule/sha/sha_test.cc
hkdf/hkdf_test.cc
hpke/hpke_test.cc
hmac_extra/hmac_test.cc
hrss/hrss_test.cc
impl_dispatch_test.cc
@@ -519,11 +540,11 @@ add_executable(
siphash/siphash_test.cc
test/file_test_gtest.cc
thread_test.cc
trust_token/trust_token_test.cc
x509/x509_test.cc
x509/x509_time_test.cc
x509v3/tab_test.cc
x509v3/v3name_test.cc
../third_party/sike/sike_test.cc
$<TARGET_OBJECTS:crypto_test_data>
$<TARGET_OBJECTS:boringssl_gtest_main>
+286 -1
View File
@@ -341,7 +341,6 @@ TEST(ABITest, ARM) {
}
#endif // OPENSSL_ARM && SUPPORTS_ABI_TEST
#if defined(OPENSSL_AARCH64) && defined(SUPPORTS_ABI_TEST)
extern "C" {
void abi_test_clobber_x0(void);
@@ -521,3 +520,289 @@ TEST(ABITest, AArch64) {
CHECK_ABI_NO_UNWIND(abi_test_clobber_v15_upper);
}
#endif // OPENSSL_AARCH64 && SUPPORTS_ABI_TEST
#if defined(OPENSSL_PPC64LE) && defined(SUPPORTS_ABI_TEST)
extern "C" {
void abi_test_clobber_r0(void);
// r1 is the stack pointer.
void abi_test_clobber_r2(void);
void abi_test_clobber_r3(void);
void abi_test_clobber_r4(void);
void abi_test_clobber_r5(void);
void abi_test_clobber_r6(void);
void abi_test_clobber_r7(void);
void abi_test_clobber_r8(void);
void abi_test_clobber_r9(void);
void abi_test_clobber_r10(void);
void abi_test_clobber_r11(void);
void abi_test_clobber_r12(void);
// r13 is the thread pointer.
void abi_test_clobber_r14(void);
void abi_test_clobber_r15(void);
void abi_test_clobber_r16(void);
void abi_test_clobber_r17(void);
void abi_test_clobber_r18(void);
void abi_test_clobber_r19(void);
void abi_test_clobber_r20(void);
void abi_test_clobber_r21(void);
void abi_test_clobber_r22(void);
void abi_test_clobber_r23(void);
void abi_test_clobber_r24(void);
void abi_test_clobber_r25(void);
void abi_test_clobber_r26(void);
void abi_test_clobber_r27(void);
void abi_test_clobber_r28(void);
void abi_test_clobber_r29(void);
void abi_test_clobber_r30(void);
void abi_test_clobber_r31(void);
void abi_test_clobber_f0(void);
void abi_test_clobber_f1(void);
void abi_test_clobber_f2(void);
void abi_test_clobber_f3(void);
void abi_test_clobber_f4(void);
void abi_test_clobber_f5(void);
void abi_test_clobber_f6(void);
void abi_test_clobber_f7(void);
void abi_test_clobber_f8(void);
void abi_test_clobber_f9(void);
void abi_test_clobber_f10(void);
void abi_test_clobber_f11(void);
void abi_test_clobber_f12(void);
void abi_test_clobber_f13(void);
void abi_test_clobber_f14(void);
void abi_test_clobber_f15(void);
void abi_test_clobber_f16(void);
void abi_test_clobber_f17(void);
void abi_test_clobber_f18(void);
void abi_test_clobber_f19(void);
void abi_test_clobber_f20(void);
void abi_test_clobber_f21(void);
void abi_test_clobber_f22(void);
void abi_test_clobber_f23(void);
void abi_test_clobber_f24(void);
void abi_test_clobber_f25(void);
void abi_test_clobber_f26(void);
void abi_test_clobber_f27(void);
void abi_test_clobber_f28(void);
void abi_test_clobber_f29(void);
void abi_test_clobber_f30(void);
void abi_test_clobber_f31(void);
void abi_test_clobber_v0(void);
void abi_test_clobber_v1(void);
void abi_test_clobber_v2(void);
void abi_test_clobber_v3(void);
void abi_test_clobber_v4(void);
void abi_test_clobber_v5(void);
void abi_test_clobber_v6(void);
void abi_test_clobber_v7(void);
void abi_test_clobber_v8(void);
void abi_test_clobber_v9(void);
void abi_test_clobber_v10(void);
void abi_test_clobber_v11(void);
void abi_test_clobber_v12(void);
void abi_test_clobber_v13(void);
void abi_test_clobber_v14(void);
void abi_test_clobber_v15(void);
void abi_test_clobber_v16(void);
void abi_test_clobber_v17(void);
void abi_test_clobber_v18(void);
void abi_test_clobber_v19(void);
void abi_test_clobber_v20(void);
void abi_test_clobber_v21(void);
void abi_test_clobber_v22(void);
void abi_test_clobber_v23(void);
void abi_test_clobber_v24(void);
void abi_test_clobber_v25(void);
void abi_test_clobber_v26(void);
void abi_test_clobber_v27(void);
void abi_test_clobber_v28(void);
void abi_test_clobber_v29(void);
void abi_test_clobber_v30(void);
void abi_test_clobber_v31(void);
void abi_test_clobber_cr0(void);
void abi_test_clobber_cr1(void);
void abi_test_clobber_cr2(void);
void abi_test_clobber_cr3(void);
void abi_test_clobber_cr4(void);
void abi_test_clobber_cr5(void);
void abi_test_clobber_cr6(void);
void abi_test_clobber_cr7(void);
void abi_test_clobber_ctr(void);
void abi_test_clobber_lr(void);
} // extern "C"
TEST(ABITest, PPC64LE) {
// abi_test_trampoline hides unsaved registers from the caller, so we can
// safely call the abi_test_clobber_* functions below.
abi_test::internal::CallerState state;
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state));
CHECK_ABI_NO_UNWIND(abi_test_trampoline,
reinterpret_cast<crypto_word_t>(abi_test_clobber_r14),
&state, nullptr, 0, 0 /* no breakpoint */);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r0);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r2);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r3);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r4);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r5);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r6);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r7);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r8);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r9);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r10);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r11);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r12);
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r14),
"r14 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r15),
"r15 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r16),
"r16 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r17),
"r17 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r18),
"r18 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r19),
"r19 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r20),
"r20 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r21),
"r21 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r22),
"r22 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r23),
"r23 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r24),
"r24 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r25),
"r25 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r26),
"r26 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r27),
"r27 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r28),
"r28 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r29),
"r29 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r30),
"r30 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r31),
"r31 was not restored after return");
CHECK_ABI_NO_UNWIND(abi_test_clobber_f0);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f1);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f2);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f3);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f4);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f5);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f6);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f7);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f8);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f9);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f10);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f11);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f12);
CHECK_ABI_NO_UNWIND(abi_test_clobber_f13);
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f14),
"f14 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f15),
"f15 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f16),
"f16 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f17),
"f17 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f18),
"f18 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f19),
"f19 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f20),
"f20 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f21),
"f21 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f22),
"f22 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f23),
"f23 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f24),
"f24 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f25),
"f25 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f26),
"f26 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f27),
"f27 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f28),
"f28 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f29),
"f29 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f30),
"f30 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f31),
"f31 was not restored after return");
CHECK_ABI_NO_UNWIND(abi_test_clobber_v0);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v1);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v2);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v3);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v4);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v5);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v6);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v7);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v8);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v9);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v10);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v11);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v12);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v13);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v14);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v15);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v16);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v17);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v18);
CHECK_ABI_NO_UNWIND(abi_test_clobber_v19);
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v20),
"v20 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v21),
"v21 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v22),
"v22 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v23),
"v23 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v24),
"v24 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v25),
"v25 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v26),
"v26 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v27),
"v27 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v28),
"v28 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v29),
"v29 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v30),
"v30 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v31),
"v31 was not restored after return");
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr0);
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr1);
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr2),
"cr was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr3),
"cr was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr4),
"cr was not restored after return");
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr5);
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr6);
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr7);
CHECK_ABI_NO_UNWIND(abi_test_clobber_ctr);
CHECK_ABI_NO_UNWIND(abi_test_clobber_lr);
}
#endif // OPENSSL_PPC64LE && SUPPORTS_ABI_TEST
+3 -3
View File
@@ -70,7 +70,7 @@ int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
return M_ASN1_BIT_STRING_set(x, d, len);
}
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp)
{
int ret, j, bits, len;
unsigned char *p, *d;
@@ -233,7 +233,7 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
return (1);
}
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
{
int w, v;
@@ -250,7 +250,7 @@ int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a,
unsigned char *flags, int flags_len)
{
int i, ok;
+3 -3
View File
@@ -108,7 +108,7 @@ int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
return (1);
}
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a)
{
int neg = 0, i;
@@ -147,7 +147,7 @@ long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
return r;
}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
{
ASN1_ENUMERATED *ret;
int len, j;
@@ -183,7 +183,7 @@ ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
return (NULL);
}
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
{
BIGNUM *ret;
+1 -1
View File
@@ -115,7 +115,7 @@ int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
* followed by optional zeros isn't padded.
*/
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
int i2c_ASN1_INTEGER(const ASN1_INTEGER *a, unsigned char **pp)
{
int pad = 0, ret, i, neg;
unsigned char *p, *n, pb = 0;
+3 -3
View File
@@ -66,7 +66,7 @@
#include "../internal.h"
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
{
unsigned char *p, *allocated = NULL;
int objsize;
@@ -98,12 +98,12 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
return objsize;
}
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
}
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
{
char buf[80], *p = buf;
int i;
+5 -6
View File
@@ -60,7 +60,6 @@
#include <time.h>
#include <openssl/asn1t.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -101,7 +100,7 @@ ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
}
int ASN1_TIME_check(ASN1_TIME *t)
int ASN1_TIME_check(const ASN1_TIME *t)
{
if (t->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_check(t);
@@ -111,7 +110,7 @@ int ASN1_TIME_check(ASN1_TIME *t)
}
/* Convert an ASN1_TIME structure to GeneralizedTime */
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret = NULL;
@@ -143,11 +142,11 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
str = (char *)ret->data;
/* Work out the century and prepend */
if (t->data[0] >= '5')
BUF_strlcpy(str, "19", newlen);
OPENSSL_strlcpy(str, "19", newlen);
else
BUF_strlcpy(str, "20", newlen);
OPENSSL_strlcpy(str, "20", newlen);
BUF_strlcat(str, (char *)t->data, newlen);
OPENSSL_strlcat(str, (char *)t->data, newlen);
done:
if (out != NULL && *out == NULL)
+1 -1
View File
@@ -61,7 +61,7 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
int ASN1_TYPE_get(ASN1_TYPE *a)
int ASN1_TYPE_get(const ASN1_TYPE *a)
{
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
return (a->type);
+1 -1
View File
@@ -430,7 +430,7 @@ void ASN1_STRING_length_set(ASN1_STRING *x, int len)
return;
}
int ASN1_STRING_type(ASN1_STRING *x)
int ASN1_STRING_type(const ASN1_STRING *x)
{
return M_ASN1_STRING_type(x);
}
+1 -1
View File
@@ -174,7 +174,7 @@ TEST(ASN1Test, SerializeObject) {
static const uint8_t kDER[] = {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01};
const ASN1_OBJECT *obj = OBJ_nid2obj(NID_rsaEncryption);
TestSerialize(const_cast<ASN1_OBJECT *>(obj), i2d_ASN1_OBJECT, kDER);
TestSerialize(obj, i2d_ASN1_OBJECT, kDER);
}
TEST(ASN1Test, SerializeBoolean) {
+1 -1
View File
@@ -93,7 +93,7 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
{
const unsigned char *p;
void *ret;
+1 -1
View File
@@ -60,7 +60,7 @@
/* Based on a_int.c: equivalent ENUMERATED functions */
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
+1 -1
View File
@@ -58,7 +58,7 @@
#include <openssl/bio.h>
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
+1 -1
View File
@@ -58,7 +58,7 @@
#include <openssl/bio.h>
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
+3 -4
View File
@@ -74,7 +74,6 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -149,7 +148,7 @@ static int split_host_and_port(char **out_host, char **out_port, const char *nam
}
}
*out_host = BUF_strndup(host, host_len);
*out_host = OPENSSL_strndup(host, host_len);
if (*out_host == NULL) {
return 0;
}
@@ -429,13 +428,13 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
bio->init = 1;
if (num == 0) {
OPENSSL_free(data->param_hostname);
data->param_hostname = BUF_strdup(ptr);
data->param_hostname = OPENSSL_strdup(ptr);
if (data->param_hostname == NULL) {
ret = 0;
}
} else if (num == 1) {
OPENSSL_free(data->param_port);
data->param_port = BUF_strdup(ptr);
data->param_port = OPENSSL_strdup(ptr);
if (data->param_port == NULL) {
ret = 0;
}
-1
View File
@@ -70,7 +70,6 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+5 -6
View File
@@ -79,7 +79,6 @@
#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -208,16 +207,16 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
b->shutdown = (int)num & BIO_CLOSE;
if (num & BIO_FP_APPEND) {
if (num & BIO_FP_READ) {
BUF_strlcpy(p, "a+", sizeof(p));
OPENSSL_strlcpy(p, "a+", sizeof(p));
} else {
BUF_strlcpy(p, "a", sizeof(p));
OPENSSL_strlcpy(p, "a", sizeof(p));
}
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) {
BUF_strlcpy(p, "r+", sizeof(p));
OPENSSL_strlcpy(p, "r+", sizeof(p));
} else if (num & BIO_FP_WRITE) {
BUF_strlcpy(p, "w", sizeof(p));
OPENSSL_strlcpy(p, "w", sizeof(p));
} else if (num & BIO_FP_READ) {
BUF_strlcpy(p, "r", sizeof(p));
OPENSSL_strlcpy(p, "r", sizeof(p));
} else {
OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE);
ret = 0;
-1
View File
@@ -55,7 +55,6 @@
#include <assert.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+10 -69
View File
@@ -132,6 +132,10 @@ size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
}
int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
// Work around a C language bug. See https://crbug.com/1019588.
if (len == 0) {
return 1;
}
size_t new_len = buf->length + len;
if (new_len < len) {
OPENSSL_PUT_ERROR(BUF, ERR_R_OVERFLOW);
@@ -145,87 +149,24 @@ int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
return 1;
}
char *BUF_strdup(const char *str) {
if (str == NULL) {
return NULL;
}
return BUF_strndup(str, strlen(str));
}
char *BUF_strdup(const char *str) { return OPENSSL_strdup(str); }
size_t BUF_strnlen(const char *str, size_t max_len) {
size_t i;
for (i = 0; i < max_len; i++) {
if (str[i] == 0) {
break;
}
}
return i;
return OPENSSL_strnlen(str, max_len);
}
char *BUF_strndup(const char *str, size_t size) {
char *ret;
size_t alloc_size;
if (str == NULL) {
return NULL;
}
size = BUF_strnlen(str, size);
alloc_size = size + 1;
if (alloc_size < size) {
// overflow
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret = OPENSSL_malloc(alloc_size);
if (ret == NULL) {
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_memcpy(ret, str, size);
ret[size] = '\0';
return ret;
return OPENSSL_strndup(str, size);
}
size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size) {
size_t l = 0;
for (; dst_size > 1 && *src; dst_size--) {
*dst++ = *src++;
l++;
}
if (dst_size) {
*dst = 0;
}
return l + strlen(src);
return OPENSSL_strlcpy(dst, src, dst_size);
}
size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) {
size_t l = 0;
for (; dst_size > 0 && *dst; dst_size--, dst++) {
l++;
}
return l + BUF_strlcpy(dst, src, dst_size);
return OPENSSL_strlcat(dst, src, dst_size);
}
void *BUF_memdup(const void *data, size_t size) {
if (size == 0) {
return NULL;
}
void *ret = OPENSSL_malloc(size);
if (ret == NULL) {
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_memcpy(ret, data, size);
return ret;
return OPENSSL_memdup(data, size);
}
+87 -1
View File
@@ -67,6 +67,14 @@ TEST(CBSTest, GetUint) {
EXPECT_EQ(0x13u, u8);
EXPECT_FALSE(CBS_get_u8(&data, &u8));
EXPECT_FALSE(CBS_get_last_u8(&data, &u8));
CBS_init(&data, kData, sizeof(kData));
ASSERT_TRUE(CBS_get_u16le(&data, &u16));
EXPECT_EQ(0x0201u, u16);
ASSERT_TRUE(CBS_get_u32le(&data, &u32));
EXPECT_EQ(0x06050403u, u32);
ASSERT_TRUE(CBS_get_u64le(&data, &u64));
EXPECT_EQ(0x0e0d0c0b0a090807u, u64);
}
TEST(CBSTest, GetPrefixed) {
@@ -316,7 +324,9 @@ TEST(CBBTest, InitUninitialized) {
TEST(CBBTest, Basic) {
static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7,
8, 9, 0xa, 0xb, 0xc, 0xd, 0xe,
0xf, 0x10, 0x11, 0x12, 0x13, 0x14};
0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 3, 2,
10, 9, 8, 7, 0x12, 0x11, 0x10,
0xf, 0xe, 0xd, 0xc, 0xb};
uint8_t *buf;
size_t buf_len;
@@ -331,6 +341,9 @@ TEST(CBBTest, Basic) {
ASSERT_TRUE(CBB_add_u32(cbb.get(), 0x708090a));
ASSERT_TRUE(CBB_add_u64(cbb.get(), 0xb0c0d0e0f101112));
ASSERT_TRUE(CBB_add_bytes(cbb.get(), (const uint8_t *)"\x13\x14", 2));
ASSERT_TRUE(CBB_add_u16le(cbb.get(), 0x203));
ASSERT_TRUE(CBB_add_u32le(cbb.get(), 0x708090a));
ASSERT_TRUE(CBB_add_u64le(cbb.get(), 0xb0c0d0e0f101112));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
bssl::UniquePtr<uint8_t> scoper(buf);
@@ -754,6 +767,79 @@ TEST(CBSTest, ASN1Uint64) {
}
}
struct ASN1Int64Test {
int64_t value;
const char *encoding;
size_t encoding_len;
};
static const ASN1Int64Test kASN1Int64Tests[] = {
{0, "\x02\x01\x00", 3},
{1, "\x02\x01\x01", 3},
{-1, "\x02\x01\xff", 3},
{127, "\x02\x01\x7f", 3},
{-127, "\x02\x01\x81", 3},
{128, "\x02\x02\x00\x80", 4},
{-128, "\x02\x01\x80", 3},
{129, "\x02\x02\x00\x81", 4},
{-129, "\x02\x02\xff\x7f", 4},
{0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
{INT64_C(0x0102030405060708), "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08",
10},
{INT64_MIN, "\x02\x08\x80\x00\x00\x00\x00\x00\x00\x00", 10},
{INT64_MAX, "\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff", 10},
};
struct ASN1InvalidInt64Test {
const char *encoding;
size_t encoding_len;
};
static const ASN1InvalidInt64Test kASN1InvalidInt64Tests[] = {
// Bad tag.
{"\x03\x01\x00", 3},
// Empty contents.
{"\x02\x00", 2},
// Overflow.
{"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
// Leading zeros.
{"\x02\x02\x00\x01", 4},
// Leading 0xff.
{"\x02\x02\xff\xff", 4},
};
TEST(CBSTest, ASN1Int64) {
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Int64Tests); i++) {
SCOPED_TRACE(i);
const ASN1Int64Test *test = &kASN1Int64Tests[i];
CBS cbs;
int64_t value;
uint8_t *out;
size_t len;
CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
ASSERT_TRUE(CBS_get_asn1_int64(&cbs, &value));
EXPECT_EQ(0u, CBS_len(&cbs));
EXPECT_EQ(test->value, value);
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1_int64(cbb.get(), test->value));
ASSERT_TRUE(CBB_finish(cbb.get(), &out, &len));
bssl::UniquePtr<uint8_t> scoper(out);
EXPECT_EQ(Bytes(test->encoding, test->encoding_len), Bytes(out, len));
}
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1InvalidInt64Tests); i++) {
const ASN1InvalidInt64Test *test = &kASN1InvalidInt64Tests[i];
CBS cbs;
int64_t value;
CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
EXPECT_FALSE(CBS_get_asn1_int64(&cbs, &value));
}
}
TEST(CBBTest, Zero) {
CBB cbb;
CBB_zero(&cbb);
+41 -2
View File
@@ -18,7 +18,6 @@
#include <limits.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/mem.h>
#include "../internal.h"
@@ -448,6 +447,10 @@ int CBB_add_u16(CBB *cbb, uint16_t value) {
return cbb_buffer_add_u(cbb->base, value, 2);
}
int CBB_add_u16le(CBB *cbb, uint16_t value) {
return CBB_add_u16(cbb, CRYPTO_bswap2(value));
}
int CBB_add_u24(CBB *cbb, uint32_t value) {
if (!CBB_flush(cbb)) {
return 0;
@@ -464,6 +467,10 @@ int CBB_add_u32(CBB *cbb, uint32_t value) {
return cbb_buffer_add_u(cbb->base, value, 4);
}
int CBB_add_u32le(CBB *cbb, uint32_t value) {
return CBB_add_u32(cbb, CRYPTO_bswap4(value));
}
int CBB_add_u64(CBB *cbb, uint64_t value) {
if (!CBB_flush(cbb)) {
return 0;
@@ -471,6 +478,10 @@ int CBB_add_u64(CBB *cbb, uint64_t value) {
return cbb_buffer_add_u(cbb->base, value, 8);
}
int CBB_add_u64le(CBB *cbb, uint64_t value) {
return CBB_add_u64(cbb, CRYPTO_bswap8(value));
}
void CBB_discard_child(CBB *cbb) {
if (cbb->child == NULL) {
return;
@@ -517,6 +528,34 @@ int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
return CBB_flush(cbb);
}
int CBB_add_asn1_int64(CBB *cbb, int64_t value) {
if (value >= 0) {
return CBB_add_asn1_uint64(cbb, value);
}
union {
int64_t i;
uint8_t bytes[sizeof(int64_t)];
} u;
u.i = value;
int start = 7;
// Skip leading sign-extension bytes unless they are necessary.
while (start > 0 && (u.bytes[start] == 0xff && (u.bytes[start - 1] & 0x80))) {
start--;
}
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
return 0;
}
for (int i = start; i >= 0; i--) {
if (!CBB_add_u8(&child, u.bytes[i])) {
return 0;
}
}
return CBB_flush(cbb);
}
int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) {
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) ||
@@ -649,7 +688,7 @@ int CBB_flush_asn1_set_of(CBB *cbb) {
// remain valid as we rewrite |cbb|.
int ret = 0;
size_t buf_len = CBB_len(cbb);
uint8_t *buf = BUF_memdup(CBB_data(cbb), buf_len);
uint8_t *buf = OPENSSL_memdup(CBB_data(cbb), buf_len);
CBS *children = OPENSSL_malloc(num_children * sizeof(CBS));
if (buf == NULL || children == NULL) {
goto err;
+60 -3
View File
@@ -12,7 +12,6 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/buf.h>
#include <openssl/mem.h>
#include <openssl/bytestring.h>
@@ -61,7 +60,7 @@ int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
if (cbs->len == 0) {
return 1;
}
*out_ptr = BUF_memdup(cbs->data, cbs->len);
*out_ptr = OPENSSL_memdup(cbs->data, cbs->len);
if (*out_ptr == NULL) {
return 0;
}
@@ -73,7 +72,7 @@ int CBS_strdup(const CBS *cbs, char **out_ptr) {
if (*out_ptr != NULL) {
OPENSSL_free(*out_ptr);
}
*out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
*out_ptr = OPENSSL_strndup((const char*)cbs->data, cbs->len);
return (*out_ptr != NULL);
}
@@ -121,6 +120,14 @@ int CBS_get_u16(CBS *cbs, uint16_t *out) {
return 1;
}
int CBS_get_u16le(CBS *cbs, uint16_t *out) {
if (!CBS_get_u16(cbs, out)) {
return 0;
}
*out = CRYPTO_bswap2(*out);
return 1;
}
int CBS_get_u24(CBS *cbs, uint32_t *out) {
uint64_t v;
if (!cbs_get_u(cbs, &v, 3)) {
@@ -139,10 +146,26 @@ int CBS_get_u32(CBS *cbs, uint32_t *out) {
return 1;
}
int CBS_get_u32le(CBS *cbs, uint32_t *out) {
if (!CBS_get_u32(cbs, out)) {
return 0;
}
*out = CRYPTO_bswap4(*out);
return 1;
}
int CBS_get_u64(CBS *cbs, uint64_t *out) {
return cbs_get_u(cbs, out, 8);
}
int CBS_get_u64le(CBS *cbs, uint64_t *out) {
if (!cbs_get_u(cbs, out, 8)) {
return 0;
}
*out = CRYPTO_bswap8(*out);
return 1;
}
int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
if (cbs->len == 0) {
return 0;
@@ -438,6 +461,40 @@ int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
return 1;
}
int CBS_get_asn1_int64(CBS *cbs, int64_t *out) {
CBS bytes;
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
return 0;
}
const uint8_t *data = CBS_data(&bytes);
const size_t len = CBS_len(&bytes);
if (len == 0 || len > sizeof(int64_t)) {
// An INTEGER is encoded with at least one octet.
return 0;
}
if (len > 1) {
if (data[0] == 0 && (data[1] & 0x80) == 0) {
return 0; // Extra leading zeros.
}
if (data[0] == 0xff && (data[1] & 0x80) != 0) {
return 0; // Extra leading 0xff.
}
}
union {
int64_t i;
uint8_t bytes[sizeof(int64_t)];
} u;
const int is_negative = (data[0] & 0x80);
memset(u.bytes, is_negative ? 0xff : 0, sizeof(u.bytes)); // Sign-extend.
for (size_t i = 0; i < len; i++) {
u.bytes[i] = data[len - i - 1];
}
*out = u.i;
return 1;
}
int CBS_get_asn1_bool(CBS *cbs, int *out) {
CBS bytes;
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) ||
+104 -9
View File
@@ -25,6 +25,7 @@
#include "../fipsmodule/cipher/internal.h"
#include "../internal.h"
#include "../test/abi_test.h"
#include "../test/file_test.h"
#include "../test/test_util.h"
#include "../test/wycheproof_util.h"
@@ -542,10 +543,10 @@ TEST_P(PerAEADTest, AliasedBuffers) {
}
TEST_P(PerAEADTest, UnalignedInput) {
alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH + 1];
alignas(64) uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH + 1];
alignas(64) uint8_t plaintext[32 + 1];
alignas(64) uint8_t ad[32 + 1];
alignas(16) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH + 1];
alignas(16) uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH + 1];
alignas(16) uint8_t plaintext[32 + 1];
alignas(16) uint8_t ad[32 + 1];
OPENSSL_memset(key, 'K', sizeof(key));
OPENSSL_memset(nonce, 'N', sizeof(nonce));
OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
@@ -563,7 +564,7 @@ TEST_P(PerAEADTest, UnalignedInput) {
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
evp_aead_seal));
alignas(64) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD];
alignas(16) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD];
size_t ciphertext_len;
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext + 1, &ciphertext_len,
sizeof(ciphertext) - 1, nonce + 1, nonce_len,
@@ -571,7 +572,7 @@ TEST_P(PerAEADTest, UnalignedInput) {
ad_len));
// It must successfully decrypt.
alignas(64) uint8_t out[sizeof(ciphertext)];
alignas(16) uint8_t out[sizeof(ciphertext)];
ctx.Reset();
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
@@ -585,7 +586,7 @@ TEST_P(PerAEADTest, UnalignedInput) {
}
TEST_P(PerAEADTest, Overflow) {
alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
OPENSSL_memset(key, 'K', sizeof(key));
bssl::ScopedEVP_AEAD_CTX ctx;
@@ -664,6 +665,91 @@ TEST_P(PerAEADTest, InvalidNonceLength) {
}
}
#if defined(SUPPORTS_ABI_TEST)
// CHECK_ABI can't pass enums, i.e. |evp_aead_seal| and |evp_aead_open|. Thus
// these two wrappers.
static int aead_ctx_init_for_seal(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len) {
return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, 0,
evp_aead_seal);
}
static int aead_ctx_init_for_open(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len) {
return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, 0,
evp_aead_open);
}
// CHECK_ABI can pass, at most, eight arguments. Thus these wrappers that
// figure out the output length from the input length, and take the nonce length
// from the configuration of the AEAD.
static int aead_ctx_seal(EVP_AEAD_CTX *ctx, uint8_t *out_ciphertext,
size_t *out_ciphertext_len, const uint8_t *nonce,
const uint8_t *plaintext, size_t plaintext_len,
const uint8_t *ad, size_t ad_len) {
const size_t nonce_len = EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(ctx));
return EVP_AEAD_CTX_seal(ctx, out_ciphertext, out_ciphertext_len,
plaintext_len + EVP_AEAD_MAX_OVERHEAD, nonce,
nonce_len, plaintext, plaintext_len, ad, ad_len);
}
static int aead_ctx_open(EVP_AEAD_CTX *ctx, uint8_t *out_plaintext,
size_t *out_plaintext_len, const uint8_t *nonce,
const uint8_t *ciphertext, size_t ciphertext_len,
const uint8_t *ad, size_t ad_len) {
const size_t nonce_len = EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(ctx));
return EVP_AEAD_CTX_open(ctx, out_plaintext, out_plaintext_len,
ciphertext_len, nonce, nonce_len, ciphertext,
ciphertext_len, ad, ad_len);
}
TEST_P(PerAEADTest, ABI) {
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
OPENSSL_memset(key, 'K', sizeof(key));
const size_t key_len = EVP_AEAD_key_length(aead());
ASSERT_LE(key_len, sizeof(key));
bssl::ScopedEVP_AEAD_CTX ctx_seal;
ASSERT_TRUE(
CHECK_ABI(aead_ctx_init_for_seal, ctx_seal.get(), aead(), key, key_len));
bssl::ScopedEVP_AEAD_CTX ctx_open;
ASSERT_TRUE(
CHECK_ABI(aead_ctx_init_for_open, ctx_open.get(), aead(), key, key_len));
alignas(2) uint8_t plaintext[512];
OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
alignas(2) uint8_t ad_buf[512];
OPENSSL_memset(ad_buf, 'A', sizeof(ad_buf));
const uint8_t *const ad = ad_buf + 1;
ASSERT_LE(GetParam().ad_len, sizeof(ad_buf) - 1);
const size_t ad_len =
GetParam().ad_len != 0 ? GetParam().ad_len : sizeof(ad_buf) - 1;
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
const size_t nonce_len = EVP_AEAD_nonce_length(aead());
ASSERT_LE(nonce_len, sizeof(nonce));
alignas(2) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD + 1];
size_t ciphertext_len;
// Knock plaintext, ciphertext, and AD off alignment and give odd lengths for
// plaintext and AD. This hopefully triggers any edge-cases in the assembly.
ASSERT_TRUE(CHECK_ABI(aead_ctx_seal, ctx_seal.get(), ciphertext + 1,
&ciphertext_len, nonce, plaintext + 1,
sizeof(plaintext) - 1, ad, ad_len));
alignas(2) uint8_t plaintext2[sizeof(ciphertext) + 1];
size_t plaintext2_len;
ASSERT_TRUE(CHECK_ABI(aead_ctx_open, ctx_open.get(), plaintext2 + 1,
&plaintext2_len, nonce, ciphertext + 1, ciphertext_len,
ad, ad_len));
EXPECT_EQ(Bytes(plaintext + 1, sizeof(plaintext) - 1),
Bytes(plaintext2 + 1, plaintext2_len));
}
#endif // SUPPORTS_ABI_TEST
TEST(AEADTest, AESCCMLargeAD) {
static const std::vector<uint8_t> kKey(16, 'A');
static const std::vector<uint8_t> kNonce(13, 'N');
@@ -728,8 +814,8 @@ static void RunWycheproofTestCase(FileTest *t, const EVP_AEAD *aead) {
size_t out_len;
// Wycheproof tags small AES-GCM IVs as "acceptable" and otherwise does not
// use it in AEADs. Any AES-GCM IV that isn't 96 bits is absurd, but our API
// supports those, so we treat "acceptable" as "valid" here.
if (result != WycheproofResult::kInvalid) {
// supports those, so we treat SmallIv tests as valid.
if (result.IsValid({"SmallIv"})) {
// Decryption should succeed.
ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
iv.data(), iv.size(), ct_and_tag.data(),
@@ -823,3 +909,12 @@ TEST(AEADTest, WycheproofChaCha20Poly1305) {
RunWycheproofTestCase(t, EVP_aead_chacha20_poly1305());
});
}
TEST(AEADTest, WycheproofXChaCha20Poly1305) {
FileTestGTest(
"third_party/wycheproof_testvectors/xchacha20_poly1305_test.txt",
[](FileTest *t) {
t->IgnoreInstruction("keySize");
RunWycheproofTestCase(t, EVP_aead_xchacha20_poly1305());
});
}
@@ -1273,7 +1273,7 @@ do_length_block:\n";
pop %rbp
.cfi_adjust_cfa_offset -8
ret
.cfi_adjust_cfa_offset (8 * 6) + 288 + 32
.cfi_adjust_cfa_offset (8 * 7) + 288 + 32
################################################################################
seal_sse_128:
movdqu .chacha20_consts(%rip), $A0\nmovdqa $A0, $A1\nmovdqa $A0, $A2
+167 -68
View File
@@ -61,8 +61,10 @@
#include <gtest/gtest.h>
#include <openssl/aes.h>
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include <openssl/span.h>
#include "../test/file_test.h"
@@ -118,7 +120,8 @@ static const EVP_CIPHER *GetCipher(const std::string &name) {
}
static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out,
bssl::Span<const uint8_t> in, size_t chunk) {
bssl::Span<const uint8_t> in, size_t chunk,
bool in_place) {
size_t max_out = in.size();
if ((EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_NO_PADDING) == 0 &&
EVP_CIPHER_CTX_encrypting(ctx)) {
@@ -126,6 +129,10 @@ static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out,
max_out += block_size - (max_out % block_size);
}
out->resize(max_out);
if (in_place) {
std::copy(in.begin(), in.end(), out->begin());
in = bssl::MakeConstSpan(out->data(), in.size());
}
size_t total = 0;
int len;
@@ -150,7 +157,7 @@ static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out,
}
static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
bool copy, size_t chunk_size,
bool copy, bool in_place, size_t chunk_size,
const std::vector<uint8_t> &key,
const std::vector<uint8_t> &iv,
const std::vector<uint8_t> &plaintext,
@@ -207,7 +214,7 @@ static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
}
ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx, 0));
std::vector<uint8_t> result;
ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size));
ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size, in_place));
EXPECT_EQ(Bytes(*out), Bytes(result));
if (encrypt && is_aead) {
uint8_t rtag[16];
@@ -216,6 +223,91 @@ static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag.size(), rtag));
EXPECT_EQ(Bytes(tag), Bytes(rtag, tag.size()));
}
// Additionally test low-level AES mode APIs. Skip runs where |copy| because
// it does not apply.
if (!copy) {
int nid = EVP_CIPHER_nid(cipher);
bool is_ctr = nid == NID_aes_128_ctr || nid == NID_aes_192_ctr ||
nid == NID_aes_256_ctr;
bool is_cbc = nid == NID_aes_128_cbc || nid == NID_aes_192_cbc ||
nid == NID_aes_256_cbc;
bool is_ofb = nid == NID_aes_128_ofb128 || nid == NID_aes_192_ofb128 ||
nid == NID_aes_256_ofb128;
if (is_ctr || is_cbc || is_ofb) {
AES_KEY aes;
if (encrypt || !is_cbc) {
ASSERT_EQ(0, AES_set_encrypt_key(key.data(), key.size() * 8, &aes));
} else {
ASSERT_EQ(0, AES_set_decrypt_key(key.data(), key.size() * 8, &aes));
}
// The low-level APIs all work in-place.
bssl::Span<const uint8_t> input = *in;
result.clear();
if (in_place) {
result = *in;
input = result;
} else {
result.resize(out->size());
}
bssl::Span<uint8_t> output = bssl::MakeSpan(result);
ASSERT_EQ(input.size(), output.size());
// The low-level APIs all use block-size IVs.
ASSERT_EQ(iv.size(), size_t{AES_BLOCK_SIZE});
uint8_t ivec[AES_BLOCK_SIZE];
OPENSSL_memcpy(ivec, iv.data(), iv.size());
if (is_ctr) {
unsigned num = 0;
uint8_t ecount_buf[AES_BLOCK_SIZE];
if (chunk_size == 0) {
AES_ctr128_encrypt(input.data(), output.data(), input.size(), &aes,
ivec, ecount_buf, &num);
} else {
do {
size_t todo = std::min(input.size(), chunk_size);
AES_ctr128_encrypt(input.data(), output.data(), todo, &aes, ivec,
ecount_buf, &num);
input = input.subspan(todo);
output = output.subspan(todo);
} while (!input.empty());
}
EXPECT_EQ(Bytes(*out), Bytes(result));
} else if (is_cbc && chunk_size % AES_BLOCK_SIZE == 0) {
// Note |AES_cbc_encrypt| requires block-aligned chunks.
if (chunk_size == 0) {
AES_cbc_encrypt(input.data(), output.data(), input.size(), &aes, ivec,
encrypt);
} else {
do {
size_t todo = std::min(input.size(), chunk_size);
AES_cbc_encrypt(input.data(), output.data(), todo, &aes, ivec,
encrypt);
input = input.subspan(todo);
output = output.subspan(todo);
} while (!input.empty());
}
EXPECT_EQ(Bytes(*out), Bytes(result));
} else if (is_ofb) {
int num = 0;
if (chunk_size == 0) {
AES_ofb128_encrypt(input.data(), output.data(), input.size(), &aes,
ivec, &num);
} else {
do {
size_t todo = std::min(input.size(), chunk_size);
AES_ofb128_encrypt(input.data(), output.data(), todo, &aes, ivec,
&num);
input = input.subspan(todo);
output = output.subspan(todo);
} while (!input.empty());
}
EXPECT_EQ(Bytes(*out), Bytes(result));
}
}
}
}
static void TestCipher(FileTest *t) {
@@ -257,21 +349,24 @@ static void TestCipher(FileTest *t) {
for (size_t chunk_size : chunk_sizes) {
SCOPED_TRACE(chunk_size);
// By default, both directions are run, unless overridden by the operation.
if (operation != kDecrypt) {
SCOPED_TRACE("encrypt");
TestOperation(t, cipher, true /* encrypt */, false /* no copy */,
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
TestOperation(t, cipher, true /* encrypt */, true /* copy */, chunk_size,
key, iv, plaintext, ciphertext, aad, tag);
}
for (bool copy : {false, true}) {
SCOPED_TRACE(copy);
for (bool in_place : {false, true}) {
SCOPED_TRACE(in_place);
// By default, both directions are run, unless overridden by the
// operation.
if (operation != kDecrypt) {
SCOPED_TRACE("encrypt");
TestOperation(t, cipher, true /* encrypt */, copy, in_place,
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
}
if (operation != kEncrypt) {
SCOPED_TRACE("decrypt");
TestOperation(t, cipher, false /* decrypt */, false /* no copy */,
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
TestOperation(t, cipher, false /* decrypt */, true /* copy */, chunk_size,
key, iv, plaintext, ciphertext, aad, tag);
if (operation != kEncrypt) {
SCOPED_TRACE("decrypt");
TestOperation(t, cipher, false /* decrypt */, copy, in_place,
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
}
}
}
}
}
@@ -319,59 +414,63 @@ TEST(CipherTest, CAVP_TDES_ECB) {
}
TEST(CipherTest, WycheproofAESCBC) {
FileTestGTest("third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
[](FileTest *t) {
t->IgnoreInstruction("type");
t->IgnoreInstruction("ivSize");
FileTestGTest(
"third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
[](FileTest *t) {
t->IgnoreInstruction("type");
t->IgnoreInstruction("ivSize");
std::string key_size;
ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
const EVP_CIPHER *cipher;
switch (atoi(key_size.c_str())) {
case 128:
cipher = EVP_aes_128_cbc();
break;
case 192:
cipher = EVP_aes_192_cbc();
break;
case 256:
cipher = EVP_aes_256_cbc();
break;
default:
FAIL() << "Unsupported key size: " << key_size;
}
std::string key_size;
ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
const EVP_CIPHER *cipher;
switch (atoi(key_size.c_str())) {
case 128:
cipher = EVP_aes_128_cbc();
break;
case 192:
cipher = EVP_aes_192_cbc();
break;
case 256:
cipher = EVP_aes_256_cbc();
break;
default:
FAIL() << "Unsupported key size: " << key_size;
}
std::vector<uint8_t> key, iv, msg, ct;
ASSERT_TRUE(t->GetBytes(&key, "key"));
ASSERT_TRUE(t->GetBytes(&iv, "iv"));
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
ASSERT_TRUE(t->GetBytes(&ct, "ct"));
ASSERT_EQ(EVP_CIPHER_key_length(cipher), key.size());
ASSERT_EQ(EVP_CIPHER_iv_length(cipher), iv.size());
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
std::vector<uint8_t> key, iv, msg, ct;
ASSERT_TRUE(t->GetBytes(&key, "key"));
ASSERT_TRUE(t->GetBytes(&iv, "iv"));
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
ASSERT_TRUE(t->GetBytes(&ct, "ct"));
ASSERT_EQ(EVP_CIPHER_key_length(cipher), key.size());
ASSERT_EQ(EVP_CIPHER_iv_length(cipher), iv.size());
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
bssl::ScopedEVP_CIPHER_CTX ctx;
std::vector<uint8_t> out;
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 : chunk_sizes) {
SCOPED_TRACE(chunk);
if (result == WycheproofResult::kValid) {
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
iv.data()));
ASSERT_TRUE(DoCipher(ctx.get(), &out, ct, chunk));
EXPECT_EQ(Bytes(msg), Bytes(out));
bssl::ScopedEVP_CIPHER_CTX ctx;
std::vector<uint8_t> out;
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 : chunk_sizes) {
SCOPED_TRACE(chunk);
for (bool in_place : {false, true}) {
SCOPED_TRACE(in_place);
if (result.IsValid()) {
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr,
key.data(), iv.data()));
ASSERT_TRUE(DoCipher(ctx.get(), &out, ct, chunk, in_place));
EXPECT_EQ(Bytes(msg), Bytes(out));
ASSERT_TRUE(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
iv.data()));
ASSERT_TRUE(DoCipher(ctx.get(), &out, msg, chunk));
EXPECT_EQ(Bytes(ct), Bytes(out));
} else {
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
iv.data()));
EXPECT_FALSE(DoCipher(ctx.get(), &out, ct, chunk));
}
}
});
ASSERT_TRUE(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr,
key.data(), iv.data()));
ASSERT_TRUE(DoCipher(ctx.get(), &out, msg, chunk, in_place));
EXPECT_EQ(Bytes(ct), Bytes(out));
} else {
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr,
key.data(), iv.data()));
EXPECT_FALSE(DoCipher(ctx.get(), &out, ct, chunk, in_place));
}
}
}
});
}
+1 -1
View File
@@ -86,7 +86,7 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
EVP_MD_CTX_init(&c);
for (;;) {
if (!EVP_DigestInit_ex(&c, md, NULL)) {
return 0;
goto err;
}
if (addmd++) {
if (!EVP_DigestUpdate(&c, md_buf, mds)) {
+8
View File
@@ -723,6 +723,14 @@ static void gcm_siv_keys(
}
OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
// Note the |ctr128_f| function uses a big-endian couner, while AES-GCM-SIV
// uses a little-endian counter. We ignore the return value and only use
// |block128_f|. This has a significant performance cost for the fallback
// bitsliced AES implementations (bsaes and aes_nohw).
//
// We currently do not consider AES-GCM-SIV to be performance-sensitive on
// client hardware. If this changes, we can write little-endian |ctr128_f|
// functions.
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
}
+1
View File
@@ -133,6 +133,7 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
assert(orig_len >= in_len);
assert(in_len >= md_size);
assert(md_size <= EVP_MAX_MD_SIZE);
assert(md_size > 0);
// scan_start contains the number of bytes that we can ignore because
// the MAC's position can only vary by 255 bytes.
+2 -2
View File
@@ -148,7 +148,7 @@ TEST(CMACTest, Wycheproof) {
// Some test vectors intentionally give the wrong key size. Our API
// requires the caller pick the sized CBC primitive, so these tests
// aren't useful for us.
EXPECT_EQ(WycheproofResult::kInvalid, result);
EXPECT_FALSE(result.IsValid());
return;
}
@@ -164,7 +164,7 @@ TEST(CMACTest, Wycheproof) {
// Truncate the tag, if requested.
out_len = std::min(out_len, tag_len);
if (result == WycheproofResult::kValid) {
if (result.IsValid()) {
EXPECT_EQ(Bytes(tag), Bytes(out, out_len));
// Test the streaming API as well.
+7 -6
View File
@@ -21,7 +21,6 @@
#include <unistd.h>
#include <openssl/arm_arch.h>
#include <openssl/buf.h>
#include <openssl/mem.h>
#include "cpu-arm-linux.h"
@@ -147,11 +146,13 @@ extern uint32_t OPENSSL_armcap_P;
static int g_has_broken_neon, g_needs_hwcap2_workaround;
void OPENSSL_cpuid_setup(void) {
char *cpuinfo_data;
size_t cpuinfo_len;
if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) {
return;
}
// We ignore the return value of |read_file| and proceed with an empty
// /proc/cpuinfo on error. If |getauxval| works, we will still detect
// capabilities. There may be a false positive due to
// |crypto_cpuinfo_has_broken_neon|, but this is now rare.
char *cpuinfo_data = NULL;
size_t cpuinfo_len = 0;
read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo");
STRING_PIECE cpuinfo;
cpuinfo.data = cpuinfo_data;
cpuinfo.len = cpuinfo_len;
+7
View File
@@ -220,6 +220,13 @@ TEST(ARMLinuxTest, CPUInfo) {
0,
false,
},
// If opening /proc/cpuinfo fails, we process the empty string.
{
"",
0,
0,
false,
},
};
for (const auto &t : kTests) {
+22 -5
View File
@@ -123,15 +123,28 @@ static uint64_t OPENSSL_xgetbv(uint32_t xcr) {
// and |out[1]|. See the comment in |OPENSSL_cpuid_setup| about this.
static void handle_cpu_env(uint32_t *out, const char *in) {
const int invert = in[0] == '~';
uint64_t v;
const int or = in[0] == '|';
const int skip_first_byte = invert || or;
const int hex = in[skip_first_byte] == '0' && in[skip_first_byte+1] == 'x';
if (!sscanf(in + invert, "%" PRIu64, &v)) {
int sscanf_result;
uint64_t v;
if (hex) {
sscanf_result = sscanf(in + invert + 2, "%" PRIx64, &v);
} else {
sscanf_result = sscanf(in + invert, "%" PRIu64, &v);
}
if (!sscanf_result) {
return;
}
if (invert) {
out[0] &= ~v;
out[1] &= ~(v >> 32);
} else if (or) {
out[0] |= v;
out[1] |= (v >> 32);
} else {
out[0] = v;
out[1] = v >> 32;
@@ -256,10 +269,14 @@ void OPENSSL_cpuid_setup(void) {
// OPENSSL_ia32cap can contain zero, one or two values, separated with a ':'.
// Each value is a 64-bit, unsigned value which may start with "0x" to
// indicate a hex value. Prior to the 64-bit value, a '~' may be given.
// indicate a hex value. Prior to the 64-bit value, a '~' or '|' may be given.
//
// If '~' isn't present, then the value is taken as the result of the CPUID.
// Otherwise the value is inverted and ANDed with the probed CPUID result.
// If the '~' prefix is present:
// the value is inverted and ANDed with the probed CPUID result
// If the '|' prefix is present:
// the value is ORed with the probed CPUID result
// Otherwise:
// the value is taken as the result of the CPUID
//
// The first value determines OPENSSL_ia32cap_P[0] and [1]. The second [2]
// and [3].
+11
View File
@@ -16,6 +16,8 @@
#include <openssl/cpu.h>
#include "fipsmodule/rand/fork_detect.h"
#include "fipsmodule/rand/internal.h"
#include "internal.h"
@@ -174,6 +176,15 @@ int CRYPTO_has_asm(void) {
#endif
}
void CRYPTO_pre_sandbox_init(void) {
// Read from /proc/cpuinfo if needed.
CRYPTO_library_init();
// Open /dev/urandom if needed.
CRYPTO_init_sysrand();
// Set up MADV_WIPEONFORK state if needed.
CRYPTO_get_fork_generation();
}
const char *SSLeay_version(int which) { return OpenSSL_version(which); }
const char *OpenSSL_version(int which) {
@@ -1,29 +1,21 @@
// The MIT License (MIT)
//
// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
/* Copyright (c) 2020, 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. */
// Some of this code is 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 parts have been replaced with code generated by Fiat
// (https://github.com/mit-plv/fiat-crypto), which is MIT licensed.
// public domain. Other parts have been replaced to call into code generated by
// Fiat (https://github.com/mit-plv/fiat-crypto) in //third_party/fiat.
//
// The field functions are shared by Ed25519 and X25519 where possible.
@@ -39,16 +31,16 @@
#include <openssl/type_check.h>
#include "internal.h"
#include "../../crypto/internal.h"
#include "../internal.h"
// Various pre-computed constants.
#include "./curve25519_tables.h"
#if defined(BORINGSSL_CURVE25519_64BIT)
#include "./curve25519_64.h"
#include "../../third_party/fiat/curve25519_64.h"
#else
#include "./curve25519_32.h"
#include "../../third_party/fiat/curve25519_32.h"
#endif // BORINGSSL_CURVE25519_64BIT
@@ -1,24 +1,16 @@
// The MIT License (MIT)
//
// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
/* Copyright (c) 2020, 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 is generated from
// ./make_curve25519_tables.py > curve25519_tables.h
@@ -1,24 +1,16 @@
// The MIT License (MIT)
//
// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
/* Copyright (c) 2020, 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_CURVE25519_INTERNAL_H
#define OPENSSL_HEADER_CURVE25519_INTERNAL_H
@@ -29,7 +21,7 @@ extern "C" {
#include <openssl/base.h>
#include "../../crypto/internal.h"
#include "../internal.h"
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_APPLE)
@@ -1,26 +1,18 @@
#!/usr/bin/env python
# coding=utf-8
# The MIT License (MIT)
# Copyright (c) 2020, Google Inc.
#
# Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
# 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.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# 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 StringIO
import subprocess
@@ -149,27 +141,19 @@ def main():
buf = StringIO.StringIO()
buf.write("""// The MIT License (MIT)
//
// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
buf.write("""/* Copyright (c) 2020, 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 is generated from
// ./make_curve25519_tables.py > curve25519_tables.h
+1 -1
View File
@@ -23,7 +23,7 @@
#include <openssl/sha.h>
#include "../internal.h"
#include "../../third_party/fiat/internal.h"
#include "./internal.h"
// The following precomputation tables are for the following
+1 -1
View File
@@ -23,7 +23,7 @@
#include <gtest/gtest.h>
#include "../internal.h"
#include "../../third_party/fiat/internal.h"
#include "./internal.h"
// TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down.
+5 -6
View File
@@ -23,6 +23,7 @@
#include "../internal.h"
#include "../test/file_test.h"
#include "../test/test_util.h"
#include "../test/wycheproof_util.h"
TEST(X25519Test, TestVector) {
@@ -132,11 +133,8 @@ TEST(X25519Test, Wycheproof) {
t->IgnoreInstruction("curve");
t->IgnoreAttribute("curve");
// Our implementation tolerates the Wycheproof "acceptable"
// inputs. Wycheproof's valid vs. acceptable criteria does not match our
// X25519 return value, so we test only the overall output.
t->IgnoreAttribute("result");
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
std::vector<uint8_t> priv, pub, shared;
ASSERT_TRUE(t->GetBytes(&priv, "private"));
ASSERT_TRUE(t->GetBytes(&pub, "public"));
@@ -144,7 +142,8 @@ TEST(X25519Test, Wycheproof) {
ASSERT_EQ(32u, priv.size());
ASSERT_EQ(32u, pub.size());
uint8_t secret[32];
X25519(secret, priv.data(), pub.data());
int ret = X25519(secret, priv.data(), pub.data());
EXPECT_EQ(ret, result.IsValid({"NonCanonicalPublic", "Twist"}) ? 1 : 0);
EXPECT_EQ(Bytes(secret), Bytes(shared));
});
}
+3 -3
View File
@@ -151,7 +151,7 @@ int DH_check(const DH *dh, int *out_flags) {
*out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR;
}
}
r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
r = BN_is_prime_ex(dh->q, BN_prime_checks_for_validation, ctx, NULL);
if (r < 0) {
goto err;
}
@@ -188,7 +188,7 @@ int DH_check(const DH *dh, int *out_flags) {
*out_flags |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR;
}
r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
r = BN_is_prime_ex(dh->p, BN_prime_checks_for_validation, ctx, NULL);
if (r < 0) {
goto err;
}
@@ -198,7 +198,7 @@ int DH_check(const DH *dh, int *out_flags) {
if (!BN_rshift1(t1, dh->p)) {
goto err;
}
r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
r = BN_is_prime_ex(t1, BN_prime_checks_for_validation, ctx, NULL);
if (r < 0) {
goto err;
}
+16 -2
View File
@@ -59,7 +59,6 @@
#include <string.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/ex_data.h>
#include <openssl/mem.h>
@@ -114,6 +113,16 @@ void DH_free(DH *dh) {
OPENSSL_free(dh);
}
const BIGNUM *DH_get0_pub_key(const DH *dh) { return dh->pub_key; }
const BIGNUM *DH_get0_priv_key(const DH *dh) { return dh->priv_key; }
const BIGNUM *DH_get0_p(const DH *dh) { return dh->p; }
const BIGNUM *DH_get0_q(const DH *dh) { return dh->q; }
const BIGNUM *DH_get0_g(const DH *dh) { return dh->g; }
void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
const BIGNUM **out_priv_key) {
if (out_pub_key != NULL) {
@@ -175,6 +184,11 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
return 1;
}
int DH_set_length(DH *dh, unsigned priv_length) {
dh->priv_length = priv_length;
return 1;
}
int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
// We generate DH parameters as follows
// find a prime q which is prime_bits/2 bits long.
@@ -476,7 +490,7 @@ static int int_dh_param_copy(DH *to, const DH *from, int is_x942) {
to->seedlen = 0;
if (from->seed) {
to->seed = BUF_memdup(from->seed, from->seedlen);
to->seed = OPENSSL_memdup(from->seed, from->seedlen);
if (!to->seed) {
return 0;
}
+64 -69
View File
@@ -53,6 +53,7 @@ static const MD sha224 = { "SHA224", &EVP_sha224, &SHA224 };
static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256 };
static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384 };
static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512 };
static const MD sha512_256 = { "SHA512-256", &EVP_sha512_256, &SHA512_256 };
static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr };
struct DigestTestVector {
@@ -69,94 +70,88 @@ struct DigestTestVector {
static const DigestTestVector kTestVectors[] = {
// MD4 tests, from RFC 1320. (crypto/md4 does not provide a
// one-shot MD4 function.)
{ md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" },
{ md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" },
{ md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" },
{ md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b" },
{ md4, "abcdefghijklmnopqrstuvwxyz", 1,
"d79e1c308aa5bbcdeea8ed63df412da9" },
{ md4,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
"043f8582f241db351ce627e153e7f0e4" },
{ md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" },
{md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0"},
{md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24"},
{md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d"},
{md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b"},
{md4, "abcdefghijklmnopqrstuvwxyz", 1, "d79e1c308aa5bbcdeea8ed63df412da9"},
{md4, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
"043f8582f241db351ce627e153e7f0e4"},
{md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536"},
// MD5 tests, from RFC 1321.
{ md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" },
{ md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" },
{ md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" },
{ md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" },
{ md5, "abcdefghijklmnopqrstuvwxyz", 1,
"c3fcd3d76192e4007dfb496cca67e13b" },
{ md5,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
"d174ab98d277d9f5a5611c2c9f419d9f" },
{ md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" },
{md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e"},
{md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661"},
{md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72"},
{md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0"},
{md5, "abcdefghijklmnopqrstuvwxyz", 1, "c3fcd3d76192e4007dfb496cca67e13b"},
{md5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
"d174ab98d277d9f5a5611c2c9f419d9f"},
{md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a"},
// SHA-1 tests, from RFC 3174.
{ sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" },
{ sha1,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"84983e441c3bd26ebaae4aa1f95129e5e54670f1" },
{ sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f" },
{ sha1,
"0123456701234567012345670123456701234567012345670123456701234567", 10,
"dea356a2cddd90c7a7ecedc5ebb563934f460452" },
{sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d"},
{sha1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"84983e441c3bd26ebaae4aa1f95129e5e54670f1"},
{sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f"},
{sha1, "0123456701234567012345670123456701234567012345670123456701234567",
10, "dea356a2cddd90c7a7ecedc5ebb563934f460452"},
// SHA-224 tests, from RFC 3874.
{ sha224, "abc", 1,
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" },
{ sha224,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" },
{ sha224,
"a", 1000000,
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" },
{sha224, "abc", 1,
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"},
{sha224, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"},
{sha224, "a", 1000000,
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"},
// SHA-256 tests, from NIST.
{ sha256, "abc", 1,
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
{ sha256,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" },
{sha256, "abc", 1,
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"},
{sha256, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"},
// SHA-384 tests, from NIST.
{ sha384, "abc", 1,
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
"8086072ba1e7cc2358baeca134c825a7" },
{ sha384,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
"fcc7c71a557e2db966c3e9fa91746039" },
{sha384, "abc", 1,
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
"8086072ba1e7cc2358baeca134c825a7"},
{sha384,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
1,
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
"fcc7c71a557e2db966c3e9fa91746039"},
// SHA-512 tests, from NIST.
{ sha512, "abc", 1,
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" },
{ sha512,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
{sha512, "abc", 1,
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"},
{sha512,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
1,
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"},
// SHA-512-256 tests, from
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha512_256.pdf
{sha512_256, "abc", 1,
"53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"},
{sha512_256,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopj"
"klmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
1, "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a"},
// MD5-SHA1 tests.
{ md5_sha1, "abc", 1,
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
{md5_sha1, "abc", 1,
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d"},
};
static void CompareDigest(const DigestTestVector *test,
const uint8_t *digest,
size_t digest_len) {
static const char kHexTable[] = "0123456789abcdef";
char digest_hex[2*EVP_MAX_MD_SIZE + 1];
for (size_t i = 0; i < digest_len; i++) {
digest_hex[2*i] = kHexTable[digest[i] >> 4];
digest_hex[2*i + 1] = kHexTable[digest[i] & 0xf];
}
digest_hex[2*digest_len] = '\0';
EXPECT_STREQ(test->expected_hex, digest_hex);
EXPECT_EQ(test->expected_hex,
EncodeHex(bssl::MakeConstSpan(digest, digest_len)));
}
static void TestDigest(const DigestTestVector *test) {
+12 -2
View File
@@ -131,6 +131,16 @@ int DSA_up_ref(DSA *dsa) {
return 1;
}
const BIGNUM *DSA_get0_pub_key(const DSA *dsa) { return dsa->pub_key; }
const BIGNUM *DSA_get0_priv_key(const DSA *dsa) { return dsa->priv_key; }
const BIGNUM *DSA_get0_p(const DSA *dsa) { return dsa->p; }
const BIGNUM *DSA_get0_q(const DSA *dsa) { return dsa->q; }
const BIGNUM *DSA_get0_g(const DSA *dsa) { return dsa->g; }
void DSA_get0_key(const DSA *dsa, const BIGNUM **out_pub_key,
const BIGNUM **out_priv_key) {
if (out_pub_key != NULL) {
@@ -256,7 +266,7 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
// Find q.
for (;;) {
// step 1
if (!BN_GENCB_call(cb, 0, m++)) {
if (!BN_GENCB_call(cb, BN_GENCB_GENERATED, m++)) {
goto err;
}
@@ -319,7 +329,7 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
n = (bits - 1) / 160;
for (;;) {
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) {
if ((counter != 0) && !BN_GENCB_call(cb, BN_GENCB_GENERATED, counter)) {
goto err;
}
+2 -3
View File
@@ -16,7 +16,6 @@
#include <string.h>
#include <openssl/buf.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/digest.h>
@@ -40,8 +39,8 @@ EC_KEY *EC_KEY_derive_from_secret(const EC_GROUP *group, const uint8_t *secret,
// separated.
static const char kLabel[] = "derive EC key ";
char info[sizeof(kLabel) + EC_KEY_DERIVE_MAX_NAME_LEN];
BUF_strlcpy(info, kLabel, sizeof(info));
BUF_strlcat(info, name, sizeof(info));
OPENSSL_strlcpy(info, kLabel, sizeof(info));
OPENSSL_strlcat(info, name, sizeof(info));
// Generate 128 bits beyond the group order so the bias is at most 2^-128.
#define EC_KEY_DERIVE_EXTRA_BITS 128
+385
View File
@@ -0,0 +1,385 @@
/* Copyright (c) 2020, 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/ec.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include <openssl/type_check.h>
#include <assert.h>
#include "internal.h"
#include "../fipsmodule/bn/internal.h"
#include "../fipsmodule/ec/internal.h"
#include "../internal.h"
// This file implements hash-to-curve, as described in
// draft-irtf-cfrg-hash-to-curve-07.
//
// This hash-to-curve implementation is written generically with the
// expectation that we will eventually wish to support other curves. If it
// becomes a performance bottleneck, some possible optimizations by
// specializing it to the curve:
//
// - Rather than using a generic |felem_exp|, specialize the exponentation to
// c2 with a faster addition chain.
//
// - |felem_mul| and |felem_sqr| are indirect calls to generic Montgomery
// code. Given the few curves, we could specialize
// |map_to_curve_simple_swu|. But doing this reasonably without duplicating
// code in C is difficult. (C++ templates would be useful here.)
//
// - P-521's Z and c2 have small power-of-two absolute values. We could save
// two multiplications in SSWU. (Other curves have reasonable values of Z
// and inconvenient c2.) This is unlikely to be worthwhile without C++
// templates to make specializing more convenient.
// expand_message_xmd implements the operation described in section 5.3.1 of
// draft-irtf-cfrg-hash-to-curve-07. It returns one on success and zero on
// allocation failure or if |out_len| was too large.
static int expand_message_xmd(const EVP_MD *md, uint8_t *out, size_t out_len,
const uint8_t *msg, size_t msg_len,
const uint8_t *dst, size_t dst_len) {
int ret = 0;
const size_t block_size = EVP_MD_block_size(md);
const size_t md_size = EVP_MD_size(md);
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
// Long DSTs are hashed down to size. See section 5.3.3.
OPENSSL_STATIC_ASSERT(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
uint8_t dst_buf[EVP_MAX_MD_SIZE];
if (dst_len >= 256) {
static const char kPrefix[] = "H2C-OVERSIZE-DST-";
if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
!EVP_DigestUpdate(&ctx, kPrefix, sizeof(kPrefix) - 1) ||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
!EVP_DigestFinal_ex(&ctx, dst_buf, NULL)) {
goto err;
}
dst = dst_buf;
dst_len = md_size;
}
uint8_t dst_len_u8 = (uint8_t)dst_len;
// Compute b_0.
static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
// If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
// be returned. This depends on the static assert above.
uint8_t l_i_b_str_zero[3] = {out_len >> 8, out_len, 0};
uint8_t b_0[EVP_MAX_MD_SIZE];
if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
!EVP_DigestUpdate(&ctx, kZeros, block_size) ||
!EVP_DigestUpdate(&ctx, msg, msg_len) ||
!EVP_DigestUpdate(&ctx, l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
!EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
!EVP_DigestFinal_ex(&ctx, b_0, NULL)) {
goto err;
}
uint8_t b_i[EVP_MAX_MD_SIZE];
uint8_t i = 1;
while (out_len > 0) {
if (i == 0) {
// Input was too large.
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
goto err;
}
if (i > 1) {
for (size_t j = 0; j < md_size; j++) {
b_i[j] ^= b_0[j];
}
} else {
OPENSSL_memcpy(b_i, b_0, md_size);
}
if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
!EVP_DigestUpdate(&ctx, b_i, md_size) ||
!EVP_DigestUpdate(&ctx, &i, 1) ||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
!EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
!EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
goto err;
}
size_t todo = out_len >= md_size ? md_size : out_len;
OPENSSL_memcpy(out, b_i, todo);
out += todo;
out_len -= todo;
i++;
}
ret = 1;
err:
EVP_MD_CTX_cleanup(&ctx);
return ret;
}
// num_bytes_to_derive determines the number of bytes to derive when hashing to
// a number modulo |modulus|. See the hash_to_field operation defined in
// section 5.2 of draft-irtf-cfrg-hash-to-curve-07.
static int num_bytes_to_derive(size_t *out, const BIGNUM *modulus, unsigned k) {
size_t bits = BN_num_bits(modulus);
size_t L = (bits + k + 7) / 8;
// We require 2^(8*L) < 2^(2*bits - 2) <= n^2 so to fit in bounds for
// |felem_reduce| and |ec_scalar_reduce|. All defined hash-to-curve suites
// define |k| to be well under this bound. (|k| is usually around half of
// |p_bits|.)
if (L * 8 >= 2 * bits - 2 ||
L > 2 * EC_MAX_BYTES) {
assert(0);
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
return 0;
}
*out = L;
return 1;
}
// big_endian_to_words decodes |in| as a big-endian integer and writes the
// result to |out|. |num_words| must be large enough to contain the output.
static void big_endian_to_words(BN_ULONG *out, size_t num_words,
const uint8_t *in, size_t len) {
assert(len <= num_words * sizeof(BN_ULONG));
// Ensure any excess bytes are zeroed.
OPENSSL_memset(out, 0, num_words * sizeof(BN_ULONG));
uint8_t *out_u8 = (uint8_t *)out;
for (size_t i = 0; i < len; i++) {
out_u8[len - 1 - i] = in[i];
}
}
// hash_to_field implements the operation described in section 5.2
// of draft-irtf-cfrg-hash-to-curve-07, with count = 2. |k| is the security
// factor.
static int hash_to_field2(const EC_GROUP *group, const EVP_MD *md,
EC_FELEM *out1, EC_FELEM *out2, const uint8_t *dst,
size_t dst_len, unsigned k, const uint8_t *msg,
size_t msg_len) {
size_t L;
uint8_t buf[4 * EC_MAX_BYTES];
if (!num_bytes_to_derive(&L, &group->field, k) ||
!expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len)) {
return 0;
}
BN_ULONG words[2 * EC_MAX_WORDS];
size_t num_words = 2 * group->field.width;
big_endian_to_words(words, num_words, buf, L);
group->meth->felem_reduce(group, out1, words, num_words);
big_endian_to_words(words, num_words, buf + L, L);
group->meth->felem_reduce(group, out2, words, num_words);
return 1;
}
// hash_to_scalar behaves like |hash_to_field2| but returns a value modulo the
// group order rather than a field element. |k| is the security factor.
static int hash_to_scalar(const EC_GROUP *group, const EVP_MD *md,
EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
unsigned k, const uint8_t *msg, size_t msg_len) {
size_t L;
uint8_t buf[EC_MAX_BYTES * 2];
if (!num_bytes_to_derive(&L, &group->order, k) ||
!expand_message_xmd(md, buf, L, msg, msg_len, dst, dst_len)) {
return 0;
}
BN_ULONG words[2 * EC_MAX_WORDS];
size_t num_words = 2 * group->order.width;
big_endian_to_words(words, num_words, buf, L);
ec_scalar_reduce(group, out, words, num_words);
return 1;
}
static inline void mul_A(const EC_GROUP *group, EC_FELEM *out,
const EC_FELEM *in) {
assert(group->a_is_minus3);
EC_FELEM tmp;
ec_felem_add(group, &tmp, in, in); // tmp = 2*in
ec_felem_add(group, &tmp, &tmp, &tmp); // tmp = 4*in
ec_felem_sub(group, out, in, &tmp); // out = -3*in
}
static inline void mul_minus_A(const EC_GROUP *group, EC_FELEM *out,
const EC_FELEM *in) {
assert(group->a_is_minus3);
EC_FELEM tmp;
ec_felem_add(group, &tmp, in, in); // tmp = 2*in
ec_felem_add(group, out, &tmp, in); // out = 3*in
}
// sgn0_le implements the operation described in section 4.1.2 of
// draft-irtf-cfrg-hash-to-curve-07.
static BN_ULONG sgn0_le(const EC_GROUP *group, const EC_FELEM *a) {
uint8_t buf[EC_MAX_BYTES];
size_t len;
ec_felem_to_bytes(group, buf, &len, a);
return buf[len - 1] & 1;
}
// map_to_curve_simple_swu implements the operation described in section 6.6.2
// of draft-irtf-cfrg-hash-to-curve-07, using the optimization in appendix
// D.2.1. It returns one on success and zero on error.
static int map_to_curve_simple_swu(const EC_GROUP *group, const EC_FELEM *Z,
const BN_ULONG *c1, size_t num_c1,
const EC_FELEM *c2, EC_RAW_POINT *out,
const EC_FELEM *u) {
void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
const EC_FELEM *b) = group->meth->felem_mul;
void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
group->meth->felem_sqr;
// This function requires the prime be 3 mod 4, and that A = -3.
if (group->field.width == 0 || (group->field.d[0] & 3) != 3 ||
!group->a_is_minus3) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
return 0;
}
EC_FELEM tv1, tv2, tv3, tv4, xd, x1n, x2n, tmp, gxd, gx1, y1, y2;
felem_sqr(group, &tv1, u); // tv1 = u^2
felem_mul(group, &tv3, Z, &tv1); // tv3 = Z * tv1
felem_sqr(group, &tv2, &tv3); // tv2 = tv3^2
ec_felem_add(group, &xd, &tv2, &tv3); // xd = tv2 + tv3
ec_felem_add(group, &x1n, &xd, &group->one); // x1n = xd + 1
felem_mul(group, &x1n, &x1n, &group->b); // x1n = x1n * B
mul_minus_A(group, &xd, &xd); // xd = -A * xd
BN_ULONG e1 = ec_felem_non_zero_mask(group, &xd); // e1 = xd == 0 [flipped]
mul_A(group, &tmp, Z);
ec_felem_select(group, &xd, e1, &xd, &tmp); // xd = CMOV(xd, Z * A, e1)
felem_sqr(group, &tv2, &xd); // tv2 = xd^2
felem_mul(group, &gxd, &tv2, &xd); // gxd = tv2 * xd = xd^3
mul_A(group, &tv2, &tv2); // tv2 = A * tv2
felem_sqr(group, &gx1, &x1n); // gx1 = x1n^2
ec_felem_add(group, &gx1, &gx1, &tv2); // gx1 = gx1 + tv2
felem_mul(group, &gx1, &gx1, &x1n); // gx1 = gx1 * x1n
felem_mul(group, &tv2, &group->b, &gxd); // tv2 = B * gxd
ec_felem_add(group, &gx1, &gx1, &tv2); // gx1 = gx1 + tv2
felem_sqr(group, &tv4, &gxd); // tv4 = gxd^2
felem_mul(group, &tv2, &gx1, &gxd); // tv2 = gx1 * gxd
felem_mul(group, &tv4, &tv4, &tv2); // tv4 = tv4 * tv2
group->meth->felem_exp(group, &y1, &tv4, c1, num_c1); // y1 = tv4^c1
felem_mul(group, &y1, &y1, &tv2); // y1 = y1 * tv2
felem_mul(group, &x2n, &tv3, &x1n); // x2n = tv3 * x1n
felem_mul(group, &y2, &y1, c2); // y2 = y1 * c2
felem_mul(group, &y2, &y2, &tv1); // y2 = y2 * tv1
felem_mul(group, &y2, &y2, u); // y2 = y2 * u
felem_sqr(group, &tv2, &y1); // tv2 = y1^2
felem_mul(group, &tv2, &tv2, &gxd); // tv2 = tv2 * gxd
ec_felem_sub(group, &tv3, &tv2, &gx1);
BN_ULONG e2 =
ec_felem_non_zero_mask(group, &tv3); // e2 = tv2 == gx1 [flipped]
ec_felem_select(group, &x1n, e2, &x2n, &x1n); // xn = CMOV(x2n, x1n, e2)
ec_felem_select(group, &y1, e2, &y2, &y1); // y = CMOV(y2, y1, e2)
BN_ULONG sgn0_u = sgn0_le(group, u);
BN_ULONG sgn0_y = sgn0_le(group, &y1);
BN_ULONG e3 = sgn0_u ^ sgn0_y;
e3 = ((BN_ULONG)0) - e3; // e3 = sgn0(u) == sgn0(y) [flipped]
ec_felem_neg(group, &y2, &y1);
ec_felem_select(group, &y1, e3, &y2, &y1); // y = CMOV(-y, y, e3)
// Appendix D.1 describes how to convert (x1n, xd, y1, 1) to Jacobian
// coordinates. Note yd = 1. Also note that gxd computed above is xd^3.
felem_mul(group, &out->X, &x1n, &xd); // X = xn * xd
felem_mul(group, &out->Y, &y1, &gxd); // Y = yn * gxd = yn * xd^3
out->Z = xd; // Z = xd
return 1;
}
static int hash_to_curve(const EC_GROUP *group, const EVP_MD *md,
const EC_FELEM *Z, const EC_FELEM *c2, unsigned k,
EC_RAW_POINT *out, const uint8_t *dst, size_t dst_len,
const uint8_t *msg, size_t msg_len) {
EC_FELEM u0, u1;
if (!hash_to_field2(group, md, &u0, &u1, dst, dst_len, k, msg, msg_len)) {
return 0;
}
// Compute |c1| = (p - 3) / 4.
BN_ULONG c1[EC_MAX_WORDS];
size_t num_c1 = group->field.width;
if (!bn_copy_words(c1, num_c1, &group->field)) {
return 0;
}
bn_rshift_words(c1, c1, /*shift=*/2, /*num=*/num_c1);
EC_RAW_POINT Q0, Q1;
if (!map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q0, &u0) ||
!map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q1, &u1)) {
return 0;
}
group->meth->add(group, out, &Q0, &Q1); // R = Q0 + Q1
// All our curves have cofactor one, so |clear_cofactor| is a no-op.
return 1;
}
static int felem_from_u8(const EC_GROUP *group, EC_FELEM *out, uint8_t a) {
uint8_t bytes[EC_MAX_BYTES] = {0};
size_t len = BN_num_bytes(&group->field);
bytes[len - 1] = a;
return ec_felem_from_bytes(group, out, bytes, len);
}
int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
size_t dst_len, const uint8_t *msg, size_t msg_len) {
// See section 8.3 of draft-irtf-cfrg-hash-to-curve-07.
if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
return 0;
}
// kSqrt1728 was computed as follows in python3:
//
// p = 2**384 - 2**128 - 2**96 + 2**32 - 1
// z3 = 12**3
// c2 = pow(z3, (p+1)//4, p)
// assert z3 == pow(c2, 2, p)
// ", ".join("0x%02x" % b for b in c2.to_bytes(384//8, 'big')
static const uint8_t kSqrt1728[] = {
0x01, 0x98, 0x77, 0xcc, 0x10, 0x41, 0xb7, 0x55, 0x57, 0x43, 0xc0, 0xae,
0x2e, 0x3a, 0x3e, 0x61, 0xfb, 0x2a, 0xaa, 0x2e, 0x0e, 0x87, 0xea, 0x55,
0x7a, 0x56, 0x3d, 0x8b, 0x59, 0x8a, 0x09, 0x40, 0xd0, 0xa6, 0x97, 0xa9,
0xe0, 0xb9, 0xe9, 0x2c, 0xfa, 0xa3, 0x14, 0xf5, 0x83, 0xc9, 0xd0, 0x66
};
// Z = -12, c2 = sqrt(1728)
EC_FELEM Z, c2;
if (!felem_from_u8(group, &Z, 12) ||
!ec_felem_from_bytes(group, &c2, kSqrt1728, sizeof(kSqrt1728))) {
return 0;
}
ec_felem_neg(group, &Z, &Z);
return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/192, out, dst,
dst_len, msg, msg_len);
}
int ec_hash_to_scalar_p384_xmd_sha512_draft07(
const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
const uint8_t *msg, size_t msg_len) {
if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
return 0;
}
return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/192, msg,
msg_len);
}
+56
View File
@@ -0,0 +1,56 @@
/* Copyright (c) 2020, 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_EC_EXTRA_INTERNAL_H
#define OPENSSL_HEADER_EC_EXTRA_INTERNAL_H
#include <openssl/ec.h>
#include "../fipsmodule/ec/internal.h"
#if defined(__cplusplus)
extern "C" {
#endif
// Hash-to-curve.
//
// The following functions implement primitives from
// draft-irtf-cfrg-hash-to-curve. The |dst| parameter in each function is the
// domain separation tag and must be unique for each protocol and between the
// |hash_to_curve| and |hash_to_scalar| variants. See section 3.1 of the spec
// for additional guidance on this parameter.
// ec_hash_to_curve_p384_xmd_sha512_sswu_draft07 hashes |msg| to a point on
// |group| and writes the result to |out|, implementing the
// P384_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-07. It
// returns one on success and zero on error.
OPENSSL_EXPORT int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
size_t dst_len, const uint8_t *msg, size_t msg_len);
// ec_hash_to_scalar_p384_xmd_sha512_draft07 hashes |msg| to a scalar on |group|
// and writes the result to |out|, using the hash_to_field operation from the
// P384_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-07, but
// generating a value modulo the group order rather than a field element.
OPENSSL_EXPORT int ec_hash_to_scalar_p384_xmd_sha512_draft07(
const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
const uint8_t *msg, size_t msg_len);
#if defined(__cplusplus)
} // extern C
#endif
#endif // OPENSSL_HEADER_EC_EXTRA_INTERNAL_H
+2 -2
View File
@@ -96,8 +96,8 @@ int ECDH_compute_key(void *out, size_t out_len, const EC_POINT *pub_key,
uint8_t buf[EC_MAX_BYTES];
size_t buf_len;
if (!ec_point_mul_scalar(group, &shared_point, &pub_key->raw, priv) ||
!ec_point_get_affine_coordinate_bytes(group, buf, NULL, &buf_len,
sizeof(buf), &shared_point)) {
!ec_get_x_coordinate_as_bytes(group, buf, &buf_len, sizeof(buf),
&shared_point)) {
OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
return -1;
}
+7 -13
View File
@@ -140,22 +140,16 @@ static void RunWycheproofTest(FileTest *t) {
ASSERT_TRUE(GetWycheproofResult(t, &result));
std::vector<uint8_t> shared;
ASSERT_TRUE(t->GetBytes(&shared, "shared"));
// BoringSSL supports compressed coordinates.
bool is_valid = result.IsValid({"CompressedPoint"});
// Wycheproof stores the peer key in an SPKI to mimic a Java API mistake.
// This is non-standard and error-prone.
CBS cbs;
CBS_init(&cbs, peer_spki.data(), peer_spki.size());
bssl::UniquePtr<EVP_PKEY> peer_evp(EVP_parse_public_key(&cbs));
if (!peer_evp) {
// Note some of Wycheproof's "acceptable" entries are unsupported by
// BoringSSL because they test explicit curves (forbidden by RFC 5480),
// while others are supported because they used compressed coordinates. If
// the peer key fails to parse, we consider it to match "acceptable", but if
// the resulting shared secret matches below, it too matches "acceptable".
//
// TODO(davidben): Use the flags field to disambiguate these. Possibly
// first get the Wycheproof folks to use flags more consistently.
EXPECT_NE(WycheproofResult::kValid, result);
if (!peer_evp || CBS_len(&cbs) != 0) {
EXPECT_FALSE(is_valid);
return;
}
EC_KEY *peer_ec = EVP_PKEY_get0_EC_KEY(peer_evp.get());
@@ -170,11 +164,11 @@ static void RunWycheproofTest(FileTest *t) {
int ret =
ECDH_compute_key(actual.data(), actual.size(),
EC_KEY_get0_public_key(peer_ec), key.get(), nullptr);
if (result == WycheproofResult::kInvalid) {
EXPECT_EQ(-1, ret);
} else {
if (is_valid) {
EXPECT_EQ(static_cast<int>(actual.size()), ret);
EXPECT_EQ(Bytes(shared), Bytes(actual.data(), static_cast<size_t>(ret)));
} else {
EXPECT_EQ(-1, ret);
}
}
+39 -38
View File
@@ -382,18 +382,16 @@ char *ERR_error_string(uint32_t packed_error, char *ret) {
OPENSSL_memset(ret, 0, ERR_ERROR_STRING_BUF_LEN);
#endif
ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
return ret;
return ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
}
void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
char *ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
char lib_buf[64], reason_buf[64];
const char *lib_str, *reason_str;
unsigned lib, reason;
if (len == 0) {
return;
return NULL;
}
lib = ERR_GET_LIB(packed_error);
@@ -425,7 +423,7 @@ void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
if (len <= num_colons) {
// In this situation it's not possible to ensure that the correct number
// of colons are included in the output.
return;
return buf;
}
for (i = 0; i < num_colons; i++) {
@@ -444,6 +442,8 @@ void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
s = colon + 1;
}
}
return buf;
}
// err_string_cmp is a compare function for searching error values with
@@ -495,38 +495,39 @@ static const char *err_string_lookup(uint32_t lib, uint32_t key,
static const char *const kLibraryNames[ERR_NUM_LIBS] = {
"invalid library (0)",
"unknown library", // ERR_LIB_NONE
"system library", // ERR_LIB_SYS
"bignum routines", // ERR_LIB_BN
"RSA routines", // ERR_LIB_RSA
"Diffie-Hellman routines", // ERR_LIB_DH
"public key routines", // ERR_LIB_EVP
"memory buffer routines", // ERR_LIB_BUF
"object identifier routines", // ERR_LIB_OBJ
"PEM routines", // ERR_LIB_PEM
"DSA routines", // ERR_LIB_DSA
"X.509 certificate routines", // ERR_LIB_X509
"ASN.1 encoding routines", // ERR_LIB_ASN1
"configuration file routines", // ERR_LIB_CONF
"common libcrypto routines", // ERR_LIB_CRYPTO
"elliptic curve routines", // ERR_LIB_EC
"SSL routines", // ERR_LIB_SSL
"BIO routines", // ERR_LIB_BIO
"PKCS7 routines", // ERR_LIB_PKCS7
"PKCS8 routines", // ERR_LIB_PKCS8
"X509 V3 routines", // ERR_LIB_X509V3
"random number generator", // ERR_LIB_RAND
"ENGINE routines", // ERR_LIB_ENGINE
"OCSP routines", // ERR_LIB_OCSP
"UI routines", // ERR_LIB_UI
"COMP routines", // ERR_LIB_COMP
"ECDSA routines", // ERR_LIB_ECDSA
"ECDH routines", // ERR_LIB_ECDH
"HMAC routines", // ERR_LIB_HMAC
"Digest functions", // ERR_LIB_DIGEST
"Cipher functions", // ERR_LIB_CIPHER
"HKDF functions", // ERR_LIB_HKDF
"User defined functions", // ERR_LIB_USER
"unknown library", // ERR_LIB_NONE
"system library", // ERR_LIB_SYS
"bignum routines", // ERR_LIB_BN
"RSA routines", // ERR_LIB_RSA
"Diffie-Hellman routines", // ERR_LIB_DH
"public key routines", // ERR_LIB_EVP
"memory buffer routines", // ERR_LIB_BUF
"object identifier routines", // ERR_LIB_OBJ
"PEM routines", // ERR_LIB_PEM
"DSA routines", // ERR_LIB_DSA
"X.509 certificate routines", // ERR_LIB_X509
"ASN.1 encoding routines", // ERR_LIB_ASN1
"configuration file routines", // ERR_LIB_CONF
"common libcrypto routines", // ERR_LIB_CRYPTO
"elliptic curve routines", // ERR_LIB_EC
"SSL routines", // ERR_LIB_SSL
"BIO routines", // ERR_LIB_BIO
"PKCS7 routines", // ERR_LIB_PKCS7
"PKCS8 routines", // ERR_LIB_PKCS8
"X509 V3 routines", // ERR_LIB_X509V3
"random number generator", // ERR_LIB_RAND
"ENGINE routines", // ERR_LIB_ENGINE
"OCSP routines", // ERR_LIB_OCSP
"UI routines", // ERR_LIB_UI
"COMP routines", // ERR_LIB_COMP
"ECDSA routines", // ERR_LIB_ECDSA
"ECDH routines", // ERR_LIB_ECDH
"HMAC routines", // ERR_LIB_HMAC
"Digest functions", // ERR_LIB_DIGEST
"Cipher functions", // ERR_LIB_CIPHER
"HKDF functions", // ERR_LIB_HKDF
"Trust Token functions", // ERR_LIB_TRUST_TOKEN
"User defined functions", // ERR_LIB_USER
};
const char *ERR_lib_error_string(uint32_t packed_error) {
+1
View File
@@ -63,6 +63,7 @@ var libraryNames = []string{
"DIGEST",
"CIPHER",
"HKDF",
"TRUST_TOKEN",
"USER",
}
+48
View File
@@ -235,3 +235,51 @@ TEST(ErrTest, PreservesErrno) {
EXPECT_EQ(EINVAL, errno);
}
#endif
TEST(ErrTest, String) {
char buf[128];
const uint32_t err = ERR_PACK(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
EXPECT_STREQ(
"error:0e000044:common libcrypto routines:OPENSSL_internal:internal "
"error",
ERR_error_string_n(err, buf, sizeof(buf)));
// The buffer is exactly the right size.
EXPECT_STREQ(
"error:0e000044:common libcrypto routines:OPENSSL_internal:internal "
"error",
ERR_error_string_n(err, buf, 73));
// If the buffer is too short, the string is truncated.
EXPECT_STREQ(
"error:0e000044:common libcrypto routines:OPENSSL_internal:internal "
"erro",
ERR_error_string_n(err, buf, 72));
EXPECT_STREQ("error:0e000044:common libcrypto routines:OPENSSL_internal:",
ERR_error_string_n(err, buf, 59));
// Truncated log lines always have the right number of colons.
EXPECT_STREQ("error:0e000044:common libcrypto routines:OPENSSL_interna:",
ERR_error_string_n(err, buf, 58));
EXPECT_STREQ("error:0e000044:common libcrypto routines:OPENSSL_intern:",
ERR_error_string_n(err, buf, 57));
EXPECT_STREQ("error:0e000044:common libcryp::",
ERR_error_string_n(err, buf, 32));
EXPECT_STREQ("error:0e0000:::",
ERR_error_string_n(err, buf, 16));
EXPECT_STREQ("err::::",
ERR_error_string_n(err, buf, 8));
EXPECT_STREQ("::::",
ERR_error_string_n(err, buf, 5));
// If the buffer is too short for even four colons, |ERR_error_string_n| does
// not bother trying to preserve the format.
EXPECT_STREQ("err", ERR_error_string_n(err, buf, 4));
EXPECT_STREQ("er", ERR_error_string_n(err, buf, 3));
EXPECT_STREQ("e", ERR_error_string_n(err, buf, 2));
EXPECT_STREQ("", ERR_error_string_n(err, buf, 1));
// A buffer length of zero should not touch the buffer.
ERR_error_string_n(err, nullptr, 0);
}
+13 -8
View File
@@ -23,7 +23,6 @@ SSL,118,BAD_WRITE_RETRY
SSL,119,BIO_NOT_SET
SSL,261,BLOCK_CIPHER_PAD_IS_WRONG
SSL,120,BN_LIB
SSL,255,BUFFERED_MESSAGES_ON_CIPHER_CHANGE
SSL,121,BUFFER_TOO_SMALL
SSL,275,CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD
SSL,272,CANNOT_PARSE_LEAF_CERT
@@ -37,6 +36,7 @@ SSL,292,CERT_DECOMPRESSION_FAILED
SSL,127,CERT_LENGTH_MISMATCH
SSL,128,CHANNEL_ID_NOT_P256
SSL,129,CHANNEL_ID_SIGNATURE_INVALID
SSL,304,CIPHER_MISMATCH_ON_EARLY_DATA
SSL,130,CIPHER_OR_HASH_UNAVAILABLE
SSL,131,CLIENTHELLO_PARSE_FAILED
SSL,132,CLIENTHELLO_TLSEXT
@@ -64,6 +64,7 @@ SSL,147,ERROR_ADDING_EXTENSION
SSL,148,ERROR_IN_RECEIVED_CIPHER_LIST
SSL,149,ERROR_PARSING_EXTENSION
SSL,150,EXCESSIVE_MESSAGE_SIZE
SSL,255,EXCESS_HANDSHAKE_DATA
SSL,151,EXTRA_DATA_IN_MESSAGE
SSL,152,FRAGMENT_MISMATCH
SSL,153,GOT_NEXT_PROTO_WITHOUT_EXTENSION
@@ -85,6 +86,7 @@ SSL,160,INVALID_SSL_SESSION
SSL,161,INVALID_TICKET_KEYS_LENGTH
SSL,302,KEY_USAGE_BIT_INCORRECT
SSL,162,LENGTH_MISMATCH
SSL,307,MISSING_ALPN
SSL,164,MISSING_EXTENSION
SSL,258,MISSING_KEY_SHARE
SSL,165,MISSING_RSA_CERTIFICATE
@@ -132,6 +134,7 @@ SSL,195,PSK_IDENTITY_NOT_FOUND
SSL,196,PSK_NO_CLIENT_CB
SSL,197,PSK_NO_SERVER_CB
SSL,298,QUIC_INTERNAL_ERROR
SSL,305,QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED
SSL,198,READ_TIMEOUT_EXPIRED
SSL,199,RECORD_LENGTH_MISMATCH
SSL,200,RECORD_TOO_LARGE
@@ -172,6 +175,10 @@ SSL,290,SSL_SESSION_ID_TOO_LONG
SSL,276,TICKET_ENCRYPTION_FAILED
SSL,297,TLS13_DOWNGRADE
SSL,1049,TLSV1_ALERT_ACCESS_DENIED
SSL,1114,TLSV1_ALERT_BAD_CERTIFICATE_HASH_VALUE
SSL,1113,TLSV1_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE
SSL,1116,TLSV1_ALERT_CERTIFICATE_REQUIRED
SSL,1111,TLSV1_ALERT_CERTIFICATE_UNOBTAINABLE
SSL,1050,TLSV1_ALERT_DECODE_ERROR
SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED
SSL,1051,TLSV1_ALERT_DECRYPT_ERROR
@@ -179,18 +186,15 @@ SSL,1060,TLSV1_ALERT_EXPORT_RESTRICTION
SSL,1086,TLSV1_ALERT_INAPPROPRIATE_FALLBACK
SSL,1071,TLSV1_ALERT_INSUFFICIENT_SECURITY
SSL,1080,TLSV1_ALERT_INTERNAL_ERROR
SSL,1120,TLSV1_ALERT_NO_APPLICATION_PROTOCOL
SSL,1100,TLSV1_ALERT_NO_RENEGOTIATION
SSL,1070,TLSV1_ALERT_PROTOCOL_VERSION
SSL,1022,TLSV1_ALERT_RECORD_OVERFLOW
SSL,1048,TLSV1_ALERT_UNKNOWN_CA
SSL,1115,TLSV1_ALERT_UNKNOWN_PSK_IDENTITY
SSL,1112,TLSV1_ALERT_UNRECOGNIZED_NAME
SSL,1110,TLSV1_ALERT_UNSUPPORTED_EXTENSION
SSL,1090,TLSV1_ALERT_USER_CANCELLED
SSL,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE
SSL,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE
SSL,1116,TLSV1_CERTIFICATE_REQUIRED
SSL,1111,TLSV1_CERTIFICATE_UNOBTAINABLE
SSL,1115,TLSV1_UNKNOWN_PSK_IDENTITY
SSL,1112,TLSV1_UNRECOGNIZED_NAME
SSL,1110,TLSV1_UNSUPPORTED_EXTENSION
SSL,217,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST
SSL,218,TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG
SSL,219,TOO_MANY_EMPTY_FRAGMENTS
@@ -200,6 +204,7 @@ SSL,300,TOO_MUCH_READ_EARLY_DATA
SSL,270,TOO_MUCH_SKIPPED_EARLY_DATA
SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS
SSL,293,UNCOMPRESSED_CERT_TOO_LARGE
SSL,306,UNEXPECTED_COMPATIBILITY_MODE
SSL,222,UNEXPECTED_EXTENSION
SSL,279,UNEXPECTED_EXTENSION_ON_EARLY_DATA
SSL,223,UNEXPECTED_MESSAGE
+15
View File
@@ -0,0 +1,15 @@
TRUST_TOKEN,111,BAD_VALIDITY_CHECK
TRUST_TOKEN,101,BUFFER_TOO_SMALL
TRUST_TOKEN,103,DECODE_ERROR
TRUST_TOKEN,105,DECODE_FAILURE
TRUST_TOKEN,109,INVALID_KEY_ID
TRUST_TOKEN,106,INVALID_METADATA
TRUST_TOKEN,113,INVALID_METADATA_KEY
TRUST_TOKEN,114,INVALID_PROOF
TRUST_TOKEN,110,INVALID_TOKEN
TRUST_TOKEN,100,KEYGEN_FAILURE
TRUST_TOKEN,108,NO_KEYS_CONFIGURED
TRUST_TOKEN,112,NO_SRR_KEY_CONFIGURED
TRUST_TOKEN,102,OVER_BATCHSIZE
TRUST_TOKEN,104,SRR_SIGNATURE_ERROR
TRUST_TOKEN,107,TOO_MANY_KEYS
+3
View File
@@ -6,13 +6,16 @@ X509,104,CANT_CHECK_DH_KEY
X509,105,CERT_ALREADY_IN_HASH_TABLE
X509,106,CRL_ALREADY_DELTA
X509,107,CRL_VERIFY_FAILURE
X509,138,DELTA_CRL_WITHOUT_CRL_NUMBER
X509,108,IDP_MISMATCH
X509,109,INVALID_BIT_STRING_BITS_LEFT
X509,110,INVALID_DIRECTORY
X509,139,INVALID_FIELD_FOR_VERSION
X509,111,INVALID_FIELD_NAME
X509,136,INVALID_PARAMETER
X509,112,INVALID_PSS_PARAMETERS
X509,113,INVALID_TRUST
X509,140,INVALID_VERSION
X509,114,ISSUER_MISMATCH
X509,115,KEY_TYPE_MISMATCH
X509,116,KEY_VALUES_MISMATCH
+143
View File
@@ -65,6 +65,7 @@
#include <openssl/rsa.h>
#include "internal.h"
#include "../bytestring/internal.h"
#include "../internal.h"
@@ -386,3 +387,145 @@ err:
EVP_PKEY_free(ret);
return NULL;
}
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **out, const uint8_t **inp, long len) {
if (len < 0) {
return NULL;
}
CBS cbs;
CBS_init(&cbs, *inp, (size_t)len);
EVP_PKEY *ret = EVP_parse_public_key(&cbs);
if (ret == NULL) {
return NULL;
}
if (out != NULL) {
EVP_PKEY_free(*out);
*out = ret;
}
*inp = CBS_data(&cbs);
return ret;
}
int i2d_PUBKEY(const EVP_PKEY *pkey, uint8_t **outp) {
CBB cbb;
if (!CBB_init(&cbb, 128) ||
!EVP_marshal_public_key(&cbb, pkey)) {
CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
}
RSA *d2i_RSA_PUBKEY(RSA **out, const uint8_t **inp, long len) {
if (len < 0) {
return NULL;
}
CBS cbs;
CBS_init(&cbs, *inp, (size_t)len);
EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
if (pkey == NULL) {
return NULL;
}
RSA *rsa = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
if (rsa == NULL) {
return NULL;
}
if (out != NULL) {
RSA_free(*out);
*out = rsa;
}
*inp = CBS_data(&cbs);
return rsa;
}
int i2d_RSA_PUBKEY(const RSA *rsa, uint8_t **outp) {
int ret = -1;
EVP_PKEY *pkey = EVP_PKEY_new();
if (pkey == NULL ||
!EVP_PKEY_set1_RSA(pkey, (RSA *)rsa)) {
goto err;
}
ret = i2d_PUBKEY(pkey, outp);
err:
EVP_PKEY_free(pkey);
return ret;
}
DSA *d2i_DSA_PUBKEY(DSA **out, const uint8_t **inp, long len) {
if (len < 0) {
return NULL;
}
CBS cbs;
CBS_init(&cbs, *inp, (size_t)len);
EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
if (pkey == NULL) {
return NULL;
}
DSA *dsa = EVP_PKEY_get1_DSA(pkey);
EVP_PKEY_free(pkey);
if (dsa == NULL) {
return NULL;
}
if (out != NULL) {
DSA_free(*out);
*out = dsa;
}
*inp = CBS_data(&cbs);
return dsa;
}
int i2d_DSA_PUBKEY(const DSA *dsa, uint8_t **outp) {
int ret = -1;
EVP_PKEY *pkey = EVP_PKEY_new();
if (pkey == NULL ||
!EVP_PKEY_set1_DSA(pkey, (DSA *)dsa)) {
goto err;
}
ret = i2d_PUBKEY(pkey, outp);
err:
EVP_PKEY_free(pkey);
return ret;
}
EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp, long len) {
if (len < 0) {
return NULL;
}
CBS cbs;
CBS_init(&cbs, *inp, (size_t)len);
EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
if (pkey == NULL) {
return NULL;
}
EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
EVP_PKEY_free(pkey);
if (ec_key == NULL) {
return NULL;
}
if (out != NULL) {
EC_KEY_free(*out);
*out = ec_key;
}
*inp = CBS_data(&cbs);
return ec_key;
}
int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp) {
int ret = -1;
EVP_PKEY *pkey = EVP_PKEY_new();
if (pkey == NULL ||
!EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY *)ec_key)) {
goto err;
}
ret = i2d_PUBKEY(pkey, outp);
err:
EVP_PKEY_free(pkey);
return ret;
}
+231 -68
View File
@@ -70,7 +70,6 @@ OPENSSL_MSVC_PRAGMA(warning(pop))
#include <gtest/gtest.h>
#include <openssl/buf.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
@@ -280,8 +279,8 @@ static bool SetupContext(FileTest *t, KeyMap *key_map, EVP_PKEY_CTX *ctx) {
}
// For historical reasons, |EVP_PKEY_CTX_set0_rsa_oaep_label| expects to be
// take ownership of the input.
bssl::UniquePtr<uint8_t> buf(
reinterpret_cast<uint8_t *>(BUF_memdup(label.data(), label.size())));
bssl::UniquePtr<uint8_t> buf(reinterpret_cast<uint8_t *>(
OPENSSL_memdup(label.data(), label.size())));
if (!buf ||
!EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, buf.get(), label.size())) {
return false;
@@ -568,40 +567,10 @@ TEST(EVPTest, TestVectors) {
});
}
static void RunWycheproofTest(const char *path) {
static void RunWycheproofVerifyTest(const char *path) {
SCOPED_TRACE(path);
FileTestGTest(path, [](FileTest *t) {
t->IgnoreInstruction("key.type");
// Extra ECDSA fields.
t->IgnoreInstruction("key.curve");
t->IgnoreInstruction("key.keySize");
t->IgnoreInstruction("key.wx");
t->IgnoreInstruction("key.wy");
t->IgnoreInstruction("key.uncompressed");
// Extra RSA fields.
t->IgnoreInstruction("e");
t->IgnoreInstruction("keyAsn");
t->IgnoreInstruction("keysize");
t->IgnoreInstruction("n");
t->IgnoreAttribute("padding");
t->IgnoreInstruction("keyJwk.alg");
t->IgnoreInstruction("keyJwk.e");
t->IgnoreInstruction("keyJwk.kid");
t->IgnoreInstruction("keyJwk.kty");
t->IgnoreInstruction("keyJwk.n");
// Extra EdDSA fields.
t->IgnoreInstruction("key.pk");
t->IgnoreInstruction("key.sk");
t->IgnoreInstruction("jwk.crv");
t->IgnoreInstruction("jwk.d");
t->IgnoreInstruction("jwk.kid");
t->IgnoreInstruction("jwk.kty");
t->IgnoreInstruction("jwk.x");
// Extra DSA fields.
t->IgnoreInstruction("key.g");
t->IgnoreInstruction("key.p");
t->IgnoreInstruction("key.q");
t->IgnoreInstruction("key.y");
t->IgnoreAllUnusedInstructions();
std::vector<uint8_t> der;
ASSERT_TRUE(t->GetInstructionBytes(&der, "keyDer"));
@@ -646,13 +615,7 @@ static void RunWycheproofTest(const char *path) {
bool sig_ok = DSA_check_signature(&valid, digest, digest_len, sig.data(),
sig.size(), dsa) &&
valid;
if (result == WycheproofResult::kValid) {
EXPECT_TRUE(sig_ok);
} else if (result == WycheproofResult::kInvalid) {
EXPECT_FALSE(sig_ok);
} else {
// this is a legacy signature, which may or may not be accepted.
}
EXPECT_EQ(sig_ok, result.IsValid());
} else {
bssl::ScopedEVP_MD_CTX ctx;
EVP_PKEY_CTX *pctx;
@@ -665,75 +628,275 @@ static void RunWycheproofTest(const char *path) {
}
int ret = EVP_DigestVerify(ctx.get(), sig.data(), sig.size(), msg.data(),
msg.size());
if (result == WycheproofResult::kValid) {
EXPECT_EQ(1, ret);
} else if (result == WycheproofResult::kInvalid) {
EXPECT_EQ(0, ret);
} else {
// this is a legacy signature, which may or may not be accepted.
EXPECT_TRUE(ret == 1 || ret == 0);
}
// BoringSSL does not enforce policies on weak keys and leaves it to the
// caller.
EXPECT_EQ(ret,
result.IsValid({"SmallModulus", "SmallPublicKey", "WeakHash"})
? 1
: 0);
}
});
}
TEST(EVPTest, WycheproofDSA) {
RunWycheproofTest("third_party/wycheproof_testvectors/dsa_test.txt");
RunWycheproofVerifyTest("third_party/wycheproof_testvectors/dsa_test.txt");
}
TEST(EVPTest, WycheproofECDSAP224) {
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt");
}
TEST(EVPTest, WycheproofECDSAP256) {
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt");
}
TEST(EVPTest, WycheproofECDSAP384) {
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt");
}
TEST(EVPTest, WycheproofECDSAP521) {
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt");
}
TEST(EVPTest, WycheproofEdDSA) {
RunWycheproofTest("third_party/wycheproof_testvectors/eddsa_test.txt");
RunWycheproofVerifyTest("third_party/wycheproof_testvectors/eddsa_test.txt");
}
TEST(EVPTest, WycheproofRSAPKCS1) {
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_2048_sha224_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_2048_sha256_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_2048_sha384_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_2048_sha512_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_3072_sha256_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_3072_sha384_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_3072_sha512_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_4096_sha384_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.txt");
// TODO(davidben): Is this file redundant with the tests above?
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_signature_test.txt");
}
TEST(EVPTest, WycheproofRSAPKCS1Sign) {
FileTestGTest(
"third_party/wycheproof_testvectors/rsa_sig_gen_misc_test.txt",
[](FileTest *t) {
t->IgnoreAllUnusedInstructions();
std::vector<uint8_t> pkcs8;
ASSERT_TRUE(t->GetInstructionBytes(&pkcs8, "privateKeyPkcs8"));
CBS cbs;
CBS_init(&cbs, pkcs8.data(), pkcs8.size());
bssl::UniquePtr<EVP_PKEY> key(EVP_parse_private_key(&cbs));
ASSERT_TRUE(key);
const EVP_MD *md = GetWycheproofDigest(t, "sha", true);
ASSERT_TRUE(md);
std::vector<uint8_t> msg, sig;
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
ASSERT_TRUE(t->GetBytes(&sig, "sig"));
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
bssl::ScopedEVP_MD_CTX ctx;
EVP_PKEY_CTX *pctx;
ASSERT_TRUE(
EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr, key.get()));
std::vector<uint8_t> out(EVP_PKEY_size(key.get()));
size_t len = out.size();
int ret =
EVP_DigestSign(ctx.get(), out.data(), &len, msg.data(), msg.size());
// BoringSSL does not enforce policies on weak keys and leaves it to the
// caller.
bool is_valid =
result.IsValid({"SmallModulus", "SmallPublicKey", "WeakHash"});
EXPECT_EQ(ret, is_valid ? 1 : 0);
if (is_valid) {
out.resize(len);
EXPECT_EQ(Bytes(sig), Bytes(out));
}
});
}
TEST(EVPTest, WycheproofRSAPSS) {
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/"
"rsa_pss_2048_sha256_mgf1_32_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/"
"rsa_pss_3072_sha256_mgf1_32_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/"
"rsa_pss_4096_sha256_mgf1_32_test.txt");
RunWycheproofTest(
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/"
"rsa_pss_4096_sha512_mgf1_32_test.txt");
RunWycheproofTest("third_party/wycheproof_testvectors/rsa_pss_misc_test.txt");
RunWycheproofVerifyTest(
"third_party/wycheproof_testvectors/rsa_pss_misc_test.txt");
}
static void RunWycheproofDecryptTest(
const char *path,
std::function<void(FileTest *, EVP_PKEY_CTX *)> setup_cb) {
FileTestGTest(path, [&](FileTest *t) {
t->IgnoreAllUnusedInstructions();
std::vector<uint8_t> pkcs8;
ASSERT_TRUE(t->GetInstructionBytes(&pkcs8, "privateKeyPkcs8"));
CBS cbs;
CBS_init(&cbs, pkcs8.data(), pkcs8.size());
bssl::UniquePtr<EVP_PKEY> key(EVP_parse_private_key(&cbs));
ASSERT_TRUE(key);
std::vector<uint8_t> ct, msg;
ASSERT_TRUE(t->GetBytes(&ct, "ct"));
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key.get(), nullptr));
ASSERT_TRUE(ctx);
ASSERT_TRUE(EVP_PKEY_decrypt_init(ctx.get()));
ASSERT_NO_FATAL_FAILURE(setup_cb(t, ctx.get()));
std::vector<uint8_t> out(EVP_PKEY_size(key.get()));
size_t len = out.size();
int ret =
EVP_PKEY_decrypt(ctx.get(), out.data(), &len, ct.data(), ct.size());
// BoringSSL does not enforce policies on weak keys and leaves it to the
// caller.
bool is_valid = result.IsValid({"SmallModulus"});
EXPECT_EQ(ret, is_valid ? 1 : 0);
if (is_valid) {
out.resize(len);
EXPECT_EQ(Bytes(msg), Bytes(out));
}
});
}
static void RunWycheproofOAEPTest(const char *path) {
RunWycheproofDecryptTest(path, [](FileTest *t, EVP_PKEY_CTX *ctx) {
const EVP_MD *md = GetWycheproofDigest(t, "sha", true);
ASSERT_TRUE(md);
const EVP_MD *mgf1_md = GetWycheproofDigest(t, "mgfSha", true);
ASSERT_TRUE(mgf1_md);
std::vector<uint8_t> label;
ASSERT_TRUE(t->GetBytes(&label, "label"));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgf1_md));
bssl::UniquePtr<uint8_t> label_copy(
static_cast<uint8_t *>(OPENSSL_memdup(label.data(), label.size())));
ASSERT_TRUE(label_copy || label.empty());
ASSERT_TRUE(
EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy.get(), label.size()));
// |EVP_PKEY_CTX_set0_rsa_oaep_label| takes ownership on success.
label_copy.release();
});
}
TEST(EVPTest, WycheproofRSAOAEP2048) {
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha1_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha224_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha224_mgf1sha224_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha256_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha256_mgf1sha256_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha384_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha384_mgf1sha384_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha512_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_2048_sha512_mgf1sha512_test.txt");
}
TEST(EVPTest, WycheproofRSAOAEP3072) {
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_3072_sha256_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_3072_sha256_mgf1sha256_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_3072_sha512_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_3072_sha512_mgf1sha512_test.txt");
}
TEST(EVPTest, WycheproofRSAOAEP4096) {
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_4096_sha256_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_4096_sha256_mgf1sha256_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_4096_sha512_mgf1sha1_test.txt");
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/"
"rsa_oaep_4096_sha512_mgf1sha512_test.txt");
}
TEST(EVPTest, WycheproofRSAOAEPMisc) {
RunWycheproofOAEPTest(
"third_party/wycheproof_testvectors/rsa_oaep_misc_test.txt");
}
static void RunWycheproofPKCS1DecryptTest(const char *path) {
RunWycheproofDecryptTest(path, [](FileTest *t, EVP_PKEY_CTX *ctx) {
// No setup needed. PKCS#1 is, sadly, the default.
});
}
TEST(EVPTest, WycheproofRSAPKCS1Decrypt) {
RunWycheproofPKCS1DecryptTest(
"third_party/wycheproof_testvectors/rsa_pkcs1_2048_test.txt");
RunWycheproofPKCS1DecryptTest(
"third_party/wycheproof_testvectors/rsa_pkcs1_3072_test.txt");
RunWycheproofPKCS1DecryptTest(
"third_party/wycheproof_testvectors/rsa_pkcs1_4096_test.txt");
}
-1
View File
@@ -58,7 +58,6 @@
#include <string.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/digest.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
+14 -2
View File
@@ -59,7 +59,6 @@
#include <string.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -135,7 +134,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
dctx->saltlen = sctx->saltlen;
if (sctx->oaep_label) {
OPENSSL_free(dctx->oaep_label);
dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
if (!dctx->oaep_label) {
return 0;
}
@@ -569,6 +568,19 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) {
0, out_padding);
}
int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
return 0;
}
int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, int salt_len) {
return 0;
}
int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx,
const EVP_MD *md) {
return 0;
}
int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) {
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
+1 -2
View File
@@ -14,7 +14,6 @@
#include <openssl/evp.h>
#include <openssl/buf.h>
#include <openssl/bytestring.h>
#include <openssl/curve25519.h>
#include <openssl/err.h>
@@ -244,6 +243,6 @@ size_t EVP_PKEY_get1_tls_encodedpoint(const EVP_PKEY *pkey, uint8_t **out_ptr) {
return 0;
}
*out_ptr = BUF_memdup(key->pub, 32);
*out_ptr = OPENSSL_memdup(key->pub, 32);
return *out_ptr == NULL ? 0 : 32;
}
-6
View File
@@ -6,7 +6,6 @@ if(${ARCH} STREQUAL "x86_64")
aesni-gcm-x86_64.${ASM_EXT}
aesni-x86_64.${ASM_EXT}
aes-x86_64.${ASM_EXT}
ghash-ssse3-x86_64.${ASM_EXT}
ghash-x86_64.${ASM_EXT}
md5-x86_64.${ASM_EXT}
@@ -27,7 +26,6 @@ if(${ARCH} STREQUAL "x86")
set(
BCM_ASM_SOURCES
aes-586.${ASM_EXT}
aesni-x86.${ASM_EXT}
bn-586.${ASM_EXT}
co-586.${ASM_EXT}
@@ -46,7 +44,6 @@ if(${ARCH} STREQUAL "arm")
set(
BCM_ASM_SOURCES
aes-armv4.${ASM_EXT}
aesv8-armx.${ASM_EXT}
armv4-mont.${ASM_EXT}
bsaes-armv7.${ASM_EXT}
@@ -83,14 +80,11 @@ if(${ARCH} STREQUAL "ppc64le")
)
endif()
perlasm(aes-586.${ASM_EXT} aes/asm/aes-586.pl)
perlasm(aes-armv4.${ASM_EXT} aes/asm/aes-armv4.pl)
perlasm(aesni-gcm-x86_64.${ASM_EXT} modes/asm/aesni-gcm-x86_64.pl)
perlasm(aesni-x86_64.${ASM_EXT} aes/asm/aesni-x86_64.pl)
perlasm(aesni-x86.${ASM_EXT} aes/asm/aesni-x86.pl)
perlasm(aesp8-ppc.${ASM_EXT} aes/asm/aesp8-ppc.pl)
perlasm(aesv8-armx.${ASM_EXT} aes/asm/aesv8-armx.pl)
perlasm(aes-x86_64.${ASM_EXT} aes/asm/aes-x86_64.pl)
perlasm(armv4-mont.${ASM_EXT} bn/asm/armv4-mont.pl)
perlasm(armv8-mont.${ASM_EXT} bn/asm/armv8-mont.pl)
perlasm(bn-586.${ASM_EXT} bn/asm/bn-586.pl)
+11
View File
@@ -10,6 +10,7 @@ BoringCrypto has undergone the following validations:
1. 2017-06-15: certificate [#2964](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/2964), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx) (in docx format).
1. 2018-07-30: certificate [#3318](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3318), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx) (in docx format).
1. 2019-08-08: certificate [#3678](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3678), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20190808.docx) (in docx format).
## Running CAVP tests
@@ -46,6 +47,10 @@ The DRBG state is kept in a thread-local structure and is seeded from one of the
In FIPS mode, each of those entropy sources is subject to a 10× overread. That is, when *n* bytes of entropy are needed, *10n* bytes will be read from the entropy source and XORed down to *n* bytes. Reads from the entropy source are also processed in blocks of 16 bytes and if two consecutive chunks are equal the process will abort.
In the case that the seed is taken from RDRAND, getrandom will also be queried with `GRND_NONBLOCK` to attempt to obtain additional entropy from the operating system. If available, that extra entropy will be XORed into the whitened seed.
On Android, only `getrandom` is supported and, when seeding for the first time, the system property `ro.boringcrypto.hwrand` is queried. If set to `true` then `getrandom` will be called with the `GRND_RANDOM` flag. Only entropy draws destined for DRBG seeds are affected by this. We are not suggesting that there is any security advantage at all to doing this, and thus recommend that Android vendors do _not_ set this flag.
The CTR-DRBG is reseeded every 4096 calls to `RAND_bytes`. Thus the process will randomly crash about every 2¹³⁵ calls.
The FIPS PRNGs allow “additional input” to be fed into a given call. We use this feature to be as robust as possible to state duplication from process forks and VM copies: for every call we read 32 bytes of “additional data” from the entropy source (without overread) which means that cloned states will diverge at the next call to `RAND_bytes`. This is called “prediction resistance” by FIPS, but we do *not* claim this property in a FIPS context because we don't implement it the way they want.
@@ -54,6 +59,12 @@ There is a second interface to the RNG which allows the caller to supply bytes t
FIPS requires that RNG state be zeroed when the process exits. In order to implement this, all per-thread RNG states are tracked in a linked list and a destructor function is included which clears them. In order for this to be safe in the presence of threads, a lock is used to stop all other threads from using the RNG once this process has begun. Thus the main thread exiting may cause other threads to deadlock, and drawing on entropy in a destructor function may also deadlock.
## Self-test optimisation
On Android, the self-tests are optimised in line with [IG](https://csrc.nist.gov/csrc/media/projects/cryptographic-module-validation-program/documents/fips140-2/fips1402ig.pdf) section 9.11. The module will always perform the integrity test at power-on, but the self-tests will test for the presence of a file named after the hex encoded, HMAC-SHA-256 hash of the module in `/dev/boringssl/selftest/`. If such a file is found then the self-tests are skipped. Otherwise, after the self-tests complete successfully, that file will be written. Any I/O errors are ignored and, if they occur when testing for the presence of the file, the module acts as if it's not present.
It is intended that a `tmpfs` be mounted at that location in order to skip running the self tests for every process once they have already passed in a given instance of the operating system.
## Integrity Test
FIPS-140 mandates that a module calculate an HMAC of its own code in a constructor function and compare the result to a known-good value. Typical code produced by a C compiler includes large numbers of relocations: places in the machine code where the linker needs to resolve and inject the final value of a symbolic expression. These relocations mean that the bytes that make up any specific bit of code generally aren't known until the final link has completed.
-752
View File
@@ -56,758 +56,6 @@
#include "../modes/internal.h"
#if defined(OPENSSL_NO_ASM) || \
(!defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && !defined(OPENSSL_ARM))
// Te0[x] = S [x].[02, 01, 01, 03];
// Te1[x] = S [x].[03, 02, 01, 01];
// Te2[x] = S [x].[01, 03, 02, 01];
// Te3[x] = S [x].[01, 01, 03, 02];
//
// Td0[x] = Si[x].[0e, 09, 0d, 0b];
// Td1[x] = Si[x].[0b, 0e, 09, 0d];
// Td2[x] = Si[x].[0d, 0b, 0e, 09];
// Td3[x] = Si[x].[09, 0d, 0b, 0e];
// Td4[x] = Si[x].[01];
static const uint32_t Te0[256] = {
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU,
0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U,
0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U,
0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU,
0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U,
0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU,
0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U,
0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U,
0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU,
0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU,
0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U,
0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U,
0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U,
0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U,
0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U,
0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU,
0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U,
0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U,
0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U,
0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U,
0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU,
0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U,
0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU,
0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U,
0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU,
0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU,
0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U,
0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U,
0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU,
0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU,
0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU,
0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U,
0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U,
0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U,
0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U,
0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U,
0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU,
0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U,
0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U,
0x2c16163aU, };
static const uint32_t Te1[256] = {
0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U,
0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U,
0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU,
0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU,
0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U,
0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U,
0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U,
0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U,
0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U,
0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U,
0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU,
0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U,
0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U,
0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU,
0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U,
0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U,
0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU,
0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U,
0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U,
0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU,
0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U,
0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U,
0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU,
0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U,
0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U,
0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U,
0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U,
0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU,
0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU,
0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U,
0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU,
0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU,
0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U,
0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U,
0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U,
0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U,
0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU,
0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U,
0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU,
0x3a2c1616U, };
static const uint32_t Te2[256] = {
0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U,
0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U,
0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU,
0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU,
0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U,
0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U,
0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U,
0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U,
0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U,
0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U,
0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU,
0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U,
0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U,
0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU,
0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U,
0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U,
0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU,
0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U,
0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U,
0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU,
0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U,
0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U,
0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU,
0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U,
0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U,
0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U,
0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U,
0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU,
0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU,
0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U,
0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU,
0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU,
0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U,
0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U,
0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U,
0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U,
0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU,
0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U,
0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU,
0x163a2c16U, };
static const uint32_t Te3[256] = {
0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU,
0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U,
0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU,
0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U,
0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U,
0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU,
0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U,
0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U,
0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU,
0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U,
0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU,
0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U,
0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U,
0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU,
0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U,
0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU,
0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U,
0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U,
0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U,
0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U,
0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U,
0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U,
0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U,
0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU,
0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U,
0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU,
0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U,
0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U,
0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U,
0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU,
0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U,
0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU,
0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U,
0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U,
0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U,
0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U,
0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U,
0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U,
0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU,
0x16163a2cU, };
static const uint32_t Td0[256] = {
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU,
0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U,
0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U,
0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U,
0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U,
0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU,
0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U,
0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U,
0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U,
0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU,
0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U,
0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U,
0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U,
0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U,
0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U,
0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU,
0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U,
0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U,
0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU,
0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU,
0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U,
0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU,
0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U,
0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU,
0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU,
0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU,
0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU,
0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U,
0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU,
0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U,
0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU,
0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU,
0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U,
0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU,
0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U,
0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U,
0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U,
0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU,
0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U,
0xd0b85742U, };
static const uint32_t Td1[256] = {
0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU,
0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU,
0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U,
0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU,
0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U,
0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU,
0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U,
0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU,
0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU,
0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU,
0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU,
0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U,
0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU,
0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U,
0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU,
0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU,
0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U,
0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U,
0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU,
0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U,
0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU,
0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U,
0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U,
0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U,
0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U,
0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U,
0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U,
0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U,
0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U,
0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U,
0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U,
0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U,
0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU,
0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U,
0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U,
0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU,
0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U,
0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U,
0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU,
0x42d0b857U, };
static const uint32_t Td2[256] = {
0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU,
0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U,
0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U,
0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU,
0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U,
0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U,
0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U,
0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U,
0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU,
0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU,
0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U,
0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU,
0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U,
0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU,
0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U,
0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU,
0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU,
0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU,
0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U,
0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U,
0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U,
0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU,
0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U,
0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U,
0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U,
0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U,
0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U,
0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U,
0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU,
0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU,
0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U,
0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU,
0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU,
0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U,
0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U,
0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U,
0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU,
0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU,
0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU,
0x5742d0b8U, };
static const uint32_t Td3[256] = {
0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU,
0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU,
0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U,
0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U,
0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U,
0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U,
0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U,
0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU,
0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U,
0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU,
0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U,
0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U,
0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U,
0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U,
0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U,
0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU,
0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U,
0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U,
0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU,
0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU,
0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U,
0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U,
0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU,
0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U,
0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U,
0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U,
0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU,
0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU,
0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU,
0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU,
0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U,
0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U,
0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U,
0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU,
0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U,
0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U,
0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U,
0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U,
0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U,
0xb85742d0U, };
static const uint8_t Td4[256] = {
0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U,
0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU,
0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U,
0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU,
0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U,
0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U, 0xf8U,
0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU,
0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU,
0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U,
0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U,
0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U, 0x11U, 0x41U,
0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U,
0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U,
0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU,
0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U,
0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U,
0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U,
0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU,
0x93U, 0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U,
0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU,
0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U,
0x21U, 0x0cU, 0x7dU, };
static const uint32_t rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
// for 128-bit blocks, Rijndael never uses more than 10 rcon values
};
int aes_nohw_set_encrypt_key(const uint8_t *key, unsigned bits,
AES_KEY *aeskey) {
uint32_t *rk;
int i = 0;
uint32_t temp;
if (!key || !aeskey) {
return -1;
}
switch (bits) {
case 128:
aeskey->rounds = 10;
break;
case 192:
aeskey->rounds = 12;
break;
case 256:
aeskey->rounds = 14;
break;
default:
return -2;
}
rk = aeskey->rd_key;
rk[0] = GETU32(key);
rk[1] = GETU32(key + 4);
rk[2] = GETU32(key + 8);
rk[3] = GETU32(key + 12);
if (bits == 128) {
while (1) {
temp = rk[3];
rk[4] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
(Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te0[(temp) & 0xff] & 0x0000ff00) ^
(Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
if (++i == 10) {
return 0;
}
rk += 4;
}
}
rk[4] = GETU32(key + 16);
rk[5] = GETU32(key + 20);
if (bits == 192) {
while (1) {
temp = rk[5];
rk[6] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
(Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te0[(temp) & 0xff] & 0x0000ff00) ^
(Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
rk[7] = rk[1] ^ rk[6];
rk[8] = rk[2] ^ rk[7];
rk[9] = rk[3] ^ rk[8];
if (++i == 8) {
return 0;
}
rk[10] = rk[4] ^ rk[9];
rk[11] = rk[5] ^ rk[10];
rk += 6;
}
}
rk[6] = GETU32(key + 24);
rk[7] = GETU32(key + 28);
if (bits == 256) {
while (1) {
temp = rk[7];
rk[8] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
(Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te0[(temp) & 0xff] & 0x0000ff00) ^
(Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
rk[9] = rk[1] ^ rk[8];
rk[10] = rk[2] ^ rk[9];
rk[11] = rk[3] ^ rk[10];
if (++i == 7) {
return 0;
}
temp = rk[11];
rk[12] = rk[4] ^ (Te2[(temp >> 24)] & 0xff000000) ^
(Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^
(Te1[(temp) & 0xff] & 0x000000ff);
rk[13] = rk[5] ^ rk[12];
rk[14] = rk[6] ^ rk[13];
rk[15] = rk[7] ^ rk[14];
rk += 8;
}
}
return 0;
}
int aes_nohw_set_decrypt_key(const uint8_t *key, unsigned bits,
AES_KEY *aeskey) {
uint32_t *rk;
int i, j, status;
uint32_t temp;
// first, start with an encryption schedule
status = AES_set_encrypt_key(key, bits, aeskey);
if (status < 0) {
return status;
}
rk = aeskey->rd_key;
// invert the order of the round keys:
for (i = 0, j = 4 * aeskey->rounds; i < j; i += 4, j -= 4) {
temp = rk[i];
rk[i] = rk[j];
rk[j] = temp;
temp = rk[i + 1];
rk[i + 1] = rk[j + 1];
rk[j + 1] = temp;
temp = rk[i + 2];
rk[i + 2] = rk[j + 2];
rk[j + 2] = temp;
temp = rk[i + 3];
rk[i + 3] = rk[j + 3];
rk[j + 3] = temp;
}
// apply the inverse MixColumn transform to all round keys but the first and
// the last:
for (i = 1; i < (int)aeskey->rounds; i++) {
rk += 4;
rk[0] =
Td0[Te1[(rk[0] >> 24)] & 0xff] ^ Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^
Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[0]) & 0xff] & 0xff];
rk[1] =
Td0[Te1[(rk[1] >> 24)] & 0xff] ^ Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^
Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[1]) & 0xff] & 0xff];
rk[2] =
Td0[Te1[(rk[2] >> 24)] & 0xff] ^ Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^
Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[2]) & 0xff] & 0xff];
rk[3] =
Td0[Te1[(rk[3] >> 24)] & 0xff] ^ Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^
Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[3]) & 0xff] & 0xff];
}
return 0;
}
void aes_nohw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
const uint32_t *rk;
uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
int r;
assert(in && out && key);
rk = key->rd_key;
// map byte array block to cipher state
// and add initial round key:
s0 = GETU32(in) ^ rk[0];
s1 = GETU32(in + 4) ^ rk[1];
s2 = GETU32(in + 8) ^ rk[2];
s3 = GETU32(in + 12) ^ rk[3];
// Nr - 1 full rounds:
r = key->rounds >> 1;
for (;;) {
t0 = Te0[(s0 >> 24)] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^
Te3[(s3) & 0xff] ^ rk[4];
t1 = Te0[(s1 >> 24)] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^
Te3[(s0) & 0xff] ^ rk[5];
t2 = Te0[(s2 >> 24)] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^
Te3[(s1) & 0xff] ^ rk[6];
t3 = Te0[(s3 >> 24)] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^
Te3[(s2) & 0xff] ^ rk[7];
rk += 8;
if (--r == 0) {
break;
}
s0 = Te0[(t0 >> 24)] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^
Te3[(t3) & 0xff] ^ rk[0];
s1 = Te0[(t1 >> 24)] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^
Te3[(t0) & 0xff] ^ rk[1];
s2 = Te0[(t2 >> 24)] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^
Te3[(t1) & 0xff] ^ rk[2];
s3 = Te0[(t3 >> 24)] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^
Te3[(t2) & 0xff] ^ rk[3];
}
// apply last round and map cipher state to byte array block:
s0 = (Te2[(t0 >> 24)] & 0xff000000) ^ (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t3) & 0xff] & 0x000000ff) ^
rk[0];
PUTU32(out, s0);
s1 = (Te2[(t1 >> 24)] & 0xff000000) ^ (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t0) & 0xff] & 0x000000ff) ^
rk[1];
PUTU32(out + 4, s1);
s2 = (Te2[(t2 >> 24)] & 0xff000000) ^ (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t1) & 0xff] & 0x000000ff) ^
rk[2];
PUTU32(out + 8, s2);
s3 = (Te2[(t3 >> 24)] & 0xff000000) ^ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t2) & 0xff] & 0x000000ff) ^
rk[3];
PUTU32(out + 12, s3);
}
void aes_nohw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
const uint32_t *rk;
uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
int r;
assert(in && out && key);
rk = key->rd_key;
// map byte array block to cipher state
// and add initial round key:
s0 = GETU32(in) ^ rk[0];
s1 = GETU32(in + 4) ^ rk[1];
s2 = GETU32(in + 8) ^ rk[2];
s3 = GETU32(in + 12) ^ rk[3];
// Nr - 1 full rounds:
r = key->rounds >> 1;
for (;;) {
t0 = Td0[(s0 >> 24)] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^
Td3[(s1) & 0xff] ^ rk[4];
t1 = Td0[(s1 >> 24)] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^
Td3[(s2) & 0xff] ^ rk[5];
t2 = Td0[(s2 >> 24)] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^
Td3[(s3) & 0xff] ^ rk[6];
t3 = Td0[(s3 >> 24)] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^
Td3[(s0) & 0xff] ^ rk[7];
rk += 8;
if (--r == 0) {
break;
}
s0 = Td0[(t0 >> 24)] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^
Td3[(t1) & 0xff] ^ rk[0];
s1 = Td0[(t1 >> 24)] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^
Td3[(t2) & 0xff] ^ rk[1];
s2 = Td0[(t2 >> 24)] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^
Td3[(t3) & 0xff] ^ rk[2];
s3 = Td0[(t3 >> 24)] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^
Td3[(t0) & 0xff] ^ rk[3];
}
// apply last round and
// map cipher state to byte array block:
s0 = ((uint32_t)Td4[(t0 >> 24)] << 24) ^
((uint32_t)Td4[(t3 >> 16) & 0xff] << 16) ^
((uint32_t)Td4[(t2 >> 8) & 0xff] << 8) ^
((uint32_t)Td4[(t1) & 0xff]) ^ rk[0];
PUTU32(out, s0);
s1 = ((uint32_t)Td4[(t1 >> 24)] << 24) ^
((uint32_t)Td4[(t0 >> 16) & 0xff] << 16) ^
((uint32_t)Td4[(t3 >> 8) & 0xff] << 8) ^
((uint32_t)Td4[(t2) & 0xff]) ^ rk[1];
PUTU32(out + 4, s1);
s2 = ((uint32_t)Td4[(t2 >> 24)] << 24) ^
((uint32_t)Td4[(t1 >> 16) & 0xff] << 16) ^
((uint32_t)Td4[(t0 >> 8) & 0xff] << 8) ^
((uint32_t)Td4[(t3) & 0xff]) ^ rk[2];
PUTU32(out + 8, s2);
s3 = ((uint32_t)Td4[(t3 >> 24)] << 24) ^
((uint32_t)Td4[(t2 >> 16) & 0xff] << 16) ^
((uint32_t)Td4[(t1 >> 8) & 0xff] << 8) ^
((uint32_t)Td4[(t0) & 0xff]) ^ rk[3];
PUTU32(out + 12, s3);
}
#endif // NO_ASM || (!X86 && !X86_64 && !ARM)
// Be aware that different sets of AES functions use incompatible key
// representations, varying in format of the key schedule, the |AES_KEY.rounds|
// value, or both. Therefore they cannot mix. Also, on AArch64, the plain-C
File diff suppressed because it is too large Load Diff
+212 -33
View File
@@ -16,6 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <memory>
#include <vector>
@@ -176,7 +177,7 @@ TEST(AESTest, WycheproofKeyWrap) {
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
if (result != WycheproofResult::kInvalid) {
if (result.IsValid()) {
ASSERT_GE(ct.size(), 8u);
AES_KEY aes;
@@ -218,7 +219,10 @@ TEST(AESTest, WycheproofKeyWrapWithPadding) {
// should pass. However, both RFC 5649 and SP 800-38F section 5.3.1 say that
// the minimum length is one. Therefore we consider test cases with an empty
// message to be invalid.
if (result != WycheproofResult::kInvalid && !msg.empty()) {
//
// Wycheproof marks various weak parameters as acceptable. We do not enforce
// policy in the library, so we map those flags to valid.
if (result.IsValid({"SmallKey", "WeakWrapping"}) && !msg.empty()) {
AES_KEY aes;
ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes));
std::vector<uint8_t> out(ct.size() - 8);
@@ -284,26 +288,6 @@ TEST(AESTest, ABI) {
block_counts = {0, 1, 8};
}
CHECK_ABI(aes_nohw_set_encrypt_key, kKey, bits, &key);
CHECK_ABI(aes_nohw_encrypt, block, block, &key);
#if defined(AES_NOHW_CBC)
for (size_t blocks : block_counts) {
SCOPED_TRACE(blocks);
CHECK_ABI(aes_nohw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
block, AES_ENCRYPT);
}
#endif
CHECK_ABI(aes_nohw_set_decrypt_key, kKey, bits, &key);
CHECK_ABI(aes_nohw_decrypt, block, block, &key);
#if defined(AES_NOHW_CBC)
for (size_t blocks : block_counts) {
SCOPED_TRACE(blocks);
CHECK_ABI(aes_nohw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
block, AES_DECRYPT);
}
#endif
if (bsaes_capable()) {
vpaes_set_encrypt_key(kKey, bits, &key);
CHECK_ABI(vpaes_encrypt_key_to_bsaes, &key, &key);
@@ -383,6 +367,201 @@ static Bytes AESKeyToBytes(const AES_KEY *key) {
return Bytes(reinterpret_cast<const uint8_t *>(key), sizeof(*key));
}
static uint8_t aes_ref_sub_byte(uint8_t b) {
static const uint8_t kSBox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
0xb0, 0x54, 0xbb, 0x16,
};
return kSBox[b];
}
static uint32_t aes_ref_sub_word(uint32_t in) {
uint32_t a0 = aes_ref_sub_byte(in);
uint32_t a1 = aes_ref_sub_byte(in >> 8);
uint32_t a2 = aes_ref_sub_byte(in >> 16);
uint32_t a3 = aes_ref_sub_byte(in >> 24);
return a0 | (a1 << 8) | (a2 << 16) | (a3 << 24);
}
static uint32_t aes_ref_rot_word(uint32_t in, uint32_t n) {
return (in >> n) | (in << (32 - n));
}
static int aes_ref_set_encrypt_key(const uint8_t *key, int key_bits,
AES_KEY *out) {
static const uint32_t kRCon[10] = {0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x1b, 0x36};
switch (key_bits) {
case 128:
out->rounds = 10;
break;
case 192:
out->rounds = 12;
break;
case 256:
out->rounds = 14;
break;
default:
return 1;
}
size_t words = key_bits / 32;
size_t num_subkey_words = (out->rounds + 1) * 4;
OPENSSL_memcpy(out->rd_key, key, words * sizeof(uint32_t));
for (size_t i = words; i < num_subkey_words; i++) {
uint32_t tmp = out->rd_key[i - 1];
if (i % words == 0) {
tmp = aes_ref_sub_word(aes_ref_rot_word(tmp, 8)) ^ kRCon[(i / words) - 1];
} else if (key_bits == 256 && i % 4 == 0) {
tmp = aes_ref_sub_word(tmp);
}
out->rd_key[i] = tmp ^ out->rd_key[i - words];
}
// The ARM bsaes implementation expects all the keys to be byteswapped.
for (size_t i = 0; i < num_subkey_words; i++) {
out->rd_key[i] = CRYPTO_bswap4(out->rd_key[i]);
}
return 0;
}
static void aes_ref_inv_mix_columns(uint32_t block[4]) {
// This tables was generated with the following Python script:
// clang-format off
/*
def mul_unreduced(a, b):
c = 0
for i in range(8):
if b & (1 << i):
c ^= a << i
return c
def mul(a, b):
c = mul_unreduced(a, b)
# c's highest term is at most x^14.
c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
# c's highest term is at most x^10.
c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
# c's highest term is at most x^7.
assert (c >> 8) == 0
return c
def inv_mix_column(a):
ret = 0
for b in [0x0e, 0x09, 0x0d, 0x0b]:
ret <<= 8
ret |= mul(a, b)
return ret
body = ", ".join("0x%08x" % inv_mix_column(a) for a in range(256))
print("static const uint32_t kTable[256] = {%s};\n" % body)
*/
// clang-format on
// kInvMixColumn[i] is the result of InvMixColumns applied to a column
// containing [i, 0, 0, 0]. (The contributions of the other positions are
// computed by rotating bytes.)
static const uint32_t kInvMixColumn[256] = {
0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3};
// Note |block| is byte-swapped so block[i] >> 24 is the first element of
// block[i]. (See |aes_ref_set_encrypt_key|).
for (size_t i = 0; i < 4; i++) {
uint32_t in = block[i];
block[i] = kInvMixColumn[in >> 24];
block[i] ^= aes_ref_rot_word(kInvMixColumn[(in >> 16) & 0xff], 8);
block[i] ^= aes_ref_rot_word(kInvMixColumn[(in >> 8) & 0xff], 16);
block[i] ^= aes_ref_rot_word(kInvMixColumn[in & 0xff], 24);
}
}
static int aes_ref_set_decrypt_key(const uint8_t *key, int bits, AES_KEY *out) {
if (aes_ref_set_encrypt_key(key, bits, out) != 0) {
return 1;
}
// bsaes expects the decryption round keys in reverse order. Note there are
// |out->rounds + 1| round keys.
for (size_t i = 0; i < out->rounds / 2; i++) {
std::swap(out->rd_key[4 * i], out->rd_key[4 * (out->rounds - i)]);
std::swap(out->rd_key[4 * i + 1], out->rd_key[4 * (out->rounds - i) + 1]);
std::swap(out->rd_key[4 * i + 2], out->rd_key[4 * (out->rounds - i) + 2]);
std::swap(out->rd_key[4 * i + 3], out->rd_key[4 * (out->rounds - i) + 3]);
}
// bsaes expects round keys other than the first and last to have
// InvMixColumns applied.
for (size_t i = 1; i < out->rounds; i++) {
aes_ref_inv_mix_columns(out->rd_key + 4 * i);
}
return 0;
}
TEST(AESTest, VPAESToBSAESConvert) {
const int kNumIterations = 1000;
for (int i = 0; i < kNumIterations; i++) {
@@ -393,36 +572,36 @@ TEST(AESTest, VPAESToBSAESConvert) {
SCOPED_TRACE(bits);
for (bool enc : {false, true}) {
SCOPED_TRACE(enc);
AES_KEY nohw, vpaes, bsaes;
OPENSSL_memset(&nohw, 0xaa, sizeof(nohw));
AES_KEY ref, vpaes, bsaes;
OPENSSL_memset(&ref, 0xaa, sizeof(ref));
OPENSSL_memset(&vpaes, 0xaa, sizeof(vpaes));
OPENSSL_memset(&bsaes, 0xaa, sizeof(bsaes));
if (enc) {
aes_nohw_set_encrypt_key(key, bits, &nohw);
vpaes_set_encrypt_key(key, bits, &vpaes);
ASSERT_EQ(0, aes_ref_set_encrypt_key(key, bits, &ref));
ASSERT_EQ(0, vpaes_set_encrypt_key(key, bits, &vpaes));
vpaes_encrypt_key_to_bsaes(&bsaes, &vpaes);
} else {
aes_nohw_set_decrypt_key(key, bits, &nohw);
vpaes_set_decrypt_key(key, bits, &vpaes);
ASSERT_EQ(0, aes_ref_set_decrypt_key(key, bits, &ref));
ASSERT_EQ(0, vpaes_set_decrypt_key(key, bits, &vpaes));
vpaes_decrypt_key_to_bsaes(&bsaes, &vpaes);
}
// Although not fatal, stop running if this fails, otherwise we'll spam
// the user's console.
ASSERT_EQ(AESKeyToBytes(&nohw), AESKeyToBytes(&bsaes));
ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
// Repeat the test in-place.
OPENSSL_memcpy(&bsaes, &vpaes, sizeof(AES_KEY));
if (enc) {
vpaes_encrypt_key_to_bsaes(&bsaes, &vpaes);
vpaes_encrypt_key_to_bsaes(&bsaes, &bsaes);
} else {
vpaes_decrypt_key_to_bsaes(&bsaes, &vpaes);
vpaes_decrypt_key_to_bsaes(&bsaes, &bsaes);
}
ASSERT_EQ(AESKeyToBytes(&nohw), AESKeyToBytes(&bsaes));
ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
}
}
}
}
#endif // !NO_ASM && X86_64 && !SHARED_LIBRARY
#endif // BSAES && !SHARED_LIBRARY
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -7
View File
@@ -218,19 +218,17 @@ OPENSSL_INLINE void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out,
#endif // !VPAES
void aes_nohw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
void aes_nohw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
int aes_nohw_set_encrypt_key(const uint8_t *key, unsigned bits,
AES_KEY *aeskey);
int aes_nohw_set_decrypt_key(const uint8_t *key, unsigned bits,
AES_KEY *aeskey);
#if !defined(OPENSSL_NO_ASM) && \
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
#define AES_NOHW_CBC
void aes_nohw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
void aes_nohw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
void aes_nohw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
size_t blocks, const AES_KEY *key,
const uint8_t ivec[16]);
void aes_nohw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t *ivec, const int enc);
#endif
#if defined(__cplusplus)
+17 -3
View File
@@ -57,7 +57,23 @@
void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[AES_BLOCK_SIZE],
uint8_t ecount_buf[AES_BLOCK_SIZE], unsigned int *num) {
CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num, AES_encrypt);
if (hwaes_capable()) {
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
aes_hw_ctr32_encrypt_blocks);
} else if (vpaes_capable()) {
#if defined(VPAES_CTR32)
// TODO(davidben): On ARM, where |BSAES| is additionally defined, this could
// use |vpaes_ctr32_encrypt_blocks_with_bsaes|.
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
vpaes_ctr32_encrypt_blocks);
#else
CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num,
vpaes_encrypt);
#endif
} else {
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
aes_nohw_ctr32_encrypt_blocks);
}
}
void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key,
@@ -79,12 +95,10 @@ void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
return;
}
#if defined(AES_NOHW_CBC)
if (!vpaes_capable()) {
aes_nohw_cbc_encrypt(in, out, len, key, ivec, enc);
return;
}
#endif
if (enc) {
CRYPTO_cbc128_encrypt(in, out, len, key, ivec, AES_encrypt);
} else {
+42 -1
View File
@@ -31,6 +31,7 @@
#include "../internal.h"
#include "aes/aes.c"
#include "aes/aes_nohw.c"
#include "aes/key_wrap.c"
#include "aes/mode_wrappers.c"
#include "bn/add.c"
@@ -69,7 +70,7 @@
#include "ec/felem.c"
#include "ec/oct.c"
#include "ec/p224-64.c"
#include "../../third_party/fiat/p256.c"
#include "ec/p256.c"
#include "ec/p256-x86_64.c"
#include "ec/scalar.c"
#include "ec/simple.c"
@@ -83,9 +84,11 @@
#include "modes/cfb.c"
#include "modes/ctr.c"
#include "modes/gcm.c"
#include "modes/gcm_nohw.c"
#include "modes/ofb.c"
#include "modes/polyval.c"
#include "rand/ctrdrbg.c"
#include "rand/fork_detect.c"
#include "rand/rand.c"
#include "rand/urandom.c"
#include "rsa/blinding.c"
@@ -115,6 +118,26 @@ extern const uint8_t BORINGSSL_bcm_rodata_start[];
extern const uint8_t BORINGSSL_bcm_rodata_end[];
#endif
// assert_within is used to sanity check that certain symbols are within the
// bounds of the integrity check. It checks that start <= symbol < end and
// aborts otherwise.
static void assert_within(const void *start, const void *symbol,
const void *end) {
const uintptr_t start_val = (uintptr_t) start;
const uintptr_t symbol_val = (uintptr_t) symbol;
const uintptr_t end_val = (uintptr_t) end;
if (start_val <= symbol_val && symbol_val < end_val) {
return;
}
fprintf(
stderr,
"FIPS module doesn't span expected symbol. Expected %p <= %p < %p\n",
start, symbol, end);
BORINGSSL_FIPS_abort();
}
#if defined(OPENSSL_ANDROID) && defined(OPENSSL_AARCH64)
static void BORINGSSL_maybe_set_module_text_permissions(int permission) {
// Android may be compiled in execute-only-memory mode, in which case the
@@ -147,11 +170,29 @@ BORINGSSL_bcm_power_on_self_test(void) {
// .text section, which triggers the global-buffer overflow detection.
const uint8_t *const start = BORINGSSL_bcm_text_start;
const uint8_t *const end = BORINGSSL_bcm_text_end;
assert_within(start, AES_encrypt, end);
assert_within(start, RSA_sign, end);
assert_within(start, RAND_bytes, end);
assert_within(start, EC_GROUP_cmp, end);
assert_within(start, SHA256_Update, end);
assert_within(start, ECDSA_do_verify, end);
assert_within(start, EVP_AEAD_CTX_seal, end);
#if defined(BORINGSSL_SHARED_LIBRARY)
const uint8_t *const rodata_start = BORINGSSL_bcm_rodata_start;
const uint8_t *const rodata_end = BORINGSSL_bcm_rodata_end;
#else
// In the static build, read-only data is placed within the .text segment.
const uint8_t *const rodata_start = BORINGSSL_bcm_text_start;
const uint8_t *const rodata_end = BORINGSSL_bcm_text_end;
#endif
assert_within(rodata_start, kPrimes, rodata_end);
assert_within(rodata_start, des_skb, rodata_end);
assert_within(rodata_start, kP256Params, rodata_end);
assert_within(rodata_start, kPKCS1SigPrefixes, rodata_end);
#if defined(OPENSSL_ANDROID)
uint8_t result[SHA256_DIGEST_LENGTH];
const EVP_MD *const kHashFunction = EVP_sha256();
-209
View File
@@ -27,7 +27,6 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
&bn_div_words("bn_div_words");
&bn_add_words("bn_add_words");
&bn_sub_words("bn_sub_words");
&bn_sub_part_words("bn_sub_part_words");
&asm_finish();
@@ -575,211 +574,3 @@ sub bn_sub_words
&function_end($name);
}
sub bn_sub_part_words
{
local($name)=@_;
&function_begin($name,"");
&comment("");
$a="esi";
$b="edi";
$c="eax";
$r="ebx";
$tmp1="ecx";
$tmp2="edx";
$num="ebp";
&mov($r,&wparam(0)); # get r
&mov($a,&wparam(1)); # get a
&mov($b,&wparam(2)); # get b
&mov($num,&wparam(3)); # get num
&xor($c,$c); # clear carry
&and($num,0xfffffff8); # num / 8
&jz(&label("aw_finish"));
&set_label("aw_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
}
&comment("");
&add($a,32);
&add($b,32);
&add($r,32);
&sub($num,8);
&jnz(&label("aw_loop"));
&set_label("aw_finish",0);
&mov($num,&wparam(3)); # get num
&and($num,7);
&jz(&label("aw_end"));
for ($i=0; $i<7; $i++)
{
&comment("Tail Round $i");
&mov($tmp1,&DWP(0,$a,"",0)); # *a
&mov($tmp2,&DWP(0,$b,"",0));# *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP(0,$r,"",0),$tmp1); # *r
&add($a, 4);
&add($b, 4);
&add($r, 4);
&dec($num) if ($i != 6);
&jz(&label("aw_end")) if ($i != 6);
}
&set_label("aw_end",0);
&cmp(&wparam(4),0);
&je(&label("pw_end"));
&mov($num,&wparam(4)); # get dl
&cmp($num,0);
&je(&label("pw_end"));
&jge(&label("pw_pos"));
&comment("pw_neg");
&mov($tmp2,0);
&sub($tmp2,$num);
&mov($num,$tmp2);
&and($num,0xfffffff8); # num / 8
&jz(&label("pw_neg_finish"));
&set_label("pw_neg_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("dl<0 Round $i");
&mov($tmp1,0);
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
}
&comment("");
&add($b,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_neg_loop"));
&set_label("pw_neg_finish",0);
&mov($tmp2,&wparam(4)); # get dl
&mov($num,0);
&sub($num,$tmp2);
&and($num,7);
&jz(&label("pw_end"));
for ($i=0; $i<7; $i++)
{
&comment("dl<0 Tail Round $i");
&mov($tmp1,0);
&mov($tmp2,&DWP($i*4,$b,"",0));# *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&dec($num) if ($i != 6);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jz(&label("pw_end")) if ($i != 6);
}
&jmp(&label("pw_end"));
&set_label("pw_pos",0);
&and($num,0xfffffff8); # num / 8
&jz(&label("pw_pos_finish"));
&set_label("pw_pos_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("dl>0 Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&sub($tmp1,$c);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jnc(&label("pw_nc".$i));
}
&comment("");
&add($a,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_pos_loop"));
&set_label("pw_pos_finish",0);
&mov($num,&wparam(4)); # get dl
&and($num,7);
&jz(&label("pw_end"));
for ($i=0; $i<7; $i++)
{
&comment("dl>0 Tail Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&sub($tmp1,$c);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jnc(&label("pw_tail_nc".$i));
&dec($num) if ($i != 6);
&jz(&label("pw_end")) if ($i != 6);
}
&mov($c,1);
&jmp(&label("pw_end"));
&set_label("pw_nc_loop",0);
for ($i=0; $i<8; $i++)
{
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&set_label("pw_nc".$i,0);
}
&comment("");
&add($a,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_nc_loop"));
&mov($num,&wparam(4)); # get dl
&and($num,7);
&jz(&label("pw_nc_end"));
for ($i=0; $i<7; $i++)
{
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&set_label("pw_tail_nc".$i,0);
&dec($num) if ($i != 6);
&jz(&label("pw_nc_end")) if ($i != 6);
}
&set_label("pw_nc_end",0);
&mov($c,0);
&set_label("pw_end",0);
# &mov("eax",$c); # $c is "eax"
&function_end($name);
}
+108 -22
View File
@@ -73,6 +73,7 @@
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <utility>
#include <gtest/gtest.h>
@@ -91,6 +92,7 @@
#include "../../test/abi_test.h"
#include "../../test/file_test.h"
#include "../../test/test_util.h"
#include "../../test/wycheproof_util.h"
static int HexToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
@@ -657,11 +659,26 @@ static void TestModMul(BIGNUMFileTest *t, BN_CTX *ctx) {
bn_mod_mul_montgomery_small(r_words.get(), a_words.get(), b_words.get(),
m_width, mont.get());
// Use the second half of |tmp| so ASan will catch out-of-bounds writes.
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width,
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
mont.get());
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A * B (mod M) (Montgomery, words)", mod_mul.get(),
ret.get());
// |bn_from_montgomery_small| must additionally work on double-width
// inputs. Test this by running |bn_from_montgomery_small| on the result
// of a product. Note |a_words| * |b_words| has an extra factor of R^2, so
// we must reduce twice.
std::unique_ptr<BN_ULONG[]> prod_words(new BN_ULONG[m_width * 2]);
bn_mul_small(prod_words.get(), m_width * 2, a_words.get(), m_width,
b_words.get(), m_width);
bn_from_montgomery_small(r_words.get(), m_width, prod_words.get(),
m_width * 2, mont.get());
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
mont.get());
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A * B (mod M) (Montgomery, words)",
mod_mul.get(), ret.get());
}
#endif
}
@@ -719,7 +736,8 @@ static void TestModSquare(BIGNUMFileTest *t, BN_CTX *ctx) {
bn_to_montgomery_small(a_words.get(), a_words.get(), m_width, mont.get());
bn_mod_mul_montgomery_small(r_words.get(), a_words.get(), a_words.get(),
m_width, mont.get());
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width, mont.get());
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
mont.get());
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A * A (mod M) (Montgomery, words)",
mod_square.get(), ret.get());
@@ -730,7 +748,7 @@ static void TestModSquare(BIGNUMFileTest *t, BN_CTX *ctx) {
bn_mod_mul_montgomery_small(r_words.get(), a_words.get(),
a_copy_words.get(), m_width, mont.get());
// Use the second half of |tmp| so ASan will catch out-of-bounds writes.
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width,
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
mont.get());
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A * A_copy (mod M) (Montgomery, words)",
@@ -781,7 +799,7 @@ static void TestModExp(BIGNUMFileTest *t, BN_CTX *ctx) {
bn_to_montgomery_small(a_words.get(), a_words.get(), m_width, mont.get());
bn_mod_exp_mont_small(r_words.get(), a_words.get(), m_width, e->d,
e->width, mont.get());
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width,
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
mont.get());
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A ^ E (mod M) (Montgomery, words)", mod_exp.get(),
@@ -1986,16 +2004,17 @@ TEST_F(BNTest, PrimeChecking) {
ASSERT_TRUE(BN_set_word(p.get(), i));
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_1, p.get(), BN_prime_checks, ctx(),
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
false /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(is_prime ? 1 : 0, is_probably_prime_1);
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_2, p.get(), BN_prime_checks, ctx(),
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
true /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(is_prime ? 1 : 0, is_probably_prime_2);
if (i > 3 && i % 2 == 1) {
ASSERT_TRUE(BN_enhanced_miller_rabin_primality_test(
&result_3, p.get(), BN_prime_checks, ctx(), nullptr /* callback */));
&result_3, p.get(), BN_prime_checks_for_generation, ctx(),
nullptr /* callback */));
EXPECT_EQ(is_prime, result_3 == bn_probably_prime);
}
}
@@ -2003,13 +2022,13 @@ TEST_F(BNTest, PrimeChecking) {
// Negative numbers are not prime.
ASSERT_TRUE(BN_set_word(p.get(), 7));
BN_set_negative(p.get(), 1);
ASSERT_TRUE(BN_primality_test(&is_probably_prime_1, p.get(), BN_prime_checks,
ctx(), false /* do_trial_division */,
nullptr /* callback */));
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
false /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(0, is_probably_prime_1);
ASSERT_TRUE(BN_primality_test(&is_probably_prime_2, p.get(), BN_prime_checks,
ctx(), true /* do_trial_division */,
nullptr /* callback */));
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
true /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(0, is_probably_prime_2);
static const char *kComposites[] = {
@@ -2068,17 +2087,18 @@ TEST_F(BNTest, PrimeChecking) {
EXPECT_NE(0, DecimalToBIGNUM(&p, str));
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_1, p.get(), BN_prime_checks, ctx(),
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
false /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(0, is_probably_prime_1);
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_2, p.get(), BN_prime_checks, ctx(),
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
true /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(0, is_probably_prime_2);
ASSERT_TRUE(BN_enhanced_miller_rabin_primality_test(
&result_3, p.get(), BN_prime_checks, ctx(), nullptr /* callback */));
&result_3, p.get(), BN_prime_checks_for_generation, ctx(),
nullptr /* callback */));
EXPECT_EQ(bn_composite, result_3);
}
@@ -2257,28 +2277,94 @@ TEST_F(BNTest, PrimeChecking) {
EXPECT_NE(0, HexToBIGNUM(&p, str));
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_1, p.get(), BN_prime_checks, ctx(),
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
false /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(1, is_probably_prime_1);
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_2, p.get(), BN_prime_checks, ctx(),
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
true /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(1, is_probably_prime_2);
ASSERT_TRUE(BN_enhanced_miller_rabin_primality_test(
&result_3, p.get(), BN_prime_checks, ctx(), nullptr /* callback */));
&result_3, p.get(), BN_prime_checks_for_generation, ctx(),
nullptr /* callback */));
EXPECT_EQ(bn_probably_prime, result_3);
}
// BN_primality_test works with null |BN_CTX|.
ASSERT_TRUE(BN_set_word(p.get(), 5));
ASSERT_TRUE(BN_primality_test(
&is_probably_prime_1, p.get(), BN_prime_checks, nullptr /* ctx */,
false /* do_trial_division */, nullptr /* callback */));
ASSERT_TRUE(
BN_primality_test(&is_probably_prime_1, p.get(),
BN_prime_checks_for_generation, nullptr /* ctx */,
false /* do_trial_division */, nullptr /* callback */));
EXPECT_EQ(1, is_probably_prime_1);
}
TEST_F(BNTest, MillerRabinIteration) {
FileTestGTest(
"crypto/fipsmodule/bn/miller_rabin_tests.txt", [&](FileTest *t) {
BIGNUMFileTest bn_test(t, /*large_mask=*/0);
bssl::UniquePtr<BIGNUM> w = bn_test.GetBIGNUM("W");
ASSERT_TRUE(w);
bssl::UniquePtr<BIGNUM> b = bn_test.GetBIGNUM("B");
ASSERT_TRUE(b);
bssl::UniquePtr<BN_MONT_CTX> mont(
BN_MONT_CTX_new_consttime(w.get(), ctx()));
ASSERT_TRUE(mont);
bssl::BN_CTXScope scope(ctx());
BN_MILLER_RABIN miller_rabin;
ASSERT_TRUE(bn_miller_rabin_init(&miller_rabin, mont.get(), ctx()));
int possibly_prime;
ASSERT_TRUE(bn_miller_rabin_iteration(&miller_rabin, &possibly_prime,
b.get(), mont.get(), ctx()));
std::string result;
ASSERT_TRUE(t->GetAttribute(&result, "Result"));
EXPECT_EQ(result, possibly_prime ? "PossiblyPrime" : "Composite");
});
}
// These tests are very slow, so we disable them by default to avoid timing out
// downstream consumers. They are enabled when running tests standalone via
// all_tests.go.
TEST_F(BNTest, DISABLED_WycheproofPrimality) {
FileTestGTest(
"third_party/wycheproof_testvectors/primality_test.txt",
[&](FileTest *t) {
WycheproofResult result;
ASSERT_TRUE(GetWycheproofResult(t, &result));
bssl::UniquePtr<BIGNUM> value = GetWycheproofBIGNUM(t, "value", false);
ASSERT_TRUE(value);
for (int checks :
{BN_prime_checks_for_validation, BN_prime_checks_for_generation}) {
SCOPED_TRACE(checks);
if (checks == BN_prime_checks_for_generation &&
std::find(result.flags.begin(), result.flags.end(),
"WorstCaseMillerRabin") != result.flags.end()) {
// Skip the worst case Miller-Rabin cases.
// |BN_prime_checks_for_generation| relies on such values being rare
// when generating primes.
continue;
}
int is_probably_prime;
ASSERT_TRUE(BN_primality_test(&is_probably_prime, value.get(), checks,
ctx(),
/*do_trial_division=*/false, nullptr));
EXPECT_EQ(result.IsValid() ? 1 : 0, is_probably_prime);
ASSERT_TRUE(BN_primality_test(&is_probably_prime, value.get(), checks,
ctx(),
/*do_trial_division=*/true, nullptr));
EXPECT_EQ(result.IsValid() ? 1 : 0, is_probably_prime);
}
});
}
TEST_F(BNTest, NumBitsWord) {
constexpr BN_ULONG kOne = 1;
+102
View File
@@ -10673,6 +10673,108 @@ A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
E = 2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020FF2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2020202020ff
# Test vectors for CVE-2019-1551. (We do not carry the assembly file with the
# bug, but we use the test vectors anyway.)
# Original test vectors by OSS-Fuzz.
ModExp = 9d675d188a07e9bd1b32638cc8cfd5002ef89bd1a9648f806567b87939140a67977dc8da17323b8e4c6bc53875cda8b656df8f54cc32e44fd9c21d122ea3c0d6
A = dea9b3e0b44ae67b2ac9b7c2b18eeb4dab206b014981a46ac409f195eeb6896f132cf8497c87d1188008ee511054ebb426203355b7d515dce9501cb759ac1373
E = b01ae745b101e9e45ec05dcff72e7f8fc04c79ffe324301fda0b4f7be81d85c4e875c73fc6c5cb40000000000000000000000000000000000
M = ffffffff01ffffffffffffffffffffffffffe2000000000000000000000000000010fab8d960706cd4c21818115650cad61d4f10da325dffffffff00ffff00ff
ModExp = 651f811b62ee8770e3598c340864dd6b0be9bb6376b6f933ab216fd55538e6ad1000cb2b3c64f54d554e004b6eec8138e6ecff00452d443a42041b72e6cd9ead
A = 3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e
E = 3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e09003e3e3e3e3e3e3e3e3e3e3e3e3e3e010900230a01230a2100ffffff0000adf300a58700000000ffffff00
M = ffffff0b00000000000000000000000000ffffffff0000ffffffff00000a0000000a00000000000000000000ffffffff000000000000ffffffffffff000000ff
# Test vectors for rsaz_512_sqr bug, with rcx/rbx=1
# between first and second iteration
ModExp = 1
A = 624e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d973b6
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between second and third iteration
ModExp = 1
A = 11024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d97360800000000000000f
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between third and fourth iteration
ModExp = 1
A = 4171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d9736080000000000000000000000000000039
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between fourth and fifth iteration
ModExp = 1
A = 6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d97360800000000000000000000000000000000000000000000006
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between fifth and sixth iteration
ModExp = 1
A = 44e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d97360800000000000000000000000000000000000000000000000000000000000003c
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between sixth and seventh iteration
ModExp = 1
A = 1024e6a171024e6a14ce297f2873536f959d8c3390d973608000000000000000000000000000000000000000000000000000000000000000000000000000000e
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between seventh and eighth iteration
ModExp = 1
A = 626eee5e3c8653be47ed15e84b97cc7f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000187
E = c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f8
M = c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f9
# Test vectors for rsaz_512_srq bug, with rcx/rbx=2
# between first and second iteration
ModExp = 1
A = 3c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf7c
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between second and third iteration
ModExp = 1
A = 485c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf47800000000000003f
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between third and forth iteration
ModExp = 1
A = 59a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf478000000000000000000000000000004e
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between forth and fifth iteration
ModExp = 1
A = 2939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf47800000000000000000000000000000000000000000000024
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between fifth and sixth iteration
ModExp = 1
A = 640939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf478000000000000000000000000000000000000000000000000000000000000057
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between sixth and seventh iteration
ModExp = 1
A = 25c40939a85c4093995e8efdb195e8efd8caf477ed8caf4780000000000000000000000000000000000000000000000000000000000000000000000000000021
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
# between seventh and eighth iteration
ModExp = 1
A = 7b4919849931b28a14fcace213f2b3884fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84b6e67b66ce4d9c
E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000004c
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000004d
# Exp tests.
#
+17 -4
View File
@@ -228,8 +228,8 @@ func main() {
checkResult(test, "A ^ E", "Exp", r)
}
case "ModSqrt":
bigOne := new(big.Int).SetInt64(1)
bigTwo := new(big.Int).SetInt64(2)
bigOne := big.NewInt(1)
bigTwo := big.NewInt(2)
if checkKeys(test, "A", "P", "ModSqrt") {
test.Values["A"].Mod(test.Values["A"], test.Values["P"])
@@ -249,8 +249,21 @@ func main() {
}
case "ModInv":
if checkKeys(test, "A", "M", "ModInv") {
r := new(big.Int).ModInverse(test.Values["A"], test.Values["M"])
checkResult(test, "A ^ -1 (mod M)", "ModInv", r)
a := test.Values["A"]
m := test.Values["M"]
var r *big.Int
if a.Sign() == 0 && m.IsInt64() && m.Int64() == 1 {
// OpenSSL says 0^(-1) mod (1) is 0, while Go says the
// inverse does not exist.
r = big.NewInt(0)
} else {
r = new(big.Int).ModInverse(a, m)
}
if r == nil {
fmt.Fprintf(os.Stderr, "Line %d: A has no inverse mod M.\n", test.LineNumber)
} else {
checkResult(test, "A ^ -1 (mod M)", "ModInv", r)
}
}
case "ModSquare":
if checkKeys(test, "A", "M", "ModSquare") {
+3 -3
View File
@@ -732,7 +732,7 @@ void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
num_p--;
}
if (num_p == 0) {
bn_from_montgomery_small(r, mont->RR.d, num, mont);
bn_from_montgomery_small(r, num, mont->RR.d, num, mont);
return;
}
unsigned bits = BN_num_bits_word(p[num_p - 1]) + (num_p - 1) * BN_BITS2;
@@ -809,8 +809,8 @@ void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
OPENSSL_cleanse(val, sizeof(val));
}
void bn_mod_inverse_prime_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
const BN_MONT_CTX *mont) {
void bn_mod_inverse0_prime_mont_small(BN_ULONG *r, const BN_ULONG *a,
size_t num, const BN_MONT_CTX *mont) {
if (num != (size_t)mont->N.width || num > BN_SMALL_MAX_WORDS) {
abort();
}
+59 -12
View File
@@ -404,9 +404,19 @@ uint64_t bn_mont_n0(const BIGNUM *n);
int bn_mod_exp_base_2_consttime(BIGNUM *r, unsigned p, const BIGNUM *n,
BN_CTX *ctx);
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
#if defined(_MSC_VER)
#if defined(OPENSSL_X86_64)
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
#elif defined(OPENSSL_AARCH64)
#define BN_UMULT_LOHI(low, high, a, b) \
do { \
const BN_ULONG _a = (a); \
const BN_ULONG _b = (b); \
(low) = _a * _b; \
(high) = __umulh(_a, _b); \
} while (0)
#endif
#endif // _MSC_VER
#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI)
#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
@@ -437,6 +447,40 @@ OPENSSL_EXPORT uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d);
// of the first several odd primes and zero otherwise.
int bn_odd_number_is_obviously_composite(const BIGNUM *bn);
// A BN_MILLER_RABIN stores state common to each Miller-Rabin iteration. It is
// initialized within an existing |BN_CTX| scope and may not be used after
// that scope is released with |BN_CTX_end|. Field names match those in FIPS
// 186-4, section C.3.1.
typedef struct {
// w1 is w-1.
BIGNUM *w1;
// m is (w-1)/2^a.
BIGNUM *m;
// one_mont is 1 (mod w) in Montgomery form.
BIGNUM *one_mont;
// w1_mont is w-1 (mod w) in Montgomery form.
BIGNUM *w1_mont;
// w_bits is BN_num_bits(w).
int w_bits;
// a is the largest integer such that 2^a divides w-1.
int a;
} BN_MILLER_RABIN;
// bn_miller_rabin_init initializes |miller_rabin| for testing if |mont->N| is
// prime. It returns one on success and zero on error.
OPENSSL_EXPORT int bn_miller_rabin_init(BN_MILLER_RABIN *miller_rabin,
const BN_MONT_CTX *mont, BN_CTX *ctx);
// bn_miller_rabin_iteration performs one Miller-Rabin iteration, checking if
// |b| is a composite witness for |mont->N|. |miller_rabin| must have been
// initialized with |bn_miller_rabin_setup|. On success, it returns one and sets
// |*out_is_possibly_prime| to one if |mont->N| may still be prime or zero if
// |b| shows it is composite. On allocation or internal failure, it returns
// zero.
OPENSSL_EXPORT int bn_miller_rabin_iteration(
const BN_MILLER_RABIN *miller_rabin, int *out_is_possibly_prime,
const BIGNUM *b, const BN_MONT_CTX *mont, BN_CTX *ctx);
// bn_rshift1_words sets |r| to |a| >> 1, where both arrays are |num| bits wide.
void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num);
@@ -613,10 +657,13 @@ void bn_to_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
const BN_MONT_CTX *mont);
// bn_from_montgomery_small sets |r| to |a| translated out of the Montgomery
// domain. |r| and |a| are |num| words long, which must be |mont->N.width|. |a|
// must be fully-reduced and may alias |r|.
void bn_from_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
const BN_MONT_CTX *mont);
// domain. |r| and |a| are |num_r| and |num_a| words long, respectively. |num_r|
// must be |mont->N.width|. |a| must be at most |mont->N|^2 and may alias |r|.
//
// Unlike most of these functions, only |num_r| is bounded by
// |BN_SMALL_MAX_WORDS|. |num_a| may exceed it, but must be at most 2 * |num_r|.
void bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont);
// bn_mod_mul_montgomery_small sets |r| to |a| * |b| mod |mont->N|. Both inputs
// and outputs are in the Montgomery domain. Each array is |num| words long,
@@ -641,13 +688,13 @@ void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
const BN_ULONG *p, size_t num_p,
const BN_MONT_CTX *mont);
// bn_mod_inverse_prime_mont_small sets |r| to |a|^-1 mod |mont->N|. |mont->N|
// must be a prime. |r| and |a| are |num| words long, which must be
// |mont->N.width| and at most |BN_SMALL_MAX_WORDS|. |a| must be fully-reduced
// and may alias |r|. This function runs in time independent of |a|, but
// |mont->N| is a public value.
void bn_mod_inverse_prime_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
const BN_MONT_CTX *mont);
// bn_mod_inverse0_prime_mont_small sets |r| to |a|^-1 mod |mont->N|. If |a| is
// zero, |r| is set to zero. |mont->N| must be a prime. |r| and |a| are |num|
// words long, which must be |mont->N.width| and at most |BN_SMALL_MAX_WORDS|.
// |a| must be fully-reduced and may alias |r|. This function runs in time
// independent of |a|, but |mont->N| is a public value.
void bn_mod_inverse0_prime_mont_small(BN_ULONG *r, const BN_ULONG *a,
size_t num, const BN_MONT_CTX *mont);
#if defined(__cplusplus)
+406
View File
@@ -0,0 +1,406 @@
# This file contains test vectors for whether B is a Miller-Rabin composite
# witness for W. W must be odd and B must satisfy 1 <= B <= W-1.
#
# The following Python function may be used to check values.
#
# def is_miller_rabin_witness(w, b):
# # Variable names taken from FIPS 186-4 C.3.1 but the algorithm skips a
# # couple of optimizations in the FIPS formulation.
# m = w - 1
# a = 0
# while m&1 == 0:
# a += 1
# m //= 2
# # b is a composite witness for w iff the following are true:
# # - b^m != 1 (mod w)
# # - b^(m*2^j) != -1 (mod w), for 0 <= j < a
# z = pow(b, m, w)
# if z == 1:
# # b^m = 1 (mod w)
# return False
# for j in range(a):
# if z == w-1:
# # b^(m*2^j) = -1 (mod w)
# return False
# z = (z * z) % w
# # At this point, z is b^(w-1) (mod w). If z is not 1, w has failed the
# # Fermat test and is composite. If z is 1, the value of z immediately
# # before it became 1 is a non-trivial root of unity and w is composite.
# return True
# Exhaustively test a small prime.
Result = PossiblyPrime
W = 7
B = 1
Result = PossiblyPrime
W = 7
B = 2
Result = PossiblyPrime
W = 7
B = 3
Result = PossiblyPrime
W = 7
B = 4
Result = PossiblyPrime
W = 7
B = 5
Result = PossiblyPrime
W = 7
B = 6
# Random large inputs which try to cover a few cases. The nontrivial square root
# case appears to be difficult to hit randomly.
# b^m = w-1
Result = PossiblyPrime
W = d6b4ffc7cf70b2a2fc5d6023015875504d40e3dcce7c2e6b762c3de7bb806a5074144e7054198dabf53d23108679ccc541d5a99efeb1d1abaf89e0dbcead2a8b
B = fabbafdbec6494ddb5ea4bf458536e87082369b0e53a200ed413f3e64b2fddc7c57c565710fbe73fae5b188fce97d8dcca74c2b5d90906c96d3c2c358a735cd
# b^m = w-1
Result = PossiblyPrime
W = 52cc61c42b341ad56dc11495e7cb2fe31e506b9e99522efbf44cd7c28468d3833c5e360f3c77b0aa43c0495c4e14665ab0d7cee9294c722f0de47d4401828401
B = 3bdc9639c0fc2e77ab48d46e0b4ac6529c11c900e8fe4d82d75767c0556feb23d3f42d4924d16876a743feb386b7b84c7fd16a6c252f662faf0024d19972e62f
# b^m = w-1
Result = PossiblyPrime
W = cff9897aa7dce0f2afad262b2de57d301305de717f3539c537c4ce062f8cb70df13fbc1eb4a3b9f0958a8810d1ca9042b4f23334b285a15fee3fc66498761d4b
B = 9ceb43132fddf9ee4104ea1cb3eb2253c1d7f803f05f0305de9e31a17dd75832f47b8bf189a9b7ca0905f2a7470d9c6349080f481ff1708696fa12d972e7d7ba
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 67d1825dad5344170e65247a87aef1634a1b32bdc22f2f04d9d2959767bb5a27610fba55cd607e0f9fdd9fbb0f7f98e40d5e1eb2f52318fb5be4dbfd30d38861
B = 260fb14724ff80984736859d8755ee98b25bcb56db9fde1db001a1e1273374034c5b75fd60b3710c7a08ce7d390776f010f384d4e32943cf0c477497d53e9e05
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = ad0bc85b58aaa204177aa9431a40929beb1cbea2dd6f66a25cc54600013213b225ba881805661df43f4208965ada7aacc8095d07d3cbef1a7bbfaae8b745f731
B = 3d9310f20e9c80269fa6830c7e1a6f02fc5c58646001a9ef6b8b3e496602ff22c3dcb2ddb6a221723fc1722ce237fb46f7a7bb2945e415c8839b15a972f076c9
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = b25c917f55f6c7b596921daba919f35039e5d805119c1587e99849dd7104460c86214f162a6f17aea847bc7f3859e59f2991d457059511972ef373d4bc75e309
B = a1f10b261dee84619b0423201d46af19eef9ec0612cf947c4d5c36c0c4b28207f75967e69452eabad0a5dcd28f27f7a8a7ed9c8b3e5026c6e0ba5634d94c2d44
# b^m = 1
Result = PossiblyPrime
W = d3eeb0eff05b6992e9fa61b02755e155f4aae28c6e45ddb874edd86acdd2d83d18a20e0e00d8b8bc94b92d14fc3f41ced6ababe8ac98c7730c075dbe0f699369
B = 6b7717269c6225203681a1cacec87cacd83003ec6e9e3f04effcc4f86634770c0860e1f2770b8f303719a44949664a1094205a99d95a0856758fed66d690105e
# b^m = 1
Result = PossiblyPrime
W = 64561b8d9aa50340c3a01ccb3e6e17f5023513661c012be288f3900a3ca76890e67290b9560fa1d480f9d2aacccca581b5690636665f243fa13aff5d0bff12d3
B = 1f5ff70d3d60671ebc5fbfca731898a04438053dbc3c841e6335f487e457d92d9efb5d506d5bef6872d58d12b9a41c950bfc38d12ed977c90eacdd6535b811a0
# b^m = 1
Result = PossiblyPrime
W = 69c63fbf44df21b0ed0ee929a740c12d1f3f064da0dcd9d509f31fa45fa27d1a759ab5a9f6f1040d7ee90a0b1e68f779273c41ea1c1198fd547ff6bd70c7e787
B = 5f7996a9bbfd8fd88e472220b70077bfdacdd63d88885134431f024c2acb7126827b174eb093eb5313f07bb5461de9b0feb7d77ca2c39c2a323a150f33ea525f
# End of iteration
Result = Composite
W = 28cc3e08c44571c6dcb98a9ab8b4f3e2b16e1f884997d94a3188bcbb7f1b7cdaecdae8329c013ec8f75dc00004da0039943e4262cd080b16a42910102e00dddb
B = 512061ab1c69931c2fa0bb89d8d09f3c9209230bf927ddd6fb6a72075f967ed3c4dbb5f437bf4d31ca7344782b22011ad56609dc19aed65319bababfc13dd7
# End of iteration
Result = Composite
W = 4eeb7b4d371c45fe8586fee3b1efd792176b70f6cc2698dfa1dd028366626febe0199c3c5f77a5c3cad0057a04767383051d41965255d03681b2a37edad34a9b
B = 4afc2e85f84017b3fd6967a227eb74c8297b40ea02733d9513bff9b3f01081963f25872f4254afc4e9321eea35b2a1e42eadb186fcc84f2f30f4a994350b93b8
# End of iteration
Result = Composite
W = 8e35a959555dd2eb66c65cee3c264071d20671f159e1f9896f1d0ceb041905fcf053eacc189de317c3ee6f93901223cbf30d5b7ddbbdab981790e2f6397e6803
B = 44c0153759309ec4e5b1e59d57c1b126545ef7ea302b6e43561df4d16068b922389d6924f01c945d9080d1f93a0732599bdedae72d6d590839dc0884dd860441
# 0x6c1 = 1729 = 7 * 13 * 19 is a Fermat pseudoprime.
# Found non-trivial square root
Result = Composite
W = 6c1
B = b8
# End of iteration
Result = Composite
W = 6c1
B = 111
# End of iteration
Result = Composite
W = 6c1
B = 11d
# Found non-trivial square root
Result = Composite
W = 6c1
B = 19c
# Found non-trivial square root
Result = Composite
W = 6c1
B = 223
# End of iteration
Result = Composite
W = 6c1
B = 3aa
# Found non-trivial square root
Result = Composite
W = 6c1
B = 653
# 1729 has a number of false witnesses.
# b^m = 1
Result = PossiblyPrime
W = 6c1
B = 78
# b^m = 1
Result = PossiblyPrime
W = 6c1
B = eb
# b^m = w-1
Result = PossiblyPrime
W = 6c1
B = 178
# b^m = w-1
Result = PossiblyPrime
W = 6c1
B = 178
# b^m = w-1
Result = PossiblyPrime
W = 6c1
B = 1aa
# b^m = 1
Result = PossiblyPrime
W = 6c1
B = 271
# b^m = 1
Result = PossiblyPrime
W = 6c1
B = 2b2
# 1 and W-1 are always nonwitnesses.
Result = PossiblyPrime
W = 6c1
B = 1
Result = PossiblyPrime
W = 6c1
B = 6c0
# https://kconrad.math.uconn.edu/blurbs/ugradnumthy/millerrabin.pdf, examples
# 3.1 and 3.2 has a complete list of false witnesses for 65 = 0x41 and
# 85 = 0x55.
# b^m = 1
Result = PossiblyPrime
W = 41
B = 1
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 41
B = 8
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 41
B = 12
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 41
B = 2f
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 41
B = 39
# b^m = w-1
Result = PossiblyPrime
W = 41
B = 40
# b^m = 1
Result = PossiblyPrime
W = 55
B = 1
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 55
B = d
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 55
B = 26
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 55
B = 2f
# Some b^(m*2^j) = w-1
Result = PossiblyPrime
W = 55
B = 48
# b^m = w-1
Result = PossiblyPrime
W = 55
B = 54
# Other witnesses for 65 and 85 will report composite:
# Found non-trivial square root
Result = Composite
W = 41
B = 2c
# End of iteration
Result = Composite
W = 41
B = 16
# End of iteration
Result = Composite
W = 41
B = 14
# End of iteration
Result = Composite
W = 41
B = 2
# End of iteration
Result = Composite
W = 41
B = 3a
# End of iteration
Result = Composite
W = 55
B = 40
# End of iteration
Result = Composite
W = 55
B = 7
# End of iteration
Result = Composite
W = 55
B = 23
# End of iteration
Result = Composite
W = 55
B = 2e
# End of iteration
Result = Composite
W = 55
B = 2a
# W below is composite, but it is one of the worst case scenarios for
# Miller-Rabin, from Wycheproof tests. 1/4 of witnesses report the value is
# prime. Test that we correctly classify false and true witnesses.
# b^m = w-1
Result = PossiblyPrime
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 379c6027f818b5164bc13dff5e996ec7210976f33570d5c60275918b8988d97a63bb6582af85682c45667a8b94b7acab4d919ede00f5bd2ba7abc8634d66f8875fd930f35ec8013d37b958e65f07de015c0574e64198d73aab5466f3a971b74830b7f1671cb9277fbc95c1ba8c29dc903d8cea1b74c22ab9164f9c438ab9ba7d9919f832e40c3e36faca7343e2314669b0104d9c4f2e1b011cdbd9c686baef0
# b^m = w-1
Result = PossiblyPrime
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 3cc4b644965b2133caffc2bb6258b1ecd5b586b900a09b010382fcef709e4cd37ee3e3182bf8d393c1ab6f9a933d46338b3d960923d8c9607c2b2763d5680230a2bc0c91138e9d0ecb35e7154a06aaa902d34b9b14964b81f4d8232641492d83b22cd805a115e75ddd8e63b864c00e4c90ba36a41e7966e97e063a60a6a6cfd53e1f62a57852c7443e88dcf6245557a4b65494c3e88e466ad75316aaa9727def
# b^m = 1
Result = PossiblyPrime
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 40c03b6ba22bd62c0379b1c36dfccd34d61e3d15f7af1d5f6a60ab972a9d0e956e2bb9e275294e0f1c879eb7a4555443429c99a8d74f7bd359a1046ac30072c04b0e2cbd005be15ff4ce0c93276de2c513fbc5771b5059904a87f180530f6773498114b5aaf70da01967d8294742e451df6377dd5e64b2a8968f4ba61b51a154317d63958ff3788defbeeebee21af5027c2291e8c5df8c0b66770d91b683cffe
# b^m = w-1
Result = PossiblyPrime
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 3c7c71b84f0c6c3817f57511946315cec7d0120a9c30ceabda801fbaec329a8f10c7b9f0ae90a3dada9885bf73a3cabed86784af9682f3dea50a7817f65cfc9190cf997f12784223c4965ed6e52a1be26d4dde31741cd3d1a2e2f3a74040d0f3868eef849727aa855f66c94791194ad5d360298364e2de9ca9288e6423f644b01d52e1bd66a9f7f00bd7995a9ca2ed16f40e902852c6250a3b52bbbf5bfd33e8
# b^m = w-1
Result = PossiblyPrime
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 36e6aa9acb399a50f52be0324dcef05f3cff3117f94538f6d0952b7d7be88ba4dc75d843ff7ff775e11f55c86ba6b2a6ddebd8850c33424b4d35c66321af426662e7074f0a2409a9ccf1c66ef7d823efc8240b8f3c7e9e8dd65a64e8a3ca5b26695ef17171ffe136c0593b179414c5b5ad0d66f2a25146c38b2f97e60b0472ed72de34bff1b6ac186f23645a1bbe909cdfc2b2d861eb44931568f1bb117d8a0c
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 278f2215d3ab836043fbfa472216bbdcedb775a6a0ed711754d05aa75089a9e5d8201e113d68656f37381e44483cd365f5d383bdca5ae8d1f2e6575d7873851cfff0e12b1cfe100a04cb300cbd924353fcbd3307d01242cf6a5e86e752c6f4586bcabf48b018bb97e65c3ed409fd6f67f98987517356d88344b3c8945ccd753148a37b648dd2db44d19522a69a9ad8eb23edc55340e85a198abf179ad731db41
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = afa1478bebbfe1157568f4ae53549b4c3a6a8771b816970bfac6ce5c8b962231db7a41da4d5f1d8bf504dcfe440325b54e1888bdae344eb969436a35e5c6ce5300d46313cb2fcb57fc83305f65f53d392de400e9231cbbc2ac8243defcaf7063c632b9601a81d83138274702ff336d727d3e82ccacce069843ac9c1c590c772c8c586b65c7085a1df5a47fc960d4098a22418b41f0062c77b5d55d17149d167
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 10f7030590b629e0313a61bdf46936a1f25db91b2b421f7ebb671f7844c22561b44b2f7699db61e5228ebb5817afad416325f9439eff7a82d8a630c504de12eaa44d97c79ee56e726ae74ee0b472f0d5fa8f20aee426e689cd33dd084f96bf4d928a21e815f7e8aaca4a5752f39c4a76bdfaa8227dc05d0dfa885d8b26d46fbcbf0d2e0d999d2c31ad84c306c9126539dbdf447f8dc707d29c7fa8021a767668
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 97dbb6a55c039ec926aaa5ff15a2917a2b4cafc3ca07c4c6b05f931d86c9bf60ee05cbbace194e5ca97682ec67c36394018d68c3536fbf13b50f8a7e31eaed87307759a0a48c6c58d21bc7c38b878c53db5d7a8e1fdd81abefc50470a3800852e74d76fdd1933e45f39ee97b8efb68837721890d867b32a894dd0ceb4c5844a05d384145865c10973ce748ccdd8fee73f1bf8611ce0535430b6b98fb36cad7a
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 225f58add44ed2b0a64a1d8452866d0f3c0cd45c8375e1bb33c188915c77fa11b81250b920245dda7f6126e5e0c79e6f98f89dc15db86394cf81b44f0d801e613fa4d5c6fef66fa31f26cfe6153f2e8159aad6b0351dcc0e93f9a68f649b2a77cff747b605b542d22419166befebec6cde3201e3c0cacaa2bc9d87073b8d1f1aa2b114d61de45ac8b0ad2141b43434a629ef284cd999fd82b310db7c57cf5c81
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 2780926c9cf7c1eb2aaa935d90b6d4dea44eeefdfcf9ccd4a33feb215e3a1cb2d358136a490fed18403947f3d98807819737c66e12d42c3cc8c0e246b96b3c3b0795ab875fbaf668b81b5b05bf23e258ea00a0a140a790f76e04ab619800b7597f614ffc1a1c94be2f3f1a71d64eb47d98e4653d76eabedacff3a97ecf590e6a1fd55096b7bc9314629f698d0fbe9b01a1f2bc0bf3a2c097f99f1fd222b52ed2
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 129cc5b0d9f8001b3895f1fcb4833779763636aeeeb3f980e63ea506202e6bde868444b6a58ff1dca08625f025a7e95a5eaaf1a8899eee640e3f05fbdb2867e2483bdc27c87b58684416e521c107f3667ed8dd23f0381edab767c5205a4378118bc011947cb6bdfe3fa4af50b8de876b555c9a0b2b0dae01261847f63e1e0cac2d032530bf19d5da60a04dfe22ce6343f60defbb94ccf0bdf010f89a4029720
# b^m = 1
Result = PossiblyPrime
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 4e2a47cf67c3331b1e9976f583f6339cf76a8d48682d01355c25b2aed90c5544e737ecfa849c17d27a64fad7e659ef48df9a3ac0410e5c7ca8d087fc3a3ba23e5a3f000be009fcc8227ead28158c5b5d66f2efb47111638ef61cea4984de42fbd476bc2236ad02154d3ce85805c45e49d16b496e313a4052a37d4b88a3b13e598d2074a3e36a37e90278601f2b2305e034f9bf3aea8e939c3ba274e8ff4d8a14
# b^m = 1
Result = PossiblyPrime
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 2455c4ab826e2ae72708a8ff51348ce4821cb86fa89e298c751c1754211c63b2e9a712d40f0235f310606fcf296726a86973f19f890d571f5b90f026e8d24d07bc0478a3c1333171587387f1f7fe4a770b593216f2743318aabacb3320c40a4e52b9f409e1176fe8db099e93a7991eb8568168e2e486fa5aa228bb1dce9df3290ef13fd21c331479bb0f8b7a7e7f03c5211ae8cc46fa4d0f46e86b2dadeddd5b
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 9951c2c02dd7deedce29bd0c78dd80066b1d69c0e6fe4a17f7d03c6a640d866d01fc8214bafb6737efd93d80a35b8993f5367ce287459b07954e9771ffbc72ccdd812d26a9bf4be0292a24eb5c3b56f09619b1c1b481f7566f7e50e65f69f5feb591bd107fec72a783429dbde6e2607f3db2c58d4b070a45b4d6b43537e19942ce890b04ae1e91069c04a96ed03ddb2f4fc456f136b98102c70a15700dbd911
# End of iteration
Result = Composite
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
B = 4cb8217d229d5f95f6d94807a99363823655d6bba6bdafa4f0dbfe7a5c538aa79c918710aad4f55caaee5ab405ebdcef29dfb76cae99fca8d5a955b6315f71a3cb2d69a217ff45aed66ba87cdc5c0de5d512c6dd12e641e9fe6a2557dd2f03bf3a18650ff139efa179f0fbe69cbb4b54e50d13177bfe7bb90de36b548d5ccfef74b05d3c08a7e2a3bb4dc8d7eb338a7a1b068c433ea204d171eda5e7c6b6722c
+8 -8
View File
@@ -455,18 +455,18 @@ void bn_to_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
bn_mod_mul_montgomery_small(r, a, mont->RR.d, num, mont);
}
void bn_from_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
const BN_MONT_CTX *mont) {
if (num != (size_t)mont->N.width || num > BN_SMALL_MAX_WORDS) {
void bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont) {
if (num_r != (size_t)mont->N.width || num_r > BN_SMALL_MAX_WORDS ||
num_a > 2 * num_r) {
abort();
}
BN_ULONG tmp[BN_SMALL_MAX_WORDS * 2];
OPENSSL_memcpy(tmp, a, num * sizeof(BN_ULONG));
OPENSSL_memset(tmp + num, 0, num * sizeof(BN_ULONG));
if (!bn_from_montgomery_in_place(r, num, tmp, 2 * num, mont)) {
BN_ULONG tmp[BN_SMALL_MAX_WORDS * 2] = {0};
OPENSSL_memcpy(tmp, a, num_a * sizeof(BN_ULONG));
if (!bn_from_montgomery_in_place(r, num_r, tmp, 2 * num_r, mont)) {
abort();
}
OPENSSL_cleanse(tmp, 2 * num * sizeof(BN_ULONG));
OPENSSL_cleanse(tmp, 2 * num_r * sizeof(BN_ULONG));
}
void bn_mod_mul_montgomery_small(BN_ULONG *r, const BN_ULONG *a,
+30 -154
View File
@@ -119,26 +119,20 @@ static void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, size_t na,
}
}
#if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM)
// Here follows specialised variants of bn_add_words() and bn_sub_words(). They
// have the property performing operations on arrays of different sizes. The
// sizes of those arrays is expressed through cl, which is the common length (
// basicall, min(len(a),len(b)) ), and dl, which is the delta between the two
// lengths, calculated as len(a)-len(b). All lengths are the number of
// BN_ULONGs... For the operations that require a result array as parameter,
// it must have the length cl+abs(dl). These functions should probably end up
// in bn_asm.c as soon as there are assembler counterparts for the systems that
// use assembler files.
// bn_sub_part_words sets |r| to |a| - |b|. It returns the borrow bit, which is
// one if the operation underflowed and zero otherwise. |cl| is the common
// length, that is, the shorter of len(a) or len(b). |dl| is the delta length,
// that is, len(a) - len(b). |r|'s length matches the larger of |a| and |b|, or
// cl + abs(dl).
//
// TODO(davidben): Make this take |size_t|. The |cl| + |dl| calling convention
// is confusing.
static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
const BN_ULONG *b, int cl, int dl) {
BN_ULONG c, t;
assert(cl >= 0);
c = bn_sub_words(r, a, b, cl);
BN_ULONG borrow = bn_sub_words(r, a, b, cl);
if (dl == 0) {
return c;
return borrow;
}
r += cl;
@@ -146,147 +140,26 @@ static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
b += cl;
if (dl < 0) {
for (;;) {
t = b[0];
r[0] = 0 - t - c;
if (t != 0) {
c = 1;
}
if (++dl >= 0) {
break;
}
t = b[1];
r[1] = 0 - t - c;
if (t != 0) {
c = 1;
}
if (++dl >= 0) {
break;
}
t = b[2];
r[2] = 0 - t - c;
if (t != 0) {
c = 1;
}
if (++dl >= 0) {
break;
}
t = b[3];
r[3] = 0 - t - c;
if (t != 0) {
c = 1;
}
if (++dl >= 0) {
break;
}
b += 4;
r += 4;
// |a| is shorter than |b|. Complete the subtraction as if the excess words
// in |a| were zeros.
dl = -dl;
for (int i = 0; i < dl; i++) {
r[i] = 0u - b[i] - borrow;
borrow |= r[i] != 0;
}
} else {
int save_dl = dl;
while (c) {
t = a[0];
r[0] = t - c;
if (t != 0) {
c = 0;
}
if (--dl <= 0) {
break;
}
t = a[1];
r[1] = t - c;
if (t != 0) {
c = 0;
}
if (--dl <= 0) {
break;
}
t = a[2];
r[2] = t - c;
if (t != 0) {
c = 0;
}
if (--dl <= 0) {
break;
}
t = a[3];
r[3] = t - c;
if (t != 0) {
c = 0;
}
if (--dl <= 0) {
break;
}
save_dl = dl;
a += 4;
r += 4;
}
if (dl > 0) {
if (save_dl > dl) {
switch (save_dl - dl) {
case 1:
r[1] = a[1];
if (--dl <= 0) {
break;
}
OPENSSL_FALLTHROUGH;
case 2:
r[2] = a[2];
if (--dl <= 0) {
break;
}
OPENSSL_FALLTHROUGH;
case 3:
r[3] = a[3];
if (--dl <= 0) {
break;
}
}
a += 4;
r += 4;
}
}
if (dl > 0) {
for (;;) {
r[0] = a[0];
if (--dl <= 0) {
break;
}
r[1] = a[1];
if (--dl <= 0) {
break;
}
r[2] = a[2];
if (--dl <= 0) {
break;
}
r[3] = a[3];
if (--dl <= 0) {
break;
}
a += 4;
r += 4;
}
// |b| is shorter than |a|. Complete the subtraction as if the excess words
// in |b| were zeros.
for (int i = 0; i < dl; i++) {
// |r| and |a| may alias, so use a temporary.
BN_ULONG tmp = a[i];
r[i] = a[i] - borrow;
borrow = tmp < r[i];
}
}
return c;
return borrow;
}
#else
// On other platforms the function is defined in asm.
BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
int cl, int dl);
#endif
// bn_abs_sub_part_words computes |r| = |a| - |b|, storing the absolute value
// and returning a mask of all ones if the result was negative and all zeros if
@@ -294,8 +167,7 @@ BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
// convention.
//
// TODO(davidben): Make this take |size_t|. The |cl| + |dl| calling convention
// is confusing. The trouble is 32-bit x86 implements |bn_sub_part_words| in
// assembly, but we can probably just delete it?
// is confusing.
static BN_ULONG bn_abs_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
const BN_ULONG *b, int cl, int dl,
BN_ULONG *tmp) {
@@ -583,7 +455,7 @@ static int bn_mul_impl(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
static const int kMulNormalSize = 16;
if (al >= kMulNormalSize && bl >= kMulNormalSize) {
if (-1 <= i && i <= 1) {
// Find the larger power of two less than or equal to the larger length.
// Find the largest power of two less than or equal to the larger length.
int j;
if (i >= 0) {
j = BN_num_bits_word((BN_ULONG)al);
@@ -599,6 +471,10 @@ static int bn_mul_impl(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
if (al > j || bl > j) {
// We know |al| and |bl| are at most one from each other, so if al > j,
// bl >= j, and vice versa. Thus we can use |bn_mul_part_recursive|.
//
// TODO(davidben): This codepath is almost unused in standard
// algorithms. Is this optimization necessary? See notes in
// https://boringssl-review.googlesource.com/q/I0bd604e2cd6a75c266f64476c23a730ca1721ea6
assert(al >= j && bl >= j);
if (!bn_wexpand(t, j * 8) ||
!bn_wexpand(rr, j * 4)) {
+273 -360
View File
@@ -119,199 +119,98 @@
// Zimmermann's, as implemented in PGP. I have had a read of his comments and
// implemented my own version.
// kPrimes contains the first 2048 primes.
// kPrimes contains the first 1024 primes.
static const uint16_t kPrimes[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257,
263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389,
397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457,
461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823,
827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,
907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977,
983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049,
1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117,
1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289,
1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453,
1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531,
1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607,
1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777,
1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871,
1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951,
1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029,
2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113,
2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293,
2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377,
2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447,
2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551,
2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659,
2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713,
2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887,
2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971,
2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187,
3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359,
3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461,
3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617,
3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701,
3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889,
3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073,
4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157,
4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253,
4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349,
4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451,
4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643,
4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729,
4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817,
4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009,
5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209,
5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309,
5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417,
5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501,
5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581,
5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683,
5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783,
5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953,
5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163,
6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263,
6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337,
6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427,
6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553,
6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659,
6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737,
6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947,
6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013,
7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127,
7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333,
7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477,
7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547,
7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621,
7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717,
7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927,
7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053,
8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147,
8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237,
8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329,
8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443,
8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563,
8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663,
8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737,
8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933,
8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029,
9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137,
9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227,
9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337,
9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421,
9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497,
9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623,
9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721,
9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901,
9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037,
10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133,
10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223,
10243, 10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313,
10321, 10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429,
10433, 10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529,
10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639,
10651, 10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733,
10739, 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957,
10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071,
11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171,
11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279,
11287, 11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393,
11399, 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491,
11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617,
11621, 11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731,
11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831,
11833, 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933,
11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037,
12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119,
12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241,
12251, 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343,
12347, 12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437,
12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527,
12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613,
12619, 12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713,
12721, 12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823,
12829, 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923,
12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009,
13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127,
13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229,
13241, 13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337,
13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457,
13463, 13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577,
13591, 13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687,
13691, 13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759,
13763, 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877,
13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967,
13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083,
14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221,
14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347,
14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447,
14449, 14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551,
14557, 14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653,
14657, 14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747,
14753, 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831,
14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939,
14947, 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161,
15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269,
15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349,
15359, 15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443,
15451, 15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559,
15569, 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649,
15661, 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749,
15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859,
15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959,
15971, 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069,
16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187,
16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301,
16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421,
16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529,
16547, 16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649,
16651, 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747,
16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883,
16889, 16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981,
16987, 16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077,
17093, 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,
17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321,
17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401,
17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491,
17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599,
17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729,
17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839,
17851, 17863,
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,
367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433,
439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593,
599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249,
1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439,
1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783,
1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143,
2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347,
2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543,
2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713,
2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119,
3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323,
3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527,
3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697,
3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003,
4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093,
4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283,
4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513,
4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621,
4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721,
4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113,
5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233,
5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531,
5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653,
5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849,
5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173,
6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271,
6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359,
6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581,
6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803,
6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907,
6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487,
7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669,
7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757,
7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879,
7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
8117, 8123, 8147, 8161,
};
// BN_prime_checks_for_size returns the number of Miller-Rabin iterations
// necessary for a 'bits'-bit prime.
// necessary for generating a 'bits'-bit candidate prime.
//
//
// This table is generated using the algorithm of FIPS PUB 186-4
@@ -394,7 +293,7 @@ static size_t num_trial_division_primes(const BIGNUM *n) {
if (n->width * BN_BITS2 > 1024) {
return OPENSSL_ARRAY_SIZE(kPrimes);
}
return OPENSSL_ARRAY_SIZE(kPrimes) / 4;
return OPENSSL_ARRAY_SIZE(kPrimes) / 2;
}
// BN_PRIME_CHECKS_BLINDED is the iteration count for blinding the constant-time
@@ -544,6 +443,11 @@ loop:
goto err;
}
// Interleave |ret| and |t|'s primality tests to avoid paying the full
// iteration count on |ret| only to quickly discover |t| is composite.
//
// TODO(davidben): This doesn't quite work because an iteration count of 1
// still runs the blinding mechanism.
for (i = 0; i < checks; i++) {
j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, NULL);
if (j == -1) {
@@ -559,7 +463,7 @@ loop:
goto loop;
}
if (!BN_GENCB_call(cb, i, c1 - 1)) {
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i)) {
goto err;
}
// We have a safe prime test pass
@@ -594,14 +498,157 @@ int bn_odd_number_is_obviously_composite(const BIGNUM *bn) {
return bn_trial_division(&prime, bn) && !BN_is_word(bn, prime);
}
int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w,
int iterations, BN_CTX *ctx, int do_trial_division,
BN_GENCB *cb) {
*out_is_probably_prime = 0;
int bn_miller_rabin_init(BN_MILLER_RABIN *miller_rabin, const BN_MONT_CTX *mont,
BN_CTX *ctx) {
// This function corresponds to steps 1 through 3 of FIPS 186-4, C.3.1.
const BIGNUM *w = &mont->N;
// Note we do not call |BN_CTX_start| in this function. We intentionally
// allocate values in the containing scope so they outlive this function.
miller_rabin->w1 = BN_CTX_get(ctx);
miller_rabin->m = BN_CTX_get(ctx);
miller_rabin->one_mont = BN_CTX_get(ctx);
miller_rabin->w1_mont = BN_CTX_get(ctx);
if (miller_rabin->w1 == NULL ||
miller_rabin->m == NULL ||
miller_rabin->one_mont == NULL ||
miller_rabin->w1_mont == NULL) {
return 0;
}
// To support RSA key generation, this function should treat |w| as secret if
// it is a large prime. Composite numbers are discarded, so they may return
// early.
// See FIPS 186-4, C.3.1, steps 1 through 3.
if (!bn_usub_consttime(miller_rabin->w1, w, BN_value_one())) {
return 0;
}
miller_rabin->a = BN_count_low_zero_bits(miller_rabin->w1);
if (!bn_rshift_secret_shift(miller_rabin->m, miller_rabin->w1,
miller_rabin->a, ctx)) {
return 0;
}
miller_rabin->w_bits = BN_num_bits(w);
// Precompute some values in Montgomery form.
if (!bn_one_to_montgomery(miller_rabin->one_mont, mont, ctx) ||
// w - 1 is -1 mod w, so we can compute it in the Montgomery domain, -R,
// with a subtraction. (|one_mont| cannot be zero.)
!bn_usub_consttime(miller_rabin->w1_mont, w, miller_rabin->one_mont)) {
return 0;
}
return 1;
}
int bn_miller_rabin_iteration(const BN_MILLER_RABIN *miller_rabin,
int *out_is_possibly_prime, const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx) {
// This function corresponds to steps 4.3 through 4.5 of FIPS 186-4, C.3.1.
int ret = 0;
BN_CTX_start(ctx);
// Step 4.3. We use Montgomery-encoding for better performance and to avoid
// timing leaks.
const BIGNUM *w = &mont->N;
BIGNUM *z = BN_CTX_get(ctx);
if (z == NULL ||
!BN_mod_exp_mont_consttime(z, b, miller_rabin->m, w, ctx, mont) ||
!BN_to_montgomery(z, z, mont, ctx)) {
goto err;
}
// is_possibly_prime is all ones if we have determined |b| is not a composite
// witness for |w|. This is equivalent to going to step 4.7 in the original
// algorithm. To avoid timing leaks, we run the algorithm to the end for prime
// inputs.
crypto_word_t is_possibly_prime = 0;
// Step 4.4. If z = 1 or z = w-1, b is not a composite witness and w is still
// possibly prime.
is_possibly_prime = BN_equal_consttime(z, miller_rabin->one_mont) |
BN_equal_consttime(z, miller_rabin->w1_mont);
is_possibly_prime = 0 - is_possibly_prime; // Make it all zeros or all ones.
// Step 4.5.
//
// To avoid leaking |a|, we run the loop to |w_bits| and mask off all
// iterations once |j| = |a|.
for (int j = 1; j < miller_rabin->w_bits; j++) {
if (constant_time_eq_int(j, miller_rabin->a) & ~is_possibly_prime) {
// If the loop is done and we haven't seen z = 1 or z = w-1 yet, the
// value is composite and we can break in variable time.
break;
}
// Step 4.5.1.
if (!BN_mod_mul_montgomery(z, z, z, mont, ctx)) {
goto err;
}
// Step 4.5.2. If z = w-1 and the loop is not done, this is not a composite
// witness.
crypto_word_t z_is_w1_mont = BN_equal_consttime(z, miller_rabin->w1_mont);
z_is_w1_mont = 0 - z_is_w1_mont; // Make it all zeros or all ones.
is_possibly_prime |= z_is_w1_mont; // Go to step 4.7 if |z_is_w1_mont|.
// Step 4.5.3. If z = 1 and the loop is not done, the previous value of z
// was not -1. There are no non-trivial square roots of 1 modulo a prime, so
// w is composite and we may exit in variable time.
if (BN_equal_consttime(z, miller_rabin->one_mont) & ~is_possibly_prime) {
break;
}
}
*out_is_possibly_prime = is_possibly_prime & 1;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w, int checks,
BN_CTX *ctx, int do_trial_division, BN_GENCB *cb) {
// This function's secrecy and performance requirements come from RSA key
// generation. We generate RSA keys by selecting two large, secret primes with
// rejection sampling.
//
// We thus treat |w| as secret if turns out to be a large prime. However, if
// |w| is composite, we treat this and |w| itself as public. (Conversely, if
// |w| is prime, that it is prime is public. Only the value is secret.) This
// is fine for RSA key generation, but note it is important that we use
// rejection sampling, with each candidate prime chosen independently. This
// would not work for, e.g., an algorithm which looked for primes in
// consecutive integers. These assumptions allow us to discard composites
// quickly. We additionally treat |w| as public when it is a small prime to
// simplify trial decryption and some edge cases.
//
// One RSA key generation will call this function on exactly two primes and
// many more composites. The overall cost is a combination of several factors:
//
// 1. Checking if |w| is divisible by a small prime is much faster than
// learning it is composite by Miller-Rabin (see below for details on that
// cost). Trial division by p saves 1/p of Miller-Rabin calls, so this is
// worthwhile until p exceeds the ratio of the two costs.
//
// 2. For a random (i.e. non-adversarial) candidate large prime and candidate
// witness, the probability of false witness is very low. (This is why FIPS
// 186-4 only requires a few iterations.) Thus composites not discarded by
// trial decryption, in practice, cost one Miller-Rabin iteration. Only the
// two actual primes cost the full iteration count.
//
// 3. A Miller-Rabin iteration is a modular exponentiation plus |a| additional
// modular squares, where |a| is the number of factors of two in |w-1|. |a|
// is likely small (the distribution falls exponentially), but it is also
// potentially secret, so we loop up to its log(w) upper bound when |w| is
// prime. When |w| is composite, we break early, so only two calls pay this
// cost. (Note that all calls pay the modular exponentiation which is,
// itself, log(w) modular multiplications and squares.)
//
// 4. While there are only two prime calls, they multiplicatively pay the full
// costs of (2) and (3).
//
// 5. After the primes are chosen, RSA keys derive some values from the
// primes, but this cost is negligible in comparison.
*out_is_probably_prime = 0;
if (BN_cmp(w, BN_value_one()) <= 0) {
return 1;
@@ -626,13 +673,13 @@ int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w,
*out_is_probably_prime = BN_is_word(w, prime);
return 1;
}
if (!BN_GENCB_call(cb, 1, -1)) {
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, -1)) {
return 0;
}
}
if (iterations == BN_prime_checks) {
iterations = BN_prime_checks_for_size(BN_num_bits(w));
if (checks == BN_prime_checks_for_generation) {
checks = BN_prime_checks_for_size(BN_num_bits(w));
}
BN_CTX *new_ctx = NULL;
@@ -646,36 +693,13 @@ int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w,
// See C.3.1 from FIPS 186-4.
int ret = 0;
BN_MONT_CTX *mont = NULL;
BN_CTX_start(ctx);
BIGNUM *w1 = BN_CTX_get(ctx);
if (w1 == NULL ||
!bn_usub_consttime(w1, w, BN_value_one())) {
goto err;
}
// Write w1 as m * 2^a (Steps 1 and 2).
int w_len = BN_num_bits(w);
int a = BN_count_low_zero_bits(w1);
BIGNUM *m = BN_CTX_get(ctx);
if (m == NULL ||
!bn_rshift_secret_shift(m, w1, a, ctx)) {
goto err;
}
// Montgomery setup for computations mod w. Additionally, compute 1 and w - 1
// in the Montgomery domain for later comparisons.
BIGNUM *b = BN_CTX_get(ctx);
BIGNUM *z = BN_CTX_get(ctx);
BIGNUM *one_mont = BN_CTX_get(ctx);
BIGNUM *w1_mont = BN_CTX_get(ctx);
mont = BN_MONT_CTX_new_consttime(w, ctx);
if (b == NULL || z == NULL || one_mont == NULL || w1_mont == NULL ||
mont == NULL ||
!bn_one_to_montgomery(one_mont, mont, ctx) ||
// w - 1 is -1 mod w, so we can compute it in the Montgomery domain, -R,
// with a subtraction. (|one_mont| cannot be zero.)
!bn_usub_consttime(w1_mont, w, one_mont)) {
BN_MONT_CTX *mont = BN_MONT_CTX_new_consttime(w, ctx);
BN_MILLER_RABIN miller_rabin;
if (b == NULL || mont == NULL ||
// Steps 1-3.
!bn_miller_rabin_init(&miller_rabin, mont, ctx)) {
goto err;
}
@@ -711,78 +735,36 @@ int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w,
// Using |constant_time_lt_w| seems to prevent the compiler from optimizing
// this into two jumps.
for (int i = 1; (i <= BN_PRIME_CHECKS_BLINDED) |
constant_time_lt_w(uniform_iterations, iterations);
constant_time_lt_w(uniform_iterations, checks);
i++) {
// Step 4.1-4.2
int is_uniform;
if (// Step 4.1-4.2
!bn_rand_secret_range(b, &is_uniform, 2, w1) ||
// Step 4.3
!BN_mod_exp_mont_consttime(z, b, m, w, ctx, mont)) {
goto err;
if (!bn_rand_secret_range(b, &is_uniform, 2, miller_rabin.w1)) {
goto err;
}
uniform_iterations += is_uniform;
// loop_done is all ones if the loop has completed and all zeros otherwise.
crypto_word_t loop_done = 0;
// next_iteration is all ones if we should continue to the next iteration
// (|b| is not a composite witness for |w|). This is equivalent to going to
// step 4.7 in the original algorithm.
crypto_word_t next_iteration = 0;
// Step 4.4. If z = 1 or z = w-1, mask off the loop and continue to the next
// iteration (go to step 4.7).
loop_done = BN_equal_consttime(z, BN_value_one()) |
BN_equal_consttime(z, w1);
loop_done = 0 - loop_done; // Make it all zeros or all ones.
next_iteration = loop_done; // Go to step 4.7 if |loop_done|.
// Step 4.5. We use Montgomery-encoding for better performance and to avoid
// timing leaks.
if (!BN_to_montgomery(z, z, mont, ctx)) {
// Steps 4.3-4.5
int is_possibly_prime = 0;
if (!bn_miller_rabin_iteration(&miller_rabin, &is_possibly_prime, b, mont,
ctx)) {
goto err;
}
// To avoid leaking |a|, we run the loop to |w_len| and mask off all
// iterations once |j| = |a|.
for (int j = 1; j < w_len; j++) {
loop_done |= constant_time_eq_int(j, a);
// Step 4.5.1.
if (!BN_mod_mul_montgomery(z, z, z, mont, ctx)) {
goto err;
}
// Step 4.5.2. If z = w-1 and the loop is not done, run through the next
// iteration.
crypto_word_t z_is_w1_mont = BN_equal_consttime(z, w1_mont) & ~loop_done;
z_is_w1_mont = 0 - z_is_w1_mont; // Make it all zeros or all ones.
loop_done |= z_is_w1_mont;
next_iteration |= z_is_w1_mont; // Go to step 4.7 if |z_is_w1_mont|.
// Step 4.5.3. If z = 1 and the loop is not done, w is composite and we
// may exit in variable time.
if (BN_equal_consttime(z, one_mont) & ~loop_done) {
assert(!next_iteration);
break;
}
}
if (!next_iteration) {
if (!is_possibly_prime) {
// Step 4.6. We did not see z = w-1 before z = 1, so w must be composite.
// (For any prime, the value of z immediately preceding 1 must be -1.
// There are no non-trivial square roots of 1 modulo a prime.)
*out_is_probably_prime = 0;
ret = 1;
goto err;
}
// Step 4.7
if (!BN_GENCB_call(cb, 1, i)) {
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i - 1)) {
goto err;
}
}
assert(uniform_iterations >= (crypto_word_t)iterations);
assert(uniform_iterations >= (crypto_word_t)checks);
*out_is_probably_prime = 1;
ret = 1;
@@ -809,7 +791,7 @@ int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx,
}
int BN_enhanced_miller_rabin_primality_test(
enum bn_primality_result_t *out_result, const BIGNUM *w, int iterations,
enum bn_primality_result_t *out_result, const BIGNUM *w, int checks,
BN_CTX *ctx, BN_GENCB *cb) {
// Enhanced Miller-Rabin is only valid on odd integers greater than 3.
if (!BN_is_odd(w) || BN_cmp_word(w, 3) <= 0) {
@@ -817,8 +799,8 @@ int BN_enhanced_miller_rabin_primality_test(
return 0;
}
if (iterations == BN_prime_checks) {
iterations = BN_prime_checks_for_size(BN_num_bits(w));
if (checks == BN_prime_checks_for_generation) {
checks = BN_prime_checks_for_size(BN_num_bits(w));
}
int ret = 0;
@@ -865,7 +847,7 @@ int BN_enhanced_miller_rabin_primality_test(
// The following loop performs in inner iteration of the Enhanced Miller-Rabin
// Primality test (Step 4).
for (int i = 1; i <= iterations; i++) {
for (int i = 1; i <= checks; i++) {
// Step 4.1-4.2
if (!BN_rand_range_ex(b, 2, w1)) {
goto err;
@@ -932,7 +914,7 @@ int BN_enhanced_miller_rabin_primality_test(
loop:
// Step 4.15
if (!BN_GENCB_call(cb, 1, i)) {
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i - 1)) {
goto err;
}
}
@@ -948,80 +930,11 @@ err:
}
static int probable_prime(BIGNUM *rnd, int bits) {
uint16_t mods[OPENSSL_ARRAY_SIZE(kPrimes)];
const size_t num_primes = num_trial_division_primes(rnd);
BN_ULONG delta;
BN_ULONG maxdelta = BN_MASK2 - kPrimes[num_primes - 1];
char is_single_word = bits <= BN_BITS2;
again:
if (!BN_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) {
return 0;
}
// we now have a random number 'rnd' to test.
for (size_t i = 1; i < num_primes; i++) {
mods[i] = bn_mod_u16_consttime(rnd, kPrimes[i]);
}
// If bits is so small that it fits into a single word then we
// additionally don't want to exceed that many bits.
if (is_single_word) {
BN_ULONG size_limit;
if (bits == BN_BITS2) {
// Avoid undefined behavior.
size_limit = ~((BN_ULONG)0) - BN_get_word(rnd);
} else {
size_limit = (((BN_ULONG)1) << bits) - BN_get_word(rnd) - 1;
do {
if (!BN_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) {
return 0;
}
if (size_limit < maxdelta) {
maxdelta = size_limit;
}
}
delta = 0;
loop:
if (is_single_word) {
BN_ULONG rnd_word = BN_get_word(rnd);
// In the case that the candidate prime is a single word then
// we check that:
// 1) It's greater than kPrimes[i] because we shouldn't reject
// 3 as being a prime number because it's a multiple of
// three.
// 2) That it's not a multiple of a known prime. We don't
// check that rnd-1 is also coprime to all the known
// primes because there aren't many small primes where
// that's true.
for (size_t i = 1; i < num_primes && kPrimes[i] < rnd_word; i++) {
if ((mods[i] + delta) % kPrimes[i] == 0) {
delta += 2;
if (delta > maxdelta) {
goto again;
}
goto loop;
}
}
} else {
for (size_t i = 1; i < num_primes; i++) {
// check that rnd is not a prime and also
// that gcd(rnd-1,primes) == 1 (except for 2)
if (((mods[i] + delta) % kPrimes[i]) <= 1) {
delta += 2;
if (delta > maxdelta) {
goto again;
}
goto loop;
}
}
}
if (!BN_add_word(rnd, delta)) {
return 0;
}
if (BN_num_bits(rnd) != (unsigned)bits) {
goto again;
}
} while (bn_odd_number_is_obviously_composite(rnd));
return 1;
}
+3 -5
View File
@@ -173,11 +173,9 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
ret = aes_nohw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = aes_nohw_decrypt;
dat->stream.cbc = NULL;
#if defined(AES_NOHW_CBC)
if (mode == EVP_CIPH_CBC_MODE) {
dat->stream.cbc = aes_nohw_cbc_encrypt;
}
#endif
}
} else if (hwaes_capable()) {
ret = aes_hw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
@@ -209,11 +207,9 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
ret = aes_nohw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = aes_nohw_encrypt;
dat->stream.cbc = NULL;
#if defined(AES_NOHW_CBC)
if (mode == EVP_CIPH_CBC_MODE) {
dat->stream.cbc = aes_nohw_cbc_encrypt;
}
#endif
}
if (ret < 0) {
@@ -318,7 +314,7 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key,
if (out_block) {
*out_block = aes_nohw_encrypt;
}
return NULL;
return aes_nohw_ctr32_encrypt_blocks;
}
#if defined(OPENSSL_32_BIT)
@@ -1296,6 +1292,8 @@ int EVP_has_aes_hardware(void) {
return hwaes_capable() && crypto_gcm_clmul_enabled();
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable();
#elif defined(OPENSSL_PPC64LE)
return CRYPTO_is_PPC64LE_vcrypto_capable();
#else
return 0;
#endif
+16
View File
@@ -243,6 +243,22 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512) {
}
static void sha512_256_init(EVP_MD_CTX *ctx) {
CHECK(SHA512_256_Init(ctx->md_data));
}
DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) {
out->type = NID_sha512_256;
out->md_size = SHA512_256_DIGEST_LENGTH;
out->flags = 0;
out->init = sha512_256_init;
out->update = sha512_update;
out->final = sha512_final;
out->block_size = 128;
out->ctx_size = sizeof(SHA512_CTX);
}
typedef struct {
MD5_CTX md5;
SHA_CTX sha1;
+289 -117
View File
@@ -84,7 +84,7 @@
static void ec_point_free(EC_POINT *point, int free_group);
static const uint8_t kP224Params[6 * 28] = {
// p
// p = 2^224 - 2^96 + 1
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
@@ -111,7 +111,7 @@ static const uint8_t kP224Params[6 * 28] = {
};
static const uint8_t kP256Params[6 * 32] = {
// p
// p = 2^256 - 2^224 + 2^192 + 2^96 - 1
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -138,7 +138,7 @@ static const uint8_t kP256Params[6 * 32] = {
};
static const uint8_t kP384Params[6 * 48] = {
// p
// p = 2^384 - 2^128 - 2^96 + 2^32 - 1
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -171,7 +171,7 @@ static const uint8_t kP384Params[6 * 48] = {
};
static const uint8_t kP521Params[6 * 66] = {
// p
// p = 2^521 - 1
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -301,17 +301,49 @@ EC_GROUP *ec_group_new(const EC_METHOD *meth) {
return ret;
}
static void ec_group_set0_generator(EC_GROUP *group, EC_POINT *generator) {
static int ec_group_set_generator(EC_GROUP *group, const EC_AFFINE *generator,
const BIGNUM *order) {
assert(group->generator == NULL);
assert(group == generator->group);
if (!BN_copy(&group->order, order)) {
return 0;
}
// Store the order in minimal form, so it can be used with |BN_ULONG| arrays.
bn_set_minimal_width(&group->order);
BN_MONT_CTX_free(group->order_mont);
group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
if (group->order_mont == NULL) {
return 0;
}
group->field_greater_than_order = BN_cmp(&group->field, order) > 0;
if (group->field_greater_than_order) {
BIGNUM tmp;
BN_init(&tmp);
int ok =
BN_sub(&tmp, &group->field, order) &&
bn_copy_words(group->field_minus_order.words, group->field.width, &tmp);
BN_free(&tmp);
if (!ok) {
return 0;
}
}
group->generator = EC_POINT_new(group);
if (group->generator == NULL) {
return 0;
}
ec_affine_to_jacobian(group, &group->generator->raw, generator);
assert(ec_felem_equal(group, &group->one, &group->generator->raw.Z));
// Avoid a reference cycle. |group->generator| does not maintain an owning
// pointer to |group|.
group->generator = generator;
int is_zero = CRYPTO_refcount_dec_and_test_zero(&group->references);
assert(!is_zero);
(void)is_zero;
return 1;
}
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
@@ -321,20 +353,37 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
return NULL;
}
EC_GROUP *ret = ec_group_new(EC_GFp_mont_method());
if (ret == NULL) {
return NULL;
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
return NULL;
}
}
if (ret->meth->group_set_curve == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
EC_GROUP_free(ret);
return NULL;
// Historically, |a| and |b| were not required to be fully reduced.
// TODO(davidben): Can this be removed?
EC_GROUP *ret = NULL;
BN_CTX_start(ctx);
BIGNUM *a_reduced = BN_CTX_get(ctx);
BIGNUM *b_reduced = BN_CTX_get(ctx);
if (a_reduced == NULL || b_reduced == NULL ||
!BN_nnmod(a_reduced, a, p, ctx) ||
!BN_nnmod(b_reduced, b, p, ctx)) {
goto err;
}
if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
ret = ec_group_new(EC_GFp_mont_method());
if (ret == NULL ||
!ret->meth->group_set_curve(ret, p, a_reduced, b_reduced, ctx)) {
EC_GROUP_free(ret);
return NULL;
ret = NULL;
goto err;
}
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
@@ -367,7 +416,6 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
// tiny prime (less than 17). See the proof in |field_element_to_scalar| in
// the ECDSA implementation.
int ret = 0;
EC_POINT *copy = NULL;
BIGNUM *tmp = BN_new();
if (tmp == NULL ||
!BN_lshift1(tmp, order)) {
@@ -378,44 +426,22 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
goto err;
}
copy = EC_POINT_new(group);
if (copy == NULL ||
!EC_POINT_copy(copy, generator) ||
!BN_copy(&group->order, order)) {
goto err;
}
// Store the order in minimal form, so it can be used with |BN_ULONG| arrays.
bn_set_minimal_width(&group->order);
BN_MONT_CTX_free(group->order_mont);
group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
if (group->order_mont == NULL) {
EC_AFFINE affine;
if (!ec_jacobian_to_affine(group, &affine, &generator->raw) ||
!ec_group_set_generator(group, &affine, order)) {
goto err;
}
group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
if (group->field_greater_than_order) {
if (!BN_sub(tmp, &group->field, &group->order) ||
!bn_copy_words(group->field_minus_order.words, group->field.width,
tmp)) {
goto err;
}
}
ec_group_set0_generator(group, copy);
copy = NULL;
ret = 1;
err:
EC_POINT_free(copy);
BN_free(tmp);
return ret;
}
static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
EC_GROUP *group = NULL;
EC_POINT *P = NULL;
BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL;
int ok = 0;
BN_CTX *ctx = BN_CTX_new();
@@ -429,7 +455,8 @@ static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
!(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
!(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
!(b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) ||
!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL))) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
}
@@ -441,42 +468,18 @@ static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
goto err;
}
if ((P = EC_POINT_new(group)) == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
EC_AFFINE G;
EC_FELEM x, y;
if (!ec_felem_from_bytes(group, &x, params + 3 * param_len, param_len) ||
!ec_felem_from_bytes(group, &y, params + 4 * param_len, param_len) ||
!ec_point_set_affine_coordinates(group, &G, &x, &y)) {
goto err;
}
if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
!(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
if (!ec_group_set_generator(group, &G, order)) {
goto err;
}
if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
goto err;
}
if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
}
group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
if (group->field_greater_than_order) {
if (!BN_sub(p, &group->field, &group->order) ||
!bn_copy_words(group->field_minus_order.words, group->field.width, p)) {
goto err;
}
}
group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx);
if (group->order_mont == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
}
ec_group_set0_generator(group, P);
P = NULL;
ok = 1;
err:
@@ -484,13 +487,11 @@ err:
EC_GROUP_free(group);
group = NULL;
}
EC_POINT_free(P);
BN_CTX_free(ctx);
BN_free(p);
BN_free(a);
BN_free(b);
BN_free(x);
BN_free(y);
BN_free(order);
return group;
}
@@ -606,7 +607,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
BN_cmp(&a->field, &b->field) != 0 ||
!ec_felem_equal(a, &a->a, &b->a) ||
!ec_felem_equal(a, &a->b, &b->b) ||
ec_GFp_simple_cmp(a, &a->generator->raw, &b->generator->raw) != 0;
!ec_GFp_simple_points_equal(a, &a->generator->raw, &b->generator->raw);
}
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
@@ -769,7 +770,9 @@ int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return -1;
}
return ec_GFp_simple_cmp(group, &a->raw, &b->raw);
// Note |EC_POINT_cmp| returns zero for equality and non-zero for inequality.
return ec_GFp_simple_points_equal(group, &a->raw, &b->raw) ? 0 : 1;
}
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
@@ -787,13 +790,67 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
if (!group->meth->point_get_affine_coordinates(group, &point->raw,
x == NULL ? NULL : &x_felem,
y == NULL ? NULL : &y_felem) ||
(x != NULL && !bn_set_words(x, x_felem.words, group->field.width)) ||
(y != NULL && !bn_set_words(y, y_felem.words, group->field.width))) {
(x != NULL && !ec_felem_to_bignum(group, x, &x_felem)) ||
(y != NULL && !ec_felem_to_bignum(group, y, &y_felem))) {
return 0;
}
return 1;
}
void ec_affine_to_jacobian(const EC_GROUP *group, EC_RAW_POINT *out,
const EC_AFFINE *p) {
out->X = p->X;
out->Y = p->Y;
out->Z = group->one;
}
int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
const EC_RAW_POINT *p) {
return group->meth->point_get_affine_coordinates(group, p, &out->X, &out->Y);
}
int ec_jacobian_to_affine_batch(const EC_GROUP *group, EC_AFFINE *out,
const EC_RAW_POINT *in, size_t num) {
if (group->meth->jacobian_to_affine_batch == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->jacobian_to_affine_batch(group, out, in, num);
}
int ec_point_set_affine_coordinates(const EC_GROUP *group, EC_AFFINE *out,
const EC_FELEM *x, const EC_FELEM *y) {
void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
const EC_FELEM *b) = group->meth->felem_mul;
void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
group->meth->felem_sqr;
// Check if the point is on the curve.
EC_FELEM lhs, rhs;
felem_sqr(group, &lhs, y); // lhs = y^2
felem_sqr(group, &rhs, x); // rhs = x^2
ec_felem_add(group, &rhs, &rhs, &group->a); // rhs = x^2 + a
felem_mul(group, &rhs, &rhs, x); // rhs = x^3 + ax
ec_felem_add(group, &rhs, &rhs, &group->b); // rhs = x^3 + ax + b
if (!ec_felem_equal(group, &lhs, &rhs)) {
OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
// In the event of an error, defend against the caller not checking the
// return value by setting a known safe value. Note this may not be possible
// if the caller is in the process of constructing an arbitrary group and
// the generator is missing.
if (group->generator != NULL) {
assert(ec_felem_equal(group, &group->one, &group->generator->raw.Z));
out->X = group->generator->raw.X;
out->Y = group->generator->raw.Y;
}
return 0;
}
out->X = *x;
out->Y = *y;
return 1;
}
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx) {
@@ -801,24 +858,24 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (!ec_GFp_simple_point_set_affine_coordinates(group, &point->raw, x, y)) {
if (x == NULL || y == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!EC_POINT_is_on_curve(group, point, ctx)) {
EC_FELEM x_felem, y_felem;
EC_AFFINE affine;
if (!ec_bignum_to_felem(group, &x_felem, x) ||
!ec_bignum_to_felem(group, &y_felem, y) ||
!ec_point_set_affine_coordinates(group, &affine, &x_felem, &y_felem)) {
// In the event of an error, defend against the caller not checking the
// return value by setting a known safe value: the base point.
const EC_POINT *generator = EC_GROUP_get0_generator(group);
// The generator can be missing if the caller is in the process of
// constructing an arbitrary group. In this, we give up and hope they're
// checking the return value.
if (generator) {
ec_GFp_simple_point_copy(&point->raw, &generator->raw);
}
OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
// return value by setting a known safe value.
ec_set_to_safe_point(group, &point->raw);
return 0;
}
ec_affine_to_jacobian(group, &point->raw, &affine);
return 1;
}
@@ -949,10 +1006,27 @@ int ec_point_mul_scalar_public(const EC_GROUP *group, EC_RAW_POINT *r,
return 0;
}
if (group->meth->mul_public == NULL) {
return group->meth->mul_public_batch(group, r, g_scalar, p, p_scalar, 1);
}
group->meth->mul_public(group, r, g_scalar, p, p_scalar);
return 1;
}
int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *g_scalar,
const EC_RAW_POINT *points,
const EC_SCALAR *scalars, size_t num) {
if (group->meth->mul_public_batch == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->mul_public_batch(group, r, g_scalar, points, scalars,
num);
}
int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p, const EC_SCALAR *scalar) {
if (p == NULL || scalar == NULL) {
@@ -961,6 +1035,14 @@ int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
}
group->meth->mul(group, r, p, scalar);
// Check the result is on the curve to defend against fault attacks or bugs.
// This has negligible cost compared to the multiplication.
if (!ec_GFp_simple_is_on_curve(group, r)) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
@@ -972,9 +1054,93 @@ int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
}
group->meth->mul_base(group, r, scalar);
// Check the result is on the curve to defend against fault attacks or bugs.
// This has negligible cost compared to the multiplication.
if (!ec_GFp_simple_is_on_curve(group, r)) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int ec_point_mul_scalar_batch(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
const EC_RAW_POINT *p2,
const EC_SCALAR *scalar2) {
if (group->meth->mul_batch == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
group->meth->mul_batch(group, r, p0, scalar0, p1, scalar1, p2, scalar2);
// Check the result is on the curve to defend against fault attacks or bugs.
// This has negligible cost compared to the multiplication.
if (!ec_GFp_simple_is_on_curve(group, r)) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int ec_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
const EC_RAW_POINT *p) {
if (group->meth->init_precomp == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->init_precomp(group, out, p);
}
int ec_point_mul_scalar_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
const EC_PRECOMP *p2,
const EC_SCALAR *scalar2) {
if (group->meth->mul_precomp == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
group->meth->mul_precomp(group, r, p0, scalar0, p1, scalar1, p2, scalar2);
// Check the result is on the curve to defend against fault attacks or bugs.
// This has negligible cost compared to the multiplication.
if (!ec_GFp_simple_is_on_curve(group, r)) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
void ec_point_select(const EC_GROUP *group, EC_RAW_POINT *out, BN_ULONG mask,
const EC_RAW_POINT *a, const EC_RAW_POINT *b) {
ec_felem_select(group, &out->X, mask, &a->X, &b->X);
ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
ec_felem_select(group, &out->Z, mask, &a->Z, &b->Z);
}
void ec_affine_select(const EC_GROUP *group, EC_AFFINE *out, BN_ULONG mask,
const EC_AFFINE *a, const EC_AFFINE *b) {
ec_felem_select(group, &out->X, mask, &a->X, &b->X);
ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
}
void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask,
const EC_PRECOMP *a, const EC_PRECOMP *b) {
OPENSSL_STATIC_ASSERT(sizeof(out->comb) == sizeof(*out),
"out->comb does not span the entire structure");
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(out->comb); i++) {
ec_affine_select(group, &out->comb[i], mask, &a->comb[i], &b->comb[i]);
}
}
int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
const EC_SCALAR *r) {
return group->meth->cmp_x_coordinate(group, p, r);
@@ -982,14 +1148,19 @@ int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
const EC_RAW_POINT *p) {
EC_FELEM x;
// For simplicity, in case of width mismatches between |group->field| and
// |group->order|, zero any untouched words in |x|.
OPENSSL_memset(&x, 0, sizeof(x));
if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
uint8_t bytes[EC_MAX_BYTES];
size_t len;
if (!ec_get_x_coordinate_as_bytes(group, bytes, &len, sizeof(bytes), p)) {
return 0;
}
// For simplicity, in case of width mismatches between |group->field| and
// |group->order|, zero any untouched words in |out|.
OPENSSL_memset(out, 0, sizeof(EC_SCALAR));
for (size_t i = 0; i < len; i++) {
out->bytes[len - i - 1] = bytes[i];
}
// We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
// can reduce by performing at most one subtraction.
//
@@ -1008,17 +1179,17 @@ int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
// The above does not guarantee |group->field| is not one word larger than
// |group->order|, so read one extra carry word.
BN_ULONG tmp[EC_MAX_WORDS];
BN_ULONG carry =
group->order.width < EC_MAX_WORDS ? x.words[group->order.width] : 0;
bn_reduce_once(out->words, x.words, carry, group->order.d,
group->order.width);
group->order.width < EC_MAX_WORDS ? out->words[group->order.width] : 0;
bn_reduce_once_in_place(out->words, carry, group->order.d, tmp,
group->order.width);
return 1;
}
int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
uint8_t *out_y, size_t *out_len,
size_t max_out,
const EC_RAW_POINT *p) {
int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out,
size_t *out_len, size_t max_out,
const EC_RAW_POINT *p) {
size_t len = BN_num_bytes(&group->field);
assert(len <= EC_MAX_BYTES);
if (max_out < len) {
@@ -1026,26 +1197,27 @@ int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
return 0;
}
EC_FELEM x, y;
if (!group->meth->point_get_affine_coordinates(
group, p, out_x == NULL ? NULL : &x, out_y == NULL ? NULL : &y)) {
EC_FELEM x;
if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
return 0;
}
if (out_x != NULL) {
for (size_t i = 0; i < len; i++) {
out_x[i] = x.bytes[len - i - 1];
}
}
if (out_y != NULL) {
for (size_t i = 0; i < len; i++) {
out_y[i] = y.bytes[len - i - 1];
}
}
ec_felem_to_bytes(group, out, out_len, &x);
*out_len = len;
return 1;
}
void ec_set_to_safe_point(const EC_GROUP *group, EC_RAW_POINT *out) {
if (group->generator != NULL) {
ec_GFp_simple_point_copy(out, &group->generator->raw);
} else {
// The generator can be missing if the caller is in the process of
// constructing an arbitrary group. In this case, we give up and use the
// point at infinity.
ec_GFp_simple_point_set_to_infinity(group, out);
}
}
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
+14 -28
View File
@@ -292,10 +292,6 @@ void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) {
}
int EC_KEY_check_key(const EC_KEY *eckey) {
int ok = 0;
BN_CTX *ctx = NULL;
EC_POINT *point = NULL;
if (!eckey || !eckey->group || !eckey->pub_key) {
OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
@@ -303,41 +299,31 @@ int EC_KEY_check_key(const EC_KEY *eckey) {
if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
goto err;
return 0;
}
ctx = BN_CTX_new();
if (ctx == NULL) {
goto err;
}
// testing whether the pub_key is on the elliptic curve
if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) {
// Test whether the public key is on the elliptic curve.
if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, NULL)) {
OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
goto err;
return 0;
}
// in case the priv_key is present :
// check if generator * priv_key == pub_key
// Check the public and private keys match.
if (eckey->priv_key != NULL) {
point = EC_POINT_new(eckey->group);
if (point == NULL ||
!ec_point_mul_scalar_base(eckey->group, &point->raw,
EC_RAW_POINT point;
if (!ec_point_mul_scalar_base(eckey->group, &point,
&eckey->priv_key->scalar)) {
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
goto err;
return 0;
}
if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
if (!ec_GFp_simple_points_equal(eckey->group, &point,
&eckey->pub_key->raw)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY);
goto err;
return 0;
}
}
ok = 1;
err:
BN_CTX_free(ctx);
EC_POINT_free(point);
return ok;
return 1;
}
int EC_KEY_check_fips(const EC_KEY *key) {
@@ -394,7 +380,7 @@ err:
return ok;
}
size_t EC_KEY_key2buf(EC_KEY *key, point_conversion_form_t form,
size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
unsigned char **out_buf, BN_CTX *ctx) {
if (key == NULL || key->pub_key == NULL || key->group == NULL) {
return 0;
+96 -55
View File
@@ -92,35 +92,20 @@ void ec_GFp_mont_group_finish(EC_GROUP *group) {
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;
int ret = 0;
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
return 0;
}
}
group->mont = BN_MONT_CTX_new_for_modulus(p, ctx);
if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
return 0;
}
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
if (!ret) {
if (!ec_GFp_simple_group_set_curve(group, p, a, b, ctx)) {
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
return 0;
}
err:
BN_CTX_free(new_ctx);
return ret;
return 1;
}
static void ec_GFp_mont_felem_to_montgomery(const EC_GROUP *group,
@@ -132,14 +117,14 @@ static void ec_GFp_mont_felem_to_montgomery(const EC_GROUP *group,
static void ec_GFp_mont_felem_from_montgomery(const EC_GROUP *group,
EC_FELEM *out,
const EC_FELEM *in) {
bn_from_montgomery_small(out->words, in->words, group->field.width,
group->mont);
bn_from_montgomery_small(out->words, group->field.width, in->words,
group->field.width, group->mont);
}
static void ec_GFp_mont_felem_inv(const EC_GROUP *group, EC_FELEM *out,
const EC_FELEM *a) {
bn_mod_inverse_prime_mont_small(out->words, a->words, group->field.width,
group->mont);
static void ec_GFp_mont_felem_inv0(const EC_GROUP *group, EC_FELEM *out,
const EC_FELEM *a) {
bn_mod_inverse0_prime_mont_small(out->words, a->words, group->field.width,
group->mont);
}
void ec_GFp_mont_felem_mul(const EC_GROUP *group, EC_FELEM *r,
@@ -154,30 +139,39 @@ void ec_GFp_mont_felem_sqr(const EC_GROUP *group, EC_FELEM *r,
group->mont);
}
int ec_GFp_mont_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out,
const BIGNUM *in) {
if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
void ec_GFp_mont_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
size_t *out_len, const EC_FELEM *in) {
EC_FELEM tmp;
ec_GFp_mont_felem_from_montgomery(group, &tmp, in);
ec_GFp_simple_felem_to_bytes(group, out, out_len, &tmp);
}
int ec_GFp_mont_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out,
const uint8_t *in, size_t len) {
if (!ec_GFp_simple_felem_from_bytes(group, out, in, len)) {
return 0;
}
if (!bn_copy_words(out->words, group->field.width, in)) {
return 0;
}
ec_GFp_mont_felem_to_montgomery(group, out, out);
return 1;
}
int ec_GFp_mont_felem_to_bignum(const EC_GROUP *group, BIGNUM *out,
const EC_FELEM *in) {
if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
return 0;
}
static void ec_GFp_mont_felem_reduce(const EC_GROUP *group, EC_FELEM *out,
const BN_ULONG *words, size_t num) {
// Convert "from" Montgomery form so the value is reduced mod p.
bn_from_montgomery_small(out->words, group->field.width, words, num,
group->mont);
// Convert "to" Montgomery form to remove the R^-1 factor added.
ec_GFp_mont_felem_to_montgomery(group, out, out);
// Convert to Montgomery form to match this implementation's representation.
ec_GFp_mont_felem_to_montgomery(group, out, out);
}
EC_FELEM tmp;
ec_GFp_mont_felem_from_montgomery(group, &tmp, in);
return bn_set_words(out, tmp.words, group->field.width);
static void ec_GFp_mont_felem_exp(const EC_GROUP *group, EC_FELEM *out,
const EC_FELEM *a, const BN_ULONG *exp,
size_t num_exp) {
bn_mod_exp_mont_small(out->words, a->words, group->field.width, exp, num_exp,
group->mont);
}
static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
@@ -188,18 +182,12 @@ static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
return 0;
}
// Transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3).
// Transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3). Note the check above
// ensures |point->Z| is non-zero, so the inverse always exists.
EC_FELEM z1, z2;
ec_GFp_mont_felem_inv(group, &z2, &point->Z);
ec_GFp_mont_felem_inv0(group, &z2, &point->Z);
ec_GFp_mont_felem_sqr(group, &z1, &z2);
// Instead of using |ec_GFp_mont_felem_from_montgomery| to convert the |x|
// coordinate and then calling |ec_GFp_mont_felem_from_montgomery| again to
// convert the |y| coordinate below, convert the common factor |z1| once now,
// saving one reduction.
ec_GFp_mont_felem_from_montgomery(group, &z1, &z1);
if (x != NULL) {
ec_GFp_mont_felem_mul(group, x, &point->X, &z1);
}
@@ -212,6 +200,52 @@ static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
return 1;
}
static int ec_GFp_mont_jacobian_to_affine_batch(const EC_GROUP *group,
EC_AFFINE *out,
const EC_RAW_POINT *in,
size_t num) {
if (num == 0) {
return 1;
}
// Compute prefix products of all Zs. Use |out[i].X| as scratch space
// to store these values.
out[0].X = in[0].Z;
for (size_t i = 1; i < num; i++) {
ec_GFp_mont_felem_mul(group, &out[i].X, &out[i - 1].X, &in[i].Z);
}
// Some input was infinity iff the product of all Zs is zero.
if (ec_felem_non_zero_mask(group, &out[num - 1].X) == 0) {
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
return 0;
}
// Invert the product of all Zs.
EC_FELEM zinvprod;
ec_GFp_mont_felem_inv0(group, &zinvprod, &out[num - 1].X);
for (size_t i = num - 1; i < num; i--) {
// Our loop invariant is that |zinvprod| is Z0^-1 * Z1^-1 * ... * Zi^-1.
// Recover Zi^-1 by multiplying by the previous product.
EC_FELEM zinv, zinv2;
if (i == 0) {
zinv = zinvprod;
} else {
ec_GFp_mont_felem_mul(group, &zinv, &zinvprod, &out[i - 1].X);
// Maintain the loop invariant for the next iteration.
ec_GFp_mont_felem_mul(group, &zinvprod, &zinvprod, &in[i].Z);
}
// Compute affine coordinates: x = X * Z^-2 and y = Y * Z^-3.
ec_GFp_mont_felem_sqr(group, &zinv2, &zinv);
ec_GFp_mont_felem_mul(group, &out[i].X, &in[i].X, &zinv2);
ec_GFp_mont_felem_mul(group, &out[i].Y, &in[i].Y, &zinv2);
ec_GFp_mont_felem_mul(group, &out[i].Y, &out[i].Y, &zinv);
}
return 1;
}
void ec_GFp_mont_add(const EC_GROUP *group, EC_RAW_POINT *out,
const EC_RAW_POINT *a, const EC_RAW_POINT *b) {
if (a == b) {
@@ -468,16 +502,23 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_mont_method) {
out->group_finish = ec_GFp_mont_group_finish;
out->group_set_curve = ec_GFp_mont_group_set_curve;
out->point_get_affine_coordinates = ec_GFp_mont_point_get_affine_coordinates;
out->jacobian_to_affine_batch = ec_GFp_mont_jacobian_to_affine_batch;
out->add = ec_GFp_mont_add;
out->dbl = ec_GFp_mont_dbl;
out->mul = ec_GFp_mont_mul;
out->mul_base = ec_GFp_mont_mul_base;
out->mul_public = ec_GFp_mont_mul_public;
out->mul_batch = ec_GFp_mont_mul_batch;
out->mul_public_batch = ec_GFp_mont_mul_public_batch;
out->init_precomp = ec_GFp_mont_init_precomp;
out->mul_precomp = ec_GFp_mont_mul_precomp;
out->felem_mul = ec_GFp_mont_felem_mul;
out->felem_sqr = ec_GFp_mont_felem_sqr;
out->bignum_to_felem = ec_GFp_mont_bignum_to_felem;
out->felem_to_bignum = ec_GFp_mont_felem_to_bignum;
out->scalar_inv_montgomery = ec_simple_scalar_inv_montgomery;
out->scalar_inv_montgomery_vartime = ec_GFp_simple_mont_inv_mod_ord_vartime;
out->felem_to_bytes = ec_GFp_mont_felem_to_bytes;
out->felem_from_bytes = ec_GFp_mont_felem_from_bytes;
out->felem_reduce = ec_GFp_mont_felem_reduce;
out->felem_exp = ec_GFp_mont_felem_exp;
out->scalar_inv0_montgomery = ec_simple_scalar_inv0_montgomery;
out->scalar_to_montgomery_inv_vartime =
ec_simple_scalar_to_montgomery_inv_vartime;
out->cmp_x_coordinate = ec_GFp_mont_cmp_x_coordinate;
}
+303 -33
View File
@@ -28,7 +28,9 @@
#include <openssl/mem.h>
#include <openssl/nid.h>
#include <openssl/obj.h>
#include <openssl/span.h>
#include "../../ec_extra/internal.h"
#include "../../test/file_test.h"
#include "../../test/test_util.h"
#include "../bn/internal.h"
@@ -132,6 +134,22 @@ static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
return true;
}
static bool EncodeECPoint(std::vector<uint8_t> *out, const EC_GROUP *group,
const EC_POINT *p, point_conversion_form_t form) {
size_t len = EC_POINT_point2oct(group, p, form, nullptr, 0, nullptr);
if (len == 0) {
return false;
}
out->resize(len);
len = EC_POINT_point2oct(group, p, form, out->data(), out->size(), nullptr);
if (len != out->size()) {
return false;
}
return true;
}
TEST(ECTest, Encoding) {
bssl::UniquePtr<EC_KEY> key =
DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
@@ -330,6 +348,23 @@ TEST(ECTest, ArbitraryCurve) {
EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL));
#endif
// group5 is the same group, but the curve coefficients are passed in
// unreduced and the caller does not pass in a |BN_CTX|.
ASSERT_TRUE(BN_sub(a.get(), a.get(), p.get()));
ASSERT_TRUE(BN_add(b.get(), b.get(), p.get()));
bssl::UniquePtr<EC_GROUP> group5(
EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), NULL));
ASSERT_TRUE(group5);
bssl::UniquePtr<EC_POINT> generator5(EC_POINT_new(group5.get()));
ASSERT_TRUE(generator5);
ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
group5.get(), generator5.get(), gx.get(), gy.get(), ctx.get()));
ASSERT_TRUE(EC_GROUP_set_generator(group5.get(), generator5.get(),
order.get(), BN_value_one()));
EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
EXPECT_EQ(0, EC_GROUP_cmp(group5.get(), group.get(), NULL));
}
TEST(ECTest, SetKeyWithoutGroup) {
@@ -458,9 +493,6 @@ TEST_P(ECCurveTest, SetAffine) {
ASSERT_TRUE(key);
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
nullptr));
// Get the public key's coordinates.
bssl::UniquePtr<BIGNUM> x(BN_new());
ASSERT_TRUE(x);
@@ -498,6 +530,84 @@ TEST_P(ECCurveTest, SetAffine) {
EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
}
TEST_P(ECCurveTest, IsOnCurve) {
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
ASSERT_TRUE(key);
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
// The generated point is on the curve.
EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
nullptr));
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
ASSERT_TRUE(p);
ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
// This should never happen outside of a bug, but |EC_POINT_is_on_curve|
// rejects points not on the curve.
OPENSSL_memset(&p->raw.X, 0, sizeof(p->raw.X));
EXPECT_FALSE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
// The point at infinity is always on the curve.
ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
OPENSSL_memset(&p->raw.Z, 0, sizeof(p->raw.Z));
EXPECT_TRUE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
}
TEST_P(ECCurveTest, Compare) {
bssl::UniquePtr<EC_KEY> key1(EC_KEY_new_by_curve_name(GetParam().nid));
ASSERT_TRUE(key1);
ASSERT_TRUE(EC_KEY_generate_key(key1.get()));
const EC_POINT *pub1 = EC_KEY_get0_public_key(key1.get());
bssl::UniquePtr<EC_KEY> key2(EC_KEY_new_by_curve_name(GetParam().nid));
ASSERT_TRUE(key2);
ASSERT_TRUE(EC_KEY_generate_key(key2.get()));
const EC_POINT *pub2 = EC_KEY_get0_public_key(key2.get());
// Two different points should not compare as equal.
EXPECT_EQ(1, EC_POINT_cmp(group(), pub1, pub2, nullptr));
// Serialize |pub1| and parse it back out. This gives a point in affine
// coordinates.
std::vector<uint8_t> serialized;
ASSERT_TRUE(
EncodeECPoint(&serialized, group(), pub1, POINT_CONVERSION_UNCOMPRESSED));
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
ASSERT_TRUE(p);
ASSERT_TRUE(EC_POINT_oct2point(group(), p.get(), serialized.data(),
serialized.size(), nullptr));
// The points should be equal.
EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
// Add something to the point. It no longer compares as equal.
ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), pub2, nullptr));
EXPECT_EQ(1, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
// Negate |pub2|. It should no longer compare as equal. This tests that we
// check both x and y coordinate.
bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group()));
ASSERT_TRUE(q);
ASSERT_TRUE(EC_POINT_copy(q.get(), pub2));
ASSERT_TRUE(EC_POINT_invert(group(), q.get(), nullptr));
EXPECT_EQ(1, EC_POINT_cmp(group(), q.get(), pub2, nullptr));
// Return |p| to the original value. It should be equal to |pub1| again.
ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), q.get(), nullptr));
EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
// Infinity compares as equal to itself, but not other points.
bssl::UniquePtr<EC_POINT> inf1(EC_POINT_new(group())),
inf2(EC_POINT_new(group()));
ASSERT_TRUE(inf1);
ASSERT_TRUE(EC_POINT_set_to_infinity(group(), inf1.get()));
// |q| is currently -|pub2|.
ASSERT_TRUE(EC_POINT_add(group(), inf2.get(), pub2, q.get(), nullptr));
EXPECT_EQ(0, EC_POINT_cmp(group(), inf1.get(), inf2.get(), nullptr));
EXPECT_EQ(1, EC_POINT_cmp(group(), inf1.get(), p.get(), nullptr));
}
TEST_P(ECCurveTest, GenerateFIPS) {
// Generate an EC_KEY.
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
@@ -704,18 +814,12 @@ TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
nullptr, nullptr));
// Serialize the point.
size_t serialized_len = EC_POINT_point2oct(
group(), point.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
ASSERT_NE(0u, serialized_len);
std::vector<uint8_t> serialized(serialized_len);
ASSERT_EQ(
serialized_len,
EC_POINT_point2oct(group(), point.get(), POINT_CONVERSION_UNCOMPRESSED,
serialized.data(), serialized_len, nullptr));
std::vector<uint8_t> serialized;
ASSERT_TRUE(EncodeECPoint(&serialized, group(), point.get(),
POINT_CONVERSION_UNCOMPRESSED));
// Create a serialized point that is not on the curve.
serialized[serialized_len - 1]++;
serialized[serialized.size() - 1]++;
ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(),
serialized.size(), nullptr));
@@ -879,11 +983,45 @@ TEST(ECTest, ScalarBaseMultVectors) {
ASSERT_TRUE(
EC_POINT_mul(group.get(), p.get(), nullptr, g, n.get(), ctx.get()));
check_point(p.get());
});
}
// These tests take a very long time, but are worth running when we make
// non-trivial changes to the EC code.
#if 0
// Test two-point multiplication.
// These tests take a very long time, but are worth running when we make
// non-trivial changes to the EC code.
TEST(ECTest, DISABLED_ScalarBaseMultVectorsTwoPoint) {
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
ASSERT_TRUE(ctx);
FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
[&](FileTest *t) {
bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
ASSERT_TRUE(group);
bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
ASSERT_TRUE(n);
bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
ASSERT_TRUE(x);
bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
ASSERT_TRUE(y);
bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
bssl::UniquePtr<BIGNUM> px(BN_new());
ASSERT_TRUE(px);
bssl::UniquePtr<BIGNUM> py(BN_new());
ASSERT_TRUE(py);
auto check_point = [&](const EC_POINT *p) {
if (is_infinity) {
EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p));
} else {
ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
group.get(), p, px.get(), py.get(), ctx.get()));
EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
}
};
const EC_POINT *g = EC_GROUP_get0_generator(group.get());
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
ASSERT_TRUE(p);
bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new());
for (int i = -64; i < 64; i++) {
SCOPED_TRACE(i);
@@ -905,29 +1043,17 @@ TEST(ECTest, ScalarBaseMultVectors) {
EC_SCALAR a_scalar, b_scalar;
ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &a_scalar, a.get()));
ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &b_scalar, b.get()));
ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), &p->raw, &a_scalar, &g->raw,
&b_scalar));
ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), &p->raw, &a_scalar,
&g->raw, &b_scalar));
check_point(p.get());
}
#endif
});
}
static uint8_t FromHexChar(char c) {
if ('0' <= c && c <= '9') {
return c - '0';
}
if ('a' <= c && c <= 'f') {
return c - 'a' + 10;
}
abort();
}
static std::vector<uint8_t> HexToBytes(const char *str) {
std::vector<uint8_t> ret;
while (str[0] != '\0') {
ret.push_back((FromHexChar(str[0]) << 4) | FromHexChar(str[1]));
str += 2;
if (!DecodeHex(&ret, str)) {
abort();
}
return ret;
}
@@ -996,3 +1122,147 @@ TEST(ECTest, DeriveFromSecret) {
EXPECT_EQ(Bytes(pub, pub_len), Bytes(test.expected_pub));
}
}
TEST(ECTest, HashToCurve) {
struct HashToCurveTest {
int (*hash_to_curve)(const EC_GROUP *group, EC_RAW_POINT *out,
const uint8_t *dst, size_t dst_len, const uint8_t *msg,
size_t msg_len);
int curve_nid;
const char *dst;
const char *msg;
const char *x_hex;
const char *y_hex;
};
static const HashToCurveTest kTests[] = {
// See draft-irtf-cfrg-hash-to-curve-07, appendix G.2.1.
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
"P384_XMD:SHA-512_SSWU_RO_TESTGEN", "",
"2fc0b9efdd63a8e43b4db88dc12f03c798f6fd91bccac0c9096185"
"4386e58fdc54fc2a01f0f358759054ce1f9b762025",
"949b936fabb72cdb02cd7980b86cb6a3adf286658e81301648851d"
"b8a49d9bec00ccb57698d559fc5960fa5030a8e54b"},
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
"P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abc",
"4f3338035391e8ce8ce40c974136f0edc97f392ffd44a643338741"
"8ed1b8c2603487e1688ec151f048fbc6b2c138c92f",
"152b90aef6558be328a3168855fb1906452e7167b0f7c8a56ff9d4"
"fa87d6fb522cdf8e409db54418b2c764fd26260757"},
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
"P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abcdef0123456789",
"e9e5d7ac397e123d060ad44301cbc8eb972f6e64ebcff29dcc9b9a"
"10357902aace2240c580fec85e5b427d98b4e80703",
"916cb8963521ad75105be43cc4148e5a5bbb4fcf107f1577e4f7fa"
"3ca58cd786aa76890c8e687d2353393bc16c78ec4d"},
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
"P384_XMD:SHA-512_SSWU_RO_TESTGEN",
"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"41941db59a7b8b633bd5bfa462f1e29a9f18e5a341445d90fc6eb9"
"37f2913224287b9dfb64742851f760eb14ca115ff9",
"1510e764f1be968d661b7aaecb26a6d38c98e5205ca150f0ae426d"
"2c3983c68e3a9ffb283c6ae4891d891b5705500475"},
};
for (const auto &test : kTests) {
SCOPED_TRACE(test.dst);
SCOPED_TRACE(test.msg);
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve_nid));
ASSERT_TRUE(group);
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
ASSERT_TRUE(p);
ASSERT_TRUE(test.hash_to_curve(
group.get(), &p->raw, reinterpret_cast<const uint8_t *>(test.dst),
strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
strlen(test.msg)));
std::vector<uint8_t> buf;
ASSERT_TRUE(EncodeECPoint(&buf, group.get(), p.get(),
POINT_CONVERSION_UNCOMPRESSED));
size_t field_len = (buf.size() - 1) / 2;
EXPECT_EQ(test.x_hex,
EncodeHex(bssl::MakeConstSpan(buf).subspan(1, field_len)));
EXPECT_EQ(test.y_hex, EncodeHex(bssl::MakeConstSpan(buf).subspan(
1 + field_len, field_len)));
}
// hash-to-curve functions should check for the wrong group.
bssl::UniquePtr<EC_GROUP> p224(EC_GROUP_new_by_curve_name(NID_secp224r1));
ASSERT_TRUE(p224);
EC_RAW_POINT p;
static const uint8_t kDST[] = {0, 1, 2, 3};
static const uint8_t kMessage[] = {4, 5, 6, 7};
EXPECT_FALSE(ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
p224.get(), &p, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
}
TEST(ECTest, HashToScalar) {
struct HashToScalarTest {
int (*hash_to_scalar)(const EC_GROUP *group, EC_SCALAR *out,
const uint8_t *dst, size_t dst_len,
const uint8_t *msg, size_t msg_len);
int curve_nid;
const char *dst;
const char *msg;
const char *result_hex;
};
static const HashToScalarTest kTests[] = {
{&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
"P384_XMD:SHA-512_SCALAR_TEST", "",
"9687acc2de56c3cf94c0e05b6811a21aa480092254ec0532bdce63"
"140ecd340f09dc2d45d77e21fb0aa76f7707b8a676"},
{&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
"P384_XMD:SHA-512_SCALAR_TEST", "abcdef0123456789",
"8f8076022a68233cbcecaceae68c2068f132724f001caa78619eff"
"1ffc58fa871db73fe9034fc9cf853c384ed34b5666"},
{&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
"P384_XMD:SHA-512_SCALAR_TEST",
"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"750f2fae7d2b2f41ac737d180c1d4363d85a1504798b4976d40921"
"1ddb3651c13a5b4daba9975cdfce18336791131915"},
};
for (const auto &test : kTests) {
SCOPED_TRACE(test.dst);
SCOPED_TRACE(test.msg);
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve_nid));
ASSERT_TRUE(group);
EC_SCALAR scalar;
ASSERT_TRUE(test.hash_to_scalar(
group.get(), &scalar, reinterpret_cast<const uint8_t *>(test.dst),
strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
strlen(test.msg)));
uint8_t buf[EC_MAX_BYTES];
size_t len;
ec_scalar_to_bytes(group.get(), buf, &len, &scalar);
EXPECT_EQ(test.result_hex, EncodeHex(bssl::MakeConstSpan(buf, len)));
}
// hash-to-scalar functions should check for the wrong group.
bssl::UniquePtr<EC_GROUP> p224(EC_GROUP_new_by_curve_name(NID_secp224r1));
ASSERT_TRUE(p224);
EC_SCALAR scalar;
static const uint8_t kDST[] = {0, 1, 2, 3};
static const uint8_t kMessage[] = {4, 5, 6, 7};
EXPECT_FALSE(ec_hash_to_scalar_p384_xmd_sha512_draft07(
p224.get(), &scalar, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
}
+25 -7
View File
@@ -14,6 +14,7 @@
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <assert.h>
@@ -23,15 +24,34 @@
int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in) {
if (BN_is_negative(in) || BN_cmp(in, &group->field) >= 0) {
uint8_t bytes[EC_MAX_BYTES];
size_t len = BN_num_bytes(&group->field);
assert(sizeof(bytes) >= len);
if (BN_is_negative(in) ||
BN_cmp(in, &group->field) >= 0 ||
!BN_bn2bin_padded(bytes, len, in)) {
OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE);
return 0;
}
return group->meth->bignum_to_felem(group, out, in);
return ec_felem_from_bytes(group, out, bytes, len);
}
int ec_felem_to_bignum(const EC_GROUP *group, BIGNUM *out, const EC_FELEM *in) {
return group->meth->felem_to_bignum(group, out, in);
uint8_t bytes[EC_MAX_BYTES];
size_t len;
ec_felem_to_bytes(group, bytes, &len, in);
return BN_bin2bn(bytes, len, out) != NULL;
}
void ec_felem_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len,
const EC_FELEM *in) {
group->meth->felem_to_bytes(group, out, out_len, in);
}
int ec_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out, const uint8_t *in,
size_t len) {
return group->meth->felem_from_bytes(group, out, in, len);
}
void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a) {
@@ -75,8 +95,6 @@ void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask,
int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a,
const EC_FELEM *b) {
// Note this function is variable-time. Constant-time operations should use
// |ec_felem_non_zero_mask|.
return OPENSSL_memcmp(a->words, b->words,
group->field.width * sizeof(BN_ULONG)) == 0;
return CRYPTO_memcmp(a->words, b->words,
group->field.width * sizeof(BN_ULONG)) == 0;
}
+434 -161
View File
@@ -71,8 +71,8 @@
#include <openssl/base.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ex_data.h>
#include <openssl/thread.h>
#include <openssl/type_check.h>
#include "../bn/internal.h"
@@ -82,6 +82,9 @@ extern "C" {
#endif
// EC internals.
// Cap the size of all field elements and scalars, including custom curves, to
// 66 bytes, large enough to fit secp521r1 and brainpoolP512r1, which appear to
// be the largest fields anyone plausibly uses.
@@ -91,6 +94,9 @@ extern "C" {
OPENSSL_STATIC_ASSERT(EC_MAX_WORDS <= BN_SMALL_MAX_WORDS,
"bn_*_small functions not usable");
// Scalars.
// An EC_SCALAR is an integer fully reduced modulo the order. Only the first
// |order->width| words are used. An |EC_SCALAR| is specific to an |EC_GROUP|
// and must not be mixed between groups.
@@ -100,6 +106,88 @@ typedef union {
BN_ULONG words[EC_MAX_WORDS];
} EC_SCALAR;
// ec_bignum_to_scalar converts |in| to an |EC_SCALAR| and writes it to
// |*out|. It returns one on success and zero if |in| is out of range.
OPENSSL_EXPORT int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
const BIGNUM *in);
// ec_scalar_to_bytes serializes |in| as a big-endian bytestring to |out| and
// sets |*out_len| to the number of bytes written. The number of bytes written
// is |BN_num_bytes(&group->order)|, which is at most |EC_MAX_BYTES|.
OPENSSL_EXPORT void ec_scalar_to_bytes(const EC_GROUP *group, uint8_t *out,
size_t *out_len, const EC_SCALAR *in);
// ec_scalar_from_bytes deserializes |in| and stores the resulting scalar over
// group |group| to |out|. It returns one on success and zero if |in| is
// invalid.
int ec_scalar_from_bytes(const EC_GROUP *group, EC_SCALAR *out,
const uint8_t *in, size_t len);
// ec_scalar_reduce sets |out| to |words|, reduced modulo the group order.
// |words| must be less than order^2. |num| must be at most twice the width of
// group order. This function treats |words| as secret.
void ec_scalar_reduce(const EC_GROUP *group, EC_SCALAR *out,
const BN_ULONG *words, size_t num);
// ec_random_nonzero_scalar sets |out| to a uniformly selected random value from
// 1 to |group->order| - 1. It returns one on success and zero on error.
int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out,
const uint8_t additional_data[32]);
// ec_scalar_equal_vartime returns one if |a| and |b| are equal and zero
// otherwise. Both values are treated as public.
int ec_scalar_equal_vartime(const EC_GROUP *group, const EC_SCALAR *a,
const EC_SCALAR *b);
// ec_scalar_is_zero returns one if |a| is zero and zero otherwise.
int ec_scalar_is_zero(const EC_GROUP *group, const EC_SCALAR *a);
// ec_scalar_add sets |r| to |a| + |b|.
void ec_scalar_add(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
const EC_SCALAR *b);
// ec_scalar_sub sets |r| to |a| - |b|.
void ec_scalar_sub(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
const EC_SCALAR *b);
// ec_scalar_neg sets |r| to -|a|.
void ec_scalar_neg(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a);
// ec_scalar_to_montgomery sets |r| to |a| in Montgomery form.
void ec_scalar_to_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_scalar_to_montgomery sets |r| to |a| converted from Montgomery form.
void ec_scalar_from_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_scalar_mul_montgomery sets |r| to |a| * |b| where inputs and outputs are
// in Montgomery form.
void ec_scalar_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a, const EC_SCALAR *b);
// ec_scalar_inv0_montgomery sets |r| to |a|^-1 where inputs and outputs are in
// Montgomery form. If |a| is zero, |r| is set to zero.
void ec_scalar_inv0_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_scalar_to_montgomery_inv_vartime sets |r| to |a|^-1 R. That is, it takes
// in |a| not in Montgomery form and computes the inverse in Montgomery form. It
// returns one on success and zero if |a| has no inverse. This function assumes
// |a| is public and may leak information about it via timing.
//
// Note this is not the same operation as |ec_scalar_inv0_montgomery|.
int ec_scalar_to_montgomery_inv_vartime(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_scalar_select, in constant time, sets |out| to |a| if |mask| is all ones
// and |b| if |mask| is all zeros.
void ec_scalar_select(const EC_GROUP *group, EC_SCALAR *out, BN_ULONG mask,
const EC_SCALAR *a, const EC_SCALAR *b);
// Field elements.
// An EC_FELEM represents a field element. Only the first |field->width| words
// are used. An |EC_FELEM| is specific to an |EC_GROUP| and must not be mixed
// between groups. Additionally, the representation (whether or not elements are
@@ -110,15 +198,268 @@ typedef union {
BN_ULONG words[EC_MAX_WORDS];
} EC_FELEM;
// An EC_RAW_POINT represents an elliptic curve point. Unlike |EC_POINT|, it is
// a plain struct which can be stack-allocated and needs no cleanup. It is
// specific to an |EC_GROUP| and must not be mixed between groups.
// ec_bignum_to_felem converts |in| to an |EC_FELEM|. It returns one on success
// and zero if |in| is out of range.
int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in);
// ec_felem_to_bignum converts |in| to a |BIGNUM|. It returns one on success and
// zero on allocation failure.
int ec_felem_to_bignum(const EC_GROUP *group, BIGNUM *out, const EC_FELEM *in);
// ec_felem_to_bytes serializes |in| as a big-endian bytestring to |out| and
// sets |*out_len| to the number of bytes written. The number of bytes written
// is |BN_num_bytes(&group->order)|, which is at most |EC_MAX_BYTES|.
void ec_felem_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len,
const EC_FELEM *in);
// ec_felem_from_bytes deserializes |in| and stores the resulting field element
// to |out|. It returns one on success and zero if |in| is invalid.
int ec_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out, const uint8_t *in,
size_t len);
// ec_felem_neg sets |out| to -|a|.
void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a);
// ec_felem_add sets |out| to |a| + |b|.
void ec_felem_add(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
const EC_FELEM *b);
// ec_felem_add sets |out| to |a| - |b|.
void ec_felem_sub(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
const EC_FELEM *b);
// ec_felem_non_zero_mask returns all ones if |a| is non-zero and all zeros
// otherwise.
BN_ULONG ec_felem_non_zero_mask(const EC_GROUP *group, const EC_FELEM *a);
// ec_felem_select, in constant time, sets |out| to |a| if |mask| is all ones
// and |b| if |mask| is all zeros.
void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask,
const EC_FELEM *a, const EC_FELEM *b);
// ec_felem_equal returns one if |a| and |b| are equal and zero otherwise.
int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a, const EC_FELEM *b);
// Points.
//
// Points may represented in affine coordinates as |EC_AFFINE| or Jacobian
// coordinates as |EC_RAW_POINT|. Affine coordinates directly represent a
// point on the curve, but point addition over affine coordinates requires
// costly field inversions, so arithmetic is done in Jacobian coordinates.
// Converting from affine to Jacobian is cheap, while converting from Jacobian
// to affine costs a field inversion. (Jacobian coordinates amortize the field
// inversions needed in a sequence of point operations.)
//
// TODO(davidben): Rename |EC_RAW_POINT| to |EC_JACOBIAN|.
// An EC_RAW_POINT represents an elliptic curve point in Jacobian coordinates.
// Unlike |EC_POINT|, it is a plain struct which can be stack-allocated and
// needs no cleanup. It is specific to an |EC_GROUP| and must not be mixed
// between groups.
typedef struct {
EC_FELEM X, Y, Z;
// X, Y, and Z are Jacobian projective coordinates. They represent
// (X/Z^2, Y/Z^3) if Z != 0 and the point at infinity otherwise.
EC_FELEM X, Y, Z;
} EC_RAW_POINT;
// An EC_AFFINE represents an elliptic curve point in affine coordinates.
// coordinates. Note the point at infinity cannot be represented in affine
// coordinates.
typedef struct {
EC_FELEM X, Y;
} EC_AFFINE;
// ec_affine_to_jacobian converts |p| to Jacobian form and writes the result to
// |*out|. This operation is very cheap and only costs a few copies.
void ec_affine_to_jacobian(const EC_GROUP *group, EC_RAW_POINT *out,
const EC_AFFINE *p);
// ec_jacobian_to_affine converts |p| to affine form and writes the result to
// |*out|. It returns one on success and zero if |p| was the point at infinity.
// This operation performs a field inversion and should only be done once per
// point.
//
// If only extracting the x-coordinate, use |ec_get_x_coordinate_*| which is
// slightly faster.
int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
const EC_RAW_POINT *p);
// ec_jacobian_to_affine_batch converts |num| points in |in| from Jacobian
// coordinates to affine coordinates and writes the results to |out|. It returns
// one on success and zero if any of the input points were infinity.
//
// This function is not implemented for all curves. Add implementations as
// needed.
int ec_jacobian_to_affine_batch(const EC_GROUP *group, EC_AFFINE *out,
const EC_RAW_POINT *in, size_t num);
// ec_point_set_affine_coordinates sets |out|'s to a point with affine
// coordinates |x| and |y|. It returns one if the point is on the curve and
// zero otherwise. If the point is not on the curve, the value of |out| is
// undefined.
int ec_point_set_affine_coordinates(const EC_GROUP *group, EC_AFFINE *out,
const EC_FELEM *x, const EC_FELEM *y);
// ec_point_mul_scalar sets |r| to |p| * |scalar|. Both inputs are considered
// secret.
int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p, const EC_SCALAR *scalar);
// ec_point_mul_scalar_base sets |r| to generator * |scalar|. |scalar| is
// treated as secret.
int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *scalar);
// ec_point_mul_scalar_batch sets |r| to |p0| * |scalar0| + |p1| * |scalar1| +
// |p2| * |scalar2|. |p2| may be NULL to skip that term.
//
// The inputs are treated as secret, however, this function leaks information
// about whether intermediate computations add a point to itself. Callers must
// ensure that discrete logs between |p0|, |p1|, and |p2| are uniformly
// distributed and independent of the scalars, which should be uniformly
// selected and not under the attackers control. This ensures the doubling case
// will occur with negligible probability.
//
// This function is not implemented for all curves. Add implementations as
// needed.
//
// TODO(davidben): This function does not use base point tables. For now, it is
// only used with the generic |EC_GFp_mont_method| implementation which has
// none. If generalizing to tuned curves, this may be useful. However, we still
// must double up to the least efficient input, so precomputed tables can only
// save table setup and allow a wider window size.
int ec_point_mul_scalar_batch(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
const EC_RAW_POINT *p2, const EC_SCALAR *scalar2);
#define EC_MONT_PRECOMP_COMB_SIZE 5
// An |EC_PRECOMP| stores precomputed information about a point, to optimize
// repeated multiplications involving it. It is a union so different
// |EC_METHOD|s can store different information in it.
typedef union {
EC_AFFINE comb[(1 << EC_MONT_PRECOMP_COMB_SIZE) - 1];
} EC_PRECOMP;
// ec_init_precomp precomputes multiples of |p| and writes the result to |out|.
// It returns one on success and zero on error. The resulting table may be used
// with |ec_point_mul_scalar_precomp|. This function will fail if |p| is the
// point at infinity.
//
// This function is not implemented for all curves. Add implementations as
// needed.
int ec_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
const EC_RAW_POINT *p);
// ec_point_mul_scalar_precomp sets |r| to |p0| * |scalar0| + |p1| * |scalar1| +
// |p2| * |scalar2|. |p1| or |p2| may be NULL to skip the corresponding term.
// The points are represented as |EC_PRECOMP| and must be initialized with
// |ec_init_precomp|. This function runs faster than |ec_point_mul_scalar_batch|
// but requires setup work per input point, so it is only appropriate for points
// which are used frequently.
//
// The inputs are treated as secret, however, this function leaks information
// about whether intermediate computations add a point to itself. Callers must
// ensure that discrete logs between |p0|, |p1|, and |p2| are uniformly
// distributed and independent of the scalars, which should be uniformly
// selected and not under the attackers control. This ensures the doubling case
// will occur with negligible probability.
//
// This function is not implemented for all curves. Add implementations as
// needed.
//
// TODO(davidben): This function does not use base point tables. For now, it is
// only used with the generic |EC_GFp_mont_method| implementation which has
// none. If generalizing to tuned curves, we should add a parameter for the base
// point and arrange for the generic implementation to have base point tables
// available.
int ec_point_mul_scalar_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
const EC_PRECOMP *p2, const EC_SCALAR *scalar2);
// ec_point_mul_scalar_public sets |r| to
// generator * |g_scalar| + |p| * |p_scalar|. It assumes that the inputs are
// public so there is no concern about leaking their values through timing.
OPENSSL_EXPORT int ec_point_mul_scalar_public(const EC_GROUP *group,
EC_RAW_POINT *r,
const EC_SCALAR *g_scalar,
const EC_RAW_POINT *p,
const EC_SCALAR *p_scalar);
// ec_point_mul_scalar_public_batch sets |r| to the sum of generator *
// |g_scalar| and |points[i]| * |scalars[i]| where |points| and |scalars| have
// |num| elements. It assumes that the inputs are public so there is no concern
// about leaking their values through timing. |g_scalar| may be NULL to skip
// that term.
//
// This function is not implemented for all curves. Add implementations as
// needed.
int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *g_scalar,
const EC_RAW_POINT *points,
const EC_SCALAR *scalars, size_t num);
// ec_point_select, in constant time, sets |out| to |a| if |mask| is all ones
// and |b| if |mask| is all zeros.
void ec_point_select(const EC_GROUP *group, EC_RAW_POINT *out, BN_ULONG mask,
const EC_RAW_POINT *a, const EC_RAW_POINT *b);
// ec_affine_select behaves like |ec_point_select| but acts on affine points.
void ec_affine_select(const EC_GROUP *group, EC_AFFINE *out, BN_ULONG mask,
const EC_AFFINE *a, const EC_AFFINE *b);
// ec_precomp_select behaves like |ec_point_select| but acts on |EC_PRECOMP|.
void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask,
const EC_PRECOMP *a, const EC_PRECOMP *b);
// ec_cmp_x_coordinate compares the x (affine) coordinate of |p|, mod the group
// order, with |r|. It returns one if the values match and zero if |p| is the
// point at infinity of the values do not match.
int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
const EC_SCALAR *r);
// ec_get_x_coordinate_as_scalar sets |*out| to |p|'s x-coordinate, modulo
// |group->order|. It returns one on success and zero if |p| is the point at
// infinity.
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
const EC_RAW_POINT *p);
// ec_get_x_coordinate_as_bytes writes |p|'s affine x-coordinate to |out|, which
// must have at must |max_out| bytes. It sets |*out_len| to the number of bytes
// written. The value is written big-endian and zero-padded to the size of the
// field. This function returns one on success and zero on failure.
int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out,
size_t *out_len, size_t max_out,
const EC_RAW_POINT *p);
// ec_point_to_bytes behaves like |EC_POINT_point2oct| but takes an
// |EC_AFFINE|.
size_t ec_point_to_bytes(const EC_GROUP *group, const EC_AFFINE *point,
point_conversion_form_t form, uint8_t *buf,
size_t len);
// ec_point_from_uncompressed parses |in| as a point in uncompressed form and
// sets the result to |out|. It returns one on success and zero if the input was
// invalid.
int ec_point_from_uncompressed(const EC_GROUP *group, EC_AFFINE *out,
const uint8_t *in, size_t len);
// ec_set_to_safe_point sets |out| to an arbitrary point on |group|, either the
// generator or the point at infinity. This is used to guard against callers of
// external APIs not checking the return value.
void ec_set_to_safe_point(const EC_GROUP *group, EC_RAW_POINT *out);
// ec_affine_jacobian_equal returns one if |a| and |b| represent the same point
// and zero otherwise. It treats both inputs as secret.
int ec_affine_jacobian_equal(const EC_GROUP *group, const EC_AFFINE *a,
const EC_RAW_POINT *b);
// Implementation details.
struct ec_method_st {
int (*group_init)(EC_GROUP *);
void (*group_finish)(EC_GROUP *);
@@ -128,12 +469,13 @@ struct ec_method_st {
// point_get_affine_coordinates sets |*x| and |*y| to the affine coordinates
// of |p|. Either |x| or |y| may be NULL to omit it. It returns one on success
// and zero if |p| is the point at infinity.
//
// Note: unlike |EC_FELEM|s used as intermediate values internal to the
// |EC_METHOD|, |*x| and |*y| are not encoded in Montgomery form.
int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_RAW_POINT *p,
EC_FELEM *x, EC_FELEM *y);
// jacobian_to_affine_batch implements |ec_jacobian_to_affine_batch|.
int (*jacobian_to_affine_batch)(const EC_GROUP *group, EC_AFFINE *out,
const EC_RAW_POINT *in, size_t num);
// add sets |r| to |a| + |b|.
void (*add)(const EC_GROUP *group, EC_RAW_POINT *r, const EC_RAW_POINT *a,
const EC_RAW_POINT *b);
@@ -146,12 +488,32 @@ struct ec_method_st {
// mul_base sets |r| to |scalar|*generator.
void (*mul_base)(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *scalar);
// mul_batch implements |ec_mul_scalar_batch|.
void (*mul_batch)(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
const EC_RAW_POINT *p2, const EC_SCALAR *scalar2);
// mul_public sets |r| to |g_scalar|*generator + |p_scalar|*|p|. It assumes
// that the inputs are public so there is no concern about leaking their
// values through timing.
//
// This function may be omitted if |mul_public_batch| is provided.
void (*mul_public)(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
const EC_SCALAR *p_scalar);
// mul_public_batch implements |ec_point_mul_scalar_public_batch|.
int (*mul_public_batch)(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *g_scalar, const EC_RAW_POINT *points,
const EC_SCALAR *scalars, size_t num);
// init_precomp implements |ec_init_precomp|.
int (*init_precomp)(const EC_GROUP *group, EC_PRECOMP *out,
const EC_RAW_POINT *p);
// mul_precomp implements |ec_point_mul_scalar_precomp|.
void (*mul_precomp)(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
const EC_PRECOMP *p2, const EC_SCALAR *scalar2);
// felem_mul and felem_sqr implement multiplication and squaring,
// respectively, so that the generic |EC_POINT_add| and |EC_POINT_dbl|
@@ -168,21 +530,36 @@ struct ec_method_st {
const EC_FELEM *b);
void (*felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a);
int (*bignum_to_felem)(const EC_GROUP *group, EC_FELEM *out,
const BIGNUM *in);
int (*felem_to_bignum)(const EC_GROUP *group, BIGNUM *out,
void (*felem_to_bytes)(const EC_GROUP *group, uint8_t *out, size_t *out_len,
const EC_FELEM *in);
int (*felem_from_bytes)(const EC_GROUP *group, EC_FELEM *out,
const uint8_t *in, size_t len);
// scalar_inv_montgomery sets |out| to |in|^-1, where both input and output
// are in Montgomery form.
void (*scalar_inv_montgomery)(const EC_GROUP *group, EC_SCALAR *out,
const EC_SCALAR *in);
// felem_reduce sets |out| to |words|, reduced modulo the field size, p.
// |words| must be less than p^2. |num| must be at most twice the width of p.
// This function treats |words| as secret.
//
// This function is only used in hash-to-curve and may be omitted in curves
// that do not support it.
void (*felem_reduce)(const EC_GROUP *group, EC_FELEM *out,
const BN_ULONG *words, size_t num);
// scalar_inv_montgomery_vartime performs the same computation as
// |scalar_inv_montgomery|. It further assumes that the inputs are public so
// there is no concern about leaking their values through timing.
int (*scalar_inv_montgomery_vartime)(const EC_GROUP *group, EC_SCALAR *out,
const EC_SCALAR *in);
// felem_exp sets |out| to |a|^|exp|. It treats |a| is secret but |exp| as
// public.
//
// This function is used in hash-to-curve and may be NULL in curves not used
// with hash-to-curve.
void (*felem_exp)(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
const BN_ULONG *exp, size_t num_exp);
// scalar_inv0_montgomery implements |ec_scalar_inv0_montgomery|.
void (*scalar_inv0_montgomery)(const EC_GROUP *group, EC_SCALAR *out,
const EC_SCALAR *in);
// scalar_to_montgomery_inv_vartime implements
// |ec_scalar_to_montgomery_inv_vartime|.
int (*scalar_to_montgomery_inv_vartime)(const EC_GROUP *group, EC_SCALAR *out,
const EC_SCALAR *in);
// cmp_x_coordinate compares the x (affine) coordinate of |p|, mod the group
// order, with |r|. It returns one if the values match and zero if |p| is the
@@ -197,7 +574,8 @@ struct ec_group_st {
const EC_METHOD *meth;
// Unlike all other |EC_POINT|s, |generator| does not own |generator->group|
// to avoid a reference cycle.
// to avoid a reference cycle. Additionally, Z is guaranteed to be one, so X
// and Y are suitable for use as an |EC_AFFINE|.
EC_POINT *generator;
BIGNUM order;
@@ -247,133 +625,20 @@ struct ec_point_st {
EC_GROUP *ec_group_new(const EC_METHOD *meth);
// ec_bignum_to_felem converts |in| to an |EC_FELEM|. It returns one on success
// and zero if |in| is out of range.
int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in);
// ec_felem_to_bignum converts |in| to a |BIGNUM|. It returns one on success and
// zero on allocation failure.
int ec_felem_to_bignum(const EC_GROUP *group, BIGNUM *out, const EC_FELEM *in);
// ec_felem_neg sets |out| to -|a|.
void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a);
// ec_felem_add sets |out| to |a| + |b|.
void ec_felem_add(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
const EC_FELEM *b);
// ec_felem_add sets |out| to |a| - |b|.
void ec_felem_sub(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
const EC_FELEM *b);
// ec_felem_non_zero_mask returns all ones if |a| is non-zero and all zeros
// otherwise.
BN_ULONG ec_felem_non_zero_mask(const EC_GROUP *group, const EC_FELEM *a);
// ec_felem_select, in constant time, sets |out| to |a| if |mask| is all ones
// and |b| if |mask| is all zeros.
void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask,
const EC_FELEM *a, const EC_FELEM *b);
// ec_felem_equal returns one if |a| and |b| are equal and zero otherwise. It
// treats |a| and |b| as public and does *not* run in constant time.
int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a, const EC_FELEM *b);
// ec_bignum_to_scalar converts |in| to an |EC_SCALAR| and writes it to
// |*out|. It returns one on success and zero if |in| is out of range.
OPENSSL_EXPORT int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
const BIGNUM *in);
// ec_random_nonzero_scalar sets |out| to a uniformly selected random value from
// 1 to |group->order| - 1. It returns one on success and zero on error.
int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out,
const uint8_t additional_data[32]);
// ec_scalar_equal_vartime returns one if |a| and |b| are equal and zero
// otherwise. Both values are treated as public.
int ec_scalar_equal_vartime(const EC_GROUP *group, const EC_SCALAR *a,
const EC_SCALAR *b);
// ec_scalar_is_zero returns one if |a| is zero and zero otherwise.
int ec_scalar_is_zero(const EC_GROUP *group, const EC_SCALAR *a);
// ec_scalar_add sets |r| to |a| + |b|.
void ec_scalar_add(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
const EC_SCALAR *b);
// ec_scalar_to_montgomery sets |r| to |a| in Montgomery form.
void ec_scalar_to_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_scalar_to_montgomery sets |r| to |a| converted from Montgomery form.
void ec_scalar_from_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_scalar_mul_montgomery sets |r| to |a| * |b| where inputs and outputs are
// in Montgomery form.
void ec_scalar_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a, const EC_SCALAR *b);
// ec_scalar_mul_montgomery sets |r| to |a|^-1 where inputs and outputs are in
// Montgomery form.
void ec_scalar_inv_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_scalar_inv_montgomery_vartime performs the same actions as
// |ec_scalar_inv_montgomery|, but in variable time.
int ec_scalar_inv_montgomery_vartime(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
// ec_point_mul_scalar sets |r| to |p| * |scalar|. Both inputs are considered
// secret.
int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p, const EC_SCALAR *scalar);
// ec_point_mul_scalar_base sets |r| to generator * |scalar|. |scalar| is
// treated as secret.
int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *scalar);
// ec_point_mul_scalar_public performs the same computation as
// ec_point_mul_scalar. It further assumes that the inputs are public so
// there is no concern about leaking their values through timing.
OPENSSL_EXPORT int ec_point_mul_scalar_public(const EC_GROUP *group,
EC_RAW_POINT *r,
const EC_SCALAR *g_scalar,
const EC_RAW_POINT *p,
const EC_SCALAR *p_scalar);
// ec_cmp_x_coordinate compares the x (affine) coordinate of |p|, mod the group
// order, with |r|. It returns one if the values match and zero if |p| is the
// point at infinity of the values do not match.
int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
const EC_SCALAR *r);
// ec_get_x_coordinate_as_scalar sets |*out| to |p|'s x-coordinate, modulo
// |group->order|. It returns one on success and zero if |p| is the point at
// infinity.
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
const EC_RAW_POINT *p);
// ec_point_get_affine_coordinate_bytes writes |p|'s affine coordinates to
// |out_x| and |out_y|, each of which must have at must |max_out| bytes. It sets
// |*out_len| to the number of bytes written in each buffer. Coordinates are
// written big-endian and zero-padded to the size of the field.
//
// Either of |out_x| or |out_y| may be NULL to omit that coordinate. This
// function returns one on success and zero on failure.
int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
uint8_t *out_y, size_t *out_len,
size_t max_out, const EC_RAW_POINT *p);
// ec_field_element_to_scalar reduces |r| modulo |group->order|. |r| must
// previously have been reduced modulo |group->field|.
int ec_field_element_to_scalar(const EC_GROUP *group, BIGNUM *r);
void ec_GFp_mont_mul(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p, const EC_SCALAR *scalar);
void ec_GFp_mont_mul_base(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *scalar);
void ec_GFp_mont_mul_batch(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
const EC_RAW_POINT *p2, const EC_SCALAR *scalar2);
int ec_GFp_mont_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
const EC_RAW_POINT *p);
void ec_GFp_mont_mul_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
const EC_PRECOMP *p2, const EC_SCALAR *scalar2);
// ec_compute_wNAF writes the modified width-(w+1) Non-Adjacent Form (wNAF) of
// |scalar| to |out|. |out| must have room for |bits| + 1 elements, each of
@@ -386,9 +651,10 @@ void ec_GFp_mont_mul_base(const EC_GROUP *group, EC_RAW_POINT *r,
void ec_compute_wNAF(const EC_GROUP *group, int8_t *out,
const EC_SCALAR *scalar, size_t bits, int w);
void ec_GFp_mont_mul_public(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
const EC_SCALAR *p_scalar);
int ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
const EC_SCALAR *g_scalar,
const EC_RAW_POINT *points,
const EC_SCALAR *scalars, size_t num);
// method functions in simple.c
int ec_GFp_simple_group_init(EC_GROUP *);
@@ -400,26 +666,29 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
void ec_GFp_simple_point_init(EC_RAW_POINT *);
void ec_GFp_simple_point_copy(EC_RAW_POINT *, const EC_RAW_POINT *);
void ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_RAW_POINT *);
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_RAW_POINT *,
const BIGNUM *x,
const BIGNUM *y);
void ec_GFp_mont_add(const EC_GROUP *, EC_RAW_POINT *r, const EC_RAW_POINT *a,
const EC_RAW_POINT *b);
void ec_GFp_mont_dbl(const EC_GROUP *, EC_RAW_POINT *r, const EC_RAW_POINT *a);
void ec_GFp_simple_invert(const EC_GROUP *, EC_RAW_POINT *);
int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_RAW_POINT *);
int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_RAW_POINT *);
int ec_GFp_simple_cmp(const EC_GROUP *, const EC_RAW_POINT *a,
const EC_RAW_POINT *b);
void ec_simple_scalar_inv_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
int ec_GFp_simple_points_equal(const EC_GROUP *, const EC_RAW_POINT *a,
const EC_RAW_POINT *b);
void ec_simple_scalar_inv0_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
int ec_GFp_simple_mont_inv_mod_ord_vartime(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a);
int ec_simple_scalar_to_montgomery_inv_vartime(const EC_GROUP *group,
EC_SCALAR *r,
const EC_SCALAR *a);
int ec_GFp_simple_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
const EC_SCALAR *r);
void ec_GFp_simple_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
size_t *out_len, const EC_FELEM *in);
int ec_GFp_simple_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out,
const uint8_t *in, size_t len);
// method functions in montgomery.c
int ec_GFp_mont_group_init(EC_GROUP *);
int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
@@ -429,12 +698,13 @@ void ec_GFp_mont_felem_mul(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
const EC_FELEM *b);
void ec_GFp_mont_felem_sqr(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a);
int ec_GFp_mont_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out,
const BIGNUM *in);
int ec_GFp_mont_felem_to_bignum(const EC_GROUP *group, BIGNUM *out,
const EC_FELEM *in);
void ec_GFp_mont_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
size_t *out_len, const EC_FELEM *in);
int ec_GFp_mont_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out,
const uint8_t *in, size_t len);
void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in);
void ec_GFp_nistp_recode_scalar_bits(crypto_word_t *sign, crypto_word_t *digit,
crypto_word_t in);
const EC_METHOD *EC_GFp_nistp224_method(void);
const EC_METHOD *EC_GFp_nistp256_method(void);
@@ -453,6 +723,9 @@ typedef struct {
struct ec_key_st {
EC_GROUP *group;
// Ideally |pub_key| would be an |EC_AFFINE| so serializing it does not pay an
// inversion each time, but the |EC_KEY_get0_public_key| API implies public
// keys are stored in an |EC_POINT|-compatible form.
EC_POINT *pub_key;
EC_WRAPPED_SCALAR *priv_key;
@@ -1,130 +0,0 @@
/* Copyright (c) 2018, 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 (
"crypto/elliptic"
"fmt"
"math/big"
"os"
)
const fileHeader = `/* Copyright (c) 2015, Intel 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 is the precomputed constant time access table for the code in
// p256-x86_64.c, for the default generator. The table consists of 37
// subtables, each subtable contains 64 affine points. The affine points are
// encoded as eight uint64's, four for the x coordinate and four for the y.
// Both values are in little-endian order. There are 37 tables because a
// signed, 6-bit wNAF form of the scalar is used and ceil(256/(6 + 1)) = 37.
// Within each table there are 64 values because the 6-bit wNAF value can take
// 64 values, ignoring the sign bit, which is implemented by performing a
// negation of the affine point when required. We would like to align it to 2MB
// in order to increase the chances of using a large page but that appears to
// lead to invalid ELF files being produced.
// This file is generated by make_p256-x86_64-table.go.
static const alignas(4096) PRECOMP256_ROW ecp_nistz256_precomputed[37] = {
`
func main() {
os.Stdout.WriteString(fileHeader)
scalar, tmp := new(big.Int), new(big.Int)
p256 := elliptic.P256()
p := p256.Params().P
// The wNAF windows are 7 bits wide, so advance across the 256-bit scalar
// space in 7-bit increments.
for shift := uint(0); shift < 256; shift += 7 {
// For each window, encode 64 multiples of the base point.
for multiple := 1; multiple <= 64; multiple++ {
scalar.SetInt64(int64(multiple))
scalar.Lsh(scalar, shift)
x, y := p256.ScalarBaseMult(scalar.Bytes())
toMontgomery(x, p)
toMontgomery(y, p)
if multiple == 1 {
os.Stdout.WriteString(" {{")
} else {
os.Stdout.WriteString(" {")
}
printNum(x, tmp)
os.Stdout.WriteString(",\n ")
printNum(y, tmp)
if multiple == 64 {
os.Stdout.WriteString("}}")
} else {
os.Stdout.WriteString("},\n")
}
}
if shift+7 < 256 {
os.Stdout.WriteString(",\n")
} else {
os.Stdout.WriteString("};\n")
}
}
}
var mask, R *big.Int
func init() {
mask = new(big.Int).SetUint64(0xffffffffffffffff)
R = new(big.Int).SetInt64(1)
R.Lsh(R, 256)
}
func printNum(n, tmp *big.Int) {
fmt.Printf("{")
for i := 0; i < 4; i++ {
tmp.And(n, mask)
limb := tmp.Uint64()
fmt.Printf("TOBN(0x%08x, 0x%08x)", uint32(limb>>32), uint32(limb))
n.Rsh(n, 64)
switch i {
case 0, 2:
os.Stdout.WriteString(", ")
case 1:
os.Stdout.WriteString(",\n ")
}
}
fmt.Printf("}")
}
// toMontgomery sets n to be n×R mod p
func toMontgomery(n, p *big.Int) {
n.Mul(n, R)
n.Mod(n, p)
}
+406
View File
@@ -0,0 +1,406 @@
/* Copyright (c) 2020, 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 (
"crypto/elliptic"
"fmt"
"io"
"math/big"
"os"
)
func main() {
if err := writeP256X86_64Table("p256-x86_64-table.h"); err != nil {
fmt.Fprintf(os.Stderr, "Error writing p256-x86_64-table.h: %s\n", err)
os.Exit(1)
}
if err := writeP256Table("p256_table.h"); err != nil {
fmt.Fprintf(os.Stderr, "Error writing p256_table.h: %s\n", err)
os.Exit(1)
}
}
func writeP256X86_64Table(path string) error {
curve := elliptic.P256()
tables := make([][][2]*big.Int, 0, 37)
for shift := 0; shift < 256; shift += 7 {
row := makeMultiples(curve, 64, shift)
tables = append(tables, row)
}
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
const fileHeader = `/*
* Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2015, Intel Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
// This is the precomputed constant time access table for the code in
// p256-x86_64.c, for the default generator. The table consists of 37
// subtables, each subtable contains 64 affine points. The affine points are
// encoded as eight uint64's, four for the x coordinate and four for the y.
// Both values are in little-endian order. There are 37 tables because a
// signed, 6-bit wNAF form of the scalar is used and ceil(256/(6 + 1)) = 37.
// Within each table there are 64 values because the 6-bit wNAF value can take
// 64 values, ignoring the sign bit, which is implemented by performing a
// negation of the affine point when required. We would like to align it to 2MB
// in order to increase the chances of using a large page but that appears to
// lead to invalid ELF files being produced.
// This file is generated by make_tables.go.
static const alignas(4096) PRECOMP256_ROW ecp_nistz256_precomputed[37] = `
if _, err := f.WriteString(fileHeader); err != nil {
return err
}
if err := writeTables(f, curve, tables, true, 4, writeBNMont); err != nil {
return err
}
if _, err := f.WriteString(";\n"); err != nil {
return err
}
return nil
}
func writeP256Table(path string) error {
curve := elliptic.P256()
tables := [][][2]*big.Int{
makeComb(curve, 64, 4, 0),
makeComb(curve, 64, 4, 32),
}
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
const fileHeader = `/* Copyright (c) 2020, 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 is generated by make_tables.go.
// Base point pre computation
// --------------------------
//
// Two different sorts of precomputed tables are used in the following code.
// Each contain various points on the curve, where each point is three field
// elements (x, y, z).
//
// For the base point table, z is usually 1 (0 for the point at infinity).
// This table has 2 * 16 elements, starting with the following:
// index | bits | point
// ------+---------+------------------------------
// 0 | 0 0 0 0 | 0G
// 1 | 0 0 0 1 | 1G
// 2 | 0 0 1 0 | 2^64G
// 3 | 0 0 1 1 | (2^64 + 1)G
// 4 | 0 1 0 0 | 2^128G
// 5 | 0 1 0 1 | (2^128 + 1)G
// 6 | 0 1 1 0 | (2^128 + 2^64)G
// 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G
// 8 | 1 0 0 0 | 2^192G
// 9 | 1 0 0 1 | (2^192 + 1)G
// 10 | 1 0 1 0 | (2^192 + 2^64)G
// 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G
// 12 | 1 1 0 0 | (2^192 + 2^128)G
// 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G
// 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G
// 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G
// followed by a copy of this with each element multiplied by 2^32.
//
// The reason for this is so that we can clock bits into four different
// locations when doing simple scalar multiplies against the base point,
// and then another four locations using the second 16 elements.
//
// Tables for other points have table[i] = iG for i in 0 .. 16.
// fiat_p256_g_pre_comp is the table of precomputed base points
#if defined(BORINGSSL_NISTP256_64BIT)
static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = `
if _, err := f.WriteString(fileHeader); err != nil {
return err
}
if err := writeTables(f, curve, tables, true, 4, writeU64Mont); err != nil {
return err
}
if _, err := f.WriteString(";\n#else\nstatic const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = "); err != nil {
return err
}
if err := writeTables(f, curve, tables, true, 4, writeU32Mont); err != nil {
return err
}
if _, err := f.WriteString(";\n#endif\n"); err != nil {
return err
}
return nil
}
// makeMultiples returns a table of the first n multiples of 2^shift * G,
// starting from 1 * 2^shift * G.
func makeMultiples(curve elliptic.Curve, n, shift int) [][2]*big.Int {
ret := make([][2]*big.Int, n)
x, y := curve.Params().Gx, curve.Params().Gy
for j := 0; j < shift; j++ {
x, y = curve.Double(x, y)
}
ret[1-1] = [2]*big.Int{x, y}
for i := 2; i <= n; i++ {
if i&1 == 0 {
x, y := curve.Double(ret[i/2-1][0], ret[i/2-1][1])
ret[i-1] = [2]*big.Int{x, y}
} else {
x, y := curve.Add(ret[i-1-1][0], ret[i-1-1][1], ret[1-1][0], ret[1-1][1])
ret[i-1] = [2]*big.Int{x, y}
}
}
return ret
}
// makeComb returns a table of 2^size - 1 points. The i-1th entry is k*G.
// If i is represented in binary by b0*2^0 + b1*2^1 + ... bn*2^n, k is
// b0*2^(shift + 0*stride) + b1*2^(shift + 1*stride) + ... + bn*2^(shift + n*stride).
// The entry for i = 0 is omitted because it is always the point at infinity.
func makeComb(curve elliptic.Curve, stride, size, shift int) [][2]*big.Int {
ret := make([][2]*big.Int, 1<<size-1)
x, y := curve.Params().Gx, curve.Params().Gy
for j := 0; j < shift; j++ {
x, y = curve.Double(x, y)
}
ret[1<<0-1] = [2]*big.Int{x, y}
for i := 1; i < size; i++ {
// Entry 2^i is entry 2^(i-1) doubled stride times.
x, y = ret[1<<(i-1)-1][0], ret[1<<(i-1)-1][1]
for j := 0; j < stride; j++ {
x, y = curve.Double(x, y)
}
ret[1<<i-1] = [2]*big.Int{x, y}
// The remaining entries with MSB 2^i are computed by adding entry 2^i
// to the corresponding previous entry.
for j := 1; j < 1<<i; j++ {
x, y = curve.Add(ret[1<<i-1][0], ret[1<<i-1][1], ret[j-1][0], ret[j-1][1])
ret[1<<i+j-1] = [2]*big.Int{x, y}
}
}
return ret
}
// toMontgomery sets n to be n×R mod p, where R is the Montgomery factor.
func toMontgomery(curve elliptic.Curve, n *big.Int) *big.Int {
params := curve.Params()
// R is the bit width of p, rounded up to word size.
rounded64 := 64 * ((params.BitSize + 63) / 64)
rounded32 := 32 * ((params.BitSize + 31) / 32)
if rounded64 != rounded32 {
panic(fmt.Sprintf("Montgomery form for %s is inconsistent between 32-bit and 64-bit", params.Name))
}
R := new(big.Int).SetInt64(1)
R.Lsh(R, uint(rounded64))
ret := new(big.Int).Mul(n, R)
ret.Mod(ret, params.P)
return ret
}
func bigIntToU64s(curve elliptic.Curve, n *big.Int) []uint64 {
words := (curve.Params().BitSize + 63) / 64
ret := make([]uint64, words)
bytes := n.Bytes()
for i, b := range bytes {
i = len(bytes) - i - 1
ret[i/8] |= uint64(b) << (8 * (i % 8))
}
return ret
}
func bigIntToU32s(curve elliptic.Curve, n *big.Int) []uint64 {
words := (curve.Params().BitSize + 31) / 32
ret := make([]uint64, words)
bytes := n.Bytes()
for i, b := range bytes {
i = len(bytes) - i - 1
ret[i/4] |= uint64(b) << (8 * (i % 4))
}
return ret
}
func writeIndent(w io.Writer, indent int) error {
for i := 0; i < indent; i++ {
if _, err := io.WriteString(w, " "); err != nil {
return err
}
}
return nil
}
func writeWords(w io.Writer, words []uint64, wrap, indent int, format func(uint64) string) error {
if _, err := io.WriteString(w, "{"); err != nil {
return err
}
for i, word := range words {
if i > 0 {
if i%wrap == 0 {
if _, err := io.WriteString(w, ",\n"); err != nil {
return err
}
if err := writeIndent(w, indent+1); err != nil {
return err
}
} else {
if _, err := io.WriteString(w, ", "); err != nil {
return err
}
}
}
if _, err := io.WriteString(w, format(word)); err != nil {
return err
}
}
if _, err := io.WriteString(w, "}"); err != nil {
return err
}
return nil
}
func writeBNMont(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error {
n = toMontgomery(curve, n)
return writeWords(w, bigIntToU64s(curve, n), 2, indent, func(word uint64) string {
return fmt.Sprintf("TOBN(0x%08x, 0x%08x)", uint32(word>>32), uint32(word))
})
}
func writeU64Mont(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error {
n = toMontgomery(curve, n)
return writeWords(w, bigIntToU64s(curve, n), 3, indent, func(word uint64) string {
return fmt.Sprintf("0x%016x", word)
})
}
func writeU32Mont(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error {
n = toMontgomery(curve, n)
return writeWords(w, bigIntToU32s(curve, n), 6, indent, func(word uint64) string {
if word >= 1<<32 {
panic(fmt.Sprintf("word too large: 0x%x", word))
}
return fmt.Sprintf("0x%08x", word)
})
}
type writeBigIntFunc func(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error
func writeTable(w io.Writer, curve elliptic.Curve, table [][2]*big.Int, isRoot bool, indent int, writeBigInt writeBigIntFunc) error {
if _, err := io.WriteString(w, "{"); err != nil {
return err
}
if isRoot {
if _, err := io.WriteString(w, "\n"); err != nil {
return err
}
if err := writeIndent(w, indent); err != nil {
return err
}
} else {
indent++
}
for i, point := range table {
if i != 0 {
if _, err := io.WriteString(w, ",\n"); err != nil {
return err
}
if err := writeIndent(w, indent); err != nil {
return err
}
}
if _, err := io.WriteString(w, "{"); err != nil {
return err
}
if err := writeBigInt(w, curve, point[0], indent+1); err != nil {
return err
}
if _, err := io.WriteString(w, ",\n"); err != nil {
return err
}
if err := writeIndent(w, indent+1); err != nil {
return err
}
if err := writeBigInt(w, curve, point[1], indent+1); err != nil {
return err
}
if _, err := io.WriteString(w, "}"); err != nil {
return err
}
}
if _, err := io.WriteString(w, "}"); err != nil {
return err
}
return nil
}
func writeTables(w io.Writer, curve elliptic.Curve, tables [][][2]*big.Int, isRoot bool, indent int, writeBigInt writeBigIntFunc) error {
if _, err := io.WriteString(w, "{"); err != nil {
return err
}
if isRoot {
if _, err := io.WriteString(w, "\n"); err != nil {
return err
}
if err := writeIndent(w, indent); err != nil {
return err
}
} else {
indent++
}
for i, table := range tables {
if i != 0 {
if _, err := io.WriteString(w, ",\n"); err != nil {
return err
}
if err := writeIndent(w, indent); err != nil {
return err
}
}
if err := writeTable(w, curve, table, false, indent, writeBigInt); err != nil {
return err
}
}
if _, err := io.WriteString(w, "}"); err != nil {
return err
}
return nil
}
+63 -71
View File
@@ -73,21 +73,15 @@
#include "internal.h"
static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
const EC_RAW_POINT *point,
point_conversion_form_t form,
uint8_t *buf, size_t len) {
size_t ec_point_to_bytes(const EC_GROUP *group, const EC_AFFINE *point,
point_conversion_form_t form, uint8_t *buf,
size_t len) {
if (form != POINT_CONVERSION_COMPRESSED &&
form != POINT_CONVERSION_UNCOMPRESSED) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
return 0;
}
if (ec_GFp_simple_is_at_infinity(group, point)) {
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
return 0;
}
const size_t field_len = BN_num_bytes(&group->field);
size_t output_len = 1 /* type byte */ + field_len;
if (form == POINT_CONVERSION_UNCOMPRESSED) {
@@ -102,79 +96,89 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
return 0;
}
uint8_t y_buf[EC_MAX_BYTES];
size_t field_len_out;
if (!ec_point_get_affine_coordinate_bytes(
group, buf + 1 /* x */,
form == POINT_CONVERSION_COMPRESSED ? y_buf : buf + 1 + field_len,
&field_len_out, field_len, point)) {
return 0;
}
ec_felem_to_bytes(group, buf + 1, &field_len_out, &point->X);
assert(field_len_out == field_len);
if (field_len_out != field_len) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
return 0;
}
if (form == POINT_CONVERSION_COMPRESSED) {
buf[0] = form + (y_buf[field_len - 1] & 1);
} else {
if (form == POINT_CONVERSION_UNCOMPRESSED) {
ec_felem_to_bytes(group, buf + 1 + field_len, &field_len_out, &point->Y);
assert(field_len_out == field_len);
buf[0] = form;
} else {
uint8_t y_buf[EC_MAX_BYTES];
ec_felem_to_bytes(group, y_buf, &field_len_out, &point->Y);
buf[0] = form + (y_buf[field_len_out - 1] & 1);
}
}
return output_len;
}
int ec_point_from_uncompressed(const EC_GROUP *group, EC_AFFINE *out,
const uint8_t *in, size_t len) {
const size_t field_len = BN_num_bytes(&group->field);
if (len != 1 + 2 * field_len || in[0] != POINT_CONVERSION_UNCOMPRESSED) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
return 0;
}
EC_FELEM x, y;
if (!ec_felem_from_bytes(group, &x, in + 1, field_len) ||
!ec_felem_from_bytes(group, &y, in + 1 + field_len, field_len) ||
!ec_point_set_affine_coordinates(group, out, &x, &y)) {
return 0;
}
return 1;
}
static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
const uint8_t *buf, size_t len,
BN_CTX *ctx) {
BN_CTX *new_ctx = NULL;
int ret = 0, used_ctx = 0;
if (len == 0) {
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
goto err;
return 0;
}
point_conversion_form_t form = buf[0];
const int y_bit = form & 1;
form = form & ~1U;
if ((form != POINT_CONVERSION_COMPRESSED &&
form != POINT_CONVERSION_UNCOMPRESSED) ||
(form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
goto err;
}
const size_t field_len = BN_num_bytes(&group->field);
size_t enc_len = 1 /* type byte */ + field_len;
if (form == POINT_CONVERSION_UNCOMPRESSED) {
// Uncompressed points have a second coordinate.
enc_len += field_len;
EC_AFFINE affine;
if (!ec_point_from_uncompressed(group, &affine, buf, len)) {
// In the event of an error, defend against the caller not checking the
// return value by setting a known safe value.
ec_set_to_safe_point(group, &point->raw);
return 0;
}
ec_affine_to_jacobian(group, &point->raw, &affine);
return 1;
}
if (len != enc_len) {
const int y_bit = form & 1;
const size_t field_len = BN_num_bytes(&group->field);
form = form & ~1u;
if (form != POINT_CONVERSION_COMPRESSED ||
len != 1 /* type byte */ + field_len) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
goto err;
return 0;
}
// TODO(davidben): Integrate compressed coordinates with the lower-level EC
// abstractions. This requires a way to compute square roots, which is tricky
// for primes which are not 3 (mod 4), namely P-224 and custom curves. P-224's
// prime is particularly inconvenient for compressed coordinates. See
// https://cr.yp.to/papers/sqroot.pdf
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
goto err;
return 0;
}
}
int ret = 0;
BN_CTX_start(ctx);
used_ctx = 1;
BIGNUM *x = BN_CTX_get(ctx);
BIGNUM *y = BN_CTX_get(ctx);
if (x == NULL || y == NULL) {
goto err;
}
if (!BN_bin2bn(buf + 1, field_len, x)) {
if (x == NULL || !BN_bin2bn(buf + 1, field_len, x)) {
goto err;
}
if (BN_ucmp(x, &group->field) >= 0) {
@@ -182,30 +186,14 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
goto err;
}
if (form == POINT_CONVERSION_COMPRESSED) {
if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) {
goto err;
}
} else {
if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) {
goto err;
}
if (BN_ucmp(y, &group->field) >= 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
goto err;
}
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
goto err;
}
if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) {
goto err;
}
ret = 1;
err:
if (used_ctx) {
BN_CTX_end(ctx);
}
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
@@ -226,7 +214,11 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return ec_GFp_simple_point2oct(group, &point->raw, form, buf, len);
EC_AFFINE affine;
if (!ec_jacobian_to_affine(group, &affine, &point->raw)) {
return 0;
}
return ec_point_to_bytes(group, &affine, form, buf, len);
}
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
+18 -25
View File
@@ -866,7 +866,7 @@ static void p224_select_point(const uint64_t idx, size_t size,
}
// p224_get_bit returns the |i|th bit in |in|
static char p224_get_bit(const p224_felem_bytearray in, size_t i) {
static crypto_word_t p224_get_bit(const p224_felem_bytearray in, size_t i) {
if (i >= 224) {
return 0;
}
@@ -977,13 +977,13 @@ static void ec_GFp_nistp224_point_mul(const EC_GROUP *group, EC_RAW_POINT *r,
// Add every 5 doublings.
if (i % 5 == 0) {
uint64_t bits = p224_get_bit(scalar->bytes, i + 4) << 5;
crypto_word_t bits = p224_get_bit(scalar->bytes, i + 4) << 5;
bits |= p224_get_bit(scalar->bytes, i + 3) << 4;
bits |= p224_get_bit(scalar->bytes, i + 2) << 3;
bits |= p224_get_bit(scalar->bytes, i + 1) << 2;
bits |= p224_get_bit(scalar->bytes, i) << 1;
bits |= p224_get_bit(scalar->bytes, i - 1);
uint8_t sign, digit;
crypto_word_t sign, digit;
ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
// Select the point to add or subtract.
@@ -1022,7 +1022,7 @@ static void ec_GFp_nistp224_point_mul_base(const EC_GROUP *group,
}
// First, look 28 bits upwards.
uint64_t bits = p224_get_bit(scalar->bytes, i + 196) << 3;
crypto_word_t bits = p224_get_bit(scalar->bytes, i + 196) << 3;
bits |= p224_get_bit(scalar->bytes, i + 140) << 2;
bits |= p224_get_bit(scalar->bytes, i + 84) << 1;
bits |= p224_get_bit(scalar->bytes, i + 28);
@@ -1080,14 +1080,15 @@ static void ec_GFp_nistp224_point_mul_public(const EC_GROUP *group,
// Add multiples of the generator.
if (i <= 27) {
// First, look 28 bits upwards.
uint64_t bits = p224_get_bit(g_scalar->bytes, i + 196) << 3;
crypto_word_t bits = p224_get_bit(g_scalar->bytes, i + 196) << 3;
bits |= p224_get_bit(g_scalar->bytes, i + 140) << 2;
bits |= p224_get_bit(g_scalar->bytes, i + 84) << 1;
bits |= p224_get_bit(g_scalar->bytes, i + 28);
size_t index = (size_t)bits;
p224_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
g_p224_pre_comp[1][bits][0], g_p224_pre_comp[1][bits][1],
g_p224_pre_comp[1][bits][2]);
g_p224_pre_comp[1][index][0], g_p224_pre_comp[1][index][1],
g_p224_pre_comp[1][index][2]);
assert(!skip);
// Second, look at the current position.
@@ -1095,20 +1096,21 @@ static void ec_GFp_nistp224_point_mul_public(const EC_GROUP *group,
bits |= p224_get_bit(g_scalar->bytes, i + 112) << 2;
bits |= p224_get_bit(g_scalar->bytes, i + 56) << 1;
bits |= p224_get_bit(g_scalar->bytes, i);
index = (size_t)bits;
p224_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
g_p224_pre_comp[0][bits][0], g_p224_pre_comp[0][bits][1],
g_p224_pre_comp[0][bits][2]);
g_p224_pre_comp[0][index][0], g_p224_pre_comp[0][index][1],
g_p224_pre_comp[0][index][2]);
}
// Incorporate |p_scalar| every 5 doublings.
if (i % 5 == 0) {
uint64_t bits = p224_get_bit(p_scalar->bytes, i + 4) << 5;
crypto_word_t bits = p224_get_bit(p_scalar->bytes, i + 4) << 5;
bits |= p224_get_bit(p_scalar->bytes, i + 3) << 4;
bits |= p224_get_bit(p_scalar->bytes, i + 2) << 3;
bits |= p224_get_bit(p_scalar->bytes, i + 1) << 2;
bits |= p224_get_bit(p_scalar->bytes, i) << 1;
bits |= p224_get_bit(p_scalar->bytes, i - 1);
uint8_t sign, digit;
crypto_word_t sign, digit;
ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
// Select the point to add or subtract.
@@ -1154,16 +1156,6 @@ static void ec_GFp_nistp224_felem_sqr(const EC_GROUP *group, EC_FELEM *r,
p224_felem_to_generic(r, felem);
}
static int ec_GFp_nistp224_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out,
const BIGNUM *in) {
return bn_copy_words(out->words, group->field.width, in);
}
static int ec_GFp_nistp224_felem_to_bignum(const EC_GROUP *group, BIGNUM *out,
const EC_FELEM *in) {
return bn_set_words(out, in->words, group->field.width);
}
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
out->group_init = ec_GFp_simple_group_init;
out->group_finish = ec_GFp_simple_group_finish;
@@ -1177,10 +1169,11 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
out->mul_public = ec_GFp_nistp224_point_mul_public;
out->felem_mul = ec_GFp_nistp224_felem_mul;
out->felem_sqr = ec_GFp_nistp224_felem_sqr;
out->bignum_to_felem = ec_GFp_nistp224_bignum_to_felem;
out->felem_to_bignum = ec_GFp_nistp224_felem_to_bignum;
out->scalar_inv_montgomery = ec_simple_scalar_inv_montgomery;
out->scalar_inv_montgomery_vartime = ec_GFp_simple_mont_inv_mod_ord_vartime;
out->felem_to_bytes = ec_GFp_simple_felem_to_bytes;
out->felem_from_bytes = ec_GFp_simple_felem_from_bytes;
out->scalar_inv0_montgomery = ec_simple_scalar_inv0_montgomery;
out->scalar_to_montgomery_inv_vartime =
ec_simple_scalar_to_montgomery_inv_vartime;
out->cmp_x_coordinate = ec_GFp_simple_cmp_x_coordinate;
}
File diff suppressed because it is too large Load Diff

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