From 11526a94fc48255eab718784f8759e368f25c5b9 Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Tue, 17 Jan 2023 17:26:32 +0200 Subject: [PATCH 1/9] Initial support for client/server-only operation --- include/picotls.h | 17 ++++++++++++++--- lib/picotls.c | 46 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index fe74d40d3..6d7ba5dbd 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -60,8 +60,9 @@ extern "C" { #define PTLS_ELEMENTSOF(x) (PTLS_ASSERT_IS_ARRAY_EXPR(x) * sizeof(x) / sizeof((x)[0])) -#ifdef _WINDOWS +#if defined(_WINDOWS) #define PTLS_THREADLOCAL __declspec(thread) +#elif defined(PARTICLE) #else #define PTLS_THREADLOCAL __thread #define PTLS_HAVE_LOG 1 @@ -1239,7 +1240,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); #define PTLS_LOG(module, type, block) \ do { \ - if (!ptls_log.is_active) \ + if (!PTLS_LOG_IS_ACTIVE(ptls_log)) \ break; \ PTLS_LOG__DO_LOG((module), (type), (block)); \ } while (0) @@ -1247,7 +1248,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); #define PTLS_LOG_CONN(type, tls, block) \ do { \ ptls_t *_tls = (tls); \ - if (!ptls_log.is_active || ptls_skip_tracing(_tls)) \ + if (!PTLS_LOG_IS_ACTIVE(ptls_log) || ptls_skip_tracing(_tls)) \ break; \ PTLS_LOG__DO_LOG(picotls, type, { \ PTLS_LOG_ELEMENT_PTR(tls, _tls); \ @@ -1352,10 +1353,20 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); * User API is exposed only when logging is supported by the platform. */ typedef struct st_ptls_log_t { +#if PTLS_HAVE_LOG unsigned is_active : 1; +#else + unsigned : 1; +#endif unsigned include_appdata : 1; } ptls_log_t; +#if PTLS_HAVE_LOG +#define PTLS_LOG_IS_ACTIVE(log) (log.is_active) +#else +#define PTLS_LOG_IS_ACTIVE(log) (0) +#endif + #if PTLS_HAVE_LOG extern volatile ptls_log_t ptls_log; /** diff --git a/lib/picotls.c b/lib/picotls.c index 83ac410fb..72083e232 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -34,6 +34,9 @@ #include #include #endif +#ifdef PARTICLE +#include +#endif #include "picotls.h" #if PICOTLS_USE_DTRACE #include "picotls-probes.h" @@ -269,7 +272,11 @@ struct st_ptls_t { */ struct st_ptls_ech_t ech; /* flags */ +#if defined(PICOTLS_CLIENT) == defined(PICOTLS_SERVER) unsigned is_server : 1; +#else + unsigned : 1; +#endif unsigned is_psk_handshake : 1; unsigned send_change_cipher_spec : 1; unsigned needs_key_update : 1; @@ -588,9 +595,12 @@ int ptls_buffer_reserve_aligned(ptls_buffer_t *buf, size_t delta, uint8_t align_ new_capacity *= 2; } if (align_bits != 0) { -#ifdef _WINDOWS +#if defined(_WINDOWS) if ((newp = _aligned_malloc(new_capacity, (size_t)1 << align_bits)) == NULL) return PTLS_ERROR_NO_MEMORY; +#elif defined(PARTICLE) + if ((newp = memalign(new_capacity, (size_t)1 << align_bits)) == NULL) + return PTLS_ERROR_NO_MEMORY; #else if (posix_memalign(&newp, 1 << align_bits, new_capacity) != 0) return PTLS_ERROR_NO_MEMORY; @@ -969,7 +979,7 @@ static void log_secret(ptls_t *tls, const char *type, ptls_iovec_t secret) PTLS_PROBE(NEW_SECRET, tls, type, ptls_hexdump(hexbuf, secret.base, secret.len)); PTLS_LOG_CONN(new_secret, tls, { PTLS_LOG_ELEMENT_SAFESTR(label, type); }); - if (tls->ctx->log_event != NULL) + if (PTLS_LOG_IS_ACTIVE(ptls_log) && tls->ctx->log_event != NULL) tls->ctx->log_event->cb(tls->ctx->log_event, tls, type, "%s", ptls_hexdump(hexbuf, secret.base, secret.len)); } @@ -3106,11 +3116,11 @@ static int send_certificate_verify(ptls_t *tls, ptls_message_emitter_t *emitter, uint8_t data[PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE]; size_t datalen = build_certificate_verify_signdata(data, tls->key_schedule, context_string); if ((ret = tls->ctx->sign_certificate->cb( - tls->ctx->sign_certificate, tls, tls->is_server ? &tls->server.async_job : NULL, &algo, sendbuf, + tls->ctx->sign_certificate, tls, ptls_is_server(tls) ? &tls->server.async_job : NULL, &algo, sendbuf, ptls_iovec_init(data, datalen), signature_algorithms != NULL ? signature_algorithms->list : NULL, signature_algorithms != NULL ? signature_algorithms->count : 0)) != 0) { if (ret == PTLS_ERROR_ASYNC_OPERATION) { - assert(tls->is_server || !"async operation only supported on the server-side"); + assert(ptls_is_server(tls) || !"async operation only supported on the server-side"); assert(tls->server.async_job != NULL); /* Reset the output to the end of the previous handshake message. CertificateVerify will be rebuilt when the * async operation completes. */ @@ -4932,7 +4942,9 @@ static ptls_t *new_instance(ptls_context_t *ctx, int is_server) update_open_count(ctx, 1); *tls = (ptls_t){ctx}; +#if defined(PICOTLS_CLIENT) == defined(PICOTLS_SERVER) tls->is_server = is_server; +#endif tls->send_change_cipher_spec = ctx->send_change_cipher_spec; tls->skip_tracing = ptls_default_skip_tracing; return tls; @@ -5049,7 +5061,7 @@ int ptls_export(ptls_t *tls, ptls_buffer_t *output) ptls_iovec_t negotiated_protocol = ptls_iovec_init(tls->negotiated_protocol, tls->negotiated_protocol != NULL ? strlen(tls->negotiated_protocol) : 0); - return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random, + return export_tls12_params(output, ptls_is_server(tls), tls->is_psk_handshake, tls->cipher_suite, tls->client_random, tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq, tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret, @@ -5184,8 +5196,8 @@ void ptls_free(ptls_t *tls) ptls_aead_free(tls->traffic_protection.enc.aead); free(tls->server_name); free(tls->negotiated_protocol); - clear_ech(&tls->ech, tls->is_server); - if (tls->is_server) { + clear_ech(&tls->ech, ptls_is_server(tls)); + if (ptls_is_server(tls)) { if (tls->server.async_job != NULL) tls->server.async_job->destroy_(tls->server.async_job); } else { @@ -5601,7 +5613,7 @@ static int handle_input(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_buffe return ret; if ((ret = aead_decrypt(&tls->traffic_protection.dec, decryptbuf->base + decryptbuf->off, &decrypted_length, rec.fragment, rec.length)) != 0) { - if (tls->is_server && tls->server.early_data_skipped_bytes != UINT32_MAX) + if (ptls_is_server(tls) && tls->server.early_data_skipped_bytes != UINT32_MAX) goto ServerSkipEarlyData; return ret; } @@ -5614,13 +5626,13 @@ static int handle_input(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_buffe if (rec.length == 0) return PTLS_ALERT_UNEXPECTED_MESSAGE; rec.type = rec.fragment[--rec.length]; - } else if (rec.type == PTLS_CONTENT_TYPE_APPDATA && tls->is_server && tls->server.early_data_skipped_bytes != UINT32_MAX) { + } else if (rec.type == PTLS_CONTENT_TYPE_APPDATA && ptls_is_server(tls) && tls->server.early_data_skipped_bytes != UINT32_MAX) { goto ServerSkipEarlyData; } if (tls->recvbuf.mess.base != NULL || rec.type == PTLS_CONTENT_TYPE_HANDSHAKE) { /* handshake record */ - ret = handle_handshake_record(tls, tls->is_server ? handle_server_handshake_message : handle_client_handshake_message, + ret = handle_handshake_record(tls, ptls_is_server(tls) ? handle_server_handshake_message : handle_client_handshake_message, emitter, &rec, properties); } else { /* handling of an alert or an application record */ @@ -6263,7 +6275,13 @@ PTLS_THREADLOCAL unsigned ptls_default_skip_tracing = 0; int ptls_is_server(ptls_t *tls) { +#if defined(PICOTLS_CLIENT) && !defined(PICOTLS_SERVER) + return 0; +#elif !defined(PICOTLS_CLIENT) && defined(PICOTLS_SERVER) + return 1; +#else return tls->is_server; +#endif } struct st_ptls_raw_message_emitter_t { @@ -6333,14 +6351,14 @@ size_t ptls_get_read_epoch(ptls_t *tls) int ptls_handle_message(ptls_t *tls, ptls_buffer_t *sendbuf, size_t epoch_offsets[5], size_t in_epoch, const void *input, size_t inlen, ptls_handshake_properties_t *properties) { - return tls->is_server ? ptls_server_handle_message(tls, sendbuf, epoch_offsets, in_epoch, input, inlen, properties) - : ptls_client_handle_message(tls, sendbuf, epoch_offsets, in_epoch, input, inlen, properties); + return ptls_is_server(tls) ? ptls_server_handle_message(tls, sendbuf, epoch_offsets, in_epoch, input, inlen, properties) + : ptls_client_handle_message(tls, sendbuf, epoch_offsets, in_epoch, input, inlen, properties); } int ptls_client_handle_message(ptls_t *tls, ptls_buffer_t *sendbuf, size_t epoch_offsets[5], size_t in_epoch, const void *input, size_t inlen, ptls_handshake_properties_t *properties) { - assert(!tls->is_server); + assert(!ptls_is_server(tls)); struct st_ptls_raw_message_emitter_t emitter = { {sendbuf, &tls->traffic_protection.enc, 0, begin_raw_message, commit_raw_message}, SIZE_MAX, epoch_offsets}; @@ -6358,7 +6376,7 @@ int ptls_client_handle_message(ptls_t *tls, ptls_buffer_t *sendbuf, size_t epoch int ptls_server_handle_message(ptls_t *tls, ptls_buffer_t *sendbuf, size_t epoch_offsets[5], size_t in_epoch, const void *input, size_t inlen, ptls_handshake_properties_t *properties) { - assert(tls->is_server); + assert(ptls_is_server(tls)); struct st_ptls_raw_message_emitter_t emitter = { {sendbuf, &tls->traffic_protection.enc, 0, begin_raw_message, commit_raw_message}, SIZE_MAX, epoch_offsets}; From a17b2789d53fec458dad50e36ac952d20c755913 Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Mon, 23 Jan 2023 18:15:44 +0200 Subject: [PATCH 2/9] Progress --- CMakeLists.txt | 5 +++++ include/picotls.h | 5 +++++ lib/hpke.c | 8 +++++-- lib/picotls.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--- t/util.h | 16 ++++++++++++++ 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3af816dcb..eda747709 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,6 +119,11 @@ SET(TEST_EXES test-minicrypto.t) SET(PTLSBENCH_LIBS picotls-minicrypto picotls-core) +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # on Darwin, try and pick up openssl from homebrew + set(CMAKE_PREFIX_PATH /usr/local/opt/openssl@1.1 /usr/local/opt/openssl) +endif() + FIND_PACKAGE(OpenSSL) IF (OPENSSL_FOUND AND NOT (OPENSSL_VERSION VERSION_LESS "1.0.1")) MESSAGE(STATUS " Enabling OpenSSL support") diff --git a/include/picotls.h b/include/picotls.h index 6d7ba5dbd..f0d97f634 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -63,6 +63,7 @@ extern "C" { #if defined(_WINDOWS) #define PTLS_THREADLOCAL __declspec(thread) #elif defined(PARTICLE) +#define PTLS_THREADLOCAL #else #define PTLS_THREADLOCAL __thread #define PTLS_HAVE_LOG 1 @@ -72,6 +73,10 @@ extern "C" { #define PTLS_FUZZ_HANDSHAKE 0 #endif +#ifdef PTLS_MINIMIZE_STACK +extern void ptls_cleanup_free(void *p); +#endif + #define PTLS_HELLO_RANDOM_SIZE 32 #define PTLS_AES128_KEY_SIZE 16 diff --git a/lib/hpke.c b/lib/hpke.c index d243a5393..4533c4a4e 100644 --- a/lib/hpke.c +++ b/lib/hpke.c @@ -172,13 +172,17 @@ static int key_schedule(ptls_hpke_kem_t *kem, ptls_hpke_cipher_suite_t *cipher, const void *shared_secret, ptls_iovec_t info) { ptls_buffer_t key_schedule_context; - uint8_t key_schedule_context_smallbuf[128], secret[PTLS_MAX_DIGEST_SIZE], key[PTLS_MAX_SECRET_SIZE], - base_nonce[PTLS_MAX_IV_SIZE]; + uint8_t secret[PTLS_MAX_DIGEST_SIZE], key[PTLS_MAX_SECRET_SIZE], base_nonce[PTLS_MAX_IV_SIZE]; int ret; *ctx = NULL; +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_init(&key_schedule_context, "", 0); +#else + uint8_t key_schedule_context_smallbuf[128]; ptls_buffer_init(&key_schedule_context, key_schedule_context_smallbuf, sizeof(key_schedule_context_smallbuf)); +#endif /* key_schedule_context = concat(mode, LabeledExtract("", "psk_id_hash", psk_id), LabeledExtract("", "info_hash", info)) */ ptls_buffer_push(&key_schedule_context, PTLS_HPKE_MODE_BASE); diff --git a/lib/picotls.c b/lib/picotls.c index 72083e232..4ab218110 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -123,6 +123,13 @@ static const char ech_info_prefix[8] = "tls ech"; #define PTLS_PROBE(LABEL, tls, ...) #endif +#ifdef PTLS_MINIMIZE_STACK +void ptls_cleanup_free(void *p) +{ + free(*(void **)p); +} +#endif + /** * list of supported versions in the preferred order */ @@ -1144,11 +1151,15 @@ static int client_setup_ech(struct st_ptls_ech_t *ech, struct st_decoded_ech_con void (*random_bytes)(void *, size_t)) { ptls_buffer_t infobuf; - uint8_t infobuf_smallbuf[256]; int ret; /* setup `enc` and `aead` by running HPKE */ +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_init(&infobuf, "", 0); +#else + uint8_t infobuf_smallbuf[256]; ptls_buffer_init(&infobuf, infobuf_smallbuf, sizeof(infobuf_smallbuf)); +#endif ptls_buffer_pushv(&infobuf, ech_info_prefix, sizeof(ech_info_prefix)); ptls_buffer_pushv(&infobuf, decoded->bytes.base, decoded->bytes.len); if ((ret = ptls_hpke_setup_base_s(decoded->kem, decoded->cipher, &ech->client.enc, &ech->aead, decoded->public_key, @@ -1852,14 +1863,18 @@ static int send_session_ticket(ptls_t *tls, ptls_message_emitter_t *emitter) { ptls_hash_context_t *msghash_backup = tls->key_schedule->hashes[0].ctx->clone_(tls->key_schedule->hashes[0].ctx); ptls_buffer_t session_id; - char session_id_smallbuf[128]; uint32_t ticket_age_add; int ret = 0; assert(tls->ctx->ticket_lifetime != 0); assert(tls->ctx->encrypt_ticket != NULL); +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_init(&session_id, "", 0); +#else + char session_id_smallbuf[128]; ptls_buffer_init(&session_id, session_id_smallbuf, sizeof(session_id_smallbuf)); +#endif { /* calculate verify-data that will be sent by the client */ size_t orig_off = emitter->buf->off; @@ -3111,6 +3126,32 @@ static int send_certificate_verify(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_buffer_t *sendbuf = emitter->buf; size_t algo_off = sendbuf->off; ptls_buffer_push16(sendbuf, 0); /* filled in later */ +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_push_block(sendbuf, 2, { + uint16_t algo; + uint8_t *data __attribute__((__cleanup__(ptls_cleanup_free))) = malloc(PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE); + assert(data); + size_t datalen = build_certificate_verify_signdata(data, tls->key_schedule, context_string); + if ((ret = tls->ctx->sign_certificate->cb( + tls->ctx->sign_certificate, tls, ptls_is_server(tls) ? &tls->server.async_job : NULL, &algo, sendbuf, + ptls_iovec_init(data, datalen), signature_algorithms != NULL ? signature_algorithms->list : NULL, + signature_algorithms != NULL ? signature_algorithms->count : 0)) != 0) { + if (ret == PTLS_ERROR_ASYNC_OPERATION) { + assert(ptls_is_server(tls) || !"async operation only supported on the server-side"); + assert(tls->server.async_job != NULL); + /* Reset the output to the end of the previous handshake message. CertificateVerify will be rebuilt when the + * async operation completes. */ + emitter->buf->off = start_off; + } else { + assert(tls->server.async_job == NULL); + } + goto Exit; + } + assert(tls->server.async_job == NULL); + sendbuf->base[algo_off] = (uint8_t)(algo >> 8); + sendbuf->base[algo_off + 1] = (uint8_t)algo; + }); +#else ptls_buffer_push_block(sendbuf, 2, { uint16_t algo; uint8_t data[PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE]; @@ -3134,9 +3175,11 @@ static int send_certificate_verify(ptls_t *tls, ptls_message_emitter_t *emitter, sendbuf->base[algo_off] = (uint8_t)(algo >> 8); sendbuf->base[algo_off + 1] = (uint8_t)algo; }); +#endif }); Exit: return ret; +#undef data } static int client_handle_certificate_request(ptls_t *tls, ptls_iovec_t message, ptls_handshake_properties_t *properties) @@ -6094,10 +6137,14 @@ int ptls_hkdf_expand_label(ptls_hash_algorithm_t *algo, void *output, size_t out ptls_iovec_t hash_value, const char *label_prefix) { ptls_buffer_t hkdf_label; - uint8_t hkdf_label_buf[80]; int ret; +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_init(&hkdf_label, "", 0); +#else + uint8_t hkdf_label_buf[80]; ptls_buffer_init(&hkdf_label, hkdf_label_buf, sizeof(hkdf_label_buf)); +#endif ptls_buffer_push16(&hkdf_label, (uint16_t)outlen); ptls_buffer_push_block(&hkdf_label, 1, { diff --git a/t/util.h b/t/util.h index 0ead3f724..6ae0f66a5 100644 --- a/t/util.h +++ b/t/util.h @@ -34,12 +34,23 @@ #include #include #include +#ifndef PARTICLE #include #include #include #include "picotls/pembase64.h" #include "picotls/openssl.h" +#else +#include "picotls/minicrypto.h" + +#define ptls_openssl_aes128gcm ptls_minicrypto_aes128gcm +#define ptls_openssl_sha256 ptls_minicrypto_sha256 +#define ptls_openssl_secp256r1 ptls_minicrypto_secp256r1 +#define ptls_openssl_cipher_suites ptls_minicrypto_cipher_suites + +#endif +#ifndef PARTICLE static inline void load_certificate_chain(ptls_context_t *ctx, const char *fn) { if (ptls_load_certificates(ctx, (char *)fn) != 0) { @@ -192,6 +203,7 @@ static inline void setup_log_event(ptls_context_t *ctx, const char *fn) ls.super.cb = log_event_cb; ctx->log_event = &ls.super; } +#endif /* single-entry session cache */ struct st_util_session_cache_t { @@ -251,6 +263,7 @@ static inline void setup_session_cache(ptls_context_t *ctx) ctx->encrypt_ticket = &sc.super; } +#ifndef PARTICLE static struct { ptls_iovec_t config_list; struct { @@ -393,6 +406,7 @@ static void ech_setup_key(ptls_context_t *ctx, const char *fn) static ptls_ech_create_opener_t opener = {.cb = ech_create_opener}; ctx->ech.server.create_opener = &opener; } +#endif static inline int resolve_address(struct sockaddr *sa, socklen_t *salen, const char *host, const char *port, int family, int type, int proto) @@ -406,8 +420,10 @@ static inline int resolve_address(struct sockaddr *sa, socklen_t *salen, const c hints.ai_protocol = proto; hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE; if ((err = getaddrinfo(host, port, &hints, &res)) != 0 || res == NULL) { +#ifndef PARTICLE fprintf(stderr, "failed to resolve address:%s:%s:%s\n", host, port, err != 0 ? gai_strerror(err) : "getaddrinfo returned NULL"); +#endif return -1; } From b91f4b0e0c62c10af480622f8e9339c3722060d7 Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Tue, 24 Jan 2023 16:48:51 +0200 Subject: [PATCH 3/9] Changes --- include/picotls.h | 24 +++++++++++------------ lib/hpke.c | 32 +++++++++++++++++++++++++++--- lib/picotls.c | 50 +++++++++++++++++++++++++++++++++++++---------- 3 files changed, 81 insertions(+), 25 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index f0d97f634..2aa1d1a63 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -1227,6 +1227,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); ptls_decode_assert_block_close((src), end); \ } while (0) +#if PTLS_HAVE_LOG #define PTLS_LOG__DO_LOG(module, type, block) \ do { \ int ptlslog_skip = 0; \ @@ -1245,7 +1246,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); #define PTLS_LOG(module, type, block) \ do { \ - if (!PTLS_LOG_IS_ACTIVE(ptls_log)) \ + if (!ptls_log.is_active) \ break; \ PTLS_LOG__DO_LOG((module), (type), (block)); \ } while (0) @@ -1253,7 +1254,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); #define PTLS_LOG_CONN(type, tls, block) \ do { \ ptls_t *_tls = (tls); \ - if (!PTLS_LOG_IS_ACTIVE(ptls_log) || ptls_skip_tracing(_tls)) \ + if (!ptls_log.is_active || ptls_skip_tracing(_tls)) \ break; \ PTLS_LOG__DO_LOG(picotls, type, { \ PTLS_LOG_ELEMENT_PTR(tls, _tls); \ @@ -1353,25 +1354,18 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); } \ } \ } while (0) +#else +#define PTLS_LOG_CONN(...) +#endif /** * User API is exposed only when logging is supported by the platform. */ typedef struct st_ptls_log_t { -#if PTLS_HAVE_LOG unsigned is_active : 1; -#else - unsigned : 1; -#endif unsigned include_appdata : 1; } ptls_log_t; -#if PTLS_HAVE_LOG -#define PTLS_LOG_IS_ACTIVE(log) (log.is_active) -#else -#define PTLS_LOG_IS_ACTIVE(log) (0) -#endif - #if PTLS_HAVE_LOG extern volatile ptls_log_t ptls_log; /** @@ -1525,7 +1519,13 @@ int ptls_update_key(ptls_t *tls, int request_update); /** * Returns if the context is a server context. */ +#if defined(PICOTLS_CLIENT) && !defined(PICOTLS_SERVER) +#define ptls_is_server(x) (0) +#elif !defined(PICOTLS_CLIENT) && defined(PICOTLS_SERVER) +#define ptls_is_server(x) (1) +#else int ptls_is_server(ptls_t *tls); +#endif /** * returns per-record overhead */ diff --git a/lib/hpke.c b/lib/hpke.c index 4533c4a4e..744ae8be1 100644 --- a/lib/hpke.c +++ b/lib/hpke.c @@ -48,10 +48,14 @@ static int labeled_extract(ptls_hpke_kem_t *kem, ptls_hpke_cipher_suite_t *ciphe const char *label, ptls_iovec_t ikm) { ptls_buffer_t labeled_ikm; - uint8_t labeled_ikm_smallbuf[64]; int ret; +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_init(&labeled_ikm, "", 0); +#else + uint8_t labeled_ikm_smallbuf[64]; ptls_buffer_init(&labeled_ikm, labeled_ikm_smallbuf, sizeof(labeled_ikm_smallbuf)); +#endif ptls_buffer_pushv(&labeled_ikm, HPKE_V1_LABEL, strlen(HPKE_V1_LABEL)); if ((ret = build_suite_id(&labeled_ikm, kem, cipher)) != 0) @@ -71,12 +75,16 @@ static int labeled_expand(ptls_hpke_kem_t *kem, ptls_hpke_cipher_suite_t *cipher const char *label, ptls_iovec_t info) { ptls_buffer_t labeled_info; - uint8_t labeled_info_smallbuf[64]; int ret; assert(outlen < UINT16_MAX); +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_init(&labeled_info, "", 0); +#else + uint8_t labeled_info_smallbuf[64]; ptls_buffer_init(&labeled_info, labeled_info_smallbuf, sizeof(labeled_info_smallbuf)); +#endif ptls_buffer_push16(&labeled_info, (uint16_t)outlen); ptls_buffer_pushv(&labeled_info, HPKE_V1_LABEL, strlen(HPKE_V1_LABEL)); @@ -97,10 +105,15 @@ static int extract_and_expand(ptls_hpke_kem_t *kem, void *secret, size_t secret_ ptls_iovec_t dh) { ptls_buffer_t kem_context; - uint8_t kem_context_smallbuf[128], eae_prk[PTLS_MAX_DIGEST_SIZE]; + uint8_t eae_prk[PTLS_MAX_DIGEST_SIZE]; int ret; +#ifdef PTLS_MINIMIZE_STACK + ptls_buffer_init(&kem_context, "", 0); +#else + uint8_t kem_context_smallbuf[128]; ptls_buffer_init(&kem_context, kem_context_smallbuf, sizeof(kem_context_smallbuf)); +#endif ptls_buffer_pushv(&kem_context, pk_s.base, pk_s.len); ptls_buffer_pushv(&kem_context, pk_r.base, pk_r.len); @@ -172,7 +185,17 @@ static int key_schedule(ptls_hpke_kem_t *kem, ptls_hpke_cipher_suite_t *cipher, const void *shared_secret, ptls_iovec_t info) { ptls_buffer_t key_schedule_context; +#ifdef PTLS_MINIMIZE_STACK + uint8_t *tmp __attribute__((__cleanup__(ptls_cleanup_free))) = + malloc(PTLS_MAX_DIGEST_SIZE + PTLS_MAX_SECRET_SIZE + PTLS_MAX_IV_SIZE); + if (tmp == NULL) + return PTLS_ERROR_NO_MEMORY; +#define secret (tmp) +#define key (tmp + PTLS_MAX_DIGEST_SIZE) +#define base_nonce (tmp + PTLS_MAX_DIGEST_SIZE + PTLS_MAX_SECRET_SIZE) +#else uint8_t secret[PTLS_MAX_DIGEST_SIZE], key[PTLS_MAX_SECRET_SIZE], base_nonce[PTLS_MAX_IV_SIZE]; +#endif int ret; *ctx = NULL; @@ -218,6 +241,9 @@ static int key_schedule(ptls_hpke_kem_t *kem, ptls_hpke_cipher_suite_t *cipher, ptls_clear_memory(key, sizeof(key)); ptls_clear_memory(base_nonce, sizeof(base_nonce)); return ret; +#undef secret +#undef key +#undef base_nonce } int ptls_hpke_setup_base_s(ptls_hpke_kem_t *kem, ptls_hpke_cipher_suite_t *cipher, ptls_iovec_t *pk_s, ptls_aead_context_t **ctx, diff --git a/lib/picotls.c b/lib/picotls.c index 4ab218110..3653b48df 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -986,7 +986,7 @@ static void log_secret(ptls_t *tls, const char *type, ptls_iovec_t secret) PTLS_PROBE(NEW_SECRET, tls, type, ptls_hexdump(hexbuf, secret.base, secret.len)); PTLS_LOG_CONN(new_secret, tls, { PTLS_LOG_ELEMENT_SAFESTR(label, type); }); - if (PTLS_LOG_IS_ACTIVE(ptls_log) && tls->ctx->log_event != NULL) + if (tls->ctx->log_event != NULL) tls->ctx->log_event->cb(tls->ctx->log_event, tls, type, "%s", ptls_hexdump(hexbuf, secret.base, secret.len)); } @@ -2320,11 +2320,22 @@ static int encode_client_hello(ptls_context_t *ctx, ptls_buffer_t *sendbuf, enum static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_handshake_properties_t *properties, ptls_iovec_t *cookie) { - ptls_iovec_t resumption_secret = {NULL}, resumption_ticket = {NULL}; uint32_t obfuscated_ticket_age = 0; const char *sni_name = NULL; size_t mess_start, msghash_off; +#ifdef PTLS_MINIMIZE_STACK + uint8_t *binder_key __attribute__((__cleanup__(ptls_cleanup_free))) = malloc(PTLS_MAX_DIGEST_SIZE); + if (binder_key == NULL) + return PTLS_ERROR_NO_MEMORY; + ptls_iovec_t *tmp __attribute__((__cleanup__(ptls_cleanup_free))) = calloc(2, sizeof(ptls_iovec_t)); + if (tmp == NULL) + return PTLS_ERROR_NO_MEMORY; +#define resumption_secret (tmp[0]) +#define resumption_ticket (tmp[1]) +#else + ptls_iovec_t resumption_secret = {NULL}, resumption_ticket = {NULL}; uint8_t binder_key[PTLS_MAX_DIGEST_SIZE]; +#endif ptls_buffer_t encoded_ch_inner; int ret, is_second_flight = tls->key_schedule != NULL; @@ -2511,6 +2522,8 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ ptls_buffer_dispose(&encoded_ch_inner); ptls_clear_memory(binder_key, sizeof(binder_key)); return ret; +#undef resumption_secret +#undef resumption_ticket } ptls_cipher_suite_t *ptls_find_cipher_suite(ptls_cipher_suite_t **cipher_suites, uint16_t id) @@ -3204,7 +3217,11 @@ static int client_handle_certificate_request(ptls_t *tls, ptls_iovec_t message, static int handle_certificate(ptls_t *tls, const uint8_t *src, const uint8_t *end, int *got_certs) { +#ifdef PTLS_MINIMIZE_STACK + ptls_iovec_t certs[4]; +#else ptls_iovec_t certs[16]; +#endif size_t num_certs = 0; int ret = 0; @@ -3350,7 +3367,13 @@ static int handle_certificate_verify(ptls_t *tls, ptls_iovec_t message, const ch const uint8_t *src = message.base + PTLS_HANDSHAKE_HEADER_SIZE, *const end = message.base + message.len; uint16_t algo; ptls_iovec_t signature; +#ifdef PTLS_MINIMIZE_STACK + uint8_t *signdata __attribute__((__cleanup__(ptls_cleanup_free))) = malloc(PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE); + if (signdata == NULL) + return PTLS_ERROR_NO_MEMORY; +#else uint8_t signdata[PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE]; +#endif size_t signdata_size; int ret; @@ -5967,8 +5990,17 @@ int ptls_send_alert(ptls_t *tls, ptls_buffer_t *sendbuf, uint8_t level, uint8_t int ptls_export_secret(ptls_t *tls, void *output, size_t outlen, const char *label, ptls_iovec_t context_value, int is_early) { ptls_hash_algorithm_t *algo = tls->key_schedule->hashes[0].algo; - uint8_t *master_secret = is_early ? tls->exporter_master_secret.early : tls->exporter_master_secret.one_rtt, - derived_secret[PTLS_MAX_DIGEST_SIZE], context_value_hash[PTLS_MAX_DIGEST_SIZE]; + uint8_t *master_secret = is_early ? tls->exporter_master_secret.early : tls->exporter_master_secret.one_rtt; +#ifdef PTLS_MINIMIZE_STACK + uint8_t *tmp __attribute__((__cleanup__(ptls_cleanup_free))) = malloc(2 * PTLS_MAX_DIGEST_SIZE); + if (tmp == NULL) + return PTLS_ERROR_NO_MEMORY; +#define derived_secret (tmp) +#define context_value_hash (tmp + PTLS_MAX_DIGEST_SIZE) +#else + uint8_t derived_secret[PTLS_MAX_DIGEST_SIZE], context_value_hash[PTLS_MAX_DIGEST_SIZE]; + +#endif int ret; if (master_secret == NULL) { @@ -6001,6 +6033,8 @@ int ptls_export_secret(ptls_t *tls, void *output, size_t outlen, const char *lab ptls_clear_memory(derived_secret, sizeof(derived_secret)); ptls_clear_memory(context_value_hash, sizeof(context_value_hash)); return ret; +#undef derived_secret +#undef context_value_hash } struct st_picotls_hmac_context_t { @@ -6320,16 +6354,12 @@ ptls_get_time_t ptls_get_time = {get_time}; PTLS_THREADLOCAL unsigned ptls_default_skip_tracing = 0; #endif +#if defined(PICOTLS_CLIENT) == defined(PICOTLS_SERVER) int ptls_is_server(ptls_t *tls) { -#if defined(PICOTLS_CLIENT) && !defined(PICOTLS_SERVER) - return 0; -#elif !defined(PICOTLS_CLIENT) && defined(PICOTLS_SERVER) - return 1; -#else return tls->is_server; -#endif } +#endif struct st_ptls_raw_message_emitter_t { ptls_message_emitter_t super; From 8ae28e6686865ccb5d109a8f1ebe737793fe06e8 Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Mon, 6 Feb 2023 18:01:32 +0200 Subject: [PATCH 4/9] Merge --- include/picotls.h | 26 +++++++++++-- include/picotls/openssl.h | 23 ++++++----- lib/fusion.c | 7 +++- lib/openssl.c | 82 +++++++++++++++++++++------------------ lib/picotls.c | 51 +++++++++++++++--------- t/openssl.c | 12 +++--- t/picotls.c | 8 ++-- 7 files changed, 129 insertions(+), 80 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index f0d97f634..e7d449978 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -141,7 +141,7 @@ extern void ptls_cleanup_free(void *p); /* negotiated_groups */ #define PTLS_GROUP_SECP256R1 23 -#define PTLS_GROUP_NAME_SECP256R1 "scep256r1" +#define PTLS_GROUP_NAME_SECP256R1 "secp256r1" #define PTLS_GROUP_SECP384R1 24 #define PTLS_GROUP_NAME_SECP384R1 "secp384r1" #define PTLS_GROUP_SECP521R1 25 @@ -656,10 +656,23 @@ PTLS_CALLBACK_TYPE(int, on_client_hello, ptls_t *tls, ptls_on_client_hello_param PTLS_CALLBACK_TYPE(int, emit_certificate, ptls_t *tls, ptls_message_emitter_t *emitter, ptls_key_schedule_t *key_sched, ptls_iovec_t context, int push_status_request, const uint16_t *compress_algos, size_t num_compress_algos); /** - * context object of an async operation (e.g., RSA signature generation) + * An object that represents an asynchronous task (e.g., RSA signature generation). + * When `ptls_handshake` returns `PTLS_ERROR_ASYNC_OPERATION`, it has an associated task in flight. The user should obtain the + * reference to the associated task by calling `ptls_get_async_job`, then either wait for the file descriptor obtained from + * the `get_fd` callback to become readable, or set a completion callback via `set_completion_callback` and wait for its + * invocation. Once notified, the user should invoke `ptls_handshake` again. + * Async jobs typically provide support for only one of the two methods. */ typedef struct st_ptls_async_job_t { void (*destroy_)(struct st_ptls_async_job_t *self); + /** + * optional callback returning a file descriptor that becomes readable when the job is complete + */ + int (*get_fd)(struct st_ptls_async_job_t *self); + /** + * optional callback for setting a completion callback + */ + void (*set_completion_callback)(struct st_ptls_async_job_t *self, void (*cb)(void *), void *cbdata); } ptls_async_job_t; /** * When gerenating CertificateVerify, the core calls the callback to sign the handshake context using the certificate. This callback @@ -1227,6 +1240,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); ptls_decode_assert_block_close((src), end); \ } while (0) +#if PTLS_HAVE_LOG #define PTLS_LOG__DO_LOG(module, type, block) \ do { \ int ptlslog_skip = 0; \ @@ -1353,6 +1367,10 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); } \ } \ } while (0) +#else +#define PTLS_LOG_CONN(...) +#define PTLS_LOG__DO_LOG(...) +#endif /** * User API is exposed only when logging is supported by the platform. @@ -1488,7 +1506,7 @@ int ptls_is_psk_handshake(ptls_t *tls); /** * return if a ECH handshake was performed, as well as optionally the kem and cipher-suite being used */ -int ptls_is_ech_handshake(ptls_t *tls, ptls_hpke_kem_t **kem, ptls_hpke_cipher_suite_t **cipher); +int ptls_is_ech_handshake(ptls_t *tls, uint8_t *config_id, ptls_hpke_kem_t **kem, ptls_hpke_cipher_suite_t **cipher); /** * returns a pointer to user data pointer (client is reponsible for freeing the associated data prior to calling ptls_free) */ @@ -1648,7 +1666,7 @@ static size_t ptls_aead_encrypt_final(ptls_aead_context_t *ctx, void *output); static size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad, size_t aadlen); /** - * Return the current read epoch. + * Return the current read epoch (i.e., that of the message being received or to be) */ size_t ptls_get_read_epoch(ptls_t *tls); /** diff --git a/include/picotls/openssl.h b/include/picotls/openssl.h index 3a7c3b532..a892f9b86 100644 --- a/include/picotls/openssl.h +++ b/include/picotls/openssl.h @@ -125,22 +125,25 @@ void ptls_openssl_random_bytes(void *buf, size_t len); */ int ptls_openssl_create_key_exchange(ptls_key_exchange_context_t **ctx, EVP_PKEY *pkey); -#if PTLS_OPENSSL_HAVE_ASYNC -/** - * Returns the file descriptor of the asynchronous operation in flight. - */ -OSSL_ASYNC_FD ptls_openssl_get_async_fd(ptls_t *ptls); -#endif - -struct st_ptls_openssl_signature_scheme_t { +typedef struct st_ptls_openssl_signature_scheme_t { uint16_t scheme_id; const EVP_MD *(*scheme_md)(void); -}; +} ptls_openssl_signature_scheme_t; + +/** + * Given a private key, returns a list of compatible signature schemes. This list is terminated by scheme_id of UINT16_MAX. + */ +const ptls_openssl_signature_scheme_t *ptls_openssl_lookup_signature_schemes(EVP_PKEY *key); +/** + * Given available schemes and input, choses one, or returns NULL if none is available. + */ +const ptls_openssl_signature_scheme_t *ptls_openssl_select_signature_scheme(const ptls_openssl_signature_scheme_t *available, + const uint16_t *algorithms, size_t num_algorithms); typedef struct st_ptls_openssl_sign_certificate_t { ptls_sign_certificate_t super; EVP_PKEY *key; - const struct st_ptls_openssl_signature_scheme_t *schemes; /* terminated by .scheme_id == UINT16_MAX */ + const ptls_openssl_signature_scheme_t *schemes; /* terminated by .scheme_id == UINT16_MAX */ /** * When set to true, indicates to the backend that the signature can be generated asynchronously. When the backend decides to * generate the signature asynchronously, `ptls_handshake` will return PTLS_ERROR_ASYNC_OPERATION. When receiving that error diff --git a/lib/fusion.c b/lib/fusion.c index efd853f9d..b9f99daca 100644 --- a/lib/fusion.c +++ b/lib/fusion.c @@ -61,6 +61,9 @@ #ifdef _WINDOWS #define aligned_alloc(a, s) _aligned_malloc((s), (a)) +#define aligned_free(p) _aligned_free(p) +#else +#define aligned_free(p) free(p) #endif struct ptls_fusion_aesgcm_context { @@ -1026,7 +1029,7 @@ ptls_fusion_aesgcm_context_t *ptls_fusion_aesgcm_set_capacity(ptls_fusion_aesgcm return NULL; memcpy(newp, ctx, old_ctx_size); ptls_clear_memory(ctx, old_ctx_size); - free(ctx); + aligned_free(ctx); ctx = newp; ctx->capacity = capacity; @@ -1041,7 +1044,7 @@ void ptls_fusion_aesgcm_free(ptls_fusion_aesgcm_context_t *ctx) ptls_clear_memory(ctx, calc_aesgcm_context_size(&ctx->ghash_cnt, ctx->ecb.aesni256)); /* skip ptls_fusion_aesecb_dispose, based on the knowledge that it does not allocate memory elsewhere */ - free(ctx); + aligned_free(ctx); } static void ctr_dispose(ptls_cipher_context_t *_ctx) diff --git a/lib/openssl.c b/lib/openssl.c index 511315eff..71b33aeff 100644 --- a/lib/openssl.c +++ b/lib/openssl.c @@ -89,22 +89,22 @@ static int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) #endif -static const struct st_ptls_openssl_signature_scheme_t rsa_signature_schemes[] = {{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, EVP_sha256}, +static const ptls_openssl_signature_scheme_t rsa_signature_schemes[] = {{PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, EVP_sha256}, {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, EVP_sha384}, {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, EVP_sha512}, {UINT16_MAX, NULL}}; -static const struct st_ptls_openssl_signature_scheme_t secp256r1_signature_schemes[] = { +static const ptls_openssl_signature_scheme_t secp256r1_signature_schemes[] = { {PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, EVP_sha256}, {UINT16_MAX, NULL}}; #if PTLS_OPENSSL_HAVE_SECP384R1 -static const struct st_ptls_openssl_signature_scheme_t secp384r1_signature_schemes[] = { +static const ptls_openssl_signature_scheme_t secp384r1_signature_schemes[] = { {PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, EVP_sha384}, {UINT16_MAX, NULL}}; #endif #if PTLS_OPENSSL_HAVE_SECP521R1 -static const struct st_ptls_openssl_signature_scheme_t secp521r1_signature_schemes[] = { +static const ptls_openssl_signature_scheme_t secp521r1_signature_schemes[] = { {PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, EVP_sha512}, {UINT16_MAX, NULL}}; #endif #if PTLS_OPENSSL_HAVE_ED25519 -static const struct st_ptls_openssl_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, NULL}, +static const ptls_openssl_signature_scheme_t ed25519_signature_schemes[] = {{PTLS_SIGNATURE_ED25519, NULL}, {UINT16_MAX, NULL}}; #endif @@ -127,9 +127,9 @@ static const uint16_t default_signature_schemes[] = { PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, UINT16_MAX}; -static const struct st_ptls_openssl_signature_scheme_t *lookup_signature_schemes(EVP_PKEY *key) +const ptls_openssl_signature_scheme_t *ptls_openssl_lookup_signature_schemes(EVP_PKEY *key) { - const struct st_ptls_openssl_signature_scheme_t *schemes = NULL; + const ptls_openssl_signature_scheme_t *schemes = NULL; switch (EVP_PKEY_id(key)) { case EVP_PKEY_RSA: @@ -168,6 +168,20 @@ static const struct st_ptls_openssl_signature_scheme_t *lookup_signature_schemes return schemes; } +const ptls_openssl_signature_scheme_t *ptls_openssl_select_signature_scheme(const ptls_openssl_signature_scheme_t *available, + const uint16_t *algorithms, size_t num_algorithms) +{ + const ptls_openssl_signature_scheme_t *scheme; + + /* select the algorithm, driven by server-isde preference of `available` */ + for (scheme = available; scheme->scheme_id != UINT16_MAX; ++scheme) + for (size_t i = 0; i != num_algorithms; ++i) + if (algorithms[i] == scheme->scheme_id) + return scheme; + + return NULL; +} + void ptls_openssl_random_bytes(void *buf, size_t len) { int ret = RAND_bytes(buf, (int)len); @@ -698,7 +712,7 @@ int ptls_openssl_create_key_exchange(ptls_key_exchange_context_t **ctx, EVP_PKEY struct async_sign_ctx { ptls_async_job_t super; - const struct st_ptls_openssl_signature_scheme_t *scheme; + const ptls_openssl_signature_scheme_t *scheme; EVP_MD_CTX *ctx; ASYNC_WAIT_CTX *waitctx; ASYNC_JOB *job; @@ -724,14 +738,26 @@ static void async_sign_ctx_free(ptls_async_job_t *_self) free(self); } -static ptls_async_job_t *async_sign_ctx_new(const struct st_ptls_openssl_signature_scheme_t *scheme, EVP_MD_CTX *ctx, size_t siglen) +int async_sign_ctx_get_fd(ptls_async_job_t *_self) +{ + struct async_sign_ctx *self = (void *)_self; + OSSL_ASYNC_FD fds[1]; + size_t numfds; + + ASYNC_WAIT_CTX_get_all_fds(self->waitctx, NULL, &numfds); + assert(numfds == 1); + ASYNC_WAIT_CTX_get_all_fds(self->waitctx, fds, &numfds); + return (int)fds[0]; +} + +static ptls_async_job_t *async_sign_ctx_new(const ptls_openssl_signature_scheme_t *scheme, EVP_MD_CTX *ctx, size_t siglen) { struct async_sign_ctx *self; if ((self = malloc(offsetof(struct async_sign_ctx, sig) + siglen)) == NULL) return NULL; - self->super = (ptls_async_job_t){async_sign_ctx_free}; + self->super = (ptls_async_job_t){async_sign_ctx_free, async_sign_ctx_get_fd}; self->scheme = scheme; self->ctx = ctx; self->waitctx = ASYNC_WAIT_CTX_new(); @@ -742,18 +768,6 @@ static ptls_async_job_t *async_sign_ctx_new(const struct st_ptls_openssl_signatu return &self->super; } -OSSL_ASYNC_FD ptls_openssl_get_async_fd(ptls_t *ptls) -{ - OSSL_ASYNC_FD fds[1]; - size_t numfds; - struct async_sign_ctx *async = (void *)ptls_get_async_job(ptls); - assert(async != NULL); - ASYNC_WAIT_CTX_get_all_fds(async->waitctx, NULL, &numfds); - assert(numfds == 1); - ASYNC_WAIT_CTX_get_all_fds(async->waitctx, fds, &numfds); - return fds[0]; -} - static int do_sign_async_job(void *_async) { struct async_sign_ctx *async = *(struct async_sign_ctx **)_async; @@ -792,7 +806,7 @@ static int do_sign_async(ptls_buffer_t *outbuf, ptls_async_job_t **_async) #endif -static int do_sign(EVP_PKEY *key, const struct st_ptls_openssl_signature_scheme_t *scheme, ptls_buffer_t *outbuf, +static int do_sign(EVP_PKEY *key, const ptls_openssl_signature_scheme_t *scheme, ptls_buffer_t *outbuf, ptls_iovec_t input, ptls_async_job_t **async) { EVP_MD_CTX *ctx = NULL; @@ -1161,7 +1175,7 @@ static int sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_as ptls_buffer_t *outbuf, ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms) { ptls_openssl_sign_certificate_t *self = (ptls_openssl_sign_certificate_t *)_self; - const struct st_ptls_openssl_signature_scheme_t *scheme; + const ptls_openssl_signature_scheme_t *scheme; /* Just resume the asynchronous operation, if one is in flight. */ #if PTLS_OPENSSL_HAVE_ASYNC @@ -1172,17 +1186,11 @@ static int sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, ptls_as } #endif - /* Select the algorithm (driven by server-side preference of `self->schemes`), or return failure if none found. */ - for (scheme = self->schemes; scheme->scheme_id != UINT16_MAX; ++scheme) { - size_t i; - for (i = 0; i != num_algorithms; ++i) - if (algorithms[i] == scheme->scheme_id) - goto Found; - } - return PTLS_ALERT_HANDSHAKE_FAILURE; - -Found: + /* Select the algorithm or return failure if none found. */ + if ((scheme = ptls_openssl_select_signature_scheme(self->schemes, algorithms, num_algorithms)) == NULL) + return PTLS_ALERT_HANDSHAKE_FAILURE; *selected_algorithm = scheme->scheme_id; + #if PTLS_OPENSSL_HAVE_ASYNC if (!self->async && async != NULL) { /* indicate to `do_sign` that async mode is disabled for this operation */ @@ -1202,7 +1210,7 @@ static X509 *to_x509(ptls_iovec_t vec) static int verify_sign(void *verify_ctx, uint16_t algo, ptls_iovec_t data, ptls_iovec_t signature) { EVP_PKEY *key = verify_ctx; - const struct st_ptls_openssl_signature_scheme_t *scheme; + const ptls_openssl_signature_scheme_t *scheme; EVP_MD_CTX *ctx = NULL; EVP_PKEY_CTX *pkey_ctx = NULL; int ret = 0; @@ -1210,7 +1218,7 @@ static int verify_sign(void *verify_ctx, uint16_t algo, ptls_iovec_t data, ptls_ if (data.base == NULL) goto Exit; - if ((scheme = lookup_signature_schemes(key)) == NULL) { + if ((scheme = ptls_openssl_lookup_signature_schemes(key)) == NULL) { ret = PTLS_ERROR_LIBRARY; goto Exit; } @@ -1282,7 +1290,7 @@ int ptls_openssl_init_sign_certificate(ptls_openssl_sign_certificate_t *self, EV { *self = (ptls_openssl_sign_certificate_t){.super = {sign_certificate}, .async = 0 /* libssl has it off by default too */}; - if ((self->schemes = lookup_signature_schemes(key)) == NULL) + if ((self->schemes = ptls_openssl_lookup_signature_schemes(key)) == NULL) return PTLS_ERROR_INCOMPATIBLE_KEY; EVP_PKEY_up_ref(key); self->key = key; diff --git a/lib/picotls.c b/lib/picotls.c index 4ab218110..419e4940f 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -95,7 +95,12 @@ static const char ech_info_prefix[8] = "tls ech"; #define PTLS_MAX_EARLY_DATA_SKIP_SIZE 65536 #endif #if defined(PTLS_DEBUG) && PTLS_DEBUG +#ifdef PARTICLE +#include +#define PTLS_DEBUGF(...) LOG_PRINTF(INFO, __VA_ARGS__) +#else #define PTLS_DEBUGF(...) fprintf(stderr, __VA_ARGS__) +#endif #else #define PTLS_DEBUGF(...) #endif @@ -1655,6 +1660,9 @@ static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_ ctx->epoch = epoch; + log_secret(tls, log_labels[ptls_is_server(tls) == is_enc][epoch], + ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size)); + /* special path for applications having their own record layer */ if (tls->ctx->update_traffic_key != NULL) { if (skip_notify) @@ -1669,8 +1677,6 @@ static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_ return PTLS_ERROR_NO_MEMORY; /* TODO obtain error from ptls_aead_new */ ctx->seq = 0; - log_secret(tls, log_labels[ptls_is_server(tls) == is_enc][epoch], - ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size)); PTLS_DEBUGF("[%s] %02x%02x,%02x%02x\n", log_labels[ptls_is_server(tls)][epoch], (unsigned)ctx->secret[0], (unsigned)ctx->secret[1], (unsigned)ctx->aead->static_iv[0], (unsigned)ctx->aead->static_iv[1]); @@ -2509,7 +2515,7 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ Exit: ptls_buffer_dispose(&encoded_ch_inner); - ptls_clear_memory(binder_key, sizeof(binder_key)); + ptls_clear_memory(binder_key, PTLS_MAX_DIGEST_SIZE); return ret; } @@ -2930,7 +2936,7 @@ static int client_handle_encrypted_extensions(ptls_t *tls, ptls_iovec_t message, break; case PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO: { /* accept retry_configs only if we offered ECH but rejected */ - if (!((tls->ech.offered || tls->ech.offered_grease) && !ptls_is_ech_handshake(tls, NULL, NULL))) { + if (!((tls->ech.offered || tls->ech.offered_grease) && !ptls_is_ech_handshake(tls, NULL, NULL, NULL))) { ret = PTLS_ALERT_UNSUPPORTED_EXTENSION; goto Exit; } @@ -3237,7 +3243,7 @@ static int handle_certificate(ptls_t *tls, const uint8_t *src, const uint8_t *en if (tls->ctx->verify_certificate != NULL) { const char *server_name = NULL; if (!ptls_is_server(tls)) { - if (tls->ech.offered && !ptls_is_ech_handshake(tls, NULL, NULL)) { + if (tls->ech.offered && !ptls_is_ech_handshake(tls, NULL, NULL, NULL)) { server_name = tls->ech.client.public_name; } else { server_name = tls->server_name; @@ -3408,7 +3414,7 @@ static int server_handle_certificate_verify(ptls_t *tls, ptls_iovec_t message) static int client_handle_finished(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_iovec_t message) { uint8_t send_secret[PTLS_MAX_DIGEST_SIZE]; - int alert_ech_required = tls->ech.offered && !ptls_is_ech_handshake(tls, NULL, NULL), ret; + int alert_ech_required = tls->ech.offered && !ptls_is_ech_handshake(tls, NULL, NULL, NULL), ret; if ((ret = verify_finished(tls, message)) != 0) goto Exit; @@ -4475,7 +4481,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl /* Either send a stateless retry (w. cookies) or a stateful one. When sending the latter, run the state machine. At the * moment, stateless retry is disabled when ECH is used (do we need to support it?). */ int retry_uses_cookie = - properties != NULL && properties->server.retry_uses_cookie && !ptls_is_ech_handshake(tls, NULL, NULL); + properties != NULL && properties->server.retry_uses_cookie && !ptls_is_ech_handshake(tls, NULL, NULL, NULL); if (!retry_uses_cookie) { key_schedule_transform_post_ch1hash(tls->key_schedule); key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0)); @@ -4485,7 +4491,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl tls->key_schedule, key_share.algorithm != NULL ? NULL : negotiated_group, { ptls_buffer_t *sendbuf = emitter->buf; - if (ptls_is_ech_handshake(tls, NULL, NULL)) { + if (ptls_is_ech_handshake(tls, NULL, NULL, NULL)) { buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO, { if ((ret = ptls_buffer_reserve(sendbuf, PTLS_ECH_CONFIRM_LENGTH)) != 0) goto Exit; @@ -4625,7 +4631,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl { tls->ctx->random_bytes(emitter->buf->base + emitter->buf->off, PTLS_HELLO_RANDOM_SIZE); /* when accepting CHInner, last 8 byte of SH.random is zero for the handshake transcript */ - if (ptls_is_ech_handshake(tls, NULL, NULL)) { + if (ptls_is_ech_handshake(tls, NULL, NULL, NULL)) { ech_confirm_off = emitter->buf->off + PTLS_HELLO_RANDOM_SIZE - PTLS_ECH_CONFIRM_LENGTH; memset(emitter->buf->base + ech_confirm_off, 0, PTLS_ECH_CONFIRM_LENGTH); } @@ -4702,7 +4708,7 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl if (tls->pending_handshake_secret != NULL) buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_EARLY_DATA, {}); /* send ECH retry_configs, if ECH was offered by rejected, even though we (the server) could have accepted ECH */ - if (tls->ech.offered && !ptls_is_ech_handshake(tls, NULL, NULL) && tls->ctx->ech.server.create_opener != NULL && + if (tls->ech.offered && !ptls_is_ech_handshake(tls, NULL, NULL, NULL) && tls->ctx->ech.server.create_opener != NULL && tls->ctx->ech.server.retry_configs.len != 0) buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO, { ptls_buffer_pushv(sendbuf, tls->ctx->ech.server.retry_configs.base, tls->ctx->ech.server.retry_configs.len); @@ -5354,9 +5360,11 @@ int ptls_is_psk_handshake(ptls_t *tls) return tls->is_psk_handshake; } -int ptls_is_ech_handshake(ptls_t *tls, ptls_hpke_kem_t **kem, ptls_hpke_cipher_suite_t **cipher) +int ptls_is_ech_handshake(ptls_t *tls, uint8_t *config_id, ptls_hpke_kem_t **kem, ptls_hpke_cipher_suite_t **cipher) { if (tls->ech.accepted) { + if (config_id != NULL) + *config_id = tls->ech.config_id; if (kem != NULL) *kem = tls->ech.kem; if (cipher != NULL) @@ -5998,8 +6006,8 @@ int ptls_export_secret(ptls_t *tls, void *output, size_t outlen, const char *lab ptls_iovec_init(context_value_hash, algo->digest_size), NULL); Exit: - ptls_clear_memory(derived_secret, sizeof(derived_secret)); - ptls_clear_memory(context_value_hash, sizeof(context_value_hash)); + ptls_clear_memory(derived_secret, PTLS_MAX_DIGEST_SIZE); + ptls_clear_memory(context_value_hash, PTLS_MAX_DIGEST_SIZE); return ret; } @@ -6382,6 +6390,7 @@ size_t ptls_get_read_epoch(ptls_t *tls) case PTLS_STATE_CLIENT_EXPECT_CERTIFICATE: case PTLS_STATE_CLIENT_EXPECT_CERTIFICATE_VERIFY: case PTLS_STATE_CLIENT_EXPECT_FINISHED: + case PTLS_STATE_SERVER_GENERATING_CERTIFICATE_VERIFY: case PTLS_STATE_SERVER_EXPECT_CERTIFICATE: case PTLS_STATE_SERVER_EXPECT_CERTIFICATE_VERIFY: case PTLS_STATE_SERVER_EXPECT_FINISHED: @@ -6430,12 +6439,11 @@ int ptls_server_handle_message(ptls_t *tls, ptls_buffer_t *sendbuf, size_t epoch struct st_ptls_record_t rec = {PTLS_CONTENT_TYPE_HANDSHAKE, 0, inlen, input}; if (tls->state == PTLS_STATE_SERVER_GENERATING_CERTIFICATE_VERIFY) { - int ret; - if ((ret = server_finish_handshake(tls, &emitter.super, 1, NULL)) != 0) - return ret; + assert(input == NULL || inlen == 0); + return server_finish_handshake(tls, &emitter.super, 1, NULL); } - assert(input); + assert(input != NULL); if (ptls_get_read_epoch(tls) != in_epoch) return PTLS_ALERT_UNEXPECTED_MESSAGE; @@ -6495,12 +6503,13 @@ static char *byte_to_hex(char *dst, uint8_t v) char *ptls_hexdump(char *dst, const void *_src, size_t len) { + char *buf = dst; const uint8_t *src = _src; for (size_t i = 0; i != len; ++i) dst = byte_to_hex(dst, src[i]); *dst = '\0'; - return dst; + return buf; } char *ptls_jsonescape(char *buf, const char *unsafe_str, size_t len) @@ -6607,6 +6616,7 @@ int ptls_log__do_push_unsigned64(ptls_buffer_t *buf, uint64_t v) volatile ptls_log_t ptls_log = {}; +#ifndef PARTICLE static struct { int *fds; size_t num_fds; @@ -6641,11 +6651,13 @@ int ptls_log_add_fd(int fd) return ret; } +#endif #endif void ptls_log__do_write(const ptls_buffer_t *buf) { #if PTLS_HAVE_LOG +#ifndef PARTICLE pthread_mutex_lock(&logctx.mutex); for (size_t fd_index = 0; fd_index < logctx.num_fds;) { @@ -6670,5 +6682,8 @@ void ptls_log__do_write(const ptls_buffer_t *buf) } pthread_mutex_unlock(&logctx.mutex); +#else + LOG_WRITE(INFO, buf->base, buf->off); +#endif #endif } diff --git a/t/openssl.c b/t/openssl.c index b4c73b09b..4ca49aa38 100644 --- a/t/openssl.c +++ b/t/openssl.c @@ -143,7 +143,7 @@ static void test_key_exchanges(void) #endif } -static void test_sign_verify(EVP_PKEY *key, const struct st_ptls_openssl_signature_scheme_t *schemes) +static void test_sign_verify(EVP_PKEY *key, const ptls_openssl_signature_scheme_t *schemes) { for (size_t i = 0; schemes[i].scheme_id != UINT16_MAX; ++i) { note("scheme 0x%04x", schemes[i].scheme_id); @@ -198,7 +198,7 @@ static void test_rsa_sign(void) test_sign_verify(sc->key, sc->schemes); } -static void do_test_ecdsa_sign(int nid, const struct st_ptls_openssl_signature_scheme_t *schemes) +static void do_test_ecdsa_sign(int nid, const ptls_openssl_signature_scheme_t *schemes) { EVP_PKEY *pkey; @@ -464,10 +464,12 @@ static void many_handshakes(void) if (num_issued < num_total) qat_set_pending(offending); break; - case PTLS_ERROR_ASYNC_OPERATION: - qat.conns[offending].wait_fd = ptls_openssl_get_async_fd(qat.conns[offending].tls); + case PTLS_ERROR_ASYNC_OPERATION: { + ptls_async_job_t *job = ptls_get_async_job(qat.conns[offending].tls); + assert(job->get_fd != NULL); + qat.conns[offending].wait_fd = job->get_fd(job); assert(qat.conns[offending].wait_fd != -1); - break; + } break; default: fprintf(stderr, "ptls_handshake returned %d\n", hsret); abort(); diff --git a/t/picotls.c b/t/picotls.c index bc68ab934..14fa849dc 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -1002,11 +1002,11 @@ static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int } if (can_ech(ctx_peer, 1) && can_ech(ctx, 0)) { - ok(ptls_is_ech_handshake(client, NULL, NULL)); - ok(ptls_is_ech_handshake(server, NULL, NULL)); + ok(ptls_is_ech_handshake(client, NULL, NULL, NULL)); + ok(ptls_is_ech_handshake(server, NULL, NULL, NULL)); } else { - ok(!ptls_is_ech_handshake(client, NULL, NULL)); - ok(!ptls_is_ech_handshake(server, NULL, NULL)); + ok(!ptls_is_ech_handshake(client, NULL, NULL, NULL)); + ok(!ptls_is_ech_handshake(server, NULL, NULL, NULL)); } ptls_buffer_dispose(&cbuf); From 31e939fe20280ae2aa46e29f29c2c9995e0c0ff2 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 9 Feb 2023 12:22:33 +0900 Subject: [PATCH 5/9] temporary revert local changes --- deps/micro-ecc/uECC.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/micro-ecc/uECC.c b/deps/micro-ecc/uECC.c index 461f7133c..daa144a50 100644 --- a/deps/micro-ecc/uECC.c +++ b/deps/micro-ecc/uECC.c @@ -307,7 +307,7 @@ uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, uECC_word_t tmp[uECC_MAX_WORDS]; uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); uECC_word_t equal = uECC_vli_isZero(tmp, num_words); - return (cmpresult_t)(!equal - 2 * neg); + return (!equal - 2 * neg); } /* Computes vli = vli >> 1. */ @@ -957,7 +957,7 @@ uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, wordcount_t i; for (i = 0; i < num_bytes; ++i) { unsigned b = num_bytes - 1 - i; - bytes[i] = (uint8_t)(native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE))); + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); } } From daf5f6b9e8b906957394e58babe5ac4aa9c63b27 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 9 Feb 2023 12:23:02 +0900 Subject: [PATCH 6/9] extract https://github.com/kmackay/micro-ecc @ b335ee8 () at deps/micro-ecc --- deps/micro-ecc/README.md | 4 +- deps/micro-ecc/asm_arm.inc | 4 +- deps/micro-ecc/asm_avr.inc | 212 +++++------ deps/micro-ecc/emk_project.py | 31 +- .../{test => examples}/ecc_test/ecc_test.ino | 5 - deps/micro-ecc/library.properties | 9 + deps/micro-ecc/platform-specific.inc | 27 ++ deps/micro-ecc/test/ecdsa_test_vectors.c | 128 +++++++ deps/micro-ecc/test/public_key_test_vectors.c | 338 ++++++++++++++++++ deps/micro-ecc/uECC.c | 243 +++++++------ deps/micro-ecc/uECC.h | 17 +- 11 files changed, 780 insertions(+), 238 deletions(-) rename deps/micro-ecc/{test => examples}/ecc_test/ecc_test.ino (98%) create mode 100644 deps/micro-ecc/library.properties create mode 100644 deps/micro-ecc/test/ecdsa_test_vectors.c create mode 100644 deps/micro-ecc/test/public_key_test_vectors.c diff --git a/deps/micro-ecc/README.md b/deps/micro-ecc/README.md index 01926e3fa..111321bf7 100644 --- a/deps/micro-ecc/README.md +++ b/deps/micro-ecc/README.md @@ -19,7 +19,7 @@ Features Usage Notes ----------- ### Point Representation ### -Compressed points are represented in the standard format as defined in http://www.secg.org/collateral/sec1_final.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_compress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations. +Compressed points are represented in the standard format as defined in http://www.secg.org/sec1-v2.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_decompress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations. Private keys are represented in the standard format. @@ -27,7 +27,7 @@ Private keys are represented in the standard format. I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions. -For use with Arduino, you can just create a symlink to the `uECC` directory in your Arduino `libraries` directory. You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu). +For use with Arduino, you can use the Library Manager to download micro-ecc (**Sketch**=>**Include Library**=>**Manage Libraries**). You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu). See uECC.h for documentation for each function. diff --git a/deps/micro-ecc/asm_arm.inc b/deps/micro-ecc/asm_arm.inc index 688fdc75a..e3c8cb15e 100644 --- a/deps/micro-ecc/asm_arm.inc +++ b/deps/micro-ecc/asm_arm.inc @@ -620,7 +620,7 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, "str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */ "pop {%[r0]} \n\t" /* pop result off the stack */ - ".syntax divided \n\t" + RESUME_SYNTAX : [r3] "+l" (num_words), [r4] "=&l" (r4), [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) : [r0] "l" (result), [r1] "l" (left), [r2] "l" (right) @@ -805,7 +805,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */ "pop {%[r0]} \n\t" /* pop result off the stack */ - ".syntax divided \n\t" + RESUME_SYNTAX : [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4), [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) : [r0] "l" (result), [r1] "l" (left) diff --git a/deps/micro-ecc/asm_avr.inc b/deps/micro-ecc/asm_avr.inc index c98804032..c14bf5554 100644 --- a/deps/micro-ecc/asm_avr.inc +++ b/deps/micro-ecc/asm_avr.inc @@ -37,12 +37,12 @@ uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { "sbc r31, __zero_reg__ \n\t" IJMP #endif - + REPEAT(uECC_MAX_WORDS, "st x+, __zero_reg__ \n\t") "1: \n\t" : "+x" (v) : [num] "r" (num_words) - : + : #if (uECC_MAX_WORDS != uECC_MIN_WORDS) "r30", "r31", "cc" #endif @@ -60,16 +60,16 @@ uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordco "sbc r31, __zero_reg__ \n\t" IJMP #endif - + REPEAT(uECC_MAX_WORDS, "ld r0, y+ \n\t" "st x+, r0 \n\t") "1: \n\t" : "+x" (d), "+y" (src) : [num] "r" ((uint8_t)(num_words * 2)) - : "r0", + : "r0" #if (uECC_MAX_WORDS != uECC_MIN_WORDS) - "r30", "r31", "cc" + , "r30", "r31", "cc" #endif ); } @@ -84,7 +84,7 @@ uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { "sub r30, %[jump] \n\t" "sbc r31, __zero_reg__ \n\t" #endif - + "add r26, %[num] \n\t" "adc r27, __zero_reg__ \n\t" "ld r0, -x \n\t" @@ -93,7 +93,7 @@ uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { #if (uECC_MAX_WORDS != uECC_MIN_WORDS) IJMP #endif - + REPEAT(DEC(uECC_MAX_WORDS), "ld r0, -x \n\t" "ror r0 \n\t" @@ -137,15 +137,15 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, "sub r30, %[num] \n\t" "sbc r31, __zero_reg__ \n\t" #endif - + "clc \n\t" #if (uECC_MAX_WORDS != uECC_MIN_WORDS) IJMP REPEATM(uECC_MAX_WORDS, ADD_RJPM_TABLE) #endif - + REPEATM(uECC_MAX_WORDS, ADD_RJPM_DEST) - + "mov %[clb], __zero_reg__ \n\t" "adc %[clb], %[clb] \n\t" /* Store carry bit. */ @@ -184,15 +184,15 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, "sub r30, %[num] \n\t" "sbc r31, __zero_reg__ \n\t" #endif - + "clc \n\t" #if (uECC_MAX_WORDS != uECC_MIN_WORDS) IJMP REPEATM(uECC_MAX_WORDS, SUB_RJPM_TABLE) #endif - + REPEATM(uECC_MAX_WORDS, SUB_RJPM_DEST) - + "mov %[clb], __zero_reg__ \n\t" "adc %[clb], %[clb] \n\t" /* Store carry bit. */ @@ -216,7 +216,7 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, wordcount_t num_words) { /* num_words should already be in r18. */ register wordcount_t r18 __asm__("r18") = num_words; - + __asm__ volatile ( "push r18 \n\t" #if (uECC_MIN_WORDS == 20) @@ -268,7 +268,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, wordcount_t num_words) { /* num_words should already be in r20. */ register wordcount_t r20 __asm__("r20") = num_words; - + __asm__ volatile ( "push r20 \n\t" #if (uECC_MIN_WORDS == 20) @@ -329,7 +329,7 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + "adiw r30, 25 \n\t" /* we are shifting by 31 bits, so shift over 4 bytes (+ 1 since z initially points below the stack) */ "adiw r26, 40 \n\t" /* end of product */ @@ -384,10 +384,10 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "ld r18, z \n\t" "adc r18, r1 \n\t" "st z+, r18 \n\t" - + "sbiw r30, 24 \n\t" /* move z back to point at tmp */ "sbiw r26, 40 \n\t" /* move x back to point at product */ - + /* add low bytes of tmp to product, storing in result */ "ld r18, z+ \n\t" "ld r19, x+ \n\t" @@ -403,13 +403,13 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { z is 20 bytes into tmp */ "sbiw r28, 20 \n\t" /* move y back to point at result */ "adiw r30, 4 \n\t" /* move z to point to the end of tmp */ - + /* do omega_mult again with the 4 relevant bytes */ /* z points to the end of tmp, x points to the end of product */ "ld r18, -z \n\t" /* Load word. */ "lsr r18 \n\t" /* Shift. */ "st -x, r18 \n\t" /* Store the first result word. */ - + "ld r18, -z \n\t" "ror r18 \n\t" "st -x, r18 \n\t" @@ -419,11 +419,11 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "ld r18, -z \n\t" "ror r18 \n\t" "st -x, r18 \n\t" - + "eor r18, r18 \n\t" /* r18 = 0 */ "ror r18 \n\t" /* get last bit */ "st -x, r18 \n\t" /* store it */ - + "sbiw r26, 3 \n\t" /* move x back to point at beginning */ /* now we add a copy of the 4 bytes */ "ld r18, z+ \n\t" @@ -432,29 +432,29 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "st x+, r18 \n\t" "ld r18, z+ \n\t" "st x+, r18 \n\t" - + "ld r18, z+ \n\t" "ld r19, x \n\t" "add r18, r19 \n\t" "st x+, r18 \n\t" - + /* Propagate over the remaining bytes */ "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + /* now z points to the end of tmp, x points to the end of product (y still points at result) */ "sbiw r26, 8 \n\t" /* move x back to point at beginning of actual data */ @@ -468,23 +468,23 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "ld r19, y \n\t" "adc r18, r19 \n\t" "st y+, r18 \n\t") - + /* Done adding, now propagate carry bit */ REPEAT(12, "ld r18, y \n\t" "adc r18, __zero_reg__ \n\t" "st y+, r18 \n\t") - + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ "sbiw r28, 20 \n\t" /* move y back to point at result */ - + "sbiw r30, 1 \n\t" /* fix stack pointer */ "in r0, __SREG__ \n\t" "cli \n\t" "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + : "+x" (product), [carry] "+r" (carry) : "y" (result) : "r0", "r18", "r19", "r30", "r31", "cc" @@ -517,7 +517,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + "adiw r30, 1 \n\t" /* add 1 since z initially points below the stack */ "adiw r26, 32 \n\t" /* product + uECC_WORDS */ "ldi r25, 0x03 \n\t" @@ -526,12 +526,12 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, x+ \n\t" "ld r20, x+ \n\t" "ld r21, x+ \n\t" - + "mul r24, r18 \n\t" "st z+, r0 \n\t" "mov r22, r1 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r19 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" /* can't overflow */ @@ -540,7 +540,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" /* can't overflow */ "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + "mul r24, r20 \n\t" "add r23, r0 \n\t" "adc r22, r1 \n\t" @@ -549,7 +549,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r21 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" @@ -558,7 +558,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + /* now we start adding the 2^32 part as well */ "add r23, r18 \n\t" // 28 "adc r22, r22 \n\t" @@ -571,7 +571,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r19 \n\t" // 27 "adc r23, r23 \n\t" "ld r19, x+ \n\t" @@ -583,7 +583,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + REPEAT(6, // 26 - 3 "add r23, r20 \n\t" "adc r22, r22 \n\t" @@ -596,7 +596,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" "adc r23, r23 \n\t" "ld r21, x+ \n\t" @@ -608,7 +608,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r18 \n\t" "adc r22, r22 \n\t" "ld r18, x+ \n\t" @@ -620,7 +620,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r19 \n\t" "adc r23, r23 \n\t" "ld r19, x+ \n\t" @@ -644,7 +644,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" // 1 "adc r23, r23 \n\t" "ld r21, x+ \n\t" @@ -656,7 +656,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + /* Now finish the carries etc */ "add r23, r18 \n\t" "adc r22, r22 \n\t" @@ -665,27 +665,27 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r19 \n\t" "adc r23, r23 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r20 \n\t" "adc r22, r22 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" "adc r23, r23 \n\t" "st z+, r22 \n\t" "st z+, r23 \n\t" "eor r1, r1 \n\t" /* make r1 be 0 again */ - + "sbiw r30, 37 \n\t" /* move z back to point at tmp */ "subi r26, 64 \n\t" /* move x back to point at product */ "sbc r27, __zero_reg__ \n\t" - + /* add low bytes of tmp to product, storing in result */ "ld r18, z+ \n\t" "ld r19, x+ \n\t" @@ -696,7 +696,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, x+ \n\t" "adc r18, r19 \n\t" "st y+, r18 \n\t") - + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ /* at this point x is at the end of product, y is at the end of result, z is 32 bytes into tmp */ @@ -710,12 +710,12 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, z+ \n\t" "ld r20, z+ \n\t" "ld r21, z+ \n\t" - + "mul r24, r18 \n\t" "st x+, r0 \n\t" "mov r22, r1 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r19 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" /* can't overflow */ @@ -724,7 +724,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" /* can't overflow */ "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "mul r24, r20 \n\t" "add r23, r0 \n\t" "adc r22, r1 \n\t" @@ -733,7 +733,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st x+, r23 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r21 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" @@ -742,7 +742,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r18 \n\t" "adc r22, r22 \n\t" "ld r18, z+ \n\t" @@ -754,7 +754,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st x+, r23 \n\t" "ldi r23, 0 \n\t" - + /* Now finish the carries etc */ "add r22, r19 \n\t" "adc r23, r23 \n\t" @@ -763,23 +763,23 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r20 \n\t" "adc r22, r22 \n\t" "st x+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" "adc r23, r23 \n\t" "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r18 \n\t" "adc r22, r22 \n\t" "st x+, r23 \n\t" "st x+, r22 \n\t" "eor r1, r1 \n\t" /* make r1 be 0 again */ - + /* now z points to the end of tmp, x points to the end of product (y still points at result) */ "sbiw r26, 10 \n\t" /* move x back to point at beginning of actual data */ @@ -793,28 +793,28 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, y \n\t" "adc r18, r19 \n\t" "st y+, r18 \n\t") - + /* Done adding, now propagate carry bit */ REPEAT(22, "ld r18, y \n\t" "adc r18, __zero_reg__ \n\t" "st y+, r18 \n\t") - + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ "sbiw r28, 32 \n\t" /* move y back to point at result */ - + "sbiw r30, 1 \n\t" /* fix stack pointer */ "in r0, __SREG__ \n\t" "cli \n\t" "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + : "+x" (product), [carry] "+r" (carry) : "y" (result) : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc" ); - + if (carry > 0) { --carry; uECC_vli_sub(result, result, curve_secp256k1.p, 32); @@ -845,7 +845,7 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, __asm__ volatile ( "clc \n\t" - + "1: \n\t" "ld %[left], x+ \n\t" /* Load left byte. */ "ld %[right], y+ \n\t" /* Load right byte. */ @@ -853,12 +853,12 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, "st z+, %[left] \n\t" /* Store the result. */ "dec %[i] \n\t" "brne 1b \n\t" - + "adc %[carry], %[carry] \n\t" /* Store carry bit. */ : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), [carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte) - : + : : "cc" ); return carry; @@ -878,7 +878,7 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, __asm__ volatile ( "clc \n\t" - + "1: \n\t" "ld %[left], x+ \n\t" /* Load left byte. */ "ld %[right], y+ \n\t" /* Load right byte. */ @@ -886,10 +886,10 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, "st z+, %[left] \n\t" /* Store the result. */ "dec %[i] \n\t" "brne 1b \n\t" - + "adc %[borrow], %[borrow] \n\t" /* Store carry bit in borrow. */ - : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (i), + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), [borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte) : : "cc" @@ -911,86 +911,86 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, uint8_t r2 = 0; uint8_t zero = 0; uint8_t k, i; - + __asm__ volatile ( "ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */ - + "1: \n\t" "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ - + "add r28, %[k] \n\t" /* pre-add right ptr */ "adc r29, %[zero] \n\t" - + "2: \n\t" "ld r0, x+ \n\t" "ld r1, -y \n\t" "mul r0, r1 \n\t" - + "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "inc %[i] \n\t" "cp %[i], %[k] \n\t" "brlo 2b \n\t" /* loop if i < k */ - + "sub r26, %[k] \n\t" /* fix up left ptr */ "sbc r27, %[zero] \n\t" - + "st z+, %[r0] \n\t" /* Store the result. */ "mov %[r0], %[r1] \n\t" "mov %[r1], %[r2] \n\t" "mov %[r2], %[zero] \n\t" - + "inc %[k] \n\t" "cp %[k], %[num] \n\t" "brlo 1b \n\t" /* loop if k < num_words */ - + /* second half */ "mov %[k], %[num] \n\t" /* k = num_words; k > 0; --k */ "add r28, %[num] \n\t" /* move right ptr to point at the end of right */ "adc r29, %[zero] \n\t" - + "1: \n\t" "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ - + "2: \n\t" "ld r0, x+ \n\t" "ld r1, -y \n\t" "mul r0, r1 \n\t" - + "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "inc %[i] \n\t" "cp %[i], %[k] \n\t" "brlo 2b \n\t" /* loop if i < k */ - + "add r28, %[k] \n\t" /* fix up right ptr */ "adc r29, %[zero] \n\t" - + "st z+, %[r0] \n\t" /* Store the result. */ "mov %[r0], %[r1] \n\t" "mov %[r1], %[r2] \n\t" "mov %[r2], %[zero] \n\t" - + "dec %[k] \n\t" "sub r26, %[k] \n\t" /* fix up left ptr (after k is decremented, so next time we start 1 higher) */ "sbc r27, %[zero] \n\t" - + "cp %[k], %[zero] \n\t" "brne 1b \n\t" /* loop if k > 0 */ - + "st z+, %[r0] \n\t" /* Store last result byte. */ "eor r1, r1 \n\t" /* fix r1 to be 0 again */ - + : "+z" (result), "+x" (left), "+y" (right), [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero), [num] "+r" (num_words), [k] "=&r" (k), [i] "=&r" (i) - : + : : "r0", "cc" ); } @@ -1007,18 +1007,18 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, uint8_t r2 = 0; uint8_t zero = 0; uint8_t k; - + __asm__ volatile ( "ldi %[k], 1 \n\t" /* k = 1; k < num_words * 2; ++k */ - + "1: \n\t" - + "movw r26, %[orig] \n\t" /* copy orig ptr to 'left' ptr */ "movw r30, %[orig] \n\t" /* copy orig ptr to 'right' ptr */ "cp %[k], %[num] \n\t" "brlo 2f \n\t" "breq 2f \n\t" - + /* when k > num_words, we start from (k - num_words) on the 'left' ptr */ "add r26, %[k] \n\t" "adc r27, %[zero] \n\t" @@ -1027,11 +1027,11 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "add r30, %[num] \n\t" /* move right ptr to point at the end */ "adc r31, %[zero] \n\t" "rjmp 3f \n\t" - + "2: \n\t" /* when k <= num_words, we add k to the 'right' ptr */ "add r30, %[k] \n\t" /* pre-add 'right' ptr */ "adc r31, %[zero] \n\t" - + "3: \n\t" "ld r0, x+ \n\t" "cp r26, r30 \n\t" /* if left == right here, then we are done after this mult @@ -1039,7 +1039,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "breq 4f \n\t" "ld r1, -z \n\t" "mul r0, r1 \n\t" - + /* add twice since it costs the same as doubling */ "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" @@ -1047,18 +1047,18 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "cpse r26, r30 \n\t" /* if left == right here, then we are done */ "rjmp 3b \n\t" "rjmp 5f \n\t" /* skip code for non-doubled mult */ - + "4: \n\t" "ld r1, -z \n\t" "mul r0, r1 \n\t" "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "5: \n\t" "movw r30, %[result] \n\t" /* make z point to result */ "st z+, %[r0] \n\t" /* Store the result. */ @@ -1066,15 +1066,15 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "mov %[r0], %[r1] \n\t" "mov %[r1], %[r2] \n\t" "mov %[r2], %[zero] \n\t" - + "inc %[k] \n\t" "cp %[k], %[max] \n\t" "brlo 1b \n\t" /* loop if k < num_words * 2 */ - + "movw r30, %[result] \n\t" /* make z point to result */ "st z+, %[r0] \n\t" /* Store last result byte. */ "eor r1, r1 \n\t" /* fix r1 to be 0 again */ - + : [result] "+r" (r), [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero), [k] "=&a" (k) diff --git a/deps/micro-ecc/emk_project.py b/deps/micro-ecc/emk_project.py index 940fadc2a..957dd7920 100644 --- a/deps/micro-ecc/emk_project.py +++ b/deps/micro-ecc/emk_project.py @@ -12,6 +12,11 @@ c_link_flags = [] cxx_link_flags = ["-fno-rtti", "-fno-exceptions"] +if "root" in emk.options: + root = emk.options["root"] +else: + root = "/" + def setup_build_dir(): build_arch = None if "arch" in emk.options: @@ -54,9 +59,9 @@ def setup_avr(): global c global link - c.compiler = c.GccCompiler("/Projects/avr-tools/bin/avr-") + c.compiler = c.GccCompiler(root + "Projects/avr-tools/bin/avr-") c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"] - link.linker = link.GccLinker("/Projects/avr-tools/bin/avr-") + link.linker = link.GccLinker(root + "Projects/avr-tools/bin/avr-") link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"] link.strip = True @@ -66,30 +71,30 @@ def setup_arm_thumb(): global asm global utils - asm.assembler = asm.GccAssembler("/cross/arm_cortex/bin/arm-none-eabi-") - c.compiler = c.GccCompiler("/cross/arm_cortex/bin/arm-none-eabi-") - link.linker = link.GccLinker("/cross/arm_cortex/bin/arm-none-eabi-") + asm.assembler = asm.GccAssembler(root + "cross/arm_cortex/bin/arm-none-eabi-") + c.compiler = c.GccCompiler(root + "cross/arm_cortex/bin/arm-none-eabi-") + link.linker = link.GccLinker(root + "cross/arm_cortex/bin/arm-none-eabi-") c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"]) c.defines["LPC11XX"] = 1 - + link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"]) - link.local_flags.extend(["-Tflash.lds", "-L/Projects/lpc11xx/core", "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"]) + link.local_flags.extend(["-Tflash.lds", "-L" + root + "Projects/lpc11xx/core", root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"]) link.local_syslibs += ["gcc"] - link.depdirs += ["/Projects/lpc11xx/stdlib"] + link.depdirs += [root + "Projects/lpc11xx/stdlib"] def do_objcopy(produces, requires): - utils.call("/cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0]) + utils.call(root + "cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0]) def handle_exe(path): - emk.depend(path, "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o") + emk.depend(path, root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o") emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True) emk.autobuild(path + ".bin") link.exe_funcs.append(handle_exe) link.strip = True - - emk.recurse("/Projects/lpc11xx/core") + + emk.recurse(root + "Projects/lpc11xx/core") def setup_linux_rpi(): global c @@ -97,7 +102,7 @@ def setup_linux_rpi(): c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") - + c.flags.extend(["-fomit-frame-pointer"]) setup_build_dir() diff --git a/deps/micro-ecc/test/ecc_test/ecc_test.ino b/deps/micro-ecc/examples/ecc_test/ecc_test.ino similarity index 98% rename from deps/micro-ecc/test/ecc_test/ecc_test.ino rename to deps/micro-ecc/examples/ecc_test/ecc_test.ino index c3c8900d8..64a0be50f 100644 --- a/deps/micro-ecc/test/ecc_test/ecc_test.ino +++ b/deps/micro-ecc/examples/ecc_test/ecc_test.ino @@ -1,7 +1,5 @@ #include -extern "C" { - static int RNG(uint8_t *dest, unsigned size) { // Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of // random noise). This can take a long time to generate random data if the result of analogRead(0) @@ -29,8 +27,6 @@ static int RNG(uint8_t *dest, unsigned size) { return 1; } -} // extern "C" - void setup() { Serial.begin(115200); Serial.print("Testing ecc\n"); @@ -82,4 +78,3 @@ void loop() { Serial.print("Shared secrets are identical\n"); } } - diff --git a/deps/micro-ecc/library.properties b/deps/micro-ecc/library.properties new file mode 100644 index 000000000..390bdc87a --- /dev/null +++ b/deps/micro-ecc/library.properties @@ -0,0 +1,9 @@ +name=micro-ecc +version=1.0.0 +author=Kenneth MacKay +maintainer=Kenneth MacKay +sentence=uECC +paragraph=A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors. +category=Other +url=https://github.com/kmackay/micro-ecc +architectures=* diff --git a/deps/micro-ecc/platform-specific.inc b/deps/micro-ecc/platform-specific.inc index 1bb595adc..7e0373f50 100644 --- a/deps/micro-ecc/platform-specific.inc +++ b/deps/micro-ecc/platform-specific.inc @@ -8,6 +8,10 @@ #if (defined(_WIN32) || defined(_WIN64)) /* Windows */ +// use pragma syntax to prevent tweaking the linker script for getting CryptXYZ function +#pragma comment(lib, "crypt32.lib") +#pragma comment(lib, "advapi32.lib") + #define WIN32_LEAN_AND_MEAN #include #include @@ -62,6 +66,29 @@ static int default_RNG(uint8_t *dest, unsigned size) { } #define default_RNG_defined 1 +#elif defined(RIOT_VERSION) + +#include + +static int default_RNG(uint8_t *dest, unsigned size) { + random_bytes(dest, size); + return 1; +} +#define default_RNG_defined 1 + +#elif defined(NRF52_SERIES) + +#include "app_error.h" +#include "nrf_crypto_rng.h" + +static int default_RNG(uint8_t *dest, unsigned size) +{ + // make sure to call nrf_crypto_init and nrf_crypto_rng_init first + ret_code_t ret_code = nrf_crypto_rng_vector_generate(dest, size); + return (ret_code == NRF_SUCCESS) ? 1 : 0; +} +#define default_RNG_defined 1 + #endif /* platform */ #endif /* _UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/deps/micro-ecc/test/ecdsa_test_vectors.c b/deps/micro-ecc/test/ecdsa_test_vectors.c new file mode 100644 index 000000000..1e902b266 --- /dev/null +++ b/deps/micro-ecc/test/ecdsa_test_vectors.c @@ -0,0 +1,128 @@ +/* Copyright 2020, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include +#include +#include + +typedef struct { + const char* private_key; + const char* public_key; + const char* k; + const char* hash; + const char* r; + const char* s; +} Test; + +Test secp256k1_tests[] = { + { + "ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f", + "779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcde94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f", + "49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a", + "4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a", + "241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795", + "021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e" + }, +}; + +extern int uECC_sign_with_k(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *k, + uint8_t *signature, + uECC_Curve curve); + + +void vli_print(uint8_t *vli, unsigned int size) { + for(unsigned i=0; i +#include +#include + +typedef struct { + const char* k; + const char* Q; + int success; +} Test; + +Test secp160r1_tests[] = { + /* Note, I couldn't find any test vectors for secp160r1 online, so these are just + generated on my desktop using uECC. */ + { + "000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "000000000000000000000000000000000000000001", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "000000000000000000000000000000000000000002", + "02F997F33C5ED04C55D3EDF8675D3E92E8F46686F083A323482993E9440E817E21CFB7737DF8797B", + 1 + }, + { + "000000000000000000000000000000000000000003", + "7B76FF541EF363F2DF13DE1650BD48DAA958BC59C915CA790D8C8877B55BE0079D12854FFE9F6F5A", + 1 + }, + { /* n - 4 */ + "0100000000000000000001F4C8F927AED3CA752253", + "B4041D8683BE99F0AFE01C307B1AD4C100CF2A88C0CD35127BE0F73FF99F338B350B5A42864112F7", + 1 + }, + { /* n - 3 */ + "0100000000000000000001F4C8F927AED3CA752254", + "7B76FF541EF363F2DF13DE1650BD48DAA958BC5936EA3586F27377884AA41FF862ED7AAF816090A5", + 1 + }, + { /* n - 2 */ + "0100000000000000000001F4C8F927AED3CA752255", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { /* n - 1 */ + "0100000000000000000001F4C8F927AED3CA752256", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { /* n */ + "0100000000000000000001F4C8F927AED3CA752257", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + + +Test secp192r1_tests[] = { + { + "000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "000000000000000000000000000000000000000000000001", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + 0 + }, + { + "000000000000000000000000000000000000000000000002", + "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB", + 1 + }, + { + "000000000000000000000000000000000000000000000003", + "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD", + 1 + }, + { /* n - 4 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282D", + "35433907297CC378B0015703374729D7A4FE46647084E4BA5D9B667B0DECA3CFE15C534F88932B0DDAC764CEE24C41CD", + 1 + }, + { /* n - 3 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282E", + "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA87D3C81C8D45BADF559D1F012EDE2B600C4ABC99F302FA02", + 1 + }, + { /* n - 2 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282F", + "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888229425F266C25F05B94D8443EBE4796FA6CCE505A3816C54", + 0 + }, + { /* n - 1 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012F8E6D46A003725879CEFEE1294DB32298C06885EE186B7EE", + 0 + }, + { /* n */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + +Test secp224r1_tests[] = { + { + "00000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "00000000000000000000000000000000000000000000000000000001", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + 0 + }, + { + "00000000000000000000000000000000000000000000000000000002", + "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA61C2B76A7BC25E7702A704FA986892849FCA629487ACF3709D2E4E8BB", + 1 + }, + { + "00000000000000000000000000000000000000000000000000000003", + "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04A3F7F03CADD0BE444C0AA56830130DDF77D317344E1AF3591981A925", + 1 + }, + { /* n - 4 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A39", + "AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301FB7DA7F5F13A43B81774373C879CD32D6934C05FA758EEB14FCFAB38", + 1 + }, + { /* n - 3 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3A", + "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D045C080FC3522F41BBB3F55A97CFECF21F882CE8CBB1E50CA6E67E56DC", + 1 + }, + { /* n - 2 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3B", + "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6E3D4895843DA188FD58FB0567976D7B50359D6B78530C8F62D1B1746", + 0 + }, + { /* n - 1 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3C", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D2142C89C774A08DC04B3DD201932BC8A5EA5F8B89BBB2A7E667AFF81CD", + 0 + }, + { /* n */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + +Test secp256r1_tests[] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000001", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000002", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC4766997807775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1", + 1 + }, + { + "0000000000000000000000000000000000000000000000000000000000000003", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032", + 1 + }, + { /* n - 4 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254D", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B0308521F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739", + 1 + }, + { /* n - 3 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD", + 1 + }, + { /* n - 2 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E", + 0 + }, + { /* n - 1 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A", + 0 + }, + { /* n */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + +Test secp256k1_tests[] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000001", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000002", + "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE51AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A", + 1 + }, + { + "0000000000000000000000000000000000000000000000000000000000000003", + "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672", + 1 + }, + { /* n - 4 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413D", + "E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13AE1266C15F2BAA48A9BD1DF6715AEBB7269851CC404201BF30168422B88C630D", + 1 + }, + { /* n - 3 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413E", + "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9C77084F09CD217EBF01CC819D5C80CA99AFF5666CB3DDCE4934602897B4715BD", + 1 + }, + { /* n - 2 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F", + "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5E51E970159C23CC65C3A7BE6B99315110809CD9ACD992F1EDC9BCE55AF301705", + 0 + }, + { /* n - 1 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777", + 0 + }, + { /* n */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + + +void vli_print(uint8_t *vli, unsigned int size) { + for(unsigned i=0; i> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random, num_words) && + uECC_vli_cmp(top, random, num_words) == 1) { + return 1; + } + } + return 0; +} + static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *private_key, uECC_Curve curve) { uECC_word_t tmp1[uECC_MAX_WORDS]; uECC_word_t tmp2[uECC_MAX_WORDS]; uECC_word_t *p2[2] = {tmp1, tmp2}; + uECC_word_t *initial_Z = 0; uECC_word_t carry; /* Regularize the bitcount for the private key so that attackers cannot use a side channel attack to learn the number of leading zeros. */ carry = regularize_k(private_key, tmp1, tmp2, curve); - EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + if (!uECC_generate_random_int(p2[carry], curve->p, curve->num_words)) { + return 0; + } + initial_Z = p2[carry]; + } + EccPoint_mult(result, curve->G, p2[!carry], initial_Z, curve->num_n_bits + 1, curve); if (EccPoint_isZero(result, curve)) { return 0; @@ -954,7 +994,7 @@ uECC_VLI_API void uECC_vli_bytesToNative(uint8_t *native, uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native) { - wordcount_t i; + int i; for (i = 0; i < num_bytes; ++i) { unsigned b = num_bytes - 1 - i; bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); @@ -964,7 +1004,7 @@ uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes) { - wordcount_t i; + int i; uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); for (i = 0; i < num_bytes; ++i) { unsigned b = num_bytes - 1 - i; @@ -975,32 +1015,6 @@ uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, #endif /* uECC_WORD_SIZE */ -/* Generates a random integer in the range 0 < random < top. - Both random and top have num_words words. */ -uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random, - const uECC_word_t *top, - wordcount_t num_words) { - uECC_word_t mask = (uECC_word_t)-1; - uECC_word_t tries; - bitcount_t num_bits = uECC_vli_numBits(top, num_words); - - if (!g_rng_function) { - return 0; - } - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { - return 0; - } - random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); - if (!uECC_vli_isZero(random, num_words) && - uECC_vli_cmp(top, random, num_words) == 1) { - return 1; - } - } - return 0; -} - int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve) { @@ -1115,7 +1129,7 @@ void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve } #endif /* uECC_SUPPORT_COMPRESSED_POINT */ -int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { +uECC_VLI_API int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { uECC_word_t tmp1[uECC_MAX_WORDS]; uECC_word_t tmp2[uECC_MAX_WORDS]; wordcount_t num_words = curve->num_words; @@ -1210,7 +1224,7 @@ static void bits2int(uECC_word_t *native, bcopy((uint8_t *) native, bits, bits_size); #else uECC_vli_bytesToNative(native, bits, bits_size); -#endif +#endif if (bits_size * 8 <= (unsigned)curve->num_n_bits) { return; } @@ -1229,7 +1243,7 @@ static void bits2int(uECC_word_t *native, } } -static int uECC_sign_with_k(const uint8_t *private_key, +static int uECC_sign_with_k_internal(const uint8_t *private_key, const uint8_t *message_hash, unsigned hash_size, uECC_word_t *k, @@ -1239,6 +1253,7 @@ static int uECC_sign_with_k(const uint8_t *private_key, uECC_word_t tmp[uECC_MAX_WORDS]; uECC_word_t s[uECC_MAX_WORDS]; uECC_word_t *k2[2] = {tmp, s}; + uECC_word_t *initial_Z = 0; #if uECC_VLI_NATIVE_LITTLE_ENDIAN uECC_word_t *p = (uECC_word_t *)signature; #else @@ -1255,7 +1270,15 @@ static int uECC_sign_with_k(const uint8_t *private_key, } carry = regularize_k(k, tmp, s, curve); - EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + if (!uECC_generate_random_int(k2[carry], curve->p, num_words)) { + return 0; + } + initial_Z = k2[carry]; + } + EccPoint_mult(p, curve->G, k2[!carry], initial_Z, num_n_bits + 1, curve); if (uECC_vli_isZero(p, num_words)) { return 0; } @@ -1299,10 +1322,22 @@ static int uECC_sign_with_k(const uint8_t *private_key, bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes); #else uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); -#endif +#endif return 1; } +/* For testing - sign with an explicitly specified k value */ +int uECC_sign_with_k(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *k, + uint8_t *signature, + uECC_Curve curve) { + uECC_word_t k2[uECC_MAX_WORDS]; + bits2int(k2, k, BITS_TO_BYTES(curve->num_n_bits), curve); + return uECC_sign_with_k_internal(private_key, message_hash, hash_size, k2, signature, curve); +} + int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, unsigned hash_size, @@ -1316,7 +1351,7 @@ int uECC_sign(const uint8_t *private_key, return 0; } - if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) { + if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, k, signature, curve)) { return 1; } } @@ -1432,7 +1467,7 @@ int uECC_sign_deterministic(const uint8_t *private_key, mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits)); } - if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) { + if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, T, signature, curve)) { return 1; } @@ -1472,7 +1507,7 @@ int uECC_verify(const uint8_t *public_key, uECC_word_t *_public = (uECC_word_t *)public_key; #else uECC_word_t _public[uECC_MAX_WORDS * 2]; -#endif +#endif uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; wordcount_t num_words = curve->num_words; wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); diff --git a/deps/micro-ecc/uECC.h b/deps/micro-ecc/uECC.h index 991176316..dcbdbfa8b 100644 --- a/deps/micro-ecc/uECC.h +++ b/deps/micro-ecc/uECC.h @@ -38,13 +38,16 @@ faster somewhat faster, but increases the code size. */ #endif /* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native -little-endian format for *all* arrays passed in and out of the public API. This includes public -and private keys, shared secrets, signatures and message hashes. +little-endian format for *all* arrays passed in and out of the public API. This includes public +and private keys, shared secrets, signatures and message hashes. Using this switch reduces the amount of call stack memory used by uECC, since less intermediate -translations are required. +translations are required. Note that this will *only* work on native little-endian processors and it will treat the uint8_t -arrays passed into the public API as word arrays, therefore requiring the provided byte arrays -to be word aligned on architectures that do not support unaligned accesses. */ +arrays passed into the public API as word arrays, therefore requiring the provided byte arrays +to be word aligned on architectures that do not support unaligned accesses. +IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible +with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use +the same endianness. */ #ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN #define uECC_VLI_NATIVE_LITTLE_ENDIAN 0 #endif @@ -163,7 +166,9 @@ Returns 1 if the key pair was generated successfully, 0 if an error occurred. int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve); /* uECC_shared_secret() function. -Compute a shared secret given your secret key and someone else's public key. +Compute a shared secret given your secret key and someone else's public key. If the public key +is not from a trusted source and has not been previously verified, you should verify it first +using uECC_valid_public_key(). Note: It is recommended that you hash the result of uECC_shared_secret() before using it for symmetric encryption or HMAC. From e16bc60fbc101919cdeb07d005ce927cf1244c67 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Thu, 9 Feb 2023 12:23:13 +0900 Subject: [PATCH 7/9] Revert "temporary revert local changes" This reverts commit 31e939fe20280ae2aa46e29f29c2c9995e0c0ff2. --- deps/micro-ecc/uECC.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/micro-ecc/uECC.c b/deps/micro-ecc/uECC.c index a3d502cf2..a3224dd02 100644 --- a/deps/micro-ecc/uECC.c +++ b/deps/micro-ecc/uECC.c @@ -312,7 +312,7 @@ uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, uECC_word_t tmp[uECC_MAX_WORDS]; uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); uECC_word_t equal = uECC_vli_isZero(tmp, num_words); - return (!equal - 2 * neg); + return (cmpresult_t)(!equal - 2 * neg); } /* Computes vli = vli >> 1. */ @@ -997,7 +997,7 @@ uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, int i; for (i = 0; i < num_bytes; ++i) { unsigned b = num_bytes - 1 - i; - bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + bytes[i] = (uint8_t)(native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE))); } } From d1af00617808f917de59fdb02b05ce2a76650105 Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Thu, 9 Feb 2023 14:01:00 +0200 Subject: [PATCH 8/9] Interim --- include/picotls.h | 14 ++++++++++++-- lib/hpke.c | 2 +- lib/picotls.c | 17 +++++++++++++++-- lib/uecc.c | 11 ++++++++++- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/include/picotls.h b/include/picotls.h index 9fbe23fad..770fb242d 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -1259,7 +1259,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); #define PTLS_LOG(module, type, block) \ do { \ - if (!ptls_log.is_active) \ + if (!PTLS_LOG_IS_ACTIVE(ptls_log)) \ break; \ PTLS_LOG__DO_LOG((module), (type), (block)); \ } while (0) @@ -1267,7 +1267,7 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); #define PTLS_LOG_CONN(type, tls, block) \ do { \ ptls_t *_tls = (tls); \ - if (!ptls_log.is_active || ptls_skip_tracing(_tls)) \ + if (!PTLS_LOG_IS_ACTIVE(ptls_log) || ptls_skip_tracing(_tls)) \ break; \ PTLS_LOG__DO_LOG(picotls, type, { \ PTLS_LOG_ELEMENT_PTR(tls, _tls); \ @@ -1376,10 +1376,20 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end); * User API is exposed only when logging is supported by the platform. */ typedef struct st_ptls_log_t { +#if PTLS_HAVE_LOG unsigned is_active : 1; +#else + unsigned : 1; +#endif unsigned include_appdata : 1; } ptls_log_t; +#if PTLS_HAVE_LOG +#define PTLS_LOG_IS_ACTIVE(log) (log.is_active) +#else +#define PTLS_LOG_IS_ACTIVE(log) (0) +#endif + #if PTLS_HAVE_LOG extern volatile ptls_log_t ptls_log; /** diff --git a/lib/hpke.c b/lib/hpke.c index 744ae8be1..daf247526 100644 --- a/lib/hpke.c +++ b/lib/hpke.c @@ -192,7 +192,7 @@ static int key_schedule(ptls_hpke_kem_t *kem, ptls_hpke_cipher_suite_t *cipher, return PTLS_ERROR_NO_MEMORY; #define secret (tmp) #define key (tmp + PTLS_MAX_DIGEST_SIZE) -#define base_nonce (tmp + PTLS_MAX_DIGEST_SIZE + PTLS_MAX_SECRET_SIZE) +#define base_nonce (key + PTLS_MAX_SECRET_SIZE) #else uint8_t secret[PTLS_MAX_DIGEST_SIZE], key[PTLS_MAX_SECRET_SIZE], base_nonce[PTLS_MAX_IV_SIZE]; #endif diff --git a/lib/picotls.c b/lib/picotls.c index c9de43771..e046f3ed3 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -41,6 +41,13 @@ #if PICOTLS_USE_DTRACE #include "picotls-probes.h" #endif +#if PARTICLE +#include +#include "/Users/lars/Documents/Code/quant/lib/deps/warpcore/lib/include/warpcore/util.h" +#else +#define LOG_PRINTF(...) +#define hexdump(...) +#endif #define PTLS_MAX_PLAINTEXT_RECORD_SIZE 16384 #define PTLS_MAX_ENCRYPTED_RECORD_SIZE (16384 + 256) @@ -2351,8 +2358,10 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ sni_name = tls->server_name; if (properties != NULL) { + LOG_PRINTF(INFO, "properties\n"); /* try to use ECH (ignore broken ECHConfigList; it is delivered insecurely) */ if (!is_second_flight && sni_name != NULL && tls->ctx->ech.client.ciphers != NULL) { + LOG_PRINTF(INFO, "ECH\n"); if (properties->client.ech.configs.len != 0) { struct st_decoded_ech_config_t decoded; client_decode_ech_config_list(tls->ctx, &decoded, properties->client.ech.configs); @@ -2397,8 +2406,10 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ } /* use the default key share if still not undetermined */ - if (tls->key_share == NULL && !(properties != NULL && properties->client.negotiate_before_key_exchange)) + if (tls->key_share == NULL && !(properties != NULL && properties->client.negotiate_before_key_exchange)) { + LOG_PRINTF(INFO, "use the default key share\n"); tls->key_share = tls->ctx->key_exchanges[0]; + } /* instantiate key share context */ assert(tls->client.key_share_ctx == NULL); @@ -2426,9 +2437,11 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ tls->ech.client.first_ech, resumption_secret, resumption_ticket, obfuscated_ticket_age, tls->key_schedule->hashes[0].algo->digest_size, cookie, tls->client.using_early_data)) != 0) goto Exit; + hexdump(emitter->buf->base, emitter->buf->off); /* update the message hash, filling in the PSK binder HMAC if necessary */ if (resumption_secret.base != NULL) { + LOG_PRINTF(INFO, "resumption_secret\n"); size_t psk_binder_off = emitter->buf->off - (3 + tls->key_schedule->hashes[0].algo->digest_size); if ((ret = derive_secret_with_empty_digest(tls->key_schedule, binder_key, "res binder")) != 0) goto Exit; @@ -2441,6 +2454,7 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ /* ECH */ if (tls->ech.aead != NULL) { + LOG_PRINTF(INFO, "ECH\n"); /* build EncodedCHInner */ if ((ret = encode_client_hello(tls->ctx, &encoded_ch_inner, ENCODE_CH_MODE_ENCODED_INNER, is_second_flight, properties, tls->ech.inner_client_random, tls->client.key_share_ctx, sni_name, @@ -6007,7 +6021,6 @@ int ptls_export_secret(ptls_t *tls, void *output, size_t outlen, const char *lab #define context_value_hash (tmp + PTLS_MAX_DIGEST_SIZE) #else uint8_t derived_secret[PTLS_MAX_DIGEST_SIZE], context_value_hash[PTLS_MAX_DIGEST_SIZE]; - #endif int ret; diff --git a/lib/uecc.c b/lib/uecc.c index 5d42b3b6f..0ebb836a8 100644 --- a/lib/uecc.c +++ b/lib/uecc.c @@ -33,6 +33,10 @@ #include "uECC_vli.h" #include "picotls.h" #include "picotls/minicrypto.h" +#include "/Users/lars/Documents/Code/quant/lib/deps/warpcore/lib/include/warpcore/util.h" +#if PARTICLE +#include +#endif #define TYPE_UNCOMPRESSED_PUBLIC_KEY 4 @@ -81,6 +85,7 @@ static int secp256r1_on_exchange(ptls_key_exchange_context_t **_ctx, int release static int secp256r1_create_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **_ctx) { + LOG_PRINTF(INFO, "secp256r1_create_key_exchange\n"); struct st_secp256r1_key_exhchange_t *ctx; if ((ctx = (struct st_secp256r1_key_exhchange_t *)malloc(sizeof(*ctx))) == NULL) @@ -88,7 +93,8 @@ static int secp256r1_create_key_exchange(ptls_key_exchange_algorithm_t *algo, pt ctx->super = (ptls_key_exchange_context_t){algo, ptls_iovec_init(ctx->pub, sizeof(ctx->pub)), secp256r1_on_exchange}; ctx->pub[0] = TYPE_UNCOMPRESSED_PUBLIC_KEY; uECC_make_key(ctx->pub + 1, ctx->priv, uECC_secp256r1()); - + hexdump(ctx->pub, SECP256R1_PUBLIC_KEY_SIZE); + hexdump(ctx->priv, SECP256R1_PRIVATE_KEY_SIZE); *_ctx = &ctx->super; return 0; } @@ -96,6 +102,7 @@ static int secp256r1_create_key_exchange(ptls_key_exchange_algorithm_t *algo, pt static int secp256r1_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey) { + LOG_PRINTF(INFO, "secp256r1_key_exchange\n"); uint8_t priv[SECP256R1_PRIVATE_KEY_SIZE], *pub = NULL, *secbytes = NULL; int ret; @@ -119,7 +126,9 @@ static int secp256r1_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iove goto Exit; } *pubkey = ptls_iovec_init(pub, SECP256R1_PUBLIC_KEY_SIZE); + hexdump(pub, SECP256R1_PUBLIC_KEY_SIZE); *secret = ptls_iovec_init(secbytes, SECP256R1_SHARED_SECRET_SIZE); + hexdump(secret, SECP256R1_SHARED_SECRET_SIZE); ret = 0; Exit: From 8bd23e831de9181db1e8cdd9bba191a28d78c388 Mon Sep 17 00:00:00 2001 From: Lars Eggert Date: Thu, 9 Feb 2023 15:45:27 +0200 Subject: [PATCH 9/9] Minimize diff to origin/master --- deps/micro-ecc/README.md | 4 +- deps/micro-ecc/asm_arm.inc | 4 +- deps/micro-ecc/asm_avr.inc | 212 +++++------ deps/micro-ecc/emk_project.py | 31 +- deps/micro-ecc/library.properties | 9 - deps/micro-ecc/platform-specific.inc | 27 -- .../{examples => test}/ecc_test/ecc_test.ino | 5 + deps/micro-ecc/test/ecdsa_test_vectors.c | 128 ------- deps/micro-ecc/test/public_key_test_vectors.c | 338 ------------------ deps/micro-ecc/uECC.c | 243 ++++++------- deps/micro-ecc/uECC.h | 17 +- include/picotls.h | 8 +- lib/picotls.c | 60 +--- lib/uecc.c | 11 +- 14 files changed, 260 insertions(+), 837 deletions(-) delete mode 100644 deps/micro-ecc/library.properties rename deps/micro-ecc/{examples => test}/ecc_test/ecc_test.ino (98%) delete mode 100644 deps/micro-ecc/test/ecdsa_test_vectors.c delete mode 100644 deps/micro-ecc/test/public_key_test_vectors.c diff --git a/deps/micro-ecc/README.md b/deps/micro-ecc/README.md index 111321bf7..01926e3fa 100644 --- a/deps/micro-ecc/README.md +++ b/deps/micro-ecc/README.md @@ -19,7 +19,7 @@ Features Usage Notes ----------- ### Point Representation ### -Compressed points are represented in the standard format as defined in http://www.secg.org/sec1-v2.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_decompress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations. +Compressed points are represented in the standard format as defined in http://www.secg.org/collateral/sec1_final.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_compress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations. Private keys are represented in the standard format. @@ -27,7 +27,7 @@ Private keys are represented in the standard format. I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions. -For use with Arduino, you can use the Library Manager to download micro-ecc (**Sketch**=>**Include Library**=>**Manage Libraries**). You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu). +For use with Arduino, you can just create a symlink to the `uECC` directory in your Arduino `libraries` directory. You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu). See uECC.h for documentation for each function. diff --git a/deps/micro-ecc/asm_arm.inc b/deps/micro-ecc/asm_arm.inc index e3c8cb15e..688fdc75a 100644 --- a/deps/micro-ecc/asm_arm.inc +++ b/deps/micro-ecc/asm_arm.inc @@ -620,7 +620,7 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, "str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */ "pop {%[r0]} \n\t" /* pop result off the stack */ - RESUME_SYNTAX + ".syntax divided \n\t" : [r3] "+l" (num_words), [r4] "=&l" (r4), [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) : [r0] "l" (result), [r1] "l" (left), [r2] "l" (right) @@ -805,7 +805,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */ "pop {%[r0]} \n\t" /* pop result off the stack */ - RESUME_SYNTAX + ".syntax divided \n\t" : [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4), [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) : [r0] "l" (result), [r1] "l" (left) diff --git a/deps/micro-ecc/asm_avr.inc b/deps/micro-ecc/asm_avr.inc index c14bf5554..c98804032 100644 --- a/deps/micro-ecc/asm_avr.inc +++ b/deps/micro-ecc/asm_avr.inc @@ -37,12 +37,12 @@ uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { "sbc r31, __zero_reg__ \n\t" IJMP #endif - + REPEAT(uECC_MAX_WORDS, "st x+, __zero_reg__ \n\t") "1: \n\t" : "+x" (v) : [num] "r" (num_words) - : + : #if (uECC_MAX_WORDS != uECC_MIN_WORDS) "r30", "r31", "cc" #endif @@ -60,16 +60,16 @@ uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordco "sbc r31, __zero_reg__ \n\t" IJMP #endif - + REPEAT(uECC_MAX_WORDS, "ld r0, y+ \n\t" "st x+, r0 \n\t") "1: \n\t" : "+x" (d), "+y" (src) : [num] "r" ((uint8_t)(num_words * 2)) - : "r0" + : "r0", #if (uECC_MAX_WORDS != uECC_MIN_WORDS) - , "r30", "r31", "cc" + "r30", "r31", "cc" #endif ); } @@ -84,7 +84,7 @@ uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { "sub r30, %[jump] \n\t" "sbc r31, __zero_reg__ \n\t" #endif - + "add r26, %[num] \n\t" "adc r27, __zero_reg__ \n\t" "ld r0, -x \n\t" @@ -93,7 +93,7 @@ uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { #if (uECC_MAX_WORDS != uECC_MIN_WORDS) IJMP #endif - + REPEAT(DEC(uECC_MAX_WORDS), "ld r0, -x \n\t" "ror r0 \n\t" @@ -137,15 +137,15 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, "sub r30, %[num] \n\t" "sbc r31, __zero_reg__ \n\t" #endif - + "clc \n\t" #if (uECC_MAX_WORDS != uECC_MIN_WORDS) IJMP REPEATM(uECC_MAX_WORDS, ADD_RJPM_TABLE) #endif - + REPEATM(uECC_MAX_WORDS, ADD_RJPM_DEST) - + "mov %[clb], __zero_reg__ \n\t" "adc %[clb], %[clb] \n\t" /* Store carry bit. */ @@ -184,15 +184,15 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, "sub r30, %[num] \n\t" "sbc r31, __zero_reg__ \n\t" #endif - + "clc \n\t" #if (uECC_MAX_WORDS != uECC_MIN_WORDS) IJMP REPEATM(uECC_MAX_WORDS, SUB_RJPM_TABLE) #endif - + REPEATM(uECC_MAX_WORDS, SUB_RJPM_DEST) - + "mov %[clb], __zero_reg__ \n\t" "adc %[clb], %[clb] \n\t" /* Store carry bit. */ @@ -216,7 +216,7 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, wordcount_t num_words) { /* num_words should already be in r18. */ register wordcount_t r18 __asm__("r18") = num_words; - + __asm__ volatile ( "push r18 \n\t" #if (uECC_MIN_WORDS == 20) @@ -268,7 +268,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, wordcount_t num_words) { /* num_words should already be in r20. */ register wordcount_t r20 __asm__("r20") = num_words; - + __asm__ volatile ( "push r20 \n\t" #if (uECC_MIN_WORDS == 20) @@ -329,7 +329,7 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + "adiw r30, 25 \n\t" /* we are shifting by 31 bits, so shift over 4 bytes (+ 1 since z initially points below the stack) */ "adiw r26, 40 \n\t" /* end of product */ @@ -384,10 +384,10 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "ld r18, z \n\t" "adc r18, r1 \n\t" "st z+, r18 \n\t" - + "sbiw r30, 24 \n\t" /* move z back to point at tmp */ "sbiw r26, 40 \n\t" /* move x back to point at product */ - + /* add low bytes of tmp to product, storing in result */ "ld r18, z+ \n\t" "ld r19, x+ \n\t" @@ -403,13 +403,13 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { z is 20 bytes into tmp */ "sbiw r28, 20 \n\t" /* move y back to point at result */ "adiw r30, 4 \n\t" /* move z to point to the end of tmp */ - + /* do omega_mult again with the 4 relevant bytes */ /* z points to the end of tmp, x points to the end of product */ "ld r18, -z \n\t" /* Load word. */ "lsr r18 \n\t" /* Shift. */ "st -x, r18 \n\t" /* Store the first result word. */ - + "ld r18, -z \n\t" "ror r18 \n\t" "st -x, r18 \n\t" @@ -419,11 +419,11 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "ld r18, -z \n\t" "ror r18 \n\t" "st -x, r18 \n\t" - + "eor r18, r18 \n\t" /* r18 = 0 */ "ror r18 \n\t" /* get last bit */ "st -x, r18 \n\t" /* store it */ - + "sbiw r26, 3 \n\t" /* move x back to point at beginning */ /* now we add a copy of the 4 bytes */ "ld r18, z+ \n\t" @@ -432,29 +432,29 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "st x+, r18 \n\t" "ld r18, z+ \n\t" "st x+, r18 \n\t" - + "ld r18, z+ \n\t" "ld r19, x \n\t" "add r18, r19 \n\t" "st x+, r18 \n\t" - + /* Propagate over the remaining bytes */ "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + "ld r18, x \n\t" "adc r18, r1 \n\t" "st x+, r18 \n\t" - + /* now z points to the end of tmp, x points to the end of product (y still points at result) */ "sbiw r26, 8 \n\t" /* move x back to point at beginning of actual data */ @@ -468,23 +468,23 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { "ld r19, y \n\t" "adc r18, r19 \n\t" "st y+, r18 \n\t") - + /* Done adding, now propagate carry bit */ REPEAT(12, "ld r18, y \n\t" "adc r18, __zero_reg__ \n\t" "st y+, r18 \n\t") - + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ "sbiw r28, 20 \n\t" /* move y back to point at result */ - + "sbiw r30, 1 \n\t" /* fix stack pointer */ "in r0, __SREG__ \n\t" "cli \n\t" "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + : "+x" (product), [carry] "+r" (carry) : "y" (result) : "r0", "r18", "r19", "r30", "r31", "cc" @@ -517,7 +517,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + "adiw r30, 1 \n\t" /* add 1 since z initially points below the stack */ "adiw r26, 32 \n\t" /* product + uECC_WORDS */ "ldi r25, 0x03 \n\t" @@ -526,12 +526,12 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, x+ \n\t" "ld r20, x+ \n\t" "ld r21, x+ \n\t" - + "mul r24, r18 \n\t" "st z+, r0 \n\t" "mov r22, r1 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r19 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" /* can't overflow */ @@ -540,7 +540,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" /* can't overflow */ "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + "mul r24, r20 \n\t" "add r23, r0 \n\t" "adc r22, r1 \n\t" @@ -549,7 +549,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r21 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" @@ -558,7 +558,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + /* now we start adding the 2^32 part as well */ "add r23, r18 \n\t" // 28 "adc r22, r22 \n\t" @@ -571,7 +571,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r19 \n\t" // 27 "adc r23, r23 \n\t" "ld r19, x+ \n\t" @@ -583,7 +583,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + REPEAT(6, // 26 - 3 "add r23, r20 \n\t" "adc r22, r22 \n\t" @@ -596,7 +596,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" "adc r23, r23 \n\t" "ld r21, x+ \n\t" @@ -608,7 +608,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r18 \n\t" "adc r22, r22 \n\t" "ld r18, x+ \n\t" @@ -620,7 +620,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r19 \n\t" "adc r23, r23 \n\t" "ld r19, x+ \n\t" @@ -644,7 +644,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" // 1 "adc r23, r23 \n\t" "ld r21, x+ \n\t" @@ -656,7 +656,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + /* Now finish the carries etc */ "add r23, r18 \n\t" "adc r22, r22 \n\t" @@ -665,27 +665,27 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r19 \n\t" "adc r23, r23 \n\t" "st z+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r20 \n\t" "adc r22, r22 \n\t" "st z+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" "adc r23, r23 \n\t" "st z+, r22 \n\t" "st z+, r23 \n\t" "eor r1, r1 \n\t" /* make r1 be 0 again */ - + "sbiw r30, 37 \n\t" /* move z back to point at tmp */ "subi r26, 64 \n\t" /* move x back to point at product */ "sbc r27, __zero_reg__ \n\t" - + /* add low bytes of tmp to product, storing in result */ "ld r18, z+ \n\t" "ld r19, x+ \n\t" @@ -696,7 +696,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, x+ \n\t" "adc r18, r19 \n\t" "st y+, r18 \n\t") - + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ /* at this point x is at the end of product, y is at the end of result, z is 32 bytes into tmp */ @@ -710,12 +710,12 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, z+ \n\t" "ld r20, z+ \n\t" "ld r21, z+ \n\t" - + "mul r24, r18 \n\t" "st x+, r0 \n\t" "mov r22, r1 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r19 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" /* can't overflow */ @@ -724,7 +724,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" /* can't overflow */ "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "mul r24, r20 \n\t" "add r23, r0 \n\t" "adc r22, r1 \n\t" @@ -733,7 +733,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st x+, r23 \n\t" "ldi r23, 0 \n\t" - + "mul r24, r21 \n\t" "add r22, r0 \n\t" "adc r23, r1 \n\t" @@ -742,7 +742,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r18 \n\t" "adc r22, r22 \n\t" "ld r18, z+ \n\t" @@ -754,7 +754,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r22, r1 \n\t" "st x+, r23 \n\t" "ldi r23, 0 \n\t" - + /* Now finish the carries etc */ "add r22, r19 \n\t" "adc r23, r23 \n\t" @@ -763,23 +763,23 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "adc r23, r1 \n\t" "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r20 \n\t" "adc r22, r22 \n\t" "st x+, r23 \n\t" "ldi r23, 0 \n\t" - + "add r22, r21 \n\t" "adc r23, r23 \n\t" "st x+, r22 \n\t" "ldi r22, 0 \n\t" - + "add r23, r18 \n\t" "adc r22, r22 \n\t" "st x+, r23 \n\t" "st x+, r22 \n\t" "eor r1, r1 \n\t" /* make r1 be 0 again */ - + /* now z points to the end of tmp, x points to the end of product (y still points at result) */ "sbiw r26, 10 \n\t" /* move x back to point at beginning of actual data */ @@ -793,28 +793,28 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { "ld r19, y \n\t" "adc r18, r19 \n\t" "st y+, r18 \n\t") - + /* Done adding, now propagate carry bit */ REPEAT(22, "ld r18, y \n\t" "adc r18, __zero_reg__ \n\t" "st y+, r18 \n\t") - + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ "sbiw r28, 32 \n\t" /* move y back to point at result */ - + "sbiw r30, 1 \n\t" /* fix stack pointer */ "in r0, __SREG__ \n\t" "cli \n\t" "out __SP_H__, r31 \n\t" "out __SREG__, r0 \n\t" "out __SP_L__, r30 \n\t" - + : "+x" (product), [carry] "+r" (carry) : "y" (result) : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc" ); - + if (carry > 0) { --carry; uECC_vli_sub(result, result, curve_secp256k1.p, 32); @@ -845,7 +845,7 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, __asm__ volatile ( "clc \n\t" - + "1: \n\t" "ld %[left], x+ \n\t" /* Load left byte. */ "ld %[right], y+ \n\t" /* Load right byte. */ @@ -853,12 +853,12 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, "st z+, %[left] \n\t" /* Store the result. */ "dec %[i] \n\t" "brne 1b \n\t" - + "adc %[carry], %[carry] \n\t" /* Store carry bit. */ : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), [carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte) - : + : : "cc" ); return carry; @@ -878,7 +878,7 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, __asm__ volatile ( "clc \n\t" - + "1: \n\t" "ld %[left], x+ \n\t" /* Load left byte. */ "ld %[right], y+ \n\t" /* Load right byte. */ @@ -886,10 +886,10 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, "st z+, %[left] \n\t" /* Store the result. */ "dec %[i] \n\t" "brne 1b \n\t" - + "adc %[borrow], %[borrow] \n\t" /* Store carry bit in borrow. */ - : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (i), [borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte) : : "cc" @@ -911,86 +911,86 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, uint8_t r2 = 0; uint8_t zero = 0; uint8_t k, i; - + __asm__ volatile ( "ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */ - + "1: \n\t" "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ - + "add r28, %[k] \n\t" /* pre-add right ptr */ "adc r29, %[zero] \n\t" - + "2: \n\t" "ld r0, x+ \n\t" "ld r1, -y \n\t" "mul r0, r1 \n\t" - + "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "inc %[i] \n\t" "cp %[i], %[k] \n\t" "brlo 2b \n\t" /* loop if i < k */ - + "sub r26, %[k] \n\t" /* fix up left ptr */ "sbc r27, %[zero] \n\t" - + "st z+, %[r0] \n\t" /* Store the result. */ "mov %[r0], %[r1] \n\t" "mov %[r1], %[r2] \n\t" "mov %[r2], %[zero] \n\t" - + "inc %[k] \n\t" "cp %[k], %[num] \n\t" "brlo 1b \n\t" /* loop if k < num_words */ - + /* second half */ "mov %[k], %[num] \n\t" /* k = num_words; k > 0; --k */ "add r28, %[num] \n\t" /* move right ptr to point at the end of right */ "adc r29, %[zero] \n\t" - + "1: \n\t" "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ - + "2: \n\t" "ld r0, x+ \n\t" "ld r1, -y \n\t" "mul r0, r1 \n\t" - + "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "inc %[i] \n\t" "cp %[i], %[k] \n\t" "brlo 2b \n\t" /* loop if i < k */ - + "add r28, %[k] \n\t" /* fix up right ptr */ "adc r29, %[zero] \n\t" - + "st z+, %[r0] \n\t" /* Store the result. */ "mov %[r0], %[r1] \n\t" "mov %[r1], %[r2] \n\t" "mov %[r2], %[zero] \n\t" - + "dec %[k] \n\t" "sub r26, %[k] \n\t" /* fix up left ptr (after k is decremented, so next time we start 1 higher) */ "sbc r27, %[zero] \n\t" - + "cp %[k], %[zero] \n\t" "brne 1b \n\t" /* loop if k > 0 */ - + "st z+, %[r0] \n\t" /* Store last result byte. */ "eor r1, r1 \n\t" /* fix r1 to be 0 again */ - + : "+z" (result), "+x" (left), "+y" (right), [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero), [num] "+r" (num_words), [k] "=&r" (k), [i] "=&r" (i) - : + : : "r0", "cc" ); } @@ -1007,18 +1007,18 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, uint8_t r2 = 0; uint8_t zero = 0; uint8_t k; - + __asm__ volatile ( "ldi %[k], 1 \n\t" /* k = 1; k < num_words * 2; ++k */ - + "1: \n\t" - + "movw r26, %[orig] \n\t" /* copy orig ptr to 'left' ptr */ "movw r30, %[orig] \n\t" /* copy orig ptr to 'right' ptr */ "cp %[k], %[num] \n\t" "brlo 2f \n\t" "breq 2f \n\t" - + /* when k > num_words, we start from (k - num_words) on the 'left' ptr */ "add r26, %[k] \n\t" "adc r27, %[zero] \n\t" @@ -1027,11 +1027,11 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "add r30, %[num] \n\t" /* move right ptr to point at the end */ "adc r31, %[zero] \n\t" "rjmp 3f \n\t" - + "2: \n\t" /* when k <= num_words, we add k to the 'right' ptr */ "add r30, %[k] \n\t" /* pre-add 'right' ptr */ "adc r31, %[zero] \n\t" - + "3: \n\t" "ld r0, x+ \n\t" "cp r26, r30 \n\t" /* if left == right here, then we are done after this mult @@ -1039,7 +1039,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "breq 4f \n\t" "ld r1, -z \n\t" "mul r0, r1 \n\t" - + /* add twice since it costs the same as doubling */ "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" @@ -1047,18 +1047,18 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "cpse r26, r30 \n\t" /* if left == right here, then we are done */ "rjmp 3b \n\t" "rjmp 5f \n\t" /* skip code for non-doubled mult */ - + "4: \n\t" "ld r1, -z \n\t" "mul r0, r1 \n\t" "add %[r0], r0 \n\t" "adc %[r1], r1 \n\t" "adc %[r2], %[zero] \n\t" - + "5: \n\t" "movw r30, %[result] \n\t" /* make z point to result */ "st z+, %[r0] \n\t" /* Store the result. */ @@ -1066,15 +1066,15 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, "mov %[r0], %[r1] \n\t" "mov %[r1], %[r2] \n\t" "mov %[r2], %[zero] \n\t" - + "inc %[k] \n\t" "cp %[k], %[max] \n\t" "brlo 1b \n\t" /* loop if k < num_words * 2 */ - + "movw r30, %[result] \n\t" /* make z point to result */ "st z+, %[r0] \n\t" /* Store last result byte. */ "eor r1, r1 \n\t" /* fix r1 to be 0 again */ - + : [result] "+r" (r), [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero), [k] "=&a" (k) diff --git a/deps/micro-ecc/emk_project.py b/deps/micro-ecc/emk_project.py index 957dd7920..940fadc2a 100644 --- a/deps/micro-ecc/emk_project.py +++ b/deps/micro-ecc/emk_project.py @@ -12,11 +12,6 @@ c_link_flags = [] cxx_link_flags = ["-fno-rtti", "-fno-exceptions"] -if "root" in emk.options: - root = emk.options["root"] -else: - root = "/" - def setup_build_dir(): build_arch = None if "arch" in emk.options: @@ -59,9 +54,9 @@ def setup_avr(): global c global link - c.compiler = c.GccCompiler(root + "Projects/avr-tools/bin/avr-") + c.compiler = c.GccCompiler("/Projects/avr-tools/bin/avr-") c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"] - link.linker = link.GccLinker(root + "Projects/avr-tools/bin/avr-") + link.linker = link.GccLinker("/Projects/avr-tools/bin/avr-") link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"] link.strip = True @@ -71,30 +66,30 @@ def setup_arm_thumb(): global asm global utils - asm.assembler = asm.GccAssembler(root + "cross/arm_cortex/bin/arm-none-eabi-") - c.compiler = c.GccCompiler(root + "cross/arm_cortex/bin/arm-none-eabi-") - link.linker = link.GccLinker(root + "cross/arm_cortex/bin/arm-none-eabi-") + asm.assembler = asm.GccAssembler("/cross/arm_cortex/bin/arm-none-eabi-") + c.compiler = c.GccCompiler("/cross/arm_cortex/bin/arm-none-eabi-") + link.linker = link.GccLinker("/cross/arm_cortex/bin/arm-none-eabi-") c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"]) c.defines["LPC11XX"] = 1 - + link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"]) - link.local_flags.extend(["-Tflash.lds", "-L" + root + "Projects/lpc11xx/core", root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"]) + link.local_flags.extend(["-Tflash.lds", "-L/Projects/lpc11xx/core", "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"]) link.local_syslibs += ["gcc"] - link.depdirs += [root + "Projects/lpc11xx/stdlib"] + link.depdirs += ["/Projects/lpc11xx/stdlib"] def do_objcopy(produces, requires): - utils.call(root + "cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0]) + utils.call("/cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0]) def handle_exe(path): - emk.depend(path, root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o") + emk.depend(path, "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o") emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True) emk.autobuild(path + ".bin") link.exe_funcs.append(handle_exe) link.strip = True - - emk.recurse(root + "Projects/lpc11xx/core") + + emk.recurse("/Projects/lpc11xx/core") def setup_linux_rpi(): global c @@ -102,7 +97,7 @@ def setup_linux_rpi(): c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") - + c.flags.extend(["-fomit-frame-pointer"]) setup_build_dir() diff --git a/deps/micro-ecc/library.properties b/deps/micro-ecc/library.properties deleted file mode 100644 index 390bdc87a..000000000 --- a/deps/micro-ecc/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=micro-ecc -version=1.0.0 -author=Kenneth MacKay -maintainer=Kenneth MacKay -sentence=uECC -paragraph=A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors. -category=Other -url=https://github.com/kmackay/micro-ecc -architectures=* diff --git a/deps/micro-ecc/platform-specific.inc b/deps/micro-ecc/platform-specific.inc index 7e0373f50..1bb595adc 100644 --- a/deps/micro-ecc/platform-specific.inc +++ b/deps/micro-ecc/platform-specific.inc @@ -8,10 +8,6 @@ #if (defined(_WIN32) || defined(_WIN64)) /* Windows */ -// use pragma syntax to prevent tweaking the linker script for getting CryptXYZ function -#pragma comment(lib, "crypt32.lib") -#pragma comment(lib, "advapi32.lib") - #define WIN32_LEAN_AND_MEAN #include #include @@ -66,29 +62,6 @@ static int default_RNG(uint8_t *dest, unsigned size) { } #define default_RNG_defined 1 -#elif defined(RIOT_VERSION) - -#include - -static int default_RNG(uint8_t *dest, unsigned size) { - random_bytes(dest, size); - return 1; -} -#define default_RNG_defined 1 - -#elif defined(NRF52_SERIES) - -#include "app_error.h" -#include "nrf_crypto_rng.h" - -static int default_RNG(uint8_t *dest, unsigned size) -{ - // make sure to call nrf_crypto_init and nrf_crypto_rng_init first - ret_code_t ret_code = nrf_crypto_rng_vector_generate(dest, size); - return (ret_code == NRF_SUCCESS) ? 1 : 0; -} -#define default_RNG_defined 1 - #endif /* platform */ #endif /* _UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/deps/micro-ecc/examples/ecc_test/ecc_test.ino b/deps/micro-ecc/test/ecc_test/ecc_test.ino similarity index 98% rename from deps/micro-ecc/examples/ecc_test/ecc_test.ino rename to deps/micro-ecc/test/ecc_test/ecc_test.ino index 64a0be50f..c3c8900d8 100644 --- a/deps/micro-ecc/examples/ecc_test/ecc_test.ino +++ b/deps/micro-ecc/test/ecc_test/ecc_test.ino @@ -1,5 +1,7 @@ #include +extern "C" { + static int RNG(uint8_t *dest, unsigned size) { // Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of // random noise). This can take a long time to generate random data if the result of analogRead(0) @@ -27,6 +29,8 @@ static int RNG(uint8_t *dest, unsigned size) { return 1; } +} // extern "C" + void setup() { Serial.begin(115200); Serial.print("Testing ecc\n"); @@ -78,3 +82,4 @@ void loop() { Serial.print("Shared secrets are identical\n"); } } + diff --git a/deps/micro-ecc/test/ecdsa_test_vectors.c b/deps/micro-ecc/test/ecdsa_test_vectors.c deleted file mode 100644 index 1e902b266..000000000 --- a/deps/micro-ecc/test/ecdsa_test_vectors.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright 2020, Kenneth MacKay. Licensed under the BSD 2-clause license. */ - -#include "uECC.h" - -#include -#include -#include - -typedef struct { - const char* private_key; - const char* public_key; - const char* k; - const char* hash; - const char* r; - const char* s; -} Test; - -Test secp256k1_tests[] = { - { - "ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f", - "779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcde94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f", - "49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a", - "4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a", - "241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795", - "021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e" - }, -}; - -extern int uECC_sign_with_k(const uint8_t *private_key, - const uint8_t *message_hash, - unsigned hash_size, - const uint8_t *k, - uint8_t *signature, - uECC_Curve curve); - - -void vli_print(uint8_t *vli, unsigned int size) { - for(unsigned i=0; i -#include -#include - -typedef struct { - const char* k; - const char* Q; - int success; -} Test; - -Test secp160r1_tests[] = { - /* Note, I couldn't find any test vectors for secp160r1 online, so these are just - generated on my desktop using uECC. */ - { - "000000000000000000000000000000000000000000", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { - "000000000000000000000000000000000000000001", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { - "000000000000000000000000000000000000000002", - "02F997F33C5ED04C55D3EDF8675D3E92E8F46686F083A323482993E9440E817E21CFB7737DF8797B", - 1 - }, - { - "000000000000000000000000000000000000000003", - "7B76FF541EF363F2DF13DE1650BD48DAA958BC59C915CA790D8C8877B55BE0079D12854FFE9F6F5A", - 1 - }, - { /* n - 4 */ - "0100000000000000000001F4C8F927AED3CA752253", - "B4041D8683BE99F0AFE01C307B1AD4C100CF2A88C0CD35127BE0F73FF99F338B350B5A42864112F7", - 1 - }, - { /* n - 3 */ - "0100000000000000000001F4C8F927AED3CA752254", - "7B76FF541EF363F2DF13DE1650BD48DAA958BC5936EA3586F27377884AA41FF862ED7AAF816090A5", - 1 - }, - { /* n - 2 */ - "0100000000000000000001F4C8F927AED3CA752255", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { /* n - 1 */ - "0100000000000000000001F4C8F927AED3CA752256", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { /* n */ - "0100000000000000000001F4C8F927AED3CA752257", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, -}; - - -Test secp192r1_tests[] = { - { - "000000000000000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { - "000000000000000000000000000000000000000000000001", - "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811", - 0 - }, - { - "000000000000000000000000000000000000000000000002", - "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB", - 1 - }, - { - "000000000000000000000000000000000000000000000003", - "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD", - 1 - }, - { /* n - 4 */ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282D", - "35433907297CC378B0015703374729D7A4FE46647084E4BA5D9B667B0DECA3CFE15C534F88932B0DDAC764CEE24C41CD", - 1 - }, - { /* n - 3 */ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282E", - "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA87D3C81C8D45BADF559D1F012EDE2B600C4ABC99F302FA02", - 1 - }, - { /* n - 2 */ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282F", - "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888229425F266C25F05B94D8443EBE4796FA6CCE505A3816C54", - 0 - }, - { /* n - 1 */ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", - "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012F8E6D46A003725879CEFEE1294DB32298C06885EE186B7EE", - 0 - }, - { /* n */ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, -}; - -Test secp224r1_tests[] = { - { - "00000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { - "00000000000000000000000000000000000000000000000000000001", - "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", - 0 - }, - { - "00000000000000000000000000000000000000000000000000000002", - "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA61C2B76A7BC25E7702A704FA986892849FCA629487ACF3709D2E4E8BB", - 1 - }, - { - "00000000000000000000000000000000000000000000000000000003", - "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04A3F7F03CADD0BE444C0AA56830130DDF77D317344E1AF3591981A925", - 1 - }, - { /* n - 4 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A39", - "AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301FB7DA7F5F13A43B81774373C879CD32D6934C05FA758EEB14FCFAB38", - 1 - }, - { /* n - 3 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3A", - "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D045C080FC3522F41BBB3F55A97CFECF21F882CE8CBB1E50CA6E67E56DC", - 1 - }, - { /* n - 2 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3B", - "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6E3D4895843DA188FD58FB0567976D7B50359D6B78530C8F62D1B1746", - 0 - }, - { /* n - 1 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3C", - "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D2142C89C774A08DC04B3DD201932BC8A5EA5F8B89BBB2A7E667AFF81CD", - 0 - }, - { /* n */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, -}; - -Test secp256r1_tests[] = { - { - "0000000000000000000000000000000000000000000000000000000000000000", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { - "0000000000000000000000000000000000000000000000000000000000000001", - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", - 0 - }, - { - "0000000000000000000000000000000000000000000000000000000000000002", - "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC4766997807775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1", - 1 - }, - { - "0000000000000000000000000000000000000000000000000000000000000003", - "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032", - 1 - }, - { /* n - 4 */ - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254D", - "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B0308521F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739", - 1 - }, - { /* n - 3 */ - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E", - "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD", - 1 - }, - { /* n - 2 */ - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F", - "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E", - 0 - }, - { /* n - 1 */ - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550", - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A", - 0 - }, - { /* n */ - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, -}; - -Test secp256k1_tests[] = { - { - "0000000000000000000000000000000000000000000000000000000000000000", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, - { - "0000000000000000000000000000000000000000000000000000000000000001", - "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", - 0 - }, - { - "0000000000000000000000000000000000000000000000000000000000000002", - "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE51AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A", - 1 - }, - { - "0000000000000000000000000000000000000000000000000000000000000003", - "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672", - 1 - }, - { /* n - 4 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413D", - "E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13AE1266C15F2BAA48A9BD1DF6715AEBB7269851CC404201BF30168422B88C630D", - 1 - }, - { /* n - 3 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413E", - "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9C77084F09CD217EBF01CC819D5C80CA99AFF5666CB3DDCE4934602897B4715BD", - 1 - }, - { /* n - 2 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F", - "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5E51E970159C23CC65C3A7BE6B99315110809CD9ACD992F1EDC9BCE55AF301705", - 0 - }, - { /* n - 1 */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", - "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777", - 0 - }, - { /* n */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 0 - }, -}; - - -void vli_print(uint8_t *vli, unsigned int size) { - for(unsigned i=0; i> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); - if (!uECC_vli_isZero(random, num_words) && - uECC_vli_cmp(top, random, num_words) == 1) { - return 1; - } - } - return 0; -} - static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *private_key, uECC_Curve curve) { uECC_word_t tmp1[uECC_MAX_WORDS]; uECC_word_t tmp2[uECC_MAX_WORDS]; uECC_word_t *p2[2] = {tmp1, tmp2}; - uECC_word_t *initial_Z = 0; uECC_word_t carry; /* Regularize the bitcount for the private key so that attackers cannot use a side channel attack to learn the number of leading zeros. */ carry = regularize_k(private_key, tmp1, tmp2, curve); - /* If an RNG function was specified, try to get a random initial Z value to improve - protection against side-channel attacks. */ - if (g_rng_function) { - if (!uECC_generate_random_int(p2[carry], curve->p, curve->num_words)) { - return 0; - } - initial_Z = p2[carry]; - } - EccPoint_mult(result, curve->G, p2[!carry], initial_Z, curve->num_n_bits + 1, curve); + EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); if (EccPoint_isZero(result, curve)) { return 0; @@ -994,7 +954,7 @@ uECC_VLI_API void uECC_vli_bytesToNative(uint8_t *native, uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native) { - int i; + wordcount_t i; for (i = 0; i < num_bytes; ++i) { unsigned b = num_bytes - 1 - i; bytes[i] = (uint8_t)(native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE))); @@ -1004,7 +964,7 @@ uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes) { - int i; + wordcount_t i; uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); for (i = 0; i < num_bytes; ++i) { unsigned b = num_bytes - 1 - i; @@ -1015,6 +975,32 @@ uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, #endif /* uECC_WORD_SIZE */ +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words) { + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + return 0; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random, num_words) && + uECC_vli_cmp(top, random, num_words) == 1) { + return 1; + } + } + return 0; +} + int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve) { @@ -1129,7 +1115,7 @@ void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve } #endif /* uECC_SUPPORT_COMPRESSED_POINT */ -uECC_VLI_API int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { uECC_word_t tmp1[uECC_MAX_WORDS]; uECC_word_t tmp2[uECC_MAX_WORDS]; wordcount_t num_words = curve->num_words; @@ -1224,7 +1210,7 @@ static void bits2int(uECC_word_t *native, bcopy((uint8_t *) native, bits, bits_size); #else uECC_vli_bytesToNative(native, bits, bits_size); -#endif +#endif if (bits_size * 8 <= (unsigned)curve->num_n_bits) { return; } @@ -1243,7 +1229,7 @@ static void bits2int(uECC_word_t *native, } } -static int uECC_sign_with_k_internal(const uint8_t *private_key, +static int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, unsigned hash_size, uECC_word_t *k, @@ -1253,7 +1239,6 @@ static int uECC_sign_with_k_internal(const uint8_t *private_key, uECC_word_t tmp[uECC_MAX_WORDS]; uECC_word_t s[uECC_MAX_WORDS]; uECC_word_t *k2[2] = {tmp, s}; - uECC_word_t *initial_Z = 0; #if uECC_VLI_NATIVE_LITTLE_ENDIAN uECC_word_t *p = (uECC_word_t *)signature; #else @@ -1270,15 +1255,7 @@ static int uECC_sign_with_k_internal(const uint8_t *private_key, } carry = regularize_k(k, tmp, s, curve); - /* If an RNG function was specified, try to get a random initial Z value to improve - protection against side-channel attacks. */ - if (g_rng_function) { - if (!uECC_generate_random_int(k2[carry], curve->p, num_words)) { - return 0; - } - initial_Z = k2[carry]; - } - EccPoint_mult(p, curve->G, k2[!carry], initial_Z, num_n_bits + 1, curve); + EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); if (uECC_vli_isZero(p, num_words)) { return 0; } @@ -1322,22 +1299,10 @@ static int uECC_sign_with_k_internal(const uint8_t *private_key, bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes); #else uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); -#endif +#endif return 1; } -/* For testing - sign with an explicitly specified k value */ -int uECC_sign_with_k(const uint8_t *private_key, - const uint8_t *message_hash, - unsigned hash_size, - const uint8_t *k, - uint8_t *signature, - uECC_Curve curve) { - uECC_word_t k2[uECC_MAX_WORDS]; - bits2int(k2, k, BITS_TO_BYTES(curve->num_n_bits), curve); - return uECC_sign_with_k_internal(private_key, message_hash, hash_size, k2, signature, curve); -} - int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, unsigned hash_size, @@ -1351,7 +1316,7 @@ int uECC_sign(const uint8_t *private_key, return 0; } - if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, k, signature, curve)) { + if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) { return 1; } } @@ -1467,7 +1432,7 @@ int uECC_sign_deterministic(const uint8_t *private_key, mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits)); } - if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, T, signature, curve)) { + if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) { return 1; } @@ -1507,7 +1472,7 @@ int uECC_verify(const uint8_t *public_key, uECC_word_t *_public = (uECC_word_t *)public_key; #else uECC_word_t _public[uECC_MAX_WORDS * 2]; -#endif +#endif uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; wordcount_t num_words = curve->num_words; wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); diff --git a/deps/micro-ecc/uECC.h b/deps/micro-ecc/uECC.h index dcbdbfa8b..991176316 100644 --- a/deps/micro-ecc/uECC.h +++ b/deps/micro-ecc/uECC.h @@ -38,16 +38,13 @@ faster somewhat faster, but increases the code size. */ #endif /* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native -little-endian format for *all* arrays passed in and out of the public API. This includes public -and private keys, shared secrets, signatures and message hashes. +little-endian format for *all* arrays passed in and out of the public API. This includes public +and private keys, shared secrets, signatures and message hashes. Using this switch reduces the amount of call stack memory used by uECC, since less intermediate -translations are required. +translations are required. Note that this will *only* work on native little-endian processors and it will treat the uint8_t -arrays passed into the public API as word arrays, therefore requiring the provided byte arrays -to be word aligned on architectures that do not support unaligned accesses. -IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible -with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use -the same endianness. */ +arrays passed into the public API as word arrays, therefore requiring the provided byte arrays +to be word aligned on architectures that do not support unaligned accesses. */ #ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN #define uECC_VLI_NATIVE_LITTLE_ENDIAN 0 #endif @@ -166,9 +163,7 @@ Returns 1 if the key pair was generated successfully, 0 if an error occurred. int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve); /* uECC_shared_secret() function. -Compute a shared secret given your secret key and someone else's public key. If the public key -is not from a trusted source and has not been previously verified, you should verify it first -using uECC_valid_public_key(). +Compute a shared secret given your secret key and someone else's public key. Note: It is recommended that you hash the result of uECC_shared_secret() before using it for symmetric encryption or HMAC. diff --git a/include/picotls.h b/include/picotls.h index 770fb242d..142b3ed6e 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -612,6 +612,10 @@ typedef struct st_ptls_on_client_hello_parameters_t { * Raw value of the client_hello message. */ ptls_iovec_t raw_message; + /** + * points to the cipher-suites section of the raw_message (see above) + */ + ptls_iovec_t cipher_suites; /** * */ @@ -627,10 +631,6 @@ typedef struct st_ptls_on_client_hello_parameters_t { const uint16_t *list; size_t count; } certificate_compression_algorithms; - struct { - const uint16_t *list; - size_t count; - } cipher_suites; struct { const uint8_t *list; size_t count; diff --git a/lib/picotls.c b/lib/picotls.c index e046f3ed3..25465e0ff 100644 --- a/lib/picotls.c +++ b/lib/picotls.c @@ -41,13 +41,6 @@ #if PICOTLS_USE_DTRACE #include "picotls-probes.h" #endif -#if PARTICLE -#include -#include "/Users/lars/Documents/Code/quant/lib/deps/warpcore/lib/include/warpcore/util.h" -#else -#define LOG_PRINTF(...) -#define hexdump(...) -#endif #define PTLS_MAX_PLAINTEXT_RECORD_SIZE 16384 #define PTLS_MAX_ENCRYPTED_RECORD_SIZE (16384 + 256) @@ -354,7 +347,6 @@ struct st_ptls_client_hello_psk_t { }; #define MAX_UNKNOWN_EXTENSIONS 16 -#define MAX_CLIENT_CIPHERS 32 #define MAX_CERTIFICATE_TYPES 8 struct st_ptls_client_hello_t { @@ -379,10 +371,6 @@ struct st_ptls_client_hello_t { uint16_t list[16]; size_t count; } cert_compression_algos; - struct { - uint16_t list[MAX_CLIENT_CIPHERS]; - size_t count; - } client_ciphers; struct { ptls_iovec_t all; ptls_iovec_t tbs; @@ -2358,10 +2346,8 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ sni_name = tls->server_name; if (properties != NULL) { - LOG_PRINTF(INFO, "properties\n"); /* try to use ECH (ignore broken ECHConfigList; it is delivered insecurely) */ if (!is_second_flight && sni_name != NULL && tls->ctx->ech.client.ciphers != NULL) { - LOG_PRINTF(INFO, "ECH\n"); if (properties->client.ech.configs.len != 0) { struct st_decoded_ech_config_t decoded; client_decode_ech_config_list(tls->ctx, &decoded, properties->client.ech.configs); @@ -2406,10 +2392,8 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ } /* use the default key share if still not undetermined */ - if (tls->key_share == NULL && !(properties != NULL && properties->client.negotiate_before_key_exchange)) { - LOG_PRINTF(INFO, "use the default key share\n"); + if (tls->key_share == NULL && !(properties != NULL && properties->client.negotiate_before_key_exchange)) tls->key_share = tls->ctx->key_exchanges[0]; - } /* instantiate key share context */ assert(tls->client.key_share_ctx == NULL); @@ -2437,11 +2421,9 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ tls->ech.client.first_ech, resumption_secret, resumption_ticket, obfuscated_ticket_age, tls->key_schedule->hashes[0].algo->digest_size, cookie, tls->client.using_early_data)) != 0) goto Exit; - hexdump(emitter->buf->base, emitter->buf->off); /* update the message hash, filling in the PSK binder HMAC if necessary */ if (resumption_secret.base != NULL) { - LOG_PRINTF(INFO, "resumption_secret\n"); size_t psk_binder_off = emitter->buf->off - (3 + tls->key_schedule->hashes[0].algo->digest_size); if ((ret = derive_secret_with_empty_digest(tls->key_schedule, binder_key, "res binder")) != 0) goto Exit; @@ -2454,7 +2436,6 @@ static int send_client_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptls_ /* ECH */ if (tls->ech.aead != NULL) { - LOG_PRINTF(INFO, "ECH\n"); /* build EncodedCHInner */ if ((ret = encode_client_hello(tls->ctx, &encoded_ch_inner, ENCODE_CH_MODE_ENCODED_INNER, is_second_flight, properties, tls->ech.inner_client_random, tls->client.key_share_ctx, sni_name, @@ -3641,18 +3622,12 @@ static int decode_client_hello(ptls_context_t *ctx, struct st_ptls_client_hello_ /* decode and select from ciphersuites */ ptls_decode_open_block(src, end, 2, { + if ((end - src) % 2 != 0) { + ret = PTLS_ALERT_DECODE_ERROR; + goto Exit; + } ch->cipher_suites = ptls_iovec_init(src, end - src); - uint16_t *id = ch->client_ciphers.list; - do { - if ((ret = ptls_decode16(id, &src, end)) != 0) - goto Exit; - id++; - ch->client_ciphers.count++; - if (id >= ch->client_ciphers.list + MAX_CLIENT_CIPHERS) { - src = end; - break; - } - } while (src != end); + src = end; }); /* decode legacy_compression_methods */ @@ -4013,10 +3988,10 @@ static int rebuild_ch_inner(ptls_buffer_t *buf, const uint8_t *src, const uint8_ /* Wrapper function for invoking the on_client_hello callback, taking an exhaustive list of parameters as arguments. The intention * is to not miss setting them as we add new parameters to the struct. */ -static inline int call_on_client_hello_cb(ptls_t *tls, ptls_iovec_t server_name, ptls_iovec_t raw_message, ptls_iovec_t *alpns, - size_t num_alpns, const uint16_t *sig_algos, size_t num_sig_algos, - const uint16_t *cert_comp_algos, size_t num_cert_comp_algos, - const uint16_t *cipher_suites, size_t num_cipher_suites, const uint8_t *server_cert_types, +static inline int call_on_client_hello_cb(ptls_t *tls, ptls_iovec_t server_name, ptls_iovec_t raw_message, + ptls_iovec_t cipher_suites, ptls_iovec_t *alpns, size_t num_alpns, + const uint16_t *sig_algos, size_t num_sig_algos, const uint16_t *cert_comp_algos, + size_t num_cert_comp_algos, const uint8_t *server_cert_types, size_t num_server_cert_types, int incompatible_version) { if (tls->ctx->on_client_hello == NULL) @@ -4024,10 +3999,10 @@ static inline int call_on_client_hello_cb(ptls_t *tls, ptls_iovec_t server_name, ptls_on_client_hello_parameters_t params = {server_name, raw_message, + cipher_suites, {alpns, num_alpns}, {sig_algos, num_sig_algos}, {cert_comp_algos, num_cert_comp_algos}, - {cipher_suites, num_cipher_suites}, {server_cert_types, num_server_cert_types}, incompatible_version}; return tls->ctx->on_client_hello->cb(tls->ctx->on_client_hello, tls, ¶ms); @@ -4051,8 +4026,8 @@ static int check_client_hello_constraints(ptls_context_t *ctx, struct st_ptls_cl /* fail with PROTOCOL_VERSION alert, after providing the applications the raw CH and SNI to help them fallback */ if (!is_second_flight) { int ret; - if ((ret = call_on_client_hello_cb(tls_cbarg, ch->server_name, raw_message, ch->alpn.list, ch->alpn.count, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 1)) != 0) + if ((ret = call_on_client_hello_cb(tls_cbarg, ch->server_name, raw_message, ch->cipher_suites, ch->alpn.list, + ch->alpn.count, NULL, 0, NULL, 0, NULL, 0, 1)) != 0) return ret; } return PTLS_ALERT_PROTOCOL_VERSION; @@ -4421,9 +4396,9 @@ static int server_handle_hello(ptls_t *tls, ptls_message_emitter_t *emitter, ptl ptls_iovec_t server_name = {NULL}; if (ch->server_name.base != NULL) server_name = ch->server_name; - if ((ret = call_on_client_hello_cb(tls, server_name, message, ch->alpn.list, ch->alpn.count, ch->signature_algorithms.list, - ch->signature_algorithms.count, ch->cert_compression_algos.list, - ch->cert_compression_algos.count, ch->client_ciphers.list, ch->client_ciphers.count, + if ((ret = call_on_client_hello_cb(tls, server_name, message, ch->cipher_suites, ch->alpn.list, ch->alpn.count, + ch->signature_algorithms.list, ch->signature_algorithms.count, + ch->cert_compression_algos.list, ch->cert_compression_algos.count, ch->server_certificate_types.list, ch->server_certificate_types.count, 0)) != 0) goto Exit; if (!certificate_type_exists(ch->server_certificate_types.list, ch->server_certificate_types.count, @@ -5147,8 +5122,7 @@ int ptls_export(ptls_t *tls, ptls_buffer_t *output) ptls_iovec_t negotiated_protocol = ptls_iovec_init(tls->negotiated_protocol, tls->negotiated_protocol != NULL ? strlen(tls->negotiated_protocol) : 0); - return export_tls12_params(output, ptls_is_server(tls), tls->is_psk_handshake, tls->cipher_suite, tls->client_random, - tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, + return export_tls12_params(output, ptls_is_server(tls), tls->is_psk_handshake, tls->cipher_suite, tls->client_random, tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret, tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq, tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret, tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq); diff --git a/lib/uecc.c b/lib/uecc.c index 0ebb836a8..5d42b3b6f 100644 --- a/lib/uecc.c +++ b/lib/uecc.c @@ -33,10 +33,6 @@ #include "uECC_vli.h" #include "picotls.h" #include "picotls/minicrypto.h" -#include "/Users/lars/Documents/Code/quant/lib/deps/warpcore/lib/include/warpcore/util.h" -#if PARTICLE -#include -#endif #define TYPE_UNCOMPRESSED_PUBLIC_KEY 4 @@ -85,7 +81,6 @@ static int secp256r1_on_exchange(ptls_key_exchange_context_t **_ctx, int release static int secp256r1_create_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **_ctx) { - LOG_PRINTF(INFO, "secp256r1_create_key_exchange\n"); struct st_secp256r1_key_exhchange_t *ctx; if ((ctx = (struct st_secp256r1_key_exhchange_t *)malloc(sizeof(*ctx))) == NULL) @@ -93,8 +88,7 @@ static int secp256r1_create_key_exchange(ptls_key_exchange_algorithm_t *algo, pt ctx->super = (ptls_key_exchange_context_t){algo, ptls_iovec_init(ctx->pub, sizeof(ctx->pub)), secp256r1_on_exchange}; ctx->pub[0] = TYPE_UNCOMPRESSED_PUBLIC_KEY; uECC_make_key(ctx->pub + 1, ctx->priv, uECC_secp256r1()); - hexdump(ctx->pub, SECP256R1_PUBLIC_KEY_SIZE); - hexdump(ctx->priv, SECP256R1_PRIVATE_KEY_SIZE); + *_ctx = &ctx->super; return 0; } @@ -102,7 +96,6 @@ static int secp256r1_create_key_exchange(ptls_key_exchange_algorithm_t *algo, pt static int secp256r1_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey) { - LOG_PRINTF(INFO, "secp256r1_key_exchange\n"); uint8_t priv[SECP256R1_PRIVATE_KEY_SIZE], *pub = NULL, *secbytes = NULL; int ret; @@ -126,9 +119,7 @@ static int secp256r1_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iove goto Exit; } *pubkey = ptls_iovec_init(pub, SECP256R1_PUBLIC_KEY_SIZE); - hexdump(pub, SECP256R1_PUBLIC_KEY_SIZE); *secret = ptls_iovec_init(secbytes, SECP256R1_SHARED_SECRET_SIZE); - hexdump(secret, SECP256R1_SHARED_SECRET_SIZE); ret = 0; Exit: