...

Source file src/github.com/google/certificate-transparency-go/x509/rpki.go

Documentation: github.com/google/certificate-transparency-go/x509

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package x509
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"errors"
    11  	"fmt"
    12  
    13  	"github.com/google/certificate-transparency-go/asn1"
    14  )
    15  
    16  // IPAddressPrefix describes an IP address prefix as an ASN.1 bit string,
    17  // where the BitLength field holds the prefix length.
    18  type IPAddressPrefix asn1.BitString
    19  
    20  // IPAddressRange describes an (inclusive) IP address range.
    21  type IPAddressRange struct {
    22  	Min IPAddressPrefix
    23  	Max IPAddressPrefix
    24  }
    25  
    26  // Most relevant values for AFI from:
    27  // http://www.iana.org/assignments/address-family-numbers.
    28  const (
    29  	IPv4AddressFamilyIndicator = uint16(1)
    30  	IPv6AddressFamilyIndicator = uint16(2)
    31  )
    32  
    33  // IPAddressFamilyBlocks describes a set of ranges of IP addresses.
    34  type IPAddressFamilyBlocks struct {
    35  	// AFI holds an address family indicator from
    36  	// http://www.iana.org/assignments/address-family-numbers.
    37  	AFI uint16
    38  	// SAFI holds a subsequent address family indicator from
    39  	// http://www.iana.org/assignments/safi-namespace.
    40  	SAFI byte
    41  	// InheritFromIssuer indicates that the set of addresses should
    42  	// be taken from the issuer's certificate.
    43  	InheritFromIssuer bool
    44  	// AddressPrefixes holds prefixes if InheritFromIssuer is false.
    45  	AddressPrefixes []IPAddressPrefix
    46  	// AddressRanges holds ranges if InheritFromIssuer is false.
    47  	AddressRanges []IPAddressRange
    48  }
    49  
    50  // Internal types for asn1 unmarshalling.
    51  type ipAddressFamily struct {
    52  	AddressFamily []byte // 2-byte AFI plus optional 1 byte SAFI
    53  	Choice        asn1.RawValue
    54  }
    55  
    56  // Internally, use raw asn1.BitString rather than the IPAddressPrefix
    57  // type alias (so that asn1.Unmarshal() decodes properly).
    58  type ipAddressRange struct {
    59  	Min asn1.BitString
    60  	Max asn1.BitString
    61  }
    62  
    63  func parseRPKIAddrBlocks(data []byte, nfe *NonFatalErrors) []*IPAddressFamilyBlocks {
    64  	// RFC 3779 2.2.3
    65  	//   IPAddrBlocks        ::= SEQUENCE OF IPAddressFamily
    66  	//
    67  	//   IPAddressFamily     ::= SEQUENCE {    -- AFI & optional SAFI --
    68  	//      addressFamily        OCTET STRING (SIZE (2..3)),
    69  	//      ipAddressChoice      IPAddressChoice }
    70  	//
    71  	//   IPAddressChoice     ::= CHOICE {
    72  	//      inherit              NULL, -- inherit from issuer --
    73  	//      addressesOrRanges    SEQUENCE OF IPAddressOrRange }
    74  	//
    75  	//   IPAddressOrRange    ::= CHOICE {
    76  	//      addressPrefix        IPAddress,
    77  	//      addressRange         IPAddressRange }
    78  	//
    79  	//   IPAddressRange      ::= SEQUENCE {
    80  	//      min                  IPAddress,
    81  	//      max                  IPAddress }
    82  	//
    83  	//   IPAddress           ::= BIT STRING
    84  
    85  	var addrBlocks []ipAddressFamily
    86  	if rest, err := asn1.Unmarshal(data, &addrBlocks); err != nil {
    87  		nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ipAddrBlocks extension: %v", err))
    88  		return nil
    89  	} else if len(rest) != 0 {
    90  		nfe.AddError(errors.New("trailing data after ipAddrBlocks extension"))
    91  		return nil
    92  	}
    93  
    94  	var results []*IPAddressFamilyBlocks
    95  	for i, block := range addrBlocks {
    96  		var fam IPAddressFamilyBlocks
    97  		if l := len(block.AddressFamily); l < 2 || l > 3 {
    98  			nfe.AddError(fmt.Errorf("invalid address family length (%d) for ipAddrBlock.addressFamily", l))
    99  			continue
   100  		}
   101  		fam.AFI = binary.BigEndian.Uint16(block.AddressFamily[0:2])
   102  		if len(block.AddressFamily) > 2 {
   103  			fam.SAFI = block.AddressFamily[2]
   104  		}
   105  		// IPAddressChoice is an ASN.1 CHOICE where the chosen alternative is indicated by (implicit)
   106  		// tagging of the alternatives -- here, either NULL or SEQUENCE OF.
   107  		if bytes.Equal(block.Choice.FullBytes, asn1.NullBytes) {
   108  			fam.InheritFromIssuer = true
   109  			results = append(results, &fam)
   110  			continue
   111  		}
   112  
   113  		var addrRanges []asn1.RawValue
   114  		if _, err := asn1.Unmarshal(block.Choice.FullBytes, &addrRanges); err != nil {
   115  			nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ipAddrBlocks[%d].ipAddressChoice.addressesOrRanges: %v", i, err))
   116  			continue
   117  		}
   118  		for j, ar := range addrRanges {
   119  			// Each IPAddressOrRange is a CHOICE where the alternatives have distinct (implicit)
   120  			// tags -- here, either BIT STRING or SEQUENCE.
   121  			switch ar.Tag {
   122  			case asn1.TagBitString:
   123  				// BIT STRING for single prefix IPAddress
   124  				var val asn1.BitString
   125  				if _, err := asn1.Unmarshal(ar.FullBytes, &val); err != nil {
   126  					nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ipAddrBlocks[%d].ipAddressChoice.addressesOrRanges[%d].addressPrefix: %v", i, j, err))
   127  					continue
   128  				}
   129  				fam.AddressPrefixes = append(fam.AddressPrefixes, IPAddressPrefix(val))
   130  
   131  			case asn1.TagSequence:
   132  				var val ipAddressRange
   133  				if _, err := asn1.Unmarshal(ar.FullBytes, &val); err != nil {
   134  					nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ipAddrBlocks[%d].ipAddressChoice.addressesOrRanges[%d].addressRange: %v", i, j, err))
   135  					continue
   136  				}
   137  				fam.AddressRanges = append(fam.AddressRanges, IPAddressRange{Min: IPAddressPrefix(val.Min), Max: IPAddressPrefix(val.Max)})
   138  
   139  			default:
   140  				nfe.AddError(fmt.Errorf("unexpected ASN.1 type in ipAddrBlocks[%d].ipAddressChoice.addressesOrRanges[%d]: %+v", i, j, ar))
   141  			}
   142  		}
   143  		results = append(results, &fam)
   144  	}
   145  	return results
   146  }
   147  
   148  // ASIDRange describes an inclusive range of AS Identifiers (AS numbers or routing
   149  // domain identifiers).
   150  type ASIDRange struct {
   151  	Min int
   152  	Max int
   153  }
   154  
   155  // ASIdentifiers describes a collection of AS Identifiers (AS numbers or routing
   156  // domain identifiers).
   157  type ASIdentifiers struct {
   158  	// InheritFromIssuer indicates that the set of AS identifiers should
   159  	// be taken from the issuer's certificate.
   160  	InheritFromIssuer bool
   161  	// ASIDs holds AS identifiers if InheritFromIssuer is false.
   162  	ASIDs []int
   163  	// ASIDs holds AS identifier ranges (inclusive) if InheritFromIssuer is false.
   164  	ASIDRanges []ASIDRange
   165  }
   166  
   167  type asIdentifiers struct {
   168  	ASNum asn1.RawValue `asn1:"optional,tag:0"`
   169  	RDI   asn1.RawValue `asn1:"optional,tag:1"`
   170  }
   171  
   172  func parseASIDChoice(val asn1.RawValue, nfe *NonFatalErrors) *ASIdentifiers {
   173  	// RFC 3779 2.3.2
   174  	//   ASIdentifierChoice  ::= CHOICE {
   175  	//      inherit              NULL, -- inherit from issuer --
   176  	//      asIdsOrRanges        SEQUENCE OF ASIdOrRange }
   177  	//   ASIdOrRange         ::= CHOICE {
   178  	//       id                  ASId,
   179  	//       range               ASRange }
   180  	//   ASRange             ::= SEQUENCE {
   181  	//       min                 ASId,
   182  	//       max                 ASId }
   183  	//   ASId                ::= INTEGER
   184  	if len(val.FullBytes) == 0 { // OPTIONAL
   185  		return nil
   186  	}
   187  	// ASIdentifierChoice is an ASN.1 CHOICE where the chosen alternative is indicated by (implicit)
   188  	// tagging of the alternatives -- here, either NULL or SEQUENCE OF.
   189  	if bytes.Equal(val.Bytes, asn1.NullBytes) {
   190  		return &ASIdentifiers{InheritFromIssuer: true}
   191  	}
   192  	var ids []asn1.RawValue
   193  	if rest, err := asn1.Unmarshal(val.Bytes, &ids); err != nil {
   194  		nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ASIdentifiers.asIdsOrRanges: %v", err))
   195  		return nil
   196  	} else if len(rest) != 0 {
   197  		nfe.AddError(errors.New("trailing data after ASIdentifiers.asIdsOrRanges"))
   198  		return nil
   199  	}
   200  	var asID ASIdentifiers
   201  	for i, id := range ids {
   202  		// Each ASIdOrRange is a CHOICE where the alternatives have distinct (implicit)
   203  		// tags -- here, either INTEGER or SEQUENCE.
   204  		switch id.Tag {
   205  		case asn1.TagInteger:
   206  			var val int
   207  			if _, err := asn1.Unmarshal(id.FullBytes, &val); err != nil {
   208  				nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ASIdentifiers.asIdsOrRanges[%d].id: %v", i, err))
   209  				continue
   210  			}
   211  			asID.ASIDs = append(asID.ASIDs, val)
   212  
   213  		case asn1.TagSequence:
   214  			var val ASIDRange
   215  			if _, err := asn1.Unmarshal(id.FullBytes, &val); err != nil {
   216  				nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ASIdentifiers.asIdsOrRanges[%d].range: %v", i, err))
   217  				continue
   218  			}
   219  			asID.ASIDRanges = append(asID.ASIDRanges, val)
   220  
   221  		default:
   222  			nfe.AddError(fmt.Errorf("unexpected value in ASIdentifiers.asIdsOrRanges[%d]: %+v", i, id))
   223  		}
   224  	}
   225  	return &asID
   226  }
   227  
   228  func parseRPKIASIdentifiers(data []byte, nfe *NonFatalErrors) (*ASIdentifiers, *ASIdentifiers) {
   229  	// RFC 3779 2.3.2
   230  	//   ASIdentifiers       ::= SEQUENCE {
   231  	//       asnum               [0] EXPLICIT ASIdentifierChoice OPTIONAL,
   232  	//       rdi                 [1] EXPLICIT ASIdentifierChoice OPTIONAL}
   233  	var asIDs asIdentifiers
   234  	if rest, err := asn1.Unmarshal(data, &asIDs); err != nil {
   235  		nfe.AddError(fmt.Errorf("failed to asn1.Unmarshal ASIdentifiers extension: %v", err))
   236  		return nil, nil
   237  	} else if len(rest) != 0 {
   238  		nfe.AddError(errors.New("trailing data after ASIdentifiers extension"))
   239  		return nil, nil
   240  	}
   241  	return parseASIDChoice(asIDs.ASNum, nfe), parseASIDChoice(asIDs.RDI, nfe)
   242  }
   243  

View as plain text