github.com/zmap/zcrypto@v0.0.0-20240512203510-0fef58d9a9db/x509/revocation/google/google_test.go (about)

     1  package google_test
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/zmap/zcrypto/x509"
    12  	"github.com/zmap/zcrypto/x509/revocation/google"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // obtained from https://firefox.settings.services.mozilla.com/v1/buckets/blocklists/collections/certificates/records
    19  const crlset_location = `./testdata/test_crlset`
    20  const VERSION = "4619"
    21  
    22  const revoked_intermediate = `
    23  -----BEGIN CERTIFICATE-----
    24  MIIHVTCCBT2gAwIBAgIIEOqAPvgqxt8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE
    25  BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
    26  cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xMzAyMjAxMDAzMTdaFw0zMDEy
    27  MzEwNTA1NDJaMIGNMQswCQYDVQQGEwJFUzEeMBwGA1UEChMVRmlybWFwcm9mZXNp
    28  b25hbCBTLkEuMRowGAYDVQQLExFTZWN1cml0eSBTZXJ2aWNlczESMBAGA1UEBRMJ
    29  QTYyNjM0MDY4MS4wLAYDVQQDEyVBQyBGaXJtYXByb2Zlc2lvbmFsIC0gSU5GUkFF
    30  U1RSVUNUVVJBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuqX7V9RP
    31  HmZ/SpGlhXSfREEtOiiRS8SdJC1QuOB2EYLiFEeL2QFZHIRP4HBm+CbLZ7ts+GLD
    32  5XOGWa84Q9BgRI2HXF4E9PeCQh+ejtnnpDRQlx/cIkX5zt750xXfjArifVS4IUHR
    33  fiyfZmNuyn3qqB5O/nz1K/YelKSZtbjc00qlwXU4sfrZRFJgm0PD6oxJqLoU8VVE
    34  jBzdbVWsG9KEc91gG0u5UJZyLWGJP2f7I/zrki2WOf9SPfrA01viYw2PSe/81Z7O
    35  tADKy076N6Z8ky4HaS1aNsqxx/LTylUh+9O0ccGKSQSpO87LFbrKNilGvIRQYzrj
    36  ItUawGsF0KuUEwIDAQABo4IC8jCCAu4wdAYIKwYBBQUHAQEEaDBmMDYGCCsGAQUF
    37  BzAChipodHRwOi8vY3JsLmZpcm1hcHJvZmVzaW9uYWwuY29tL2Nhcm9vdC5jcnQw
    38  LAYIKwYBBQUHMAGGIGh0dHA6Ly9vY3NwLmZpcm1hcHJvZmVzaW9uYWwuY29tMB0G
    39  A1UdDgQWBBRiFau1swh5pYf+gNki8I78jxH9eTASBgNVHRMBAf8ECDAGAQH/AgEA
    40  MB8GA1UdIwQYMBaAFGXN66s1HgA+ftV0wBy0c0cOGmQvMIIB0gYDVR0gBIIByTCC
    41  AcUwggHBBgorBgEEAeZ5CgoBMIIBsTAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5m
    42  aXJtYXByb2Zlc2lvbmFsLmNvbS9jcHMwggF8BggrBgEFBQcCAjCCAW4eggFqAEMA
    43  ZQByAHQAaQBmAGkAYwBhAGQAbwAgAGQAZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAA
    44  ZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAuACAAQwBvAG4AcwB1AGwA
    45  dABlACAAbABhAHMAIABjAG8AbgBkAGkAYwBpAG8AbgBlAHMAIABkAGUAIAB1AHMA
    46  bwAgAGUAbgAgAC8AIABDAGUAcgB0AGkAZgBpAGMAYQB0AGkAbwBuACAAQQB1AHQA
    47  aABvAHIAaQB0AHkAIABjAGUAcgB0AGkAZgBpAGMAYQB0AGUALgAgAFMAZQBlACAA
    48  dABlAHIAbQBzACAAYQBuAGQAIABjAG8AbgBkAGkAdABpAG8AbgBzACAAYQB0ACAA
    49  IABoAHQAdABwADoALwAvAHcAdwB3AC4AZgBpAHIAbQBhAHAAcgBvAGYAZQBzAGkA
    50  bwBuAGEAbAAuAGMAbwBtAC8AYwBwAHMwPAYDVR0fBDUwMzAxoC+gLYYraHR0cHM6
    51  Ly9jcmwuZmlybWFwcm9mZXNpb25hbC5jb20vZnByb290LmNybDAOBgNVHQ8BAf8E
    52  BAMCAQYwDQYJKoZIhvcNAQEFBQADggIBAGRD/ej1VKQGfWiBwL8I6plyFfvplmwO
    53  +N7EpzUifUgn2sDHiL2L2V5nQdN2lLL5tI83JimPKybrHbv9EwSGPsTOgY+8HWCA
    54  iaq9dLKVHRK93/FvI+Wj63X6pvx5YDiT2Kq7RuXQFx8AG+acwMa7WHaeravzAiSd
    55  pak4qW5KlZ54RxiTNtFGwuEGpHc7wakdWSH3hUYfXNLz8JC9DmNqG8ZxAf3Z8AJq
    56  vIeH4NRPkZ6//QG5JzPowb8eNG2v84ZYQStIAsHa0sVdq9o/zK9x2isv4Y+5GAw4
    57  bnfq14G23Zh1oFS2T6la7W+AR3OGhP8Y6Xt+TFhn10yfE4TrFGNr20akj2TddsMj
    58  SAatoB2gE3f7wTFsrXdJn0aJ/18KdlqV0NNuHrs/ZOIhnt7qswZVQfeQHHUQpwOp
    59  CJrveDbSDZz3Kmo0afJtkcyAnZEPdFdyq8YgqfSqyJs6PJuemsj2ipai0gWO/3f8
    60  EcApsll70fMRVXfOObBcO+hEO1tN0etNLlT5mlulpbMpkJ6hRgcHmVqogw1YJhmL
    61  /E03f6Lw8aaCT9yDunE66bFZ/gwNky0V9PvCQni4GmGSKqcM2hFPux6FIWOOokBE
    62  bicOgqIPCJodWamv++aE/6VKV6Th5gyYBJQ5Pjb6BRxpXtCVAVrev9ZIFcmYn6LX
    63  wp6ggHtX2lGF
    64  -----END CERTIFICATE-----
    65  `
    66  
    67  const PARENT_SPKI_HASH = `3b0d73b4be4a854adc3e51d7ef9fa48aefbb2cdd824d67bdc7d7d09a2abc2d43`
    68  
    69  func parseCertPEM(t *testing.T) (revoked *x509.Certificate) {
    70  	certPool := x509.NewCertPool()
    71  	ok := certPool.AppendCertsFromPEM([]byte(revoked_intermediate))
    72  	if !ok {
    73  		t.Fail()
    74  	}
    75  	revoked = certPool.Certificates()[0]
    76  	return
    77  }
    78  
    79  func loadRevokedList(t *testing.T) (crlset *google.CRLSet) {
    80  	crlSetFile, err := os.Open(crlset_location)
    81  	if err != nil {
    82  		t.Error(err.Error())
    83  	}
    84  	defer crlSetFile.Close()
    85  
    86  	crlSetBytes, err := ioutil.ReadAll(crlSetFile)
    87  	if err != nil {
    88  		t.Error(err.Error())
    89  	}
    90  
    91  	crlset, err = google.Parse(crlSetBytes, VERSION)
    92  	if err != nil {
    93  		t.Error(err.Error())
    94  	}
    95  	return
    96  }
    97  
    98  // Parses a static, stored version of an issued CRLSet - to prevent
    99  // unexpected breakage with tests, use this instead of a live
   100  // fetch when possible
   101  func TestParse(t *testing.T) {
   102  	loadRevokedList(t)
   103  }
   104  
   105  func TestParse6375(t *testing.T) {
   106  	raw, err := ioutil.ReadFile("testdata/crl-set-6375")
   107  	if err != nil {
   108  		t.Error(err.Error())
   109  	}
   110  
   111  	set, err := google.Parse(raw, "6375")
   112  	if err != nil {
   113  		t.Error(err.Error())
   114  	}
   115  	if "6375" != set.Version {
   116  		t.Fail()
   117  	}
   118  }
   119  
   120  // just tests that there are no major complaints when live fetching,
   121  // don't actually use this in case google removes our testing intermediate
   122  // cert from the revocation list
   123  func TestFetchRemote(t *testing.T) {
   124  	list, err := google.FetchAndParse()
   125  	if list == nil || err != nil {
   126  		t.Fail()
   127  	}
   128  }
   129  
   130  func TestCheck(t *testing.T) {
   131  	revoked := parseCertPEM(t)
   132  	crlset := loadRevokedList(t)
   133  
   134  	entry := crlset.Check(revoked, PARENT_SPKI_HASH)
   135  	if entry == nil { // this should provide an entry, since cert is revoked and in the provided sst file
   136  		t.Fail()
   137  	}
   138  	if entry.SerialNumber.Cmp(revoked.SerialNumber) != 0 {
   139  		t.Fail()
   140  	}
   141  }
   142  
   143  func TestFetch(t *testing.T) {
   144  	bytes, err := ioutil.ReadFile("testdata/APm1SaUzZaPllaSDuZS5yng")
   145  	require.NoError(t, err)
   146  
   147  	versionResponse := `xml version="1.0" encoding="UTF-8"?>
   148  	<gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod">
   149  	<daystart elapsed_days="5134" elapsed_seconds="36004"/>
   150  	<app appid="hfnkpimlhhgieaddgfemjhofmfblmnib" cohort="1:jcl:" cohortname="Auto" status="ok">
   151  	<updatecheck codebase="http://dl.google.com/APm1SaUzZaPllaSDuZS5yng" 
   152  	fp="1.dfee9fe7c749d1d15c6e8118bfe5281a0263474de2037516a525c3a885afe763" hash="LSXbDXGMp13JH5whBObmE4X7qCE=" hash_sha256="dfee9fe7c749d1d15c6e8118bfe5281a0263474de2037516a525c3a885afe763" size="24898" status="ok" version="6376"/>
   153  	</app>
   154  	</gupdate>`
   155  
   156  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   157  		w.WriteHeader(http.StatusOK)
   158  
   159  		if r.RequestURI == "/APm1SaUzZaPllaSDuZS5yng" {
   160  			w.Write(bytes)
   161  		} else {
   162  			w.Write([]byte(versionResponse))
   163  		}
   164  	})
   165  	server := httptest.NewServer(h)
   166  	defer server.Close()
   167  
   168  	versionResponse = strings.Replace(versionResponse,
   169  		"http://dl.google.com/APm1SaUzZaPllaSDuZS5yng",
   170  		server.URL+"/APm1SaUzZaPllaSDuZS5yng", 1)
   171  
   172  	p := google.NewProvider(server.URL)
   173  	set, err := p.FetchAndParse()
   174  	require.NoError(t, err)
   175  	assert.Equal(t, 6376, set.Sequence)
   176  }