1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package p11token
18
19 import (
20 "crypto"
21 "crypto/ecdsa"
22 "crypto/rand"
23 "crypto/rsa"
24 "encoding/hex"
25 "errors"
26
27 "github.com/miekg/pkcs11"
28 "github.com/sassoftware/relic/lib/pkcs8"
29 "github.com/sassoftware/relic/token"
30 )
31
32
33 var newPublicKeyAttrs = []*pkcs11.Attribute{
34 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
35 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
36 pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, false),
37 pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
38 }
39
40
41 var newPrivateKeyAttrs = []*pkcs11.Attribute{
42 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
43 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
44 pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
45 pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
46 pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
47 pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
48 }
49
50
51
52 func (tok *Token) importPkcs8(pk8 []byte, attrs []*pkcs11.Attribute) error {
53
54 genMech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_KEY_GEN, nil)}
55 wrapKey, err := tok.ctx.GenerateKey(tok.sh, genMech, []*pkcs11.Attribute{
56 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, false),
57 pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
58 pkcs11.NewAttribute(pkcs11.CKA_UNWRAP, true),
59 })
60 if err != nil {
61 return err
62 }
63 defer tok.ctx.DestroyObject(tok.sh, wrapKey)
64
65 iv := make([]byte, 8)
66 if _, err := rand.Reader.Read(iv); err != nil {
67 return err
68 }
69 encMech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DES3_CBC_PAD, iv)}
70 if err := tok.ctx.EncryptInit(tok.sh, encMech, wrapKey); err != nil {
71 return err
72 }
73 wrapped, err := tok.ctx.Encrypt(tok.sh, pk8)
74 if err != nil {
75 return err
76 }
77
78 if _, err := tok.ctx.UnwrapKey(tok.sh, encMech, wrapKey, wrapped, attrs); err != nil {
79 return err
80 }
81 return nil
82 }
83
84
85 func (tok *Token) Import(keyName string, privKey crypto.PrivateKey) (token.Key, error) {
86 keyConf, err := tok.config.GetKey(keyName)
87 if err != nil {
88 return nil, err
89 }
90 if keyConf.Label == "" {
91 return nil, errors.New("Key attribute 'label' must be defined in order to create an object")
92 }
93 keyID := makeKeyID()
94 if keyID == nil {
95 return nil, errors.New("failed to make key ID")
96 }
97 var pubTypeAttrs, privTypeAttrs []*pkcs11.Attribute
98 var keyType uint
99 switch priv := privKey.(type) {
100 case *rsa.PrivateKey:
101 keyType = pkcs11.CKK_RSA
102 pubTypeAttrs, privTypeAttrs, err = rsaImportAttrs(priv)
103 case *ecdsa.PrivateKey:
104 keyType = pkcs11.CKK_ECDSA
105 pubTypeAttrs, privTypeAttrs, err = ecdsaImportAttrs(priv)
106 default:
107 return nil, errors.New("Unsupported key type")
108 }
109 if err != nil {
110 return nil, err
111 }
112 commonAttrs := []*pkcs11.Attribute{
113 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, keyType),
114 pkcs11.NewAttribute(pkcs11.CKA_ID, keyID),
115 pkcs11.NewAttribute(pkcs11.CKA_LABEL, keyConf.Label),
116 }
117 pubAttrs := attrConcat(commonAttrs, newPublicKeyAttrs, pubTypeAttrs)
118 privAttrsSensitive := attrConcat(commonAttrs, newPrivateKeyAttrs, privTypeAttrs)
119 pubHandle, err := tok.ctx.CreateObject(tok.sh, pubAttrs)
120 if err != nil {
121 return nil, err
122 }
123 _, err = tok.ctx.CreateObject(tok.sh, privAttrsSensitive)
124 if err2, ok := err.(pkcs11.Error); ok && err2 == pkcs11.CKR_TEMPLATE_INCONSISTENT {
125
126
127
128 privAttrsUnwrap := attrConcat(commonAttrs, newPrivateKeyAttrs)
129 var pk8 []byte
130 pk8, err = pkcs8.MarshalPKCS8PrivateKey(privKey)
131 if err == nil {
132 err = tok.importPkcs8(pk8, privAttrsUnwrap)
133 }
134 }
135 if err != nil {
136 tok.ctx.DestroyObject(tok.sh, pubHandle)
137 return nil, err
138 }
139 keyConf.ID = hex.EncodeToString(keyID)
140 return tok.getKey(keyConf, keyName)
141 }
142
143
144 func (tok *Token) Generate(keyName string, keyType token.KeyType, bits uint) (token.Key, error) {
145 tok.mutex.Lock()
146 defer tok.mutex.Unlock()
147 keyConf, err := tok.config.GetKey(keyName)
148 if err != nil {
149 return nil, err
150 }
151 if keyConf.Label == "" {
152 return nil, errors.New("Key attribute 'label' must be defined in order to create an object")
153 }
154 keyID := makeKeyID()
155 if keyID == nil {
156 return nil, errors.New("failed to make key ID")
157 }
158 var pubTypeAttrs []*pkcs11.Attribute
159 var mech *pkcs11.Mechanism
160 switch keyType {
161 case token.KeyTypeRsa:
162 pubTypeAttrs, mech, err = rsaGenerateAttrs(bits)
163 case token.KeyTypeEcdsa:
164 pubTypeAttrs, mech, err = ecdsaGenerateAttrs(bits)
165 default:
166 return nil, errors.New("Unsupported key type")
167 }
168 if err != nil {
169 return nil, err
170 }
171 commonAttrs := []*pkcs11.Attribute{
172 pkcs11.NewAttribute(pkcs11.CKA_ID, keyID),
173 pkcs11.NewAttribute(pkcs11.CKA_LABEL, keyConf.Label),
174 }
175 pubAttrs := attrConcat(commonAttrs, newPublicKeyAttrs, pubTypeAttrs)
176 privAttrs := attrConcat(commonAttrs, newPrivateKeyAttrs)
177 if _, _, err := tok.ctx.GenerateKeyPair(tok.sh, []*pkcs11.Mechanism{mech}, pubAttrs, privAttrs); err != nil {
178 if err2, ok := err.(pkcs11.Error); ok && err2 == pkcs11.CKR_MECHANISM_INVALID && mech.Mechanism == pkcs11.CKM_RSA_X9_31_KEY_PAIR_GEN {
179 mech.Mechanism = pkcs11.CKM_RSA_PKCS_KEY_PAIR_GEN
180 if _, _, err := tok.ctx.GenerateKeyPair(tok.sh, []*pkcs11.Mechanism{mech}, pubAttrs, privAttrs); err != nil {
181 return nil, err
182 }
183 } else {
184 return nil, err
185 }
186 }
187 keyConf.ID = hex.EncodeToString(keyID)
188 return tok.getKey(keyConf, keyName)
189 }
190
191 func attrConcat(attrSets ...[]*pkcs11.Attribute) []*pkcs11.Attribute {
192 ret := make([]*pkcs11.Attribute, 0)
193 for _, attrs := range attrSets {
194 ret = append(ret, attrs...)
195 }
196 return ret
197 }
198
View as plain text