diff --git a/imgtool/imgtool.go b/imgtool/imgtool.go index 14c90a0b..b880244e 100644 --- a/imgtool/imgtool.go +++ b/imgtool/imgtool.go @@ -8,12 +8,14 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "crypto/rsa" "crypto/x509" "encoding/asn1" "encoding/pem" "errors" "fmt" "io/ioutil" + "math/big" "os" "strings" "text/template" @@ -141,6 +143,14 @@ func init() { generate: genEcdsaP224, } keyGens[kg.name] = kg + + kg = &KeyGenerator{ + name: "rsa-2048", + description: "RSA 2048", + pemType: "RSA PRIVATE KEY", + generate: genRSA2048, + } + keyGens[kg.name] = kg } func genEcdsaP224() ([]byte, error) { @@ -161,6 +171,15 @@ func genEcdsaP256() ([]byte, error) { return x509.MarshalECPrivateKey(priv) } +func genRSA2048() ([]byte, error) { + priv, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, err + } + + return x509.MarshalPKCS1PrivateKey(priv), nil +} + func doGetPub(cmd *cobra.Command, args []string) { data, err := ioutil.ReadFile(keyFile) if err != nil { @@ -177,10 +196,16 @@ func doGetPub(cmd *cobra.Command, args []string) { } // fmt.Printf("type=%q, headers=%v, data=\n%s", block.Type, block.Headers, hex.Dump(block.Bytes)) - if block.Type != "EC PRIVATE KEY" { - log.Fatal("Only supports ECDSA keys") + if block.Type == "EC PRIVATE KEY" { + dumpECPub(block) + } else if block.Type == "RSA PRIVATE KEY" { + dumpRSAPub(block) + } else { + log.Fatal("Only supports ECDSA and RSA keys") } +} +func dumpECPub(block *pem.Block) { privateKey, err := x509.ParseECPrivateKey(block.Bytes) if err != nil { log.Fatal(err) @@ -242,12 +267,42 @@ const unsigned int ec_pub_key_len = %d; formatCData(asnBytes, 1), len(asnBytes)) } +func dumpRSAPub(block *pem.Block) { + privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + log.Fatal(err) + } + + pubKey := RSAPublicKey{ + N: privateKey.N, + E: privateKey.E, + } + + asnBytes, err := asn1.Marshal(pubKey) + if err != nil { + log.Fatal(err) + } + + fmt.Printf(`/* Autogenerated, do not edit */ + +const unsigned char rsa_pub_key[] = { + %s }; +const unsigned int ec_pub_key_len = %d; +`, + formatCData(asnBytes, 1), len(asnBytes)) +} + // ecPublicKey represents an ASN.1 Elliptic Curve Public Key structure type EcPublicKey struct { Algorithm AlgorithmId PubKey asn1.BitString } +type RSAPublicKey struct { + N *big.Int + E int +} + type AlgorithmId struct { Algorithm asn1.ObjectIdentifier Curve asn1.ObjectIdentifier