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