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 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
25 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 */
46
47 #if !defined(MBEDTLS_CONFIG_FILE)
48 #include "mbedtls/config.h"
49 #else
50 #include MBEDTLS_CONFIG_FILE
51 #endif
52
53 #if defined(MBEDTLS_PLATFORM_C)
54 #include "mbedtls/platform.h"
55 #else
56 #include <stdio.h>
57 #include <stdlib.h>
58 #define mbedtls_printf printf
59 #define mbedtls_exit exit
60 #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
61 #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
62 #endif /* MBEDTLS_PLATFORM_C */
63
64 #if defined(MBEDTLS_ECDSA_C) && \
65 defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
66 #include "mbedtls/entropy.h"
67 #include "mbedtls/ctr_drbg.h"
68 #include "mbedtls/ecdsa.h"
69 #include "mbedtls/sha256.h"
70
71 #include <string.h>
72 #endif
73
74 /*
75 * Uncomment to show key and signature details
76 */
77 #define VERBOSE
78
79 /*
80 * Uncomment to force use of a specific curve
81 */
82 #define ECPARAMS MBEDTLS_ECP_DP_SECP192R1
83
84 #if !defined(ECPARAMS)
85 #define ECPARAMS mbedtls_ecp_curve_list()->grp_id
86 #endif
87
88 #if !defined(MBEDTLS_ECDSA_C) || !defined(MBEDTLS_SHA256_C) || \
89 !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
main(void)90 int main( void )
91 {
92 mbedtls_printf("MBEDTLS_ECDSA_C and/or MBEDTLS_SHA256_C and/or "
93 "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C not defined\n");
94 mbedtls_exit( 0 );
95 }
96 #else
97 #if defined(VERBOSE)
dump_buf(const char * title,unsigned char * buf,size_t len)98 static void dump_buf( const char *title, unsigned char *buf, size_t len )
99 {
100 size_t i;
101
102 mbedtls_printf( "%s", title );
103 for( i = 0; i < len; i++ )
104 mbedtls_printf("%c%c", "0123456789ABCDEF" [buf[i] / 16],
105 "0123456789ABCDEF" [buf[i] % 16] );
106 mbedtls_printf( "\n" );
107 }
108
dump_pubkey(const char * title,mbedtls_ecdsa_context * key)109 static void dump_pubkey( const char *title, mbedtls_ecdsa_context *key )
110 {
111 unsigned char buf[300];
112 size_t len;
113
114 if( mbedtls_ecp_point_write_binary( &key->grp, &key->Q,
115 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, buf, sizeof buf ) != 0 )
116 {
117 mbedtls_printf("internal error\n");
118 return;
119 }
120
121 dump_buf( title, buf, len );
122 }
123 #else
124 #define dump_buf( a, b, c )
125 #define dump_pubkey( a, b )
126 #endif
127
128
main(int argc,char * argv[])129 int main( int argc, char *argv[] )
130 {
131 int ret = 1;
132 int exit_code = MBEDTLS_EXIT_FAILURE;
133 mbedtls_ecdsa_context ctx_sign, ctx_verify;
134 mbedtls_entropy_context entropy;
135 mbedtls_ctr_drbg_context ctr_drbg;
136 unsigned char message[100];
137 unsigned char hash[32];
138 unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
139 size_t sig_len;
140 const char *pers = "ecdsa";
141 ((void) argv);
142
143 mbedtls_ecdsa_init( &ctx_sign );
144 mbedtls_ecdsa_init( &ctx_verify );
145 mbedtls_ctr_drbg_init( &ctr_drbg );
146
147 memset( sig, 0, sizeof( sig ) );
148 memset( message, 0x25, sizeof( message ) );
149
150 if( argc != 1 )
151 {
152 mbedtls_printf( "usage: ecdsa\n" );
153
154 #if defined(_WIN32)
155 mbedtls_printf( "\n" );
156 #endif
157
158 goto exit;
159 }
160
161 /*
162 * Generate a key pair for signing
163 */
164 mbedtls_printf( "\n . Seeding the random number generator..." );
165 fflush( stdout );
166
167 mbedtls_entropy_init( &entropy );
168 if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
169 (const unsigned char *) pers,
170 strlen( pers ) ) ) != 0 )
171 {
172 mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
173 goto exit;
174 }
175
176 mbedtls_printf( " ok\n . Generating key pair..." );
177 fflush( stdout );
178
179 if( ( ret = mbedtls_ecdsa_genkey( &ctx_sign, ECPARAMS,
180 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
181 {
182 mbedtls_printf( " failed\n ! mbedtls_ecdsa_genkey returned %d\n", ret );
183 goto exit;
184 }
185
186 mbedtls_printf( " ok (key size: %d bits)\n", (int) ctx_sign.grp.pbits );
187
188 dump_pubkey( " + Public key: ", &ctx_sign );
189
190 /*
191 * Compute message hash
192 */
193 mbedtls_printf( " . Computing message hash..." );
194 fflush( stdout );
195
196 if( ( ret = mbedtls_sha256_ret( message, sizeof( message ), hash, 0 ) ) != 0 )
197 {
198 mbedtls_printf( " failed\n ! mbedtls_sha256_ret returned %d\n", ret );
199 goto exit;
200 }
201
202 mbedtls_printf( " ok\n" );
203
204 dump_buf( " + Hash: ", hash, sizeof( hash ) );
205
206 /*
207 * Sign message hash
208 */
209 mbedtls_printf( " . Signing message hash..." );
210 fflush( stdout );
211
212 if( ( ret = mbedtls_ecdsa_write_signature( &ctx_sign, MBEDTLS_MD_SHA256,
213 hash, sizeof( hash ),
214 sig, &sig_len,
215 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
216 {
217 mbedtls_printf( " failed\n ! mbedtls_ecdsa_write_signature returned %d\n", ret );
218 goto exit;
219 }
220 mbedtls_printf( " ok (signature length = %u)\n", (unsigned int) sig_len );
221
222 dump_buf( " + Signature: ", sig, sig_len );
223
224 /*
225 * Transfer public information to verifying context
226 *
227 * We could use the same context for verification and signatures, but we
228 * chose to use a new one in order to make it clear that the verifying
229 * context only needs the public key (Q), and not the private key (d).
230 */
231 mbedtls_printf( " . Preparing verification context..." );
232 fflush( stdout );
233
234 if( ( ret = mbedtls_ecp_group_copy( &ctx_verify.grp, &ctx_sign.grp ) ) != 0 )
235 {
236 mbedtls_printf( " failed\n ! mbedtls_ecp_group_copy returned %d\n", ret );
237 goto exit;
238 }
239
240 if( ( ret = mbedtls_ecp_copy( &ctx_verify.Q, &ctx_sign.Q ) ) != 0 )
241 {
242 mbedtls_printf( " failed\n ! mbedtls_ecp_copy returned %d\n", ret );
243 goto exit;
244 }
245
246 /*
247 * Verify signature
248 */
249 mbedtls_printf( " ok\n . Verifying signature..." );
250 fflush( stdout );
251
252 if( ( ret = mbedtls_ecdsa_read_signature( &ctx_verify,
253 hash, sizeof( hash ),
254 sig, sig_len ) ) != 0 )
255 {
256 mbedtls_printf( " failed\n ! mbedtls_ecdsa_read_signature returned %d\n", ret );
257 goto exit;
258 }
259
260 mbedtls_printf( " ok\n" );
261
262 exit_code = MBEDTLS_EXIT_SUCCESS;
263
264 exit:
265
266 #if defined(_WIN32)
267 mbedtls_printf( " + Press Enter to exit this program.\n" );
268 fflush( stdout ); getchar();
269 #endif
270
271 mbedtls_ecdsa_free( &ctx_verify );
272 mbedtls_ecdsa_free( &ctx_sign );
273 mbedtls_ctr_drbg_free( &ctr_drbg );
274 mbedtls_entropy_free( &entropy );
275
276 mbedtls_exit( exit_code );
277 }
278 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
279 ECPARAMS */
280