From 13f53620998ed8b906bffbb2a999293a1c311d1e Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Sat, 13 Jan 2024 14:01:32 +0000 Subject: [PATCH 1/5] delocate: update to handle SVE2 Aarch64's SVE2 extension adds more syntax forms for registers, and a new "tweak" pattern that means "multiply offset by the hardware's vector length". This change tweaks delocate so that it can pass these forms. See https://developer.arm.com/documentation/102340/0100/SVE2-architecture-fundamentals Change-Id: I9a736dcf0b57d36d5e08a53e073da7fe3c62dea2 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65349 Commit-Queue: David Benjamin Reviewed-by: David Benjamin Auto-Submit: Adam Langley (cherry picked from commit 672efb1f8ee029762e29ff16811b68a071a0528e) AWS-LC: Merged in delocator instructions for SVE2 Generated new delecote.peg.go file --- util/fipstools/delocate/delocate.peg | 9 +- util/fipstools/delocate/delocate.peg.go | 2835 +++++++++-------- .../delocate/testdata/aarch64-Basic/in.s | 4 + .../delocate/testdata/aarch64-Basic/out.s | 4 + 4 files changed, 1516 insertions(+), 1336 deletions(-) diff --git a/util/fipstools/delocate/delocate.peg b/util/fipstools/delocate/delocate.peg index f57380f0b3..45984d67d1 100644 --- a/util/fipstools/delocate/delocate.peg +++ b/util/fipstools/delocate/delocate.peg @@ -86,9 +86,12 @@ RegisterOrConstant <- (('%'[[A-Z]][[A-Z0-9]]*) / ('$(-' [0-9]+ ')') / ARMRegister) ![fb:(+\-] -ARMConstantTweak <- (([us] "xt" [xwhb]) / "lsl" / "lsr" / "ror" / "asr") (WS '#'? Offset)? -ARMRegister <- "sp" / ([xwdqshb] [0-9] [0-9]?) / "xzr" / "wzr" / "NZCV" / ARMVectorRegister / ('{' WS? ARMVectorRegister WS? ([,\-] WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')? ) -ARMVectorRegister <- "v" [0-9] [0-9]? ('.' [0-9]* [bsdhq] ('[' [0-9] [0-9]? ']')? )? +ARMConstantTweak <- ((([us] "xt" [xwhb]) / "lsl" / "lsr" / "ror" / "asr") (WS '#'? Offset)?)/ + "mul vl" # multiply offset by the hardware's vector length +ARMRegister <- "sp" / ([xwdqshb] [0-9] [0-9]?) / "xzr" / "wzr" / "NZCV" / ARMVectorRegister / SVE2PredicateRegister / + ('{' WS? ARMVectorRegister WS? ([,\-] WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')? ) +ARMVectorRegister <- [vz] [0-9] [0-9]? ('.' [0-9]* [bsdhq] ('[' [0-9] [0-9]? ']')? )? +SVE2PredicateRegister <- "p" [0-9] [0-9]? "/" [mMzZ] # Compilers only output a very limited number of expression forms. Rather than # implement a full expression parser, this enumerate those forms plus a few # that appear in our hand-written assembly. diff --git a/util/fipstools/delocate/delocate.peg.go b/util/fipstools/delocate/delocate.peg.go index 9d07100bb6..f20936ea08 100644 --- a/util/fipstools/delocate/delocate.peg.go +++ b/util/fipstools/delocate/delocate.peg.go @@ -1,6 +1,6 @@ package main -// Code generated by /var/folders/1x/_423tbkn7k7c4jxmd4tnnj_r0000gr/T/go-build804476870/b001/exe/peg delocate.peg DO NOT EDIT. +// Code generated by /Users/smittals/go/bin/peg /Users/smittals/Desktop/aws-lc/util/fipstools/delocate/delocate.peg DO NOT EDIT. import ( "fmt" @@ -64,6 +64,7 @@ const ( ruleARMConstantTweak ruleARMRegister ruleARMVectorRegister + ruleSVE2PredicateRegister ruleMemoryRef ruleSymbolRef ruleLow12BitsSymbolRef @@ -126,6 +127,7 @@ var rul3s = [...]string{ "ARMConstantTweak", "ARMRegister", "ARMVectorRegister", + "SVE2PredicateRegister", "MemoryRef", "SymbolRef", "Low12BitsSymbolRef", @@ -252,7 +254,7 @@ func (t *tokens32) Tokens() []token32 { type Asm struct { Buffer string buffer []rune - rules [59]func() bool + rules [60]func() bool parse func(rule ...int) error reset func() Pretty bool @@ -5067,7 +5069,7 @@ func (p *Asm) Init(options ...func(*Asm) error) error { position, tokenIndex = position551, tokenIndex551 return false }, - /* 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)?)> */ + /* 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)?) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' ('v' / 'V') ('l' / 'L')))> */ func() bool { position631, tokenIndex631 := position, tokenIndex { @@ -5076,296 +5078,382 @@ func (p *Asm) Init(options ...func(*Asm) error) error { position633, tokenIndex633 := position, tokenIndex { position635, tokenIndex635 := position, tokenIndex - if buffer[position] != rune('u') { - goto l636 - } - position++ - goto l635 - l636: - position, tokenIndex = position635, tokenIndex635 - if buffer[position] != rune('s') { - goto l634 - } - position++ - } - l635: - { - position637, tokenIndex637 := position, tokenIndex - if buffer[position] != rune('x') { - goto l638 - } - position++ - goto l637 - l638: - position, tokenIndex = position637, tokenIndex637 - if buffer[position] != rune('X') { - goto l634 - } - position++ - } - l637: - { - position639, tokenIndex639 := position, tokenIndex - if buffer[position] != rune('t') { - goto l640 + { + position637, tokenIndex637 := position, tokenIndex + if buffer[position] != rune('u') { + goto l638 + } + position++ + goto l637 + l638: + position, tokenIndex = position637, tokenIndex637 + if buffer[position] != rune('s') { + goto l636 + } + position++ } - position++ - goto l639 - l640: - position, tokenIndex = position639, tokenIndex639 - if buffer[position] != rune('T') { - goto l634 + l637: + { + position639, tokenIndex639 := position, tokenIndex + if buffer[position] != rune('x') { + goto l640 + } + position++ + goto l639 + l640: + position, tokenIndex = position639, tokenIndex639 + if buffer[position] != rune('X') { + goto l636 + } + position++ } - position++ - } - l639: - { - position641, tokenIndex641 := position, tokenIndex - if buffer[position] != rune('x') { - goto l642 + l639: + { + position641, tokenIndex641 := position, tokenIndex + if buffer[position] != rune('t') { + goto l642 + } + position++ + goto l641 + l642: + position, tokenIndex = position641, tokenIndex641 + if buffer[position] != rune('T') { + goto l636 + } + position++ } - position++ - goto l641 - l642: - position, tokenIndex = position641, tokenIndex641 - if buffer[position] != rune('w') { + l641: + { + position643, tokenIndex643 := position, tokenIndex + if buffer[position] != rune('x') { + goto l644 + } + position++ + goto l643 + l644: + position, tokenIndex = position643, tokenIndex643 + if buffer[position] != rune('w') { + goto l645 + } + position++ + goto l643 + l645: + position, tokenIndex = position643, tokenIndex643 + if buffer[position] != rune('h') { + goto l646 + } + position++ goto l643 + l646: + position, tokenIndex = position643, tokenIndex643 + if buffer[position] != rune('b') { + goto l636 + } + position++ } - position++ - goto l641 l643: - position, tokenIndex = position641, tokenIndex641 - if buffer[position] != rune('h') { - goto l644 + goto l635 + l636: + position, tokenIndex = position635, tokenIndex635 + { + position648, tokenIndex648 := position, tokenIndex + if buffer[position] != rune('l') { + goto l649 + } + position++ + goto l648 + l649: + position, tokenIndex = position648, tokenIndex648 + if buffer[position] != rune('L') { + goto l647 + } + position++ } - position++ - goto l641 - l644: - position, tokenIndex = position641, tokenIndex641 - if buffer[position] != rune('b') { - goto l634 + l648: + { + position650, tokenIndex650 := position, tokenIndex + if buffer[position] != rune('s') { + goto l651 + } + position++ + goto l650 + l651: + position, tokenIndex = position650, tokenIndex650 + if buffer[position] != rune('S') { + goto l647 + } + position++ } - position++ - } - l641: - goto l633 - l634: - position, tokenIndex = position633, tokenIndex633 - { - position646, tokenIndex646 := position, tokenIndex - if buffer[position] != rune('l') { - goto l647 + l650: + { + position652, tokenIndex652 := position, tokenIndex + if buffer[position] != rune('l') { + goto l653 + } + position++ + goto l652 + l653: + position, tokenIndex = position652, tokenIndex652 + if buffer[position] != rune('L') { + goto l647 + } + position++ } - position++ - goto l646 + l652: + goto l635 l647: - position, tokenIndex = position646, tokenIndex646 - if buffer[position] != rune('L') { - goto l645 + position, tokenIndex = position635, tokenIndex635 + { + position655, tokenIndex655 := position, tokenIndex + if buffer[position] != rune('l') { + goto l656 + } + position++ + goto l655 + l656: + position, tokenIndex = position655, tokenIndex655 + if buffer[position] != rune('L') { + goto l654 + } + position++ } - position++ - } - l646: - { - position648, tokenIndex648 := position, tokenIndex - if buffer[position] != rune('s') { - goto l649 + l655: + { + position657, tokenIndex657 := position, tokenIndex + if buffer[position] != rune('s') { + goto l658 + } + position++ + goto l657 + l658: + position, tokenIndex = position657, tokenIndex657 + if buffer[position] != rune('S') { + goto l654 + } + position++ } - position++ - goto l648 - l649: - position, tokenIndex = position648, tokenIndex648 - if buffer[position] != rune('S') { - goto l645 + l657: + { + position659, tokenIndex659 := position, tokenIndex + if buffer[position] != rune('r') { + goto l660 + } + position++ + goto l659 + l660: + position, tokenIndex = position659, tokenIndex659 + if buffer[position] != rune('R') { + goto l654 + } + position++ } - position++ - } - l648: - { - position650, tokenIndex650 := position, tokenIndex - if buffer[position] != rune('l') { - goto l651 + l659: + goto l635 + l654: + position, tokenIndex = position635, tokenIndex635 + { + position662, tokenIndex662 := position, tokenIndex + if buffer[position] != rune('r') { + goto l663 + } + position++ + goto l662 + l663: + position, tokenIndex = position662, tokenIndex662 + if buffer[position] != rune('R') { + goto l661 + } + position++ } - position++ - goto l650 - l651: - position, tokenIndex = position650, tokenIndex650 - if buffer[position] != rune('L') { - goto l645 + l662: + { + position664, tokenIndex664 := position, tokenIndex + if buffer[position] != rune('o') { + goto l665 + } + position++ + goto l664 + l665: + position, tokenIndex = position664, tokenIndex664 + if buffer[position] != rune('O') { + goto l661 + } + position++ } - position++ - } - l650: - goto l633 - l645: - position, tokenIndex = position633, tokenIndex633 - { - position653, tokenIndex653 := position, tokenIndex - if buffer[position] != rune('l') { - goto l654 + l664: + { + position666, tokenIndex666 := position, tokenIndex + if buffer[position] != rune('r') { + goto l667 + } + position++ + goto l666 + l667: + position, tokenIndex = position666, tokenIndex666 + if buffer[position] != rune('R') { + goto l661 + } + position++ } - position++ - goto l653 - l654: - position, tokenIndex = position653, tokenIndex653 - if buffer[position] != rune('L') { - goto l652 + l666: + goto l635 + l661: + position, tokenIndex = position635, tokenIndex635 + { + position668, tokenIndex668 := position, tokenIndex + if buffer[position] != rune('a') { + goto l669 + } + position++ + goto l668 + l669: + position, tokenIndex = position668, tokenIndex668 + if buffer[position] != rune('A') { + goto l634 + } + position++ } - position++ - } - l653: - { - position655, tokenIndex655 := position, tokenIndex - if buffer[position] != rune('s') { - goto l656 + l668: + { + position670, tokenIndex670 := position, tokenIndex + if buffer[position] != rune('s') { + goto l671 + } + position++ + goto l670 + l671: + position, tokenIndex = position670, tokenIndex670 + if buffer[position] != rune('S') { + goto l634 + } + position++ } - position++ - goto l655 - l656: - position, tokenIndex = position655, tokenIndex655 - if buffer[position] != rune('S') { - goto l652 + l670: + { + position672, tokenIndex672 := position, tokenIndex + if buffer[position] != rune('r') { + goto l673 + } + position++ + goto l672 + l673: + position, tokenIndex = position672, tokenIndex672 + if buffer[position] != rune('R') { + goto l634 + } + position++ } - position++ + l672: } - l655: + l635: { - position657, tokenIndex657 := position, tokenIndex - if buffer[position] != rune('r') { - goto l658 + position674, tokenIndex674 := position, tokenIndex + if !_rules[ruleWS]() { + goto l674 } - position++ - goto l657 - l658: - position, tokenIndex = position657, tokenIndex657 - if buffer[position] != rune('R') { - goto l652 + { + position676, tokenIndex676 := position, tokenIndex + if buffer[position] != rune('#') { + goto l676 + } + position++ + goto l677 + l676: + position, tokenIndex = position676, tokenIndex676 } - position++ + l677: + if !_rules[ruleOffset]() { + goto l674 + } + goto l675 + l674: + position, tokenIndex = position674, tokenIndex674 } - l657: + l675: goto l633 - l652: + l634: position, tokenIndex = position633, tokenIndex633 { - position660, tokenIndex660 := position, tokenIndex - if buffer[position] != rune('r') { - goto l661 - } - position++ - goto l660 - l661: - position, tokenIndex = position660, tokenIndex660 - if buffer[position] != rune('R') { - goto l659 - } - position++ - } - l660: - { - position662, tokenIndex662 := position, tokenIndex - if buffer[position] != rune('o') { - goto l663 + position678, tokenIndex678 := position, tokenIndex + if buffer[position] != rune('m') { + goto l679 } position++ - goto l662 - l663: - position, tokenIndex = position662, tokenIndex662 - if buffer[position] != rune('O') { - goto l659 + goto l678 + l679: + position, tokenIndex = position678, tokenIndex678 + if buffer[position] != rune('M') { + goto l631 } position++ } - l662: + l678: { - position664, tokenIndex664 := position, tokenIndex - if buffer[position] != rune('r') { - goto l665 + position680, tokenIndex680 := position, tokenIndex + if buffer[position] != rune('u') { + goto l681 } position++ - goto l664 - l665: - position, tokenIndex = position664, tokenIndex664 - if buffer[position] != rune('R') { - goto l659 + goto l680 + l681: + position, tokenIndex = position680, tokenIndex680 + if buffer[position] != rune('U') { + goto l631 } position++ } - l664: - goto l633 - l659: - position, tokenIndex = position633, tokenIndex633 + l680: { - position666, tokenIndex666 := position, tokenIndex - if buffer[position] != rune('a') { - goto l667 + position682, tokenIndex682 := position, tokenIndex + if buffer[position] != rune('l') { + goto l683 } position++ - goto l666 - l667: - position, tokenIndex = position666, tokenIndex666 - if buffer[position] != rune('A') { + goto l682 + l683: + position, tokenIndex = position682, tokenIndex682 + if buffer[position] != rune('L') { goto l631 } position++ } - l666: + l682: + if buffer[position] != rune(' ') { + goto l631 + } + position++ { - position668, tokenIndex668 := position, tokenIndex - if buffer[position] != rune('s') { - goto l669 + position684, tokenIndex684 := position, tokenIndex + if buffer[position] != rune('v') { + goto l685 } position++ - goto l668 - l669: - position, tokenIndex = position668, tokenIndex668 - if buffer[position] != rune('S') { + goto l684 + l685: + position, tokenIndex = position684, tokenIndex684 + if buffer[position] != rune('V') { goto l631 } position++ } - l668: + l684: { - position670, tokenIndex670 := position, tokenIndex - if buffer[position] != rune('r') { - goto l671 + position686, tokenIndex686 := position, tokenIndex + if buffer[position] != rune('l') { + goto l687 } position++ - goto l670 - l671: - position, tokenIndex = position670, tokenIndex670 - if buffer[position] != rune('R') { + goto l686 + l687: + position, tokenIndex = position686, tokenIndex686 + if buffer[position] != rune('L') { goto l631 } position++ } - l670: + l686: } l633: - { - position672, tokenIndex672 := position, tokenIndex - if !_rules[ruleWS]() { - goto l672 - } - { - position674, tokenIndex674 := position, tokenIndex - if buffer[position] != rune('#') { - goto l674 - } - position++ - goto l675 - l674: - position, tokenIndex = position674, tokenIndex674 - } - l675: - if !_rules[ruleOffset]() { - goto l672 - } - goto l673 - l672: - position, tokenIndex = position672, tokenIndex672 - } - l673: add(ruleARMConstantTweak, position632) } return true @@ -5373,2191 +5461,2272 @@ func (p *Asm) Init(options ...func(*Asm) error) error { position, tokenIndex = position631, tokenIndex631 return false }, - /* 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? ((',' / '-') 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 / SVE2PredicateRegister / ('{' WS? ARMVectorRegister WS? ((',' / '-') WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')?))> */ func() bool { - position676, tokenIndex676 := position, tokenIndex + position688, tokenIndex688 := position, tokenIndex { - position677 := position + position689 := position { - position678, tokenIndex678 := position, tokenIndex + position690, tokenIndex690 := position, tokenIndex { - position680, tokenIndex680 := position, tokenIndex + position692, tokenIndex692 := position, tokenIndex if buffer[position] != rune('s') { - goto l681 + goto l693 } position++ - goto l680 - l681: - position, tokenIndex = position680, tokenIndex680 + goto l692 + l693: + position, tokenIndex = position692, tokenIndex692 if buffer[position] != rune('S') { - goto l679 + goto l691 } position++ } - l680: + l692: { - position682, tokenIndex682 := position, tokenIndex + position694, tokenIndex694 := position, tokenIndex if buffer[position] != rune('p') { - goto l683 + goto l695 } position++ - goto l682 - l683: - position, tokenIndex = position682, tokenIndex682 + goto l694 + l695: + position, tokenIndex = position694, tokenIndex694 if buffer[position] != rune('P') { - goto l679 + goto l691 } position++ } - l682: - goto l678 - l679: - position, tokenIndex = position678, tokenIndex678 + l694: + goto l690 + l691: + position, tokenIndex = position690, tokenIndex690 { - position685, tokenIndex685 := position, tokenIndex + position697, tokenIndex697 := position, tokenIndex if buffer[position] != rune('x') { - goto l686 + goto l698 } position++ - goto l685 - l686: - position, tokenIndex = position685, tokenIndex685 + goto l697 + l698: + position, tokenIndex = position697, tokenIndex697 if buffer[position] != rune('w') { - goto l687 + goto l699 } position++ - goto l685 - l687: - position, tokenIndex = position685, tokenIndex685 + goto l697 + l699: + position, tokenIndex = position697, tokenIndex697 if buffer[position] != rune('d') { - goto l688 + goto l700 } position++ - goto l685 - l688: - position, tokenIndex = position685, tokenIndex685 + goto l697 + l700: + position, tokenIndex = position697, tokenIndex697 if buffer[position] != rune('q') { - goto l689 + goto l701 } position++ - goto l685 - l689: - position, tokenIndex = position685, tokenIndex685 + goto l697 + l701: + position, tokenIndex = position697, tokenIndex697 if buffer[position] != rune('s') { - goto l690 + goto l702 } position++ - goto l685 - l690: - position, tokenIndex = position685, tokenIndex685 + goto l697 + l702: + position, tokenIndex = position697, tokenIndex697 if buffer[position] != rune('h') { - goto l691 + goto l703 } position++ - goto l685 - l691: - position, tokenIndex = position685, tokenIndex685 + goto l697 + l703: + position, tokenIndex = position697, tokenIndex697 if buffer[position] != rune('b') { - goto l684 + goto l696 } position++ } - l685: + l697: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l684 + goto l696 } position++ { - position692, tokenIndex692 := position, tokenIndex + position704, tokenIndex704 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l692 + goto l704 } position++ - goto l693 - l692: - position, tokenIndex = position692, tokenIndex692 + goto l705 + l704: + position, tokenIndex = position704, tokenIndex704 } - l693: - goto l678 - l684: - position, tokenIndex = position678, tokenIndex678 + l705: + goto l690 + l696: + position, tokenIndex = position690, tokenIndex690 { - position695, tokenIndex695 := position, tokenIndex + position707, tokenIndex707 := position, tokenIndex if buffer[position] != rune('x') { - goto l696 + goto l708 } position++ - goto l695 - l696: - position, tokenIndex = position695, tokenIndex695 + goto l707 + l708: + position, tokenIndex = position707, tokenIndex707 if buffer[position] != rune('X') { - goto l694 + goto l706 } position++ } - l695: + l707: { - position697, tokenIndex697 := position, tokenIndex + position709, tokenIndex709 := position, tokenIndex if buffer[position] != rune('z') { - goto l698 + goto l710 } position++ - goto l697 - l698: - position, tokenIndex = position697, tokenIndex697 + goto l709 + l710: + position, tokenIndex = position709, tokenIndex709 if buffer[position] != rune('Z') { - goto l694 + goto l706 } position++ } - l697: + l709: { - position699, tokenIndex699 := position, tokenIndex + position711, tokenIndex711 := position, tokenIndex if buffer[position] != rune('r') { - goto l700 + goto l712 } position++ - goto l699 - l700: - position, tokenIndex = position699, tokenIndex699 + goto l711 + l712: + position, tokenIndex = position711, tokenIndex711 if buffer[position] != rune('R') { - goto l694 + goto l706 } position++ } - l699: - goto l678 - l694: - position, tokenIndex = position678, tokenIndex678 + l711: + goto l690 + l706: + position, tokenIndex = position690, tokenIndex690 { - position702, tokenIndex702 := position, tokenIndex + position714, tokenIndex714 := position, tokenIndex if buffer[position] != rune('w') { - goto l703 + goto l715 } position++ - goto l702 - l703: - position, tokenIndex = position702, tokenIndex702 + goto l714 + l715: + position, tokenIndex = position714, tokenIndex714 if buffer[position] != rune('W') { - goto l701 + goto l713 } position++ } - l702: + l714: { - position704, tokenIndex704 := position, tokenIndex + position716, tokenIndex716 := position, tokenIndex if buffer[position] != rune('z') { - goto l705 + goto l717 } position++ - goto l704 - l705: - position, tokenIndex = position704, tokenIndex704 + goto l716 + l717: + position, tokenIndex = position716, tokenIndex716 if buffer[position] != rune('Z') { - goto l701 + goto l713 } position++ } - l704: + l716: { - position706, tokenIndex706 := position, tokenIndex + position718, tokenIndex718 := position, tokenIndex if buffer[position] != rune('r') { - goto l707 + goto l719 } position++ - goto l706 - l707: - position, tokenIndex = position706, tokenIndex706 + goto l718 + l719: + position, tokenIndex = position718, tokenIndex718 if buffer[position] != rune('R') { - goto l701 + goto l713 } position++ } - l706: - goto l678 - l701: - position, tokenIndex = position678, tokenIndex678 + l718: + goto l690 + l713: + position, tokenIndex = position690, tokenIndex690 { - position709, tokenIndex709 := position, tokenIndex + position721, tokenIndex721 := position, tokenIndex if buffer[position] != rune('n') { - goto l710 + goto l722 } position++ - goto l709 - l710: - position, tokenIndex = position709, tokenIndex709 + goto l721 + l722: + position, tokenIndex = position721, tokenIndex721 if buffer[position] != rune('N') { - goto l708 + goto l720 } position++ } - l709: + l721: { - position711, tokenIndex711 := position, tokenIndex + position723, tokenIndex723 := position, tokenIndex if buffer[position] != rune('z') { - goto l712 + goto l724 } position++ - goto l711 - l712: - position, tokenIndex = position711, tokenIndex711 + goto l723 + l724: + position, tokenIndex = position723, tokenIndex723 if buffer[position] != rune('Z') { - goto l708 + goto l720 } position++ } - l711: + l723: { - position713, tokenIndex713 := position, tokenIndex + position725, tokenIndex725 := position, tokenIndex if buffer[position] != rune('c') { - goto l714 + goto l726 } position++ - goto l713 - l714: - position, tokenIndex = position713, tokenIndex713 + goto l725 + l726: + position, tokenIndex = position725, tokenIndex725 if buffer[position] != rune('C') { - goto l708 + goto l720 } position++ } - l713: + l725: { - position715, tokenIndex715 := position, tokenIndex + position727, tokenIndex727 := position, tokenIndex if buffer[position] != rune('v') { - goto l716 + goto l728 } position++ - goto l715 - l716: - position, tokenIndex = position715, tokenIndex715 + goto l727 + l728: + position, tokenIndex = position727, tokenIndex727 if buffer[position] != rune('V') { - goto l708 + goto l720 } position++ } - l715: - goto l678 - l708: - position, tokenIndex = position678, tokenIndex678 + l727: + goto l690 + l720: + position, tokenIndex = position690, tokenIndex690 if !_rules[ruleARMVectorRegister]() { - goto l717 + goto l729 + } + goto l690 + l729: + position, tokenIndex = position690, tokenIndex690 + if !_rules[ruleSVE2PredicateRegister]() { + goto l730 } - goto l678 - l717: - position, tokenIndex = position678, tokenIndex678 + goto l690 + l730: + position, tokenIndex = position690, tokenIndex690 if buffer[position] != rune('{') { - goto l676 + goto l688 } position++ { - position718, tokenIndex718 := position, tokenIndex + position731, tokenIndex731 := position, tokenIndex if !_rules[ruleWS]() { - goto l718 + goto l731 } - goto l719 - l718: - position, tokenIndex = position718, tokenIndex718 + goto l732 + l731: + position, tokenIndex = position731, tokenIndex731 } - l719: + l732: if !_rules[ruleARMVectorRegister]() { - goto l676 + goto l688 } { - position720, tokenIndex720 := position, tokenIndex + position733, tokenIndex733 := position, tokenIndex if !_rules[ruleWS]() { - goto l720 + goto l733 } - goto l721 - l720: - position, tokenIndex = position720, tokenIndex720 + goto l734 + l733: + position, tokenIndex = position733, tokenIndex733 } - l721: - l722: + l734: + l735: { - position723, tokenIndex723 := position, tokenIndex + position736, tokenIndex736 := position, tokenIndex { - position724, tokenIndex724 := position, tokenIndex + position737, tokenIndex737 := position, tokenIndex if buffer[position] != rune(',') { - goto l725 + goto l738 } position++ - goto l724 - l725: - position, tokenIndex = position724, tokenIndex724 + goto l737 + l738: + position, tokenIndex = position737, tokenIndex737 if buffer[position] != rune('-') { - goto l723 + goto l736 } position++ } - l724: + l737: { - position726, tokenIndex726 := position, tokenIndex + position739, tokenIndex739 := position, tokenIndex if !_rules[ruleWS]() { - goto l726 + goto l739 } - goto l727 - l726: - position, tokenIndex = position726, tokenIndex726 + goto l740 + l739: + position, tokenIndex = position739, tokenIndex739 } - l727: + l740: if !_rules[ruleARMVectorRegister]() { - goto l723 + goto l736 } - goto l722 - l723: - position, tokenIndex = position723, tokenIndex723 + goto l735 + l736: + position, tokenIndex = position736, tokenIndex736 } { - position728, tokenIndex728 := position, tokenIndex + position741, tokenIndex741 := position, tokenIndex if !_rules[ruleWS]() { - goto l728 + goto l741 } - goto l729 - l728: - position, tokenIndex = position728, tokenIndex728 + goto l742 + l741: + position, tokenIndex = position741, tokenIndex741 } - l729: + l742: if buffer[position] != rune('}') { - goto l676 + goto l688 } position++ { - position730, tokenIndex730 := position, tokenIndex + position743, tokenIndex743 := position, tokenIndex if buffer[position] != rune('[') { - goto l730 + goto l743 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l730 + goto l743 } position++ { - position732, tokenIndex732 := position, tokenIndex + position745, tokenIndex745 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l732 + goto l745 } position++ - goto l733 - l732: - position, tokenIndex = position732, tokenIndex732 + goto l746 + l745: + position, tokenIndex = position745, tokenIndex745 } - l733: + l746: if buffer[position] != rune(']') { - goto l730 + goto l743 } position++ - goto l731 - l730: - position, tokenIndex = position730, tokenIndex730 + goto l744 + l743: + position, tokenIndex = position743, tokenIndex743 } - l731: + l744: } - l678: - add(ruleARMRegister, position677) + l690: + add(ruleARMRegister, position689) } return true - l676: - position, tokenIndex = position676, tokenIndex676 + l688: + position, tokenIndex = position688, tokenIndex688 return false }, - /* 45 ARMVectorRegister <- <(('v' / 'V') [0-9] [0-9]? ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */ + /* 45 ARMVectorRegister <- <(('v' / 'z') [0-9] [0-9]? ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */ func() bool { - position734, tokenIndex734 := position, tokenIndex + position747, tokenIndex747 := position, tokenIndex { - position735 := position + position748 := position { - position736, tokenIndex736 := position, tokenIndex + position749, tokenIndex749 := position, tokenIndex if buffer[position] != rune('v') { - goto l737 + goto l750 } position++ - goto l736 - l737: - position, tokenIndex = position736, tokenIndex736 - if buffer[position] != rune('V') { - goto l734 + goto l749 + l750: + position, tokenIndex = position749, tokenIndex749 + if buffer[position] != rune('z') { + goto l747 } position++ } - l736: + l749: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l734 + goto l747 } position++ { - position738, tokenIndex738 := position, tokenIndex + position751, tokenIndex751 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l738 + goto l751 } position++ - goto l739 - l738: - position, tokenIndex = position738, tokenIndex738 + goto l752 + l751: + position, tokenIndex = position751, tokenIndex751 } - l739: + l752: { - position740, tokenIndex740 := position, tokenIndex + position753, tokenIndex753 := position, tokenIndex if buffer[position] != rune('.') { - goto l740 + goto l753 } position++ - l742: + l755: { - position743, tokenIndex743 := position, tokenIndex + position756, tokenIndex756 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l743 + goto l756 } position++ - goto l742 - l743: - position, tokenIndex = position743, tokenIndex743 + goto l755 + l756: + position, tokenIndex = position756, tokenIndex756 } { - position744, tokenIndex744 := position, tokenIndex + position757, tokenIndex757 := position, tokenIndex if buffer[position] != rune('b') { - goto l745 + goto l758 } position++ - goto l744 - l745: - position, tokenIndex = position744, tokenIndex744 + goto l757 + l758: + position, tokenIndex = position757, tokenIndex757 if buffer[position] != rune('s') { - goto l746 + goto l759 } position++ - goto l744 - l746: - position, tokenIndex = position744, tokenIndex744 + goto l757 + l759: + position, tokenIndex = position757, tokenIndex757 if buffer[position] != rune('d') { - goto l747 + goto l760 } position++ - goto l744 - l747: - position, tokenIndex = position744, tokenIndex744 + goto l757 + l760: + position, tokenIndex = position757, tokenIndex757 if buffer[position] != rune('h') { - goto l748 + goto l761 } position++ - goto l744 - l748: - position, tokenIndex = position744, tokenIndex744 + goto l757 + l761: + position, tokenIndex = position757, tokenIndex757 if buffer[position] != rune('q') { - goto l740 + goto l753 } position++ } - l744: + l757: { - position749, tokenIndex749 := position, tokenIndex + position762, tokenIndex762 := position, tokenIndex if buffer[position] != rune('[') { - goto l749 + goto l762 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l749 + goto l762 } position++ { - position751, tokenIndex751 := position, tokenIndex + position764, tokenIndex764 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l751 + goto l764 } position++ - goto l752 - l751: - position, tokenIndex = position751, tokenIndex751 + goto l765 + l764: + position, tokenIndex = position764, tokenIndex764 } - l752: + l765: if buffer[position] != rune(']') { - goto l749 + goto l762 } position++ - goto l750 - l749: - position, tokenIndex = position749, tokenIndex749 + goto l763 + l762: + position, tokenIndex = position762, tokenIndex762 } - l750: - goto l741 - l740: - position, tokenIndex = position740, tokenIndex740 + l763: + goto l754 + l753: + position, tokenIndex = position753, tokenIndex753 + } + l754: + add(ruleARMVectorRegister, position748) + } + return true + l747: + position, tokenIndex = position747, tokenIndex747 + return false + }, + /* 46 SVE2PredicateRegister <- <(('p' / 'P') [0-9] [0-9]? '/' ('m' / 'M' / 'z' / 'Z'))> */ + func() bool { + position766, tokenIndex766 := position, tokenIndex + { + position767 := position + { + position768, tokenIndex768 := position, tokenIndex + if buffer[position] != rune('p') { + goto l769 + } + position++ + goto l768 + l769: + position, tokenIndex = position768, tokenIndex768 + if buffer[position] != rune('P') { + goto l766 + } + position++ + } + l768: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l766 + } + position++ + { + position770, tokenIndex770 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l770 + } + position++ + goto l771 + l770: + position, tokenIndex = position770, tokenIndex770 + } + l771: + if buffer[position] != rune('/') { + goto l766 + } + position++ + { + position772, tokenIndex772 := position, tokenIndex + if buffer[position] != rune('m') { + goto l773 + } + position++ + goto l772 + l773: + position, tokenIndex = position772, tokenIndex772 + if buffer[position] != rune('M') { + goto l774 + } + position++ + goto l772 + l774: + position, tokenIndex = position772, tokenIndex772 + if buffer[position] != rune('z') { + goto l775 + } + position++ + goto l772 + l775: + position, tokenIndex = position772, tokenIndex772 + if buffer[position] != rune('Z') { + goto l766 + } + position++ } - l741: - add(ruleARMVectorRegister, position735) + l772: + add(ruleSVE2PredicateRegister, position767) } return true - l734: - position, tokenIndex = position734, tokenIndex734 + l766: + position, tokenIndex = position766, tokenIndex766 return false }, - /* 46 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */ + /* 47 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */ func() bool { - position753, tokenIndex753 := position, tokenIndex + position776, tokenIndex776 := position, tokenIndex { - position754 := position + position777 := position { - position755, tokenIndex755 := position, tokenIndex + position778, tokenIndex778 := position, tokenIndex if !_rules[ruleSymbolRef]() { - goto l756 + goto l779 } if !_rules[ruleBaseIndexScale]() { - goto l756 + goto l779 } - goto l755 - l756: - position, tokenIndex = position755, tokenIndex755 + goto l778 + l779: + position, tokenIndex = position778, tokenIndex778 if !_rules[ruleSymbolRef]() { - goto l757 + goto l780 } - goto l755 - l757: - position, tokenIndex = position755, tokenIndex755 + goto l778 + l780: + position, tokenIndex = position778, tokenIndex778 if !_rules[ruleLow12BitsSymbolRef]() { - goto l758 + goto l781 } - goto l755 - l758: - position, tokenIndex = position755, tokenIndex755 - l760: + goto l778 + l781: + position, tokenIndex = position778, tokenIndex778 + l783: { - position761, tokenIndex761 := position, tokenIndex + position784, tokenIndex784 := position, tokenIndex if !_rules[ruleOffset]() { - goto l761 + goto l784 } - goto l760 - l761: - position, tokenIndex = position761, tokenIndex761 + goto l783 + l784: + position, tokenIndex = position784, tokenIndex784 } if !_rules[ruleBaseIndexScale]() { - goto l759 + goto l782 } - goto l755 - l759: - position, tokenIndex = position755, tokenIndex755 + goto l778 + l782: + position, tokenIndex = position778, tokenIndex778 if !_rules[ruleSegmentRegister]() { - goto l762 + goto l785 } if !_rules[ruleOffset]() { - goto l762 + goto l785 } if !_rules[ruleBaseIndexScale]() { - goto l762 + goto l785 } - goto l755 - l762: - position, tokenIndex = position755, tokenIndex755 + goto l778 + l785: + position, tokenIndex = position778, tokenIndex778 if !_rules[ruleSegmentRegister]() { - goto l763 + goto l786 } if !_rules[ruleBaseIndexScale]() { - goto l763 + goto l786 } - goto l755 - l763: - position, tokenIndex = position755, tokenIndex755 + goto l778 + l786: + position, tokenIndex = position778, tokenIndex778 if !_rules[ruleSegmentRegister]() { - goto l764 + goto l787 } if !_rules[ruleOffset]() { - goto l764 + goto l787 } - goto l755 - l764: - position, tokenIndex = position755, tokenIndex755 + goto l778 + l787: + position, tokenIndex = position778, tokenIndex778 if !_rules[ruleARMBaseIndexScale]() { - goto l765 + goto l788 } - goto l755 - l765: - position, tokenIndex = position755, tokenIndex755 + goto l778 + l788: + position, tokenIndex = position778, tokenIndex778 if !_rules[ruleBaseIndexScale]() { - goto l753 + goto l776 } } - l755: - add(ruleMemoryRef, position754) + l778: + add(ruleMemoryRef, position777) } return true - l753: - position, tokenIndex = position753, tokenIndex753 + l776: + position, tokenIndex = position776, tokenIndex776 return false }, - /* 47 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ + /* 48 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ func() bool { - position766, tokenIndex766 := position, tokenIndex + position789, tokenIndex789 := position, tokenIndex { - position767 := position + position790 := position { - position768, tokenIndex768 := position, tokenIndex - l770: + position791, tokenIndex791 := position, tokenIndex + l793: { - position771, tokenIndex771 := position, tokenIndex + position794, tokenIndex794 := position, tokenIndex if !_rules[ruleOffset]() { - goto l771 + goto l794 } - goto l770 - l771: - position, tokenIndex = position771, tokenIndex771 + goto l793 + l794: + position, tokenIndex = position794, tokenIndex794 } if buffer[position] != rune('+') { - goto l768 + goto l791 } position++ - goto l769 - l768: - position, tokenIndex = position768, tokenIndex768 + goto l792 + l791: + position, tokenIndex = position791, tokenIndex791 } - l769: + l792: { - position772, tokenIndex772 := position, tokenIndex + position795, tokenIndex795 := position, tokenIndex if !_rules[ruleLocalSymbol]() { - goto l773 + goto l796 } - goto l772 - l773: - position, tokenIndex = position772, tokenIndex772 + goto l795 + l796: + position, tokenIndex = position795, tokenIndex795 if !_rules[ruleSymbolName]() { - goto l766 + goto l789 } } - l772: - l774: + l795: + l797: { - position775, tokenIndex775 := position, tokenIndex + position798, tokenIndex798 := position, tokenIndex if !_rules[ruleOffset]() { - goto l775 + goto l798 } - goto l774 - l775: - position, tokenIndex = position775, tokenIndex775 + goto l797 + l798: + position, tokenIndex = position798, tokenIndex798 } { - position776, tokenIndex776 := position, tokenIndex + position799, tokenIndex799 := position, tokenIndex if buffer[position] != rune('@') { - goto l776 + goto l799 } position++ if !_rules[ruleSection]() { - goto l776 + goto l799 } - l778: + l801: { - position779, tokenIndex779 := position, tokenIndex + position802, tokenIndex802 := position, tokenIndex if !_rules[ruleOffset]() { - goto l779 + goto l802 } - goto l778 - l779: - position, tokenIndex = position779, tokenIndex779 + goto l801 + l802: + position, tokenIndex = position802, tokenIndex802 } - goto l777 - l776: - position, tokenIndex = position776, tokenIndex776 + goto l800 + l799: + position, tokenIndex = position799, tokenIndex799 } - l777: - add(ruleSymbolRef, position767) + l800: + add(ruleSymbolRef, position790) } return true - l766: - position, tokenIndex = position766, tokenIndex766 + l789: + position, tokenIndex = position789, tokenIndex789 return false }, - /* 48 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */ + /* 49 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */ func() bool { - position780, tokenIndex780 := position, tokenIndex + position803, tokenIndex803 := position, tokenIndex { - position781 := position + position804 := position if buffer[position] != rune(':') { - goto l780 + goto l803 } position++ { - position782, tokenIndex782 := position, tokenIndex + position805, tokenIndex805 := position, tokenIndex if buffer[position] != rune('l') { - goto l783 + goto l806 } position++ - goto l782 - l783: - position, tokenIndex = position782, tokenIndex782 + goto l805 + l806: + position, tokenIndex = position805, tokenIndex805 if buffer[position] != rune('L') { - goto l780 + goto l803 } position++ } - l782: + l805: { - position784, tokenIndex784 := position, tokenIndex + position807, tokenIndex807 := position, tokenIndex if buffer[position] != rune('o') { - goto l785 + goto l808 } position++ - goto l784 - l785: - position, tokenIndex = position784, tokenIndex784 + goto l807 + l808: + position, tokenIndex = position807, tokenIndex807 if buffer[position] != rune('O') { - goto l780 + goto l803 } position++ } - l784: + l807: if buffer[position] != rune('1') { - goto l780 + goto l803 } position++ if buffer[position] != rune('2') { - goto l780 + goto l803 } position++ if buffer[position] != rune(':') { - goto l780 + goto l803 } position++ { - position786, tokenIndex786 := position, tokenIndex + position809, tokenIndex809 := position, tokenIndex if !_rules[ruleLocalSymbol]() { - goto l787 + goto l810 } - goto l786 - l787: - position, tokenIndex = position786, tokenIndex786 + goto l809 + l810: + position, tokenIndex = position809, tokenIndex809 if !_rules[ruleSymbolName]() { - goto l780 + goto l803 } } - l786: + l809: { - position788, tokenIndex788 := position, tokenIndex + position811, tokenIndex811 := position, tokenIndex if !_rules[ruleOffset]() { - goto l788 + goto l811 } - goto l789 - l788: - position, tokenIndex = position788, tokenIndex788 + goto l812 + l811: + position, tokenIndex = position811, tokenIndex811 } - l789: - add(ruleLow12BitsSymbolRef, position781) + l812: + add(ruleLow12BitsSymbolRef, position804) } return true - l780: - position, tokenIndex = position780, tokenIndex780 + l803: + position, tokenIndex = position803, tokenIndex803 return false }, - /* 49 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#'? Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ('#'? ARMGOTLow12) / ('#'? Low12BitsSymbolRef) / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */ + /* 50 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#'? Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ('#'? ARMGOTLow12) / ('#'? Low12BitsSymbolRef) / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */ func() bool { - position790, tokenIndex790 := position, tokenIndex + position813, tokenIndex813 := position, tokenIndex { - position791 := position + position814 := position if buffer[position] != rune('[') { - goto l790 + goto l813 } position++ if !_rules[ruleARMRegister]() { - goto l790 + goto l813 } { - position792, tokenIndex792 := position, tokenIndex + position815, tokenIndex815 := position, tokenIndex if buffer[position] != rune(',') { - goto l792 + goto l815 } position++ { - position794, tokenIndex794 := position, tokenIndex + position817, tokenIndex817 := position, tokenIndex if !_rules[ruleWS]() { - goto l794 + goto l817 } - goto l795 - l794: - position, tokenIndex = position794, tokenIndex794 + goto l818 + l817: + position, tokenIndex = position817, tokenIndex817 } - l795: + l818: { - position796, tokenIndex796 := position, tokenIndex + position819, tokenIndex819 := position, tokenIndex { - position798, tokenIndex798 := position, tokenIndex + position821, tokenIndex821 := position, tokenIndex if buffer[position] != rune('#') { - goto l798 + goto l821 } position++ - goto l799 - l798: - position, tokenIndex = position798, tokenIndex798 + goto l822 + l821: + position, tokenIndex = position821, tokenIndex821 } - l799: + l822: if !_rules[ruleOffset]() { - goto l797 + goto l820 } { - position800, tokenIndex800 := position, tokenIndex + position823, tokenIndex823 := position, tokenIndex { - position802, tokenIndex802 := position, tokenIndex + position825, tokenIndex825 := position, tokenIndex if buffer[position] != rune('*') { - goto l803 + goto l826 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l803 + goto l826 } position++ - l804: + l827: { - position805, tokenIndex805 := position, tokenIndex + position828, tokenIndex828 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l805 + goto l828 } position++ - goto l804 - l805: - position, tokenIndex = position805, tokenIndex805 + goto l827 + l828: + position, tokenIndex = position828, tokenIndex828 } - goto l802 - l803: - position, tokenIndex = position802, tokenIndex802 + goto l825 + l826: + position, tokenIndex = position825, tokenIndex825 if buffer[position] != rune('*') { - goto l806 + goto l829 } position++ if buffer[position] != rune('(') { - goto l806 + goto l829 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l806 + goto l829 } position++ - l807: + l830: { - position808, tokenIndex808 := position, tokenIndex + position831, tokenIndex831 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l808 + goto l831 } position++ - goto l807 - l808: - position, tokenIndex = position808, tokenIndex808 + goto l830 + l831: + position, tokenIndex = position831, tokenIndex831 } if !_rules[ruleOperator]() { - goto l806 + goto l829 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l806 + goto l829 } position++ - l809: + l832: { - position810, tokenIndex810 := position, tokenIndex + position833, tokenIndex833 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l810 + goto l833 } position++ - goto l809 - l810: - position, tokenIndex = position810, tokenIndex810 + goto l832 + l833: + position, tokenIndex = position833, tokenIndex833 } if buffer[position] != rune(')') { - goto l806 + goto l829 } position++ - goto l802 - l806: - position, tokenIndex = position802, tokenIndex802 - l811: + goto l825 + l829: + position, tokenIndex = position825, tokenIndex825 + l834: { - position812, tokenIndex812 := position, tokenIndex + position835, tokenIndex835 := position, tokenIndex if buffer[position] != rune('+') { - goto l812 + goto l835 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l812 + goto l835 } position++ - l813: + l836: { - position814, tokenIndex814 := position, tokenIndex + position837, tokenIndex837 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l814 + goto l837 } position++ - goto l813 - l814: - position, tokenIndex = position814, tokenIndex814 + goto l836 + l837: + position, tokenIndex = position837, tokenIndex837 } - goto l811 - l812: - position, tokenIndex = position812, tokenIndex812 + goto l834 + l835: + position, tokenIndex = position835, tokenIndex835 } } - l802: - goto l801 + l825: + goto l824 - position, tokenIndex = position800, tokenIndex800 + position, tokenIndex = position823, tokenIndex823 } - l801: - goto l796 - l797: - position, tokenIndex = position796, tokenIndex796 + l824: + goto l819 + l820: + position, tokenIndex = position819, tokenIndex819 { - position816, tokenIndex816 := position, tokenIndex + position839, tokenIndex839 := position, tokenIndex if buffer[position] != rune('#') { - goto l816 + goto l839 } position++ - goto l817 - l816: - position, tokenIndex = position816, tokenIndex816 + goto l840 + l839: + position, tokenIndex = position839, tokenIndex839 } - l817: + l840: if !_rules[ruleARMGOTLow12]() { - goto l815 + goto l838 } - goto l796 - l815: - position, tokenIndex = position796, tokenIndex796 + goto l819 + l838: + position, tokenIndex = position819, tokenIndex819 { - position819, tokenIndex819 := position, tokenIndex + position842, tokenIndex842 := position, tokenIndex if buffer[position] != rune('#') { - goto l819 + goto l842 } position++ - goto l820 - l819: - position, tokenIndex = position819, tokenIndex819 + goto l843 + l842: + position, tokenIndex = position842, tokenIndex842 } - l820: + l843: if !_rules[ruleLow12BitsSymbolRef]() { - goto l818 + goto l841 } - goto l796 - l818: - position, tokenIndex = position796, tokenIndex796 + goto l819 + l841: + position, tokenIndex = position819, tokenIndex819 if !_rules[ruleARMRegister]() { - goto l792 + goto l815 } } - l796: + l819: { - position821, tokenIndex821 := position, tokenIndex + position844, tokenIndex844 := position, tokenIndex if buffer[position] != rune(',') { - goto l821 + goto l844 } position++ { - position823, tokenIndex823 := position, tokenIndex + position846, tokenIndex846 := position, tokenIndex if !_rules[ruleWS]() { - goto l823 + goto l846 } - goto l824 - l823: - position, tokenIndex = position823, tokenIndex823 + goto l847 + l846: + position, tokenIndex = position846, tokenIndex846 } - l824: + l847: if !_rules[ruleARMConstantTweak]() { - goto l821 + goto l844 } - goto l822 - l821: - position, tokenIndex = position821, tokenIndex821 + goto l845 + l844: + position, tokenIndex = position844, tokenIndex844 } - l822: - goto l793 - l792: - position, tokenIndex = position792, tokenIndex792 + l845: + goto l816 + l815: + position, tokenIndex = position815, tokenIndex815 } - l793: + l816: if buffer[position] != rune(']') { - goto l790 + goto l813 } position++ { - position825, tokenIndex825 := position, tokenIndex + position848, tokenIndex848 := position, tokenIndex if !_rules[ruleARMPostincrement]() { - goto l825 + goto l848 } - goto l826 - l825: - position, tokenIndex = position825, tokenIndex825 + goto l849 + l848: + position, tokenIndex = position848, tokenIndex848 } - l826: - add(ruleARMBaseIndexScale, position791) + l849: + add(ruleARMBaseIndexScale, position814) } return true - l790: - position, tokenIndex = position790, tokenIndex790 + l813: + position, tokenIndex = position813, tokenIndex813 return false }, - /* 50 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */ + /* 51 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */ func() bool { - position827, tokenIndex827 := position, tokenIndex + position850, tokenIndex850 := position, tokenIndex { - position828 := position + position851 := position if buffer[position] != rune(':') { - goto l827 + goto l850 } position++ { - position829, tokenIndex829 := position, tokenIndex + position852, tokenIndex852 := position, tokenIndex if buffer[position] != rune('g') { - goto l830 + goto l853 } position++ - goto l829 - l830: - position, tokenIndex = position829, tokenIndex829 + goto l852 + l853: + position, tokenIndex = position852, tokenIndex852 if buffer[position] != rune('G') { - goto l827 + goto l850 } position++ } - l829: + l852: { - position831, tokenIndex831 := position, tokenIndex + position854, tokenIndex854 := position, tokenIndex if buffer[position] != rune('o') { - goto l832 + goto l855 } position++ - goto l831 - l832: - position, tokenIndex = position831, tokenIndex831 + goto l854 + l855: + position, tokenIndex = position854, tokenIndex854 if buffer[position] != rune('O') { - goto l827 + goto l850 } position++ } - l831: + l854: { - position833, tokenIndex833 := position, tokenIndex + position856, tokenIndex856 := position, tokenIndex if buffer[position] != rune('t') { - goto l834 + goto l857 } position++ - goto l833 - l834: - position, tokenIndex = position833, tokenIndex833 + goto l856 + l857: + position, tokenIndex = position856, tokenIndex856 if buffer[position] != rune('T') { - goto l827 + goto l850 } position++ } - l833: + l856: if buffer[position] != rune('_') { - goto l827 + goto l850 } position++ { - position835, tokenIndex835 := position, tokenIndex + position858, tokenIndex858 := position, tokenIndex if buffer[position] != rune('l') { - goto l836 + goto l859 } position++ - goto l835 - l836: - position, tokenIndex = position835, tokenIndex835 + goto l858 + l859: + position, tokenIndex = position858, tokenIndex858 if buffer[position] != rune('L') { - goto l827 + goto l850 } position++ } - l835: + l858: { - position837, tokenIndex837 := position, tokenIndex + position860, tokenIndex860 := position, tokenIndex if buffer[position] != rune('o') { - goto l838 + goto l861 } position++ - goto l837 - l838: - position, tokenIndex = position837, tokenIndex837 + goto l860 + l861: + position, tokenIndex = position860, tokenIndex860 if buffer[position] != rune('O') { - goto l827 + goto l850 } position++ } - l837: + l860: if buffer[position] != rune('1') { - goto l827 + goto l850 } position++ if buffer[position] != rune('2') { - goto l827 + goto l850 } position++ if buffer[position] != rune(':') { - goto l827 + goto l850 } position++ if !_rules[ruleSymbolName]() { - goto l827 + goto l850 } - add(ruleARMGOTLow12, position828) + add(ruleARMGOTLow12, position851) } return true - l827: - position, tokenIndex = position827, tokenIndex827 + l850: + position, tokenIndex = position850, tokenIndex850 return false }, - /* 51 ARMPostincrement <- <'!'> */ + /* 52 ARMPostincrement <- <'!'> */ func() bool { - position839, tokenIndex839 := position, tokenIndex + position862, tokenIndex862 := position, tokenIndex { - position840 := position + position863 := position if buffer[position] != rune('!') { - goto l839 + goto l862 } position++ - add(ruleARMPostincrement, position840) + add(ruleARMPostincrement, position863) } return true - l839: - position, tokenIndex = position839, tokenIndex839 + l862: + position, tokenIndex = position862, tokenIndex862 return false }, - /* 52 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ + /* 53 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ func() bool { - position841, tokenIndex841 := position, tokenIndex + position864, tokenIndex864 := position, tokenIndex { - position842 := position + position865 := position if buffer[position] != rune('(') { - goto l841 + goto l864 } position++ { - position843, tokenIndex843 := position, tokenIndex + position866, tokenIndex866 := position, tokenIndex if !_rules[ruleRegisterOrConstant]() { - goto l843 + goto l866 } - goto l844 - l843: - position, tokenIndex = position843, tokenIndex843 + goto l867 + l866: + position, tokenIndex = position866, tokenIndex866 } - l844: + l867: { - position845, tokenIndex845 := position, tokenIndex + position868, tokenIndex868 := position, tokenIndex if !_rules[ruleWS]() { - goto l845 + goto l868 } - goto l846 - l845: - position, tokenIndex = position845, tokenIndex845 + goto l869 + l868: + position, tokenIndex = position868, tokenIndex868 } - l846: + l869: { - position847, tokenIndex847 := position, tokenIndex + position870, tokenIndex870 := position, tokenIndex if buffer[position] != rune(',') { - goto l847 + goto l870 } position++ { - position849, tokenIndex849 := position, tokenIndex + position872, tokenIndex872 := position, tokenIndex if !_rules[ruleWS]() { - goto l849 + goto l872 } - goto l850 - l849: - position, tokenIndex = position849, tokenIndex849 + goto l873 + l872: + position, tokenIndex = position872, tokenIndex872 } - l850: + l873: if !_rules[ruleRegisterOrConstant]() { - goto l847 + goto l870 } { - position851, tokenIndex851 := position, tokenIndex + position874, tokenIndex874 := position, tokenIndex if !_rules[ruleWS]() { - goto l851 + goto l874 } - goto l852 - l851: - position, tokenIndex = position851, tokenIndex851 + goto l875 + l874: + position, tokenIndex = position874, tokenIndex874 } - l852: + l875: { - position853, tokenIndex853 := position, tokenIndex + position876, tokenIndex876 := position, tokenIndex if buffer[position] != rune(',') { - goto l853 + goto l876 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l853 + goto l876 } position++ - l855: + l878: { - position856, tokenIndex856 := position, tokenIndex + position879, tokenIndex879 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l856 + goto l879 } position++ - goto l855 - l856: - position, tokenIndex = position856, tokenIndex856 + goto l878 + l879: + position, tokenIndex = position879, tokenIndex879 } - goto l854 - l853: - position, tokenIndex = position853, tokenIndex853 + goto l877 + l876: + position, tokenIndex = position876, tokenIndex876 } - l854: - goto l848 - l847: - position, tokenIndex = position847, tokenIndex847 + l877: + goto l871 + l870: + position, tokenIndex = position870, tokenIndex870 } - l848: + l871: if buffer[position] != rune(')') { - goto l841 + goto l864 } position++ - add(ruleBaseIndexScale, position842) + add(ruleBaseIndexScale, position865) } return true - l841: - position, tokenIndex = position841, tokenIndex841 + l864: + position, tokenIndex = position864, tokenIndex864 return false }, - /* 53 Operator <- <('+' / '-')> */ + /* 54 Operator <- <('+' / '-')> */ func() bool { - position857, tokenIndex857 := position, tokenIndex + position880, tokenIndex880 := position, tokenIndex { - position858 := position + position881 := position { - position859, tokenIndex859 := position, tokenIndex + position882, tokenIndex882 := position, tokenIndex if buffer[position] != rune('+') { - goto l860 + goto l883 } position++ - goto l859 - l860: - position, tokenIndex = position859, tokenIndex859 + goto l882 + l883: + position, tokenIndex = position882, tokenIndex882 if buffer[position] != rune('-') { - goto l857 + goto l880 } position++ } - l859: - add(ruleOperator, position858) + l882: + add(ruleOperator, position881) } return true - l857: - position, tokenIndex = position857, tokenIndex857 + l880: + position, tokenIndex = position880, tokenIndex880 return false }, - /* 54 OffsetOperator <- <('+' / '-' / '*')> */ + /* 55 OffsetOperator <- <('+' / '-' / '*')> */ func() bool { - position861, tokenIndex861 := position, tokenIndex + position884, tokenIndex884 := position, tokenIndex { - position862 := position + position885 := position { - position863, tokenIndex863 := position, tokenIndex + position886, tokenIndex886 := position, tokenIndex if buffer[position] != rune('+') { - goto l864 + goto l887 } position++ - goto l863 - l864: - position, tokenIndex = position863, tokenIndex863 + goto l886 + l887: + position, tokenIndex = position886, tokenIndex886 if buffer[position] != rune('-') { - goto l865 + goto l888 } position++ - goto l863 - l865: - position, tokenIndex = position863, tokenIndex863 + goto l886 + l888: + position, tokenIndex = position886, tokenIndex886 if buffer[position] != rune('*') { - goto l861 + goto l884 } position++ } - l863: - add(ruleOffsetOperator, position862) + l886: + add(ruleOffsetOperator, position885) } return true - l861: - position, tokenIndex = position861, tokenIndex861 + l884: + position, tokenIndex = position884, tokenIndex884 return false }, - /* 55 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / ((([0-9]+ WS OffsetOperator [0-9]+) / ([0-9]+ (OffsetOperator '(' [0-9]+ OffsetOperator [0-9]+ ')')?) / ([0-9]+ (OffsetOperator [0-9]+ OffsetOperator [0-9]+)?) / ([0-9]+ (OffsetOperator [0-9]+)?) / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ ')' OffsetOperator [0-9]+ OffsetOperator [0-9]+) / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ ')' OffsetOperator [0-9]+ !'x') / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ ')') / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ WS? OffsetOperator WS? [0-9]+ ')')) !([a-z] / [A-Z]))))> */ + /* 56 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / ((([0-9]+ WS OffsetOperator [0-9]+) / ([0-9]+ (OffsetOperator '(' [0-9]+ OffsetOperator [0-9]+ ')')?) / ([0-9]+ (OffsetOperator [0-9]+ OffsetOperator [0-9]+)?) / ([0-9]+ (OffsetOperator [0-9]+)?) / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ ')' OffsetOperator [0-9]+ OffsetOperator [0-9]+) / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ ')' OffsetOperator [0-9]+ !'x') / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ ')') / ('(' [0-9]+ WS? OffsetOperator WS? [0-9]+ WS? OffsetOperator WS? [0-9]+ ')')) !([a-z] / [A-Z]))))> */ func() bool { - position866, tokenIndex866 := position, tokenIndex + position889, tokenIndex889 := position, tokenIndex { - position867 := position + position890 := position { - position868, tokenIndex868 := position, tokenIndex + position891, tokenIndex891 := position, tokenIndex if buffer[position] != rune('+') { - goto l868 + goto l891 } position++ - goto l869 - l868: - position, tokenIndex = position868, tokenIndex868 + goto l892 + l891: + position, tokenIndex = position891, tokenIndex891 } - l869: + l892: { - position870, tokenIndex870 := position, tokenIndex + position893, tokenIndex893 := position, tokenIndex if buffer[position] != rune('-') { - goto l870 + goto l893 } position++ - goto l871 - l870: - position, tokenIndex = position870, tokenIndex870 + goto l894 + l893: + position, tokenIndex = position893, tokenIndex893 } - l871: + l894: { - position872, tokenIndex872 := position, tokenIndex + position895, tokenIndex895 := position, tokenIndex if buffer[position] != rune('0') { - goto l873 + goto l896 } position++ { - position874, tokenIndex874 := position, tokenIndex + position897, tokenIndex897 := position, tokenIndex if buffer[position] != rune('b') { - goto l875 + goto l898 } position++ - goto l874 - l875: - position, tokenIndex = position874, tokenIndex874 + goto l897 + l898: + position, tokenIndex = position897, tokenIndex897 if buffer[position] != rune('B') { - goto l873 + goto l896 } position++ } - l874: + l897: { - position878, tokenIndex878 := position, tokenIndex + position901, tokenIndex901 := position, tokenIndex if buffer[position] != rune('0') { - goto l879 + goto l902 } position++ - goto l878 - l879: - position, tokenIndex = position878, tokenIndex878 + goto l901 + l902: + position, tokenIndex = position901, tokenIndex901 if buffer[position] != rune('1') { - goto l873 + goto l896 } position++ } - l878: - l876: + l901: + l899: { - position877, tokenIndex877 := position, tokenIndex + position900, tokenIndex900 := position, tokenIndex { - position880, tokenIndex880 := position, tokenIndex + position903, tokenIndex903 := position, tokenIndex if buffer[position] != rune('0') { - goto l881 + goto l904 } position++ - goto l880 - l881: - position, tokenIndex = position880, tokenIndex880 + goto l903 + l904: + position, tokenIndex = position903, tokenIndex903 if buffer[position] != rune('1') { - goto l877 + goto l900 } position++ } - l880: - goto l876 - l877: - position, tokenIndex = position877, tokenIndex877 + l903: + goto l899 + l900: + position, tokenIndex = position900, tokenIndex900 } - goto l872 - l873: - position, tokenIndex = position872, tokenIndex872 + goto l895 + l896: + position, tokenIndex = position895, tokenIndex895 if buffer[position] != rune('0') { - goto l882 + goto l905 } position++ { - position883, tokenIndex883 := position, tokenIndex + position906, tokenIndex906 := position, tokenIndex if buffer[position] != rune('x') { - goto l884 + goto l907 } position++ - goto l883 - l884: - position, tokenIndex = position883, tokenIndex883 + goto l906 + l907: + position, tokenIndex = position906, tokenIndex906 if buffer[position] != rune('X') { - goto l882 + goto l905 } position++ } - l883: + l906: { - position887, tokenIndex887 := position, tokenIndex + position910, tokenIndex910 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l888 + goto l911 } position++ - goto l887 - l888: - position, tokenIndex = position887, tokenIndex887 + goto l910 + l911: + position, tokenIndex = position910, tokenIndex910 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l889 + goto l912 } position++ - goto l887 - l889: - position, tokenIndex = position887, tokenIndex887 + goto l910 + l912: + position, tokenIndex = position910, tokenIndex910 { - position890, tokenIndex890 := position, tokenIndex + position913, tokenIndex913 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l891 + goto l914 } position++ - goto l890 - l891: - position, tokenIndex = position890, tokenIndex890 + goto l913 + l914: + position, tokenIndex = position913, tokenIndex913 if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l882 + goto l905 } position++ } - l890: + l913: } - l887: - l885: + l910: + l908: { - position886, tokenIndex886 := position, tokenIndex + position909, tokenIndex909 := position, tokenIndex { - position892, tokenIndex892 := position, tokenIndex + position915, tokenIndex915 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l893 + goto l916 } position++ - goto l892 - l893: - position, tokenIndex = position892, tokenIndex892 + goto l915 + l916: + position, tokenIndex = position915, tokenIndex915 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l894 + goto l917 } position++ - goto l892 - l894: - position, tokenIndex = position892, tokenIndex892 + goto l915 + l917: + position, tokenIndex = position915, tokenIndex915 { - position895, tokenIndex895 := position, tokenIndex + position918, tokenIndex918 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l896 + goto l919 } position++ - goto l895 - l896: - position, tokenIndex = position895, tokenIndex895 + goto l918 + l919: + position, tokenIndex = position918, tokenIndex918 if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l886 + goto l909 } position++ } - l895: + l918: } - l892: - goto l885 - l886: - position, tokenIndex = position886, tokenIndex886 + l915: + goto l908 + l909: + position, tokenIndex = position909, tokenIndex909 } - goto l872 - l882: - position, tokenIndex = position872, tokenIndex872 + goto l895 + l905: + position, tokenIndex = position895, tokenIndex895 { - position897, tokenIndex897 := position, tokenIndex + position920, tokenIndex920 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l898 + goto l921 } position++ - l899: + l922: { - position900, tokenIndex900 := position, tokenIndex + position923, tokenIndex923 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l900 + goto l923 } position++ - goto l899 - l900: - position, tokenIndex = position900, tokenIndex900 + goto l922 + l923: + position, tokenIndex = position923, tokenIndex923 } if !_rules[ruleWS]() { - goto l898 + goto l921 } if !_rules[ruleOffsetOperator]() { - goto l898 + goto l921 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l898 + goto l921 } position++ - l901: + l924: { - position902, tokenIndex902 := position, tokenIndex + position925, tokenIndex925 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l902 + goto l925 } position++ - goto l901 - l902: - position, tokenIndex = position902, tokenIndex902 + goto l924 + l925: + position, tokenIndex = position925, tokenIndex925 } - goto l897 - l898: - position, tokenIndex = position897, tokenIndex897 + goto l920 + l921: + position, tokenIndex = position920, tokenIndex920 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l903 + goto l926 } position++ - l904: + l927: { - position905, tokenIndex905 := position, tokenIndex + position928, tokenIndex928 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l905 + goto l928 } position++ - goto l904 - l905: - position, tokenIndex = position905, tokenIndex905 + goto l927 + l928: + position, tokenIndex = position928, tokenIndex928 } { - position906, tokenIndex906 := position, tokenIndex + position929, tokenIndex929 := position, tokenIndex if !_rules[ruleOffsetOperator]() { - goto l906 + goto l929 } if buffer[position] != rune('(') { - goto l906 + goto l929 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l906 + goto l929 } position++ - l908: + l931: { - position909, tokenIndex909 := position, tokenIndex + position932, tokenIndex932 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l909 + goto l932 } position++ - goto l908 - l909: - position, tokenIndex = position909, tokenIndex909 + goto l931 + l932: + position, tokenIndex = position932, tokenIndex932 } if !_rules[ruleOffsetOperator]() { - goto l906 + goto l929 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l906 + goto l929 } position++ - l910: + l933: { - position911, tokenIndex911 := position, tokenIndex + position934, tokenIndex934 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l911 + goto l934 } position++ - goto l910 - l911: - position, tokenIndex = position911, tokenIndex911 + goto l933 + l934: + position, tokenIndex = position934, tokenIndex934 } if buffer[position] != rune(')') { - goto l906 + goto l929 } position++ - goto l907 - l906: - position, tokenIndex = position906, tokenIndex906 - } - l907: - goto l897 - l903: - position, tokenIndex = position897, tokenIndex897 + goto l930 + l929: + position, tokenIndex = position929, tokenIndex929 + } + l930: + goto l920 + l926: + position, tokenIndex = position920, tokenIndex920 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l912 + goto l935 } position++ - l913: + l936: { - position914, tokenIndex914 := position, tokenIndex + position937, tokenIndex937 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l914 + goto l937 } position++ - goto l913 - l914: - position, tokenIndex = position914, tokenIndex914 + goto l936 + l937: + position, tokenIndex = position937, tokenIndex937 } { - position915, tokenIndex915 := position, tokenIndex + position938, tokenIndex938 := position, tokenIndex if !_rules[ruleOffsetOperator]() { - goto l915 + goto l938 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l915 + goto l938 } position++ - l917: + l940: { - position918, tokenIndex918 := position, tokenIndex + position941, tokenIndex941 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l918 + goto l941 } position++ - goto l917 - l918: - position, tokenIndex = position918, tokenIndex918 + goto l940 + l941: + position, tokenIndex = position941, tokenIndex941 } if !_rules[ruleOffsetOperator]() { - goto l915 + goto l938 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l915 + goto l938 } position++ - l919: + l942: { - position920, tokenIndex920 := position, tokenIndex + position943, tokenIndex943 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l920 + goto l943 } position++ - goto l919 - l920: - position, tokenIndex = position920, tokenIndex920 + goto l942 + l943: + position, tokenIndex = position943, tokenIndex943 } - goto l916 - l915: - position, tokenIndex = position915, tokenIndex915 + goto l939 + l938: + position, tokenIndex = position938, tokenIndex938 } - l916: - goto l897 - l912: - position, tokenIndex = position897, tokenIndex897 + l939: + goto l920 + l935: + position, tokenIndex = position920, tokenIndex920 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l921 + goto l944 } position++ - l922: + l945: { - position923, tokenIndex923 := position, tokenIndex + position946, tokenIndex946 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l923 + goto l946 } position++ - goto l922 - l923: - position, tokenIndex = position923, tokenIndex923 + goto l945 + l946: + position, tokenIndex = position946, tokenIndex946 } { - position924, tokenIndex924 := position, tokenIndex + position947, tokenIndex947 := position, tokenIndex if !_rules[ruleOffsetOperator]() { - goto l924 + goto l947 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l924 + goto l947 } position++ - l926: + l949: { - position927, tokenIndex927 := position, tokenIndex + position950, tokenIndex950 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l927 + goto l950 } position++ - goto l926 - l927: - position, tokenIndex = position927, tokenIndex927 + goto l949 + l950: + position, tokenIndex = position950, tokenIndex950 } - goto l925 - l924: - position, tokenIndex = position924, tokenIndex924 + goto l948 + l947: + position, tokenIndex = position947, tokenIndex947 } - l925: - goto l897 - l921: - position, tokenIndex = position897, tokenIndex897 + l948: + goto l920 + l944: + position, tokenIndex = position920, tokenIndex920 if buffer[position] != rune('(') { - goto l928 + goto l951 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l928 + goto l951 } position++ - l929: + l952: { - position930, tokenIndex930 := position, tokenIndex + position953, tokenIndex953 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l930 + goto l953 } position++ - goto l929 - l930: - position, tokenIndex = position930, tokenIndex930 + goto l952 + l953: + position, tokenIndex = position953, tokenIndex953 } { - position931, tokenIndex931 := position, tokenIndex + position954, tokenIndex954 := position, tokenIndex if !_rules[ruleWS]() { - goto l931 + goto l954 } - goto l932 - l931: - position, tokenIndex = position931, tokenIndex931 + goto l955 + l954: + position, tokenIndex = position954, tokenIndex954 } - l932: + l955: if !_rules[ruleOffsetOperator]() { - goto l928 + goto l951 } { - position933, tokenIndex933 := position, tokenIndex + position956, tokenIndex956 := position, tokenIndex if !_rules[ruleWS]() { - goto l933 + goto l956 } - goto l934 - l933: - position, tokenIndex = position933, tokenIndex933 + goto l957 + l956: + position, tokenIndex = position956, tokenIndex956 } - l934: + l957: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l928 + goto l951 } position++ - l935: + l958: { - position936, tokenIndex936 := position, tokenIndex + position959, tokenIndex959 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l936 + goto l959 } position++ - goto l935 - l936: - position, tokenIndex = position936, tokenIndex936 + goto l958 + l959: + position, tokenIndex = position959, tokenIndex959 } if buffer[position] != rune(')') { - goto l928 + goto l951 } position++ if !_rules[ruleOffsetOperator]() { - goto l928 + goto l951 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l928 + goto l951 } position++ - l937: + l960: { - position938, tokenIndex938 := position, tokenIndex + position961, tokenIndex961 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l938 + goto l961 } position++ - goto l937 - l938: - position, tokenIndex = position938, tokenIndex938 + goto l960 + l961: + position, tokenIndex = position961, tokenIndex961 } if !_rules[ruleOffsetOperator]() { - goto l928 + goto l951 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l928 + goto l951 } position++ - l939: + l962: { - position940, tokenIndex940 := position, tokenIndex + position963, tokenIndex963 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l940 + goto l963 } position++ - goto l939 - l940: - position, tokenIndex = position940, tokenIndex940 + goto l962 + l963: + position, tokenIndex = position963, tokenIndex963 } - goto l897 - l928: - position, tokenIndex = position897, tokenIndex897 + goto l920 + l951: + position, tokenIndex = position920, tokenIndex920 if buffer[position] != rune('(') { - goto l941 + goto l964 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l941 + goto l964 } position++ - l942: + l965: { - position943, tokenIndex943 := position, tokenIndex + position966, tokenIndex966 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l943 + goto l966 } position++ - goto l942 - l943: - position, tokenIndex = position943, tokenIndex943 + goto l965 + l966: + position, tokenIndex = position966, tokenIndex966 } { - position944, tokenIndex944 := position, tokenIndex + position967, tokenIndex967 := position, tokenIndex if !_rules[ruleWS]() { - goto l944 + goto l967 } - goto l945 - l944: - position, tokenIndex = position944, tokenIndex944 + goto l968 + l967: + position, tokenIndex = position967, tokenIndex967 } - l945: + l968: if !_rules[ruleOffsetOperator]() { - goto l941 + goto l964 } { - position946, tokenIndex946 := position, tokenIndex + position969, tokenIndex969 := position, tokenIndex if !_rules[ruleWS]() { - goto l946 + goto l969 } - goto l947 - l946: - position, tokenIndex = position946, tokenIndex946 + goto l970 + l969: + position, tokenIndex = position969, tokenIndex969 } - l947: + l970: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l941 + goto l964 } position++ - l948: + l971: { - position949, tokenIndex949 := position, tokenIndex + position972, tokenIndex972 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l949 + goto l972 } position++ - goto l948 - l949: - position, tokenIndex = position949, tokenIndex949 + goto l971 + l972: + position, tokenIndex = position972, tokenIndex972 } if buffer[position] != rune(')') { - goto l941 + goto l964 } position++ if !_rules[ruleOffsetOperator]() { - goto l941 + goto l964 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l941 + goto l964 } position++ - l950: + l973: { - position951, tokenIndex951 := position, tokenIndex + position974, tokenIndex974 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l951 + goto l974 } position++ - goto l950 - l951: - position, tokenIndex = position951, tokenIndex951 + goto l973 + l974: + position, tokenIndex = position974, tokenIndex974 } { - position952, tokenIndex952 := position, tokenIndex + position975, tokenIndex975 := position, tokenIndex if buffer[position] != rune('x') { - goto l952 + goto l975 } position++ - goto l941 - l952: - position, tokenIndex = position952, tokenIndex952 + goto l964 + l975: + position, tokenIndex = position975, tokenIndex975 } - goto l897 - l941: - position, tokenIndex = position897, tokenIndex897 + goto l920 + l964: + position, tokenIndex = position920, tokenIndex920 if buffer[position] != rune('(') { - goto l953 + goto l976 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l953 + goto l976 } position++ - l954: + l977: { - position955, tokenIndex955 := position, tokenIndex + position978, tokenIndex978 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l955 + goto l978 } position++ - goto l954 - l955: - position, tokenIndex = position955, tokenIndex955 + goto l977 + l978: + position, tokenIndex = position978, tokenIndex978 } { - position956, tokenIndex956 := position, tokenIndex + position979, tokenIndex979 := position, tokenIndex if !_rules[ruleWS]() { - goto l956 + goto l979 } - goto l957 - l956: - position, tokenIndex = position956, tokenIndex956 + goto l980 + l979: + position, tokenIndex = position979, tokenIndex979 } - l957: + l980: if !_rules[ruleOffsetOperator]() { - goto l953 + goto l976 } { - position958, tokenIndex958 := position, tokenIndex + position981, tokenIndex981 := position, tokenIndex if !_rules[ruleWS]() { - goto l958 + goto l981 } - goto l959 - l958: - position, tokenIndex = position958, tokenIndex958 + goto l982 + l981: + position, tokenIndex = position981, tokenIndex981 } - l959: + l982: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l953 + goto l976 } position++ - l960: + l983: { - position961, tokenIndex961 := position, tokenIndex + position984, tokenIndex984 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l961 + goto l984 } position++ - goto l960 - l961: - position, tokenIndex = position961, tokenIndex961 + goto l983 + l984: + position, tokenIndex = position984, tokenIndex984 } if buffer[position] != rune(')') { - goto l953 + goto l976 } position++ - goto l897 - l953: - position, tokenIndex = position897, tokenIndex897 + goto l920 + l976: + position, tokenIndex = position920, tokenIndex920 if buffer[position] != rune('(') { - goto l866 + goto l889 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l866 + goto l889 } position++ - l962: + l985: { - position963, tokenIndex963 := position, tokenIndex + position986, tokenIndex986 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l963 + goto l986 } position++ - goto l962 - l963: - position, tokenIndex = position963, tokenIndex963 + goto l985 + l986: + position, tokenIndex = position986, tokenIndex986 } { - position964, tokenIndex964 := position, tokenIndex + position987, tokenIndex987 := position, tokenIndex if !_rules[ruleWS]() { - goto l964 + goto l987 } - goto l965 - l964: - position, tokenIndex = position964, tokenIndex964 + goto l988 + l987: + position, tokenIndex = position987, tokenIndex987 } - l965: + l988: if !_rules[ruleOffsetOperator]() { - goto l866 + goto l889 } { - position966, tokenIndex966 := position, tokenIndex + position989, tokenIndex989 := position, tokenIndex if !_rules[ruleWS]() { - goto l966 + goto l989 } - goto l967 - l966: - position, tokenIndex = position966, tokenIndex966 + goto l990 + l989: + position, tokenIndex = position989, tokenIndex989 } - l967: + l990: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l866 + goto l889 } position++ - l968: + l991: { - position969, tokenIndex969 := position, tokenIndex + position992, tokenIndex992 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l969 + goto l992 } position++ - goto l968 - l969: - position, tokenIndex = position969, tokenIndex969 + goto l991 + l992: + position, tokenIndex = position992, tokenIndex992 } { - position970, tokenIndex970 := position, tokenIndex + position993, tokenIndex993 := position, tokenIndex if !_rules[ruleWS]() { - goto l970 + goto l993 } - goto l971 - l970: - position, tokenIndex = position970, tokenIndex970 + goto l994 + l993: + position, tokenIndex = position993, tokenIndex993 } - l971: + l994: if !_rules[ruleOffsetOperator]() { - goto l866 + goto l889 } { - position972, tokenIndex972 := position, tokenIndex + position995, tokenIndex995 := position, tokenIndex if !_rules[ruleWS]() { - goto l972 + goto l995 } - goto l973 - l972: - position, tokenIndex = position972, tokenIndex972 + goto l996 + l995: + position, tokenIndex = position995, tokenIndex995 } - l973: + l996: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l866 + goto l889 } position++ - l974: + l997: { - position975, tokenIndex975 := position, tokenIndex + position998, tokenIndex998 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l975 + goto l998 } position++ - goto l974 - l975: - position, tokenIndex = position975, tokenIndex975 + goto l997 + l998: + position, tokenIndex = position998, tokenIndex998 } if buffer[position] != rune(')') { - goto l866 + goto l889 } position++ } - l897: + l920: { - position976, tokenIndex976 := position, tokenIndex + position999, tokenIndex999 := position, tokenIndex { - position977, tokenIndex977 := position, tokenIndex + position1000, tokenIndex1000 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l978 + goto l1001 } position++ - goto l977 - l978: - position, tokenIndex = position977, tokenIndex977 + goto l1000 + l1001: + position, tokenIndex = position1000, tokenIndex1000 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l976 + goto l999 } position++ } - l977: - goto l866 - l976: - position, tokenIndex = position976, tokenIndex976 + l1000: + goto l889 + l999: + position, tokenIndex = position999, tokenIndex999 } } - l872: - add(ruleOffset, position867) + l895: + add(ruleOffset, position890) } return true - l866: - position, tokenIndex = position866, tokenIndex866 + l889: + position, tokenIndex = position889, tokenIndex889 return false }, - /* 56 Section <- <([a-z] / [A-Z] / '@')+> */ + /* 57 Section <- <([a-z] / [A-Z] / '@')+> */ func() bool { - position979, tokenIndex979 := position, tokenIndex + position1002, tokenIndex1002 := position, tokenIndex { - position980 := position + position1003 := position { - position983, tokenIndex983 := position, tokenIndex + position1006, tokenIndex1006 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l984 + goto l1007 } position++ - goto l983 - l984: - position, tokenIndex = position983, tokenIndex983 + goto l1006 + l1007: + position, tokenIndex = position1006, tokenIndex1006 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l985 + goto l1008 } position++ - goto l983 - l985: - position, tokenIndex = position983, tokenIndex983 + goto l1006 + l1008: + position, tokenIndex = position1006, tokenIndex1006 if buffer[position] != rune('@') { - goto l979 + goto l1002 } position++ } - l983: - l981: + l1006: + l1004: { - position982, tokenIndex982 := position, tokenIndex + position1005, tokenIndex1005 := position, tokenIndex { - position986, tokenIndex986 := position, tokenIndex + position1009, tokenIndex1009 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l987 + goto l1010 } position++ - goto l986 - l987: - position, tokenIndex = position986, tokenIndex986 + goto l1009 + l1010: + position, tokenIndex = position1009, tokenIndex1009 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l988 + goto l1011 } position++ - goto l986 - l988: - position, tokenIndex = position986, tokenIndex986 + goto l1009 + l1011: + position, tokenIndex = position1009, tokenIndex1009 if buffer[position] != rune('@') { - goto l982 + goto l1005 } position++ } - l986: - goto l981 - l982: - position, tokenIndex = position982, tokenIndex982 + l1009: + goto l1004 + l1005: + position, tokenIndex = position1005, tokenIndex1005 } - add(ruleSection, position980) + add(ruleSection, position1003) } return true - l979: - position, tokenIndex = position979, tokenIndex979 + l1002: + position, tokenIndex = position1002, tokenIndex1002 return false }, - /* 57 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ + /* 58 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ func() bool { - position989, tokenIndex989 := position, tokenIndex + position1012, tokenIndex1012 := position, tokenIndex { - position990 := position + position1013 := position if buffer[position] != rune('%') { - goto l989 + goto l1012 } position++ { - position991, tokenIndex991 := position, tokenIndex + position1014, tokenIndex1014 := position, tokenIndex if c := buffer[position]; c < rune('c') || c > rune('g') { - goto l992 + goto l1015 } position++ - goto l991 - l992: - position, tokenIndex = position991, tokenIndex991 + goto l1014 + l1015: + position, tokenIndex = position1014, tokenIndex1014 if buffer[position] != rune('s') { - goto l989 + goto l1012 } position++ } - l991: + l1014: if buffer[position] != rune('s') { - goto l989 + goto l1012 } position++ if buffer[position] != rune(':') { - goto l989 + goto l1012 } position++ - add(ruleSegmentRegister, position990) + add(ruleSegmentRegister, position1013) } return true - l989: - position, tokenIndex = position989, tokenIndex989 + l1012: + position, tokenIndex = position1012, tokenIndex1012 return false }, } diff --git a/util/fipstools/delocate/testdata/aarch64-Basic/in.s b/util/fipstools/delocate/testdata/aarch64-Basic/in.s index c65a88f0c7..a06a592b40 100644 --- a/util/fipstools/delocate/testdata/aarch64-Basic/in.s +++ b/util/fipstools/delocate/testdata/aarch64-Basic/in.s @@ -91,6 +91,10 @@ foo: adrp x4, :got:BORINGSSL_bcm_text_start adrp x5, :got:BORINGSSL_bcm_text_end + // Aarch64 SVE2 added these forms: + ld1d { z1.d }, p0/z, [x13, x11, lsl #3] + ld1b { z11.b }, p15/z, [x10, #1, mul vl] + local_function: // BSS data diff --git a/util/fipstools/delocate/testdata/aarch64-Basic/out.s b/util/fipstools/delocate/testdata/aarch64-Basic/out.s index dafe5d2a9b..b6860b20ab 100644 --- a/util/fipstools/delocate/testdata/aarch64-Basic/out.s +++ b/util/fipstools/delocate/testdata/aarch64-Basic/out.s @@ -159,6 +159,10 @@ foo: ldp x0, x30, [sp], #16 add sp, sp, 128 + // Aarch64 SVE2 added these forms: + ld1d { z1.d }, p0/z, [x13, x11, lsl #3] + ld1b { z11.b }, p15/z, [x10, #1, mul vl] + .Llocal_function_local_target: local_function: From f1b7084b93bc426206408d54cd74a1a26867a373 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Tue, 9 Jan 2024 16:21:53 -0800 Subject: [PATCH 2/5] Fix threads detection for CROS_EC/CROS_ZEPHYR The CROS_EC and CROS_ZEPHYR platforms currently have threads disabled, so we should not attempt to search for (or link) a threads library. BUG=b/273639386 Change-Id: I094a989680160f9ecefbdb4cb3e94c4825a651e3 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65568 Reviewed-by: David Benjamin Reviewed-by: Bob Beck Commit-Queue: Bob Beck (cherry picked from commit becb3ffccdecff83047285ebea20e5b85b2d65b1) --- crypto/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 63af5a4cff..b4a9154b4d 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -701,7 +701,11 @@ else() build_libcrypto(crypto $) endif() -if(NOT ANDROID) +# CMAKE_SYSTEM_NAME is "Generic" for embedded OSes: +# https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html#toolchain-files +# +# For now we assume embedded OSes do not have threads. +if(NOT (ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "Generic")) find_package(Threads REQUIRED) target_link_libraries(crypto PUBLIC Threads::Threads) endif() From bc2cdcd7885e25adedf1c42b946c1597bf052196 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 25 Dec 2023 18:24:41 -0500 Subject: [PATCH 3/5] Document and test X509_PURPOSE and X509_TRUST machinery The trust and purpose is all a bit tied up together, as is the meaning of the certificates in an X509_STORE at all. (It's hard to discuss whether a "trusted certificate" is actually a trust anchor without a description of trust settings to reference.) Cut the Gordian Knot by documenting all that first. Later CLs will move other symbols into the sections established here. Also as the behavior is a little complex, add some tests to cover some of this machinery. Bug: 426 Change-Id: Idde8bc4e588de92ebabf6ecf640b62a2a6803688 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65207 Commit-Queue: David Benjamin Reviewed-by: Bob Beck (cherry picked from commit 352740cef428f0f1eccdfff8dca9aaf1f85e31e4) AWS-LC: Moved functions around in x509.h Added two new tests to x509_test.cc --- crypto/x509/v3_purp.c | 19 +- crypto/x509/x509_test.cc | 406 ++++++++++++++++++++++++++++++ crypto/x509/x509_trs.c | 8 +- crypto/x509/x509_vfy.c | 3 +- include/openssl/x509.h | 524 +++++++++++++++++++++++++++++---------- 5 files changed, 810 insertions(+), 150 deletions(-) diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c index fdd920f779..f8cd1b8c3d 100644 --- a/crypto/x509/v3_purp.c +++ b/crypto/x509/v3_purp.c @@ -437,6 +437,10 @@ static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, return 0; } if (ca) { + // TODO(davidben): Move the various |check_ca| calls out of the + // |check_purpose| callbacks. Those checks are purpose-independent. They are + // also redundant when called from |X509_verify_cert|, though + // not when |X509_check_purpose| is called directly. return check_ca(x); } // We need to do digital signatures or key agreement @@ -478,8 +482,7 @@ static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca) { - int ret; - ret = check_purpose_ssl_server(xp, x, ca); + int ret = check_purpose_ssl_server(xp, x, ca); if (!ret || ca) { return ret; } @@ -512,8 +515,7 @@ static int purpose_smime(const X509 *x, int ca) { static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca) { - int ret; - ret = purpose_smime(x, ca); + int ret = purpose_smime(x, ca); if (!ret || ca) { return ret; } @@ -525,8 +527,7 @@ static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca) { - int ret; - ret = purpose_smime(x, ca); + int ret = purpose_smime(x, ca); if (!ret || ca) { return ret; } @@ -560,8 +561,6 @@ static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) { static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca) { - int i_ext; - // If ca is true we must return if this is a valid CA certificate. if (ca) { return check_ca(x); @@ -585,9 +584,9 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, } // Extended Key Usage MUST be critical - i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1); + int i_ext = X509_get_ext_by_NID(x, NID_ext_key_usage, -1); if (i_ext >= 0) { - const X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); + const X509_EXTENSION *ext = X509_get_ext(x, i_ext); if (!X509_EXTENSION_get_critical(ext)) { return 0; } diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index 6d78309855..105134c4a3 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -2223,6 +2223,46 @@ static bssl::UniquePtr MakeTestCert(const char *issuer, return cert; } +static bool AddExtendedKeyUsage(X509 *x509, const std::vector &eku_nids) { + bssl::UniquePtr objs(sk_ASN1_OBJECT_new_null()); + if (objs == nullptr) { + return false; + } + for (int nid : eku_nids) { + if (!sk_ASN1_OBJECT_push(objs.get(), OBJ_nid2obj(nid))) { + return false; + } + } + return X509_add1_ext_i2d(x509, NID_ext_key_usage, objs.get(), /*crit=*/1, + /*flags=*/0); +} + +enum class KeyUsage : int { + kDigitalSignature = 0, + kNonRepudiation = 1, + kKeyEncipherment = 2, + kDataEncipherment = 3, + kKeyAgreement = 4, + kKeyCertSign = 5, + kCRLSign = 6, + kEncipherOnly = 7, + kDecipherOnly = 8, +}; + +static bool AddKeyUsage(X509 *x509, const std::vector usages) { + bssl::UniquePtr str(ASN1_BIT_STRING_new()); + if (str == nullptr) { + return false; + } + for (KeyUsage usage : usages) { + if (!ASN1_BIT_STRING_set_bit(str.get(), static_cast(usage), 1)) { + return false; + } + } + return X509_add1_ext_i2d(x509, NID_key_usage, str.get(), /*crit=*/1, + /*flags=*/0); +} + TEST(X509Test, NameConstraints) { bssl::UniquePtr key = PrivateKeyFromPEM(kP256Key); ASSERT_TRUE(key); @@ -3295,6 +3335,15 @@ TEST(X509Test, NoBasicConstraintsCertSign) { // basicConstraints. EXPECT_EQ(X509_V_ERR_INVALID_CA, Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0)); + + // |X509_check_purpose| with |X509_PURPOSE_ANY| and purpose -1 do not check + // basicConstraints, but other purpose types do. (This is redundant with the + // actual basicConstraints check, but |X509_check_purpose| is public API.) + EXPECT_TRUE(X509_check_purpose(intermediate.get(), -1, /*ca=*/1)); + EXPECT_TRUE( + X509_check_purpose(intermediate.get(), X509_PURPOSE_ANY, /*ca=*/1)); + EXPECT_FALSE(X509_check_purpose(intermediate.get(), X509_PURPOSE_SSL_SERVER, + /*ca=*/1)); } TEST(X509Test, NoBasicConstraintsNetscapeCA) { @@ -7719,3 +7768,360 @@ TEST(X509Test, SPKIPrint) { strlen(expected_certificate_string)); EXPECT_EQ(print, expected_certificate_string); } + +// Tests some unusual behavior in |X509_STORE_CTX_set_purpose| and +// |X509_STORE_CTX_set_trust|. +TEST(X509Test, ContextTrustAndPurpose) { + bssl::UniquePtr store(X509_STORE_new()); + ASSERT_TRUE(store); + bssl::UniquePtr leaf(CertFromPEM(kLeafPEM)); + ASSERT_TRUE(leaf); + + bssl::UniquePtr ctx(X509_STORE_CTX_new()); + ASSERT_TRUE(ctx); + ASSERT_TRUE(X509_STORE_CTX_init(ctx.get(), store.get(), leaf.get(), nullptr)); + + // Initially, neither parameter is set. + EXPECT_EQ(ctx->param->purpose, 0); + EXPECT_EQ(ctx->param->trust, 0); + + // Invalid purpose and trust types fail. + EXPECT_FALSE(X509_STORE_CTX_set_purpose(ctx.get(), 999)); + EXPECT_FALSE(X509_STORE_CTX_set_trust(ctx.get(), 999)); + + // It is not possible to set |X509_PURPOSE_ANY| with this API, because there + // is no corresponding trust. + EXPECT_FALSE(X509_STORE_CTX_set_purpose(ctx.get(), X509_PURPOSE_ANY)); + + // Setting a purpose also sets the corresponding trust. + ASSERT_TRUE(X509_STORE_CTX_set_purpose(ctx.get(), X509_PURPOSE_SSL_SERVER)); + EXPECT_EQ(ctx->param->purpose, X509_PURPOSE_SSL_SERVER); + EXPECT_EQ(ctx->param->trust, X509_TRUST_SSL_SERVER); + + // Once set, the functions silently do nothing. + ASSERT_TRUE(X509_STORE_CTX_set_purpose(ctx.get(), X509_PURPOSE_SSL_CLIENT)); + ASSERT_TRUE(X509_STORE_CTX_set_trust(ctx.get(), X509_TRUST_SSL_CLIENT)); + EXPECT_EQ(ctx->param->purpose, X509_PURPOSE_SSL_SERVER); + EXPECT_EQ(ctx->param->trust, X509_TRUST_SSL_SERVER); + + // Start over. + ctx.reset(X509_STORE_CTX_new()); + ASSERT_TRUE(ctx); + ASSERT_TRUE(X509_STORE_CTX_init(ctx.get(), store.get(), leaf.get(), nullptr)); + EXPECT_EQ(ctx->param->purpose, 0); + EXPECT_EQ(ctx->param->trust, 0); + + // Setting trust leaves purpose unset. + ASSERT_TRUE(X509_STORE_CTX_set_trust(ctx.get(), X509_TRUST_SSL_SERVER)); + EXPECT_EQ(ctx->param->purpose, 0); + EXPECT_EQ(ctx->param->trust, X509_TRUST_SSL_SERVER); + + // If trust is set, but not purpose, |X509_STORE_CTX_set_purpose| only sets + // purpose. + ASSERT_TRUE(X509_STORE_CTX_set_purpose(ctx.get(), X509_PURPOSE_SSL_CLIENT)); + EXPECT_EQ(ctx->param->purpose, X509_PURPOSE_SSL_CLIENT); + EXPECT_EQ(ctx->param->trust, X509_TRUST_SSL_SERVER); + + // Start over. + ctx.reset(X509_STORE_CTX_new()); + ASSERT_TRUE(ctx); + ASSERT_TRUE(X509_STORE_CTX_init(ctx.get(), store.get(), leaf.get(), nullptr)); + EXPECT_EQ(ctx->param->purpose, 0); + EXPECT_EQ(ctx->param->trust, 0); + + // If purpose is set, but not trust, |X509_STORE_CTX_set_purpose| only sets + // trust. + ASSERT_TRUE(X509_VERIFY_PARAM_set_purpose( + X509_STORE_CTX_get0_param(ctx.get()), X509_PURPOSE_SSL_CLIENT)); + EXPECT_EQ(ctx->param->purpose, X509_PURPOSE_SSL_CLIENT); + EXPECT_EQ(ctx->param->trust, 0); + + ASSERT_TRUE(X509_STORE_CTX_set_purpose(ctx.get(), X509_PURPOSE_SSL_SERVER)); + EXPECT_EQ(ctx->param->purpose, X509_PURPOSE_SSL_CLIENT); + EXPECT_EQ(ctx->param->trust, X509_TRUST_SSL_SERVER); +} + +TEST(X509Test, Purpose) { + bssl::UniquePtr key = PrivateKeyFromPEM(kP256Key); + ASSERT_TRUE(key); + + struct { + int purpose; + int eku_nid; + std::vector key_usages; + } kTests[] = { + {X509_PURPOSE_SSL_CLIENT, + NID_client_auth, + {KeyUsage::kDigitalSignature, KeyUsage::kKeyAgreement}}, + {X509_PURPOSE_SSL_SERVER, + NID_server_auth, + {KeyUsage::kDigitalSignature, KeyUsage::kKeyAgreement, + KeyUsage::kKeyEncipherment}}, + {X509_PURPOSE_NS_SSL_SERVER, + NID_server_auth, + {KeyUsage::kKeyEncipherment}}, + {X509_PURPOSE_SMIME_SIGN, + NID_email_protect, + {KeyUsage::kDigitalSignature, KeyUsage::kNonRepudiation}}, + {X509_PURPOSE_SMIME_ENCRYPT, + NID_email_protect, + {KeyUsage::kKeyEncipherment}}, + {X509_PURPOSE_CRL_SIGN, NID_undef, {KeyUsage::kCRLSign}}, + }; + for (const auto &t : kTests) { + SCOPED_TRACE(t.purpose); + + auto configure_callback = [&](X509_STORE_CTX *ctx) { + X509_STORE_CTX_set_purpose(ctx, t.purpose); + }; + + // An unconstrained cert chain is valid. + bssl::UniquePtr root = + MakeTestCert("Root", "Root", key.get(), /*is_ca=*/true); + ASSERT_TRUE(root); + ASSERT_TRUE(X509_sign(root.get(), key.get(), EVP_sha256())); + + bssl::UniquePtr intermediate = + MakeTestCert("Root", "Intermediate", key.get(), /*is_ca=*/true); + ASSERT_TRUE(intermediate); + ASSERT_TRUE(X509_sign(intermediate.get(), key.get(), EVP_sha256())); + + bssl::UniquePtr leaf = + MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + + EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()}, + {}, 0, configure_callback)); + + // A leaf and intermediate with compatible constraints is valid. + intermediate = + MakeTestCert("Root", "Intermediate", key.get(), /*is_ca=*/true); + ASSERT_TRUE(intermediate); + ASSERT_TRUE(AddKeyUsage(intermediate.get(), {KeyUsage::kKeyCertSign})); + if (t.eku_nid != NID_undef) { + ASSERT_TRUE(AddExtendedKeyUsage(intermediate.get(), {t.eku_nid})); + } + ASSERT_TRUE(X509_sign(intermediate.get(), key.get(), EVP_sha256())); + + leaf = MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + if (t.eku_nid != NID_undef) { + ASSERT_TRUE(AddExtendedKeyUsage(leaf.get(), {t.eku_nid})); + } + ASSERT_TRUE(AddKeyUsage(leaf.get(), t.key_usages)); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + + EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()}, + {}, 0, configure_callback)); + + // Each key usage asserted individually is valid. + for (KeyUsage usage : t.key_usages) { + SCOPED_TRACE(static_cast(usage)); + leaf = MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + if (t.eku_nid != NID_undef) { + ASSERT_TRUE(AddExtendedKeyUsage(leaf.get(), {t.eku_nid})); + } + ASSERT_TRUE(AddKeyUsage(leaf.get(), {usage})); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + EXPECT_EQ(X509_V_OK, + Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0, + configure_callback)); + } + + // A leaf with the wrong EKU is invalid. + if (t.eku_nid != NID_undef) { + leaf = MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + ASSERT_TRUE(AddExtendedKeyUsage(leaf.get(), {NID_rsaEncryption})); + ASSERT_TRUE(AddKeyUsage(leaf.get(), t.key_usages)); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + EXPECT_EQ(X509_V_ERR_INVALID_PURPOSE, + Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0, + configure_callback)); + } + + // A leaf without any of the requested key usages is invalid. + std::vector usages; + for (int i = 0; i < 10; i++) { + auto k = static_cast(i); + if (std::find(t.key_usages.begin(), t.key_usages.end(), k) == + t.key_usages.end()) { + usages.push_back(k); + } + } + leaf = MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + if (t.eku_nid != NID_undef) { + ASSERT_TRUE(AddExtendedKeyUsage(leaf.get(), {t.eku_nid})); + } + ASSERT_TRUE(AddKeyUsage(leaf.get(), usages)); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + EXPECT_EQ(X509_V_ERR_INVALID_PURPOSE, + Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0, + configure_callback)); + + // Extra EKUs and key usages are fine. + usages.clear(); + for (int i = 0; i < 10; i++) { + usages.push_back(static_cast(i)); + } + leaf = MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + if (t.eku_nid != NID_undef) { + ASSERT_TRUE( + AddExtendedKeyUsage(leaf.get(), {t.eku_nid, NID_rsaEncryption})); + } + ASSERT_TRUE(AddKeyUsage(leaf.get(), usages)); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + EXPECT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()}, + {}, 0, configure_callback)); + + // anyExtendedKeyUsage is not allowed in place of a concrete EKU. + if (t.eku_nid != NID_undef) { + leaf = MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + ASSERT_TRUE(AddExtendedKeyUsage(leaf.get(), {NID_anyExtendedKeyUsage})); + ASSERT_TRUE(AddKeyUsage(leaf.get(), t.key_usages)); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + EXPECT_EQ(X509_V_ERR_INVALID_PURPOSE, + Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0, + configure_callback)); + } + + // Restore |leaf| to a valid option. + leaf = MakeTestCert("Intermediate", "Leaf", key.get(), /*is_ca=*/false); + ASSERT_TRUE(leaf); + ASSERT_TRUE(X509_sign(leaf.get(), key.get(), EVP_sha256())); + + // The intermediate must have the keyCertSign bit. This bit is checked in + // multiple places. The first place that fails is in looking for candidate + // issuers. + intermediate = + MakeTestCert("Root", "Intermediate", key.get(), /*is_ca=*/true); + ASSERT_TRUE(intermediate); + ASSERT_TRUE(AddKeyUsage(intermediate.get(), {KeyUsage::kDigitalSignature})); + if (t.eku_nid != NID_undef) { + ASSERT_TRUE(AddExtendedKeyUsage(intermediate.get(), {t.eku_nid})); + } + ASSERT_TRUE(X509_sign(intermediate.get(), key.get(), EVP_sha256())); + EXPECT_EQ(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0, + configure_callback)); + + // The intermediate must have the EKU asserted. + if (t.eku_nid != NID_undef) { + intermediate = + MakeTestCert("Root", "Intermediate", key.get(), /*is_ca=*/true); + ASSERT_TRUE(intermediate); + ASSERT_TRUE(AddKeyUsage(intermediate.get(), {KeyUsage::kKeyCertSign})); + ASSERT_TRUE(AddExtendedKeyUsage(intermediate.get(), {NID_rsaEncryption})); + ASSERT_TRUE(X509_sign(intermediate.get(), key.get(), EVP_sha256())); + EXPECT_EQ(X509_V_ERR_INVALID_PURPOSE, + Verify(leaf.get(), {root.get()}, {intermediate.get()}, {}, 0, + configure_callback)); + } + } +} + +TEST(X509Test, Trust) { + struct Certs { + bssl::UniquePtr normal; + bssl::UniquePtr trusted_server, distrusted_server; + bssl::UniquePtr trusted_any, distrusted_any; + }; + auto certs_from_pem = [](const char *pem) -> Certs { + Certs certs; + certs.normal = CertFromPEM(pem); + certs.trusted_server = CertFromPEM(pem); + certs.distrusted_server = CertFromPEM(pem); + certs.trusted_any = CertFromPEM(pem); + certs.distrusted_any = CertFromPEM(pem); + if (certs.normal == nullptr || certs.trusted_server == nullptr || + certs.distrusted_server == nullptr || certs.trusted_any == nullptr || + certs.distrusted_any == nullptr || + !X509_add1_trust_object(certs.trusted_server.get(), + OBJ_nid2obj(NID_server_auth)) || + !X509_add1_reject_object(certs.distrusted_server.get(), + OBJ_nid2obj(NID_server_auth)) || + !X509_add1_trust_object(certs.trusted_any.get(), + OBJ_nid2obj(NID_anyExtendedKeyUsage)) || + !X509_add1_reject_object(certs.distrusted_any.get(), + OBJ_nid2obj(NID_anyExtendedKeyUsage))) { + return Certs{}; + } + return certs; + }; + + Certs root = certs_from_pem(kRootCAPEM); + Certs intermediate = certs_from_pem(kIntermediatePEM); + Certs leaf = certs_from_pem(kLeafPEM); + ASSERT_TRUE(root.normal); + ASSERT_TRUE(intermediate.normal); + ASSERT_TRUE(leaf.normal); + + // By default, trust is determined by a combination of self-signedness and + // NID_anyExtendedKeyUsage. + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), {root.normal.get()}, + {intermediate.normal.get()}, {})); + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), {root.trusted_any.get()}, + {intermediate.normal.get()}, {})); + EXPECT_EQ(X509_V_ERR_CERT_REJECTED, + Verify(leaf.normal.get(), {root.distrusted_any.get()}, + {intermediate.normal.get()}, {})); + + // Intermediate certificates are not self-signed, so must have an + // NID_anyExtendedKeyUsage trust setting. + EXPECT_EQ(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, + Verify(leaf.normal.get(), {intermediate.normal.get()}, {}, {})); + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), + {intermediate.trusted_any.get()}, {}, {})); + EXPECT_EQ( + X509_V_ERR_CERT_REJECTED, + Verify(leaf.normal.get(), {intermediate.distrusted_any.get()}, {}, {})); + + // If a certificate has trust settings, but only for a different OID, the + // self-signed rule still takes effect. + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), {root.trusted_server.get()}, + {intermediate.normal.get()}, {})); + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), {root.distrusted_server.get()}, + {intermediate.normal.get()}, {})); + EXPECT_EQ( + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, + Verify(leaf.normal.get(), {intermediate.trusted_server.get()}, {}, {})); + + // |X509_TRUST_SSL_SERVER| should instead look at self-signedness and + // |NID_server_auth|. + auto set_server_trust = [](X509_STORE_CTX *ctx) { + X509_STORE_CTX_set_trust(ctx, X509_TRUST_SSL_SERVER); + }; + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), {root.normal.get()}, + {intermediate.normal.get()}, {}, /*flags=*/0, + set_server_trust)); + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), {root.trusted_server.get()}, + {intermediate.normal.get()}, {}, /*flags=*/0, + set_server_trust)); + EXPECT_EQ( + X509_V_ERR_CERT_REJECTED, + Verify(leaf.normal.get(), {root.distrusted_server.get()}, + {intermediate.normal.get()}, {}, /*flags=*/0, set_server_trust)); + + EXPECT_EQ(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, + Verify(leaf.normal.get(), {intermediate.normal.get()}, {}, {}, + /*flags=*/0, set_server_trust)); + EXPECT_EQ(X509_V_OK, Verify(leaf.normal.get(), + {intermediate.trusted_server.get()}, {}, {}, + /*flags=*/0, set_server_trust)); + EXPECT_EQ(X509_V_ERR_CERT_REJECTED, + Verify(leaf.normal.get(), {intermediate.distrusted_server.get()}, + {}, {}, /*flags=*/0, set_server_trust)); + + // NID_anyExtendedKeyUsage is just an unrelated OID to X509_TRUST_SSL_SERVER. + // Unlike the default behavior, once a certificate has explicit trust settings + // for any OID, the self-signed check is disabled. + EXPECT_EQ( + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, + Verify(leaf.normal.get(), {root.trusted_any.get()}, + {intermediate.normal.get()}, {}, /*flags=*/0, set_server_trust)); +} diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c index 95daf46657..deb8930119 100644 --- a/crypto/x509/x509_trs.c +++ b/crypto/x509/x509_trs.c @@ -85,20 +85,18 @@ static const X509_TRUST trstandard[] = { NULL}}; int X509_check_trust(X509 *x, int id, int flags) { - int idx; if (id == -1) { - return 1; + return X509_TRUST_TRUSTED; } // We get this as a default value if (id == 0) { - int rv; - rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); + int rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); if (rv != X509_TRUST_UNTRUSTED) { return rv; } return trust_compat(NULL, x, 0); } - idx = X509_TRUST_get_by_id(id); + int idx = X509_TRUST_get_by_id(id); if (idx == -1) { return obj_trust(id, x, flags); } diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 298a14f0ab..ecfd357453 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1749,8 +1749,7 @@ void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, } int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) { - const X509_VERIFY_PARAM *param; - param = X509_VERIFY_PARAM_lookup(name); + const X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_lookup(name); if (!param) { return 0; } diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 31824bdb6c..162e8168bc 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -676,11 +676,15 @@ OPENSSL_EXPORT const uint8_t *X509_keyid_get0(const X509 *x509, int *out_len); // X509_add1_trust_object configures |x509| as a valid trust anchor for |obj|. // It returns one on success and zero on error. |obj| should be a certificate // usage OID associated with an |X509_TRUST| object. +// +// See |X509_VERIFY_PARAM_set_trust| for details on how this value is evaluated. OPENSSL_EXPORT int X509_add1_trust_object(X509 *x509, const ASN1_OBJECT *obj); // X509_add1_reject_object configures |x509| as distrusted for |obj|. It returns // one on success and zero on error. |obj| should be a certificate usage OID // associated with an |X509_TRUST| object. +// +// See |X509_VERIFY_PARAM_set_trust| for details on how this value is evaluated. OPENSSL_EXPORT int X509_add1_reject_object(X509 *x509, const ASN1_OBJECT *obj); // X509_trust_clear clears the list of OIDs for which |x509| is trusted. See @@ -2247,6 +2251,341 @@ OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); +// Certificate stores. +// +// An |X509_STORE| contains trusted certificates, CRLs, and verification +// parameters that are shared between multiple certificate verifications. +// +// Certificates in an |X509_STORE| are referred to as "trusted certificates", +// but an individual certificate verification may not necessarily treat every +// trusted certificate as a trust anchor. See |X509_VERIFY_PARAM_set_trust| for +// details. +// +// WARNING: Although a trusted certificate which fails the +// |X509_VERIFY_PARAM_set_trust| check is functionally an untrusted +// intermediate certificate, callers should not rely on this to configure +// untrusted intermediates in an |X509_STORE|. The trust check is complex, so +// this risks inadvertently treating it as a trust anchor. Instead, configure +// untrusted intermediates with the |chain| parameter of |X509_STORE_CTX_init|. +// +// Certificates in |X509_STORE| may be specified in several ways: +// - Added by |X509_STORE_add_cert|. +// - Returned by an |X509_LOOKUP| added by |X509_STORE_add_lookup|. +// +// |X509_STORE|s are reference-counted and may be shared by certificate +// verifications running concurrently on multiple threads. However, an +// |X509_STORE|'s verification parameters may not be modified concurrently with +// certificate verification or other operations. Unless otherwise documented, +// functions which take const pointer may be used concurrently, while +// functions which take a non-const pointer may not. Callers that wish to modify +// verification parameters in a shared |X509_STORE| should instead modify +// |X509_STORE_CTX|s individually. + +// X509_STORE_new returns a newly-allocated |X509_STORE|, or NULL on error. +OPENSSL_EXPORT X509_STORE *X509_STORE_new(void); + +// X509_STORE_up_ref adds one to the reference count of |store| and returns one. +// Although |store| is not const, this function's use of |store| is thread-safe. +OPENSSL_EXPORT int X509_STORE_up_ref(X509_STORE *store); + +// X509_STORE_free releases memory associated with |store|. +OPENSSL_EXPORT void X509_STORE_free(X509_STORE *store); + +// X509_STORE_add_cert adds |x509| to |store| as a trusted certificate. It +// returns one on success and zero on error. This function internally increments +// |x509|'s reference count, so the caller retains ownership of |x509|. +// +// Certificates configured by this function are still subject to the checks +// described in |X509_VERIFY_PARAM_set_trust|. +// +// Although |store| is not const, this function's use of |store| is thread-safe. +// However, if this function is called concurrently with |X509_verify_cert|, it +// is a race condition whether |x509| is available for issuer lookups. +// Moreover, the result may differ for each issuer lookup performed by a single +// |X509_verify_cert| call. +OPENSSL_EXPORT int X509_STORE_add_cert(X509_STORE *store, X509 *x509); + +// X509_STORE_add_crl adds |crl| to |store|. It returns one on success and zero +// on error. This function internally increments |crl|'s reference count, so the +// caller retains ownership of |crl|. CRLs added in this way are candidates for +// CRL lookup when |X509_V_FLAG_CRL_CHECK| is set. +// +// Although |store| is not const, this function's use of |store| is thread-safe. +// However, if this function is called concurrently with |X509_verify_cert|, it +// is a race condition whether |crl| is available for CRL checks. Moreover, the +// result may differ for each CRL check performed by a single +// |X509_verify_cert| call. +// +// Note there are no supported APIs to remove CRLs from |store| once inserted. +// To vary the set of CRLs over time, callers should either create a new +// |X509_STORE| or configure CRLs on a per-verification basis with +// |X509_STORE_CTX_set0_crls|. +OPENSSL_EXPORT int X509_STORE_add_crl(X509_STORE *store, X509_CRL *crl); + +// X509_STORE_set_purpose configures the purpose check for |store|. See +// |X509_VERIFY_PARAM_set_purpose| for details. +OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *store, int purpose); + +// X509_STORE_set_trust configures the trust check for |store|. See +// |X509_VERIFY_PARAM_set_trust| for details. +OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *store, int trust); + +// TODO(crbug.com/boringssl/426): Move the other |X509_STORE| functions here. + + +// Certificate verification. +// +// An |X509_STORE_CTX| object represents a single certificate verification +// operation. To verify a certificate chain, callers construct an +// |X509_STORE_CTX|, initialize it with |X509_STORE_CTX_init|, configure extra +// parameters, and call |X509_verify_cert|. + +// X509_STORE_CTX_new returns a newly-allocated, empty |X509_STORE_CTX|, or NULL +// on error. +OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_new(void); + +// X509_STORE_CTX_free releases memory associated with |ctx|. +OPENSSL_EXPORT void X509_STORE_CTX_free(X509_STORE_CTX *ctx); + +// X509_STORE_CTX_init initializes |ctx| to verify |x509|, using trusted +// certificates and parameters in |store|. It returns one on success and zero on +// error. |chain| is a list of untrusted intermediate certificates to use in +// verification. +// +// |ctx| stores pointers to |store|, |x509|, and |chain|. Each of these objects +// must outlive |ctx| and may not be mutated for the duration of the certificate +// verification. +OPENSSL_EXPORT int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); + +// X509_verify_cert attempts to discover and validate a certificate chain based +// on parameters in |ctx|. |ctx| usually includes a target certificate to be +// verified, a set of certificates serving as trust anchors, a list of +// non-trusted certificates that may be helpful for chain construction, flags, +// and various other optional components such as callback functions. |ctx| +// must have been initialized with |X509_STORE_CTX_init|. A certificate chain +// is built up starting from the target certificate and ending +// in a trust anchor. The chain is built up iteratively, looking up in turn a +// certificate with suitable key usage that matches as an issuer of the current +// "subject" certificate. +// +// NOTE: +// 1. Applications rarely call this function directly, but it is used +// internally for certificate validation. +// 2. |X509_verify_cert| and other related functions call +// |sk_X509_OBJECT_sort| internally, which rearranges the certificate +// ordering. There will be cases where two certs have an identical +// |subject| and |X509_OBJECT_cmp| will return 0, but one is a valid cert +// and the other is invalid. +// Due to https://github.com/openssl/openssl/issues/18708, certificate +// verification could fail if an invalid cert is checked before the valid +// cert. What we do with sorting behavior when certs are identical is +// considered "unstable" and certain sorting expectations shouldn't be +// depended on. +OPENSSL_EXPORT int X509_verify_cert(X509_STORE_CTX *ctx); + +// X509_STORE_CTX_set0_trusted_stack configures |ctx| to trust the certificates +// in |sk|. |sk| must remain valid for the duration of |ctx|. Calling this +// function causes |ctx| to ignore any certificates configured in the +// |X509_STORE|. Certificates in |sk| are still subject to the check described +// in |X509_VERIFY_PARAM_set_trust|. +// +// WARNING: This function differs from most |set0| functions in that it does not +// take ownership of its input. The caller is required to ensure the lifetimes +// are consistent. +OPENSSL_EXPORT void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, + STACK_OF(X509) *sk); + +// X509_STORE_CTX_set_default looks up the set of parameters named |name| and +// applies those default verification parameters for |ctx|. As in +// |X509_VERIFY_PARAM_inherit|, only unset parameters are changed. This function +// returns one on success and zero on error. +// +// The supported values of |name| are: +// - "default" is an internal value which configures some late defaults. See the +// discussion in |X509_STORE_get0_param|. +// - "pkcs7" configures default trust and purpose checks for PKCS#7 signatures. +// - "smime_sign" configures trust and purpose checks for S/MIME signatures. +// - "ssl_client" configures trust and purpose checks for TLS clients. +// - "ssl_server" configures trust and purpose checks for TLS servers. +// +// TODO(crbug.com/boringssl/441): Make "default" a no-op. +OPENSSL_EXPORT int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, + const char *name); + +// X509_STORE_CTX_set_purpose simultaneously configures |ctx|'s purpose and +// trust checks, if unset. It returns one on success and zero if |purpose| is +// not a valid purpose value. |purpose| should be an |X509_PURPOSE_*| constant. +// If so, it configures |ctx| with a purpose check of |purpose| and a trust +// check of |purpose|'s corresponding trust value. If either the purpose or +// trust check had already been specified for |ctx|, that corresponding +// modification is silently dropped. +// +// See |X509_VERIFY_PARAM_set_purpose| and |X509_VERIFY_PARAM_set_trust| for +// details on the purpose and trust checks, respectively. +// +// If |purpose| is |X509_PURPOSE_ANY|, this function returns an error because it +// has no corresponding |X509_TRUST_*| value. It is not possible to set +// |X509_PURPOSE_ANY| with this function, only |X509_VERIFY_PARAM_set_purpose|. +// +// WARNING: Unlike similarly named functions in this header, this function +// silently does not behave the same as |X509_VERIFY_PARAM_set_purpose|. Callers +// may use |X509_VERIFY_PARAM_set_purpose| with |X509_STORE_CTX_get0_param| to +// avoid this difference. +OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); + +// X509_STORE_CTX_set_trust configures |ctx|'s trust check, if unset. It returns +// one on success and zero if |trust| is not a valid trust value. |trust| should +// be an |X509_TRUST_*| constant. If so, it configures |ctx| with a trust check +// of |trust|. If the trust check had already been specified for |ctx|, it +// silently does nothing. +// +// See |X509_VERIFY_PARAM_set_trust| for details on the purpose and trust check. +// +// WARNING: Unlike similarly named functions in this header, this function +// does not behave the same as |X509_VERIFY_PARAM_set_trust|. Callers may use +// |X509_VERIFY_PARAM_set_trust| with |X509_STORE_CTX_get0_param| to avoid this +// difference. +OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); + +// TODO(crbug.com/boringssl/426): Move the other |X509_STORE_CTX| functions +// here. + + +// Verification parameters +// +// An |X509_VERIFY_PARAM| contains a set of parameters for certificate +// verification. + +// X509_VERIFY_PARAM_new returns a newly-allocated |X509_VERIFY_PARAM|, or NULL +// on error. +OPENSSL_EXPORT X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); + +// X509_VERIFY_PARAM_free releases memory associated with |param|. +OPENSSL_EXPORT void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); + +// X509_PURPOSE_SSL_CLIENT validates TLS client certificates. It checks for the +// id-kp-clientAuth EKU and one of digitalSignature or keyAgreement key usages. +// The TLS library is expected to check for the key usage specific to the +// negotiated TLS parameters. +#define X509_PURPOSE_SSL_CLIENT 1 +// X509_PURPOSE_SSL_SERVER validates TLS server certificates. It checks for the +// id-kp-clientAuth EKU and one of digitalSignature, keyAgreement, or +// keyEncipherment key usages. The TLS library is expected to check for the key +// usage specific to the negotiated TLS parameters. +#define X509_PURPOSE_SSL_SERVER 2 +// X509_PURPOSE_NS_SSL_SERVER is a legacy mode. It behaves like +// |X509_PURPOSE_SSL_SERVER|, but only accepts the keyEncipherment key usage, +// used by SSL 2.0 and RSA key exchange. Do not use this. +#define X509_PURPOSE_NS_SSL_SERVER 3 +// X509_PURPOSE_SMIME_SIGN validates S/MIME signing certificates. It checks for +// the id-kp-emailProtection EKU and one of digitalSignature or nonRepudiation +// key usages. +#define X509_PURPOSE_SMIME_SIGN 4 +// X509_PURPOSE_SMIME_ENCRYPT validates S/MIME encryption certificates. It +// checks for the id-kp-emailProtection EKU and keyEncipherment key usage. +#define X509_PURPOSE_SMIME_ENCRYPT 5 +// X509_PURPOSE_CRL_SIGN validates indirect CRL signers. It checks for the +// cRLSign key usage. BoringSSL does not support indirect CRLs and does not use +// this mode. +#define X509_PURPOSE_CRL_SIGN 6 +// X509_PURPOSE_ANY performs no EKU or key usage checks. Such checks are the +// responsibility of the caller. +#define X509_PURPOSE_ANY 7 +// X509_PURPOSE_OCSP_HELPER performs no EKU or key usage checks. It was +// historically used in OpenSSL's OCSP implementation, which left those checks +// to the OCSP implementation itself. +#define X509_PURPOSE_OCSP_HELPER 8 +// X509_PURPOSE_TIMESTAMP_SIGN validates Time Stamping Authority (RFC 3161) +// certificates. It checks for the id-kp-timeStamping EKU and one of +// digitalSignature or nonRepudiation key usages. It additionally checks that +// the EKU extension is critical and that no other EKUs or key usages are +// asserted. +#define X509_PURPOSE_TIMESTAMP_SIGN 9 + +// X509_VERIFY_PARAM_set_purpose configures |param| to validate certificates for +// a specified purpose. It returns one on success and zero if |purpose| is not a +// valid purpose type. |purpose| should be one of the |X509_PURPOSE_*| values. +// +// This option controls checking the extended key usage (EKU) and key usage +// extensions. These extensions specify how a certificate's public key may be +// used and are important to avoid cross-protocol attacks, particularly in PKIs +// that may issue certificates for multiple protocols, or for protocols that use +// keys in multiple ways. If not configured, these security checks are the +// caller's responsibility. +// +// This library applies the EKU checks to all untrusted intermediates. Although +// not defined in RFC 5280, this matches widely-deployed practice. It also does +// not accept anyExtendedKeyUsage. +// +// Many purpose values have a corresponding trust value, which is not configured +// by this function. See |X509_VERIFY_PARAM_set_trust| for details. Callers +// that wish to configure both should either call both functions, or use +// |X509_STORE_CTX_set_purpose|. +// +// It is currently not possible to configure custom EKU OIDs or key usage bits. +// Contact the BoringSSL maintainers if your application needs to do so. OpenSSL +// had an |X509_PURPOSE_add| API, but it was not thread-safe and relied on +// global mutable state, so we removed it. +// +// TODO(davidben): This function additionally configures checking the legacy +// Netscape certificate type extension. Remove this. +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, + int purpose); + +// X509_TRUST_COMPAT evaluates trust using only the self-signed fallback. Trust +// and distrust OIDs are ignored. +#define X509_TRUST_COMPAT 1 +// X509_TRUST_SSL_CLIENT evaluates trust with the |NID_client_auth| OID, for +// validating TLS client certificates. +#define X509_TRUST_SSL_CLIENT 2 +// X509_TRUST_SSL_SERVER evaluates trust with the |NID_server_auth| OID, for +// validating TLS server certificates. +#define X509_TRUST_SSL_SERVER 3 +// X509_TRUST_EMAIL evaluates trust with the |NID_email_protect| OID, for +// validating S/MIME email certificates. +#define X509_TRUST_EMAIL 4 +// X509_TRUST_OBJECT_SIGN evaluates trust with the |NID_code_sign| OID, for +// validating code signing certificates. +#define X509_TRUST_OBJECT_SIGN 5 +// X509_TRUST_TSA evaluates trust with the |NID_time_stamp| OID, for validating +// Time Stamping Authority (RFC 3161) certificates. +#define X509_TRUST_TSA 8 + +// X509_VERIFY_PARAM_set_trust configures which certificates from |X509_STORE| +// are trust anchors. It returns one on success and zero if |trust| is not a +// valid trust value. |trust| should be one of the |X509_TRUST_*| constants. +// This function allows applications to vary trust anchors when the same set of +// trusted certificates is used in multiple contexts. +// +// Two properties determine whether a certificate is a trust anchor: +// +// - Whether it is trusted or distrusted for some OID, via auxiliary information +// configured by |X509_add1_trust_object| or |X509_add1_reject_object|. +// +// - Whether it is "self-signed". That is, whether |X509_get_extension_flags| +// includes |EXFLAG_SS|. The signature itself is not checked. +// +// When this function is called, |trust| determines the OID to check in the +// first case. If the certificate is not explicitly trusted or distrusted for +// any OID, it is trusted if self-signed instead. +// +// If unset, the default behavior is to check for the |NID_anyExtendedKeyUsage| +// OID. If the certificate is not explicitly trusted or distrusted for this OID, +// it is trusted if self-signed instead. Note this slightly differs from the +// above. +// +// It is currently not possible to configure custom trust OIDs. Contact the +// BoringSSL maintainers if your application needs to do so. OpenSSL had an +// |X509_TRUST_add| API, but it was not thread-safe and relied on global mutable +// state, so we removed it. +OPENSSL_EXPORT int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, + int trust); + +// TODO(crbug.com/boringssl/426): Move the other |X509_VERIFY_PARAM| functions +// here. + + // SignedPublicKeyAndChallenge structures. // // The SignedPublicKeyAndChallenge (SPKAC) is a legacy structure to request @@ -3202,6 +3541,43 @@ OPENSSL_EXPORT int X509_check_ip(const X509 *x509, const uint8_t *chk, OPENSSL_EXPORT int X509_check_ip_asc(const X509 *x509, const char *ipasc, unsigned int flags); +// X509_STORE_CTX_get1_issuer looks up a candidate trusted issuer for |x509| out +// of |ctx|'s |X509_STORE|, based on the criteria in |X509_check_issued|. If one +// was found, it returns one and sets |*out_issuer| to the issuer. The caller +// must release |*out_issuer| with |X509_free| when done. If none was found, it +// returns zero and leaves |*out_issuer| unchanged. +// +// This function only searches for trusted issuers. It does not consider +// untrusted intermediates passed in to |X509_STORE_CTX_init|. +// +// TODO(crbug.com/boringssl/407): |x509| should be const. +OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **out_issuer, + X509_STORE_CTX *ctx, X509 *x509); + +// X509_check_purpose performs checks if |x509|'s basic constraints, key usage, +// and extended key usage extensions for the specified purpose. |purpose| should +// be one of |X509_PURPOSE_*| constants. See |X509_VERIFY_PARAM_set_purpose| for +// details. It returns one if |x509|'s extensions are consistent with |purpose| +// and zero otherwise. If |ca| is non-zero, |x509| is checked as a CA +// certificate. Otherwise, it is checked as an end-entity certificate. +// +// If |purpose| is -1, this function performs no purpose checks, but it parses +// some extensions in |x509| and may return zero on syntax error. Historically, +// callers primarily used this function to trigger this parsing, but this is no +// longer necessary. Functions acting on |X509| will internally parse as needed. +OPENSSL_EXPORT int X509_check_purpose(X509 *x509, int purpose, int ca); + +#define X509_TRUST_TRUSTED 1 +#define X509_TRUST_REJECTED 2 +#define X509_TRUST_UNTRUSTED 3 + +// X509_check_trust checks if |x509| is a valid trust anchor for trust type +// |id|. See |X509_VERIFY_PARAM_set_trust| for details. It returns +// |X509_TRUST_TRUSTED| if |x509| is a trust anchor, |X509_TRUST_REJECTED| if it +// was distrusted, and |X509_TRUST_UNTRUSTED| otherwise. |id| should be one of +// the |X509_TRUST_*| constants, or zero to indicate the default behavior. +// |flags| should be zero and is ignored. +OPENSSL_EXPORT int X509_check_trust(X509 *x509, int id, int flags); // X.509 information. // @@ -3665,19 +4041,6 @@ DEFINE_STACK_OF(X509_TRUST) #define X509_TRUST_DEFAULT (-1) // Only valid in purpose settings -#define X509_TRUST_COMPAT 1 -#define X509_TRUST_SSL_CLIENT 2 -#define X509_TRUST_SSL_SERVER 3 -#define X509_TRUST_EMAIL 4 -#define X509_TRUST_OBJECT_SIGN 5 -#define X509_TRUST_TSA 8 - -// check_trust return codes - -#define X509_TRUST_TRUSTED 1 -#define X509_TRUST_REJECTED 2 -#define X509_TRUST_UNTRUSTED 3 - // X509_verify_cert_error_string returns |err| as a human-readable string, where // |err| should be one of the |X509_V_*| values. If |err| is unknown, it returns // a default description. @@ -3723,32 +4086,6 @@ 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); -// X509_verify_cert attempts to discover and validate a certificate chain based -// on parameters in |ctx|. |ctx| usually includes a target certificate to be -// verified, a set of certificates serving as trust anchors, a list of -// non-trusted certificates that may be helpful for chain construction, flags, -// and various other optional components such as callback functions. A -// certificate chain is built up starting from the target certificate and ending -// in a trust anchor. The chain is built up iteratively, looking up in turn a -// certificate with suitable key usage that matches as an issuer of the current -// "subject" certificate. -// -// NOTE: -// 1. Applications rarely call this function directly, but it is used -// internally for certificate validation. -// 2. |X509_verify_cert| and other related functions call -// |sk_X509_OBJECT_sort| internally, which rearranges the certificate -// ordering. There will be cases where two certs have an identical -// |subject| and |X509_OBJECT_cmp| will return 0, but one is a valid cert -// and the other is invalid. -// Due to https://github.com/openssl/openssl/issues/18708, certificate -// verification could fail if an invalid cert is checked before the valid -// cert. What we do with sorting behavior when certs are identical is -// considered "unstable" and certain sorting expectations shouldn't be -// depended on. -OPENSSL_EXPORT int X509_verify_cert(X509_STORE_CTX *ctx); - -OPENSSL_EXPORT int X509_check_trust(X509 *x, int id, int flags); OPENSSL_EXPORT int X509_TRUST_get_count(void); OPENSSL_EXPORT const X509_TRUST *X509_TRUST_get0(int idx); OPENSSL_EXPORT int X509_TRUST_get_by_id(int id); @@ -3996,15 +4333,6 @@ OPENSSL_EXPORT int X509_STORE_lock(X509_STORE *v); // X509_STORE_unlock releases a lock on |v|. return 1 on success, 0 on failure OPENSSL_EXPORT int X509_STORE_unlock(X509_STORE *v); -// X509_STORE_new returns a newly-allocated |X509_STORE|, or NULL on error. -OPENSSL_EXPORT X509_STORE *X509_STORE_new(void); - -// X509_STORE_up_ref adds one to the reference count of |store| and returns one. -OPENSSL_EXPORT int X509_STORE_up_ref(X509_STORE *store); - -// X509_STORE_free releases memory associated with |store|. -OPENSSL_EXPORT void X509_STORE_free(X509_STORE *store); - OPENSSL_EXPORT STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st); OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); @@ -4019,10 +4347,7 @@ OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st, // the |X509_STORE|. See discussion in |X509_STORE_get0_param|. OPENSSL_EXPORT int X509_STORE_set_flags(X509_STORE *store, unsigned long flags); -OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *store, int purpose); -OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *store, int trust); - -// X509_STORE_set1_param copies verification parameters from |param| as in +// |X509_STORE_set1_param| copies verification parameters from |param| as in // |X509_VERIFY_PARAM_set1|. It returns one on success and zero on error. OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *store, const X509_VERIFY_PARAM *param); @@ -4047,38 +4372,6 @@ OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *store, // |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_CTX_new returns a newly-allocated, empty |X509_STORE_CTX|, or NULL -// on error. -OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_new(void); - -OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **issuer, - X509_STORE_CTX *ctx, X509 *x); - -// X509_STORE_CTX_free releases memory associated with |ctx|. -OPENSSL_EXPORT void X509_STORE_CTX_free(X509_STORE_CTX *ctx); - -// X509_STORE_CTX_init initializes |ctx| to verify |x509|, using trusted -// certificates and parameters in |store|. It returns one on success and zero on -// error. |chain| is a list of untrusted intermediate certificates to use in -// verification. -// -// |ctx| stores pointers to |store|, |x509|, and |chain|. Each of these objects -// must outlive |ctx| and may not be mutated for the duration of the certificate -// verification. -OPENSSL_EXPORT int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, - X509 *x509, STACK_OF(X509) *chain); - -// X509_STORE_CTX_set0_trusted_stack configures |ctx| to trust the certificates -// in |sk|. |sk| must remain valid for the duration of |ctx|. Calling this -// function causes |ctx| to ignore any certificates configured in the -// |X509_STORE|. -// -// WARNING: This function differs from most |set0| functions in that it does not -// take ownership of its input. The caller is required to ensure the lifetimes -// are consistent. -OPENSSL_EXPORT void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, - STACK_OF(X509) *sk); - // X509_STORE_CTX_get0_store returns the |X509_STORE| that |ctx| uses. OPENSSL_EXPORT X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); @@ -4092,8 +4385,17 @@ OPENSSL_EXPORT X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, OPENSSL_EXPORT const X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); OPENSSL_EXPORT const X509_LOOKUP_METHOD *X509_LOOKUP_file(void); -OPENSSL_EXPORT int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); -OPENSSL_EXPORT int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); +// X509_STORE_get_by_subject is an alias to |X509_STORE_CTX_get_by_subject| in +// OpenSSL 1.1.1. +#define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject + +// X509_STORE_CTX_get_by_subject tries to find an object of a given type, which +// may be |X509_LU_X509| or |X509_LU_CRL|, and the subject name from the store +// in |vs|. If found and |ret| is not NULL, it increments the reference count +// and stores the object in |ret|. +OPENSSL_EXPORT int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, int type, + X509_NAME *name, + X509_OBJECT *ret); OPENSSL_EXPORT int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); @@ -4134,8 +4436,9 @@ OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get0_untrusted( X509_STORE_CTX *ctx); OPENSSL_EXPORT void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk); -OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); -OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); + +// X509_STORE_CTX_purpose_inherit is an internal implementation detail that will +// shortly be removed. OPENSSL_EXPORT int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, int purpose, int trust); @@ -4178,34 +4481,6 @@ OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_CTX_get0_param( OPENSSL_EXPORT void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); -// X509_STORE_CTX_set_default looks up the set of parameters named |name| and -// applies those default verification parameters for |ctx|. As in -// |X509_VERIFY_PARAM_inherit|, only unset parameters are changed. This function -// returns one on success and zero on error. -OPENSSL_EXPORT int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, - const char *name); - -// X509_STORE_get_by_subject is an alias to |X509_STORE_CTX_get_by_subject| in -// OpenSSL 1.1.1. -#define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject - -// X509_STORE_CTX_get_by_subject tries to find an object of a given type, which -// may be |X509_LU_X509| or |X509_LU_CRL|, and the subject name from the store -// in |vs|. If found and |ret| is not NULL, it increments the reference count -// and stores the object in |ret|. -OPENSSL_EXPORT int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, int type, - X509_NAME *name, - X509_OBJECT *ret); - -// X509_VERIFY_PARAM functions - -// X509_VERIFY_PARAM_new returns a newly-allocated |X509_VERIFY_PARAM|, or NULL -// on error. -OPENSSL_EXPORT X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); - -// X509_VERIFY_PARAM_free releases memory associated with |param|. -OPENSSL_EXPORT void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); - // X509_VERIFY_PARAM_inherit applies |from| as the default values for |to|. That // is, for each parameter that is unset in |to|, it copies the value in |from|. // This function returns one on success and zero on error. @@ -4234,11 +4509,6 @@ OPENSSL_EXPORT int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, OPENSSL_EXPORT unsigned long X509_VERIFY_PARAM_get_flags( const X509_VERIFY_PARAM *param); -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). @@ -4541,16 +4811,6 @@ typedef struct x509_purpose_st { void *usr_data; } X509_PURPOSE; -#define X509_PURPOSE_SSL_CLIENT 1 -#define X509_PURPOSE_SSL_SERVER 2 -#define X509_PURPOSE_NS_SSL_SERVER 3 -#define X509_PURPOSE_SMIME_SIGN 4 -#define X509_PURPOSE_SMIME_ENCRYPT 5 -#define X509_PURPOSE_CRL_SIGN 6 -#define X509_PURPOSE_ANY 7 -#define X509_PURPOSE_OCSP_HELPER 8 -#define X509_PURPOSE_TIMESTAMP_SIGN 9 - DEFINE_STACK_OF(X509_PURPOSE) DECLARE_ASN1_FUNCTIONS_const(BASIC_CONSTRAINTS) @@ -4771,8 +5031,6 @@ OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, OPENSSL_EXPORT int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags); -OPENSSL_EXPORT int X509_check_purpose(X509 *x, int id, int ca); - OPENSSL_EXPORT int X509_PURPOSE_set(int *p, int purpose); OPENSSL_EXPORT int X509_PURPOSE_get_count(void); From 0396a2e40381d262adeded34daddea5532444b8f Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sun, 24 Dec 2023 02:06:11 -0500 Subject: [PATCH 4/5] Remove X509_STORE_CTX_purpose_inherit X509_STORE_CTX_purpose_inherit's behavior is even more bizarre than X509_STORE_CTX_set_purpose and X509_STORE_CTX_set_trust. Remove it and reimplement X509_STORE_CTX_set_purpose and X509_STORE_CTX_set_trust's behaviors directly. Change-Id: Icc6a4a84ee8fa38e2fe70a4cfa06e74dee186d29 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65208 Reviewed-by: Bob Beck Commit-Queue: David Benjamin (cherry picked from commit 3d9e5a355b1ce8518aefce2df00dfab3fe63c379) --- crypto/x509/x509_vfy.c | 78 +++++++++++++++--------------------------- include/openssl/x509.h | 6 ---- 2 files changed, 28 insertions(+), 56 deletions(-) diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index ecfd357453..8fdd82cd92 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1569,62 +1569,40 @@ void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) { } int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) { - return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); -} + // If |purpose| is zero, this function historically silently did nothing. + if (purpose == 0) { + return 1; + } -int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) { - return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); -} - -// This function is used to set the X509_STORE_CTX purpose and trust values. -// This is intended to be used when another structure has its own trust and -// purpose values which (if set) will be inherited by the ctx. If they aren't -// set then we will usually have a default purpose in mind which should then -// be used to set the trust value. An example of this is SSL use: an SSL -// structure will have its own purpose and trust settings which the -// application can set: if they aren't set then we use the default of SSL -// client/server. - -int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, - int purpose, int trust) { - int idx; - // If purpose not set use default - if (!purpose) { - purpose = def_purpose; - } - // If we have a purpose then check it is valid - if (purpose) { - idx = X509_PURPOSE_get_by_id(purpose); - if (idx == -1) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); - return 0; - } - const X509_PURPOSE *ptmp = X509_PURPOSE_get0(idx); - if (ptmp->trust == X509_TRUST_DEFAULT) { - idx = X509_PURPOSE_get_by_id(def_purpose); - if (idx == -1) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); - return 0; - } - ptmp = X509_PURPOSE_get0(idx); - } - // If trust not set then get from purpose default - if (!trust) { - trust = ptmp->trust; - } + int idx = X509_PURPOSE_get_by_id(purpose); + if (idx == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID); + return 0; } - if (trust) { - idx = X509_TRUST_get_by_id(trust); - if (idx == -1) { - OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID); - return 0; - } + + int trust = X509_PURPOSE_get_trust(X509_PURPOSE_get0(idx)); + if (!X509_STORE_CTX_set_trust(ctx, trust)) { + return 0; } - if (purpose && !ctx->param->purpose) { + if (ctx->param->purpose == 0) { ctx->param->purpose = purpose; } - if (trust && !ctx->param->trust) { + return 1; +} + +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) { + // If |trust| is zero, this function historically silently did nothing. + if (trust == 0) { + return 1; + } + + if (X509_TRUST_get_by_id(trust) == -1) { + OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID); + return 0; + } + + if (ctx->param->trust == 0) { ctx->param->trust = trust; } return 1; diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 162e8168bc..f092246250 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -4437,12 +4437,6 @@ OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get0_untrusted( OPENSSL_EXPORT void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk); -// X509_STORE_CTX_purpose_inherit is an internal implementation detail that will -// shortly be removed. -OPENSSL_EXPORT int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, - int def_purpose, int purpose, - int trust); - // X509_STORE_CTX_set_flags enables all values in |flags| in |ctx|'s // verification flags. |flags| should be a combination of |X509_V_FLAG_*| // constants. From d78dbc49a17acf07dd6538cf2d8b7ab7688722fc Mon Sep 17 00:00:00 2001 From: Shubham Mittal Date: Fri, 2 Aug 2024 15:12:34 -0700 Subject: [PATCH 5/5] comment change --- include/openssl/x509.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openssl/x509.h b/include/openssl/x509.h index f092246250..1cf54d2c39 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -4347,7 +4347,7 @@ OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st, // the |X509_STORE|. See discussion in |X509_STORE_get0_param|. OPENSSL_EXPORT int X509_STORE_set_flags(X509_STORE *store, unsigned long flags); -// |X509_STORE_set1_param| copies verification parameters from |param| as in +// X509_STORE_set1_param copies verification parameters from |param| as in // |X509_VERIFY_PARAM_set1|. It returns one on success and zero on error. OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *store, const X509_VERIFY_PARAM *param);