-
Notifications
You must be signed in to change notification settings - Fork 40
/
ecdsa.go
92 lines (84 loc) · 2.89 KB
/
ecdsa.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//
// Copyright (c) SAS Institute Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package p11token
import (
"crypto"
"crypto/ecdsa"
"errors"
"github.com/miekg/pkcs11"
"github.com/sassoftware/relic/v8/lib/x509tools"
)
// Convert token ECDSA public key to *ecdsa.PublicKey
func (key *Key) toEcdsaKey() (crypto.PublicKey, error) {
ecparams := key.token.getAttribute(key.pub, pkcs11.CKA_EC_PARAMS)
ecpoint := key.token.getAttribute(key.pub, pkcs11.CKA_EC_POINT)
if len(ecparams) == 0 || len(ecpoint) == 0 {
return nil, errors.New("Unable to retrieve ECDSA public key")
}
curve, err := x509tools.CurveByDer(ecparams)
if err != nil {
return nil, err
}
x, y := x509tools.DerToPoint(curve.Curve, ecpoint)
if x == nil || y == nil {
return nil, errors.New("Invalid elliptic curve point")
}
eckey := &ecdsa.PublicKey{Curve: curve.Curve, X: x, Y: y}
return eckey, nil
}
// Sign a digest using token ECDSA private key
func (key *Key) signECDSA(digest []byte) (der []byte, err error) {
mech := pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)
err = key.token.ctx.SignInit(key.token.sh, []*pkcs11.Mechanism{mech}, key.priv)
if err != nil {
return nil, err
}
sig, err := key.token.ctx.Sign(key.token.sh, digest)
if err != nil {
return nil, err
}
parsed, err := x509tools.UnpackEcdsaSignature(sig)
if err != nil {
return nil, err
}
return parsed.Marshal(), nil
}
// Generate ECDSA-specific public and private key attributes from a PrivateKey
func ecdsaImportAttrs(priv *ecdsa.PrivateKey) (pubAttrs, privAttrs []*pkcs11.Attribute, err error) {
curve, err := x509tools.CurveByCurve(priv.Curve)
if err != nil {
return nil, nil, err
}
pubAttrs = []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, curve.ToDer()),
pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, x509tools.PointToDer(&priv.PublicKey)),
}
privAttrs = []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, curve.ToDer()),
pkcs11.NewAttribute(pkcs11.CKA_VALUE, priv.D.Bytes()),
}
return
}
// Generate ECDSA-specific public attributes to generate an ECSDA key in the token
func ecdsaGenerateAttrs(bits uint) ([]*pkcs11.Attribute, *pkcs11.Mechanism, error) {
curve, err := x509tools.CurveByBits(bits)
if err != nil {
return nil, nil, err
}
pubAttrs := []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, curve.ToDer())}
mech := pkcs11.NewMechanism(pkcs11.CKM_EC_KEY_PAIR_GEN, nil)
return pubAttrs, mech, nil
}