From c77d0f8c776c89195d4095d51f2eaebb621887a6 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Wed, 6 Dec 2023 23:07:11 -0500 Subject: [PATCH 01/15] Document and fix up name hashing functions These return 32-bit hashes, so they should return a platform-independent uint32_t. I've categorized X509_issuer_name_hash and friends under "convenience" functions. X509_NAME_hash and X509_NAME_hash_old are as yet unclassified. Since the hash function is only relevant to X509_LOOKUP_hash_dir, I'm thinking I'll put them with that, once that's organized. While I'm here, simplify the implementations of these functions. The hash operation itself can be made infallible and allocation-free easily. However the function itself is still fallible (and non-const, and not thread-safe) due to the cached encoding mess. X509Test.NameHash captures existing hash values, so we'd notice if this changed the output. Update-Note: This is source-compatible for C/C++, including with -Wconversion, but some bindings need a patch in cl/588632028 to be compatible. Bug: 426 Change-Id: I9bfd3f1093ab15c44d8cb2d81d53aeb3d6e49fc9 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64647 Commit-Queue: David Benjamin Reviewed-by: Bob Beck --- crypto/x509/by_dir.c | 10 ++++--- crypto/x509/internal.h | 1 - crypto/x509/x509_cmp.c | 57 ++++++++++++++++------------------------ crypto/x509/x509_test.cc | 4 +-- include/openssl/x509.h | 40 ++++++++++++++++++++++------ 5 files changed, 62 insertions(+), 50 deletions(-) diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 64cec53259..f5e4787224 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -54,6 +54,7 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +#include #include #include #include @@ -68,7 +69,7 @@ #include "internal.h" typedef struct lookup_dir_hashes_st { - unsigned long hash; + uint32_t hash; int suffix; } BY_DIR_HASH; @@ -246,8 +247,8 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, int ok = 0; size_t i; int j, k; - unsigned long h; - unsigned long hash_array[2]; + uint32_t h; + uint32_t hash_array[2]; int hash_index; BUF_MEM *b = NULL; X509_OBJECT stmp, *tmp; @@ -309,7 +310,8 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, hent = NULL; } for (;;) { - snprintf(b->data, b->max, "%s/%08lx.%s%d", ent->dir, h, postfix, k); + snprintf(b->data, b->max, "%s/%08" PRIx32 ".%s%d", ent->dir, h, postfix, + k); #ifndef OPENSSL_NO_POSIX_IO #if defined(_WIN32) && !defined(stat) #define stat _stat diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h index afc6cd7e78..b277eb0dba 100644 --- a/crypto/x509/internal.h +++ b/crypto/x509/internal.h @@ -105,7 +105,6 @@ struct X509_name_st { STACK_OF(X509_NAME_ENTRY) *entries; int modified; // true if 'bytes' needs to be built BUF_MEM *bytes; - // unsigned long hash; Keep the hash around for lookups unsigned char *canon_enc; int canon_enclen; } /* X509_NAME */; diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index a934e39e3c..714212a308 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -60,7 +60,9 @@ #include #include #include +#include #include +#include #include #include @@ -88,11 +90,11 @@ X509_NAME *X509_get_issuer_name(const X509 *a) { return a->cert_info->issuer; } -unsigned long X509_issuer_name_hash(X509 *x) { - return (X509_NAME_hash(x->cert_info->issuer)); +uint32_t X509_issuer_name_hash(X509 *x) { + return X509_NAME_hash(x->cert_info->issuer); } -unsigned long X509_issuer_name_hash_old(X509 *x) { +uint32_t X509_issuer_name_hash_old(X509 *x) { return (X509_NAME_hash_old(x->cert_info->issuer)); } @@ -108,12 +110,12 @@ const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x509) { return x509->cert_info->serialNumber; } -unsigned long X509_subject_name_hash(X509 *x) { - return (X509_NAME_hash(x->cert_info->subject)); +uint32_t X509_subject_name_hash(X509 *x) { + return X509_NAME_hash(x->cert_info->subject); } -unsigned long X509_subject_name_hash_old(X509 *x) { - return (X509_NAME_hash_old(x->cert_info->subject)); +uint32_t X509_subject_name_hash_old(X509 *x) { + return X509_NAME_hash_old(x->cert_info->subject); } // Compare two certificates: they must be identical for this to work. NB: @@ -165,44 +167,29 @@ int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { return OPENSSL_memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); } -unsigned long X509_NAME_hash(X509_NAME *x) { - unsigned long ret = 0; - unsigned char md[SHA_DIGEST_LENGTH]; - - // Make sure X509_NAME structure contains valid cached encoding - i2d_X509_NAME(x, NULL); - if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(), NULL)) { +uint32_t X509_NAME_hash(X509_NAME *x) { + // Make sure the X509_NAME structure contains a valid cached encoding. + if (i2d_X509_NAME(x, NULL) < 0) { return 0; } - ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | - ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)) & - 0xffffffffL; - return ret; + uint8_t md[SHA_DIGEST_LENGTH]; + SHA1(x->canon_enc, x->canon_enclen, md); + return CRYPTO_load_u32_le(md); } // I now DER encode the name and hash it. Since I cache the DER encoding, // this is reasonably efficient. -unsigned long X509_NAME_hash_old(X509_NAME *x) { - EVP_MD_CTX md_ctx; - unsigned long ret = 0; - unsigned char md[16]; - - // Make sure X509_NAME structure contains valid cached encoding - i2d_X509_NAME(x, NULL); - EVP_MD_CTX_init(&md_ctx); - // EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) && - EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) && - EVP_DigestFinal_ex(&md_ctx, md, NULL)) { - ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | - ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)) & - 0xffffffffL; +uint32_t X509_NAME_hash_old(X509_NAME *x) { + // Make sure the X509_NAME structure contains a valid cached encoding. + if (i2d_X509_NAME(x, NULL) < 0) { + return 0; } - EVP_MD_CTX_cleanup(&md_ctx); - return ret; + uint8_t md[SHA_DIGEST_LENGTH]; + MD5((const uint8_t *)x->bytes->data, x->bytes->length, md); + return CRYPTO_load_u32_le(md); } X509 *X509_find_by_issuer_and_serial(const STACK_OF(X509) *sk, X509_NAME *name, diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index d30f9bbcab..f8c930fb54 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -2582,8 +2582,8 @@ TEST(X509Test, X509NameSet) { TEST(X509Test, NameHash) { struct { std::vector name_der; - unsigned long hash; - unsigned long hash_old; + uint32_t hash; + uint32_t hash_old; } kTests[] = { // SEQUENCE { // SET { diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 989b70909d..66668a635d 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -2831,6 +2831,22 @@ OPENSSL_EXPORT int X509_subject_name_cmp(const X509 *a, const X509 *b); // CRL, only the issuer fields using |X509_NAME_cmp|. OPENSSL_EXPORT int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +// X509_issuer_name_hash returns the hash of |x509|'s issuer name with +// |X509_NAME_hash|. +OPENSSL_EXPORT uint32_t X509_issuer_name_hash(X509 *x509); + +// X509_subject_name_hash returns the hash of |x509|'s subject name with +// |X509_NAME_hash|. +OPENSSL_EXPORT uint32_t X509_subject_name_hash(X509 *x509); + +// X509_issuer_name_hash returns the hash of |x509|'s issuer name with +// |X509_NAME_hash_old|. +OPENSSL_EXPORT uint32_t X509_issuer_name_hash_old(X509 *x509); + +// X509_usjbect_name_hash returns the hash of |x509|'s usjbect name with +// |X509_NAME_hash_old|. +OPENSSL_EXPORT uint32_t X509_subject_name_hash_old(X509 *x509); + // ex_data functions. // @@ -3443,16 +3459,24 @@ OPENSSL_EXPORT const char *X509_get_default_private_dir(void); OPENSSL_EXPORT int X509_TRUST_set(int *t, int trust); -OPENSSL_EXPORT unsigned long X509_issuer_name_hash(X509 *a); - -OPENSSL_EXPORT unsigned long X509_subject_name_hash(X509 *x); +OPENSSL_EXPORT int X509_cmp(const X509 *a, const X509 *b); -OPENSSL_EXPORT unsigned long X509_issuer_name_hash_old(X509 *a); -OPENSSL_EXPORT unsigned long X509_subject_name_hash_old(X509 *x); +// X509_NAME_hash returns a hash of |name|, or zero on error. This is the new +// hash used by |X509_LOOKUP_hash_dir|. +// +// TODO(https://crbug.com/boringssl/407): This should be const and thread-safe +// but currently is neither, notably if |name| was modified from its parsed +// value. +OPENSSL_EXPORT uint32_t X509_NAME_hash(X509_NAME *name); -OPENSSL_EXPORT int X509_cmp(const X509 *a, const X509 *b); -OPENSSL_EXPORT unsigned long X509_NAME_hash(X509_NAME *x); -OPENSSL_EXPORT unsigned long X509_NAME_hash_old(X509_NAME *x); +// X509_NAME_hash_old returns a hash of |name|, or zero on error. This is the +// legacy hash used by |X509_LOOKUP_hash_dir|, which is still supported for +// compatibility. +// +// TODO(https://crbug.com/boringssl/407): This should be const and thread-safe +// but currently is neither, notably if |name| was modified from its parsed +// value. +OPENSSL_EXPORT uint32_t X509_NAME_hash_old(X509_NAME *name); OPENSSL_EXPORT int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); From 547221f5dc50e62543733cd65bd71bd97785afb6 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Tue, 12 Dec 2023 11:48:10 -0500 Subject: [PATCH 02/15] Assume the Arm assembler can handle ADR It's 2023. We shouldn't need to be counting offsets from PC anymore. Instead, let the assembler figure this out with an ADR instruction. Additionally, since it's easy, in chacha-armv4.pl, avoid depending on the exact offset between code and data. We still depend on the code and data being close enough to fit within ADR's (very tight) bounds however. (E.g. an ADR of K256 inside sha256_block_data_order_armv8 would not work because K256 is too far away.) I have not removed the offset dependency in the SHA-2 files yet as they're a bit thorny and .Lsha256_block_data_order-K256 does not seem to work on Apple's 32-bit Arm assembler. (We probably should drop 32-bit Arm assembly on Apple platforms. It doesn't really exist anymore.) Once the armcap references are gone, that will be more straightforward. Update-Note: If 32-bit Arm assembly no longer builds, let us know and tell us what your toolchain is. Change-Id: Ie191781fed98d53c3b986b2f535132b970d79f98 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64747 Auto-Submit: David Benjamin Reviewed-by: Bob Beck Commit-Queue: David Benjamin --- crypto/chacha/asm/chacha-armv4.pl | 11 +++-------- crypto/fipsmodule/sha/asm/sha256-armv4.pl | 6 ++---- crypto/fipsmodule/sha/asm/sha512-armv4.pl | 6 ++---- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/crypto/chacha/asm/chacha-armv4.pl b/crypto/chacha/asm/chacha-armv4.pl index 1f5ceffb26..24fbb840c2 100755 --- a/crypto/chacha/asm/chacha-armv4.pl +++ b/crypto/chacha/asm/chacha-armv4.pl @@ -198,7 +198,7 @@ sub ROUND { .long 1,0,0,0 #if __ARM_MAX_ARCH__>=7 .LOPENSSL_armcap: -.word OPENSSL_armcap_P-.LChaCha20_ctr32 +.word OPENSSL_armcap_P-.Lsigma #else .word -1 #endif @@ -210,11 +210,7 @@ sub ROUND { .LChaCha20_ctr32: ldr r12,[sp,#0] @ pull pointer to counter and nonce stmdb sp!,{r0-r2,r4-r11,lr} -#if __ARM_ARCH<7 && !defined(__thumb2__) - sub r14,pc,#16 @ ChaCha20_ctr32 -#else - adr r14,.LChaCha20_ctr32 -#endif + adr r14,.Lsigma cmp r2,#0 @ len==0? #ifdef __thumb2__ itt eq @@ -224,7 +220,7 @@ sub ROUND { #if __ARM_MAX_ARCH__>=7 cmp r2,#192 @ test len bls .Lshort - ldr r4,[r14,#-32] + ldr r4,[r14,#32] ldr r4,[r14,r4] # ifdef __APPLE__ ldr r4,[r4] @@ -235,7 +231,6 @@ sub ROUND { #endif ldmia r12,{r4-r7} @ load counter and nonce sub sp,sp,#4*(16) @ off-load area - sub r14,r14,#64 @ .Lsigma stmdb sp!,{r4-r7} @ copy counter and nonce ldmia r3,{r4-r11} @ load key ldmia r14,{r0-r3} @ load sigma diff --git a/crypto/fipsmodule/sha/asm/sha256-armv4.pl b/crypto/fipsmodule/sha/asm/sha256-armv4.pl index 6812b27a7e..fa82f3c24e 100644 --- a/crypto/fipsmodule/sha/asm/sha256-armv4.pl +++ b/crypto/fipsmodule/sha/asm/sha256-armv4.pl @@ -227,11 +227,7 @@ sub BODY_16_XX { .type sha256_block_data_order,%function sha256_block_data_order: .Lsha256_block_data_order: -#if __ARM_ARCH<7 && !defined(__thumb2__) - sub r3,pc,#8 @ sha256_block_data_order -#else adr r3,.Lsha256_block_data_order -#endif #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) ldr r12,.LOPENSSL_armcap ldr r12,[r3,r12] @ OPENSSL_armcap_P @@ -246,6 +242,8 @@ sub BODY_16_XX { add $len,$inp,$len,lsl#6 @ len to point at the end of inp stmdb sp!,{$ctx,$inp,$len,r4-r11,lr} ldmia $ctx,{$A,$B,$C,$D,$E,$F,$G,$H} + @ TODO(davidben): When the OPENSSL_armcap logic above is removed, + @ replace this with a simple ADR. sub $Ktbl,r3,#256+32 @ K256 sub sp,sp,#16*4 @ alloca(X[16]) .Loop: diff --git a/crypto/fipsmodule/sha/asm/sha512-armv4.pl b/crypto/fipsmodule/sha/asm/sha512-armv4.pl index d470dafadc..f52b5b0e8b 100644 --- a/crypto/fipsmodule/sha/asm/sha512-armv4.pl +++ b/crypto/fipsmodule/sha/asm/sha512-armv4.pl @@ -288,11 +288,7 @@ () .type sha512_block_data_order,%function sha512_block_data_order: .Lsha512_block_data_order: -#if __ARM_ARCH<7 && !defined(__thumb2__) - sub r3,pc,#8 @ sha512_block_data_order -#else adr r3,.Lsha512_block_data_order -#endif #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) ldr r12,.LOPENSSL_armcap ldr r12,[r3,r12] @ OPENSSL_armcap_P @@ -304,6 +300,8 @@ () #endif add $len,$inp,$len,lsl#7 @ len to point at the end of inp stmdb sp!,{r4-r12,lr} + @ TODO(davidben): When the OPENSSL_armcap logic above is removed, + @ replace this with a simple ADR. sub $Ktbl,r3,#672 @ K512 sub sp,sp,#9*8 From fcec1397a411cbe4e27bd1428dad63adf207dc33 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Tue, 12 Dec 2023 13:58:22 -0500 Subject: [PATCH 03/15] Disable 32-bit Arm assembly optimizations on iOS The last iOS version that supported 32-bit was iOS 10, which I don't believe any of our consumers support anymore. (Chromium does not, neither does google/oss-policies-info.) Our iOS CI coverage comes from Chromium, so this means we don't actually have any test coverage for 32-bit iOS, only compile coverage. In addition to lacking any test coverage, 32-bit Arm assembly is more platform-dependent than one might expect, between different limitiations on patterns for PC-relative loads and lots of assembler quirks around what kinds of label expressions (which show up in PC-relative loads a lot) are allowed. Finally, since iOS in that era did not do runtime detection of features and relied on compiling a binary multiple times, the 32-bit assembly would never enable AES acceleration anyway, so it's not as impactful as on other platforms. Between all that, it's no longer worth enabling this. Disable it in target.h which, with the all the recent build simplifications, should be sufficient to disable this code. Update-Note: iOS on 32-bit Arm now disables assembly. This is unlikely to impact anyone. As far as I can tell, 32-bit Arm for iOS thoroughly does not exist anymore. Change-Id: If31208b42047377ad1b4fb0af6fee17334f18330 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64748 Auto-Submit: David Benjamin Reviewed-by: Bob Beck Commit-Queue: Bob Beck --- include/openssl/target.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/openssl/target.h b/include/openssl/target.h index 3e777313c3..d5b5c7e592 100644 --- a/include/openssl/target.h +++ b/include/openssl/target.h @@ -208,6 +208,12 @@ #endif #endif +// Disable 32-bit Arm assembly on Apple platforms. The last iOS version that +// supported 32-bit Arm was iOS 10. +#if defined(OPENSSL_APPLE) && defined(OPENSSL_ARM) +#define OPENSSL_ASM_INCOMPATIBLE +#endif + #if defined(OPENSSL_ASM_INCOMPATIBLE) #undef OPENSSL_ASM_INCOMPATIBLE #if !defined(OPENSSL_NO_ASM) From 62f43f5ea57b9b208fc784e5fa959bce89ebd718 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 11 Dec 2023 21:23:27 -0500 Subject: [PATCH 04/15] sha: Move Armv7 dispatching to C sha256_block_data_order_hw required a bit of wrestling with Arm immediate limits. PC-relative addressing in 32-bit Arm is a huge mess. I think I could have avoided the extra load with a lot of effort (convincing the assembler to evaluate a messy expression), but this is simpler and there was no measurable performance difference. Change-Id: I3fab4abc0fa24e0d689581e2c9b9faaa32bd7442 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64749 Commit-Queue: Bob Beck Auto-Submit: David Benjamin Reviewed-by: Bob Beck --- crypto/fipsmodule/sha/asm/sha1-armv4-large.pl | 41 +++---------- crypto/fipsmodule/sha/asm/sha256-armv4.pl | 61 ++++++++----------- crypto/fipsmodule/sha/asm/sha512-armv4.pl | 35 ++--------- crypto/fipsmodule/sha/internal.h | 32 +++++++++- crypto/fipsmodule/sha/sha1.c | 6 ++ crypto/fipsmodule/sha/sha256.c | 6 ++ crypto/fipsmodule/sha/sha512.c | 6 ++ crypto/fipsmodule/sha/sha_test.cc | 15 +++++ 8 files changed, 105 insertions(+), 97 deletions(-) diff --git a/crypto/fipsmodule/sha/asm/sha1-armv4-large.pl b/crypto/fipsmodule/sha/asm/sha1-armv4-large.pl index c52b546f72..532a81b0b4 100644 --- a/crypto/fipsmodule/sha/asm/sha1-armv4-large.pl +++ b/crypto/fipsmodule/sha/asm/sha1-armv4-large.pl @@ -197,24 +197,11 @@ sub BODY_40_59 { .code 32 #endif -.global sha1_block_data_order -.type sha1_block_data_order,%function +.global sha1_block_data_order_nohw +.type sha1_block_data_order_nohw,%function .align 5 -sha1_block_data_order: -#if __ARM_MAX_ARCH__>=7 -.Lsha1_block: - adr r3,.Lsha1_block - ldr r12,.LOPENSSL_armcap - ldr r12,[r3,r12] @ OPENSSL_armcap_P -#ifdef __APPLE__ - ldr r12,[r12] -#endif - tst r12,#ARMV8_SHA1 - bne .LARMv8 - tst r12,#ARMV7_NEON - bne .LNEON -#endif +sha1_block_data_order_nohw: stmdb sp!,{r4-r12,lr} add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp ldmia $ctx,{$a,$b,$c,$d,$e} @@ -304,17 +291,13 @@ sub BODY_40_59 { moveq pc,lr @ be binary compatible with V4, yet bx lr @ interoperable with Thumb ISA:-) #endif -.size sha1_block_data_order,.-sha1_block_data_order +.size sha1_block_data_order_nohw,.-sha1_block_data_order_nohw .align 5 .LK_00_19: .word 0x5a827999 .LK_20_39: .word 0x6ed9eba1 .LK_40_59: .word 0x8f1bbcdc .LK_60_79: .word 0xca62c1d6 -#if __ARM_MAX_ARCH__>=7 -.LOPENSSL_armcap: -.word OPENSSL_armcap_P-.Lsha1_block -#endif .asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " .align 5 ___ @@ -530,10 +513,10 @@ () .arch armv7-a .fpu neon +.global sha1_block_data_order_neon .type sha1_block_data_order_neon,%function .align 4 sha1_block_data_order_neon: -.LNEON: stmdb sp!,{r4-r12,lr} add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp @ dmb @ errata #451034 on early Cortex A8 @@ -625,10 +608,10 @@ () # define INST(a,b,c,d) .byte a,b,c,d|0x10 # endif -.type sha1_block_data_order_armv8,%function +.global sha1_block_data_order_hw +.type sha1_block_data_order_hw,%function .align 5 -sha1_block_data_order_armv8: -.LARMv8: +sha1_block_data_order_hw: vstmdb sp!,{d8-d15} @ ABI specification says so veor $E,$E,$E @@ -693,16 +676,10 @@ () vldmia sp!,{d8-d15} ret @ bx lr -.size sha1_block_data_order_armv8,.-sha1_block_data_order_armv8 +.size sha1_block_data_order_hw,.-sha1_block_data_order_hw #endif ___ }}} -$code.=<<___; -#if __ARM_MAX_ARCH__>=7 -.comm OPENSSL_armcap_P,4,4 -.hidden OPENSSL_armcap_P -#endif -___ { my %opcode = ( "sha1c" => 0xf2000c40, "sha1p" => 0xf2100c40, diff --git a/crypto/fipsmodule/sha/asm/sha256-armv4.pl b/crypto/fipsmodule/sha/asm/sha256-armv4.pl index fa82f3c24e..59f34174e4 100644 --- a/crypto/fipsmodule/sha/asm/sha256-armv4.pl +++ b/crypto/fipsmodule/sha/asm/sha256-armv4.pl @@ -217,34 +217,15 @@ sub BODY_16_XX { .word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 .size K256,.-K256 .word 0 @ terminator -#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -.LOPENSSL_armcap: -.word OPENSSL_armcap_P-.Lsha256_block_data_order -#endif .align 5 -.global sha256_block_data_order -.type sha256_block_data_order,%function -sha256_block_data_order: -.Lsha256_block_data_order: - adr r3,.Lsha256_block_data_order -#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) - ldr r12,.LOPENSSL_armcap - ldr r12,[r3,r12] @ OPENSSL_armcap_P -#ifdef __APPLE__ - ldr r12,[r12] -#endif - tst r12,#ARMV8_SHA256 - bne .LARMv8 - tst r12,#ARMV7_NEON - bne .LNEON -#endif +.global sha256_block_data_order_nohw +.type sha256_block_data_order_nohw,%function +sha256_block_data_order_nohw: add $len,$inp,$len,lsl#6 @ len to point at the end of inp stmdb sp!,{$ctx,$inp,$len,r4-r11,lr} ldmia $ctx,{$A,$B,$C,$D,$E,$F,$G,$H} - @ TODO(davidben): When the OPENSSL_armcap logic above is removed, - @ replace this with a simple ADR. - sub $Ktbl,r3,#256+32 @ K256 + adr $Ktbl,K256 sub sp,sp,#16*4 @ alloca(X[16]) .Loop: # if __ARM_ARCH>=7 @@ -298,7 +279,7 @@ sub BODY_16_XX { moveq pc,lr @ be binary compatible with V4, yet bx lr @ interoperable with Thumb ISA:-) #endif -.size sha256_block_data_order,.-sha256_block_data_order +.size sha256_block_data_order_nohw,.-sha256_block_data_order_nohw ___ ###################################################################### # NEON stuff @@ -483,10 +464,12 @@ () .align 5 .skip 16 sha256_block_data_order_neon: -.LNEON: stmdb sp!,{r4-r12,lr} sub $H,sp,#16*4+16 + @ In Arm mode, the following ADR runs up against the limits of encodable + @ offsets. It only fits because the offset, when the ADR is placed here, + @ is a multiple of 16. adr $Ktbl,K256 bic $H,$H,#15 @ align for 128-bit stores mov $t2,sp @@ -613,12 +596,26 @@ () # define INST(a,b,c,d) .byte a,b,c,d # endif -.type sha256_block_data_order_armv8,%function +.LK256_shortcut: +@ PC is 8 bytes ahead in Arm mode and 4 bytes ahead in Thumb mode. +#if defined(__thumb2__) +.word K256-(.LK256_add+4) +#else +.word K256-(.LK256_add+8) +#endif + +.global sha256_block_data_order_hw +.type sha256_block_data_order_hw,%function .align 5 -sha256_block_data_order_armv8: -.LARMv8: +sha256_block_data_order_hw: + @ K256 is too far to reference from one ADR command in Thumb mode. In + @ Arm mode, we could make it fit by aligning the ADR offset to a 64-byte + @ boundary. For simplicity, just load the offset from .LK256_shortcut. + ldr $Ktbl,.LK256_shortcut +.LK256_add: + add $Ktbl,pc,$Ktbl + vld1.32 {$ABCD,$EFGH},[$ctx] - sub $Ktbl,$Ktbl,#256+32 add $len,$inp,$len,lsl#6 @ len to point at the end of inp b .Loop_v8 @@ -680,17 +677,13 @@ () vst1.32 {$ABCD,$EFGH},[$ctx] ret @ bx lr -.size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 +.size sha256_block_data_order_hw,.-sha256_block_data_order_hw #endif ___ }}} $code.=<<___; .asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " .align 2 -#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -.comm OPENSSL_armcap_P,4,4 -.hidden OPENSSL_armcap_P -#endif ___ open SELF,$0; diff --git a/crypto/fipsmodule/sha/asm/sha512-armv4.pl b/crypto/fipsmodule/sha/asm/sha512-armv4.pl index f52b5b0e8b..f2d1d22fa5 100644 --- a/crypto/fipsmodule/sha/asm/sha512-armv4.pl +++ b/crypto/fipsmodule/sha/asm/sha512-armv4.pl @@ -276,33 +276,13 @@ () WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a) WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817) .size K512,.-K512 -#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -.LOPENSSL_armcap: -.word OPENSSL_armcap_P-.Lsha512_block_data_order -.skip 32-4 -#else -.skip 32 -#endif -.global sha512_block_data_order -.type sha512_block_data_order,%function -sha512_block_data_order: -.Lsha512_block_data_order: - adr r3,.Lsha512_block_data_order -#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) - ldr r12,.LOPENSSL_armcap - ldr r12,[r3,r12] @ OPENSSL_armcap_P -#ifdef __APPLE__ - ldr r12,[r12] -#endif - tst r12,#ARMV7_NEON - bne .LNEON -#endif +.global sha512_block_data_order_nohw +.type sha512_block_data_order_nohw,%function +sha512_block_data_order_nohw: add $len,$inp,$len,lsl#7 @ len to point at the end of inp stmdb sp!,{r4-r12,lr} - @ TODO(davidben): When the OPENSSL_armcap logic above is removed, - @ replace this with a simple ADR. - sub $Ktbl,r3,#672 @ K512 + adr $Ktbl,K512 sub sp,sp,#9*8 ldr $Elo,[$ctx,#$Eoff+$lo] @@ -501,7 +481,7 @@ () moveq pc,lr @ be binary compatible with V4, yet bx lr @ interoperable with Thumb ISA:-) #endif -.size sha512_block_data_order,.-sha512_block_data_order +.size sha512_block_data_order_nohw,.-sha512_block_data_order_nohw ___ { @@ -612,7 +592,6 @@ () .type sha512_block_data_order_neon,%function .align 4 sha512_block_data_order_neon: -.LNEON: dmb @ errata #451034 on early Cortex A8 add $len,$inp,$len,lsl#7 @ len to point at the end of inp adr $Ktbl,K512 @@ -650,10 +629,6 @@ () $code.=<<___; .asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " .align 2 -#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -.comm OPENSSL_armcap_P,4,4 -.hidden OPENSSL_armcap_P -#endif ___ $code =~ s/\`([^\`]*)\`/eval $1/gem; diff --git a/crypto/fipsmodule/sha/internal.h b/crypto/fipsmodule/sha/internal.h index 28975e16ca..b55ea8e5e8 100644 --- a/crypto/fipsmodule/sha/internal.h +++ b/crypto/fipsmodule/sha/internal.h @@ -26,7 +26,7 @@ extern "C" { // Define SHA{n}[_{variant}]_ASM if sha{n}_block_data_order[_{variant}] is // defined in assembly. -#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_ARM)) +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) #define SHA1_ASM #define SHA256_ASM @@ -39,6 +39,35 @@ void sha256_block_data_order(uint32_t *state, const uint8_t *data, void sha512_block_data_order(uint64_t *state, const uint8_t *data, size_t num_blocks); +#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM) + +#define SHA1_ASM_NOHW +#define SHA256_ASM_NOHW +#define SHA512_ASM_NOHW + +#define SHA1_ASM_HW +OPENSSL_INLINE int sha1_hw_capable(void) { + return CRYPTO_is_ARMv8_SHA1_capable(); +} + +#define SHA1_ASM_NEON +void sha1_block_data_order_neon(uint32_t *state, const uint8_t *data, + size_t num); + +#define SHA256_ASM_HW +OPENSSL_INLINE int sha256_hw_capable(void) { + return CRYPTO_is_ARMv8_SHA256_capable(); +} + +#define SHA256_ASM_NEON +void sha256_block_data_order_neon(uint32_t *state, const uint8_t *data, + size_t num); + +// Armv8.2 SHA-512 instructions are not available in 32-bit. +#define SHA512_ASM_NEON +void sha512_block_data_order_neon(uint64_t *state, const uint8_t *data, + size_t num); + #elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64) #define SHA1_ASM_NOHW @@ -148,6 +177,7 @@ void sha256_block_data_order_nohw(uint32_t *state, const uint8_t *data, void sha512_block_data_order_hw(uint64_t *state, const uint8_t *data, size_t num); #endif + #if defined(SHA512_ASM_NOHW) void sha512_block_data_order_nohw(uint64_t *state, const uint8_t *data, size_t num); diff --git a/crypto/fipsmodule/sha/sha1.c b/crypto/fipsmodule/sha/sha1.c index 7b267e3df7..7a972660cb 100644 --- a/crypto/fipsmodule/sha/sha1.c +++ b/crypto/fipsmodule/sha/sha1.c @@ -409,6 +409,12 @@ static void sha1_block_data_order(uint32_t *state, const uint8_t *data, sha1_block_data_order_ssse3(state, data, num); return; } +#endif +#if defined(SHA1_ASM_NEON) + if (CRYPTO_is_NEON_capable()) { + sha1_block_data_order_neon(state, data, num); + return; + } #endif sha1_block_data_order_nohw(state, data, num); } diff --git a/crypto/fipsmodule/sha/sha256.c b/crypto/fipsmodule/sha/sha256.c index 0b0aca22fe..8cedc5f198 100644 --- a/crypto/fipsmodule/sha/sha256.c +++ b/crypto/fipsmodule/sha/sha256.c @@ -331,6 +331,12 @@ static void sha256_block_data_order(uint32_t *state, const uint8_t *data, sha256_block_data_order_ssse3(state, data, num); return; } +#endif +#if defined(SHA256_ASM_NEON) + if (CRYPTO_is_NEON_capable()) { + sha256_block_data_order_neon(state, data, num); + return; + } #endif sha256_block_data_order_nohw(state, data, num); } diff --git a/crypto/fipsmodule/sha/sha512.c b/crypto/fipsmodule/sha/sha512.c index 0f4142ca26..d31ab71979 100644 --- a/crypto/fipsmodule/sha/sha512.c +++ b/crypto/fipsmodule/sha/sha512.c @@ -515,6 +515,12 @@ static void sha512_block_data_order(uint64_t *state, const uint8_t *data, sha512_block_data_order_avx(state, data, num); return; } +#endif +#if defined(SHA512_ASM_NEON) + if (CRYPTO_is_NEON_capable()) { + sha512_block_data_order_neon(state, data, num); + return; + } #endif sha512_block_data_order_nohw(state, data, num); } diff --git a/crypto/fipsmodule/sha/sha_test.cc b/crypto/fipsmodule/sha/sha_test.cc index 22856f80fe..671c170f98 100644 --- a/crypto/fipsmodule/sha/sha_test.cc +++ b/crypto/fipsmodule/sha/sha_test.cc @@ -75,6 +75,11 @@ TEST(SHATest, SHA1ABI) { return; } #endif +#if defined(SHA1_ASM_NEON) + if (CRYPTO_is_NEON_capable()) { + CHECK_ABI(sha1_block_data_order_neon, ctx.h, kBuf, blocks); + } +#endif #if defined(SHA1_ASM_NOHW) CHECK_ABI(sha1_block_data_order_nohw, ctx.h, kBuf, blocks); #endif @@ -107,6 +112,11 @@ TEST(SHATest, SHA256ABI) { return; } #endif +#if defined(SHA256_ASM_NEON) + if (CRYPTO_is_NEON_capable()) { + CHECK_ABI(sha256_block_data_order_neon, ctx.h, kBuf, blocks); + } +#endif #if defined(SHA256_ASM_NOHW) CHECK_ABI(sha256_block_data_order_nohw, ctx.h, kBuf, blocks); #endif @@ -132,6 +142,11 @@ TEST(SHATest, SHA512ABI) { CHECK_ABI(sha512_block_data_order_avx, ctx.h, kBuf, blocks); } #endif +#if defined(SHA512_ASM_NEON) + if (CRYPTO_is_NEON_capable()) { + CHECK_ABI(sha512_block_data_order_neon, ctx.h, kBuf, blocks); + } +#endif #if defined(SHA512_ASM_NOHW) CHECK_ABI(sha512_block_data_order_nohw, ctx.h, kBuf, blocks); #endif From 23d58423169a2d473a6028228e46f68d1e65f503 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Wed, 13 Dec 2023 10:33:17 -0500 Subject: [PATCH 05/15] Fix X509_ATTRIBUTE_set1_data with negative attributes One of the WARNINGs in this function is unambiguously a bug. Just fix it. In doing so, add a helper for the ASN1_STRING -> ASN1_TYPE conversion and make this function easier to follow. Also document the attrtype == 0 case. I missed that one when enumerating this overcomplicated calling convention. Move that check earlier so we don't try to process the input. It's ignored anyway. Change-Id: Ia6e2dcb7c69488b6e2e58a68c3b701040ed3d4ef Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64827 Reviewed-by: Bob Beck Auto-Submit: David Benjamin Commit-Queue: David Benjamin --- crypto/asn1/a_strex.c | 19 ++------- crypto/asn1/a_type.c | 20 ++++++++- crypto/asn1/internal.h | 4 ++ crypto/x509/x509_att.c | 67 +++++++++++++++-------------- crypto/x509/x509_test.cc | 91 ++++++++++++++++++++++++++-------------- include/openssl/x509.h | 20 ++++----- 6 files changed, 131 insertions(+), 90 deletions(-) diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index 7e9afad0b5..516f7df54d 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -68,6 +68,7 @@ #include #include "../bytestring/internal.h" +#include "../internal.h" #include "internal.h" @@ -238,22 +239,8 @@ static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) { // Placing the ASN1_STRING in a temporary ASN1_TYPE allows the DER encoding // to readily obtained. ASN1_TYPE t; - t.type = str->type; - // Negative INTEGER and ENUMERATED values are the only case where - // |ASN1_STRING| and |ASN1_TYPE| types do not match. - // - // TODO(davidben): There are also some type fields which, in |ASN1_TYPE|, do - // not correspond to |ASN1_STRING|. It is unclear whether those are allowed - // in |ASN1_STRING| at all, or what the space of allowed types is. - // |ASN1_item_ex_d2i| will never produce such a value so, for now, we say - // this is an invalid input. But this corner of the library in general - // should be more robust. - if (t.type == V_ASN1_NEG_INTEGER) { - t.type = V_ASN1_INTEGER; - } else if (t.type == V_ASN1_NEG_ENUMERATED) { - t.type = V_ASN1_ENUMERATED; - } - t.value.asn1_string = (ASN1_STRING *)str; + OPENSSL_memset(&t, 0, sizeof(ASN1_TYPE)); + asn1_type_set0_string(&t, (ASN1_STRING *)str); unsigned char *der_buf = NULL; int der_len = i2d_ASN1_TYPE(&t, &der_buf); if (der_len < 0) { diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c index 0c2fd136d3..af603a3e8e 100644 --- a/crypto/asn1/a_type.c +++ b/crypto/asn1/a_type.c @@ -56,7 +56,8 @@ #include -#include +#include + #include #include #include @@ -89,6 +90,23 @@ const void *asn1_type_value_as_pointer(const ASN1_TYPE *a) { } } +void asn1_type_set0_string(ASN1_TYPE *a, ASN1_STRING *str) { + // |ASN1_STRING| types are almost the same as |ASN1_TYPE| types, except that + // the negative flag is not reflected into |ASN1_TYPE|. + int type = str->type; + if (type == V_ASN1_NEG_INTEGER) { + type = V_ASN1_INTEGER; + } else if (type == V_ASN1_NEG_ENUMERATED) { + type = V_ASN1_ENUMERATED; + } + + // These types are not |ASN1_STRING| types and use a different + // representation when stored in |ASN1_TYPE|. + assert(type != V_ASN1_NULL && type != V_ASN1_OBJECT && + type != V_ASN1_BOOLEAN); + ASN1_TYPE_set(a, type, str); +} + void asn1_type_cleanup(ASN1_TYPE *a) { switch (a->type) { case V_ASN1_NULL: diff --git a/crypto/asn1/internal.h b/crypto/asn1/internal.h index 414b5a97de..57e69668d3 100644 --- a/crypto/asn1/internal.h +++ b/crypto/asn1/internal.h @@ -210,6 +210,10 @@ void asn1_encoding_clear(ASN1_ENCODING *enc); // a pointer. const void *asn1_type_value_as_pointer(const ASN1_TYPE *a); +// asn1_type_set0_string sets |a|'s value to the object represented by |str| and +// takes ownership of |str|. +void asn1_type_set0_string(ASN1_TYPE *a, ASN1_STRING *str); + // asn1_type_cleanup releases memory associated with |a|'s value, without // freeing |a| itself. void asn1_type_cleanup(ASN1_TYPE *a); diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index 062168eaf7..e3d0c6a595 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c @@ -137,54 +137,57 @@ int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) { int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len) { - ASN1_TYPE *ttmp = NULL; - ASN1_STRING *stmp = NULL; - int atype = 0; if (!attr) { return 0; } + + if (attrtype == 0) { + // Do nothing. This is used to create an empty value set in + // |X509_ATTRIBUTE_create_by_*|. This is invalid, but supported by OpenSSL. + return 1; + } + + ASN1_TYPE *typ = ASN1_TYPE_new(); + if (typ == NULL) { + return 0; + } + + // This function is several functions in one. if (attrtype & MBSTRING_FLAG) { - stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, - OBJ_obj2nid(attr->object)); - if (!stmp) { + // |data| is an encoded string. We must decode and re-encode it to |attr|'s + // preferred ASN.1 type. Note |len| may be -1, in which case + // |ASN1_STRING_set_by_NID| calls |strlen| automatically. + ASN1_STRING *str = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, + OBJ_obj2nid(attr->object)); + if (str == NULL) { OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB); - return 0; - } - atype = stmp->type; - } else if (len != -1) { - if (!(stmp = ASN1_STRING_type_new(attrtype))) { goto err; } - if (!ASN1_STRING_set(stmp, data, len)) { + asn1_type_set0_string(typ, str); + } else if (len != -1) { + // |attrtype| must be a valid |ASN1_STRING| type. |data| and |len| is a + // value in the corresponding |ASN1_STRING| representation. + ASN1_STRING *str = ASN1_STRING_type_new(attrtype); + if (str == NULL || !ASN1_STRING_set(str, data, len)) { + ASN1_STRING_free(str); goto err; } - atype = attrtype; - } - // This is a bit naughty because the attribute should really have at - // least one value but some types use and zero length SET and require - // this. - if (attrtype == 0) { - ASN1_STRING_free(stmp); - return 1; - } - if (!(ttmp = ASN1_TYPE_new())) { - goto err; - } - if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { - if (!ASN1_TYPE_set1(ttmp, attrtype, data)) { + asn1_type_set0_string(typ, str); + } else { + // |attrtype| must be a valid |ASN1_TYPE| type. |data| is a pointer to an + // object of the corresponding type. + if (!ASN1_TYPE_set1(typ, attrtype, data)) { goto err; } - } else { - ASN1_TYPE_set(ttmp, atype, stmp); - stmp = NULL; } - if (!sk_ASN1_TYPE_push(attr->set, ttmp)) { + + if (!sk_ASN1_TYPE_push(attr->set, typ)) { goto err; } return 1; + err: - ASN1_TYPE_free(ttmp); - ASN1_STRING_free(stmp); + ASN1_TYPE_free(typ); return 0; } diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index f8c930fb54..a590e08769 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -3832,46 +3832,62 @@ TEST(X509Test, X509AlgorExtract) { // Test the various |X509_ATTRIBUTE| creation functions. TEST(X509Test, Attribute) { - // The friendlyName attribute has a BMPString value. See RFC 2985, - // section 5.5.1. + // The expected attribute values are: + // 1. BMPString U+2603 + // 2. BMPString "test" + // 3. INTEGER -1 (not valid for friendlyName) static const uint8_t kTest1[] = {0x26, 0x03}; // U+2603 SNOWMAN static const uint8_t kTest1UTF8[] = {0xe2, 0x98, 0x83}; static const uint8_t kTest2[] = {0, 't', 0, 'e', 0, 's', 0, 't'}; - auto check_attribute = [&](X509_ATTRIBUTE *attr, bool has_test2) { + constexpr uint32_t kTest1Mask = 1 << 0; + constexpr uint32_t kTest2Mask = 1 << 1; + constexpr uint32_t kTest3Mask = 1 << 2; + auto check_attribute = [&](X509_ATTRIBUTE *attr, uint32_t mask) { EXPECT_EQ(NID_friendlyName, OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr))); - EXPECT_EQ(has_test2 ? 2 : 1, X509_ATTRIBUTE_count(attr)); - - // The first attribute should contain |kTest1|. - const ASN1_TYPE *value = X509_ATTRIBUTE_get0_type(attr, 0); - ASSERT_TRUE(value); - EXPECT_EQ(V_ASN1_BMPSTRING, value->type); - EXPECT_EQ(Bytes(kTest1), - Bytes(ASN1_STRING_get0_data(value->value.bmpstring), - ASN1_STRING_length(value->value.bmpstring))); - - // |X509_ATTRIBUTE_get0_data| requires the type match. - EXPECT_FALSE( - X509_ATTRIBUTE_get0_data(attr, 0, V_ASN1_OCTET_STRING, nullptr)); - const ASN1_BMPSTRING *bmpstring = static_cast( - X509_ATTRIBUTE_get0_data(attr, 0, V_ASN1_BMPSTRING, nullptr)); - ASSERT_TRUE(bmpstring); - EXPECT_EQ(Bytes(kTest1), Bytes(ASN1_STRING_get0_data(bmpstring), - ASN1_STRING_length(bmpstring))); - - if (has_test2) { - value = X509_ATTRIBUTE_get0_type(attr, 1); + int idx = 0; + if (mask & kTest1Mask) { + // The first attribute should contain |kTest1|. + const ASN1_TYPE *value = X509_ATTRIBUTE_get0_type(attr, idx); + ASSERT_TRUE(value); + EXPECT_EQ(V_ASN1_BMPSTRING, value->type); + EXPECT_EQ(Bytes(kTest1), + Bytes(ASN1_STRING_get0_data(value->value.bmpstring), + ASN1_STRING_length(value->value.bmpstring))); + + // |X509_ATTRIBUTE_get0_data| requires the type match. + EXPECT_FALSE( + X509_ATTRIBUTE_get0_data(attr, idx, V_ASN1_OCTET_STRING, nullptr)); + const ASN1_BMPSTRING *bmpstring = static_cast( + X509_ATTRIBUTE_get0_data(attr, idx, V_ASN1_BMPSTRING, nullptr)); + ASSERT_TRUE(bmpstring); + EXPECT_EQ(Bytes(kTest1), Bytes(ASN1_STRING_get0_data(bmpstring), + ASN1_STRING_length(bmpstring))); + idx++; + } + + if (mask & kTest2Mask) { + const ASN1_TYPE *value = X509_ATTRIBUTE_get0_type(attr, idx); ASSERT_TRUE(value); EXPECT_EQ(V_ASN1_BMPSTRING, value->type); EXPECT_EQ(Bytes(kTest2), Bytes(ASN1_STRING_get0_data(value->value.bmpstring), ASN1_STRING_length(value->value.bmpstring))); - } else { - EXPECT_FALSE(X509_ATTRIBUTE_get0_type(attr, 1)); + idx++; } - EXPECT_FALSE(X509_ATTRIBUTE_get0_type(attr, 2)); + if (mask & kTest3Mask) { + const ASN1_TYPE *value = X509_ATTRIBUTE_get0_type(attr, idx); + ASSERT_TRUE(value); + EXPECT_EQ(V_ASN1_INTEGER, value->type); + int64_t v; + ASSERT_TRUE(ASN1_INTEGER_get_int64(&v, value->value.integer)); + EXPECT_EQ(v, -1); + idx++; + } + + EXPECT_FALSE(X509_ATTRIBUTE_get0_type(attr, idx)); }; bssl::UniquePtr str(ASN1_STRING_type_new(V_ASN1_BMPSTRING)); @@ -3883,7 +3899,7 @@ TEST(X509Test, Attribute) { X509_ATTRIBUTE_create(NID_friendlyName, V_ASN1_BMPSTRING, str.get())); ASSERT_TRUE(attr); str.release(); // |X509_ATTRIBUTE_create| takes ownership on success. - check_attribute(attr.get(), /*has_test2=*/false); + check_attribute(attr.get(), kTest1Mask); // Test the |MBSTRING_*| form of |X509_ATTRIBUTE_set1_data|. attr.reset(X509_ATTRIBUTE_new()); @@ -3892,12 +3908,19 @@ TEST(X509Test, Attribute) { X509_ATTRIBUTE_set1_object(attr.get(), OBJ_nid2obj(NID_friendlyName))); ASSERT_TRUE(X509_ATTRIBUTE_set1_data(attr.get(), MBSTRING_UTF8, kTest1UTF8, sizeof(kTest1UTF8))); - check_attribute(attr.get(), /*has_test2=*/false); + check_attribute(attr.get(), kTest1Mask); // Test the |ASN1_STRING| form of |X509_ATTRIBUTE_set1_data|. ASSERT_TRUE(X509_ATTRIBUTE_set1_data(attr.get(), V_ASN1_BMPSTRING, kTest2, sizeof(kTest2))); - check_attribute(attr.get(), /*has_test2=*/true); + check_attribute(attr.get(), kTest1Mask | kTest2Mask); + + // The |ASN1_STRING| form of |X509_ATTRIBUTE_set1_data| should correctly + // handle negative integers. + const uint8_t kOne = 1; + ASSERT_TRUE( + X509_ATTRIBUTE_set1_data(attr.get(), V_ASN1_NEG_INTEGER, &kOne, 1)); + check_attribute(attr.get(), kTest1Mask | kTest2Mask | kTest3Mask); // Test the |ASN1_TYPE| form of |X509_ATTRIBUTE_set1_data|. attr.reset(X509_ATTRIBUTE_new()); @@ -3909,7 +3932,13 @@ TEST(X509Test, Attribute) { ASSERT_TRUE(ASN1_STRING_set(str.get(), kTest1, sizeof(kTest1))); ASSERT_TRUE( X509_ATTRIBUTE_set1_data(attr.get(), V_ASN1_BMPSTRING, str.get(), -1)); - check_attribute(attr.get(), /*has_test2=*/false); + check_attribute(attr.get(), kTest1Mask); + + // An |attrtype| of zero leaves the attribute empty. + attr.reset(X509_ATTRIBUTE_create_by_NID( + nullptr, NID_friendlyName, /*attrtype=*/0, /*data=*/nullptr, /*len=*/0)); + ASSERT_TRUE(attr); + check_attribute(attr.get(), 0); } // Test that, by default, |X509_V_FLAG_TRUSTED_FIRST| is set, which means we'll diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 66668a635d..852a96f5e9 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -2101,21 +2101,21 @@ OPENSSL_EXPORT int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, // X509_ATTRIBUTE_set1_data appends a value to |attr|'s value set and returns // one on success or zero on error. The value is determined as follows: // -// If |attrtype| is a |MBSTRING_*| constant, the value is an ASN.1 string. The -// string is determined by decoding |len| bytes from |data| in the encoding -// specified by |attrtype|, and then re-encoding it in a form appropriate for -// |attr|'s type. If |len| is -1, |strlen(data)| is used instead. See -// |ASN1_STRING_set_by_NID| for details. +// If |attrtype| is zero, this function returns one and does nothing. This form +// may be used when calling |X509_ATTRIBUTE_create_by_*| to create an attribute +// with an empty value set. Such attributes are invalid, but OpenSSL supports +// creating them. +// +// Otherwise, if |attrtype| is a |MBSTRING_*| constant, the value is an ASN.1 +// string. The string is determined by decoding |len| bytes from |data| in the +// encoding specified by |attrtype|, and then re-encoding it in a form +// appropriate for |attr|'s type. If |len| is -1, |strlen(data)| is used +// instead. See |ASN1_STRING_set_by_NID| for details. // // Otherwise, if |len| is not -1, the value is an ASN.1 string. |attrtype| is an // |ASN1_STRING| type value and the |len| bytes from |data| are copied as the // type-specific representation of |ASN1_STRING|. See |ASN1_STRING| for details. // -// WARNING: If this form is used to construct a negative INTEGER or ENUMERATED, -// |attrtype| includes the |V_ASN1_NEG| flag for |ASN1_STRING|, but the function -// forgets to clear the flag for |ASN1_TYPE|. This matches OpenSSL but is -// probably a bug. For now, do not use this form with negative values. -// // Otherwise, if |len| is -1, the value is constructed by passing |attrtype| and // |data| to |ASN1_TYPE_set1|. That is, |attrtype| is an |ASN1_TYPE| type value, // and |data| is cast to the corresponding pointer type. From b251d813ec615e7ef01d82073f94960eb13b1e0a Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 11 Dec 2023 01:18:00 -0500 Subject: [PATCH 06/15] Change certificate depth limit to match OpenSSL and document OpenSSL 1.1.0 included d9b8b89bec4480de3a10bdaf9425db371c19145b, which a cleanup change to X509_verify_cert. This cleanup changed the semanitcs of the depth limit. Previously, the depth limit omitted the leaf but included the trust anchor. Now it omits both. We forked a little before 1.0.2, so we still had the old behavior. Now that the new behavior is well-established, switch to new one. Bump BORINGSSL_API_VERSION so callers can detect one or the other as needed. Document the new semantics. Also fix up some older docs where I implied -1 was unlimited depth. Negative numbers were actually enforced as negative numbers (which means only explicitly-trusted self-signed certs worked). Update-Note: The new semantics increase the limit by 1 compared to the old ones. Thus this change should only accept more chains than previously and be relatively safe. It also makes us more OpenSSL-compatible. Envoy will need a tweak because they unit test the boundary condition for the depth limit. Bug: 426 Fixed: 459 Change-Id: Ifaa108b8135ea3d875f2ac1f2a3b2cd8a22aa323 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64707 Reviewed-by: Bob Beck Commit-Queue: David Benjamin --- crypto/x509/internal.h | 5 ++-- crypto/x509/x509_test.cc | 61 +++++++++++++++++++++++++++++++--------- crypto/x509/x509_vfy.c | 30 +++++++++++--------- include/openssl/base.h | 2 +- include/openssl/ssl.h | 8 +++--- include/openssl/x509.h | 22 +++++++++++---- 6 files changed, 86 insertions(+), 42 deletions(-) diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h index b277eb0dba..cc40ee538c 100644 --- a/crypto/x509/internal.h +++ b/crypto/x509/internal.h @@ -379,9 +379,8 @@ struct x509_store_ctx_st { X509_STORE_CTX_check_crl_fn check_crl; // Check CRL validity // The following is built up - int valid; // if 0, rebuild chain - int last_untrusted; // index of last untrusted cert - STACK_OF(X509) *chain; // chain of X509s - built up and trusted + int last_untrusted; // index of last untrusted cert + STACK_OF(X509) *chain; // chain of X509s - built up and trusted // When something goes wrong, this is why int error_depth; diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index a590e08769..ab8ef7f655 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -12,6 +12,8 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #include #include #include @@ -1180,33 +1182,37 @@ TEST(X509Test, TestVerify) { // though in different ways. for (bool trusted_first : {true, false}) { SCOPED_TRACE(trusted_first); - std::function configure_callback; - if (!trusted_first) { + bool override_depth = false; + int depth = -1; + auto configure_callback = [&](X509_VERIFY_PARAM *param) { // Note we need the callback to clear the flag. Setting |flags| to zero // only skips setting new flags. - configure_callback = [&](X509_VERIFY_PARAM *param) { + if (!trusted_first) { X509_VERIFY_PARAM_clear_flags(param, X509_V_FLAG_TRUSTED_FIRST); - }; - } + } + if (override_depth) { + X509_VERIFY_PARAM_set_depth(param, depth); + } + }; // No trust anchors configured. - ASSERT_EQ(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + EXPECT_EQ(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, Verify(leaf.get(), /*roots=*/{}, /*intermediates=*/{}, /*crls=*/{}, /*flags=*/0, configure_callback)); - ASSERT_EQ( + EXPECT_EQ( X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, Verify(leaf.get(), /*roots=*/{}, {intermediate.get()}, /*crls=*/{}, /*flags=*/0, configure_callback)); // Each chain works individually. - ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()}, + EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()}, /*crls=*/{}, /*flags=*/0, configure_callback)); - ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {cross_signing_root.get()}, + EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {cross_signing_root.get()}, {intermediate.get(), root_cross_signed.get()}, /*crls=*/{}, /*flags=*/0, configure_callback)); // When both roots are available, we pick one or the other. - ASSERT_EQ(X509_V_OK, + EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {cross_signing_root.get(), root.get()}, {intermediate.get(), root_cross_signed.get()}, /*crls=*/{}, /*flags=*/0, configure_callback)); @@ -1215,7 +1221,7 @@ TEST(X509Test, TestVerify) { // the cross-sign in the intermediates. With |trusted_first|, we // preferentially stop path-building at |intermediate|. Without // |trusted_first|, the "altchains" logic repairs it. - ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, + EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get(), root_cross_signed.get()}, /*crls=*/{}, /*flags=*/0, configure_callback)); @@ -1226,7 +1232,7 @@ TEST(X509Test, TestVerify) { // This test exists to confirm our current behavior, but these modes are // just workarounds for not having an actual path-building verifier. If we // fix it, this test can be removed. - ASSERT_EQ(trusted_first ? X509_V_OK + EXPECT_EQ(trusted_first ? X509_V_OK : X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, Verify(leaf.get(), {root.get()}, {intermediate.get(), root_cross_signed.get()}, /*crls=*/{}, @@ -1234,18 +1240,45 @@ TEST(X509Test, TestVerify) { // |forgery| is signed by |leaf_no_key_usage|, but is rejected because the // leaf is not a CA. - ASSERT_EQ(X509_V_ERR_INVALID_CA, + EXPECT_EQ(X509_V_ERR_INVALID_CA, Verify(forgery.get(), {intermediate_self_signed.get()}, {leaf_no_key_usage.get()}, /*crls=*/{}, /*flags=*/0, configure_callback)); // Test that one cannot skip Basic Constraints checking with a contorted set // of roots and intermediates. This is a regression test for CVE-2015-1793. - ASSERT_EQ(X509_V_ERR_INVALID_CA, + EXPECT_EQ(X509_V_ERR_INVALID_CA, Verify(forgery.get(), {intermediate_self_signed.get(), root_cross_signed.get()}, {leaf_no_key_usage.get(), intermediate.get()}, /*crls=*/{}, /*flags=*/0, configure_callback)); + + // Test depth limits. |configure_callback| looks at |override_depth| and + // |depth|. Negative numbers have historically worked, so test those too. + for (int d : {-4, -3, -2, -1, 0, 1, 2, 3, 4, INT_MAX - 3, INT_MAX - 2, + INT_MAX - 1, INT_MAX}) { + SCOPED_TRACE(d); + override_depth = true; + depth = d; + // A chain with a leaf, two intermediates, and a root is depth two. + EXPECT_EQ( + depth >= 2 ? X509_V_OK : X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + Verify(leaf.get(), {cross_signing_root.get()}, + {intermediate.get(), root_cross_signed.get()}, + /*crls=*/{}, /*flags=*/0, configure_callback)); + + // A chain with a leaf, a root, and no intermediates is depth zero. + EXPECT_EQ( + depth >= 0 ? X509_V_OK : X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + Verify(root_cross_signed.get(), {cross_signing_root.get()}, {}, + /*crls=*/{}, /*flags=*/0, configure_callback)); + + // An explicitly trusted self-signed certificate is unaffected by depth + // checks. + EXPECT_EQ(X509_V_OK, + Verify(cross_signing_root.get(), {cross_signing_root.get()}, {}, + /*crls=*/{}, /*flags=*/0, configure_callback)); + } } } diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 090ed033a9..9b013883c6 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -55,6 +55,7 @@ * [including the GNU Public Licence.] */ #include +#include #include #include @@ -160,11 +161,11 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) { } int X509_verify_cert(X509_STORE_CTX *ctx) { - X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; + X509 *xtmp, *xtmp2, *chain_ss = NULL; int bad_chain = 0; X509_VERIFY_PARAM *param = ctx->param; - int depth, i, ok = 0; - int num, j, retry, trust; + int i, ok = 0; + int j, retry, trust; STACK_OF(X509) *sktmp = NULL; if (ctx->cert == NULL) { @@ -207,17 +208,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) { goto end; } - num = (int)sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, num - 1); - depth = param->depth; + int num = (int)sk_X509_num(ctx->chain); + X509 *x = sk_X509_value(ctx->chain, num - 1); + // |param->depth| does not include the leaf certificate or the trust anchor, + // so the maximum size is 2 more. + int max_chain = param->depth >= INT_MAX - 2 ? INT_MAX : param->depth + 2; for (;;) { - // If we have enough, we break - if (depth < num) { - break; // FIXME: If this happens, we should take - // note of it and, if appropriate, use the - // X509_V_ERR_CERT_CHAIN_TOO_LONG error code - // later. + if (num >= max_chain) { + // FIXME: If this happens, we should take note of it and, if appropriate, + // use the X509_V_ERR_CERT_CHAIN_TOO_LONG error code later. + break; } int is_self_signed; @@ -321,8 +322,9 @@ int X509_verify_cert(X509_STORE_CTX *ctx) { } // We now lookup certs from the certificate store for (;;) { - // If we have enough, we break - if (depth < num) { + if (num >= max_chain) { + // FIXME: If this happens, we should take note of it and, if + // appropriate, use the X509_V_ERR_CERT_CHAIN_TOO_LONG error code later. break; } if (!cert_self_signed(x, &is_self_signed)) { diff --git a/include/openssl/base.h b/include/openssl/base.h index f0981b8b78..9a47321bdd 100644 --- a/include/openssl/base.h +++ b/include/openssl/base.h @@ -109,7 +109,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 28 +#define BORINGSSL_API_VERSION 29 #if defined(BORINGSSL_SHARED_LIBRARY) diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index f1d4eb0662..ab6225e9e6 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2601,13 +2601,13 @@ OPENSSL_EXPORT int SSL_set1_host(SSL *ssl, const char *hostname); OPENSSL_EXPORT void SSL_set_hostflags(SSL *ssl, unsigned flags); // SSL_CTX_set_verify_depth sets the maximum depth of a certificate chain -// accepted in verification. This number does not include the leaf, so a depth -// of 1 allows the leaf and one CA certificate. +// accepted in verification. This count excludes both the target certificate and +// the trust anchor (root certificate). OPENSSL_EXPORT void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); // SSL_set_verify_depth sets the maximum depth of a certificate chain accepted -// in verification. This number does not include the leaf, so a depth of 1 -// allows the leaf and one CA certificate. +// in verification. This count excludes both the target certificate and the +// trust anchor (root certificate). OPENSSL_EXPORT void SSL_set_verify_depth(SSL *ssl, int depth); // SSL_CTX_get_verify_depth returns the maximum depth of a certificate accepted diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 852a96f5e9..b27c97d331 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -3522,8 +3522,14 @@ typedef int (*X509_STORE_CTX_get_crl_fn)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); typedef int (*X509_STORE_CTX_check_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl); +// X509_STORE_set_depth configures |store| to, by default, limit certificate +// chains to |depth| intermediate certificates. This count excludes both the +// target certificate and the trust anchor (root certificate). OPENSSL_EXPORT int X509_STORE_set_depth(X509_STORE *store, int depth); +// X509_STORE_CTX_set_depth configures |ctx| to, by default, limit certificate +// chains to |depth| intermediate certificates. This count excludes both the +// target certificate and the trust anchor (root certificate). OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); #define X509_STORE_CTX_set_app_data(ctx, data) \ @@ -3734,14 +3740,12 @@ OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *store, // // As of writing these late defaults are a depth limit (see // |X509_VERIFY_PARAM_set_depth|) and the |X509_V_FLAG_TRUSTED_FIRST| flag. This -// warning does not apply if the parameters were set in |store|. That is, -// callers may safely set a concrete depth limit in |store|, but unlimited depth -// must be configured at |X509_STORE_CTX|. +// warning does not apply if the parameters were set in |store|. // // TODO(crbug.com/boringssl/441): This behavior is very surprising. Can we -// remove this notion of late defaults? A depth limit of 100 can probably be -// applied unconditionally. |X509_V_FLAG_TRUSTED_FIRST| is mostly a workaround -// for poor path-building. +// remove this notion of late defaults? The unsettable value at |X509_STORE| is +// -1, which rejects everything but explicitly-trusted self-signed certificates. +// |X509_V_FLAG_TRUSTED_FIRST| is mostly a workaround for poor path-building. OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store); // X509_STORE_set_verify_cb acts like |X509_STORE_CTX_set_verify_cb| but sets @@ -3963,6 +3967,10 @@ OPENSSL_EXPORT int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose); OPENSSL_EXPORT int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust); + +// X509_VERIFY_PARAM_set_depth configures |param| to limit certificate chains to +// |depth| intermediate certificates. This count excludes both the target +// certificate and the trust anchor (root certificate). OPENSSL_EXPORT void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); @@ -4043,6 +4051,8 @@ OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc); +// X509_VERIFY_PARAM_get_depth returns the maximum depth configured in |param|. +// See |X509_VERIFY_PARAM_set_depth|. OPENSSL_EXPORT int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); typedef void *(*X509V3_EXT_NEW)(void); From 7460d7456433fbaf28ec679fc138fefd6b2120cd Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Thu, 14 Dec 2023 19:46:51 +0000 Subject: [PATCH 07/15] Support medium memory models. With `-mcmodel=medium`, Clang may emit loads of the GOT address. Delocate needs to handle that in order to avoid a relocation inside the module. Bug: b:316210772 Change-Id: I55eb2711860e43f68de131e28538aef9f5ce1889 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64791 Auto-Submit: Adam Langley Reviewed-by: David Benjamin Commit-Queue: David Benjamin --- util/fipstools/delocate/delocate.go | 16 + util/fipstools/delocate/delocate.peg | 3 +- util/fipstools/delocate/delocate.peg.go | 2768 +++++++++-------- .../delocate/testdata/x86_64-GOTRewrite/in.s | 3 + .../delocate/testdata/x86_64-GOTRewrite/out.s | 7 + 5 files changed, 1476 insertions(+), 1321 deletions(-) diff --git a/util/fipstools/delocate/delocate.go b/util/fipstools/delocate/delocate.go index 8e0e508a80..cd08bed07b 100644 --- a/util/fipstools/delocate/delocate.go +++ b/util/fipstools/delocate/delocate.go @@ -1163,6 +1163,22 @@ Args: args = append(args, argStr) + case ruleGOTAddress: + if instructionName != "leaq" { + return nil, fmt.Errorf("_GLOBAL_OFFSET_TABLE_ used outside of lea") + } + if i != 0 || len(argNodes) != 2 { + return nil, fmt.Errorf("Load of _GLOBAL_OFFSET_TABLE_ address didn't have expected form") + } + d.gotDeltaNeeded = true + changed = true + targetReg := d.contents(argNodes[1]) + args = append(args, ".Lboringssl_got_delta(%rip)") + wrappers = append(wrappers, func(k func()) { + k() + d.output.WriteString(fmt.Sprintf("\taddq .Lboringssl_got_delta(%%rip), %s\n", targetReg)) + }) + case ruleGOTLocation: if instructionName != "movabsq" { return nil, fmt.Errorf("_GLOBAL_OFFSET_TABLE_ lookup didn't use movabsq") diff --git a/util/fipstools/delocate/delocate.peg b/util/fipstools/delocate/delocate.peg index d5537e2da0..2247f24f89 100644 --- a/util/fipstools/delocate/delocate.peg +++ b/util/fipstools/delocate/delocate.peg @@ -68,8 +68,9 @@ LocalLabel <- [0-9][0-9$]* LocalLabelRef <- [0-9][0-9$]*[bf] Instruction <- InstructionName (WS InstructionArg ((WS? ',' WS?) InstructionArg)*)? InstructionName <- [[A-Z]][[A-Z.0-9]]* [.+\-]? -InstructionArg <- IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTSymbolOffset / MemoryRef) AVX512Token* +InstructionArg <- IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTAddress / GOTSymbolOffset / MemoryRef) AVX512Token* GOTLocation <- '$_GLOBAL_OFFSET_TABLE_-' LocalSymbol +GOTAddress <- '_GLOBAL_OFFSET_TABLE_(%rip)' GOTSymbolOffset <- ('$' SymbolName '@GOT' 'OFF'?) / (":got:" SymbolName) AVX512Token <- WS? '{' '%'? [0-9a-z]* '}' TOCRefHigh <- '.TOC.-' ('0b' / ('.L' [a-zA-Z_0-9]+)) "@ha" diff --git a/util/fipstools/delocate/delocate.peg.go b/util/fipstools/delocate/delocate.peg.go index 7659cbc586..fa214191f8 100644 --- a/util/fipstools/delocate/delocate.peg.go +++ b/util/fipstools/delocate/delocate.peg.go @@ -54,6 +54,7 @@ const ( ruleInstructionName ruleInstructionArg ruleGOTLocation + ruleGOTAddress ruleGOTSymbolOffset ruleAVX512Token ruleTOCRefHigh @@ -114,6 +115,7 @@ var rul3s = [...]string{ "InstructionName", "InstructionArg", "GOTLocation", + "GOTAddress", "GOTSymbolOffset", "AVX512Token", "TOCRefHigh", @@ -248,7 +250,7 @@ func (t *tokens32) Tokens() []token32 { type Asm struct { Buffer string buffer []rune - rules [57]func() bool + rules [58]func() bool parse func(rule ...int) error reset func() Pretty bool @@ -3671,7 +3673,7 @@ func (p *Asm) Init(options ...func(*Asm) error) error { position, tokenIndex = position438, tokenIndex438 return false }, - /* 34 InstructionArg <- <(IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTSymbolOffset / MemoryRef) AVX512Token*)> */ + /* 34 InstructionArg <- <(IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTAddress / GOTSymbolOffset / MemoryRef) AVX512Token*)> */ func() bool { position455, tokenIndex455 := position, tokenIndex { @@ -3724,26 +3726,32 @@ func (p *Asm) Init(options ...func(*Asm) error) error { goto l459 l465: position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleGOTSymbolOffset]() { + if !_rules[ruleGOTAddress]() { goto l466 } goto l459 l466: + position, tokenIndex = position459, tokenIndex459 + if !_rules[ruleGOTSymbolOffset]() { + goto l467 + } + goto l459 + l467: position, tokenIndex = position459, tokenIndex459 if !_rules[ruleMemoryRef]() { goto l455 } } l459: - l467: + l468: { - position468, tokenIndex468 := position, tokenIndex + position469, tokenIndex469 := position, tokenIndex if !_rules[ruleAVX512Token]() { - goto l468 + goto l469 } - goto l467 - l468: - position, tokenIndex = position468, tokenIndex468 + goto l468 + l469: + position, tokenIndex = position469, tokenIndex469 } add(ruleInstructionArg, position456) } @@ -3754,1024 +3762,1126 @@ func (p *Asm) Init(options ...func(*Asm) error) error { }, /* 35 GOTLocation <- <('$' '_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '-' LocalSymbol)> */ func() bool { - position469, tokenIndex469 := position, tokenIndex + position470, tokenIndex470 := position, tokenIndex { - position470 := position + position471 := position if buffer[position] != rune('$') { - goto l469 + goto l470 } position++ if buffer[position] != rune('_') { - goto l469 + goto l470 } position++ if buffer[position] != rune('G') { - goto l469 + goto l470 } position++ if buffer[position] != rune('L') { - goto l469 + goto l470 } position++ if buffer[position] != rune('O') { - goto l469 + goto l470 } position++ if buffer[position] != rune('B') { - goto l469 + goto l470 } position++ if buffer[position] != rune('A') { - goto l469 + goto l470 } position++ if buffer[position] != rune('L') { - goto l469 + goto l470 } position++ if buffer[position] != rune('_') { - goto l469 + goto l470 } position++ if buffer[position] != rune('O') { - goto l469 + goto l470 } position++ if buffer[position] != rune('F') { - goto l469 + goto l470 } position++ if buffer[position] != rune('F') { - goto l469 + goto l470 } position++ if buffer[position] != rune('S') { - goto l469 + goto l470 } position++ if buffer[position] != rune('E') { - goto l469 + goto l470 } position++ if buffer[position] != rune('T') { - goto l469 + goto l470 } position++ if buffer[position] != rune('_') { - goto l469 + goto l470 } position++ if buffer[position] != rune('T') { - goto l469 + goto l470 } position++ if buffer[position] != rune('A') { - goto l469 + goto l470 } position++ if buffer[position] != rune('B') { - goto l469 + goto l470 } position++ if buffer[position] != rune('L') { - goto l469 + goto l470 } position++ if buffer[position] != rune('E') { - goto l469 + goto l470 } position++ if buffer[position] != rune('_') { - goto l469 + goto l470 } position++ if buffer[position] != rune('-') { - goto l469 + goto l470 } position++ if !_rules[ruleLocalSymbol]() { - goto l469 + goto l470 + } + add(ruleGOTLocation, position471) + } + return true + l470: + position, tokenIndex = position470, tokenIndex470 + return false + }, + /* 36 GOTAddress <- <('_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '(' '%' 'r' 'i' 'p' ')')> */ + func() bool { + position472, tokenIndex472 := position, tokenIndex + { + position473 := position + if buffer[position] != rune('_') { + goto l472 + } + position++ + if buffer[position] != rune('G') { + goto l472 + } + position++ + if buffer[position] != rune('L') { + goto l472 + } + position++ + if buffer[position] != rune('O') { + goto l472 + } + position++ + if buffer[position] != rune('B') { + goto l472 + } + position++ + if buffer[position] != rune('A') { + goto l472 + } + position++ + if buffer[position] != rune('L') { + goto l472 + } + position++ + if buffer[position] != rune('_') { + goto l472 + } + position++ + if buffer[position] != rune('O') { + goto l472 + } + position++ + if buffer[position] != rune('F') { + goto l472 + } + position++ + if buffer[position] != rune('F') { + goto l472 + } + position++ + if buffer[position] != rune('S') { + goto l472 + } + position++ + if buffer[position] != rune('E') { + goto l472 + } + position++ + if buffer[position] != rune('T') { + goto l472 + } + position++ + if buffer[position] != rune('_') { + goto l472 + } + position++ + if buffer[position] != rune('T') { + goto l472 + } + position++ + if buffer[position] != rune('A') { + goto l472 + } + position++ + if buffer[position] != rune('B') { + goto l472 + } + position++ + if buffer[position] != rune('L') { + goto l472 } - add(ruleGOTLocation, position470) + position++ + if buffer[position] != rune('E') { + goto l472 + } + position++ + if buffer[position] != rune('_') { + goto l472 + } + position++ + if buffer[position] != rune('(') { + goto l472 + } + position++ + if buffer[position] != rune('%') { + goto l472 + } + position++ + if buffer[position] != rune('r') { + goto l472 + } + position++ + if buffer[position] != rune('i') { + goto l472 + } + position++ + if buffer[position] != rune('p') { + goto l472 + } + position++ + if buffer[position] != rune(')') { + goto l472 + } + position++ + add(ruleGOTAddress, position473) } return true - l469: - position, tokenIndex = position469, tokenIndex469 + l472: + position, tokenIndex = position472, tokenIndex472 return false }, - /* 36 GOTSymbolOffset <- <(('$' SymbolName ('@' 'G' 'O' 'T') ('O' 'F' 'F')?) / (':' ('g' / 'G') ('o' / 'O') ('t' / 'T') ':' SymbolName))> */ + /* 37 GOTSymbolOffset <- <(('$' SymbolName ('@' 'G' 'O' 'T') ('O' 'F' 'F')?) / (':' ('g' / 'G') ('o' / 'O') ('t' / 'T') ':' SymbolName))> */ func() bool { - position471, tokenIndex471 := position, tokenIndex + position474, tokenIndex474 := position, tokenIndex { - position472 := position + position475 := position { - position473, tokenIndex473 := position, tokenIndex + position476, tokenIndex476 := position, tokenIndex if buffer[position] != rune('$') { - goto l474 + goto l477 } position++ if !_rules[ruleSymbolName]() { - goto l474 + goto l477 } if buffer[position] != rune('@') { - goto l474 + goto l477 } position++ if buffer[position] != rune('G') { - goto l474 + goto l477 } position++ if buffer[position] != rune('O') { - goto l474 + goto l477 } position++ if buffer[position] != rune('T') { - goto l474 + goto l477 } position++ { - position475, tokenIndex475 := position, tokenIndex + position478, tokenIndex478 := position, tokenIndex if buffer[position] != rune('O') { - goto l475 + goto l478 } position++ if buffer[position] != rune('F') { - goto l475 + goto l478 } position++ if buffer[position] != rune('F') { - goto l475 + goto l478 } position++ - goto l476 - l475: - position, tokenIndex = position475, tokenIndex475 + goto l479 + l478: + position, tokenIndex = position478, tokenIndex478 } - l476: - goto l473 - l474: - position, tokenIndex = position473, tokenIndex473 + l479: + goto l476 + l477: + position, tokenIndex = position476, tokenIndex476 if buffer[position] != rune(':') { - goto l471 + goto l474 } position++ { - position477, tokenIndex477 := position, tokenIndex + position480, tokenIndex480 := position, tokenIndex if buffer[position] != rune('g') { - goto l478 + goto l481 } position++ - goto l477 - l478: - position, tokenIndex = position477, tokenIndex477 + goto l480 + l481: + position, tokenIndex = position480, tokenIndex480 if buffer[position] != rune('G') { - goto l471 + goto l474 } position++ } - l477: + l480: { - position479, tokenIndex479 := position, tokenIndex + position482, tokenIndex482 := position, tokenIndex if buffer[position] != rune('o') { - goto l480 + goto l483 } position++ - goto l479 - l480: - position, tokenIndex = position479, tokenIndex479 + goto l482 + l483: + position, tokenIndex = position482, tokenIndex482 if buffer[position] != rune('O') { - goto l471 + goto l474 } position++ } - l479: + l482: { - position481, tokenIndex481 := position, tokenIndex + position484, tokenIndex484 := position, tokenIndex if buffer[position] != rune('t') { - goto l482 + goto l485 } position++ - goto l481 - l482: - position, tokenIndex = position481, tokenIndex481 + goto l484 + l485: + position, tokenIndex = position484, tokenIndex484 if buffer[position] != rune('T') { - goto l471 + goto l474 } position++ } - l481: + l484: if buffer[position] != rune(':') { - goto l471 + goto l474 } position++ if !_rules[ruleSymbolName]() { - goto l471 + goto l474 } } - l473: - add(ruleGOTSymbolOffset, position472) + l476: + add(ruleGOTSymbolOffset, position475) } return true - l471: - position, tokenIndex = position471, tokenIndex471 + l474: + position, tokenIndex = position474, tokenIndex474 return false }, - /* 37 AVX512Token <- <(WS? '{' '%'? ([0-9] / [a-z])* '}')> */ + /* 38 AVX512Token <- <(WS? '{' '%'? ([0-9] / [a-z])* '}')> */ func() bool { - position483, tokenIndex483 := position, tokenIndex + position486, tokenIndex486 := position, tokenIndex { - position484 := position + position487 := position { - position485, tokenIndex485 := position, tokenIndex + position488, tokenIndex488 := position, tokenIndex if !_rules[ruleWS]() { - goto l485 + goto l488 } - goto l486 - l485: - position, tokenIndex = position485, tokenIndex485 + goto l489 + l488: + position, tokenIndex = position488, tokenIndex488 } - l486: + l489: if buffer[position] != rune('{') { - goto l483 + goto l486 } position++ { - position487, tokenIndex487 := position, tokenIndex + position490, tokenIndex490 := position, tokenIndex if buffer[position] != rune('%') { - goto l487 + goto l490 } position++ - goto l488 - l487: - position, tokenIndex = position487, tokenIndex487 + goto l491 + l490: + position, tokenIndex = position490, tokenIndex490 } - l488: - l489: + l491: + l492: { - position490, tokenIndex490 := position, tokenIndex + position493, tokenIndex493 := position, tokenIndex { - position491, tokenIndex491 := position, tokenIndex + position494, tokenIndex494 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l492 + goto l495 } position++ - goto l491 - l492: - position, tokenIndex = position491, tokenIndex491 + goto l494 + l495: + position, tokenIndex = position494, tokenIndex494 if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l490 + goto l493 } position++ } - l491: - goto l489 - l490: - position, tokenIndex = position490, tokenIndex490 + l494: + goto l492 + l493: + position, tokenIndex = position493, tokenIndex493 } if buffer[position] != rune('}') { - goto l483 + goto l486 } position++ - add(ruleAVX512Token, position484) + add(ruleAVX512Token, position487) } return true - l483: - position, tokenIndex = position483, tokenIndex483 + l486: + position, tokenIndex = position486, tokenIndex486 return false }, - /* 38 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */ + /* 39 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */ func() bool { - position493, tokenIndex493 := position, tokenIndex + position496, tokenIndex496 := position, tokenIndex { - position494 := position + position497 := position if buffer[position] != rune('.') { - goto l493 + goto l496 } position++ if buffer[position] != rune('T') { - goto l493 + goto l496 } position++ if buffer[position] != rune('O') { - goto l493 + goto l496 } position++ if buffer[position] != rune('C') { - goto l493 + goto l496 } position++ if buffer[position] != rune('.') { - goto l493 + goto l496 } position++ if buffer[position] != rune('-') { - goto l493 + goto l496 } position++ { - position495, tokenIndex495 := position, tokenIndex + position498, tokenIndex498 := position, tokenIndex if buffer[position] != rune('0') { - goto l496 + goto l499 } position++ if buffer[position] != rune('b') { - goto l496 + goto l499 } position++ - goto l495 - l496: - position, tokenIndex = position495, tokenIndex495 + goto l498 + l499: + position, tokenIndex = position498, tokenIndex498 if buffer[position] != rune('.') { - goto l493 + goto l496 } position++ if buffer[position] != rune('L') { - goto l493 + goto l496 } position++ { - position499, tokenIndex499 := position, tokenIndex + position502, tokenIndex502 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l500 + goto l503 } position++ - goto l499 - l500: - position, tokenIndex = position499, tokenIndex499 + goto l502 + l503: + position, tokenIndex = position502, tokenIndex502 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l501 + goto l504 } position++ - goto l499 - l501: - position, tokenIndex = position499, tokenIndex499 + goto l502 + l504: + position, tokenIndex = position502, tokenIndex502 if buffer[position] != rune('_') { - goto l502 + goto l505 } position++ - goto l499 - l502: - position, tokenIndex = position499, tokenIndex499 + goto l502 + l505: + position, tokenIndex = position502, tokenIndex502 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l493 + goto l496 } position++ } - l499: - l497: + l502: + l500: { - position498, tokenIndex498 := position, tokenIndex + position501, tokenIndex501 := position, tokenIndex { - position503, tokenIndex503 := position, tokenIndex + position506, tokenIndex506 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l504 + goto l507 } position++ - goto l503 - l504: - position, tokenIndex = position503, tokenIndex503 + goto l506 + l507: + position, tokenIndex = position506, tokenIndex506 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l505 + goto l508 } position++ - goto l503 - l505: - position, tokenIndex = position503, tokenIndex503 + goto l506 + l508: + position, tokenIndex = position506, tokenIndex506 if buffer[position] != rune('_') { - goto l506 + goto l509 } position++ - goto l503 - l506: - position, tokenIndex = position503, tokenIndex503 + goto l506 + l509: + position, tokenIndex = position506, tokenIndex506 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l498 + goto l501 } position++ } - l503: - goto l497 - l498: - position, tokenIndex = position498, tokenIndex498 + l506: + goto l500 + l501: + position, tokenIndex = position501, tokenIndex501 } } - l495: + l498: if buffer[position] != rune('@') { - goto l493 + goto l496 } position++ { - position507, tokenIndex507 := position, tokenIndex + position510, tokenIndex510 := position, tokenIndex if buffer[position] != rune('h') { - goto l508 + goto l511 } position++ - goto l507 - l508: - position, tokenIndex = position507, tokenIndex507 + goto l510 + l511: + position, tokenIndex = position510, tokenIndex510 if buffer[position] != rune('H') { - goto l493 + goto l496 } position++ } - l507: + l510: { - position509, tokenIndex509 := position, tokenIndex + position512, tokenIndex512 := position, tokenIndex if buffer[position] != rune('a') { - goto l510 + goto l513 } position++ - goto l509 - l510: - position, tokenIndex = position509, tokenIndex509 + goto l512 + l513: + position, tokenIndex = position512, tokenIndex512 if buffer[position] != rune('A') { - goto l493 + goto l496 } position++ } - l509: - add(ruleTOCRefHigh, position494) + l512: + add(ruleTOCRefHigh, position497) } return true - l493: - position, tokenIndex = position493, tokenIndex493 + l496: + position, tokenIndex = position496, tokenIndex496 return false }, - /* 39 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */ + /* 40 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */ func() bool { - position511, tokenIndex511 := position, tokenIndex + position514, tokenIndex514 := position, tokenIndex { - position512 := position + position515 := position if buffer[position] != rune('.') { - goto l511 + goto l514 } position++ if buffer[position] != rune('T') { - goto l511 + goto l514 } position++ if buffer[position] != rune('O') { - goto l511 + goto l514 } position++ if buffer[position] != rune('C') { - goto l511 + goto l514 } position++ if buffer[position] != rune('.') { - goto l511 + goto l514 } position++ if buffer[position] != rune('-') { - goto l511 + goto l514 } position++ { - position513, tokenIndex513 := position, tokenIndex + position516, tokenIndex516 := position, tokenIndex if buffer[position] != rune('0') { - goto l514 + goto l517 } position++ if buffer[position] != rune('b') { - goto l514 + goto l517 } position++ - goto l513 - l514: - position, tokenIndex = position513, tokenIndex513 + goto l516 + l517: + position, tokenIndex = position516, tokenIndex516 if buffer[position] != rune('.') { - goto l511 + goto l514 } position++ if buffer[position] != rune('L') { - goto l511 + goto l514 } position++ { - position517, tokenIndex517 := position, tokenIndex + position520, tokenIndex520 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l518 + goto l521 } position++ - goto l517 - l518: - position, tokenIndex = position517, tokenIndex517 + goto l520 + l521: + position, tokenIndex = position520, tokenIndex520 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l519 + goto l522 } position++ - goto l517 - l519: - position, tokenIndex = position517, tokenIndex517 + goto l520 + l522: + position, tokenIndex = position520, tokenIndex520 if buffer[position] != rune('_') { - goto l520 + goto l523 } position++ - goto l517 - l520: - position, tokenIndex = position517, tokenIndex517 + goto l520 + l523: + position, tokenIndex = position520, tokenIndex520 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l511 + goto l514 } position++ } - l517: - l515: + l520: + l518: { - position516, tokenIndex516 := position, tokenIndex + position519, tokenIndex519 := position, tokenIndex { - position521, tokenIndex521 := position, tokenIndex + position524, tokenIndex524 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l522 + goto l525 } position++ - goto l521 - l522: - position, tokenIndex = position521, tokenIndex521 + goto l524 + l525: + position, tokenIndex = position524, tokenIndex524 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l523 + goto l526 } position++ - goto l521 - l523: - position, tokenIndex = position521, tokenIndex521 + goto l524 + l526: + position, tokenIndex = position524, tokenIndex524 if buffer[position] != rune('_') { - goto l524 + goto l527 } position++ - goto l521 - l524: - position, tokenIndex = position521, tokenIndex521 + goto l524 + l527: + position, tokenIndex = position524, tokenIndex524 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l516 + goto l519 } position++ } - l521: - goto l515 - l516: - position, tokenIndex = position516, tokenIndex516 + l524: + goto l518 + l519: + position, tokenIndex = position519, tokenIndex519 } } - l513: + l516: if buffer[position] != rune('@') { - goto l511 + goto l514 } position++ { - position525, tokenIndex525 := position, tokenIndex + position528, tokenIndex528 := position, tokenIndex if buffer[position] != rune('l') { - goto l526 + goto l529 } position++ - goto l525 - l526: - position, tokenIndex = position525, tokenIndex525 + goto l528 + l529: + position, tokenIndex = position528, tokenIndex528 if buffer[position] != rune('L') { - goto l511 + goto l514 } position++ } - l525: - add(ruleTOCRefLow, position512) + l528: + add(ruleTOCRefLow, position515) } return true - l511: - position, tokenIndex = position511, tokenIndex511 + l514: + position, tokenIndex = position514, tokenIndex514 return false }, - /* 40 IndirectionIndicator <- <'*'> */ + /* 41 IndirectionIndicator <- <'*'> */ func() bool { - position527, tokenIndex527 := position, tokenIndex + position530, tokenIndex530 := position, tokenIndex { - position528 := position + position531 := position if buffer[position] != rune('*') { - goto l527 + goto l530 } position++ - add(ruleIndirectionIndicator, position528) + add(ruleIndirectionIndicator, position531) } return true - l527: - position, tokenIndex = position527, tokenIndex527 + l530: + position, tokenIndex = position530, tokenIndex530 return false }, - /* 41 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset)) / ('#' Offset ('*' [0-9]+ ('-' [0-9] [0-9]*)?)?) / ('#' '~'? '(' [0-9] WS? ('<' '<') WS? [0-9] ')') / ARMRegister) !('f' / 'b' / ':' / '(' / '+' / '-'))> */ + /* 42 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset)) / ('#' Offset ('*' [0-9]+ ('-' [0-9] [0-9]*)?)?) / ('#' '~'? '(' [0-9] WS? ('<' '<') WS? [0-9] ')') / ARMRegister) !('f' / 'b' / ':' / '(' / '+' / '-'))> */ func() bool { - position529, tokenIndex529 := position, tokenIndex + position532, tokenIndex532 := position, tokenIndex { - position530 := position + position533 := position { - position531, tokenIndex531 := position, tokenIndex + position534, tokenIndex534 := position, tokenIndex if buffer[position] != rune('%') { - goto l532 + goto l535 } position++ { - position533, tokenIndex533 := position, tokenIndex + position536, tokenIndex536 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l534 + goto l537 } position++ - goto l533 - l534: - position, tokenIndex = position533, tokenIndex533 + goto l536 + l537: + position, tokenIndex = position536, tokenIndex536 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l532 + goto l535 } position++ } - l533: - l535: + l536: + l538: { - position536, tokenIndex536 := position, tokenIndex + position539, tokenIndex539 := position, tokenIndex { - position537, tokenIndex537 := position, tokenIndex + position540, tokenIndex540 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l538 + goto l541 } position++ - goto l537 - l538: - position, tokenIndex = position537, tokenIndex537 + goto l540 + l541: + position, tokenIndex = position540, tokenIndex540 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l539 + goto l542 } position++ - goto l537 - l539: - position, tokenIndex = position537, tokenIndex537 + goto l540 + l542: + position, tokenIndex = position540, tokenIndex540 { - position540, tokenIndex540 := position, tokenIndex + position543, tokenIndex543 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l541 + goto l544 } position++ - goto l540 - l541: - position, tokenIndex = position540, tokenIndex540 + goto l543 + l544: + position, tokenIndex = position543, tokenIndex543 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l536 + goto l539 } position++ } - l540: + l543: } - l537: - goto l535 - l536: - position, tokenIndex = position536, tokenIndex536 + l540: + goto l538 + l539: + position, tokenIndex = position539, tokenIndex539 } - goto l531 - l532: - position, tokenIndex = position531, tokenIndex531 + goto l534 + l535: + position, tokenIndex = position534, tokenIndex534 { - position543, tokenIndex543 := position, tokenIndex + position546, tokenIndex546 := position, tokenIndex if buffer[position] != rune('$') { - goto l543 + goto l546 } position++ - goto l544 - l543: - position, tokenIndex = position543, tokenIndex543 + goto l547 + l546: + position, tokenIndex = position546, tokenIndex546 } - l544: + l547: { - position545, tokenIndex545 := position, tokenIndex + position548, tokenIndex548 := position, tokenIndex if !_rules[ruleOffset]() { - goto l546 + goto l549 } if !_rules[ruleOffset]() { - goto l546 + goto l549 } - goto l545 - l546: - position, tokenIndex = position545, tokenIndex545 + goto l548 + l549: + position, tokenIndex = position548, tokenIndex548 if !_rules[ruleOffset]() { - goto l542 + goto l545 } } + l548: + goto l534 l545: - goto l531 - l542: - position, tokenIndex = position531, tokenIndex531 + position, tokenIndex = position534, tokenIndex534 if buffer[position] != rune('#') { - goto l547 + goto l550 } position++ if !_rules[ruleOffset]() { - goto l547 + goto l550 } { - position548, tokenIndex548 := position, tokenIndex + position551, tokenIndex551 := position, tokenIndex if buffer[position] != rune('*') { - goto l548 + goto l551 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l548 + goto l551 } position++ - l550: + l553: { - position551, tokenIndex551 := position, tokenIndex + position554, tokenIndex554 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l551 + goto l554 } position++ - goto l550 - l551: - position, tokenIndex = position551, tokenIndex551 + goto l553 + l554: + position, tokenIndex = position554, tokenIndex554 } { - position552, tokenIndex552 := position, tokenIndex + position555, tokenIndex555 := position, tokenIndex if buffer[position] != rune('-') { - goto l552 + goto l555 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l552 + goto l555 } position++ - l554: + l557: { - position555, tokenIndex555 := position, tokenIndex + position558, tokenIndex558 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l555 + goto l558 } position++ - goto l554 - l555: - position, tokenIndex = position555, tokenIndex555 + goto l557 + l558: + position, tokenIndex = position558, tokenIndex558 } - goto l553 - l552: - position, tokenIndex = position552, tokenIndex552 - } - l553: - goto l549 - l548: - position, tokenIndex = position548, tokenIndex548 - } - l549: - goto l531 - l547: - position, tokenIndex = position531, tokenIndex531 + goto l556 + l555: + position, tokenIndex = position555, tokenIndex555 + } + l556: + goto l552 + l551: + position, tokenIndex = position551, tokenIndex551 + } + l552: + goto l534 + l550: + position, tokenIndex = position534, tokenIndex534 if buffer[position] != rune('#') { - goto l556 + goto l559 } position++ { - position557, tokenIndex557 := position, tokenIndex + position560, tokenIndex560 := position, tokenIndex if buffer[position] != rune('~') { - goto l557 + goto l560 } position++ - goto l558 - l557: - position, tokenIndex = position557, tokenIndex557 + goto l561 + l560: + position, tokenIndex = position560, tokenIndex560 } - l558: + l561: if buffer[position] != rune('(') { - goto l556 + goto l559 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l556 + goto l559 } position++ { - position559, tokenIndex559 := position, tokenIndex + position562, tokenIndex562 := position, tokenIndex if !_rules[ruleWS]() { - goto l559 + goto l562 } - goto l560 - l559: - position, tokenIndex = position559, tokenIndex559 + goto l563 + l562: + position, tokenIndex = position562, tokenIndex562 } - l560: + l563: if buffer[position] != rune('<') { - goto l556 + goto l559 } position++ if buffer[position] != rune('<') { - goto l556 + goto l559 } position++ { - position561, tokenIndex561 := position, tokenIndex + position564, tokenIndex564 := position, tokenIndex if !_rules[ruleWS]() { - goto l561 + goto l564 } - goto l562 - l561: - position, tokenIndex = position561, tokenIndex561 + goto l565 + l564: + position, tokenIndex = position564, tokenIndex564 } - l562: + l565: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l556 + goto l559 } position++ if buffer[position] != rune(')') { - goto l556 + goto l559 } position++ - goto l531 - l556: - position, tokenIndex = position531, tokenIndex531 + goto l534 + l559: + position, tokenIndex = position534, tokenIndex534 if !_rules[ruleARMRegister]() { - goto l529 + goto l532 } } - l531: + l534: { - position563, tokenIndex563 := position, tokenIndex + position566, tokenIndex566 := position, tokenIndex { - position564, tokenIndex564 := position, tokenIndex + position567, tokenIndex567 := position, tokenIndex if buffer[position] != rune('f') { - goto l565 + goto l568 } position++ - goto l564 - l565: - position, tokenIndex = position564, tokenIndex564 + goto l567 + l568: + position, tokenIndex = position567, tokenIndex567 if buffer[position] != rune('b') { - goto l566 + goto l569 } position++ - goto l564 - l566: - position, tokenIndex = position564, tokenIndex564 + goto l567 + l569: + position, tokenIndex = position567, tokenIndex567 if buffer[position] != rune(':') { - goto l567 + goto l570 } position++ - goto l564 - l567: - position, tokenIndex = position564, tokenIndex564 + goto l567 + l570: + position, tokenIndex = position567, tokenIndex567 if buffer[position] != rune('(') { - goto l568 + goto l571 } position++ - goto l564 - l568: - position, tokenIndex = position564, tokenIndex564 + goto l567 + l571: + position, tokenIndex = position567, tokenIndex567 if buffer[position] != rune('+') { - goto l569 + goto l572 } position++ - goto l564 - l569: - position, tokenIndex = position564, tokenIndex564 + goto l567 + l572: + position, tokenIndex = position567, tokenIndex567 if buffer[position] != rune('-') { - goto l563 + goto l566 } position++ } - l564: - goto l529 - l563: - position, tokenIndex = position563, tokenIndex563 + l567: + goto l532 + l566: + position, tokenIndex = position566, tokenIndex566 } - add(ruleRegisterOrConstant, position530) + add(ruleRegisterOrConstant, position533) } return true - l529: - position, tokenIndex = position529, tokenIndex529 + l532: + position, tokenIndex = position532, tokenIndex532 return false }, - /* 42 ARMConstantTweak <- <(((('u' / 's') (('x' / 'X') ('t' / 'T')) ('x' / 'w' / 'h' / 'b')) / (('l' / 'L') ('s' / 'S') ('l' / 'L')) / (('l' / 'L') ('s' / 'S') ('r' / 'R')) / (('r' / 'R') ('o' / 'O') ('r' / 'R')) / (('a' / 'A') ('s' / 'S') ('r' / 'R'))) (WS '#' Offset)?)> */ + /* 43 ARMConstantTweak <- <(((('u' / 's') (('x' / 'X') ('t' / 'T')) ('x' / 'w' / 'h' / 'b')) / (('l' / 'L') ('s' / 'S') ('l' / 'L')) / (('l' / 'L') ('s' / 'S') ('r' / 'R')) / (('r' / 'R') ('o' / 'O') ('r' / 'R')) / (('a' / 'A') ('s' / 'S') ('r' / 'R'))) (WS '#' Offset)?)> */ func() bool { - position570, tokenIndex570 := position, tokenIndex + position573, tokenIndex573 := position, tokenIndex { - position571 := position + position574 := position { - position572, tokenIndex572 := position, tokenIndex + position575, tokenIndex575 := position, tokenIndex { - position574, tokenIndex574 := position, tokenIndex + position577, tokenIndex577 := position, tokenIndex if buffer[position] != rune('u') { - goto l575 + goto l578 } position++ - goto l574 - l575: - position, tokenIndex = position574, tokenIndex574 + goto l577 + l578: + position, tokenIndex = position577, tokenIndex577 if buffer[position] != rune('s') { - goto l573 + goto l576 } position++ } - l574: + l577: { - position576, tokenIndex576 := position, tokenIndex + position579, tokenIndex579 := position, tokenIndex if buffer[position] != rune('x') { - goto l577 + goto l580 } position++ - goto l576 - l577: - position, tokenIndex = position576, tokenIndex576 + goto l579 + l580: + position, tokenIndex = position579, tokenIndex579 if buffer[position] != rune('X') { - goto l573 + goto l576 } position++ } - l576: + l579: { - position578, tokenIndex578 := position, tokenIndex + position581, tokenIndex581 := position, tokenIndex if buffer[position] != rune('t') { - goto l579 + goto l582 } position++ - goto l578 - l579: - position, tokenIndex = position578, tokenIndex578 + goto l581 + l582: + position, tokenIndex = position581, tokenIndex581 if buffer[position] != rune('T') { - goto l573 + goto l576 } position++ } - l578: + l581: { - position580, tokenIndex580 := position, tokenIndex + position583, tokenIndex583 := position, tokenIndex if buffer[position] != rune('x') { - goto l581 + goto l584 } position++ - goto l580 - l581: - position, tokenIndex = position580, tokenIndex580 + goto l583 + l584: + position, tokenIndex = position583, tokenIndex583 if buffer[position] != rune('w') { - goto l582 + goto l585 } position++ - goto l580 - l582: - position, tokenIndex = position580, tokenIndex580 + goto l583 + l585: + position, tokenIndex = position583, tokenIndex583 if buffer[position] != rune('h') { - goto l583 + goto l586 } position++ - goto l580 - l583: - position, tokenIndex = position580, tokenIndex580 + goto l583 + l586: + position, tokenIndex = position583, tokenIndex583 if buffer[position] != rune('b') { - goto l573 + goto l576 } position++ } - l580: - goto l572 - l573: - position, tokenIndex = position572, tokenIndex572 + l583: + goto l575 + l576: + position, tokenIndex = position575, tokenIndex575 { - position585, tokenIndex585 := position, tokenIndex + position588, tokenIndex588 := position, tokenIndex if buffer[position] != rune('l') { - goto l586 + goto l589 } position++ - goto l585 - l586: - position, tokenIndex = position585, tokenIndex585 + goto l588 + l589: + position, tokenIndex = position588, tokenIndex588 if buffer[position] != rune('L') { - goto l584 + goto l587 } position++ } - l585: + l588: { - position587, tokenIndex587 := position, tokenIndex + position590, tokenIndex590 := position, tokenIndex if buffer[position] != rune('s') { - goto l588 + goto l591 } position++ - goto l587 - l588: - position, tokenIndex = position587, tokenIndex587 + goto l590 + l591: + position, tokenIndex = position590, tokenIndex590 if buffer[position] != rune('S') { - goto l584 - } - position++ - } - l587: - { - position589, tokenIndex589 := position, tokenIndex - if buffer[position] != rune('l') { - goto l590 - } - position++ - goto l589 - l590: - position, tokenIndex = position589, tokenIndex589 - if buffer[position] != rune('L') { - goto l584 + goto l587 } position++ } - l589: - goto l572 - l584: - position, tokenIndex = position572, tokenIndex572 + l590: { position592, tokenIndex592 := position, tokenIndex if buffer[position] != rune('l') { @@ -4782,44 +4892,44 @@ func (p *Asm) Init(options ...func(*Asm) error) error { l593: position, tokenIndex = position592, tokenIndex592 if buffer[position] != rune('L') { - goto l591 + goto l587 } position++ } l592: + goto l575 + l587: + position, tokenIndex = position575, tokenIndex575 { - position594, tokenIndex594 := position, tokenIndex - if buffer[position] != rune('s') { - goto l595 + position595, tokenIndex595 := position, tokenIndex + if buffer[position] != rune('l') { + goto l596 } position++ - goto l594 - l595: - position, tokenIndex = position594, tokenIndex594 - if buffer[position] != rune('S') { - goto l591 + goto l595 + l596: + position, tokenIndex = position595, tokenIndex595 + if buffer[position] != rune('L') { + goto l594 } position++ } - l594: + l595: { - position596, tokenIndex596 := position, tokenIndex - if buffer[position] != rune('r') { - goto l597 + position597, tokenIndex597 := position, tokenIndex + if buffer[position] != rune('s') { + goto l598 } position++ - goto l596 - l597: - position, tokenIndex = position596, tokenIndex596 - if buffer[position] != rune('R') { - goto l591 + goto l597 + l598: + position, tokenIndex = position597, tokenIndex597 + if buffer[position] != rune('S') { + goto l594 } position++ } - l596: - goto l572 - l591: - position, tokenIndex = position572, tokenIndex572 + l597: { position599, tokenIndex599 := position, tokenIndex if buffer[position] != rune('r') { @@ -4830,1639 +4940,1657 @@ func (p *Asm) Init(options ...func(*Asm) error) error { l600: position, tokenIndex = position599, tokenIndex599 if buffer[position] != rune('R') { - goto l598 + goto l594 } position++ } l599: + goto l575 + l594: + position, tokenIndex = position575, tokenIndex575 { - position601, tokenIndex601 := position, tokenIndex + position602, tokenIndex602 := position, tokenIndex + if buffer[position] != rune('r') { + goto l603 + } + position++ + goto l602 + l603: + position, tokenIndex = position602, tokenIndex602 + if buffer[position] != rune('R') { + goto l601 + } + position++ + } + l602: + { + position604, tokenIndex604 := position, tokenIndex if buffer[position] != rune('o') { - goto l602 + goto l605 } position++ - goto l601 - l602: - position, tokenIndex = position601, tokenIndex601 + goto l604 + l605: + position, tokenIndex = position604, tokenIndex604 if buffer[position] != rune('O') { - goto l598 + goto l601 } position++ } - l601: + l604: { - position603, tokenIndex603 := position, tokenIndex + position606, tokenIndex606 := position, tokenIndex if buffer[position] != rune('r') { - goto l604 + goto l607 } position++ - goto l603 - l604: - position, tokenIndex = position603, tokenIndex603 + goto l606 + l607: + position, tokenIndex = position606, tokenIndex606 if buffer[position] != rune('R') { - goto l598 + goto l601 } position++ } - l603: - goto l572 - l598: - position, tokenIndex = position572, tokenIndex572 + l606: + goto l575 + l601: + position, tokenIndex = position575, tokenIndex575 { - position605, tokenIndex605 := position, tokenIndex + position608, tokenIndex608 := position, tokenIndex if buffer[position] != rune('a') { - goto l606 + goto l609 } position++ - goto l605 - l606: - position, tokenIndex = position605, tokenIndex605 + goto l608 + l609: + position, tokenIndex = position608, tokenIndex608 if buffer[position] != rune('A') { - goto l570 + goto l573 } position++ } - l605: + l608: { - position607, tokenIndex607 := position, tokenIndex + position610, tokenIndex610 := position, tokenIndex if buffer[position] != rune('s') { - goto l608 + goto l611 } position++ - goto l607 - l608: - position, tokenIndex = position607, tokenIndex607 + goto l610 + l611: + position, tokenIndex = position610, tokenIndex610 if buffer[position] != rune('S') { - goto l570 + goto l573 } position++ } - l607: + l610: { - position609, tokenIndex609 := position, tokenIndex + position612, tokenIndex612 := position, tokenIndex if buffer[position] != rune('r') { - goto l610 + goto l613 } position++ - goto l609 - l610: - position, tokenIndex = position609, tokenIndex609 + goto l612 + l613: + position, tokenIndex = position612, tokenIndex612 if buffer[position] != rune('R') { - goto l570 + goto l573 } position++ } - l609: + l612: } - l572: + l575: { - position611, tokenIndex611 := position, tokenIndex + position614, tokenIndex614 := position, tokenIndex if !_rules[ruleWS]() { - goto l611 + goto l614 } if buffer[position] != rune('#') { - goto l611 + goto l614 } position++ if !_rules[ruleOffset]() { - goto l611 + goto l614 } - goto l612 - l611: - position, tokenIndex = position611, tokenIndex611 + goto l615 + l614: + position, tokenIndex = position614, tokenIndex614 } - l612: - add(ruleARMConstantTweak, position571) + l615: + add(ruleARMConstantTweak, position574) } return true - l570: - position, tokenIndex = position570, tokenIndex570 + l573: + position, tokenIndex = position573, tokenIndex573 return false }, - /* 43 ARMRegister <- <((('s' / 'S') ('p' / 'P')) / (('x' / 'w' / 'd' / 'q' / 's' / 'h' / 'b') [0-9] [0-9]?) / (('x' / 'X') ('z' / 'Z') ('r' / 'R')) / (('w' / 'W') ('z' / 'Z') ('r' / 'R')) / (('n' / 'N') ('z' / 'Z') ('c' / 'C') ('v' / 'V')) / ARMVectorRegister / ('{' WS? ARMVectorRegister (',' WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')?))> */ + /* 44 ARMRegister <- <((('s' / 'S') ('p' / 'P')) / (('x' / 'w' / 'd' / 'q' / 's' / 'h' / 'b') [0-9] [0-9]?) / (('x' / 'X') ('z' / 'Z') ('r' / 'R')) / (('w' / 'W') ('z' / 'Z') ('r' / 'R')) / (('n' / 'N') ('z' / 'Z') ('c' / 'C') ('v' / 'V')) / ARMVectorRegister / ('{' WS? ARMVectorRegister (',' WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')?))> */ func() bool { - position613, tokenIndex613 := position, tokenIndex + position616, tokenIndex616 := position, tokenIndex { - position614 := position + position617 := position { - position615, tokenIndex615 := position, tokenIndex + position618, tokenIndex618 := position, tokenIndex { - position617, tokenIndex617 := position, tokenIndex + position620, tokenIndex620 := position, tokenIndex if buffer[position] != rune('s') { - goto l618 + goto l621 } position++ - goto l617 - l618: - position, tokenIndex = position617, tokenIndex617 + goto l620 + l621: + position, tokenIndex = position620, tokenIndex620 if buffer[position] != rune('S') { - goto l616 + goto l619 } position++ } - l617: + l620: { - position619, tokenIndex619 := position, tokenIndex + position622, tokenIndex622 := position, tokenIndex if buffer[position] != rune('p') { - goto l620 + goto l623 } position++ - goto l619 - l620: - position, tokenIndex = position619, tokenIndex619 + goto l622 + l623: + position, tokenIndex = position622, tokenIndex622 if buffer[position] != rune('P') { - goto l616 + goto l619 } position++ } + l622: + goto l618 l619: - goto l615 - l616: - position, tokenIndex = position615, tokenIndex615 + position, tokenIndex = position618, tokenIndex618 { - position622, tokenIndex622 := position, tokenIndex + position625, tokenIndex625 := position, tokenIndex if buffer[position] != rune('x') { - goto l623 + goto l626 } position++ - goto l622 - l623: - position, tokenIndex = position622, tokenIndex622 + goto l625 + l626: + position, tokenIndex = position625, tokenIndex625 if buffer[position] != rune('w') { - goto l624 + goto l627 } position++ - goto l622 - l624: - position, tokenIndex = position622, tokenIndex622 + goto l625 + l627: + position, tokenIndex = position625, tokenIndex625 if buffer[position] != rune('d') { - goto l625 + goto l628 } position++ - goto l622 - l625: - position, tokenIndex = position622, tokenIndex622 + goto l625 + l628: + position, tokenIndex = position625, tokenIndex625 if buffer[position] != rune('q') { - goto l626 + goto l629 } position++ - goto l622 - l626: - position, tokenIndex = position622, tokenIndex622 + goto l625 + l629: + position, tokenIndex = position625, tokenIndex625 if buffer[position] != rune('s') { - goto l627 + goto l630 } position++ - goto l622 - l627: - position, tokenIndex = position622, tokenIndex622 + goto l625 + l630: + position, tokenIndex = position625, tokenIndex625 if buffer[position] != rune('h') { - goto l628 + goto l631 } position++ - goto l622 - l628: - position, tokenIndex = position622, tokenIndex622 + goto l625 + l631: + position, tokenIndex = position625, tokenIndex625 if buffer[position] != rune('b') { - goto l621 + goto l624 } position++ } - l622: + l625: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l621 + goto l624 } position++ { - position629, tokenIndex629 := position, tokenIndex + position632, tokenIndex632 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l629 + goto l632 } position++ - goto l630 - l629: - position, tokenIndex = position629, tokenIndex629 + goto l633 + l632: + position, tokenIndex = position632, tokenIndex632 } - l630: - goto l615 - l621: - position, tokenIndex = position615, tokenIndex615 + l633: + goto l618 + l624: + position, tokenIndex = position618, tokenIndex618 { - position632, tokenIndex632 := position, tokenIndex + position635, tokenIndex635 := position, tokenIndex if buffer[position] != rune('x') { - goto l633 + goto l636 } position++ - goto l632 - l633: - position, tokenIndex = position632, tokenIndex632 + goto l635 + l636: + position, tokenIndex = position635, tokenIndex635 if buffer[position] != rune('X') { - goto l631 + goto l634 } position++ } - l632: + l635: { - position634, tokenIndex634 := position, tokenIndex + position637, tokenIndex637 := position, tokenIndex if buffer[position] != rune('z') { - goto l635 + goto l638 } position++ - goto l634 - l635: - position, tokenIndex = position634, tokenIndex634 + goto l637 + l638: + position, tokenIndex = position637, tokenIndex637 if buffer[position] != rune('Z') { - goto l631 + goto l634 } position++ } - l634: + l637: { - position636, tokenIndex636 := position, tokenIndex + position639, tokenIndex639 := position, tokenIndex if buffer[position] != rune('r') { - goto l637 + goto l640 } position++ - goto l636 - l637: - position, tokenIndex = position636, tokenIndex636 + goto l639 + l640: + position, tokenIndex = position639, tokenIndex639 if buffer[position] != rune('R') { - goto l631 + goto l634 } position++ } - l636: - goto l615 - l631: - position, tokenIndex = position615, tokenIndex615 + l639: + goto l618 + l634: + position, tokenIndex = position618, tokenIndex618 { - position639, tokenIndex639 := position, tokenIndex + position642, tokenIndex642 := position, tokenIndex if buffer[position] != rune('w') { - goto l640 + goto l643 } position++ - goto l639 - l640: - position, tokenIndex = position639, tokenIndex639 + goto l642 + l643: + position, tokenIndex = position642, tokenIndex642 if buffer[position] != rune('W') { - goto l638 + goto l641 } position++ } - l639: + l642: { - position641, tokenIndex641 := position, tokenIndex + position644, tokenIndex644 := position, tokenIndex if buffer[position] != rune('z') { - goto l642 + goto l645 } position++ - goto l641 - l642: - position, tokenIndex = position641, tokenIndex641 + goto l644 + l645: + position, tokenIndex = position644, tokenIndex644 if buffer[position] != rune('Z') { - goto l638 + goto l641 } position++ } - l641: + l644: { - position643, tokenIndex643 := position, tokenIndex + position646, tokenIndex646 := position, tokenIndex if buffer[position] != rune('r') { - goto l644 + goto l647 } position++ - goto l643 - l644: - position, tokenIndex = position643, tokenIndex643 + goto l646 + l647: + position, tokenIndex = position646, tokenIndex646 if buffer[position] != rune('R') { - goto l638 + goto l641 } position++ } - l643: - goto l615 - l638: - position, tokenIndex = position615, tokenIndex615 + l646: + goto l618 + l641: + position, tokenIndex = position618, tokenIndex618 { - position646, tokenIndex646 := position, tokenIndex + position649, tokenIndex649 := position, tokenIndex if buffer[position] != rune('n') { - goto l647 + goto l650 } position++ - goto l646 - l647: - position, tokenIndex = position646, tokenIndex646 + goto l649 + l650: + position, tokenIndex = position649, tokenIndex649 if buffer[position] != rune('N') { - goto l645 + goto l648 } position++ } - l646: + l649: { - position648, tokenIndex648 := position, tokenIndex + position651, tokenIndex651 := position, tokenIndex if buffer[position] != rune('z') { - goto l649 + goto l652 } position++ - goto l648 - l649: - position, tokenIndex = position648, tokenIndex648 + goto l651 + l652: + position, tokenIndex = position651, tokenIndex651 if buffer[position] != rune('Z') { - goto l645 + goto l648 } position++ } - l648: + l651: { - position650, tokenIndex650 := position, tokenIndex + position653, tokenIndex653 := position, tokenIndex if buffer[position] != rune('c') { - goto l651 + goto l654 } position++ - goto l650 - l651: - position, tokenIndex = position650, tokenIndex650 + goto l653 + l654: + position, tokenIndex = position653, tokenIndex653 if buffer[position] != rune('C') { - goto l645 + goto l648 } position++ } - l650: + l653: { - position652, tokenIndex652 := position, tokenIndex + position655, tokenIndex655 := position, tokenIndex if buffer[position] != rune('v') { - goto l653 + goto l656 } position++ - goto l652 - l653: - position, tokenIndex = position652, tokenIndex652 + goto l655 + l656: + position, tokenIndex = position655, tokenIndex655 if buffer[position] != rune('V') { - goto l645 + goto l648 } position++ } - l652: - goto l615 - l645: - position, tokenIndex = position615, tokenIndex615 + l655: + goto l618 + l648: + position, tokenIndex = position618, tokenIndex618 if !_rules[ruleARMVectorRegister]() { - goto l654 + goto l657 } - goto l615 - l654: - position, tokenIndex = position615, tokenIndex615 + goto l618 + l657: + position, tokenIndex = position618, tokenIndex618 if buffer[position] != rune('{') { - goto l613 + goto l616 } position++ { - position655, tokenIndex655 := position, tokenIndex + position658, tokenIndex658 := position, tokenIndex if !_rules[ruleWS]() { - goto l655 + goto l658 } - goto l656 - l655: - position, tokenIndex = position655, tokenIndex655 + goto l659 + l658: + position, tokenIndex = position658, tokenIndex658 } - l656: + l659: if !_rules[ruleARMVectorRegister]() { - goto l613 + goto l616 } - l657: + l660: { - position658, tokenIndex658 := position, tokenIndex + position661, tokenIndex661 := position, tokenIndex if buffer[position] != rune(',') { - goto l658 + goto l661 } position++ { - position659, tokenIndex659 := position, tokenIndex + position662, tokenIndex662 := position, tokenIndex if !_rules[ruleWS]() { - goto l659 + goto l662 } - goto l660 - l659: - position, tokenIndex = position659, tokenIndex659 + goto l663 + l662: + position, tokenIndex = position662, tokenIndex662 } - l660: + l663: if !_rules[ruleARMVectorRegister]() { - goto l658 + goto l661 } - goto l657 - l658: - position, tokenIndex = position658, tokenIndex658 + goto l660 + l661: + position, tokenIndex = position661, tokenIndex661 } { - position661, tokenIndex661 := position, tokenIndex + position664, tokenIndex664 := position, tokenIndex if !_rules[ruleWS]() { - goto l661 + goto l664 } - goto l662 - l661: - position, tokenIndex = position661, tokenIndex661 + goto l665 + l664: + position, tokenIndex = position664, tokenIndex664 } - l662: + l665: if buffer[position] != rune('}') { - goto l613 + goto l616 } position++ { - position663, tokenIndex663 := position, tokenIndex + position666, tokenIndex666 := position, tokenIndex if buffer[position] != rune('[') { - goto l663 + goto l666 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l663 + goto l666 } position++ { - position665, tokenIndex665 := position, tokenIndex + position668, tokenIndex668 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l665 + goto l668 } position++ - goto l666 - l665: - position, tokenIndex = position665, tokenIndex665 + goto l669 + l668: + position, tokenIndex = position668, tokenIndex668 } - l666: + l669: if buffer[position] != rune(']') { - goto l663 + goto l666 } position++ - goto l664 - l663: - position, tokenIndex = position663, tokenIndex663 + goto l667 + l666: + position, tokenIndex = position666, tokenIndex666 } - l664: + l667: } - l615: - add(ruleARMRegister, position614) + l618: + add(ruleARMRegister, position617) } return true - l613: - position, tokenIndex = position613, tokenIndex613 + l616: + position, tokenIndex = position616, tokenIndex616 return false }, - /* 44 ARMVectorRegister <- <(('v' / 'V') [0-9] [0-9]? ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */ + /* 45 ARMVectorRegister <- <(('v' / 'V') [0-9] [0-9]? ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */ func() bool { - position667, tokenIndex667 := position, tokenIndex + position670, tokenIndex670 := position, tokenIndex { - position668 := position + position671 := position { - position669, tokenIndex669 := position, tokenIndex + position672, tokenIndex672 := position, tokenIndex if buffer[position] != rune('v') { - goto l670 + goto l673 } position++ - goto l669 - l670: - position, tokenIndex = position669, tokenIndex669 + goto l672 + l673: + position, tokenIndex = position672, tokenIndex672 if buffer[position] != rune('V') { - goto l667 + goto l670 } position++ } - l669: + l672: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l667 + goto l670 } position++ { - position671, tokenIndex671 := position, tokenIndex + position674, tokenIndex674 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l671 + goto l674 } position++ - goto l672 - l671: - position, tokenIndex = position671, tokenIndex671 + goto l675 + l674: + position, tokenIndex = position674, tokenIndex674 } - l672: + l675: { - position673, tokenIndex673 := position, tokenIndex + position676, tokenIndex676 := position, tokenIndex if buffer[position] != rune('.') { - goto l673 + goto l676 } position++ - l675: + l678: { - position676, tokenIndex676 := position, tokenIndex + position679, tokenIndex679 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l676 + goto l679 } position++ - goto l675 - l676: - position, tokenIndex = position676, tokenIndex676 + goto l678 + l679: + position, tokenIndex = position679, tokenIndex679 } { - position677, tokenIndex677 := position, tokenIndex + position680, tokenIndex680 := position, tokenIndex if buffer[position] != rune('b') { - goto l678 + goto l681 } position++ - goto l677 - l678: - position, tokenIndex = position677, tokenIndex677 + goto l680 + l681: + position, tokenIndex = position680, tokenIndex680 if buffer[position] != rune('s') { - goto l679 + goto l682 } position++ - goto l677 - l679: - position, tokenIndex = position677, tokenIndex677 + goto l680 + l682: + position, tokenIndex = position680, tokenIndex680 if buffer[position] != rune('d') { - goto l680 + goto l683 } position++ - goto l677 - l680: - position, tokenIndex = position677, tokenIndex677 + goto l680 + l683: + position, tokenIndex = position680, tokenIndex680 if buffer[position] != rune('h') { - goto l681 + goto l684 } position++ - goto l677 - l681: - position, tokenIndex = position677, tokenIndex677 + goto l680 + l684: + position, tokenIndex = position680, tokenIndex680 if buffer[position] != rune('q') { - goto l673 + goto l676 } position++ } - l677: + l680: { - position682, tokenIndex682 := position, tokenIndex + position685, tokenIndex685 := position, tokenIndex if buffer[position] != rune('[') { - goto l682 + goto l685 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l682 + goto l685 } position++ { - position684, tokenIndex684 := position, tokenIndex + position687, tokenIndex687 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l684 + goto l687 } position++ - goto l685 - l684: - position, tokenIndex = position684, tokenIndex684 + goto l688 + l687: + position, tokenIndex = position687, tokenIndex687 } - l685: + l688: if buffer[position] != rune(']') { - goto l682 + goto l685 } position++ - goto l683 - l682: - position, tokenIndex = position682, tokenIndex682 + goto l686 + l685: + position, tokenIndex = position685, tokenIndex685 } - l683: - goto l674 - l673: - position, tokenIndex = position673, tokenIndex673 + l686: + goto l677 + l676: + position, tokenIndex = position676, tokenIndex676 } - l674: - add(ruleARMVectorRegister, position668) + l677: + add(ruleARMVectorRegister, position671) } return true - l667: - position, tokenIndex = position667, tokenIndex667 + l670: + position, tokenIndex = position670, tokenIndex670 return false }, - /* 45 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */ + /* 46 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */ func() bool { - position686, tokenIndex686 := position, tokenIndex + position689, tokenIndex689 := position, tokenIndex { - position687 := position + position690 := position { - position688, tokenIndex688 := position, tokenIndex + position691, tokenIndex691 := position, tokenIndex if !_rules[ruleSymbolRef]() { - goto l689 + goto l692 } if !_rules[ruleBaseIndexScale]() { - goto l689 + goto l692 } - goto l688 - l689: - position, tokenIndex = position688, tokenIndex688 + goto l691 + l692: + position, tokenIndex = position691, tokenIndex691 if !_rules[ruleSymbolRef]() { - goto l690 + goto l693 } - goto l688 - l690: - position, tokenIndex = position688, tokenIndex688 + goto l691 + l693: + position, tokenIndex = position691, tokenIndex691 if !_rules[ruleLow12BitsSymbolRef]() { - goto l691 + goto l694 } - goto l688 - l691: - position, tokenIndex = position688, tokenIndex688 - l693: + goto l691 + l694: + position, tokenIndex = position691, tokenIndex691 + l696: { - position694, tokenIndex694 := position, tokenIndex + position697, tokenIndex697 := position, tokenIndex if !_rules[ruleOffset]() { - goto l694 + goto l697 } - goto l693 - l694: - position, tokenIndex = position694, tokenIndex694 + goto l696 + l697: + position, tokenIndex = position697, tokenIndex697 } if !_rules[ruleBaseIndexScale]() { - goto l692 + goto l695 } - goto l688 - l692: - position, tokenIndex = position688, tokenIndex688 + goto l691 + l695: + position, tokenIndex = position691, tokenIndex691 if !_rules[ruleSegmentRegister]() { - goto l695 + goto l698 } if !_rules[ruleOffset]() { - goto l695 + goto l698 } if !_rules[ruleBaseIndexScale]() { - goto l695 + goto l698 } - goto l688 - l695: - position, tokenIndex = position688, tokenIndex688 + goto l691 + l698: + position, tokenIndex = position691, tokenIndex691 if !_rules[ruleSegmentRegister]() { - goto l696 + goto l699 } if !_rules[ruleBaseIndexScale]() { - goto l696 + goto l699 } - goto l688 - l696: - position, tokenIndex = position688, tokenIndex688 + goto l691 + l699: + position, tokenIndex = position691, tokenIndex691 if !_rules[ruleSegmentRegister]() { - goto l697 + goto l700 } if !_rules[ruleOffset]() { - goto l697 + goto l700 } - goto l688 - l697: - position, tokenIndex = position688, tokenIndex688 + goto l691 + l700: + position, tokenIndex = position691, tokenIndex691 if !_rules[ruleARMBaseIndexScale]() { - goto l698 + goto l701 } - goto l688 - l698: - position, tokenIndex = position688, tokenIndex688 + goto l691 + l701: + position, tokenIndex = position691, tokenIndex691 if !_rules[ruleBaseIndexScale]() { - goto l686 + goto l689 } } - l688: - add(ruleMemoryRef, position687) + l691: + add(ruleMemoryRef, position690) } return true - l686: - position, tokenIndex = position686, tokenIndex686 + l689: + position, tokenIndex = position689, tokenIndex689 return false }, - /* 46 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ + /* 47 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ func() bool { - position699, tokenIndex699 := position, tokenIndex + position702, tokenIndex702 := position, tokenIndex { - position700 := position + position703 := position { - position701, tokenIndex701 := position, tokenIndex - l703: + position704, tokenIndex704 := position, tokenIndex + l706: { - position704, tokenIndex704 := position, tokenIndex + position707, tokenIndex707 := position, tokenIndex if !_rules[ruleOffset]() { - goto l704 + goto l707 } - goto l703 - l704: - position, tokenIndex = position704, tokenIndex704 + goto l706 + l707: + position, tokenIndex = position707, tokenIndex707 } if buffer[position] != rune('+') { - goto l701 + goto l704 } position++ - goto l702 - l701: - position, tokenIndex = position701, tokenIndex701 + goto l705 + l704: + position, tokenIndex = position704, tokenIndex704 } - l702: + l705: { - position705, tokenIndex705 := position, tokenIndex + position708, tokenIndex708 := position, tokenIndex if !_rules[ruleLocalSymbol]() { - goto l706 + goto l709 } - goto l705 - l706: - position, tokenIndex = position705, tokenIndex705 + goto l708 + l709: + position, tokenIndex = position708, tokenIndex708 if !_rules[ruleSymbolName]() { - goto l699 + goto l702 } } - l705: - l707: + l708: + l710: { - position708, tokenIndex708 := position, tokenIndex + position711, tokenIndex711 := position, tokenIndex if !_rules[ruleOffset]() { - goto l708 + goto l711 } - goto l707 - l708: - position, tokenIndex = position708, tokenIndex708 + goto l710 + l711: + position, tokenIndex = position711, tokenIndex711 } { - position709, tokenIndex709 := position, tokenIndex + position712, tokenIndex712 := position, tokenIndex if buffer[position] != rune('@') { - goto l709 + goto l712 } position++ if !_rules[ruleSection]() { - goto l709 + goto l712 } - l711: + l714: { - position712, tokenIndex712 := position, tokenIndex + position715, tokenIndex715 := position, tokenIndex if !_rules[ruleOffset]() { - goto l712 + goto l715 } - goto l711 - l712: - position, tokenIndex = position712, tokenIndex712 + goto l714 + l715: + position, tokenIndex = position715, tokenIndex715 } - goto l710 - l709: - position, tokenIndex = position709, tokenIndex709 + goto l713 + l712: + position, tokenIndex = position712, tokenIndex712 } - l710: - add(ruleSymbolRef, position700) + l713: + add(ruleSymbolRef, position703) } return true - l699: - position, tokenIndex = position699, tokenIndex699 + l702: + position, tokenIndex = position702, tokenIndex702 return false }, - /* 47 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */ + /* 48 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */ func() bool { - position713, tokenIndex713 := position, tokenIndex + position716, tokenIndex716 := position, tokenIndex { - position714 := position + position717 := position if buffer[position] != rune(':') { - goto l713 + goto l716 } position++ { - position715, tokenIndex715 := position, tokenIndex + position718, tokenIndex718 := position, tokenIndex if buffer[position] != rune('l') { - goto l716 + goto l719 } position++ - goto l715 - l716: - position, tokenIndex = position715, tokenIndex715 + goto l718 + l719: + position, tokenIndex = position718, tokenIndex718 if buffer[position] != rune('L') { - goto l713 + goto l716 } position++ } - l715: + l718: { - position717, tokenIndex717 := position, tokenIndex + position720, tokenIndex720 := position, tokenIndex if buffer[position] != rune('o') { - goto l718 + goto l721 } position++ - goto l717 - l718: - position, tokenIndex = position717, tokenIndex717 + goto l720 + l721: + position, tokenIndex = position720, tokenIndex720 if buffer[position] != rune('O') { - goto l713 + goto l716 } position++ } - l717: + l720: if buffer[position] != rune('1') { - goto l713 + goto l716 } position++ if buffer[position] != rune('2') { - goto l713 + goto l716 } position++ if buffer[position] != rune(':') { - goto l713 + goto l716 } position++ { - position719, tokenIndex719 := position, tokenIndex + position722, tokenIndex722 := position, tokenIndex if !_rules[ruleLocalSymbol]() { - goto l720 + goto l723 } - goto l719 - l720: - position, tokenIndex = position719, tokenIndex719 + goto l722 + l723: + position, tokenIndex = position722, tokenIndex722 if !_rules[ruleSymbolName]() { - goto l713 + goto l716 } } - l719: + l722: { - position721, tokenIndex721 := position, tokenIndex + position724, tokenIndex724 := position, tokenIndex if !_rules[ruleOffset]() { - goto l721 + goto l724 } - goto l722 - l721: - position, tokenIndex = position721, tokenIndex721 + goto l725 + l724: + position, tokenIndex = position724, tokenIndex724 } - l722: - add(ruleLow12BitsSymbolRef, position714) + l725: + add(ruleLow12BitsSymbolRef, position717) } return true - l713: - position, tokenIndex = position713, tokenIndex713 + l716: + position, tokenIndex = position716, tokenIndex716 return false }, - /* 48 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */ + /* 49 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */ func() bool { - position723, tokenIndex723 := position, tokenIndex + position726, tokenIndex726 := position, tokenIndex { - position724 := position + position727 := position if buffer[position] != rune('[') { - goto l723 + goto l726 } position++ if !_rules[ruleARMRegister]() { - goto l723 + goto l726 } { - position725, tokenIndex725 := position, tokenIndex + position728, tokenIndex728 := position, tokenIndex if buffer[position] != rune(',') { - goto l725 + goto l728 } position++ { - position727, tokenIndex727 := position, tokenIndex + position730, tokenIndex730 := position, tokenIndex if !_rules[ruleWS]() { - goto l727 + goto l730 } - goto l728 - l727: - position, tokenIndex = position727, tokenIndex727 + goto l731 + l730: + position, tokenIndex = position730, tokenIndex730 } - l728: + l731: { - position729, tokenIndex729 := position, tokenIndex + position732, tokenIndex732 := position, tokenIndex if buffer[position] != rune('#') { - goto l730 + goto l733 } position++ if !_rules[ruleOffset]() { - goto l730 + goto l733 } { - position731, tokenIndex731 := position, tokenIndex + position734, tokenIndex734 := position, tokenIndex { - position733, tokenIndex733 := position, tokenIndex + position736, tokenIndex736 := position, tokenIndex if buffer[position] != rune('*') { - goto l734 + goto l737 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l734 + goto l737 } position++ - l735: + l738: { - position736, tokenIndex736 := position, tokenIndex + position739, tokenIndex739 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l736 + goto l739 } position++ - goto l735 - l736: - position, tokenIndex = position736, tokenIndex736 + goto l738 + l739: + position, tokenIndex = position739, tokenIndex739 } - goto l733 - l734: - position, tokenIndex = position733, tokenIndex733 + goto l736 + l737: + position, tokenIndex = position736, tokenIndex736 if buffer[position] != rune('*') { - goto l737 + goto l740 } position++ if buffer[position] != rune('(') { - goto l737 + goto l740 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l737 + goto l740 } position++ - l738: + l741: { - position739, tokenIndex739 := position, tokenIndex + position742, tokenIndex742 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l739 + goto l742 } position++ - goto l738 - l739: - position, tokenIndex = position739, tokenIndex739 + goto l741 + l742: + position, tokenIndex = position742, tokenIndex742 } if !_rules[ruleOperator]() { - goto l737 + goto l740 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l737 + goto l740 } position++ - l740: + l743: { - position741, tokenIndex741 := position, tokenIndex + position744, tokenIndex744 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l741 + goto l744 } position++ - goto l740 - l741: - position, tokenIndex = position741, tokenIndex741 + goto l743 + l744: + position, tokenIndex = position744, tokenIndex744 } if buffer[position] != rune(')') { - goto l737 + goto l740 } position++ - goto l733 - l737: - position, tokenIndex = position733, tokenIndex733 - l742: + goto l736 + l740: + position, tokenIndex = position736, tokenIndex736 + l745: { - position743, tokenIndex743 := position, tokenIndex + position746, tokenIndex746 := position, tokenIndex if buffer[position] != rune('+') { - goto l743 + goto l746 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l743 + goto l746 } position++ - l744: + l747: { - position745, tokenIndex745 := position, tokenIndex + position748, tokenIndex748 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l745 + goto l748 } position++ - goto l744 - l745: - position, tokenIndex = position745, tokenIndex745 + goto l747 + l748: + position, tokenIndex = position748, tokenIndex748 } - goto l742 - l743: - position, tokenIndex = position743, tokenIndex743 + goto l745 + l746: + position, tokenIndex = position746, tokenIndex746 } } - l733: - goto l732 + l736: + goto l735 - position, tokenIndex = position731, tokenIndex731 + position, tokenIndex = position734, tokenIndex734 } - l732: - goto l729 - l730: - position, tokenIndex = position729, tokenIndex729 + l735: + goto l732 + l733: + position, tokenIndex = position732, tokenIndex732 if !_rules[ruleARMGOTLow12]() { - goto l746 + goto l749 } - goto l729 - l746: - position, tokenIndex = position729, tokenIndex729 + goto l732 + l749: + position, tokenIndex = position732, tokenIndex732 if !_rules[ruleLow12BitsSymbolRef]() { - goto l747 + goto l750 } - goto l729 - l747: - position, tokenIndex = position729, tokenIndex729 + goto l732 + l750: + position, tokenIndex = position732, tokenIndex732 if !_rules[ruleARMRegister]() { - goto l725 + goto l728 } } - l729: + l732: { - position748, tokenIndex748 := position, tokenIndex + position751, tokenIndex751 := position, tokenIndex if buffer[position] != rune(',') { - goto l748 + goto l751 } position++ { - position750, tokenIndex750 := position, tokenIndex + position753, tokenIndex753 := position, tokenIndex if !_rules[ruleWS]() { - goto l750 + goto l753 } - goto l751 - l750: - position, tokenIndex = position750, tokenIndex750 + goto l754 + l753: + position, tokenIndex = position753, tokenIndex753 } - l751: + l754: if !_rules[ruleARMConstantTweak]() { - goto l748 + goto l751 } - goto l749 - l748: - position, tokenIndex = position748, tokenIndex748 + goto l752 + l751: + position, tokenIndex = position751, tokenIndex751 } - l749: - goto l726 - l725: - position, tokenIndex = position725, tokenIndex725 + l752: + goto l729 + l728: + position, tokenIndex = position728, tokenIndex728 } - l726: + l729: if buffer[position] != rune(']') { - goto l723 + goto l726 } position++ { - position752, tokenIndex752 := position, tokenIndex + position755, tokenIndex755 := position, tokenIndex if !_rules[ruleARMPostincrement]() { - goto l752 + goto l755 } - goto l753 - l752: - position, tokenIndex = position752, tokenIndex752 + goto l756 + l755: + position, tokenIndex = position755, tokenIndex755 } - l753: - add(ruleARMBaseIndexScale, position724) + l756: + add(ruleARMBaseIndexScale, position727) } return true - l723: - position, tokenIndex = position723, tokenIndex723 + l726: + position, tokenIndex = position726, tokenIndex726 return false }, - /* 49 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */ + /* 50 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */ func() bool { - position754, tokenIndex754 := position, tokenIndex + position757, tokenIndex757 := position, tokenIndex { - position755 := position + position758 := position if buffer[position] != rune(':') { - goto l754 + goto l757 } position++ { - position756, tokenIndex756 := position, tokenIndex + position759, tokenIndex759 := position, tokenIndex if buffer[position] != rune('g') { - goto l757 + goto l760 } position++ - goto l756 - l757: - position, tokenIndex = position756, tokenIndex756 + goto l759 + l760: + position, tokenIndex = position759, tokenIndex759 if buffer[position] != rune('G') { - goto l754 + goto l757 } position++ } - l756: + l759: { - position758, tokenIndex758 := position, tokenIndex + position761, tokenIndex761 := position, tokenIndex if buffer[position] != rune('o') { - goto l759 + goto l762 } position++ - goto l758 - l759: - position, tokenIndex = position758, tokenIndex758 + goto l761 + l762: + position, tokenIndex = position761, tokenIndex761 if buffer[position] != rune('O') { - goto l754 + goto l757 } position++ } - l758: + l761: { - position760, tokenIndex760 := position, tokenIndex + position763, tokenIndex763 := position, tokenIndex if buffer[position] != rune('t') { - goto l761 + goto l764 } position++ - goto l760 - l761: - position, tokenIndex = position760, tokenIndex760 + goto l763 + l764: + position, tokenIndex = position763, tokenIndex763 if buffer[position] != rune('T') { - goto l754 + goto l757 } position++ } - l760: + l763: if buffer[position] != rune('_') { - goto l754 + goto l757 } position++ { - position762, tokenIndex762 := position, tokenIndex + position765, tokenIndex765 := position, tokenIndex if buffer[position] != rune('l') { - goto l763 + goto l766 } position++ - goto l762 - l763: - position, tokenIndex = position762, tokenIndex762 + goto l765 + l766: + position, tokenIndex = position765, tokenIndex765 if buffer[position] != rune('L') { - goto l754 + goto l757 } position++ } - l762: + l765: { - position764, tokenIndex764 := position, tokenIndex + position767, tokenIndex767 := position, tokenIndex if buffer[position] != rune('o') { - goto l765 + goto l768 } position++ - goto l764 - l765: - position, tokenIndex = position764, tokenIndex764 + goto l767 + l768: + position, tokenIndex = position767, tokenIndex767 if buffer[position] != rune('O') { - goto l754 + goto l757 } position++ } - l764: + l767: if buffer[position] != rune('1') { - goto l754 + goto l757 } position++ if buffer[position] != rune('2') { - goto l754 + goto l757 } position++ if buffer[position] != rune(':') { - goto l754 + goto l757 } position++ if !_rules[ruleSymbolName]() { - goto l754 + goto l757 } - add(ruleARMGOTLow12, position755) + add(ruleARMGOTLow12, position758) } return true - l754: - position, tokenIndex = position754, tokenIndex754 + l757: + position, tokenIndex = position757, tokenIndex757 return false }, - /* 50 ARMPostincrement <- <'!'> */ + /* 51 ARMPostincrement <- <'!'> */ func() bool { - position766, tokenIndex766 := position, tokenIndex + position769, tokenIndex769 := position, tokenIndex { - position767 := position + position770 := position if buffer[position] != rune('!') { - goto l766 + goto l769 } position++ - add(ruleARMPostincrement, position767) + add(ruleARMPostincrement, position770) } return true - l766: - position, tokenIndex = position766, tokenIndex766 + l769: + position, tokenIndex = position769, tokenIndex769 return false }, - /* 51 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ + /* 52 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ func() bool { - position768, tokenIndex768 := position, tokenIndex + position771, tokenIndex771 := position, tokenIndex { - position769 := position + position772 := position if buffer[position] != rune('(') { - goto l768 + goto l771 } position++ { - position770, tokenIndex770 := position, tokenIndex + position773, tokenIndex773 := position, tokenIndex if !_rules[ruleRegisterOrConstant]() { - goto l770 + goto l773 } - goto l771 - l770: - position, tokenIndex = position770, tokenIndex770 + goto l774 + l773: + position, tokenIndex = position773, tokenIndex773 } - l771: + l774: { - position772, tokenIndex772 := position, tokenIndex + position775, tokenIndex775 := position, tokenIndex if !_rules[ruleWS]() { - goto l772 + goto l775 } - goto l773 - l772: - position, tokenIndex = position772, tokenIndex772 + goto l776 + l775: + position, tokenIndex = position775, tokenIndex775 } - l773: + l776: { - position774, tokenIndex774 := position, tokenIndex + position777, tokenIndex777 := position, tokenIndex if buffer[position] != rune(',') { - goto l774 + goto l777 } position++ { - position776, tokenIndex776 := position, tokenIndex + position779, tokenIndex779 := position, tokenIndex if !_rules[ruleWS]() { - goto l776 + goto l779 } - goto l777 - l776: - position, tokenIndex = position776, tokenIndex776 + goto l780 + l779: + position, tokenIndex = position779, tokenIndex779 } - l777: + l780: if !_rules[ruleRegisterOrConstant]() { - goto l774 + goto l777 } { - position778, tokenIndex778 := position, tokenIndex + position781, tokenIndex781 := position, tokenIndex if !_rules[ruleWS]() { - goto l778 + goto l781 } - goto l779 - l778: - position, tokenIndex = position778, tokenIndex778 + goto l782 + l781: + position, tokenIndex = position781, tokenIndex781 } - l779: + l782: { - position780, tokenIndex780 := position, tokenIndex + position783, tokenIndex783 := position, tokenIndex if buffer[position] != rune(',') { - goto l780 + goto l783 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l780 + goto l783 } position++ - l782: + l785: { - position783, tokenIndex783 := position, tokenIndex + position786, tokenIndex786 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l783 + goto l786 } position++ - goto l782 - l783: - position, tokenIndex = position783, tokenIndex783 + goto l785 + l786: + position, tokenIndex = position786, tokenIndex786 } - goto l781 - l780: - position, tokenIndex = position780, tokenIndex780 + goto l784 + l783: + position, tokenIndex = position783, tokenIndex783 } - l781: - goto l775 - l774: - position, tokenIndex = position774, tokenIndex774 + l784: + goto l778 + l777: + position, tokenIndex = position777, tokenIndex777 } - l775: + l778: if buffer[position] != rune(')') { - goto l768 + goto l771 } position++ - add(ruleBaseIndexScale, position769) + add(ruleBaseIndexScale, position772) } return true - l768: - position, tokenIndex = position768, tokenIndex768 + l771: + position, tokenIndex = position771, tokenIndex771 return false }, - /* 52 Operator <- <('+' / '-')> */ + /* 53 Operator <- <('+' / '-')> */ func() bool { - position784, tokenIndex784 := position, tokenIndex + position787, tokenIndex787 := position, tokenIndex { - position785 := position + position788 := position { - position786, tokenIndex786 := position, tokenIndex + position789, tokenIndex789 := position, tokenIndex if buffer[position] != rune('+') { - goto l787 + goto l790 } position++ - goto l786 - l787: - position, tokenIndex = position786, tokenIndex786 + goto l789 + l790: + position, tokenIndex = position789, tokenIndex789 if buffer[position] != rune('-') { - goto l784 + goto l787 } position++ } - l786: - add(ruleOperator, position785) + l789: + add(ruleOperator, position788) } return true - l784: - position, tokenIndex = position784, tokenIndex784 + l787: + position, tokenIndex = position787, tokenIndex787 return false }, - /* 53 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */ + /* 54 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */ func() bool { - position788, tokenIndex788 := position, tokenIndex + position791, tokenIndex791 := position, tokenIndex { - position789 := position + position792 := position { - position790, tokenIndex790 := position, tokenIndex + position793, tokenIndex793 := position, tokenIndex if buffer[position] != rune('+') { - goto l790 + goto l793 } position++ - goto l791 - l790: - position, tokenIndex = position790, tokenIndex790 + goto l794 + l793: + position, tokenIndex = position793, tokenIndex793 } - l791: + l794: { - position792, tokenIndex792 := position, tokenIndex + position795, tokenIndex795 := position, tokenIndex if buffer[position] != rune('-') { - goto l792 + goto l795 } position++ - goto l793 - l792: - position, tokenIndex = position792, tokenIndex792 + goto l796 + l795: + position, tokenIndex = position795, tokenIndex795 } - l793: + l796: { - position794, tokenIndex794 := position, tokenIndex + position797, tokenIndex797 := position, tokenIndex if buffer[position] != rune('0') { - goto l795 + goto l798 } position++ { - position796, tokenIndex796 := position, tokenIndex + position799, tokenIndex799 := position, tokenIndex if buffer[position] != rune('b') { - goto l797 + goto l800 } position++ - goto l796 - l797: - position, tokenIndex = position796, tokenIndex796 + goto l799 + l800: + position, tokenIndex = position799, tokenIndex799 if buffer[position] != rune('B') { - goto l795 + goto l798 } position++ } - l796: + l799: { - position800, tokenIndex800 := position, tokenIndex + position803, tokenIndex803 := position, tokenIndex if buffer[position] != rune('0') { - goto l801 + goto l804 } position++ - goto l800 - l801: - position, tokenIndex = position800, tokenIndex800 + goto l803 + l804: + position, tokenIndex = position803, tokenIndex803 if buffer[position] != rune('1') { - goto l795 + goto l798 } position++ } - l800: - l798: + l803: + l801: { - position799, tokenIndex799 := position, tokenIndex + position802, tokenIndex802 := position, tokenIndex { - position802, tokenIndex802 := position, tokenIndex + position805, tokenIndex805 := position, tokenIndex if buffer[position] != rune('0') { - goto l803 + goto l806 } position++ - goto l802 - l803: - position, tokenIndex = position802, tokenIndex802 + goto l805 + l806: + position, tokenIndex = position805, tokenIndex805 if buffer[position] != rune('1') { - goto l799 + goto l802 } position++ } + l805: + goto l801 l802: - goto l798 - l799: - position, tokenIndex = position799, tokenIndex799 + position, tokenIndex = position802, tokenIndex802 } - goto l794 - l795: - position, tokenIndex = position794, tokenIndex794 + goto l797 + l798: + position, tokenIndex = position797, tokenIndex797 if buffer[position] != rune('0') { - goto l804 + goto l807 } position++ { - position805, tokenIndex805 := position, tokenIndex + position808, tokenIndex808 := position, tokenIndex if buffer[position] != rune('x') { - goto l806 + goto l809 } position++ - goto l805 - l806: - position, tokenIndex = position805, tokenIndex805 + goto l808 + l809: + position, tokenIndex = position808, tokenIndex808 if buffer[position] != rune('X') { - goto l804 + goto l807 } position++ } - l805: + l808: { - position809, tokenIndex809 := position, tokenIndex + position812, tokenIndex812 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l810 + goto l813 } position++ - goto l809 - l810: - position, tokenIndex = position809, tokenIndex809 + goto l812 + l813: + position, tokenIndex = position812, tokenIndex812 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l811 + goto l814 } position++ - goto l809 - l811: - position, tokenIndex = position809, tokenIndex809 + goto l812 + l814: + position, tokenIndex = position812, tokenIndex812 { - position812, tokenIndex812 := position, tokenIndex + position815, tokenIndex815 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l813 + goto l816 } position++ - goto l812 - l813: - position, tokenIndex = position812, tokenIndex812 + goto l815 + l816: + position, tokenIndex = position815, tokenIndex815 if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l804 + goto l807 } position++ } - l812: + l815: } - l809: - l807: + l812: + l810: { - position808, tokenIndex808 := position, tokenIndex + position811, tokenIndex811 := position, tokenIndex { - position814, tokenIndex814 := position, tokenIndex + position817, tokenIndex817 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l815 + goto l818 } position++ - goto l814 - l815: - position, tokenIndex = position814, tokenIndex814 + goto l817 + l818: + position, tokenIndex = position817, tokenIndex817 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l816 + goto l819 } position++ - goto l814 - l816: - position, tokenIndex = position814, tokenIndex814 + goto l817 + l819: + position, tokenIndex = position817, tokenIndex817 { - position817, tokenIndex817 := position, tokenIndex + position820, tokenIndex820 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l818 + goto l821 } position++ - goto l817 - l818: - position, tokenIndex = position817, tokenIndex817 + goto l820 + l821: + position, tokenIndex = position820, tokenIndex820 if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l808 + goto l811 } position++ } - l817: + l820: } - l814: - goto l807 - l808: - position, tokenIndex = position808, tokenIndex808 + l817: + goto l810 + l811: + position, tokenIndex = position811, tokenIndex811 } - goto l794 - l804: - position, tokenIndex = position794, tokenIndex794 + goto l797 + l807: + position, tokenIndex = position797, tokenIndex797 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l788 + goto l791 } position++ - l819: + l822: { - position820, tokenIndex820 := position, tokenIndex + position823, tokenIndex823 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l820 + goto l823 } position++ - goto l819 - l820: - position, tokenIndex = position820, tokenIndex820 + goto l822 + l823: + position, tokenIndex = position823, tokenIndex823 } } - l794: - add(ruleOffset, position789) + l797: + add(ruleOffset, position792) } return true - l788: - position, tokenIndex = position788, tokenIndex788 + l791: + position, tokenIndex = position791, tokenIndex791 return false }, - /* 54 Section <- <([a-z] / [A-Z] / '@')+> */ + /* 55 Section <- <([a-z] / [A-Z] / '@')+> */ func() bool { - position821, tokenIndex821 := position, tokenIndex + position824, tokenIndex824 := position, tokenIndex { - position822 := position + position825 := position { - position825, tokenIndex825 := position, tokenIndex + position828, tokenIndex828 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l826 + goto l829 } position++ - goto l825 - l826: - position, tokenIndex = position825, tokenIndex825 + goto l828 + l829: + position, tokenIndex = position828, tokenIndex828 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l827 + goto l830 } position++ - goto l825 - l827: - position, tokenIndex = position825, tokenIndex825 + goto l828 + l830: + position, tokenIndex = position828, tokenIndex828 if buffer[position] != rune('@') { - goto l821 + goto l824 } position++ } - l825: - l823: + l828: + l826: { - position824, tokenIndex824 := position, tokenIndex + position827, tokenIndex827 := position, tokenIndex { - position828, tokenIndex828 := position, tokenIndex + position831, tokenIndex831 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l829 + goto l832 } position++ - goto l828 - l829: - position, tokenIndex = position828, tokenIndex828 + goto l831 + l832: + position, tokenIndex = position831, tokenIndex831 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l830 + goto l833 } position++ - goto l828 - l830: - position, tokenIndex = position828, tokenIndex828 + goto l831 + l833: + position, tokenIndex = position831, tokenIndex831 if buffer[position] != rune('@') { - goto l824 + goto l827 } position++ } - l828: - goto l823 - l824: - position, tokenIndex = position824, tokenIndex824 + l831: + goto l826 + l827: + position, tokenIndex = position827, tokenIndex827 } - add(ruleSection, position822) + add(ruleSection, position825) } return true - l821: - position, tokenIndex = position821, tokenIndex821 + l824: + position, tokenIndex = position824, tokenIndex824 return false }, - /* 55 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ + /* 56 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ func() bool { - position831, tokenIndex831 := position, tokenIndex + position834, tokenIndex834 := position, tokenIndex { - position832 := position + position835 := position if buffer[position] != rune('%') { - goto l831 + goto l834 } position++ { - position833, tokenIndex833 := position, tokenIndex + position836, tokenIndex836 := position, tokenIndex if c := buffer[position]; c < rune('c') || c > rune('g') { - goto l834 + goto l837 } position++ - goto l833 - l834: - position, tokenIndex = position833, tokenIndex833 + goto l836 + l837: + position, tokenIndex = position836, tokenIndex836 if buffer[position] != rune('s') { - goto l831 + goto l834 } position++ } - l833: + l836: if buffer[position] != rune('s') { - goto l831 + goto l834 } position++ if buffer[position] != rune(':') { - goto l831 + goto l834 } position++ - add(ruleSegmentRegister, position832) + add(ruleSegmentRegister, position835) } return true - l831: - position, tokenIndex = position831, tokenIndex831 + l834: + position, tokenIndex = position834, tokenIndex834 return false }, } diff --git a/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s index a00a69147c..3b7a1ed156 100644 --- a/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s +++ b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s @@ -65,4 +65,7 @@ bar: cmpq foo@GOTPCREL(%rip), %rax cmpq %rax, foo@GOTPCREL(%rip) + # With -mcmodel=medium, the code may load the address of the GOT directly. + leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx + .comm foobar,64,32 diff --git a/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s index f118e4fa9d..ae47e41177 100644 --- a/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s +++ b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s @@ -268,6 +268,11 @@ bar: popq %rbx leaq 128(%rsp), %rsp + # With -mcmodel=medium, the code may load the address of the GOT directly. +# WAS leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx + leaq .Lboringssl_got_delta(%rip), %rcx + addq .Lboringssl_got_delta(%rip), %rcx + .comm foobar,64,32 .text .loc 1 2 0 @@ -302,6 +307,8 @@ OPENSSL_ia32cap_get: .size OPENSSL_ia32cap_addr_delta, 8 OPENSSL_ia32cap_addr_delta: .quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta +.Lboringssl_got_delta: + .quad _GLOBAL_OFFSET_TABLE_-.Lboringssl_got_delta .type BORINGSSL_bcm_text_hash, @object .size BORINGSSL_bcm_text_hash, 32 BORINGSSL_bcm_text_hash: From 56112cc01f8be29578d52c1c2af6f481c3d77bd2 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Fri, 15 Dec 2023 18:28:54 -0500 Subject: [PATCH 08/15] Skip emitting empty
 blocks in documentation

