iPXE
ecdsa.c File Reference

Elliptic curve digital signature algorithm (ECDSA). More...

#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ipxe/crypto.h>
#include <ipxe/bigint.h>
#include <ipxe/hmac_drbg.h>
#include <ipxe/ecdsa.h>

Go to the source code of this file.

Data Structures

struct  ecdsa_key
 An ECDSA key. More...
struct  ecdsa_context
 ECDSA context. More...

Macros

#define EINVAL_POINTSIZE   __einfo_error ( EINFO_EINVAL_POINTSIZE )
#define EINFO_EINVAL_POINTSIZE   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid point size" )
#define EINVAL_KEYSIZE   __einfo_error ( EINFO_EINVAL_KEYSIZE )
#define EINFO_EINVAL_KEYSIZE   __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid key size" )
#define EINVAL_COMPRESSION   __einfo_error ( EINFO_EINVAL_COMPRESSION )
#define EINFO_EINVAL_COMPRESSION   __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid compression")
#define EINVAL_INFINITY   __einfo_error ( EINFO_EINVAL_INFINITY )
#define EINFO_EINVAL_INFINITY   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Point is infinity" )
#define EINVAL_SIGNATURE   __einfo_error ( EINFO_EINVAL_SIGNATURE )
#define EINFO_EINVAL_SIGNATURE   __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid signature" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static int ecdsa_parse_key (struct ecdsa_key *key, const struct asn1_cursor *raw)
 Parse ECDSA key.
static int ecdsa_parse_signature (struct ecdsa_context *ctx, bigint_element_t *rs0, const struct asn1_cursor *raw)
 Parse ECDSA signature value.
static int ecdsa_prepend_signature (struct ecdsa_context *ctx, bigint_element_t *rs0, struct asn1_builder *builder)
 Prepend ECDSA signature value.
static int ecdsa_alloc (struct ecdsa_context *ctx)
 Allocate ECDSA context dynamic storage.
static void ecdsa_free (struct ecdsa_context *ctx)
 Free ECDSA context dynamic storage.
static void ecdsa_init_values (struct ecdsa_context *ctx, struct digest_algorithm *digest, const void *value)
 Initialise ECDSA values.
static int ecdsa_init (struct ecdsa_context *ctx, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value)
 Initialise ECDSA context.
static void ecdsa_invert (struct ecdsa_context *ctx, bigint_element_t *val0)
 Invert ECDSA value.
static int ecdsa_sign_rs (struct ecdsa_context *ctx)
 Generate ECDSA "r" and "s" values.
static int ecdsa_verify_rs (struct ecdsa_context *ctx)
 Verify ECDSA "r" and "s" values.
static int ecdsa_sign (struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, struct asn1_builder *signature)
 Sign digest value using ECDSA.
