Skip to content

Commit

Permalink
[python] Rewrite SGX signing in cryptography.io
Browse files Browse the repository at this point in the history
Signed-off-by: Wojtek Porczyk <[email protected]>
  • Loading branch information
woju committed Feb 23, 2023
1 parent 7ad92e9 commit e10dde8
Showing 1 changed file with 55 additions and 20 deletions.
75 changes: 55 additions & 20 deletions python/graminelibos/sgx_sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@
import os
import pathlib
import struct
import subprocess

import click

from cryptography.hazmat import backends
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa

import elftools.elf.elffile

Expand Down Expand Up @@ -547,16 +546,41 @@ def get_tbssigstruct(manifest_path, date, libpal=SGX_LIBPAL, verbose=False):


@click.command(add_help_option=False)
@click.pass_context
@click.help_option('--help-file')
@click.option('--key', '-k', metavar='FILE',
type=click.Path(exists=True, dir_okay=False),
type=click.File('rb'),
default=os.fspath(SGX_RSA_KEY_PATH),
help='specify signing key (.pem) file')
def sign_with_file(key):
return functools.partial(sign_with_local_key, key=key), [key]
def sign_with_file(ctx, key):
try:
private_key = load_pem_private_key_from_file(key)
except InvalidRSAKeyError as e:
ctx.fail(str(e))

return functools.partial(sign_with_rsa_key, private_key=private_key), [key.name]


class InvalidRSAKeyError(Exception):
pass


def load_pem_private_key_from_file(file, passphrase=None):
with file:
private_key = serialization.load_pem_private_key(
file.read(), password=passphrase, backend=_cryptography_backend)

exponent = private_key.public_key().public_numbers().e

if exponent != SGX_RSA_PUBLIC_EXPONENT:
raise InvalidRSAKeyError(
f'invalid RSA key: expected exponent {SGX_RSA_PUBLIC_EXPONENT}, got {exponent}')

return private_key


def sign_with_local_key(data, key):
"""Signs *data* using *key*.
"""Signs *data* using *key* loaded from file.
Function used to generate an RSA signature over provided data using a 3072-bit private key with
the public exponent of 3 (hard Intel SGX requirement on the key size and the exponent).
Expand All @@ -569,22 +593,32 @@ def sign_with_local_key(data, key):
Returns:
(int, int, int): Tuple of exponent, modulus and signature respectively.
"""
proc = subprocess.Popen(
['openssl', 'rsa', '-modulus', '-in', key, '-noout'],
stdout=subprocess.PIPE)
modulus_out, _ = proc.communicate()
modulus = bytes.fromhex(modulus_out[8:8+offs.SE_KEY_SIZE*2].decode())

proc = subprocess.Popen(
['openssl', 'sha256', '-binary', '-sign', key],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
signature, _ = proc.communicate(data)
with open(key, 'rb') as file:
private_key = load_pem_private_key_from_file(file)

exponent_int = 3
modulus_int = int.from_bytes(modulus, byteorder='big')
signature_int = int.from_bytes(signature, byteorder='big')
return sign_with_rsa_key(data, private_key)

return exponent_int, modulus_int, signature_int

def sign_with_rsa_key(data, private_key):
"""Signs *data* using *private_key*.
Function used to generate an RSA signature over provided data using a 3072-bit private key with
the public exponent of 3 (hard Intel SGX requirement on the key size and the exponent).
Suitable to be used as a callback to :py:func:`graminelibos.Sigstruct.sign()`.
Args:
data (bytes): Data to calculate the signature over.
private_key (cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey): RSA private key.
Returns:
(int, int, int): Tuple of exponent, modulus and signature respectively.
"""

public_numbers = private_key.public_key().public_numbers()
assert public_numbers.e == SGX_RSA_PUBLIC_EXPONENT
signature = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
return public_numbers.e, public_numbers.n, int.from_bytes(signature, byteorder='big')


def generate_private_key():
Expand All @@ -598,6 +632,7 @@ def generate_private_key():
key_size=SGX_RSA_KEY_SIZE,
backend=_cryptography_backend)


def generate_private_key_pem():
"""Generate PEM-encoded RSA key suitable for use with SGX
Expand Down

0 comments on commit e10dde8

Please sign in to comment.