1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/dist/tools/suit/suit-manifest-generator/suit_tool/get_pubkey.py

96 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------
# Copyright 2020 ARM Limited or its affiliates
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ----------------------------------------------------------------------------
import textwrap
import binascii
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec, ed25519
from cryptography.hazmat.primitives.asymmetric import utils as asymmetric_utils
from cryptography.hazmat.primitives import serialization as ks
def to_uecc_pubkey(pk):
if not isinstance(pk, ec.EllipticCurvePrivateKey):
raise Exception('Private key of type {} is not supported'.format(type(pk)))
public_numbers = pk.public_key().public_numbers()
x = public_numbers.x
y = public_numbers.y
uecc_bytes = x.to_bytes(
(x.bit_length() + 7) // 8, byteorder='big'
) + y.to_bytes(
(y.bit_length() + 7) // 8, byteorder='big'
)
uecc_c_def = ['const uint8_t public_key[] = {'] + textwrap.wrap(
', '.join(['{:0=#4x}'.format(x) for x in uecc_bytes]),
76
)
return '\n '.join(uecc_c_def) + '\n};\n'
def to_header(pk):
if isinstance(pk, ec.EllipticCurvePrivateKey):
return to_uecc_pubkey(pk)
if isinstance(pk, ed25519.Ed25519PrivateKey):
public_bytes = pk.public_key().public_bytes(ks.Encoding.Raw,
ks.PublicFormat.Raw)
public_c_def = ['const uint8_t public_key[] = {'] + textwrap.wrap(
', '.join(['{:0=#4x}'.format(x) for x in public_bytes]),
76
)
return str.encode('\n '.join(public_c_def) + '\n};\n')
OutputFormaters = {
'uecc' : to_uecc_pubkey,
'header': to_header,
'pem' : lambda pk: pk.public_key().public_bytes(ks.Encoding.PEM, ks.PublicFormat.SubjectPublicKeyInfo),
'der' : lambda pk: pk.public_key().public_bytes(ks.Encoding.DER, ks.PublicFormat.SubjectPublicKeyInfo),
'hsslms' : lambda pk: pk.publicKey().serialize(),
'c-hsslms' : lambda pk: ('\n '.join(['const uint8_t hsslms_public_key[] = {'] + textwrap.wrap(
', '.join(['{:0=#4x}'.format(x) for x in pk.publicKey().serialize()]),
76
)) + '\n};\n').encode('utf-8')
}
def main(options):
private_key = None
# This test is here because the cryptography module doesn't know about hss-lms keys
if options.output_format in ('pem', 'der', 'uecc', 'header'):
private_key = ks.load_pem_private_key(
options.private_key.read(),
password=None,
backend=default_backend()
)
odata = OutputFormaters.get(options.output_format)(private_key)
try:
odata = odata.decode('utf-8')
except:
odata = binascii.b2a_hex(odata).decode('utf-8')
odata = '\n'.join(
[line for lines in [textwrap.wrap(line, 80)
for line in odata.split('\n')] for line in lines]
) + '\n'
options.output_file.write(odata)
return 0