Skip to content

Commit d812dc7

Browse files
author
Volodymyr Paprotski
committed
Introduce placeholder for PKCS11 CSP
This is simply a copy of the SW CSP: - sw directory -> pkcs11 directory - swfactory.go -> pkcs11factory.go Not much changed: pkcs11factory.go uses PKCS11 instead of "Software" or "SW". And new package name. The code is currently un-reachable (except by copied tests). Next set of changes will add - configuration: probably integrate what Keith did for https://gerrit.hyperledger.org/r/#/c/3735/2 - replace (operation at a time) SW operations with PKCS11 operations Change-Id: I46f35b92be9303e52d66fdbc0962990efb47104e Signed-off-by: Volodymyr Paprotski <[email protected]>
1 parent c701cb5 commit d812dc7

13 files changed

+4164
-0
lines changed

bccsp/factory/pkcs11factory.go

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package factory
17+
18+
import (
19+
"errors"
20+
"fmt"
21+
"sync"
22+
23+
"github.com/hyperledger/fabric/bccsp"
24+
"github.com/hyperledger/fabric/bccsp/pkcs11"
25+
)
26+
27+
const (
28+
// PKCS11BasedFactoryName is the name of the factory of the hsm-based BCCSP implementation
29+
PKCS11BasedFactoryName = "P11"
30+
)
31+
32+
// PKCS11Factory is the factory of the HSM-based BCCSP.
33+
type PKCS11Factory struct {
34+
initOnce sync.Once
35+
bccsp bccsp.BCCSP
36+
err error
37+
}
38+
39+
// Name returns the name of this factory
40+
func (f *PKCS11Factory) Name() string {
41+
return PKCS11BasedFactoryName
42+
}
43+
44+
// Get returns an instance of BCCSP using Opts.
45+
func (f *PKCS11Factory) Get(opts Opts) (bccsp.BCCSP, error) {
46+
// Validate arguments
47+
if opts == nil {
48+
return nil, errors.New("Invalid opts. It must not be nil.")
49+
}
50+
51+
if opts.FactoryName() != f.Name() {
52+
return nil, fmt.Errorf("Invalid Provider Name [%s]. Opts must refer to [%s].", opts.FactoryName(), f.Name())
53+
}
54+
55+
pkcs11Opts, ok := opts.(*PKCS11Opts)
56+
if !ok {
57+
return nil, errors.New("Invalid opts. They must be of type PKCS11Opts.")
58+
}
59+
60+
if !opts.Ephemeral() {
61+
f.initOnce.Do(func() {
62+
f.bccsp, f.err = pkcs11.New(pkcs11Opts.SecLevel, pkcs11Opts.HashFamily, pkcs11Opts.KeyStore)
63+
return
64+
})
65+
return f.bccsp, f.err
66+
}
67+
68+
return pkcs11.New(pkcs11Opts.SecLevel, pkcs11Opts.HashFamily, pkcs11Opts.KeyStore)
69+
}
70+
71+
// PKCS11Opts contains options for the P11Factory
72+
type PKCS11Opts struct {
73+
Ephemeral_ bool
74+
SecLevel int
75+
HashFamily string
76+
KeyStore bccsp.KeyStore
77+
}
78+
79+
// FactoryName returns the name of the provider
80+
func (o *PKCS11Opts) FactoryName() string {
81+
return PKCS11BasedFactoryName
82+
}
83+
84+
// Ephemeral returns true if the CSP has to be ephemeral, false otherwise
85+
func (o *PKCS11Opts) Ephemeral() bool {
86+
return o.Ephemeral_
87+
}

bccsp/pkcs11/aes.go

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package pkcs11
18+
19+
import (
20+
"bytes"
21+
"crypto/aes"
22+
"crypto/cipher"
23+
"crypto/rand"
24+
"errors"
25+
"fmt"
26+
"io"
27+
)
28+
29+
// GetRandomBytes returns len random looking bytes
30+
func GetRandomBytes(len int) ([]byte, error) {
31+
buffer := make([]byte, len)
32+
33+
n, err := rand.Read(buffer)
34+
if err != nil {
35+
return nil, err
36+
}
37+
if n != len {
38+
return nil, fmt.Errorf("Buffer not filled. Requested [%d], got [%d]", len, n)
39+
}
40+
41+
return buffer, nil
42+
}
43+
44+
func pkcs7Padding(src []byte) []byte {
45+
padding := aes.BlockSize - len(src)%aes.BlockSize
46+
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
47+
return append(src, padtext...)
48+
}
49+
50+
func pkcs7UnPadding(src []byte) ([]byte, error) {
51+
length := len(src)
52+
unpadding := int(src[length-1])
53+
54+
if unpadding > aes.BlockSize || unpadding == 0 {
55+
return nil, errors.New("Invalid pkcs7 padding (unpadding > aes.BlockSize || unpadding == 0)")
56+
}
57+
58+
pad := src[len(src)-unpadding:]
59+
for i := 0; i < unpadding; i++ {
60+
if pad[i] != byte(unpadding) {
61+
return nil, errors.New("Invalid pkcs7 padding (pad[i] != unpadding)")
62+
}
63+
}
64+
65+
return src[:(length - unpadding)], nil
66+
}
67+
68+
func aesCBCEncrypt(key, s []byte) ([]byte, error) {
69+
if len(s)%aes.BlockSize != 0 {
70+
return nil, errors.New("Invalid plaintext. It must be a multiple of the block size")
71+
}
72+
73+
block, err := aes.NewCipher(key)
74+
if err != nil {
75+
return nil, err
76+
}
77+
78+
ciphertext := make([]byte, aes.BlockSize+len(s))
79+
iv := ciphertext[:aes.BlockSize]
80+
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
81+
return nil, err
82+
}
83+
84+
mode := cipher.NewCBCEncrypter(block, iv)
85+
mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
86+
87+
return ciphertext, nil
88+
}
89+
90+
func aesCBCDecrypt(key, src []byte) ([]byte, error) {
91+
block, err := aes.NewCipher(key)
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
if len(src) < aes.BlockSize {
97+
return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
98+
}
99+
iv := src[:aes.BlockSize]
100+
src = src[aes.BlockSize:]
101+
102+
if len(src)%aes.BlockSize != 0 {
103+
return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
104+
}
105+
106+
mode := cipher.NewCBCDecrypter(block, iv)
107+
108+
mode.CryptBlocks(src, src)
109+
110+
return src, nil
111+
}
112+
113+
// AESCBCPKCS7Encrypt combines CBC encryption and PKCS7 padding
114+
func AESCBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
115+
// First pad
116+
tmp := pkcs7Padding(src)
117+
118+
// Then encrypt
119+
return aesCBCEncrypt(key, tmp)
120+
}
121+
122+
// AESCBCPKCS7Decrypt combines CBC decryption and PKCS7 unpadding
123+
func AESCBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
124+
// First decrypt
125+
pt, err := aesCBCDecrypt(key, src)
126+
if err != nil {
127+
return nil, err
128+
}
129+
130+
// Then remove padding
131+
original, err := pkcs7UnPadding(pt)
132+
if err != nil {
133+
return nil, err
134+
}
135+
136+
return original, nil
137+
}

0 commit comments

Comments
 (0)