static int ecdsa_verify (struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
 Verify signed digest using ECDSA.
static int ecdsa_match (struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *private_key, const struct asn1_cursor *public_key)
 Check for matching ECDSA public/private key pair.

Variables

static uint8_t oid_ecpublickey [] = { ASN1_OID_ECPUBLICKEY }
 "ecPublicKey" object identifier
struct asn1_algorithm ecpubkey_algorithm __asn1_algorithm
 Generic elliptic curve container algorithm.
struct pubkey_algorithm ecdsa_algorithm
 ECDSA public-key algorithm.

Detailed Description

Elliptic curve digital signature algorithm (ECDSA).

The elliptic curve public key format is documented in RFC 5480. The original private key format is documented in RFC 5915, and the generic container PKCS#8 format documented in RFC 5208.

Definition in file ecdsa.c.

Macro Definition Documentation

◆ EINVAL_POINTSIZE

#define EINVAL_POINTSIZE   __einfo_error ( EINFO_EINVAL_POINTSIZE )

Definition at line 46 of file ecdsa.c.

46#define EINVAL_POINTSIZE \
47 __einfo_error ( EINFO_EINVAL_POINTSIZE )

Referenced by ecdsa_parse_key().

◆ EINFO_EINVAL_POINTSIZE

#define EINFO_EINVAL_POINTSIZE   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid point size" )

Definition at line 48 of file ecdsa.c.

48#define EINFO_EINVAL_POINTSIZE \
49 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid point size" )

◆ EINVAL_KEYSIZE

#define EINVAL_KEYSIZE   __einfo_error ( EINFO_EINVAL_KEYSIZE )

Definition at line 50 of file ecdsa.c.

50#define EINVAL_KEYSIZE \
51 __einfo_error ( EINFO_EINVAL_KEYSIZE )

Referenced by ecdsa_parse_key(), and ecdsa_parse_signature().

◆ EINFO_EINVAL_KEYSIZE

#define EINFO_EINVAL_KEYSIZE   __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid key size" )

Definition at line 52 of file ecdsa.c.

52#define EINFO_EINVAL_KEYSIZE \
53 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid key size" )

◆ EINVAL_COMPRESSION

#define EINVAL_COMPRESSION   __einfo_error ( EINFO_EINVAL_COMPRESSION )

Definition at line 54 of file ecdsa.c.

54#define EINVAL_COMPRESSION \
55 __einfo_error ( EINFO_EINVAL_COMPRESSION )

Referenced by ecdsa_parse_key().

◆ EINFO_EINVAL_COMPRESSION

#define EINFO_EINVAL_COMPRESSION   __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid compression")

Definition at line 56 of file ecdsa.c.

56#define EINFO_EINVAL_COMPRESSION \
57 __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid compression")

◆ EINVAL_INFINITY

#define EINVAL_INFINITY   __einfo_error ( EINFO_EINVAL_INFINITY )

Definition at line 58 of file ecdsa.c.

58#define EINVAL_INFINITY \
59 __einfo_error ( EINFO_EINVAL_INFINITY )

Referenced by ecdsa_parse_key().

◆ EINFO_EINVAL_INFINITY

#define EINFO_EINVAL_INFINITY   __einfo_uniqify ( EINFO_EINVAL, 0x04, "Point is infinity" )

Definition at line 60 of file ecdsa.c.

60#define EINFO_EINVAL_INFINITY \
61 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Point is infinity" )

◆ EINVAL_SIGNATURE

#define EINVAL_SIGNATURE   __einfo_error ( EINFO_EINVAL_SIGNATURE )

Definition at line 62 of file ecdsa.c.

62#define EINVAL_SIGNATURE \
63 __einfo_error ( EINFO_EINVAL_SIGNATURE )

Referenced by ecdsa_verify(), and ecdsa_verify_rs().

◆ EINFO_EINVAL_SIGNATURE

#define EINFO_EINVAL_SIGNATURE   __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid signature" )

Definition at line 64 of file ecdsa.c.

64#define EINFO_EINVAL_SIGNATURE \
65 __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid signature" )

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ ecdsa_parse_key()

int ecdsa_parse_key ( struct ecdsa_key * key,
const struct asn1_cursor * raw )
static

Parse ECDSA key.

Parameters
keyECDSA key
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 141 of file ecdsa.c.

142 {
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}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
__be32 raw[7]
Definition CIB_PRM.h:0
union @162305117151260234136356364136041353210355154177 key
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned char uint8_t
Definition stdint.h:10
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:382
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:767
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:261
int asn1_enter_any(struct asn1_cursor *cursor)
Enter ASN.1 object of any type.
Definition asn1.c:372
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:323
int asn1_enter_bits(struct asn1_cursor *cursor, unsigned int *unused)
Enter ASN.1 bit string.
Definition asn1.c:403
#define ASN1_INTEGER
ASN.1 integer.
Definition asn1.h:63
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition asn1.h:102
static void asn1_invalidate_cursor(struct asn1_cursor *cursor)
Invalidate ASN.1 object cursor.
Definition asn1.h:494
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:93
#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:505
ring len
Length.
Definition dwmac.h:226
#define EINVAL_INFINITY
Definition ecdsa.c:58
#define EINVAL_POINTSIZE
Definition ecdsa.c:46
#define EINVAL_COMPRESSION
Definition ecdsa.c:54
#define EINVAL_KEYSIZE
Definition ecdsa.c:50
#define ECDSA_UNCOMPRESSED
Uncompressed curve point.
Definition ecdsa.h:16
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
u16 algorithm
Authentication algorithm (Open System or Shared Key).
Definition ieee80211.h:1
static int elliptic_is_infinity(struct elliptic_curve *curve, const void *point)
Definition crypto.h:414
void * memcpy(void *dest, const void *src, size_t len) __nonnull
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An ASN.1 OID-identified algorithm.
Definition asn1.h:429
An ASN.1 object cursor.
Definition asn1.h:21

References algorithm, asn1_curve_algorithm(), asn1_enter(), asn1_enter_any(), asn1_enter_bits(), ASN1_EXPLICIT_TAG, ASN1_INTEGER, asn1_invalidate_cursor(), ASN1_OCTET_STRING, ASN1_SEQUENCE, asn1_skip(), asn1_skip_any(), asn1_type(), asn1_cursor::data, DBGC, DBGC_HDA, ECDSA_UNCOMPRESSED, EINVAL_COMPRESSION, EINVAL_INFINITY, EINVAL_KEYSIZE, EINVAL_POINTSIZE, elliptic_is_infinity(), key, asn1_cursor::len, len, memcpy(), NULL, raw, rc, and strerror().

Referenced by ecdsa_init(), and ecdsa_match().

◆ ecdsa_parse_signature()

int ecdsa_parse_signature ( struct ecdsa_context * ctx,
bigint_element_t * rs0,
const struct asn1_cursor * raw )
static

Parse ECDSA signature value.

Parameters
ctxECDSA context
rs0Element 0 of signature "r" or "s" value
rawASN.1 cursor
Return values
lenCanonical length of "r"/"s", or negative error

Definition at line 288 of file ecdsa.c.

290 {
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 uint8_t msb;
299 size_t len;
300 int rc;
301
302 /* Enter integer */
303 memcpy ( &cursor, raw, sizeof ( cursor ) );
304 if ( ( rc = asn1_enter_unsigned ( &cursor ) ) != 0 ) {
305 DBGC ( ctx, "ECDSA %p invalid integer:\n", ctx );
306 DBGC_HDA ( ctx, 0, raw->data, raw->len );
307 return rc;
308 }
309
310 /* Extract value */
311 if ( cursor.len > keysize ) {
312 DBGC ( ctx, "ECDSA %p invalid signature value:\n", ctx );
313 DBGC_HDA ( ctx, 0, raw->data, raw->len );
314 return -EINVAL_KEYSIZE;
315 }
316 bigint_init ( rs, cursor.data, cursor.len );
317
318 /* Check that value is within the required range */
319 if ( bigint_is_zero ( rs ) || bigint_is_geq ( rs, modulus ) ) {
320 DBGC ( ctx, "ECDSA %p out-of-range signature value:\n", ctx );
321 DBGC_HDA ( ctx, 0, raw->data, raw->len );
322 return -ERANGE;
323 }
324
325 /* Calculate canonical length */
326 msb = *( ( const uint8_t * ) cursor.data );
327 len = ( cursor.len + ( ( msb & 0x80 ) ? 1 : 0 ) );
328 len += asn1_header_len ( len );
329
330 return len;
331}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
int asn1_enter_unsigned(struct asn1_cursor *cursor)
Enter ASN.1 unsigned integer.
Definition asn1.c:459
size_t asn1_header_len(size_t len)
Calculate ASN.1 header length.
Definition asn1.c:1023
uint16_t size
Buffer size.
Definition dwmac.h:3
#define ERANGE
Result too large.
Definition errno.h:683
#define __attribute__(x)
Definition compiler.h:10
#define bigint_is_geq(value, reference)
Compare big integers.
Definition bigint.h:146
#define bigint_is_zero(value)
Test if big integer is equal to zero.
Definition bigint.h:135
#define bigint_t(size)
Define a big-integer type.
Definition bigint.h:21
#define bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:63
u16 keysize
Length of encryption key to be used, network byte order.
Definition wpa.h:10

References __attribute__, asn1_enter_unsigned(), asn1_header_len(), bigint_init, bigint_is_geq, bigint_is_zero, bigint_t, ctx, asn1_cursor::data, DBGC, DBGC_HDA, EINVAL_KEYSIZE, ERANGE, keysize, asn1_cursor::len, len, memcpy(), raw, rc, and size.

Referenced by ecdsa_verify().

◆ ecdsa_prepend_signature()

int ecdsa_prepend_signature ( struct ecdsa_context * ctx,
bigint_element_t * rs0,
struct asn1_builder * builder )
static

Prepend ECDSA signature value.

Parameters
ctxECDSA context
rs0Element 0 of signature "r" or "s" value
builderASN.1 builder
Return values
rcReturn status code

Definition at line 341 of file ecdsa.c.

343 {
344 size_t keysize = ctx->key.curve->keysize;
345 unsigned int size = ctx->size;
346 bigint_t ( size ) __attribute__ (( may_alias )) *rs =
347 ( ( void * ) rs0 );
348 uint8_t buf[ 1 /* potential sign byte */ + keysize ];
349 uint8_t *data;
350 size_t len;
351 int rc;
352
353 /* Construct value */
354 buf[0] = 0;
355 bigint_done ( rs, &buf[1], keysize );
356
357 /* Strip leading zeros */
358 data = buf;
359 len = sizeof ( buf );
360 while ( ( len > 1 ) && ( data[0] == 0 ) && ( data[1] < 0x80 ) ) {
361 data++;
362 len--;
363 }
364
365 /* Prepend integer */
366 if ( ( rc = asn1_prepend ( builder, ASN1_INTEGER, data, len ) ) != 0 )
367 return rc;
368
369 return 0;
370}
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:1092
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define bigint_done(value, out, len)
Finalise big integer.
Definition bigint.h:76

References __attribute__, ASN1_INTEGER, asn1_prepend(), bigint_done, bigint_t, ctx, data, keysize, len, rc, and size.

Referenced by ecdsa_sign().

◆ ecdsa_alloc()

int ecdsa_alloc ( struct ecdsa_context * ctx)
static

Allocate ECDSA context dynamic storage.

Parameters
ctxECDSA context
Return values
rcReturn status code

Definition at line 378 of file ecdsa.c.

378 {
379 struct elliptic_curve *curve = ctx->key.curve;
380 size_t pointsize = curve->pointsize;
381 size_t keysize = curve->keysize;
382 unsigned int size =
383 bigint_required_size ( keysize + 1 /* for addition */ );
384 struct {
385 bigint_t ( size ) modulus;
386 bigint_t ( size ) fermat;
387 bigint_t ( size ) square;
388 bigint_t ( size ) one;
389 bigint_t ( size ) z;
390 bigint_t ( size ) k;
391 bigint_t ( size ) r;
392 bigint_t ( size ) s;
393 bigint_t ( size ) temp;
394 bigint_t ( size * 2 ) product;
395 uint8_t point1[pointsize];
396 uint8_t point2[pointsize];
397 uint8_t scalar[keysize];
398 struct hmac_drbg_state drbg;
399 } *dynamic;
400
401 /* Allocate dynamic storage */
402 dynamic = malloc ( sizeof ( *dynamic ) );
403 if ( ! dynamic )
404 return -ENOMEM;
405
406 /* Populate context */
407 ctx->size = size;
408 ctx->dynamic = dynamic;
409 ctx->modulus0 = dynamic->modulus.element;
410 ctx->fermat0 = dynamic->fermat.element;
411 ctx->square0 = dynamic->square.element;
412 ctx->one0 = dynamic->one.element;
413 ctx->z0 = dynamic->z.element;
414 ctx->k0 = dynamic->k.element;
415 ctx->r0 = dynamic->r.element;
416 ctx->s0 = dynamic->s.element;
417 ctx->temp0 = dynamic->temp.element;
418 ctx->product0 = dynamic->product.element;
419 ctx->point1 = dynamic->point1;
420 ctx->point2 = dynamic->point2;
421 ctx->scalar = dynamic->scalar;
422 ctx->drbg = &dynamic->drbg;
423
424 return 0;
425}
#define ENOMEM
Not enough space.
Definition errno.h:578
#define bigint_required_size(len)
Determine number of elements required for a big-integer type.
Definition bigint.h:32
uint8_t product
Product string.
Definition smbios.h:5
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:677
static const uint8_t r[3][4]
MD4 shift amounts.
Definition md4.c:50
static const uint32_t k[64]
MD5 constants.
Definition md5.c:50
An elliptic curve.
Definition crypto.h:246
size_t keysize
Scalar (and private key) size.
Definition crypto.h:252
size_t pointsize
Point (and public key) size.
Definition crypto.h:250

References bigint_required_size, bigint_t, ctx, ENOMEM, k, elliptic_curve::keysize, keysize, malloc(), elliptic_curve::pointsize, product, r, and size.

Referenced by ecdsa_init().

◆ ecdsa_free()

void ecdsa_free ( struct ecdsa_context * ctx)
static

Free ECDSA context dynamic storage.

Parameters
ctxECDSA context

Definition at line 432 of file ecdsa.c.

432 {
433
434 /* Free dynamic storage */
435 zfree ( ctx->dynamic );
436}
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:738

References ctx, and zfree().

Referenced by ecdsa_init(), ecdsa_sign(), and ecdsa_verify().

◆ ecdsa_init_values()

void ecdsa_init_values ( struct ecdsa_context * ctx,
struct digest_algorithm * digest,
const void * value )
static

Initialise ECDSA values.

Parameters
ctxECDSA context
digestDigest algorithm
valueDigest value

Definition at line 445 of file ecdsa.c.

447 {
448 struct elliptic_curve *curve = ctx->key.curve;
449 unsigned int size = ctx->size;
450 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
451 ( ( void * ) ctx->modulus0 );
452 bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
453 ( ( void * ) ctx->fermat0 );
454 bigint_t ( size ) __attribute__ (( may_alias )) *square =
455 ( ( void * ) ctx->square0 );
456 bigint_t ( size ) __attribute__ (( may_alias )) *one =
457 ( ( void * ) ctx->one0 );
458 bigint_t ( size ) __attribute__ (( may_alias )) *z =
459 ( ( void * ) ctx->z0 );
460 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
461 ( ( void * ) ctx->product0 );
462 static const uint8_t two_raw[] = { 2 };
463 size_t zlen;
464
465 /* Initialise modulus N */
466 bigint_init ( modulus, curve->order, curve->keysize );
467 DBGC2 ( ctx, "ECDSA %p N = %s\n", ctx, bigint_ntoa ( modulus ) );
468
469 /* Calculate N-2 (using Montgomery constant as temporary buffer) */
470 bigint_copy ( modulus, fermat );
471 bigint_init ( square, two_raw, sizeof ( two_raw ) );
472 bigint_subtract ( square, fermat );
473
474 /* Calculate Montgomery constant */
475 bigint_reduce ( modulus, square );
476 DBGC2 ( ctx, "ECDSA %p R^2 = %s mod N\n",
477 ctx, bigint_ntoa ( square ) );
478
479 /* Construct one in Montgomery form */
480 bigint_grow ( square, product );
481 bigint_montgomery ( modulus, product, one );
482 DBGC2 ( ctx, "ECDSA %p R = %s mod N\n",
483 ctx, bigint_ntoa ( one ) );
484
485 /* Initialise digest */
486 ctx->digest = digest;
487 zlen = ctx->key.curve->keysize;
488 if ( zlen > digest->digestsize )
489 zlen = digest->digestsize;
490 ctx->zlen = zlen;
491 bigint_init ( z, value, zlen );
492 DBGC2 ( ctx, "ECDSA %p z = %s (%s)\n",
493 ctx, bigint_ntoa ( z ), digest->name );
494}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
#define DBGC2(...)
Definition compiler.h:547
#define bigint_grow(source, dest)
Grow big integer.
Definition bigint.h:210
#define bigint_reduce(modulus, result)
Reduce big integer R^2 modulo N.
Definition bigint.h:275
#define bigint_subtract(subtrahend, value)
Subtract big integers.
Definition bigint.h:100
#define bigint_montgomery(modulus, value, result)
Perform classic Montgomery reduction (REDC) of a big integer.
Definition bigint.h:315
#define bigint_copy(source, dest)
Copy big integer.
Definition bigint.h:236
#define bigint_ntoa(value)
Transcribe big integer (for debugging).
Definition bigint.h:51
size_t digestsize
Digest size.
Definition crypto.h:27
const char * name
Algorithm name.
Definition crypto.h:21
const void * order
Order of the generator (if prime).
Definition crypto.h:256

References __attribute__, bigint_copy, bigint_grow, bigint_init, bigint_montgomery, bigint_ntoa, bigint_reduce, bigint_subtract, bigint_t, ctx, DBGC2, digest_algorithm::digestsize, elliptic_curve::keysize, digest_algorithm::name, elliptic_curve::order, product, size, and value.

Referenced by ecdsa_init().

◆ ecdsa_init()

int ecdsa_init ( struct ecdsa_context * ctx,
const struct asn1_cursor * key,
struct digest_algorithm * digest,
const void * value )
static

Initialise ECDSA context.

Parameters
ctxECDSA context
keyKey
digestDigest algorithm
valueDigest value
Return values
rcReturn status code

Definition at line 505 of file ecdsa.c.

508 {
509 int rc;
510
511 /* Parse key */
512 if ( ( rc = ecdsa_parse_key ( &ctx->key, key ) ) != 0 )
513 goto err_parse;
514
515 /* Allocate dynamic storage */
516 if ( ( rc = ecdsa_alloc ( ctx ) ) != 0 )
517 goto err_alloc;
518
519 /* Initialise values */
520 ecdsa_init_values ( ctx, digest, value );
521
522 return 0;
523
524 ecdsa_free ( ctx );
525 err_alloc:
526 err_parse:
527 return rc;
528}
static int ecdsa_parse_key(struct ecdsa_key *key, const struct asn1_cursor *raw)
Parse ECDSA key.
Definition ecdsa.c:141
static void ecdsa_init_values(struct ecdsa_context *ctx, struct digest_algorithm *digest, const void *value)
Initialise ECDSA values.
Definition ecdsa.c:445
static int ecdsa_alloc(struct ecdsa_context *ctx)
Allocate ECDSA context dynamic storage.
Definition ecdsa.c:378
static void ecdsa_free(struct ecdsa_context *ctx)
Free ECDSA context dynamic storage.
Definition ecdsa.c:432

References ctx, ecdsa_alloc(), ecdsa_free(), ecdsa_init_values(), ecdsa_parse_key(), key, rc, and value.

Referenced by ecdsa_sign(), and ecdsa_verify().

◆ ecdsa_invert()

void ecdsa_invert ( struct ecdsa_context * ctx,
bigint_element_t * val0 )
static

Invert ECDSA value.

Parameters
ctxECDSA context
val0Element 0 of value to invert

Definition at line 536 of file ecdsa.c.

537 {
538 unsigned int size = ctx->size;
539 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
540 ( ( void * ) ctx->modulus0 );
541 bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
542 ( ( void * ) ctx->fermat0 );
543 bigint_t ( size ) __attribute__ (( may_alias )) *square =
544 ( ( void * ) ctx->square0 );
545 bigint_t ( size ) __attribute__ (( may_alias )) *one =
546 ( ( void * ) ctx->one0 );
547 bigint_t ( size ) __attribute__ (( may_alias )) *temp =
548 ( ( void * ) ctx->temp0 );
549 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
550 ( ( void * ) ctx->product0 );
551 bigint_t ( size ) __attribute__ (( may_alias )) *val =
552 ( ( void * ) val0 );
553
554 /* Convert value to Montgomery form */
555 bigint_multiply ( val, square, product );
556 bigint_montgomery ( modulus, product, temp );
557
558 /* Invert value via Fermat's little theorem */
559 bigint_copy ( one, val );
560 bigint_ladder ( val, temp, fermat, bigint_mod_exp_ladder, modulus,
561 product );
562}
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:854
#define bigint_ladder(result, multiple, exponent, op, ctx, tmp)
Perform generalised exponentiation via a Montgomery ladder.
Definition bigint.h:331
#define bigint_multiply(multiplicand, multiplier, result)
Multiply big integers.
Definition bigint.h:261
void __asmcall int val
Definition setjmp.h:12

References __attribute__, bigint_copy, bigint_ladder, bigint_mod_exp_ladder(), bigint_montgomery, bigint_multiply, bigint_t, ctx, product, size, and val.

Referenced by ecdsa_sign_rs(), and ecdsa_verify_rs().

◆ ecdsa_sign_rs()

int ecdsa_sign_rs ( struct ecdsa_context * ctx)
static

Generate ECDSA "r" and "s" values.

Parameters
ctxECDSA context
sigSignature
Return values
rcReturn status code

Definition at line 571 of file ecdsa.c.

571 {
572 struct digest_algorithm *digest = ctx->digest;
573 struct elliptic_curve *curve = ctx->key.curve;
574 size_t pointsize = curve->pointsize;
575 size_t keysize = curve->keysize;
576 unsigned int size = ctx->size;
577 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
578 ( ( void * ) ctx->modulus0 );
579 bigint_t ( size ) __attribute__ (( may_alias )) *square =
580 ( ( void * ) ctx->square0 );
581 bigint_t ( size ) __attribute__ (( may_alias )) *one =
582 ( ( void * ) ctx->one0 );
583 bigint_t ( size ) __attribute__ (( may_alias )) *z =
584 ( ( void * ) ctx->z0 );
585 bigint_t ( size ) __attribute__ (( may_alias )) *k =
586 ( ( void * ) ctx->k0 );
587 bigint_t ( size ) __attribute__ (( may_alias )) *r =
588 ( ( void * ) ctx->r0 );
589 bigint_t ( size ) __attribute__ (( may_alias )) *s =
590 ( ( void * ) ctx->s0 );
591 bigint_t ( size ) __attribute__ (( may_alias )) *temp =
592 ( ( void * ) ctx->temp0 );
593 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
594 ( ( void * ) ctx->product0 );
595 bigint_t ( size ) __attribute__ (( may_alias )) *x1 =
596 ( ( void * ) temp );
597 void *point1 = ctx->point1;
598 void *scalar = ctx->scalar;
599 int rc;
600
601 /* Loop until a suitable signature is generated */
602 while ( 1 ) {
603
604 /* Generate pseudo-random data */
605 if ( ( rc = hmac_drbg_generate ( digest, ctx->drbg, NULL, 0,
606 scalar, keysize ) ) != 0 ) {
607 DBGC ( ctx, "ECDSA %p could not generate: %s\n",
608 ctx, strerror ( rc ) );
609 return rc;
610 }
611
612 /* Check suitability of pseudo-random data */
613 bigint_init ( k, scalar, keysize );
614 DBGC2 ( ctx, "ECDSA %p k = %s\n",
615 ctx, bigint_ntoa ( k ) );
616 if ( bigint_is_zero ( k ) )
617 continue;
618 if ( bigint_is_geq ( k, modulus ) )
619 continue;
620
621 /* Calculate (x1,y1) = k*G */
622 elliptic_multiply ( curve, curve->base, scalar, point1 );
623 bigint_init ( x1, point1, ( pointsize / 2 ) );
624 DBGC2 ( ctx, "ECDSA %p x1 = %s mod N\n",
625 ctx, bigint_ntoa ( x1 ) );
626
627 /* Calculate r = x1 mod N */
628 bigint_multiply ( x1, one, product );
629 bigint_montgomery ( modulus, product, r );
630 DBGC2 ( ctx, "ECDSA %p r = %s\n",
631 ctx, bigint_ntoa ( r ) );
632
633 /* Check suitability of r */
634 if ( bigint_is_zero ( r ) )
635 continue;
636
637 /* Calculate k^-1 mod N (in Montgomery form) */
638 ecdsa_invert ( ctx, k->element );
639 DBGC2 ( ctx, "ECDSA %p (k^-1)R = %s mod N\n",
640 ctx, bigint_ntoa ( k ) );
641
642 /* Calculate r * dA */
643 bigint_init ( temp, ctx->key.private, keysize );
644 DBGC2 ( ctx, "ECDSA %p dA = %s\n",
645 ctx, bigint_ntoa ( temp ) );
646 bigint_multiply ( r, temp, product );
647 bigint_montgomery ( modulus, product, temp );
648 bigint_multiply ( temp, square, product );
649 bigint_montgomery ( modulus, product, temp );
650 DBGC2 ( ctx, "ECDSA %p r*dA = %s mod N\n",
651 ctx, bigint_ntoa ( temp ) );
652
653 /* Calculate k^-1 * (z + r*dA) */
654 bigint_add ( z, temp );
655 DBGC2 ( ctx, "ECDSA %p z+r*dA = %s mod N\n",
656 ctx, bigint_ntoa ( temp ) );
657 bigint_multiply ( k, temp, product );
658 bigint_montgomery ( modulus, product, s );
659 DBGC2 ( ctx, "ECDSA %p s = %s\n",
660 ctx, bigint_ntoa ( s ) );
661
662 /* Check suitability of s */
663 if ( bigint_is_zero ( s ) )
664 continue;
665
666 return 0;
667 }
668}
static void ecdsa_invert(struct ecdsa_context *ctx, bigint_element_t *val0)
Invert ECDSA value.
Definition ecdsa.c:536
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
#define bigint_add(addend, value)
Add big integers.
Definition bigint.h:88
static int elliptic_multiply(struct elliptic_curve *curve, const void *base, const void *scalar, void *result)
Definition crypto.h:419
A message digest algorithm.
Definition crypto.h:19
const void * base
Generator base point.
Definition crypto.h:254

References __attribute__, elliptic_curve::base, bigint_add, bigint_init, bigint_is_geq, bigint_is_zero, bigint_montgomery, bigint_multiply, bigint_ntoa, bigint_t, ctx, DBGC, DBGC2, ecdsa_invert(), elliptic_multiply(), hmac_drbg_generate(), k, elliptic_curve::keysize, keysize, NULL, elliptic_curve::pointsize, product, r, rc, size, and strerror().

Referenced by ecdsa_sign().

◆ ecdsa_verify_rs()

int ecdsa_verify_rs ( struct ecdsa_context * ctx)
static

Verify ECDSA "r" and "s" values.

Parameters
ctxECDSA context
sigSignature
Return values
rcReturn status code

Definition at line 677 of file ecdsa.c.

677 {
678 struct elliptic_curve *curve = ctx->key.curve;
679 size_t pointsize = curve->pointsize;
680 size_t keysize = curve->keysize;
681 const void *public = ctx->key.public;
682 unsigned int size = ctx->size;
683 bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
684 ( ( void * ) ctx->modulus0 );
685 bigint_t ( size ) __attribute__ (( may_alias )) *one =
686 ( ( void * ) ctx->one0 );
687 bigint_t ( size ) __attribute__ (( may_alias )) *z =
688 ( ( void * ) ctx->z0 );
689 bigint_t ( size ) __attribute__ (( may_alias )) *r =
690 ( ( void * ) ctx->r0 );
691 bigint_t ( size ) __attribute__ (( may_alias )) *s =
692 ( ( void * ) ctx->s0 );
693 bigint_t ( size ) __attribute__ (( may_alias )) *temp =
694 ( ( void * ) ctx->temp0 );
695 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
696 ( ( void * ) ctx->product0 );
697 bigint_t ( size ) __attribute__ (( may_alias )) *u1 =
698 ( ( void * ) temp );
699 bigint_t ( size ) __attribute__ (( may_alias )) *u2 =
700 ( ( void * ) temp );
701 bigint_t ( size ) __attribute__ (( may_alias )) *x1 =
702 ( ( void * ) temp );
703 void *point1 = ctx->point1;
704 void *point2 = ctx->point2;
705 void *scalar = ctx->scalar;
706 int valid;
707 int rc;
708
709 DBGC2 ( ctx, "ECDSA %p r = %s\n", ctx, bigint_ntoa ( r ) );
710 DBGC2 ( ctx, "ECDSA %p s = %s\n", ctx, bigint_ntoa ( s ) );
711
712 /* Calculate s^-1 mod N (in Montgomery form) */
713 ecdsa_invert ( ctx, s->element );
714 DBGC2 ( ctx, "ECDSA %p (s^-1)R = %s mod N\n", ctx, bigint_ntoa ( s ) );
715
716 /* Calculate u1 = (z * s^-1) mod N */
717 bigint_multiply ( z, s, product );
718 bigint_montgomery ( modulus, product, u1 );
719 DBGC2 ( ctx, "ECDSA %p u1 = %s mod N\n",
720 ctx, bigint_ntoa ( u1 ) );
721 bigint_done ( u1, scalar, keysize );
722
723 /* Calculate u1 * G */
724 if ( ( rc = elliptic_multiply ( curve, curve->base, scalar,
725 point1 ) ) != 0 ) {
726 DBGC ( ctx, "ECDSA %p could not calculate u1*G: %s\n",
727 ctx, strerror ( rc ) );
728 return rc;
729 }
730
731 /* Calculate u2 = (r * s^-1) mod N */
732 bigint_multiply ( r, s, product );
733 bigint_montgomery ( modulus, product, u2 );
734 bigint_done ( u2, scalar, keysize );
735 DBGC2 ( ctx, "ECDSA %p u2 = %s mod N\n",
736 ctx, bigint_ntoa ( u2 ) );
737
738 /* Calculate u2 * Qa */
739 if ( ( rc = elliptic_multiply ( curve, public, scalar,
740 point2 ) ) != 0 ) {
741 DBGC ( ctx, "ECDSA %p could not calculate u2*Qa: %s\n",
742 ctx, strerror ( rc ) );
743 return rc;
744 }
745
746 /* Calculate u1 * G + u2 * Qa */
747 if ( ( rc = elliptic_add ( curve, point1, point2, point1 ) ) != 0 ) {
748 DBGC ( ctx, "ECDSA %p could not calculate u1*G+u2*Qa: %s\n",
749 ctx, strerror ( rc ) );
750 return rc;
751 }
752
753 /* Check that result is not the point at infinity */
754 if ( elliptic_is_infinity ( curve, point1 ) ) {
755 DBGC ( ctx, "ECDSA %p result is point at infinity\n", ctx );
756 return -EINVAL;
757 }
758
759 /* Calculate x1 mod N */
760 bigint_init ( x1, point1, ( pointsize / 2 ) );
761 DBGC2 ( ctx, "ECDSA %p x1 = %s mod N\n", ctx, bigint_ntoa ( x1 ) );
762 bigint_multiply ( x1, one, product );
763 bigint_montgomery ( modulus, product, x1 );
764 DBGC2 ( ctx, "ECDSA %p x1 = %s\n", ctx, bigint_ntoa ( x1 ) );
765
766 /* Check signature */
767 bigint_subtract ( x1, r );
768 valid = bigint_is_zero ( r );
769 DBGC2 ( ctx, "ECDSA %p signature is%s valid\n",
770 ctx, ( valid ? "" : " not" ) );
771
772 return ( valid ? 0 : -EINVAL_SIGNATURE );
773}
#define EINVAL_SIGNATURE
Definition ecdsa.c:62
#define EINVAL
Invalid argument.
Definition errno.h:472
static int elliptic_add(struct elliptic_curve *curve, const void *addend, const void *augend, void *result)
Definition crypto.h:425

References __attribute__, elliptic_curve::base, bigint_done, bigint_init, bigint_is_zero, bigint_montgomery, bigint_multiply, bigint_ntoa, bigint_subtract, bigint_t, ctx, DBGC, DBGC2, ecdsa_invert(), EINVAL, EINVAL_SIGNATURE, elliptic_add(), elliptic_is_infinity(), elliptic_multiply(), elliptic_curve::keysize, keysize, elliptic_curve::pointsize, product, r, rc, size, and strerror().

Referenced by ecdsa_verify().

◆ ecdsa_sign()

int ecdsa_sign ( struct pubkey_algorithm *pubkey __unused,
const struct asn1_cursor * key,
struct digest_algorithm * digest,
const void * value,
struct asn1_builder * signature )
static

Sign digest value using ECDSA.

Parameters
pubkeyPublic-key algorithm
keyKey
digestDigest algorithm
valueDigest value
signatureSignature
Return values
rcReturn status code

Definition at line 785 of file ecdsa.c.

788 {
789 struct ecdsa_context ctx;
790 int rc;
791
792 /* Initialise context */
793 if ( ( rc = ecdsa_init ( &ctx, key, digest, value ) ) != 0 )
794 goto err_init;
795
796 /* Fail unless we have a private key */
797 if ( ! ctx.key.private ) {
798 rc = -ENOTTY;
799 goto err_no_key;
800 }
801
802 /* Instantiate DRBG */
803 hmac_drbg_instantiate ( digest, ctx.drbg, ctx.key.private,
804 ctx.key.curve->keysize, value, ctx.zlen );
805
806 /* Create signature */
807 if ( ( rc = ecdsa_sign_rs ( &ctx ) ) != 0 )
808 goto err_signature;
809
810 /* Construct "r" and "s" values */
811 if ( ( rc = ecdsa_prepend_signature ( &ctx, ctx.s0, signature ) ) != 0)
812 goto err_s;
813 if ( ( rc = ecdsa_prepend_signature ( &ctx, ctx.r0, signature ) ) != 0)
814 goto err_r;
815 if ( ( rc = asn1_wrap ( signature, ASN1_SEQUENCE ) ) != 0 )
816 goto err_wrap;
817
818 /* Free context */
819 ecdsa_free ( &ctx );
820
821 return 0;
822
823 err_wrap:
824 err_r:
825 err_s:
826 err_signature:
827 err_no_key:
828 ecdsa_free ( &ctx );
829 err_init:
830 return rc;
831}
u8 signature
CPU signature.
Definition CIB_PRM.h:7
int asn1_wrap(struct asn1_builder *builder, unsigned int type)
Wrap ASN.1 builder.
Definition asn1.c:1119
static int ecdsa_sign_rs(struct ecdsa_context *ctx)
Generate ECDSA "r" and "s" values.
Definition ecdsa.c:571
static int ecdsa_prepend_signature(struct ecdsa_context *ctx, bigint_element_t *rs0, struct asn1_builder *builder)
Prepend ECDSA signature value.
Definition ecdsa.c:341
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:505
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
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
ECDSA context.
Definition ecdsa.c:92
struct digest_algorithm * digest
Digest algorithm.
Definition ecdsa.c:98

References __unused, ASN1_SEQUENCE, asn1_wrap(), ctx, ecdsa_context::digest, ecdsa_free(), ecdsa_init(), ecdsa_prepend_signature(), ecdsa_sign_rs(), ENOTTY, hmac_drbg_instantiate(), key, rc, signature, and value.

◆ ecdsa_verify()

int ecdsa_verify ( struct pubkey_algorithm *pubkey __unused,
const struct asn1_cursor * key,
struct digest_algorithm * digest,
const void * value,
const struct asn1_cursor * signature )
static

Verify signed digest using ECDSA.

Parameters
pubkeyPublic-key algorithm
keyKey
digestDigest algorithm
valueDigest value
signatureSignature
Return values
rcReturn status code

Definition at line 843 of file ecdsa.c.

846 {
847 struct ecdsa_context ctx;
848 struct asn1_cursor cursor;
849 int rlen;
850 int slen;
851 size_t len;
852 int rc;
853
854 /* Initialise context */
855 if ( ( rc = ecdsa_init ( &ctx, key, digest, value ) ) != 0 )
856 goto err_init;
857
858 /* Enter sequence */
859 memcpy ( &cursor, signature, sizeof ( cursor ) );
860 asn1_enter ( &cursor, ASN1_SEQUENCE );
861
862 /* Extract "r" and "s" values */
863 if ( ( rlen = ecdsa_parse_signature ( &ctx, ctx.r0, &cursor ) ) < 0 ) {
864 rc = rlen;
865 goto err_parse;
866 }
867 asn1_skip_any ( &cursor );
868 if ( ( slen = ecdsa_parse_signature ( &ctx, ctx.s0, &cursor ) ) < 0 ) {
869 rc = slen;
870 goto err_parse;
871 }
872
873 /* Check for any extraneous content in signature */
874 len = ( rlen + slen );
875 len += asn1_header_len ( len );
876 if ( len != signature->len ) {
877 DBGC ( &ctx, "ECDSA %p non-canonical signature:\n", &ctx );
878 DBGC_HDA ( &ctx, 0, signature->data, signature->len );
880 goto err_parse;
881 }
882
883 /* Verify signature */
884 if ( ( rc = ecdsa_verify_rs ( &ctx ) ) != 0 )
885 goto err_verify;
886
887 /* Free context */
888 ecdsa_free ( &ctx );
889
890 return 0;
891
892 err_verify:
893 err_parse:
894 ecdsa_free ( &ctx );
895 err_init:
896 return rc;
897}
static int ecdsa_verify_rs(struct ecdsa_context *ctx)
Verify ECDSA "r" and "s" values.
Definition ecdsa.c:677
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

References __unused, asn1_enter(), asn1_header_len(), ASN1_SEQUENCE, asn1_skip_any(), ctx, DBGC, DBGC_HDA, ecdsa_free(), ecdsa_init(), ecdsa_parse_signature(), ecdsa_verify_rs(), EINVAL_SIGNATURE, key, len, memcpy(), rc, signature, and value.

◆ ecdsa_match()

int ecdsa_match ( struct pubkey_algorithm *pubkey __unused,
const struct asn1_cursor * private_key,
const struct asn1_cursor * public_key )
static

Check for matching ECDSA public/private key pair.

Parameters
pubkeyPublic-key algorithm
private_keyPrivate key
public_keyPublic key
Return values
rcReturn status code

Definition at line 907 of file ecdsa.c.

909 {
910 struct elliptic_curve *curve;
911 struct ecdsa_key private;
912 struct ecdsa_key public;
913 int rc;
914
915 /* Parse keys */
916 if ( ( rc = ecdsa_parse_key ( &private, private_key ) ) != 0 )
917 return rc;
918 if ( ( rc = ecdsa_parse_key ( &public, public_key ) ) != 0 )
919 return rc;
920
921 /* Compare curves */
922 if ( private.curve != public.curve )
923 return -ENOTTY;
924 curve = private.curve;
925
926 /* Compare public curve points */
927 if ( memcmp ( private.public, public.public, curve->pointsize ) != 0 )
928 return -ENOTTY;
929
930 return 0;
931}
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An ECDSA key.
Definition ecdsa.c:82
struct elliptic_curve * curve
Elliptic curve.
Definition ecdsa.c:84
const void * private
Private multiple of base curve point (if applicable).
Definition ecdsa.c:88
const void * public
Public curve point.
Definition ecdsa.c:86
A private key.
Definition privkey.h:17

References __unused, ecdsa_key::curve, ecdsa_parse_key(), ENOTTY, memcmp(), elliptic_curve::pointsize, ecdsa_key::private, ecdsa_key::public, and rc.

Variable Documentation

◆ oid_ecpublickey

uint8_t oid_ecpublickey[] = { ASN1_OID_ECPUBLICKEY }
static

"ecPublicKey" object identifier

Definition at line 68 of file ecdsa.c.

#define ASN1_OID_ECPUBLICKEY
ASN.1 OID for ecPublicKey (1.2.840.10045.2.1).
Definition asn1.h:135

◆ __asn1_algorithm

struct asn1_algorithm ecpubkey_algorithm __asn1_algorithm
Initial value:
= {
.name = "ecPublicKey",
.pubkey = &ecdsa_algorithm,
}
#define ASN1_CURSOR(value)
Define an ASN.1 cursor for a static value.
Definition asn1.h:423
struct pubkey_algorithm ecdsa_algorithm
ECDSA public-key algorithm.
Definition ecdsa.c:934
static uint8_t oid_ecpublickey[]
"ecPublicKey" object identifier
Definition ecdsa.c:68

Generic elliptic curve container algorithm.

The actual curve to be used is identified via the algorithm parameters, rather than the top-level OID.

Definition at line 75 of file ecdsa.c.

75 {
76 .name = "ecPublicKey",
78 .pubkey = &ecdsa_algorithm,
79};

◆ ecdsa_algorithm

struct pubkey_algorithm ecdsa_algorithm
Initial value:
= {
.name = "ecdsa",
.encrypt = pubkey_null_encrypt,
.decrypt = pubkey_null_decrypt,
.sign = ecdsa_sign,
.verify = ecdsa_verify,
.match = ecdsa_match,
}
int pubkey_null_decrypt(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key __unused, const struct asn1_cursor *ciphertext __unused, struct asn1_builder *plaintext __unused)
int pubkey_null_encrypt(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key __unused, const struct asn1_cursor *plaintext __unused, struct asn1_builder *ciphertext __unused)
static int ecdsa_match(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *private_key, const struct asn1_cursor *public_key)
Check for matching ECDSA public/private key pair.
Definition ecdsa.c:907
static int ecdsa_sign(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, struct asn1_builder *signature)
Sign digest value using ECDSA.
Definition ecdsa.c:785
static int ecdsa_verify(struct pubkey_algorithm *pubkey __unused, 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:843

ECDSA public-key algorithm.

Definition at line 934 of file ecdsa.c.

934 {
935 .name = "ecdsa",
936 .encrypt = pubkey_null_encrypt,
937 .decrypt = pubkey_null_decrypt,
938 .sign = ecdsa_sign,
939 .verify = ecdsa_verify,
940 .match = ecdsa_match,
941};

Referenced by __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), and PUBKEY_TEST().