Пример #1
0
// DeviceSessionRequest produces a device-session-request with the given nonce, it also returns the encoded device serial assertion. It returns ErrNoSerial if the device serial is not yet initialized.
func (ac *authContext) DeviceSessionRequest(nonce string) (deviceSessionRequest []byte, serial []byte, err error) {
	if ac.deviceAsserts == nil {
		return nil, nil, ErrNoSerial
	}
	req, ser, err := ac.deviceAsserts.DeviceSessionRequest(nonce)
	if err == state.ErrNoState {
		return nil, nil, ErrNoSerial
	}
	if err != nil {
		return nil, nil, err
	}
	return asserts.Encode(req), asserts.Encode(ser), nil
}
Пример #2
0
func (chks *checkSuite) TestCheckForgery(c *C) {
	trustedKey := testPrivKey0

	cfg := &asserts.DatabaseConfig{
		Backstore: chks.bs,
		Trusted:   []asserts.Assertion{asserts.BootstrapAccountKeyForTest("canonical", trustedKey.PublicKey())},
	}
	db, err := asserts.OpenDatabase(cfg)
	c.Assert(err, IsNil)

	encoded := asserts.Encode(chks.a)
	content, encodedSig := chks.a.Signature()
	// forgery
	forgedSig := new(packet.Signature)
	forgedSig.PubKeyAlgo = packet.PubKeyAlgoRSA
	forgedSig.Hash = crypto.SHA512
	forgedSig.CreationTime = time.Now()
	h := crypto.SHA512.New()
	h.Write(content)
	pk1 := packet.NewRSAPrivateKey(time.Unix(1, 0), testPrivKey1RSA)
	err = forgedSig.Sign(h, pk1, &packet.Config{DefaultHash: crypto.SHA512})
	c.Assert(err, IsNil)
	buf := new(bytes.Buffer)
	forgedSig.Serialize(buf)
	b := append([]byte{0x1}, buf.Bytes()...)
	forgedSigEncoded := base64.StdEncoding.EncodeToString(b)
	forgedEncoded := bytes.Replace(encoded, encodedSig, []byte(forgedSigEncoded), 1)
	c.Assert(forgedEncoded, Not(DeepEquals), encoded)

	forgedAssert, err := asserts.Decode(forgedEncoded)
	c.Assert(err, IsNil)

	err = db.Check(forgedAssert)
	c.Assert(err, ErrorMatches, "failed signature verification: .*")
}
Пример #3
0
func (s *FirstBootTestSuite) TestImportAssertionsFromSeedHappy(c *C) {
	ovld, err := overlord.New()
	c.Assert(err, IsNil)
	st := ovld.State()

	// add a bunch of assert files
	assertsChain := s.makeModelAssertionChain(c)
	for i, as := range assertsChain {
		fn := filepath.Join(dirs.SnapSeedDir, "assertions", strconv.Itoa(i))
		err := ioutil.WriteFile(fn, asserts.Encode(as), 0644)
		c.Assert(err, IsNil)
	}

	// import them
	err = boot.ImportAssertionsFromSeed(st)
	c.Assert(err, IsNil)

	// verify that the model was added
	st.Lock()
	defer st.Unlock()
	db := assertstate.DB(st)
	as, err := db.Find(asserts.ModelType, map[string]string{
		"series":   "16",
		"brand-id": "my-brand",
		"model":    "my-model",
	})
	c.Assert(err, IsNil)
	_, ok := as.(*asserts.Model)
	c.Check(ok, Equals, true)

	ds, err := auth.Device(st)
	c.Assert(err, IsNil)
	c.Check(ds.Brand, Equals, "my-brand")
	c.Check(ds.Model, Equals, "my-model")
}
Пример #4
0
func (ss *serialSuite) TestSerialRequestHappy(c *C) {
	sreq, err := asserts.SignWithoutAuthority(asserts.SerialRequestType,
		map[string]interface{}{
			"brand-id":   "brand-id1",
			"model":      "baz-3000",
			"device-key": ss.encodedDevKey,
			"request-id": "REQID",
		}, []byte("HW-DETAILS"), ss.deviceKey)
	c.Assert(err, IsNil)

	// roundtrip
	a, err := asserts.Decode(asserts.Encode(sreq))
	c.Assert(err, IsNil)

	sreq2, ok := a.(*asserts.SerialRequest)
	c.Assert(ok, Equals, true)

	// standalone signature check
	err = asserts.SignatureCheck(sreq2, sreq2.DeviceKey())
	c.Check(err, IsNil)

	c.Check(sreq2.BrandID(), Equals, "brand-id1")
	c.Check(sreq2.Model(), Equals, "baz-3000")
	c.Check(sreq2.RequestID(), Equals, "REQID")

	c.Check(sreq2.Serial(), Equals, "")
}
Пример #5
0
func (aks *accountKeySuite) TestAccountKeyRequestUntil(c *C) {
	db := aks.openDB(c)
	aks.prereqAccount(c, db)

	tests := []struct {
		untilHeader string
		until       time.Time
	}{
		{"", time.Time{}},                           // zero time default
		{aks.until.Format(time.RFC3339), aks.until}, // in the future
		{aks.since.Format(time.RFC3339), aks.since}, // same as since
	}

	for _, test := range tests {
		c.Log(test)
		headers := map[string]interface{}{
			"account-id":          "acc-id1",
			"name":                "default",
			"public-key-sha3-384": aks.keyID,
			"since":               aks.since.Format(time.RFC3339),
		}
		if test.untilHeader != "" {
			headers["until"] = test.untilHeader
		}
		akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType, headers, []byte(aks.pubKeyBody), aks.privKey)
		c.Assert(err, IsNil)
		a, err := asserts.Decode(asserts.Encode(akr))
		c.Assert(err, IsNil)
		akr2 := a.(*asserts.AccountKeyRequest)
		c.Check(akr2.Until(), Equals, test.until)
		err = db.Check(akr2)
		c.Check(err, IsNil)
	}
}
Пример #6
0
func (as *assertsSuite) TestAssembleRoundtrip(c *C) {
	encoded := []byte("type: test-only\n" +
		"format: 1\n" +
		"authority-id: auth-id2\n" +
		"primary-key: abc\n" +
		"revision: 5\n" +
		"header1: value1\n" +
		"header2: value2\n" +
		"body-length: 8\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
		"THE-BODY" +
		"\n\n" +
		"AXNpZw==")
	a, err := asserts.Decode(encoded)
	c.Assert(err, IsNil)

	cont, sig := a.Signature()
	reassembled, err := asserts.Assemble(a.Headers(), a.Body(), cont, sig)
	c.Assert(err, IsNil)

	c.Check(reassembled.Headers(), DeepEquals, a.Headers())
	c.Check(reassembled.Body(), DeepEquals, a.Body())

	reassembledEncoded := asserts.Encode(reassembled)
	c.Check(reassembledEncoded, DeepEquals, encoded)
}
func generateSerialRequestAssertion() (string, error) {
	privateKey, err := generatePrivateKey()
	if err != nil {
		return "", err
	}
	encodedPubKey, err := asserts.EncodePublicKey(privateKey.PublicKey())
	if err != nil {
		return "", err
	}

	// Generate a request-id
	r, _ := getRequestID()

	headers := map[string]interface{}{
		"brand-id":   request.Brand,
		"device-key": string(encodedPubKey),
		"request-id": r,
		"model":      request.Model,
		"serial":     request.SerialNumber,
	}

	sreq, err := asserts.SignWithoutAuthority(asserts.SerialRequestType, headers, []byte(""), privateKey)
	if err != nil {
		return "", err
	}

	assertSR := asserts.Encode(sreq)
	return string(assertSR), nil
}
Пример #8
0
func (as *assertsSuite) TestSignFormatSanitySupportMultilineHeaderValues(c *C) {
	headers := map[string]interface{}{
		"authority-id": "auth-id1",
		"primary-key":  "0",
	}

	multilineVals := []string{
		"a\n",
		"\na",
		"a\n\b\nc",
		"a\n\b\nc\n",
		"\na\n",
		"\n\na\n\nb\n\nc",
	}

	for _, multilineVal := range multilineVals {
		headers["multiline"] = multilineVal
		if len(multilineVal)%2 == 1 {
			headers["odd"] = "true"
		}

		a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
		c.Assert(err, IsNil)

		decoded, err := asserts.Decode(asserts.Encode(a))
		c.Assert(err, IsNil)

		c.Check(decoded.Header("multiline"), Equals, multilineVal)
	}
}
Пример #9
0
func (s *authContextSetupSuite) TestDeviceSessionRequest(c *C) {
	st := s.o.State()
	st.Lock()
	defer st.Unlock()

	st.Unlock()
	_, _, err := s.ac.DeviceSessionRequest("NONCE")
	st.Lock()
	c.Check(err, Equals, auth.ErrNoSerial)

	// setup serial and key in system state
	err = assertstate.Add(st, s.serial)
	c.Assert(err, IsNil)
	kpMgr, err := asserts.OpenFSKeypairManager(dirs.SnapDeviceDir)
	c.Assert(err, IsNil)
	err = kpMgr.Put(deviceKey)
	c.Assert(err, IsNil)
	auth.SetDevice(st, &auth.DeviceState{
		Brand:  s.serial.BrandID(),
		Model:  s.serial.Model(),
		Serial: s.serial.Serial(),
		KeyID:  deviceKey.PublicKey().ID(),
	})

	st.Unlock()
	req, encSerial, err := s.ac.DeviceSessionRequest("NONCE")
	st.Lock()
	c.Assert(err, IsNil)
	c.Check(bytes.HasPrefix(req, []byte("type: device-session-request\n")), Equals, true)
	c.Check(encSerial, DeepEquals, asserts.Encode(s.serial))
}
Пример #10
0
func (ss *serialSuite) TestDeviceSessionRequest(c *C) {
	ts := time.Now().UTC().Round(time.Second)
	sessReq, err := asserts.SignWithoutAuthority(asserts.DeviceSessionRequestType,
		map[string]interface{}{
			"brand-id":  "brand-id1",
			"model":     "baz-3000",
			"serial":    "99990",
			"nonce":     "NONCE",
			"timestamp": ts.Format(time.RFC3339),
		}, nil, ss.deviceKey)
	c.Assert(err, IsNil)

	// roundtrip
	a, err := asserts.Decode(asserts.Encode(sessReq))
	c.Assert(err, IsNil)

	sessReq2, ok := a.(*asserts.DeviceSessionRequest)
	c.Assert(ok, Equals, true)

	// standalone signature check
	err = asserts.SignatureCheck(sessReq2, ss.deviceKey.PublicKey())
	c.Check(err, IsNil)

	c.Check(sessReq2.BrandID(), Equals, "brand-id1")
	c.Check(sessReq2.Model(), Equals, "baz-3000")
	c.Check(sessReq2.Serial(), Equals, "99990")
	c.Check(sessReq2.Nonce(), Equals, "NONCE")
	c.Check(sessReq2.Timestamp().Equal(ts), Equals, true)
}
Пример #11
0
func (aks *accountKeySuite) TestAccountKeyRequestHappy(c *C) {
	akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType,
		map[string]interface{}{
			"account-id":          "acc-id1",
			"name":                "default",
			"public-key-sha3-384": aks.keyID,
			"since":               aks.since.Format(time.RFC3339),
		}, []byte(aks.pubKeyBody), aks.privKey)
	c.Assert(err, IsNil)

	// roundtrip
	a, err := asserts.Decode(asserts.Encode(akr))
	c.Assert(err, IsNil)

	akr2, ok := a.(*asserts.AccountKeyRequest)
	c.Assert(ok, Equals, true)

	db := aks.openDB(c)
	aks.prereqAccount(c, db)

	err = db.Check(akr2)
	c.Check(err, IsNil)

	c.Check(akr2.AccountID(), Equals, "acc-id1")
	c.Check(akr2.Name(), Equals, "default")
	c.Check(akr2.PublicKeyID(), Equals, aks.keyID)
	c.Check(akr2.Since(), Equals, aks.since)
}
Пример #12
0
func getSerial(t *state.Task, privKey asserts.PrivateKey, device *auth.DeviceState, cfg *serialRequestConfig) (*asserts.Serial, error) {
	var serialSup serialSetup
	err := t.Get("serial-setup", &serialSup)
	if err != nil && err != state.ErrNoState {
		return nil, err
	}

	if serialSup.Serial != "" {
		// we got a serial, just haven't managed to save its info yet
		a, err := asserts.Decode([]byte(serialSup.Serial))
		if err != nil {
			return nil, fmt.Errorf("internal error: cannot decode previously saved serial: %v", err)
		}
		return a.(*asserts.Serial), nil
	}

	client := &http.Client{Timeout: 30 * time.Second}

	// NB: until we get at least an Accepted (202) we need to
	// retry from scratch creating a new request-id because the
	// previous one used could have expired

	if serialSup.SerialRequest == "" {
		serialRequest, err := prepareSerialRequest(t, privKey, device, client, cfg)
		if err != nil { // errors & retries
			return nil, err
		}

		serialSup.SerialRequest = serialRequest
	}

	serial, err := submitSerialRequest(t, serialSup.SerialRequest, client, cfg)
	if err == errPoll {
		// we can/should reuse the serial-request
		t.Set("serial-setup", serialSup)
		return nil, errPoll
	}
	if err != nil { // errors & retries
		return nil, err
	}

	keyID := privKey.PublicKey().ID()
	if serial.BrandID() != device.Brand || serial.Model() != device.Model || serial.DeviceKey().ID() != keyID {
		return nil, fmt.Errorf("obtained serial assertion does not match provided device identity information (brand, model, key id): %s / %s / %s != %s / %s / %s", serial.BrandID(), serial.Model(), serial.DeviceKey().ID(), device.Brand, device.Model, keyID)
	}

	serialSup.Serial = string(asserts.Encode(serial))
	t.Set("serial-setup", serialSup)

	if repeatRequestSerial == "after-got-serial" {
		// For testing purposes, ensure a crash in this state works.
		return nil, &state.Retry{}
	}

	return serial, nil
}
Пример #13
0
func (s *imageSuite) TestHappyDecodeModelAssertion(c *C) {
	fn := filepath.Join(c.MkDir(), "model.assertion")
	err := ioutil.WriteFile(fn, asserts.Encode(s.model), 0644)
	c.Assert(err, IsNil)

	a, err := image.DecodeModelAssertion(&image.Options{
		ModelFile: fn,
	})
	c.Assert(err, IsNil)
	c.Check(a.Type(), Equals, asserts.ModelType)
}
Пример #14
0
func (as *assertsSuite) TestSignFormatSanityEmptyBody(c *C) {
	headers := map[string]interface{}{
		"authority-id": "auth-id1",
		"primary-key":  "0",
	}
	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)
	c.Assert(err, IsNil)

	_, err = asserts.Decode(asserts.Encode(a))
	c.Check(err, IsNil)
}
Пример #15
0
func (s *FirstBootTestSuite) TestImportAssertionsFromSeedTwoModelAsserts(c *C) {
	st := s.overlord.State()
	st.Lock()
	defer st.Unlock()

	// write out two model assertions
	model := s.makeModelAssertion(c, "my-model")
	fn := filepath.Join(dirs.SnapSeedDir, "assertions", "model")
	err := ioutil.WriteFile(fn, asserts.Encode(model), 0644)
	c.Assert(err, IsNil)

	model2 := s.makeModelAssertion(c, "my-second-model")
	fn = filepath.Join(dirs.SnapSeedDir, "assertions", "model2")
	err = ioutil.WriteFile(fn, asserts.Encode(model2), 0644)
	c.Assert(err, IsNil)

	// try import and verify that its rejects because other assertions are
	// missing
	err = devicestate.ImportAssertionsFromSeed(st)
	c.Assert(err, ErrorMatches, "cannot add more than one model assertion")
}
Пример #16
0
func (s *deviceMgrSuite) mockServer(c *C, reqID string) *httptest.Server {
	var mu sync.Mutex
	count := 0
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		switch r.URL.Path {
		case "/identity/api/v1/request-id":
			w.WriteHeader(http.StatusOK)
			io.WriteString(w, fmt.Sprintf(`{"request-id": "%s"}`, reqID))

		case "/identity/api/v1/serial":
			c.Check(r.Header.Get("X-Extra-Header"), Equals, "extra")
			fallthrough
		case "/identity/api/v1/devices":
			mu.Lock()
			serialNum := 9999 + count
			count++
			mu.Unlock()

			b, err := ioutil.ReadAll(r.Body)
			c.Assert(err, IsNil)
			a, err := asserts.Decode(b)
			c.Assert(err, IsNil)
			serialReq, ok := a.(*asserts.SerialRequest)
			c.Assert(ok, Equals, true)
			err = asserts.SignatureCheck(serialReq, serialReq.DeviceKey())
			c.Assert(err, IsNil)
			c.Check(serialReq.BrandID(), Equals, "canonical")
			c.Check(serialReq.Model(), Equals, "pc")
			if reqID == "REQID-POLL" && serialNum != 10002 {
				w.WriteHeader(http.StatusAccepted)
				return
			}
			serialStr := fmt.Sprintf("%d", serialNum)
			if serialReq.Serial() != "" {
				// use proposed serial
				serialStr = serialReq.Serial()
			}
			serial, err := s.storeSigning.Sign(asserts.SerialType, map[string]interface{}{
				"brand-id":            "canonical",
				"model":               "pc",
				"serial":              serialStr,
				"device-key":          serialReq.HeaderString("device-key"),
				"device-key-sha3-384": serialReq.SignKeyID(),
				"timestamp":           time.Now().Format(time.RFC3339),
			}, serialReq.Body(), "")
			c.Assert(err, IsNil)
			w.Header().Set("Content-Type", asserts.MediaType)
			w.WriteHeader(http.StatusOK)
			w.Write(asserts.Encode(serial))
		}
	}))
}
Пример #17
0
func (s *storeTestSuite) TestAssertionsEndpointPreloaded(c *C) {
	// something preloaded
	resp, err := s.StoreGet(`/assertions/account/testrootorg`)
	c.Assert(err, IsNil)
	defer resp.Body.Close()

	c.Assert(resp.StatusCode, Equals, 200)
	c.Check(resp.Header.Get("Content-Type"), Equals, "application/x.ubuntu.assertion")

	body, err := ioutil.ReadAll(resp.Body)
	c.Assert(err, IsNil)
	c.Check(string(body), Equals, string(asserts.Encode(systestkeys.TestRootAccount)))
}
Пример #18
0
func (as *assertsSuite) TestSignFormatSanityNonEmptyBody(c *C) {
	headers := map[string]interface{}{
		"authority-id": "auth-id1",
		"primary-key":  "0",
	}
	body := []byte("THE-BODY")
	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, body, testPrivKey1)
	c.Assert(err, IsNil)
	c.Check(a.Body(), DeepEquals, body)

	decoded, err := asserts.Decode(asserts.Encode(a))
	c.Assert(err, IsNil)
	c.Check(decoded.Body(), DeepEquals, body)
}
Пример #19
0
func prepareSerialRequest(t *state.Task, privKey asserts.PrivateKey, device *auth.DeviceState, client *http.Client, cfg *serialRequestConfig) (string, error) {
	st := t.State()
	st.Unlock()
	defer st.Lock()

	req, err := http.NewRequest("POST", cfg.requestIDURL, nil)
	if err != nil {
		return "", fmt.Errorf("internal error: cannot create request-id request %q", cfg.requestIDURL)
	}
	cfg.applyHeaders(req)

	resp, err := client.Do(req)
	if err != nil {
		return "", retryErr(t, "cannot retrieve request-id for making a request for a serial: %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return "", retryErr(t, "cannot retrieve request-id for making a request for a serial: unexpected status %d", resp.StatusCode)
	}

	dec := json.NewDecoder(resp.Body)
	var requestID requestIDResp
	err = dec.Decode(&requestID)
	if err != nil { // assume broken i/o
		return "", retryErr(t, "cannot read response with request-id for making a request for a serial: %v", err)
	}

	encodedPubKey, err := asserts.EncodePublicKey(privKey.PublicKey())
	if err != nil {
		return "", fmt.Errorf("internal error: cannot encode device public key: %v", err)

	}

	headers := map[string]interface{}{
		"brand-id":   device.Brand,
		"model":      device.Model,
		"request-id": requestID.RequestID,
		"device-key": string(encodedPubKey),
	}
	if cfg.proposedSerial != "" {
		headers["serial"] = cfg.proposedSerial
	}

	serialReq, err := asserts.SignWithoutAuthority(asserts.SerialRequestType, headers, cfg.body, privKey)
	if err != nil {
		return "", err
	}

	return string(asserts.Encode(serialReq)), nil
}
Пример #20
0
func (x *cmdSignBuild) Execute(args []string) error {
	if len(args) > 0 {
		return ErrExtraArgs
	}

	snapDigest, snapSize, err := asserts.SnapFileSHA3_384(x.Positional.Filename)
	if err != nil {
		return err
	}

	gkm := asserts.NewGPGKeypairManager()
	privKey, err := gkm.GetByName(x.KeyName)
	if err != nil {
		// TRANSLATORS: %q is the key name, %v the error message
		return fmt.Errorf(i18n.G("cannot use %q key: %v"), x.KeyName, err)
	}

	pubKey := privKey.PublicKey()
	timestamp := time.Now().Format(time.RFC3339)

	headers := map[string]interface{}{
		"developer-id":  x.DeveloperID,
		"authority-id":  x.DeveloperID,
		"snap-sha3-384": snapDigest,
		"snap-id":       x.SnapID,
		"snap-size":     fmt.Sprintf("%d", snapSize),
		"grade":         x.Grade,
		"timestamp":     timestamp,
	}

	adb, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
		KeypairManager: gkm,
	})
	if err != nil {
		return fmt.Errorf(i18n.G("cannot open the assertions database: %v"), err)
	}

	a, err := adb.Sign(asserts.SnapBuildType, headers, nil, pubKey.ID())
	if err != nil {
		return fmt.Errorf(i18n.G("cannot sign assertion: %v"), err)
	}

	_, err = Stdout.Write(asserts.Encode(a))
	if err != nil {
		return err
	}

	return nil
}
Пример #21
0
func (as *assertsSuite) TestEncode(c *C) {
	encoded := []byte("type: test-only\n" +
		"authority-id: auth-id2\n" +
		"primary-key: xyz\n" +
		"revision: 5\n" +
		"header1: value1\n" +
		"header2: value2\n" +
		"body-length: 8\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
		"THE-BODY" +
		"\n\n" +
		"AXNpZw==")
	a, err := asserts.Decode(encoded)
	c.Assert(err, IsNil)
	encodeRes := asserts.Encode(a)
	c.Check(encodeRes, DeepEquals, encoded)
}
Пример #22
0
// Sign produces the text of a signed assertion as specified by opts.
func Sign(opts *Options, keypairMgr asserts.KeypairManager) ([]byte, error) {
	var headers map[string]interface{}
	err := json.Unmarshal(opts.Statement, &headers)
	if err != nil {
		return nil, fmt.Errorf("cannot parse the assertion input as JSON: %v", err)
	}
	typCand, ok := headers["type"]
	if !ok {
		return nil, fmt.Errorf("missing assertion type header")
	}
	typStr, ok := typCand.(string)
	if !ok {
		return nil, fmt.Errorf("assertion type must be a string, not: %v", typCand)
	}
	typ := asserts.Type(typStr)
	if typ == nil {
		return nil, fmt.Errorf("invalid assertion type: %v", headers["type"])
	}

	var body []byte
	if bodyCand, ok := headers["body"]; ok {
		bodyStr, ok := bodyCand.(string)
		if !ok {
			return nil, fmt.Errorf("body if specified must be a string")
		}
		body = []byte(bodyStr)
		delete(headers, "body")
	}

	adb, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
		KeypairManager: keypairMgr,
	})
	if err != nil {
		return nil, err
	}

	// TODO: teach Sign to cross check keyID and authority-id
	// against an account-key
	a, err := adb.Sign(typ, headers, body, opts.KeyID)
	if err != nil {
		return nil, err
	}

	return asserts.Encode(a), nil
}
Пример #23
0
func (s *Store) assertionsEndpoint(w http.ResponseWriter, req *http.Request) {
	assertPath := strings.TrimPrefix(req.URL.Path, "/assertions/")

	bs, err := s.collectAssertions()
	if err != nil {
		http.Error(w, fmt.Sprintf("internal error collecting assertions: %v", err), http.StatusInternalServerError)
		return
	}

	comps := strings.Split(assertPath, "/")

	if len(comps) == 0 {
		http.Error(w, "missing assertion type", http.StatusBadRequest)
		return

	}

	typ := asserts.Type(comps[0])
	if typ == nil {
		http.Error(w, fmt.Sprintf("unknown assertion type: %s", comps[0]), http.StatusBadRequest)
		return
	}

	if len(typ.PrimaryKey) != len(comps)-1 {
		http.Error(w, fmt.Sprintf("wrong primary key length: %v", comps), http.StatusBadRequest)
		return
	}

	a, err := s.retrieveAssertion(bs, typ, comps[1:])
	if isAssertNotFound(err) {
		w.Header().Set("Content-Type", "application/problem+json")
		w.WriteHeader(404)
		w.Write([]byte(`{"status": 404}`))
		return
	}
	if err != nil {
		http.Error(w, fmt.Sprintf("cannot retrieve assertion %v: %v", comps, err), http.StatusBadRequest)
		return
	}

	w.Header().Set("Content-Type", asserts.MediaType)
	w.WriteHeader(http.StatusOK)
	w.Write(asserts.Encode(a))
}
Пример #24
0
func (x *cmdExportKey) Execute(args []string) error {
	if len(args) > 0 {
		return ErrExtraArgs
	}

	keyName := string(x.Positional.KeyName)
	if keyName == "" {
		keyName = "default"
	}

	manager := asserts.NewGPGKeypairManager()
	if x.Account != "" {
		privKey, err := manager.GetByName(keyName)
		if err != nil {
			return err
		}
		pubKey := privKey.PublicKey()
		headers := map[string]interface{}{
			"account-id":          x.Account,
			"name":                keyName,
			"public-key-sha3-384": pubKey.ID(),
			"since":               time.Now().UTC().Format(time.RFC3339),
			// XXX: To support revocation, we need to check for matching known assertions and set a suitable revision if we find one.
		}
		body, err := asserts.EncodePublicKey(pubKey)
		if err != nil {
			return err
		}
		assertion, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType, headers, body, privKey)
		if err != nil {
			return err
		}
		fmt.Fprint(Stdout, string(asserts.Encode(assertion)))
	} else {
		encoded, err := manager.Export(keyName)
		if err != nil {
			return err
		}
		fmt.Fprintf(Stdout, "%s\n", encoded)
	}
	return nil
}
Пример #25
0
func (ss *serialSuite) TestSerialProofHappy(c *C) {
	sproof, err := asserts.SignWithoutAuthority(asserts.SerialProofType,
		map[string]interface{}{
			"nonce": "NONCE",
		}, nil, ss.deviceKey)
	c.Assert(err, IsNil)

	// roundtrip
	a, err := asserts.Decode(asserts.Encode(sproof))
	c.Assert(err, IsNil)

	sproof2, ok := a.(*asserts.SerialProof)
	c.Assert(ok, Equals, true)

	// standalone signature check
	err = asserts.SignatureCheck(sproof2, ss.deviceKey.PublicKey())
	c.Check(err, IsNil)

	c.Check(sproof2.Nonce(), Equals, "NONCE")
}
Пример #26
0
func (s *FirstBootTestSuite) TestImportAssertionsFromSeedNoModelAsserts(c *C) {
	st := s.overlord.State()
	st.Lock()
	defer st.Unlock()

	assertsChain := s.makeModelAssertionChain(c)
	for _, as := range assertsChain {
		if as.Type() != asserts.ModelType {
			fn := filepath.Join(dirs.SnapSeedDir, "assertions", "model")
			err := ioutil.WriteFile(fn, asserts.Encode(as), 0644)
			c.Assert(err, IsNil)
			break
		}
	}

	// try import and verify that its rejects because other assertions are
	// missing
	err := devicestate.ImportAssertionsFromSeed(st)
	c.Assert(err, ErrorMatches, "need a model assertion")
}
Пример #27
0
func (s *FirstBootTestSuite) TestImportAssertionsFromSeedMissingSig(c *C) {
	ovld, err := overlord.New()
	c.Assert(err, IsNil)
	st := ovld.State()

	// write out only the model assertion
	assertsChain := s.makeModelAssertionChain(c)
	for _, as := range assertsChain {
		if as.Type() == asserts.ModelType {
			fn := filepath.Join(dirs.SnapSeedDir, "assertions", "model")
			err := ioutil.WriteFile(fn, asserts.Encode(as), 0644)
			c.Assert(err, IsNil)
			break
		}
	}

	// try import and verify that its rejects because other assertions are
	// missing
	err = boot.ImportAssertionsFromSeed(st)
	c.Assert(err, ErrorMatches, "cannot find account-key .*: assertion not found")
}
Пример #28
0
func (as *assertsSuite) TestSignFormatAndRevision(c *C) {
	headers := map[string]interface{}{
		"authority-id": "auth-id1",
		"primary-key":  "0",
		"format":       "1",
		"revision":     "11",
	}

	a, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey1)

	c.Check(a.Revision(), Equals, 11)
	c.Check(a.Format(), Equals, 1)
	c.Check(a.SupportedFormat(), Equals, true)

	a1, err := asserts.Decode(asserts.Encode(a))
	c.Assert(err, IsNil)

	c.Check(a1.Revision(), Equals, 11)
	c.Check(a1.Format(), Equals, 1)
	c.Check(a1.SupportedFormat(), Equals, true)
}
Пример #29
0
func generateSerialRequestAssertion(model, serial string) (string, error) {
	privateKey, _ := generatePrivateKey()
	encodedPubKey, _ := asserts.EncodePublicKey(privateKey.PublicKey())

	headers := map[string]interface{}{
		"brand-id":   "System",
		"device-key": string(encodedPubKey),
		"request-id": "REQID",
		"model":      model,
	}

	body := fmt.Sprintf("serial: %s", serial)

	sreq, err := asserts.SignWithoutAuthority(asserts.SerialRequestType, headers, []byte(body), privateKey)
	if err != nil {
		return "", err
	}

	assertSR := asserts.Encode(sreq)
	return string(assertSR), nil
}
Пример #30
0
func (s *baseDeclSuite) TestBuiltin(c *C) {
	baseDecl := asserts.BuiltinBaseDeclaration()
	c.Check(baseDecl, IsNil)

	defer asserts.InitBuiltinBaseDeclaration(nil)

	const headers = `
type: base-declaration
authority-id: canonical
series: 16
revision: 0
plugs:
  network: true
slots:
  network:
    allow-installation:
      slot-snap-type:
        - core
`

	err := asserts.InitBuiltinBaseDeclaration([]byte(headers))
	c.Assert(err, IsNil)

	baseDecl = asserts.BuiltinBaseDeclaration()
	c.Assert(baseDecl, NotNil)

	cont, _ := baseDecl.Signature()
	c.Check(string(cont), Equals, strings.TrimSpace(headers))

	c.Check(baseDecl.AuthorityID(), Equals, "canonical")
	c.Check(baseDecl.Series(), Equals, "16")
	c.Check(baseDecl.PlugRule("network").AllowAutoConnection[0].SlotAttributes, Equals, asserts.AlwaysMatchAttributes)
	c.Check(baseDecl.SlotRule("network").AllowInstallation[0].SlotSnapTypes, DeepEquals, []string{"core"})

	enc := asserts.Encode(baseDecl)
	// it's expected that it cannot be decoded
	_, err = asserts.Decode(enc)
	c.Check(err, NotNil)
}