Skip to content

Commit

Permalink
[crypto] add cryptography for bls
Browse files Browse the repository at this point in the history
  • Loading branch information
spalmer25 committed Oct 17, 2024
1 parent 8708488 commit 8183e5a
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 3 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ENABLE_NBGL_QRCODE = 1

HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1

CURVE_APP_LOAD_PARAMS = ed25519 secp256k1 secp256r1
CURVE_APP_LOAD_PARAMS = ed25519 secp256k1 secp256r1 bls12381g1
PATH_APP_LOAD_PARAMS = "44'/1729'"

# VERSION
Expand All @@ -35,7 +35,8 @@ GIT_DESCRIBE ?= $(shell git describe --tags --abbrev=8 --always --long --dirty 2
VERSION_TAG ?= $(shell echo "$(GIT_DESCRIBE)" | cut -f1 -d-)
COMMIT ?= $(shell echo "$(GIT_DESCRIBE)" | awk -F'-g' '{print $2}' | sed 's/-dirty/*/')

DEFINES += COMMIT=\"$(COMMIT)\"
DEFINES += COMMIT=\"$(COMMIT)\"
DEFINES += HAVE_BLS

# Only warn about version tags if specified/inferred
ifeq ($(VERSION_TAG),)
Expand Down
2 changes: 1 addition & 1 deletion misra.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"script": "misra.py",
"args": [
"--rule-texts=misra.md",
"--suppress-rules 2.7,3.1,8.2,8.9,11.3,15.1,15.2,15.5,16.3,17.7,18.4,18.8,19.2,20.7"
"--suppress-rules 2.7,3.1,8.2,8.9,11.3,15.1,15.2,15.5,16.3,17.6,17.7,18.4,18.8,19.2,20.7"
]
}
166 changes: 166 additions & 0 deletions src/crypto.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/* Tezos Ledger application - Cryptography operations
Copyright 2024 Functori <[email protected]>
Copyright 2023 Ledger SAS
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.
*/

#include <stdint.h> // uint*_t
#include <string.h> // memset, explicit_bzero
#include <stdbool.h> // bool

#include "crypto.h"

#include "cx.h"
#include "os.h"
#include "os_io_seproxyhal.h"

/**
* @brief Gets the bls private key from the device seed using the specified bip32 path
* key.
*
* @param[in] path Bip32 path to use for derivation.
*
* @param[in] path_len Bip32 path length.
*
* @param[out] privkey Generated private key.
*
* @return Error code:
* - CX_OK on success
* - CX_EC_INVALID_CURVE
* - CX_INTERNAL_ERROR
*/
static WARN_UNUSED_RESULT cx_err_t
bip32_derive_init_privkey_bls(const uint32_t *path,
size_t path_len,
cx_ecfp_384_private_key_t *privkey) {
cx_err_t error = CX_OK;
// Allocate 64 bytes to respect Syscall API but only 32 will be used
uint8_t raw_privkey[64] = {0};
cx_curve_t curve = CX_CURVE_BLS12_381_G1;
size_t length = 48;

// Derive private key according to the path
io_seproxyhal_io_heartbeat();
CX_CHECK(os_derive_eip2333_no_throw(curve, path, path_len, raw_privkey + 16));
io_seproxyhal_io_heartbeat();

// Init privkey from raw
CX_CHECK(cx_ecfp_init_private_key_no_throw(curve,
raw_privkey,
length,
(cx_ecfp_private_key_t *) privkey));

end:
explicit_bzero(raw_privkey, sizeof(raw_privkey));

if (error != CX_OK) {
// Make sure the caller doesn't use uninitialized data in case
// the return code is not checked.
explicit_bzero(privkey, sizeof(cx_ecfp_384_private_key_t));
}
return error;
}

