imgtool: Add support for P-224

The --key-type (-t) parameter to keygen allows (requires) the user to
specify the type of key to generate.  This now supports "ecdsa-p224" and
"ecdsa-256".  Note that the curve must match the one coded into the
bootloader.
This commit is contained in:
David Brown 2017-01-31 13:32:40 -07:00
parent 039649548c
commit 6b0df8103a
2 changed files with 102 additions and 10 deletions

View File

@ -63,6 +63,19 @@ Keys are generated with the ``keygen`` subcommand. The ``-k`` option
allows you to specify a different file for the resulting key. The key
is stored in *PEM* format.
You must specify a ``--key-type`` parameter. Current valid entries
are:
.. list-table:: Key types
:header-rows: 1
* - Parameter
- Description
* - ecdsa-p224
- ECDSA with SHA256 and NIST P-224 (secp224r1)
* - ecdsa-p256
- ECDSA with SHA256 and NIST P-256 (secp256r1)
Extracting the public key
-------------------------

View File

@ -11,6 +11,7 @@ import (
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"os"
@ -22,6 +23,7 @@ import (
)
var keyFile string
var keyType KeyGenerator
func main() {
root := &cobra.Command{
@ -42,6 +44,9 @@ func main() {
Run: doKeyGen,
}
fl = keygen.Flags()
fl.VarP(&keyType, "key-type", "t", "Type of key to generate")
root.AddCommand(keygen)
getpub := &cobra.Command{
@ -60,19 +65,17 @@ func main() {
}
func doKeyGen(cmd *cobra.Command, args []string) {
if keyType.generate == nil {
cmd.Usage()
log.Fatal("Must specify key type with --key-type")
}
if len(args) != 0 {
cmd.Usage()
log.Fatal("Expecting no arguments to keygen")
}
// For now, there are no parameters, we just generate a
// PEM-encoded ECDSA P-256 key.
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatal(err)
}
priv509, err := x509.MarshalECPrivateKey(priv)
priv509, err := keyType.generate()
if err != nil {
log.Fatal(err)
}
@ -84,7 +87,7 @@ func doKeyGen(cmd *cobra.Command, args []string) {
defer fd.Close()
block := pem.Block{
Type: "EC PRIVATE KEY",
Type: keyType.pemType,
Bytes: priv509,
}
err = pem.Encode(fd, &block)
@ -93,6 +96,71 @@ func doKeyGen(cmd *cobra.Command, args []string) {
}
}
var keyGens map[string]*KeyGenerator
type KeyGenerator struct {
name string
description string
pemType string
generate func() ([]byte, error)
}
func (g *KeyGenerator) Set(text string) error {
kg, ok := keyGens[text]
if !ok {
return errors.New("Unsupported key type")
}
*g = *kg
return nil
}
func (g *KeyGenerator) String() string {
return g.name
}
func (g *KeyGenerator) Type() string {
return "keytype"
}
func init() {
keyGens = make(map[string]*KeyGenerator)
kg := &KeyGenerator{
name: "ecdsa-p256",
description: "ECDSA with SHA256 and the NIST P-256 curve",
pemType: "EC PRIVATE KEY",
generate: genEcdsaP256,
}
keyGens[kg.name] = kg
kg = &KeyGenerator{
name: "ecdsa-p224",
description: "ECDSA with SHA256 and the NIST P-224 curve",
pemType: "EC PRIVATE KEY",
generate: genEcdsaP224,
}
keyGens[kg.name] = kg
}
func genEcdsaP224() ([]byte, error) {
priv, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
if err != nil {
return nil, err
}
return x509.MarshalECPrivateKey(priv)
}
func genEcdsaP256() ([]byte, error) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
return x509.MarshalECPrivateKey(priv)
}
func doGetPub(cmd *cobra.Command, args []string) {
data, err := ioutil.ReadFile(keyFile)
if err != nil {
@ -131,6 +199,17 @@ func doGetPub(cmd *cobra.Command, args []string) {
// log.Fatal(err)
// }
// The public key needs the algorithm and curve parameters.
var curve []int
switch privateKey.Params().Name {
case "P-224":
curve = []int{1, 3, 132, 0, 33}
case "P-256":
curve = []int{1, 2, 840, 10045, 3, 1, 7}
default:
log.Fatal("Key uses unsupported curve: %q", privateKey.Params().Name)
}
// The public key is encoded uncompressed, as a concatenation
// of the bytes.
var bbuf bytes.Buffer
@ -142,7 +221,7 @@ func doGetPub(cmd *cobra.Command, args []string) {
pkey := EcPublicKey{
Algorithm: AlgorithmId{
Algorithm: []int{1, 2, 840, 10045, 2, 1},
Curve: []int{1, 2, 840, 10045, 3, 1, 7},
Curve: curve,
},
PubKey: asn1.BitString{
Bytes: pkeyBytes,