gitee.com/mysnapcore/mysnapd@v0.1.0/asserts/asserts_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2015-2022 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package asserts_test
    21  
    22  import (
    23  	"bytes"
    24  	"io"
    25  	"strings"
    26  
    27  	. "gopkg.in/check.v1"
    28  
    29  	"gitee.com/mysnapcore/mysnapd/asserts"
    30  )
    31  
    32  type assertsSuite struct{}
    33  
    34  var _ = Suite(&assertsSuite{})
    35  
    36  func (as *assertsSuite) TestType(c *C) {
    37  	c.Check(asserts.Type("test-only"), Equals, asserts.TestOnlyType)
    38  }
    39  
    40  func (as *assertsSuite) TestUnknown(c *C) {
    41  	c.Check(asserts.Type(""), IsNil)
    42  	c.Check(asserts.Type("unknown"), IsNil)
    43  }
    44  
    45  func (as *assertsSuite) TestTypeMaxSupportedFormat(c *C) {
    46  	c.Check(asserts.Type("test-only").MaxSupportedFormat(), Equals, 1)
    47  }
    48  
    49  func (as *assertsSuite) TestTypeNames(c *C) {
    50  	c.Check(asserts.TypeNames(), DeepEquals, []string{
    51  		"account",
    52  		"account-key",
    53  		"account-key-request",
    54  		// XXX "authority-delegation",
    55  		"base-declaration",
    56  		"device-session-request",
    57  		"model",
    58  		"preseed",
    59  		"repair",
    60  		"serial",
    61  		"serial-request",
    62  		"snap-build",
    63  		"snap-declaration",
    64  		"snap-developer",
    65  		"snap-revision",
    66  		"store",
    67  		"system-user",
    68  		"test-only",
    69  		"test-only-2",
    70  		"test-only-decl",
    71  		"test-only-no-authority",
    72  		"test-only-no-authority-pk",
    73  		"test-only-rev",
    74  		"test-only-seq",
    75  		"validation",
    76  		"validation-set",
    77  	})
    78  }
    79  
    80  func (as *assertsSuite) TestMaxSupportedFormats(c *C) {
    81  	snapDeclMaxFormat := asserts.SnapDeclarationType.MaxSupportedFormat()
    82  	systemUserMaxFormat := asserts.SystemUserType.MaxSupportedFormat()
    83  	// validity
    84  	c.Check(snapDeclMaxFormat >= 4, Equals, true)
    85  	c.Check(systemUserMaxFormat >= 2, Equals, true)
    86  	c.Check(asserts.MaxSupportedFormats(1), DeepEquals, map[string]int{
    87  		"snap-declaration": snapDeclMaxFormat,
    88  		"system-user":      systemUserMaxFormat,
    89  		"test-only":        1,
    90  		"test-only-seq":    2,
    91  	})
    92  
    93  	// all
    94  	maxFormats := asserts.MaxSupportedFormats(0)
    95  	c.Assert(maxFormats, HasLen, len(asserts.TypeNames()))
    96  	c.Check(maxFormats["test-only"], Equals, 1)
    97  	c.Check(maxFormats["test-only-2"], Equals, 0)
    98  	c.Check(maxFormats["snap-declaration"], Equals, snapDeclMaxFormat)
    99  }
   100  
   101  func (as *assertsSuite) TestSuggestFormat(c *C) {
   102  	fmtnum, err := asserts.SuggestFormat(asserts.Type("test-only-2"), nil, nil)
   103  	c.Assert(err, IsNil)
   104  	c.Check(fmtnum, Equals, 0)
   105  }
   106  
   107  func (as *assertsSuite) TestPrimaryKeyHelpers(c *C) {
   108  	headers, err := asserts.HeadersFromPrimaryKey(asserts.TestOnlyType, []string{"one"})
   109  	c.Assert(err, IsNil)
   110  	c.Check(headers, DeepEquals, map[string]string{
   111  		"primary-key": "one",
   112  	})
   113  
   114  	headers, err = asserts.HeadersFromPrimaryKey(asserts.TestOnly2Type, []string{"bar", "baz"})
   115  	c.Assert(err, IsNil)
   116  	c.Check(headers, DeepEquals, map[string]string{
   117  		"pk1": "bar",
   118  		"pk2": "baz",
   119  	})
   120  
   121  	_, err = asserts.HeadersFromPrimaryKey(asserts.TestOnly2Type, []string{"bar"})
   122  	c.Check(err, ErrorMatches, `primary key has wrong length for "test-only-2" assertion`)
   123  
   124  	_, err = asserts.HeadersFromPrimaryKey(asserts.TestOnly2Type, []string{"", "baz"})
   125  	c.Check(err, ErrorMatches, `primary key "pk1" header cannot be empty`)
   126  
   127  	pk, err := asserts.PrimaryKeyFromHeaders(asserts.TestOnly2Type, headers)
   128  	c.Assert(err, IsNil)
   129  	c.Check(pk, DeepEquals, []string{"bar", "baz"})
   130  
   131  	headers["other"] = "foo"
   132  	pk1, err := asserts.PrimaryKeyFromHeaders(asserts.TestOnly2Type, headers)
   133  	c.Assert(err, IsNil)
   134  	c.Check(pk1, DeepEquals, pk)
   135  
   136  	delete(headers, "pk2")
   137  	_, err = asserts.PrimaryKeyFromHeaders(asserts.TestOnly2Type, headers)
   138  	c.Check(err, ErrorMatches, `must provide primary key: pk2`)
   139  }
   140  
   141  func (as *assertsSuite) TestPrimaryKeyHelpersOptionalPrimaryKeys(c *C) {
   142  	// optional primary key headers
   143  	r := asserts.MockOptionalPrimaryKey(asserts.TestOnlyType, "opt1", "o1-defl")
   144  	defer r()
   145  
   146  	pk, err := asserts.PrimaryKeyFromHeaders(asserts.TestOnlyType, map[string]string{"primary-key": "k1"})
   147  	c.Assert(err, IsNil)
   148  	c.Check(pk, DeepEquals, []string{"k1", "o1-defl"})
   149  
   150  	pk, err = asserts.PrimaryKeyFromHeaders(asserts.TestOnlyType, map[string]string{"primary-key": "k1", "opt1": "B"})
   151  	c.Assert(err, IsNil)
   152  	c.Check(pk, DeepEquals, []string{"k1", "B"})
   153  
   154  	hdrs, err := asserts.HeadersFromPrimaryKey(asserts.TestOnlyType, []string{"k1", "B"})
   155  	c.Assert(err, IsNil)
   156  	c.Check(hdrs, DeepEquals, map[string]string{
   157  		"primary-key": "k1",
   158  		"opt1":        "B",
   159  	})
   160  
   161  	hdrs, err = asserts.HeadersFromPrimaryKey(asserts.TestOnlyType, []string{"k1"})
   162  	c.Assert(err, IsNil)
   163  	c.Check(hdrs, DeepEquals, map[string]string{
   164  		"primary-key": "k1",
   165  		"opt1":        "o1-defl",
   166  	})
   167  
   168  	_, err = asserts.HeadersFromPrimaryKey(asserts.TestOnlyType, nil)
   169  	c.Check(err, ErrorMatches, `primary key has wrong length for "test-only" assertion`)
   170  
   171  	_, err = asserts.HeadersFromPrimaryKey(asserts.TestOnlyType, []string{"pk", "opt1", "what"})
   172  	c.Check(err, ErrorMatches, `primary key has wrong length for "test-only" assertion`)
   173  }
   174  
   175  func (as *assertsSuite) TestRef(c *C) {
   176  	ref := &asserts.Ref{
   177  		Type:       asserts.TestOnly2Type,
   178  		PrimaryKey: []string{"abc", "xyz"},
   179  	}
   180  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz")
   181  }
   182  
   183  func (as *assertsSuite) TestRefString(c *C) {
   184  	ref := &asserts.Ref{
   185  		Type:       asserts.AccountType,
   186  		PrimaryKey: []string{"canonical"},
   187  	}
   188  
   189  	c.Check(ref.String(), Equals, "account (canonical)")
   190  
   191  	ref = &asserts.Ref{
   192  		Type:       asserts.SnapDeclarationType,
   193  		PrimaryKey: []string{"18", "SNAPID"},
   194  	}
   195  
   196  	c.Check(ref.String(), Equals, "snap-declaration (SNAPID; series:18)")
   197  
   198  	ref = &asserts.Ref{
   199  		Type:       asserts.ModelType,
   200  		PrimaryKey: []string{"18", "BRAND", "baz-3000"},
   201  	}
   202  
   203  	c.Check(ref.String(), Equals, "model (baz-3000; series:18 brand-id:BRAND)")
   204  
   205  	// broken primary key
   206  	ref = &asserts.Ref{
   207  		Type:       asserts.ModelType,
   208  		PrimaryKey: []string{"18"},
   209  	}
   210  	c.Check(ref.String(), Equals, "model (???)")
   211  
   212  	ref = &asserts.Ref{
   213  		Type: asserts.TestOnlyNoAuthorityType,
   214  	}
   215  	c.Check(ref.String(), Equals, "test-only-no-authority (-)")
   216  }
   217  
   218  func (as *assertsSuite) TestRefResolveError(c *C) {
   219  	ref := &asserts.Ref{
   220  		Type:       asserts.TestOnly2Type,
   221  		PrimaryKey: []string{"abc"},
   222  	}
   223  	_, err := ref.Resolve(nil)
   224  	c.Check(err, ErrorMatches, `"test-only-2" assertion reference primary key has the wrong length \(expected \[pk1 pk2\]\): \[abc\]`)
   225  }
   226  
   227  func (as *assertsSuite) TestReducePrimaryKey(c *C) {
   228  	// optional primary key headers
   229  	defer asserts.MockOptionalPrimaryKey(asserts.TestOnly2Type, "opt1", "o1-defl")()
   230  	defer asserts.MockOptionalPrimaryKey(asserts.TestOnly2Type, "opt2", "o2-defl")()
   231  
   232  	tests := []struct {
   233  		pk      []string
   234  		reduced []string
   235  	}{
   236  		{nil, nil},
   237  		{[]string{"k1"}, []string{"k1"}},
   238  		{[]string{"k1", "k2"}, []string{"k1", "k2"}},
   239  		{[]string{"k1", "k2", "A"}, []string{"k1", "k2", "A"}},
   240  		{[]string{"k1", "k2", "o1-defl"}, []string{"k1", "k2"}},
   241  		{[]string{"k1", "k2", "A", "o2-defl"}, []string{"k1", "k2", "A"}},
   242  		{[]string{"k1", "k2", "A", "B"}, []string{"k1", "k2", "A", "B"}},
   243  		{[]string{"k1", "k2", "o1-defl", "B"}, []string{"k1", "k2", "o1-defl", "B"}},
   244  		{[]string{"k1", "k2", "o1-defl", "o2-defl"}, []string{"k1", "k2"}},
   245  		{[]string{"k1", "k2", "o1-defl", "o2-defl", "what"}, []string{"k1", "k2", "o1-defl", "o2-defl", "what"}},
   246  	}
   247  
   248  	for _, t := range tests {
   249  		c.Check(asserts.ReducePrimaryKey(asserts.TestOnly2Type, t.pk), DeepEquals, t.reduced)
   250  	}
   251  }
   252  
   253  func (as *assertsSuite) TestRefOptionalPrimaryKeys(c *C) {
   254  	// optional primary key headers
   255  	defer asserts.MockOptionalPrimaryKey(asserts.TestOnly2Type, "opt1", "o1-defl")()
   256  	defer asserts.MockOptionalPrimaryKey(asserts.TestOnly2Type, "opt2", "o2-defl")()
   257  
   258  	ref := &asserts.Ref{
   259  		Type:       asserts.TestOnly2Type,
   260  		PrimaryKey: []string{"abc", "xyz"},
   261  	}
   262  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz")
   263  	c.Check(ref.String(), Equals, `test-only-2 (xyz; pk1:abc)`)
   264  
   265  	ref = &asserts.Ref{
   266  		Type:       asserts.TestOnly2Type,
   267  		PrimaryKey: []string{"abc", "xyz", "o1-defl"},
   268  	}
   269  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz")
   270  	c.Check(ref.String(), Equals, `test-only-2 (xyz; pk1:abc)`)
   271  
   272  	ref = &asserts.Ref{
   273  		Type:       asserts.TestOnly2Type,
   274  		PrimaryKey: []string{"abc", "xyz", "o1-defl", "o2-defl"},
   275  	}
   276  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz")
   277  	c.Check(ref.String(), Equals, `test-only-2 (xyz; pk1:abc)`)
   278  
   279  	ref = &asserts.Ref{
   280  		Type:       asserts.TestOnly2Type,
   281  		PrimaryKey: []string{"abc", "xyz", "A"},
   282  	}
   283  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz/A")
   284  	c.Check(ref.String(), Equals, `test-only-2 (xyz; pk1:abc opt1:A)`)
   285  
   286  	ref = &asserts.Ref{
   287  		Type:       asserts.TestOnly2Type,
   288  		PrimaryKey: []string{"abc", "xyz", "A", "o2-defl"},
   289  	}
   290  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz/A")
   291  	c.Check(ref.String(), Equals, `test-only-2 (xyz; pk1:abc opt1:A)`)
   292  
   293  	ref = &asserts.Ref{
   294  		Type:       asserts.TestOnly2Type,
   295  		PrimaryKey: []string{"abc", "xyz", "o1-defl", "B"},
   296  	}
   297  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz/o1-defl/B")
   298  	c.Check(ref.String(), Equals, `test-only-2 (xyz; pk1:abc opt2:B)`)
   299  
   300  	ref = &asserts.Ref{
   301  		Type:       asserts.TestOnly2Type,
   302  		PrimaryKey: []string{"abc", "xyz", "A", "B"},
   303  	}
   304  	c.Check(ref.Unique(), Equals, "test-only-2/abc/xyz/A/B")
   305  	c.Check(ref.String(), Equals, `test-only-2 (xyz; pk1:abc opt1:A opt2:B)`)
   306  }
   307  
   308  func (as *assertsSuite) TestAcceptablePrimaryKey(c *C) {
   309  	// optional primary key headers
   310  	defer asserts.MockOptionalPrimaryKey(asserts.TestOnly2Type, "opt1", "o1-defl")()
   311  	defer asserts.MockOptionalPrimaryKey(asserts.TestOnly2Type, "opt2", "o2-defl")()
   312  
   313  	tests := []struct {
   314  		pk []string
   315  		ok bool
   316  	}{
   317  		{nil, false},
   318  		{[]string{"k1"}, false},
   319  		{[]string{"k1", "k2"}, true},
   320  		{[]string{"k1", "k2", "A"}, true},
   321  		{[]string{"k1", "k2", "o1-defl"}, true},
   322  		{[]string{"k1", "k2", "A", "B"}, true},
   323  		{[]string{"k1", "k2", "o1-defl", "o2-defl", "what"}, false},
   324  	}
   325  
   326  	for _, t := range tests {
   327  		c.Check(asserts.TestOnly2Type.AcceptablePrimaryKey(t.pk), Equals, t.ok)
   328  	}
   329  }
   330  
   331  func (as *assertsSuite) TestAtRevisionString(c *C) {
   332  	ref := asserts.Ref{
   333  		Type:       asserts.AccountType,
   334  		PrimaryKey: []string{"canonical"},
   335  	}
   336  
   337  	at := &asserts.AtRevision{
   338  		Ref: ref,
   339  	}
   340  	c.Check(at.String(), Equals, "account (canonical) at revision 0")
   341  
   342  	at = &asserts.AtRevision{
   343  		Ref:      ref,
   344  		Revision: asserts.RevisionNotKnown,
   345  	}
   346  	c.Check(at.String(), Equals, "account (canonical)")
   347  }
   348  
   349  const exKeyID = "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij"
   350  
   351  const exampleEmptyBodyAllDefaults = "type: test-only\n" +
   352  	"authority-id: auth-id1\n" +
   353  	"primary-key: abc\n" +
   354  	"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
   355  	"\n\n" +
   356  	"AXNpZw=="
   357  
   358  func (as *assertsSuite) TestDecodeEmptyBodyAllDefaults(c *C) {
   359  	a, err := asserts.Decode([]byte(exampleEmptyBodyAllDefaults))
   360  	c.Assert(err, IsNil)
   361  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   362  	_, ok := a.(*asserts.TestOnly)
   363  	c.Check(ok, Equals, true)
   364  	c.Check(a.Revision(), Equals, 0)
   365  	c.Check(a.Format(), Equals, 0)
   366  	c.Check(a.Body(), IsNil)
   367  	c.Check(a.Header("header1"), IsNil)
   368  	c.Check(a.HeaderString("header1"), Equals, "")
   369  	c.Check(a.AuthorityID(), Equals, "auth-id1")
   370  	c.Check(a.SignKeyID(), Equals, exKeyID)
   371  }
   372  
   373  const exampleEmptyBodyOptionalPrimaryKeySet = "type: test-only\n" +
   374  	"authority-id: auth-id1\n" +
   375  	"primary-key: abc\n" +
   376  	"opt1: A\n" +
   377  	"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
   378  	"\n\n" +
   379  	"AXNpZw=="
   380  
   381  func (as *assertsSuite) TestDecodeOptionalPrimaryKeys(c *C) {
   382  	r := asserts.MockOptionalPrimaryKey(asserts.TestOnlyType, "opt1", "o1-defl")
   383  	defer r()
   384  
   385  	a, err := asserts.Decode([]byte(exampleEmptyBodyAllDefaults))
   386  	c.Assert(err, IsNil)
   387  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   388  	_, ok := a.(*asserts.TestOnly)
   389  	c.Check(ok, Equals, true)
   390  	c.Check(a.Revision(), Equals, 0)
   391  	c.Check(a.Format(), Equals, 0)
   392  	c.Check(a.Body(), IsNil)
   393  	c.Check(a.HeaderString("opt1"), Equals, "o1-defl")
   394  	c.Check(a.Header("header1"), IsNil)
   395  	c.Check(a.HeaderString("header1"), Equals, "")
   396  	c.Check(a.AuthorityID(), Equals, "auth-id1")
   397  	c.Check(a.SignKeyID(), Equals, exKeyID)
   398  
   399  	a, err = asserts.Decode([]byte(exampleEmptyBodyOptionalPrimaryKeySet))
   400  	c.Assert(err, IsNil)
   401  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   402  	_, ok = a.(*asserts.TestOnly)
   403  	c.Check(ok, Equals, true)
   404  	c.Check(a.Revision(), Equals, 0)
   405  	c.Check(a.Format(), Equals, 0)
   406  	c.Check(a.Body(), IsNil)
   407  	c.Check(a.HeaderString("opt1"), Equals, "A")
   408  	c.Check(a.Header("header1"), IsNil)
   409  	c.Check(a.HeaderString("header1"), Equals, "")
   410  	c.Check(a.AuthorityID(), Equals, "auth-id1")
   411  	c.Check(a.SignKeyID(), Equals, exKeyID)
   412  }
   413  
   414  const exampleEmptyBody2NlNl = "type: test-only\n" +
   415  	"authority-id: auth-id1\n" +
   416  	"primary-key: xyz\n" +
   417  	"revision: 0\n" +
   418  	"body-length: 0\n" +
   419  	"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
   420  	"\n\n" +
   421  	"\n\n" +
   422  	"AXNpZw==\n"
   423  
   424  func (as *assertsSuite) TestDecodeEmptyBodyNormalize2NlNl(c *C) {
   425  	a, err := asserts.Decode([]byte(exampleEmptyBody2NlNl))
   426  	c.Assert(err, IsNil)
   427  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   428  	c.Check(a.Revision(), Equals, 0)
   429  	c.Check(a.Format(), Equals, 0)
   430  	c.Check(a.Body(), IsNil)
   431  }
   432  
   433  const exampleBodyAndExtraHeaders = "type: test-only\n" +
   434  	"format: 1\n" +
   435  	"authority-id: auth-id2\n" +
   436  	"primary-key: abc\n" +
   437  	"revision: 5\n" +
   438  	"header1: value1\n" +
   439  	"header2: value2\n" +
   440  	"body-length: 8\n" +
   441  	"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
   442  	"THE-BODY" +
   443  	"\n\n" +
   444  	"AXNpZw==\n"
   445  
   446  func (as *assertsSuite) TestDecodeWithABodyAndExtraHeaders(c *C) {
   447  	a, err := asserts.Decode([]byte(exampleBodyAndExtraHeaders))
   448  	c.Assert(err, IsNil)
   449  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   450  	c.Check(a.AuthorityID(), Equals, "auth-id2")
   451  	c.Check(a.SignKeyID(), Equals, exKeyID)
   452  	c.Check(a.Header("primary-key"), Equals, "abc")
   453  	c.Check(a.Revision(), Equals, 5)
   454  	c.Check(a.Format(), Equals, 1)
   455  	c.Check(a.SupportedFormat(), Equals, true)
   456  	c.Check(a.Header("header1"), Equals, "value1")
   457  	c.Check(a.Header("header2"), Equals, "value2")
   458  	c.Check(a.Body(), DeepEquals, []byte("THE-BODY"))
   459  
   460  }
   461  
   462  const exampleUnsupportedFormat = "type: test-only\n" +
   463  	"format: 77\n" +
   464  	"authority-id: auth-id2\n" +
   465  	"primary-key: abc\n" +
   466  	"revision: 5\n" +
   467  	"header1: value1\n" +
   468  	"header2: value2\n" +
   469  	"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
   470  	"AXNpZw==\n"
   471  
   472  func (as *assertsSuite) TestDecodeUnsupportedFormat(c *C) {
   473  	a, err := asserts.Decode([]byte(exampleUnsupportedFormat))
   474  	c.Assert(err, IsNil)
   475  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   476  	c.Check(a.AuthorityID(), Equals, "auth-id2")
   477  	c.Check(a.SignKeyID(), Equals, exKeyID)
   478  	c.Check(a.Header("primary-key"), Equals, "abc")
   479  	c.Check(a.Revision(), Equals, 5)
   480  	c.Check(a.Format(), Equals, 77)
   481  	c.Check(a.SupportedFormat(), Equals, false)
   482  }
   483  
   484  func (as *assertsSuite) TestDecodeGetSignatureBits(c *C) {
   485  	content := "type: test-only\n" +
   486  		"authority-id: auth-id1\n" +
   487  		"primary-key: xyz\n" +
   488  		"revision: 5\n" +
   489  		"header1: value1\n" +
   490  		"body-length: 8\n" +
   491  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
   492  		"THE-BODY"
   493  	encoded := content +
   494  		"\n\n" +
   495  		"AXNpZw=="
   496  	a, err := asserts.Decode([]byte(encoded))
   497  	c.Assert(err, IsNil)
   498  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   499  	c.Check(a.AuthorityID(), Equals, "auth-id1")
   500  	c.Check(a.SignKeyID(), Equals, exKeyID)
   501  	cont, signature := a.Signature()
   502  	c.Check(signature, DeepEquals, []byte("AXNpZw=="))
   503  	c.Check(cont, DeepEquals, []byte(content))
   504  }
   505  
   506  func (as *assertsSuite) TestDecodeNoSignatureSplit(c *C) {
   507  	for _, encoded := range []string{"", "foo"} {
   508  		_, err := asserts.Decode([]byte(encoded))
   509  		c.Check(err, ErrorMatches, "assertion content/signature separator not found")
   510  	}
   511  }
   512  
   513  func (as *assertsSuite) TestDecodeHeaderParsingErrors(c *C) {
   514  	headerParsingErrorsTests := []struct{ encoded, expectedErr string }{
   515  		{string([]byte{255, '\n', '\n'}), "header is not utf8"},
   516  		{"foo: a\nbar\n\n", `header entry missing ':' separator: "bar"`},
   517  		{"TYPE: foo\n\n", `invalid header name: "TYPE"`},
   518  		{"foo: a\nbar:>\n\n", `header entry should have a space or newline \(for multiline\) before value: "bar:>"`},
   519  		{"foo: a\nbar:\n\n", `expected 4 chars nesting prefix after multiline introduction "bar:": EOF`},
   520  		{"foo: a\nbar:\nbaz: x\n\n", `expected 4 chars nesting prefix after multiline introduction "bar:": "baz: x"`},
   521  		{"foo: a:\nbar: b\nfoo: x\n\n", `repeated header: "foo"`},
   522  	}
   523  
   524  	for _, test := range headerParsingErrorsTests {
   525  		_, err := asserts.Decode([]byte(test.encoded))
   526  		c.Check(err, ErrorMatches, "parsing assertion headers: "+test.expectedErr)
   527  	}
   528  }
   529  
   530  func (as *assertsSuite) TestDecodeInvalid(c *C) {
   531  	keyIDHdr := "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n"
   532  	encoded := "type: test-only\n" +
   533  		"format: 0\n" +
   534  		"authority-id: auth-id\n" +
   535  		"primary-key: abc\n" +
   536  		"revision: 0\n" +
   537  		"body-length: 5\n" +
   538  		keyIDHdr +
   539  		"\n" +
   540  		"abcde" +
   541  		"\n\n" +
   542  		"AXNpZw=="
   543  
   544  	invalidAssertTests := []struct{ original, invalid, expectedErr string }{
   545  		{"body-length: 5", "body-length: z", `assertion: "body-length" header is not an integer: z`},
   546  		{"body-length: 5", "body-length: 3", "assertion body length and declared body-length don't match: 5 != 3"},
   547  		{"authority-id: auth-id\n", "", `assertion: "authority-id" header is mandatory`},
   548  		{"authority-id: auth-id\n", "authority-id: \n", `assertion: "authority-id" header should not be empty`},
   549  		{keyIDHdr, "", `assertion: "sign-key-sha3-384" header is mandatory`},
   550  		{keyIDHdr, "sign-key-sha3-384: \n", `assertion: "sign-key-sha3-384" header should not be empty`},
   551  		{keyIDHdr, "sign-key-sha3-384: $\n", `assertion: "sign-key-sha3-384" header cannot be decoded: .*`},
   552  		{keyIDHdr, "sign-key-sha3-384: eHl6\n", `assertion: "sign-key-sha3-384" header does not have the expected bit length: 24`},
   553  		{"AXNpZw==", "", "empty assertion signature"},
   554  		{"type: test-only\n", "", `assertion: "type" header is mandatory`},
   555  		{"type: test-only\n", "type: unknown\n", `unknown assertion type: "unknown"`},
   556  		{"revision: 0\n", "revision: Z\n", `assertion: "revision" header is not an integer: Z`},
   557  		{"revision: 0\n", "revision:\n  - 1\n", `assertion: "revision" header is not an integer: \[1\]`},
   558  		{"revision: 0\n", "revision: 00\n", `assertion: "revision" header has invalid prefix zeros: 00`},
   559  		{"revision: 0\n", "revision: -10\n", "assertion: revision should be positive: -10"},
   560  		{"revision: 0\n", "revision: 99999999999999999999\n", `assertion: "revision" header is out of range: 99999999999999999999`},
   561  		{"format: 0\n", "format: Z\n", `assertion: "format" header is not an integer: Z`},
   562  		{"format: 0\n", "format: -10\n", "assertion: format should be positive: -10"},
   563  		{"primary-key: abc\n", "", `assertion test-only: "primary-key" header is mandatory`},
   564  		{"primary-key: abc\n", "primary-key:\n  - abc\n", `assertion test-only: "primary-key" header must be a string`},
   565  		{"primary-key: abc\n", "primary-key: a/c\n", `assertion test-only: "primary-key" primary key header cannot contain '/'`},
   566  		{"abcde", "ab\xffde", "assertion body is not utf8"},
   567  	}
   568  
   569  	for _, test := range invalidAssertTests {
   570  		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
   571  		_, err := asserts.Decode([]byte(invalid))
   572  		c.Check(err, ErrorMatches, test.expectedErr)
   573  	}
   574  }
   575  
   576  func (as *assertsSuite) TestDecodeNoAuthorityInvalid(c *C) {
   577  	invalid := "type: test-only-no-authority\n" +
   578  		"authority-id: auth-id1\n" +
   579  		"hdr: FOO\n" +
   580  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
   581  		"\n\n" +
   582  		"openpgp c2ln"
   583  
   584  	_, err := asserts.Decode([]byte(invalid))
   585  	c.Check(err, ErrorMatches, `"test-only-no-authority" assertion cannot have authority-id set`)
   586  }
   587  
   588  func checkContent(c *C, a asserts.Assertion, encoded string) {
   589  	expected, err := asserts.Decode([]byte(encoded))
   590  	c.Assert(err, IsNil)
   591  	expectedCont, _ := expected.Signature()
   592  
   593  	cont, _ := a.Signature()
   594  	c.Check(cont, DeepEquals, expectedCont)
   595  }
   596  
   597  func (as *assertsSuite) TestEncoderDecoderHappy(c *C) {
   598  	stream := new(bytes.Buffer)
   599  	enc := asserts.NewEncoder(stream)
   600  	enc.WriteEncoded([]byte(exampleEmptyBody2NlNl))
   601  	enc.WriteEncoded([]byte(exampleBodyAndExtraHeaders))
   602  	enc.WriteEncoded([]byte(exampleEmptyBodyAllDefaults))
   603  
   604  	decoder := asserts.NewDecoder(stream)
   605  	a, err := decoder.Decode()
   606  	c.Assert(err, IsNil)
   607  	c.Check(a.Type(), Equals, asserts.TestOnlyType)
   608  	_, ok := a.(*asserts.TestOnly)
   609  	c.Check(ok, Equals, true)
   610  	checkContent(c, a, exampleEmptyBody2NlNl)
   611  
   612  	a, err = decoder.Decode()
   613  	c.Assert(err, IsNil)
   614  	checkContent(c, a, exampleBodyAndExtraHeaders)
   615  
   616  	a, err = decoder.Decode()
   617  	c.Assert(err, IsNil)
   618  	checkContent(c, a, exampleEmptyBodyAllDefaults)
   619  
   620  	a, err = decoder.Decode()
   621  	c.Assert(err, Equals, io.EOF)
   622  	c.Check(a, IsNil)
   623  }
   624  
   625  func (as *assertsSuite) TestDecodeEmptyStream(c *C) {
   626  	stream := new(bytes.Buffer)
   627  	decoder := asserts.NewDecoder(stream)
   628  	_, err := decoder.Decode()
   629  	c.Check(err, Equals, io.EOF)
   630  }
   631  
   632  func (as *assertsSuite) TestDecoderHappyWithSeparatorsVariations(c *C) {
   633  	streams := []string{
   634  		exampleBodyAndExtraHeaders,
   635  		exampleEmptyBody2NlNl,
   636  		exampleEmptyBodyAllDefaults,
   637  	}
   638  
   639  	for _, streamData := range streams {
   640  		stream := bytes.NewBufferString(streamData)
   641  		decoder := asserts.NewDecoderStressed(stream, 16, 1024, 1024, 1024)
   642  		a, err := decoder.Decode()
   643  		c.Assert(err, IsNil, Commentf("stream: %q", streamData))
   644  
   645  		checkContent(c, a, streamData)
   646  
   647  		a, err = decoder.Decode()
   648  		c.Check(a, IsNil)
   649  		c.Check(err, Equals, io.EOF, Commentf("stream: %q", streamData))
   650  	}
   651  }
   652  
   653  func (as *assertsSuite) TestDecoderHappyWithTrailerDoubleNewlines(c *C) {
   654  	streams := []string{
   655  		exampleBodyAndExtraHeaders,
   656  		exampleEmptyBody2NlNl,
   657  		exampleEmptyBodyAllDefaults,
   658  	}
   659  
   660  	for _, streamData := range streams {
   661  		stream := bytes.NewBufferString(streamData)
   662  		if strings.HasSuffix(streamData, "\n") {
   663  			stream.WriteString("\n")
   664  		} else {
   665  			stream.WriteString("\n\n")
   666  		}
   667  
   668  		decoder := asserts.NewDecoderStressed(stream, 16, 1024, 1024, 1024)
   669  		a, err := decoder.Decode()
   670  		c.Assert(err, IsNil, Commentf("stream: %q", streamData))
   671  
   672  		checkContent(c, a, streamData)
   673  
   674  		a, err = decoder.Decode()
   675  		c.Check(a, IsNil)
   676  		c.Check(err, Equals, io.EOF, Commentf("stream: %q", streamData))
   677  	}
   678  }
   679  
   680  func (as *assertsSuite) TestDecoderUnexpectedEOF(c *C) {
   681  	streamData := exampleBodyAndExtraHeaders + "\n" + exampleEmptyBodyAllDefaults
   682  	fstHeadEnd := strings.Index(exampleBodyAndExtraHeaders, "\n\n")
   683  	sndHeadEnd := len(exampleBodyAndExtraHeaders) + 1 + strings.Index(exampleEmptyBodyAllDefaults, "\n\n")
   684  
   685  	for _, brk := range []int{1, fstHeadEnd / 2, fstHeadEnd, fstHeadEnd + 1, fstHeadEnd + 2, fstHeadEnd + 6} {
   686  		stream := bytes.NewBufferString(streamData[:brk])
   687  		decoder := asserts.NewDecoderStressed(stream, 16, 1024, 1024, 1024)
   688  		_, err := decoder.Decode()
   689  		c.Check(err, Equals, io.ErrUnexpectedEOF, Commentf("brk: %d", brk))
   690  	}
   691  
   692  	for _, brk := range []int{sndHeadEnd, sndHeadEnd + 1} {
   693  		stream := bytes.NewBufferString(streamData[:brk])
   694  		decoder := asserts.NewDecoder(stream)
   695  		_, err := decoder.Decode()
   696  		c.Assert(err, IsNil)
   697  
   698  		_, err = decoder.Decode()
   699  		c.Check(err, Equals, io.ErrUnexpectedEOF, Commentf("brk: %d", brk))
   700  	}
   701  }
   702  
   703  func (as *assertsSuite) TestDecoderBrokenBodySeparation(c *C) {
   704  	streamData := strings.Replace(exampleBodyAndExtraHeaders, "THE-BODY\n\n", "THE-BODY", 1)
   705  	decoder := asserts.NewDecoder(bytes.NewBufferString(streamData))
   706  	_, err := decoder.Decode()
   707  	c.Assert(err, ErrorMatches, "missing content/signature separator")
   708  
   709  	streamData = strings.Replace(exampleBodyAndExtraHeaders, "THE-BODY\n\n", "THE-BODY\n", 1)
   710  	decoder = asserts.NewDecoder(bytes.NewBufferString(streamData))
   711  	_, err = decoder.Decode()
   712  	c.Assert(err, ErrorMatches, "missing content/signature separator")
   713  }
   714  
   715  func (as *assertsSuite) TestDecoderHeadTooBig(c *C) {
   716  	decoder := asserts.NewDecoderStressed(bytes.NewBufferString(exampleBodyAndExtraHeaders), 4, 4, 1024, 1024)
   717  	_, err := decoder.Decode()
   718  	c.Assert(err, ErrorMatches, `error reading assertion headers: maximum size exceeded while looking for delimiter "\\n\\n"`)
   719  }
   720  
   721  func (as *assertsSuite) TestDecoderBodyTooBig(c *C) {
   722  	decoder := asserts.NewDecoderStressed(bytes.NewBufferString(exampleBodyAndExtraHeaders), 1024, 1024, 5, 1024)
   723  	_, err := decoder.Decode()
   724  	c.Assert(err, ErrorMatches, "assertion body length 8 exceeds maximum body size")
   725  }
   726  
   727  func (as *assertsSuite) TestDecoderSignatureTooBig(c *C) {
   728  	decoder := asserts.NewDecoderStressed(bytes.NewBufferString(exampleBodyAndExtraHeaders), 4, 1024, 1024, 7)
   729  	_, err := decoder.Decode()
   730  	c.Assert(err, ErrorMatches, `error reading assertion signature: maximum size exceeded while looking for delimiter "\\n\\n"`)
   731  }
   732  
   733  func (as *assertsSuite) TestDecoderDefaultMaxBodySize(c *C) {
   734  	enc := strings.Replace(exampleBodyAndExtraHeaders, "body-length: 8", "body-length: 2097153", 1)
   735  	decoder := asserts.NewDecoder(bytes.NewBufferString(enc))
   736  	_, err := decoder.Decode()
   737  	c.Assert(err, ErrorMatches, "assertion body length 2097153 exceeds maximum body size")
   738  }
   739  
   740  func (as *assertsSuite) TestDecoderWithTypeMaxBodySize(c *C) {
   741  	ex1 := strings.Replace(exampleBodyAndExtraHeaders, "body-length: 8", "body-length: 2097152", 1)
   742  	ex1 = strings.Replace(ex1, "THE-BODY", strings.Repeat("B", 2*1024*1024), 1)
   743  	ex1toobig := strings.Replace(exampleBodyAndExtraHeaders, "body-length: 8", "body-length: 2097153", 1)
   744  	ex1toobig = strings.Replace(ex1toobig, "THE-BODY", strings.Repeat("B", 2*1024*1024+1), 1)
   745  	const ex2 = `type: test-only-2
   746  authority-id: auth-id1
   747  pk1: foo
   748  pk2: bar
   749  body-length: 3
   750  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
   751  
   752  XYZ
   753  
   754  AXNpZw==`
   755  
   756  	decoder := asserts.NewDecoderWithTypeMaxBodySize(bytes.NewBufferString(ex1+"\n"+ex2), map[*asserts.AssertionType]int{
   757  		asserts.TestOnly2Type: 3,
   758  	})
   759  	a1, err := decoder.Decode()
   760  	c.Assert(err, IsNil)
   761  	c.Check(a1.Body(), HasLen, 2*1024*1024)
   762  	a2, err := decoder.Decode()
   763  	c.Assert(err, IsNil)
   764  	c.Check(a2.Body(), DeepEquals, []byte("XYZ"))
   765  
   766  	decoder = asserts.NewDecoderWithTypeMaxBodySize(bytes.NewBufferString(ex1+"\n"+ex2), map[*asserts.AssertionType]int{
   767  		asserts.TestOnly2Type: 2,
   768  	})
   769  	a1, err = decoder.Decode()
   770  	c.Assert(err, IsNil)
   771  	c.Check(a1.Body(), HasLen, 2*1024*1024)
   772  	_, err = decoder.Decode()
   773  	c.Assert(err, ErrorMatches, `assertion body length 3 exceeds maximum body size 2 for "test-only-2" assertions`)
   774  
   775  	decoder = asserts.NewDecoderWithTypeMaxBodySize(bytes.NewBufferString(ex2+"\n\n"+ex1toobig), map[*asserts.AssertionType]int{
   776  		asserts.TestOnly2Type: 3,
   777  	})
   778  	a2, err = decoder.Decode()
   779  	c.Assert(err, IsNil)
   780  	c.Check(a2.Body(), DeepEquals, []byte("XYZ"))
   781  	_, err = decoder.Decode()
   782  	c.Assert(err, ErrorMatches, "assertion body length 2097153 exceeds maximum body size")
   783  }
   784  
   785  func (as *assertsSuite) TestEncode(c *C) {
   786  	encoded := []byte("type: test-only\n" +
   787  		"authority-id: auth-id2\n" +
   788  		"primary-key: xyz\n" +
   789  		"revision: 5\n" +
   790  		"header1: value1\n" +
   791  		"header2: value2\n" +
   792  		"body-length: 8\n" +
   793  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
   794  		"THE-BODY" +
   795  		"\n\n" +
   796  		"AXNpZw==")
   797  	a, err := asserts.Decode(encoded)
   798  	c.Assert(err, IsNil)
   799  	encodeRes := asserts.Encode(a)
   800  	c.Check(encodeRes, DeepEquals, encoded)
   801  }
   802  
   803  func (as *assertsSuite) TestEncoderOK(c *C) {
   804  	encoded := []byte("type: test-only\n" +
   805  		"authority-id: auth-id2\n" +
   806  		"primary-key: xyzyz\n" +
   807  		"revision: 5\n" +
   808  		"header1: value1\n" +
   809  		"header2: value2\n" +
   810  		"body-length: 8\n" +
   811  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
   812  		"THE-BODY" +
   813  		"\n\n" +
   814  		"AXNpZw==")
   815  	a0, err := asserts.Decode(encoded)
   816  	c.Assert(err, IsNil)
   817  	cont0, _ := a0.Signature()
   818  
   819  	stream := new(bytes.Buffer)
   820  	enc := asserts.NewEncoder(stream)
   821  	enc.Encode(a0)
   822  
   823  	c.Check(bytes.HasSuffix(stream.Bytes(), []byte{'\n'}), Equals, true)
   824  
   825  	dec := asserts.NewDecoder(stream)
   826  	a1, err := dec.Decode()
   827  	c.Assert(err, IsNil)
   828  
   829  	cont1, _ := a1.Signature()
   830  	c.Check(cont1, DeepEquals, cont0)
   831  }
   832  
   833  func (as *assertsSuite) TestEncoderSingleDecodeOK(c *C) {
   834  	encoded := []byte("type: test-only\n" +
   835  		"authority-id: auth-id2\n" +
   836  		"primary-key: abc\n" +
   837  		"revision: 5\n" +
   838  		"header1: value1\n" +
   839  		"header2: value2\n" +
   840  		"body-length: 8\n" +
   841  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
   842  		"THE-BODY" +
   843  		"\n\n" +
   844  		"AXNpZw==")
   845  	a0, err := asserts.Decode(encoded)
   846  	c.Assert(err, IsNil)
   847  	cont0, _ := a0.Signature()
   848  
   849  	stream := new(bytes.Buffer)
   850  	enc := asserts.NewEncoder(stream)
   851  	enc.Encode(a0)
   852  
   853  	a1, err := asserts.Decode(stream.Bytes())
   854  	c.Assert(err, IsNil)
   855  
   856  	cont1, _ := a1.Signature()
   857  	c.Check(cont1, DeepEquals, cont0)
   858  }
   859  
   860  func (as *assertsSuite) TestSignFormatValidityEmptyBody(c *C) {
   861  	headers := map[string]interface{}{
   862  		"authority-id": "auth-id1",
   863  		"primary-key":  "0",
   864  	}
   865  	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
   866  	c.Assert(err, IsNil)
   867  
   868  	_, err = asserts.Decode(asserts.Encode(a))
   869  	c.Check(err, IsNil)
   870  }
   871  
   872  func (as *assertsSuite) TestSignFormatValidityNonEmptyBody(c *C) {
   873  	headers := map[string]interface{}{
   874  		"authority-id": "auth-id1",
   875  		"primary-key":  "0",
   876  	}
   877  	body := []byte("THE-BODY")
   878  	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, body, testPrivKey1)
   879  	c.Assert(err, IsNil)
   880  	c.Check(a.Body(), DeepEquals, body)
   881  
   882  	decoded, err := asserts.Decode(asserts.Encode(a))
   883  	c.Assert(err, IsNil)
   884  	c.Check(decoded.Body(), DeepEquals, body)
   885  }
   886  
   887  func (as *assertsSuite) TestSignFormatValiditySupportMultilineHeaderValues(c *C) {
   888  	headers := map[string]interface{}{
   889  		"authority-id": "auth-id1",
   890  		"primary-key":  "0",
   891  	}
   892  
   893  	multilineVals := []string{
   894  		"a\n",
   895  		"\na",
   896  		"a\n\b\nc",
   897  		"a\n\b\nc\n",
   898  		"\na\n",
   899  		"\n\na\n\nb\n\nc",
   900  	}
   901  
   902  	for _, multilineVal := range multilineVals {
   903  		headers["multiline"] = multilineVal
   904  		if len(multilineVal)%2 == 1 {
   905  			headers["odd"] = "true"
   906  		}
   907  
   908  		a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
   909  		c.Assert(err, IsNil)
   910  
   911  		decoded, err := asserts.Decode(asserts.Encode(a))
   912  		c.Assert(err, IsNil)
   913  
   914  		c.Check(decoded.Header("multiline"), Equals, multilineVal)
   915  	}
   916  }
   917  
   918  func (as *assertsSuite) TestSignFormatAndRevision(c *C) {
   919  	headers := map[string]interface{}{
   920  		"authority-id": "auth-id1",
   921  		"primary-key":  "0",
   922  		"format":       "1",
   923  		"revision":     "11",
   924  	}
   925  
   926  	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
   927  	c.Assert(err, IsNil)
   928  
   929  	c.Check(a.Revision(), Equals, 11)
   930  	c.Check(a.Format(), Equals, 1)
   931  	c.Check(a.SupportedFormat(), Equals, true)
   932  
   933  	a1, err := asserts.Decode(asserts.Encode(a))
   934  	c.Assert(err, IsNil)
   935  
   936  	c.Check(a1.Revision(), Equals, 11)
   937  	c.Check(a1.Format(), Equals, 1)
   938  	c.Check(a1.SupportedFormat(), Equals, true)
   939  }
   940  
   941  func (as *assertsSuite) TestSignFormatOptionalPrimaryKeys(c *C) {
   942  	r := asserts.MockOptionalPrimaryKey(asserts.TestOnlyType, "opt1", "o1-defl")
   943  	defer r()
   944  
   945  	headers := map[string]interface{}{
   946  		"authority-id": "auth-id1",
   947  		"primary-key":  "k1",
   948  		"header1":      "a",
   949  	}
   950  	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
   951  	c.Assert(err, IsNil)
   952  
   953  	b := asserts.Encode(a)
   954  	c.Check(bytes.HasPrefix(b, []byte(`type: test-only
   955  authority-id: auth-id1
   956  primary-key: k1
   957  header1:`)), Equals, true)
   958  	c.Check(a.HeaderString("opt1"), Equals, "o1-defl")
   959  
   960  	_, err = asserts.Decode(b)
   961  	c.Check(err, IsNil)
   962  
   963  	// defaults are always normalized away
   964  	headers = map[string]interface{}{
   965  		"authority-id": "auth-id1",
   966  		"primary-key":  "k1",
   967  		"opt1":         "o1-defl",
   968  		"header1":      "a",
   969  	}
   970  	a, err = asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
   971  	c.Assert(err, IsNil)
   972  
   973  	b = asserts.Encode(a)
   974  	c.Check(bytes.HasPrefix(b, []byte(`type: test-only
   975  authority-id: auth-id1
   976  primary-key: k1
   977  header1:`)), Equals, true)
   978  	c.Check(a.HeaderString("opt1"), Equals, "o1-defl")
   979  
   980  	_, err = asserts.Decode(b)
   981  	c.Check(err, IsNil)
   982  
   983  	headers = map[string]interface{}{
   984  		"authority-id": "auth-id1",
   985  		"primary-key":  "k1",
   986  		"opt1":         "A",
   987  		"header1":      "a",
   988  	}
   989  	a, err = asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
   990  	c.Assert(err, IsNil)
   991  
   992  	b = asserts.Encode(a)
   993  	c.Check(bytes.HasPrefix(b, []byte(`type: test-only
   994  authority-id: auth-id1
   995  primary-key: k1
   996  opt1: A
   997  header1:`)), Equals, true)
   998  	c.Check(a.HeaderString("opt1"), Equals, "A")
   999  
  1000  	_, err = asserts.Decode(b)
  1001  	c.Check(err, IsNil)
  1002  }
  1003  
  1004  func (as *assertsSuite) TestSignBodyIsUTF8Text(c *C) {
  1005  	headers := map[string]interface{}{
  1006  		"authority-id": "auth-id1",
  1007  		"primary-key":  "0",
  1008  	}
  1009  	_, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, []byte{'\xff'}, testPrivKey1)
  1010  	c.Assert(err, ErrorMatches, "assertion body is not utf8")
  1011  }
  1012  
  1013  func (as *assertsSuite) TestHeaders(c *C) {
  1014  	encoded := []byte("type: test-only\n" +
  1015  		"authority-id: auth-id2\n" +
  1016  		"primary-key: abc\n" +
  1017  		"revision: 5\n" +
  1018  		"header1: value1\n" +
  1019  		"header2: value2\n" +
  1020  		"body-length: 8\n" +
  1021  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
  1022  		"THE-BODY" +
  1023  		"\n\n" +
  1024  		"AXNpZw==")
  1025  	a, err := asserts.Decode(encoded)
  1026  	c.Assert(err, IsNil)
  1027  
  1028  	hs := a.Headers()
  1029  	c.Check(hs, DeepEquals, map[string]interface{}{
  1030  		"type":              "test-only",
  1031  		"authority-id":      "auth-id2",
  1032  		"primary-key":       "abc",
  1033  		"revision":          "5",
  1034  		"header1":           "value1",
  1035  		"header2":           "value2",
  1036  		"body-length":       "8",
  1037  		"sign-key-sha3-384": exKeyID,
  1038  	})
  1039  }
  1040  
  1041  func (as *assertsSuite) TestHeadersReturnsCopy(c *C) {
  1042  	encoded := []byte("type: test-only\n" +
  1043  		"authority-id: auth-id2\n" +
  1044  		"primary-key: xyz\n" +
  1045  		"revision: 5\n" +
  1046  		"header1: value1\n" +
  1047  		"header2: value2\n" +
  1048  		"body-length: 8\n" +
  1049  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
  1050  		"THE-BODY" +
  1051  		"\n\n" +
  1052  		"AXNpZw==")
  1053  	a, err := asserts.Decode(encoded)
  1054  	c.Assert(err, IsNil)
  1055  
  1056  	hs := a.Headers()
  1057  	// casual later result mutation doesn't trip us
  1058  	delete(hs, "primary-key")
  1059  	c.Check(a.Header("primary-key"), Equals, "xyz")
  1060  }
  1061  
  1062  func (as *assertsSuite) TestAssembleRoundtrip(c *C) {
  1063  	encoded := []byte("type: test-only\n" +
  1064  		"format: 1\n" +
  1065  		"authority-id: auth-id2\n" +
  1066  		"primary-key: abc\n" +
  1067  		"revision: 5\n" +
  1068  		"header1: value1\n" +
  1069  		"header2: value2\n" +
  1070  		"body-length: 8\n" +
  1071  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
  1072  		"THE-BODY" +
  1073  		"\n\n" +
  1074  		"AXNpZw==")
  1075  	a, err := asserts.Decode(encoded)
  1076  	c.Assert(err, IsNil)
  1077  
  1078  	cont, sig := a.Signature()
  1079  	reassembled, err := asserts.Assemble(a.Headers(), a.Body(), cont, sig)
  1080  	c.Assert(err, IsNil)
  1081  
  1082  	c.Check(reassembled.Headers(), DeepEquals, a.Headers())
  1083  	c.Check(reassembled.Body(), DeepEquals, a.Body())
  1084  
  1085  	reassembledEncoded := asserts.Encode(reassembled)
  1086  	c.Check(reassembledEncoded, DeepEquals, encoded)
  1087  }
  1088  
  1089  func (as *assertsSuite) TestSignKeyID(c *C) {
  1090  	headers := map[string]interface{}{
  1091  		"authority-id": "auth-id1",
  1092  		"primary-key":  "0",
  1093  	}
  1094  	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
  1095  	c.Assert(err, IsNil)
  1096  
  1097  	keyID := a.SignKeyID()
  1098  	c.Check(keyID, Equals, testPrivKey1.PublicKey().ID())
  1099  }
  1100  
  1101  func (as *assertsSuite) TestSelfRef(c *C) {
  1102  	headers := map[string]interface{}{
  1103  		"authority-id": "auth-id1",
  1104  		"primary-key":  "0",
  1105  	}
  1106  	a1, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
  1107  	c.Assert(err, IsNil)
  1108  
  1109  	c.Check(a1.Ref(), DeepEquals, &asserts.Ref{
  1110  		Type:       asserts.TestOnlyType,
  1111  		PrimaryKey: []string{"0"},
  1112  	})
  1113  
  1114  	c.Check(a1.At(), DeepEquals, &asserts.AtRevision{
  1115  		Ref: asserts.Ref{
  1116  			Type:       asserts.TestOnlyType,
  1117  			PrimaryKey: []string{"0"},
  1118  		},
  1119  		Revision: 0,
  1120  	})
  1121  
  1122  	headers = map[string]interface{}{
  1123  		"authority-id": "auth-id1",
  1124  		"pk1":          "a",
  1125  		"pk2":          "b",
  1126  		"revision":     "1",
  1127  	}
  1128  	a2, err := asserts.AssembleAndSignInTest(asserts.TestOnly2Type, headers, nil, testPrivKey1)
  1129  	c.Assert(err, IsNil)
  1130  
  1131  	c.Check(a2.Ref(), DeepEquals, &asserts.Ref{
  1132  		Type:       asserts.TestOnly2Type,
  1133  		PrimaryKey: []string{"a", "b"},
  1134  	})
  1135  
  1136  	c.Check(a2.At(), DeepEquals, &asserts.AtRevision{
  1137  		Ref: asserts.Ref{
  1138  			Type:       asserts.TestOnly2Type,
  1139  			PrimaryKey: []string{"a", "b"},
  1140  		},
  1141  		Revision: 1,
  1142  	})
  1143  }
  1144  
  1145  func (as *assertsSuite) TestAssembleHeadersCheck(c *C) {
  1146  	cont := []byte("type: test-only\n" +
  1147  		"authority-id: auth-id2\n" +
  1148  		"primary-key: abc\n" +
  1149  		"revision: 5")
  1150  	headers := map[string]interface{}{
  1151  		"type":         "test-only",
  1152  		"authority-id": "auth-id2",
  1153  		"primary-key":  "abc",
  1154  		"revision":     5, // must be a string actually!
  1155  	}
  1156  
  1157  	_, err := asserts.Assemble(headers, nil, cont, nil)
  1158  	c.Check(err, ErrorMatches, `header "revision": header values must be strings or nested lists or maps with strings as the only scalars: 5`)
  1159  }
  1160  
  1161  func (as *assertsSuite) TestSignWithoutAuthorityMisuse(c *C) {
  1162  	_, err := asserts.SignWithoutAuthority(asserts.TestOnlyType, nil, nil, testPrivKey1)
  1163  	c.Check(err, ErrorMatches, `cannot sign assertions needing a definite authority with SignWithoutAuthority`)
  1164  
  1165  	_, err = asserts.SignWithoutAuthority(asserts.TestOnlyNoAuthorityType,
  1166  		map[string]interface{}{
  1167  			"authority-id": "auth-id1",
  1168  			"hdr":          "FOO",
  1169  		}, nil, testPrivKey1)
  1170  	c.Check(err, ErrorMatches, `"test-only-no-authority" assertion cannot have authority-id set`)
  1171  }
  1172  
  1173  func (ss *serialSuite) TestSignatureCheckError(c *C) {
  1174  	sreq, err := asserts.SignWithoutAuthority(asserts.TestOnlyNoAuthorityType,
  1175  		map[string]interface{}{
  1176  			"hdr": "FOO",
  1177  		}, nil, testPrivKey1)
  1178  	c.Assert(err, IsNil)
  1179  
  1180  	err = asserts.SignatureCheck(sreq, testPrivKey2.PublicKey())
  1181  	c.Check(err, ErrorMatches, `failed signature verification:.*`)
  1182  }
  1183  
  1184  func (as *assertsSuite) TestWithAuthority(c *C) {
  1185  	withAuthority := []string{
  1186  		"account",
  1187  		"account-key",
  1188  		// XXX "authority-delegation",
  1189  		"base-declaration",
  1190  		"store",
  1191  		"snap-declaration",
  1192  		"snap-build",
  1193  		"snap-revision",
  1194  		"snap-developer",
  1195  		"model",
  1196  		"preseed",
  1197  		"serial",
  1198  		"system-user",
  1199  		"validation",
  1200  		"validation-set",
  1201  		"repair",
  1202  	}
  1203  	c.Check(withAuthority, HasLen, asserts.NumAssertionType-3) // excluding device-session-request, serial-request, account-key-request
  1204  	for _, name := range withAuthority {
  1205  		typ := asserts.Type(name)
  1206  		_, err := asserts.AssembleAndSignInTest(typ, nil, nil, testPrivKey1)
  1207  		c.Check(err, ErrorMatches, `"authority-id" header is mandatory`)
  1208  	}
  1209  }
  1210  
  1211  func (as *assertsSuite) TestSequenceForming(c *C) {
  1212  	sequenceForming := []string{
  1213  		"repair",
  1214  		"validation-set",
  1215  	}
  1216  	for _, name := range sequenceForming {
  1217  		typ := asserts.Type(name)
  1218  		c.Check(typ.SequenceForming(), Equals, true)
  1219  	}
  1220  
  1221  	c.Check(asserts.SnapDeclarationType.SequenceForming(), Equals, false)
  1222  }
  1223  
  1224  func (as *assertsSuite) TestHeadersFromSequenceKey(c *C) {
  1225  	headers, err := asserts.HeadersFromSequenceKey(asserts.TestOnlySeqType, []string{"one"})
  1226  	c.Assert(err, IsNil)
  1227  	c.Check(headers, DeepEquals, map[string]string{"n": "one"})
  1228  
  1229  	_, err = asserts.HeadersFromSequenceKey(asserts.TestOnlySeqType, []string{"one", "two"})
  1230  	c.Check(err, ErrorMatches, `sequence key has wrong length for "test-only-seq" assertion`)
  1231  
  1232  	_, err = asserts.HeadersFromSequenceKey(asserts.TestOnlySeqType, []string{})
  1233  	c.Check(err, ErrorMatches, `sequence key has wrong length for "test-only-seq" assertion`)
  1234  
  1235  	_, err = asserts.HeadersFromSequenceKey(asserts.TestOnlySeqType, []string{""})
  1236  	c.Check(err, ErrorMatches, `sequence key "n" header cannot be empty`)
  1237  }
  1238  
  1239  func (as *assertsSuite) TestAtSequenceString(c *C) {
  1240  	atSeq := asserts.AtSequence{
  1241  		Type:        asserts.ValidationSetType,
  1242  		SequenceKey: []string{"16", "canonical", "foo"},
  1243  		Sequence:    8,
  1244  		Revision:    2,
  1245  	}
  1246  	c.Check(atSeq.String(), Equals, "validation-set canonical/foo/8 at revision 2")
  1247  
  1248  	// Sequence number not set
  1249  	atSeq = asserts.AtSequence{
  1250  		Type:        asserts.ValidationSetType,
  1251  		SequenceKey: []string{"16", "canonical", "foo"},
  1252  		Revision:    asserts.RevisionNotKnown,
  1253  	}
  1254  	c.Check(atSeq.String(), Equals, "validation-set canonical/foo")
  1255  
  1256  	atSeq = asserts.AtSequence{
  1257  		Type:        asserts.ValidationSetType,
  1258  		SequenceKey: []string{"16", "canonical", "foo"},
  1259  		Sequence:    8,
  1260  		Pinned:      true,
  1261  		Revision:    2,
  1262  	}
  1263  	c.Check(atSeq.String(), Equals, "validation-set canonical/foo=8 at revision 2")
  1264  
  1265  	atSeq = asserts.AtSequence{
  1266  		Type:        asserts.ValidationSetType,
  1267  		SequenceKey: []string{"16", "canonical"},
  1268  		Revision:    2,
  1269  	}
  1270  	c.Check(atSeq.String(), Equals, "validation-set ??? at revision 2")
  1271  }
  1272  
  1273  func (as *assertsSuite) TestAtSequenceUnique(c *C) {
  1274  	atSeq := asserts.AtSequence{
  1275  		Type:        asserts.ValidationSetType,
  1276  		SequenceKey: []string{"16", "canonical", "foo"},
  1277  		Sequence:    8,
  1278  		Revision:    2,
  1279  	}
  1280  	c.Check(atSeq.Unique(), Equals, "validation-set/16/canonical/foo")
  1281  
  1282  	// not a valid sequence-key (but Unique() doesn't care).
  1283  	atSeq = asserts.AtSequence{
  1284  		Type:        asserts.ValidationSetType,
  1285  		SequenceKey: []string{"16", "canonical"},
  1286  	}
  1287  	c.Check(atSeq.Unique(), Equals, "validation-set/16/canonical")
  1288  }
  1289  
  1290  func (as *assertsSuite) TestAtSequenceResolveError(c *C) {
  1291  	atSeq := asserts.AtSequence{
  1292  		Type:        asserts.ValidationSetType,
  1293  		SequenceKey: []string{"abc"},
  1294  		Sequence:    1,
  1295  	}
  1296  	_, err := atSeq.Resolve(nil)
  1297  	c.Check(err, ErrorMatches, `"validation-set" assertion reference primary key has the wrong length \(expected \[series account-id name sequence\]\): \[abc 1\]`)
  1298  
  1299  	atSeq = asserts.AtSequence{
  1300  		Type:        asserts.ValidationSetType,
  1301  		SequenceKey: []string{"16", "canonical", "foo"},
  1302  	}
  1303  	_, err = atSeq.Resolve(nil)
  1304  	c.Assert(err, DeepEquals, &asserts.NotFoundError{
  1305  		Type: asserts.ValidationSetType,
  1306  		Headers: map[string]string{
  1307  			"series":     "16",
  1308  			"account-id": "canonical",
  1309  			"name":       "foo",
  1310  		},
  1311  	})
  1312  }
  1313  
  1314  func (as *assertsSuite) TestAtSequenceResolve(c *C) {
  1315  	atSeq := asserts.AtSequence{
  1316  		Type:        asserts.TestOnlySeqType,
  1317  		SequenceKey: []string{"foo"},
  1318  		Sequence:    3,
  1319  	}
  1320  	a, err := atSeq.Resolve(func(atype *asserts.AssertionType, hdrs map[string]string) (asserts.Assertion, error) {
  1321  		c.Assert(atype, Equals, asserts.TestOnlySeqType)
  1322  		c.Assert(hdrs, DeepEquals, map[string]string{
  1323  			"n":        "foo",
  1324  			"sequence": "3",
  1325  		})
  1326  		encoded := []byte("type: test-only-seq\n" +
  1327  			"format: 1\n" +
  1328  			"authority-id: auth-id2\n" +
  1329  			"n: abc\n" +
  1330  			"revision: 5\n" +
  1331  			"sequence: 3\n" +
  1332  			"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
  1333  			"\n\n" +
  1334  			"AXNpZw==")
  1335  		a, err := asserts.Decode(encoded)
  1336  		return a, err
  1337  	})
  1338  	c.Assert(err, IsNil)
  1339  	c.Assert(a, NotNil)
  1340  	c.Check(a.Type().Name, Equals, "test-only-seq")
  1341  }