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