blob: 11457354d2a79bbd53465754c1c1716fe5950a20 [file] [log] [blame]
David Brown1314bf32017-12-20 11:10:55 -07001# Copyright 2017 Linaro Limited
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
David Brown23f91ad2017-05-16 11:38:17 -060015"""
16Cryptographic key management for imgtool.
17"""
18
David Brown5e7c6dd2017-11-16 14:47:16 -070019from cryptography.hazmat.backends import default_backend
20from cryptography.hazmat.primitives import serialization
21from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey
David Brownb6e0ae62017-11-21 15:13:04 -070022from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey, EllipticCurvePublicKey
Fabio Utzig8101d1f2019-05-09 15:03:22 -030023from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
David Brown23f91ad2017-05-16 11:38:17 -060024
Fabio Utzig19fd79a2019-05-08 18:20:39 -030025from .rsa import RSA, RSAPublic, RSAUsageError, RSA_KEY_SIZES
David Brownb6e0ae62017-11-21 15:13:04 -070026from .ecdsa import ECDSA256P1, ECDSA256P1Public, ECDSAUsageError
Fabio Utzig8101d1f2019-05-09 15:03:22 -030027from .ed25519 import Ed25519, Ed25519Public, Ed25519UsageError
David Brown23f91ad2017-05-16 11:38:17 -060028
David Brown5e7c6dd2017-11-16 14:47:16 -070029class PasswordRequired(Exception):
30 """Raised to indicate that the key is password protected, but a
31 password was not specified."""
32 pass
33
34def load(path, passwd=None):
35 """Try loading a key from the given path. Returns None if the password wasn't specified."""
David Brown23f91ad2017-05-16 11:38:17 -060036 with open(path, 'rb') as f:
David Brown5e7c6dd2017-11-16 14:47:16 -070037 raw_pem = f.read()
David Brown23f91ad2017-05-16 11:38:17 -060038 try:
David Brown5e7c6dd2017-11-16 14:47:16 -070039 pk = serialization.load_pem_private_key(
40 raw_pem,
41 password=passwd,
42 backend=default_backend())
David Brown1d5bea12017-11-16 15:11:10 -070043 # Unfortunately, the crypto library raises unhelpful exceptions,
44 # so we have to look at the text.
45 except TypeError as e:
46 msg = str(e)
47 if "private key is encrypted" in msg:
48 return None
49 raise e
David Brown23f91ad2017-05-16 11:38:17 -060050 except ValueError:
David Brown5e7c6dd2017-11-16 14:47:16 -070051 # This seems to happen if the key is a public key, let's try
52 # loading it as a public key.
53 pk = serialization.load_pem_public_key(
54 raw_pem,
55 backend=default_backend())
56
57 if isinstance(pk, RSAPrivateKey):
Fabio Utzig19fd79a2019-05-08 18:20:39 -030058 if pk.key_size not in RSA_KEY_SIZES:
David Brown5e7c6dd2017-11-16 14:47:16 -070059 raise Exception("Unsupported RSA key size: " + pk.key_size)
Fabio Utzig19fd79a2019-05-08 18:20:39 -030060 return RSA(pk)
David Brown5e7c6dd2017-11-16 14:47:16 -070061 elif isinstance(pk, RSAPublicKey):
Fabio Utzig19fd79a2019-05-08 18:20:39 -030062 if pk.key_size not in RSA_KEY_SIZES:
David Brown5e7c6dd2017-11-16 14:47:16 -070063 raise Exception("Unsupported RSA key size: " + pk.key_size)
Fabio Utzig19fd79a2019-05-08 18:20:39 -030064 return RSAPublic(pk)
David Brownb6e0ae62017-11-21 15:13:04 -070065 elif isinstance(pk, EllipticCurvePrivateKey):
66 if pk.curve.name != 'secp256r1':
67 raise Exception("Unsupported EC curve: " + pk.curve.name)
68 if pk.key_size != 256:
69 raise Exception("Unsupported EC size: " + pk.key_size)
70 return ECDSA256P1(pk)
71 elif isinstance(pk, EllipticCurvePublicKey):
72 if pk.curve.name != 'secp256r1':
73 raise Exception("Unsupported EC curve: " + pk.curve.name)
74 if pk.key_size != 256:
75 raise Exception("Unsupported EC size: " + pk.key_size)
76 return ECDSA256P1Public(pk)
Fabio Utzig8101d1f2019-05-09 15:03:22 -030077 elif isinstance(pk, Ed25519PrivateKey):
78 return Ed25519(pk)
79 elif isinstance(pk, Ed25519PublicKey):
80 return Ed25519Public(pk)
David Brown5e7c6dd2017-11-16 14:47:16 -070081 else:
82 raise Exception("Unknown key type: " + str(type(pk)))