Most asymmetric operations scale superlinearly, which makes them
potential DoS vectors. This (and other problems) are mitigated with
fixed sizes, like RSA-2048, P-256, or curve25519.
In older algorithms like RSA and DSA, these sizes are conventions rather
than well-defined algorithms. "Everyone" uses RSA-2048, but code which
imports an RSA key may see an arbitrary key size, possibly from an
untrusted source. This is commonly a public key, so we bound RSA key
sizes in check_modulus_and_exponent_sizes.
However, some applications import external private keys, and may need
tighter bounds. These typically parse the key then check the result.
However, parsing itself can perform superlinear work (RSA_check_key or
recovering the DSA public key).
This CL does the following:
- Rename check_modulus_and_exponent_sizes to rsa_check_public_key and
additionally call it from RSA_check_key.
- Fix a bug where RSA_check_key, on CRT-less keys, did not bound d, and
bound p and q before multiplying (quadratic).
- Our DSA verifier had stricter checks on q (160-, 224-, and 256-bit
only) than our DSA signer (multiple of 8 bits). Aligner the signer to
the verifier's checks.
- Validate DSA group sizes on parse, as well as priv_key < q, to bound
the running time.
Ideally these invariants would be checked exactly once at construction,
but our RSA and DSA implementations suffer from some OpenSSL's API
mistakes (https://crbug.com/boringssl/316), which means it is hard to
consistently enforce invariants. This CL focuses on the parser, but
later I'd like to better rationalize the freeze_private_key logic.
Performance of parsing RSA and DSA keys, gathered on my laptop.
Did 15130 RSA-2048 parse operations in 5022458us (3012.5 ops/sec)
Did 4888 RSA-4096 parse operations in 5060606us (965.9 ops/sec)
Did 354 RSA-16384 parse operations in 5043565us (70.2 ops/sec)
Did 88 RSA-32768 parse operations in 5038293us (17.5 ops/sec) [rejected by this CL]
Did 35000 DSA-1024/256 parse operations in 5030447us (6957.6 ops/sec)
Did 11316 DSA-2048/256 parse operations in 5094664us (2221.1 ops/sec)
Did 5488 DSA-3072/256 parse operations in 5096032us (1076.9 ops/sec)
Did 3172 DSA-4096/256 parse operations in 5041220us (629.2 ops/sec)
Did 840 DSA-8192/256 parse operations in 5070616us (165.7 ops/sec)
Did 285 DSA-10000/256 parse operations in 5004033us (57.0 ops/sec)
Did 74 DSA-20000/256 parse operations in 5066299us (14.6 ops/sec) [rejected by this CL]
Update-Note: Some invalid or overly large RSA and DSA keys may
previously have been accepted that are now rejected at parse time. For
public keys, this only moves the error from verification to parsing. In
some private key cases, we would previously allow signing with those
keys, but the resulting signatures would not be accepted by BoringSSL
anyway. This CL makes us behave more consistently.
Bug: oss-fuzz:24730
Change-Id: I4ad2003ee61138b693e65d3da4c6aa00bc165251
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42504
Reviewed-by: Adam Langley <agl@google.com>
OpenSSL renamed the preferred spelling of X509_set_notBefore to
X509_set1_notBefore, etc., in 568ce3a583a17c33feacbf5028ece9f7f0680478.
Add the set1 names and update uses within the library.
Change-Id: Ib211e356da9de963990ad2b330249383ccfef7e5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42524
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Most of the output formats manually call sorted(), which I've retained
since they often concatenate multiple file lists, but the JSON output
dumps the object to JSON directly. Sort everything earlier so the JSON
output is deterministic.
Change-Id: I9940f4ef3eb85a3fd7337058f5d7ce0ce6e28b9d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42544
Reviewed-by: Adam Langley <agl@google.com>
I tried to save space and use 32-bit GOT offsets since a GOT > 2GiB is
crazy. However, Clang's linker emits 64-bit relocations even for .long,
thus the four bytes following each offset get stomped. It mostly works
because the relocations are applied in order, thus the following
relocation gets stomped but is then processed and fixed. But there's
four bytes of stomp at the end which hits the module integrity hash,
which is fatal.
This could be fixed by adding four bytes of padding after the list of
offsets, but that's piling a hack on a hack. So this change just
switches to 64-bit offsets.
Change-Id: I227eec67c481d93a414fbed19aa99471f9df0f0e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42484
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Prior to 5d7c2f8b1d, these i2d functions would fail, rather than crash,
if passed a NULL argument. While we don't generally have much truck with
the idea that functions should be expected to handle NULL arguments
where not documented, it seems that a fair amount of code is depending
on this.
Change-Id: I928b35533aa2a7beed57d7f58ba44681a8eb05c6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42464
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
This change adds optional support for
- Armv8.3-A Pointer Authentication (PAuth) and
- Armv8.5-A Branch Target Identification (BTI)
features to the perl scripts.
Both features can be enabled with additional compiler flags.
Unless any of these are enabled explicitly there is no code change at
all.
The extensions are briefly described below. Please read the appropriate
chapters of the Arm Architecture Reference Manual for the complete
specification.
Scope
-----
This change only affects generated assembly code.
Armv8.3-A Pointer Authentication
--------------------------------
Pointer Authentication extension supports the authentication of the
contents of registers before they are used for indirect branching
or load.
PAuth provides a probabilistic method to detect corruption of register
values. PAuth signing instructions generate a Pointer Authentication
Code (PAC) based on the value of a register, a seed and a key.
The generated PAC is inserted into the original value in the register.
A PAuth authentication instruction recomputes the PAC, and if it matches
the PAC in the register, restores its original value. In case of a
mismatch, an architecturally unmapped address is generated instead.
With PAuth, mitigation against ROP (Return-oriented Programming) attacks
can be implemented. This is achieved by signing the contents of the
link-register (LR) before it is pushed to stack. Once LR is popped,
it is authenticated. This way a stack corruption which overwrites the
LR on the stack is detectable.
The PAuth extension adds several new instructions, some of which are not
recognized by older hardware. To support a single codebase for both pre
Armv8.3-A targets and newer ones, only NOP-space instructions are added
by this patch. These instructions are treated as NOPs on hardware
which does not support Armv8.3-A. Furthermore, this patch only considers
cases where LR is saved to the stack and then restored before branching
to its content. There are cases in the code where LR is pushed to stack
but it is not used later. We do not address these cases as they are not
affected by PAuth.
There are two keys available to sign an instruction address: A and B.
PACIASP and PACIBSP only differ in the used keys: A and B, respectively.
The keys are typically managed by the operating system.
To enable generating code for PAuth compile with
-mbranch-protection=<mode>:
- standard or pac-ret: add PACIASP and AUTIASP, also enables BTI
(read below)
- pac-ret+b-key: add PACIBSP and AUTIBSP
Armv8.5-A Branch Target Identification
--------------------------------------
Branch Target Identification features some new instructions which
protect the execution of instructions on guarded pages which are not
intended branch targets.
If Armv8.5-A is supported by the hardware, execution of an instruction
changes the value of PSTATE.BTYPE field. If an indirect branch
lands on a guarded page the target instruction must be one of the
BTI <jc> flavors, or in case of a direct call or jump it can be any
other instruction. If the target instruction is not compatible with the
value of PSTATE.BTYPE a Branch Target Exception is generated.
In short, indirect jumps are compatible with BTI <j> and <jc> while
indirect calls are compatible with BTI <c> and <jc>. Please refer to the
specification for the details.
Armv8.3-A PACIASP and PACIBSP are implicit branch target
identification instructions which are equivalent with BTI c or BTI jc
depending on system register configuration.
BTI is used to mitigate JOP (Jump-oriented Programming) attacks by
limiting the set of instructions which can be jumped to.
BTI requires active linker support to mark the pages with BTI-enabled
code as guarded. For ELF64 files BTI compatibility is recorded in the
.note.gnu.property section. For a shared object or static binary it is
required that all linked units support BTI. This means that even a
single assembly file without the required note section turns-off BTI
for the whole binary or shared object.
The new BTI instructions are treated as NOPs on hardware which does
not support Armv8.5-A or on pages which are not guarded.
To insert this new and optional instruction compile with
-mbranch-protection=standard (also enables PAuth) or +bti.
When targeting a guarded page from a non-guarded page, weaker
compatibility restrictions apply to maintain compatibility between
legacy and new code. For detailed rules please refer to the Arm ARM.
Compiler support
----------------
Compiler support requires understanding '-mbranch-protection=<mode>'
and emitting the appropriate feature macros (__ARM_FEATURE_BTI_DEFAULT
and __ARM_FEATURE_PAC_DEFAULT). The current state is the following:
-------------------------------------------------------
| Compiler | -mbranch-protection | Feature macros |
+----------+---------------------+--------------------+
| clang | 9.0.0 | 11.0.0 |
+----------+---------------------+--------------------+
| gcc | 9 | expected in 10.1+ |
-------------------------------------------------------
Available Platforms
------------------
Arm Fast Model and QEMU support both extensions.
https://developer.arm.com/tools-and-software/simulation-models/fast-modelshttps://www.qemu.org/
Implementation Notes
--------------------
This change adds BTI landing pads even to assembly functions which are
likely to be directly called only. In these cases, landing pads might
be superfluous depending on what code the linker generates.
Code size and performance impact for these cases would be negligble.
Interaction with C code
-----------------------
Pointer Authentication is a per-frame protection while Branch Target
Identification can be turned on and off only for all code pages of a
whole shared object or static binary. Because of these properties if
C/C++ code is compiled without any of the above features but assembly
files support any of them unconditionally there is no incompatibility
between the two.
Useful Links
------------
To fully understand the details of both PAuth and BTI it is advised to
read the related chapters of the Arm Architecture Reference Manual
(Arm ARM):
https://developer.arm.com/documentation/ddi0487/latest/
Additional materials:
"Providing protection for complex software"
https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software
Arm Compiler Reference Guide Version 6.14: -mbranch-protection
https://developer.arm.com/documentation/101754/0614/armclang-Reference/armclang-Command-line-Options/-mbranch-protection?lang=en
Arm C Language Extensions (ACLE)
https://developer.arm.com/docs/101028/latest
Change-Id: I4335f92e2ccc8e209c7d68a0a79f1acdf3aeb791
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42084
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
This version adds signature algorithms to the extension
Change-Id: I91dc78d33ee81cb7a6221c7bdeefc8ea460a2d6c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42424
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
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>
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>
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>
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>
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>
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>
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>
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.
53a5ad34c0/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>
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>
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>
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>
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>
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>
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>
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>