Skip to content

Commit

Permalink
Implemented package_index.json signature verification (#791)
Browse files Browse the repository at this point in the history
* Added download of signature files for 'downloads.arduino.cc' domain

* Slightly simplified tmp file creation

* Use patched version of rice-box

This version must be kept until the following pull request is merged
upstream: GeertJohan/go.rice#159

* Added signature verification subroutines

* Implemented package_index.json signature verification

* Added missing license headers

* Added negative test on signature check

* Only copy signature if the file is present
  • Loading branch information
cmaglie committed Jul 7, 2020
1 parent 1fa4874 commit 1ad33cd
Show file tree
Hide file tree
Showing 9 changed files with 7,848 additions and 8 deletions.
Binary file added arduino/security/keys/arduino_public.gpg.key
Binary file not shown.
43 changes: 43 additions & 0 deletions arduino/security/rice-box.go

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions arduino/security/signature_test.go
@@ -0,0 +1,36 @@
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.

package security

import (
"testing"

"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
)

func TestSignatureVerification(t *testing.T) {
res, signer, err := VerifyArduinoDetachedSignature(paths.New("testdata/package_index.json"), paths.New("testdata/package_index.json.sig"))
require.NoError(t, err)
require.NotNil(t, signer)
require.True(t, res)
require.Equal(t, uint64(0x7baf404c2dfab4ae), signer.PrimaryKey.KeyId)

res, signer, err = VerifyArduinoDetachedSignature(paths.New("testdata/invalid_file.json"), paths.New("testdata/package_index.json.sig"))
require.False(t, res)
require.Nil(t, signer)
require.Error(t, err)
}
54 changes: 54 additions & 0 deletions arduino/security/signatures.go
@@ -0,0 +1,54 @@
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.

package security

import (
"fmt"

rice "github.com/GeertJohan/go.rice"
"github.com/arduino/go-paths-helper"
"golang.org/x/crypto/openpgp"
)

// VerifyArduinoDetachedSignature that give signaturePath GPG signature match the given targetPath file
// ant the is an authentic signature from Arduino.
func VerifyArduinoDetachedSignature(targetPath *paths.Path, signaturePath *paths.Path) (bool, *openpgp.Entity, error) {
keysBox, err := rice.FindBox("keys")
if err != nil {
panic("could not find bundled signature keys")
}
arduinoKeyringFile, err := keysBox.Open("arduino_public.gpg.key")
if err != nil {
panic("could not find bundled signature keys")
}
keyRing, err := openpgp.ReadKeyRing(arduinoKeyringFile)
if err != nil {
return false, nil, fmt.Errorf("retrieving Arduino public keys: %s", err)
}

target, err := targetPath.Open()
if err != nil {
return false, nil, fmt.Errorf("opening target file: %s", err)
}
defer target.Close()
signature, err := signaturePath.Open()
if err != nil {
return false, nil, fmt.Errorf("opening signature file: %s", err)
}
defer signature.Close()
signer, err := openpgp.CheckDetachedSignature(keyRing, target, signature)
return (signer != nil && err == nil), signer, err
}

2 comments on commit 1ad33cd

@matthijskooijman
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that commit breaks building arduino-builder against arduino-cli git, since go only respects replace directives in the top-level package, not dependencies. To fix this, the dependency could be updated in the main list rather than adding a replace, or adding the replace in arduino-builder too. Or we just wait and hope that the fix is merged quickly :-)

@cmaglie
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is there from Jul 6, I think it will not be merged soon...
I'll prepare a PR to update the dependency and remove the replace.

Please sign in to comment.