iPXE
ecdsa.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/** @file
28 *
29 * Elliptic curve digital signature algorithm (ECDSA)
30 *
31 * The elliptic curve public key format is documented in RFC 5480.
32 * The original private key format is documented in RFC 5915, and the
33 * generic container PKCS#8 format documented in RFC 5208.
34 *
35 */
36
37#include <stdlib.h>
38#include <errno.h>
39#include <string.h>
40#include <ipxe/crypto.h>
41#include <ipxe/bigint.h>
42#include <ipxe/hmac_drbg.h>
43#include <ipxe/ecdsa.h>
44
45/* Disambiguate the various error causes */
46#define EINVAL_POINTSIZE \
47 __einfo_error ( EINFO_EINVAL_POINTSIZE )
48#define EINFO_EINVAL_POINTSIZE \
49 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid point size" )
50#define EINVAL_KEYSIZE \
51 __einfo_error ( EINFO_EINVAL_KEYSIZE )
52#define EINFO_EINVAL_KEYSIZE \
53 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid key size" )
54#define EINVAL_COMPRESSION \
55 __einfo_error ( EINFO_EINVAL_COMPRESSION )
56#define EINFO_EINVAL_COMPRESSION \
57 __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid compression")
58#define EINVAL_INFINITY \
59 __einfo_error ( EINFO_EINVAL_INFINITY )
60#define EINFO_EINVAL_INFINITY \
61 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Point is infinity" )
62#define EINVAL_SIGNATURE \
63 __einfo_error ( EINFO_EINVAL_SIGNATURE )
64#define EINFO_EINVAL_SIGNATURE \
65 __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid signature" )
66
67/** "ecPublicKey" object identifier */
69
70/** Generic elliptic curve container algorithm
71 *
72 * The actual curve to be used is identified via the algorithm
73 * parameters, rather than the top-level OID.
74 */
75struct asn1_algorithm ecpubkey_algorithm __asn1_algorithm = {
76 .name = "ecPublicKey",
78 .pubkey = &ecdsa_algorithm,
79};
80
81/** An ECDSA key */
82struct ecdsa_key {
83 /** Elliptic curve */
85 /** Public curve point */
86 const void *public;
87 /** Private multiple of base curve point (if applicable) */
88 const void *private;
89};
90
91/** ECDSA context */
93 /** Key */
94 struct ecdsa_key key;
95 /** Big integer size */
96 unsigned int size;
97 /** Digest algorithm */
99 /** Digest length */
100 size_t zlen;
101
102 /** Dynamically allocated storage */
103 void *dynamic;
104 /** Element 0 of modulus N (i.e. curve group order */
106 /** Element 0 of constant N-2 (for Fermat's little theorem) */
108 /** Element 0 of Montgomery constant R^2 mod N */
110 /** Element 0 of constant 1 (in Montgomery form) */
112 /** Element 0 of digest value "z" */
114 /** Element 0 of random key "k" */
116 /** Element 0 of signature value "r" */
118 /** Element 0 of signature value "s" */
120 /** Element 0 of temporary value */
122 /** Element 0 of product buffer */
124 /** Curve point 1 */
125 void *point1;
126 /** Curve point 2 */
127 void *point2;
128 /** Scalar value */
129 void *scalar;
130 /** HMAC_DRBG state for random value generation */
132};
133
134/**
135 * Parse ECDSA key
136 *
137 * @v key ECDSA key
138 * @v raw ASN.1 cursor
139 * @ret rc Return status code
140 */
141static int ecdsa_parse_key ( struct ecdsa_key *key,
142 const struct asn1_cursor *raw ) {
144 struct asn1_cursor cursor;
145 struct asn1_cursor curve;
146 struct asn1_cursor private;
147 const uint8_t *compression;
148 int is_private;
149 int rc;
150
151 /* Enter subjectPublicKeyInfo/ECPrivateKey */
152 memcpy ( &cursor, raw, sizeof ( cursor ) );
153 asn1_enter ( &cursor, ASN1_SEQUENCE );
154 asn1_invalidate_cursor ( &curve );
155 asn1_invalidate_cursor ( &private );
156
157 /* Determine key format */
158 if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
159
160 /* Private key */
161 is_private = 1;
162
163 /* Skip version */
164 asn1_skip_any ( &cursor );
165
166 /* Parse privateKeyAlgorithm, if present */
167 if ( asn1_type ( &cursor ) == ASN1_SEQUENCE ) {
168
169 /* PKCS#8 format */
170 DBGC ( key, "ECDSA %p is in PKCS#8 format\n", key );
171
172 /* Parse privateKeyAlgorithm */
173 memcpy ( &curve, &cursor, sizeof ( curve ) );
174 asn1_skip_any ( &cursor );
175
176 /* Enter privateKey */
177 asn1_enter ( &cursor, ASN1_OCTET_STRING );
178
179 /* Enter ECPrivateKey */
180 asn1_enter ( &cursor, ASN1_SEQUENCE );
181
182 /* Skip version */
183 asn1_skip ( &cursor, ASN1_INTEGER );
184 }
185
186 /* Parse privateKey */
187 memcpy ( &private, &cursor, sizeof ( private ) );
188 asn1_enter ( &private, ASN1_OCTET_STRING );
189 asn1_skip_any ( &cursor );
190
191 /* Parse parameters, if present */
192 if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
193 memcpy ( &curve, &cursor, sizeof ( curve ) );
194 asn1_enter_any ( &curve );
195 asn1_skip_any ( &cursor );
196 }
197
198 /* Enter publicKey */
199 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );
200
201 } else {
202
203 /* Public key */
204 is_private = 0;
205
206 /* Parse algorithm */
207 memcpy ( &curve, &cursor, sizeof ( curve ) );
208 asn1_skip_any ( &cursor );
209 }
210
211 /* Enter publicKey */
212 asn1_enter_bits ( &cursor, NULL );
213
214 /* Identify curve */
215 if ( ( rc = asn1_curve_algorithm ( &curve, &ecpubkey_algorithm,
216 &algorithm ) ) != 0 ) {
217 DBGC ( key, "ECDSA %p unknown curve: %s\n",
218 key, strerror ( rc ) );
219 DBGC_HDA ( key, 0, raw->data, raw->len );
220 return rc;
221 }
222 key->curve = algorithm->curve;
223 DBGC ( key, "ECDSA %p is a %s (%s) %s key\n", key, algorithm->name,
224 key->curve->name, ( is_private ? "private" : "public" ) );
225
226 /* Check public key length */
227 if ( cursor.len != ( sizeof ( *compression ) +
228 key->curve->pointsize ) ) {
229 DBGC ( key, "ECDSA %p invalid public key length %zd\n",
230 key, cursor.len );
231 DBGC_HDA ( key, 0, raw->data, raw->len );
232 return -EINVAL_POINTSIZE;
233 }
234
235 /* Check that key is uncompressed */
236 compression = cursor.data;
237 if ( *compression != ECDSA_UNCOMPRESSED ) {
238 DBGC ( key, "ECDSA %p invalid compression %#02x\n",
239 key, *compression );
240 DBGC_HDA ( key, 0, raw->data, raw->len );
241 return -EINVAL_COMPRESSION;
242 }
243
244 /* Extract public curve point */
245 key->public = ( cursor.data + sizeof ( *compression ) );
246 DBGC ( key, "ECDSA %p public curve point:\n", key );
247 DBGC_HDA ( key, 0, key->public, key->curve->pointsize );
248
249 /* Check that public key is not the point at infinity */
250 if ( elliptic_is_infinity ( key->curve, key->public ) ) {
251 DBGC ( key, "ECDSA %p public curve point is infinity\n", key );
252 return -EINVAL_INFINITY;
253 }
254
255 /* Extract private key, if applicable */
256 if ( is_private ) {
257
258 /* Check private key length */
259 if ( private.len != key->curve->keysize ) {
260 DBGC ( key, "ECDSA %p invalid private key length "
261 "%zd\n", key, private.len );
262 DBGC_HDA ( key, 0, raw->data, raw->len );
263 return -EINVAL_KEYSIZE;
264 }
265
266 /* Extract private key */
267 key->private = private.data;
268 DBGC ( key, "ECDSA %p private multiplier:\n", key );
269 DBGC_HDA ( key, 0, key->private, key->curve->keysize );
270
271 } else {
272
273 /* No private key */
274 key->private = NULL;
275 }
276
277 return 0;
278}
279
280/**
281 * Parse ECDSA signature value
282 *
283 * @v ctx ECDSA context
284 * @v rs0 Element 0 of signature "r" or "s" value
285 * @v raw ASN.1 cursor
286 * @ret rc Return status code
287 */
289 bigint_element_t *rs0,
290 const struct asn1_cursor *raw ) {
291 size_t keysize = ctx->key.curve->keysize;
292 unsigned int size = ctx->size;
293 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
294 ( ( void * ) ctx->modulus0 );
295 bigint_t ( size ) __attribute__ (( may_alias )) *rs =
296 ( ( void * ) rs0 );
297 struct asn1_cursor cursor;
298 int rc;
299
300 /* Enter integer */
301 memcpy ( &cursor, raw, sizeof ( cursor ) );
302 if ( ( rc = asn1_enter_unsigned ( &cursor ) ) != 0 ) {
303 DBGC ( ctx, "ECDSA %p invalid integer:\n", ctx );
304 DBGC_HDA ( ctx, 0, raw->data, raw->len );
305 return rc;
306 }
307
308 /* Extract value */
309 if ( cursor.len > keysize ) {
310 DBGC ( ctx, "ECDSA %p invalid signature value:\n", ctx );
311 DBGC_HDA ( ctx, 0, raw->data, raw->len );
312 return -EINVAL_KEYSIZE;
313 }
314 bigint_init ( rs, cursor.data, cursor.len );
315
316 /* Check that value is within the required range */
317 if ( bigint_is_zero ( rs ) || bigint_is_geq ( rs, modulus ) ) {
318 DBGC ( ctx, "ECDSA %p out-of-range signature value:\n", ctx );
319 DBGC_HDA ( ctx, 0, raw->data, raw->len );
320 return -ERANGE;
321 }
322
323 return 0;
324}
325
326/**
327 * Prepend ECDSA signature value
328 *
329 * @v ctx ECDSA context
330 * @v rs0 Element 0 of signature "r" or "s" value
331 * @v builder ASN.1 builder
332 * @ret rc Return status code
333 */
335 bigint_element_t *rs0,
336 struct asn1_builder *builder ) {
337 size_t keysize = ctx->key.curve->keysize;
338 unsigned int size = ctx->size;
339 bigint_t ( size ) __attribute__ (( may_alias )) *rs =
340 ( ( void * ) rs0 );
341 uint8_t buf[ 1 /* potential sign byte */ + keysize ];
342 uint8_t *data;
343 size_t len;
344 int rc;
345
346 /* Construct value */
347 buf[0] = 0;
348 bigint_done ( rs, &buf[1], keysize );
349
350 /* Strip leading zeros */
351 data = buf;
352 len = sizeof ( buf );
353 while ( ( len > 1 ) && ( data[0] == 0 ) && ( data[1] < 0x80 ) ) {
354 data++;
355 len--;
356 }
357
358 /* Prepend integer */
359 if ( ( rc = asn1_prepend ( builder, ASN1_INTEGER, data, len ) ) != 0 )
360 return rc;
361
362 return 0;
363}
364
365/**
366 * Allocate ECDSA context dynamic storage
367 *
368 * @v ctx ECDSA context
369 * @ret rc Return status code
370 */
371static int ecdsa_alloc ( struct ecdsa_context *ctx ) {
372 struct elliptic_curve *curve = ctx->key.curve;
373 size_t pointsize = curve->pointsize;
374 size_t keysize = curve->keysize;
375 unsigned int size =
376 bigint_required_size ( keysize + 1 /* for addition */ );
377 struct {
378 bigint_t ( size ) modulus;
379 bigint_t ( size ) fermat;
380 bigint_t ( size ) square;
381 bigint_t ( size ) one;
382 bigint_t ( size ) z;
383 bigint_t ( size ) k;
384 bigint_t ( size ) r;
385 bigint_t ( size ) s;
386 bigint_t ( size ) temp;
387 bigint_t ( size * 2 ) product;
388 uint8_t point1[pointsize];
389 uint8_t point2[pointsize];
390 uint8_t scalar[keysize];
391 struct hmac_drbg_state drbg;
392 } *dynamic;
393
394 /* Allocate dynamic storage */
395 dynamic = malloc ( sizeof ( *dynamic ) );
396 if ( ! dynamic )
397 return -ENOMEM;
398
399 /* Populate context */
400 ctx->size = size;
401 ctx->dynamic = dynamic;
402 ctx->modulus0 = dynamic->modulus.element;
403 ctx->fermat0 = dynamic->fermat.element;
404 ctx->square0 = dynamic->square.element;
405 ctx->one0 = dynamic->one.element;
406 ctx->z0 = dynamic->z.element;
407 ctx->k0 = dynamic->k.element;
408 ctx->r0 = dynamic->r.element;
409 ctx->s0 = dynamic->s.element;
410 ctx->temp0 = dynamic->temp.element;
411 ctx->product0 = dynamic->product.element;
412 ctx->point1 = dynamic->point1;
413 ctx->point2 = dynamic->point2;
414 ctx->scalar = dynamic->scalar;
415 ctx->drbg = &dynamic->drbg;
416
417 return 0;
418}
419
420/**
421 * Free ECDSA context dynamic storage
422 *
423 * @v ctx ECDSA context
424 */
425static void ecdsa_free ( struct ecdsa_context *ctx ) {
426
427 /* Free dynamic storage */
428 free ( ctx->dynamic );
429}
430
431/**
432 * Initialise ECDSA values
433 *
434 * @v ctx ECDSA context
435 * @v digest Digest algorithm
436 * @v value Digest value
437 */
438static void ecdsa_init_values ( struct ecdsa_context *ctx,
439 struct digest_algorithm *digest,
440 const void *value ) {
441 struct elliptic_curve *curve = ctx->key.curve;
442 unsigned int size = ctx->size;
443 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
444 ( ( void * ) ctx->modulus0 );
445 bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
446 ( ( void * ) ctx->fermat0 );
447 bigint_t ( size ) __attribute__ (( may_alias )) *square =
448 ( ( void * ) ctx->square0 );
449 bigint_t ( size ) __attribute__ (( may_alias )) *one =
450 ( ( void * ) ctx->one0 );
451 bigint_t ( size ) __attribute__ (( may_alias )) *z =
452 ( ( void * ) ctx->z0 );
453 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
454 ( ( void * ) ctx->product0 );
455 static const uint8_t two_raw[] = { 2 };
456 size_t zlen;
457
458 /* Initialise modulus N */
459 bigint_init ( modulus, curve->order, curve->keysize );
460 DBGC2 ( ctx, "ECDSA %p N = %s\n", ctx, bigint_ntoa ( modulus ) );
461
462 /* Calculate N-2 (using Montgomery constant as temporary buffer) */
463 bigint_copy ( modulus, fermat );
464 bigint_init ( square, two_raw, sizeof ( two_raw ) );
465 bigint_subtract ( square, fermat );
466
467 /* Calculate Montgomery constant */
468 bigint_reduce ( modulus, square );
469 DBGC2 ( ctx, "ECDSA %p R^2 = %s mod N\n",
470 ctx, bigint_ntoa ( square ) );
471
472 /* Construct one in Montgomery form */
473 bigint_grow ( square, product );
474 bigint_montgomery ( modulus, product, one );
475 DBGC2 ( ctx, "ECDSA %p R = %s mod N\n",
476 ctx, bigint_ntoa ( one ) );
477
478 /* Initialise digest */
479 ctx->digest = digest;
480 zlen = ctx->key.curve->keysize;
481 if ( zlen > digest->digestsize )
482 zlen = digest->digestsize;
483 ctx->zlen = zlen;
484 bigint_init ( z, value, zlen );
485 DBGC2 ( ctx, "ECDSA %p z = %s (%s)\n",
486 ctx, bigint_ntoa ( z ), digest->name );
487}
488
489/**
490 * Initialise ECDSA context
491 *
492 * @v ctx ECDSA context
493 * @v key Key
494 * @v digest Digest algorithm
495 * @v value Digest value
496 * @ret rc Return status code
497 */
498static int ecdsa_init ( struct ecdsa_context *ctx,
499 const struct asn1_cursor *key,
500 struct digest_algorithm *digest,
501 const void *value ) {
502 int rc;
503
504 /* Parse key */
505 if ( ( rc = ecdsa_parse_key ( &ctx->key, key ) ) != 0 )
506 goto err_parse;
507
508 /* Allocate dynamic storage */
509 if ( ( rc = ecdsa_alloc ( ctx ) ) != 0 )
510 goto err_alloc;
511
512 /* Initialise values */
513 ecdsa_init_values ( ctx, digest, value );
514
515 return 0;
516
517 ecdsa_free ( ctx );
518 err_alloc:
519 err_parse:
520 return rc;
521}
522
523/**
524 * Invert ECDSA value
525 *
526 * @v ctx ECDSA context
527 * @v val0 Element 0 of value to invert
528 */
529static void ecdsa_invert ( struct ecdsa_context *ctx,
530 bigint_element_t *val0 ) {
531 unsigned int size = ctx->size;
532 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
533 ( ( void * ) ctx->modulus0 );
534 bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
535 ( ( void * ) ctx->fermat0 );
536 bigint_t ( size ) __attribute__ (( may_alias )) *square =
537 ( ( void * ) ctx->square0 );
538 bigint_t ( size ) __attribute__ (( may_alias )) *one =
539 ( ( void * ) ctx->one0 );
540 bigint_t ( size ) __attribute__ (( may_alias )) *temp =
541 ( ( void * ) ctx->temp0 );
542 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
543 ( ( void * ) ctx->product0 );
544 bigint_t ( size ) __attribute__ (( may_alias )) *val =
545 ( ( void * ) val0 );
546
547 /* Convert value to Montgomery form */
548 bigint_multiply ( val, square, product );
549 bigint_montgomery ( modulus, product, temp );
550
551 /* Invert value via Fermat's little theorem */
552 bigint_copy ( one, val );
553 bigint_ladder ( val, temp, fermat, bigint_mod_exp_ladder, modulus,
554 product );
555}
556
557/**
558 * Generate ECDSA "r" and "s" values
559 *
560 * @v ctx ECDSA context
561 * @v sig Signature
562 * @ret rc Return status code
563 */
564static int ecdsa_sign_rs ( struct ecdsa_context *ctx ) {
565 struct digest_algorithm *digest = ctx->digest;
566 struct elliptic_curve *curve = ctx->key.curve;
567 size_t pointsize = curve->pointsize;
568 size_t keysize = curve->keysize;
569 unsigned int size = ctx->size;
570 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
571 ( ( void * ) ctx->modulus0 );
572 bigint_t ( size ) __attribute__ (( may_alias )) *square =
573 ( ( void * ) ctx->square0 );
574 bigint_t ( size ) __attribute__ (( may_alias )) *one =
575 ( ( void * ) ctx->one0 );
576 bigint_t ( size ) __attribute__ (( may_alias )) *z =
577 ( ( void * ) ctx->z0 );
578 bigint_t ( size ) __attribute__ (( may_alias )) *k =
579 ( ( void * ) ctx->k0 );
580 bigint_t ( size ) __attribute__ (( may_alias )) *r =
581 ( ( void * ) ctx->r0 );
582 bigint_t ( size ) __attribute__ (( may_alias )) *s =
583 ( ( void * ) ctx->s0 );
584 bigint_t ( size ) __attribute__ (( may_alias )) *temp =
585 ( ( void * ) ctx->temp0 );
586 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
587 ( ( void * ) ctx->product0 );
588 bigint_t ( size ) __attribute__ (( may_alias )) *x1 =
589 ( ( void * ) temp );
590 void *point1 = ctx->point1;
591 void *scalar = ctx->scalar;
592 int rc;
593
594 /* Loop until a suitable signature is generated */
595 while ( 1 ) {
596
597 /* Generate pseudo-random data */
598 if ( ( rc = hmac_drbg_generate ( digest, ctx->drbg, NULL, 0,
599 scalar, keysize ) ) != 0 ) {
600 DBGC ( ctx, "ECDSA %p could not generate: %s\n",
601 ctx, strerror ( rc ) );
602 return rc;
603 }
604
605 /* Check suitability of pseudo-random data */
606 bigint_init ( k, scalar, keysize );
607 DBGC2 ( ctx, "ECDSA %p k = %s\n",
608 ctx, bigint_ntoa ( k ) );
609 if ( bigint_is_zero ( k ) )
610 continue;
611 if ( bigint_is_geq ( k, modulus ) )
612 continue;
613
614 /* Calculate (x1,y1) = k*G */
615 elliptic_multiply ( curve, curve->base, scalar, point1 );
616 bigint_init ( x1, point1, ( pointsize / 2 ) );
617 DBGC2 ( ctx, "ECDSA %p x1 = %s mod N\n",
618 ctx, bigint_ntoa ( x1 ) );
619
620 /* Calculate r = x1 mod N */
621 bigint_multiply ( x1, one, product );
622 bigint_montgomery ( modulus, product, r );
623 DBGC2 ( ctx, "ECDSA %p r = %s\n",
624 ctx, bigint_ntoa ( r ) );
625
626 /* Check suitability of r */
627 if ( bigint_is_zero ( r ) )
628 continue;
629
630 /* Calculate k^-1 mod N (in Montgomery form) */
631 ecdsa_invert ( ctx, k->element );
632 DBGC2 ( ctx, "ECDSA %p (k^-1)R = %s mod N\n",
633 ctx, bigint_ntoa ( k ) );
634
635 /* Calculate r * dA */
636 bigint_init ( temp, ctx->key.private, keysize );
637 DBGC2 ( ctx, "ECDSA %p dA = %s\n",
638 ctx, bigint_ntoa ( temp ) );
639 bigint_multiply ( r, temp, product );
640 bigint_montgomery ( modulus, product, temp );
641 bigint_multiply ( temp, square, product );
642 bigint_montgomery ( modulus, product, temp );
643 DBGC2 ( ctx, "ECDSA %p r*dA = %s mod N\n",
644 ctx, bigint_ntoa ( temp ) );
645
646 /* Calculate k^-1 * (z + r*dA) */
647 bigint_add ( z, temp );
648 DBGC2 ( ctx, "ECDSA %p z+r*dA = %s mod N\n",
649 ctx, bigint_ntoa ( temp ) );
650 bigint_multiply ( k, temp, product );
651 bigint_montgomery ( modulus, product, s );
652 DBGC2 ( ctx, "ECDSA %p s = %s\n",
653 ctx, bigint_ntoa ( s ) );
654
655 /* Check suitability of s */
656 if ( bigint_is_zero ( s ) )
657 continue;
658
659 return 0;
660 }
661}
662
663/**
664 * Verify ECDSA "r" and "s" values
665 *
666 * @v ctx ECDSA context
667 * @v sig Signature
668 * @ret rc Return status code
669 */
670static int ecdsa_verify_rs ( struct ecdsa_context *ctx ) {
671 struct elliptic_curve *curve = ctx->key.curve;
672 size_t pointsize = curve->pointsize;
673 size_t keysize = curve->keysize;
674 const void *public = ctx->key.public;
675 unsigned int size = ctx->size;
676 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
677 ( ( void * ) ctx->modulus0 );
678 bigint_t ( size ) __attribute__ (( may_alias )) *one =
679 ( ( void * ) ctx->one0 );
680 bigint_t ( size ) __attribute__ (( may_alias )) *z =
681 ( ( void * ) ctx->z0 );
682 bigint_t ( size ) __attribute__ (( may_alias )) *r =
683 ( ( void * ) ctx->r0 );
684 bigint_t ( size ) __attribute__ (( may_alias )) *s =
685 ( ( void * ) ctx->s0 );
686 bigint_t ( size ) __attribute__ (( may_alias )) *temp =
687 ( ( void * ) ctx->temp0 );
688 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
689 ( ( void * ) ctx->product0 );
690 bigint_t ( size ) __attribute__ (( may_alias )) *u1 =
691 ( ( void * ) temp );
692 bigint_t ( size ) __attribute__ (( may_alias )) *u2 =
693 ( ( void * ) temp );
694 bigint_t ( size ) __attribute__ (( may_alias )) *x1 =
695 ( ( void * ) temp );
696 void *point1 = ctx->point1;
697 void *point2 = ctx->point2;
698 void *scalar = ctx->scalar;
699 int valid;
700 int rc;
701
702 DBGC2 ( ctx, "ECDSA %p r = %s\n", ctx, bigint_ntoa ( r ) );
703 DBGC2 ( ctx, "ECDSA %p s = %s\n", ctx, bigint_ntoa ( s ) );
704
705 /* Calculate s^-1 mod N (in Montgomery form) */
706 ecdsa_invert ( ctx, s->element );
707 DBGC2 ( ctx, "ECDSA %p (s^-1)R = %s mod N\n", ctx, bigint_ntoa ( s ) );
708
709 /* Calculate u1 = (z * s^-1) mod N */
710 bigint_multiply ( z, s, product );
711 bigint_montgomery ( modulus, product, u1 );
712 DBGC2 ( ctx, "ECDSA %p u1 = %s mod N\n",
713 ctx, bigint_ntoa ( u1 ) );
714 bigint_done ( u1, scalar, keysize );
715
716 /* Calculate u1 * G */
717 if ( ( rc = elliptic_multiply ( curve, curve->base, scalar,
718 point1 ) ) != 0 ) {
719 DBGC ( ctx, "ECDSA %p could not calculate u1*G: %s\n",
720 ctx, strerror ( rc ) );
721 return rc;
722 }
723
724 /* Calculate u2 = (r * s^-1) mod N */
725 bigint_multiply ( r, s, product );
726 bigint_montgomery ( modulus, product, u2 );
727 bigint_done ( u2, scalar, keysize );
728 DBGC2 ( ctx, "ECDSA %p u2 = %s mod N\n",
729 ctx, bigint_ntoa ( u2 ) );
730
731 /* Calculate u2 * Qa */
732 if ( ( rc = elliptic_multiply ( curve, public, scalar,
733 point2 ) ) != 0 ) {
734 DBGC ( ctx, "ECDSA %p could not calculate u2*Qa: %s\n",
735 ctx, strerror ( rc ) );
736 return rc;
737 }
738
739 /* Calculate u1 * G + u2 * Qa */
740 if ( ( rc = elliptic_add ( curve, point1, point2, point1 ) ) != 0 ) {
741 DBGC ( ctx, "ECDSA %p could not calculate u1*G+u2*Qa: %s\n",
742 ctx, strerror ( rc ) );
743 return rc;
744 }
745
746 /* Check that result is not the point at infinity */
747 if ( elliptic_is_infinity ( curve, point1 ) ) {
748 DBGC ( ctx, "ECDSA %p result is point at infinity\n", ctx );
749 return -EINVAL;
750 }
751
752 /* Calculate x1 mod N */
753 bigint_init ( x1, point1, ( pointsize / 2 ) );
754 DBGC2 ( ctx, "ECDSA %p x1 = %s mod N\n", ctx, bigint_ntoa ( x1 ) );
755 bigint_multiply ( x1, one, product );
756 bigint_montgomery ( modulus, product, x1 );
757 DBGC2 ( ctx, "ECDSA %p x1 = %s\n", ctx, bigint_ntoa ( x1 ) );
758
759 /* Check signature */
760 bigint_subtract ( x1, r );
761 valid = bigint_is_zero ( r );
762 DBGC2 ( ctx, "ECDSA %p signature is%s valid\n",
763 ctx, ( valid ? "" : " not" ) );
764
765 return ( valid ? 0 : -EINVAL_SIGNATURE );
766}
767
768/**
769 * Encrypt using ECDSA
770 *
771 * @v key Key
772 * @v plaintext Plaintext
773 * @v ciphertext Ciphertext
774 * @ret rc Return status code
775 */
776static int ecdsa_encrypt ( const struct asn1_cursor *key __unused,
777 const struct asn1_cursor *plaintext __unused,
778 struct asn1_builder *ciphertext __unused ) {
779
780 /* Not a defined operation for ECDSA */
781 return -ENOTTY;
782}
783
784/**
785 * Decrypt using ECDSA
786 *
787 * @v key Key
788 * @v ciphertext Ciphertext
789 * @v plaintext Plaintext
790 * @ret rc Return status code
791 */
792static int ecdsa_decrypt ( const struct asn1_cursor *key __unused,
793 const struct asn1_cursor *ciphertext __unused,
794 struct asn1_builder *plaintext __unused ) {
795
796 /* Not a defined operation for ECDSA */
797 return -ENOTTY;
798}
799
800/**
801 * Sign digest value using ECDSA
802 *
803 * @v key Key
804 * @v digest Digest algorithm
805 * @v value Digest value
806 * @v signature Signature
807 * @ret rc Return status code
808 */
809static int ecdsa_sign ( const struct asn1_cursor *key,
810 struct digest_algorithm *digest, const void *value,
811 struct asn1_builder *signature ) {
812 struct ecdsa_context ctx;
813 int rc;
814
815 /* Initialise context */
816 if ( ( rc = ecdsa_init ( &ctx, key, digest, value ) ) != 0 )
817 goto err_init;
818
819 /* Fail unless we have a private key */
820 if ( ! ctx.key.private ) {
821 rc = -ENOTTY;
822 goto err_no_key;
823 }
824
825 /* Instantiate DRBG */
826 hmac_drbg_instantiate ( digest, ctx.drbg, ctx.key.private,
827 ctx.key.curve->keysize, value, ctx.zlen );
828
829 /* Create signature */
830 if ( ( rc = ecdsa_sign_rs ( &ctx ) ) != 0 )
831 goto err_signature;
832
833 /* Construct "r" and "s" values */
834 if ( ( rc = ecdsa_prepend_signature ( &ctx, ctx.s0, signature ) ) != 0)
835 goto err_s;
836 if ( ( rc = ecdsa_prepend_signature ( &ctx, ctx.r0, signature ) ) != 0)
837 goto err_r;
838 if ( ( rc = asn1_wrap ( signature, ASN1_SEQUENCE ) ) != 0 )
839 goto err_wrap;
840
841 /* Free context */
842 ecdsa_free ( &ctx );
843
844 return 0;
845
846 err_wrap:
847 err_r:
848 err_s:
849 err_signature:
850 err_no_key:
851 ecdsa_free ( &ctx );
852 err_init:
853 return rc;
854}
855
856/**
857 * Verify signed digest using ECDSA
858 *
859 * @v key Key
860 * @v digest Digest algorithm
861 * @v value Digest value
862 * @v signature Signature
863 * @ret rc Return status code
864 */
865static int ecdsa_verify ( const struct asn1_cursor *key,
866 struct digest_algorithm *digest, const void *value,
867 const struct asn1_cursor *signature ) {
868 struct ecdsa_context ctx;
869 struct asn1_cursor cursor;
870 int rc;
871
872 /* Initialise context */
873 if ( ( rc = ecdsa_init ( &ctx, key, digest, value ) ) != 0 )
874 goto err_init;
875
876 /* Enter sequence */
877 memcpy ( &cursor, signature, sizeof ( cursor ) );
878 asn1_enter ( &cursor, ASN1_SEQUENCE );
879
880 /* Extract "r" and "s" values */
881 if ( ( rc = ecdsa_parse_signature ( &ctx, ctx.r0, &cursor ) ) != 0 )
882 goto err_r;
883 asn1_skip_any ( &cursor );
884 if ( ( rc = ecdsa_parse_signature ( &ctx, ctx.s0, &cursor ) ) != 0 )
885 goto err_s;
886
887 /* Verify signature */
888 if ( ( rc = ecdsa_verify_rs ( &ctx ) ) != 0 )
889 goto err_verify;
890
891 /* Free context */
892 ecdsa_free ( &ctx );
893
894 return 0;
895
896 err_verify:
897 err_s:
898 err_r:
899 ecdsa_free ( &ctx );
900 err_init:
901 return rc;
902}
903
904/**
905 * Check for matching ECDSA public/private key pair
906 *
907 * @v private_key Private key
908 * @v public_key Public key
909 * @ret rc Return status code
910 */
911static int ecdsa_match ( const struct asn1_cursor *private_key,
912 const struct asn1_cursor *public_key ) {
913 struct elliptic_curve *curve;
914 struct ecdsa_key privkey;
915 struct ecdsa_key pubkey;
916 int rc;
917
918 /* Parse keys */
919 if ( ( rc = ecdsa_parse_key ( &privkey, private_key ) ) != 0 )
920 return rc;
921 if ( ( rc = ecdsa_parse_key ( &pubkey, public_key ) ) != 0 )
922 return rc;
923
924 /* Compare curves */
925 if ( privkey.curve != pubkey.curve )
926 return -ENOTTY;
927 curve = privkey.curve;
928
929 /* Compare public curve points */
930 if ( memcmp ( privkey.public, pubkey.public, curve->pointsize ) != 0 )
931 return -ENOTTY;
932
933 return 0;
934}
935
936/** ECDSA public-key algorithm */
938 .name = "ecdsa",
939 .encrypt = ecdsa_encrypt,
940 .decrypt = ecdsa_decrypt,
941 .sign = ecdsa_sign,
942 .verify = ecdsa_verify,
943 .match = ecdsa_match,
944};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 raw[7]
Definition CIB_PRM.h:0
u8 signature
CPU signature.
Definition CIB_PRM.h:7
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
uint32_t bigint_element_t
Element of a big integer.
Definition bigint.h:16
int asn1_prepend(struct asn1_builder *builder, unsigned int type, const void *data, size_t len)
Prepend data to ASN.1 builder.
Definition asn1.c:972
int asn1_enter_unsigned(struct asn1_cursor *cursor)
Enter ASN.1 unsigned integer.
Definition asn1.c:369
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:290
int asn1_curve_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm *wrapper, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified elliptic curve algorithm.
Definition asn1.c:659
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:169
int asn1_enter_any(struct asn1_cursor *cursor)
Enter ASN.1 object of any type.
Definition asn1.c:280
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:231
int asn1_enter_bits(struct asn1_cursor *cursor, unsigned int *unused)
Enter ASN.1 bit string.
Definition asn1.c:311
int asn1_wrap(struct asn1_builder *builder, unsigned int type)
Wrap ASN.1 builder.
Definition asn1.c:999
#define ASN1_INTEGER
ASN.1 integer.
Definition asn1.h:63
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition asn1.h:99
static void asn1_invalidate_cursor(struct asn1_cursor *cursor)
Invalidate ASN.1 object cursor.
Definition asn1.h:468
#define __asn1_algorithm
Declare an ASN.1 OID-identified algorithm.
Definition asn1.h:436
#define ASN1_OID_ECPUBLICKEY
ASN.1 OID for ecPublicKey (1.2.840.10045.2.1)
Definition asn1.h:132
#define ASN1_CURSOR(value)
Define an ASN.1 cursor for a static value.
Definition asn1.h:402
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:90
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition asn1.h:69
static unsigned int asn1_type(const struct asn1_cursor *cursor)
Extract ASN.1 type.
Definition asn1.h:479
void bigint_mod_exp_ladder(const bigint_element_t *multiplier0, bigint_element_t *result0, unsigned int size, const void *ctx, void *tmp)
Perform modular multiplication as part of a Montgomery ladder.
Definition bigint.c:720
ring len
Length.
Definition dwmac.h:226
#define EINVAL_INFINITY
Definition ecdsa.c:58
static int ecdsa_verify_rs(struct ecdsa_context *ctx)
Verify ECDSA "r" and "s" values.
Definition ecdsa.c:670
static int ecdsa_parse_key(struct ecdsa_key *key, const struct asn1_cursor *raw)
Parse ECDSA key.
Definition ecdsa.c:141
static int ecdsa_encrypt(const struct asn1_cursor *key __unused, const struct asn1_cursor *plaintext __unused, struct asn1_builder *ciphertext __unused)
Encrypt using ECDSA.
Definition ecdsa.c:776
#define EINVAL_POINTSIZE
Definition ecdsa.c:46
static int ecdsa_sign(const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, struct asn1_builder *signature)
Sign digest value using ECDSA.
Definition ecdsa.c:809
static void ecdsa_init_values(struct ecdsa_context *ctx, struct digest_algorithm *digest, const void *value)
Initialise ECDSA values.
Definition ecdsa.c:438
#define EINVAL_COMPRESSION
Definition ecdsa.c:54
static int ecdsa_alloc(struct ecdsa_context *ctx)
Allocate ECDSA context dynamic storage.
Definition ecdsa.c:371
#define EINVAL_SIGNATURE
Definition ecdsa.c:62
static int ecdsa_verify(const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Verify signed digest using ECDSA.
Definition ecdsa.c:865
struct pubkey_algorithm ecdsa_algorithm
ECDSA public-key algorithm.
Definition ecdsa.c:937
static int ecdsa_match(const struct asn1_cursor *private_key, const struct asn1_cursor *public_key)
Check for matching ECDSA public/private key pair.
Definition ecdsa.c:911
static int ecdsa_decrypt(const struct asn1_cursor *key __unused, const struct asn1_cursor *ciphertext __unused, struct asn1_builder *plaintext __unused)
Decrypt using ECDSA.
Definition ecdsa.c:792
#define EINVAL_KEYSIZE
Definition ecdsa.c:50
static int ecdsa_sign_rs(struct ecdsa_context *ctx)
Generate ECDSA "r" and "s" values.
Definition ecdsa.c:564
static int ecdsa_prepend_signature(struct ecdsa_context *ctx, bigint_element_t *rs0, struct asn1_builder *builder)
Prepend ECDSA signature value.
Definition ecdsa.c:334
static int ecdsa_init(struct ecdsa_context *ctx, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value)
Initialise ECDSA context.
Definition ecdsa.c:498
static uint8_t oid_ecpublickey[]
"ecPublicKey" object identifier
Definition ecdsa.c:68
static void ecdsa_free(struct ecdsa_context *ctx)
Free ECDSA context dynamic storage.
Definition ecdsa.c:425
static void ecdsa_invert(struct ecdsa_context *ctx, bigint_element_t *val0)
Invert ECDSA value.
Definition ecdsa.c:529
static int ecdsa_parse_signature(struct ecdsa_context *ctx, bigint_element_t *rs0, const struct asn1_cursor *raw)
Parse ECDSA signature value.
Definition ecdsa.c:288
Elliptic curve digital signature algorithm (ECDSA)
#define ECDSA_UNCOMPRESSED
Uncompressed curve point.
Definition ecdsa.h:16
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
uint16_t size
Buffer size.
Definition dwmac.h:3
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ERANGE
Result too large.
Definition errno.h:640
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
int hmac_drbg_generate(struct digest_algorithm *hash, struct hmac_drbg_state *state, const void *additional, size_t additional_len, void *data, size_t len)
Generate pseudorandom bits using HMAC_DRBG.
Definition hmac_drbg.c:307
void hmac_drbg_instantiate(struct digest_algorithm *hash, struct hmac_drbg_state *state, const void *entropy, size_t entropy_len, const void *personal, size_t personal_len)
Instantiate HMAC_DRBG.
Definition hmac_drbg.c:207
HMAC_DRBG algorithm.
u16 algorithm
Authentication algorithm (Open System or Shared Key)
Definition ieee80211.h:1
#define __attribute__(x)
Definition compiler.h:10
Big integer support.
#define bigint_grow(source, dest)
Grow big integer.
Definition bigint.h:209
#define bigint_ladder(result, multiple, exponent, op, ctx, tmp)
Perform generalised exponentiation via a Montgomery ladder.
Definition bigint.h:330
#define bigint_reduce(modulus, result)
Reduce big integer R^2 modulo N.
Definition bigint.h:274
#define bigint_subtract(subtrahend, value)
Subtract big integers.
Definition bigint.h:99
#define bigint_montgomery(modulus, value, result)
Perform classic Montgomery reduction (REDC) of a big integer.
Definition bigint.h:314
#define bigint_copy(source, dest)
Copy big integer.
Definition bigint.h:235
#define bigint_is_geq(value, reference)
Compare big integers.
Definition bigint.h:145
#define bigint_is_zero(value)
Test if big integer is equal to zero.
Definition bigint.h:134
#define bigint_t(size)
Define a big-integer type.
Definition bigint.h:20
#define bigint_required_size(len)
Determine number of elements required for a big-integer type.
Definition bigint.h:31
#define bigint_multiply(multiplicand, multiplier, result)
Multiply big integers.
Definition bigint.h:260
#define bigint_done(value, out, len)
Finalise big integer.
Definition bigint.h:75
#define bigint_add(addend, value)
Add big integers.
Definition bigint.h:87
#define bigint_ntoa(value)
Transcribe big integer (for debugging)
Definition bigint.h:50
#define bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:62
Cryptographic API.
static int elliptic_multiply(struct elliptic_curve *curve, const void *base, const void *scalar, void *result)
Definition crypto.h:327
static int elliptic_is_infinity(struct elliptic_curve *curve, const void *point)
Definition crypto.h:322
static int elliptic_add(struct elliptic_curve *curve, const void *addend, const void *augend, void *result)
Definition crypto.h:333
uint8_t product
Product string.
Definition smbios.h:5
void __asmcall int val
Definition setjmp.h:12
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
static const uint8_t r[3][4]
MD4 shift amounts.
Definition md4.c:54
static const uint32_t k[64]
MD5 constants.
Definition md5.c:54
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An ASN.1 OID-identified algorithm.
Definition asn1.h:408
An ASN.1 object builder.
Definition asn1.h:29
An ASN.1 object cursor.
Definition asn1.h:21
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
const char * name
Algorithm name.
Definition crypto.h:21
ECDSA context.
Definition ecdsa.c:92
void * dynamic
Dynamically allocated storage.
Definition ecdsa.c:103
bigint_element_t * s0
Element 0 of signature value "s".
Definition ecdsa.c:119
size_t zlen
Digest length.
Definition ecdsa.c:100
struct digest_algorithm * digest
Digest algorithm.
Definition ecdsa.c:98
bigint_element_t * z0
Element 0 of digest value "z".
Definition ecdsa.c:113
void * point1
Curve point 1.
Definition ecdsa.c:125
bigint_element_t * modulus0
Element 0 of modulus N (i.e.
Definition ecdsa.c:105
unsigned int size
Big integer size.
Definition ecdsa.c:96
bigint_element_t * product0
Element 0 of product buffer.
Definition ecdsa.c:123
bigint_element_t * temp0
Element 0 of temporary value.
Definition ecdsa.c:121
bigint_element_t * fermat0
Element 0 of constant N-2 (for Fermat's little theorem)
Definition ecdsa.c:107
struct ecdsa_key key
Key.
Definition ecdsa.c:94
bigint_element_t * r0
Element 0 of signature value "r".
Definition ecdsa.c:117
bigint_element_t * k0
Element 0 of random key "k".
Definition ecdsa.c:115
bigint_element_t * square0
Element 0 of Montgomery constant R^2 mod N.
Definition ecdsa.c:109
void * point2
Curve point 2.
Definition ecdsa.c:127
void * scalar
Scalar value.
Definition ecdsa.c:129
bigint_element_t * one0
Element 0 of constant 1 (in Montgomery form)
Definition ecdsa.c:111
struct hmac_drbg_state * drbg
HMAC_DRBG state for random value generation.
Definition ecdsa.c:131
An ECDSA key.
Definition ecdsa.c:82
struct elliptic_curve * curve
Elliptic curve.
Definition ecdsa.c:84
const void * public
Public curve point.
Definition ecdsa.c:86
An elliptic curve.
Definition crypto.h:178
const void * order
Order of the generator (if prime)
Definition crypto.h:188
size_t keysize
Scalar (and private key) size.
Definition crypto.h:184
size_t pointsize
Point (and public key) size.
Definition crypto.h:182
const void * base
Generator base point.
Definition crypto.h:186
HMAC_DRBG internal state.
Definition hmac_drbg.h:219
A private key.
Definition privkey.h:17
A public key algorithm.
Definition crypto.h:122
u16 keysize
Length of encryption key to be used, network byte order.
Definition wpa.h:10