WARN_UNUSED_RESULT cx_err_t bip32_derive_get_pubkey_bls(const uint32_t *path,
size_t path_len,
uint8_t raw_pubkey[static 97]) {
cx_err_t error = CX_OK;
cx_curve_t curve = CX_CURVE_BLS12_381_G1;

uint8_t yFlag = 0;
uint8_t tmp[96] = {0};
uint8_t bls_field[48] = {0};
int diff = 0;

cx_ecfp_384_private_key_t privkey = {0};
cx_ecfp_384_public_key_t pubkey = {0};

// Derive private key according to BIP32 path
CX_CHECK(bip32_derive_init_privkey_bls(path, path_len, &privkey));

// Generate associated pubkey
CX_CHECK(cx_ecfp_generate_pair_no_throw(curve,
(cx_ecfp_public_key_t *) &pubkey,
(cx_ecfp_private_key_t *) &privkey,
true));

tmp[47] = 2;
CX_CHECK(cx_math_mult_no_throw(tmp, pubkey.W + 1 + 48, tmp, 48));
CX_CHECK(cx_ecdomain_parameter(curve, CX_CURVE_PARAM_Field, bls_field, sizeof(bls_field)));
CX_CHECK(cx_math_cmp_no_throw(tmp + 48, bls_field, 48, &diff));
if (diff > 0) {
yFlag = 0x20u;
}
pubkey.W[1] &= 0x1fu;
pubkey.W[1] |= 0x80u | yFlag;

// Check pubkey length then copy it to raw_pubkey
if (pubkey.W_len != 97) {
error = CX_EC_INVALID_CURVE;
goto end;
}
memmove(raw_pubkey, pubkey.W, pubkey.W_len);

end:
explicit_bzero(&privkey, sizeof(privkey));

if (error != CX_OK) {
// Make sure the caller doesn't use uninitialized data in case
// the return code is not checked.
explicit_bzero(raw_pubkey, 97);
}
return error;
}

#ifndef TARGET_NANOS
WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_bls_sign_hash(const uint32_t *path,
size_t path_len,
uint8_t const *msg,
uint8_t msg_len,
uint8_t *sig,
size_t *sig_len) {
cx_err_t error = CX_OK;
// cipher suite used in tezos:
// https://gitlab.com/tezos/tezos/-/blob/master/src/lib_bls12_381_signature/bls12_381_signature.ml?ref_type=heads#L351
const uint8_t ciphersuite[] = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_";
cx_ecfp_384_private_key_t privkey;
uint8_t hash[192];

if ((sig_len == NULL) || (*sig_len < 96)) {
error = CX_INVALID_PARAMETER_VALUE;
goto end;
}

// Derive private key according to BIP32 path
CX_CHECK(bip32_derive_init_privkey_bls(path, path_len, &privkey));

CX_CHECK(
cx_hash_to_field(msg, msg_len, ciphersuite, sizeof(ciphersuite) - 1u, hash, sizeof(hash)));

CX_CHECK(ox_bls12381_sign(&privkey, hash, sizeof(hash), sig, 96));
*sig_len = 96;

end:
explicit_bzero(&privkey, sizeof(privkey));

if (error != CX_OK) {
// Make sure the caller doesn't use uninitialized data in case
// the return code is not checked.
explicit_bzero(sig, 96);
}
return error;
}
#endif
74 changes: 74 additions & 0 deletions src/crypto.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* Tezos Ledger application - Cryptography operations
Copyright 2024 Functori <[email protected]>
Copyright 2023 Ledger SAS
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.
*/

#pragma once

#include <stdint.h> // uint*_t

#include "cx.h"

/**
* @brief Gets the bls public key from the device seed using the specified bip32 path
* key.
*
* @param[in] path Bip32 path to use for derivation.
*
* @param[in] path_len Bip32 path length.
*
* @param[out] raw_pubkey Buffer where to store the public key.
*
* @return Error code:
* - CX_OK on success
* - CX_EC_INVALID_CURVE
* - CX_INTERNAL_ERROR
*/
WARN_UNUSED_RESULT cx_err_t bip32_derive_get_pubkey_bls(const uint32_t *path,
size_t path_len,
uint8_t raw_pubkey[static 97]);

#ifndef TARGET_NANOS
/**
* @brief Sign a hash with bls using the device seed derived from the specified bip32 path.
*
* @param[in] path Bip32 path to use for derivation.
*
* @param[in] path_len Bip32 path length.
*
* @param[in] msg Digest of the message to be signed.
* The length of *message* must be shorter than the group order size.
* Otherwise it is truncated.
*
* @param[in] msg_len Length of the digest in octets.
*
* @param[out] sig Buffer where to store the signature.
*
* @param[in] sig_len Length of the signature buffer, updated with signature length.
*
* @return Error code:
* - CX_OK on success
* - CX_EC_INVALID_CURVE
* - CX_INTERNAL_ERROR
*/
WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_bls_sign_hash(const uint32_t *path,
size_t path_len,
uint8_t const *msg,
uint8_t msg_len,
uint8_t *sig,
size_t *sig_len);
#endif

0 comments on commit 8183e5a

Please sign in to comment.