1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * Example ECDSA program 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci */ 7a8e1175bSopenharmony_ci 8a8e1175bSopenharmony_ci#include "mbedtls/build_info.h" 9a8e1175bSopenharmony_ci 10a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 11a8e1175bSopenharmony_ci 12a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDSA_C) && \ 13a8e1175bSopenharmony_ci defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C) 14a8e1175bSopenharmony_ci#include "mbedtls/entropy.h" 15a8e1175bSopenharmony_ci#include "mbedtls/ctr_drbg.h" 16a8e1175bSopenharmony_ci#include "mbedtls/ecdsa.h" 17a8e1175bSopenharmony_ci#include "mbedtls/sha256.h" 18a8e1175bSopenharmony_ci 19a8e1175bSopenharmony_ci#include <string.h> 20a8e1175bSopenharmony_ci#endif 21a8e1175bSopenharmony_ci 22a8e1175bSopenharmony_ci/* 23a8e1175bSopenharmony_ci * Uncomment to show key and signature details 24a8e1175bSopenharmony_ci */ 25a8e1175bSopenharmony_ci#define VERBOSE 26a8e1175bSopenharmony_ci 27a8e1175bSopenharmony_ci/* 28a8e1175bSopenharmony_ci * Uncomment to force use of a specific curve 29a8e1175bSopenharmony_ci */ 30a8e1175bSopenharmony_ci#define ECPARAMS MBEDTLS_ECP_DP_SECP192R1 31a8e1175bSopenharmony_ci 32a8e1175bSopenharmony_ci#if !defined(ECPARAMS) 33a8e1175bSopenharmony_ci#define ECPARAMS mbedtls_ecp_curve_list()->grp_id 34a8e1175bSopenharmony_ci#endif 35a8e1175bSopenharmony_ci 36a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECDSA_C) || !defined(MBEDTLS_SHA256_C) || \ 37a8e1175bSopenharmony_ci !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) 38a8e1175bSopenharmony_ciint main(void) 39a8e1175bSopenharmony_ci{ 40a8e1175bSopenharmony_ci mbedtls_printf("MBEDTLS_ECDSA_C and/or MBEDTLS_SHA256_C and/or " 41a8e1175bSopenharmony_ci "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C not defined\n"); 42a8e1175bSopenharmony_ci mbedtls_exit(0); 43a8e1175bSopenharmony_ci} 44a8e1175bSopenharmony_ci#else 45a8e1175bSopenharmony_ci#if defined(VERBOSE) 46a8e1175bSopenharmony_cistatic void dump_buf(const char *title, unsigned char *buf, size_t len) 47a8e1175bSopenharmony_ci{ 48a8e1175bSopenharmony_ci size_t i; 49a8e1175bSopenharmony_ci 50a8e1175bSopenharmony_ci mbedtls_printf("%s", title); 51a8e1175bSopenharmony_ci for (i = 0; i < len; i++) { 52a8e1175bSopenharmony_ci mbedtls_printf("%c%c", "0123456789ABCDEF" [buf[i] / 16], 53a8e1175bSopenharmony_ci "0123456789ABCDEF" [buf[i] % 16]); 54a8e1175bSopenharmony_ci } 55a8e1175bSopenharmony_ci mbedtls_printf("\n"); 56a8e1175bSopenharmony_ci} 57a8e1175bSopenharmony_ci 58a8e1175bSopenharmony_cistatic void dump_pubkey(const char *title, mbedtls_ecdsa_context *key) 59a8e1175bSopenharmony_ci{ 60a8e1175bSopenharmony_ci unsigned char buf[300]; 61a8e1175bSopenharmony_ci size_t len; 62a8e1175bSopenharmony_ci 63a8e1175bSopenharmony_ci if (mbedtls_ecp_write_public_key(key, MBEDTLS_ECP_PF_UNCOMPRESSED, 64a8e1175bSopenharmony_ci &len, buf, sizeof(buf)) != 0) { 65a8e1175bSopenharmony_ci mbedtls_printf("internal error\n"); 66a8e1175bSopenharmony_ci return; 67a8e1175bSopenharmony_ci } 68a8e1175bSopenharmony_ci 69a8e1175bSopenharmony_ci dump_buf(title, buf, len); 70a8e1175bSopenharmony_ci} 71a8e1175bSopenharmony_ci#else 72a8e1175bSopenharmony_ci#define dump_buf(a, b, c) 73a8e1175bSopenharmony_ci#define dump_pubkey(a, b) 74a8e1175bSopenharmony_ci#endif 75a8e1175bSopenharmony_ci 76a8e1175bSopenharmony_ci 77a8e1175bSopenharmony_ciint main(int argc, char *argv[]) 78a8e1175bSopenharmony_ci{ 79a8e1175bSopenharmony_ci int ret = 1; 80a8e1175bSopenharmony_ci int exit_code = MBEDTLS_EXIT_FAILURE; 81a8e1175bSopenharmony_ci mbedtls_ecdsa_context ctx_sign, ctx_verify; 82a8e1175bSopenharmony_ci mbedtls_ecp_point Q; 83a8e1175bSopenharmony_ci mbedtls_ecp_point_init(&Q); 84a8e1175bSopenharmony_ci mbedtls_entropy_context entropy; 85a8e1175bSopenharmony_ci mbedtls_ctr_drbg_context ctr_drbg; 86a8e1175bSopenharmony_ci unsigned char message[100]; 87a8e1175bSopenharmony_ci unsigned char hash[32]; 88a8e1175bSopenharmony_ci unsigned char sig[MBEDTLS_ECDSA_MAX_LEN]; 89a8e1175bSopenharmony_ci size_t sig_len; 90a8e1175bSopenharmony_ci const char *pers = "ecdsa"; 91a8e1175bSopenharmony_ci ((void) argv); 92a8e1175bSopenharmony_ci 93a8e1175bSopenharmony_ci mbedtls_ecdsa_init(&ctx_sign); 94a8e1175bSopenharmony_ci mbedtls_ecdsa_init(&ctx_verify); 95a8e1175bSopenharmony_ci mbedtls_ctr_drbg_init(&ctr_drbg); 96a8e1175bSopenharmony_ci 97a8e1175bSopenharmony_ci memset(sig, 0, sizeof(sig)); 98a8e1175bSopenharmony_ci memset(message, 0x25, sizeof(message)); 99a8e1175bSopenharmony_ci 100a8e1175bSopenharmony_ci if (argc != 1) { 101a8e1175bSopenharmony_ci mbedtls_printf("usage: ecdsa\n"); 102a8e1175bSopenharmony_ci 103a8e1175bSopenharmony_ci#if defined(_WIN32) 104a8e1175bSopenharmony_ci mbedtls_printf("\n"); 105a8e1175bSopenharmony_ci#endif 106a8e1175bSopenharmony_ci 107a8e1175bSopenharmony_ci goto exit; 108a8e1175bSopenharmony_ci } 109a8e1175bSopenharmony_ci 110a8e1175bSopenharmony_ci /* 111a8e1175bSopenharmony_ci * Generate a key pair for signing 112a8e1175bSopenharmony_ci */ 113a8e1175bSopenharmony_ci mbedtls_printf("\n . Seeding the random number generator..."); 114a8e1175bSopenharmony_ci fflush(stdout); 115a8e1175bSopenharmony_ci 116a8e1175bSopenharmony_ci mbedtls_entropy_init(&entropy); 117a8e1175bSopenharmony_ci if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 118a8e1175bSopenharmony_ci (const unsigned char *) pers, 119a8e1175bSopenharmony_ci strlen(pers))) != 0) { 120a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret); 121a8e1175bSopenharmony_ci goto exit; 122a8e1175bSopenharmony_ci } 123a8e1175bSopenharmony_ci 124a8e1175bSopenharmony_ci mbedtls_printf(" ok\n . Generating key pair..."); 125a8e1175bSopenharmony_ci fflush(stdout); 126a8e1175bSopenharmony_ci 127a8e1175bSopenharmony_ci if ((ret = mbedtls_ecdsa_genkey(&ctx_sign, ECPARAMS, 128a8e1175bSopenharmony_ci mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) { 129a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ecdsa_genkey returned %d\n", ret); 130a8e1175bSopenharmony_ci goto exit; 131a8e1175bSopenharmony_ci } 132a8e1175bSopenharmony_ci 133a8e1175bSopenharmony_ci mbedtls_ecp_group_id grp_id = mbedtls_ecp_keypair_get_group_id(&ctx_sign); 134a8e1175bSopenharmony_ci const mbedtls_ecp_curve_info *curve_info = 135a8e1175bSopenharmony_ci mbedtls_ecp_curve_info_from_grp_id(grp_id); 136a8e1175bSopenharmony_ci mbedtls_printf(" ok (key size: %d bits)\n", (int) curve_info->bit_size); 137a8e1175bSopenharmony_ci 138a8e1175bSopenharmony_ci dump_pubkey(" + Public key: ", &ctx_sign); 139a8e1175bSopenharmony_ci 140a8e1175bSopenharmony_ci /* 141a8e1175bSopenharmony_ci * Compute message hash 142a8e1175bSopenharmony_ci */ 143a8e1175bSopenharmony_ci mbedtls_printf(" . Computing message hash..."); 144a8e1175bSopenharmony_ci fflush(stdout); 145a8e1175bSopenharmony_ci 146a8e1175bSopenharmony_ci if ((ret = mbedtls_sha256(message, sizeof(message), hash, 0)) != 0) { 147a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_sha256 returned %d\n", ret); 148a8e1175bSopenharmony_ci goto exit; 149a8e1175bSopenharmony_ci } 150a8e1175bSopenharmony_ci 151a8e1175bSopenharmony_ci mbedtls_printf(" ok\n"); 152a8e1175bSopenharmony_ci 153a8e1175bSopenharmony_ci dump_buf(" + Hash: ", hash, sizeof(hash)); 154a8e1175bSopenharmony_ci 155a8e1175bSopenharmony_ci /* 156a8e1175bSopenharmony_ci * Sign message hash 157a8e1175bSopenharmony_ci */ 158a8e1175bSopenharmony_ci mbedtls_printf(" . Signing message hash..."); 159a8e1175bSopenharmony_ci fflush(stdout); 160a8e1175bSopenharmony_ci 161a8e1175bSopenharmony_ci if ((ret = mbedtls_ecdsa_write_signature(&ctx_sign, MBEDTLS_MD_SHA256, 162a8e1175bSopenharmony_ci hash, sizeof(hash), 163a8e1175bSopenharmony_ci sig, sizeof(sig), &sig_len, 164a8e1175bSopenharmony_ci mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) { 165a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ecdsa_write_signature returned %d\n", ret); 166a8e1175bSopenharmony_ci goto exit; 167a8e1175bSopenharmony_ci } 168a8e1175bSopenharmony_ci mbedtls_printf(" ok (signature length = %u)\n", (unsigned int) sig_len); 169a8e1175bSopenharmony_ci 170a8e1175bSopenharmony_ci dump_buf(" + Signature: ", sig, sig_len); 171a8e1175bSopenharmony_ci 172a8e1175bSopenharmony_ci /* 173a8e1175bSopenharmony_ci * Transfer public information to verifying context 174a8e1175bSopenharmony_ci * 175a8e1175bSopenharmony_ci * We could use the same context for verification and signatures, but we 176a8e1175bSopenharmony_ci * chose to use a new one in order to make it clear that the verifying 177a8e1175bSopenharmony_ci * context only needs the public key (Q), and not the private key (d). 178a8e1175bSopenharmony_ci */ 179a8e1175bSopenharmony_ci mbedtls_printf(" . Preparing verification context..."); 180a8e1175bSopenharmony_ci fflush(stdout); 181a8e1175bSopenharmony_ci 182a8e1175bSopenharmony_ci if ((ret = mbedtls_ecp_export(&ctx_sign, NULL, NULL, &Q)) != 0) { 183a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ecp_export returned %d\n", ret); 184a8e1175bSopenharmony_ci goto exit; 185a8e1175bSopenharmony_ci } 186a8e1175bSopenharmony_ci 187a8e1175bSopenharmony_ci if ((ret = mbedtls_ecp_set_public_key(grp_id, &ctx_verify, &Q)) != 0) { 188a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ecp_set_public_key returned %d\n", ret); 189a8e1175bSopenharmony_ci goto exit; 190a8e1175bSopenharmony_ci } 191a8e1175bSopenharmony_ci 192a8e1175bSopenharmony_ci /* 193a8e1175bSopenharmony_ci * Verify signature 194a8e1175bSopenharmony_ci */ 195a8e1175bSopenharmony_ci mbedtls_printf(" ok\n . Verifying signature..."); 196a8e1175bSopenharmony_ci fflush(stdout); 197a8e1175bSopenharmony_ci 198a8e1175bSopenharmony_ci if ((ret = mbedtls_ecdsa_read_signature(&ctx_verify, 199a8e1175bSopenharmony_ci hash, sizeof(hash), 200a8e1175bSopenharmony_ci sig, sig_len)) != 0) { 201a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ecdsa_read_signature returned %d\n", ret); 202a8e1175bSopenharmony_ci goto exit; 203a8e1175bSopenharmony_ci } 204a8e1175bSopenharmony_ci 205a8e1175bSopenharmony_ci mbedtls_printf(" ok\n"); 206a8e1175bSopenharmony_ci 207a8e1175bSopenharmony_ci exit_code = MBEDTLS_EXIT_SUCCESS; 208a8e1175bSopenharmony_ci 209a8e1175bSopenharmony_ciexit: 210a8e1175bSopenharmony_ci 211a8e1175bSopenharmony_ci mbedtls_ecdsa_free(&ctx_verify); 212a8e1175bSopenharmony_ci mbedtls_ecdsa_free(&ctx_sign); 213a8e1175bSopenharmony_ci mbedtls_ecp_point_free(&Q); 214a8e1175bSopenharmony_ci mbedtls_ctr_drbg_free(&ctr_drbg); 215a8e1175bSopenharmony_ci mbedtls_entropy_free(&entropy); 216a8e1175bSopenharmony_ci 217a8e1175bSopenharmony_ci mbedtls_exit(exit_code); 218a8e1175bSopenharmony_ci} 219a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && 220a8e1175bSopenharmony_ci ECPARAMS */ 221