We sometimes have decl-less comments interspersed in headers. Avoid the
empty patch of blue when they get rendered.

Change-Id: I6668946d07349febd6d28bbe7d4fd8d2426adca9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64927
Auto-Submit: David Benjamin 
Commit-Queue: David Benjamin 
Reviewed-by: Bob Beck 
Commit-Queue: Bob Beck 
---
 util/doc.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/util/doc.go b/util/doc.go
index 4fb73ca0dc..ae5c45df8b 100644
--- a/util/doc.go
+++ b/util/doc.go
@@ -649,7 +649,7 @@ func generate(outPath string, config *Config) (map[string]string, error) {
           {{range .Comment}}
             

{{. | markupPipeWords | newlinesToBR | markupFirstWord | markupRFC}}

{{end}} -
{{.Decl}}
+ {{if .Decl}}
{{.Decl}}
{{end}} {{end}} From 9c821af02f2c38ac9ba58708164ccb6c4d7654bc Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Fri, 15 Dec 2023 18:23:43 -0500 Subject: [PATCH 09/15] Add conf.h to the documentation output We don't want anyone using it, but we probably should render all our documented headers. I've grouped it with the rest of the legacy X.509 stack. Change-Id: If01dfd19c71598f47a40cd334b0fd7ef3e00685d Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64928 Reviewed-by: Bob Beck Commit-Queue: David Benjamin --- include/openssl/conf.h | 5 ++++- util/doc.config | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/openssl/conf.h b/include/openssl/conf.h index c9027c1db5..1e613261b5 100644 --- a/include/openssl/conf.h +++ b/include/openssl/conf.h @@ -67,7 +67,9 @@ extern "C" { #endif -// Config files look like: +// Config files. +// +// This library handles OpenSSL's config files, which look like: // // # Comment // @@ -82,6 +84,7 @@ extern "C" { // untrusted input as a config file risks string injection and denial of service // vulnerabilities. + struct conf_value_st { char *section; char *name; diff --git a/util/doc.config b/util/doc.config index d6ae925850..49b0ec6685 100644 --- a/util/doc.config +++ b/util/doc.config @@ -56,6 +56,7 @@ "Name": "Legacy ASN.1 and X.509 implementation (documentation in progress)", "Headers": [ "include/openssl/asn1.h", + "include/openssl/conf.h", "include/openssl/time.h" ] },{ From faac623b09d6b14fbb06fe5150016de78b359eea Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sat, 16 Dec 2023 21:07:46 -0500 Subject: [PATCH 10/15] Restore the X509 ASN1_ITEM https://boringssl-review.googlesource.com/c/boringssl/+/63946 removed it, but sadly wpa_supplicant depends on it. Change-Id: Ib3aca5269d740457ba83ca529b797bfb4a089763 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64907 Reviewed-by: Bob Beck Auto-Submit: David Benjamin Commit-Queue: Bob Beck --- crypto/asn1/asn1_test.cc | 57 ++++++++++++++++++++++++++++++++++++++++ crypto/x509/x_x509.c | 48 +++++++++++++++++++++++++++++++++ include/openssl/x509.h | 4 +++ 3 files changed, 109 insertions(+) diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc index efeb72816a..196d7b7e52 100644 --- a/crypto/asn1/asn1_test.cc +++ b/crypto/asn1/asn1_test.cc @@ -2834,6 +2834,12 @@ struct EMBED_X509_NAME { STACK_OF(X509_NAME) *seq; }; +struct EMBED_X509 { + X509 *simple; + X509 *opt; + STACK_OF(X509) *seq; +}; + DECLARE_ASN1_FUNCTIONS(EMBED_X509_ALGOR) ASN1_SEQUENCE(EMBED_X509_ALGOR) = { ASN1_SIMPLE(EMBED_X509_ALGOR, simple, X509_ALGOR), @@ -2850,6 +2856,14 @@ ASN1_SEQUENCE(EMBED_X509_NAME) = { } ASN1_SEQUENCE_END(EMBED_X509_NAME) IMPLEMENT_ASN1_FUNCTIONS(EMBED_X509_NAME) +DECLARE_ASN1_FUNCTIONS(EMBED_X509) +ASN1_SEQUENCE(EMBED_X509) = { + ASN1_SIMPLE(EMBED_X509, simple, X509), + ASN1_EXP_OPT(EMBED_X509, opt, X509, 0), + ASN1_IMP_SEQUENCE_OF_OPT(EMBED_X509, seq, X509, 1), +} ASN1_SEQUENCE_END(EMBED_X509) +IMPLEMENT_ASN1_FUNCTIONS(EMBED_X509) + template void TestEmbedType(bssl::Span inp, int (*i2d)(MaybeConstT *, uint8_t **), @@ -2925,6 +2939,49 @@ TEST(ASN1Test, EmbedTypes) { TestEmbedType(kTestName, i2d_X509_NAME, EMBED_X509_NAME_new, EMBED_X509_NAME_free, d2i_EMBED_X509_NAME, i2d_EMBED_X509_NAME, sk_X509_NAME_num, sk_X509_NAME_value); + + static const uint8_t kTestCert[] = { + 0x30, 0x82, 0x01, 0xcf, 0x30, 0x82, 0x01, 0x76, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xd9, 0x4c, 0x04, 0xda, 0x49, 0x7d, 0xbf, 0xeb, + 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01, 0x30, + 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, + 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, + 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x34, 0x30, 0x34, 0x32, 0x33, 0x32, 0x33, 0x32, 0x31, + 0x35, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x33, 0x32, + 0x33, 0x32, 0x31, 0x35, 0x37, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, + 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, + 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xe6, 0x2b, 0x69, 0xe2, + 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e, 0x0d, 0x94, 0x8a, 0x4c, 0xd5, + 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d, 0x46, 0xfb, 0xdd, 0xa9, 0xa9, 0x1e, + 0x9d, 0xdc, 0xba, 0x5a, 0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, 0xf9, + 0xc3, 0xc4, 0xa3, 0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, 0x1a, + 0x1c, 0xf5, 0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, 0xc1, + 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0xab, 0x84, 0xd2, 0xac, 0xab, 0x95, 0xf0, 0x82, 0x4e, + 0x16, 0x78, 0x07, 0x55, 0x57, 0x5f, 0xe4, 0x26, 0x8d, 0x82, 0xd1, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xab, 0x84, 0xd2, 0xac, 0xab, 0x95, 0xf0, 0x82, 0x4e, 0x16, 0x78, 0x07, + 0x55, 0x57, 0x5f, 0xe4, 0x26, 0x8d, 0x82, 0xd1, 0x30, 0x0c, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x09, + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01, 0x03, 0x48, 0x00, + 0x30, 0x45, 0x02, 0x21, 0x00, 0xf2, 0xa0, 0x35, 0x5e, 0x51, 0x3a, 0x36, + 0xc3, 0x82, 0x79, 0x9b, 0xee, 0x27, 0x50, 0x85, 0x8e, 0x70, 0x06, 0x74, + 0x95, 0x57, 0xd2, 0x29, 0x74, 0x00, 0xf4, 0xbe, 0x15, 0x87, 0x5d, 0xc4, + 0x07, 0x02, 0x20, 0x7c, 0x1e, 0x79, 0x14, 0x6a, 0x21, 0x83, 0xf0, 0x7a, + 0x74, 0x68, 0x79, 0x5f, 0x14, 0x99, 0x9a, 0x68, 0xb4, 0xf1, 0xcb, 0x9e, + 0x15, 0x5e, 0xe6, 0x1f, 0x32, 0x52, 0x61, 0x5e, 0x75, 0xc9, 0x14}; + TestEmbedType(kTestCert, i2d_X509, EMBED_X509_new, EMBED_X509_free, + d2i_EMBED_X509, i2d_EMBED_X509, sk_X509_num, sk_X509_value); } #endif // !WINDOWS || !SHARED_LIBRARY diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c index d5b9d4d1e0..1d3ebf6456 100644 --- a/crypto/x509/x_x509.c +++ b/crypto/x509/x_x509.c @@ -299,6 +299,54 @@ int i2d_X509(X509 *x509, uint8_t **outp) { return -1; } +static int x509_new_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { + *pval = (ASN1_VALUE *)X509_new(); + return *pval != NULL; +} + +static void x509_free_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { + X509_free((X509 *)*pval); + *pval = NULL; +} + +static int x509_d2i_cb(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, int opt, ASN1_TLC *ctx) { + if (len < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); + return 0; + } + + CBS cbs; + CBS_init(&cbs, *in, len); + if (opt && !CBS_peek_asn1_tag(&cbs, CBS_ASN1_SEQUENCE)) { + return -1; + } + + X509 *ret = x509_parse(&cbs, NULL); + if (ret == NULL) { + return 0; + } + + *in = CBS_data(&cbs); + X509_free((X509 *)*pval); + *pval = (ASN1_VALUE *)ret; + return 1; +} + +static int x509_i2d_cb(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it) { + return i2d_X509((X509 *)*pval, out); +} + +static const ASN1_EXTERN_FUNCS x509_extern_funcs = { + x509_new_cb, + x509_free_cb, + x509_d2i_cb, + x509_i2d_cb, +}; + +IMPLEMENT_EXTERN_ASN1(X509, V_ASN1_SEQUENCE, x509_extern_funcs) + X509 *X509_dup(X509 *x509) { uint8_t *der = NULL; int len = i2d_X509(x509, &der); diff --git a/include/openssl/x509.h b/include/openssl/x509.h index b27c97d331..6fb07aa624 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -123,6 +123,10 @@ extern "C" { DEFINE_STACK_OF(X509) +// X509 is an |ASN1_ITEM| whose ASN.1 type is X.509 Certificate (RFC 5280) and C +// type is |X509*|. +DECLARE_ASN1_ITEM(X509) + // X509_up_ref adds one to the reference count of |x509| and returns one. OPENSSL_EXPORT int X509_up_ref(X509 *x509); From 3d5a848d2fc081872123ba3d6e2b0f653281aa13 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sat, 16 Dec 2023 02:43:26 -0500 Subject: [PATCH 11/15] Give time.h a title and move to low-level infra group Change-Id: I4cb50bda726fcc0f22fcb53dca92cf297aeea169 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64929 Commit-Queue: David Benjamin Reviewed-by: Bob Beck --- include/openssl/time.h | 4 ++++ util/doc.config | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/openssl/time.h b/include/openssl/time.h index 723ce10a03..50db22d324 100644 --- a/include/openssl/time.h +++ b/include/openssl/time.h @@ -23,6 +23,10 @@ extern "C" { #endif + +// Time functions. + + // OPENSSL_posix_to_tm converts a int64_t POSIX time value in |time|, which must // be in the range of year 0000 to 9999, to a broken out time value in |tm|. It // returns one on success and zero on error. diff --git a/util/doc.config b/util/doc.config index 49b0ec6685..29bba6701b 100644 --- a/util/doc.config +++ b/util/doc.config @@ -15,7 +15,8 @@ "include/openssl/obj.h", "include/openssl/pool.h", "include/openssl/rand.h", - "include/openssl/stack.h" + "include/openssl/stack.h", + "include/openssl/time.h" ] },{ "Name": "Low-level crypto primitives", @@ -56,8 +57,7 @@ "Name": "Legacy ASN.1 and X.509 implementation (documentation in progress)", "Headers": [ "include/openssl/asn1.h", - "include/openssl/conf.h", - "include/openssl/time.h" + "include/openssl/conf.h" ] },{ "Name": "SSL implementation", From 3599db2e40df28f0f1335f5f00dd2bf0e5d2684a Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Tue, 5 Dec 2023 19:15:30 -0800 Subject: [PATCH 12/15] sha: Add SSSE3 check to SHAEXT SHA-256 implementation. The implementation does use SSSE3 (palignr, pshufb). Change-Id: I86a44c1dc505b27b87fdc3cc7f6e8115abb3dcc9 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64567 Reviewed-by: David Benjamin Reviewed-by: Bob Beck Commit-Queue: Bob Beck --- crypto/fipsmodule/sha/internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/fipsmodule/sha/internal.h b/crypto/fipsmodule/sha/internal.h index b55ea8e5e8..0c05d73a14 100644 --- a/crypto/fipsmodule/sha/internal.h +++ b/crypto/fipsmodule/sha/internal.h @@ -126,7 +126,8 @@ void sha1_block_data_order_ssse3(uint32_t *state, const uint8_t *data, #define SHA256_ASM_HW OPENSSL_INLINE int sha256_hw_capable(void) { - return CRYPTO_is_x86_SHA_capable(); + // Note that the original assembly did not check SSSE3. + return CRYPTO_is_x86_SHA_capable() && CRYPTO_is_SSSE3_capable(); } #define SHA256_ASM_AVX From a942d572073e98944200e154597442796fdb13de Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Thu, 14 Dec 2023 14:27:27 -0500 Subject: [PATCH 13/15] Support lists and code blocks in doc.go Our documentation comments already include examples of code blocks and lists, they just don't get rendered right. We also have things that were trying to be lists but aren't. Go ahead and add support for it, and fix the handful of list-like things that didn't get rendered as lists. I took inspiration from CommonMark (https://spec.commonmark.org/0.30/) to resolve questions such as whether blank lines are needed between lists, etc., but this does not support any kind of nesting and is still far from a CommonMark parser. Aligning with CommonMark leaves the door open to pulling in a real Markdown parser if we start to need too many features. I've also borrowed the "block" terminology from CommonMark. One ambiguity of note: whether lists may interrupt paragraphs (i.e. without a blank line in between) is a little thorny. If we say no, this doesn't work: Callers should heed the following warnings: 1) Don't use the function 2) Seriously, don't use this function 3) This function is a bad idea But if we say yes, this renders wrong: This function parses an X.509 certificate (see RFC 5280) into an X509 object. We have examples of both in existing comments, though we could easily add a blank line in the former or rewrap the latter. CommonMark has a discussion on this in https://spec.commonmark.org/0.30/#lists CommonMark says yes, but with a hack that only lists starting with 1 can interrupt paragraphs. Since we're unlikely to cite RFC 1, I've matched for now, but we may want to revisit this if it gets to be a pain. I could imagine this becoming a problem: This function, on success, does some stuff and returns 1. Otherwise, it returns 0. But that looks a little weird and we usually spell out "one" and "zero". I printed all the lists we detected in existing comments, and this has not happened so far. I've also required fewer spaces than CommonMark to trigger a code block. CommonMark uses four, but four spaces plus a leading "//" and a " " is quite a lot. For now I'm not stripping the spaces after the comment marker at comment extraction time and then requiring three spaces, so two spaces relative to normal text. This is mostly to match what we've currently been doing, but we can always change it and our comments later. Change-Id: Ic61a8e93491ed96aba755aec2a5f32914bdc42ae Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64930 Reviewed-by: Bob Beck Commit-Queue: David Benjamin --- include/openssl/bn.h | 6 +- include/openssl/curve25519.h | 4 +- include/openssl/ec.h | 8 +- include/openssl/ssl.h | 30 ++-- util/doc.css | 11 +- util/doc.go | 283 +++++++++++++++++++++++++++-------- 6 files changed, 249 insertions(+), 93 deletions(-) diff --git a/include/openssl/bn.h b/include/openssl/bn.h index 92ff7a140a..fb6e96259a 100644 --- a/include/openssl/bn.h +++ b/include/openssl/bn.h @@ -666,11 +666,11 @@ OPENSSL_EXPORT int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); // The callback receives the address of that |BN_GENCB| structure as its last // argument and the user is free to put an arbitrary pointer in |arg|. The other // arguments are set as follows: -// event=BN_GENCB_GENERATED, n=i: after generating the i'th possible prime +// - event=BN_GENCB_GENERATED, n=i: after generating the i'th possible prime // number. -// event=BN_GENCB_PRIME_TEST, n=-1: when finished trial division primality +// - event=BN_GENCB_PRIME_TEST, n=-1: when finished trial division primality // checks. -// event=BN_GENCB_PRIME_TEST, n=i: when the i'th primality test has finished. +// - event=BN_GENCB_PRIME_TEST, n=i: when the i'th primality test has finished. // // The callback can return zero to abort the generation progress or one to // allow it to continue. diff --git a/include/openssl/curve25519.h b/include/openssl/curve25519.h index a455389c1a..b87df52789 100644 --- a/include/openssl/curve25519.h +++ b/include/openssl/curve25519.h @@ -161,10 +161,10 @@ OPENSSL_EXPORT int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, // |*out_key_len| to the number of bytes written. // // The resulting keying material is suitable for: -// a) Using directly in a key-confirmation step: i.e. each side could +// - Using directly in a key-confirmation step: i.e. each side could // transmit a hash of their role, a channel-binding value and the key // material to prove to the other side that they know the shared key. -// b) Using as input keying material to HKDF to generate a variety of subkeys +// - Using as input keying material to HKDF to generate a variety of subkeys // for encryption etc. // // If |max_out_key_key| is smaller than the amount of key material generated diff --git a/include/openssl/ec.h b/include/openssl/ec.h index 2d005af6c3..e8a2db0a07 100644 --- a/include/openssl/ec.h +++ b/include/openssl/ec.h @@ -121,10 +121,10 @@ OPENSSL_EXPORT const EC_GROUP *EC_group_p521(void); // calling |EC_GROUP_free| is optional. // // The supported NIDs are: -// NID_secp224r1 (P-224), -// NID_X9_62_prime256v1 (P-256), -// NID_secp384r1 (P-384), -// NID_secp521r1 (P-521) +// - |NID_secp224r1| (P-224) +// - |NID_X9_62_prime256v1| (P-256) +// - |NID_secp384r1| (P-384) +// - |NID_secp521r1| (P-521) // // Calling this function causes all four curves to be linked into the binary. // Prefer calling |EC_group_*| to allow the static linker to drop unused curves. diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index ab6225e9e6..ff4d4c91c3 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1461,19 +1461,19 @@ OPENSSL_EXPORT size_t SSL_get_all_standard_cipher_names(const char **out, // // Available opcodes are: // -// The empty opcode enables and appends all matching disabled ciphers to the +// - The empty opcode enables and appends all matching disabled ciphers to the // end of the enabled list. The newly appended ciphers are ordered relative to // each other matching their order in the disabled list. // -// |-| disables all matching enabled ciphers and prepends them to the disabled +// - |-| disables all matching enabled ciphers and prepends them to the disabled // list, with relative order from the enabled list preserved. This means the // most recently disabled ciphers get highest preference relative to other // disabled ciphers if re-enabled. // -// |+| moves all matching enabled ciphers to the end of the enabled list, with +// - |+| moves all matching enabled ciphers to the end of the enabled list, with // relative order preserved. // -// |!| deletes all matching ciphers, enabled or not, from either list. Deleted +// - |!| deletes all matching ciphers, enabled or not, from either list. Deleted // ciphers will not matched by future operations. // // A selector may be a specific cipher (using either the standard or OpenSSL @@ -1483,36 +1483,36 @@ OPENSSL_EXPORT size_t SSL_get_all_standard_cipher_names(const char **out, // // Available cipher rules are: // -// |ALL| matches all ciphers, except for deprecated ciphers which must be +// - |ALL| matches all ciphers, except for deprecated ciphers which must be // named explicitly. // -// |kRSA|, |kDHE|, |kECDHE|, and |kPSK| match ciphers using plain RSA, DHE, +// - |kRSA|, |kDHE|, |kECDHE|, and |kPSK| match ciphers using plain RSA, DHE, // ECDHE, and plain PSK key exchanges, respectively. Note that ECDHE_PSK is // matched by |kECDHE| and not |kPSK|. // -// |aRSA|, |aECDSA|, and |aPSK| match ciphers authenticated by RSA, ECDSA, and +// - |aRSA|, |aECDSA|, and |aPSK| match ciphers authenticated by RSA, ECDSA, and // a pre-shared key, respectively. // -// |RSA|, |DHE|, |ECDHE|, |PSK|, |ECDSA|, and |PSK| are aliases for the +// - |RSA|, |DHE|, |ECDHE|, |PSK|, |ECDSA|, and |PSK| are aliases for the // corresponding |k*| or |a*| cipher rule. |RSA| is an alias for |kRSA|, not // |aRSA|. // -// |3DES|, |AES128|, |AES256|, |AES|, |AESGCM|, |CHACHA20| match ciphers +// - |3DES|, |AES128|, |AES256|, |AES|, |AESGCM|, |CHACHA20| match ciphers // whose bulk cipher use the corresponding encryption scheme. Note that // |AES|, |AES128|, and |AES256| match both CBC and GCM ciphers. // -// |SHA1|, and its alias |SHA|, match legacy cipher suites using HMAC-SHA1. +// - |SHA1|, and its alias |SHA|, match legacy cipher suites using HMAC-SHA1. // // Deprecated cipher rules: // -// |kEDH|, |EDH|, |kEECDH|, and |EECDH| are legacy aliases for |kDHE|, |DHE|, +// - |kEDH|, |EDH|, |kEECDH|, and |EECDH| are legacy aliases for |kDHE|, |DHE|, // |kECDHE|, and |ECDHE|, respectively. // -// |HIGH| is an alias for |ALL|. +// - |HIGH| is an alias for |ALL|. // -// |FIPS| is an alias for |HIGH|. +// - |FIPS| is an alias for |HIGH|. // -// |SSLv3| and |TLSv1| match ciphers available in TLS 1.1 or earlier. +// - |SSLv3| and |TLSv1| match ciphers available in TLS 1.1 or earlier. // |TLSv1_2| matches ciphers new in TLS 1.2. This is confusing and should not // be used. // @@ -5319,7 +5319,7 @@ enum ssl_compliance_policy_t BORINGSSL_ENUM_INT { // doesn't undo other policies it's an error to try and set it. ssl_compliance_policy_none, - // ssl_policy_fips_202205 configures a TLS connection to use: + // ssl_compliance_policy_fips_202205 configures a TLS connection to use: // * TLS 1.2 or 1.3 // * For TLS 1.2, only ECDHE_[RSA|ECDSA]_WITH_AES_*_GCM_SHA*. // * For TLS 1.3, only AES-GCM diff --git a/util/doc.css b/util/doc.css index a868e44445..f176f259b7 100644 --- a/util/doc.css +++ b/util/doc.css @@ -16,12 +16,13 @@ div.title { margin-bottom: 2em; } -ol { +ol.toc { list-style: none; + padding-left: 0; margin-bottom: 4em; } -li a { +ol.toc li a { color: black; } @@ -49,12 +50,16 @@ div.decl p:first-child .first-word { font-size: 1.5em; } -.section pre { +pre.code { background-color: #b2c9db; padding: 5px; border-radius: 5px; } +.comment pre { + margin-left: 2em; +} + td { padding: 2px; } diff --git a/util/doc.go b/util/doc.go index ae5c45df8b..21d9dab1fc 100644 --- a/util/doc.go +++ b/util/doc.go @@ -18,7 +18,9 @@ import ( "os" "path/filepath" "regexp" + "strconv" "strings" + "unicode" ) // Config describes the structure of the config JSON file. @@ -41,7 +43,7 @@ type HeaderFile struct { Name string // Preamble contains a comment for the file as a whole. Each string // is a separate paragraph. - Preamble []string + Preamble []CommentBlock Sections []HeaderSection // AllDecls maps all decls to their URL fragments. AllDecls map[string]string @@ -49,7 +51,7 @@ type HeaderFile struct { type HeaderSection struct { // Preamble contains a comment for a group of functions. - Preamble []string + Preamble []CommentBlock Decls []HeaderDecl // Anchor, if non-empty, is the URL fragment to use in anchor tags. Anchor string @@ -62,7 +64,7 @@ type HeaderDecl struct { // Comment contains a comment for a specific function. Each string is a // paragraph. Some paragraph may contain \n runes to indicate that they // are preformatted. - Comment []string + Comment []CommentBlock // Name contains the name of the function, if it could be extracted. Name string // Decl contains the preformatted C declaration itself. @@ -71,6 +73,20 @@ type HeaderDecl struct { Anchor string } +type CommentBlockType int + +const ( + CommentParagraph CommentBlockType = iota + CommentOrderedListItem + CommentBulletListItem + CommentCode +) + +type CommentBlock struct { + Type CommentBlockType + Paragraph string +} + const ( cppGuard = "#if defined(__cplusplus)" commentStart = "/* " @@ -95,7 +111,7 @@ func commentSubject(line string) string { return line[:idx] } -func extractComment(lines []string, lineNo int) (comment []string, rest []string, restLineNo int, err error) { +func extractCommentLines(lines []string, lineNo int) (comment []string, rest []string, restLineNo int, err error) { if len(lines) == 0 { return nil, lines, lineNo, nil } @@ -109,22 +125,19 @@ func extractComment(lines []string, lineNo int) (comment []string, rest []string } else if !strings.HasPrefix(rest[0], lineComment) { panic("extractComment called on non-comment") } - commentParagraph := rest[0][len(commentStart):] + comment = []string{rest[0][len(commentStart):]} rest = rest[1:] restLineNo++ for len(rest) > 0 { if isBlock { - i := strings.Index(commentParagraph, commentEnd) - if i >= 0 { - if i != len(commentParagraph)-len(commentEnd) { + last := &comment[len(comment)-1] + if i := strings.Index(*last, commentEnd); i >= 0 { + if i != len(*last)-len(commentEnd) { err = fmt.Errorf("garbage after comment end on line %d", restLineNo) return } - commentParagraph = commentParagraph[:i] - if len(commentParagraph) > 0 { - comment = append(comment, commentParagraph) - } + *last = (*last)[:i] return } } @@ -136,36 +149,136 @@ func extractComment(lines []string, lineNo int) (comment []string, rest []string return } } else if !strings.HasPrefix(line, "//") { - if len(commentParagraph) > 0 { - comment = append(comment, commentParagraph) - } return } - if len(line) == 2 || !isBlock || line[2] != '/' { - line = line[2:] + comment = append(comment, line[2:]) + rest = rest[1:] + restLineNo++ + } + + err = errors.New("hit EOF in comment") + return +} + +func removeBulletListMarker(line string) (string, bool) { + orig := line + line = strings.TrimSpace(line) + if !strings.HasPrefix(line, "+ ") && !strings.HasPrefix(line, "- ") && !strings.HasPrefix(line, "* ") { + return orig, false + } + return line[2:], true +} + +func removeOrderedListMarker(line string) (rest string, num int, ok bool) { + orig := line + line = strings.TrimSpace(line) + if len(line) == 0 || !unicode.IsDigit(rune(line[0])) { + return orig, -1, false + } + + l := 0 + for l < len(line) && unicode.IsDigit(rune(line[l])) { + l++ + } + num, err := strconv.Atoi(line[:l]) + if err != nil { + return orig, -1, false + } + + line = line[l:] + if line, ok := strings.CutPrefix(line, ". "); ok { + return line, num, true + } + if line, ok := strings.CutPrefix(line, ") "); ok { + return line, num, true + } + + return orig, -1, false +} + +func removeCodeIndent(line string) (string, bool) { + return strings.CutPrefix(line, " ") +} + +func extractComment(lines []string, lineNo int) (comment []CommentBlock, rest []string, restLineNo int, err error) { + commentLines, rest, restLineNo, err := extractCommentLines(lines, lineNo) + if err != nil { + return + } + + // This syntax and parsing algorithm is loosely inspired by CommonMark, + // but reduced to a small subset with no nesting. Blocks being open vs. + // closed can be tracked implicitly. We're also much slopplier about how + // indentation. Additionally, rather than grouping list items into + // lists, our parser just emits a list items, which are grouped later at + // rendering time. + // + // If we later need more features, such as nested lists, this can evolve + // into a more complex implementation. + var numBlankLines int + for _, line := range commentLines { + // Defer blank lines until we know the next element. + if len(strings.TrimSpace(line)) == 0 { + numBlankLines++ + continue } - if strings.HasPrefix(line, " ") { - /* Identing the lines of a paragraph marks them as - * preformatted. */ - if len(commentParagraph) > 0 { - commentParagraph += "\n" + + blankLinesSkipped := numBlankLines + numBlankLines = 0 + + // Attempt to continue the previous block. + if len(comment) > 0 { + last := &comment[len(comment)-1] + if last.Type == CommentCode { + l, ok := removeCodeIndent(line) + if ok { + for i := 0; i < blankLinesSkipped; i++ { + last.Paragraph += "\n" + } + last.Paragraph += l + "\n" + continue + } + } else if blankLinesSkipped == 0 { + _, isBulletList := removeBulletListMarker(line) + _, num, isOrderedList := removeOrderedListMarker(line) + if isOrderedList && last.Type == CommentParagraph && num != 1 { + // A list item can only interrupt a paragraph if the number is one. + // See the discussion in https://spec.commonmark.org/0.30/#lists. + // This avoids wrapping like "(See RFC\n5280)" turning into a list. + isOrderedList = false + } + if !isBulletList && !isOrderedList { + // This is a continuation line of the previous paragraph. + last.Paragraph += " " + strings.TrimSpace(line) + continue + } } - line = line[3:] } - if len(line) > 0 { - commentParagraph = commentParagraph + line - if len(commentParagraph) > 0 && commentParagraph[0] == ' ' { - commentParagraph = commentParagraph[1:] - } + + // Make a new block. + if line, ok := removeBulletListMarker(line); ok { + comment = append(comment, CommentBlock{ + Type: CommentBulletListItem, + Paragraph: strings.TrimSpace(line), + }) + } else if line, _, ok := removeOrderedListMarker(line); ok { + comment = append(comment, CommentBlock{ + Type: CommentOrderedListItem, + Paragraph: strings.TrimSpace(line), + }) + } else if line, ok := removeCodeIndent(line); ok { + comment = append(comment, CommentBlock{ + Type: CommentCode, + Paragraph: line + "\n", + }) } else { - comment = append(comment, commentParagraph) - commentParagraph = "" + comment = append(comment, CommentBlock{ + Type: CommentParagraph, + Paragraph: strings.TrimSpace(line), + }) } - rest = rest[1:] - restLineNo++ } - err = errors.New("hit EOF in comment") return } @@ -390,7 +503,8 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) { return nil, err } if len(rest) > 0 && len(rest[0]) == 0 { - anchor := sanitizeAnchor(firstSentence(comment)) + heading := firstSentence(comment) + anchor := sanitizeAnchor(heading) if len(anchor) > 0 { if _, ok := allAnchors[anchor]; ok { return nil, fmt.Errorf("duplicate anchor: %s", anchor) @@ -399,7 +513,7 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) { } section.Preamble = comment - section.IsPrivate = len(comment) > 0 && isPrivateSection(comment[0]) + section.IsPrivate = isPrivateSection(heading) section.Anchor = anchor lines = rest[1:] lineNo = restLineNo + 1 @@ -417,7 +531,7 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) { return nil, fmt.Errorf("hit ending C++ guard while in section on line %d (possibly missing two empty lines ahead of guard?)", lineNo) } - var comment []string + var comment []CommentBlock var decl string if isComment(line) { comment, lines, lineNo, err = extractComment(lines, lineNo) @@ -444,10 +558,11 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) { // with the name of the thing that they are // commenting on. We make an exception here for // collective comments. + sentence := firstSentence(comment) if len(comment) > 0 && len(name) > 0 && - !isCollectiveComment(comment[0]) { - subject := commentSubject(comment[0]) + !isCollectiveComment(sentence) { + subject := commentSubject(sentence) ok := subject == name if l := len(subject); l > 0 && subject[l-1] == '*' { // Groups of names, notably #defines, are often @@ -486,11 +601,11 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) { return header, nil } -func firstSentence(paragraphs []string) string { - if len(paragraphs) == 0 { +func firstSentence(comment []CommentBlock) string { + if len(comment) == 0 { return "" } - s := paragraphs[0] + s := comment[0].Paragraph i := strings.Index(s, ". ") if i >= 0 { return s[:i] @@ -501,6 +616,61 @@ func firstSentence(paragraphs []string) string { return s } +func markupComment(allDecls map[string]string, comment []CommentBlock) template.HTML { + var b strings.Builder + lastType := CommentParagraph + closeList := func() { + if lastType == CommentOrderedListItem { + b.WriteString("") + } else if lastType == CommentBulletListItem { + b.WriteString("") + } + } + + for _, block := range comment { + // Group consecutive list items of the same type into a list. + if block.Type != lastType { + closeList() + if block.Type == CommentOrderedListItem { + b.WriteString("
    ") + } else if block.Type == CommentBulletListItem { + b.WriteString("
      ") + } + } + lastType = block.Type + + switch block.Type { + case CommentParagraph: + b.WriteString("

      ") + b.WriteString(string(markupParagraph(allDecls, block.Paragraph))) + b.WriteString("

      ") + case CommentOrderedListItem, CommentBulletListItem: + b.WriteString("
    • ") + b.WriteString(string(markupParagraph(allDecls, block.Paragraph))) + b.WriteString("
    • ") + case CommentCode: + b.WriteString("
      ")
      +			b.WriteString(block.Paragraph)
      +			b.WriteString("
      ") + default: + panic(block.Type) + } + } + + closeList() + return template.HTML(b.String()) +} + +func markupParagraph(allDecls map[string]string, s string) template.HTML { + // TODO(davidben): Ideally the inline transforms would be unified into + // one pass, so that the HTML output of one pass does not interfere with + // the next. + ret := markupPipeWords(allDecls, s, true /* linkDecls */) + ret = markupFirstWord(ret) + ret = markupRFC(ret) + return ret +} + // markupPipeWords converts |s| into an HTML string, safe to be included outside // a tag, while also marking up words surrounded by |. func markupPipeWords(allDecls map[string]string, s string, linkDecls bool) template.HTML { @@ -585,27 +755,14 @@ func markupRFC(html template.HTML) template.HTML { return template.HTML(b.String()) } -func newlinesToBR(html template.HTML) template.HTML { - s := string(html) - if !strings.Contains(s, "\n") { - return html - } - s = strings.Replace(s, "\n", "
      ", -1) - s = strings.Replace(s, " ", " ", -1) - return template.HTML(s) -} - func generate(outPath string, config *Config) (map[string]string, error) { allDecls := make(map[string]string) headerTmpl := template.New("headerTmpl") headerTmpl.Funcs(template.FuncMap{ "firstSentence": firstSentence, - "markupPipeWords": func(s string) template.HTML { return markupPipeWords(allDecls, s, true /* linkDecls */) }, "markupPipeWordsNoLink": func(s string) template.HTML { return markupPipeWords(allDecls, s, false /* linkDecls */) }, - "markupFirstWord": markupFirstWord, - "markupRFC": markupRFC, - "newlinesToBR": newlinesToBR, + "markupComment": func(c []CommentBlock) template.HTML { return markupComment(allDecls, c) }, }) headerTmpl, err := headerTmpl.Parse(` @@ -622,9 +779,9 @@ func generate(outPath string, config *Config) (map[string]string, error) { All headers - {{range .Preamble}}

      {{. | markupPipeWords | markupRFC}}

      {{end}} + {{if .Preamble}}
      {{.Preamble | markupComment}}
      {{end}} -
        +
          {{range .Sections}} {{if not .IsPrivate}} {{if .Anchor}}
        1. {{.Preamble | firstSentence | markupPipeWordsNoLink}}
        2. {{end}} @@ -638,18 +795,12 @@ func generate(outPath string, config *Config) (map[string]string, error) { {{range .Sections}} {{if not .IsPrivate}}
          - {{if .Preamble}} -
          - {{range .Preamble}}

          {{. | markupPipeWords | markupRFC}}

          {{end}} -
          - {{end}} + {{if .Preamble}}
          {{.Preamble | markupComment}}
          {{end}} {{range .Decls}}
          - {{range .Comment}} -

          {{. | markupPipeWords | newlinesToBR | markupFirstWord | markupRFC}}

          - {{end}} - {{if .Decl}}
          {{.Decl}}
          {{end}} + {{if .Comment}}
          {{.Comment | markupComment}}
          {{end}} + {{if .Decl}}
          {{.Decl}}
          {{end}}
          {{end}}
          From 89dd8d9eb4eabb4fbe20eac977f4827065bc493b Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sat, 16 Dec 2023 10:47:35 -0500 Subject: [PATCH 14/15] Give WARNING paragraphs a splash of color I'm not sure if this is necessary. I was playing around and this didn't look terrible. Though it will probably turn x509.h into a sea of yellow when it's ready to be rendered. Change-Id: I34b26aad8a779a3fde761558d15b64c79159892a Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64931 Reviewed-by: Bob Beck Commit-Queue: David Benjamin --- util/doc.css | 10 ++++++++++ util/doc.go | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/util/doc.css b/util/doc.css index f176f259b7..05d90bec6b 100644 --- a/util/doc.css +++ b/util/doc.css @@ -56,6 +56,16 @@ pre.code { border-radius: 5px; } +p.warning { + background-color: #fef5d3; + padding: 5px; + border-radius: 5px; +} + +p.warning .first-word { + font-weight: bold; +} + .comment pre { margin-left: 2em; } diff --git a/util/doc.go b/util/doc.go index 21d9dab1fc..1de7064bba 100644 --- a/util/doc.go +++ b/util/doc.go @@ -641,7 +641,11 @@ func markupComment(allDecls map[string]string, comment []CommentBlock) template. switch block.Type { case CommentParagraph: - b.WriteString("

          ") + if strings.HasPrefix(block.Paragraph, "WARNING:") { + b.WriteString("

          ") + } else { + b.WriteString("

          ") + } b.WriteString(string(markupParagraph(allDecls, block.Paragraph))) b.WriteString("

          ") case CommentOrderedListItem, CommentBulletListItem: From 538b2a6cf0497cf8bb61ae726a484a3d7a34e54e Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 18 Dec 2023 13:33:36 -0500 Subject: [PATCH 15/15] Restore the X509_EXTENSION ASN1_ITEM too wpa_supplicant also depends on that one. Change-Id: I6abb505d076eb258e6b8d68be42e624f4aedc725 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64947 Auto-Submit: David Benjamin Commit-Queue: Bob Beck Reviewed-by: Bob Beck --- crypto/asn1/asn1_test.cc | 22 ++++++++++++++++++++++ include/openssl/x509.h | 4 ++++ 2 files changed, 26 insertions(+) diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc index 196d7b7e52..c2e5f5b4d6 100644 --- a/crypto/asn1/asn1_test.cc +++ b/crypto/asn1/asn1_test.cc @@ -2828,6 +2828,12 @@ struct EMBED_X509_ALGOR { STACK_OF(X509_ALGOR) *seq; }; +struct EMBED_X509_EXTENSION { + X509_EXTENSION *simple; + X509_EXTENSION *opt; + STACK_OF(X509_EXTENSION) *seq; +}; + struct EMBED_X509_NAME { X509_NAME *simple; X509_NAME *opt; @@ -2856,6 +2862,14 @@ ASN1_SEQUENCE(EMBED_X509_NAME) = { } ASN1_SEQUENCE_END(EMBED_X509_NAME) IMPLEMENT_ASN1_FUNCTIONS(EMBED_X509_NAME) +DECLARE_ASN1_FUNCTIONS(EMBED_X509_EXTENSION) +ASN1_SEQUENCE(EMBED_X509_EXTENSION) = { + ASN1_SIMPLE(EMBED_X509_EXTENSION, simple, X509_EXTENSION), + ASN1_EXP_OPT(EMBED_X509_EXTENSION, opt, X509_EXTENSION, 0), + ASN1_IMP_SEQUENCE_OF_OPT(EMBED_X509_EXTENSION, seq, X509_EXTENSION, 1), +} ASN1_SEQUENCE_END(EMBED_X509_EXTENSION) +IMPLEMENT_ASN1_FUNCTIONS(EMBED_X509_EXTENSION) + DECLARE_ASN1_FUNCTIONS(EMBED_X509) ASN1_SEQUENCE(EMBED_X509) = { ASN1_SIMPLE(EMBED_X509, simple, X509), @@ -2940,6 +2954,14 @@ TEST(ASN1Test, EmbedTypes) { EMBED_X509_NAME_free, d2i_EMBED_X509_NAME, i2d_EMBED_X509_NAME, sk_X509_NAME_num, sk_X509_NAME_value); + static const uint8_t kTestExtension[] = {0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xf}; + TestEmbedType(kTestExtension, i2d_X509_EXTENSION, EMBED_X509_EXTENSION_new, + EMBED_X509_EXTENSION_free, d2i_EMBED_X509_EXTENSION, + i2d_EMBED_X509_EXTENSION, sk_X509_EXTENSION_num, + sk_X509_EXTENSION_value); + static const uint8_t kTestCert[] = { 0x30, 0x82, 0x01, 0xcf, 0x30, 0x82, 0x01, 0x76, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xd9, 0x4c, 0x04, 0xda, 0x49, 0x7d, 0xbf, 0xeb, diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 6fb07aa624..b3a988b1cc 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -1630,6 +1630,10 @@ OPENSSL_EXPORT const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key( // determined by the extension type. This library represents extensions with the // |X509_EXTENSION| type. +// X509_EXTENSION is an |ASN1_ITEM| whose ASN.1 type is X.509 Extension (RFC +// 5280) and C type is |X509_EXTENSION*|. +DECLARE_ASN1_ITEM(X509_EXTENSION) + // X509_EXTENSION_new returns a newly-allocated, empty |X509_EXTENSION| object // or NULL on error. OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_new(void);