...
1 package main
2
3 import (
4 "crypto"
5 "crypto/x509"
6 "encoding/pem"
7 "fmt"
8 "log"
9
10 "github.com/letsencrypt/boulder/pkcs11helpers"
11 "github.com/miekg/pkcs11"
12 )
13
14 type hsmRandReader struct {
15 *pkcs11helpers.Session
16 }
17
18 func newRandReader(session *pkcs11helpers.Session) *hsmRandReader {
19 return &hsmRandReader{session}
20 }
21
22 func (hrr hsmRandReader) Read(p []byte) (n int, err error) {
23 r, err := hrr.Module.GenerateRandom(hrr.Session.Session, len(p))
24 if err != nil {
25 return 0, err
26 }
27 copy(p[:], r)
28 return len(r), nil
29 }
30
31 type generateArgs struct {
32 mechanism []*pkcs11.Mechanism
33 privateAttrs []*pkcs11.Attribute
34 publicAttrs []*pkcs11.Attribute
35 }
36
37
38
39
40
41 type keyInfo struct {
42 key crypto.PublicKey
43 der []byte
44 id []byte
45 }
46
47 func generateKey(session *pkcs11helpers.Session, label string, outputPath string, config keyGenConfig) (*keyInfo, error) {
48 _, err := session.FindObject([]*pkcs11.Attribute{
49 {Type: pkcs11.CKA_LABEL, Value: []byte(label)},
50 })
51 if err != pkcs11helpers.ErrNoObject {
52 return nil, fmt.Errorf("expected no preexisting objects with label %q in slot for key storage. got error: %s", label, err)
53 }
54
55 var pubKey crypto.PublicKey
56 var keyID []byte
57 switch config.Type {
58 case "rsa":
59 pubKey, keyID, err = rsaGenerate(session, label, config.RSAModLength)
60 if err != nil {
61 return nil, fmt.Errorf("failed to generate RSA key pair: %s", err)
62 }
63 case "ecdsa":
64 pubKey, keyID, err = ecGenerate(session, label, config.ECDSACurve)
65 if err != nil {
66 return nil, fmt.Errorf("failed to generate ECDSA key pair: %s", err)
67 }
68 }
69
70 der, err := x509.MarshalPKIXPublicKey(pubKey)
71 if err != nil {
72 return nil, fmt.Errorf("Failed to marshal public key: %s", err)
73 }
74
75 pemBytes := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: der})
76 log.Printf("Public key PEM:\n%s\n", pemBytes)
77 err = writeFile(outputPath, pemBytes)
78 if err != nil {
79 return nil, fmt.Errorf("Failed to write public key to %q: %s", outputPath, err)
80 }
81 log.Printf("Public key written to %q\n", outputPath)
82
83 return &keyInfo{key: pubKey, der: der, id: keyID}, nil
84 }
85
View as plain text