blob: 65b709f6fce1d3afa3d0ddf789c423b171a86d0d [file] [log] [blame]
David Brownb6e0ae62017-11-21 15:13:04 -07001"""
2Tests for ECDSA keys
3"""
4
David Brown79c4fcf2021-01-26 15:04:05 -07005# SPDX-License-Identifier: Apache-2.0
6
David Brownb6e0ae62017-11-21 15:13:04 -07007import io
8import os.path
9import sys
10import tempfile
11import unittest
12
13from cryptography.exceptions import InvalidSignature
14from cryptography.hazmat.primitives.asymmetric import ec
15from cryptography.hazmat.primitives.hashes import SHA256
16
17sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
18
19from imgtool.keys import load, ECDSA256P1, ECDSAUsageError
20
21class EcKeyGeneration(unittest.TestCase):
22
23 def setUp(self):
24 self.test_dir = tempfile.TemporaryDirectory()
25
26 def tname(self, base):
27 return os.path.join(self.test_dir.name, base)
28
29 def tearDown(self):
30 self.test_dir.cleanup()
31
32 def test_keygen(self):
33 name1 = self.tname("keygen.pem")
34 k = ECDSA256P1.generate()
35 k.export_private(name1, b'secret')
36
37 self.assertIsNone(load(name1))
38
39 k2 = load(name1, b'secret')
40
41 pubname = self.tname('keygen-pub.pem')
42 k2.export_public(pubname)
43 pk2 = load(pubname)
44
45 # We should be able to export the public key from the loaded
46 # public key, but not the private key.
47 pk2.export_public(self.tname('keygen-pub2.pem'))
48 self.assertRaises(ECDSAUsageError,
49 pk2.export_private, self.tname('keygen-priv2.pem'))
50
51 def test_emit(self):
52 """Basic sanity check on the code emitters."""
53 k = ECDSA256P1.generate()
54
55 ccode = io.StringIO()
Fabio Utzig9560d772020-04-02 13:44:30 -030056 k.emit_c_public(ccode)
David Brownb6e0ae62017-11-21 15:13:04 -070057 self.assertIn("ecdsa_pub_key", ccode.getvalue())
58 self.assertIn("ecdsa_pub_key_len", ccode.getvalue())
59
60 rustcode = io.StringIO()
Fabio Utzig9560d772020-04-02 13:44:30 -030061 k.emit_rust_public(rustcode)
David Brownb6e0ae62017-11-21 15:13:04 -070062 self.assertIn("ECDSA_PUB_KEY", rustcode.getvalue())
63
64 def test_emit_pub(self):
65 """Basic sanity check on the code emitters."""
66 pubname = self.tname("public.pem")
67 k = ECDSA256P1.generate()
68 k.export_public(pubname)
69
70 k2 = load(pubname)
71
72 ccode = io.StringIO()
Fabio Utzig9560d772020-04-02 13:44:30 -030073 k2.emit_c_public(ccode)
David Brownb6e0ae62017-11-21 15:13:04 -070074 self.assertIn("ecdsa_pub_key", ccode.getvalue())
75 self.assertIn("ecdsa_pub_key_len", ccode.getvalue())
76
77 rustcode = io.StringIO()
Fabio Utzig9560d772020-04-02 13:44:30 -030078 k2.emit_rust_public(rustcode)
David Brownb6e0ae62017-11-21 15:13:04 -070079 self.assertIn("ECDSA_PUB_KEY", rustcode.getvalue())
80
81 def test_sig(self):
82 k = ECDSA256P1.generate()
83 buf = b'This is the message'
David Brown2c9153a2017-11-21 15:18:12 -070084 sig = k.raw_sign(buf)
David Brownb6e0ae62017-11-21 15:13:04 -070085
86 # The code doesn't have any verification, so verify this
87 # manually.
88 k.key.public_key().verify(
89 signature=sig,
90 data=buf,
91 signature_algorithm=ec.ECDSA(SHA256()))
92
93 # Modify the message to make sure the signature fails.
94 self.assertRaises(InvalidSignature,
95 k.key.public_key().verify,
96 signature=sig,
97 data=b'This is thE message',
98 signature_algorithm=ec.ECDSA(SHA256()))
99
100if __name__ == '__main__':
101 unittest.main()