xref: /third_party/mbedtls/programs/pkey/ecdsa.c (revision a8e1175b)
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