Source file src/crypto/x509/parser_test.go

     1  // Copyright 2021 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  	"encoding/asn1"
     9  	"encoding/pem"
    10  	"os"
    11  	"testing"
    12  
    13  	cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
    14  )
    15  
    16  func TestParseASN1String(t *testing.T) {
    17  	tests := []struct {
    18  		name        string
    19  		tag         cryptobyte_asn1.Tag
    20  		value       []byte
    21  		expected    string
    22  		expectedErr string
    23  	}{
    24  		{
    25  			name:     "T61String",
    26  			tag:      cryptobyte_asn1.T61String,
    27  			value:    []byte{0xbf, 0x61, 0x3f},
    28  			expected: string("¿a?"),
    29  		},
    30  		{
    31  			name:     "PrintableString",
    32  			tag:      cryptobyte_asn1.PrintableString,
    33  			value:    []byte{80, 81, 82},
    34  			expected: string("PQR"),
    35  		},
    36  		{
    37  			name:        "PrintableString (invalid)",
    38  			tag:         cryptobyte_asn1.PrintableString,
    39  			value:       []byte{1, 2, 3},
    40  			expectedErr: "invalid PrintableString",
    41  		},
    42  		{
    43  			name:     "UTF8String",
    44  			tag:      cryptobyte_asn1.UTF8String,
    45  			value:    []byte{80, 81, 82},
    46  			expected: string("PQR"),
    47  		},
    48  		{
    49  			name:        "UTF8String (invalid)",
    50  			tag:         cryptobyte_asn1.UTF8String,
    51  			value:       []byte{255},
    52  			expectedErr: "invalid UTF-8 string",
    53  		},
    54  		{
    55  			name:     "BMPString",
    56  			tag:      cryptobyte_asn1.Tag(asn1.TagBMPString),
    57  			value:    []byte{80, 81},
    58  			expected: string("偑"),
    59  		},
    60  		{
    61  			name:        "BMPString (invalid length)",
    62  			tag:         cryptobyte_asn1.Tag(asn1.TagBMPString),
    63  			value:       []byte{255},
    64  			expectedErr: "invalid BMPString",
    65  		},
    66  		{
    67  			name:        "BMPString (invalid surrogate)",
    68  			tag:         cryptobyte_asn1.Tag(asn1.TagBMPString),
    69  			value:       []byte{80, 81, 216, 1},
    70  			expectedErr: "invalid BMPString",
    71  		},
    72  		{
    73  			name:        "BMPString (invalid noncharacter 0xfdd1)",
    74  			tag:         cryptobyte_asn1.Tag(asn1.TagBMPString),
    75  			value:       []byte{80, 81, 253, 209},
    76  			expectedErr: "invalid BMPString",
    77  		},
    78  		{
    79  			name:        "BMPString (invalid noncharacter 0xffff)",
    80  			tag:         cryptobyte_asn1.Tag(asn1.TagBMPString),
    81  			value:       []byte{80, 81, 255, 255},
    82  			expectedErr: "invalid BMPString",
    83  		},
    84  		{
    85  			name:        "BMPString (invalid noncharacter 0xfffe)",
    86  			tag:         cryptobyte_asn1.Tag(asn1.TagBMPString),
    87  			value:       []byte{80, 81, 255, 254},
    88  			expectedErr: "invalid BMPString",
    89  		},
    90  		{
    91  			name:     "IA5String",
    92  			tag:      cryptobyte_asn1.IA5String,
    93  			value:    []byte{80, 81},
    94  			expected: string("PQ"),
    95  		},
    96  		{
    97  			name:        "IA5String (invalid)",
    98  			tag:         cryptobyte_asn1.IA5String,
    99  			value:       []byte{255},
   100  			expectedErr: "invalid IA5String",
   101  		},
   102  		{
   103  			name:     "NumericString",
   104  			tag:      cryptobyte_asn1.Tag(asn1.TagNumericString),
   105  			value:    []byte{49, 50},
   106  			expected: string("12"),
   107  		},
   108  		{
   109  			name:        "NumericString (invalid)",
   110  			tag:         cryptobyte_asn1.Tag(asn1.TagNumericString),
   111  			value:       []byte{80},
   112  			expectedErr: "invalid NumericString",
   113  		},
   114  	}
   115  
   116  	for _, tc := range tests {
   117  		t.Run(tc.name, func(t *testing.T) {
   118  			out, err := parseASN1String(tc.tag, tc.value)
   119  			if err != nil && err.Error() != tc.expectedErr {
   120  				t.Fatalf("parseASN1String returned unexpected error: got %q, want %q", err, tc.expectedErr)
   121  			} else if err == nil && tc.expectedErr != "" {
   122  				t.Fatalf("parseASN1String didn't fail, expected: %s", tc.expectedErr)
   123  			}
   124  			if out != tc.expected {
   125  				t.Fatalf("parseASN1String returned unexpected value: got %q, want %q", out, tc.expected)
   126  			}
   127  		})
   128  	}
   129  }
   130  
   131  const policyPEM = `-----BEGIN CERTIFICATE-----
   132  MIIGeDCCBWCgAwIBAgIUED9KQBi0ScBDoufB2mgAJ63G5uIwDQYJKoZIhvcNAQEL
   133  BQAwVTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDENMAsG
   134  A1UECxMERlBLSTEdMBsGA1UEAxMURmVkZXJhbCBCcmlkZ2UgQ0EgRzQwHhcNMjAx
   135  MDIyMTcwNDE5WhcNMjMxMDIyMTcwNDE5WjCBgTELMAkGA1UEBhMCVVMxHTAbBgNV
   136  BAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVz
   137  dCBOZXR3b3JrMTIwMAYDVQQDEylTeW1hbnRlYyBDbGFzcyAzIFNTUCBJbnRlcm1l
   138  ZGlhdGUgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2p
   139  75cMpx86sS2aH4r+0o8r+m/KTrPrknWP0RA9Kp6sewAzkNa7BVwg0jOhyamiv1iP
   140  Cns10usoH93nxYbXLWF54vOLRdYU/53KEPNmgkj2ipMaTLuaReBghNibikWSnAmy
   141  S8RItaDMs8tdF2goKPI4xWiamNwqe92VC+pic2tq0Nva3Y4kvMDJjtyje3uduTtL
   142  oyoaaHkrX7i7gE67psnMKj1THUtre1JV1ohl9+oOuyot4p3eSxVlrMWiiwb11bnk
   143  CakecOz/mP2DHMGg6pZ/BeJ+ThaLUylAXECARIqHc9UwRPKC9BfLaCX4edIoeYiB
   144  loRs4KdqLdg/I9eTwKkCAwEAAaOCAxEwggMNMB0GA1UdDgQWBBQ1Jn1QleGhwb0F
   145  1cOdd0LHDBOWjDAfBgNVHSMEGDAWgBR58ABJ6393wl1BAmU0ipAjmx4HbzAOBgNV
   146  HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCBiAYDVR0gBIGAMH4wDAYKYIZI
   147  AWUDAgEDAzAMBgpghkgBZQMCAQMMMAwGCmCGSAFlAwIBAw4wDAYKYIZIAWUDAgED
   148  DzAMBgpghkgBZQMCAQMSMAwGCmCGSAFlAwIBAxMwDAYKYIZIAWUDAgEDFDAMBgpg
   149  hkgBZQMCAQMlMAwGCmCGSAFlAwIBAyYwggESBgNVHSEEggEJMIIBBTAbBgpghkgB
   150  ZQMCAQMDBg1ghkgBhvhFAQcXAwEGMBsGCmCGSAFlAwIBAwwGDWCGSAGG+EUBBxcD
   151  AQcwGwYKYIZIAWUDAgEDDgYNYIZIAYb4RQEHFwMBDjAbBgpghkgBZQMCAQMPBg1g
   152  hkgBhvhFAQcXAwEPMBsGCmCGSAFlAwIBAxIGDWCGSAGG+EUBBxcDARIwGwYKYIZI
   153  AWUDAgEDEwYNYIZIAYb4RQEHFwMBETAbBgpghkgBZQMCAQMUBg1ghkgBhvhFAQcX
   154  AwEUMBsGCmCGSAFlAwIBAyUGDWCGSAGG+EUBBxcDAQgwGwYKYIZIAWUDAgEDJgYN
   155  YIZIAYb4RQEHFwMBJDBgBggrBgEFBQcBCwRUMFIwUAYIKwYBBQUHMAWGRGh0dHA6
   156  Ly9zc3Atc2lhLnN5bWF1dGguY29tL1NUTlNTUC9DZXJ0c19Jc3N1ZWRfYnlfQ2xh
   157  c3MzU1NQQ0EtRzMucDdjMA8GA1UdJAQIMAaAAQCBAQAwCgYDVR02BAMCAQAwUQYI
   158  KwYBBQUHAQEERTBDMEEGCCsGAQUFBzAChjVodHRwOi8vcmVwby5mcGtpLmdvdi9i
   159  cmlkZ2UvY2FDZXJ0c0lzc3VlZFRvZmJjYWc0LnA3YzA3BgNVHR8EMDAuMCygKqAo
   160  hiZodHRwOi8vcmVwby5mcGtpLmdvdi9icmlkZ2UvZmJjYWc0LmNybDANBgkqhkiG
   161  9w0BAQsFAAOCAQEAA751TycC1f/WTkHmedF9ZWxP58Jstmwvkyo8bKueJ0eF7LTG
   162  BgQlzE2B9vke4sFhd4V+BdgOPGE1dsGzllYKCWg0BhkCBs5kIJ7F6Ay6G1TBuGU1
   163  Ie8247GL+P9pcC5TVvXHC/62R2w3DuD/vAPLbYEbSQjobXlsqt8Kmtd6yK/jVuDV
   164  BTZMdZmvoNtjemqmgcBXHsf0ctVm0m6tH5uYqyVxu8tfyUis6Cf303PHj+spWP1k
   165  gc5PYnVF0ot7qAmNFENIpbKg3BdusBkF9rGxLaDSUBvSc7+s9iQz9d/iRuAebrYu
   166  +eqUlJ2lsjS1U8qyPmlH+spfPNbAEQEsuP32Aw==
   167  -----END CERTIFICATE-----
   168  `
   169  
   170  func TestPolicyParse(t *testing.T) {
   171  	b, _ := pem.Decode([]byte(policyPEM))
   172  	c, err := ParseCertificate(b.Bytes)
   173  	if err != nil {
   174  		t.Fatal(err)
   175  	}
   176  	if len(c.Policies) != 9 {
   177  		t.Errorf("unexpected number of policies: got %d, want %d", len(c.Policies), 9)
   178  	}
   179  	if len(c.PolicyMappings) != 9 {
   180  		t.Errorf("unexpected number of policy mappings: got %d, want %d", len(c.PolicyMappings), 9)
   181  	}
   182  	if !c.RequireExplicitPolicyZero {
   183  		t.Error("expected RequireExplicitPolicyZero to be set")
   184  	}
   185  	if !c.InhibitPolicyMappingZero {
   186  		t.Error("expected InhibitPolicyMappingZero to be set")
   187  	}
   188  	if !c.InhibitAnyPolicyZero {
   189  		t.Error("expected InhibitAnyPolicyZero to be set")
   190  	}
   191  }
   192  
   193  func TestParsePolicies(t *testing.T) {
   194  	for _, tc := range []string{
   195  		"testdata/policy_leaf_duplicate.pem",
   196  		"testdata/policy_leaf_invalid.pem",
   197  	} {
   198  		t.Run(tc, func(t *testing.T) {
   199  			b, err := os.ReadFile(tc)
   200  			if err != nil {
   201  				t.Fatal(err)
   202  			}
   203  			p, _ := pem.Decode(b)
   204  			_, err = ParseCertificate(p.Bytes)
   205  			if err == nil {
   206  				t.Error("parsing should've failed")
   207  			}
   208  		})
   209  	}
   210  }
   211  

View as plain text