imgtool: Improve ECDSA key generation

This patch improves the existing ECDSA key generation feature
in the imgtool by:
 - Fix a bug in the 'minimal' representation of PKCS#8 keys where
   the resulting ASN.1 DER encoding is not compliant
 - Add the option to export ECDSA private keys in SEC1 format by
   providing a command line option -f or --format that can be
   'openssl' (for SEC1 format) or 'pkcs8'. This format ends up in
   key encodings which are generally smaller than PKCS#8.

Signed-off-by: Antonio de Angelis <Antonio.deAngelis@arm.com>
diff --git a/scripts/imgtool/keys/ecdsa.py b/scripts/imgtool/keys/ecdsa.py
index 9198bb4..0433beb 100644
--- a/scripts/imgtool/keys/ecdsa.py
+++ b/scripts/imgtool/keys/ecdsa.py
@@ -3,6 +3,7 @@
 """
 
 # SPDX-License-Identifier: Apache-2.0
+import os.path
 
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives import serialization
@@ -102,37 +103,60 @@
     def _get_public(self):
         return self.key.public_key()
 
-    def _build_minimal_ecdsa_privkey(self, der):
+    def _build_minimal_ecdsa_privkey(self, der, format):
         '''
         Builds a new DER that only includes the EC private key, removing the
         public key that is added as an "optional" BITSTRING.
         '''
-        offset_PUB = 68
+
+        if format == serialization.PrivateFormat.OpenSSH:
+            print(os.path.basename(__file__) +
+                  ': Warning: --minimal is supported only for PKCS8 '
+                  'or TraditionalOpenSSL formats')
+            return bytearray(der)
+
         EXCEPTION_TEXT = "Error parsing ecdsa key. Please submit an issue!"
-        if der[offset_PUB] != 0xa1:
-            raise ECDSAUsageError(EXCEPTION_TEXT)
-        len_PUB = der[offset_PUB + 1]
-        b = bytearray(der[:-offset_PUB])
-        offset_SEQ = 29
-        if b[offset_SEQ] != 0x30:
-            raise ECDSAUsageError(EXCEPTION_TEXT)
-        b[offset_SEQ + 1] -= len_PUB
-        offset_OCT_STR = 27
-        if b[offset_OCT_STR] != 0x04:
-            raise ECDSAUsageError(EXCEPTION_TEXT)
-        b[offset_OCT_STR + 1] -= len_PUB
-        if b[0] != 0x30 or b[1] != 0x81:
-            raise ECDSAUsageError(EXCEPTION_TEXT)
-        b[2] -= len_PUB
+        if format == serialization.PrivateFormat.PKCS8:
+            offset_PUB = 68  # where the context specific TLV starts (tag 0xA1)
+            if der[offset_PUB] != 0xa1:
+                raise ECDSAUsageError(EXCEPTION_TEXT)
+            len_PUB = der[offset_PUB + 1] + 2  # + 2 for 0xA1 0x44 bytes
+            b = bytearray(der[:offset_PUB])  # remove the TLV with the PUB key
+            offset_SEQ = 29
+            if b[offset_SEQ] != 0x30:
+                raise ECDSAUsageError(EXCEPTION_TEXT)
+            b[offset_SEQ + 1] -= len_PUB
+            offset_OCT_STR = 27
+            if b[offset_OCT_STR] != 0x04:
+                raise ECDSAUsageError(EXCEPTION_TEXT)
+            b[offset_OCT_STR + 1] -= len_PUB
+            if b[0] != 0x30 or b[1] != 0x81:
+                raise ECDSAUsageError(EXCEPTION_TEXT)
+            # as b[1] has bit7 set, the length is on b[2]
+            b[2] -= len_PUB
+            if b[2] < 0x80:
+                del(b[1])
+
+        elif format == serialization.PrivateFormat.TraditionalOpenSSL:
+            offset_PUB = 51
+            if der[offset_PUB] != 0xA1:
+                raise ECDSAUsageError(EXCEPTION_TEXT)
+            len_PUB = der[offset_PUB + 1] + 2
+            b = bytearray(der[0:offset_PUB])
+            b[1] -= len_PUB
+
         return b
 
-    def get_private_bytes(self, minimal):
+    def get_private_bytes(self, minimal, format):
+        formats = {'pkcs8': serialization.PrivateFormat.PKCS8,
+                   'openssl': serialization.PrivateFormat.TraditionalOpenSSL
+                   }
         priv = self.key.private_bytes(
                 encoding=serialization.Encoding.DER,
-                format=serialization.PrivateFormat.PKCS8,
+                format=formats[format],
                 encryption_algorithm=serialization.NoEncryption())
         if minimal:
-            priv = self._build_minimal_ecdsa_privkey(priv)
+            priv = self._build_minimal_ecdsa_privkey(priv, formats[format])
         return priv
 
     def export_private(self, path, passwd=None):