Compare commits

...

47 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
175 changed files with 7097 additions and 11981 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
+14 -3
View File
@@ -471,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")
@@ -573,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})
+3 -1
View File
@@ -299,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
@@ -456,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()
@@ -519,6 +520,7 @@ add_executable(
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
+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;
+2 -2
View File
@@ -100,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);
@@ -110,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;
+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";
+12 -52
View File
@@ -50,12 +50,10 @@
// 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. If |is_draft06| is one, it
// implements the operation from draft-irtf-cfrg-hash-to-curve-06 instead.
// 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 is_draft06) {
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);
@@ -88,9 +86,8 @@ static int expand_message_xmd(const EVP_MD *md, uint8_t *out, size_t out_len,
!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)) ||
(is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
(!is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
!EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
!EVP_DigestFinal_ex(&ctx, b_0, NULL)) {
goto err;
}
@@ -114,9 +111,8 @@ static int expand_message_xmd(const EVP_MD *md, uint8_t *out, size_t out_len,
if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
!EVP_DigestUpdate(&ctx, b_i, md_size) ||
!EVP_DigestUpdate(&ctx, &i, 1) ||
(is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
(!is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
!EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
!EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
goto err;
}
@@ -175,12 +171,11 @@ static void big_endian_to_words(BN_ULONG *out, size_t num_words,
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, int is_draft06) {
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,
is_draft06)) {
!expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len)) {
return 0;
}
BN_ULONG words[2 * EC_MAX_WORDS];
@@ -196,12 +191,11 @@ static int hash_to_field2(const EC_GROUP *group, const EVP_MD *md,
// 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,
int is_draft06) {
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, is_draft06)) {
!expand_message_xmd(md, buf, L, msg, msg_len, dst, dst_len)) {
return 0;
}
@@ -310,10 +304,9 @@ static int map_to_curve_simple_swu(const EC_GROUP *group, const EC_FELEM *Z,
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, int is_draft06) {
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,
is_draft06)) {
if (!hash_to_field2(group, md, &u0, &u1, dst, dst_len, k, msg, msg_len)) {
return 0;
}
@@ -376,7 +369,7 @@ int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
ec_felem_neg(group, &Z, &Z);
return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/192, out, dst,
dst_len, msg, msg_len, /*is_draft06=*/0);
dst_len, msg, msg_len);
}
int ec_hash_to_scalar_p384_xmd_sha512_draft07(
@@ -388,38 +381,5 @@ int ec_hash_to_scalar_p384_xmd_sha512_draft07(
}
return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/192, msg,
msg_len, /*is_draft06=*/0);
}
int ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
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-06.
if (EC_GROUP_get_curve_name(group) != NID_secp521r1) {
OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
return 0;
}
// Z = -4, c2 = 8.
EC_FELEM Z, c2;
if (!felem_from_u8(group, &Z, 4) ||
!felem_from_u8(group, &c2, 8)) {
return 0;
}
ec_felem_neg(group, &Z, &Z);
return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/256, out, dst,
dst_len, msg, msg_len, /*is_draft06=*/1);
}
int ec_hash_to_scalar_p521_xmd_sha512_draft06(
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_secp521r1) {
OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
return 0;
}
return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/256, msg,
msg_len, /*is_draft06=*/1);
msg_len);
}
-22
View File
@@ -48,28 +48,6 @@ 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);
// ec_hash_to_curve_p521_xmd_sha512_sswu_draft06 hashes |msg| to a point on
// |group| and writes the result to |out|, implementing the
// P521_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-06. It
// returns one on success and zero on error.
//
// This function implements an older version of the draft and should not be used
// in new code.
OPENSSL_EXPORT int ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
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_p521_xmd_sha512_draft06 hashes |msg| to a scalar on |group|
// and writes the result to |out|, using the hash_to_field operation from the
// P521_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-06, but
// generating a value modulo the group order rather than a field element.
//
// This function implements an older version of the draft and should not be used
// in new code.
OPENSSL_EXPORT int ec_hash_to_scalar_p521_xmd_sha512_draft06(
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
+10 -7
View File
@@ -86,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
@@ -174,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
@@ -181,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
@@ -202,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
+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;
}
+1
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
+11 -1
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."
-97
View File
@@ -1170,74 +1170,6 @@ TEST(ECTest, HashToCurve) {
"37f2913224287b9dfb64742851f760eb14ca115ff9",
"1510e764f1be968d661b7aaecb26a6d38c98e5205ca150f0ae426d"
"2c3983c68e3a9ffb283c6ae4891d891b5705500475"},
// Note these tests do not match the tests vectors
// draft-irtf-cfrg-hash-to-curve-06 due to a
// spec issue. See
// https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/pull/238 for
// corrected test vectors.
{&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SSWU_RO_TESTGEN", "",
"00758617b5e40aa8b30fcfd3c7453ad1abeff158de5697d6f1ccb8"
"4690aaa8bb6692986200d16206e85e4f39f1d2829fee1a5904a089"
"b4fab3b76873429877c58f99",
"016edf324d95fcbe4a30f06751f16cdd5d0b49921dd653cefb3ea2"
"dc2b5b903e36d9924a65407283588cc6c224ab6d6324c73cdc166c"
"e1530b46984b459e966349b3"},
{&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SSWU_RO_TESTGEN", "abc",
"00dcec1a83b676247293e96b1672f67aa5d041a4ded49f542a971a"
"60603dd39194f4d8e587f640563a9ab57dcc69af638129b220683f"
"f03ed9ad8cfdff3833a01452",
"01edc4b497be85361a0afc508058792dc7fc6499a4c51fa3475093"
"fd9951ea46fe055e1b007a12caf9be1ce3028bd0b4ca4ffa5200f9"
"d11e7fc96e068276ad1319c2"},
{&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SSWU_RO_TESTGEN", "abcdef0123456789",
"01f58bfb34825d028c392976a09cebee829734f7714c84b8a13580"
"afcc2eb4726e18e307476c1fccdc857a3d6767fd2882875ab132b7"
"fa7f3f6bae8954384001b1a1",
"00ee0d2d0bfb0bdc6215814fe7096a3dfbf020dce4f0645e8e21a9"
"0d6a6113a5ca61ae7d8f3b485b04f2eb2b85e34fc7f9f1bf367386"
"2e03932b0acc3655e84d480f"},
{&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SSWU_RO_TESTGEN",
"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"016d9a90619bb20c49a2a73cc8c6218cd9b3fb13c720fff2e1f8db"
"ac92862c7da4faf404faeff6b64f0d9b1c5824cec99b0d0ed02b3f"
"acb6275ce553404ea361503e",
"007e301e3357fb1d53961c56e53ce2763e44b297062a3eb14b9f8d"
"6aadc92162a74f7e254a606275e76ea0ac343b3bc746f99804bacd"
"7351a76fce44347c72a6fe9a"},
// Custom test vector which triggers long DST path.
{&ec_hash_to_curve_p521_xmd_sha512_sswu_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SSWU_RO_TESTGEN_aaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"abcdef0123456789",
"0036b0c8bbec60335ff8b0397c2cb80283b97051cc949c5c190c28"
"92b279fafd6c372dcec3e71eab85c48ed440c14498332548ee46d0"
"c85442cbdc5b4032e86c3884",
"0081e32ca4378ae89b03142361d9c7fbe66acf0351aca3a71eca50"
"7a37fb8673b69cb108d079a248aedd74f06949d6623e7f7605ea10"
"f6f751ab574c005db7377d7f"},
};
for (const auto &test : kTests) {
@@ -1269,8 +1201,6 @@ TEST(ECTest, HashToCurve) {
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_p521_xmd_sha512_sswu_draft06(
p224.get(), &p, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
EXPECT_FALSE(ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
p224.get(), &p, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
}
@@ -1308,31 +1238,6 @@ TEST(ECTest, HashToScalar) {
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"750f2fae7d2b2f41ac737d180c1d4363d85a1504798b4976d40921"
"1ddb3651c13a5b4daba9975cdfce18336791131915"},
{&ec_hash_to_scalar_p521_xmd_sha512_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SCALAR_TEST", "",
"01a6206c2fc677c11d51807bf46d64a17f92396673074c5cee9299"
"4d28eec5445d5ed89799b30b39c964ecf62f39d59e7d43de15d910"
"c2c1d69f3ebc01eab241e5dc"},
{&ec_hash_to_scalar_p521_xmd_sha512_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SCALAR_TEST", "abcdef0123456789",
"00af484a5d9389a9912f555234c578d4b1b7c4a6f5009018d133a4"
"069172c9f5ce2d853b8643fe7bb50a83427ed3520a7a793c41a455"
"a02aa99431434fb6b5b0b26e"},
{&ec_hash_to_scalar_p521_xmd_sha512_draft06, NID_secp521r1,
"P521_XMD:SHA-512_SCALAR_TEST",
"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"00b2db2ceb64ad055cafc5a0fc92560525d6dcc4975b86bbb79013"
"a1c3ab5d412320cb55df8088a658039a70c5657d5aefaaaa81cc5d"
"eecdd40c03eb0517fe2e158c"},
};
for (const auto &test : kTests) {
@@ -1358,8 +1263,6 @@ TEST(ECTest, HashToScalar) {
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_p521_xmd_sha512_draft06(
p224.get(), &scalar, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
EXPECT_FALSE(ec_hash_to_scalar_p384_xmd_sha512_draft07(
p224.get(), &scalar, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
}
+2 -1
View File
@@ -703,7 +703,8 @@ void ec_GFp_mont_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
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);
+13 -11
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.
+24 -23
View File
@@ -50,8 +50,8 @@ static const BN_ULONG ONE[P256_LIMBS] = {
// Recode window to a signed digit, see |ec_GFp_nistp_recode_scalar_bits| in
// util.c for details
static unsigned booth_recode_w5(unsigned in) {
unsigned s, d;
static crypto_word_t booth_recode_w5(crypto_word_t in) {
crypto_word_t s, d;
s = ~((in >> 5) - 1);
d = (1 << 6) - in - 1;
@@ -61,8 +61,8 @@ static unsigned booth_recode_w5(unsigned in) {
return (d << 1) + (s & 1);
}
static unsigned booth_recode_w7(unsigned in) {
unsigned s, d;
static crypto_word_t booth_recode_w7(crypto_word_t in) {
crypto_word_t s, d;
s = ~((in >> 7) - 1);
d = (1 << 8) - in - 1;
@@ -194,8 +194,8 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r,
assert(p_scalar != NULL);
assert(group->field.width == P256_LIMBS);
static const unsigned kWindowSize = 5;
static const unsigned kMask = (1 << (5 /* kWindowSize */ + 1)) - 1;
static const size_t kWindowSize = 5;
static const crypto_word_t kMask = (1 << (5 /* kWindowSize */ + 1)) - 1;
// A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should
// add no more than 63 bytes of overhead. Thus, |table| should require
@@ -232,17 +232,17 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r,
BN_ULONG tmp[P256_LIMBS];
alignas(32) P256_POINT h;
unsigned index = 255;
unsigned wvalue = p_str[(index - 1) / 8];
size_t index = 255;
crypto_word_t wvalue = p_str[(index - 1) / 8];
wvalue = (wvalue >> ((index - 1) % 8)) & kMask;
ecp_nistz256_select_w5(r, table, booth_recode_w5(wvalue) >> 1);
while (index >= 5) {
if (index != 255) {
unsigned off = (index - 1) / 8;
size_t off = (index - 1) / 8;
wvalue = p_str[off] | p_str[off + 1] << 8;
wvalue = (crypto_word_t)p_str[off] | (crypto_word_t)p_str[off + 1] << 8;
wvalue = (wvalue >> ((index - 1) % 8)) & kMask;
wvalue = booth_recode_w5(wvalue);
@@ -283,21 +283,22 @@ typedef union {
P256_POINT_AFFINE a;
} p256_point_union_t;
static unsigned calc_first_wvalue(unsigned *index, const uint8_t p_str[33]) {
static const unsigned kWindowSize = 7;
static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
static crypto_word_t calc_first_wvalue(size_t *index, const uint8_t p_str[33]) {
static const size_t kWindowSize = 7;
static const crypto_word_t kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
*index = kWindowSize;
unsigned wvalue = (p_str[0] << 1) & kMask;
crypto_word_t wvalue = (p_str[0] << 1) & kMask;
return booth_recode_w7(wvalue);
}
static unsigned calc_wvalue(unsigned *index, const uint8_t p_str[33]) {
static const unsigned kWindowSize = 7;
static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
static crypto_word_t calc_wvalue(size_t *index, const uint8_t p_str[33]) {
static const size_t kWindowSize = 7;
static const crypto_word_t kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
const unsigned off = (*index - 1) / 8;
unsigned wvalue = p_str[off] | p_str[off + 1] << 8;
const size_t off = (*index - 1) / 8;
crypto_word_t wvalue =
(crypto_word_t)p_str[off] | (crypto_word_t)p_str[off + 1] << 8;
wvalue = (wvalue >> ((*index - 1) % 8)) & kMask;
*index += kWindowSize;
@@ -325,8 +326,8 @@ static void ecp_nistz256_point_mul_base(const EC_GROUP *group, EC_RAW_POINT *r,
p_str[32] = 0;
// First window
unsigned index = 0;
unsigned wvalue = calc_first_wvalue(&index, p_str);
size_t index = 0;
crypto_word_t wvalue = calc_first_wvalue(&index, p_str);
ecp_nistz256_select_w7(&p.a, ecp_nistz256_precomputed[0], wvalue >> 1);
ecp_nistz256_neg(p.p.Z, p.p.Y);
@@ -370,8 +371,8 @@ static void ecp_nistz256_points_mul_public(const EC_GROUP *group,
p_str[32] = 0;
// First window
unsigned index = 0;
unsigned wvalue = calc_first_wvalue(&index, p_str);
size_t index = 0;
size_t wvalue = calc_first_wvalue(&index, p_str);
// Convert |p| from affine to Jacobian coordinates. We set Z to zero if |p|
// is infinity and |ONE| otherwise. |p| was computed from the table, so it
+20 -16
View File
@@ -67,7 +67,7 @@ static fiat_p256_limb_t fiat_p256_nz(
static void fiat_p256_copy(fiat_p256_limb_t out[FIAT_P256_NLIMBS],
const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) {
for (int i = 0; i < FIAT_P256_NLIMBS; i++) {
for (size_t i = 0; i < FIAT_P256_NLIMBS; i++) {
out[i] = in1[i];
}
}
@@ -393,7 +393,7 @@ static void fiat_p256_select_point(const fiat_p256_limb_t idx, size_t size,
}
// fiat_p256_get_bit returns the |i|th bit in |in|
static char fiat_p256_get_bit(const uint8_t *in, int i) {
static crypto_word_t fiat_p256_get_bit(const uint8_t *in, int i) {
if (i < 0 || i >= 256) {
return 0;
}
@@ -498,20 +498,20 @@ static void ec_GFp_nistp256_point_mul(const EC_GROUP *group, EC_RAW_POINT *r,
// do other additions every 5 doublings
if (i % 5 == 0) {
uint64_t bits = fiat_p256_get_bit(scalar->bytes, i + 4) << 5;
crypto_word_t bits = fiat_p256_get_bit(scalar->bytes, i + 4) << 5;
bits |= fiat_p256_get_bit(scalar->bytes, i + 3) << 4;
bits |= fiat_p256_get_bit(scalar->bytes, i + 2) << 3;
bits |= fiat_p256_get_bit(scalar->bytes, i + 1) << 2;
bits |= fiat_p256_get_bit(scalar->bytes, i) << 1;
bits |= fiat_p256_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, in constant time.
fiat_p256_select_point(digit, 17, (const fiat_p256_felem(*)[3])p_pre_comp,
tmp);
fiat_p256_select_point((fiat_p256_limb_t)digit, 17,
(const fiat_p256_felem(*)[3])p_pre_comp, tmp);
fiat_p256_opp(ftmp, tmp[1]); // (X, -Y, Z) is the negative point.
fiat_p256_cmovznz(tmp[1], sign, tmp[1], ftmp);
fiat_p256_cmovznz(tmp[1], (fiat_p256_limb_t)sign, tmp[1], ftmp);
if (!skip) {
fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2],
@@ -543,12 +543,13 @@ static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group,
}
// First, look 32 bits upwards.
uint64_t bits = fiat_p256_get_bit(scalar->bytes, i + 224) << 3;
crypto_word_t bits = fiat_p256_get_bit(scalar->bytes, i + 224) << 3;
bits |= fiat_p256_get_bit(scalar->bytes, i + 160) << 2;
bits |= fiat_p256_get_bit(scalar->bytes, i + 96) << 1;
bits |= fiat_p256_get_bit(scalar->bytes, i + 32);
// Select the point to add, in constant time.
fiat_p256_select_point_affine(bits, 15, fiat_p256_g_pre_comp[1], tmp);
fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15,
fiat_p256_g_pre_comp[1], tmp);
if (!skip) {
fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2],
@@ -566,7 +567,8 @@ static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group,
bits |= fiat_p256_get_bit(scalar->bytes, i + 64) << 1;
bits |= fiat_p256_get_bit(scalar->bytes, i);
// Select the point to add, in constant time.
fiat_p256_select_point_affine(bits, 15, fiat_p256_g_pre_comp[0], tmp);
fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15,
fiat_p256_g_pre_comp[0], tmp);
fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
tmp[0], tmp[1], tmp[2]);
}
@@ -613,14 +615,15 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group,
// constant-time lookup.
if (i <= 31) {
// First, look 32 bits upwards.
uint64_t bits = fiat_p256_get_bit(g_scalar->bytes, i + 224) << 3;
crypto_word_t bits = fiat_p256_get_bit(g_scalar->bytes, i + 224) << 3;
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 160) << 2;
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 96) << 1;
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 32);
if (bits != 0) {
size_t index = (size_t)(bits - 1);
fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2],
1 /* mixed */, fiat_p256_g_pre_comp[1][bits - 1][0],
fiat_p256_g_pre_comp[1][bits - 1][1],
1 /* mixed */, fiat_p256_g_pre_comp[1][index][0],
fiat_p256_g_pre_comp[1][index][1],
fiat_p256_one);
skip = 0;
}
@@ -631,9 +634,10 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group,
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 64) << 1;
bits |= fiat_p256_get_bit(g_scalar->bytes, i);
if (bits != 0) {
size_t index = (size_t)(bits - 1);
fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2],
1 /* mixed */, fiat_p256_g_pre_comp[0][bits - 1][0],
fiat_p256_g_pre_comp[0][bits - 1][1],
1 /* mixed */, fiat_p256_g_pre_comp[0][index][0],
fiat_p256_g_pre_comp[0][index][1],
fiat_p256_one);
skip = 0;
}
@@ -642,7 +646,7 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group,
int digit = p_wNAF[i];
if (digit != 0) {
assert(digit & 1);
int idx = digit < 0 ? (-digit) >> 1 : digit >> 1;
size_t idx = (size_t)(digit < 0 ? (-digit) >> 1 : digit >> 1);
fiat_p256_felem *y = &p_pre_comp[idx][1], tmp;
if (digit < 0) {
fiat_p256_opp(tmp, p_pre_comp[idx][1]);
+2 -2
View File
@@ -108,7 +108,7 @@ static void ec_GFp_mont_batch_get_window(const EC_GROUP *group,
if (i > 0) {
window |= bn_is_bit_set_words(scalar->words, width, i - 1);
}
uint8_t sign, digit;
crypto_word_t sign, digit;
ec_GFp_nistp_recode_scalar_bits(&sign, &digit, window);
// Select the entry in constant-time.
@@ -121,7 +121,7 @@ static void ec_GFp_mont_batch_get_window(const EC_GROUP *group,
// Negate if necessary.
EC_FELEM neg_Y;
ec_felem_neg(group, &neg_Y, &out->Y);
BN_ULONG sign_mask = sign;
crypto_word_t sign_mask = sign;
sign_mask = 0u - sign_mask;
ec_felem_select(group, &out->Y, sign_mask, &neg_Y, &out->Y);
}
+3 -3
View File
@@ -240,9 +240,9 @@
// P-384: ...01110011; w = 2, 5, 6, 7 are okay
// P-256: ...01010001; w = 5, 7 are okay
// P-224: ...00111101; w = 3, 4, 5, 6 are okay
void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit,
uint8_t in) {
uint8_t s, d;
void ec_GFp_nistp_recode_scalar_bits(crypto_word_t *sign, crypto_word_t *digit,
crypto_word_t in) {
crypto_word_t s, d;
s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as
* 6-bit value */
+2 -5
View File
@@ -108,10 +108,7 @@ die "can't locate x86_64-xlate.pl";
# versions, but BoringSSL is intended to be used with pre-generated perlasm
# output, so this isn't useful anyway.
$avx = 2;
# TODO(davidben): Consider enabling the Intel SHA Extensions code once it's
# been tested.
$shaext=0; ### set to zero if compiling for 1.0.1
$shaext=1; ### set to zero if compiling for 1.0.1
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
*STDOUT=*OUT;
@@ -456,8 +453,8 @@ $code.=<<___ if ($win64);
.Lepilogue_shaext:
___
$code.=<<___;
.cfi_endproc
ret
.cfi_endproc
.size sha1_block_data_order_shaext,.-sha1_block_data_order_shaext
___
}}}
+459
View File
@@ -0,0 +1,459 @@
/* 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 <assert.h>
#include <string.h>
#include <openssl/aead.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hkdf.h>
#include <openssl/sha.h>
#include "../internal.h"
#include "internal.h"
// As of writing, the editor's draft of HPKE has a number of changes on top of
// the latest IETF draft (draft-irtf-cfrg-hpke-04). This file implements the
// editor's draft as of July 15, 2020.
//
// TODO(dmcardle): Remove this comment when draft-irtf-cfrg-hpke-05 is
// published.
#define KEM_CONTEXT_LEN (2 * X25519_PUBLIC_VALUE_LEN)
// HPKE KEM scheme IDs.
#define HPKE_DHKEM_X25519_HKDF_SHA256 0x0020
// This is strlen("HPKE") + 3 * sizeof(uint16_t).
#define HPKE_SUITE_ID_LEN 10
#define HPKE_MODE_BASE 0
static const char kHpkeRfcId[] = "RFCXXXX ";
static int add_label_string(CBB *cbb, const char *label) {
return CBB_add_bytes(cbb, (const uint8_t *)label, strlen(label));
}
// The suite_id for the KEM is defined as concat("KEM", I2OSP(kem_id, 2)). Note
// that the suite_id used outside of the KEM also includes the kdf_id and
// aead_id.
static const uint8_t kX25519SuiteID[] = {
'K', 'E', 'M', HPKE_DHKEM_X25519_HKDF_SHA256 >> 8,
HPKE_DHKEM_X25519_HKDF_SHA256 & 0x00ff};
// The suite_id for non-KEM pieces of HPKE is defined as concat("HPKE",
// I2OSP(kem_id, 2), I2OSP(kdf_id, 2), I2OSP(aead_id, 2)).
static int hpke_build_suite_id(uint8_t out[HPKE_SUITE_ID_LEN], uint16_t kdf_id,
uint16_t aead_id) {
CBB cbb;
int ret = CBB_init_fixed(&cbb, out, HPKE_SUITE_ID_LEN) &&
add_label_string(&cbb, "HPKE") &&
CBB_add_u16(&cbb, HPKE_DHKEM_X25519_HKDF_SHA256) &&
CBB_add_u16(&cbb, kdf_id) &&
CBB_add_u16(&cbb, aead_id);
CBB_cleanup(&cbb);
return ret;
}
static int hpke_labeled_extract(const EVP_MD *hkdf_md, uint8_t *out_key,
size_t *out_len, const uint8_t *salt,
size_t salt_len, const uint8_t *suite_id,
size_t suite_id_len, const char *label,
const uint8_t *ikm, size_t ikm_len) {
// labeledIKM = concat("RFCXXXX ", suite_id, label, IKM)
CBB labeled_ikm;
int ok = CBB_init(&labeled_ikm, 0) &&
add_label_string(&labeled_ikm, kHpkeRfcId) &&
CBB_add_bytes(&labeled_ikm, suite_id, suite_id_len) &&
add_label_string(&labeled_ikm, label) &&
CBB_add_bytes(&labeled_ikm, ikm, ikm_len) &&
HKDF_extract(out_key, out_len, hkdf_md, CBB_data(&labeled_ikm),
CBB_len(&labeled_ikm), salt, salt_len);
CBB_cleanup(&labeled_ikm);
return ok;
}
static int hpke_labeled_expand(const EVP_MD *hkdf_md, uint8_t *out_key,
size_t out_len, const uint8_t *prk,
size_t prk_len, const uint8_t *suite_id,
size_t suite_id_len, const char *label,
const uint8_t *info, size_t info_len) {
// labeledInfo = concat(I2OSP(L, 2), "RFCXXXX ", suite_id, label, info)
CBB labeled_info;
int ok = CBB_init(&labeled_info, 0) &&
CBB_add_u16(&labeled_info, out_len) &&
add_label_string(&labeled_info, kHpkeRfcId) &&
CBB_add_bytes(&labeled_info, suite_id, suite_id_len) &&
add_label_string(&labeled_info, label) &&
CBB_add_bytes(&labeled_info, info, info_len) &&
HKDF_expand(out_key, out_len, hkdf_md, prk, prk_len,
CBB_data(&labeled_info), CBB_len(&labeled_info));
CBB_cleanup(&labeled_info);
return ok;
}
static int hpke_extract_and_expand(const EVP_MD *hkdf_md, uint8_t *out_key,
size_t out_len,
const uint8_t dh[X25519_PUBLIC_VALUE_LEN],
const uint8_t kem_context[KEM_CONTEXT_LEN]) {
uint8_t prk[EVP_MAX_MD_SIZE];
size_t prk_len;
static const char kEaePrkLabel[] = "eae_prk";
if (!hpke_labeled_extract(hkdf_md, prk, &prk_len, NULL, 0, kX25519SuiteID,
sizeof(kX25519SuiteID), kEaePrkLabel, dh,
X25519_PUBLIC_VALUE_LEN)) {
return 0;
}
const char kPRKExpandLabel[] = "zz";
if (!hpke_labeled_expand(hkdf_md, out_key, out_len, prk, prk_len,
kX25519SuiteID, sizeof(kX25519SuiteID),
kPRKExpandLabel, kem_context, KEM_CONTEXT_LEN)) {
return 0;
}
return 1;
}
static const EVP_AEAD *hpke_get_aead(uint16_t aead_id) {
switch (aead_id) {
case EVP_HPKE_AEAD_AES_GCM_128:
return EVP_aead_aes_128_gcm();
case EVP_HPKE_AEAD_AES_GCM_256:
return EVP_aead_aes_256_gcm();
case EVP_HPKE_AEAD_CHACHA20POLY1305:
return EVP_aead_chacha20_poly1305();
}
OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
return NULL;
}
static const EVP_MD *hpke_get_kdf(uint16_t kdf_id) {
switch (kdf_id) {
case EVP_HPKE_HKDF_SHA256:
return EVP_sha256();
case EVP_HPKE_HKDF_SHA384:
return EVP_sha384();
case EVP_HPKE_HKDF_SHA512:
return EVP_sha512();
}
OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
return NULL;
}
static int hpke_key_schedule(EVP_HPKE_CTX *hpke, const uint8_t *zz,
size_t zz_len, const uint8_t *info,
size_t info_len) {
// Attempt to get an EVP_AEAD*.
const EVP_AEAD *aead = hpke_get_aead(hpke->aead_id);
if (aead == NULL) {
return 0;
}
uint8_t suite_id[HPKE_SUITE_ID_LEN];
if (!hpke_build_suite_id(suite_id, hpke->kdf_id, hpke->aead_id)) {
return 0;
}
// pskID_hash = LabeledExtract(zero(0), "pskID_hash", pskID)
static const char kPskIdHashLabel[] = "pskID_hash";
uint8_t psk_id_hash[EVP_MAX_MD_SIZE];
size_t psk_id_hash_len;
if (!hpke_labeled_extract(hpke->hkdf_md, psk_id_hash, &psk_id_hash_len, NULL,
0, suite_id, sizeof(suite_id), kPskIdHashLabel,
NULL, 0)) {
return 0;
}
// info_hash = LabeledExtract(zero(0), "info_hash", info)
static const char kInfoHashLabel[] = "info_hash";
uint8_t info_hash[EVP_MAX_MD_SIZE];
size_t info_hash_len;
if (!hpke_labeled_extract(hpke->hkdf_md, info_hash, &info_hash_len, NULL, 0,
suite_id, sizeof(suite_id), kInfoHashLabel, info,
info_len)) {
return 0;
}
// key_schedule_context = concat(mode, pskID_hash, info_hash)
uint8_t context[sizeof(uint8_t) + 2 * EVP_MAX_MD_SIZE];
size_t context_len;
CBB context_cbb;
if (!CBB_init_fixed(&context_cbb, context, sizeof(context)) ||
!CBB_add_u8(&context_cbb, HPKE_MODE_BASE) ||
!CBB_add_bytes(&context_cbb, psk_id_hash, psk_id_hash_len) ||
!CBB_add_bytes(&context_cbb, info_hash, info_hash_len) ||
!CBB_finish(&context_cbb, NULL, &context_len)) {
return 0;
}
// psk_hash = LabeledExtract(zero(0), "psk_hash", psk)
//
// For our purposes, the draft's psk parameter is just the default empty PSK.
static const char kPskHashLabel[] = "psk_hash";
uint8_t psk_hash[EVP_MAX_MD_SIZE];
size_t psk_hash_len;
if (!hpke_labeled_extract(hpke->hkdf_md, psk_hash, &psk_hash_len, NULL, 0,
suite_id, sizeof(suite_id), kPskHashLabel, NULL,
0)) {
return 0;
}
// secret = LabeledExtract(psk_hash, "secret", zz)
static const char kSecretExtractLabel[] = "secret";
uint8_t secret[EVP_MAX_MD_SIZE];
size_t secret_len;
if (!hpke_labeled_extract(hpke->hkdf_md, secret, &secret_len, psk_hash,
psk_hash_len, suite_id, sizeof(suite_id),
kSecretExtractLabel, zz, zz_len)) {
return 0;
}
// key = LabeledExpand(secret, "key", key_schedule_context, Nk)
static const char kKeyExpandLabel[] = "key";
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
const size_t kKeyLen = EVP_AEAD_key_length(aead);
if (!hpke_labeled_expand(hpke->hkdf_md, key, kKeyLen, secret, secret_len,
suite_id, sizeof(suite_id), kKeyExpandLabel, context,
context_len)) {
return 0;
}
// Initialize the HPKE context's AEAD context, storing a copy of |key|.
if (!EVP_AEAD_CTX_init(&hpke->aead_ctx, aead, key, kKeyLen, 0, NULL)) {
return 0;
}
// nonce = LabeledExpand(secret, "nonce", key_schedule_context, Nn)
static const char kNonceExpandLabel[] = "nonce";
if (!hpke_labeled_expand(hpke->hkdf_md, hpke->nonce,
EVP_AEAD_nonce_length(aead), secret, secret_len,
suite_id, sizeof(suite_id), kNonceExpandLabel,
context, context_len)) {
return 0;
}
// exporter_secret = LabeledExpand(secret, "exp", key_schedule_context, Nh)
static const char kExporterSecretExpandLabel[] = "exp";
if (!hpke_labeled_expand(hpke->hkdf_md, hpke->exporter_secret,
EVP_MD_size(hpke->hkdf_md), secret, secret_len,
suite_id, sizeof(suite_id),
kExporterSecretExpandLabel, context, context_len)) {
return 0;
}
return 1;
}
// The number of bytes written to |out_zz| is the size of the KEM's KDF
// (currently we only support SHA256).
static int hpke_encap(EVP_HPKE_CTX *hpke, uint8_t out_zz[SHA256_DIGEST_LENGTH],
const uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN],
const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN],
const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]) {
uint8_t dh[X25519_PUBLIC_VALUE_LEN];
if (!X25519(dh, ephemeral_private, public_key_r)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
return 0;
}
uint8_t kem_context[KEM_CONTEXT_LEN];
OPENSSL_memcpy(kem_context, ephemeral_public, X25519_PUBLIC_VALUE_LEN);
OPENSSL_memcpy(kem_context + X25519_PUBLIC_VALUE_LEN, public_key_r,
X25519_PUBLIC_VALUE_LEN);
if (!hpke_extract_and_expand(EVP_sha256(), out_zz, SHA256_DIGEST_LENGTH, dh,
kem_context)) {
return 0;
}
return 1;
}
static int hpke_decap(const EVP_HPKE_CTX *hpke,
uint8_t out_zz[SHA256_DIGEST_LENGTH],
const uint8_t enc[X25519_PUBLIC_VALUE_LEN],
const uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN],
const uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN]) {
uint8_t dh[X25519_PUBLIC_VALUE_LEN];
if (!X25519(dh, secret_key_r, enc)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
return 0;
}
uint8_t kem_context[KEM_CONTEXT_LEN];
OPENSSL_memcpy(kem_context, enc, X25519_PUBLIC_VALUE_LEN);
OPENSSL_memcpy(kem_context + X25519_PUBLIC_VALUE_LEN, public_key_r,
X25519_PUBLIC_VALUE_LEN);
if (!hpke_extract_and_expand(EVP_sha256(), out_zz, SHA256_DIGEST_LENGTH, dh,
kem_context)) {
return 0;
}
return 1;
}
void EVP_HPKE_CTX_init(EVP_HPKE_CTX *ctx) {
OPENSSL_memset(ctx, 0, sizeof(EVP_HPKE_CTX));
EVP_AEAD_CTX_zero(&ctx->aead_ctx);
}
void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx) {
EVP_AEAD_CTX_cleanup(&ctx->aead_ctx);
}
int EVP_HPKE_CTX_setup_base_s_x25519(
EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN],
uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len) {
// The GenerateKeyPair() step technically belongs in the KEM's Encap()
// function, but we've moved it up a layer to make it easier for tests to
// inject an ephemeral keypair.
uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN];
X25519_keypair(out_enc, ephemeral_private);
return EVP_HPKE_CTX_setup_base_s_x25519_for_test(
hpke, kdf_id, aead_id, peer_public_value, info, info_len,
ephemeral_private, out_enc);
}
int EVP_HPKE_CTX_setup_base_s_x25519_for_test(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len,
const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN],
const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]) {
hpke->is_sender = 1;
hpke->kdf_id = kdf_id;
hpke->aead_id = aead_id;
hpke->hkdf_md = hpke_get_kdf(kdf_id);
if (hpke->hkdf_md == NULL) {
return 0;
}
uint8_t zz[SHA256_DIGEST_LENGTH];
if (!hpke_encap(hpke, zz, peer_public_value, ephemeral_private,
ephemeral_public) ||
!hpke_key_schedule(hpke, zz, sizeof(zz), info, info_len)) {
return 0;
}
return 1;
}
int EVP_HPKE_CTX_setup_base_r_x25519(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t enc[X25519_PUBLIC_VALUE_LEN],
const uint8_t public_key[X25519_PUBLIC_VALUE_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info,
size_t info_len) {
hpke->is_sender = 0;
hpke->kdf_id = kdf_id;
hpke->aead_id = aead_id;
hpke->hkdf_md = hpke_get_kdf(kdf_id);
if (hpke->hkdf_md == NULL) {
return 0;
}
uint8_t zz[SHA256_DIGEST_LENGTH];
if (!hpke_decap(hpke, zz, enc, public_key, private_key) ||
!hpke_key_schedule(hpke, zz, sizeof(zz), info, info_len)) {
return 0;
}
return 1;
}
static void hpke_nonce(const EVP_HPKE_CTX *hpke, uint8_t *out_nonce,
size_t nonce_len) {
assert(nonce_len >= 8);
// Write padded big-endian bytes of |hpke->seq| to |out_nonce|.
OPENSSL_memset(out_nonce, 0, nonce_len);
uint64_t seq_copy = hpke->seq;
for (size_t i = 0; i < 8; i++) {
out_nonce[nonce_len - i - 1] = seq_copy & 0xff;
seq_copy >>= 8;
}
// XOR the encoded sequence with the |hpke->nonce|.
for (size_t i = 0; i < nonce_len; i++) {
out_nonce[i] ^= hpke->nonce[i];
}
}
size_t EVP_HPKE_CTX_max_overhead(const EVP_HPKE_CTX *hpke) {
assert(hpke->is_sender);
return EVP_AEAD_max_overhead(hpke->aead_ctx.aead);
}
int EVP_HPKE_CTX_open(EVP_HPKE_CTX *hpke, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
if (hpke->is_sender) {
OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (hpke->seq == UINT64_MAX) {
OPENSSL_PUT_ERROR(EVP, ERR_R_OVERFLOW);
return 0;
}
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
const size_t nonce_len = EVP_AEAD_nonce_length(hpke->aead_ctx.aead);
hpke_nonce(hpke, nonce, nonce_len);
if (!EVP_AEAD_CTX_open(&hpke->aead_ctx, out, out_len, max_out_len, nonce,
nonce_len, in, in_len, ad, ad_len)) {
return 0;
}
hpke->seq++;
return 1;
}
int EVP_HPKE_CTX_seal(EVP_HPKE_CTX *hpke, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
if (!hpke->is_sender) {
OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (hpke->seq == UINT64_MAX) {
OPENSSL_PUT_ERROR(EVP, ERR_R_OVERFLOW);
return 0;
}
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
const size_t nonce_len = EVP_AEAD_nonce_length(hpke->aead_ctx.aead);
hpke_nonce(hpke, nonce, nonce_len);
if (!EVP_AEAD_CTX_seal(&hpke->aead_ctx, out, out_len, max_out_len, nonce,
nonce_len, in, in_len, ad, ad_len)) {
return 0;
}
hpke->seq++;
return 1;
}
int EVP_HPKE_CTX_export(const EVP_HPKE_CTX *hpke, uint8_t *out,
size_t secret_len, const uint8_t *context,
size_t context_len) {
uint8_t suite_id[HPKE_SUITE_ID_LEN];
if (!hpke_build_suite_id(suite_id, hpke->kdf_id, hpke->aead_id)) {
return 0;
}
static const char kExportExpandLabel[] = "sec";
if (!hpke_labeled_expand(hpke->hkdf_md, out, secret_len,
hpke->exporter_secret, EVP_MD_size(hpke->hkdf_md),
suite_id, sizeof(suite_id), kExportExpandLabel,
context, context_len)) {
return 0;
}
return 1;
}
+382
View File
@@ -0,0 +1,382 @@
/* 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 <cstdint>
#include <string>
#include <limits>
#include <vector>
#include <gtest/gtest.h>
#include <openssl/base.h>
#include <openssl/curve25519.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include "../test/file_test.h"
#include "../test/test_util.h"
#include "internal.h"
namespace bssl {
namespace {
// HpkeTestVector corresponds to one array member in the published
// test-vectors.json.
class HpkeTestVector {
public:
explicit HpkeTestVector() = default;
~HpkeTestVector() = default;
bool ReadFromFileTest(FileTest *t);
void Verify() const {
// Set up the sender.
ScopedEVP_HPKE_CTX sender_ctx;
ASSERT_GT(secret_key_e_.size(), 0u);
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519_for_test(
sender_ctx.get(), kdf_id_, aead_id_, public_key_r_.data(), info_.data(),
info_.size(), secret_key_e_.data(), public_key_e_.data()));
// Set up the receiver.
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), kdf_id_, aead_id_, public_key_e_.data(),
public_key_r_.data(), secret_key_r_.data(), info_.data(),
info_.size()));
VerifyEncryptions(sender_ctx.get(), receiver_ctx.get());
VerifyExports(sender_ctx.get());
VerifyExports(receiver_ctx.get());
}
private:
void VerifyEncryptions(EVP_HPKE_CTX *sender_ctx,
EVP_HPKE_CTX *receiver_ctx) const {
for (const Encryption &task : encryptions_) {
std::vector<uint8_t> encrypted(task.plaintext.size() +
EVP_HPKE_CTX_max_overhead(sender_ctx));
size_t encrypted_len;
ASSERT_TRUE(EVP_HPKE_CTX_seal(
sender_ctx, encrypted.data(), &encrypted_len, encrypted.size(),
task.plaintext.data(), task.plaintext.size(), task.aad.data(),
task.aad.size()));
ASSERT_EQ(Bytes(encrypted.data(), encrypted_len), Bytes(task.ciphertext));
std::vector<uint8_t> decrypted(task.ciphertext.size());
size_t decrypted_len;
ASSERT_TRUE(EVP_HPKE_CTX_open(
receiver_ctx, decrypted.data(), &decrypted_len, decrypted.size(),
task.ciphertext.data(), task.ciphertext.size(), task.aad.data(),
task.aad.size()));
ASSERT_EQ(Bytes(decrypted.data(), decrypted_len), Bytes(task.plaintext));
}
}
void VerifyExports(EVP_HPKE_CTX *ctx) const {
for (const Export &task : exports_) {
std::vector<uint8_t> exported_secret(task.exportLength);
ASSERT_TRUE(EVP_HPKE_CTX_export(
ctx, exported_secret.data(), exported_secret.size(),
task.exportContext.data(), task.exportContext.size()));
ASSERT_EQ(Bytes(exported_secret), Bytes(task.exportValue));
}
}
struct Encryption {
std::vector<uint8_t> aad;
std::vector<uint8_t> ciphertext;
std::vector<uint8_t> plaintext;
};
struct Export {
std::vector<uint8_t> exportContext;
size_t exportLength;
std::vector<uint8_t> exportValue;
};
uint16_t kdf_id_;
uint16_t aead_id_;
std::vector<uint8_t> context_;
std::vector<uint8_t> info_;
std::vector<uint8_t> public_key_e_;
std::vector<uint8_t> secret_key_e_;
std::vector<uint8_t> public_key_r_;
std::vector<uint8_t> secret_key_r_;
std::vector<Encryption> encryptions_;
std::vector<Export> exports_;
};
// Match FileTest's naming scheme for duplicated attribute names.
std::string BuildAttrName(const std::string &name, int iter) {
return iter == 1 ? name : name + "/" + std::to_string(iter);
}
// Parses |s| as an unsigned integer of type T and writes the value to |out|.
// Returns true on success. If the integer value exceeds the maximum T value,
// returns false.
template <typename T>
bool ParseIntSafe(T *out, const std::string &s) {
T value = 0;
for (char c : s) {
if (c < '0' || c > '9') {
return false;
}
if (value > (std::numeric_limits<T>::max() - (c - '0')) / 10) {
return false;
}
value = 10 * value + (c - '0');
}
*out = value;
return true;
}
// Read the |key| attribute from |file_test| and convert it to an integer.
template <typename T>
bool FileTestReadInt(FileTest *file_test, T *out, const std::string &key) {
std::string s;
return file_test->GetAttribute(&s, key) && ParseIntSafe(out, s);
}
bool HpkeTestVector::ReadFromFileTest(FileTest *t) {
if (!FileTestReadInt(t, &kdf_id_, "kdfID") ||
!FileTestReadInt(t, &aead_id_, "aeadID") ||
!t->GetBytes(&info_, "info") ||
!t->GetBytes(&secret_key_r_, "skRm") ||
!t->GetBytes(&public_key_r_, "pkRm") ||
!t->GetBytes(&secret_key_e_, "skEm") ||
!t->GetBytes(&public_key_e_, "pkEm")) {
return false;
}
for (int i = 1; t->HasAttribute(BuildAttrName("aad", i)); i++) {
Encryption encryption;
if (!t->GetBytes(&encryption.aad, BuildAttrName("aad", i)) ||
!t->GetBytes(&encryption.ciphertext, BuildAttrName("ciphertext", i)) ||
!t->GetBytes(&encryption.plaintext, BuildAttrName("plaintext", i))) {
return false;
}
encryptions_.push_back(std::move(encryption));
}
for (int i = 1; t->HasAttribute(BuildAttrName("exportContext", i)); i++) {
Export exp;
if (!t->GetBytes(&exp.exportContext, BuildAttrName("exportContext", i)) ||
!FileTestReadInt(t, &exp.exportLength,
BuildAttrName("exportLength", i)) ||
!t->GetBytes(&exp.exportValue, BuildAttrName("exportValue", i))) {
return false;
}
exports_.push_back(std::move(exp));
}
return true;
}
} // namespace
TEST(HPKETest, VerifyTestVectors) {
FileTestGTest("crypto/hpke/hpke_test_vectors.txt", [](FileTest *t) {
HpkeTestVector test_vec;
EXPECT_TRUE(test_vec.ReadFromFileTest(t));
test_vec.Verify();
});
}
// The test vectors used fixed sender ephemeral keys, while HPKE itself
// generates new keys for each context. Test this codepath by checking we can
// decrypt our own messages.
TEST(HPKETest, RoundTrip) {
uint16_t kdf_ids[] = {EVP_HPKE_HKDF_SHA256, EVP_HPKE_HKDF_SHA384,
EVP_HPKE_HKDF_SHA512};
uint16_t aead_ids[] = {EVP_HPKE_AEAD_AES_GCM_128, EVP_HPKE_AEAD_AES_GCM_256,
EVP_HPKE_AEAD_CHACHA20POLY1305};
const uint8_t info_a[] = {1, 1, 2, 3, 5, 8};
const uint8_t info_b[] = {42, 42, 42};
const uint8_t ad_a[] = {1, 2, 4, 8, 16};
const uint8_t ad_b[] = {7};
Span<const uint8_t> info_values[] = {{nullptr, 0}, info_a, info_b};
Span<const uint8_t> ad_values[] = {{nullptr, 0}, ad_a, ad_b};
// Generate the receiver's keypair.
uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(public_key_r, secret_key_r);
for (uint16_t kdf_id : kdf_ids) {
for (uint16_t aead_id : aead_ids) {
for (const Span<const uint8_t> &info : info_values) {
for (const Span<const uint8_t> &ad : ad_values) {
// Set up the sender.
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), enc, kdf_id, aead_id, public_key_r, info.data(),
info.size()));
// Set up the receiver.
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), kdf_id, aead_id, enc, public_key_r,
secret_key_r, info.data(), info.size()));
const char kCleartextPayload[] = "foobar";
// Have sender encrypt message for the receiver.
std::vector<uint8_t> ciphertext(
sizeof(kCleartextPayload) +
EVP_HPKE_CTX_max_overhead(sender_ctx.get()));
size_t ciphertext_len;
ASSERT_TRUE(EVP_HPKE_CTX_seal(
sender_ctx.get(), ciphertext.data(), &ciphertext_len,
ciphertext.size(),
reinterpret_cast<const uint8_t *>(kCleartextPayload),
sizeof(kCleartextPayload), ad.data(), ad.size()));
// Have receiver decrypt the message.
std::vector<uint8_t> cleartext(ciphertext.size());
size_t cleartext_len;
ASSERT_TRUE(EVP_HPKE_CTX_open(receiver_ctx.get(), cleartext.data(),
&cleartext_len, cleartext.size(),
ciphertext.data(), ciphertext_len,
ad.data(), ad.size()));
// Verify that decrypted message matches the original.
ASSERT_EQ(Bytes(cleartext.data(), cleartext_len),
Bytes(kCleartextPayload, sizeof(kCleartextPayload)));
}
}
}
}
}
// Verify that the DH operations inside Encap() and Decap() both fail when the
// public key is on a small-order point in the curve.
TEST(HPKETest, X25519EncapSmallOrderPoint) {
// Borrowed from X25519Test.SmallOrder.
static const uint8_t kSmallOrderPoint[32] = {
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
};
// Generate a valid keypair for the receiver.
uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(public_key_r, secret_key_r);
uint16_t kdf_ids[] = {EVP_HPKE_HKDF_SHA256, EVP_HPKE_HKDF_SHA384,
EVP_HPKE_HKDF_SHA512};
uint16_t aead_ids[] = {EVP_HPKE_AEAD_AES_GCM_128, EVP_HPKE_AEAD_AES_GCM_256,
EVP_HPKE_AEAD_CHACHA20POLY1305};
for (uint16_t kdf_id : kdf_ids) {
for (uint16_t aead_id : aead_ids) {
// Set up the sender, passing in kSmallOrderPoint as |peer_public_value|.
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), enc, kdf_id, aead_id, kSmallOrderPoint, nullptr,
0));
// Set up the receiver, passing in kSmallOrderPoint as |enc|.
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_FALSE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), kdf_id, aead_id, kSmallOrderPoint, public_key_r,
secret_key_r, nullptr, 0));
}
}
}
// Test that Seal() fails when the context has been initialized as a receiver.
TEST(HPKETest, ReceiverInvalidSeal) {
const uint8_t kMockEnc[X25519_PUBLIC_VALUE_LEN] = {0xff};
const char kCleartextPayload[] = "foobar";
// Generate the receiver's keypair.
uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(public_key_r, secret_key_r);
// Set up the receiver.
ScopedEVP_HPKE_CTX receiver_ctx;
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_r_x25519(
receiver_ctx.get(), EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
kMockEnc, public_key_r, secret_key_r, nullptr, 0));
// Call Seal() on the receiver.
size_t ciphertext_len;
uint8_t ciphertext[100];
ASSERT_FALSE(EVP_HPKE_CTX_seal(
receiver_ctx.get(), ciphertext, &ciphertext_len, sizeof(ciphertext),
reinterpret_cast<const uint8_t *>(kCleartextPayload),
sizeof(kCleartextPayload), nullptr, 0));
}
// Test that Open() fails when the context has been initialized as a sender.
TEST(HPKETest, SenderInvalidOpen) {
const uint8_t kMockCiphertext[100] = {0xff};
const size_t kMockCiphertextLen = 80;
// Generate the receiver's keypair.
uint8_t secret_key_r[X25519_PRIVATE_KEY_LEN];
uint8_t public_key_r[X25519_PUBLIC_VALUE_LEN];
X25519_keypair(public_key_r, secret_key_r);
// Set up the sender.
ScopedEVP_HPKE_CTX sender_ctx;
uint8_t enc[X25519_PUBLIC_VALUE_LEN];
ASSERT_TRUE(EVP_HPKE_CTX_setup_base_s_x25519(
sender_ctx.get(), enc, EVP_HPKE_HKDF_SHA256, EVP_HPKE_AEAD_AES_GCM_128,
public_key_r, nullptr, 0));
// Call Open() on the sender.
uint8_t cleartext[128];
size_t cleartext_len;
ASSERT_FALSE(EVP_HPKE_CTX_open(sender_ctx.get(), cleartext, &cleartext_len,
sizeof(cleartext), kMockCiphertext,
kMockCiphertextLen, nullptr, 0));
}
TEST(HPKETest, InternalParseIntSafe) {
uint8_t u8 = 0xff;
ASSERT_FALSE(ParseIntSafe(&u8, "-1"));
ASSERT_TRUE(ParseIntSafe(&u8, "0"));
ASSERT_EQ(u8, 0);
ASSERT_TRUE(ParseIntSafe(&u8, "255"));
ASSERT_EQ(u8, 255);
ASSERT_FALSE(ParseIntSafe(&u8, "256"));
uint16_t u16 = 0xffff;
ASSERT_TRUE(ParseIntSafe(&u16, "257"));
ASSERT_EQ(u16, 257);
ASSERT_TRUE(ParseIntSafe(&u16, "65535"));
ASSERT_EQ(u16, 65535);
ASSERT_FALSE(ParseIntSafe(&u16, "65536"));
}
} // namespace bssl
+407
View File
@@ -0,0 +1,407 @@
kdfID = 1
aeadID = 1
info = 4f6465206f6e2061204772656369616e2055726e
skRm = b3e438a60baef3800d7efd1c4c83c67e003c7c2b36b671b3e51d570f5c224cc6
skEm = 46baf826b58e5ad2e6277de734fe5c0bc88d49a3d26d937f2f8b0ef0e361adcc
pkRm = 1b033b44a9f9fa57fddd7b583a310f3f8e550099d3af284709ca9eab4fa34673
pkEm = 7d832f404f70071d69f285292f0758291f966274fdc5fa494bf6f1bbf81c2252
# encryptions[0]
aad = 436f756e742d30
ciphertext = 437ee37ee8210fcda87a7aae7c5e97b0caf37b93e70b916444cd9762fa3aa2fc877bae2fe16dee3924968063bf
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[1]
aad = 436f756e742d31
ciphertext = 448fdab5b1331bc2daf1c3e4de42da186c1180235cccf69af0062cb22d646e48cdcd8babe828c3367ba1056c2c
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[2]
aad = 436f756e742d32
ciphertext = 78af7509a1b84eae6f59b1bdccef888421b020a97f1a6be270363e5c45005389418e73235a942f9fd46b37a352
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[3]
aad = 436f756e742d33
ciphertext = 5152f55bf389fba1eeb972a88b7a7391f1102b2105f78b1a03baad2543b0ac008f7a59ea64ec044d43d7aeebf8
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[4]
aad = 436f756e742d34
ciphertext = d4939ff18065a54b1e988c72649aa81b1bbdcf9496d150efbe2c03c084f6477653bc03fd58a58a03d4ab78e47b
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[5]
aad = 436f756e742d35
ciphertext = 771277b0c50eab4b1aa802b019391f52d2e08459ffea6ca84de9ad691414d15ed9f6f091b3a2190d01e364394c
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[6]
aad = 436f756e742d36
ciphertext = 914144c371d68501260ce1281e9d4b86710a4184f734e0d00dca765c8e2ffbde118ca63019b749717afc99cc6a
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[7]
aad = 436f756e742d37
ciphertext = 91c6f9894280f4185b9a1f66d11afd94a81884306c73159b9bad702cf568bbcb5424ecb32388fdf1b0523b99ba
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[8]
aad = 436f756e742d38
ciphertext = 8901bd3602f5fc51b85367695a4f003e0094e86f01a8564434b12ca2ad290d13476772ae87fbbb091b1a755981
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[9]
aad = 436f756e742d39
ciphertext = e996c46f77eadd23098140d3223c4b890d1a9ed5b8e02941ab5c93fc370ddbf9477edc26b48b3ec6b8067e32d2
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# exports[0]
exportContext = 436f6e746578742d30
exportLength = 32
exportValue = 9bc841c822d823b56312319e28775373eb5ba1259b6c721393f9bf9868f0ba8e
# exports[1]
exportContext = 436f6e746578742d31
exportLength = 32
exportValue = dd76d8a3fbfd50a6468c0a332ebd50ac518ca1747ce5014b4d6fb584968246eb
# exports[2]
exportContext = 436f6e746578742d32
exportLength = 32
exportValue = 3a70fe6e8409f204bcfada3d8795c59a676de533d2451b4d5e7506ec48529277
# exports[3]
exportContext = 436f6e746578742d33
exportLength = 32
exportValue = 1a5df4a86790fbbe9164463d927ba7b7c7f3daea8d1f39576076b00f03b7372e
# exports[4]
exportContext = 436f6e746578742d34
exportLength = 32
exportValue = 03d04b52901947dea1d034489cbc07d8cb94aa3365842c5bb1b6ca52969b86ba
kdfID = 1
aeadID = 2
info = 4f6465206f6e2061204772656369616e2055726e
skRm = da634eee68734edcd50b2b14c73262fa3ed2726cc85d3c328ccdaabbbec9d53d
skEm = e28ec716ac495417440ef674ccf438722932da41b5481b8826f4f7947c4d9069
pkRm = 1ea4497701b05912be470df9d06ee114b825b9f9feec09f6aa9b2ca6b7be1360
pkEm = 1a468c14ca9d0615f9a14b565c0625058f9b56485006dcab10d762e5260d3041
# encryptions[0]
aad = 436f756e742d30
ciphertext = bb9270559e7f209f764aca4e186040a561e6f2a4f34d6edc59163786ccc41231166f40bf6699f45bc11e25163f
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[1]
aad = 436f756e742d31
ciphertext = d6743a322f18e3fff2d06e3912b3d484c315772bee09929dba1a27e8e93f11fbced8efbf45d422210bb09f52e5
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[2]
aad = 436f756e742d32
ciphertext = 89964cbd1aedd4398a9e0fcca0ac245d04e6823666ea639be02bb9ad1bb297e9a974ea1c489414a8e5032a3609
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[3]
aad = 436f756e742d33
ciphertext = bc8f37b1f7b179b6e97ae97dd08674a7124e9af73b6131b3bff3a071027c27a3e8210522130ad7c2ad20afbbec
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[4]
aad = 436f756e742d34
ciphertext = e2477e3230130508f8ff9a076b3ff0b4d162defd595962f10dceb9caf72ddddfd8739b184c92a7546e1ad93d49
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[5]
aad = 436f756e742d35
ciphertext = ee5d485f2e6670b65d7a31fb134823016d3f9059b12bfbda706c4e592f862aca43631f94619f7ad2126bbdf771
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[6]
aad = 436f756e742d36
ciphertext = a7ebc5793d72288bd382222aae883355a5eab73ba5c7271d66328e1825f3b9f0418e1b204933374e4dd55d8316
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[7]
aad = 436f756e742d37
ciphertext = 2a5bb8b837de5b0bfea4070918c27c9aadea777bc043189a12dd78aacc197aef16ec3f4d90e7889f8962181bfe
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[8]
aad = 436f756e742d38
ciphertext = 5fbab7888d1df36f9a7f7607dfc67eb2878e87cb4972fb5e0f2dd6570153c5f64a21bd042fa1a07135482e9767
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[9]
aad = 436f756e742d39
ciphertext = ac94f708e42b900361fabe181d638d03faf663530bdb635944d5fc48425ee2598b311ba6c7b2495ab9cec34338
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# exports[0]
exportContext = 436f6e746578742d30
exportLength = 32
exportValue = 57c5a85e2538d066a529c321a740e0dba3ab413b5d7a74fd5e9c535dc92a9c93
# exports[1]
exportContext = 436f6e746578742d31
exportLength = 32
exportValue = adae370a00458fe0815fb39e0c6708a1e32d8a41d299ec6ec3ff0b3aafa5e9ef
# exports[2]
exportContext = 436f6e746578742d32
exportLength = 32
exportValue = 68ddde9847cf50fc0c31eb94a5071c119a4f018bbcff323614b4664808e9567b
# exports[3]
exportContext = 436f6e746578742d33
exportLength = 32
exportValue = 6d0684b38f5f05aceefeaaa17bf71b39d5379940761bd38cb0499161565394cf
# exports[4]
exportContext = 436f6e746578742d34
exportLength = 32
exportValue = c694953e7e6df9c1d74550b5d54b62a316227c5b08c8f1ff51f124d29b3ae2f8
kdfID = 1
aeadID = 3
info = 4f6465206f6e2061204772656369616e2055726e
skRm = 677b64ff70915fb0404a1905139013a33fcdbc39f3d1914a007984e2413eca48
skEm = 22e0948a3fd086e7ec1cb96155499962bc470680db725dd008d39d25f6191bf6
pkRm = 02bd698c34ef1c3ec60d5b209135310d52e125038a0ce0bf1e0ee2c8dfc20e55
pkEm = de17360c5c7f244cd06ebc73f2808195329ea69ff829410a6450040d50af363f
# encryptions[0]
aad = 436f756e742d30
ciphertext = b706a7523384a553fb1c44d5d3186bb78484947cd17e72f15f1c83152510e49680cac8f057f175187e94f18083
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[1]
aad = 436f756e742d31
ciphertext = cdc1a9425ceea83e9f1d0a2be77525460cbe259d1a9314eba520c5f5f879376a9ad7f8672ec943de425c6655c8
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[2]
aad = 436f756e742d32
ciphertext = 5bb2028896d91f156cd6e171d1470361bc07aa804a3ed64163ea67da67bce84e3d2f73b8d75f9a4dcb452b97e6
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[3]
aad = 436f756e742d33
ciphertext = 220790f4242aa714ad2c44967810cc8c9483e1833d7f9dadd08999abd892aeb3fb1ca54a29c4ea22d1395d85d3
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[4]
aad = 436f756e742d34
ciphertext = 73973035d480c8299d1773522b738af626a5c834fc6af5ef5f8778fa6a767da89660f4aea7b4241b1f8b5cdebd
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[5]
aad = 436f756e742d35
ciphertext = 2e35688b0bed657bc213ce0c960e478e2d708700b3b3ff7048bc62130f23a0752ad867167f1d1b709a48ea89c8
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[6]
aad = 436f756e742d36
ciphertext = 14dd79e4ee9e416dfb954e4f0d73c44757ad375018a802cd0c4a7ba3fe378e5c8cc4cf21e648e6a8645a085cad
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[7]
aad = 436f756e742d37
ciphertext = a996ed2f2680a15351eeb87643b99b558a59d8c1114a214acc8bf3dbe6b40c4d41e06ce8b1e11e795e37c75143
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[8]
aad = 436f756e742d38
ciphertext = 8123ec5ffb77c7395bdf2baf9c73cd2b1bbfa0ec79870a1d6260189b559af29a9478c2675c82bd1e19d2e422bb
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[9]
aad = 436f756e742d39
ciphertext = 55c9731edc92dee7683bbabc425fafa4dd199aaf74569bec1bbf79e082eab9006392ea1b3a2d07622b62bf0bbf
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# exports[0]
exportContext = 436f6e746578742d30
exportLength = 32
exportValue = bed211016a1fcc4328de46fd11d8be1f00a7e2c17979450e760c152fb77bc825
# exports[1]
exportContext = 436f6e746578742d31
exportLength = 32
exportValue = f1c29485807379d0deec17a65606307c2723a1653ecb1bb601ed5f703623fec9
# exports[2]
exportContext = 436f6e746578742d32
exportLength = 32
exportValue = 477680ef89421fd862866dfe00b70ac8906785c2346db09c8a868b0c23c28e98
# exports[3]
exportContext = 436f6e746578742d33
exportLength = 32
exportValue = d0d5e1460ed084ae579eb5408d03d99482d74b5293e7aa19df06acbf16af8fab
# exports[4]
exportContext = 436f6e746578742d34
exportLength = 32
exportValue = f5fec947f00eccf828dcd4f1b405a115001cce97f3bc0d6f8c831f1cbebce36f
kdfID = 3
aeadID = 1
info = 4f6465206f6e2061204772656369616e2055726e
skRm = 2ad8f8d251b97bdb392dcf671af13d6d26041e411faad5c984f68efaaa3b88b6
skEm = b841f4832197fc363c965592a97fa762b04683114a9126f56dfff82c49a6f207
pkRm = 6421cec0bf7fdead5b4d3f70acbf6f08577fe73961708e31d6df522d4ad6b20e
pkEm = 04ecf81b3a34094121586e4d237fcb9df92df22bb7ae2c0c7c187d839c29b953
# encryptions[0]
aad = 436f756e742d30
ciphertext = 9c4a9834cf1d2bfd16c7fe0a19f9f66afaecb805e06c212f08c245f772de9123e1bf41678f2e910a20158a0273
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[1]
aad = 436f756e742d31
ciphertext = 1bb872e187c72ac6f89db81309d0fe2c57787efc3d076aab394e0218e33955039650da12e3f0241fd52cef41a5
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[2]
aad = 436f756e742d32
ciphertext = c5a95f473b853e190b5eab703080c9ddf313d7e6751b2af382ad7f8e910c897757d7256801ef83e408795453c9
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[3]
aad = 436f756e742d33
ciphertext = 1b5a3d36a34781f93f5508dabc74bd3c82a47bd05af7b2729ef254f42d5a068fa86a918c9cbe1db552d2d8d4d9
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[4]
aad = 436f756e742d34
ciphertext = 46d9196849ad448e03a7603bb0eb2775586463051f2497f39cdd9211d1fd8ff71c97428639b0764f0ffba29f32
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[5]
aad = 436f756e742d35
ciphertext = 346a0ecb07e20f32174095a32ef87fde07cefa99fbc70d2cda903fdb8128c204037e7c659b40047e66fc416e19
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[6]
aad = 436f756e742d36
ciphertext = 41331c5365a8354fe9f221f0ebc6344bd86dfffe253da5cfa06d08089a6e0312e9c18ef57509c9faa2d0995650
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[7]
aad = 436f756e742d37
ciphertext = b2ff99114ab4b8267f005bb6554b766d6f6c8274c2c669a325354cfb27034afaf0f6f7eb56901292ff804e7553
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[8]
aad = 436f756e742d38
ciphertext = ae653f1d8dc035745b7e3fc2f81e4e6636f0597a9b6f6f1c7d5b0a23c50d76e1dc0a7cf4fa3b3126e12011302c
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[9]
aad = 436f756e742d39
ciphertext = 0266729d852d16e9af909841bbe2444bccfab0575cd1c84ff6ddbf3259627fd5b73d24f402bb60bfbee1715951
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# exports[0]
exportContext = 436f6e746578742d30
exportLength = 32
exportValue = 3dba6be0ff119e093d6260766375f0f80c461c6592735ff58a1cf8989805192d
# exports[1]
exportContext = 436f6e746578742d31
exportLength = 32
exportValue = e43ef15f82fd672484625d6d3d8b1b157a98a20a6f55c4c084d2fd76b63d3be7
# exports[2]
exportContext = 436f6e746578742d32
exportLength = 32
exportValue = 237c2e9a25524ca44ff5683b62e2fb366c583fbb72644b7208e7594e9d3221a5
# exports[3]
exportContext = 436f6e746578742d33
exportLength = 32
exportValue = b421f68b38b2bb916e0925a21c80d1a8227ec6ad9a1e1539229142486f88c8af
# exports[4]
exportContext = 436f6e746578742d34
exportLength = 32
exportValue = 7736ddde377f0bf3da742d7baac698812a267441c3bcf86b72fed0503bfbac0c
kdfID = 3
aeadID = 2
info = 4f6465206f6e2061204772656369616e2055726e
skRm = 7dddb757b5c12c7c28b4f7a7e3f4d10f5d077e5d410a66997cb4e73b69e824d7
skEm = 089af845076a811768c8eaed47322755f47f4907d2610a1629893d6e1143acca
pkRm = ffe3129f906112823ec1c619e0025f5a44cd5a93e0807c61c91336aa22222f6e
pkEm = 9bf7495a8ed10966c9f285170ce99ee8aa686095cb1f44500324fae45aba7953
# encryptions[0]
aad = 436f756e742d30
ciphertext = b2263e5b1651fae482259475f2d71d5a95e430ea360c88cfe656ef8cef6a97fec94d0bfb996bd794a183269368
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[1]
aad = 436f756e742d31
ciphertext = b502c5fb389b8c128f58065f6767063132c53a401300679df875a1688f0d05a0b2e3859add4fe82891356690c8
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[2]
aad = 436f756e742d32
ciphertext = a0afe304ea046340a3c8c8806f227a2ad6d8a48b583bc6a766af0cd0b0231dc3806d597651b5805cd9062e1f87
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[3]
aad = 436f756e742d33
ciphertext = 75b462e185cd1af728b4853152379f59af8a29af409a206c9d63b02042089d28662eac4d2af800138bcc52cd34
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[4]
aad = 436f756e742d34
ciphertext = 2d6a758ac9da40a3a1b965152941bf58602f56e12db95636ad5d9c465a1872884e795ec232bd591ea804829458
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[5]
aad = 436f756e742d35
ciphertext = dd2e30e1c9b30a0130e88e96239ade666961a8de16d79b75d638ede224d662509a17404e7479097c1658921047
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[6]
aad = 436f756e742d36
ciphertext = bc20bc221ea15f84e41774bc11b684f074d414be09659b147f186891325f7d52b7d19ae57d9fff88cc4ba825a2
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[7]
aad = 436f756e742d37
ciphertext = 6ef4d0678cf026651f56c53719a678b178105e1a791051076f2567364a536e8aac76bac03178b2276337e12320
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[8]
aad = 436f756e742d38
ciphertext = 5da431e3723f549ccada9d122ccd127b031c9a221c7bb360e742e7c0f68fc81d012df7aa1c6181980ce793644c
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[9]
aad = 436f756e742d39
ciphertext = 9ba2c8e0477d370d71b486c3f52a9f9ef99d7e8991eb50b2692d777e552801f0a7f7deb8d0567ca8575b4c2331
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# exports[0]
exportContext = 436f6e746578742d30
exportLength = 32
exportValue = 9fda6d97dafe3768680d87a5e10fe251aa46693329ebdf56f49b3c467b76e9c0
# exports[1]
exportContext = 436f6e746578742d31
exportLength = 32
exportValue = 4c9e496f3265a28a73ce85b3143a5ffba3b55ce8025d735e9ed39aebaab80efe
# exports[2]
exportContext = 436f6e746578742d32
exportLength = 32
exportValue = 2425dfcdf16879e51f6c6f3c0d0d0f814d132ad575ce416b7485facd34bb42b9
# exports[3]
exportContext = 436f6e746578742d33
exportLength = 32
exportValue = 51f1bdf3bf8bce5b10b76c957034ce3630fe7fc1be7c00bcec7e837ceed2f3cd
# exports[4]
exportContext = 436f6e746578742d34
exportLength = 32
exportValue = 80ad324b3e7763a7309ce0615fe8bb5723065be5aa7f68a7ca9e3d3a76c0a0f3
kdfID = 3
aeadID = 3
info = 4f6465206f6e2061204772656369616e2055726e
skRm = 124759e117f6aa5677c747d09a2d82607db2a388a6473647aeb605b66822819c
skEm = 70fe54f14893759e23b4c975cfcb8cbc1ae9b8a4d78a48789a5f47324bda5b84
pkRm = 0b9c41a605aba4ffa30f336a976cf4f30a1dd5e8fdf0d4da0f745a147e491828
pkEm = 147b25161de4080624c11d1cde83d5a571ba17201385ca22302b9509d1101e46
# encryptions[0]
aad = 436f756e742d30
ciphertext = 77f434a667845f41c5bf5e6e6113484d45fbf7fd61cc36a141b920e4bb5b6ad3a61c67033a15dc495e8595ef45
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[1]
aad = 436f756e742d31
ciphertext = e5f64ec06a92fb2f81ad6203629d981c265aee092b3e20ddc161e163c0a29d1b9fcc7ddb5dede6d34571406f50
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[2]
aad = 436f756e742d32
ciphertext = 9252583ed8c5258877afa5dac29acb338cf57c702b03d20130b86234b231e3866b1732369cf6c7fdaace68c246
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[3]
aad = 436f756e742d33
ciphertext = d5c2e0a633d6786a7d919f40c26ee8a1491a4101a441460d51720ff769b86a71ff74fc9601bd8f4c597d95c057
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[4]
aad = 436f756e742d34
ciphertext = 807165bdd35f448b9b649ce3ec8a9835836ef88dab28c5a77d0f46bac1dd6f543ebd64bbd7840c860c5a2d1ee5
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[5]
aad = 436f756e742d35
ciphertext = 208e3adb17a694d567a84428ecf76a562d38fbee827e245eb0e96426429c3a32805f9f675b99a28325c11a9d51
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[6]
aad = 436f756e742d36
ciphertext = f34e3f00d1b731786b5b7ab0e4bf23fd8f3889d6ee75ca9de755d22f8e099ef0d92a6ab4d6e635c788faaac588
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[7]
aad = 436f756e742d37
ciphertext = fd45de4d582f57bd5228688c0e08553c3e3d6a875bcd1c67e196b94fc6238ddbf69a17186416669b0ee124bddb
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[8]
aad = 436f756e742d38
ciphertext = 6416f410aa1aecb24c8c17cd9b6eabda1bfee2bd13aa52c5dfc80c482236b99568de15b3543522486dc594dc13
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# encryptions[9]
aad = 436f756e742d39
ciphertext = 2bc1f3380dc05ce46a004a679dca47cdc46d25b02662274442562e1f03db3860d1abf28027718cb73a6c2c05f8
plaintext = 4265617574792069732074727574682c20747275746820626561757479
# exports[0]
exportContext = 436f6e746578742d30
exportLength = 32
exportValue = 73ceb7e41223a42a3e6661f15530ae494ecfd2c6a9e809c67243a0910ee75794
# exports[1]
exportContext = 436f6e746578742d31
exportLength = 32
exportValue = 9af39f0e6462be9a3efb1fe2eedc6e2d2942c0c9ecae1ee4e8831d675cce6fc4
# exports[2]
exportContext = 436f6e746578742d32
exportLength = 32
exportValue = 0ea567aa2da373a71ff88cc6b91abc8b1dd48baaf032f878a5e6d9335f813003
# exports[3]
exportContext = 436f6e746578742d33
exportLength = 32
exportValue = ee6ca654a57a66cd0315716d709d4c52f5f41a69249776c13077967c4c418af2
# exports[4]
exportContext = 436f6e746578742d34
exportLength = 32
exportValue = 50dfd00952f71e8c1bd51ed6acde15bd558c97581f7dc17fe6e637d61e12df02
+192
View File
@@ -0,0 +1,192 @@
/* 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_CRYPTO_HPKE_INTERNAL_H
#define OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H
#include <openssl/aead.h>
#include <openssl/base.h>
#include <openssl/curve25519.h>
#if defined(__cplusplus)
extern "C" {
#endif
// Hybrid Public Key Encryption.
//
// Hybrid Public Key Encryption (HPKE) enables a sender to encrypt messages to a
// receiver with a public key.
//
// See https://tools.ietf.org/html/draft-irtf-cfrg-hpke-04.
// EVP_HPKE_AEAD_* are AEAD identifiers.
#define EVP_HPKE_AEAD_AES_GCM_128 0x0001
#define EVP_HPKE_AEAD_AES_GCM_256 0x0002
#define EVP_HPKE_AEAD_CHACHA20POLY1305 0x0003
// EVP_HPKE_HKDF_* are HKDF identifiers.
#define EVP_HPKE_HKDF_SHA256 0x0001
#define EVP_HPKE_HKDF_SHA384 0x0002
#define EVP_HPKE_HKDF_SHA512 0x0003
// EVP_HPKE_MAX_OVERHEAD contains the largest value that
// |EVP_HPKE_CTX_max_overhead| would ever return for any context.
#define EVP_HPKE_MAX_OVERHEAD EVP_AEAD_MAX_OVERHEAD
// Encryption contexts.
// An |EVP_HPKE_CTX| is an HPKE encryption context.
typedef struct evp_hpke_ctx_st {
const EVP_MD *hkdf_md;
EVP_AEAD_CTX aead_ctx;
uint16_t kdf_id;
uint16_t aead_id;
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
uint8_t exporter_secret[EVP_MAX_MD_SIZE];
uint64_t seq;
int is_sender;
} EVP_HPKE_CTX;
// EVP_HPKE_CTX_init initializes an already-allocated |EVP_HPKE_CTX|. The caller
// should then use one of the |EVP_HPKE_CTX_setup_*| functions.
//
// It is safe, but not necessary to call |EVP_HPKE_CTX_cleanup| in this state.
OPENSSL_EXPORT void EVP_HPKE_CTX_init(EVP_HPKE_CTX *ctx);
// EVP_HPKE_CTX_cleanup releases memory referenced by |ctx|. |ctx| must have
// been initialized with |EVP_HPKE_CTX_init|.
OPENSSL_EXPORT void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx);
// Setting up HPKE contexts.
//
// In each of the following functions, |hpke| must have been initialized with
// |EVP_HPKE_CTX_init|. |kdf_id| selects the KDF for non-KEM HPKE operations and
// must be one of the |EVP_HPKE_HKDF_*| constants. |aead_id| selects the AEAD
// for the "open" and "seal" operations and must be one of the |EVP_HPKE_AEAD_*"
// constants."
//
// See https://www.ietf.org/id/draft-irtf-cfrg-hpke-04.html#section-5.1.1.
// EVP_HPKE_CTX_setup_base_s_x25519 sets up |hpke| as a sender context that can
// encrypt for the private key corresponding to |peer_public_value| (the
// recipient's public key). It returns one on success, and zero otherwise. Note
// that this function may fail if |peer_public_value| is invalid.
//
// This function writes the encapsulated shared secret to |out_enc|.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519(
EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN],
uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len);
// EVP_HPKE_CTX_setup_base_s_x25519_for_test behaves like
// |EVP_HPKE_CTX_setup_base_s_x25519|, but takes a pre-generated ephemeral
// sender key.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519_for_test(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t *info, size_t info_len,
const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN],
const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]);
// EVP_HPKE_CTX_setup_base_r_x25519 sets up |hpke| as a recipient context that
// can decrypt messages. |private_key| is the recipient's private key, and |enc|
// is the encapsulated shared secret from the sender. Note that this function
// may fail if |enc| is invalid.
OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_r_x25519(
EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id,
const uint8_t enc[X25519_PUBLIC_VALUE_LEN],
const uint8_t public_key[X25519_PUBLIC_VALUE_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info,
size_t info_len);
// Using an HPKE context.
// EVP_HPKE_CTX_open uses the HPKE context |hpke| to authenticate |in_len| bytes
// from |in| and |ad_len| bytes from |ad| and to decrypt at most |in_len| bytes
// into |out|. It returns one on success, and zero otherwise.
//
// This operation will fail if the |hpke| context is not set up as a receiver.
//
// Note that HPKE encryption is stateful and ordered. The sender's first call to
// |EVP_HPKE_CTX_seal| must correspond to the recipient's first call to
// |EVP_HPKE_CTX_open|, etc.
//
// At most |in_len| bytes are written to |out|. In order to ensure success,
// |max_out_len| should be at least |in_len|. On successful return, |*out_len|
// is set to the actual number of bytes written.
OPENSSL_EXPORT int EVP_HPKE_CTX_open(EVP_HPKE_CTX *hpke, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len);
// EVP_HPKE_CTX_seal uses the HPKE context |hpke| to encrypt and authenticate
// |in_len| bytes of ciphertext |in| and authenticate |ad_len| bytes from |ad|,
// writing the result to |out|. It returns one on success and zero otherwise.
//
// This operation will fail if the |hpke| context is not set up as a sender.
//
// Note that HPKE encryption is stateful and ordered. The sender's first call to
// |EVP_HPKE_CTX_seal| must correspond to the recipient's first call to
// |EVP_HPKE_CTX_open|, etc.
//
// At most, |max_out_len| encrypted bytes are written to |out|. On successful
// return, |*out_len| is set to the actual number of bytes written.
//
// To ensure success, |max_out_len| should be |in_len| plus the result of
// |EVP_HPKE_CTX_max_overhead| or |EVP_HPKE_MAX_OVERHEAD|.
OPENSSL_EXPORT int EVP_HPKE_CTX_seal(EVP_HPKE_CTX *hpke, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len);
// EVP_HPKE_CTX_export uses the HPKE context |hpke| to export a secret of
// |secret_len| bytes into |out|. This function uses |context_len| bytes from
// |context| as a context string for the secret. This is necessary to separate
// different uses of exported secrets and bind relevant caller-specific context
// into the output. It returns one on success and zero otherwise.
OPENSSL_EXPORT int EVP_HPKE_CTX_export(const EVP_HPKE_CTX *hpke, uint8_t *out,
size_t secret_len,
const uint8_t *context,
size_t context_len);
// EVP_HPKE_CTX_max_overhead returns the maximum number of additional bytes
// added by sealing data with |EVP_HPKE_CTX_seal|. The |hpke| context must be
// set up as a sender.
OPENSSL_EXPORT size_t EVP_HPKE_CTX_max_overhead(const EVP_HPKE_CTX *hpke);
#if defined(__cplusplus)
} // extern C
#endif
#if !defined(BORINGSSL_NO_CXX)
extern "C++" {
BSSL_NAMESPACE_BEGIN
using ScopedEVP_HPKE_CTX =
internal::StackAllocated<EVP_HPKE_CTX, void, EVP_HPKE_CTX_init,
EVP_HPKE_CTX_cleanup>;
BSSL_NAMESPACE_END
} // extern C++
#endif
#endif // OPENSSL_HEADER_CRYPTO_HPKE_INTERNAL_H
File diff suppressed because one or more lines are too long
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/env python
# coding=utf-8
# 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 script translates JSON test vectors to BoringSSL's "FileTest" format.
Usage: translate_test_vectors.py TEST_VECTORS_JSON_FILE
The TEST_VECTORS_JSON_FILE is expected to come from the HPKE reference
implementation at https://github.com/cisco/go-hpke. The output file is
hardcoded as "hpke_test_vectors.txt".
"""
import collections
import json
import sys
HPKE_MODE_BASE = 0
HPKE_DHKEM_X25519_SHA256 = 0x0020
def read_test_vectors_and_generate_code(json_file_in_path, test_file_out_path):
"""Translates JSON test vectors into BoringSSL's FileTest language.
Args:
json_file_in_path: Path to the JSON test vectors file.
test_file_out_path: Path to output file.
"""
# Load the JSON file into |test_vecs|.
with open(json_file_in_path) as file_in:
test_vecs = json.load(file_in)
lines = []
for test in test_vecs:
# Filter out test cases that we don't use.
if (test["mode"] != HPKE_MODE_BASE or
test["kemID"] != HPKE_DHKEM_X25519_SHA256):
continue
for key in ("kdfID", "aeadID", "info", "skRm", "skEm", "pkRm", "pkEm"):
lines.append("{} = {}".format(key, str(test[key])))
for i, enc in enumerate(test["encryptions"]):
lines.append("# encryptions[{}]".format(i))
for key in ("aad", "ciphertext", "plaintext"):
lines.append("{} = {}".format(key, str(enc[key])))
for i, exp in enumerate(test["exports"]):
lines.append("# exports[{}]".format(i))
for key in ("exportContext", "exportLength", "exportValue"):
lines.append("{} = {}".format(key, str(exp[key])))
lines.append("")
with open(test_file_out_path, "w") as file_out:
file_out.write("\n".join(lines))
def main(argv):
if len(argv) != 2:
print(__doc__)
sys.exit(1)
read_test_vectors_and_generate_code(argv[1], "hpke_test_vectors.txt")
if __name__ == "__main__":
main(sys.argv)
+7
View File
@@ -63,6 +63,13 @@ extern "C" {
#endif
struct pkcs8_priv_key_info_st {
ASN1_INTEGER *version;
X509_ALGOR *pkeyalg;
ASN1_OCTET_STRING *pkey;
STACK_OF(X509_ATTRIBUTE) *attributes;
};
// pkcs8_pbe_decrypt decrypts |in| using the PBE scheme described by
// |algorithm|, which should be a serialized AlgorithmIdentifier structure. On
// success, it sets |*out| to a newly-allocated buffer containing the decrypted
+36 -5
View File
@@ -96,10 +96,8 @@ static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
// Since the structure must still be valid use ASN1_OP_FREE_PRE
if (operation == ASN1_OP_FREE_PRE) {
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING &&
key->pkey->value.octet_string) {
OPENSSL_cleanse(key->pkey->value.octet_string->data,
key->pkey->value.octet_string->length);
if (key->pkey) {
OPENSSL_cleanse(key->pkey->data, key->pkey->length);
}
}
return 1;
@@ -108,12 +106,45 @@ static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_OCTET_STRING),
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
int ptype, void *pval, uint8_t *penc, int penclen) {
if (version >= 0 &&
!ASN1_INTEGER_set(priv->version, version)) {
return 0;
}
if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) {
return 0;
}
if (penc != NULL) {
ASN1_STRING_set0(priv->pkey, penc, penclen);
}
return 1;
}
int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, const uint8_t **pk, int *ppklen,
X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8) {
if (ppkalg) {
*ppkalg = p8->pkeyalg->algorithm;
}
if (pk) {
*pk = ASN1_STRING_data(p8->pkey);
*ppklen = ASN1_STRING_length(p8->pkey);
}
if (pa) {
*pa = p8->pkeyalg;
}
return 1;
}
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
uint8_t *der = NULL;
int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der);
-29
View File
@@ -77,27 +77,6 @@ OPENSSL_EXPORT void PMBTOKEN_PRETOKEN_free(PMBTOKEN_PRETOKEN *token);
DEFINE_STACK_OF(PMBTOKEN_PRETOKEN)
// The following functions implement the corresponding |TRUST_TOKENS_METHOD|
// functions for |TRUST_TOKENS_experiment_v0|'s PMBTokens construction which
// uses P-521.
int pmbtoken_exp0_generate_key(CBB *out_private, CBB *out_public);
int pmbtoken_exp0_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
const uint8_t *in, size_t len);
int pmbtoken_exp0_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
const uint8_t *in, size_t len);
STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp0_blind(CBB *cbb, size_t count);
int pmbtoken_exp0_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
size_t num_requested, size_t num_to_issue,
uint8_t private_metadata);
STACK_OF(TRUST_TOKEN) *
pmbtoken_exp0_unblind(const PMBTOKEN_CLIENT_KEY *key,
const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
CBS *cbs, size_t count, uint32_t key_id);
int pmbtoken_exp0_read(const PMBTOKEN_ISSUER_KEY *key,
uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
uint8_t *out_private_metadata, const uint8_t *token,
size_t token_len);
// The following functions implement the corresponding |TRUST_TOKENS_METHOD|
// functions for |TRUST_TOKENS_experiment_v1|'s PMBTokens construction which
// uses P-384.
@@ -193,14 +172,6 @@ struct trust_token_method_st {
uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
uint8_t *out_private_metadata, const uint8_t *token,
size_t token_len);
// use_token_hash determines whether to include the token hash in the SRR and
// private metadata encryption.
int use_token_hash : 1;
// batched_proof determines whether PMBToken uses a batched DLEQOR proof when
// signing tokens.
int batched_proof : 1;
};
// Structure representing a single Trust Token public key with the specified ID.
+116 -363
View File
@@ -52,9 +52,6 @@ typedef struct {
// hash_c implements the H_c operation in PMBTokens. It returns one on success
// and zero on error.
hash_c_func_t hash_c;
// batched_proof determines whether PMBToken uses a batched DLEQOR proof when
// signing tokens.
int batched_proof : 1;
} PMBTOKEN_METHOD;
static const uint8_t kDefaultAdditionalData[32] = {0};
@@ -62,7 +59,7 @@ static const uint8_t kDefaultAdditionalData[32] = {0};
static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid,
const uint8_t *h_bytes, size_t h_len,
hash_t_func_t hash_t, hash_s_func_t hash_s,
hash_c_func_t hash_c, int batched_proof) {
hash_c_func_t hash_c) {
method->group = EC_GROUP_new_by_curve_name(curve_nid);
if (method->group == NULL) {
return 0;
@@ -71,7 +68,6 @@ static int pmbtoken_init_method(PMBTOKEN_METHOD *method, int curve_nid,
method->hash_t = hash_t;
method->hash_s = hash_s;
method->hash_c = hash_c;
method->batched_proof = batched_proof;
EC_AFFINE h;
if (!ec_point_from_uncompressed(method->group, &h, h_bytes, h_len)) {
@@ -724,37 +720,31 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
return 0;
}
if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
return 0;
}
int ret = 0;
EC_RAW_POINT *Tps = NULL;
EC_RAW_POINT *Sps = NULL;
EC_RAW_POINT *Wps = NULL;
EC_RAW_POINT *Wsps = NULL;
EC_SCALAR *es = NULL;
EC_RAW_POINT *Tps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
EC_RAW_POINT *Sps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
EC_RAW_POINT *Wps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
EC_RAW_POINT *Wsps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
EC_SCALAR *es = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
CBB batch_cbb;
CBB_zero(&batch_cbb);
if (method->batched_proof) {
if (num_to_issue > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
num_to_issue > ((size_t)-1) / sizeof(EC_SCALAR)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
goto err;
}
Tps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
Sps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
Wps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
Wsps = OPENSSL_malloc(num_to_issue * sizeof(EC_RAW_POINT));
es = OPENSSL_malloc(num_to_issue * sizeof(EC_SCALAR));
if (!Tps ||
!Sps ||
!Wps ||
!Wsps ||
!es ||
!CBB_init(&batch_cbb, 0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!Tps ||
!Sps ||
!Wps ||
!Wsps ||
!es ||
!CBB_init(&batch_cbb, 0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
for (size_t i = 0; i < num_to_issue; i++) {
@@ -793,25 +783,17 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
goto err;
}
if (!method->batched_proof) {
if (!CBB_add_u16_length_prefixed(cbb, &child) ||
!dleq_generate(method, &child, key, &Tp, &jacobians[0], &jacobians[1],
&jacobians[2], private_metadata)) {
goto err;
}
} else {
if (!point_to_cbb(&batch_cbb, group, &Tp_affine) ||
!point_to_cbb(&batch_cbb, group, &affines[0]) ||
!point_to_cbb(&batch_cbb, group, &affines[1]) ||
!point_to_cbb(&batch_cbb, group, &affines[2])) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
Tps[i] = Tp;
Sps[i] = jacobians[0];
Wps[i] = jacobians[1];
Wsps[i] = jacobians[2];
if (!point_to_cbb(&batch_cbb, group, &Tp_affine) ||
!point_to_cbb(&batch_cbb, group, &affines[0]) ||
!point_to_cbb(&batch_cbb, group, &affines[1]) ||
!point_to_cbb(&batch_cbb, group, &affines[2])) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
Tps[i] = Tp;
Sps[i] = jacobians[0];
Wps[i] = jacobians[1];
Wsps[i] = jacobians[2];
if (!CBB_flush(cbb)) {
goto err;
@@ -821,36 +803,34 @@ static int pmbtoken_sign(const PMBTOKEN_METHOD *method,
// The DLEQ batching construction is described in appendix B of
// https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
// computations all act on public inputs.
if (method->batched_proof) {
for (size_t i = 0; i < num_to_issue; i++) {
if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
goto err;
}
}
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
/*g_scalar=*/NULL, Tps, es,
num_to_issue) ||
!ec_point_mul_scalar_public_batch(group, &Sp_batch,
/*g_scalar=*/NULL, Sps, es,
num_to_issue) ||
!ec_point_mul_scalar_public_batch(group, &Wp_batch,
/*g_scalar=*/NULL, Wps, es,
num_to_issue) ||
!ec_point_mul_scalar_public_batch(group, &Wsp_batch,
/*g_scalar=*/NULL, Wsps, es,
num_to_issue)) {
for (size_t i = 0; i < num_to_issue; i++) {
if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
goto err;
}
}
CBB proof;
if (!CBB_add_u16_length_prefixed(cbb, &proof) ||
!dleq_generate(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
&Wsp_batch, private_metadata) ||
!CBB_flush(cbb)) {
goto err;
}
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
/*g_scalar=*/NULL, Tps, es,
num_to_issue) ||
!ec_point_mul_scalar_public_batch(group, &Sp_batch,
/*g_scalar=*/NULL, Sps, es,
num_to_issue) ||
!ec_point_mul_scalar_public_batch(group, &Wp_batch,
/*g_scalar=*/NULL, Wps, es,
num_to_issue) ||
!ec_point_mul_scalar_public_batch(group, &Wsp_batch,
/*g_scalar=*/NULL, Wsps, es,
num_to_issue)) {
goto err;
}
CBB proof;
if (!CBB_add_u16_length_prefixed(cbb, &proof) ||
!dleq_generate(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
&Wsp_batch, private_metadata) ||
!CBB_flush(cbb)) {
goto err;
}
// Skip over any unused requests.
@@ -890,36 +870,29 @@ static STACK_OF(TRUST_TOKEN) *
return NULL;
}
EC_RAW_POINT *Tps = NULL;
EC_RAW_POINT *Sps = NULL;
EC_RAW_POINT *Wps = NULL;
EC_RAW_POINT *Wsps = NULL;
EC_SCALAR *es = NULL;
if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
count > ((size_t)-1) / sizeof(EC_SCALAR)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
return 0;
}
EC_RAW_POINT *Tps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
EC_RAW_POINT *Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
EC_RAW_POINT *Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
EC_RAW_POINT *Wsps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
EC_SCALAR *es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
CBB batch_cbb;
CBB_zero(&batch_cbb);
if (method->batched_proof) {
if (count > ((size_t)-1) / sizeof(EC_RAW_POINT) ||
count > ((size_t)-1) / sizeof(EC_SCALAR)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_OVERFLOW);
goto err;
}
Tps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
Sps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
Wps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
Wsps = OPENSSL_malloc(count * sizeof(EC_RAW_POINT));
es = OPENSSL_malloc(count * sizeof(EC_SCALAR));
if (!Tps ||
!Sps ||
!Wps ||
!Wsps ||
!es ||
!CBB_init(&batch_cbb, 0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!Tps ||
!Sps ||
!Wps ||
!Wsps ||
!es ||
!CBB_init(&batch_cbb, 0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pubs) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub0) ||
!point_to_cbb(&batch_cbb, method->group, &key->pub1)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
for (size_t i = 0; i < count; i++) {
@@ -928,7 +901,6 @@ static STACK_OF(TRUST_TOKEN) *
uint8_t s[PMBTOKEN_NONCE_SIZE];
EC_AFFINE Wp_affine, Wsp_affine;
CBS proof;
if (!CBS_copy_bytes(cbs, s, PMBTOKEN_NONCE_SIZE) ||
!cbs_get_prefixed_point(cbs, group, &Wp_affine) ||
!cbs_get_prefixed_point(cbs, group, &Wsp_affine)) {
@@ -936,50 +908,29 @@ static STACK_OF(TRUST_TOKEN) *
goto err;
}
EC_RAW_POINT Tp, Wp, Wsp, Sp;
ec_affine_to_jacobian(group, &Tp, &pretoken->Tp);
ec_affine_to_jacobian(group, &Wp, &Wp_affine);
ec_affine_to_jacobian(group, &Wsp, &Wsp_affine);
if (!method->hash_s(group, &Sp, &pretoken->Tp, s)) {
ec_affine_to_jacobian(group, &Tps[i], &pretoken->Tp);
ec_affine_to_jacobian(group, &Wps[i], &Wp_affine);
ec_affine_to_jacobian(group, &Wsps[i], &Wsp_affine);
if (!method->hash_s(group, &Sps[i], &pretoken->Tp, s)) {
goto err;
}
if (!method->batched_proof) {
if(!CBS_get_u16_length_prefixed(cbs, &proof)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
goto err;
}
if (!dleq_verify(method, &proof, key, &Tp, &Sp, &Wp, &Wsp)) {
goto err;
}
if (CBS_len(&proof) != 0) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE);
goto err;
}
} else {
EC_AFFINE Sp_affine;
if (!point_to_cbb(&batch_cbb, group, &pretoken->Tp) ||
!ec_jacobian_to_affine(group, &Sp_affine, &Sp) ||
!point_to_cbb(&batch_cbb, group, &Sp_affine) ||
!point_to_cbb(&batch_cbb, group, &Wp_affine) ||
!point_to_cbb(&batch_cbb, group, &Wsp_affine)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
Tps[i] = Tp;
Sps[i] = Sp;
Wps[i] = Wp;
Wsps[i] = Wsp;
EC_AFFINE Sp_affine;
if (!point_to_cbb(&batch_cbb, group, &pretoken->Tp) ||
!ec_jacobian_to_affine(group, &Sp_affine, &Sps[i]) ||
!point_to_cbb(&batch_cbb, group, &Sp_affine) ||
!point_to_cbb(&batch_cbb, group, &Wp_affine) ||
!point_to_cbb(&batch_cbb, group, &Wsp_affine)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
// Unblind the token.
EC_RAW_POINT jacobians[3];
EC_AFFINE affines[3];
if (!ec_point_mul_scalar(group, &jacobians[0], &Sp, &pretoken->r) ||
!ec_point_mul_scalar(group, &jacobians[1], &Wp, &pretoken->r) ||
!ec_point_mul_scalar(group, &jacobians[2], &Wsp, &pretoken->r) ||
if (!ec_point_mul_scalar(group, &jacobians[0], &Sps[i], &pretoken->r) ||
!ec_point_mul_scalar(group, &jacobians[1], &Wps[i], &pretoken->r) ||
!ec_point_mul_scalar(group, &jacobians[2], &Wsps[i], &pretoken->r) ||
!ec_jacobian_to_affine_batch(group, affines, jacobians, 3)) {
goto err;
}
@@ -1018,32 +969,30 @@ static STACK_OF(TRUST_TOKEN) *
// The DLEQ batching construction is described in appendix B of
// https://eprint.iacr.org/2020/072/20200324:214215. Note the additional
// computations all act on public inputs.
if (method->batched_proof) {
for (size_t i = 0; i < count; i++) {
if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
goto err;
}
}
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
/*g_scalar=*/NULL, Tps, es, count) ||
!ec_point_mul_scalar_public_batch(group, &Sp_batch,
/*g_scalar=*/NULL, Sps, es, count) ||
!ec_point_mul_scalar_public_batch(group, &Wp_batch,
/*g_scalar=*/NULL, Wps, es, count) ||
!ec_point_mul_scalar_public_batch(group, &Wsp_batch,
/*g_scalar=*/NULL, Wsps, es, count)) {
for (size_t i = 0; i < count; i++) {
if (!hash_c_batch(method, &es[i], &batch_cbb, i)) {
goto err;
}
}
CBS proof;
if (!CBS_get_u16_length_prefixed(cbs, &proof) ||
!dleq_verify(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
&Wsp_batch) ||
CBS_len(&proof) != 0) {
goto err;
}
EC_RAW_POINT Tp_batch, Sp_batch, Wp_batch, Wsp_batch;
if (!ec_point_mul_scalar_public_batch(group, &Tp_batch,
/*g_scalar=*/NULL, Tps, es, count) ||
!ec_point_mul_scalar_public_batch(group, &Sp_batch,
/*g_scalar=*/NULL, Sps, es, count) ||
!ec_point_mul_scalar_public_batch(group, &Wp_batch,
/*g_scalar=*/NULL, Wps, es, count) ||
!ec_point_mul_scalar_public_batch(group, &Wsp_batch,
/*g_scalar=*/NULL, Wsps, es, count)) {
goto err;
}
CBS proof;
if (!CBS_get_u16_length_prefixed(cbs, &proof) ||
!dleq_verify(method, &proof, key, &Tp_batch, &Sp_batch, &Wp_batch,
&Wsp_batch) ||
CBS_len(&proof) != 0) {
goto err;
}
ok = 1;
@@ -1127,202 +1076,6 @@ static int pmbtoken_read(const PMBTOKEN_METHOD *method,
}
// PMBTokens experiment v0.
static int pmbtoken_exp0_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
const uint8_t t[PMBTOKEN_NONCE_SIZE]) {
const uint8_t kHashTLabel[] = "PMBTokensV0 HashT";
return ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
group, out, kHashTLabel, sizeof(kHashTLabel), t, PMBTOKEN_NONCE_SIZE);
}
static int pmbtoken_exp0_hash_s(const EC_GROUP *group, EC_RAW_POINT *out,
const EC_AFFINE *t,
const uint8_t s[PMBTOKEN_NONCE_SIZE]) {
const uint8_t kHashSLabel[] = "PMBTokensV0 HashS";
int ret = 0;
CBB cbb;
uint8_t *buf = NULL;
size_t len;
if (!CBB_init(&cbb, 0) ||
!point_to_cbb(&cbb, group, t) ||
!CBB_add_bytes(&cbb, s, PMBTOKEN_NONCE_SIZE) ||
!CBB_finish(&cbb, &buf, &len) ||
!ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
group, out, kHashSLabel, sizeof(kHashSLabel), buf, len)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
ret = 1;
err:
OPENSSL_free(buf);
CBB_cleanup(&cbb);
return ret;
}
static int pmbtoken_exp0_hash_c(const EC_GROUP *group, EC_SCALAR *out,
uint8_t *buf, size_t len) {
const uint8_t kHashCLabel[] = "PMBTokensV0 HashC";
return ec_hash_to_scalar_p521_xmd_sha512_draft06(
group, out, kHashCLabel, sizeof(kHashCLabel), buf, len);
}
// H for PMBTokens v0 was generated with the following Python code.
/*
import hashlib
SEED_H = 'PrivacyPass H'
A = -3
B = 0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
P = 2**521 - 1
def get_y(x):
y2 = (x**3 + A*x + B) % P
y = pow(y2, (P+1)/4, P)
if (y*y) % P != y2:
raise ValueError("point not on curve")
return y
def bit(h,i):
return (ord(h[i/8]) >> (i%8)) & 1
b = 521
def decode_point(so):
s = hashlib.sha256(so + '0').digest() + hashlib.sha256(so + '1').digest() + \
hashlib.sha256(so + '2').digest()
x = 0
for i in range(0,b):
x = x + (long(bit(s,i))<<i)
if x >= P:
raise ValueError("x out of range")
y = get_y(x)
if y & 1 != bit(s,b-1): y = P-y
return (x, y)
def gen_point(seed):
v = hashlib.sha256(seed).digest()
it = 1
while True:
try:
x,y = decode_point(v)
except Exception, e:
print e
it += 1
v = hashlib.sha256(v).digest()
continue
print "Found in %d iterations:" % it
print " x = %d" % x
print " y = %d" % y
print " Encoded (hex): (%x, %x)" % (x, y)
return (x, y)
if __name__ == "__main__":
gen_point(SEED_H)
*/
static int pmbtoken_exp0_ok = 0;
static PMBTOKEN_METHOD pmbtoken_exp0_method;
static CRYPTO_once_t pmbtoken_exp0_method_once = CRYPTO_ONCE_INIT;
static void pmbtoken_exp0_init_method_impl(void) {
static const uint8_t kH[] = {
0x04, 0x01, 0xf0, 0xa9, 0xf7, 0x9e, 0xbc, 0x12, 0x6c, 0xef, 0xd1, 0xab,
0x29, 0x10, 0x03, 0x6f, 0x4e, 0xf5, 0xbd, 0xeb, 0x0f, 0x6b, 0xc0, 0x5c,
0x0e, 0xce, 0xfe, 0x59, 0x45, 0xd1, 0x3e, 0x25, 0x33, 0x7e, 0x4c, 0xda,
0x64, 0x53, 0x54, 0x4e, 0xf9, 0x76, 0x0d, 0x6d, 0xc5, 0x39, 0x2a, 0xd4,
0xce, 0x84, 0x6e, 0x31, 0xc2, 0x86, 0x21, 0xf9, 0x5c, 0x98, 0xb9, 0x3d,
0x01, 0x74, 0x9f, 0xc5, 0x1e, 0x47, 0x24, 0x00, 0x5c, 0x17, 0x62, 0x51,
0x7d, 0x32, 0x5e, 0x29, 0xac, 0x52, 0x14, 0x75, 0x6f, 0x36, 0xd9, 0xc7,
0xfa, 0xbb, 0xa9, 0x3b, 0x9d, 0x70, 0x49, 0x1e, 0xb4, 0x53, 0xbc, 0x55,
0xea, 0xad, 0x8f, 0x26, 0x1d, 0xe0, 0xbc, 0xf3, 0x50, 0x5c, 0x7e, 0x66,
0x41, 0xb5, 0x61, 0x70, 0x12, 0x72, 0xac, 0x6a, 0xb0, 0x6e, 0x78, 0x3d,
0x17, 0x08, 0xe3, 0xdf, 0x3c, 0xff, 0xa6, 0xa0, 0xea, 0x96, 0x67, 0x92,
0xcd,
};
pmbtoken_exp0_ok =
pmbtoken_init_method(&pmbtoken_exp0_method, NID_secp521r1, kH, sizeof(kH),
pmbtoken_exp0_hash_t, pmbtoken_exp0_hash_s,
pmbtoken_exp0_hash_c, /*batched_proof=*/0);
}
static int pmbtoken_exp0_init_method(void) {
CRYPTO_once(&pmbtoken_exp0_method_once, pmbtoken_exp0_init_method_impl);
if (!pmbtoken_exp0_ok) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int pmbtoken_exp0_generate_key(CBB *out_private, CBB *out_public) {
if (!pmbtoken_exp0_init_method()) {
return 0;
}
return pmbtoken_generate_key(&pmbtoken_exp0_method, out_private, out_public);
}
int pmbtoken_exp0_client_key_from_bytes(PMBTOKEN_CLIENT_KEY *key,
const uint8_t *in, size_t len) {
if (!pmbtoken_exp0_init_method()) {
return 0;
}
return pmbtoken_client_key_from_bytes(&pmbtoken_exp0_method, key, in, len);
}
int pmbtoken_exp0_issuer_key_from_bytes(PMBTOKEN_ISSUER_KEY *key,
const uint8_t *in, size_t len) {
if (!pmbtoken_exp0_init_method()) {
return 0;
}
return pmbtoken_issuer_key_from_bytes(&pmbtoken_exp0_method, key, in, len);
}
STACK_OF(PMBTOKEN_PRETOKEN) * pmbtoken_exp0_blind(CBB *cbb, size_t count) {
if (!pmbtoken_exp0_init_method()) {
return NULL;
}
return pmbtoken_blind(&pmbtoken_exp0_method, cbb, count);
}
int pmbtoken_exp0_sign(const PMBTOKEN_ISSUER_KEY *key, CBB *cbb, CBS *cbs,
size_t num_requested, size_t num_to_issue,
uint8_t private_metadata) {
if (!pmbtoken_exp0_init_method()) {
return 0;
}
return pmbtoken_sign(&pmbtoken_exp0_method, key, cbb, cbs, num_requested,
num_to_issue, private_metadata);
}
STACK_OF(TRUST_TOKEN) *
pmbtoken_exp0_unblind(const PMBTOKEN_CLIENT_KEY *key,
const STACK_OF(PMBTOKEN_PRETOKEN) * pretokens,
CBS *cbs, size_t count, uint32_t key_id) {
if (!pmbtoken_exp0_init_method()) {
return NULL;
}
return pmbtoken_unblind(&pmbtoken_exp0_method, key, pretokens, cbs, count,
key_id);
}
int pmbtoken_exp0_read(const PMBTOKEN_ISSUER_KEY *key,
uint8_t out_nonce[PMBTOKEN_NONCE_SIZE],
uint8_t *out_private_metadata, const uint8_t *token,
size_t token_len) {
if (!pmbtoken_exp0_init_method()) {
return 0;
}
return pmbtoken_read(&pmbtoken_exp0_method, key, out_nonce,
out_private_metadata, token, token_len);
}
// PMBTokens experiment v1.
static int pmbtoken_exp1_hash_t(const EC_GROUP *group, EC_RAW_POINT *out,
@@ -1387,7 +1140,7 @@ static void pmbtoken_exp1_init_method_impl(void) {
pmbtoken_exp1_ok =
pmbtoken_init_method(&pmbtoken_exp1_method, NID_secp384r1, kH, sizeof(kH),
pmbtoken_exp1_hash_t, pmbtoken_exp1_hash_s,
pmbtoken_exp1_hash_c, /*batched_proof=*/1);
pmbtoken_exp1_hash_c);
}
static int pmbtoken_exp1_init_method(void) {
+7 -45
View File
@@ -27,21 +27,6 @@
// protocol for issuing and redeeming tokens built on top of the PMBTokens
// construction.
const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v0(void) {
static const TRUST_TOKEN_METHOD kMethod = {
pmbtoken_exp0_generate_key,
pmbtoken_exp0_client_key_from_bytes,
pmbtoken_exp0_issuer_key_from_bytes,
pmbtoken_exp0_blind,
pmbtoken_exp0_sign,
pmbtoken_exp0_unblind,
pmbtoken_exp0_read,
0 /* don't use token hash */,
0 /* don't use batched proof */,
};
return &kMethod;
}
const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void) {
static const TRUST_TOKEN_METHOD kMethod = {
pmbtoken_exp1_generate_key,
@@ -51,8 +36,6 @@ const TRUST_TOKEN_METHOD *TRUST_TOKEN_experiment_v1(void) {
pmbtoken_exp1_sign,
pmbtoken_exp1_unblind,
pmbtoken_exp1_read,
1 /* use token hash */,
1 /* use batched proof */,
};
return &kMethod;
}
@@ -597,16 +580,8 @@ int TRUST_TOKEN_ISSUER_redeem(const TRUST_TOKEN_ISSUER *ctx, uint8_t **out,
SHA256_Update(&sha_ctx, CBS_data(&token_copy), CBS_len(&token_copy));
SHA256_Final(token_hash, &sha_ctx);
uint8_t metadata_obfuscator;
if (ctx->method->use_token_hash) {
metadata_obfuscator =
get_metadata_obfuscator(ctx->metadata_key, ctx->metadata_key_len,
token_hash, sizeof(token_hash));
} else {
metadata_obfuscator =
get_metadata_obfuscator(ctx->metadata_key, ctx->metadata_key_len,
CBS_data(&client_data), CBS_len(&client_data));
}
uint8_t metadata_obfuscator = get_metadata_obfuscator(
ctx->metadata_key, ctx->metadata_key_len, token_hash, sizeof(token_hash));
// The SRR is constructed as per the format described in
// https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#heading=h.7mkzvhpqb8l5
@@ -625,10 +600,7 @@ int TRUST_TOKEN_ISSUER_redeem(const TRUST_TOKEN_ISSUER *ctx, uint8_t **out,
assert(strlen(kClientDataLabel) < strlen(kExpiryTimestampLabel));
assert(strlen(kPublicLabel) < strlen(kPrivateLabel));
size_t map_entries = 3;
if (ctx->method->use_token_hash) {
map_entries = 4;
}
size_t map_entries = 4;
if (!CBB_init(&srr, 0) ||
!add_cbor_map(&srr, map_entries) || // SRR map
@@ -637,20 +609,10 @@ int TRUST_TOKEN_ISSUER_redeem(const TRUST_TOKEN_ISSUER *ctx, uint8_t **out,
!add_cbor_text(&srr, kPublicLabel, strlen(kPublicLabel)) ||
!add_cbor_int(&srr, public_metadata) ||
!add_cbor_text(&srr, kPrivateLabel, strlen(kPrivateLabel)) ||
!add_cbor_int(&srr, private_metadata ^ metadata_obfuscator)) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
if (ctx->method->use_token_hash) {
if (!add_cbor_text(&srr, kTokenHashLabel, strlen(kTokenHashLabel)) ||
!add_cbor_bytes(&srr, token_hash, sizeof(token_hash))) {
OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (!add_cbor_text(&srr, kClientDataLabel, strlen(kClientDataLabel)) ||
!add_cbor_int(&srr, private_metadata ^ metadata_obfuscator) ||
!add_cbor_text(&srr, kTokenHashLabel, strlen(kTokenHashLabel)) ||
!add_cbor_bytes(&srr, token_hash, sizeof(token_hash)) ||
!add_cbor_text(&srr, kClientDataLabel, strlen(kClientDataLabel)) ||
!CBB_add_bytes(&srr, CBS_data(&client_data), CBS_len(&client_data)) ||
!add_cbor_text(&srr, kExpiryTimestampLabel,
strlen(kExpiryTimestampLabel)) ||
+37 -92
View File
@@ -44,18 +44,6 @@ BSSL_NAMESPACE_BEGIN
namespace {
TEST(TrustTokenTest, KeyGenExp0) {
uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
size_t priv_key_len, pub_key_len;
ASSERT_TRUE(TRUST_TOKEN_generate_key(
TRUST_TOKEN_experiment_v0(), priv_key, &priv_key_len,
TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key, &pub_key_len,
TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0x0001));
ASSERT_EQ(400u, priv_key_len);
ASSERT_EQ(409u, pub_key_len);
}
TEST(TrustTokenTest, KeyGenExp1) {
uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
@@ -91,7 +79,7 @@ TEST(TrustTokenTest, HExp1) {
}
static std::vector<const TRUST_TOKEN_METHOD *> AllMethods() {
return {TRUST_TOKEN_experiment_v0(), TRUST_TOKEN_experiment_v1()};
return {TRUST_TOKEN_experiment_v1()};
}
class TrustTokenProtocolTestBase : public ::testing::Test {
@@ -454,14 +442,7 @@ TEST_P(TrustTokenMetadataTest, SetAndGetMetadata) {
const uint8_t kClientData[] = "\x70TEST CLIENT DATA";
uint64_t kRedemptionTime = 13374242;
const uint8_t kExpectedSRRNoTokenHash[] =
"\xa3\x68\x6d\x65\x74\x61\x64\x61\x74\x61\xa2\x66\x70\x75\x62\x6c\x69"
"\x63\x00\x67\x70\x72\x69\x76\x61\x74\x65\x00\x6b\x63\x6c\x69\x65\x6e"
"\x74\x2d\x64\x61\x74\x61\x70\x54\x45\x53\x54\x20\x43\x4c\x49\x45\x4e"
"\x54\x20\x44\x41\x54\x41\x70\x65\x78\x70\x69\x72\x79\x2d\x74\x69\x6d"
"\x65\x73\x74\x61\x6d\x70\x1a\x00\xcc\x15\x7a";
const uint8_t kExpectedSRRTokenHash[] =
const uint8_t kExpectedSRR[] =
"\xa4\x68\x6d\x65\x74\x61\x64\x61\x74\x61\xa2\x66\x70\x75\x62\x6c\x69"
"\x63\x00\x67\x70\x72\x69\x76\x61\x74\x65\x00\x6a\x74\x6f\x6b\x65\x6e"
"\x2d\x68\x61\x73\x68\x58\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
@@ -498,50 +479,33 @@ TEST_P(TrustTokenMetadataTest, SetAndGetMetadata) {
bssl::UniquePtr<uint8_t> free_srr(srr);
bssl::UniquePtr<uint8_t> free_sig(sig);
if (method()->use_token_hash) {
const uint8_t kTokenHashDSTLabel[] = "TrustTokenV0 TokenHash";
uint8_t token_hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha_ctx;
SHA256_Init(&sha_ctx);
SHA256_Update(&sha_ctx, kTokenHashDSTLabel, sizeof(kTokenHashDSTLabel));
SHA256_Update(&sha_ctx, token->data, token->len);
SHA256_Final(token_hash, &sha_ctx);
const uint8_t kTokenHashDSTLabel[] = "TrustTokenV0 TokenHash";
uint8_t token_hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha_ctx;
SHA256_Init(&sha_ctx);
SHA256_Update(&sha_ctx, kTokenHashDSTLabel, sizeof(kTokenHashDSTLabel));
SHA256_Update(&sha_ctx, token->data, token->len);
SHA256_Final(token_hash, &sha_ctx);
// Check the token hash is in the SRR.
ASSERT_EQ(Bytes(token_hash), Bytes(srr + 41, sizeof(token_hash)));
// Check the token hash is in the SRR.
ASSERT_EQ(Bytes(token_hash), Bytes(srr + 41, sizeof(token_hash)));
uint8_t decode_private_metadata;
ASSERT_TRUE(TRUST_TOKEN_decode_private_metadata(
method(), &decode_private_metadata, metadata_key,
sizeof(metadata_key), token_hash, sizeof(token_hash), srr[27]));
ASSERT_EQ(srr[18], public_metadata());
ASSERT_EQ(decode_private_metadata, private_metadata());
uint8_t decode_private_metadata;
ASSERT_TRUE(TRUST_TOKEN_decode_private_metadata(
method(), &decode_private_metadata, metadata_key, sizeof(metadata_key),
token_hash, sizeof(token_hash), srr[27]));
ASSERT_EQ(srr[18], public_metadata());
ASSERT_EQ(decode_private_metadata, private_metadata());
// Clear out the metadata bits.
srr[18] = 0;
srr[27] = 0;
// Clear out the metadata bits.
srr[18] = 0;
srr[27] = 0;
// Clear out the token hash.
OPENSSL_memset(srr + 41, 0, sizeof(token_hash));
// Clear out the token hash.
OPENSSL_memset(srr + 41, 0, sizeof(token_hash));
ASSERT_EQ(Bytes(kExpectedSRRTokenHash, sizeof(kExpectedSRRTokenHash) - 1),
Bytes(srr, srr_len));
} else {
uint8_t decode_private_metadata;
ASSERT_TRUE(TRUST_TOKEN_decode_private_metadata(
method(), &decode_private_metadata, metadata_key,
sizeof(metadata_key), kClientData, sizeof(kClientData) - 1, srr[27]));
ASSERT_EQ(srr[18], public_metadata());
ASSERT_EQ(decode_private_metadata, private_metadata());
// Clear out the metadata bits.
srr[18] = 0;
srr[27] = 0;
ASSERT_EQ(
Bytes(kExpectedSRRNoTokenHash, sizeof(kExpectedSRRNoTokenHash) - 1),
Bytes(srr, srr_len));
}
ASSERT_EQ(Bytes(kExpectedSRR, sizeof(kExpectedSRR) - 1),
Bytes(srr, srr_len));
}
}
@@ -607,23 +571,14 @@ TEST_P(TrustTokenMetadataTest, TruncatedProof) {
ASSERT_TRUE(CBB_add_u16(bad_response.get(), CBS_len(&tmp)));
ASSERT_TRUE(
CBB_add_bytes(bad_response.get(), CBS_data(&tmp), CBS_len(&tmp)));
if (!method()->batched_proof) {
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
CBB dleq;
ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp) - 2));
ASSERT_TRUE(CBB_flush(bad_response.get()));
}
}
if (method()->batched_proof) {
CBS tmp;
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
CBB dleq;
ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp) - 2));
ASSERT_TRUE(CBB_flush(bad_response.get()));
}
CBS tmp;
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
CBB dleq;
ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp) - 2));
ASSERT_TRUE(CBB_flush(bad_response.get()));
uint8_t *bad_buf;
size_t bad_len;
@@ -675,25 +630,15 @@ TEST_P(TrustTokenMetadataTest, ExcessDataProof) {
ASSERT_TRUE(CBB_add_u16(bad_response.get(), CBS_len(&tmp)));
ASSERT_TRUE(
CBB_add_bytes(bad_response.get(), CBS_data(&tmp), CBS_len(&tmp)));
if (!method()->batched_proof) {
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
CBB dleq;
ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp)));
ASSERT_TRUE(CBB_add_u16(&dleq, 42));
ASSERT_TRUE(CBB_flush(bad_response.get()));
}
}
if (method()->batched_proof) {
CBS tmp;
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
CBB dleq;
ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp)));
ASSERT_TRUE(CBB_add_u16(&dleq, 42));
ASSERT_TRUE(CBB_flush(bad_response.get()));
}
CBS tmp;
ASSERT_TRUE(CBS_get_u16_length_prefixed(&real_response, &tmp));
CBB dleq;
ASSERT_TRUE(CBB_add_u16_length_prefixed(bad_response.get(), &dleq));
ASSERT_TRUE(CBB_add_bytes(&dleq, CBS_data(&tmp), CBS_len(&tmp)));
ASSERT_TRUE(CBB_add_u16(&dleq, 42));
ASSERT_TRUE(CBB_flush(bad_response.get()));
uint8_t *bad_buf;
size_t bad_len;
+4 -4
View File
@@ -296,7 +296,7 @@ static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
*/
static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
ASN1_STRING *str)
const ASN1_STRING *str)
{
/*
* Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
@@ -354,7 +354,7 @@ static const signed char tag2nbyte[] = {
*/
static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
ASN1_STRING *str)
const ASN1_STRING *str)
{
int outlen, len;
int type;
@@ -610,13 +610,13 @@ int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent,
}
#endif
int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_bio_chars, out, flags, str);
}
#ifndef OPENSSL_NO_FP_API
int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_fp_chars, fp, flags, str);
}
+8
View File
@@ -142,6 +142,14 @@ int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
return 0;
}
/* RSA signature algorithms include an explicit NULL parameter but we also
* accept omitted values for compatibility. Other algorithms must omit it. */
if (sigalg->parameter != NULL && (pkey_nid != EVP_PKEY_RSA ||
sigalg->parameter->type != V_ASN1_NULL)) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PARAMETER);
return 0;
}
/* Otherwise, initialize with the digest from the OID. */
const EVP_MD *digest = EVP_get_digestbynid(digest_nid);
if (digest == NULL) {
+4 -4
View File
@@ -123,7 +123,7 @@ typedef struct {
int exp_count;
} tag_exp_arg;
static ASN1_TYPE *generate_v3(char *str, X509V3_CTX *cnf, int depth,
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
int *perr);
static int bitstr_cb(const char *elem, int len, void *bitstr);
static int asn1_cb(const char *elem, int len, void *bitstr);
@@ -136,7 +136,7 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
static int asn1_str2tag(const char *tagstr, int len);
ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf)
{
X509V3_CTX cnf;
@@ -147,7 +147,7 @@ ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
return ASN1_generate_v3(str, &cnf);
}
ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
{
int err = 0;
ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err);
@@ -156,7 +156,7 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
return ret;
}
static ASN1_TYPE *generate_v3(char *str, X509V3_CTX *cnf, int depth,
static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
int *perr)
{
ASN1_TYPE *ret;
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBdTCCARugAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjODA2MA4G
A1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD
AQH/MAoGCCqGSM49BAMCA0gAMEUCIDkCS9RrLeO556C9apswg90ZdI2kn3ru31bp
a4Rqp82BAiEAqJn5GbUzqjVaI5UthWdcu1zmpdTJntbheeNstXa7k+E=
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjSDBGMA4G
A1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdIwQHSU5WQUxJRDAKBggqhkjOPQQDAgNIADBFAiEAl5TMKihFw6jD
ajc1I7R177t3d4HyW7qCB/M3PHu9HDsCIDI0oBBsuXAHX43N1Jx8LO0sMAzujYom
/NZn/qBanQnZ
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBdTCCARqgAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjNzA1MA4G
A1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHRMEB0lOVkFM
SUQwCgYIKoZIzj0EAwIDSQAwRgIhAK/zCwmg3s63Ndeg9piiBbMsUF6ZPcNFltEa
3cKSMPthAiEAkMq/CmljQigMgXVWOhacYeRLyzZyi2i9hOjrCeKFuno=
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBbzCCARagAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjMzAxMA4G
A1UdDwEB/wQEAwICBDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdJQQHSU5WQUxJRDAK
BggqhkjOPQQDAgNHADBEAiAGr6/3ad6TX4h/HgD5oFiifT7SsRzYVD1yvfyHEYRI
qgIgYDbO0XKLN9kSUF8ZBaLPyC1AIbw+m9cQy4/GaJuzxH4=
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBdDCCARugAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjODA2MBMG
A1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PBAdJTlZB
TElEMAoGCCqGSM49BAMCA0cAMEQCIE1gJ4wr8D0UPRfhQ5sx1WJWEOc+IEtktigk
giSupcouAiBFa441h0NvODAwsb39sQ/uaUhucb11vwKSZItwViMp/w==
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjSDBGMA4G
A1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdHgQHSU5WQUxJRDAKBggqhkjOPQQDAgNIADBFAiB7QedoT6bEccGY
/Pofovdtfdzl/AXCtbJjiu59Yt3UTAIhANdfkR5PShTke3o9diKz6G/cVvL9jkF2
SKzPRxnRVxNo
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhDCCASugAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjSDBGMA4G
A1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdEQQHSU5WQUxJRDAKBggqhkjOPQQDAgNHADBEAiA4J8X4tb775IOP
gBZ8BjlQZXPaRAgO/0d8a5Bgb5j0awIgN1i84TX34Dm8SjArcZLN38mm0zbrvEY0
wILouqC75wI=
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgIBAjAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowKjEoMCYGA1UEAxMfSW52YWxpZCBFeHRlbnNpb25zIEludGVybWVkaWF0ZTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI6fKiM3jFLkLyAn88cvlw4SwxuygRj
opP3FFBKHyUQvh3VVvfqSpSCSmp50QiajQ6Dg7CTpVZVVH+bguT7JTCjSDBGMA4G
A1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdDgQHSU5WQUxJRDAKBggqhkjOPQQDAgNIADBFAiBXToga6ILFNSXj
FiwI/ZaZvJubBHzMcrEXtIv85ybV3wIhAL3DMOezrq+dSjf+RdshlTDKwvTY8QYX
ehvRzctnYHTd
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhzCCASygAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo1EwTzAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREE
EzARgg93d3cuZXhhbXBsZS5jb20wCgYIKoZIzj0EAwIDSQAwRgIhAJ1DkyH6QYsM
bxN/aXhKYGFc1upPpxfHrzmVrVrYq34GAiEAgzAn1bws7mwi4fTBJ4XY44OisCi6
gPDLe2H4Esop38o=
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBljCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo2EwXzAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREE
EzARgg93d3cuZXhhbXBsZS5jb20wDgYDVR0jBAdJTlZBTElEMAoGCCqGSM49BAMC
A0gAMEUCIDCqsRJC3IrUHxm5txOfnjrpGmoeSvr1EhVFDhHCuV6GAiEAwJ15sf7y
+CGw0rzYTLUHw4nc5aJC9oKOhypg3SrQeGw=
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBiDCCAS6gAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo1MwUTAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGgYDVR0RBBMwEYIPd3d3LmV4YW1w
bGUuY29tMA4GA1UdEwQHSU5WQUxJRDAKBggqhkjOPQQDAgNIADBFAiEA6btgd6HI
SCvxfnaHqhAiBjLl665JJC/wpSejPlxFmI0CIGZ7pLkRuQKv132ffDBmobAsBBnT
YXmJWAHc4rsJCYEx
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBgTCCASegAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo0wwSjAOBgNVHQ8BAf8E
BAMCAgQwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhhbXBsZS5jb20w
DgYDVR0lBAdJTlZBTElEMAoGCCqGSM49BAMCA0gAMEUCIH3jx0mZhPAY2QZHYVPQ
ld6RNFGris9CFCD8AMOaZTR+AiEAgr4hSxoIm3g/CVeQkDORqgSrXU0AuVvQL2KO
NM5UG1Q=
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBhjCCASygAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo1EwTzATBgNVHSUEDDAK
BggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGCD3d3dy5leGFtcGxl
LmNvbTAOBgNVHQ8EB0lOVkFMSUQwCgYIKoZIzj0EAwIDSAAwRQIgPoSLUcWwjnDx
3N+DJPzpgHRRSZtJz6w5njQ+zcyQvrQCIQDThWHI9F5s6xQN42stFw0sasdWFc/9
No9QQf1zbGfGDw==
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBljCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo2EwXzAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREE
EzARgg93d3cuZXhhbXBsZS5jb20wDgYDVR0eBAdJTlZBTElEMAoGCCqGSM49BAMC
A0gAMEUCIQCYofdTDXH2HIpc/ZSI6IQVCM0L0/QbKbEOGeAwDtikGAIgV48ECoAt
8maDdh8y9qj/TZe6XA39BzkjtsLKhecCuV8=
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBeTCCASCgAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo0UwQzAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAOBgNVHREE
B0lOVkFMSUQwCgYIKoZIzj0EAwIDRwAwRAIgDatlhmjkW4lgYc/eyrqJp1kxKrL8
0WkPsmdUZmXiI1QCIC1bl+3ponxSaCvn81xKrQzuIq2OzWxy2PTHyNbPnGcz
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAqMSgwJgYDVQQDEx9JbnZhbGlk
IEV4dGVuc2lvbnMgSW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAw
MTAxMDAwMDAwWjAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZR
EvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5Xo2EwXzAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREE
EzARgg93d3cuZXhhbXBsZS5jb20wDgYDVR0OBAdJTlZBTElEMAoGCCqGSM49BAMC
A0kAMEYCIQDNfoYMjJUzrw2qxHKwopCt9lTQIfOCJDzndJwHLSI97gIhAIDRRWkU
OpOxpzO5zJtvsPSuFJTPtFi6dKwyZA0VVX5m
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBbjCCAROgAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjoltozgwNjAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAKBggq
hkjOPQQDAgNJADBGAiEAkLonK/c0Wai8LSe6Nhf3ln+dpPxIQD9z0e2bXzgp3ZgC
IQDUjv8fhl6szNN6cV4NElVrsuFRigAvt6Z5M132Ybgavw==
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBfTCCASOgAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolto0gwRjAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HSMEB0lOVkFMSUQwCgYIKoZIzj0EAwIDSAAwRQIgO/L4Oi8esLDZ5HQgVYd/GUey
8yPPRUkfr8+ZH5YJ724CIQCToZDd4kEPRmwjS6R20n5qrDElE4SDBq8cmJEToh57
3Q==
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBazCCARKgAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjoltozcwNTAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDgYDVR0TBAdJTlZBTElEMAoGCCqG
SM49BAMCA0cAMEQCICRNoNJx8TOSe4FKoB7EdfvG56/zvzVK8F4SDV35nbfTAiAF
QjSD7CDdbaRQymgX3ojBbAP3hj1fFbCzopKR7UUvxQ==
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBaDCCAQ6gAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjoltozMwMTAOBgNVHQ8BAf8E
BAMCAgQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHSUEB0lOVkFMSUQwCgYIKoZIzj0E
AwIDSAAwRQIgVjuDRpd+kVlqUDJcX899ZsAoIvkSPxo/lCVJ+ae28BkCIQD/9Aig
0CaivgJ8Z6mUW9ozp6ClMPfSpCEUtrhm/dg2og==
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBbjCCAROgAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjoltozgwNjATBgNVHSUEDDAK
BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwQHSU5WQUxJRDAKBggq
hkjOPQQDAgNJADBGAiEAmX21h0WJPZ8VjGRaGwYWAh2q7iS0Wzm+besT06qgnPwC
IQCEF2G9d/DaDL7H9aw51xA0B+WwHBN5r1kx6b9A5pJVtg==
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBfTCCASOgAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolto0gwRjAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HR4EB0lOVkFMSUQwCgYIKoZIzj0EAwIDSAAwRQIhALYRk6SPzWoKF3wLI6N+bWh/
iap7zpRrAZqmL3EDTlitAiB0CFMk9r5h/RDkvrP4Z+JZKum9ZVbGew73cdjDVBA3
dA==
-----END CERTIFICATE-----
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBfDCCASOgAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolto0gwRjAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HREEB0lOVkFMSUQwCgYIKoZIzj0EAwIDRwAwRAIgZKRMQGAIoUuzwYQS8UNkuTI5
H9kJYpOGZhZ3esyfvC4CIAsJGY8kgzzFpLwd3e9Zp6WAPK/snDzF9Tb4KL+GB85n
-----END CERTIFICATE-----
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBfjCCASOgAwIBAgIBATAKBggqhkjOPQQDAjAiMSAwHgYDVQQDExdJbnZhbGlk
IEV4dGVuc2lvbnMgUm9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAw
MFowIjEgMB4GA1UEAxMXSW52YWxpZCBFeHRlbnNpb25zIFJvb3QwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44TqChRYI6IeV9tI
B6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolto0gwRjAOBgNVHQ8BAf8E
BAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ4EB0lOVkFMSUQwCgYIKoZIzj0EAwIDSQAwRgIhAJbUNO8zfK439VpI2rrG9gTl
fjunP2fKsz3EK8NUtS12AiEA1m9Uzb+sUTCGhAlGEsDkjFbp3SCbvbWn7YhzqJkR
xvQ=
-----END CERTIFICATE-----
+184
View File
@@ -0,0 +1,184 @@
/* 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. */
// make_invalid_extensions.go generates a number of certificate chains with
// invalid extension encodings.
package main
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"os"
"time"
)
type extension struct {
// The name of the extension, in a form suitable for including in a
// filename.
name string
// The extension's OID.
oid []int
}
var extensions = []extension{
{name: "authority_key_identifier", oid: []int{2, 5, 29, 35}},
{name: "basic_constraints", oid: []int{2, 5, 29, 19}},
{name: "ext_key_usage", oid: []int{2, 5, 29, 37}},
{name: "key_usage", oid: []int{2, 5, 29, 15}},
{name: "name_constraints", oid: []int{2, 5, 29, 30}},
{name: "subject_alt_name", oid: []int{2, 5, 29, 17}},
{name: "subject_key_identifier", oid: []int{2, 5, 29, 14}},
}
var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey
func init() {
leafKey = ecdsaKeyFromPEMOrPanic(leafKeyPEM)
intermediateKey = ecdsaKeyFromPEMOrPanic(intermediateKeyPEM)
rootKey = ecdsaKeyFromPEMOrPanic(rootKeyPEM)
}
type templateAndKey struct {
template x509.Certificate
key *ecdsa.PrivateKey
}
func generateCertificateOrPanic(path string, subject, issuer *templateAndKey) {
cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
if err != nil {
panic(err)
}
file, err := os.Create(path)
if err != nil {
panic(err)
}
defer file.Close()
err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
if err != nil {
panic(err)
}
}
func main() {
notBefore, err := time.Parse(time.RFC3339, "2000-01-01T00:00:00Z")
if err != nil {
panic(err)
}
notAfter, err := time.Parse(time.RFC3339, "2100-01-01T00:00:00Z")
if err != nil {
panic(err)
}
root := templateAndKey{
template: x509.Certificate{
SerialNumber: new(big.Int).SetInt64(1),
Subject: pkix.Name{CommonName: "Invalid Extensions Root"},
NotBefore: notBefore,
NotAfter: notAfter,
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign,
SignatureAlgorithm: x509.ECDSAWithSHA256,
},
key: rootKey,
}
intermediate := templateAndKey{
template: x509.Certificate{
SerialNumber: new(big.Int).SetInt64(2),
Subject: pkix.Name{CommonName: "Invalid Extensions Intermediate"},
NotBefore: notBefore,
NotAfter: notAfter,
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign,
SignatureAlgorithm: x509.ECDSAWithSHA256,
},
key: intermediateKey,
}
leaf := templateAndKey{
template: x509.Certificate{
SerialNumber: new(big.Int).SetInt64(3),
Subject: pkix.Name{CommonName: "www.example.com"},
NotBefore: notBefore,
NotAfter: notAfter,
BasicConstraintsValid: true,
IsCA: false,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign,
SignatureAlgorithm: x509.ECDSAWithSHA256,
DNSNames: []string{"www.example.com"},
},
key: leafKey,
}
// Generate a valid certificate chain from the templates.
generateCertificateOrPanic("invalid_extension_root.pem", &root, &root)
generateCertificateOrPanic("invalid_extension_intermediate.pem", &intermediate, &root)
generateCertificateOrPanic("invalid_extension_leaf.pem", &leaf, &intermediate)
// Make copies of each of the three certificates with invalid extensions.
// These copies may be substituted into the valid chain.
for _, ext := range extensions {
invalidExtension := []pkix.Extension{{Id: ext.oid, Value: []byte("INVALID")}}
rootInvalid := root
rootInvalid.template.ExtraExtensions = invalidExtension
generateCertificateOrPanic(fmt.Sprintf("invalid_extension_root_%s.pem", ext.name), &rootInvalid, &rootInvalid)
intermediateInvalid := intermediate
intermediateInvalid.template.ExtraExtensions = invalidExtension
generateCertificateOrPanic(fmt.Sprintf("invalid_extension_intermediate_%s.pem", ext.name), &intermediateInvalid, &root)
leafInvalid := leaf
leafInvalid.template.ExtraExtensions = invalidExtension
generateCertificateOrPanic(fmt.Sprintf("invalid_extension_leaf_%s.pem", ext.name), &leafInvalid, &intermediate)
}
}
const leafKeyPEM = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk
024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5
w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X
-----END PRIVATE KEY-----`
const intermediateKeyPEM = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWHKCKgY058ahE3t6
vpxVQgzlycgCVMogwjK0y3XMNfWhRANCAATiOnyojN4xS5C8gJ/PHL5cOEsMbsoE
Y6KT9xRQSh8lEL4d1Vb36kqUgkpqedEImo0Og4Owk6VWVVR/m4Lk+yUw
-----END PRIVATE KEY-----`
const rootKeyPEM = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBwND/eHytW0I417J
Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq
ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt
-----END PRIVATE KEY-----`
func ecdsaKeyFromPEMOrPanic(in string) *ecdsa.PrivateKey {
keyBlock, _ := pem.Decode([]byte(in))
if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
panic("could not decode private key")
}
key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
if err != nil {
panic(err)
}
return key.(*ecdsa.PrivateKey)
}
-67
View File
@@ -65,73 +65,6 @@
* it to avoid downstream churn. */
OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM)
int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
int ptype, void *pval, uint8_t *penc, int penclen) {
uint8_t **ppenc = NULL;
if (version >= 0) {
if (!ASN1_INTEGER_set(priv->version, version)) {
return 0;
}
}
if (penc) {
int pmtype;
ASN1_OCTET_STRING *oct;
oct = ASN1_OCTET_STRING_new();
if (!oct) {
return 0;
}
oct->data = penc;
ppenc = &oct->data;
oct->length = penclen;
if (priv->broken == PKCS8_NO_OCTET) {
pmtype = V_ASN1_SEQUENCE;
} else {
pmtype = V_ASN1_OCTET_STRING;
}
ASN1_TYPE_set(priv->pkey, pmtype, oct);
}
if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) {
/* If call fails do not swallow 'enc' */
if (ppenc) {
*ppenc = NULL;
}
return 0;
}
return 1;
}
int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, const uint8_t **pk, int *ppklen,
X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8) {
if (ppkalg) {
*ppkalg = p8->pkeyalg->algorithm;
}
if (p8->pkey->type == V_ASN1_OCTET_STRING) {
p8->broken = PKCS8_OK;
if (pk) {
*pk = p8->pkey->value.octet_string->data;
*ppklen = p8->pkey->value.octet_string->length;
}
} else if (p8->pkey->type == V_ASN1_SEQUENCE) {
p8->broken = PKCS8_NO_OCTET;
if (pk) {
*pk = p8->pkey->value.sequence->data;
*ppklen = p8->pkey->value.sequence->length;
}
} else {
return 0;
}
if (pa) {
*pa = p8->pkeyalg;
}
return 1;
}
int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) {
const uint8_t *s;
int i, n;
+12 -5
View File
@@ -67,6 +67,7 @@
#include <openssl/x509v3.h>
#include "../internal.h"
#include "../x509v3/internal.h"
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
@@ -175,12 +176,18 @@ unsigned long X509_subject_name_hash_old(X509 *x)
*/
int X509_cmp(const X509 *a, const X509 *b)
{
int rv;
/* ensure hash is valid */
X509_check_purpose((X509 *)a, -1, 0);
X509_check_purpose((X509 *)b, -1, 0);
/* Fill in the |sha1_hash| fields.
*
* TODO(davidben): This may fail, in which case the the hash will be all
* zeros. This produces a consistent comparison (failures are sticky), but
* not a good one. OpenSSL now returns -2, but this is not a consistent
* comparison and may cause misbehaving sorts by transitivity. For now, we
* retain the old OpenSSL behavior, which was to ignore the error. See
* https://crbug.com/boringssl/355. */
x509v3_cache_extensions((X509 *)a);
x509v3_cache_extensions((X509 *)b);
rv = OPENSSL_memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
int rv = OPENSSL_memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
if (rv)
return rv;
/* Check for match against stored encoding too */
+10
View File
@@ -107,6 +107,16 @@ X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
return (NULL);
}
long X509_REQ_get_version(const X509_REQ *req)
{
return ASN1_INTEGER_get(req->req_info->version);
}
X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req)
{
return req->req_info->subject;
}
EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
{
if ((req == NULL) || (req->req_info == NULL))
+41
View File
@@ -60,6 +60,16 @@
#include <openssl/obj.h>
#include <openssl/x509.h>
long X509_get_version(const X509 *x509)
{
return ASN1_INTEGER_get(x509->cert_info->version);
}
X509_CINF *X509_get_cert_info(const X509 *x509)
{
return x509->cert_info;
}
int X509_set_version(X509 *x, long version)
{
if (x == NULL)
@@ -137,6 +147,14 @@ ASN1_TIME *X509_getm_notBefore(X509 *x)
return x->cert_info->validity->notBefore;
}
ASN1_TIME *X509_get_notBefore(const X509 *x509)
{
// In OpenSSL, this function is an alias for |X509_getm_notBefore|, but our
// |X509_getm_notBefore| is const-correct. |X509_get_notBefore| was
// originally a macro, so it needs to capture both get0 and getm use cases.
return x509->cert_info->validity->notBefore;
}
int X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
{
ASN1_TIME *in;
@@ -167,6 +185,14 @@ ASN1_TIME *X509_getm_notAfter(X509 *x)
return x->cert_info->validity->notAfter;
}
ASN1_TIME *X509_get_notAfter(const X509 *x509)
{
// In OpenSSL, this function is an alias for |X509_getm_notAfter|, but our
// |X509_getm_notAfter| is const-correct. |X509_get_notAfter| was
// originally a macro, so it needs to capture both get0 and getm use cases.
return x509->cert_info->validity->notAfter;
}
int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
{
if ((x == NULL) || (x->cert_info == NULL))
@@ -183,3 +209,18 @@ const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
{
return x->cert_info->signature;
}
void X509_CINF_set_modified(X509_CINF *cinf)
{
cinf->enc.modified = 1;
}
const X509_ALGOR *X509_CINF_get_signature(const X509_CINF *cinf)
{
return cinf->signature;
}
X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x509)
{
return x509->cert_info->key;
}
+361 -26
View File
@@ -233,6 +233,13 @@ static const char kRSAKey[] =
"moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
"-----END RSA PRIVATE KEY-----\n";
static const char kP256Key[] =
"-----BEGIN PRIVATE KEY-----\n"
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBw8IcnrUoEqc3VnJ\n"
"TYlodwi1b8ldMHcO6NHJzgqLtGqhRANCAATmK2niv2Wfl74vHg2UikzVl2u3qR4N\n"
"Rvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYaHPUdfvGULUvPciLB\n"
"-----END PRIVATE KEY-----\n";
// kCRLTestRoot is a test root certificate. It has private key:
//
// -----BEGIN RSA PRIVATE KEY-----
@@ -354,16 +361,16 @@ static const char kBadIssuerCRL[] =
// extension.
static const char kKnownCriticalCRL[] =
"-----BEGIN X509 CRL-----\n"
"MIIBujCBowIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
"MIIBuDCBoQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
"CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
"Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoCEwHzAKBgNV\n"
"HRQEAwIBATARBgNVHRwBAf8EBzAFoQMBAf8wDQYJKoZIhvcNAQELBQADggEBAA+3\n"
"i+5e5Ub8sccfgOBs6WVJFI9c8gvJjrJ8/dYfFIAuCyeocs7DFXn1n13CRZ+URR/Q\n"
"mVWgU28+xeusuSPYFpd9cyYTcVyNUGNTI3lwgcE/yVjPaOmzSZKdPakApRxtpKKQ\n"
"NN/56aQz3bnT/ZSHQNciRB8U6jiD9V30t0w+FDTpGaG+7bzzUH3UVF9xf9Ctp60A\n"
"3mfLe0scas7owSt4AEFuj2SPvcE7yvdOXbu+IEv21cEJUVExJAbhvIweHXh6yRW+\n"
"7VVeiNzdIjkZjyTmAzoXGha4+wbxXyBRbfH+XWcO/H+8nwyG8Gktdu2QB9S9nnIp\n"
"o/1TpfOMSGhMyMoyPrk=\n"
"Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoB8wHTAKBgNV\n"
"HRQEAwIBATAPBgNVHRwBAf8EBTADgQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAs37Jq\n"
"3Htcehm6C2PKXOHekwTqTLOPWsYHfF68kYhdzcopDZBeoKE7jLRkRRGFDaR/tfUs\n"
"kwLSDNSQ8EwPb9PT1X8kmFn9QmJgWD6f6BzaH5ZZ9iBUwOcvrydlb/jnjdIZHQxs\n"
"fKOAceW5XX3f7DANC3qwYLsQZR/APkfV8nXjPYVUz1kKj04uq/BbQviInjyUYixN\n"
"xDx+GDWVVXccehcwAu983kAqP+JDaVQPBVksLuBXz2adrEWwvbLCnZeL3zH1IY9h\n"
"6MFO6echpvGbU/H+dRX9UkhdJ7gdwKVD3RjfJl+DRVox9lz8Pbo5H699Tkv9/DQP\n"
"9dMWxqhQlv23osLp\n"
"-----END X509 CRL-----\n";
// kUnknownCriticalCRL is kBasicCRL but with an unknown critical extension.
@@ -385,16 +392,32 @@ static const char kUnknownCriticalCRL[] =
// point extension followed by an unknown critical extension
static const char kUnknownCriticalCRL2[] =
"-----BEGIN X509 CRL-----\n"
"MIIBzzCBuAIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
"MIIBzTCBtgIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
"CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
"Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoDYwNDAKBgNV\n"
"HRQEAwIBATARBgNVHRwBAf8EBzAFoQMBAf8wEwYMKoZIhvcSBAGEtwkAAQH/BAAw\n"
"DQYJKoZIhvcNAQELBQADggEBACTcpQC8jXL12JN5YzOcQ64ubQIe0XxRAd30p7qB\n"
"BTXGpgqBjrjxRfLms7EBYodEXB2oXMsDq3km0vT1MfYdsDD05S+SQ9CDsq/pUfaC\n"
"E2WNI5p8WircRnroYvbN2vkjlRbMd1+yNITohXYXCJwjEOAWOx3XIM10bwPYBv4R\n"
"rDobuLHoMgL3yHgMHmAkP7YpkBucNqeBV8cCdeAZLuhXFWi6yfr3r/X18yWbC/r2\n"
"2xXdkrSqXLFo7ToyP8YKTgiXpya4x6m53biEYwa2ULlas0igL6DK7wjYZX95Uy7H\n"
"GKljn9weIYiMPV/BzGymwfv2EW0preLwtyJNJPaxbdin6Jc=\n"
"Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoDQwMjAKBgNV\n"
"HRQEAwIBATAPBgNVHRwBAf8EBTADgQH/MBMGDCqGSIb3EgQBhLcJAAEB/wQAMA0G\n"
"CSqGSIb3DQEBCwUAA4IBAQBgSogsC5kf2wzr+0hmZtmLXYd0itAiYO0Gh9AyaEOO\n"
"myJFuqICHBSLXXUgwNkTUa2x2I/ivyReVFV756VOlWoaV2wJUs0zeCeVBgC9ZFsq\n"
"5a+8OGgXwgoYESFV5Y3QRF2a1Ytzfbw/o6xLXzTngvMsLOs12D4B5SkopyEZibF4\n"
"tXlRZyvEudTg3CCrjNP+p/GV07nZ3wcMmKJwQeilgzFUV7NaVCCo9jvPBGp0RxAN\n"
"KNif7jmjK4hD5mswo/Eq5kxQIc+mTfuUFdgHuAu1hfLYe0YK+Hr4RFf6Qy4hl7Ne\n"
"YjqkkSVIcr87u+8AznwdstnQzsyD27Jt7SjVORkYRywi\n"
"-----END X509 CRL-----\n";
// kBadExtensionCRL is kBasicCRL but with an incorrectly-encoded issuing
// distribution point extension.
static const char kBadExtensionCRL[] =
"-----BEGIN X509 CRL-----\n"
"MIIBujCBowIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
"CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
"Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoCEwHzAKBgNV\n"
"HRQEAwIBATARBgNVHRwBAf8EBzAFoQMBAf8wDQYJKoZIhvcNAQELBQADggEBAA+3\n"
"i+5e5Ub8sccfgOBs6WVJFI9c8gvJjrJ8/dYfFIAuCyeocs7DFXn1n13CRZ+URR/Q\n"
"mVWgU28+xeusuSPYFpd9cyYTcVyNUGNTI3lwgcE/yVjPaOmzSZKdPakApRxtpKKQ\n"
"NN/56aQz3bnT/ZSHQNciRB8U6jiD9V30t0w+FDTpGaG+7bzzUH3UVF9xf9Ctp60A\n"
"3mfLe0scas7owSt4AEFuj2SPvcE7yvdOXbu+IEv21cEJUVExJAbhvIweHXh6yRW+\n"
"7VVeiNzdIjkZjyTmAzoXGha4+wbxXyBRbfH+XWcO/H+8nwyG8Gktdu2QB9S9nnIp\n"
"o/1TpfOMSGhMyMoyPrk=\n"
"-----END X509 CRL-----\n";
// kEd25519Cert is a self-signed Ed25519 certificate.
@@ -1314,29 +1337,32 @@ TEST(X509Test, TestCRL) {
ASSERT_EQ(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
Verify(leaf.get(), {root.get()}, {root.get()},
{unknown_critical_crl2.get()}, X509_V_FLAG_CRL_CHECK));
// Parsing kBadExtensionCRL should fail.
EXPECT_FALSE(CRLFromPEM(kBadExtensionCRL));
}
TEST(X509Test, ManyNamesAndConstraints) {
bssl::UniquePtr<X509> many_constraints(
CertFromPEM(GetTestData("crypto/x509/many_constraints.pem").c_str()));
bssl::UniquePtr<X509> many_constraints(CertFromPEM(
GetTestData("crypto/x509/test/many_constraints.pem").c_str()));
ASSERT_TRUE(many_constraints);
bssl::UniquePtr<X509> many_names1(
CertFromPEM(GetTestData("crypto/x509/many_names1.pem").c_str()));
CertFromPEM(GetTestData("crypto/x509/test/many_names1.pem").c_str()));
ASSERT_TRUE(many_names1);
bssl::UniquePtr<X509> many_names2(
CertFromPEM(GetTestData("crypto/x509/many_names2.pem").c_str()));
CertFromPEM(GetTestData("crypto/x509/test/many_names2.pem").c_str()));
ASSERT_TRUE(many_names2);
bssl::UniquePtr<X509> many_names3(
CertFromPEM(GetTestData("crypto/x509/many_names3.pem").c_str()));
CertFromPEM(GetTestData("crypto/x509/test/many_names3.pem").c_str()));
ASSERT_TRUE(many_names3);
bssl::UniquePtr<X509> some_names1(
CertFromPEM(GetTestData("crypto/x509/some_names1.pem").c_str()));
CertFromPEM(GetTestData("crypto/x509/test/some_names1.pem").c_str()));
ASSERT_TRUE(some_names1);
bssl::UniquePtr<X509> some_names2(
CertFromPEM(GetTestData("crypto/x509/some_names2.pem").c_str()));
CertFromPEM(GetTestData("crypto/x509/test/some_names2.pem").c_str()));
ASSERT_TRUE(some_names2);
bssl::UniquePtr<X509> some_names3(
CertFromPEM(GetTestData("crypto/x509/some_names3.pem").c_str()));
CertFromPEM(GetTestData("crypto/x509/test/some_names3.pem").c_str()));
ASSERT_TRUE(some_names3);
EXPECT_EQ(X509_V_ERR_UNSPECIFIED,
@@ -2226,3 +2252,312 @@ TEST(X509Test, ServerGatedCryptoEKUs) {
EXPECT_EQ(X509_V_OK, verify_cert(leaf));
}
}
// Test that invalid extensions are rejected by, if not the parser, at least the
// verifier.
TEST(X509Test, InvalidExtensions) {
bssl::UniquePtr<X509> root = CertFromPEM(
GetTestData("crypto/x509/test/invalid_extension_root.pem").c_str());
ASSERT_TRUE(root);
bssl::UniquePtr<X509> intermediate = CertFromPEM(
GetTestData("crypto/x509/test/invalid_extension_intermediate.pem")
.c_str());
ASSERT_TRUE(intermediate);
bssl::UniquePtr<X509> leaf = CertFromPEM(
GetTestData("crypto/x509/test/invalid_extension_leaf.pem").c_str());
ASSERT_TRUE(leaf);
// Sanity-check that the baseline chain is accepted.
EXPECT_EQ(X509_V_OK,
Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}));
static const char *kExtensions[] = {
"authority_key_identifier",
"basic_constraints",
"ext_key_usage",
"key_usage",
"name_constraints",
"subject_alt_name",
"subject_key_identifier",
};
for (const char *ext : kExtensions) {
SCOPED_TRACE(ext);
bssl::UniquePtr<X509> invalid_root = CertFromPEM(
GetTestData((std::string("crypto/x509/test/invalid_extension_root_") +
ext + ".pem")
.c_str())
.c_str());
ASSERT_TRUE(invalid_root);
bssl::UniquePtr<X509> invalid_intermediate = CertFromPEM(
GetTestData(
(std::string("crypto/x509/test/invalid_extension_intermediate_") +
ext + ".pem")
.c_str())
.c_str());
ASSERT_TRUE(invalid_intermediate);
bssl::UniquePtr<X509> invalid_leaf = CertFromPEM(
GetTestData((std::string("crypto/x509/test/invalid_extension_leaf_") +
ext + ".pem")
.c_str())
.c_str());
ASSERT_TRUE(invalid_leaf);
EXPECT_EQ(
X509_V_ERR_INVALID_EXTENSION,
Verify(invalid_leaf.get(), {root.get()}, {intermediate.get()}, {}));
// If the invalid extension is on an intermediate or root,
// |X509_verify_cert| notices by way of being unable to build a path to
// a valid issuer.
EXPECT_EQ(
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
Verify(leaf.get(), {root.get()}, {invalid_intermediate.get()}, {}));
EXPECT_EQ(
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
Verify(leaf.get(), {invalid_root.get()}, {intermediate.get()}, {}));
}
}
// kExplicitDefaultVersionPEM is an X.509v1 certificate with the version number
// encoded explicitly, rather than omitted as required by DER.
static const char kExplicitDefaultVersionPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBfTCCASSgAwIBAAIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC\n"
"QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp\n"
"dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ\n"
"BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l\n"
"dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni\n"
"v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa\n"
"HPUdfvGULUvPciLBMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb7idQhY5w\n"
"BnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYfMlJhXnXJ\n"
"FA==\n"
"-----END CERTIFICATE-----\n";
// kNegativeVersionPEM is an X.509 certificate with a negative version number.
static const char kNegativeVersionPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBfTCCASSgAwIB/wIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC\n"
"QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp\n"
"dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ\n"
"BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l\n"
"dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni\n"
"v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa\n"
"HPUdfvGULUvPciLBMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb7idQhY5w\n"
"BnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYfMlJhXnXJ\n"
"FA==\n"
"-----END CERTIFICATE-----\n";
// kFutureVersionPEM is an X.509 certificate with a version number value of
// three, which is not defined. (v3 has value two).
static const char kFutureVersionPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBfTCCASSgAwIBAwIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC\n"
"QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp\n"
"dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ\n"
"BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l\n"
"dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni\n"
"v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa\n"
"HPUdfvGULUvPciLBMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb7idQhY5w\n"
"BnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYfMlJhXnXJ\n"
"FA==\n"
"-----END CERTIFICATE-----\n";
// kOverflowVersionPEM is an X.509 certificate with a version field which
// overflows |uint64_t|.
static const char kOverflowVersionPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBoDCCAUegJgIkAP//////////////////////////////////////////////\n"
"AgkA2UwE2kl9v+swCQYHKoZIzj0EATBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwK\n"
"U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4X\n"
"DTE0MDQyMzIzMjE1N1oXDTE0MDUyMzIzMjE1N1owRTELMAkGA1UEBhMCQVUxEzAR\n"
"BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5\n"
"IEx0ZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8eDZSKTNWX\n"
"a7epHg1G+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQtS89yIsEw\n"
"CQYHKoZIzj0EAQNIADBFAiEA8qA1XlE6NsOCeZvuJ1CFjnAGdJVX0il0APS+FYdd\n"
"xAcCIHweeRRqIYPwenRoeV8UmZpotPHLnhVe5h8yUmFedckU\n"
"-----END CERTIFICATE-----\n";
// kV1WithExtensionsPEM is an X.509v1 certificate with extensions.
static const char kV1WithExtensionsPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIByjCCAXECCQDZTATaSX2/6zAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw\n"
"EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0\n"
"eSBMdGQwHhcNMTQwNDIzMjMyMTU3WhcNMTQwNTIzMjMyMTU3WjBFMQswCQYDVQQG\n"
"EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk\n"
"Z2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+\n"
"Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7x\n"
"lC1Lz3IiwaNQME4wHQYDVR0OBBYEFKuE0qyrlfCCThZ4B1VXX+QmjYLRMB8GA1Ud\n"
"IwQYMBaAFKuE0qyrlfCCThZ4B1VXX+QmjYLRMAwGA1UdEwQFMAMBAf8wCQYHKoZI\n"
"zj0EAQNIADBFAiEA8qA1XlE6NsOCeZvuJ1CFjnAGdJVX0il0APS+FYddxAcCIHwe\n"
"eRRqIYPwenRoeV8UmZpotPHLnhVe5h8yUmFedckU\n"
"-----END CERTIFICATE-----\n";
// kV2WithExtensionsPEM is an X.509v2 certificate with extensions.
static const char kV2WithExtensionsPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBzzCCAXagAwIBAQIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC\n"
"QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp\n"
"dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ\n"
"BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l\n"
"dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni\n"
"v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa\n"
"HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw\n"
"HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ\n"
"BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E\n"
"BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ=\n"
"-----END CERTIFICATE-----\n";
// kV1WithIssuerUniqueIDPEM is an X.509v1 certificate with an issuerUniqueID.
static const char kV1WithIssuerUniqueIDPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBgzCCASoCCQDZTATaSX2/6zAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw\n"
"EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0\n"
"eSBMdGQwHhcNMTQwNDIzMjMyMTU3WhcNMTQwNTIzMjMyMTU3WjBFMQswCQYDVQQG\n"
"EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk\n"
"Z2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+\n"
"Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7x\n"
"lC1Lz3IiwYEJAAEjRWeJq83vMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb\n"
"7idQhY5wBnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYf\n"
"MlJhXnXJFA==\n"
"-----END CERTIFICATE-----\n";
// kV1WithSubjectUniqueIDPEM is an X.509v1 certificate with an issuerUniqueID.
static const char kV1WithSubjectUniqueIDPEM[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBgzCCASoCCQDZTATaSX2/6zAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw\n"
"EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0\n"
"eSBMdGQwHhcNMTQwNDIzMjMyMTU3WhcNMTQwNTIzMjMyMTU3WjBFMQswCQYDVQQG\n"
"EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk\n"
"Z2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+\n"
"Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7x\n"
"lC1Lz3IiwYIJAAEjRWeJq83vMAkGByqGSM49BAEDSAAwRQIhAPKgNV5ROjbDgnmb\n"
"7idQhY5wBnSVV9IpdAD0vhWHXcQHAiB8HnkUaiGD8Hp0aHlfFJmaaLTxy54VXuYf\n"
"MlJhXnXJFA==\n"
"-----END CERTIFICATE-----\n";
// Test that the X.509 parser enforces versions are valid and match the fields
// present.
TEST(X509Test, InvalidVersion) {
// kExplicitDefaultVersionPEM is invalid but, for now, we accept it. See
// https://crbug.com/boringssl/364.
EXPECT_TRUE(CertFromPEM(kExplicitDefaultVersionPEM));
EXPECT_FALSE(CertFromPEM(kNegativeVersionPEM));
EXPECT_FALSE(CertFromPEM(kFutureVersionPEM));
EXPECT_FALSE(CertFromPEM(kOverflowVersionPEM));
EXPECT_FALSE(CertFromPEM(kV1WithExtensionsPEM));
EXPECT_FALSE(CertFromPEM(kV2WithExtensionsPEM));
EXPECT_FALSE(CertFromPEM(kV1WithIssuerUniqueIDPEM));
EXPECT_FALSE(CertFromPEM(kV1WithSubjectUniqueIDPEM));
}
// The following strings are test certificates signed by kP256Key and kRSAKey,
// with missing, NULL, or invalid algorithm parameters.
static const char kP256NoParam[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBIDCBxqADAgECAgIE0jAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRUZXN0MCAX\n"
"DTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRUZXN0\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6ke\n"
"DUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMQMA4w\n"
"DAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNJADBGAiEAqdIiF+bN9Cl44oUeICpy\n"
"aXd7HqhpVUaglYKw9ChmNUACIQCpMdL0fNkFNDbRww9dSl/y7kBdk/tp16HiqeSy\n"
"gGzFYg==\n"
"-----END CERTIFICATE-----\n";
static const char kP256NullParam[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBJDCByKADAgECAgIE0jAMBggqhkjOPQQDAgUAMA8xDTALBgNVBAMTBFRlc3Qw\n"
"IBcNMDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMA8xDTALBgNVBAMTBFRl\n"
"c3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2niv2Wfl74vHg2UikzVl2u3\n"
"qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYaHPUdfvGULUvPciLBoxAw\n"
"DjAMBgNVHRMEBTADAQH/MAwGCCqGSM49BAMCBQADSQAwRgIhAKILHmyo+F3Cn/VX\n"
"UUeSXOQQKX5aLzsQitwwmNF3ZgH3AiEAsYHcrVj/ftmoQIORARkQ/+PrqntXev8r\n"
"t6uPxHrmpUY=\n"
"-----END CERTIFICATE-----\n";
static const char kP256InvalidParam[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBMTCBz6ADAgECAgIE0jATBggqhkjOPQQDAgQHZ2FyYmFnZTAPMQ0wCwYDVQQD\n"
"EwRUZXN0MCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYD\n"
"VQQDEwRUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4N\n"
"lIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1L\n"
"z3IiwaMQMA4wDAYDVR0TBAUwAwEB/zATBggqhkjOPQQDAgQHZ2FyYmFnZQNIADBF\n"
"AiAglpDf/YhN89LeJ2WAs/F0SJIrsuhS4uoInIz6WXUiuQIhAIu5Pwhp5E3Pbo8y\n"
"fLULTZnynuQUULQkRcF7S7T2WpIL\n"
"-----END CERTIFICATE-----\n";
static const char kRSANoParam[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBWzCBx6ADAgECAgIE0jALBgkqhkiG9w0BAQswDzENMAsGA1UEAxMEVGVzdDAg\n"
"Fw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsGA1UEAxMEVGVz\n"
"dDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8eDZSKTNWXa7ep\n"
"Hg1G+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQtS89yIsGjEDAO\n"
"MAwGA1UdEwQFMAMBAf8wCwYJKoZIhvcNAQELA4GBAC1f8W3W0Ao7CPfIBQYDSbPh\n"
"brZpbxdBU5x27JOS7iSa+Lc9pEH5VCX9vIypHVHXLPEfZ38yIt11eiyrmZB6w62N\n"
"l9kIeZ6FVPmC30d3sXx70Jjs+ZX9yt7kD1gLyNAQQfeYfa4rORAZT1n2YitD74NY\n"
"TWUH2ieFP3l+ecj1SeQR\n"
"-----END CERTIFICATE-----\n";
static const char kRSANullParam[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBXzCByaADAgECAgIE0jANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRUZXN0\n"
"MCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRU\n"
"ZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdr\n"
"t6keDUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMQ\n"
"MA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAzVcfIv+Rq1KrMXqIL\n"
"fPq/cWZjgqFZA1RGaGElNaqp+rkJfamq5tDGzckWpebrK+jjRN7yIlcWDtPpy3Gy\n"
"seZfvtBDR0TwJm0S/pQl8prKB4wgALcwe3bmi56Rq85nzY5ZLNcP16LQxL+jAAua\n"
"SwmQUz4bRpckRBj+sIyp1We+pg==\n"
"-----END CERTIFICATE-----\n";
static const char kRSAInvalidParam[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIBbTCB0KADAgECAgIE0jAUBgkqhkiG9w0BAQsEB2dhcmJhZ2UwDzENMAsGA1UE\n"
"AxMEVGVzdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowDzENMAsG\n"
"A1UEAxMEVGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOYraeK/ZZ+Xvi8e\n"
"DZSKTNWXa7epHg1G+92pqR6d3LpaAefWl6gKGPnDxKMeVuJ8g0jbFhoc9R1+8ZQt\n"
"S89yIsGjEDAOMAwGA1UdEwQFMAMBAf8wFAYJKoZIhvcNAQELBAdnYXJiYWdlA4GB\n"
"AHTJ6cWWjCNrZhqiWWVI3jdK+h5xpRG8jGMXxR4JnjtoYRRusJLOXhmapwCB6fA0\n"
"4vc+66O27v36yDmQX+tIc/hDrTpKNJptU8q3n2VagREvoHhkOTYkcCeS8vmnMtn8\n"
"5OMNZ/ajVwOssw61GcAlScRqEHkZFBoGp7e+QpgB2tf9\n"
"-----END CERTIFICATE-----\n";
TEST(X509Test, AlgorithmParameters) {
// P-256 requires the parameter be omitted.
bssl::UniquePtr<EVP_PKEY> key = PrivateKeyFromPEM(kP256Key);
ASSERT_TRUE(key);
bssl::UniquePtr<X509> cert = CertFromPEM(kP256NoParam);
ASSERT_TRUE(cert);
EXPECT_TRUE(X509_verify(cert.get(), key.get()));
cert = CertFromPEM(kP256NullParam);
ASSERT_TRUE(cert);
EXPECT_FALSE(X509_verify(cert.get(), key.get()));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
EXPECT_EQ(X509_R_INVALID_PARAMETER, ERR_GET_REASON(err));
cert = CertFromPEM(kP256InvalidParam);
ASSERT_TRUE(cert);
EXPECT_FALSE(X509_verify(cert.get(), key.get()));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
EXPECT_EQ(X509_R_INVALID_PARAMETER, ERR_GET_REASON(err));
// RSA parameters should be NULL, but we accept omitted ones.
key = PrivateKeyFromPEM(kRSAKey);
ASSERT_TRUE(key);
cert = CertFromPEM(kRSANoParam);
ASSERT_TRUE(cert);
EXPECT_TRUE(X509_verify(cert.get(), key.get()));
cert = CertFromPEM(kRSANullParam);
ASSERT_TRUE(cert);
EXPECT_TRUE(X509_verify(cert.get(), key.get()));
cert = CertFromPEM(kRSAInvalidParam);
ASSERT_TRUE(cert);
EXPECT_FALSE(X509_verify(cert.get(), key.get()));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
EXPECT_EQ(X509_R_INVALID_PARAMETER, ERR_GET_REASON(err));
}
+4 -1
View File
@@ -59,6 +59,8 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
#include "../x509v3/internal.h"
static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b);
static void trtable_free(X509_TRUST *p);
@@ -293,7 +295,8 @@ static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
{
X509_check_purpose(x, -1, 0);
if (!x509v3_cache_extensions(x))
return X509_TRUST_UNTRUSTED;
if (x->ex_flags & EXFLAG_SS)
return X509_TRUST_TRUSTED;
else
+28 -9
View File
@@ -146,14 +146,16 @@ static int null_callback(int ok, X509_STORE_CTX *e)
return ok;
}
/* Return 1 is a certificate is self signed */
static int cert_self_signed(X509 *x)
/* cert_self_signed checks if |x| is self-signed. If |x| is valid, it returns
* one and sets |*out_is_self_signed| to the result. If |x| is invalid, it
* returns zero. */
static int cert_self_signed(X509 *x, int *out_is_self_signed)
{
X509_check_purpose(x, -1, 0);
if (x->ex_flags & EXFLAG_SS)
return 1;
else
if (!x509v3_cache_extensions(x)) {
return 0;
}
*out_is_self_signed = (x->ex_flags & EXFLAG_SS) != 0;
return 1;
}
/* Given a certificate try and find an exact match in the store */
@@ -263,8 +265,14 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
* X509_V_ERR_CERT_CHAIN_TOO_LONG error code
* later. */
int is_self_signed;
if (!cert_self_signed(x, &is_self_signed)) {
ctx->error = X509_V_ERR_INVALID_EXTENSION;
goto end;
}
/* If we are self signed, we break */
if (cert_self_signed(x))
if (is_self_signed)
break;
/*
* If asked see if we can find issuer in trusted store first
@@ -323,7 +331,14 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
*/
i = sk_X509_num(ctx->chain);
x = sk_X509_value(ctx->chain, i - 1);
if (cert_self_signed(x)) {
int is_self_signed;
if (!cert_self_signed(x, &is_self_signed)) {
ctx->error = X509_V_ERR_INVALID_EXTENSION;
goto end;
}
if (is_self_signed) {
/* we have a self signed certificate */
if (sk_X509_num(ctx->chain) == 1) {
/*
@@ -368,8 +383,12 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
/* If we have enough, we break */
if (depth < num)
break;
if (!cert_self_signed(x, &is_self_signed)) {
ctx->error = X509_V_ERR_INVALID_EXTENSION;
goto end;
}
/* If we are self signed, we break */
if (cert_self_signed(x))
if (is_self_signed)
break;
ok = ctx->get_issuer(&xtmp, ctx, x);
+25
View File
@@ -135,6 +135,11 @@ int X509_CRL_up_ref(X509_CRL *crl)
return 1;
}
long X509_CRL_get_version(const X509_CRL *crl)
{
return ASN1_INTEGER_get(crl->crl->version);
}
const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl)
{
return crl->crl->lastUpdate;
@@ -145,6 +150,26 @@ const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl)
return crl->crl->nextUpdate;
}
ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl)
{
return crl->crl->lastUpdate;
}
ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl)
{
return crl->crl->nextUpdate;
}
X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl)
{
return crl->crl->issuer;
}
STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl)
{
return crl->crl->revoked;
}
void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg)
{
+35 -13
View File
@@ -86,7 +86,7 @@ struct x509_crl_method_st {
};
static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b);
static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
ASN1_SEQUENCE(X509_REVOKED) = {
ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
@@ -126,6 +126,9 @@ static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
* affect the output of X509_CRL_print().
*/
case ASN1_OP_D2I_POST:
/* TODO(davidben): Check that default |versions| are never encoded and
* that |extensions| is only present in v2. */
(void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
break;
}
@@ -226,6 +229,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
STACK_OF(X509_EXTENSION) *exts;
X509_EXTENSION *ext;
size_t idx;
int i;
switch (operation) {
case ASN1_OP_NEW_POST:
@@ -242,26 +246,44 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
break;
case ASN1_OP_D2I_POST:
X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
if (!X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL)) {
return 0;
}
crl->idp = X509_CRL_get_ext_d2i(crl,
NID_issuing_distribution_point, NULL,
NID_issuing_distribution_point, &i,
NULL);
if (crl->idp)
setup_idp(crl, crl->idp);
if (crl->idp != NULL) {
if (!setup_idp(crl, crl->idp)) {
return 0;
}
} else if (i != -1) {
return 0;
}
crl->akid = X509_CRL_get_ext_d2i(crl,
NID_authority_key_identifier, NULL,
NID_authority_key_identifier, &i,
NULL);
if (crl->akid == NULL && i != -1) {
return 0;
}
crl->crl_number = X509_CRL_get_ext_d2i(crl,
NID_crl_number, NULL, NULL);
NID_crl_number, &i, NULL);
if (crl->crl_number == NULL && i != -1) {
return 0;
}
crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
NID_delta_crl, NULL,
crl->base_crl_number = X509_CRL_get_ext_d2i(crl, NID_delta_crl, &i,
NULL);
if (crl->base_crl_number == NULL && i != -1) {
return 0;
}
/* Delta CRLs must have CRL number */
if (crl->base_crl_number && !crl->crl_number)
crl->flags |= EXFLAG_INVALID;
if (crl->base_crl_number && !crl->crl_number) {
OPENSSL_PUT_ERROR(X509, X509_R_DELTA_CRL_WITHOUT_CRL_NUMBER);
return 0;
}
/*
* See if we have any unhandled critical CRL extensions and indicate
@@ -319,7 +341,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
/* Convert IDP into a more convenient form */
static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
{
int idp_only = 0;
/* Set various flags according to IDP */
@@ -352,7 +374,7 @@ static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
crl->idp_reasons &= CRLDP_ALL_REASONS;
}
DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
}
ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
-154
View File
@@ -180,160 +180,6 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
return NULL;
}
/*
* Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
* decode as X509_PUBKEY
*/
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
{
X509_PUBKEY *xpk;
EVP_PKEY *pktmp;
xpk = d2i_X509_PUBKEY(NULL, pp, length);
if (!xpk)
return NULL;
pktmp = X509_PUBKEY_get(xpk);
X509_PUBKEY_free(xpk);
if (!pktmp)
return NULL;
if (a) {
EVP_PKEY_free(*a);
*a = pktmp;
}
return pktmp;
}
int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
{
X509_PUBKEY *xpk = NULL;
int ret;
if (!a)
return 0;
if (!X509_PUBKEY_set(&xpk, (EVP_PKEY *)a))
return 0;
ret = i2d_X509_PUBKEY(xpk, pp);
X509_PUBKEY_free(xpk);
return ret;
}
/*
* The following are equivalents but which return RSA and DSA keys
*/
RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
RSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
RSA_free(*a);
*a = key;
}
return key;
}
int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
pktmp = EVP_PKEY_new();
if (!pktmp) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_PKEY_set1_RSA(pktmp, (RSA *)a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
}
#ifndef OPENSSL_NO_DSA
DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
DSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_DSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
DSA_free(*a);
*a = key;
}
return key;
}
int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
pktmp = EVP_PKEY_new();
if (!pktmp) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_PKEY_set1_DSA(pktmp, (DSA *)a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
}
#endif
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
EC_KEY *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return (NULL);
key = EVP_PKEY_get1_EC_KEY(pkey);
EVP_PKEY_free(pkey);
if (!key)
return (NULL);
*pp = q;
if (a) {
EC_KEY_free(*a);
*a = key;
}
return (key);
}
int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return (0);
if ((pktmp = EVP_PKEY_new()) == NULL) {
OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
return (0);
}
EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY *)a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return (ret);
}
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj,
int ptype, void *pval,
unsigned char *penc, int penclen)
+20
View File
@@ -67,3 +67,23 @@ ASN1_SEQUENCE(X509_SIG) = {
} ASN1_SEQUENCE_END(X509_SIG)
IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)
void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **out_alg,
const ASN1_OCTET_STRING **out_digest) {
if (out_alg != NULL) {
*out_alg = sig->algor;
}
if (out_digest != NULL) {
*out_digest = sig->digest;
}
}
void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **out_alg,
ASN1_OCTET_STRING **out_digest) {
if (out_alg != NULL) {
*out_alg = sig->algor;
}
if (out_digest != NULL) {
*out_digest = sig->digest;
}
}
+28 -6
View File
@@ -98,7 +98,6 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
switch (operation) {
case ASN1_OP_NEW_POST:
ret->name = NULL;
ret->ex_flags = 0;
ret->ex_pathlen = -1;
ret->skid = NULL;
@@ -115,11 +114,35 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ret->buf = NULL;
break;
case ASN1_OP_D2I_POST:
if (ret->name != NULL)
OPENSSL_free(ret->name);
ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
case ASN1_OP_D2I_POST: {
/* The version must be one of v1(0), v2(1), or v3(2). */
long version = 0;
if (ret->cert_info->version != NULL) {
version = ASN1_INTEGER_get(ret->cert_info->version);
/* TODO(https://crbug.com/boringssl/364): |version| = 0 should also
* be rejected. This means an explicitly-encoded X.509v1 version.
* v1 is DEFAULT, so DER requires it be omitted. */
if (version < 0 || version > 2) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
return 0;
}
}
/* Per RFC5280, section 4.1.2.8, these fields require v2 or v3. */
if (version == 0 && (ret->cert_info->issuerUID != NULL ||
ret->cert_info->subjectUID != NULL)) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
return 0;
}
/* Per RFC5280, section 4.1.2.9, extensions require v3. */
if (version != 2 && ret->cert_info->extensions != NULL) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
return 0;
}
break;
}
case ASN1_OP_FREE_POST:
CRYPTO_MUTEX_cleanup(&ret->lock);
@@ -132,7 +155,6 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
GENERAL_NAMES_free(ret->altname);
NAME_CONSTRAINTS_free(ret->nc);
CRYPTO_BUFFER_free(ret->buf);
OPENSSL_free(ret->name);
break;
}
+5
View File
@@ -48,6 +48,11 @@ int x509v3_name_cmp(const char *name, const char *cmp);
OPENSSL_EXPORT int x509v3_looks_like_dns_name(const unsigned char *in,
size_t len);
// x509v3_cache_extensions fills in a number of fields relating to X.509
// extensions in |x|. It returns one on success and zero if some extensions were
// invalid.
int x509v3_cache_extensions(X509 *x);
#if defined(__cplusplus)
} /* extern C */
+75 -36
View File
@@ -68,6 +68,7 @@
#include <openssl/x509v3.h>
#include "../internal.h"
#include "internal.h"
#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
#define ku_reject(x, usage) \
@@ -77,8 +78,6 @@
#define ns_reject(x, usage) \
(((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
static void x509v3_cache_extensions(X509 *x);
static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
int ca);
static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
@@ -144,7 +143,10 @@ int X509_check_purpose(X509 *x, int id, int ca)
{
int idx;
const X509_PURPOSE *pt;
x509v3_cache_extensions(x);
if (!x509v3_cache_extensions(x)) {
return -1;
}
if (id == -1)
return 1;
idx = X509_PURPOSE_get_by_id(id);
@@ -368,7 +370,7 @@ int X509_supported_extension(X509_EXTENSION *ex)
return 0;
}
static void setup_dp(X509 *x, DIST_POINT *dp)
static int setup_dp(X509 *x, DIST_POINT *dp)
{
X509_NAME *iname = NULL;
size_t i;
@@ -381,7 +383,7 @@ static void setup_dp(X509 *x, DIST_POINT *dp)
} else
dp->dp_reasons = CRLDP_ALL_REASONS;
if (!dp->distpoint || (dp->distpoint->type != 1))
return;
return 1;
for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
if (gen->type == GEN_DIRNAME) {
@@ -392,19 +394,25 @@ static void setup_dp(X509 *x, DIST_POINT *dp)
if (!iname)
iname = X509_get_issuer_name(x);
DIST_POINT_set_dpname(dp->distpoint, iname);
return DIST_POINT_set_dpname(dp->distpoint, iname);
}
static void setup_crldp(X509 *x)
static int setup_crldp(X509 *x)
{
size_t i;
x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
int j;
x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &j, NULL);
if (x->crldp == NULL && j != -1) {
return 0;
}
for (size_t i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
if (!setup_dp(x, sk_DIST_POINT_value(x->crldp, i))) {
return 0;
}
}
return 1;
}
static void x509v3_cache_extensions(X509 *x)
int x509v3_cache_extensions(X509 *x)
{
BASIC_CONSTRAINTS *bs;
PROXY_CERT_INFO_EXTENSION *pci;
@@ -420,21 +428,22 @@ static void x509v3_cache_extensions(X509 *x)
CRYPTO_MUTEX_unlock_read(&x->lock);
if (is_set) {
return;
return (x->ex_flags & EXFLAG_INVALID) == 0;
}
CRYPTO_MUTEX_lock_write(&x->lock);
if (x->ex_flags & EXFLAG_SET) {
CRYPTO_MUTEX_unlock_write(&x->lock);
return;
return (x->ex_flags & EXFLAG_INVALID) == 0;
}
X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
x->ex_flags |= EXFLAG_INVALID;
/* V1 should mean no extensions ... */
if (!X509_get_version(x))
x->ex_flags |= EXFLAG_V1;
/* Handle basic constraints */
if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &j, NULL))) {
if (bs->ca)
x->ex_flags |= EXFLAG_CA;
if (bs->pathlen) {
@@ -448,9 +457,11 @@ static void x509v3_cache_extensions(X509 *x)
x->ex_pathlen = -1;
BASIC_CONSTRAINTS_free(bs);
x->ex_flags |= EXFLAG_BCONS;
} else if (j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
/* Handle proxy certificates */
if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &j, NULL))) {
if (x->ex_flags & EXFLAG_CA
|| X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
|| X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
@@ -462,9 +473,11 @@ static void x509v3_cache_extensions(X509 *x)
x->ex_pcpathlen = -1;
PROXY_CERT_INFO_EXTENSION_free(pci);
x->ex_flags |= EXFLAG_PROXY;
} else if (j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
/* Handle key usage */
if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
if ((usage = X509_get_ext_d2i(x, NID_key_usage, &j, NULL))) {
if (usage->length > 0) {
x->ex_kusage = usage->data[0];
if (usage->length > 1)
@@ -473,9 +486,11 @@ static void x509v3_cache_extensions(X509 *x)
x->ex_kusage = 0;
x->ex_flags |= EXFLAG_KUSAGE;
ASN1_BIT_STRING_free(usage);
} else if (j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
x->ex_xkusage = 0;
if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &j, NULL))) {
x->ex_flags |= EXFLAG_XKUSAGE;
for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
@@ -518,18 +533,28 @@ static void x509v3_cache_extensions(X509 *x)
}
}
sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
} else if (j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &j, NULL))) {
if (ns->length > 0)
x->ex_nscert = ns->data[0];
else
x->ex_nscert = 0;
x->ex_flags |= EXFLAG_NSCERT;
ASN1_BIT_STRING_free(ns);
} else if (j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &j, NULL);
if (x->skid == NULL && j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &j, NULL);
if (x->akid == NULL && j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
/* Does subject name match issuer ? */
if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
x->ex_flags |= EXFLAG_SI;
@@ -538,11 +563,17 @@ static void x509v3_cache_extensions(X509 *x)
!ku_reject(x, KU_KEY_CERT_SIGN))
x->ex_flags |= EXFLAG_SS;
}
x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL);
if (!x->nc && (j != -1))
x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, &j, NULL);
if (x->altname == NULL && j != -1) {
x->ex_flags |= EXFLAG_INVALID;
setup_crldp(x);
}
x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL);
if (x->nc == NULL && j != -1) {
x->ex_flags |= EXFLAG_INVALID;
}
if (!setup_crldp(x)) {
x->ex_flags |= EXFLAG_INVALID;
}
for (j = 0; j < X509_get_ext_count(x); j++) {
ex = X509_get_ext(x, j);
@@ -559,6 +590,7 @@ static void x509v3_cache_extensions(X509 *x)
x->ex_flags |= EXFLAG_SET;
CRYPTO_MUTEX_unlock_write(&x->lock);
return (x->ex_flags & EXFLAG_INVALID) == 0;
}
/* check_ca returns one if |x| should be considered a CA certificate and zero
@@ -579,7 +611,9 @@ static int check_ca(const X509 *x)
int X509_check_ca(X509 *x)
{
x509v3_cache_extensions(x);
if (!x509v3_cache_extensions(x)) {
return 0;
}
return check_ca(x);
}
@@ -761,8 +795,10 @@ int X509_check_issued(X509 *issuer, X509 *subject)
if (X509_NAME_cmp(X509_get_subject_name(issuer),
X509_get_issuer_name(subject)))
return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
x509v3_cache_extensions(issuer);
x509v3_cache_extensions(subject);
if (!x509v3_cache_extensions(issuer) ||
!x509v3_cache_extensions(subject)) {
return X509_V_ERR_UNSPECIFIED;
}
if (subject->akid) {
int ret = X509_check_akid(issuer, subject->akid);
@@ -819,15 +855,17 @@ int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
uint32_t X509_get_extension_flags(X509 *x)
{
/* Call for side-effect of computing hash and caching extensions */
X509_check_purpose(x, -1, -1);
if (!x509v3_cache_extensions(x)) {
return 0;
}
return x->ex_flags;
}
uint32_t X509_get_key_usage(X509 *x)
{
/* Call for side-effect of computing hash and caching extensions */
X509_check_purpose(x, -1, -1);
if (!x509v3_cache_extensions(x)) {
return 0;
}
if (x->ex_flags & EXFLAG_KUSAGE)
return x->ex_kusage;
return UINT32_MAX;
@@ -835,8 +873,9 @@ uint32_t X509_get_key_usage(X509 *x)
uint32_t X509_get_extended_key_usage(X509 *x)
{
/* Call for side-effect of computing hash and caching extensions */
X509_check_purpose(x, -1, -1);
if (!x509v3_cache_extensions(x)) {
return 0;
}
if (x->ex_flags & EXFLAG_XKUSAGE)
return x->ex_xkusage;
return UINT32_MAX;
+1 -8
View File
@@ -513,17 +513,10 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) {
}
static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) {
long ret = 1;
if (b->next_bio == NULL) {
return 0;
}
switch (cmd) {
default:
ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
break;
}
return ret;
return BIO_callback_ctrl(b->next_bio, cmd, fp);
}
static const BIO_METHOD b64_method = {
+2
View File
@@ -1,3 +1,5 @@
module boringssl.googlesource.com/boringssl
go 1.13
require golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
+8
View File
@@ -0,0 +1,8 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+16 -4
View File
@@ -106,7 +106,10 @@ OPENSSL_EXPORT void AES_decrypt(const uint8_t *in, uint8_t *out,
// AES_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode) |len|
// bytes from |in| to |out|. The |num| parameter must be set to zero on the
// first call and |ivec| will be incremented.
// first call and |ivec| will be incremented. This function may be called
// in-place with |in| equal to |out|, but otherwise the buffers may not
// partially overlap. A partial overlap may overwrite input data before it is
// read.
OPENSSL_EXPORT void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out,
size_t len, const AES_KEY *key,
uint8_t ivec[AES_BLOCK_SIZE],
@@ -114,26 +117,35 @@ OPENSSL_EXPORT void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out,
unsigned int *num);
// AES_ecb_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) a single,
// 16 byte block from |in| to |out|.
// 16 byte block from |in| to |out|. This function may be called in-place with
// |in| equal to |out|, but otherwise the buffers may not partially overlap. A
// partial overlap may overwrite input data before it is read.
OPENSSL_EXPORT void AES_ecb_encrypt(const uint8_t *in, uint8_t *out,
const AES_KEY *key, const int enc);
// AES_cbc_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len|
// bytes from |in| to |out|. The length must be a multiple of the block size.
// This function may be called in-place with |in| equal to |out|, but otherwise
// the buffers may not partially overlap. A partial overlap may overwrite input
// data before it is read.
OPENSSL_EXPORT void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t *ivec,
const int enc);
// AES_ofb128_encrypt encrypts (or decrypts, it's the same in OFB mode) |len|
// bytes from |in| to |out|. The |num| parameter must be set to zero on the
// first call.
// first call. This function may be called in-place with |in| equal to |out|,
// but otherwise the buffers may not partially overlap. A partial overlap may
// overwrite input data before it is read.
OPENSSL_EXPORT void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out,
size_t len, const AES_KEY *key,
uint8_t *ivec, int *num);
// AES_cfb128_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len|
// bytes from |in| to |out|. The |num| parameter must be set to zero on the
// first call.
// first call. This function may be called in-place with |in| equal to |out|,
// but otherwise the buffers may not partially overlap. A partial overlap may
// overwrite input data before it is read.
OPENSSL_EXPORT void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out,
size_t len, const AES_KEY *key,
uint8_t *ivec, int *num, int enc);
+22 -22
View File
@@ -619,14 +619,14 @@ typedef struct BIT_STRING_BITNAME_st {
DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
OPENSSL_EXPORT int ASN1_TYPE_get(ASN1_TYPE *a);
OPENSSL_EXPORT int ASN1_TYPE_get(const ASN1_TYPE *a);
OPENSSL_EXPORT void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
OPENSSL_EXPORT int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
OPENSSL_EXPORT int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b);
OPENSSL_EXPORT ASN1_OBJECT * ASN1_OBJECT_new(void );
OPENSSL_EXPORT void ASN1_OBJECT_free(ASN1_OBJECT *a);
OPENSSL_EXPORT int i2d_ASN1_OBJECT(ASN1_OBJECT *a,unsigned char **pp);
OPENSSL_EXPORT int i2d_ASN1_OBJECT(const ASN1_OBJECT *a,unsigned char **pp);
OPENSSL_EXPORT ASN1_OBJECT * c2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
long length);
OPENSSL_EXPORT ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
@@ -648,23 +648,23 @@ OPENSSL_EXPORT int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len
OPENSSL_EXPORT void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
OPENSSL_EXPORT int ASN1_STRING_length(const ASN1_STRING *x);
OPENSSL_EXPORT void ASN1_STRING_length_set(ASN1_STRING *x, int n);
OPENSSL_EXPORT int ASN1_STRING_type(ASN1_STRING *x);
OPENSSL_EXPORT int ASN1_STRING_type(const ASN1_STRING *x);
OPENSSL_EXPORT unsigned char * ASN1_STRING_data(ASN1_STRING *x);
OPENSSL_EXPORT const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
OPENSSL_EXPORT int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp);
OPENSSL_EXPORT int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a,unsigned char **pp);
OPENSSL_EXPORT ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,const unsigned char **pp, long length);
OPENSSL_EXPORT int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length );
OPENSSL_EXPORT int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
OPENSSL_EXPORT int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n);
OPENSSL_EXPORT int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a, unsigned char *flags, int flags_len);
OPENSSL_EXPORT int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n);
OPENSSL_EXPORT int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, unsigned char *flags, int flags_len);
OPENSSL_EXPORT int i2d_ASN1_BOOLEAN(int a,unsigned char **pp);
OPENSSL_EXPORT int d2i_ASN1_BOOLEAN(int *a,const unsigned char **pp,long length);
DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
OPENSSL_EXPORT int i2c_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp);
OPENSSL_EXPORT int i2c_ASN1_INTEGER(const ASN1_INTEGER *a,unsigned char **pp);
OPENSSL_EXPORT ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a,const unsigned char **pp, long length);
OPENSSL_EXPORT ASN1_INTEGER * ASN1_INTEGER_dup(const ASN1_INTEGER *x);
OPENSSL_EXPORT int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
@@ -713,15 +713,15 @@ DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t);
OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s,time_t t, int offset_day, long offset_sec);
OPENSSL_EXPORT int ASN1_TIME_check(ASN1_TIME *t);
OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
OPENSSL_EXPORT int ASN1_TIME_check(const ASN1_TIME *t);
OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
OPENSSL_EXPORT int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
OPENSSL_EXPORT int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
OPENSSL_EXPORT int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a);
OPENSSL_EXPORT int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a);
OPENSSL_EXPORT int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type);
OPENSSL_EXPORT int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a);
OPENSSL_EXPORT int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a);
OPENSSL_EXPORT int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a);
OPENSSL_EXPORT int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a);
OPENSSL_EXPORT int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type);
OPENSSL_EXPORT int i2t_ASN1_OBJECT(char *buf,int buf_len, const ASN1_OBJECT *a);
OPENSSL_EXPORT ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len, const char *sn, const char *ln);
@@ -732,9 +732,9 @@ OPENSSL_EXPORT ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *
OPENSSL_EXPORT BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai,BIGNUM *bn);
OPENSSL_EXPORT int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
OPENSSL_EXPORT long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a);
OPENSSL_EXPORT ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai);
OPENSSL_EXPORT BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai,BIGNUM *bn);
OPENSSL_EXPORT long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a);
OPENSSL_EXPORT ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai);
OPENSSL_EXPORT BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai,BIGNUM *bn);
/* General */
/* given a string, return the correct type, max is the maximum length */
@@ -753,7 +753,7 @@ OPENSSL_EXPORT void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
#ifndef OPENSSL_NO_FP_API
OPENSSL_EXPORT void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
OPENSSL_EXPORT int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
OPENSSL_EXPORT int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
OPENSSL_EXPORT int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags);
#endif
OPENSSL_EXPORT int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
@@ -764,12 +764,12 @@ OPENSSL_EXPORT int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
OPENSSL_EXPORT int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a);
OPENSSL_EXPORT int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
OPENSSL_EXPORT int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
OPENSSL_EXPORT int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags);
OPENSSL_EXPORT const char *ASN1_tag2str(int tag);
/* Used to load and write netscape format cert */
OPENSSL_EXPORT void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
OPENSSL_EXPORT void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);
OPENSSL_EXPORT ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
@@ -793,8 +793,8 @@ OPENSSL_EXPORT ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char
OPENSSL_EXPORT int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
OPENSSL_EXPORT int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf);
OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf);
#ifdef __cplusplus
+2 -2
View File
@@ -90,7 +90,7 @@ extern "C" {
#elif defined(__x86) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
#define OPENSSL_32_BIT
#define OPENSSL_X86
#elif defined(__aarch64__)
#elif defined(__aarch64__) || defined(_M_ARM64)
#define OPENSSL_64_BIT
#define OPENSSL_AARCH64
#elif defined(__arm) || defined(__arm__) || defined(_M_ARM)
@@ -184,7 +184,7 @@ extern "C" {
// A consumer may use this symbol in the preprocessor to temporarily build
// against multiple revisions of BoringSSL at the same time. It is not
// recommended to do so for longer than is necessary.
#define BORINGSSL_API_VERSION 10
#define BORINGSSL_API_VERSION 11
#if defined(BORINGSSL_SHARED_LIBRARY)
+69
View File
@@ -947,6 +947,75 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx,
OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx,
const EVP_MD *md);
// i2d_PUBKEY marshals a public key from |pkey| as a DER-encoded
// SubjectPublicKeyInfo. If |outp| is not NULL, the result is written to |*outp|
// and |*outp| is advanced just past the output. It returns the number of bytes
// in the result, whether written or not, or a negative value on error.
//
// Use |EVP_marshal_public_key| instead.
OPENSSL_EXPORT int i2d_PUBKEY(const EVP_PKEY *pkey, uint8_t **outp);
// d2i_PUBKEY parses a DER-encoded SubjectPublicKeyInfo from |len| bytes at
// |*inp|. It returns a newly-allocated result, or NULL on error. On success,
// |*inp| is advanced past the DER structure. If |out| is not NULL, it also
// frees any existing object pointed by |*out| and writes the result.
//
// Use |EVP_parse_public_key| instead.
OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY(EVP_PKEY **out, const uint8_t **inp,
long len);
// i2d_RSA_PUBKEY marshals |rsa| as a DER-encoded SubjectPublicKeyInfo. If
// |outp| is not NULL, the result is written to |*outp| and
// |*outp| is advanced just past the output. It returns the number of bytes in
// the result, whether written or not, or a negative value on error.
//
// Use |EVP_marshal_public_key| instead.
OPENSSL_EXPORT int i2d_RSA_PUBKEY(const RSA *rsa, uint8_t **outp);
// d2i_RSA_PUBKEY parses an RSA public key as a DER-encoded SubjectPublicKeyInfo
// from |len| bytes at |*inp|. It returns a newly-allocated result, or NULL on
// error. On success, |*inp| is advanced past the DER structure. If |out| is not
// NULL, it also frees any existing object pointed by |*out| and writes the
// result.
//
// Use |EVP_parse_public_key| instead.
OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY(RSA **out, const uint8_t **inp, long len);
// i2d_DSA_PUBKEY marshals |dsa| as a DER-encoded SubjectPublicKeyInfo. If
// |outp| is not NULL, the result is written to |*outp| and |*outp| is advanced
// just past the output. It returns the number of bytes in the result, whether
// written or not, or a negative value on error.
//
// Use |EVP_marshal_public_key| instead.
OPENSSL_EXPORT int i2d_DSA_PUBKEY(const DSA *dsa, uint8_t **outp);
// d2i_DSA_PUBKEY parses a DSA public key as a DER-encoded SubjectPublicKeyInfo
// from |len| bytes at |*inp|. It returns a newly-allocated result, or NULL on
// error. On success, |*inp| is advanced past the DER structure. If |out| is not
// NULL, it also frees any existing object pointed by |*out| and writes the
// result.
//
// Use |EVP_parse_public_key| instead.
OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY(DSA **out, const uint8_t **inp, long len);
// i2d_EC_PUBKEY marshals |ec_key| as a DER-encoded SubjectPublicKeyInfo. If
// |outp| is not NULL, the result is written to |*outp| and |*outp| is advanced
// just past the output. It returns the number of bytes in the result, whether
// written or not, or a negative value on error.
//
// Use |EVP_marshal_public_key| instead.
OPENSSL_EXPORT int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp);
// d2i_EC_PUBKEY parses an EC public key as a DER-encoded SubjectPublicKeyInfo
// from |len| bytes at |*inp|. It returns a newly-allocated result, or NULL on
// error. On success, |*inp| is advanced past the DER structure. If |out| is not
// NULL, it also frees any existing object pointed by |*out| and writes the
// result.
//
// Use |EVP_parse_public_key| instead.
OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp,
long len);
// Preprocessor compatibility section (hidden).
//

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