Skip to content

Commit 88057f2

Browse files
committed
refactor: clarify error handling for missing vs malformed params for EC2 and OKP keys
Signed-off-by: Ken Takayama <[email protected]>
1 parent 52af599 commit 88057f2

File tree

2 files changed

+57
-23
lines changed

2 files changed

+57
-23
lines changed

key.go

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,9 @@ var (
427427
// The following errors are used multiple times
428428
// in Key.validate. We declare them here to avoid
429429
// duplication. They are not considered public errors.
430-
errCoordOverflow = fmt.Errorf("%w: overflowing coordinate", ErrInvalidKey)
431-
errReqParamsMissing = fmt.Errorf("%w: required parameters missing", ErrInvalidKey)
432-
errInvalidCurve = fmt.Errorf("%w: curve not supported for the given key type", ErrInvalidKey)
430+
errCoordSizeMismatch = fmt.Errorf("%w: coordinate size mismatch", ErrInvalidKey)
431+
errReqParamsMissing = fmt.Errorf("%w: required parameters missing", ErrInvalidKey)
432+
errInvalidCurve = fmt.Errorf("%w: curve not supported for the given key type", ErrInvalidKey)
433433
)
434434

435435
// Validate ensures that the parameters set inside the Key are internally
@@ -439,28 +439,49 @@ func (k Key) validate(op KeyOp) error {
439439
switch k.Type {
440440
case KeyTypeEC2:
441441
crv, x, y, d := k.EC2()
442+
// Check required paraemeters exist
442443
switch op {
443444
case KeyOpVerify:
444-
if len(x) == 0 || len(y) == 0 {
445+
if x == nil || y == nil {
445446
return ErrEC2NoPub
446447
}
447448
case KeyOpSign:
448-
if len(d) == 0 {
449+
if d == nil {
449450
return ErrNotPrivKey
450451
}
451452
}
452-
if crv == CurveReserved || (len(x) == 0 && len(y) == 0 && len(d) == 0) {
453+
if crv == CurveReserved || (x == nil && y == nil && d == nil) {
453454
return errReqParamsMissing
454455
}
456+
457+
// Then, validate their length if exist and if the size is known
455458
if size := curveSize(crv); size > 0 {
456459
if len(y) == 0 && len(x) == size+1 {
460+
// NOTE: RFC 9053 Section 7.1.1 describes compressed points in COSE_Key
461+
// using a boolean y-coordinate value (false/true). However, this code
462+
// currently assumes SEC1-style compression, where 0x02 or 0x03 is prepended
463+
// to the x-coordinate.
464+
//
465+
// This behavior may change in the future, for example, we might compute the
466+
// y-coordinate during UnmarshalCBOR, and MarshalCBOR would avoid emitting
467+
// compressed points entirely.
468+
//
469+
// In that case, this conditional may become unnecessary, since the general
470+
// length check below (`len(x) > 0 && len(x) != size`) would already catch
471+
// invalid compressed input.
472+
//
473+
// See discussion in https://github.com/veraison/go-cose/pull/223 .
474+
// Consider revisiting this logic in a future update.
457475
return fmt.Errorf("%w: compressed point not supported", ErrInvalidPubKey)
458476
}
459-
if len(x) != size || len(y) != size {
460-
return ErrInvalidPubKey
477+
if len(x) > 0 && len(x) != size {
478+
return errCoordSizeMismatch
479+
}
480+
if len(y) > 0 && len(y) != size {
481+
return errCoordSizeMismatch
461482
}
462483
if len(d) > 0 && len(d) != size {
463-
return ErrInvalidPrivKey
484+
return errCoordSizeMismatch
464485
}
465486
}
466487
switch crv {
@@ -472,21 +493,27 @@ func (k Key) validate(op KeyOp) error {
472493
}
473494
case KeyTypeOKP:
474495
crv, x, d := k.OKP()
496+
// Check required paraemeters exist
475497
switch op {
476498
case KeyOpVerify:
477-
if len(x) == 0 {
499+
if x == nil {
478500
return ErrOKPNoPub
479501
}
480502
case KeyOpSign:
481-
if len(d) == 0 {
503+
if d == nil {
482504
return ErrNotPrivKey
483505
}
484506
}
485-
if crv == CurveReserved || (len(x) == 0 && len(d) == 0) {
507+
if crv == CurveReserved || (x == nil && d == nil) {
486508
return errReqParamsMissing
487509
}
488-
if (len(x) > 0 && len(x) != ed25519.PublicKeySize) || (len(d) > 0 && len(d) != ed25519.SeedSize) {
489-
return errCoordOverflow
510+
511+
// Then, validate their length if exist and if the size is known
512+
if len(x) > 0 && len(x) != ed25519.PublicKeySize {
513+
return errCoordSizeMismatch
514+
}
515+
if len(d) > 0 && len(d) != ed25519.SeedSize {
516+
return errCoordSizeMismatch
490517
}
491518
switch crv {
492519
case CurveP256, CurveP384, CurveP521:

key_test.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -869,11 +869,11 @@ func TestNewKeyOKP(t *testing.T) {
869869
}, {
870870
name: "invalid x", args: args{AlgorithmEdDSA, x[:31], d},
871871
want: nil,
872-
wantErr: errCoordOverflow.Error(),
872+
wantErr: errCoordSizeMismatch.Error(),
873873
}, {
874874
name: "invalid d", args: args{AlgorithmEdDSA, x, d[:31]},
875875
want: nil,
876-
wantErr: errCoordOverflow.Error(),
876+
wantErr: errCoordSizeMismatch.Error(),
877877
},
878878
}
879879
for _, tt := range tests {
@@ -1520,8 +1520,15 @@ func TestKey_PrivateKey(t *testing.T) {
15201520
KeyLabelEC2D: ec256d,
15211521
},
15221522
},
1523-
nil,
1524-
ErrInvalidPubKey.Error(),
1523+
&ecdsa.PrivateKey{
1524+
PublicKey: ecdsa.PublicKey{
1525+
Curve: elliptic.P256(),
1526+
X: new(big.Int).SetBytes([]byte{}),
1527+
Y: new(big.Int).SetBytes([]byte{}),
1528+
},
1529+
D: new(big.Int).SetBytes(ec256d),
1530+
},
1531+
"",
15251532
}, {
15261533
"CurveP384", &Key{
15271534
Type: KeyTypeEC2,
@@ -1597,7 +1604,7 @@ func TestKey_PrivateKey(t *testing.T) {
15971604
},
15981605
},
15991606
nil,
1600-
"invalid key: overflowing coordinate",
1607+
errCoordSizeMismatch.Error(),
16011608
}, {
16021609
"OKP incorrect d size", &Key{
16031610
Type: KeyTypeOKP,
@@ -1608,7 +1615,7 @@ func TestKey_PrivateKey(t *testing.T) {
16081615
},
16091616
},
16101617
nil,
1611-
"invalid key: overflowing coordinate",
1618+
errCoordSizeMismatch.Error(),
16121619
}, {
16131620
"EC2 missing D", &Key{
16141621
Type: KeyTypeEC2,
@@ -1643,7 +1650,7 @@ func TestKey_PrivateKey(t *testing.T) {
16431650
},
16441651
},
16451652
nil,
1646-
ErrInvalidPubKey.Error(),
1653+
errCoordSizeMismatch.Error(),
16471654
}, {
16481655
"EC2 incorrect y size", &Key{
16491656
Type: KeyTypeEC2,
@@ -1655,7 +1662,7 @@ func TestKey_PrivateKey(t *testing.T) {
16551662
},
16561663
},
16571664
nil,
1658-
ErrInvalidPubKey.Error(),
1665+
errCoordSizeMismatch.Error(),
16591666
}, {
16601667
"EC2 incorrect d size", &Key{
16611668
Type: KeyTypeEC2,
@@ -1667,7 +1674,7 @@ func TestKey_PrivateKey(t *testing.T) {
16671674
},
16681675
},
16691676
nil,
1670-
ErrInvalidPrivKey.Error(),
1677+
errCoordSizeMismatch.Error(),
16711678
},
16721679
}
16731680
for _, tt := range tests {

0 commit comments

Comments
 (0)