diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 4368f1e2c4a..9edab3288e7 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1,6 +1,6 @@
{
"ImportPath": "github.com/letsencrypt/boulder",
- "GoVersion": "go1.4.1",
+ "GoVersion": "go1.4.2",
"Packages": [
"./..."
],
@@ -16,77 +16,97 @@
},
{
"ImportPath": "github.com/cloudflare/cfssl/api",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/auth",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/bundler",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cli",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/cmd/cfssl",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/config",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
+ },
+ {
+ "ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs11key",
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
+ },
+ {
+ "ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs12",
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/csr",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/errors",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/helpers",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
+ },
+ {
+ "ImportPath": "github.com/cloudflare/cfssl/info",
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/initca",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/log",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
+ },
+ {
+ "ImportPath": "github.com/cloudflare/cfssl/revoke",
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/scan",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/selfsign",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ubiquity",
- "Rev": "e2aa27ef15c4f9c13bb2202ebfedbc90454dd947"
+ "Rev": "39ec5f93190f042ddf337955d4df679b0305c9df"
},
{
"ImportPath": "github.com/codegangsta/cli",
"Comment": "1.2.0-64-ge1712f3",
"Rev": "e1712f381785e32046927f64a7c86fe569203196"
},
+ {
+ "ImportPath": "github.com/dgryski/go-rc2",
+ "Rev": "fd90a5fcd260ebe709a689d0bdca2043afffabfa"
+ },
{
"ImportPath": "github.com/go-sql-driver/mysql",
"Comment": "v1.2-88-ga197e5d",
@@ -96,6 +116,10 @@
"ImportPath": "github.com/mattn/go-sqlite3",
"Rev": "308067797b0fcce4ca06362580dc6db77c1bfeda"
},
+ {
+ "ImportPath": "github.com/miekg/pkcs11",
+ "Rev": "88c9f842544e629ec046105d7fb50d5daafae737"
+ },
{
"ImportPath": "github.com/square/go-jose",
"Rev": "d3ba9be3fbf631c353e477ab8fba8ec04f05a8b4"
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api.go
index 9d123e5fa18..267cbb4f1e5 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api.go
@@ -1,4 +1,4 @@
-// Package api implements an HTTP-based API and server for CF-SSL.
+// Package api implements an HTTP-based API and server for CFSSL.
package api
import (
@@ -16,10 +16,10 @@ type Handler interface {
}
// HTTPHandler is a wrapper that encapsulates Handler interface as http.Handler.
-// HttpHandler also enforces that the Handler only responds to requests with registered HTTP method.
+// HTTPHandler also enforces that the Handler only responds to requests with registered HTTP methods.
type HTTPHandler struct {
- Handler // CFSSL handler
- Method string // The assoicated HTTP method
+ Handler // CFSSL handler
+ Methods []string // The associated HTTP methods
}
// HandlerFunc is similar to the http.HandlerFunc type; it serves as
@@ -41,9 +41,9 @@ func handleError(w http.ResponseWriter, err error) (code int) {
msg := err.Error()
httpCode := http.StatusInternalServerError
- // If it is recognized as HttpError emitted from cf-ssl,
+ // If it is recognized as HttpError emitted from cfssl,
// we rewrite the status code accordingly. If it is a
- // cf-ssl error, set the http status to StatusBadRequest
+ // cfssl error, set the http status to StatusBadRequest
switch err := err.(type) {
case *errors.HTTPError:
httpCode = err.StatusCode
@@ -69,11 +69,17 @@ func handleError(w http.ResponseWriter, err error) (code int) {
// and return the response with proper HTTP status code
func (h HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var err error
+ var match bool
// Throw 405 when requested with an unsupported verb.
- if r.Method != h.Method {
- err = errors.NewMethodNotAllowed(r.Method)
- } else {
+ for _, m := range h.Methods {
+ if m == r.Method {
+ match = true
+ }
+ }
+ if match {
err = h.Handle(w, r)
+ } else {
+ err = errors.NewMethodNotAllowed(r.Method)
}
status := handleError(w, err)
log.Infof("%s - \"%s %s\" %d", r.RemoteAddr, r.Method, r.URL, status)
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api_test.go
index fe82f726160..78ebb77d30f 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/api_test.go
@@ -73,7 +73,7 @@ func get(t *testing.T, ts *httptest.Server) (resp *http.Response, body []byte) {
}
func TestRigidHandle(t *testing.T) {
- ts := httptest.NewServer(HTTPHandler{Handler: HandlerFunc(simpleHandle), Method: "POST"})
+ ts := httptest.NewServer(HTTPHandler{Handler: HandlerFunc(simpleHandle), Methods: []string{"POST"}})
defer ts.Close()
// Response to compliment
@@ -143,7 +143,7 @@ func TestRigidHandle(t *testing.T) {
}
func TestCleverHandle(t *testing.T) {
- ts := httptest.NewServer(HTTPHandler{Handler: HandlerFunc(cleverHandle), Method: "POST"})
+ ts := httptest.NewServer(HTTPHandler{Handler: HandlerFunc(cleverHandle), Methods: []string{"POST"}})
defer ts.Close()
// Response ty to compliment
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/bundle/bundle.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/bundle/bundle.go
index b90f2f63f45..15702847984 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/bundle/bundle.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/bundle/bundle.go
@@ -1,3 +1,4 @@
+// Package bundle implements the HTTP handler for the bundle command.
package bundle
import (
@@ -27,7 +28,7 @@ func NewHandler(caBundleFile, intBundleFile string) (http.Handler, error) {
}
log.Info("bundler API ready")
- return api.HTTPHandler{Handler: b, Method: "POST"}, nil
+ return api.HTTPHandler{Handler: b, Methods: []string{"POST"}}, nil
}
// Handle implements an http.Handler interface for the bundle handler.
@@ -59,7 +60,7 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
}
result = bundle
case "certificate":
- bundle, err := h.bundler.BundleFromPEM([]byte(blob["certificate"]), []byte(blob["private_key"]), bf)
+ bundle, err := h.bundler.BundleFromPEMorDER([]byte(blob["certificate"]), []byte(blob["private_key"]), bf, "")
if err != nil {
log.Warning("bad PEM certifcate or private key")
return err
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/api.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/api.go
index 6e624fc1a95..22abf87774e 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/api.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/api.go
@@ -4,14 +4,3 @@ package client
type SignResult struct {
Certificate []byte `json:"certificate"`
}
-
-// InfoReq is the request struct for an info API request.
-type InfoReq struct {
- Label string `json:"label"`
- Profile string `json:"profile"`
-}
-
-// InfoResp is the response for an Info API request.
-type InfoResp struct {
- Certificate string `json:"certificate"`
-}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/client.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/client.go
index 9a0df32284e..3565dbc95af 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/client.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client/client.go
@@ -1,3 +1,4 @@
+// Package client implements the a Go client for CFSSL API commands.
package client
import (
@@ -14,10 +15,11 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/auth"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/info"
)
-type // A Server points to a remote CFSSL instance.
-Server struct {
+// A Server points to a remote CFSSL instance.
+type Server struct {
Address string
Port int
}
@@ -145,22 +147,56 @@ func (srv *Server) Sign(jsonData []byte) ([]byte, error) {
}
// Info sends an info request to the remote CFSSL server, receiving a
-// certificate or an error in response.
+// response or an error in response.
// It takes the serialized JSON request to send.
-func (srv *Server) Info(jsonData []byte) ([]byte, error) {
- return srv.Req(jsonData, "info")
+func (srv *Server) Info(jsonData []byte) (*info.Resp, error) {
+ res, err := srv.getResultMap(jsonData, "info")
+ if err != nil {
+ return nil, err
+ }
+
+ info := new(info.Resp)
+
+ if val, ok := res["certificate"]; ok {
+ info.Certificate = val.(string)
+ }
+ var usages []interface{}
+ if val, ok := res["usages"]; ok {
+ usages = val.([]interface{})
+ }
+ if val, ok := res["expiry"]; ok {
+ info.ExpiryString = val.(string)
+ }
+
+ info.Usage = make([]string, len(usages))
+ for i, s := range usages {
+ info.Usage[i] = s.(string)
+ }
+
+ return info, nil
+}
+
+func (srv *Server) getResultMap(jsonData []byte, target string) (result map[string]interface{}, err error) {
+ url := srv.getURL(target)
+ response, err := srv.post(url, jsonData)
+ if err != nil {
+ return
+ }
+ result, ok := response.Result.(map[string]interface{})
+ if !ok {
+ err = errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New("response is formatted improperly"))
+ return
+ }
+ return
}
// Req performs the common logic for Sign and Info, performing the actual
// request and returning the resultant certificate.
func (srv *Server) Req(jsonData []byte, target string) ([]byte, error) {
- url := srv.getURL(target)
-
- response, err := srv.post(url, jsonData)
+ result, err := srv.getResultMap(jsonData, target)
if err != nil {
return nil, err
}
- result := response.Result.(map[string]interface{})
cert := result["certificate"].(string)
if cert != "" {
return []byte(cert), nil
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/generator/generator.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/generator/generator.go
index b07f7d47fbd..0cbc3547845 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/generator/generator.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/generator/generator.go
@@ -1,3 +1,4 @@
+// Package generator implements the HTTP handlers for certificate generation.
package generator
import (
@@ -51,7 +52,7 @@ func NewHandler(validator Validator) (http.Handler, error) {
Handler: &Handler{
generator: &csr.Generator{Validator: validator},
},
- Method: "POST",
+ Methods: []string{"POST"},
}, nil
}
@@ -176,7 +177,7 @@ func NewCertGeneratorHandler(validator Validator, caFile, caKeyFile string, poli
cg.generator = &csr.Generator{Validator: validator}
- return api.HTTPHandler{Handler: cg, Method: "POST"}, nil
+ return api.HTTPHandler{Handler: cg, Methods: []string{"POST"}}, nil
}
// NewCertGeneratorHandlerFromSigner returns a handler directly from
@@ -187,7 +188,7 @@ func NewCertGeneratorHandlerFromSigner(validator Validator, signer signer.Signer
generator: &csr.Generator{Validator: validator},
signer: signer,
},
- Method: "POST",
+ Methods: []string{"POST"},
}
}
@@ -234,18 +235,6 @@ func (cg *CertGeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) e
return err
}
- var certPEM []byte
-
- var profile *config.SigningProfile
- policy := cg.signer.Policy()
- if policy != nil && policy.Profiles != nil && req.Profile != "" {
- profile = policy.Profiles[req.Profile]
- }
-
- if profile == nil && policy != nil {
- profile = policy.Default
- }
-
// This API does not override the subject because it was already added to the CSR
signReq := signer.SignRequest{
Hosts: signer.SplitHosts(req.Hostname),
@@ -273,7 +262,7 @@ func (cg *CertGeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) e
result := map[string]interface{}{
"private_key": string(key),
"certificate_request": string(csr),
- "certificate": string(certPEM),
+ "certificate": string(certBytes),
"sums": map[string]Sum{
"certificate_request": reqSum,
"certificate": certSum,
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/info/info.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/info/info.go
index 6fb1a9c3fa8..8caec52ad09 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/info/info.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/info/info.go
@@ -1,15 +1,14 @@
+// Package info implements the HTTP handler for the info command.
package info
import (
"encoding/json"
- "encoding/pem"
"io/ioutil"
"net/http"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api"
- "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client"
- "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/info"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
)
@@ -27,14 +26,14 @@ func NewHandler(s signer.Signer) (http.Handler, error) {
Handler: &Handler{
sign: s,
},
- Method: "POST",
+ Methods: []string{"POST"},
}, nil
}
// Handle listens for incoming requests for CA information, and returns
// a list containing information on each root certificate.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
- req := new(client.InfoReq)
+ req := new(info.Req)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Warningf("failed to read request body: %v", err)
@@ -46,13 +45,10 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
return errors.NewBadRequest(err)
}
- cert, err := h.sign.Certificate(req.Label, req.Profile)
+ resp, err := h.sign.Info(*req)
if err != nil {
return err
}
- resp := client.InfoResp{
- Certificate: bundler.PemBlockToString(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}),
- }
response := api.NewSuccessResponse(resp)
w.Header().Set("Content-Type", "application/json")
@@ -77,7 +73,7 @@ func NewMultiHandler(signers map[string]signer.Signer, defaultLabel string) (htt
signers: signers,
defaultLabel: defaultLabel,
},
- Method: "POST",
+ Methods: []string{"POST"},
}, nil
}
@@ -85,7 +81,7 @@ func NewMultiHandler(signers map[string]signer.Signer, defaultLabel string) (htt
// look up the signer whose public certificate should be retrieved. If
// the label is empty, the default label is used.
func (h *MultiHandler) Handle(w http.ResponseWriter, r *http.Request) error {
- req := new(client.InfoReq)
+ req := new(info.Req)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Warningf("failed to read request body: %v", err)
@@ -107,17 +103,13 @@ func (h *MultiHandler) Handle(w http.ResponseWriter, r *http.Request) error {
return errors.NewBadRequestString("bad label")
}
- log.Debug("getting cert")
- cert, err := h.signers[req.Label].Certificate("", req.Profile)
+ log.Debug("getting info")
+ resp, err := h.signers[req.Label].Info(*req)
if err != nil {
log.Infof("error getting certificate: %v", err)
return err
}
- resp := client.InfoResp{
- Certificate: bundler.PemBlockToString(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}),
- }
-
response := api.NewSuccessResponse(resp)
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/initca/initca.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/initca/initca.go
index 56918a28e43..c51c0e092fc 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/initca/initca.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/initca/initca.go
@@ -1,3 +1,4 @@
+// Package initca implements the HTTP handler for the CA initialization command
package initca
import (
@@ -38,7 +39,7 @@ func initialCAHandler(w http.ResponseWriter, r *http.Request) error {
return errors.NewBadRequest(err)
}
- key, cert, err := initca.New(req)
+ key, _, cert, err := initca.New(req)
if err != nil {
log.Warningf("failed to initialise new CA: %v", err)
return err
@@ -54,5 +55,5 @@ func initialCAHandler(w http.ResponseWriter, r *http.Request) error {
// NewHandler returns a new http.Handler that handles request to
// initialize a CA.
func NewHandler() http.Handler {
- return api.HTTPHandler{Handler: api.HandlerFunc(initialCAHandler), Method: "POST"}
+ return api.HTTPHandler{Handler: api.HandlerFunc(initialCAHandler), Methods: []string{"POST"}}
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/scan/scan.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/scan/scan.go
index 08d2cca278f..1289a81ed21 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/scan/scan.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/scan/scan.go
@@ -51,7 +51,10 @@ func scanHandler(w http.ResponseWriter, r *http.Request) error {
// NewHandler returns a new http.Handler that handles a scan request.
func NewHandler() http.Handler {
- return api.HTTPHandler{Handler: api.HandlerFunc(scanHandler), Method: "GET"}
+ return api.HTTPHandler{
+ Handler: api.HandlerFunc(scanHandler),
+ Methods: []string{"GET"},
+ }
}
// scanInfoHandler is an HTTP handler that returns a JSON blob result describing
@@ -66,5 +69,5 @@ func scanInfoHandler(w http.ResponseWriter, r *http.Request) error {
// NewInfoHandler returns a new http.Handler that handles a request for scan info.
func NewInfoHandler() http.Handler {
- return api.HTTPHandler{Handler: api.HandlerFunc(scanInfoHandler), Method: "GET"}
+ return api.HTTPHandler{Handler: api.HandlerFunc(scanInfoHandler), Methods: []string{"GET"}}
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign.go
index 23a31ef7ab5..21299bee10e 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign.go
@@ -1,3 +1,4 @@
+// Package sign implements the HTTP handler for the certificate signing command.
package sign
import (
@@ -70,7 +71,7 @@ func NewHandlerFromSigner(signer signer.Signer) (h *api.HTTPHandler, err error)
Handler: &Handler{
signer: signer,
},
- Method: "POST",
+ Methods: []string{"POST"},
}, nil
}
@@ -139,24 +140,15 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
}
signReq := jsonReqToTrue(req)
- if signReq.Hosts == nil {
- return errors.NewBadRequestString("missing parameter 'hostname' or 'hosts'")
- }
if req.Request == "" {
return errors.NewBadRequestString("missing parameter 'certificate_request'")
}
var cert []byte
- var profile *config.SigningProfile
-
- policy := h.signer.Policy()
- if policy != nil && policy.Profiles != nil && req.Profile != "" {
- profile = policy.Profiles[req.Profile]
- }
-
- if profile == nil && policy != nil {
- profile = policy.Default
+ profile, err := signer.Profile(h.signer, req.Profile)
+ if err != nil {
+ return err
}
if profile.Provider != nil {
@@ -231,7 +223,7 @@ func NewAuthHandlerFromSigner(signer signer.Signer) (http.Handler, error) {
Handler: &AuthHandler{
signer: signer,
},
- Method: "POST",
+ Methods: []string{"POST"},
}, nil
}
@@ -267,15 +259,10 @@ func (h *AuthHandler) Handle(w http.ResponseWriter, r *http.Request) error {
log.Critical("signer was initialised without a signing policy")
return errors.NewBadRequestString("invalid policy")
}
- profile := policy.Default
-
- if policy.Profiles != nil && req.Profile != "" {
- profile = policy.Profiles[req.Profile]
- }
- if profile == nil {
- log.Critical("signer was initialised without any valid profiles")
- return errors.NewBadRequestString("invalid profile")
+ profile, err := signer.Profile(h.signer, req.Profile)
+ if err != nil {
+ return err
}
if profile.Provider == nil {
@@ -289,9 +276,6 @@ func (h *AuthHandler) Handle(w http.ResponseWriter, r *http.Request) error {
}
signReq := jsonReqToTrue(req)
- if signReq.Hosts == nil {
- return errors.NewBadRequestString("missing parameter 'hostname' or 'hosts'")
- }
if signReq.Request == "" {
return errors.NewBadRequestString("missing parameter 'certificate_request'")
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign_test.go
index 3fc99ae12a7..a4878edc46a 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/sign/sign_test.go
@@ -319,9 +319,9 @@ var signTests = []signTest{
{
Hosts: nil,
CSRFile: testCSRFile,
- ExpectedHTTPStatus: http.StatusBadRequest,
- ExpectedSuccess: false,
- ExpectedErrorCode: http.StatusBadRequest,
+ ExpectedHTTPStatus: http.StatusOK,
+ ExpectedSuccess: true,
+ ExpectedErrorCode: 0,
},
{
Hosts: []string{testDomainName},
@@ -335,7 +335,7 @@ var signTests = []signTest{
CSRFile: testBrokenCSRFile,
ExpectedHTTPStatus: http.StatusBadRequest,
ExpectedSuccess: false,
- ExpectedErrorCode: 1002,
+ ExpectedErrorCode: 9002,
},
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_file_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_file_test.go
index 578f5badd06..a636103e80e 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_file_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_file_test.go
@@ -38,10 +38,6 @@ For each pair of crypto algorithm X and key size Y, a CA chain is constructed:
|-> cfssl-leaf-rsa4096
Test_root_CA is a RSA cert, inter-L1 is RSA 4096 cert, inter-L2 is ecdsa-384 cert.
-In addition, we construct another mixed chain of RSA->ECDSA->RSA->ECDSA
- Test_root_CA -> inter-L1-v2 -> inter-L2-v2 --> cfssl-leaf-ecdsa256-v2
- |-> cfssl-leaf-ecdsa384-v2
- |-> cfssl-leaf-ecdsa521-v2
The max path length is set to be 1 for non-root CAs.
Two inter-* certs are assembled in intermediates.crt
@@ -71,11 +67,6 @@ const (
interL1Expired = "testdata/inter-L1-expired.pem"
interL1CSR = "testdata/inter-L1.csr"
interL2 = "testdata/inter-L2.pem"
- interL1v2 = "testdata/inter-L1-v2.pem"
- interL2v2 = "testdata/inter-L2-v2.pem"
- leafECDSA256v2 = "testdata/cfssl-leaf-ecdsa256-v2.pem"
- leafECDSA384v2 = "testdata/cfssl-leaf-ecdsa384-v2.pem"
- leafECDSA521v2 = "testdata/cfssl-leaf-ecdsa521-v2.pem"
interL2Direct = "testdata/inter-L2-direct.pem"
partialBundle = "testdata/partial-bundle.pem" // partialBundle is a partial cert chain {leaf-ecds256, inter-L2}
@@ -145,30 +136,6 @@ var fileTests = []fileTest{
errorCallback: nil,
bundleChecking: ExpectBundleLength(3),
},
- {
- cert: leafECDSA256v2,
- caBundleFile: testCFSSLRootBundle,
- intBundleFile: interL1v2,
- extraIntermediates: interL2v2,
- errorCallback: nil,
- bundleChecking: ExpectBundleLength(3),
- },
- {
- cert: leafECDSA384v2,
- caBundleFile: testCFSSLRootBundle,
- intBundleFile: interL1v2,
- extraIntermediates: interL2v2,
- errorCallback: nil,
- bundleChecking: ExpectBundleLength(3),
- },
- {
- cert: leafECDSA521v2,
- caBundleFile: testCFSSLRootBundle,
- intBundleFile: interL1v2,
- extraIntermediates: interL2v2,
- errorCallback: nil,
- bundleChecking: ExpectBundleLength(3),
- },
// Normal bundling with private key for all supported key types
{
@@ -371,7 +338,7 @@ var fileTests = []fileTest{
func TestBundleFromFile(t *testing.T) {
for _, test := range fileTests {
b := newCustomizedBundlerFromFile(t, test.caBundleFile, test.intBundleFile, test.extraIntermediates)
- bundle, err := b.BundleFromFile(test.cert, test.key, Optimal)
+ bundle, err := b.BundleFromFile(test.cert, test.key, Optimal, "")
if test.errorCallback != nil {
test.errorCallback(t, err)
} else {
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_pem_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_pem_test.go
index 8ebe0d44685..85250107a10 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_pem_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundle_from_pem_test.go
@@ -69,7 +69,7 @@ var pemTests = []pemTest{
func TestBundleFromPEM(t *testing.T) {
for _, test := range pemTests {
b := test.bundlerConstructor(t)
- bundle, err := b.BundleFromPEM(test.cert, test.key, Optimal)
+ bundle, err := b.BundleFromPEMorDER(test.cert, test.key, Optimal, "")
if test.errorCallback != nil {
test.errorCallback(t, err)
} else {
@@ -83,7 +83,7 @@ func TestBundleFromPEM(t *testing.T) {
}
}
-// GoDaddy intermeidate cert valid until year 2034
+// GoDaddy intermediate cert valid until year 2034
var GoDaddyRootCert = []byte(`-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
@@ -109,7 +109,7 @@ dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
ReYNnyicsbkqWletNw+vHX/bvZ8=
-----END CERTIFICATE-----`)
-// GoDaddy intermeidate cert valid until year 2026
+// GoDaddy intermediate cert valid until year 2026
var GoDaddyIntermediateCert = []byte(`-----BEGIN CERTIFICATE-----
MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler.go
index ae075e87ac4..3358c9bdbec 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler.go
@@ -1,5 +1,5 @@
// Package bundler implements certificate bundling functionality for
-// CF-SSL.
+// CFSSL.
package bundler
import (
@@ -47,12 +47,11 @@ const (
)
const (
- sha2Warning = "The bundle contains certs signed with advanced hash functions such as SHA2, which are problematic at certain operating systems, e.g. Windows XP SP2."
- ecdsaWarning = "The bundle contains ECDSA signatures, which are problematic at certain operating systems, e.g. Windows XP SP2, Android 2.2 and Android 2.3."
- expiringWarningStub = "The bundle is expiring within 30 days. "
- untrustedWarningStub = "The bundle may not be trusted by the following platform(s):"
- ubiquityWarning = "The bundle trust ubiquity is not guaranteed: No platform metadata found."
- deprecateSHA1WarningStub = "Due to SHA-1 deprecation, the bundle may not be trusted by the following platform(s):"
+ sha2Warning = "The bundle contains certificates signed with advanced hash functions such as SHA2, which are problematic for certain operating systems, e.g. Windows XP SP2."
+ ecdsaWarning = "The bundle contains ECDSA signatures, which are problematic for certain operating systems, e.g. Windows XP SP2, Android 2.2 and Android 2.3."
+ expiringWarningStub = "The bundle is expiring within 30 days."
+ untrustedWarningStub = "The bundle may not be trusted by the following platform(s):"
+ ubiquityWarning = "Unable to measure bundle ubiquity: No platform metadata present."
)
// A Bundler contains the certificate pools for producing certificate
@@ -69,14 +68,14 @@ type Bundler struct {
// of valid intermediate certificates, respectively.
func NewBundler(caBundleFile, intBundleFile string) (*Bundler, error) {
log.Debug("Loading CA bundle: ", caBundleFile)
- caBundlePEM, err := ioutil.ReadFile(caBundleFile)
+ caBundle, err := ioutil.ReadFile(caBundleFile)
if err != nil {
log.Errorf("root bundle failed to load: %v", err)
return nil, errors.Wrap(errors.RootError, errors.ReadFailed, err)
}
log.Debug("Loading Intermediate bundle: ", intBundleFile)
- intBundlePEM, err := ioutil.ReadFile(intBundleFile)
+ intBundle, err := ioutil.ReadFile(intBundleFile)
if err != nil {
log.Errorf("intermediate bundle failed to load: %v", err)
return nil, errors.Wrap(errors.IntermediatesError, errors.ReadFailed, err)
@@ -92,7 +91,8 @@ func NewBundler(caBundleFile, intBundleFile string) (*Bundler, error) {
}
log.Infof("intermediate stash directory %s created", IntermediateStash)
}
- return NewBundlerFromPEM(caBundlePEM, intBundlePEM)
+ return NewBundlerFromPEM(caBundle, intBundle)
+
}
// NewBundlerFromPEM creates a new Bundler from PEM-encoded root certificates and
@@ -150,9 +150,9 @@ func (b *Bundler) VerifyOptions() x509.VerifyOptions {
// BundleFromFile takes a set of files containing the PEM-encoded leaf certificate
// (optionally along with some intermediate certs), the PEM-encoded private key
// and returns the bundle built from that key and the certificate(s).
-func (b *Bundler) BundleFromFile(bundleFile, keyFile string, flavor BundleFlavor) (*Bundle, error) {
+func (b *Bundler) BundleFromFile(bundleFile, keyFile string, flavor BundleFlavor, password string) (*Bundle, error) {
log.Debug("Loading Certificate: ", bundleFile)
- certsPEM, err := ioutil.ReadFile(bundleFile)
+ certsRaw, err := ioutil.ReadFile(bundleFile)
if err != nil {
return nil, errors.Wrap(errors.CertificateError, errors.ReadFailed, err)
}
@@ -172,12 +172,12 @@ func (b *Bundler) BundleFromFile(bundleFile, keyFile string, flavor BundleFlavor
}
}
- return b.BundleFromPEM(certsPEM, keyPEM, flavor)
+ return b.BundleFromPEMorDER(certsRaw, keyPEM, flavor, password)
}
-// BundleFromPEM builds a certificate bundle from the set of byte
-// slices containing the PEM-encoded certificate(s), private key.
-func (b *Bundler) BundleFromPEM(certsPEM, keyPEM []byte, flavor BundleFlavor) (*Bundle, error) {
+// BundleFromPEMorDER builds a certificate bundle from the set of byte
+// slices containing the PEM or DER-encoded certificate(s), private key.
+func (b *Bundler) BundleFromPEMorDER(certsRaw, keyPEM []byte, flavor BundleFlavor, password string) (*Bundle, error) {
log.Debug("bundling from PEM files")
var key crypto.Signer
var err error
@@ -189,11 +189,24 @@ func (b *Bundler) BundleFromPEM(certsPEM, keyPEM []byte, flavor BundleFlavor) (*
}
}
- certs, err := helpers.ParseCertificatesPEM(certsPEM)
+ certs, err := helpers.ParseCertificatesPEM(certsRaw)
if err != nil {
- log.Debugf("failed to parse certificates: %v", err)
- return nil, err
- } else if len(certs) == 0 {
+ // If PEM doesn't work try DER
+ var keyDER crypto.Signer
+ var errDER error
+ certs, keyDER, errDER = helpers.ParseCertificatesDER(certsRaw, password)
+ // Only use DER key if no key read from file
+ if key == nil && keyDER != nil {
+ key = keyDER
+ }
+ if errDER != nil {
+ log.Debugf("failed to parse certificates: %v", err)
+ // If neither parser works pass along PEM error
+ return nil, err
+ }
+
+ }
+ if len(certs) == 0 {
log.Debugf("no certificates found")
return nil, errors.New(errors.CertificateError, errors.DecodeFailed)
}
@@ -642,11 +655,11 @@ func (b *Bundler) Bundle(certs []*x509.Certificate, key crypto.Signer, flavor Bu
messages = append(messages, untrustedMsg)
}
// Check if there is any platform that rejects the chain because of SHA1 deprecation.
- deprecated := ubiquity.DeprecatedSHA1Platforms(matchingChains[0])
- if len(deprecated) > 0 {
+ sha1Msgs := ubiquity.SHA1DeprecationMessages(matchingChains[0])
+ if len(sha1Msgs) > 0 {
log.Debug("Populate SHA1 deprecation warning.")
statusCode |= errors.BundleNotUbiquitousBit
- messages = append(messages, deprecateSHA1Warning(deprecated))
+ messages = append(messages, sha1Msgs...)
}
bundle.Status = &BundleStatus{ExpiringSKIs: getSKIs(bundle.Chain, expiringCerts), Code: statusCode, Messages: messages, Untrusted: untrusted}
@@ -716,22 +729,6 @@ func untrustedPlatformsWarning(platforms []string) string {
return msg
}
-// deprecateSHA1Warning generates a warning message with platform names which deprecates SHA1.
-func deprecateSHA1Warning(platforms []string) string {
- if len(platforms) == 0 {
- return ""
- }
- msg := deprecateSHA1WarningStub
- for i, platform := range platforms {
- if i > 0 {
- msg += ","
- }
- msg += " " + platform
- }
- msg += "."
- return msg
-}
-
// Optimal chains are the shortest chains, with newest intermediates and most advanced crypto suite being the tie breaker.
func optimalChains(chains [][]*x509.Certificate) [][]*x509.Certificate {
// Find shortest chains
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_sha1_deprecation_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_sha1_deprecation_test.go
index 4e1b5de59bd..5133bb7715b 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_sha1_deprecation_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_sha1_deprecation_test.go
@@ -2,114 +2,182 @@ package bundler
// This test file contains tests on checking Bundle.Status with SHA-1 deprecation warning.
import (
+ "crypto/x509"
+ "io/ioutil"
"testing"
+ "time"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity"
)
const (
- sha1CA = "testdata/ca.pem"
- testChromeMetadata = "testdata/ca.pem.metadata"
- sha1Intermediate = "testdata/inter-L1-sha1.pem"
- sha2Intermediate = "testdata/inter-L1.pem"
- sha2LeafExp2015Jun2nd = "testdata/inter-L2-1.pem"
- sha2LeafExp2016Jan2nd = "testdata/inter-L2-2.pem"
- sha2LeafExp2016Jun2nd = "testdata/inter-L2-3.pem"
- sha2LeafExp2017Jan2nd = "testdata/inter-L2-4.pem"
+ sha1CA = "testdata/ca.pem"
+ sha1CAKey = "testdata/ca.key"
+ sha1Intermediate = "testdata/inter-L1-sha1.pem"
+ sha2Intermediate = "testdata/inter-L1.pem"
+ intermediateKey = "testdata/inter-L1.key"
+ intermediateCSR = "testdata/inter-L1.csr"
+ leafCSR = "testdata/cfssl-leaf-ecdsa256.csr"
)
func TestChromeWarning(t *testing.T) {
b := newCustomizedBundlerFromFile(t, sha1CA, sha1Intermediate, "")
- // The metadata contains Chrome M39, M40 and M41. The effective date for their SHA1 deprecation
- // is pushed to 2014-09-01 to enable unit testing.
- ubiquity.Platforms = nil
- ubiquity.LoadPlatforms(testChromeMetadata)
-
- // Bundle a leaf cert with expiration on 2015-06-02.
- // Expect no SHA-1 deprecation warnings but a SHA2 warning.
- bundle, err := b.BundleFromFile(sha2LeafExp2015Jun2nd, "", Ubiquitous)
+
+ s, err := local.NewSignerFromFile(sha1Intermediate, intermediateKey, nil)
if err != nil {
- t.Fatal("bundling failed: ", err)
+ t.Fatal(err)
}
- if bundle.Status.Code|errors.BundleNotUbiquitousBit != errors.BundleNotUbiquitousBit {
- t.Fatal("Incorrect bundle status code. Bundle status:", bundle.Status)
+
+ csrBytes, err := ioutil.ReadFile(leafCSR)
+ if err != nil {
+ t.Fatal(err)
}
- if len(bundle.Status.Messages) != 2 ||
- bundle.Status.Messages[0] != sha2Warning ||
- bundle.Status.Messages[1] != ecdsaWarning {
- t.Fatal("Incorrect bundle status messages. Bundle status messages:", bundle.Status.Messages)
+ signingRequest := signer.SignRequest{Request: string(csrBytes)}
+
+ certBytes, err := s.Sign(signingRequest)
+ if err != nil {
+ t.Fatal(err)
}
- // Bundle a leaf cert with expiration on 2016-01-02.
- // Expect one SHA-1 deprecation warning from Chrome M41 and a SHA2 warning.
- bundle, err = b.BundleFromFile(sha2LeafExp2016Jan2nd, "", Ubiquitous)
+ // Bundle a leaf cert with default 1 year expiration
+ bundle, err := b.BundleFromPEMorDER(certBytes, nil, Ubiquitous, "")
if err != nil {
t.Fatal("bundling failed: ", err)
}
- if bundle.Status.Code|errors.BundleNotUbiquitousBit != errors.BundleNotUbiquitousBit {
- t.Fatal("Incorrect bundle status code. Bundle status:", bundle.Status)
+
+ // should be not ubiquitous due to SHA2 and ECDSA support issues in legacy platforms
+ if bundle.Status.Code&errors.BundleNotUbiquitousBit != errors.BundleNotUbiquitousBit {
+ t.Fatal("Incorrect bundle status code. Bundle status code:", bundle.Status.Code)
}
- if len(bundle.Status.Messages) != 3 ||
- bundle.Status.Messages[0] != sha2Warning ||
- bundle.Status.Messages[1] != ecdsaWarning ||
- bundle.Status.Messages[2] != deprecateSHA1WarningStub+" Chrome Browser M41." {
- t.Fatal("Incorrect bundle status messages. Bundle status messages:", bundle.Status.Messages)
+ fullChain := append(bundle.Chain, bundle.Root)
+ sha1Msgs := ubiquity.SHA1DeprecationMessages(fullChain)
+ // Since the new SHA-1 cert is expired after 2015, it definitely trigger Chrome's deprecation policies.
+ if len(sha1Msgs) == 0 {
+ t.Fatal("SHA1 Deprecation Message should not be empty")
+ }
+ // check SHA1 deprecation warnings
+ var sha1MsgNotFound bool
+ for _, sha1Msg := range sha1Msgs {
+ foundMsg := false
+ for _, message := range bundle.Status.Messages {
+ if message == sha1Msg {
+ foundMsg = true
+ }
+ }
+ if !foundMsg {
+ sha1MsgNotFound = true
+ break
+ }
+ }
+ if sha1MsgNotFound {
+ t.Fatalf("Incorrect bundle status messages. Bundle status messages:%v, expected to contain: %v\n", bundle.Status.Messages, sha1Msgs)
}
- // Bundle a leaf cert with expiration on 2016-06-02.
- // Expect SHA-1 deprecation warnings from Chrome M40, M41 and a SHA2 warning.
- bundle, err = b.BundleFromFile(sha2LeafExp2016Jun2nd, "", Ubiquitous)
+}
+
+func TestSHA2Preferences(t *testing.T) {
+ // create a CA signer and signs a new intermediate with SHA-1
+ sha1CASigner := makeCASignerFromFile(sha1CA, sha1CAKey, x509.SHA1WithRSA, t)
+ // create a CA signer and signs a new intermediate with SHA-2
+ sha2CASigner := makeCASignerFromFile(sha1CA, sha1CAKey, x509.SHA256WithRSA, t)
+
+ // sign two different intermediates
+ sha1InterBytes := signCSRFile(sha1CASigner, intermediateCSR, t)
+ sha2InterBytes := signCSRFile(sha2CASigner, intermediateCSR, t)
+
+ interKeyBytes, err := ioutil.ReadFile(intermediateKey)
if err != nil {
- t.Fatal("bundling failed: ", err)
- }
- if bundle.Status.Code|errors.BundleNotUbiquitousBit != errors.BundleNotUbiquitousBit {
- t.Fatal("Incorrect bundle status code. Bundle status:", bundle.Status)
+ t.Fatal(err)
}
- if len(bundle.Status.Messages) != 3 ||
- bundle.Status.Messages[0] != sha2Warning ||
- bundle.Status.Messages[1] != ecdsaWarning ||
- bundle.Status.Messages[2] != deprecateSHA1WarningStub+" Chrome Browser M40, Chrome Browser M41." {
- t.Fatal("Incorrect bundle status messages. Bundle status messages:", bundle.Status.Messages)
+ // create a intermediate signer from SHA-1 intermediate cert/key
+ sha2InterSigner := makeCASigner(sha1InterBytes, interKeyBytes, x509.SHA256WithRSA, t)
+ // sign a leaf cert
+ leafBytes := signCSRFile(sha2InterSigner, leafCSR, t)
+
+ // create a bundler with SHA-1 and SHA-2 intermediate certs of same key.
+ b := newCustomizedBundlerFromFile(t, sha1CA, sha1Intermediate, "")
+ if err != nil {
+ t.Fatal(err)
}
+ sha1Inter, _ := helpers.ParseCertificatePEM(sha1InterBytes)
+ sha2Inter, _ := helpers.ParseCertificatePEM(sha2InterBytes)
+ b.IntermediatePool.AddCert(sha1Inter)
+ b.IntermediatePool.AddCert(sha2Inter)
- // Bundle a leaf cert with expiration on 2017-01-02.
- // Expect SHA-1 deprecation warnings from Chrome M39, M40, M41 and a SHA2 warning.
- bundle, err = b.BundleFromFile(sha2LeafExp2017Jan2nd, "", Ubiquitous)
+ bundle, err := b.BundleFromPEMorDER(leafBytes, nil, Ubiquitous, "")
if err != nil {
t.Fatal("bundling failed: ", err)
}
- if bundle.Status.Code|errors.BundleNotUbiquitousBit != errors.BundleNotUbiquitousBit {
- t.Fatal("Incorrect bundle status code. Bundle status:", bundle.Status)
+
+ if bundle.Chain[1].SignatureAlgorithm != x509.SHA256WithRSA {
+ t.Fatal("ubiquity selection by SHA-2 homogenity failed.")
}
- if len(bundle.Status.Messages) != 3 ||
- bundle.Status.Messages[0] != sha2Warning ||
- bundle.Status.Messages[1] != ecdsaWarning ||
- bundle.Status.Messages[2] != deprecateSHA1WarningStub+" Chrome Browser M39, Chrome Browser M40, Chrome Browser M41." {
- t.Fatal("Incorrect bundle status messages. Bundle status messages:", bundle.Status.Messages)
+}
+
+func makeCASignerFromFile(certFile, keyFile string, sigAlgo x509.SignatureAlgorithm, t *testing.T) signer.Signer {
+ certBytes, err := ioutil.ReadFile(certFile)
+ if err != nil {
+ t.Fatal(err)
}
+
+ keyBytes, err := ioutil.ReadFile(keyFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ return makeCASigner(certBytes, keyBytes, sigAlgo, t)
+
}
-func TestUbiquitySHA2Preference(t *testing.T) {
- // Add a SHA-2 L1 cert to the intermediate pool.
- b := newCustomizedBundlerFromFile(t, sha1CA, sha1Intermediate, sha2Intermediate)
- ubiquity.Platforms = nil
- ubiquity.LoadPlatforms(testChromeMetadata)
+func makeCASigner(certBytes, keyBytes []byte, sigAlgo x509.SignatureAlgorithm, t *testing.T) signer.Signer {
+ cert, err := helpers.ParseCertificatePEM(certBytes)
+ if err != nil {
+ t.Fatal(err)
+ }
- bundle, err := b.BundleFromFile(sha2LeafExp2017Jan2nd, "", Ubiquitous)
+ key, err := helpers.ParsePrivateKeyPEM(keyBytes)
if err != nil {
- t.Fatal("bundling failed: ", err)
+ t.Fatal(err)
+ }
+
+ defaultProfile := &config.SigningProfile{
+ Usage: []string{"cert sign"},
+ CA: true,
+ Expiry: time.Hour,
+ ExpiryString: "1h",
+ }
+ policy := &config.Signing{
+ Profiles: map[string]*config.SigningProfile{},
+ Default: defaultProfile,
+ }
+ s, err := local.NewSigner(key, cert, sigAlgo, policy)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ return s
+}
+
+func signCSRFile(s signer.Signer, csrFile string, t *testing.T) []byte {
+ csrBytes, err := ioutil.ReadFile(csrFile)
+ if err != nil {
+ t.Fatal(err)
}
- // With same ubiquity score, the chain with SHA2 L1 will be chosen. And so there is no Chrome warning.
- if len(bundle.Status.Messages) != 2 ||
- bundle.Status.Messages[0] != sha2Warning ||
- bundle.Status.Messages[1] != ecdsaWarning {
- t.Fatal("Incorrect bundle status messages. Bundle status messages:", bundle.Status.Messages)
+ signingRequest := signer.SignRequest{Request: string(csrBytes)}
+ certBytes, err := s.Sign(signingRequest)
+ if err != nil {
+ t.Fatal(err)
}
+ return certBytes
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_test.go
index a034e6f576d..a604b7ea809 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/bundler_test.go
@@ -23,18 +23,15 @@ const (
testIntCaBundle = "testdata/int-bundle.pem"
testNSSRootBundle = "testdata/nss.pem"
testMetadata = "testdata/ca-bundle.crt.metadata"
- firstdataPEM = "testdata/firstdata.pem"
- forcebundlePEM = "testdata/forcebundle.pem"
- draftkingsPEM = "testdata/draftkings.pem" // expires in July 2015
- riotPEM = "testdata/riot.pem"
- bunningsPEM = "testdata/bunnings.pem"
testCFSSLRootBundle = "testdata/ca.pem"
testCAFile = "testdata/ca.pem"
testCAKeyFile = "testdata/ca.key"
testCFSSLIntBundle = "testdata/intermediates.crt"
emptyPEM = "testdata/empty.pem"
interL1SHA1 = "testdata/inter-L1-sha1.pem"
+ interL1Key = "testdata/inter-L1.key"
interL2SHA1 = "testdata/inter-L2-sha1.pem"
+ interL2Key = "testdata/inter-L2.key"
)
// Simply create a bundler
@@ -92,7 +89,7 @@ var godaddySubjectString = `/Country=US/Province=Arizona/Locality=Scottsdale/Org
// Also serves as a JSON format regression test.
func TestBundleMarshalJSON(t *testing.T) {
b := newBundler(t)
- bundle, _ := b.BundleFromPEM(GoDaddyIntermediateCert, nil, Optimal)
+ bundle, _ := b.BundleFromPEMorDER(GoDaddyIntermediateCert, nil, Optimal, "")
bytes, err := json.Marshal(bundle)
if err != nil {
@@ -167,7 +164,7 @@ func TestBundleMarshalJSON(t *testing.T) {
func TestBundleWithECDSAKeyMarshalJSON(t *testing.T) {
b := newCustomizedBundlerFromFile(t, testCFSSLRootBundle, testCFSSLIntBundle, "")
- bundle, _ := b.BundleFromFile(leafECDSA256, leafKeyECDSA256, Optimal)
+ bundle, _ := b.BundleFromFile(leafECDSA256, leafKeyECDSA256, Optimal, "")
jsonBytes, err := json.Marshal(bundle)
if err != nil {
@@ -203,7 +200,7 @@ func TestBundleWithECDSAKeyMarshalJSON(t *testing.T) {
func TestBundleWithRSAKeyMarshalJSON(t *testing.T) {
b := newCustomizedBundlerFromFile(t, testCFSSLRootBundle, testCFSSLIntBundle, "")
- bundle, _ := b.BundleFromFile(leafRSA2048, leafKeyRSA2048, Optimal)
+ bundle, _ := b.BundleFromFile(leafRSA2048, leafKeyRSA2048, Optimal, "")
jsonBytes, err := json.Marshal(bundle)
if err != nil {
@@ -250,7 +247,7 @@ func TestBundleHostnamesMarshalJSON(t *testing.T) {
t.Fatal("Hostnames construction failed for cloudflare.com.", string(hostnames))
}
- bundle, _ = b.BundleFromPEM(GoDaddyIntermediateCert, nil, Optimal)
+ bundle, _ = b.BundleFromPEMorDER(GoDaddyIntermediateCert, nil, Optimal, "")
expected := []byte(`["Go Daddy Secure Certification Authority"]`)
hostnames, _ = json.Marshal(bundle.Hostnames)
if !bytes.Equal(hostnames, expected) {
@@ -262,7 +259,7 @@ func TestBundleHostnamesMarshalJSON(t *testing.T) {
// Tests on verifying the rebundle flag and error code in Bundle.Status when rebundling.
func TestRebundleFromPEM(t *testing.T) {
newBundler := newCustomizedBundlerFromFile(t, testCFSSLRootBundle, interL1, "")
- newBundle, err := newBundler.BundleFromPEM(expiredBundlePEM, nil, Optimal)
+ newBundle, err := newBundler.BundleFromPEMorDER(expiredBundlePEM, nil, Optimal, "")
if err != nil {
t.Fatalf("Re-bundle failed. %s", err.Error())
}
@@ -314,7 +311,7 @@ func TestRebundleExpiring(t *testing.T) {
if err != nil {
t.Fatalf("bundle failed. %s", err.Error())
}
- newBundle, err := bundler.BundleFromPEM(expiredBundlePEM, nil, Optimal)
+ newBundle, err := bundler.BundleFromPEMorDER(expiredBundlePEM, nil, Optimal, "")
if err != nil {
t.Fatalf("Re-bundle failed. %s", err.Error())
}
@@ -349,7 +346,7 @@ func TestUbiquitousBundle(t *testing.T) {
ubiquity.Platforms = []ubiquity.Platform{platformA, platformB}
// Optimal bundle algorithm will picks up the new root and shorten the chain.
- optimalBundle, err := b.BundleFromFile(leafECDSA256, "", Optimal)
+ optimalBundle, err := b.BundleFromFile(leafECDSA256, "", Optimal, "")
if err != nil {
t.Fatal("Optimal bundle failed:", err)
}
@@ -363,7 +360,7 @@ func TestUbiquitousBundle(t *testing.T) {
checkUbiquityWarningAndCode(t, optimalBundle, true)
// Ubiquitous bundle will remain the same.
- ubiquitousBundle, err := b.BundleFromFile(leafECDSA256, "", Ubiquitous)
+ ubiquitousBundle, err := b.BundleFromFile(leafECDSA256, "", Ubiquitous, "")
if err != nil {
t.Fatal("Ubiquitous bundle failed")
@@ -385,7 +382,7 @@ func TestUbiquityBundleWithoutMetadata(t *testing.T) {
// Without platform info, ubiquitous bundling falls back to optimal bundling.
ubiquity.Platforms = nil
- nuBundle, err := b.BundleFromFile(leafECDSA256, "", Ubiquitous)
+ nuBundle, err := b.BundleFromFile(leafECDSA256, "", Ubiquitous, "")
if err != nil {
t.Fatal("Ubiquitous-fall-back-to-optimal bundle failed: ", err)
@@ -417,155 +414,271 @@ func checkUbiquityWarningAndCode(t *testing.T, bundle *Bundle, expected bool) {
}
}
-// FIXME: test case expires in July 2015
-// Regression test on ubiquity.
-// It is to make sure ubiquitous bundles are generated so they can be trusted by Android 2.2
-// and its variants.
-//
-// Leaf cert from DraftKings.com is issued by a GoDaddy intermediate cert,
-// which in turn is issued by a GoDaddy Root Certificate (CN: Go Daddy Root Certificate Authority
-// G2). The NSS library includes this root cert. So optimal bundle should only have two certs.
-// However, that root cert is not present in trust stores of Android <= 2.2. Ubiquitous bundling
-// should be able to recognize this scenario and produces a bundle that includes the GoDaddy Root
-// cert as an intermediate, which is verified by older trust roots.
-func TestAndroidUbiquitousBundle(t *testing.T) {
- leafs := []string{draftkingsPEM}
- for _, leaf := range leafs {
- b := newCustomizedBundlerFromFile(t, testNSSRootBundle, testIntCaBundle, "")
- ubiquity.Platforms = nil
- ubiquity.LoadPlatforms(testMetadata)
-
- // Optimal bundle algorithm will use the Godaddy Root/GeoTrust CA.
- optimalBundle, err := b.BundleFromFile(leaf, "", Optimal)
- if err != nil {
- t.Fatal("Optimal bundle failed:", err)
- }
- if len(optimalBundle.Chain) != 2 {
- t.Fatal("Optimal bundle failed")
- }
- checkUbiquityWarningAndCode(t, optimalBundle, true)
-
- // Ubiquitous bundle will include a 2nd intermediate CA.
- ubiquitousBundle, err := b.BundleFromFile(leaf, "", Ubiquitous)
- if err != nil {
- t.Fatal("Ubiquitous bundle failed")
-
- }
- if len(ubiquitousBundle.Chain) != 3 {
- t.Fatal("Ubiquitous bundle failed")
- }
- if len(ubiquitousBundle.Status.Untrusted) != 0 {
- t.Fatal("Regression: Ubiquitous bundle has untrusted platforms: ", ubiquitousBundle.Status.Untrusted)
- }
- checkUbiquityWarningAndCode(t, ubiquitousBundle, false)
- }
-}
-
// Regression test on bundle with flavor 'Force'.
// Compare to ubiquitous bundle which will optimize bundle length given the platform ubiquity is the same, force bundle
// with return the same bundle as long as the input bundle is verified.
func TestForceBundle(t *testing.T) {
- b := newCustomizedBundlerFromFile(t, testNSSRootBundle, testIntCaBundle, "")
- ubiquity.Platforms = nil
- ubiquity.LoadPlatforms(testMetadata)
- bundle, err := b.BundleFromFile(firstdataPEM, "", Ubiquitous)
+ // create a CA signer and signs a new intermediate with SHA-2
+ caSigner := makeCASignerFromFile(testCAFile, testCAKeyFile, x509.SHA256WithRSA, t)
+ interL1Bytes := signCSRFile(caSigner, interL1CSR, t)
+
+ // create a inter L1 signer
+ interL1KeyBytes, err := ioutil.ReadFile(interL1Key)
if err != nil {
- t.Fatal("ubiquitous bundling failed.", err)
+ t.Fatal(err)
}
- if len(bundle.Chain) != 2 {
- t.Fatal("ubiquitous bundling failed. Bundle length:", len(bundle.Chain))
+ interL1Signer := makeCASigner(interL1Bytes, interL1KeyBytes, x509.SHA256WithRSA, t)
+
+ // sign a level 2 intermediate
+ interL2Bytes := signCSRFile(interL1Signer, interL2CSR, t)
+
+ // create a inter L2 signer
+ interL2KeyBytes, err := ioutil.ReadFile(interL2Key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ interL2Signer := makeCASigner(interL2Bytes, interL2KeyBytes, x509.ECDSAWithSHA256, t)
+
+ // interL2 sign a leaf cert
+ leafBytes := signCSRFile(interL2Signer, leafCSR, t)
+
+ // create two platforms
+ // both trust the CA cert and L1 intermediate
+ caBytes, err := ioutil.ReadFile(testCAFile)
+ if err != nil {
+ t.Fatal(err)
}
- if bundle.Status.IsRebundled == false {
- t.Fatal("force bundling failed, incorrect bundle.Status", bundle.Status)
+ ca, _ := helpers.ParseCertificatePEM(caBytes)
+ interL1, _ := helpers.ParseCertificatePEM(interL1Bytes)
+ platformA := ubiquity.Platform{
+ Name: "A",
+ Weight: 100,
+ KeyStore: make(ubiquity.CertSet),
+ HashUbiquity: ubiquity.SHA2Ubiquity,
+ KeyAlgoUbiquity: ubiquity.ECDSA521Ubiquity,
}
+ platformB := ubiquity.Platform{
+ Name: "B",
+ Weight: 100,
+ KeyStore: make(ubiquity.CertSet),
+ HashUbiquity: ubiquity.SHA2Ubiquity,
+ KeyAlgoUbiquity: ubiquity.ECDSA521Ubiquity,
+ }
+
+ platformA.KeyStore.Add(ca)
+ platformA.KeyStore.Add(interL1)
+ platformB.KeyStore.Add(ca)
+ platformB.KeyStore.Add(interL1)
+ ubiquity.Platforms = []ubiquity.Platform{platformA, platformB}
+
+ caBundle := string(caBytes) + string(interL1Bytes)
+ interBundle := string(interL2Bytes) + string(interL1Bytes)
+ fullChain := string(leafBytes) + string(interL2Bytes) + string(interL1Bytes)
- bundle, err = b.BundleFromFile(firstdataPEM, "", Force)
+ // create bundler
+ b, err := NewBundlerFromPEM([]byte(caBundle), []byte(interBundle))
if err != nil {
- t.Fatal("force bundling failed.", err)
+ t.Fatal(err)
}
+ // The input PEM bundle is 3-cert chain.
+ bundle, err := b.BundleFromPEMorDER([]byte(fullChain), nil, Force, "")
+ if err != nil {
+ t.Fatal("Force bundle failed:", err)
+ }
if len(bundle.Chain) != 3 {
- t.Fatal("force bundling failed. Bundle length:", len(bundle.Chain))
+ t.Fatal("Force bundle failed:")
+ }
+ if len(bundle.Status.Untrusted) != 0 {
+ t.Fatal("Force bundle failed:")
}
- if bundle.Status.IsRebundled == true {
- t.Fatal("force bundling failed, incorrect bundle.Status", bundle.Status)
+ // With ubiquity flavor, we should have a shorter chain, given L1 is ubiquitous trusted.
+ bundle, err = b.BundleFromPEMorDER([]byte(fullChain), nil, Ubiquitous, "")
+ if err != nil {
+ t.Fatal("Ubiquitous bundle failed:", err)
+ }
+ if len(bundle.Chain) != 2 {
+ t.Fatal("Ubiquitous bundle failed:")
+ }
+ if len(bundle.Status.Untrusted) != 0 {
+ t.Fatal("Ubiquitous bundle failed:")
}
+ // With optimal flavor, we should have a shorter chain as well.
+ bundle, err = b.BundleFromPEMorDER([]byte(fullChain), nil, Optimal, "")
+ if err != nil {
+ t.Fatal("Optimal bundle failed:", err)
+ }
+ if len(bundle.Chain) != 2 {
+ t.Fatal("Optimal bundle failed:")
+ }
+ if len(bundle.Status.Untrusted) != 0 {
+ t.Fatal("Optimal bundle failed:")
+ }
}
-// TODO(nick): re-enable with non-expired certificate
-func testUpdateIntermediate(t *testing.T) {
- b := newCustomizedBundlerFromFile(t, testNSSRootBundle, testIntCaBundle, "")
- ubiquity.Platforms = nil
- ubiquity.LoadPlatforms(testMetadata)
- // forcebundle.pem contains a newer intermediate, which should be used when bundling.
- ub, err := b.BundleFromFile(forcebundlePEM, "", Ubiquitous)
+func TestUpdateIntermediate(t *testing.T) {
+ // create a CA signer and signs a new intermediate with SHA-2
+ caSigner := makeCASignerFromFile(testCAFile, testCAKeyFile, x509.SHA256WithRSA, t)
+ sha2InterBytes := signCSRFile(caSigner, interL1CSR, t)
+ interKeyBytes, err := ioutil.ReadFile(interL1Key)
if err != nil {
- t.Fatal("ubiquitous bundling failed.", err)
+ t.Fatal(err)
}
- // Ubiquitous bundle should use the intermediate from NSS since it will score higher.
- if len(ub.Chain) != 2 {
- t.Fatal("force bundling failed. Bundle length:", len(ub.Chain))
- }
+ // create a intermediate signer from intermediate cert/key
+ sha2InterSigner := makeCASigner(sha2InterBytes, interKeyBytes, x509.SHA256WithRSA, t)
+ // sign a leaf cert
+ leafBytes := signCSRFile(sha2InterSigner, leafCSR, t)
- if ub.Status.IsRebundled == false {
- t.Fatal("force bundling failed, incorrect bundle.Status", ub.Status)
+ // read CA cert bytes
+ caCertBytes, err := ioutil.ReadFile(testCAFile)
+ if err != nil {
+ t.Fatal(err)
}
-
- fb, err := b.BundleFromFile(forcebundlePEM, "", Force)
-
+ // create a bundler with the test root CA and no intermediates
+ b, err := NewBundlerFromPEM(caCertBytes, nil)
if err != nil {
- t.Fatal("force bundling failed.", err)
+ t.Fatal(err)
}
- // Force bundle should use the intermediate from input, indicating intermediate pool is updated.
- if len(fb.Chain) != 2 {
- t.Fatal("force bundling failed. Bundle length:", len(fb.Chain))
+ // create a cert bundle: leaf + inter
+ chainBytes := string(leafBytes) + string(sha2InterBytes)
+ bundle, err := b.BundleFromPEMorDER([]byte(chainBytes), nil, Ubiquitous, "")
+ if err != nil {
+ t.Fatal("Valid bundle should be accepted. error:", err)
+ }
+ if bundle.Status.IsRebundled {
+ t.Fatal("rebundle should never happen here")
}
- if fb.Status.IsRebundled == true {
- t.Fatal("force bundling failed, incorrect bundle.Status", fb.Status)
+ // Now bundle with the leaf cert
+ bundle2, err := b.BundleFromPEMorDER(leafBytes, nil, Ubiquitous, "")
+ if err != nil {
+ t.Fatal("Valid bundle should be accepted. error:", err)
+ }
+ if !bundle2.Status.IsRebundled {
+ t.Fatal("rebundle should happen here")
}
}
-// FIXME: test case expires in July 2015
func TestForceBundleFallback(t *testing.T) {
- leafs := []string{draftkingsPEM}
- for _, leaf := range leafs {
- b := newCustomizedBundlerFromFile(t, testNSSRootBundle, testIntCaBundle, "")
- ubiquity.Platforms = nil
- ubiquity.LoadPlatforms(testMetadata)
+ // create a CA signer and signs a new intermediate with SHA-2
+ caSigner := makeCASignerFromFile(testCAFile, testCAKeyFile, x509.SHA256WithRSA, t)
+ sha2InterBytes := signCSRFile(caSigner, interL1CSR, t)
- forceBundle, err := b.BundleFromFile(leaf, "", Force)
- if err != nil {
- t.Fatal("Force bundle failed:", err)
- }
+ interKeyBytes, err := ioutil.ReadFile(interL1Key)
+ if err != nil {
+ t.Fatal(err)
+ }
- ubiquitousBundle, err := b.BundleFromFile(leaf, "", Ubiquitous)
- if err != nil {
- t.Fatal("Ubiquitous bundle failed")
+ // create a intermediate signer from intermediate cert/key
+ sha2InterSigner := makeCASigner(sha2InterBytes, interKeyBytes, x509.SHA256WithRSA, t)
+ // sign a leaf cert
+ leafBytes := signCSRFile(sha2InterSigner, leafCSR, t)
- }
+ // read CA cert bytes
+ caCertBytes, err := ioutil.ReadFile(testCAFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // create a bundler with the test root CA and the new intermediate
+ b, err := NewBundlerFromPEM(caCertBytes, sha2InterBytes)
+ if err != nil {
+ t.Fatal(err)
+ }
- if diff(ubiquitousBundle.Chain, forceBundle.Chain) {
- t.Fatal("Force bundle fallback failed.")
- }
+ // Now bundle with the leaf cert with Force
+ bundle, err := b.BundleFromPEMorDER(leafBytes, nil, Force, "")
+ if err != nil {
+ t.Fatal("Valid bundle should be generated, error:", err)
+ }
+
+ // Force bundle fallback to creating a valid bundle
+ if len(bundle.Chain) != 2 {
+ t.Fatal("incorrect bundling")
+ }
+ if !bundle.Status.IsRebundled {
+ t.Fatal("rebundle should happen here")
}
+
}
// Regression test: ubiquity bundle test with SHA2-homogeneous preference should not override root ubiquity.
-func TestSHA2Homogeneity(t *testing.T) {
- b := newCustomizedBundlerFromFile(t, testNSSRootBundle, testIntCaBundle, "")
- ubiquity.Platforms = nil
- ubiquity.LoadPlatforms(testMetadata)
- // The input PEM bundle is 3-cert chain with a cross-signed GeoTrust certificate,
- // aimed to provide cert ubiquity to Android 2.2
- bundle, err := b.BundleFromFile(bunningsPEM, "", Force)
+func TestSHA2HomogeneityAgainstUbiquity(t *testing.T) {
+ // create a CA signer and signs a new intermediate with SHA-1
+ caSigner := makeCASignerFromFile(testCAFile, testCAKeyFile, x509.SHA1WithRSA, t)
+ interL1Bytes := signCSRFile(caSigner, interL1CSR, t)
+
+ // create a inter L1 signer
+ interL1KeyBytes, err := ioutil.ReadFile(interL1Key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ interL1Signer := makeCASigner(interL1Bytes, interL1KeyBytes, x509.SHA256WithRSA, t)
+
+ // sign a level 2 intermediate
+ interL2Bytes := signCSRFile(interL1Signer, interL2CSR, t)
+
+ // create a inter L2 signer
+ interL2KeyBytes, err := ioutil.ReadFile(interL2Key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ interL2Signer := makeCASigner(interL2Bytes, interL2KeyBytes, x509.ECDSAWithSHA256, t)
+
+ // interL2 sign a leaf cert
+ leafBytes := signCSRFile(interL2Signer, leafCSR, t)
+
+ // create two platforms
+ // platform A trusts the CA cert and L1 intermediate
+ // platform B trusts the CA cert
+ caBytes, err := ioutil.ReadFile(testCAFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ca, _ := helpers.ParseCertificatePEM(caBytes)
+ interL1, _ := helpers.ParseCertificatePEM(interL1Bytes)
+ platformA := ubiquity.Platform{
+ Name: "A",
+ Weight: 100,
+ KeyStore: make(ubiquity.CertSet),
+ HashUbiquity: ubiquity.SHA2Ubiquity,
+ KeyAlgoUbiquity: ubiquity.ECDSA521Ubiquity,
+ }
+ platformB := ubiquity.Platform{
+ Name: "B",
+ Weight: 100,
+ KeyStore: make(ubiquity.CertSet),
+ HashUbiquity: ubiquity.SHA2Ubiquity,
+ KeyAlgoUbiquity: ubiquity.ECDSA521Ubiquity,
+ }
+
+ platformA.KeyStore.Add(ca)
+ platformA.KeyStore.Add(interL1)
+ platformB.KeyStore.Add(ca)
+ ubiquity.Platforms = []ubiquity.Platform{platformA, platformB}
+
+ caBundle := string(caBytes) + string(interL1Bytes)
+ interBundle := string(interL2Bytes) + string(interL1Bytes)
+ fullChain := string(leafBytes) + string(interL2Bytes) + string(interL1Bytes)
+
+ // create bundler
+ b, err := NewBundlerFromPEM([]byte(caBundle), []byte(interBundle))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // The input PEM bundle is 3-cert chain.
+ bundle, err := b.BundleFromPEMorDER([]byte(fullChain), nil, Force, "")
if err != nil {
t.Fatal("Force bundle failed:", err)
}
@@ -576,8 +689,9 @@ func TestSHA2Homogeneity(t *testing.T) {
t.Fatal("Force bundle failed:")
}
- // With ubiquity flavor, we should not sacrifice Android 2.2 and rebundle with a shorter chain.
- bundle, err = b.BundleFromFile(bunningsPEM, "", Ubiquitous)
+ // With ubiquity flavor, we should not sacrifice trust store ubiquity and rebundle with a shorter chain
+ // with SHA2 homogenity.
+ bundle, err = b.BundleFromPEMorDER([]byte(fullChain), nil, Ubiquitous, "")
if err != nil {
t.Fatal("Ubiquitous bundle failed:", err)
}
@@ -588,9 +702,8 @@ func TestSHA2Homogeneity(t *testing.T) {
t.Fatal("Ubiquitous bundle failed:")
}
- // With optimal flavor, we should have a shorter chain with only SHA-2 intermediates. But Android 2.2
- // is untrusted.
- bundle, err = b.BundleFromFile(bunningsPEM, "", Optimal)
+ // With optimal flavor, we should have a shorter chain.
+ bundle, err = b.BundleFromPEMorDER([]byte(fullChain), nil, Optimal, "")
if err != nil {
t.Fatal("Optimal bundle failed:", err)
}
@@ -640,16 +753,30 @@ func checkECDSAWarningAndCode(t *testing.T, bundle *Bundle, expected bool) {
// bundle uses SHA-256 which is not supported in Windows XP SP2. We should present a warning
// on this.
func TestSHA2Warning(t *testing.T) {
- b := newCustomizedBundlerFromFile(t, testNSSRootBundle, testIntCaBundle, "")
- // Optimal bundle algorithm will use the Godaddy Root/GeoTrust CA.
- optimalBundle, err := b.BundleFromFile(riotPEM, "", Optimal)
+ // create a CA signer and signs a new intermediate with SHA-2
+ caSigner := makeCASignerFromFile(testCAFile, testCAKeyFile, x509.SHA256WithRSA, t)
+ sha2InterBytes := signCSRFile(caSigner, interL1CSR, t)
+
+ // read CA cert bytes
+ caCertBytes, err := ioutil.ReadFile(testCAFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // create a bundler with the test root CA and no intermediates
+ b, err := NewBundlerFromPEM(caCertBytes, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ optimalBundle, err := b.BundleFromPEMorDER(sha2InterBytes, nil, Optimal, "")
if err != nil {
t.Fatal("Optimal bundle failed:", err)
}
checkSHA2WarningAndCode(t, optimalBundle, true)
// Ubiquitous bundle will include a 2nd intermediate CA.
- ubiquitousBundle, err := b.BundleFromFile(riotPEM, "", Ubiquitous)
+ ubiquitousBundle, err := b.BundleFromPEMorDER(sha2InterBytes, nil, Ubiquitous, "")
if err != nil {
t.Fatal("Ubiquitous bundle failed")
@@ -661,11 +788,12 @@ func TestSHA2Warning(t *testing.T) {
// A test bundle that contains ECDSA384 but no SHA1. Expect ECDSA warning and no SHA-2 warning.
func TestECDSAWarning(t *testing.T) {
b := newCustomizedBundlerFromFile(t, testCAFile, interL1SHA1, "")
- // Optimal
- optimalBundle, err := b.BundleFromFile(interL2SHA1, "", Optimal)
+
+ optimalBundle, err := b.BundleFromFile(interL2SHA1, "", Optimal, "")
if err != nil {
t.Fatal("Optimal bundle failed:", err)
}
+
checkSHA2WarningAndCode(t, optimalBundle, false)
checkECDSAWarningAndCode(t, optimalBundle, true)
}
@@ -713,6 +841,8 @@ func createInterCert(t *testing.T, csrFile string, policy *config.Signing, profi
return
}
+
+// newBundler creates bundler from byte slices of CA certs and intermediate certs in PEM format
func newBundlerFromPEM(t *testing.T, caBundlePEM, intBundlePEM []byte) (b *Bundler) {
b, err := NewBundlerFromPEM(caBundlePEM, intBundlePEM)
if err != nil {
@@ -722,7 +852,7 @@ func newBundlerFromPEM(t *testing.T, caBundlePEM, intBundlePEM []byte) (b *Bundl
}
// newCustomizedBundleCreator is a helper function that returns a new Bundler
-// takes specified CA bundle, intermediate bundle, and any additional intermdiate certs to generate a bundler.
+// takes specified CA bundle, intermediate bundle, and any additional intermdiate certs to generate a bundler.
func newCustomizedBundlerFromFile(t *testing.T, caBundle, intBundle, adhocInters string) (b *Bundler) {
b, err := NewBundler(caBundle, intBundle)
if err != nil {
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/CADisigI1CertificationService_cb619f69c2d820b4bc23e4d4339f06a96d6373d4_021c8d95a0308df09c0000000000611515.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/CADisigI1CertificationService_cb619f69c2d820b4bc23e4d4339f06a96d6373d4_021c8d95a0308df09c0000000000611515.crt
new file mode 100644
index 00000000000..233904f2a3e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/CADisigI1CertificationService_cb619f69c2d820b4bc23e4d4339f06a96d6373d4_021c8d95a0308df09c0000000000611515.crt
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE5zCCA8+gAwIBAgIRAhyNlaAwjfCcAAAAAABhFRUwDQYJKoZIhvcNAQEFBQAw
+SjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRp
+c2lnIGEucy4xETAPBgNVBAMTCENBIERpc2lnMB4XDTEyMDUzMTE3NDkwMloXDTE2
+MDMxNTE3NDkwMlowYzELMAkGA1UEBhMCU0sxEzARBgNVBAcMCkJyYXRpc2xhdmEx
+EzARBgNVBAoMCkRpc2lnIGEucy4xKjAoBgNVBAMMIUNBIERpc2lnIEkxIENlcnRp
+ZmljYXRpb24gU2VydmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANBg8jAhWMX34D/st646D2g+5dAYB0o6Pv9SYdEzNZvozFj/1fO80vMQMRX75DUv
+nvAkKIZvDALuqVRVuj7fDGlsQiu9GlFvtAXg6cDd/5WbnQns/ersDLFZ9vFVOYZQ
+PgLpy2O0AiBgL5bxrYx0kUvurySstNlrYMzrtMiZpOmu+bVFHQrGjpTInfwiZOgB
+4Tr+KcP/k0y7QRC+QTE2PNT7k/H/FxzGfQvc8zayGxYFuq85Kpk1wKtIfxBy37M4
+nMg4zQfeKbTQajrWh3/Yl0JGlR49oS/wmnyvMWq3VTx8D0BYShSAq2nkBg+Yf1GL
+Fpm18TlwVy8dvXBv9QqrY08CAwEAAaOCAa0wggGpMGkGCCsGAQUFBwEBBF0wWzAj
+BggrBgEFBQcwAYYXaHR0cDovL2NhLW9jc3AuZGlzaWcuc2swNAYIKwYBBQUHMAKG
+KGh0dHA6Ly93d3cuZGlzaWcuc2svY2EvY2VydC9jYV9kaXNpZy5kZXIwHQYDVR0O
+BBYEFMthn2nC2CC0vCPk1DOfBqltY3PUMB8GA1UdIwQYMBaAFI2ySWidcgglucAn
+9VCTVkhGcfmPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMGYG
+A1UdHwRfMF0wLaAroCmGJ2h0dHA6Ly93d3cuZGlzaWcuc2svY2EvY3JsL2NhX2Rp
+c2lnLmNybDAsoCqgKIYmaHR0cDovL2NhLmRpc2lnLnNrL2NhL2NybC9jYV9kaXNp
+Zy5jcmwwUAYDVR0gBEkwRzBFBg4rgR6Rk+YKAAAAAQEEAzAzMDEGCCsGAQUFBwIB
+FiVodHRwOi8vd3d3LmRpc2lnLnNrL19wZGYvY3AtZGlzaWcucGRmMB4GA1UdEQQX
+MBWBE2Nhb3BlcmF0b3JAZGlzaWcuc2swDQYJKoZIhvcNAQEFBQADggEBAHiH87TX
++efGy8a3Te8Pxa/KBXhbS1nB6N2WyzklQmWRqfhGFecMPq4OeKtcE/M/K28KiP8e
+4HgPM8XiwJ1k7MFp8dc6k/9LBiIeI+w4pGBXoIp0TfZJU4kUDRjAGVR6R1nj2/Iz
+UCnXa9+35pyRvFSuA6q7P2xC6OL4wNnbG6wPU3PUX2kCEUxfhxKJnpa2XZtZCCOC
+zWqRTHihw05HjfoayIp3O71kYe1LWxpl4QPStwO3gHOQKKUR1f9XCwqqlYwN/wbY
+Cv/ef1hzECVsFL7kGGEbA6P+DDu3EnRcsVot1XCI0rsFFgF241qiUiiwf26jf+53
+e1FbYT/ZFR0D3BI=
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/COMODOECCDomainValidationSecureServerCA2_40096167f0bc83714fde12082c6fd4d42b763d96_5b25ce6907c4265566d3390c99a954ad.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/COMODOECCDomainValidationSecureServerCA2_40096167f0bc83714fde12082c6fd4d42b763d96_5b25ce6907c4265566d3390c99a954ad.crt
new file mode 100644
index 00000000000..3e0f6c08512
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/COMODOECCDomainValidationSecureServerCA2_40096167f0bc83714fde12082c6fd4d42b763d96_5b25ce6907c4265566d3390c99a954ad.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAyWgAwIBAgIQWyXOaQfEJlVm0zkMmalUrTAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwOTI1MDAw
+MDAwWhcNMjkwOTI0MjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBFQ0MgRG9tYWluIFZhbGlk
+YXRpb24gU2VjdXJlIFNlcnZlciBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAEAjgZgTrJaYRwWQKOqIofMN+83gP8eR06JSxrQSEYgur5PkrkM8wSzypD/A7y
+ZADA4SVQgiTNtkk4DyVHkUikraOCAWYwggFiMB8GA1UdIwQYMBaAFHVxpxlIGbyd
+nepBR9+UxEh3mdN5MB0GA1UdDgQWBBRACWFn8LyDcU/eEggsb9TUK3Y9ljAOBgNV
+HQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEF
+BQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgGBmeBDAECATBMBgNV
+HR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9FQ0ND
+ZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDByBggrBgEFBQcBAQRmMGQwOwYIKwYB
+BQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET0VDQ0FkZFRydXN0
+Q0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMAoG
+CCqGSM49BAMDA2gAMGUCMQCsaEclgBNPE1bAojcJl1pQxOfttGHLKIoKETKm4nHf
+EQGJbwd6IGZrGNC5LkP3Um8CMBKFfI4TZpIEuppFCZRKMGHRSdxv6+ctyYnPHmp8
+7IXOMCVZuoFwNLg0f+cB0eLLUg==
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/DigiCertSHA2HighAssuranceServerCA_5168ff90af0207753cccd9656462a212b859723b_04e1e7a4dc5cf2f36dc02b42b85d159f.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/DigiCertSHA2HighAssuranceServerCA_5168ff90af0207753cccd9656462a212b859723b_04e1e7a4dc5cf2f36dc02b42b85d159f.crt
new file mode 100644
index 00000000000..8c4c7410586
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/DigiCertSHA2HighAssuranceServerCA_5168ff90af0207753cccd9656462a212b859723b_04e1e7a4dc5cf2f36dc02b42b85d159f.crt
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
+YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
+4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
+Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
+itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
+4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
+sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
+bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
+MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
+NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
+dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
+L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
+BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
+UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
+aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
+aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
+E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
+/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
+xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
+0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
+cPUeybQ=
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/GeoTrustSSLCA-G3_d26ff796f4853f723c307d23da85789ba37c5a7c_023a6f.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/GeoTrustSSLCA-G3_d26ff796f4853f723c307d23da85789ba37c5a7c_023a6f.crt
new file mode 100644
index 00000000000..8d12709910d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/GeoTrustSSLCA-G3_d26ff796f4853f723c307d23da85789ba37c5a7c_023a6f.crt
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIETzCCAzegAwIBAgIDAjpvMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMTMxMTA1MjEzNjUwWhcNMjIwNTIwMjEzNjUwWjBEMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
+U1NMIENBIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjvn4K
+hqPPa209K6GXrUkkTdd3uTR5CKWeop7eRxKSPX7qGYax6E89X/fQp3eaWx8KA7UZ
+U9ulIZRpY51qTJEMEEe+EfpshiW3qwRoQjgJZfAU2hme+msLq2LvjafvY3AjqK+B
+89FuiGdT7BKkKXWKp/JXPaKDmJfyCn3U50NuMHhiIllZuHEnRaoPZsZVP/oyFysx
+j0ag+mkUfJ2fWuLrM04QprPtd2PYw5703d95mnrU7t7dmszDt6ldzBE6B7tvl6QB
+I0eVH6N3+liSxsfQvc+TGEK3fveeZerVO8rtrMVwof7UEJrwEgRErBpbeFBFV0xv
+vYDLgVwts7x2oR5lAgMBAAGjggFKMIIBRjAfBgNVHSMEGDAWgBTAephojYn7qwVk
+DBF9qn1luMrMTjAdBgNVHQ4EFgQU0m/3lvSFP3I8MH0j2oV4m6N8WnwwEgYDVR0T
+AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwNgYDVR0fBC8wLTAroCmgJ4Yl
+aHR0cDovL2cxLnN5bWNiLmNvbS9jcmxzL2d0Z2xvYmFsLmNybDAvBggrBgEFBQcB
+AQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9nMi5zeW1jYi5jb20wTAYDVR0gBEUw
+QzBBBgpghkgBhvhFAQc2MDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuZ2VvdHJ1
+c3QuY29tL3Jlc291cmNlcy9jcHMwKQYDVR0RBCIwIKQeMBwxGjAYBgNVBAMTEVN5
+bWFudGVjUEtJLTEtNTM5MA0GCSqGSIb3DQEBCwUAA4IBAQCg1Pcs+3QLf2TxzUNq
+n2JTHAJ8mJCi7k9o1CAacxI+d7NQ63K87oi+fxfqd4+DYZVPhKHLMk9sIb7SaZZ9
+Y73cK6gf0BOEcP72NZWJ+aZ3sEbIu7cT9clgadZM/tKO79NgwYCA4ef7i28heUrg
+3Kkbwbf7w0lZXLV3B0TUl/xJAIlvBk4BcBmsLxHA4uYPL4ZLjXvDuacu9PGsFj45
+SVGeF0tPEDpbpaiSb/361gsDTUdWVxnzy2v189bPsPX1oxHSIFMTNDcFLENaY9+N
+QNaFHlHpURceA1bJ8TCt55sRornQMYGbaLHZ6PPmlH7HrhMvh+3QJbBo+d4IWvMp
+zNSS
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/GoogleInternetAuthorityG2_4add06161bbcf668b576f581b6bb621aba5a812f_023a76.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/GoogleInternetAuthorityG2_4add06161bbcf668b576f581b6bb621aba5a812f_023a76.crt
new file mode 100644
index 00000000000..5273269a24f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/GoogleInternetAuthorityG2_4add06161bbcf668b576f581b6bb621aba5a812f_023a76.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID8DCCAtigAwIBAgIDAjp2MA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG
+EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy
+bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP
+VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv
+h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE
+ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ
+EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC
+DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7
+qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD
+VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwNQYDVR0fBC4wLDAqoCig
+JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMC4GCCsGAQUF
+BwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDovL2cuc3ltY2QuY29tMBcGA1UdIAQQ
+MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQUFAAOCAQEAJ4zP6cc7vsBv6JaE
++5xcXZDkd9uLMmCbZdiFJrW6nx7eZE4fxsggWwmfq6ngCTRFomUlNz1/Wm8gzPn6
+8R2PEAwCOsTJAXaWvpv5Fdg50cUDR3a4iowx1mDV5I/b+jzG1Zgo+ByPF5E0y8tS
+etH7OiDk4Yax2BgPvtaHZI3FCiVCUe+yOLjgHdDh/Ob0r0a678C/xbQF9ZR1DP6i
+vgK66oZb+TWzZvXFjYWhGiN3GhkXVBNgnwvhtJwoKvmuAjRtJZOcgqgXe/GFsNMP
+WOH7sf6coaPo/ck/9Ndx3L2MpBngISMjVROPpBYCCX65r+7bU2S9cS+5Oc4wt7S8
+VOBHBw==
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/cloudflare-intercom_8860ba18a477b841041bd5ef7751c25b14ba203f_5bc0b8bee6f8e914.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/cloudflare-intercom_8860ba18a477b841041bd5ef7751c25b14ba203f_5bc0b8bee6f8e914.crt
new file mode 100644
index 00000000000..73066696c39
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/intermediates/cloudflare-intercom_8860ba18a477b841041bd5ef7751c25b14ba203f_5bc0b8bee6f8e914.crt
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEbTCCA9igAwIBAgIIW8C4vub46RQwCwYJKoZIhvcNAQELMH0xCzAJBgNVBAYT
+AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv
+MRMwEQYDVQQKDApDbG91ZEZsYXJlMRQwEgYDVQQLDAtERVZfVEVTVElORzEWMBQG
+A1UEAwwNQ0ZTU0xfVEVTVF9DQTAeFw0xNTA1MjkyMTUyMDBaFw0xNTA1MjkyMjUy
+MDBaMIGMMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UE
+CxMTU3lzdGVtcyBFbmdpbmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzET
+MBEGA1UECBMKQ2FsaWZvcm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDlCnV+vj0sVPy8SqHL
+AlI+xwnPhWgzj2VevD6Nz1Zu1BeQ5m5y4CWCf+GmRGTP7+a/C510Fw6rpmInB0Ng
+xxwQ2rC08fJtCnijlGH/VjEPIHY5lRaAomcM8Rgx6JOuv9BpZJKpr9pyUMV53JeW
+RbWuLH5nEMdyk9NpetS2gWxt4/D20QlhK/tHkROrcLmEUddwIGdwE8JzI88c77Fu
+u6pgMtHKvl4GGH0yvb4T7PvCdH8V2tCH7bt8roXd9MSyFVy7uORkfouip7EsVREU
+mlcY5EvpR141KXbZqiOQiusJ+u76mEUQNk8wCR1/CW/ii9v1BKOVjXwCfEtIXjg0
+APJx1VNSSH6XoDpUETL+eQ4J0FL9XNbsDuYar7+zD0N1/5vSo3HLNRQR9f0lbsys
+sWBEN+CxK19xyPumr21Z0bU0f1B5H52VSF0q3I1Ju9wRo994a7YipdGcmZ2lChmT
+7r3mzlBTYl3poU26q34v8wG9U7Jv4fsZJ+RGebDI+TR3QG6Yod06l9oEYZxWXBY7
+STOs8wuTu3huSnan/IpWnV017Vsc61D5G+QrqcxZdXckt3anZKCF75JpUnJ7vuow
+TmmHlb8KIMa9mOvcuGX4P6mz8gTi2arl/aL27kj9Q0Jgv/y1ebe2Bx2P9TF6+VND
+DL3J/vSVlFeqLt2reAIBKnytLwIDAQABo2YwZDAOBgNVHQ8BAf8EBAMCAAQwEgYD
+VR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUiGC6GKR3uEEEG9Xvd1HCWxS6ID8w
+HwYDVR0jBBgwFoAUuF7vrmdQt9bzB+VqvlWzZzoNkj4wCwYJKoZIhvcNAQELA4GB
+ACn1ZlQ9fzh/XH2jK6rv8C+H/sMKfRQ0f+UCa4K3vQpg/jiliNlP6ZtBi/TFTd0y
+GfGPQlCKktZuw6SuNmXD/lUc3A1H1IcYfKVpK7bOJ6+q9OD1CAO+xt3VQdr4K5W+
+inQTvCvz0oFEKh2rSbmFferidcKBN+nkeHcLUOSn7zDN
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/bunnings.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/bunnings.pem
deleted file mode 100644
index 5b4ce36a633..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/bunnings.pem
+++ /dev/null
@@ -1,75 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIE2jCCA8KgAwIBAgIQB0GfyZ37ARHtj7oFnxJVqDANBgkqhkiG9w0BAQsFADBE
-MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMU
-R2VvVHJ1c3QgU1NMIENBIC0gRzMwHhcNMTQwNTA2MDAwMDAwWhcNMTYwNjIxMjM1
-OTU5WjCBiTELMAkGA1UEBhMCQVUxETAPBgNVBAgMCFZpY3RvcmlhMRYwFAYDVQQH
-DA1IYXd0aG9ybiBFYXN0MR8wHQYDVQQKDBZCdW5uaW5ncyBHcm91cCBMaW1pdGVk
-MRIwEAYDVQQLDAlFY29tbWVyY2UxGjAYBgNVBAMMESouYnVubmluZ3MuY29tLmF1
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqpFpWh6yMFhX6O24zyjD
-/RKi3qwQeCokwLf2mkEIkcZPvrm/aDQ26e+ZieUJeXHTK9zwxibHCRqYZYAkMvuS
-k5ZuB6bdA9ipdPLQN9sG4dsJGNRV3MdbXRK6534BWc8LbbG3O+1p6X8Fm3tpYC5u
-C5H+Ek2Gm2uf3hQys+O8mYieEONg5Xf3SqBzGyT3yPztPZQXthjRJfMcBF9UJe5b
-a1MB0IYYefph3Bo7HHb3pX9ywqiC8zffoIoowsysg+gU9tKoPRUgAbUcV/IjM037
-sy+qe4BK++cifD9UN7R2to6F373MtOl5ldMG7fXdOhf3cALPiwYe5P3XAHC3UkXA
-aQIDAQABo4IBgDCCAXwwLQYDVR0RBCYwJIIRKi5idW5uaW5ncy5jb20uYXWCD2J1
-bm5pbmdzLmNvbS5hdTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDAtBgNVHR8E
-JjAkMCKgIKAehhxodHRwOi8vZ24xLnN5bWNiLmNvbS9nbjEuY3JsMGUGA1UdIARe
-MFwwWgYKYIZIAYb4RQEHNjBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2Iu
-Y29tL2NwczAlBggrBgEFBQcCAjAZFhdodHRwczovL2Quc3ltY2IuY29tL3JwYTAd
-BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0jBBgwFoAU0m/3lvSF
-P3I8MH0j2oV4m6N8WnwwWgYIKwYBBQUHAQEETjBMMCAGCCsGAQUFBzABhhRodHRw
-Oi8vZ24yLnN5bWNiLmNvbTAoBggrBgEFBQcwAoYcaHR0cDovL2duMS5zeW1jYi5j
-b20vZ24xLmNydDANBgkqhkiG9w0BAQsFAAOCAQEA1jfVww4Vm/aXvfev4UOgg+7G
-LWuJDm7j0F7oB48Xjah9iuGFWSfmq0Z8nTfM+d5X+BOH1fmJ+O1zLs8S8IBUTgVk
-hbdWXy8NA+r8ufaF2MDJiL1tfHwn3WgAnc1T+w+HMIRMPNlRs+ZEBXEbpXUJmHOW
-rSbFlLN4fwWvN8icuNWO4TuJDqvh5WjQvIFdytygJbMeb5FjLEHFmYftAW5co2cN
-2+FRA+WZ8lfebr5/rObxUoZs8PYCNp7BkXoYZRSI49TEEe+QmO9Q1OmbfPzflJfJ
-fIR/XQZ2zHvuZTd3nfbIkDZoHYnyJwKj29UUKWwHRL+6celDM9/kDwIXbIem2g==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIETzCCAzegAwIBAgIDAjpvMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT
-MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
-YWwgQ0EwHhcNMTMxMTA1MjEzNjUwWhcNMjIwNTIwMjEzNjUwWjBEMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
-U1NMIENBIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjvn4K
-hqPPa209K6GXrUkkTdd3uTR5CKWeop7eRxKSPX7qGYax6E89X/fQp3eaWx8KA7UZ
-U9ulIZRpY51qTJEMEEe+EfpshiW3qwRoQjgJZfAU2hme+msLq2LvjafvY3AjqK+B
-89FuiGdT7BKkKXWKp/JXPaKDmJfyCn3U50NuMHhiIllZuHEnRaoPZsZVP/oyFysx
-j0ag+mkUfJ2fWuLrM04QprPtd2PYw5703d95mnrU7t7dmszDt6ldzBE6B7tvl6QB
-I0eVH6N3+liSxsfQvc+TGEK3fveeZerVO8rtrMVwof7UEJrwEgRErBpbeFBFV0xv
-vYDLgVwts7x2oR5lAgMBAAGjggFKMIIBRjAfBgNVHSMEGDAWgBTAephojYn7qwVk
-DBF9qn1luMrMTjAdBgNVHQ4EFgQU0m/3lvSFP3I8MH0j2oV4m6N8WnwwEgYDVR0T
-AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwNgYDVR0fBC8wLTAroCmgJ4Yl
-aHR0cDovL2cxLnN5bWNiLmNvbS9jcmxzL2d0Z2xvYmFsLmNybDAvBggrBgEFBQcB
-AQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9nMi5zeW1jYi5jb20wTAYDVR0gBEUw
-QzBBBgpghkgBhvhFAQc2MDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuZ2VvdHJ1
-c3QuY29tL3Jlc291cmNlcy9jcHMwKQYDVR0RBCIwIKQeMBwxGjAYBgNVBAMTEVN5
-bWFudGVjUEtJLTEtNTM5MA0GCSqGSIb3DQEBCwUAA4IBAQCg1Pcs+3QLf2TxzUNq
-n2JTHAJ8mJCi7k9o1CAacxI+d7NQ63K87oi+fxfqd4+DYZVPhKHLMk9sIb7SaZZ9
-Y73cK6gf0BOEcP72NZWJ+aZ3sEbIu7cT9clgadZM/tKO79NgwYCA4ef7i28heUrg
-3Kkbwbf7w0lZXLV3B0TUl/xJAIlvBk4BcBmsLxHA4uYPL4ZLjXvDuacu9PGsFj45
-SVGeF0tPEDpbpaiSb/361gsDTUdWVxnzy2v189bPsPX1oxHSIFMTNDcFLENaY9+N
-QNaFHlHpURceA1bJ8TCt55sRornQMYGbaLHZ6PPmlH7HrhMvh+3QJbBo+d4IWvMp
-zNSS
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
-aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw
-WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE
-AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m
-OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu
-T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c
-JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR
-Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz
-PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm
-aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM
-TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g
-LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO
-BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv
-dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB
-AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL
-NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W
-b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S
------END CERTIFICATE-----
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/ca.pem.metadata b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/ca.pem.metadata
deleted file mode 100644
index 2dc32cfdec1..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/ca.pem.metadata
+++ /dev/null
@@ -1,42 +0,0 @@
-[
-{
- "name":"Chrome Browser M39",
- "weight": 0,
- "hash_algo": "SHA2",
- "key_algo": "ECDSA256",
- "hash_algo_expiry": {
- "target": "SHA1",
- "effective_date": "2014-09-01T00:00:00Z",
- "expiry_deadline": "2017-01-01T00:00:00Z"
- }
-},
-{
- "name":"Chrome Browser M40",
- "weight": 0,
- "hash_algo": "SHA2",
- "key_algo": "ECDSA256",
- "hash_algo_expiry": {
- "target": "SHA1",
- "effective_date": "2014-09-01T00:00:00Z",
- "expiry_deadline": "2016-06-01T00:00:00Z"
- }
-},
-{
- "name":"Chrome Browser M41",
- "weight": 0,
- "hash_algo": "SHA2",
- "key_algo": "ECDSA256",
- "hash_algo_expiry": {
- "target": "SHA1",
- "effective_date": "2014-09-01T00:00:00Z",
- "expiry_deadline": "2016-01-01T00:00:00Z"
- }
-},
-{
- "name":"Test Platform",
- "weight": 1,
- "hash_algo": "SHA2",
- "key_algo": "ECDSA521",
- "keystore": "ca.pem"
-}
-]
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa256-v2.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa256-v2.pem
deleted file mode 100644
index d487bd05dce..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa256-v2.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDTTCCAjegAwIBAgIIaqaClruOQWMwCwYJKoZIhvcNAQELMIGGMQswCQYDVQQG
-EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
-bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
-cm5pYTEXMBUGA1UEAxMOY2xvdWRmbGFyZS5jb20wHhcNMTQwNTI3MTgwMzA4WhcN
-MTUwNTI3MTgwODA4WjCBizELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNsb3VkRmxh
-cmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcTDVNhbiBG
-cmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHDAaBgNVBAMTE2Nsb3VkZmxh
-cmUtbGVhZi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASMRv3xvcv4I5QF
-7we+23hES2waKDffBRhQMVVAOSIJcpb4JnzcVJiPJjNlMPbczi5vbzkQK2kkjOP+
-okqQia3go4GGMIGDMA4GA1UdDwEB/wQEAwIApjAdBgNVHSUEFjAUBggrBgEFBQcD
-AQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU4t+cr91m
-a5IxOPeiezgN8W9FBNowHwYDVR0jBBgwFoAUfb7i6rIruh9UuqhvSZlEoevO5qgw
-CwYJKoZIhvcNAQELA4IBAQDXW01KmbTDyOcVvF+gU9tIUs0xjrEaMEmm5vwlukSH
-AmliEUEAieRdsJsPgFxwzifBksZpa4J8FTUNs7tS1JIievAgtTj08wY/sdBhF8pX
-s0JmfTyW93IJYOqJrgkpqHRH0bOfuNidxjzEeqg06GL1rnqD3wS7q4wKpJ0jR8Ws
-iYK9URC6KB8WMLqJTOt4GwRSHfhink1iAc7Nlw2Id26o2kFDGHHyB4S5XsSc0YrB
-hUuzKOkC1hHsvR07OBolpvzXsGR1S77UVOKvgpU5DiTbyjX2iycJGtBdhil+w0U/
-Gq99AYLLfFKG67C1lSM5BLincp0AX2wYrY/hf8MTDdag
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa384-v2.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa384-v2.pem
deleted file mode 100644
index 4a4fa04c677..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa384-v2.pem
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDajCCAlSgAwIBAgIIKkKT9A/MDD4wCwYJKoZIhvcNAQELMIGGMQswCQYDVQQG
-EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
-bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
-cm5pYTEXMBUGA1UEAxMOY2xvdWRmbGFyZS5jb20wHhcNMTQwNTI3MTgwNDEyWhcN
-MTUwNTI3MTgwOTEyWjCBizELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNsb3VkRmxh
-cmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcTDVNhbiBG
-cmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHDAaBgNVBAMTE2Nsb3VkZmxh
-cmUtbGVhZi5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATWIrww4dyIpJG/t/zq
-HIrcuCUF5sSz9p42U4WDbUeMuwcYsadOSi6KvILWs8nHA5JbnruDlhZ6ZpI8qj0P
-tDCH/wSSqAOEOIjYgjf2XxevdC0f6WT6zEWblkhlW9vPdC+jgYYwgYMwDgYDVR0P
-AQH/BAQDAgCmMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMB
-Af8ECDAGAQH/AgEBMB0GA1UdDgQWBBTiTQoJuFODtNnEnbYaxy+He8lO+DAfBgNV
-HSMEGDAWgBR9vuLqsiu6H1S6qG9JmUSh687mqDALBgkqhkiG9w0BAQsDggEBAJIu
-Gg+4SJYA1vwlP6di/cXrctbfuFmxkHb+2+xMnJhRGzWZSk26ZRSfJmfyl4VR8x5y
-oYFpvIV1JsihIKoVWt34gZJrtUM5yZLIqEpaIzQd+yxg3NtUZ+Br0YDYKJOJ+GOl
-/uk5Nz10I5qqGZgCLTxW2riQH2z8hY8Bow7eh1SfazSVzuqOHGobaspbrxzkbqYE
-OlJeGyg1YUsf6X2SlaGgO3uYon6gVanPj3e/I3yUciCLouD72PP2IY5O/bllVp1R
-7VEgbrJAsfMtVywH5KV9R8A+VuxGj8nIh3JrckBlCfj5U9sicJbWIQbcjlBXn4/Y
-EHD1hD0LRPKdq7eZ1GI=
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa521-v2.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa521-v2.pem
deleted file mode 100644
index 7fbb82b50d3..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/cfssl-leaf-ecdsa521-v2.pem
+++ /dev/null
@@ -1,22 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDkDCCAnqgAwIBAgIIQafPjiBzOXkwCwYJKoZIhvcNAQELMIGGMQswCQYDVQQG
-EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
-bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
-cm5pYTEXMBUGA1UEAxMOY2xvdWRmbGFyZS5jb20wHhcNMTQwNTI3MTgwNDI2WhcN
-MTUwNTI3MTgwOTI2WjCBizELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNsb3VkRmxh
-cmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcTDVNhbiBG
-cmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHDAaBgNVBAMTE2Nsb3VkZmxh
-cmUtbGVhZi5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAEp3UqqoJpe6UV7
-y9YR3a8SgMpoRotSKNqeA9JKi+3LyE6p5w3WsENvych1DQc4Tq7nvH4gjRPqO752
-1eXsbmrAYwEK3F1RdexFJJ53DaKuUnYOqiI5pcHKjTDqkr2CABh3cE11Hg2vPHf4
-3vpMp82ojKFzNtSJBSnnV7ab9+g+ziveqKOBhjCBgzAOBgNVHQ8BAf8EBAMCAKYw
-HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
-AQEwHQYDVR0OBBYEFDYrMNrJaqxCJjszyculXPsseU/yMB8GA1UdIwQYMBaAFH2+
-4uqyK7ofVLqob0mZRKHrzuaoMAsGCSqGSIb3DQEBCwOCAQEAmytI+1j8r9KmCGEF
-9iq60KycOXKlVIsEH890WrpvMLBspr0+NGDHCZA5BcVB0aOpyno8Vj/9y6qlr2Wr
-+CNrChF3UmGTzROqJeAXH4N8gnOoZGSUVYBcNJnGgji/ZURsrE5IPw5d9oMGRRvb
-q+JdUVlr1G7YGo6mtVHHUCG3okeUj7ddjLMCDGaprIPk1teqR/94jvcG+2cLgrge
-riJMqtOI8EFckcvHfcA3bZ4G2mXmikWje2od0UaWT5VS1htCKJhlxAFTcaz3qg2o
-T1hNaWSM72HiBCZERI+iwI0CmBBRkOIBOxznh1/boa5O0tWN4o55Ureh9rbF3xep
-q2GQSw==
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/draftkings.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/draftkings.pem
deleted file mode 100644
index baeb882d811..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/draftkings.pem
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFLDCCBBSgAwIBAgIHBEK/bqLmmjANBgkqhkiG9w0BAQsFADCBtDELMAkGA1UE
-BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
-BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMS0wKwYDVQQLEyRodHRwOi8vY2VydHMu
-Z29kYWRkeS5jb20vcmVwb3NpdG9yeS8xMzAxBgNVBAMTKkdvIERhZGR5IFNlY3Vy
-ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjAeFw0xNDA0MjgxODIyMDlaFw0x
-NTA3MTMyMDI0MDlaMD4xITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl
-ZDEZMBcGA1UEAwwQKi5kcmFmdGtpbmdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBANGdW/XXPUTqrbTkDwOEKD4aN7t6qdo6kbyVeozX0WXfSuVG
-JoFPnHYRc1NBlgRpz+2fcWJaAm61IRg2OGVbgM86JqI1B4/TnjHTgHqtxiu8oyKF
-mAJFV15ZEqdKa4sDgx+HWUgLIljsF4BjSgXLdFKY05pBnNOxMEgrypZUE3sAKRcZ
-WUOJUsL7fLi+mjtbCtzvaO5zpMpmsSlodvt481i1nhQauh4mpGimxWXuvJp49uuz
-OnVwmaB3JiBk8QeOTbIfzjvbW0yO/8nTL3z75oZRll/mKhxhYruRLH2s/Fnfad3c
-KRZTHVAwGeU75CHeu5EhCwIDYWrOrF33P5ShR/kCAwEAAaOCAbYwggGyMA8GA1Ud
-EwEB/wQFMAMBAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1Ud
-DwEB/wQEAwIFoDA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vY3JsLmdvZGFkZHku
-Y29tL2dkaWcyczEtNDkuY3JsMFMGA1UdIARMMEowSAYLYIZIAYb9bQEHFwEwOTA3
-BggrBgEFBQcCARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
-c2l0b3J5LzB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw
-LmdvZGFkZHkuY29tLzBABggrBgEFBQcwAoY0aHR0cDovL2NlcnRpZmljYXRlcy5n
-b2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkaWcyLmNydDAfBgNVHSMEGDAWgBRAwr0n
-jsw0gzCiM9f7bLPwtCyAzjArBgNVHREEJDAighAqLmRyYWZ0a2luZ3MuY29tgg5k
-cmFmdGtpbmdzLmNvbTAdBgNVHQ4EFgQUkF4a4BpBmRLNfTDDir3K9m++N3AwDQYJ
-KoZIhvcNAQELBQADggEBAGU/LaXNXEyagwZxxDOTJHRH6CUofPwvJJiIIfF3ANLz
-ulFb4H9ap38X/rOnIZHJHUjYVGBhVfwFfhhJHXjQHm+V9ixHYNIVPeCifAQw0xE5
-V6M79+9BbuRvrKNF7mI60gtY2JL/L1L+Uj1R2VX2velw2GSMr6fyJdwq5N4cfmwf
-QP0LRkyHOn6wMX74mYzPQ/51OQi9pzvKPXJE8vwUi1rKvAiViqivXbCLiisdx13h
-5/BOx8fUjLSew66QJLjU8laZDK2bIzEf2JczLuY92yyS2ifgLyalKieY6y10y/O+
-4TWjhNY5msjyIqXeLXwAO1CjRZzFIv/li+HXka6qAFQ=
------END CERTIFICATE-----
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/firstdata.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/firstdata.pem
deleted file mode 100644
index 9c4842f4be6..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/firstdata.pem
+++ /dev/null
@@ -1,94 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFjDCCBHSgAwIBAgIQTeNLe9jcoRyAtFeMsEB3/DANBgkqhkiG9w0BAQUFADCB
-tTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug
-YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDEvMC0GA1UEAxMm
-VmVyaVNpZ24gQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzMwHhcNMTQwOTA0
-MDAwMDAwWhcNMTYwOTA0MjM1OTU5WjCBsjELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
-B0dlb3JnaWExEDAOBgNVBAcUB0F0bGFudGExHzAdBgNVBAoUFkZpcnN0IERhdGEg
-Q29ycG9yYXRpb24xNjA0BgNVBAsULUZpcnN0IERhdGEgUkFTIChSZXRhaWwgYW5k
-IEFsbGlhbmNlIFNlcnZpY2VzKTEmMCQGA1UEAxQdZ2xvYmFsZ2F0ZXdheWU0LmZp
-cnN0ZGF0YS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCunuir
-5P0VQDraZ+iHqz1XItS2sEKCNoG23eWz1Xh87GSPYtrBgOXznNo079ruf48vY5da
-KKs6YhjMsOXhJrA0kGfsq3/0WPLZjlWzFdM/0NMdV/Z9iYzBPkrR6Hz64sNGBnEP
-BWYvpblmchtyUWhuy58W69VoufYUJMnmbBj1OxPufI97AXdoaoFapMYbaHKdqBJy
-2lLmqDalR7oYb4dnZvZY/arEAstLULCAn36X1O7/dKQQXxtmUkUS4XZj26pHEmIJ
-5ld4ERZJU67AnKimk5nXmlGWIJPpOo9Aw/0Lwx3BCDN4eC7hPiL+atgtLBKHxy1m
-HaWLSdXOLCvrqZKnAgMBAAGjggGXMIIBkzBJBgNVHREEQjBAgh8qLmdsb2JhbGdh
-dGV3YXlFNC5maXJzdGRhdGEuY29tgh1nbG9iYWxnYXRld2F5ZTQuZmlyc3RkYXRh
-LmNvbTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEF
-BQcDAQYIKwYBBQUHAwIwZQYDVR0gBF4wXDBaBgpghkgBhvhFAQc2MEwwIwYIKwYB
-BQUHAgEWF2h0dHBzOi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkaF2h0
-dHBzOi8vZC5zeW1jYi5jb20vcnBhMB8GA1UdIwQYMBaAFA1EXBZTRMGCfh0gqyX0
-AWPYvnmlMCsGA1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9zZC5zeW1jYi5jb20vc2Qu
-Y3JsMFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3NkLnN5bWNk
-LmNvbTAmBggrBgEFBQcwAoYaaHR0cDovL3NkLnN5bWNiLmNvbS9zZC5jcnQwDQYJ
-KoZIhvcNAQEFBQADggEBAEhlHPB7R1QwmpQPG1JzplryKqJ5fYZoPEiF3qfSoB+6
-cKJ8Xkhg7uga+/ZH55lErVIbWZjxIxtImAOYnQjm8uWiW8ElrbS42plUkNCk/tuU
-X7JcomwCaeE4dUrHF/pe9ao6SOh5KXCZGr0HyY64MOvdxOy6RXTsjDeabwI8CeNn
-LauoOg9Ey9hl2Dmv+iAY9ANtb+4nMLQoeH3HPfUpaeIUaCm500RKiEw3pjvWRpwV
-5HC7RoWa9tyK/7AvMNbXLfURmhO5/MJ9iUjrSdwJOfryscSSPPrGdrgeKTufn4qu
-n7W3DwNqap9Cog4hn7KZJXNaNA0qjB54UPEERcd0bTE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIF7DCCBNSgAwIBAgIQbsx6pacDIAm4zrz06VLUkTANBgkqhkiG9w0BAQUFADCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
-ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5IC0gRzUwHhcNMTAwMjA4MDAwMDAwWhcNMjAwMjA3MjM1OTU5WjCBtTEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
-ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQg
-aHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDEvMC0GA1UEAxMmVmVy
-aVNpZ24gQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzMwggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQCxh4QfwgxF9byrJZenraI+nLr2wTm4i8rCrFbG
-5btljkRPTc5v7QlK1K9OEJxoiy6Ve4mbE8riNDTB81vzSXtig0iBdNGIeGwCU/m8
-f0MmV1gzgzszChew0E6RJK2GfWQS3HRKNKEdCuqWHQsV/KNLO85jiND4LQyUhhDK
-tpo9yus3nABINYYpUHjoRWPNGUFP9ZXse5jUxHGzUL4os4+guVOc9cosI6n9FAbo
-GLSa6Dxugf3kzTU2s1HTaewSulZub5tXxYsU5w7HnO1KVGrJTcW/EbGuHGeBy0RV
-M5l/JJs/U0V/hhrzPPptf4H1uErT9YU3HLWm0AnkGHs4TvoPAgMBAAGjggHfMIIB
-2zA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnZlcmlz
-aWduLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMHAGA1UdIARpMGcwZQYLYIZIAYb4
-RQEHFwMwVjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL2Nw
-czAqBggrBgEFBQcCAjAeGhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMDQG
-A1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMtZzUu
-Y3JsMA4GA1UdDwEB/wQEAwIBBjBtBggrBgEFBQcBDARhMF+hXaBbMFkwVzBVFglp
-bWFnZS9naWYwITAfMAcGBSsOAwIaBBSP5dMahqyNjmvDz4Bq1EgYLHsZLjAlFiNo
-dHRwOi8vbG9nby52ZXJpc2lnbi5jb20vdnNsb2dvLmdpZjAoBgNVHREEITAfpB0w
-GzEZMBcGA1UEAxMQVmVyaVNpZ25NUEtJLTItNjAdBgNVHQ4EFgQUDURcFlNEwYJ+
-HSCrJfQBY9i+eaUwHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnzQzn6Aq8zMTMwDQYJ
-KoZIhvcNAQEFBQADggEBAAyDJO/dwwzZWJz+NrbrioBL0aP3nfPMU++CnqOh5pfB
-WJ11bOAdG0z60cEtBcDqbrIicFXZIDNAMwfCZYP6j0M3m+oOmmxw7vacgDvZN/R6
-bezQGH1JSsqZxxkoor7YdyT3hSaGbYcFQEFn0Sc67dxIHSLNCwuLvPSxe/20majp
-dirhGi2HbnTTiN0eIsbfFrYrghQKlFzyUOyvzv9iNw2tZdMGQVPtAhTItVgooazg
-W+yzf5VK+wPIrSbb5mZ4EkrZn0L74ZjmQoObj49nJOhhGbXdzbULJgWOw27EyHW4
-Rs/iGAZeqa6ogZpHFt4MKGwlJ7net4RYxh84HqTEy2Y=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIE0DCCBDmgAwIBAgIQJQzo4DBhLp8rifcFTXz4/TANBgkqhkiG9w0BAQUFADBf
-MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT
-LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
-HhcNMDYxMTA4MDAwMDAwWhcNMjExMTA3MjM1OTU5WjCByjELMAkGA1UEBhMCVVMx
-FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
-dCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZv
-ciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAz
-IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEi
-MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8
-RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbext0uz/o9+B1fs70Pb
-ZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhDY2pSS9KP6HBR
-TdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
-Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNH
-iDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMB
-AAGjggGbMIIBlzAPBgNVHRMBAf8EBTADAQH/MDEGA1UdHwQqMCgwJqAkoCKGIGh0
-dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMuY3JsMA4GA1UdDwEB/wQEAwIBBjA9
-BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVy
-aXNpZ24uY29tL2NwczAdBgNVHQ4EFgQUf9Nlp8Ld7LvwMAnzQzn6Aq8zMTMwbQYI
-KwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQU
-j+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29t
-L3ZzbG9nby5naWYwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8v
-b2NzcC52ZXJpc2lnbi5jb20wPgYDVR0lBDcwNQYIKwYBBQUHAwEGCCsGAQUFBwMC
-BggrBgEFBQcDAwYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEBBQUA
-A4GBABMC3fjohgDyWvj4IAxZiGIHzs73Tvm7WaGY5eE43U68ZhjTresY8g3JbT5K
-lCDDPLq9ZVTGr0SzEK0saz6r1we2uIFjxfleLuUqZ87NMwwq14lWAyMfs77oOghZ
-tOxFNfeKW/9mz1Cvxm1XjRl4t7mi0VfqH5pLr7rJjhJ+xr3/
------END CERTIFICATE-----
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.csr b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.csr
deleted file mode 100644
index b8f274fd092..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.csr
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN CERTIFICATE REQUEST-----
-MIIBezCCASECAQAwgYwxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
-MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
-bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMR0wGwYDVQQDExRjbG91ZGZsYXJl
-LWludGVyLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLgOKlWwIAIeURde
-yvDMhgfn6xPp1gn8oUeLmsniBm7I+j84IsVzUso8/MpjMZ9nB8lQUanhv3Kmqcyj
-HNj+iFegMjAwBgkqhkiG9w0BCQ4xIzAhMB8GA1UdEQQYMBaCFGNsb3VkZmxhcmUt
-aW50ZXIuY29tMAoGCCqGSM49BAMCA0gAMEUCIEJcy2mn2YyK8lVE+HHmr2OsmdbH
-4CLDVXFBwxke8ObqAiEAx/il1cDKvQ/I36b4XjBnOX2jcQ5oaCNPFFBE74WQ/ps=
------END CERTIFICATE REQUEST-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.key b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.key
deleted file mode 100644
index 156aec3c833..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.key
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEILbwI4u4bw+HtafMqFnrL7LOrqNEZH5rW5ygSrigfrVLoAoGCCqGSM49
-AwEHoUQDQgAEuA4qVbAgAh5RF17K8MyGB+frE+nWCfyhR4uayeIGbsj6PzgixXNS
-yjz8ymMxn2cHyVBRqeG/cqapzKMc2P6IVw==
------END EC PRIVATE KEY-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.pem
deleted file mode 100644
index c626d86606e..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L1-v2.pem
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICwzCCAi6gAwIBAgIIOdnmLRHpa9owCwYJKoZIhvcNAQEFMH0xCzAJBgNVBAYT
-AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv
-MRMwEQYDVQQKDApDbG91ZEZsYXJlMRQwEgYDVQQLDAtERVZfVEVTVElORzEWMBQG
-A1UEAwwNQ0ZTU0xfVEVTVF9DQTAeFw0xNDA1MjcxNzUzMjhaFw0xNTA1MjcxNzU4
-MjhaMIGMMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UE
-CxMTU3lzdGVtcyBFbmdpbmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzET
-MBEGA1UECBMKQ2FsaWZvcm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5j
-b20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4DipVsCACHlEXXsrwzIYH5+sT
-6dYJ/KFHi5rJ4gZuyPo/OCLFc1LKPPzKYzGfZwfJUFGp4b9ypqnMoxzY/ohXo4GG
-MIGDMA4GA1UdDwEB/wQEAwIApjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH
-AwIwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUwsdbMieQ99qPYmlsL5L8
-2HWQyakwHwYDVR0jBBgwFoAUuF7vrmdQt9bzB+VqvlWzZzoNkj4wCwYJKoZIhvcN
-AQEFA4GBAIyZZ7dPQsDKLR+ZwDXjSdsTws+9mZvqzfTb89LJ7H1pEoVI0x+MQncG
-zbsN713Vu2GCBHZilmfINsBbZYdaqqVTpqLtAFMce7aBiLrpcLHyegzTJIn+zzMa
-v5498Mo7S8NUOeGtTAPepExf9lOxiexynEkk5U+AF04nzspNOwTY
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-1.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-1.pem
deleted file mode 100644
index 3be24fa17d8..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-1.pem
+++ /dev/null
@@ -1,26 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEZTCCAk+gAwIBAgIIQTLl8XrmJF0wCwYJKoZIhvcNAQENMIGMMQswCQYDVQQG
-EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
-bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
-cm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwOTIzMTc1
-NTI4WhcNMTUwNTMxMTgwMDI4WjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNs
-b3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcT
-DVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHTAbBgNVBAMTFGNs
-b3VkZmxhcmUtaW50ZXIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEIVkjNJGw
-f3F0XWJH7yQSVtxuoBidi5JNsQ7FhxEQcZEl3b+/1iF60TBY2Yi6KwJuA6nIE73P
-IXGyfNhThw4D8CiZbackQ/ufgz2DyvxyWFDPzLr7TXeM/0wSp/imoxWeo3sweTAO
-BgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgw
-BgEB/wIBATAdBgNVHQ4EFgQUPd/cWIaY6MopIO6ldKx79dLpF1cwHwYDVR0jBBgw
-FoAU111IKWksDvRzq0AcRqjjkhR7BxAwCwYJKoZIhvcNAQENA4ICAQAz96PKFCed
-WSwOchAQszXDzaIcKSyyA1DQYEn5LvDTAcMgHg0KSb9bArv40ctwwvWQKwb9M4+M
-ax1+xmZi7Vg9wjad4Pz+UHDxf+rnEAFBuN6dneNpv1J9qxK1yf9GkMsl10CGeh0x
-AkHOut5rbb2hL0OrLOxhUK5M7pJf8zCMIirz9MHBDC+Xy4IKfEh8s4sKc2XRjnKv
-/H2tjcUL9AP8c7AA3GPoMuMVZSygI3SmH0gu+wQcR3KQCnetvObqNoI/DEv+45pI
-2B7CAf5FVhErqM9Gq2IuQQt9/7YosxL+wTvVNobKYmwP9NWFVtkJYpF1I63LtnaJ
-+MN9b/fVYDjI9IBKXFD10eec2CZkUEj13bWOgIN1gwyL6IzXPOaT/oax/TVlMIpI
-q3YnjMCEVS09sp2zAuLMYd97G8CMaRtGrtJM5V4rZ5l5u0w0So8FJac3pYugRm3V
-udpPNUBkR4FPMCMUGExJWNADooDXs31UxPQXMdcRai8Gb1mZQGyOhQQJgH1MsoYY
-f4OFvwvWsWlKL063Jc+a31fLs6LaH+4AVDyYgfBT5SyK9jQEr1q3HSGyzs7K48iP
-MEBWnfd2VOyoUdbENab5vZo5ewnj79xp7Qbcugduu2phs0oxp1737fS13BgdpDdQ
-9eueSTt1QsRE0SShMG5VqewfxQNk5BYrYg==
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-2.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-2.pem
deleted file mode 100644
index 71cd0cf03af..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-2.pem
+++ /dev/null
@@ -1,26 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEZTCCAk+gAwIBAgIIQkDSA6gKNdAwCwYJKoZIhvcNAQENMIGMMQswCQYDVQQG
-EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
-bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
-cm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwOTIzMTc1
-NjEwWhcNMTYwMTAyMTgwMTEwWjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNs
-b3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcT
-DVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHTAbBgNVBAMTFGNs
-b3VkZmxhcmUtaW50ZXIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEIVkjNJGw
-f3F0XWJH7yQSVtxuoBidi5JNsQ7FhxEQcZEl3b+/1iF60TBY2Yi6KwJuA6nIE73P
-IXGyfNhThw4D8CiZbackQ/ufgz2DyvxyWFDPzLr7TXeM/0wSp/imoxWeo3sweTAO
-BgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgw
-BgEB/wIBATAdBgNVHQ4EFgQUPd/cWIaY6MopIO6ldKx79dLpF1cwHwYDVR0jBBgw
-FoAU111IKWksDvRzq0AcRqjjkhR7BxAwCwYJKoZIhvcNAQENA4ICAQCi53nUiAaE
-aHSpCkebgcktFfDTTsY/7YCPFv0RxE08f+OMzndWpoS6dFYCxP1HetlYOh5a/3wm
-9zj2IL6rY7CXyI6x2RH97Sdc4ibjcIqHdUuaFmG+qwjtI8TGeOFvwrdwx6i610Mc
-cLqgc3gvtcLeqbMFkA0/js+viMg+bMTR+cEEIT3MHMq7byOzQa+koia9ZLAdiZsj
-IkWGTg5tkySnwyQztLRjWknZ1syujarcoJ9VY8uWipQNMzrs91ZaAwHmeSdODsbn
-Wvg7HZInbxCIzQz1/65FhdHzPbOv8MmQ1wlHqNNPYehXOgptsv9GN+DJlhiM62dp
-tTRJnc3URyP4xfkVWtYXxuGBdGXPaktsNFBb163QJtrajAe9FtBqsIEUDDuUjNB1
-rbw7xYUW5byiMPA1auHU3CHXg86LwU3TpE0d5hZriNCKzfLSpWJZa3WmQ0bc1ZLC
-1m3EhK0fDqGz+NbyP7eyJl1nUGwElbhbHaK1HpopxtGKKi1xbMTjpU2Ery8bUXcK
-EsUJWsxb8yU6BC25+ZWcHeuTaeSK+zlk/kvyMXgueslAoWUznmNhrLrTX3Ansjrf
-MT1eo/cy+OU5FJslmhV0lhMy2W/lsAUqTGugMP2x1lhUnKy3/17XULh8v6BfmddR
-XpQy1L6IceNMPfsKCvt5pg3urtpunV8ImQ==
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-3.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-3.pem
deleted file mode 100644
index 2ff7807435e..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-3.pem
+++ /dev/null
@@ -1,26 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEZTCCAk+gAwIBAgIIbHgGsniC/IUwCwYJKoZIhvcNAQENMIGMMQswCQYDVQQG
-EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
-bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
-cm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwOTIzMTc1
-NzE3WhcNMTYwNjAyMTgwMjE3WjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNs
-b3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcT
-DVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHTAbBgNVBAMTFGNs
-b3VkZmxhcmUtaW50ZXIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEIVkjNJGw
-f3F0XWJH7yQSVtxuoBidi5JNsQ7FhxEQcZEl3b+/1iF60TBY2Yi6KwJuA6nIE73P
-IXGyfNhThw4D8CiZbackQ/ufgz2DyvxyWFDPzLr7TXeM/0wSp/imoxWeo3sweTAO
-BgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgw
-BgEB/wIBATAdBgNVHQ4EFgQUPd/cWIaY6MopIO6ldKx79dLpF1cwHwYDVR0jBBgw
-FoAU111IKWksDvRzq0AcRqjjkhR7BxAwCwYJKoZIhvcNAQENA4ICAQDkbiOxZ4Pq
-y6TrubrmTwcRLLSDcXi8WeWv2AG6nAqZWAJXi/eUFggzNNgvAt4B/VH81YCkRN7R
-YAefVztVSRxffOFTEk8PDQ55pthTbCdnaeJL1dP7PGZ7Dg1djxSC9G2jJ38xFQY3
-5aM7BwbFcs5Iqd9MhbJIhrJfL22O5XpTTWzHGLOsS4H42If9qkTtajjMPwMbPUrZ
-jJj6bWyOqfuGKef/Orn72EV9fPwyrLoTg9TPlKqX9ghm7fvuc9UVcEbFOAVSV9lS
-3mEct1uwLBAEi/xhOlGN7jOn6q/w/0h2CI04FUe3/HB5rR0ffbqc2AdjO2R5uMgl
-9XQ+u4/kOE5hHha8cSNSyScRiWr3yrG+3TaX4qdKnVUdP0LcoKZBm7+JYqTqsW5U
-jr+sQmJrvWcEMx9Q5+5krDRhTWmyd4V27zgZ5T5Ilv3TC3zZ+VjJASKEHPFrClae
-PdwkBdhxJRaXhkku7slW9Dgw4E0/0el2iytODoikzwcdlQQwQhvAnbtrJOhsXX1b
-OpSQGfSZerAsuYSpiaNygF39HKxzgeZAEI5H+0R048Fcpysq8KVIET2B78zn0+mx
-nSNOBP3SDLMcvlXDALpD6svSzQKuoQ1gyZUZzrJanbNJgA1gg2dQyEs13xhS8Vuc
-Jtq40kpRnc9Pr3LNTL4Z95xMMqxYRBc3Xw==
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-4.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-4.pem
deleted file mode 100644
index d202e376381..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-4.pem
+++ /dev/null
@@ -1,26 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEZTCCAk+gAwIBAgIIfwUOgDbzUY4wCwYJKoZIhvcNAQENMIGMMQswCQYDVQQG
-EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
-bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
-cm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwOTIzMTc1
-NzM1WhcNMTcwMTAyMTgwMjM1WjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNs
-b3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcT
-DVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHTAbBgNVBAMTFGNs
-b3VkZmxhcmUtaW50ZXIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEIVkjNJGw
-f3F0XWJH7yQSVtxuoBidi5JNsQ7FhxEQcZEl3b+/1iF60TBY2Yi6KwJuA6nIE73P
-IXGyfNhThw4D8CiZbackQ/ufgz2DyvxyWFDPzLr7TXeM/0wSp/imoxWeo3sweTAO
-BgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgw
-BgEB/wIBATAdBgNVHQ4EFgQUPd/cWIaY6MopIO6ldKx79dLpF1cwHwYDVR0jBBgw
-FoAU111IKWksDvRzq0AcRqjjkhR7BxAwCwYJKoZIhvcNAQENA4ICAQAyTpWzbiOa
-cB6FIsfRCGpqKZiaNMeuaJr8RPDYgXMAU4pK0ymZfZPWcUDDsVLEt5Zz4fJBd4E1
-UzJ0GuuFswhGoICmYF397akwfOnXcbV+TBjdPPtsnsq71jRFlswdf6HkGqdQfMls
-x6JnkM9XXDlWqKoVV8sHhnfvDOD5xZv2nLhIwBzt3dnrkhAKAI9jncHuJWO0KaxW
-n8KhrAuoerQAz3+VM0y30siSAs4tBgmrKIc8AFh/S72VHUzBAnlc00LYE4M26/fQ
-28EJzy01F3uuHHyRn56uQ/miWT5ttPxdUneN4SzQV7oB3ij6W9+QIrK0/uDMhw7l
-NLk3nyj9V+XYbgynpgB2N92BK0MNYI9Jp0ULFgrAQaGadoo4XfDquQulWx8c7Zo+
-/qpcjnAVy317LjvWZbdGu/rBEU6j7rMOKqRcmjkm+7ESuLv6OOj4JVMtvSEdtpPL
-MK4mNAYa3O8qJMphjwokseF+9AfpBEJJzFFYiV7LyjFZlexSFOE1XZ1i0KaR7k+0
-RxbBxz9ciovhYgDr9db3jQqcU8UR8mIgxcpqmWFinNmZ0Sr0/pkXyZzZPUmH99bD
-vZEsmuFsEv1r+/7BAaPtWFnXwaacFkdEpVOKq5VJtNXMvAgYt7RJQobTDFFIMTaN
-j4NKTmOqq1CTnqNmxPZqAyDotTucUJAbRA==
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.csr b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.csr
deleted file mode 100644
index 232fa779831..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.csr
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE REQUEST-----
-MIIDCjCCAfQCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
-MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
-bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
-LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOLFLykOd2j31AQn
-kaToYtstGvw5wLb4YnlzipQ6aULlD0H0GHM9IwhdSmcTWUWPb/U83g/ma1uD3Pp2
-IdWd6xfjyOJF5XhgkyfRY65wS6vPZRm2MNSFXem+0AKHdhxIhb/QPMASqC/yaiPi
-nvtOpBiCNl1Q2N4y9pkV0oD/T4rrn3RXP6iL1k4CNRS54JPCd+aI5Om+axVPU8Id
-ZeUXQwXISaFrcC/bFXAHGX5hBMVu34lhCxvR4smweZkVmW++bIv26az8TSb5nVn4
-TstLJIaOoOqot0sis04+0oX/GXfTPfkWyzfTVFN7cb9H+gz0FZJKtXQZv6qdntji
-9FdR+pkCAwEAAaBAMD4GCSqGSIb3DQEJDjExMC8wLQYDVR0RBCYwJIIOY2xvdWRm
-bGFyZS5jb22CEnd3dy5jbG91ZGZsYXJlLmNvbTALBgkqhkiG9w0BAQsDggEBABfM
-9XTMqMqmfAAymWC4/W+vbh301KBoydcTnDQ/7B+ftHRE0O3FUsdL3wobj3qBieJo
-MiQwiL7+GksszHvN9+YOUi70wpFuKghLhadb7p5GzL0+JgK2eQnLYb37/lQSiWwn
-hht1YMOzErR/KHlxNUafk71bDEeytUcOvvtujf86nZiEnBpvp47zDjMkDersczM0
-wj7S50IY8/vRsc2Q8vy+Q7D2FPEwjs4wCGVSqzwX2NPn3fZb/2pWRCie9kxHUfUP
-L5xO4WoFGuirT6E2GnUWDdH661Pj5yEKvmr+qPl+eVoLjrtx0g5rAmA7rGlGrkqp
-r4idH/BbJUaDlRHM/Hk=
------END CERTIFICATE REQUEST-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.key b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.key
deleted file mode 100644
index 36ecabb1afd..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.key
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEA4sUvKQ53aPfUBCeRpOhi2y0a/DnAtvhieXOKlDppQuUPQfQY
-cz0jCF1KZxNZRY9v9TzeD+ZrW4Pc+nYh1Z3rF+PI4kXleGCTJ9FjrnBLq89lGbYw
-1IVd6b7QAod2HEiFv9A8wBKoL/JqI+Ke+06kGII2XVDY3jL2mRXSgP9PiuufdFc/
-qIvWTgI1FLngk8J35ojk6b5rFU9Twh1l5RdDBchJoWtwL9sVcAcZfmEExW7fiWEL
-G9HiybB5mRWZb75si/bprPxNJvmdWfhOy0skho6g6qi3SyKzTj7Shf8Zd9M9+RbL
-N9NUU3txv0f6DPQVkkq1dBm/qp2e2OL0V1H6mQIDAQABAoIBAQCzT3HcCAlZoeUu
-p88dU3efkUnuOQhuZXcQS9E/JfTHpXHsF8Qhky0ZVxMW8BC91Q6VHt0EO5GWWm0o
-SrK0Q9t6F25npRcumUaizIoCi9756tMpgouX8CDzTCMUbOJyuNGxe0oeImKFDyzo
-VTCazHMqwgOUw/HHuQqOv9ekkrzlva8U+Z5MGZB4B2acHIAJHO9uYGzdeAjF3grm
-dQ3QFGXJM0JzPmXfnUiDeOWIoVbo4YROFhf7qNlcnyLdkrYe0/XsSYQM9dRGKRPK
-nkOkMv0sC8rOqNuJUn3tf1OOjzVQxlzB8Key6MOQ1c+kqsdCnL88/93CvI5NHazx
-hwUmesmBAoGBAPpkDtgeWjxeIjOfuxXDYb04XbVmKquKNOIEk5OADmaacSGzdemh
-XLRaNVMEYMcgMJViDDKW8g4k+zuZgzooMxNynlLNU5wfazwX2LLjReJFvZb/SxMM
-N9+vQo8fcGz+p5g1tbeE6w86mpsTiAGx9Wa4J4GnY8jF6XUjZHO0X91pAoGBAOfZ
-qrDkPMDSiVk62FP6LlPrj09bt1NTkBfv5dWhN/XeHjuus7unDhNiRmphhgF0VZse
-XPtT/PUO0YgYlyaYJDDDE0IxgHuoK9wvEb2sqEtkZSw7IUhehheZ/+YfXzSA5fwa
-vhXt0ghB0d9oVJuRoxb17MncjpjDAKy0QR5drR2xAoGBAMlNwkVseZ2JDLQ2WgHQ
-N/cZpvUc83dAQO3pQgBW9rz0s7mlf0naqh5xW+enYGsW7RhcYHQXuPk4MCelbsRF
-53JeNv1ZCDw/YkZI4bZIVDnrWdZY3zGsJAuY6skIPKnUPkd3/uVRXm267ut4U2MR
-gLsZmOF7AxU6UEwVrT/8pwnpAoGAKxbVFlMUx3FZfW/mTJUujwI0fDc7dw0MtqYr
-POzdjaBeVhE97h46C3g0Rgkh8ptAXbfi6ALP/GtonbaUQOP9teJLbf3tNw4mOKG2
-1l2EWZ6q/vFuWhjXKwO//3DNLODX3WbK9SBh7I7vBmpJbzA980J5Y3rONa3oLjDB
-+XbHecECgYEArOEv2D3fE3Hd6rEbxXinqekxMa+V1OCDO1IPz4wwr9RDMVUMxwqF
-f0es1PQ2eMJGrAMbySxPfSZG05ou/tA+zR0qPwc/+dX0BbaXCiNT3gbhvL1L2fBc
-7wr+MIUe2fi54JUWrUNMDHngRhXRKt2rZZRTfqVaFmZX02Y3fMZ2dWg=
------END RSA PRIVATE KEY-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.pem
deleted file mode 100644
index 3b632524033..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/inter-L2-v2.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDXDCCAwKgAwIBAgIIfTkIXBckiQ4wCgYIKoZIzj0EAwIwgYwxCzAJBgNVBAYT
-AlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJlMRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2lu
-ZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9y
-bmlhMR0wGwYDVQQDExRjbG91ZGZsYXJlLWludGVyLmNvbTAeFw0xNDA1MjcxNzU1
-MjZaFw0xNTA1MjcxODAwMjZaMIGGMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQ2xv
-dWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdpbmVlcmluZzEWMBQGA1UEBxMN
-U2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZvcm5pYTEXMBUGA1UEAxMOY2xv
-dWRmbGFyZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDixS8p
-Dndo99QEJ5Gk6GLbLRr8OcC2+GJ5c4qUOmlC5Q9B9BhzPSMIXUpnE1lFj2/1PN4P
-5mtbg9z6diHVnesX48jiReV4YJMn0WOucEurz2UZtjDUhV3pvtACh3YcSIW/0DzA
-Eqgv8moj4p77TqQYgjZdUNjeMvaZFdKA/0+K6590Vz+oi9ZOAjUUueCTwnfmiOTp
-vmsVT1PCHWXlF0MFyEmha3Av2xVwBxl+YQTFbt+JYQsb0eLJsHmZFZlvvmyL9ums
-/E0m+Z1Z+E7LSySGjqDqqLdLIrNOPtKF/xl30z35Fss301RTe3G/R/oM9BWSSrV0
-Gb+qnZ7Y4vRXUfqZAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgCmMB0GA1UdJQQW
-MBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1Ud
-DgQWBBR9vuLqsiu6H1S6qG9JmUSh687mqDAfBgNVHSMEGDAWgBTCx1syJ5D32o9i
-aWwvkvzYdZDJqTAKBggqhkjOPQQDAgNIADBFAiA1sNmHjK4MF0USUIYiCBINpG3b
-G8zRSWc5mEwCVCCGGQIhAPuTm12Hnmc6PUMmS12uQoz+UpQ536lYpHqLoe/yZHDk
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/lazada.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/lazada.pem
deleted file mode 100644
index 7afddd7c8eb..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/lazada.pem
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFMzCCBBugAwIBAgIDESgIMA0GCSqGSIb3DQEBCwUAMDwxCzAJBgNVBAYTAlVT
-MRcwFQYDVQQKEw5HZW9UcnVzdCwgSW5jLjEUMBIGA1UEAxMLUmFwaWRTU0wgQ0Ew
-HhcNMTQwMzA5MDcwODA2WhcNMTUwNDEwMTkwODU3WjCBvjEpMCcGA1UEBRMgOWRp
-eGpNZTVGQS9Fd0pjMWxhM01IQ1JBOTNnTFZobkoxEzARBgNVBAsTCkdUODM1NTg5
-ODAxMTAvBgNVBAsTKFNlZSB3d3cucmFwaWRzc2wuY29tL3Jlc291cmNlcy9jcHMg
-KGMpMTQxLzAtBgNVBAsTJkRvbWFpbiBDb250cm9sIFZhbGlkYXRlZCAtIFJhcGlk
-U1NMKFIpMRgwFgYDVQQDDA8qLmxhemFkYS5jb20ucGgwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQDKlGxmI33lQbcQHI5Fhf6EQGoqVVmHYRU5whipFg5g
-BButLAPj8TTDgD6a1iKPDsnQvNZnVjKLnjAu8c/lwwF7GevfuAS/SXasmKiONJ1b
-w+/MPWia/j++AoGIwKJe6py6r9INy3rTFrwuzSemzTnAja/VYtMPiAR/tAIK8FmU
-JZpop8JvGMr0KpmCBrJ4/HxFQwlmJjjSuvronNtN3h10vX1vNXCyobwaL2UplY8c
-0QZv6PdS8gzdki4H5AwOSnzJiY6RJPH6qR9dotQFYvSEHwUACHp7AOKkhdtO/+fG
-rd0+0vXLznyhIGZjT+T8at1H3/1udBhUkoAc76Xlqu3FAgMBAAGjggG5MIIBtTAf
-BgNVHSMEGDAWgBRraT1qGEJK3Y8CZTn9NSSGeJEWMDAOBgNVHQ8BAf8EBAMCBaAw
-HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCkGA1UdEQQiMCCCDyoubGF6
-YWRhLmNvbS5waIINbGF6YWRhLmNvbS5waDBDBgNVHR8EPDA6MDigNqA0hjJodHRw
-Oi8vcmFwaWRzc2wtY3JsLmdlb3RydXN0LmNvbS9jcmxzL3JhcGlkc3NsLmNybDAd
-BgNVHQ4EFgQUWh9QqoLYcrJ8u85o7CXAemGUtKQwDAYDVR0TAQH/BAIwADB4Bggr
-BgEFBQcBAQRsMGowLQYIKwYBBQUHMAGGIWh0dHA6Ly9yYXBpZHNzbC1vY3NwLmdl
-b3RydXN0LmNvbTA5BggrBgEFBQcwAoYtaHR0cDovL3JhcGlkc3NsLWFpYS5nZW90
-cnVzdC5jb20vcmFwaWRzc2wuY3J0MEwGA1UdIARFMEMwQQYKYIZIAYb4RQEHNjAz
-MDEGCCsGAQUFBwIBFiVodHRwOi8vd3d3Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMv
-Y3BzMA0GCSqGSIb3DQEBCwUAA4IBAQA8NsDVERjLyQ8CjsF4IcE9jNjr0ryXMV2E
-qLu27SAAp+walxOlf8RbZbwO7NxjiJi6Lubu0GOEVIrzqTzGta131dkKwmxVpSVq
-LcOpHHqmQTv0WDYKjhNc5PhjhfpjLnK5xjhJsd6us/FT/VYaeeq9XEnjCTc9JME8
-DUWnE0DK+14pOgH/KAzIpQCUGRaWOZgXbFkptIhgKikqOd/otKBHy/JNvqOk9ugJ
-zz+O5ZMBUZq3h7rDIjt/o+l4mv+f2DG1eiugOXLIukpMeK+ixM5b8uuprXqEK7oG
-qTal86QTe9+E/2KbOO+jUmh5JNsQmkYZKm4foM7pk4bHXPWxUco5
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/riot.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/riot.pem
deleted file mode 100644
index c6f31f5de86..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/riot.pem
+++ /dev/null
@@ -1,45 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIH5TCCBs2gAwIBAgIQBVtqmc8x2tl8Fe1v9s7UoDANBgkqhkiG9w0BAQsFADBw
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
-dXJhbmNlIFNlcnZlciBDQTAeFw0xMzEyMzEwMDAwMDBaFw0xNzAxMDQxMjAwMDBa
-MHcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRUwEwYDVQQHEwxT
-YW50YSBNb25pY2ExGTAXBgNVBAoTEFJpb3QgR2FtZXMsIEluYy4xITAfBgNVBAMT
-GGxxLm5hMS5sb2wucmlvdGdhbWVzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAKpicFUVqYz1ArARQ5LoncPu14OhxYq9dYUJvm9tdKCdig7KQYDa
-4SDo8cMiWPuxr3DB48ZeIOpZtF9VplDhdDGMnbifO8ohCiAuCITnP+ft+dLdcTeB
-AW5M5l2MaLxj/vdCRzENPa7KbzS0jnd5WBIkwsgkh8E4OSrTkIfNK+kQiBMz+9Td
-EHJagUvZ9vfTu0aSXx7+9bw/rDxCylWDbevYNBiBFMfgclhrW6NLlXBhbmRzxeY+
-lOScZdJkKoMGFXVaXsHh6BILdIypedCNrURBKWzFoke3y9dU8IPqgfdkvhm1aQXv
-EdLo/gh+GMbaYK5ZFBYhneX/MQIqMNpoBZcCAwEAAaOCBHIwggRuMB8GA1UdIwQY
-MBaAFFFo/5CvAgd1PMzZZWRiohK4WXI7MB0GA1UdDgQWBBQXUcvgDtxEapXyIy30
-2IYF6jYhvjCCASgGA1UdEQSCAR8wggEbghhscS5uYTEubG9sLnJpb3RnYW1lcy5j
-b22CF2xxLmV1LmxvbC5yaW90Z2FtZXMuY29tghlscS5ldW4xLmxvbC5yaW90Z2Ft
-ZXMuY29tghdscS5rci5sb2wucmlvdGdhbWVzLmNvbYIXbHEuYnIubG9sLnJpb3Rn
-YW1lcy5jb22CF2xxLnRyLmxvbC5yaW90Z2FtZXMuY29tghdscS5ydS5sb2wucmlv
-dGdhbWVzLmNvbYIYbHEub2MxLmxvbC5yaW90Z2FtZXMuY29tghhscS5sYTEubG9s
-LnJpb3RnYW1lcy5jb22CGGxxLmxhMi5sb2wucmlvdGdhbWVzLmNvbYIZbHEucGJl
-MS5sb2wucmlvdGdhbWVzLmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI
-KwYBBQUHAwEGCCsGAQUFBwMCMHUGA1UdHwRuMGwwNKAyoDCGLmh0dHA6Ly9jcmwz
-LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMS5jcmwwNKAyoDCGLmh0dHA6
-Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMS5jcmwwggHEBgNV
-HSAEggG7MIIBtzCCAbMGCWCGSAGG/WwBATCCAaQwOgYIKwYBBQUHAgEWLmh0dHA6
-Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggr
-BgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAA
-QwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAA
-YQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUA
-cgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4A
-ZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAA
-bABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAA
-aQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIA
-ZQBmAGUAcgBlAG4AYwBlAC4wgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYY
-aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2Fj
-ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZl
-ckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBzj+qBxGES
-JBeOuJo2rc2xT8ezNT2l+Kg/NjSr65t/U+u6xMELufGF/fqWPzsfHT3CXHMiAW2P
-lVHejbaePfkeNxHbkaLa15X3+dGOXR04a2QTI4zdexTZ9Xsx8chQZA4bEradIVl+
-o2y+MPN+6Hr1g2M2aw2d+1xxvVQcNe2iQDfUWSRd70wt8DXnpqFCumlCwZfYojpk
-NQ/ahCg3AKu/3gQPgjyXB7HUf14M8x6PwNw4IK0LCC99HaqQID/V4jVw47beJ6FC
-7+dW9nkrZBRgIHnqah90El+75oqwAmW8rewmTOKAXxRafGK6WreAZ0x9qfbBXFiH
-VRL8HkH3gqBT
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/sgizmo.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/sgizmo.pem
deleted file mode 100644
index bbf0aedfb82..00000000000
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler/testdata/sgizmo.pem
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFLzCCBBegAwIBAgIHBJgUJzNPaDANBgkqhkiG9w0BAQsFADCBtDELMAkGA1UE
-BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
-BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMS0wKwYDVQQLEyRodHRwOi8vY2VydHMu
-Z29kYWRkeS5jb20vcmVwb3NpdG9yeS8xMzAxBgNVBAMTKkdvIERhZGR5IFNlY3Vy
-ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjAeFw0xNDA0MDkxNjIyMDlaFw0x
-NDEyMDQxNjU4NTVaMD8xITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl
-ZDEaMBgGA1UEAwwRKi5zdXJ2ZXlnaXptby5jb20wggEiMA0GCSqGSIb3DQEBAQUA
-A4IBDwAwggEKAoIBAQC+U1kaSViTxGfD5U5krfafN9+4jSq51CNnTZJY1CTJjihb
-ym8n1ZNVrrCvivcGHT0BMHzDLVnQ2VLcac1F7TkjT5OCL5neSGLS6fnjoR5lPIvU
-KZfG94hPAMXXjqc3/cpDEenQv2JaNDL6r/f4fNzGalqSf5IkPvg0GxX2knWhjwTG
-f8cO+z08fKKKGt0tDt5/Dx6rxuqLxSg/eQhTU/QUUObuMeQCXtGfbC4n/sQJz0O5
-It5+EofG+KYb4gxJf/aScJv1PRSlSy9wYw6TJoUEn905VsFMH/mJuThzw5H976Vn
-Vchh5fUJItlU5T2kVRAnuLF0dI3unl+fx5h+cEXPAgMBAAGjggG4MIIBtDAPBgNV
-HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV
-HQ8BAf8EBAMCBaAwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nb2RhZGR5
-LmNvbS9nZGlnMnMxLTM4LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkw
-NwYIKwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVw
-b3NpdG9yeS8wdgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
-cC5nb2RhZGR5LmNvbS8wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jZXJ0aWZpY2F0ZXMu
-Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZGlnMi5jcnQwHwYDVR0jBBgwFoAUQMK9
-J47MNIMwojPX+2yz8LQsgM4wLQYDVR0RBCYwJIIRKi5zdXJ2ZXlnaXptby5jb22C
-D3N1cnZleWdpem1vLmNvbTAdBgNVHQ4EFgQUogJIgFe3mwaqFPDUiPyEd+JcDi0w
-DQYJKoZIhvcNAQELBQADggEBAF+Lu4aZ7JJmxHUY7w+fAxH8iBdMH5zwyjDWEFmP
-quUuoy7G+1V5cFecKbXk9iYUgazygDETa2UP8wBWTS6V2RYL/PsF9+HdwOX0e9QA
-JxZQ0ry9MZU72H1ZeIDRYGHqKOLMqkLIsbpSyDD6GyRNzLvZx7MiwDJ8Ou5wAT/6
-is5Sga9DZ/ffXbg79Ku0yalDwQfimHDAHRQhoYdCf6QhDog+RiNfSdJsU2NofiFu
-f920or/2t9t9egCzXQHi3iPC979+eII0YAxnnHEQkndUvSoihVn625wqHetXpcz3
-zkQ5F7NVrR/giUHmVE6rpy4uuQ16cwBgMqoTzDBQ/0rs6lo=
------END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/bundle/bundle.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/bundle/bundle.go
index 1f5e8affaf1..c177f171c9b 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/bundle/bundle.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/bundle/bundle.go
@@ -1,3 +1,4 @@
+// Package bundle implements the bundle command.
package bundle
import (
@@ -9,23 +10,24 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity"
)
-var bundlerUsageText = // Usage text of 'cfssl bundle'
-`cfssl bundle -- create a certificate bundle that contains the client cert
+// Usage text of 'cfssl bundle'
+var bundlerUsageText = `cfssl bundle -- create a certificate bundle that contains the client cert
Usage of bundle:
- Bundle local certificate files
- cfssl bundle -cert file [-ca-bundle file] [-int-bundle file] [-metadata file] [-key keyfile] [-flavor optimal|ubiquitous|force]
+ cfssl bundle -cert file [-ca-bundle file] [-int-bundle file] [-int-dir dir] [-metadata file] [-key keyfile] [-flavor optimal|ubiquitous|force] [-password password]
- Bundle certificate from remote server.
- cfssl bundle -domain domain_name [-ip ip_address] [-ca-bundle file] [-int-bundle file] [-metadata file]
+ cfssl bundle -domain domain_name [-ip ip_address] [-ca-bundle file] [-int-bundle file] [-int-dir dir] [-metadata file]
Flags:
`
// flags used by 'cfssl bundle'
-var bundlerFlags = []string{"cert", "key", "ca-bundle", "int-bundle", "flavor", "metadata", "domain", "ip"}
+var bundlerFlags = []string{"cert", "key", "ca-bundle", "int-bundle", "flavor", "int-dir", "metadata", "domain", "ip", "password"}
// bundlerMain is the main CLI of bundler functionality.
func bundlerMain(args []string, c cli.Config) (err error) {
+ bundler.IntermediateStash = c.IntDir
ubiquity.LoadPlatforms(c.Metadata)
flavor := bundler.BundleFlavor(c.Flavor)
// Initialize a bundler with CA bundle and intermediate bundle.
@@ -48,13 +50,13 @@ func bundlerMain(args []string, c cli.Config) (err error) {
return
}
}
- bundle, err = b.BundleFromPEM(certPEM, keyPEM, flavor)
+ bundle, err = b.BundleFromPEMorDER(certPEM, keyPEM, flavor, "")
if err != nil {
return
}
} else {
// Bundle the client cert
- bundle, err = b.BundleFromFile(c.CertFile, c.KeyFile, flavor)
+ bundle, err = b.BundleFromFile(c.CertFile, c.KeyFile, flavor, c.Password)
if err != nil {
return
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli.go
index e5b00deebc4..052b41dafd6 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli.go
@@ -1,3 +1,4 @@
+// Package cli provides the template for adding new cfssl commands
package cli
/*
@@ -84,16 +85,19 @@ func Start(cmds map[string]*Command) {
registerFlags(&c, cfsslFlagSet)
// Initial parse of command line arguments. By convention, only -h/-help is supported.
- flag.Parse()
if flag.Usage == nil {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, usage)
for name := range cmds {
- fmt.Fprintf(os.Stderr, "%s\n", name)
+ fmt.Fprintf(os.Stderr, "\t%s\n", name)
}
+ fmt.Fprintf(os.Stderr, "Top-level flags:\n")
+ flag.PrintDefaults()
}
}
+ flag.Parse()
+
if flag.NArg() < 1 {
fmt.Fprintf(os.Stderr, "No command is given.\n")
flag.Usage()
@@ -112,7 +116,7 @@ func Start(cmds map[string]*Command) {
// The usage of each individual command is re-written to mention
// flags defined and referenced only in that command.
cfsslFlagSet.Usage = func() {
- fmt.Fprintf(os.Stderr, "%s", cmd.UsageText)
+ fmt.Fprintf(os.Stderr, "\t%s", cmd.UsageText)
for _, name := range cmd.Flags {
if f := cfsslFlagSet.Lookup(name); f != nil {
printDefaultValue(f)
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli_test.go
index 9114c31d7b0..9619580fbfa 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/cli_test.go
@@ -8,6 +8,11 @@ import (
var cfsslFlagSet = flag.NewFlagSet("cfssl", flag.ExitOnError)
+// The testing style from this package is borrowed from the Go flag
+// library's methodology for testing this. We set flag.Usage to nil,
+// then replace it with a closure to ensure the usage function was
+// called appropriately.
+
// 'cfssl -help' should be supported.
func TestHelp(t *testing.T) {
called := false
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/config.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/config.go
index 8d951b20d48..882d3096e10 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/config.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/config.go
@@ -22,6 +22,7 @@ type Config struct {
IntBundleFile string
Address string
Port int
+ Password string
ConfigFile string
CFG *config.Config
Profile string
@@ -46,6 +47,9 @@ type Config struct {
List bool
Family string
Scanner string
+ Responses string
+ Path string
+ UseLocal bool
}
// registerFlags defines all cfssl command flags and associates their values with variables.
@@ -80,6 +84,10 @@ func registerFlags(c *Config, f *flag.FlagSet) {
f.BoolVar(&c.List, "list", false, "list possible scanners")
f.StringVar(&c.Family, "family", "", "scanner family regular expression")
f.StringVar(&c.Scanner, "scanner", "", "scanner regular expression")
+ f.StringVar(&c.Responses, "responses", "", "file to load OCSP responses from")
+ f.StringVar(&c.Path, "path", "/", "Path on which the server will listen")
+ f.StringVar(&c.Password, "password", "", "Password for accessing PKCS #12 data passed to bundler")
+ f.BoolVar(&c.UseLocal, "uselocal", false, "serve local static files as opposed to compiled ones")
if pkcs11.Enabled {
f.StringVar(&c.Module, "pkcs11-module", "", "PKCS #11 module")
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/gencert/gencert.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/gencert/gencert.go
index 3d2d4a82488..1ee43d84057 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/gencert/gencert.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/gencert/gencert.go
@@ -1,3 +1,4 @@
+// Package gencert implements the gencert command.
package gencert
import (
@@ -52,7 +53,7 @@ func gencertMain(args []string, c cli.Config) (err error) {
if err != nil {
log.Errorf("%v\n", err)
log.Infof("generating a new CA key and certificate from CSR")
- cert, key, err = initca.New(&req)
+ cert, _, key, err = initca.New(&req)
if err != nil {
return
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey.go
index 10060a4dc77..4bee7da4937 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey.go
@@ -1,3 +1,4 @@
+// Package genkey implements the genkey command.
package genkey
import (
@@ -41,13 +42,13 @@ func genkeyMain(args []string, c cli.Config) (err error) {
}
if c.IsCA {
- var key, cert []byte
- cert, key, err = initca.New(&req)
+ var key, csrPEM, cert []byte
+ cert, csrPEM, key, err = initca.New(&req)
if err != nil {
return
}
- cli.PrintCert(key, nil, cert)
+ cli.PrintCert(key, csrPEM, cert)
} else {
if req.CA != nil {
err = errors.New("ca section only permitted in initca")
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey_test.go
index 5bc1f3fd0e6..bbdde7e5f20 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey/genkey_test.go
@@ -1 +1,50 @@
package genkey
+
+import (
+ "encoding/json"
+ "os"
+ "os/exec"
+ "path"
+ "testing"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli"
+)
+
+func TestGenkey(t *testing.T) {
+ //testing through console
+ gopath := os.Getenv("GOPATH")
+ cfssl := path.Join(gopath, "bin", "cfssl")
+ testdata := path.Join(gopath, "src", "github.com", "cloudflare", "cfssl", "testdata")
+
+ out, err := exec.Command(cfssl, "genkey", path.Join(testdata, "csr.json")).Output()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var response map[string]interface{}
+ err = json.Unmarshal(out, &response)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if response["key"] == nil {
+ t.Fatal("No key is outputted.")
+ }
+ if response["csr"] == nil {
+ t.Fatal("No csr is outputted.")
+ }
+
+ c := cli.Config{}
+
+ err = genkeyMain([]string{path.Join(testdata, "csr.json")}, c)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ c.IsCA = true
+
+ err = genkeyMain([]string{path.Join(testdata, "csr.json")}, c)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/info/info.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/info/info.go
new file mode 100644
index 00000000000..b63b49410ec
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/info/info.go
@@ -0,0 +1,103 @@
+// Package info implements the info command.
+package info
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/sign"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/info"
+
+ goerr "errors"
+)
+
+var infoUsageTxt = `cfssl info -- get info about a remote signer
+
+Usage:
+
+Get info about a remote signer:
+cfssl info -remote remote_host [-label label] [-profile profile] [-label label]
+
+Flags:
+`
+
+var infoFlags = []string{"remote", "label", "profile", "config"}
+
+func getInfoFromRemote(c cli.Config) (resp *info.Resp, err error) {
+ req := new(info.Req)
+ req.Label = c.Label
+ req.Profile = c.Profile
+
+ serv := client.NewServer(c.Remote)
+
+ reqJSON, _ := json.Marshal(req)
+ resp, err = serv.Info(reqJSON)
+ if err != nil {
+ return
+ }
+
+ _, err = helpers.ParseCertificatePEM([]byte(resp.Certificate))
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+func getInfoFromConfig(c cli.Config) (resp *info.Resp, err error) {
+ s, err := sign.SignerFromConfig(c)
+ if err != nil {
+ return
+ }
+
+ req := new(info.Req)
+ req.Label = c.Label
+ req.Profile = c.Profile
+
+ resp, err = s.Info(*req)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+func infoMain(args []string, c cli.Config) (err error) {
+ if len(args) > 0 {
+ return goerr.New("argument is provided but not defined; please refer to the usage by flag -h.")
+ }
+
+ var resp *info.Resp
+
+ if c.Remote != "" {
+ resp, err = getInfoFromRemote(c)
+ if err != nil {
+ return
+ }
+ } else if c.CFG != nil {
+ resp, err = getInfoFromConfig(c)
+ if err != nil {
+ return
+ }
+ } else {
+ return goerr.New("Either -remote or -config must be given. Refer to cfssl info -h for usage.")
+ }
+
+ respJSON, err := json.Marshal(resp)
+ if err != nil {
+ return errors.NewBadRequest(err)
+ }
+ fmt.Print(string(respJSON))
+ return nil
+}
+
+// Command defines the commmand-line procedure for info
+var Command = &cli.Command{
+ UsageText: infoUsageTxt,
+ Flags: infoFlags,
+ Main: infoMain,
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspserve/oscpserve.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspserve/oscpserve.go
new file mode 100644
index 00000000000..c9060738c90
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspserve/oscpserve.go
@@ -0,0 +1,52 @@
+// Package ocspserve implements the oscpserve function.
+package ocspserve
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
+)
+
+// Usage text of 'cfssl serve'
+var ocspServerUsageText = `cfssl ocspserve -- set up an HTTP server that handles OCSP requests from a file (see RFC 5019)
+
+ Usage of ocspserve:
+ cfssl ocspserve [-address address] [-port port] [-responses file]
+
+ Flags:
+ `
+
+// Flags used by 'cfssl serve'
+var ocspServerFlags = []string{"address", "port", "responses"}
+
+// ocspServerMain is the command line entry point to the OCSP responder.
+// It sets up a new HTTP server that responds to OCSP requests.
+func ocspServerMain(args []string, c cli.Config) error {
+ // serve doesn't support arguments.
+ if len(args) > 0 {
+ return errors.New("argument is provided but not defined; please refer to the usage by flag -h")
+ }
+
+ if c.Responses == "" {
+ return errors.New("no response file provided, please set the -responses flag")
+ }
+
+ src, err := ocsp.NewSourceFromFile(c.Responses)
+ if err != nil {
+ return errors.New("unable to read response file")
+ }
+
+ log.Info("Registering OCSP responder handler")
+ http.Handle(c.Path, ocsp.Responder{Source: src})
+
+ addr := fmt.Sprintf("%s:%d", c.Address, c.Port)
+ log.Info("Now listening on ", addr)
+ return http.ListenAndServe(addr, nil)
+}
+
+// CLIServer assembles the definition of Command 'serve'
+var Command = &cli.Command{UsageText: ocspServerUsageText, Flags: ocspServerFlags, Main: ocspServerMain}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspsign/ocspsign.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspsign/ocspsign.go
index 38a07df13c3..ee7fd8658e2 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspsign/ocspsign.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspsign/ocspsign.go
@@ -1,3 +1,4 @@
+// Package ocspsign implements the ocspsign command.
package ocspsign
import (
@@ -10,8 +11,8 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
)
-var ocspSignerUsageText = // Usage text of 'cfssl ocspsign'
-`cfssl ocspsign -- signs an OCSP response for a given CA, cert, and status"
+// Usage text of 'cfssl ocspsign'
+var ocspSignerUsageText = `cfssl ocspsign -- signs an OCSP response for a given CA, cert, and status"
Usage of ocspsign:
cfssl ocspsign -ca cert -responder cert -key key -cert cert [-reason code]
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/scan/scan.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/scan/scan.go
index 64b3595a5f5..8c4e5bde3a3 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/scan/scan.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/scan/scan.go
@@ -1,3 +1,4 @@
+// Package scan implements the scan CLI.
package scan
import (
@@ -21,7 +22,7 @@ var scanFlags = []string{"list", "family", "scanner"}
func printJSON(v interface{}) {
b, _ := json.MarshalIndent(v, "", " ")
- fmt.Printf("%s\n", b)
+ fmt.Printf("%s\n\n", b)
}
func scanMain(args []string, c cli.Config) (err error) {
@@ -36,6 +37,8 @@ func scanMain(args []string, c cli.Config) (err error) {
return
}
+ fmt.Printf("Scanning %s...\n", host)
+
var results map[string]scan.FamilyResult
results, err = scan.Default.RunScans(host, c.Family, c.Scanner)
if err != nil {
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/selfsign/selfsign.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/selfsign/selfsign.go
index 14ef2e455cd..8b43ae05bd5 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/selfsign/selfsign.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/selfsign/selfsign.go
@@ -1,3 +1,4 @@
+// Package selfsign implements the selfsign command.
package selfsign
import (
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/serve.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/serve.go
index 4bf211b0351..005cc19ebc1 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/serve.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/serve.go
@@ -1,3 +1,4 @@
+// Package serve implements the serve command for CFSSL's API.
package serve
import (
@@ -18,19 +19,19 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity"
)
-var serverUsageText = // Usage text of 'cfssl serve'
-`cfssl serve -- set up a HTTP server handles CF SSL requests
+// Usage text of 'cfssl serve'
+var serverUsageText = `cfssl serve -- set up a HTTP server handles CF SSL requests
Usage of serve:
cfssl serve [-address address] [-ca cert] [-ca-bundle bundle] \
- [-ca-key key] [-int-bundle bundle] [-port port] [-metadata file] \
- [-remote remote_host] [-config config]
+ [-ca-key key] [-int-bundle bundle] [-int-dir dir] [-port port] \
+ [-metadata file] [-remote remote_host] [-config config] [-uselocal]
Flags:
`
// Flags used by 'cfssl serve'
-var serverFlags = []string{"address", "port", "ca", "ca-key", "ca-bundle", "int-bundle", "int-dir", "metadata", "remote", "config"}
+var serverFlags = []string{"address", "port", "ca", "ca-key", "ca-bundle", "int-bundle", "int-dir", "metadata", "remote", "config", "uselocal"}
// registerHandlers instantiates various handlers and associate them to corresponding endpoints.
func registerHandlers(c cli.Config) error {
@@ -95,6 +96,9 @@ func registerHandlers(c cli.Config) error {
log.Info("Setting up scaninfo endpoint")
http.Handle("/api/v1/cfssl/scaninfo", scan.NewInfoHandler())
+ log.Info("Setting up static endpoints")
+ http.Handle("/", http.FileServer(FS(c.UseLocal)))
+
log.Info("Handler set up complete.")
return nil
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static.go
new file mode 100644
index 00000000000..1453c1322dc
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static.go
@@ -0,0 +1,201 @@
+package serve
+
+import (
+ "bytes"
+ "compress/gzip"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path"
+ "sync"
+ "time"
+)
+
+type escLocalFS struct{}
+
+var escLocal escLocalFS
+
+type escStaticFS struct{}
+
+var escStatic escStaticFS
+
+type escFile struct {
+ compressed string
+ size int64
+ local string
+ isDir bool
+
+ data []byte
+ once sync.Once
+ name string
+}
+
+func (escLocalFS) Open(name string) (http.File, error) {
+ f, present := escData[path.Clean(name)]
+ if !present {
+ return nil, os.ErrNotExist
+ }
+ return os.Open(f.local)
+}
+
+func (escStaticFS) prepare(name string) (*escFile, error) {
+ f, present := escData[path.Clean(name)]
+ if !present {
+ return nil, os.ErrNotExist
+ }
+ var err error
+ f.once.Do(func() {
+ f.name = path.Base(name)
+ if f.size == 0 {
+ return
+ }
+ var gr *gzip.Reader
+ gr, err = gzip.NewReader(bytes.NewBufferString(f.compressed))
+ if err != nil {
+ return
+ }
+ f.data, err = ioutil.ReadAll(gr)
+ })
+ if err != nil {
+ return nil, err
+ }
+ return f, nil
+}
+
+func (fs escStaticFS) Open(name string) (http.File, error) {
+ f, err := fs.prepare(name)
+ if err != nil {
+ return nil, err
+ }
+ return f.File()
+}
+
+func (f *escFile) File() (http.File, error) {
+ type httpFile struct {
+ *bytes.Reader
+ *escFile
+ }
+ return &httpFile{
+ Reader: bytes.NewReader(f.data),
+ escFile: f,
+ }, nil
+}
+
+func (f *escFile) Close() error {
+ return nil
+}
+
+func (f *escFile) Readdir(count int) ([]os.FileInfo, error) {
+ return nil, nil
+}
+
+func (f *escFile) Stat() (os.FileInfo, error) {
+ return f, nil
+}
+
+func (f *escFile) Name() string {
+ return f.name
+}
+
+func (f *escFile) Size() int64 {
+ return f.size
+}
+
+func (f *escFile) Mode() os.FileMode {
+ return 0
+}
+
+func (f *escFile) ModTime() time.Time {
+ return time.Time{}
+}
+
+func (f *escFile) IsDir() bool {
+ return f.isDir
+}
+
+func (f *escFile) Sys() interface{} {
+ return f
+}
+
+// FS returns a http.Filesystem for the embedded assets. If useLocal is true,
+// the filesystem's contents are instead used.
+func FS(useLocal bool) http.FileSystem {
+ if useLocal {
+ return escLocal
+ }
+ return escStatic
+}
+
+// FSByte returns the named file from the embedded assets. If useLocal is
+// true, the filesystem's contents are instead used.
+func FSByte(useLocal bool, name string) ([]byte, error) {
+ if useLocal {
+ f, err := escLocal.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ return ioutil.ReadAll(f)
+ }
+ f, err := escStatic.prepare(name)
+ if err != nil {
+ return nil, err
+ }
+ return f.data, nil
+}
+
+// FSMustByte is the same as FSByte, but panics if name is not present.
+func FSMustByte(useLocal bool, name string) []byte {
+ b, err := FSByte(useLocal, name)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+// FSString is the string version of FSByte.
+func FSString(useLocal bool, name string) (string, error) {
+ b, err := FSByte(useLocal, name)
+ return string(b), err
+}
+
+// FSMustString is the string version of FSMustByte.
+func FSMustString(useLocal bool, name string) string {
+ return string(FSMustByte(useLocal, name))
+}
+
+var escData = map[string]*escFile{
+
+ "/index.html": {
+ local: "cli/serve/static/index.html",
+ size: 943,
+ compressed: "" +
+ "\x1f\x8b\b\x00\x00\tn\x88\x00\xff|S\xc1\x8e\xd30\x10\xbd\xf7+\x86\\zj\x86\xd5r@+7\x97B\x01\x81\xc4J]\x0e\x1c\x1d\xdbm\xbc\xebږ=\x81\xae\x10\xff\x8e\xed$ݴ+q\x8a\xed\x99\xf7f\xe6\xcd\v{\xf3\xe1\xfb\xe6\xe1\xe7\xfdG\xe8\xe8h\x9a\x05\x9b>\x8a\xcbf\x01\xc0\x8e\x8a8\x88\x8e\x87\xa8h]\xfdxخ" +
+ "\xdeW\xcd\"GH\x93Q\xcdf\xbb\xdb}\x83\x15\xec\x04\xb7\f\x87\xb7\x1c5\xda>A\x17\xd4~\xbdD\x14\xd2>\xc6Z\x18\xd7˽\xe1A\xd5\xc2\x1d\x91?\xf2\x13\x1a\xddF\xa4ߚH\x85U\xeb\x1cE\n\xdc\xe3m}[\xbfC\x11#\x9e\xdfꣶuzYBPf\xbd\x8c\xf4lT\xec\x94\"\xf0\xa9\x8a\"\xd1-K\xe1\x12\xc8" +
+ "'\x80\xd6\xc9g\xf8S\x8e\x00\x9eK\xa9\xedaE\xce\xdfݾ\xf5\xa7\xf2\xfc7#p\x840\x1c\xa6^\xb0\f,d\x96\xff\x02ax\x8c\xeb*\x1d[\x1e`\xf8\xac\xa4\xda\xf3\xde\xd0t\xdd듒\x99\xba\x1a*3\xa9\xcf@\xe1,qmU\x18c\x97ё W\x9ee\xa4\x1c~\x95\xd1\x06ne5HZa5\bϐ\x9fI1" +
+ "\xb1\x96ͼn\xc0\x18\ue8da\x9a\x9d\xee\xf3j\xbd\x99\x95\x9b\x12\xd3g\x96S\x96:\xbf\x96&\xc7~bZ\u007f\x9d\xbdS5\x83\x13\xf8\x05\x10\xe7H\x86\xbd\xb9\xea\xfa\xe2\xc80\x15\x1e<\xf6\x1f\x19Yw3\x85\xa8\xb3\x82E\x97;\xd8d\xb3m\xb3ٖ\x11\xee\xbf~\x01r\xce33\x9aiN\xe3\xe7/oo\u007fC\x01\xbaMI\x15a7ff9\xabޡB\xd2|\xe1c\x9cf\xd5J\x85)\x17M\x96s\"i\x98\x8a\x12\x93\x15\xd9`\xce\x12\x85\xf5{\xa65\x95A\"\x84VZ\x92\x1a_\x85W\xe15N\x95»\xb1\xb0dU\b#>\x92\x94/" +
+ "|\xa5\xb7\x9c\xaa\x82R\x8dj@\xa1:-|\vl'L+\x11\xd9\x16\xfd\v\r\xf3\xd4$\xcbX\xb5\f\xb4\xa8\xbfGW_כ\x1b;\xf1\xd1h\xe0V%\xc2\xce\xeb\xb3ȨZc\x15Y\xa3\x94\x13\xa5\x16\x1e4\x13\"\x91{\x05\x19\xcdI\xc3u\xd7\xcdنfƸ\x17[\xbbQ\xc6v\x8a\xa9\xa84a\x15\x95\xed\xdcp\xb65" +
+ "`\x90{\x12 CF\x12\x89$U湐z\xd8s\x81\x8f0\xd9\x19\xc5`ծ\xcc!\x01\xceI\xadhG\xb6\xeb\xf7\xd1\x1aރ\xeb\x04\xe1Փ\xb1\x8b\xda\xefZ\x92-\x1f\x05\xcb\x1f\x9a\xdc\xf1b\x97\td\xa0\x88\xfb\x9a\x11n\xf8\x88\xf5\xa0\x19a\x00v9\xf6@\x18\xa3ⲛ\xaaɒ\xee\"\xe8\xe0\x8b\xcb6\x14}\x13R" +
+ "\xbc\x9f\\\x03\bH\xa0\xca\xe0[d\x1ae\x16\\w\r\x91\xe7\x90\xf6\xc1u?R\xb9\x90e\xa7h\xda\x01\xab ש\x87X\x06\x96r\xa5\xc0\x16P\xf0 \x88%\x1d\x8c\fCI\x12\xca\x11\x18Xx\x85Pڋ\u007f\x81\u007f\x88\x93\x19\x8eQĪ\xba\xd1\x03\x18\xe3\xbf\x14\xdc\xe1X\x95\x16\xc1\xb5kNRZ\b\x0e1hAC!\x97" +
+ "\x1e\xd2\xdb\x1ad4\xdd\x00\x04\x8a\x92FkQuv\x13]!\xf8\x05\xb5d%\x91\xdbNX5I\xc9t\x17I\xa7\xd2_=C\xe7\xf8\xfa}\x99\xa8k\x92p\xdai\xba\x8e\xfd\x87\x9a!\xc1e\x9a\xb5](\x15\xac\xa6\x99\x8b\x92\xa4\n\xf6\xa8\xf2b(Lfv\xb7;\x86DjRQ\x1e,\xa5hj\xa7G\xd2\x14\xac2Q\x19͝" +
+ "\u007fǒ\xb5\xf3:R)`k\xa4d\n\x1b\xe2T\xcd[\xfd\xd3P\xb9\xc5߄\x97\xe1U۱\x15ne\xe9:S\xf1ުC}2\xf3\xbf\xda'\x94?\x0f\xddR\xcd\xf2\xa6J5\xf0\x9d\xd15\xad\xf4|W\xf5\x8c|\x1b\x04\x10\xa6e\xad\xb7\xb3\xf9M7\x19.\xa9\xfe\xf5\xf6\xd5\xef3\x1f\x93\x9a\xe1\xf5%\xb6\xb6\xed^\xfe\xc1d" +
+ "\xd5\xc2GϬ\r\xd3\x01\x03k\xc2g\xf3\v\xb4Cˈ&{0\x84X\x8e\xec\xd8\x1b_5iJ\xa1Vߡ\xa7O\x91\x1br<\xfc\xbb\xbe\x82!AIZ̆\"=\x88\x9c\x94\x8co\xefM\xa6_ CL\r\xf5\x11ZCQv\x8a\xf7\x90ih\x81\xfcH\xcbؿ\x19\b\xf5\x04\x9eY\x89,6\xbe\xf5\xacCϏ\xdeb" +
+ "3qR\xf5\xb3\xb3ql\xb3\xf5\xda\xfa\xd3s\xd6\xf4\xa1\xc0\xb5\xde:౻\x13\x84\xc0\xdbS\"\xceݾ\xfd\x9e\xbf#e\x13Х\x84b\n\xb1t\x86\xdex\xb6\xef\xdd\u074cD͂\xb7\xa2\v\xe4\xfd,D\xe6\x1d\xf2\x9d\x0e\xa1\x82]\xd7Epɷu\xc1\xa0\xc0\xa1]+\x10\xef\x02Ŗf\a\xbe\xc5F6F\xc6\xfc\xe4\n" +
+ "\xc11\x8e(\x87\xf3mH\xe7/\"+8\xf2\x1f\x8d\x11\xdd\xc0dI\xccJ\x8d\xa9\xb5P\x9f\xc3\xeeG\xf2x\xb1\x92\xb4\x14k:&\x05\b\x0f\x13z\x1cp(]j\"&ǠOd*h\x1dl^\x97\x92\xa2\xd1\xe6H\xdc\xe5\xa4\xef\x06\xfcɤl\x85\xcf!\xd2M\x05w58\xa0\xb3O\x8c\xf6\x01x\x1f\xfeޜ\x90\xc0\xe1I" +
+ "h\x1a-\xcc\xfcPcϡՀ\x15\x17Ɋ\xa6pR\u007f\xf8\x80\xc6SDJ\xb2\x9dL\x87\t\x8a\xff\xb3\xf6\xb8\xa7\xad@\x8eH\xaf\x041\x88\xd6\xe6\x02<\xe6\r\x9d\xe63]\x80\xa60\x0e\xc3p~\xc2\xd7cK\x02\xc5\xca\x12;Z\xa4\xbbg\x9c^\x0f\x9a4g_h\xc2T-Y\xbe\x9d\xb5>\x9f\x82\xf8\xb4\x8c\xb5d&\x12c" +
+ "R\xdf\xdeM&L\x1cݧc+#O\x8e\xa6\xe5ax&\u061cܵc\xbf\x8ey4ilx%!uM\xabl\xb6\xb700\xfdq~6f\xb0ǶW\x9d\x10\xbe\xfd\xcc\xfb\x85\xfb\x1c\xeb.7Nj\u007f\x8d\x82[\xac\xfd\xa2\x83\xef\x02\xf3y\xfb_\x00\x00\x00\xff\xff\x06N\x9fR\xf5\x0e\x00\x00",
+ },
+
+ "/": {
+ isDir: true,
+ local: "cli/serve/static",
+ },
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static/index.html b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static/index.html
new file mode 100644
index 00000000000..b6942f5dce7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+ CFSSL - Scan
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static/scan.html b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static/scan.html
new file mode 100644
index 00000000000..db73a12e1a3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/serve/static/scan.html
@@ -0,0 +1,106 @@
+
+
+
+
+
+ CFSSL - Scan
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/sign/sign.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/sign/sign.go
index bd8aa2e1dfe..e67e34cc7f1 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/sign/sign.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/sign/sign.go
@@ -1,3 +1,4 @@
+// Package sign implements the sign command.
package sign
import (
@@ -11,8 +12,8 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/universal"
)
-var signerUsageText = // Usage text of 'cfssl sign'
-`cfssl sign -- signs a client cert with a host name by a given CA and CA key
+// Usage text of 'cfssl sign'
+var signerUsageText = `cfssl sign -- signs a client cert with a host name by a given CA and CA key
Usage of sign:
cfssl sign -ca cert -ca-key key [-config config] [-profile profile] [-hostname hostname] CSR [SUBJECT]
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/version/version.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/version/version.go
index 251394b7170..02915b57a2e 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/version/version.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/version/version.go
@@ -1,3 +1,4 @@
+// Package version implements the version command.
package version
import (
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cmd/cfssl/cfssl.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cmd/cfssl/cfssl.go
index 2546403c3d8..e0fe26ed296 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/cmd/cfssl/cfssl.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/cmd/cfssl/cfssl.go
@@ -27,6 +27,8 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/bundle"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/gencert"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/genkey"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/info"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspserve"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/ocspsign"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/scan"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/cli/selfsign"
@@ -38,20 +40,22 @@ import (
// main defines the cfssl usage and registers all defined commands and flags.
func main() {
- flag.Usage = nil
// Add command names to cfssl usage
+ flag.Usage = nil // this is set to nil for testabilty
flag.IntVar(&log.Level, "loglevel", log.LevelInfo, "Log level")
// Register commands.
cmds := map[string]*cli.Command{
- "bundle": bundle.Command,
- "sign": sign.Command,
- "serve": serve.Command,
- "version": version.Command,
- "genkey": genkey.Command,
- "gencert": gencert.Command,
- "ocspsign": ocspsign.Command,
- "selfsign": selfsign.Command,
- "scan": scan.Command,
+ "bundle": bundle.Command,
+ "sign": sign.Command,
+ "serve": serve.Command,
+ "version": version.Command,
+ "genkey": genkey.Command,
+ "gencert": gencert.Command,
+ "ocspsign": ocspsign.Command,
+ "ocspserve": ocspserve.Command,
+ "selfsign": selfsign.Command,
+ "scan": scan.Command,
+ "info": info.Command,
}
// Register all command flags.
cli.Start(cmds)
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/config/config.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/config/config.go
index 91dc1b8e287..9bbe39a0346 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/config/config.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/config/config.go
@@ -1,4 +1,4 @@
-// Package config contains the configuration logic for CF-SSL.
+// Package config contains the configuration logic for CFSSL.
package config
import (
@@ -16,6 +16,7 @@ import (
cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
+ ocspConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config"
)
// A CSRWhitelist stores booleans for fields in the CSR. If a CSRWhitelist is
@@ -297,6 +298,7 @@ type Signing struct {
// Config stores configuration information for the CA.
type Config struct {
Signing *Signing `json:"signing"`
+ OCSP *ocspConfig.Config `json:"ocsp"`
AuthKeys map[string]AuthKey `json:"auth_keys,omitempty"`
Remotes map[string]string `json:"remotes,omitempty"`
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key.go
new file mode 100644
index 00000000000..8c72fd54034
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key.go
@@ -0,0 +1,235 @@
+// +build pkcs11
+
+// Package pkcs11key implements crypto.Signer for PKCS #11 private
+// keys. Currently, only RSA keys are support.
+package pkcs11key
+
+import (
+ "crypto"
+ "crypto/rsa"
+ "errors"
+ "io"
+ "math/big"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/pkcs11"
+)
+
+// from src/pkg/crypto/rsa/pkcs1v15.go
+var hashPrefixes = map[crypto.Hash][]byte{
+ crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
+ crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
+ crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
+ crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
+ crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
+ crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
+ crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix.
+ crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
+}
+
+// PKCS11Key is an implementation of the crypto.Signer interface
+// using a key stored in a PKCS#11 hardware token. This enables
+// the use of PKCS#11 tokens with the Go x509 library's methods
+// for signing certificates.
+type PKCS11Key struct {
+ // The PKCS#11 library to use
+ module *pkcs11.Ctx
+
+ // The name of the slot to be used.
+ // We will automatically search for this in the slot list.
+ slotDescription string
+
+ // The PIN to be used to log in to the device
+ pin string
+
+ // The public key corresponding to the private key.
+ publicKey rsa.PublicKey
+
+ // The an ObjectHandle pointing to the private key on the HSM.
+ privateKeyHandle pkcs11.ObjectHandle
+}
+
+// New instantiates a new handle to a PKCS #11-backed key.
+func New(module, slot, pin, privLabel string) (ps *PKCS11Key, err error) {
+ // Set up a new pkcs11 object and initialize it
+ p := pkcs11.New(module)
+ if p == nil {
+ err = errors.New("unable to load PKCS#11 module")
+ return
+ }
+
+ if err = p.Initialize(); err != nil {
+ return
+ }
+
+ // Initialize a partial key
+ ps = &PKCS11Key{
+ module: p,
+ slotDescription: slot,
+ pin: pin,
+ }
+
+ // Look up the private key
+ session, err := ps.openSession()
+ if err != nil {
+ ps.Destroy()
+ return
+ }
+ defer ps.closeSession(session)
+
+ template := []*pkcs11.Attribute{
+ pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
+ pkcs11.NewAttribute(pkcs11.CKA_LABEL, privLabel),
+ }
+ if err = p.FindObjectsInit(session, template); err != nil {
+ ps.Destroy()
+ return
+ }
+ objs, _, err := p.FindObjects(session, 2)
+ if err != nil {
+ ps.Destroy()
+ return
+ }
+ if err = p.FindObjectsFinal(session); err != nil {
+ ps.Destroy()
+ return
+ }
+
+ if len(objs) == 0 {
+ err = errors.New("private key not found")
+ ps.Destroy()
+ return
+ }
+ ps.privateKeyHandle = objs[0]
+
+ // Populate the pubic key from the private key
+ // TODO: Add support for non-RSA keys, switching on CKA_KEY_TYPE
+ template = []*pkcs11.Attribute{
+ pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
+ pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
+ }
+ attr, err := p.GetAttributeValue(session, ps.privateKeyHandle, template)
+ if err != nil {
+ ps.Destroy()
+ return
+ }
+
+ n := big.NewInt(0)
+ e := int(0)
+ gotModulus, gotExponent := false, false
+ for _, a := range attr {
+ if a.Type == pkcs11.CKA_MODULUS {
+ n.SetBytes(a.Value)
+ gotModulus = true
+ } else if a.Type == pkcs11.CKA_PUBLIC_EXPONENT {
+ bigE := big.NewInt(0)
+ bigE.SetBytes(a.Value)
+ e = int(bigE.Int64())
+ gotExponent = true
+ }
+ }
+ if !gotModulus || !gotExponent {
+ ps.Destroy()
+ return
+ }
+ ps.publicKey = rsa.PublicKey{n, e}
+
+ return
+}
+
+// Destroy tears down a PKCS11Key.
+//
+// This method must be called before the PKCS11Key is GC'ed, in order
+// to ensure that the PKCS#11 module itself is properly finalized and
+// destroyed.
+//
+// The idiomatic way to do this (assuming no need for a long-lived
+// signer) is as follows:
+//
+// ps, err := NewPKCS11Signer(...)
+// if err != nil { ... }
+// defer ps.Destroy()
+func (ps *PKCS11Key) Destroy() {
+ if ps.module != nil {
+ ps.module.Finalize()
+ ps.module.Destroy()
+ }
+}
+
+func (ps *PKCS11Key) openSession() (session pkcs11.SessionHandle, err error) {
+ // Find slot by description
+ slots, err := ps.module.GetSlotList(true)
+ if err != nil {
+ return
+ }
+ for _, slot := range slots {
+ slotInfo, err := ps.module.GetSlotInfo(slot)
+ if err != nil {
+ continue
+ }
+
+ if slotInfo.SlotDescription == ps.slotDescription {
+ // Open session
+ session, err = ps.module.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION)
+ if err != nil {
+ return session, err
+ }
+
+ // Login
+ if err = ps.module.Login(session, pkcs11.CKU_USER, ps.pin); err != nil {
+ return session, err
+ }
+
+ return session, err
+ }
+ }
+
+ err = errors.New("slot not found")
+ return
+}
+
+func (ps *PKCS11Key) closeSession(session pkcs11.SessionHandle) {
+ ps.module.Logout(session)
+ ps.module.CloseSession(session)
+}
+
+// Public returns the public key for the PKCS #11 key.
+func (ps *PKCS11Key) Public() crypto.PublicKey {
+ return &ps.publicKey
+}
+
+// Sign performs a signature using the PKCS #11 key.
+func (ps *PKCS11Key) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) {
+ // Verify that the length of the hash is as expected
+ hash := opts.HashFunc()
+ hashLen := hash.Size()
+ if len(msg) != hashLen {
+ err = errors.New("input size does not match hash function output size")
+ return
+ }
+
+ // Add DigestInfo prefix
+ // TODO: Switch mechanisms based on CKA_KEY_TYPE
+ mechanism := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}
+ prefix, ok := hashPrefixes[hash]
+ if !ok {
+ err = errors.New("unknown hash function")
+ return
+ }
+ signatureInput := append(prefix, msg...)
+
+ // Open a session
+ session, err := ps.openSession()
+ if err != nil {
+ return
+ }
+ defer ps.closeSession(session)
+
+ // Perform the sign operation
+ err = ps.module.SignInit(session, mechanism, ps.privateKeyHandle)
+ if err != nil {
+ return
+ }
+
+ signature, err = ps.module.Sign(session, signatureInput)
+ return
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key_stub.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key_stub.go
new file mode 100644
index 00000000000..e4c4f0a5049
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key_stub.go
@@ -0,0 +1,6 @@
+// Package pkcs11key exists to satisfy Go build tools.
+// Some Go tools will complain "no buildable Go source files in ..." because
+// pkcs11key.go only builds when the pkcs11 tag is supplied. This empty file
+// exists only to suppress that error, which blocks completion in some tools
+// (specifically godep).
+package pkcs11key
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/crypto.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/crypto.go
new file mode 100644
index 00000000000..bbcab707d42
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/crypto.go
@@ -0,0 +1,114 @@
+package pkcs12
+
+// Much credit to at Microsoft's Azure project https://github.com/Azure/go-pkcs12/blob/master/pkcs12.go,
+// from which the following decryption code was adapted under the MIT License. The functions in this
+// file implement the decryption of pkcs12 formatted data as described in
+// https://tools.ietf.org/html/rfc2898#section-6.1.2
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/sha1"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pbkdf"
+ rc2 "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/dgryski/go-rc2"
+)
+
+type pbeParams struct {
+ Salt []byte
+ Iterations int
+}
+
+const (
+ pbeWithSHAAnd3KeyTripleDESCBC = "pbeWithSHAAnd3-KeyTripleDES-CBC"
+ pbewithSHAAnd40BitRC2CBC = "pbewithSHAAnd40BitRC2-CBC"
+)
+
+var algByOID = map[string]string{
+ "1.2.840.113549.1.12.1.3": pbeWithSHAAnd3KeyTripleDESCBC,
+ "1.2.840.113549.1.12.1.6": pbewithSHAAnd40BitRC2CBC,
+}
+
+var blockcodeByAlg = map[string]func(key []byte) (cipher.Block, error){
+ pbeWithSHAAnd3KeyTripleDESCBC: des.NewTripleDESCipher,
+ pbewithSHAAnd40BitRC2CBC: func(key []byte) (cipher.Block, error) {
+ return rc2.New(key, len(key)*8)
+ },
+}
+
+var (
+ deriveKeyByAlg = map[string]func(salt, password []byte, iterations int) []byte{
+ pbeWithSHAAnd3KeyTripleDESCBC: func(salt, password []byte, iterations int) []byte {
+ return pbkdf.PBKDF(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
+ },
+ pbewithSHAAnd40BitRC2CBC: func(salt, password []byte, iterations int) []byte {
+ return pbkdf.PBKDF(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
+ },
+ }
+ deriveIVByAlg = map[string]func(salt, password []byte, iterations int) []byte{
+ pbeWithSHAAnd3KeyTripleDESCBC: func(salt, password []byte, iterations int) []byte {
+ return pbkdf.PBKDF(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
+ },
+ pbewithSHAAnd40BitRC2CBC: func(salt, password []byte, iterations int) []byte {
+ return pbkdf.PBKDF(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
+ },
+ }
+)
+
+func sha1Sum(in []byte) []byte {
+ sum := sha1.Sum(in)
+ return sum[:]
+}
+
+//For use decrypting key and certificates, apart from a few minor changes
+//this entire function was taken from Azure: https://github.com/Azure/go-pkcs12/blob/master/crypto.go
+func decrypt(algorithm pkix.AlgorithmIdentifier, encrypted, password []byte) (decrypted []byte, err error) {
+ // Generate a CBC Decrypter
+ cbc, err := cbcGen(algorithm, password)
+ if err != nil {
+ return nil, err
+ }
+ // Decrypting the secret data
+ decrypted = make([]byte, len(encrypted))
+ cbc.CryptBlocks(decrypted, encrypted)
+
+ if psLen := int(decrypted[len(decrypted)-1]); psLen > 0 && psLen < 9 {
+ m := decrypted[:len(decrypted)-psLen]
+ ps := decrypted[len(decrypted)-psLen:]
+ if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 {
+ return nil, errors.New("decryption error, incorrect padding")
+ }
+ decrypted = m
+ } else {
+ return nil, errors.New("decryption error, incorrect padding")
+ }
+
+ return
+}
+
+// Generating a cbc cipher decoder
+func cbcGen(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, error) {
+ algorithmName, supported := algByOID[algorithm.Algorithm.String()]
+ if !supported {
+ return nil, errors.New("Algorithm not supported")
+ }
+ var params pbeParams
+ if _, err := asn1.Unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil {
+ return nil, err
+ }
+ k := deriveKeyByAlg[algorithmName](params.Salt, password, params.Iterations)
+ iv := deriveIVByAlg[algorithmName](params.Salt, password, params.Iterations)
+
+ code, err := blockcodeByAlg[algorithmName](k)
+ if err != nil {
+ return nil, err
+ }
+
+ cbc := cipher.NewCBCDecrypter(code, iv)
+ return cbc, nil
+
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pbkdf/pbkdf.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pbkdf/pbkdf.go
new file mode 100644
index 00000000000..1f8eeff22e1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pbkdf/pbkdf.go
@@ -0,0 +1,201 @@
+// Package pbkdf implements
+//
+// Entire package adapted from https://github.com/Azure/go-pkcs12/blob/master/pbkdf.go
+// and https://github.com/Azure/go-pkcs12/blob/master/crypto.go under the MIT
+// license. These functions implement cryptographic processes used in decoding
+// password protected pfx objects adhering to the pkcs12 standard as documented at
+//
+// https://tools.ietf.org/html/rfc7292#appendix-B.2
+//
+//
+package pbkdf
+
+import (
+ "errors"
+ "math/big"
+ "unicode/utf16"
+ "unicode/utf8"
+)
+
+// PBKDF implements RSA Labs' Password-Based Key Derivation Function
+func PBKDF(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) {
+ // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments
+
+ // Let H be a hash function built around a compression function f:
+
+ // Z_2^u x Z_2^v -> Z_2^u
+
+ // (that is, H has a chaining variable and output of length u bits, and
+ // the message input to the compression function of H is v bits). The
+ // values for u and v are as follows:
+
+ // HASH FUNCTION VALUE u VALUE v
+ // MD2, MD5 128 512
+ // SHA-1 160 512
+ // SHA-224 224 512
+ // SHA-256 256 512
+ // SHA-384 384 1024
+ // SHA-512 512 1024
+ // SHA-512/224 224 1024
+ // SHA-512/256 256 1024
+
+ // Furthermore, let r be the iteration count.
+
+ // We assume here that u and v are both multiples of 8, as are the
+ // lengths of the password and salt strings (which we denote by p and s,
+ // respectively) and the number n of pseudorandom bits required. In
+ // addition, u and v are of course non-zero.
+
+ // For information on security considerations for MD5 [19], see [25] and
+ // [1], and on those for MD2, see [18].
+
+ // The following procedure can be used to produce pseudorandom bits for
+ // a particular "purpose" that is identified by a byte called "ID".
+ // This standard specifies 3 different values for the ID byte:
+
+ // 1. If ID=1, then the pseudorandom bits being produced are to be used
+ // as key material for performing encryption or decryption.
+
+ // 2. If ID=2, then the pseudorandom bits being produced are to be used
+ // as an IV (Initial Value) for encryption or decryption.
+
+ // 3. If ID=3, then the pseudorandom bits being produced are to be used
+ // as an integrity key for MACing.
+
+ // 1. Construct a string, D (the "diversifier"), by concatenating v/8
+ // copies of ID.
+ D := []byte{}
+ for i := 0; i < v; i++ {
+ D = append(D, ID)
+ }
+
+ // 2. Concatenate copies of the salt together to create a string S of
+ // length v(ceiling(s/v)) bits (the final copy of the salt may be
+ // truncated to create S). Note that if the salt is the empty
+ // string, then so is S.
+
+ S := []byte{}
+ {
+ s := len(salt)
+ times := s / v
+ if s%v > 0 {
+ times++
+ }
+ for len(S) < times*v {
+ S = append(S, salt...)
+ }
+ S = S[:times*v]
+ }
+
+ // 3. Concatenate copies of the password together to create a string P
+ // of length v(ceiling(p/v)) bits (the final copy of the password
+ // may be truncated to create P). Note that if the password is the
+ // empty string, then so is P.
+
+ P := []byte{}
+ {
+ s := len(password)
+ times := s / v
+ if s%v > 0 {
+ times++
+ }
+ for len(P) < times*v {
+ P = append(P, password...)
+ }
+ password = nil
+ P = P[:times*v]
+ }
+
+ // 4. Set I=S||P to be the concatenation of S and P.
+ I := append(S, P...)
+
+ // 5. Set c=ceiling(n/u).
+ c := size / u
+ if size%u > 0 {
+ c++
+ }
+
+ // 6. For i=1, 2, ..., c, do the following:
+ A := make([]byte, c*20)
+ for i := 0; i < c; i++ {
+
+ // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
+ // H(H(H(... H(D||I))))
+ Ai := hash(append(D, I...))
+ for j := 1; j < r; j++ {
+ Ai = hash(Ai[:])
+ }
+ copy(A[i*20:], Ai[:])
+
+ if i < c-1 { // skip on last iteration
+
+ // B. Concatenate copies of Ai to create a string B of length v
+ // bits (the final copy of Ai may be truncated to create B).
+ B := []byte{}
+ for len(B) < v {
+ B = append(B, Ai[:]...)
+ }
+ B = B[:v]
+
+ // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
+ // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
+ // setting I_j=(I_j+B+1) mod 2^v for each j.
+ {
+ Bbi := new(big.Int)
+ Bbi.SetBytes(B)
+
+ one := big.NewInt(1)
+
+ for j := 0; j < len(I)/v; j++ {
+ Ij := new(big.Int)
+ Ij.SetBytes(I[j*v : (j+1)*v])
+ Ij.Add(Ij, Bbi)
+ Ij.Add(Ij, one)
+ Ijb := Ij.Bytes()
+ if len(Ijb) > v {
+ Ijb = Ijb[len(Ijb)-v:]
+ }
+ copy(I[j*v:(j+1)*v], Ijb)
+ }
+ }
+ }
+ }
+ // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
+ // bit string, A.
+
+ // 8. Use the first n bits of A as the output of this entire process.
+ A = A[:size]
+
+ return A
+
+ // If the above process is being used to generate a DES key, the process
+ // should be used to create 64 random bits, and the key's parity bits
+ // should be set after the 64 bits have been produced. Similar concerns
+ // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any
+ // similar keys with parity bits "built into them".
+}
+
+// BMPString computes the Basic Multilingual Plane (BMP) string
+// of a []byte
+func BMPString(utf8String []byte) ([]byte, error) {
+ // References:
+ // https://tools.ietf.org/html/rfc7292#appendix-B.1
+ // http://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
+ // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes
+ // EncodeRune returns 0xfffd if the rune does not need special encoding
+ // - the above RFC provides the info that BMPStrings are NULL terminated.
+
+ rv := make([]byte, 0, 2*len(utf8String)+2)
+
+ start := 0
+ for start < len(utf8String) {
+ c, size := utf8.DecodeRune(utf8String[start:])
+ start += size
+ if t, _ := utf16.EncodeRune(c); t != 0xfffd {
+ return nil, errors.New("password contains characters that cannot be encoded in UCS-2")
+ }
+ rv = append(rv, byte(c/256), byte(c%256))
+ }
+ rv = append(rv, 0, 0)
+ return rv, nil
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pkcs12.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pkcs12.go
new file mode 100644
index 00000000000..3b160109640
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pkcs12.go
@@ -0,0 +1,222 @@
+// Package pkcs12 implements a subset of PKCS #12 as described here:
+// https://tools.ietf.org/html/rfc7292
+//
+//
+// Much credit to at Microsoft's Azure project https:
+// github.com/Azure/go-pkcs12/blob/master/pkcs12.go,
+// from which much of the parser code was adapted under the MIT License.
+// PKCS #12 is a format used for transferring certificates and private keys.
+//
+//
+// In particular the PFX/P12 structure storing certificates and private keys is parsed into a go structure.
+// In almost all cases PKCS #12 stored certificates and private keys are password protected at the time of
+// marshaling, and so the parse function in this package takes in a password []byte. PKCS #12 make extensive
+// use of the PKCS #7 standard, and so the PKCS #7 parser is used frequently here. Although there is
+// flexibility in the data a PKCS #12 object can hold, the typical (i.e. openssl generated) form is roughly
+// as follows (for more specific details on allowed asn1 structure see the standard)
+//
+//
+// PFX ->
+// Version int
+// PKCS #7 Data ->
+// PKCS #7 encryptedData ->
+// CertificateBag ->
+// Certificates
+// PKCS #7 Data ->
+// PKCS #8 ShroudedBag ->
+// Private Key
+// MAC Data (Not used here)
+//
+package pkcs12
+
+import (
+ "crypto"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/asn1"
+ "errors"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12/pbkdf"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs7"
+ cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/derhelpers"
+)
+
+const (
+ certBagID = "1.2.840.113549.1.12.10.1.3"
+ pkcs8ShroudedBagID = "1.2.840.113549.1.12.10.1.2"
+)
+
+// Internal types used for asn1 Unmarshaling
+type pfx struct {
+ Raw asn1.RawContent
+ Version int
+ AuthSafe asn1.RawValue
+ MacData asn1.RawValue `asn1:"optional"`
+}
+
+type contentInfo struct {
+ ContentType asn1.ObjectIdentifier
+ Content asn1.RawValue `asn1:"tag:0,explicit,optional"`
+}
+
+type safeBag struct {
+ ID asn1.ObjectIdentifier
+ Value asn1.RawValue `asn1:"tag:0,explicit"`
+ Attributes []pkcs12Attribute `asn1:"set,optional"`
+}
+
+type certBag struct {
+ ID asn1.ObjectIdentifier
+ Data []byte `asn1:"tag:0,explicit"`
+}
+
+type pkcs12Attribute struct {
+ ID asn1.ObjectIdentifier
+ Value asn1.RawValue `asn1:"set"`
+}
+
+type encryptedPrivateKeyInfo struct {
+ AlgorithmIdentifier pkix.AlgorithmIdentifier
+ EncryptedData []byte
+}
+
+// PKCS12 contains the Data expected in PKCS #12 objects, one or more certificates
+// a private key, an integer indicating the version, and the raw content
+// of the structure
+type PKCS12 struct {
+ Version int
+ Certificates []*x509.Certificate
+ PrivateKey crypto.Signer
+}
+
+// ParsePKCS12 parses a pkcs12 syntax object
+// into a container for a private key, certificate(s), and
+// version number
+func ParsePKCS12(raw, password []byte) (msg *PKCS12, err error) {
+ msg = new(PKCS12)
+ password, err = pbkdf.BMPString(password)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ var Pfx pfx
+ _, err = asn1.Unmarshal(raw, &Pfx)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+
+ if msg.Version = Pfx.Version; msg.Version != 3 {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for PKCS #12 PFX version 3"))
+ }
+ authSafe, err := pkcs7.ParsePKCS7(Pfx.AuthSafe.FullBytes)
+
+ if err != nil {
+ return nil, err
+ }
+ if authSafe.ContentInfo != "Data" {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("No support for AuthSafe Format"))
+ }
+ var authenticatedSafe []asn1.RawValue
+ _, err = asn1.Unmarshal(authSafe.Content.Data, &authenticatedSafe)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+
+ }
+
+ if len(authenticatedSafe) != 2 {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("No support for AuthSafe Format"))
+ }
+ var bags []safeBag
+ bags, err = getBags(authenticatedSafe, password)
+ if err != nil {
+ return nil, err
+ }
+ if len(bags) > 2 || bags == nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("No support for AuthSafe Format"))
+ }
+
+ certs, pkey, err := parseBags(bags, password)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ msg.Certificates = certs
+ msg.PrivateKey = pkey
+ return
+
+}
+
+// Given a slice of PKCS #7 content infos containing PKCS #12 Safe Bag Data,
+// getBags returns those Safe Bags.
+func getBags(authenticatedSafe []asn1.RawValue, password []byte) (bags []safeBag, err error) {
+ for _, contentInfo := range authenticatedSafe {
+
+ var safeContents []safeBag
+ bagContainer, err := pkcs7.ParsePKCS7(contentInfo.FullBytes)
+ if err != nil {
+ return nil, err
+ }
+ switch {
+ case bagContainer.ContentInfo == "Data":
+ if _, err = asn1.Unmarshal(bagContainer.Content.Data, &safeContents); err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ case bagContainer.ContentInfo == "EncryptedData":
+ data, err := decrypt(bagContainer.Content.EncryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm,
+ bagContainer.Content.EncryptedData.EncryptedContentInfo.EncryptedContent, password)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ if _, err = asn1.Unmarshal(data, &safeContents); err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ default:
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for bags encoded in Data and EncryptedData types"))
+ }
+
+ bags = append(bags, safeContents...)
+ }
+ return bags, nil
+
+}
+
+// Take in either two or one safeBags and return the certificates and or
+// Private key within the bags
+func parseBags(bags []safeBag, password []byte) (certs []*x509.Certificate, key crypto.Signer, err error) {
+ for _, bag := range bags {
+ bagid := bag.ID.String()
+ switch bagid {
+ case certBagID:
+ var CertBag certBag
+ if _, err = asn1.Unmarshal(bag.Value.Bytes, &CertBag); err != nil {
+ return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ certs, err = x509.ParseCertificates(CertBag.Data)
+
+ if err != nil {
+ return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+
+ case pkcs8ShroudedBagID:
+ var pkinfo encryptedPrivateKeyInfo
+ if _, err := asn1.Unmarshal(bag.Value.Bytes, &pkinfo); err != nil {
+ return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ pkDecrypted, err := decrypt(pkinfo.AlgorithmIdentifier, pkinfo.EncryptedData, password)
+ if err != nil {
+ return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ // Checking if private key data has been properly decoded
+ var rv asn1.RawValue
+ if _, err = asn1.Unmarshal(pkDecrypted, &rv); err != nil {
+ return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ if key, err = derhelpers.ParsePrivateKeyDER(pkDecrypted); err != nil {
+ return nil, nil, err
+ }
+
+ default:
+ return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for certificate bags and PKCS #8 Shrouded Bags"))
+ }
+ }
+ return certs, key, nil
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go
index 408d74d6c81..d70b49a10bc 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go
@@ -1,7 +1,7 @@
// Package pkcs7 implements the subset of the CMS PKCS #7 datatype that is typically
// used to package certificates and CRLs. Using openssl, every certificate converted
// to PKCS #7 format from another encoding such as PEM conforms to this implementation.
-// reference: https://www.openssl.org/docs/apps/crl2pkcs7.html)
+// reference: https://www.openssl.org/docs/apps/crl2pkcs7.html
//
// PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315
//
@@ -16,10 +16,12 @@
// }
//
// There are 6 possible ContentTypes, data, signedData, envelopedData,
-// signedAndEnvelopedData, digestedData, and encryptedData. Here onlysignedData is
-// implemented, as the degenerate case of signedData without a signature is the typical
-// format for transferring certificates and CRLS. The ContentType signedData has the
-// form:
+// signedAndEnvelopedData, digestedData, and encryptedData. Here signedData, Data, and encrypted
+// Data are implemented, as the degenerate case of signedData without a signature is the typical
+// format for transferring certificates and CRLS, and Data and encryptedData are used in PKCS #12
+// formats.
+// The ContentType signedData has the form:
+//
//
// signedData ::= SEQUENCE {
// version Version,
@@ -36,12 +38,21 @@
// usage. The ExtendedCertificatesAndCertificates type consists of a sequence of choices
// between PKCS #6 extended certificates andx509 certificates. Any sequence consisting
// of any number of extended certificates is not yet supported in this implementation
+//
+// The ContentType Data is simpy a raw octet string and is parsed directly into a Go []byte
+//
+// The ContentType encryptedData is the most complicated and its form can be gathered by
+// the go type below. It essentially contains a raw octet string of encrypted data and an
+// algorithm identifier for use in decrypting this data
package pkcs7
import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
+ "errors"
+
+ cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
)
// Types used for asn1 Unmarshaling
@@ -55,24 +66,66 @@ type signedData struct {
SignerInfos asn1.RawValue
}
-type content struct {
- SignedData signedData
-}
-
type initPKCS7 struct {
Raw asn1.RawContent
ContentType asn1.ObjectIdentifier
- Content content `asn1:"tag:0"`
+ Content asn1.RawValue `asn1:"tag:0,explicit,optional"`
}
-// PKCS7 represents the ASN1 PKCS7 degenerate signedData content type
+// Object identifiers strings of the three implemented PKCS7 types
+const (
+ ObjIDData = "1.2.840.113549.1.7.1"
+ ObjIDSignedData = "1.2.840.113549.1.7.2"
+ ObjIDEncryptedData = "1.2.840.113549.1.7.6"
+)
+
+// PKCS7 represents the ASN1 PKCS #7 Content type. It contains one of three
+// possible types of Content objects, as denoted by the object identifier in
+// the ContentInfo field, the other two being nil. SignedData
+// is the degenerate SignedData Content info without signature used
+// to hold certificates and crls. Data is raw bytes, and EncryptedData
+// is as defined in PKCS #7 standard
type PKCS7 struct {
+ Raw asn1.RawContent
+ ContentInfo string
+ Content Content
+}
+
+// Content implements three of the six possible PKCS7 data types. Only one is non-nil
+type Content struct {
+ Data []byte
+ SignedData SignedData
+ EncryptedData EncryptedData
+}
+
+// SignedData defines the typical carrier of certificates and crls
+type SignedData struct {
Raw asn1.RawContent
Version int
Certificates []*x509.Certificate
Crl *pkix.CertificateList
}
+// Data contains raw bytes. Used as a subtype in PKCS12
+type Data struct {
+ Bytes []byte
+}
+
+// EncryptedData contains encrypted data. Used as a subtype in PKCS12
+type EncryptedData struct {
+ Raw asn1.RawContent
+ Version int
+ EncryptedContentInfo EncryptedContentInfo
+}
+
+// EncryptedContentInfo is a subtype of PKCS7EncryptedData
+type EncryptedContentInfo struct {
+ Raw asn1.RawContent
+ ContentType asn1.ObjectIdentifier
+ ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
+ EncryptedContent []byte `asn1:"tag:0,optional"`
+}
+
// ParsePKCS7 attempts to parse the DER encoded bytes of a
// PKCS7 structure
func ParsePKCS7(raw []byte) (msg *PKCS7, err error) {
@@ -80,29 +133,54 @@ func ParsePKCS7(raw []byte) (msg *PKCS7, err error) {
var pkcs7 initPKCS7
_, err = asn1.Unmarshal(raw, &pkcs7)
if err != nil {
- return nil, err
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
}
msg = new(PKCS7)
msg.Raw = pkcs7.Raw
- msg.Version = pkcs7.Content.SignedData.Version
-
- if len(pkcs7.Content.SignedData.Certificates.Bytes) == 0 {
- msg.Certificates = nil
- } else {
- msg.Certificates, err = x509.ParseCertificates(pkcs7.Content.SignedData.Certificates.Bytes)
+ msg.ContentInfo = pkcs7.ContentType.String()
+ switch {
+ case msg.ContentInfo == ObjIDData:
+ msg.ContentInfo = "Data"
+ _, err = asn1.Unmarshal(pkcs7.Content.Bytes, &msg.Content.Data)
if err != nil {
- return nil, err
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
}
- }
-
- if len(pkcs7.Content.SignedData.Crls.Bytes) == 0 {
- msg.Crl = nil
- } else {
- msg.Crl, err = x509.ParseDERCRL(pkcs7.Content.SignedData.Crls.Bytes)
+ case msg.ContentInfo == ObjIDSignedData:
+ msg.ContentInfo = "SignedData"
+ var signedData signedData
+ _, err = asn1.Unmarshal(pkcs7.Content.Bytes, &signedData)
if err != nil {
- return nil, err
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ if len(signedData.Certificates.Bytes) != 0 {
+ msg.Content.SignedData.Certificates, err = x509.ParseCertificates(signedData.Certificates.Bytes)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
}
+ if len(signedData.Crls.Bytes) != 0 {
+ msg.Content.SignedData.Crl, err = x509.ParseDERCRL(signedData.Crls.Bytes)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ }
+ msg.Content.SignedData.Version = signedData.Version
+ msg.Content.SignedData.Raw = pkcs7.Content.Bytes
+ case msg.ContentInfo == ObjIDEncryptedData:
+ msg.ContentInfo = "EncryptedData"
+ var encryptedData EncryptedData
+ _, err = asn1.Unmarshal(pkcs7.Content.Bytes, &encryptedData)
+ if err != nil {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ }
+ if encryptedData.Version != 0 {
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for PKCS #7 encryptedData version 0"))
+ }
+ msg.Content.EncryptedData = encryptedData
+
+ default:
+ return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Attempt to parse PKCS# 7 Content not of type data, signed data or encrypted data"))
}
return msg, nil
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr.go
index 1472f3b01ee..0bf0303c018 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr.go
@@ -1,4 +1,4 @@
-// Package csr implements certificate requests for CF-SSL.
+// Package csr implements certificate requests for CFSSL.
package csr
import (
@@ -10,6 +10,8 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"errors"
+ "net"
+ "strings"
cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
@@ -189,17 +191,20 @@ func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
var tpl = x509.CertificateRequest{
Subject: req.Name(),
SignatureAlgorithm: req.KeyRequest.SigAlgo(),
- DNSNames: req.Hosts,
}
+
+ for i := range req.Hosts {
+ if ip := net.ParseIP(req.Hosts[i]); ip != nil {
+ tpl.IPAddresses = append(tpl.IPAddresses, ip)
+ } else {
+ tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
+ }
+ }
+
csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv)
if err != nil {
log.Errorf("failed to generate a CSR: %v", err)
- // The use of CertificateError was a matter of some
- // debate; it is the one edge case in which a new
- // error category specifically for CSRs might be
- // useful, but it was deemed that one edge case did
- // not a new category justify.
- err = cferr.Wrap(cferr.CertificateError, cferr.BadRequest, err)
+ err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
return
}
block := pem.Block{
@@ -234,3 +239,13 @@ func (g *Generator) ProcessRequest(req *CertificateRequest) (csr, key []byte, er
}
return
}
+
+// IsNameEmpty returns true if the name has no identifying information in it.
+func IsNameEmpty(n Name) bool {
+ empty := func(s string) bool { return strings.TrimSpace(s) == "" }
+
+ if empty(n.C) && empty(n.ST) && empty(n.L) && empty(n.O) && empty(n.OU) {
+ return true
+ }
+ return false
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr_test.go
index 72813a25986..8519f52d8ad 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr/csr_test.go
@@ -97,7 +97,7 @@ func TestParseRequest(t *testing.T) {
OU: "Systems Engineering",
},
},
- Hosts: []string{"cloudflare.com", "www.cloudflare.com"},
+ Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1"},
KeyRequest: &kr,
}
@@ -304,16 +304,38 @@ func TestGenerator(t *testing.T) {
},
},
CN: "cloudflare.com",
- Hosts: []string{"cloudflare.com", "www.cloudflare.com"},
+ Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1"},
KeyRequest: &KeyRequest{
Algo: "rsa",
Size: 2048,
},
}
- _, _, err := g.ProcessRequest(req)
+ csrBytes, _, err := g.ProcessRequest(req)
if err != nil {
- t.Fatalf("%v", err)
+ t.Fatal(err)
+ }
+
+ block, _ := pem.Decode([]byte(csrBytes))
+ if block == nil {
+ t.Fatalf("bad CSR in PEM")
+ }
+
+ if block.Type != "CERTIFICATE REQUEST" {
+ t.Fatalf("bad CSR in PEM")
+ }
+
+ csr, err := x509.ParseCertificateRequest(block.Bytes)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(csr.DNSNames) != 2 {
+ t.Fatal("SAN parsing error")
+ }
+
+ if len(csr.IPAddresses) != 1 {
+ t.Fatal("SAN parsing error")
}
}
@@ -371,3 +393,41 @@ func TestWeakCSR(t *testing.T) {
t.Fatalf("Request should have failed.")
}
}
+
+var testEmpty = []struct {
+ name Name
+ ok bool
+}{
+ {
+ Name{},
+ true,
+ },
+ {
+ Name{C: "OK"},
+ false,
+ },
+ {
+ Name{ST: "OK"},
+ false,
+ },
+ {
+ Name{L: "OK"},
+ false,
+ },
+ {
+ Name{O: "OK"},
+ false,
+ },
+ {
+ Name{OU: "OK"},
+ false,
+ },
+}
+
+func TestIsNameEmpty(t *testing.T) {
+ for i, c := range testEmpty {
+ if IsNameEmpty(c.name) != c.ok {
+ t.Fatalf("%d: expected IsNameEmpty to return %v, but have %v", i, c.ok, !c.ok)
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error.go
index 5fe5ff32058..a88af6995a7 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error.go
@@ -49,6 +49,9 @@ const (
// OCSPError indicates a problem with OCSP signing
OCSPError // 8XXX
+
+ // CSRError indicates a problem with CSR parsing
+ CSRError // 9XXX
)
// None is a non-specified error.
@@ -213,7 +216,7 @@ func New(category Category, reason Reason) *Error {
case BadRequest:
msg = "Invalid certificate request"
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CertificateError.",
+ panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category CertificateError.",
reason))
}
@@ -238,7 +241,7 @@ func New(category Category, reason Reason) *Error {
case Unavailable:
msg = "Private key is unavailable"
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category PrivateKeyError.",
+ panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PrivateKeyError.",
reason))
}
case IntermediatesError:
@@ -252,7 +255,7 @@ func New(category Category, reason Reason) *Error {
case ParseFailed:
msg = "Failed to parse intermediate certificate"
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category IntermediatesError.",
+ panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category IntermediatesError.",
reason))
}
case RootError:
@@ -266,7 +269,7 @@ func New(category Category, reason Reason) *Error {
case ParseFailed:
msg = "Failed to parse root certificate"
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category RootError.",
+ panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category RootError.",
reason))
}
case PolicyError:
@@ -280,7 +283,7 @@ func New(category Category, reason Reason) *Error {
case InvalidRequest:
msg = "Policy violation request"
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category PolicyError.",
+ panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
reason))
}
case DialError:
@@ -288,7 +291,7 @@ func New(category Category, reason Reason) *Error {
case Unknown:
msg = "Failed to dial remote server"
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category DialError.",
+ panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category DialError.",
reason))
}
case APIClientError:
@@ -304,12 +307,27 @@ func New(category Category, reason Reason) *Error {
case ServerRequestFailed:
msg = "API client error: Server request failed"
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category APIClientError.",
+ panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category APIClientError.",
reason))
}
+ case CSRError:
+ switch reason {
+ case Unknown:
+ msg = "CSR parsing failed due to unknown error"
+ case ReadFailed:
+ msg = "CSR file read failed"
+ case ParseFailed:
+ msg = "CSR Parsing failed"
+ case DecodeFailed:
+ msg = "CSR Decode failed"
+ case BadRequest:
+ msg = "CSR Bad request"
+ default:
+ panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category APIClientError.", reason))
+ }
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error type: %d.",
+ panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
category))
}
return &Error{ErrorCode: errorCode, Message: msg}
@@ -342,10 +360,10 @@ func Wrap(category Category, reason Reason, err error) *Error {
errorCode += unknownAuthority
}
}
- case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError, APIClientError:
+ case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError, APIClientError, CSRError:
// no-op, just use the error
default:
- panic(fmt.Sprintf("Unsupported CF-SSL error type: %d.",
+ panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
category))
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error_test.go
index 4b54f6f46de..9221daca0e9 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors/error_test.go
@@ -176,6 +176,31 @@ func TestNew(t *testing.T) {
if code != 7500 {
t.Fatal("Improper error code")
}
+
+ code = New(CSRError, Unknown).ErrorCode
+ if code != 9000 {
+ t.Fatal("Improper error code")
+ }
+ code = New(CSRError, ReadFailed).ErrorCode
+ if code != 9001 {
+ t.Fatal("Improper error code")
+ }
+ code = New(CSRError, DecodeFailed).ErrorCode
+ if code != 9002 {
+ t.Fatal("Improper error code")
+ }
+ code = New(CSRError, ParseFailed).ErrorCode
+ if code != 9003 {
+ t.Fatal("Improper error code")
+ }
+ code = New(CSRError, KeyMismatch).ErrorCode
+ if code != 9300 {
+ t.Fatal("Improper error code")
+ }
+ code = New(CSRError, BadRequest).ErrorCode
+ if code != 9300 {
+ t.Fatal("Improper error code")
+ }
}
func TestWrap(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go
new file mode 100644
index 00000000000..31928fad1d3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go
@@ -0,0 +1,42 @@
+// Package derhelpers implements common functionality
+// on DER encoded data
+package derhelpers
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "crypto/x509"
+
+ cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+)
+
+// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve
+// DER-encoded private key. The key must not be in PEM format.
+func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
+ generalKey, err := x509.ParsePKCS8PrivateKey(keyDER)
+ if err != nil {
+ generalKey, err = x509.ParsePKCS1PrivateKey(keyDER)
+ if err != nil {
+ generalKey, err = x509.ParseECPrivateKey(keyDER)
+ if err != nil {
+ // We don't include the actual error into
+ // the final error. The reason might be
+ // we don't want to leak any info about
+ // the private key.
+ return nil, cferr.New(cferr.PrivateKeyError,
+ cferr.ParseFailed)
+ }
+ }
+ }
+
+ switch generalKey.(type) {
+ case *rsa.PrivateKey:
+ return generalKey.(*rsa.PrivateKey), nil
+ case *ecdsa.PrivateKey:
+ return generalKey.(*ecdsa.PrivateKey), nil
+ }
+
+ // should never reach here
+ return nil, cferr.New(cferr.PrivateKeyError, cferr.ParseFailed)
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers.go
index 587fe0e96a0..c39e0af0afa 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers.go
@@ -1,5 +1,5 @@
// Package helpers implements utility functionality common to many
-// CF-SSL packages.
+// CFSSL packages.
package helpers
import (
@@ -10,11 +10,14 @@ import (
"crypto/x509"
"encoding/pem"
"errors"
+ //"fmt"
"strings"
"time"
- pkcs7 "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs7"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs12"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs7"
cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/derhelpers"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
)
@@ -128,6 +131,7 @@ func ParseCertificatesPEM(certsPEM []byte) ([]*x509.Certificate, error) {
var cert []*x509.Certificate
cert, certsPEM, err = ParseOneCertificateFromPEM(certsPEM)
if err != nil {
+
return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed)
} else if cert == nil {
break
@@ -141,6 +145,37 @@ func ParseCertificatesPEM(certsPEM []byte) ([]*x509.Certificate, error) {
return certs, nil
}
+// ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key,
+// either PKCS #7, PKCS #12, or raw x509.
+func ParseCertificatesDER(certsDER []byte, password string) ([]*x509.Certificate, crypto.Signer, error) {
+ var certs []*x509.Certificate
+ var key crypto.Signer
+ certsDER = bytes.TrimSpace(certsDER)
+ pkcs7data, err := pkcs7.ParsePKCS7(certsDER)
+ if err != nil {
+ pkcs12data, err := pkcs12.ParsePKCS12(certsDER, []byte(password))
+ if err != nil {
+ certs, err = x509.ParseCertificates(certsDER)
+ if err != nil {
+ //fmt.Println("\n\n\n\n\n\nCRITICALZONE\n\n\n\n\n\n\n\n\n\n")
+ return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
+ }
+ } else {
+ key = pkcs12data.PrivateKey
+ certs = pkcs12data.Certificates
+ }
+ } else {
+ if pkcs7data.ContentInfo != "SignedData" {
+ return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("Can only extract certificates from signed data content info"))
+ }
+ certs = pkcs7data.Content.SignedData.Certificates
+ }
+ if certs == nil {
+ return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
+ }
+ return certs, key, nil
+}
+
// ParseSelfSignedCertificatePEM parses a PEM-encoded certificate and check if it is self-signed.
func ParseSelfSignedCertificatePEM(certPEM []byte) (*x509.Certificate, error) {
cert, err := ParseCertificatePEM(certPEM)
@@ -189,9 +224,12 @@ func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, e
if err != nil {
return nil, rest, err
}
- certs := pkcs7data.Certificates
+ if pkcs7data.ContentInfo != "SignedData" {
+ return nil, rest, errors.New("Only PKCS #7 Signed Data Content Info supported for certificate parsing")
+ }
+ certs := pkcs7data.Content.SignedData.Certificates
if certs == nil {
- return nil, rest, errors.New("Pkcs#7 structure contains no certificates")
+ return nil, rest, errors.New("PKCS #7 structure contains no certificates")
}
return certs, rest, nil
}
@@ -208,37 +246,7 @@ func ParsePrivateKeyPEM(keyPEM []byte) (key crypto.Signer, err error) {
return nil, err
}
- return ParsePrivateKeyDER(keyDER)
-}
-
-// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve
-// DER-encoded private key. The key must not be in PEM format.
-func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
- generalKey, err := x509.ParsePKCS8PrivateKey(keyDER)
- if err != nil {
- generalKey, err = x509.ParsePKCS1PrivateKey(keyDER)
- if err != nil {
- generalKey, err = x509.ParseECPrivateKey(keyDER)
- if err != nil {
- // We don't include the actual error into
- // the final error. The reason might be
- // we don't want to leak any info about
- // the private key.
- return nil, cferr.New(cferr.PrivateKeyError,
- cferr.ParseFailed)
- }
- }
- }
-
- switch generalKey.(type) {
- case *rsa.PrivateKey:
- return generalKey.(*rsa.PrivateKey), nil
- case *ecdsa.PrivateKey:
- return generalKey.(*ecdsa.PrivateKey), nil
- }
-
- // should never reach here
- return nil, cferr.New(cferr.PrivateKeyError, cferr.ParseFailed)
+ return derhelpers.ParsePrivateKeyDER(keyDER)
}
// GetKeyDERFromPEM parses a PEM-encoded private key and returns DER-format key bytes.
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers_test.go
index fe72994330b..a4a6471f0de 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/helpers_test.go
@@ -14,24 +14,46 @@ import (
)
const (
- testCertFile = "testdata/cert.pem"
- testBundleFile = "testdata/bundle.pem"
- testExtraWSCertFile = "testdata/cert_with_whitespace.pem"
- testExtraWSBundleFile = "testdata/bundle_with_whitespace.pem"
- testMessedUpBundleFile = "testdata/messed_up_bundle.pem"
- testMessedUpCertFile = "testdata/messedupcert.pem"
- testEmptyCertFile = "testdata/emptycert.pem"
- testPrivateRSAKey = "testdata/priv_rsa_key.pem"
- testPrivateECDSAKey = "testdata/private_ecdsa_key.pem"
- testUnsupportedECDSAKey = "testdata/secp256k1-key.pem"
- testMessedUpPrivateKey = "testdata/messed_up_priv_key.pem"
- testEncryptedPrivateKey = "testdata/enc_priv_key.pem"
- testEmptyPem = "testdata/empty.pem"
- testNoHeaderCert = "testdata/noheadercert.pem"
- testSinglePKCS7 = "testdata/cert_pkcs7.pem"
- testMultiplePKCS7 = "testdata/bundle_pkcs7.pem"
+ testCertFile = "testdata/cert.pem"
+ testCertDERFile = "testdata/cert.der"
+ testBundleFile = "testdata/bundle.pem"
+ testExtraWSCertFile = "testdata/cert_with_whitespace.pem"
+ testExtraWSBundleFile = "testdata/bundle_with_whitespace.pem"
+ testMessedUpBundleFile = "testdata/messed_up_bundle.pem"
+ testMessedUpCertFile = "testdata/messedupcert.pem"
+ testEmptyCertFile = "testdata/emptycert.pem"
+ testPrivateRSAKey = "testdata/priv_rsa_key.pem"
+ testPrivateECDSAKey = "testdata/private_ecdsa_key.pem"
+ testUnsupportedECDSAKey = "testdata/secp256k1-key.pem"
+ testMessedUpPrivateKey = "testdata/messed_up_priv_key.pem"
+ testEncryptedPrivateKey = "testdata/enc_priv_key.pem"
+ testEmptyPem = "testdata/empty.pem"
+ testNoHeaderCert = "testdata/noheadercert.pem"
+ testSinglePKCS7 = "testdata/cert_pkcs7.pem"
+ testMultiplePKCS7 = "testdata/bundle_pkcs7.pem"
+ testPKCS12EmptyPswd = "testdata/emptypasswordpkcs12.p12"
+ testPKCS12Passwordispassword = "testdata/passwordpkcs12.p12"
+ testPKCS12MultipleCerts = "testdata/multiplecerts.p12"
)
+func TestParseCertificatesDER(t *testing.T) {
+ var password = []string{"password", "", "", "multiple"}
+ for i, testFile := range []string{testPKCS12Passwordispassword, testPKCS12EmptyPswd, testCertDERFile} {
+ testDER, err := ioutil.ReadFile(testFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, _, err := ParseCertificatesDER(testDER, password[i]); err != nil {
+ t.Fatal(err)
+ }
+ // Incorrect Password for PKCS12 formatted files
+ if _, _, err := ParseCertificatesDER(testDER, "incorrectpassword"); err == nil && i != 2 {
+ t.Fatal(err)
+ }
+ }
+
+}
+
func TestKeyLength(t *testing.T) {
expNil := 0
recNil := KeyLength(nil)
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/cert.der b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/cert.der
new file mode 100644
index 00000000000..fa90568bffc
Binary files /dev/null and b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/cert.der differ
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/emptypasswordpkcs12.p12 b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/emptypasswordpkcs12.p12
new file mode 100644
index 00000000000..335991ba44a
Binary files /dev/null and b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/emptypasswordpkcs12.p12 differ
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/multiplecerts.p12 b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/multiplecerts.p12
new file mode 100644
index 00000000000..bef8ca44f08
Binary files /dev/null and b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/multiplecerts.p12 differ
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/passwordpkcs12.p12 b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/passwordpkcs12.p12
new file mode 100644
index 00000000000..35fe6234581
Binary files /dev/null and b/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers/testdata/passwordpkcs12.p12 differ
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/info/info.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/info/info.go
new file mode 100644
index 00000000000..926a411ffbb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/info/info.go
@@ -0,0 +1,15 @@
+// Package info contains the definitions for the info endpoint
+package info
+
+// Req is the request struct for an info API request.
+type Req struct {
+ Label string `json:"label"`
+ Profile string `json:"profile"`
+}
+
+// Resp is the response for an Info API request.
+type Resp struct {
+ Certificate string `json:"certificate"`
+ Usage []string `json:"usages"`
+ ExpiryString string `json:"expiry"`
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca.go
index db775375747..94ba26cdf59 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca.go
@@ -23,24 +23,28 @@ import (
)
// validator contains the default validation logic for certificate
-// requests to the API server. This follows the Baseline Requirements
-// for the Issuance and Management of Publicly-Trusted Certificates,
-// v.1.1.6, from the CA/Browser Forum
-// (https://cabforum.org). Specifically, section 10.2.3 ("Information
-// Requirements"), states:
-//
-// "Applicant information MUST include, but not be limited to, at least one
-// Fully-Qualified Domain Name or IP address to be included in the Certificate’s
-// SubjectAltName extension."
+// authority certificates. The only requirement here is that the
+// certificate have a non-empty subject field.
func validator(req *csr.CertificateRequest) error {
- if len(req.Hosts) == 0 {
- return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing hosts field"))
+ if req.CN != "" {
+ return nil
}
+
+ if len(req.Names) == 0 {
+ return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information"))
+ }
+
+ for i := range req.Names {
+ if csr.IsNameEmpty(req.Names[i]) {
+ return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information"))
+ }
+ }
+
return nil
}
// New creates a new root certificate from the certificate request.
-func New(req *csr.CertificateRequest) (cert, key []byte, err error) {
+func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
if req.CA != nil {
if req.CA.Expiry != "" {
CAPolicy.Default.ExpiryString = req.CA.Expiry
@@ -53,7 +57,7 @@ func New(req *csr.CertificateRequest) (cert, key []byte, err error) {
}
g := &csr.Generator{Validator: validator}
- csr, key, err := g.ProcessRequest(req)
+ csrPEM, key, err = g.ProcessRequest(req)
if err != nil {
log.Errorf("failed to process request: %v", err)
key = nil
@@ -73,7 +77,7 @@ func New(req *csr.CertificateRequest) (cert, key []byte, err error) {
}
s.SetPolicy(CAPolicy)
- signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csr)}
+ signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
cert, err = s.Sign(signReq)
return
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca_test.go
index 373ff3d46a4..94f74f0d0fb 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/initca/initca_test.go
@@ -93,7 +93,7 @@ func TestInitCA(t *testing.T) {
Size: param.keyLen,
},
}
- certBytes, keyBytes, err := New(req)
+ certBytes, _, keyBytes, err := New(req)
if err != nil {
t.Fatal("InitCA failed:", err)
}
@@ -169,35 +169,6 @@ func TestInitCA(t *testing.T) {
}
}
-func TestNoHostname(t *testing.T) {
- req := &csr.CertificateRequest{
- Names: []csr.Name{
- {
- C: "US",
- ST: "California",
- L: "San Francisco",
- O: "CloudFlare",
- OU: "Systems Engineering",
- },
- },
- CN: "cloudflare.com",
- // Empty hosts
- Hosts: []string{},
- KeyRequest: &csr.KeyRequest{
- Algo: "rsa",
- Size: 2048,
- },
- }
- _, _, err := New(req)
- if err == nil {
- t.Fatal("InitCA should failed.")
- }
-
- if !strings.Contains(err.Error(), `"code":5300`) {
- t.Fatal(err)
- }
-}
-
func TestInvalidCryptoParams(t *testing.T) {
var req *csr.CertificateRequest
hostname := "cloudflare.com"
@@ -219,7 +190,7 @@ func TestInvalidCryptoParams(t *testing.T) {
Size: test.keyLen,
},
}
- _, _, err := New(req)
+ _, _, _, err := New(req)
if err == nil {
t.Fatal("InitCA with bad params should fail:", err)
}
@@ -229,3 +200,36 @@ func TestInvalidCryptoParams(t *testing.T) {
}
}
}
+
+type validation struct {
+ r *csr.CertificateRequest
+ v bool
+}
+
+var testValidations = []validation{
+ {&csr.CertificateRequest{}, false},
+ {&csr.CertificateRequest{
+ CN: "test CA",
+ }, true},
+ {&csr.CertificateRequest{
+ Names: []csr.Name{csr.Name{}},
+ }, false},
+ {&csr.CertificateRequest{
+ Names: []csr.Name{
+ csr.Name{O: "Example CA"},
+ },
+ }, true},
+}
+
+func TestValidations(t *testing.T) {
+ for i, tv := range testValidations {
+ err := validator(tv.r)
+ if tv.v && err != nil {
+ t.Fatalf("%v", err)
+ }
+
+ if !tv.v && err == nil {
+ t.Fatalf("%d: expected error, but no error was reported", i)
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config/config.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config/config.go
new file mode 100644
index 00000000000..2f9eb307f5c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config/config.go
@@ -0,0 +1,28 @@
+// Package config in the ocsp directory provides configuration data for an OCSP
+// signer.
+package config
+
+import (
+ "time"
+)
+
+// Config contains configuration information required to set up an OCSP
+// signer. If PKCS11.Module is non-empty, PKCS11 signing will be used.
+// Otherwise signing from a key file will be used.
+type Config struct {
+ CACertFile string
+ ResponderCertFile string
+ KeyFile string
+ Interval time.Duration
+ PKCS11 PKCS11Config
+}
+
+// PKCS11Config contains information specific to setting up a PKCS11 OCSP
+// signer.
+type PKCS11Config struct {
+ Module string
+ Token string
+ PIN string
+ Label string
+}
+
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/ocsp_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/ocsp_test.go
new file mode 100644
index 00000000000..8e2977efe5b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/ocsp_test.go
@@ -0,0 +1,151 @@
+package ocsp
+
+import (
+ "io/ioutil"
+ "testing"
+ "time"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+)
+
+const (
+ serverCertFile = "testdata/ca.pem"
+ serverKeyFile = "testdata/ca-key.pem"
+ otherCertFile = "testdata/cert.pem"
+ brokenServerCert = "testdata/server_broken.crt"
+ brokenServerKey = "testdata/server_broken.key"
+ wrongServerCertFile = "testdata/server.crt"
+ wrongServerKeyFile = "testdata/server.key"
+ responseFile = "testdata/resp64.pem"
+ binResponseFile = "testdata/response.pem"
+ brokenResponseFile = "testdata/response_broken.pem"
+ mixResponseFile = "testdata/response_mix.pem"
+)
+
+func TestNewSignerFromFile(t *testing.T) {
+ // arbitrary duration
+ dur, _ := time.ParseDuration("1ms")
+
+ // nonexistent files
+ _, err := NewSignerFromFile("", "", "", dur)
+ if err == nil {
+ t.Fatal("Failed to issue error on improper file")
+ }
+
+ _, err = NewSignerFromFile(serverCertFile, "", "", dur)
+ if err == nil {
+ t.Fatal("Failed to issue error on improper file")
+ }
+
+ _, err = NewSignerFromFile(serverCertFile, otherCertFile, "", dur)
+ if err == nil {
+ t.Fatal("Failed to issue error on improper file")
+ }
+
+ // malformed certs
+ _, err = NewSignerFromFile(brokenServerCert, otherCertFile, serverKeyFile, dur)
+ if err == nil {
+ t.Fatal("Didn't fail on malformed file")
+ }
+
+ _, err = NewSignerFromFile(serverCertFile, brokenServerCert, serverKeyFile, dur)
+ if err == nil {
+ t.Fatal("Didn't fail on malformed file")
+ }
+
+ _, err = NewSignerFromFile(serverCertFile, otherCertFile, brokenServerKey, dur)
+ if err == nil {
+ t.Fatal("Didn't fail on malformed file")
+ }
+
+ // expected case
+ _, err = NewSignerFromFile(serverCertFile, otherCertFile, serverKeyFile, dur)
+ if err != nil {
+ t.Fatalf("Signer creation failed %v", err)
+ }
+}
+
+func TestSign(t *testing.T) {
+ dur, _ := time.ParseDuration("1ms")
+ // expected case
+ s, err := NewSignerFromFile(serverCertFile, otherCertFile, serverKeyFile, dur)
+ if err != nil {
+ t.Fatalf("Signer creation failed: %v", err)
+ }
+
+ _, err = s.Sign(SignRequest{})
+ if err == nil {
+ t.Fatal("Signed request with nil certificate")
+ }
+
+ certPEM, err := ioutil.ReadFile(otherCertFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cert, err := helpers.ParseCertificatePEM(certPEM)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ req := SignRequest{
+ Certificate: cert,
+ Status: "good",
+ }
+
+ _, err = s.Sign(req)
+ if err != nil {
+ t.Fatal("Sign failed")
+ }
+
+ sMismatch, err := NewSignerFromFile(wrongServerCertFile, otherCertFile, wrongServerKeyFile, dur)
+ _, err = sMismatch.Sign(req)
+ if err == nil {
+ t.Fatal("Signed a certificate from the wrong issuer")
+ }
+
+ // incorrect status code
+ req.Status = "aalkjsfdlkafdslkjahds"
+ _, err = s.Sign(req)
+ if err == nil {
+ t.Fatal("Failed to fail on improper status code")
+ }
+
+ // revoked
+ req.Status = "revoked"
+ _, err = s.Sign(req)
+ if err != nil {
+ t.Fatal("Error on revoked certificate")
+ }
+}
+
+func TestNewSourceFromFile(t *testing.T) {
+ _, err := NewSourceFromFile("")
+ if err == nil {
+ t.Fatal("Didn't fail on non-file input")
+ }
+
+ // expected case
+ _, err = NewSourceFromFile(responseFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // binary-formatted file
+ _, err = NewSourceFromFile(binResponseFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // the response file from before, with stuff deleted
+ _, err = NewSourceFromFile(brokenResponseFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // mix of a correct and malformed responses
+ _, err = NewSourceFromFile(mixResponseFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/pkcs11/pkcs11.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/pkcs11/pkcs11.go
new file mode 100644
index 00000000000..3d2f7f76ce8
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/pkcs11/pkcs11.go
@@ -0,0 +1,42 @@
+// Package pkcs11 in the ocsp directory provides a way to construct a
+// PKCS#11-based OCSP signer. It is only available in binaries built with the
+// pkcs11 tag, i.e. `go build -tags pkcs11 ./cmd/cfssl`.
+// +build pkcs11
+
+package pkcs11
+
+import (
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
+ ocspConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config"
+ "io/ioutil"
+)
+
+// Enabled is set to true if PKCS #11 support is present.
+const Enabled = true
+
+// New returns a new PKCS #11 signer.
+func NewPKCS11Signer(cfg ocspConfig.Config) (ocsp.Signer, error) {
+ log.Debugf("Loading PKCS #11 module %s", cfg.PKCS11.Module)
+ certData, err := ioutil.ReadFile(cfg.CACertFile)
+ if err != nil {
+ return nil, errors.New(errors.CertificateError, errors.ReadFailed)
+ }
+
+ cert, err := helpers.ParseCertificatePEM(certData)
+ if err != nil {
+ return nil, err
+ }
+
+ PKCS11 := cfg.PKCS11
+ priv, err := pkcs11key.New(PKCS11.Module, PKCS11.Token, PKCS11.PIN,
+ PKCS11.Label)
+ if err != nil {
+ return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
+ }
+
+ return ocsp.NewSigner(cert, cert, priv, cfg.Interval)
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/pkcs11/pkcs11_stub.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/pkcs11/pkcs11_stub.go
new file mode 100644
index 00000000000..73c27511d3e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/pkcs11/pkcs11_stub.go
@@ -0,0 +1,17 @@
+// +build !pkcs11
+
+package pkcs11
+
+import (
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
+ ocspConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config"
+)
+
+// Enabled is set to true if PKCS #11 support is present.
+const Enabled = false
+
+// NewPKCS11Signer returns a new PKCS #11 signer.
+func NewPKCS11Signer(cfg ocspConfig.Config) (ocsp.Signer, error) {
+ return nil, errors.New(errors.PrivateKeyError, errors.Unavailable)
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/ca-key.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/ca-key.pem
new file mode 100644
index 00000000000..5d4f8b557a2
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/ca-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAvKOCXwP8Y6x1YkjcimQafnP1bRCF/iWY+z4ffuTWA150RRpA
+GnhwOen8muU5wxOEm1A2IkWhNfXQ9GYVdOnzXumTx9Go4Gm8/1nRCYG69GZbQAEr
+pNGx/l4wReLVj2iizCf/xkcch5ZM/5zplXWZXCQiavmKz6M+1aSYdsGP0mrLu31c
+yod2iJmlISt+nuP5yXkgoKxzGrKjP5qrs6XniVXrKMt+5g1Ta5blWUoft2pwM6yp
+8+IAtxh+iYTIJc8dDHbVl9AjVfsfaYeS8SkHcIRyIuD8/3HgLmP/gMLDzuLXvH+W
+slOEYqLGMkSo2JPOwLguggDyjt1rI2cEcFkgJwIDAQABAoIBAQCTAZW6+D87ag28
+f22nR+XBwBp2WVcivSggO8SNvkXuMDDKHW/xcQR8jZW3HIZMOSyxYOwe/0Zn595k
+aB22lA9+Wuc45HIIGT8ZfGREVV5d0lqwYXkio+xjgAF8pQ6rCO89zLouSgK4w2/U
+D/OU7yWJwfs0hK4hrGVuVywd+DBd2Fc7UfZ4oEcy89mwUIRVK8+eXrRCav6lGDrz
+I+GmW6GL16U8lS8vsUNciYyNYCzgSIIa/yyiZO/Aje93yJRVpmujAK2p6/w/7vmK
+OareeixlpNYpiY7Nk6o3w6sKEEVzf+AquDgeH5IkzD1nkYbd+JY7bdg1cgjz3kJg
+IhsiIER5AoGBAOkZpicTIsiAMxz43bzMt1IMYu1ezAEw4Vk2sVEbSfFXdbO5J9gW
+/Ou+AhwxhsDeO6vgh3mYkG+2s5U+ztk68X1BVIf87kYBQiz175XvxcLmDBFm5S6g
+eyTCwsop9J4XlgQQ5HNm80G9oHnF50oujCqpUiC5xj5fEd8vULmua5jTAoGBAM8r
+rTTpVBHKArDlzYF5EpyXDkcFT2uAgw9Xpc6xIl/UWQ+XU1qD5Te0fmjpdwo3VZTL
+W2e8eg0U9O2skrxBcRLREnh1U2znCMSIGTkwYQ2JDjhz2Jjbh8r/NhvSdydql9wQ
+LGyPOIpcURaD+ohOExF82EtEqWgNp4QfQHH70cbdAoGAPBoy7yxN8aishTHd6opW
+Uj+DWnTw4PW7hQdHHQSOQj4syRRao6r5t8ccQCy89AnZFO4lwEKIK2XOVBMHvpcm
+IQexRgb/YOl+KJ2ZEu3p7eDnB62iNi2G0ums0/eRbRnjwlSgsui+nBrKv9s5UbVC
+ytUxqeJ8rSRSNVu70sSYVaUCgYALYUrSbT7A+2fKb9UqF4x+LY4LOK90KEsKvLXO
+9Mv+l5uMz7M0dapRtQh8mtZ/KSr6UXFj8WaC8XPC2of072NWtUVeeJNsmARTR2ab
+TZ0HMVAmqbZsLyL2c651OMpyz9gnrnvCOtvQPeH2aqmIc0F45HK9L7hejuF00IKp
+wDt1wQKBgQC8sjlF/8e03m3AfLs2ZW/w0Rsggz52TgBdH24BMUmvd5McVZlH8uZq
+zwx5ht3ppVjObG28JPEj8c/FtAmsUjURDD7EVdjb5bDxrMtH++8sHrXUuMMBeUxl
+DN2IU+xL9MwMh5H0cyJbXnE+LWGpSefCccDnH5qlEjwNXE5/RggOrw==
+-----END RSA PRIVATE KEY-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/ca.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/ca.pem
new file mode 100644
index 00000000000..9775b857c0f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/ca.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqigAwIBAgIIWhorb65IXvUwCwYJKoZIhvcNAQELMG0xCzAJBgNVBAYT
+AlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJlMRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2lu
+ZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9y
+bmlhMB4XDTE1MDQxOTE2MTAwMFoXDTIwMDQxNzE2MTAwMFowbTELMAkGA1UEBhMC
+VVMxEzARBgNVBAoTCkNsb3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5l
+ZXJpbmcxFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3Ju
+aWEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8o4JfA/xjrHViSNyK
+ZBp+c/VtEIX+JZj7Ph9+5NYDXnRFGkAaeHA56fya5TnDE4SbUDYiRaE19dD0ZhV0
+6fNe6ZPH0ajgabz/WdEJgbr0ZltAASuk0bH+XjBF4tWPaKLMJ//GRxyHlkz/nOmV
+dZlcJCJq+YrPoz7VpJh2wY/Sasu7fVzKh3aImaUhK36e4/nJeSCgrHMasqM/mquz
+peeJVesoy37mDVNrluVZSh+3anAzrKnz4gC3GH6JhMglzx0MdtWX0CNV+x9ph5Lx
+KQdwhHIi4Pz/ceAuY/+AwsPO4te8f5ayU4RiosYyRKjYk87AuC6CAPKO3WsjZwRw
+WSAnAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIABjASBgNVHRMBAf8ECDAGAQH/AgEC
+MB0GA1UdDgQWBBSrzjPP4Y5PLsqeyp6iddofBjoRmTAfBgNVHSMEGDAWgBSrzjPP
+4Y5PLsqeyp6iddofBjoRmTALBgkqhkiG9w0BAQsDggEBAH7McpSm7+DeIZPQKYpF
+kFUlNn3N4MRvek5lxOw6jLE1QmzG3lTB79g6iBiGKsYLPoJqNS6VxMoLrMC+qFhM
+0QM5eIzRpdfYa83IDIYcbUYx7fLG/azX+FMFh/O5yPtS+bqbxGinxofRIyuKGs9r
+dks6I5lGncRs0Liysp4mHJAjyj9G2W2onI3Y00BYhiOy4mYvZ5/S31KI4550HZ+p
+dnexuC29CsWGkOTXTOS7+e7Zmbh8UjsYcA5YOojew+EjJfETPVO+Pn7WGg/+XrFX
+8UOG3o9k8M0ePQof4R6FTJ+BQxtSkWWdp1HrMQbZ1TXfZx84XkmFdcmy8FjYiHbP
+M+M=
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/cert.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/cert.pem
new file mode 100644
index 00000000000..f3cad55e49f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/cert.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID4TCCAsugAwIBAgIIEoDcqfKl/s4wCwYJKoZIhvcNAQELMG0xCzAJBgNVBAYT
+AlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJlMRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2lu
+ZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9y
+bmlhMB4XDTE1MDQxOTE2MTkwMFoXDTE2MDQxODE2MTkwMFowXTELMAkGA1UEBhMC
+VVMxEDAOBgNVBAoTB0V4YW1wbGUxDzANBgNVBAsTBlRoaW5nczEWMBQGA1UEBxMN
+U2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZvcm5pYTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAK7jUnRUeD5QY9YPjbW6aiGkVWRWAebi4nZl++C+
+HEBHSyB0jXX+J93y97PuhgeguCuMM6KZU7C0tPZKjwdxBSqpXeyFpvcj+UWMjZjz
+9FrBAzZ1DIYquqfYuKUtavoFv29IomRqzyZ4FrMJ2qy0RudnWMTqn4P6/7DrWos+
+oJMCpl/mdWl+YXMXypgW5JwM7ladx8GkEKQwGMtXrG9pop7qS6LNikN76tLPYWjR
+DhrWLBe8gCGjuXkwvxw78CeeJNyWF+P/+x4lVsWphip3jX57SUx/bjaRjsWSfpMz
+xHueHtuCrGffgCkFzYH1/Z60FZNxuHYqJeL4V3gcR8IIaZECAwEAAaOBmDCBlTAO
+BgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwG
+A1UdEwEB/wQCMAAwHQYDVR0OBBYEFBnFrxc1gkG2CYImTYKL0DAaGxRBMB8GA1Ud
+IwQYMBaAFKvOM8/hjk8uyp7KnqJ12h8GOhGZMBYGA1UdEQQPMA2CC2V4YW1wbGUu
+Y29tMAsGCSqGSIb3DQEBCwOCAQEAX31Jk7R9gDMw/gepIxxeKx9m+c7eOYDxjJ12
+bfXQVKNNPLZsO9M9r2/0BCTFsNTF2jh6ZTeIf7qy+Jw08YqTcO5m8jhiGzCjOYu5
+tiGxCUe+cYjXcCRk83+XGkVrQm3fQ0cVtic0yfm/fez3iv915jH0GYO5X8/d7bKa
+0kWJ3uOjur6tenfnisypEsuYYjPRcQdXSG6/qgHEc4r279Z2ltjy1bFFr86hHUbj
+DX7XNWH/MXFgqLzfQm5VzmqBj9om+0/tgTWdkgI1DK/Hnvm9A4YZfaxh4fxv7ITo
+Ce8FWW13Wj55x64peb8ZiW1jUyoaJQcxQxFpRHIVu26nXApWtg==
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/resp64.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/resp64.pem
new file mode 100644
index 00000000000..c5152dc779c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/resp64.pem
@@ -0,0 +1 @@
+MIICGAoBAKCCAhEwggINBgkrBgEFBQcwAQEEggH+MIIB+jCB46ADAgEAoV8wXTELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGUxDzANBgNVBAsTBlRoaW5nczEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZvcm5pYRcRMTUwNDIzMTkwODAwLTA0MDAwaDBmMDswCQYFKw4DAhoFAAQUKO/Z4m+OZ4ZSKS2J85Kr9UaI2LAEFKvOM8/hjk8uyp7KnqJ12h8GOhGZAgIBdaADAQH/GA8wMDAxMDEwMTAwMDAwMFqgERgPMDAwMTAxMDEwMDAwMDBaMA0GCSqGSIb3DQEBCwUAA4IBAQCBGs+8UNwUdkEBladnajZIV+sHtmao/mMTIvpyPqnmV2Ab9KfNWlSDSDuMtZYKS4VsEwtbZ+4kKWI8DugE6egjP3o64R7VP2aqrh41IORwccLGVsexILBpxg4h602JbhXM0sxgXoh5WAt9f1oy6PsHAt/XAuJGSo7yMNv3nHKNFwjExmZt21sNLYlWlljjtX92rlo/mBTWKO0js4YRNyeNQhchARbn9oL18jW0yAVqB9a8rees+EippbTfoktFf0cIhnmkiknPZSZ+dN2qHkxiXIujWlymZzUZcqRTNtrmmhlOdt35QSg7Vw8eyw2rl8ZU94zaI5DPWn1QYn0dk7l9
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response.pem
new file mode 100644
index 00000000000..bd43e37bfd1
Binary files /dev/null and b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response.pem differ
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response_broken.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response_broken.pem
new file mode 100644
index 00000000000..29a64c66661
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response_broken.pem
@@ -0,0 +1 @@
+MIICGAoBAKCCAhEwggINBgkrBgEFBQcwAQEEggH+OZ4ZSKS2J85Kr9UaI2LAEFKvOM8/hjk8uyp7KnqJ12h8GOhGZAgIBdaADAQH/GA8wMDAxMDEwMTAwMDAwMFqgERgPMDAwMTAxMDEwMDAwMDBaMA0GCSqGSIb3DQEBCwUAA4IBAQCBGs+8UNwUdkEBladnajZIV+sHtmao/mMTIvpyPqnmV2Ab9KfNWlSDSDuMtZYKS4VsEwtbZ+4kKWI8DugE6egjP3o64R7VP2aqrh41IORwccLGVsexILBpxg4h602JbhXM0sxgXoh5WAt9f1oy6PsHAt/XAuJGSo7yMNv3nHKNFwjExmZt21sNLYlWlljjtX92rlo/mBTWKO0js4YRNyeNQhchARbn9oL18jW0yAVqB9a8rees+EippbTfoktFf0cIhnmkiknPZSZ+dN2qHkxiXIujWlymZzUZcqRTNtrmmhlOdt35QSg7Vw8eyw2rl8ZU94zaI5DPWn1QYn0dk7l9
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response_mix.pem b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response_mix.pem
new file mode 100644
index 00000000000..43249fb0aeb
Binary files /dev/null and b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/response_mix.pem differ
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server.crt
new file mode 100644
index 00000000000..9e4deb0e995
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server.crt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIICATCCAWoCCQDidF+uNJR6czANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTEyMDUwMTIyNTUxN1oXDTEzMDUwMTIyNTUxN1owRTELMAkG
+A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtpjl
+nodhz31kLEJoeLSkRmrv8l7exkGtO0REtIbirj9BBy64ZXVBE7khKGO2cnM8U7yj
+w7Ntfh+IvCjZVA3d2XqHS3Pjrt4HmU/cGCONE8+NEXoqdzLUDPOix1qDDRBvXs81
+KAV2qh6CYHZbdqixhDerjvJcD4Nsd7kExEZfHuECAwEAATANBgkqhkiG9w0BAQUF
+AAOBgQCyOqs7+qpMrYCgL6OamDeCVojLoEp036PsnaYWf2NPmsVXdpYW40Foyyjp
+iv5otkxO5rxtGPv7o2J1eMBpCuSkydvoz3Ey/QwGqbBwEXQ4xYCgra336gqW2KQt
++LnDCkE8f5oBhCIisExc2i8PDvsRsY70g/2gs983ImJjVR8sDw==
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server.key b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server.key
new file mode 100644
index 00000000000..ab101624c3f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQC2mOWeh2HPfWQsQmh4tKRGau/yXt7GQa07RES0huKuP0EHLrhl
+dUETuSEoY7ZyczxTvKPDs21+H4i8KNlUDd3ZeodLc+Ou3geZT9wYI40Tz40Reip3
+MtQM86LHWoMNEG9ezzUoBXaqHoJgdlt2qLGEN6uO8lwPg2x3uQTERl8e4QIDAQAB
+AoGAVxnsPojZ8X4g8LPk3d9dlXGhb/4tSmk9102jcHH/Y5ssy95Pe6ZJGr1uwbN+
+7m1l05PikpHeoxEryoW51cyfjDVkXUT0zPp2JC38DUA/0A8qWav/aENM64wg1I0P
+Dil8FywzZEonRNJst53+9cxFye70ely5br/tWxEp4/MsM1kCQQDqV4Lwn8BXOeKg
+xOwNmcL+0XPedvSPBSPUoGJCzu12rH6Z+UHXipXsqRNSyQ+KGlur14y0kCh5uiVA
+jmWYVEEjAkEAx3keAo1nFsVW35EPt5LIbh6L6ty7GrvGRvOVeSd6YLtixMety24k
+hpt1cEv2xlFnbjbBbMkr9eUiUNpttLT6KwJBANGKaLoSjqEwUFYjX1OV/wdtcGcn
+BOzx0qUouFQ2xZ0NBrNVbyt1bzPLx0yKHkwF35ybw+Qc1yRpby/3ZB6+j/MCQFLl
+vtcItOL9uBDJVGLSGYHKKBO/D/MYPlqWOHRVN8KjnXRyF4QHjh5y1OeKalAY3Ict
+Mk1nfWF/jDdVz2neHGkCQHHBR4Xt1/euDku+14z5aLpphTEQVuRD2vQoeKi/W/CY
+OgNmKj1DzucnCS6yRCrF8Q0Pn8l054a3Wdbl1gqI/gA=
+-----END RSA PRIVATE KEY-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.crt b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.crt
new file mode 100644
index 00000000000..09f3f52a442
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.crt
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtpjl
+nodhz31kLEJoeLSkRmrv8l7exkGtO0REtIbirj9BBy64ZXVBE7khKGO2cnM8U7yj
+w7Ntfh+IvCjZVA3d2XqHS3Pjrt4HmU/cGCONE8+NEXoqdzLUDPOix1qDDRBvXs81
+KAV2qh6CYHZbdqixhDerjvJcD4Nsd7kExEZfHuECAwEAATANBgkqhkiG9w0BAQUF
+AAOBgQCyOqs7+qpMrYCgL6OamDeCVojLoEp036PsnaYWf2NPmsVXdpYW40Foyyjp
+iv5otkxO5rxtGPv7o2J1eMBpCuSkydvoz3Ey/QwGqbBwEXQ4xYCgra336gqW2KQt
++LnDCkE8f5oBhCIisExc2i8PDvsRsY70g/2gs983ImJjVR8sDw==
+-----END CERTIFICATE-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.key b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.key
new file mode 100644
index 00000000000..98e860f7340
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.key
@@ -0,0 +1,8 @@
+-----BEGIN RSA PRIVATE KEY-----
+jmWYVEEjAkEAx3keAo1nFsVW35EPt5LIbh6L6ty7GrvGRvOVeSd6YLtixMety24k
+hpt1cEv2xlFnbjbBbMkr9eUiUNpttLT6KwJBANGKaLoSjqEwUFYjX1OV/wdtcGcn
+BOzx0qUouFQ2xZ0NBrNVbyt1bzPLx0yKHkwF35ybw+Qc1yRpby/3ZB6+j/MCQFLl
+vtcItOL9uBDJVGLSGYHKKBO/D/MYPlqWOHRVN8KjnXRyF4QHjh5y1OeKalAY3Ict
+Mk1nfWF/jDdVz2neHGkCQHHBR4Xt1/euDku+14z5aLpphTEQVuRD2vQoeKi/W/CY
+OgNmKj1DzucnCS6yRCrF8Q0Pn8l054a3Wdbl1gqI/gA=
+-----END RSA PRIVATE KEY-----
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/universal/universal.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/universal/universal.go
new file mode 100644
index 00000000000..76b82b4c8f1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/universal/universal.go
@@ -0,0 +1,16 @@
+package universal
+
+import (
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
+ ocspConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/pkcs11"
+)
+
+// NewSignerFromConfig generates a new OCSP signer from a config object.
+func NewSignerFromConfig(cfg ocspConfig.Config) (ocsp.Signer, error) {
+ if cfg.PKCS11.Module != "" {
+ return pkcs11.NewPKCS11Signer(cfg)
+ }
+ return ocsp.NewSignerFromFile(cfg.CACertFile, cfg.ResponderCertFile,
+ cfg.KeyFile, cfg.Interval)
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/revoke/revoke.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/revoke/revoke.go
new file mode 100644
index 00000000000..3056925d4cd
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/revoke/revoke.go
@@ -0,0 +1,281 @@
+// Package revoke provides functionality for checking the validity of
+// a cert. Specifically, the temporal validity of the certificate is
+// checked first, then any CRL in the cert is checked. OCSP is not
+// supported at this time.
+package revoke
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/base64"
+ "encoding/pem"
+ "errors"
+ "io/ioutil"
+ "net/http"
+ neturl "net/url"
+ "time"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/crypto/ocsp"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
+)
+
+// HardFail determines whether the failure to check the revocation
+// status of a certificate (i.e. due to network failure) causes
+// verification to fail (a hard failure).
+var HardFail = false
+
+// TODO (kyle): figure out a good mechanism for OCSP; this requires
+// presenting both the certificate and the issuer, and we don't have a
+// good way at this time of getting the issuer.
+
+// CRLSet associates a PKIX certificate list with the URL the CRL is
+// fetched from.
+var CRLSet = map[string]*pkix.CertificateList{}
+
+// We can't handle LDAP certificates, so this checks to see if the
+// URL string points to an LDAP resource so that we can ignore it.
+func ldapURL(url string) bool {
+ u, err := neturl.Parse(url)
+ if err != nil {
+ log.Warningf("error parsing url %s: %v", url, err)
+ return false
+ }
+ if u.Scheme == "ldap" {
+ return true
+ }
+ return false
+}
+
+// revCheck should check the certificate for any revocations. It
+// returns a pair of booleans: the first indicates whether the certificate
+// is revoked, the second indicates whether the revocations were
+// successfully checked.. This leads to the following combinations:
+//
+// false, false: an error was encountered while checking revocations.
+//
+// false, true: the certificate was checked successfully and
+// it is not revoked.
+//
+// true, true: the certificate was checked successfully and
+// it is revoked.
+//
+// true, false: failure to check revocation status causes
+// verification to fail
+func revCheck(cert *x509.Certificate) (revoked, ok bool) {
+ for _, url := range cert.CRLDistributionPoints {
+ if ldapURL(url) {
+ log.Infof("skipping LDAP CRL: %s", url)
+ continue
+ }
+
+ if revoked, ok := certIsRevokedCRL(cert, url); !ok {
+ log.Warning("error checking revocation via CRL")
+ if HardFail {
+ return true, false
+ }
+ return false, false
+ } else if revoked {
+ log.Info("certificate is revoked via CRL")
+ return true, true
+ }
+
+ if revoked, ok := certIsRevokedOCSP(cert, HardFail); !ok {
+ log.Warning("error checking revocation via OCSP")
+ if HardFail {
+ return true, false
+ }
+ return false, false
+ } else if revoked {
+ log.Info("certificate is revoked via OCSP")
+ return true, true
+ }
+ }
+
+ return false, true
+}
+
+// fetchCRL fetches and parses a CRL.
+func fetchCRL(url string) (*pkix.CertificateList, error) {
+ resp, err := http.Get(url)
+ if err != nil {
+ return nil, err
+ } else if resp.StatusCode >= 300 {
+ return nil, errors.New("failed to retrieve CRL")
+ }
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ resp.Body.Close()
+
+ return x509.ParseCRL(body)
+}
+
+// check a cert against a specific CRL. Returns the same bool pair
+// as revCheck.
+func certIsRevokedCRL(cert *x509.Certificate, url string) (revoked, ok bool) {
+ crl, ok := CRLSet[url]
+ if ok && crl == nil {
+ ok = false
+ delete(CRLSet, url)
+ }
+
+ var shouldFetchCRL = true
+ if ok {
+ if !crl.HasExpired(time.Now()) {
+ shouldFetchCRL = false
+ }
+ }
+
+ if shouldFetchCRL {
+ var err error
+ crl, err = fetchCRL(url)
+ if err != nil {
+ log.Warningf("failed to fetch CRL: %v", err)
+ return false, false
+ }
+ CRLSet[url] = crl
+ }
+
+ for _, revoked := range crl.TBSCertList.RevokedCertificates {
+ if cert.SerialNumber.Cmp(revoked.SerialNumber) == 0 {
+ log.Info("Serial number match: intermediate is revoked.")
+ return true, true
+ }
+ }
+
+ return false, true
+}
+
+// VerifyCertificate ensures that the certificate passed in hasn't
+// expired and checks the CRL for the server.
+func VerifyCertificate(cert *x509.Certificate) (revoked, ok bool) {
+ if !time.Now().Before(cert.NotAfter) {
+ log.Infof("Certificate expired %s\n", cert.NotAfter)
+ return true, true
+ } else if !time.Now().After(cert.NotBefore) {
+ log.Infof("Certificate isn't valid until %s\n", cert.NotBefore)
+ return true, true
+ }
+
+ return revCheck(cert)
+}
+
+func fetchRemote(url string) (*x509.Certificate, error) {
+ resp, err := http.Get(url)
+ if err != nil {
+ return nil, err
+ }
+
+ in, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ resp.Body.Close()
+
+ p, _ := pem.Decode(in)
+ if p != nil {
+ return helpers.ParseCertificatePEM(in)
+ }
+
+ return x509.ParseCertificate(in)
+}
+
+var ocspOpts = ocsp.RequestOptions{
+ Hash: crypto.SHA1,
+}
+
+func certIsRevokedOCSP(leaf *x509.Certificate, strict bool) (revoked, ok bool) {
+ var err error
+
+ ocspURLs := leaf.OCSPServer
+ if len(ocspURLs) == 0 {
+ // OCSP not enabled for this certificate.
+ return false, true
+ }
+
+ var issuer *x509.Certificate
+ for _, issuingCert := range leaf.IssuingCertificateURL {
+ issuer, err = fetchRemote(issuingCert)
+ if err != nil {
+ continue
+ }
+ break
+ }
+
+ if issuer == nil {
+ return
+ }
+
+ ocspRequest, err := ocsp.CreateRequest(leaf, issuer, &ocspOpts)
+ if err != nil {
+ return
+ }
+
+ for _, server := range ocspURLs {
+ resp, err := sendOCSPRequest(server, ocspRequest, issuer)
+ if err != nil {
+ if strict {
+ return
+ }
+ continue
+ }
+
+ // There wasn't an error fetching the OCSP status.
+ ok = true
+
+ if resp.Status != ocsp.Good {
+ // The certificate was revoked.
+ revoked = true
+ }
+
+ return
+ }
+ return
+}
+
+var ocspUnauthorised = []byte{0x30, 0x03, 0x0a, 0x01, 0x06}
+var ocspMalformed = []byte{0x30, 0x03, 0x0a, 0x01, 0x01}
+
+// sendOCSPRequest attempts to request an OCSP response from the
+// server. The error only indicates a failure to *fetch* the
+// certificate, and *does not* mean the certificate is valid.
+func sendOCSPRequest(server string, req []byte, issuer *x509.Certificate) (ocspResponse *ocsp.Response, err error) {
+ var resp *http.Response
+ if len(req) > 256 {
+ buf := bytes.NewBuffer(req)
+ resp, err = http.Post(server, "application/ocsp-request", buf)
+ } else {
+ reqURL := server + "/" + base64.StdEncoding.EncodeToString(req)
+ resp, err = http.Get(reqURL)
+ }
+
+ if err != nil {
+ return
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ return
+ }
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return
+ }
+ resp.Body.Close()
+
+ if bytes.Equal(body, ocspUnauthorised) {
+ return
+ }
+
+ if bytes.Equal(body, ocspMalformed) {
+ return
+ }
+
+ return ocsp.ParseResponse(body, issuer)
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/revoke/revoke_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/revoke/revoke_test.go
new file mode 100644
index 00000000000..02e5baa0675
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/revoke/revoke_test.go
@@ -0,0 +1,223 @@
+package revoke
+
+import (
+ "crypto/x509"
+ //"crypto/x509/pkix"
+ "encoding/pem"
+ "fmt"
+ "os"
+ "testing"
+ "time"
+)
+
+// The first three test cases represent known revoked, expired, and good
+// certificates that were checked on the date listed in the log. The
+// good certificate will eventually need to be replaced.
+
+// If there is a soft-fail, the test will pass to mimic the default
+// behaviour used in this software. However, it will print a warning
+// to indicate that this is the case.
+
+// 2014/05/22 14:18:17 Certificate expired 2014-04-04 14:14:20 +0000 UTC
+// 2014/05/22 14:18:17 Revoked certificate: misc/intermediate_ca/ActalisServerAuthenticationCA.crt
+var expiredCert = mustParse(`-----BEGIN CERTIFICATE-----
+MIIEXTCCA8agAwIBAgIEBycURTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
+UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
+cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
+b2JhbCBSb290MB4XDTA3MDQwNDE0MTUxNFoXDTE0MDQwNDE0MTQyMFowejELMAkG
+A1UEBhMCSVQxFzAVBgNVBAoTDkFjdGFsaXMgUy5wLkEuMScwJQYDVQQLEx5DZXJ0
+aWZpY2F0aW9uIFNlcnZpY2UgUHJvdmlkZXIxKTAnBgNVBAMTIEFjdGFsaXMgU2Vy
+dmVyIEF1dGhlbnRpY2F0aW9uIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAv6P0bhXbUQkVW8ox0HJ+sP5+j6pTwS7yg/wGEUektB/G1duQiT1v21fo
+LANr6F353jILQDCpHIfal3MhbSsHEMKU7XaqsyLWV93bcIKbIloS/eXDfkog6KB3
+u0JHgrtNz584Jg/OLm9feffNbCJ38TiLo0/UWkAQ6PQWaOwZEgyKjVI5F3swoTB3
+g0LZAzegvkU00Kfp13cSg+cJeU4SajwtfQ+g6s6dlaekaHy/0ef46PfiHHRuhEhE
+JWIpDtUN2ywTT33MSSUe5glDIiXYfcamJQrebzGsHEwyqI195Yaxb+FLNND4n3HM
+e7EI2OrLyT+r/WMvQbl+xNihwtv+HwIDAQABo4IBbzCCAWswEgYDVR0TAQH/BAgw
+BgEB/wIBADBTBgNVHSAETDBKMEgGCSsGAQQBsT4BADA7MDkGCCsGAQUFBwIBFi1o
+dHRwOi8vd3d3LnB1YmxpYy10cnVzdC5jb20vQ1BTL09tbmlSb290Lmh0bWwwDgYD
+VR0PAQH/BAQDAgEGMIGJBgNVHSMEgYEwf6F5pHcwdTELMAkGA1UEBhMCVVMxGDAW
+BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg
+U29sdXRpb25zLCBJbmMuMSMwIQYDVQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwg
+Um9vdIICAaUwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1
+c3QuY29tL2NnaS1iaW4vQ1JMLzIwMTgvY2RwLmNybDAdBgNVHQ4EFgQUpi6OuXYt
+oxHC3cTezVLuraWpAFEwDQYJKoZIhvcNAQEFBQADgYEAAtjJBwjsvw7DBs+v7BQz
+gSGeg6nbYUuPL7+1driT5XsUKJ7WZjiwW2zW/WHZ+zGo1Ev8Dc574RpSrg/EIlfH
+TpBiBuFgiKtJksKdoxPZGSI8FitwcgeW+y8wotmm0CtDzWN27g2kfSqHb5eHfZY5
+sESPRwHkcMUNdAp37FLweUw=
+-----END CERTIFICATE-----`)
+
+// 2014/05/22 14:18:31 Serial number match: intermediate is revoked.
+// 2014/05/22 14:18:31 certificate is revoked via CRL
+// 2014/05/22 14:18:31 Revoked certificate: misc/intermediate_ca/MobileArmorEnterpriseCA.crt
+var revokedCert = mustParse(`-----BEGIN CERTIFICATE-----
+MIIEEzCCAvugAwIBAgILBAAAAAABGMGjftYwDQYJKoZIhvcNAQEFBQAwcTEoMCYG
+A1UEAxMfR2xvYmFsU2lnbiBSb290U2lnbiBQYXJ0bmVycyBDQTEdMBsGA1UECxMU
+Um9vdFNpZ24gUGFydG5lcnMgQ0ExGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
+CzAJBgNVBAYTAkJFMB4XDTA4MDMxODEyMDAwMFoXDTE4MDMxODEyMDAwMFowJTEj
+MCEGA1UEAxMaTW9iaWxlIEFybW9yIEVudGVycHJpc2UgQ0EwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCaEjeDR73jSZVlacRn5bc5VIPdyouHvGIBUxyS
+C6483HgoDlWrWlkEndUYFjRPiQqJFthdJxfglykXD+btHixMIYbz/6eb7hRTdT9w
+HKsfH+wTBIdb5AZiNjkg3QcCET5HfanJhpREjZWP513jM/GSrG3VwD6X5yttCIH1
+NFTDAr7aqpW/UPw4gcPfkwS92HPdIkb2DYnsqRrnKyNValVItkxJiotQ1HOO3YfX
+ivGrHIbJdWYg0rZnkPOgYF0d+aIA4ZfwvdW48+r/cxvLevieuKj5CTBZZ8XrFt8r
+JTZhZljbZvnvq/t6ZIzlwOj082f+lTssr1fJ3JsIPnG2lmgTAgMBAAGjgfcwgfQw
+DgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFIZw
+ns4uzXdLX6xDRXUzFgZxWM7oME0GA1UdIARGMEQwQgYJKwYBBAGgMgE8MDUwMwYI
+KwYBBQUHAgIwJxolaHR0cDovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5
+LzA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmdsb2JhbHNpZ24ubmV0L1Jv
+b3RTaWduUGFydG5lcnMuY3JsMB8GA1UdIwQYMBaAFFaE7LVxpedj2NtRBNb65vBI
+UknOMA0GCSqGSIb3DQEBBQUAA4IBAQBZvf+2xUJE0ekxuNk30kPDj+5u9oI3jZyM
+wvhKcs7AuRAbcxPtSOnVGNYl8By7DPvPun+U3Yci8540y143RgD+kz3jxIBaoW/o
+c4+X61v6DBUtcBPEt+KkV6HIsZ61SZmc/Y1I2eoeEt6JYoLjEZMDLLvc1cK/+wpg
+dUZSK4O9kjvIXqvsqIOlkmh/6puSugTNao2A7EIQr8ut0ZmzKzMyZ0BuQhJDnAPd
+Kz5vh+5tmytUPKA8hUgmLWe94lMb7Uqq2wgZKsqun5DAWleKu81w7wEcOrjiiB+x
+jeBHq7OnpWm+ccTOPCE6H4ZN4wWVS7biEBUdop/8HgXBPQHWAdjL
+-----END CERTIFICATE-----`)
+
+// 2014/05/22 14:18:51 added misc/intermediate_ca/GandiProSSLCA.crt to intermediate bundle
+var goodstring = (`-----BEGIN CERTIFICATE-----
+MIIEnjCCA4agAwIBAgIQPBkQvAZ54yVvTfQWo16zFDANBgkqhkiG9w0BAQUFADCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmUwHhcNMDgxMDIzMDAwMDAwWhcNMjAwNTMwMTA0ODM4WjA8MQswCQYD
+VQQGEwJGUjESMBAGA1UEChMJR0FOREkgU0FTMRkwFwYDVQQDExBHYW5kaSBQcm8g
+U1NMIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw5nFDd2ffWY4
+OxZxUVj2uQ49ms1N68h471Kq5j3R9OkVJYwObJqozTZvnlcmJ/QG5lZY9+RXDNyU
+V1EKVL92l4vHkngDhhTQaoIB0sNeJMdnCzzjebnmN3VTbSTniQhYEZPg1554Zo+2
+U39kHBCPKZbwNk11EP4f7U7goyatkNJl0b28zEjbfGvJbPNE6vfaiBfM06spAHft
+gJbCC2lzmv9L5R+KlixFFk3P8IkZInLnrGZ6iP0XIckVI8ENoMxu0SXb5JnfF8OS
+QKdqBZKFBMbNJCCBQjXiv50hQEvVTX/INrqoMUfOVV1OT2HmuhPEBdoU0tU75mwm
+VArKuQAdwwIDAQABo4IBPjCCATowHwYDVR0jBBgwFoAUoXJfJhsomEOVXQc31YWW
+nUvSw0UwHQYDVR0OBBYEFMGxMoDxE5IUL21nMJIYqnw5VRQ+MA4GA1UdDwEB/wQE
+AwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMBgGA1UdIAQRMA8wDQYLKwYBBAGyMQEC
+AhowRAYDVR0fBD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VU
+Ti1VU0VSRmlyc3QtSGFyZHdhcmUuY3JsMHQGCCsGAQUFBwEBBGgwZjA9BggrBgEF
+BQcwAoYxaHR0cDovL2NydC51c2VydHJ1c3QuY29tL1VUTkFkZFRydXN0U2VydmVy
+X0NBLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTAN
+BgkqhkiG9w0BAQUFAAOCAQEAjSvVDlj6cT/RDFCrOvqpd1gZD7rzKzDGpfi3IciU
+cjatYny806bAaAxRqL56e3O4rRMr+Jw1sHGpcqfKkm3YBW0CyJAum4vI07lYjZpn
+9ihcWeatDX4gp/6Pm862lGITpB6TLriX1G7EYdnjOudIajawz64vnyTdvzmC18BV
++wC3A9f57mnqzm5SghMSeGlF78y9vPUXWPfBx9JY4Ga/r+U59djQrgbKY93sgyXD
+3LS+K6NqGCKt58LcXQq75/e0OnHoJ3tiPMiB1IuYoIRCXevitc1ynVyP/m5wuZqB
+wHHiX3Eo2RFMBCfSE7mSUoSwgHWtp1tHh0IvL8H7dmKjZQ==
+-----END CERTIFICATE-----`)
+
+var goodCert = mustParse(goodstring)
+
+func mustParse(pemData string) *x509.Certificate {
+ block, _ := pem.Decode([]byte(pemData))
+ if block == nil {
+ panic("Invalid PEM data.")
+ } else if block.Type != "CERTIFICATE" {
+ panic("Invalid PEM type.")
+ }
+
+ cert, err := x509.ParseCertificate([]byte(block.Bytes))
+ if err != nil {
+ panic(err.Error())
+ }
+ return cert
+}
+
+func TestRevoked(t *testing.T) {
+ if revoked, ok := VerifyCertificate(revokedCert); !ok {
+ fmt.Fprintf(os.Stderr, "Warning: soft fail checking revocation")
+ } else if !revoked {
+ t.Fatalf("revoked certificate should have been marked as revoked")
+ }
+}
+
+func TestExpired(t *testing.T) {
+ if revoked, ok := VerifyCertificate(expiredCert); !ok {
+ fmt.Fprintf(os.Stderr, "Warning: soft fail checking revocation")
+ } else if !revoked {
+ t.Fatalf("expired certificate should have been marked as revoked")
+ }
+}
+
+func TestGood(t *testing.T) {
+ if revoked, ok := VerifyCertificate(goodCert); !ok {
+ fmt.Fprintf(os.Stderr, "Warning: soft fail checking revocation")
+ } else if revoked {
+ t.Fatalf("good certificate should not have been marked as revoked")
+ }
+
+}
+
+func TestLdap(t *testing.T) {
+ ldapCert := mustParse(goodstring)
+ ldapCert.CRLDistributionPoints = append(ldapCert.CRLDistributionPoints, "ldap://myldap.example.com")
+ if revoked, ok := VerifyCertificate(ldapCert); revoked || !ok {
+ t.Fatalf("ldap certificate should have been recognized")
+ }
+}
+
+func TestLdapURLErr(t *testing.T) {
+ if ldapURL(":") {
+ t.Fatalf("bad url does not cause error")
+ }
+}
+
+func TestCertNotYetValid(t *testing.T) {
+ notReadyCert := expiredCert
+ notReadyCert.NotBefore = time.Date(3000, time.January, 1, 1, 1, 1, 1, time.Local)
+ notReadyCert.NotAfter = time.Date(3005, time.January, 1, 1, 1, 1, 1, time.Local)
+ if revoked, _ := VerifyCertificate(expiredCert); !revoked {
+ t.Fatalf("not yet verified certificate should have been marked as revoked")
+ }
+}
+
+func TestCRLFetchError(t *testing.T) {
+ ldapCert := mustParse(goodstring)
+ ldapCert.CRLDistributionPoints[0] = ""
+ if revoked, ok := VerifyCertificate(ldapCert); ok || revoked {
+ t.Fatalf("Fetching error not encountered")
+ }
+ HardFail = true
+ if revoked, ok := VerifyCertificate(ldapCert); ok || !revoked {
+ t.Fatalf("Fetching error not encountered, hardfail not registered")
+ }
+ HardFail = false
+}
+
+func TestBadCRLSet(t *testing.T) {
+ ldapCert := mustParse(goodstring)
+ ldapCert.CRLDistributionPoints[0] = ""
+ CRLSet[""] = nil
+ certIsRevokedCRL(ldapCert, "")
+ if _, ok := CRLSet[""]; ok {
+ t.Fatalf("key emptystring should be deleted from CRLSet")
+ }
+ delete(CRLSet, "")
+
+}
+
+func TestCachedCRLSet(t *testing.T) {
+ VerifyCertificate(goodCert)
+ if revoked, ok := VerifyCertificate(goodCert); !ok || revoked {
+ t.Fatalf("Previously fetched CRL's should be read smoothly and unrevoked")
+ }
+}
+
+func TestRemoteFetchError(t *testing.T) {
+
+ badurl := ":"
+
+ if _, err := fetchRemote(badurl); err == nil {
+ t.Fatalf("fetching bad url should result in non-nil error")
+ }
+
+}
+
+func TestNoOCSPServers(t *testing.T) {
+ badIssuer := goodCert
+ badIssuer.IssuingCertificateURL = []string{" "}
+ certIsRevokedOCSP(badIssuer, true)
+ noOCSPCert := goodCert
+ noOCSPCert.OCSPServer = make([]string, 0)
+ if revoked, ok := certIsRevokedOCSP(noOCSPCert, true); revoked || !ok {
+ t.Fatalf("OCSP falsely registered as enabled for this certificate")
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/broad.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/broad.go
new file mode 100644
index 00000000000..6f49e3022f3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/broad.go
@@ -0,0 +1,84 @@
+package scan
+
+import (
+ "crypto/x509"
+ "net"
+ "sync"
+ "time"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cf-tls/tls"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler"
+)
+
+// Broad contains scanners for large swaths of TLS hosts on the internet.
+var Broad = &Family{
+ Description: "Large scale scans of TLS hosts",
+ Scanners: map[string]*Scanner{
+ "IntermediateCAs": {
+ "Scans a CIDR IP range for unknown Intermediate CAs",
+ intermediateCAScan,
+ },
+ },
+}
+
+func incrementBytes(bytes []byte) {
+ lsb := len(bytes) - 1
+ bytes[lsb]++
+ if bytes[lsb] == 0 {
+ incrementBytes(bytes[:lsb])
+ }
+}
+
+var (
+ caBundleFile = "/etc/cfssl/ca-bundle.crt"
+ intBundleFile = "/etc/cfssl/int-bundle.crt"
+ numWorkers = 32
+ timeout = time.Second
+)
+
+// intermediateCAScan scans for new intermediate CAs not in the trust store.
+func intermediateCAScan(host string) (grade Grade, output Output, err error) {
+ cidr, port, _ := net.SplitHostPort(host)
+ _, ipnet, err := net.ParseCIDR(cidr)
+ if err != nil {
+ return Skipped, nil, nil
+ }
+ b, err := bundler.NewBundler(caBundleFile, intBundleFile)
+ if err != nil {
+ return
+ }
+ var wg sync.WaitGroup
+ wg.Add(numWorkers)
+ dialer := &net.Dialer{Timeout: timeout}
+ config := &tls.Config{InsecureSkipVerify: true}
+ addrs := make(chan string)
+ chains := make(chan []*x509.Certificate, numWorkers)
+ go func() {
+ for chain := range chains {
+ b.Bundle(chain, nil, bundler.Force)
+ }
+ }()
+ for i := 0; i < numWorkers; i++ {
+ go func() {
+ for addr := range addrs {
+ conn, err := tls.DialWithDialer(dialer, Network, addr, config)
+ if err != nil {
+ continue
+ }
+ conn.Close()
+ if conn.ConnectionState().HandshakeComplete {
+ chains <- conn.ConnectionState().PeerCertificates
+ }
+ }
+ wg.Done()
+ }()
+ }
+ for ip := ipnet.IP.To16(); ipnet.Contains(ip); incrementBytes(ip) {
+ addrs <- net.JoinHostPort(ip.String(), port)
+ }
+ close(addrs)
+ wg.Wait()
+ close(chains)
+ grade = Good
+ return
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/pki.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/pki.go
index 77b81aa42af..b829f1bf083 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/pki.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/pki.go
@@ -1,84 +1,160 @@
package scan
import (
+ "bytes"
"crypto/x509"
- "net"
- "sync"
+ "fmt"
"time"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cf-tls/tls"
- "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/bundler"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/revoke"
)
-// PKI contains scanners to test application layer HTTP(S) features
+// PKI contains scanners for the Public Key Infrastructure.
var PKI = &Family{
Description: "Scans for the Public Key Infrastructure",
Scanners: map[string]*Scanner{
- "IntermediateCAs": {
- "Scans a CIDR IP range for unknown Intermediate CAs",
- intermediateCAScan,
+ "ChainExpiration": {
+ "Host's chain hasn't expired and won't expire in the next 30 days",
+ chainExpiration,
+ },
+ "ChainValidation": {
+ "All certificates in host's chain are valid",
+ chainValidation,
+ },
+ "MultipleCerts": {
+ "Host serves same certificate chain across all IPs",
+ multipleCerts,
},
},
}
-func incrementBytes(bytes []byte) {
- lsb := len(bytes) - 1
- bytes[lsb]++
- if bytes[lsb] == 0 {
- incrementBytes(bytes[:lsb])
+// getChain is a helper function that retreives the host's certificate chain.
+func getChain(host string, config *tls.Config) (chain []*x509.Certificate, err error) {
+ var conn *tls.Conn
+ conn, err = tls.DialWithDialer(Dialer, Network, host, config)
+ if err != nil {
+ return
+ }
+
+ err = conn.Close()
+ if err != nil {
+ return
+ }
+
+ chain = conn.ConnectionState().PeerCertificates
+ if len(chain) == 0 {
+ err = fmt.Errorf("%s returned empty certificate chain", host)
}
+ return
}
-var (
- caBundleFile = "/etc/cfssl/ca-bundle.crt"
- intBundleFile = "/etc/cfssl/int-bundle.crt"
- numWorkers = 32
- timeout = time.Second
-)
+type expiration time.Time
+
+func (e expiration) String() string {
+ return time.Time(e).Format("Jan 2 15:04:05 2006 MST")
+}
-// intermediateCAScan scans for new intermediate CAs not in the trust store.
-func intermediateCAScan(host string) (grade Grade, output Output, err error) {
- cidr, port, _ := net.SplitHostPort(host)
- _, ipnet, err := net.ParseCIDR(cidr)
+func chainExpiration(host string) (grade Grade, output Output, err error) {
+ chain, err := getChain(host, defaultTLSConfig(host))
if err != nil {
- return Skipped, nil, nil
+ return
+ }
+
+ e := helpers.ExpiryTime(chain)
+ if e == nil {
+ return
+ }
+ expirationTime := *e
+ output = expirationTime
+
+ if time.Now().After(expirationTime) {
+ return
}
- b, err := bundler.NewBundler(caBundleFile, intBundleFile)
+
+ // Warn if cert will expire in the next 30 days
+ if time.Now().Add(time.Hour * 24 * 30).After(expirationTime) {
+ grade = Warning
+ return
+ }
+
+ grade = Good
+ return
+}
+
+func chainValidation(host string) (grade Grade, output Output, err error) {
+ chain, err := getChain(host, defaultTLSConfig(host))
if err != nil {
return
}
- var wg sync.WaitGroup
- wg.Add(numWorkers)
- dialer := &net.Dialer{Timeout: timeout}
- config := &tls.Config{InsecureSkipVerify: true}
- addrs := make(chan string)
- chains := make(chan []*x509.Certificate, numWorkers)
- go func() {
- for chain := range chains {
- b.Bundle(chain, nil, bundler.Force)
+
+ var warnings []string
+
+ for i := 0; i < len(chain)-1; i++ {
+ cert, parent := chain[i], chain[i+1]
+
+ revoked, ok := revoke.VerifyCertificate(cert)
+ if !ok {
+ warnings = append(warnings, fmt.Sprintf("couldn't check if %s is revoked", cert.Subject.CommonName))
+ }
+ if revoked {
+ err = fmt.Errorf("%s is revoked", cert.Subject.CommonName)
+ return
+ }
+
+ if !parent.IsCA {
+ err = fmt.Errorf("%s is not a CA", parent.Subject.CommonName)
+ return
+ }
+
+ if !bytes.Equal(cert.AuthorityKeyId, parent.SubjectKeyId) {
+ err = fmt.Errorf("%s AuthorityKeyId differs from %s SubjectKeyId", cert.Subject.CommonName, parent.Subject.CommonName)
+ return
+ }
+
+ if err = cert.CheckSignatureFrom(parent); err != nil {
+ return
+ }
+
+ switch cert.SignatureAlgorithm {
+ case x509.ECDSAWithSHA1:
+ warnings = append(warnings, fmt.Sprintf("%s is signed by ECDSAWithSHA1", cert.Subject.CommonName))
+ case x509.SHA1WithRSA:
+ warnings = append(warnings, fmt.Sprintf("%s is signed by RSAWithSHA1", cert.Subject.CommonName))
}
- }()
- for i := 0; i < numWorkers; i++ {
- go func() {
- for addr := range addrs {
- conn, err := tls.DialWithDialer(dialer, Network, addr, config)
- if err != nil {
- continue
- }
- conn.Close()
- if conn.ConnectionState().HandshakeComplete {
- chains <- conn.ConnectionState().PeerCertificates
- }
- }
- wg.Done()
- }()
}
- for ip := ipnet.IP.To16(); ipnet.Contains(ip); incrementBytes(ip) {
- addrs <- net.JoinHostPort(ip.String(), port)
+
+ if len(warnings) == 0 {
+ grade = Good
+ } else {
+ grade = Warning
+ output = warnings
}
- close(addrs)
- wg.Wait()
- close(chains)
- grade = Good
+ return
+}
+
+func multipleCerts(host string) (grade Grade, output Output, err error) {
+ config := defaultTLSConfig(host)
+
+ firstChain, err := getChain(host, config)
+ if err != nil {
+ return
+ }
+
+ grade, _, err = multiscan(host, func(addrport string) (g Grade, o Output, e error) {
+ g = Good
+ chain, e1 := getChain(addrport, config)
+ if e1 != nil {
+ return
+ }
+
+ if !chain[0].Equal(firstChain[0]) {
+ e = fmt.Errorf("%s not equal to %s", chain[0].Subject.CommonName, firstChain[0].Subject.CommonName)
+ g = Bad
+ return
+ }
+ return
+ })
return
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common.go
index 79c06198805..f36779c7d2b 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common.go
@@ -1,7 +1,6 @@
package scan
import (
- "fmt"
"net"
"regexp"
"time"
@@ -11,7 +10,6 @@ import (
)
var (
-
// Network is the default network to use.
Network = "tcp"
// Dialer is the default dialer to use, with a 1s timeout.
@@ -24,8 +22,8 @@ type Grade int
const (
// Bad describes a host with serious misconfiguration or vulnerability.
Bad Grade = iota
- // Legacy describes a host with non-ideal configuration that maintains support for legacy clients.
- Legacy
+ // Warning describes a host with non-ideal configuration that maintains support for Warning clients.
+ Warning
// Good describes host performing the expected state-of-the-art.
Good
// Skipped descibes the "grade" of a scan that has been skipped.
@@ -37,8 +35,8 @@ func (g Grade) String() string {
switch g {
case Bad:
return "Bad"
- case Legacy:
- return "Legacy"
+ case Warning:
+ return "Warning"
case Good:
return "Good"
case Skipped:
@@ -49,8 +47,41 @@ func (g Grade) String() string {
}
// Output is the result of a scan, to be stored for potential use by later Scanners.
-type Output interface {
- fmt.Stringer
+type Output interface{}
+
+type scanFunc func(string) (Grade, Output, error)
+
+// multiscan scans all DNS addresses returned for the host, returning the lowest grade
+// and the concatenation of all the output.
+func multiscan(host string, scan scanFunc) (grade Grade, output Output, err error) {
+ domain, port, _ := net.SplitHostPort(host)
+ var addrs []string
+ addrs, err = net.LookupHost(domain)
+ if err != nil {
+ return
+ }
+
+ grade = Good
+ out := make(map[string]Output)
+
+ for _, addr := range addrs {
+ var g Grade
+ var o Output
+
+ g, o, err = scan(net.JoinHostPort(addr, port))
+ if err != nil {
+ grade = Bad
+ return
+ }
+
+ if g < grade {
+ grade = g
+ }
+
+ out[addr] = o
+ }
+ output = out
+ return
}
// Scanner describes a type of scan to perform on a host.
@@ -58,7 +89,7 @@ type Scanner struct {
// Description describes the nature of the scan to be performed.
Description string `json:"description"`
// scan is the function that scans the given host and provides a Grade and Output.
- scan func(host string) (Grade, Output, error)
+ scan scanFunc
}
// Scan performs the scan to be performed on the given host and stores its result.
@@ -88,13 +119,14 @@ var Default = FamilySet{
"TLSHandshake": TLSHandshake,
"TLSSession": TLSSession,
"PKI": PKI,
+ "Broad": Broad,
}
// ScannerResult contains the result for a single scan.
type ScannerResult struct {
Grade string `json:"grade"`
Output Output `json:"output,omitempty"`
- Error error `json:"error,omitempty"`
+ Error string `json:"error,omitempty"`
}
// FamilyResult contains a scan response for a single Family
@@ -126,11 +158,16 @@ func (fs FamilySet) RunScans(host, family, scanner string) (map[string]FamilyRes
for scannerName, scanner := range family.Scanners {
if scannerRegexp.MatchString(scannerName) {
grade, output, err := scanner.Scan(host)
- scannerResults[scannerName] = ScannerResult{
+
+ result := ScannerResult{
Grade: grade.String(),
Output: output,
- Error: err,
}
+ if err != nil {
+ result.Error = err.Error()
+ }
+
+ scannerResults[scannerName] = result
}
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common_test.go
index c57adfee28b..b916f6ca027 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/scan_common_test.go
@@ -5,26 +5,20 @@ import (
"testing"
)
-type OutputString string
-
-func (os OutputString) String() string {
- return string(os)
-}
-
var TestingScanner = &Scanner{
Description: "Tests common scan functions",
scan: func(host string) (Grade, Output, error) {
switch host {
case "bad.example.com:443":
- return Bad, OutputString("bad.com"), nil
- case "legacy.example.com:443":
- return Legacy, OutputString("legacy.com"), nil
+ return Bad, "bad.com", nil
+ case "Warning.example.com:443":
+ return Warning, "Warning.com", nil
case "good.example.com:443":
- return Good, OutputString("good.com"), nil
+ return Good, "good.com", nil
case "skipped.example.com:443/0":
- return Skipped, OutputString("skipped"), nil
+ return Skipped, "skipped", nil
default:
- return Grade(-1), OutputString("invalid"), fmt.Errorf("scan: invalid grade")
+ return Grade(-1), "invalid", fmt.Errorf("scan: invalid grade")
}
},
}
@@ -46,22 +40,22 @@ func TestCommon(t *testing.T) {
var err error
grade, output, err = TestingScanner.Scan("bad.example.com:443")
- if grade != Bad || output.String() != "bad.com" || err != nil {
+ if grade != Bad || output.(string) != "bad.com" || err != nil {
t.FailNow()
}
- grade, output, err = TestingScanner.Scan("legacy.example.com:443")
- if grade != Legacy || output.String() != "legacy.com" || err != nil {
+ grade, output, err = TestingScanner.Scan("Warning.example.com:443")
+ if grade != Warning || output.(string) != "Warning.com" || err != nil {
t.FailNow()
}
grade, output, err = TestingScanner.Scan("good.example.com:443")
- if grade != Good || output.String() != "good.com" || err != nil {
+ if grade != Good || output.(string) != "good.com" || err != nil {
t.FailNow()
}
grade, output, err = TestingScanner.Scan("skipped.example.com:443/0")
- if grade != Skipped || output.String() != "skipped" || err != nil {
+ if grade != Skipped || output.(string) != "skipped" || err != nil {
t.FailNow()
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_handshake.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_handshake.go
index ee50aab7703..c16f003decf 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_handshake.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_handshake.go
@@ -99,6 +99,7 @@ func (cvList cipherVersionList) MarshalJSON() ([]byte, error) {
func cipherSuiteScan(host string) (grade Grade, output Output, err error) {
var cvList cipherVersionList
allCiphers := allCiphersIDs()
+
var vers uint16
for vers = tls.VersionTLS12; vers >= tls.VersionSSL30; vers-- {
ciphers := make([]uint16, len(allCiphers))
@@ -109,7 +110,7 @@ func cipherSuiteScan(host string) (grade Grade, output Output, err error) {
break
}
if vers == tls.VersionSSL30 {
- grade = Legacy
+ grade = Warning
}
cipherID := ciphers[cipherIndex]
for i, c := range cvList {
@@ -123,11 +124,16 @@ func cipherSuiteScan(host string) (grade Grade, output Output, err error) {
ciphers = append(ciphers[:cipherIndex], ciphers[cipherIndex+1:]...)
}
}
- if grade != Legacy && len(cvList) > 0 {
- grade = Good
- } else {
+
+ if len(cvList) == 0 {
err = errors.New("couldn't negotiate any cipher suites")
+ return
}
+
+ if grade != Warning {
+ grade = Good
+ }
+
output = cvList
return
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_session.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_session.go
index ebae8ac5e7c..185886ae866 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_session.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/scan/tls_session.go
@@ -1,11 +1,6 @@
package scan
-import (
- "errors"
- "net"
-
- "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cf-tls/tls"
-)
+import "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cf-tls/tls"
// TLSSession contains tests of host TLS Session Resumption via
// Session Tickets and Session IDs
@@ -21,36 +16,29 @@ var TLSSession = &Family{
// SessionResumeScan tests that host is able to resume sessions across all addresses.
func sessionResumeScan(host string) (grade Grade, output Output, err error) {
- var hostname, port string
- hostname, port, err = net.SplitHostPort(host)
- if err != nil {
- return
- }
- ips, err := net.LookupIP(hostname)
- if err != nil {
- return
- }
config := defaultTLSConfig(host)
config.ClientSessionCache = tls.NewLRUClientSessionCache(1)
- var conn *tls.Conn
- conn, err = tls.DialWithDialer(Dialer, Network, host, config)
+
+ conn, err := tls.DialWithDialer(Dialer, Network, host, config)
if err != nil {
return
}
- conn.Close()
+ if err = conn.Close(); err != nil {
+ return
+ }
- for _, ip := range ips {
- host = net.JoinHostPort(ip.String(), port)
- conn, err = tls.Dial(Network, host, config)
- if err != nil {
+ return multiscan(host, func(addrport string) (g Grade, o Output, e error) {
+ g = Good
+ conn, e1 := tls.DialWithDialer(Dialer, Network, addrport, config)
+ if e1 != nil {
return
}
conn.Close()
+
+ o = conn.ConnectionState().DidResume
if !conn.ConnectionState().DidResume {
- err = errors.New("did not resume")
- return
+ grade = Bad
}
- }
- grade = Good
- return
+ return
+ })
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/selfsign/selfsign.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/selfsign/selfsign.go
index 5e876981911..2ca4d190ad0 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/selfsign/selfsign.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/selfsign/selfsign.go
@@ -28,13 +28,13 @@ func parseCertificateRequest(priv crypto.Signer, csrBytes []byte) (template *x50
csr, err := x509.ParseCertificateRequest(csrBytes)
if err != nil {
- err = cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
return
}
err = signer.CheckSignature(csr, csr.SignatureAlgorithm, csr.RawTBSCertificateRequest, csr.Signature)
if err != nil {
- err = cferr.Wrap(cferr.CertificateError, cferr.KeyMismatch, err)
+ err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
return
}
@@ -61,7 +61,7 @@ func Sign(priv crypto.Signer, csrPEM []byte, profile *config.SigningProfile) ([]
p, _ := pem.Decode(csrPEM)
if p == nil || p.Type != "CERTIFICATE REQUEST" {
- return nil, cferr.New(cferr.CertificateError, cferr.BadRequest)
+ return nil, cferr.New(cferr.CSRError, cferr.BadRequest)
}
template, err := parseCertificateRequest(priv, p.Bytes)
@@ -108,7 +108,7 @@ func Sign(priv crypto.Signer, csrPEM []byte, profile *config.SigningProfile) ([]
now := time.Now()
serialNumber, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
if err != nil {
- err = cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
+ err = cferr.Wrap(cferr.CSRError, cferr.Unknown, err)
return nil, err
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local/local.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local/local.go
index 274efa1db85..9f569b5e959 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local/local.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local/local.go
@@ -1,7 +1,8 @@
-// Package local implements certificate signature functionality for CF-SSL.
+// Package local implements certificate signature functionality for CFSSL.
package local
import (
+ "bytes"
"crypto"
"crypto/rand"
"crypto/x509"
@@ -14,6 +15,7 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/info"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
)
@@ -168,9 +170,9 @@ func OverrideHosts(template *x509.Certificate, hosts []string) {
// certificate or certificate request with the signing profile,
// specified by profileName.
func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
- profile := s.policy.Profiles[req.Profile]
- if profile == nil {
- profile = s.policy.Default
+ profile, err := signer.Profile(s, req.Profile)
+ if err != nil {
+ return
}
serialSeq := ""
@@ -180,11 +182,11 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
block, _ := pem.Decode([]byte(req.Request))
if block == nil {
- return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
+ return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
}
if block.Type != "CERTIFICATE REQUEST" {
- return nil, cferr.Wrap(cferr.CertificateError,
+ return nil, cferr.Wrap(cferr.CSRError,
cferr.BadRequest, errors.New("not a certificate or csr"))
}
@@ -226,6 +228,28 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
return s.sign(&safeTemplate, profile, serialSeq)
}
+// Info return a populated info.Resp struct or an error.
+func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
+ cert, err := s.Certificate(req.Label, req.Profile)
+ if err != nil {
+ return
+ }
+
+ profile, err := signer.Profile(s, req.Profile)
+ if err != nil {
+ return
+ }
+
+ resp = new(info.Resp)
+ if cert.Raw != nil {
+ resp.Certificate = string(bytes.TrimSpace(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})))
+ }
+ resp.Usage = profile.Usage
+ resp.ExpiryString = profile.ExpiryString
+
+ return
+}
+
// SigAlgo returns the RSA signer's signature algorithm.
func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
return s.sigAlgo
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/pkcs11/pkcs11.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/pkcs11/pkcs11.go
index 09f1b478c77..77bfdf85963 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/pkcs11/pkcs11.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/pkcs11/pkcs11.go
@@ -5,8 +5,8 @@ package pkcs11
import (
"io/ioutil"
- "github.com/cloudflare/cfssl/crypto/pkcs11key"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote.go
index 3e0002fd87e..b0cc20894aa 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote.go
@@ -8,7 +8,7 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
- "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/info"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
)
@@ -38,29 +38,39 @@ func NewSigner(policy *config.Signing) (*Signer, error) {
// csr, and profileName are used as with a local signing operation, and
// the label is used to select a signing root in a multi-root CA.
func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
- return s.remoteOp(req, req.Profile, "sign")
+ resp, err := s.remoteOp(req, req.Profile, "sign")
+ if err != nil {
+ return
+ }
+ if cert, ok := resp.([]byte); ok {
+ return cert, nil
+ }
+ return
}
-// Info sends an info request to the remote CFSSL server, receiving a signed
-// certificate or an error in response.
-func (s *Signer) Info(req client.InfoReq) (cert []byte, err error) {
- return s.remoteOp(req, req.Profile, "info")
+// Info sends an info request to the remote CFSSL server, receiving an
+// Resp struct or an error in response.
+func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
+ respInterface, err := s.remoteOp(req, req.Profile, "info")
+ if err != nil {
+ return
+ }
+ if resp, ok := respInterface.(*info.Resp); ok {
+ return resp, nil
+ }
+ return
}
// Helper function to perform a remote sign or info request.
-func (s *Signer) remoteOp(req interface{}, profile, target string) (cert []byte, err error) {
+func (s *Signer) remoteOp(req interface{}, profile, target string) (resp interface{}, err error) {
jsonData, err := json.Marshal(req)
if err != nil {
return nil, cferr.Wrap(cferr.APIClientError, cferr.JSONError, err)
}
- var p *config.SigningProfile
- if s.policy.Profiles != nil && profile != "" {
- p = s.policy.Profiles[profile]
- }
-
- if p == nil {
- p = s.policy.Default
+ p, err := signer.Profile(s, profile)
+ if err != nil {
+ return
}
server := client.NewServer(p.RemoteServer)
@@ -69,19 +79,20 @@ func (s *Signer) remoteOp(req interface{}, profile, target string) (cert []byte,
errors.New("failed to connect to remote"))
}
- // There's no server-side auth provider for the "info" method
- // TODO: Revert this change once there is an AuthInfo provider.
- if p.Provider != nil && target != "info" {
- cert, err = server.AuthReq(jsonData, nil, p.Provider, target)
+ // There's no auth provider for the "info" method
+ if target == "info" {
+ resp, err = server.Info(jsonData)
+ } else if p.Provider != nil {
+ resp, err = server.AuthReq(jsonData, nil, p.Provider, target)
} else {
- cert, err = server.Req(jsonData, target)
+ resp, err = server.Req(jsonData, target)
}
if err != nil {
return nil, err
}
- return []byte(cert), nil
+ return
}
// SigAlgo returns the RSA signer's signature algorithm.
@@ -90,19 +101,6 @@ func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
return x509.UnknownSignatureAlgorithm
}
-// Certificate returns the signer's certificate.
-func (s *Signer) Certificate(label, profile string) (*x509.Certificate, error) {
- certStr, err := s.Info(client.InfoReq{Label: label, Profile: profile})
- if err != nil {
- return nil, err
- }
- cert, err := helpers.ParseCertificatePEM(certStr)
- if err != nil {
- return nil, err
- }
- return cert, nil
-}
-
// SetPolicy sets the signer's signature policy.
func (s *Signer) SetPolicy(policy *config.Signing) {
s.policy = policy
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote_test.go
index 56bb3f7c747..f491e0e0816 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/remote/remote_test.go
@@ -11,11 +11,11 @@ import (
"time"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api"
- "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/client"
- "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/info"
+ apiinfo "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/api/info"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/info"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local"
@@ -83,8 +83,8 @@ func TestRemoteInfo(t *testing.T) {
// override with test server address, ignore url prefix "http://"
remoteConfig.Signing.OverrideRemotes(remoteServer.URL[7:])
s := newRemoteSigner(t, remoteConfig.Signing)
- req := client.InfoReq{}
- certBytes, err := s.Info(req)
+ req := info.Req{}
+ resp, err := s.Info(req)
if err != nil {
t.Fatal("remote info failed:", err)
}
@@ -95,8 +95,8 @@ func TestRemoteInfo(t *testing.T) {
t.Fatal("fail to read test CA cert:", err)
}
- if bytes.Compare(caBytes, certBytes) != 0 {
- t.Fatal("Get a different CA cert through info api.", len(certBytes), len(caBytes))
+ if bytes.Compare(caBytes, []byte(resp.Certificate)) != 0 {
+ t.Fatal("Get a different CA cert through info api.", len(resp.Certificate), len(caBytes))
}
}
@@ -305,7 +305,7 @@ func newHandler(t *testing.T, caFile, caKeyFile, op string) (http.Handler, error
if op == "sign" {
return NewSignHandlerFromSigner(s)
} else if op == "info" {
- return info.NewHandler(s)
+ return apiinfo.NewHandler(s)
}
t.Fatal("Bad op code")
@@ -340,7 +340,7 @@ func NewSignHandlerFromSigner(s signer.Signer) (h http.Handler, err error) {
Handler: &SignHandler{
signer: s,
},
- Method: "POST",
+ Methods: []string{"POST"},
}, nil
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/signer.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/signer.go
index a7ea4a41941..db3dde9f912 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/signer.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/signer.go
@@ -1,4 +1,4 @@
-// Package signer implements certificate signature functionality for CF-SSL.
+// Package signer implements certificate signature functionality for CFSSL.
package signer
import (
@@ -21,6 +21,7 @@ import (
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/csr"
cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/info"
)
// MaxPathLen is the default path length for a new CA certificate.
@@ -87,13 +88,31 @@ func SplitHosts(hostList string) []string {
// A Signer contains a CA's certificate and private key for signing
// certificates, a Signing policy to refer to and a SignatureAlgorithm.
type Signer interface {
- Certificate(label, profile string) (*x509.Certificate, error)
+ Info(info.Req) (*info.Resp, error)
Policy() *config.Signing
SetPolicy(*config.Signing)
SigAlgo() x509.SignatureAlgorithm
Sign(req SignRequest) (cert []byte, err error)
}
+// Profile gets the specific profile from the signer
+func Profile(s Signer, profile string) (*config.SigningProfile, error) {
+ var p *config.SigningProfile
+ policy := s.Policy()
+ if policy != nil && policy.Profiles != nil && profile != "" {
+ p = policy.Profiles[profile]
+ }
+
+ if p == nil && policy != nil {
+ p = policy.Default
+ }
+
+ if p == nil {
+ return nil, cferr.Wrap(cferr.APIClientError, cferr.ClientHTTPError, errors.New("profile must not be nil"))
+ }
+ return p, nil
+}
+
// DefaultSigAlgo returns an appropriate X.509 signature algorithm given
// the CA's private key.
func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
@@ -132,13 +151,13 @@ func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
func ParseCertificateRequest(s Signer, csrBytes []byte) (template *x509.Certificate, err error) {
csr, err := x509.ParseCertificateRequest(csrBytes)
if err != nil {
- err = cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
+ err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
return
}
err = CheckSignature(csr, csr.SignatureAlgorithm, csr.RawTBSCertificateRequest, csr.Signature)
if err != nil {
- err = cferr.Wrap(cferr.CertificateError, cferr.KeyMismatch, err)
+ err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
return
}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/universal/universal_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/universal/universal_test.go
index 897888bc4ef..075bd6d014e 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/universal/universal_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/universal/universal_test.go
@@ -1 +1,42 @@
package universal
+
+import (
+ "testing"
+ "time"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
+)
+
+var expiry = 1 * time.Minute
+var validLocalConfig = &config.Config{
+ Signing: &config.Signing{
+ Profiles: map[string]*config.SigningProfile{
+ "valid": {
+ Usage: []string{"digital signature"},
+ Expiry: expiry,
+ },
+ },
+ Default: &config.SigningProfile{
+ Usage: []string{"digital signature"},
+ Expiry: expiry,
+ },
+ },
+}
+
+func TestNewSigner(t *testing.T) {
+ h := map[string]string{
+ "key-file": "../local/testdata/ca_key.pem",
+ "cert-file": "../local/testdata/ca.pem",
+ }
+
+ r := &Root{
+ Config: h,
+ ForceRemote: false,
+ }
+
+ _, err := NewSigner(*r, validLocalConfig.Signing)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/filter.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/filter.go
index 28f01bf9db0..94060455fd3 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/filter.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/filter.go
@@ -1,4 +1,4 @@
-// Package ubiquity contains the ubiquity scoring logic for CF-SSL bundling.
+// Package ubiquity contains the ubiquity scoring logic for CFSSL bundling.
package ubiquity
// Ubiquity is addressed as selecting the chains that are most likely being accepted for different client systems.
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/sha1.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/sha1.go
new file mode 100644
index 00000000000..978094ba273
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/sha1.go
@@ -0,0 +1,153 @@
+package ubiquity
+
+import (
+ "crypto/x509"
+ "fmt"
+ "time"
+
+ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
+)
+
+// DeprecationSeverity encodes the severity of a deprecation policy
+type DeprecationSeverity int
+
+const (
+ // None indicates there is no deprecation
+ None DeprecationSeverity = iota
+ // Low indicates the deprecation policy won't affect user experience
+ Low
+ // Medium indicates the deprecation policy will affect user experience
+ // either in a minor way or for a limited scope of users.
+ Medium
+ // High indicates the deprecation policy will strongly affect user experience
+ High
+)
+
+// SHA1DeprecationPolicy encodes how a platform deprecates the support of SHA1
+type SHA1DeprecationPolicy struct {
+ // the name of platform
+ Platform string `json:"platform"`
+ // policy severity, policies of the same platform will only trigger the one of highest severity
+ Severity DeprecationSeverity `json:"severity"`
+ // a human readable message describing the deprecation effects
+ Description string `json:"description"`
+ // the date when the policy is effective. zero value means effective immediately
+ EffectiveDate time.Time `json:"effective_date"`
+ // the expiry deadline indicates the latest date which a end-entity
+ // certificate with SHA1 can be valid through.
+ ExpiryDeadline time.Time `json:"expiry_deadline"`
+ // the date beyond which SHA1 cert should not be issued.
+ NeverIssueAfter time.Time `json:"never_issue_after"`
+}
+
+// SHA1DeprecationPolicys ia a list of various SHA1DeprecationPolicy's
+// proposed by major browser producers
+var SHA1DeprecationPolicys = []SHA1DeprecationPolicy{
+ // Chrome:
+ // if the leaf certificate expires between 01-01-2016 and 01-01-2017
+ // and the chain (excluding root) contains SHA-1 cert, show "minor errors".
+ SHA1DeprecationPolicy{
+ Platform: "Google Chrome",
+ Description: "shows the SSL connection has minor problems",
+ Severity: Medium,
+ ExpiryDeadline: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
+ },
+ // Chrome:
+ // if the leaf certificate expires after Jan. 1st 2017
+ // and the chain (excluding root) contains SHA-1 cert, show "untrusted SSL".
+ SHA1DeprecationPolicy{
+ Platform: "Google Chrome",
+ Description: "shows the SSL connection is untrusted",
+ Severity: High,
+ ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
+ },
+ // Mozilla Firefox:
+ // if the leaf certificate expires after Jan. 1st 2017, and
+ // the chain (excluding root) contains SHA-1 cert, show a warning in the developer console.
+ SHA1DeprecationPolicy{
+ Platform: "Mozilla Firefox",
+ Description: "gives warning in the developer console",
+ Severity: Low,
+ ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
+ },
+ // Mozilla Firefox:
+ // if a new certificate is issued after Jan. 1st 2016, and
+ // it is a SHA-1 cert, reject it.
+ SHA1DeprecationPolicy{
+ Platform: "Mozilla Firefox",
+ Description: "shows the SSL connection is untrusted",
+ Severity: Medium,
+ EffectiveDate: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
+ NeverIssueAfter: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
+ },
+ // Mozilla Firefox:
+ // deprecate all valid SHA-1 cert chain on Jan. 1st 2017
+ SHA1DeprecationPolicy{
+ Platform: "Mozilla Firefox",
+ Description: "shows the SSL connection is untrusted",
+ Severity: High,
+ EffectiveDate: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
+ ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
+ },
+ // Microsoft Windows:
+ // deprecate all valid SHA-1 cert chain on Jan. 1st 2017
+ SHA1DeprecationPolicy{
+ Platform: "Microsoft Windows Vista and later",
+ Description: "shows the SSL connection is untrusted",
+ Severity: High,
+ EffectiveDate: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
+ ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
+ },
+}
+
+// Flag returns whether the policy flags the cert chain as deprecated for matching its deprecation criteria
+func (p SHA1DeprecationPolicy) Flag(chain []*x509.Certificate) bool {
+ leaf := chain[0]
+ if time.Now().After(p.EffectiveDate) {
+
+ // Reject newly issued leaf certificate with SHA-1 after the specified deadline.
+ if !p.NeverIssueAfter.IsZero() && leaf.NotBefore.After(p.NeverIssueAfter) {
+ // Check hash algorithm of non-root leaf cert.
+ if len(chain) > 1 && helpers.HashAlgoString(leaf.SignatureAlgorithm) == "SHA1" {
+ return true
+ }
+ }
+
+ // Reject certificate chain with SHA-1 that are still valid after expiry deadline.
+ if !p.ExpiryDeadline.IsZero() && leaf.NotAfter.After(p.ExpiryDeadline) {
+ // Check hash algorithm of non-root certs.
+ for i, cert := range chain {
+ if i < len(chain)-1 {
+ if helpers.HashAlgoString(cert.SignatureAlgorithm) == "SHA1" {
+ return true
+ }
+ }
+ }
+ }
+ }
+
+ return false
+}
+
+// SHA1DeprecationMessages returns a list of human-readable messages. Each message describes
+// how one platform rejects the chain based on SHA1 deprecation policies.
+func SHA1DeprecationMessages(chain []*x509.Certificate) []string {
+ // record the most severe deprecation policy by each platform
+ selectedPolicies := map[string]SHA1DeprecationPolicy{}
+ for _, policy := range SHA1DeprecationPolicys {
+ if policy.Flag(chain) {
+ // only keep the policy with highest severity
+ if selectedPolicies[policy.Platform].Severity < policy.Severity {
+ selectedPolicies[policy.Platform] = policy
+ }
+ }
+ }
+ // build the message list
+ list := []string{}
+ for _, policy := range selectedPolicies {
+ if policy.Severity > None {
+ list = append(list, fmt.Sprintf("%s %s due to SHA-1 deprecation", policy.Platform, policy.Description))
+ }
+ }
+ return list
+}
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/testdata/ca.pem.metadata b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/testdata/ca.pem.metadata
new file mode 100644
index 00000000000..fcec6a33d87
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/testdata/ca.pem.metadata
@@ -0,0 +1,15 @@
+[
+{
+ "name":"Browser Everywhere",
+ "weight": 0,
+ "hash_algo": "SHA2",
+ "key_algo": "ECDSA256"
+},
+{
+ "name":"Pineapple",
+ "weight": 1,
+ "hash_algo": "SHA2",
+ "key_algo": "ECDSA521",
+ "keystore": "pineapple.pem"
+}
+]
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go
index 850802fc240..08a9e6ea180 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go
@@ -12,7 +12,6 @@ import (
"io/ioutil"
"path"
"path/filepath"
- "time"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
@@ -36,57 +35,18 @@ func (s CertSet) Add(cert *x509.Certificate) {
s[SHA1RawPublicKey(cert)] = true
}
-// CryptoDeprecationPolicy encodes how a platform plans to deprecate the support of a crypto hash/key algorithm.
-type CryptoDeprecationPolicy struct {
- // The name of target algorithm to be deprecated.
- Target string `json:"target"`
- // The date when the policy is effective.
- EffectiveDate time.Time `json:"effective_date"`
- // The expiry deadline indicates the latest date which a end-entity certificate with the deprecating
- // algorithm can be valid through.
- ExpiryDeadline time.Time `json:"expiry_deadline"`
-}
-
// A Platform contains ubiquity information on supported crypto algorithms and root certificate store name.
type Platform struct {
- Name string `json:"name"`
- Weight int `json:"weight"`
- HashAlgo string `json:"hash_algo"`
- KeyAlgo string `json:"key_algo"`
- KeyStoreFile string `json:"keystore"`
- HashDeprecation *CryptoDeprecationPolicy `json:"hash_algo_expiry"`
+ Name string `json:"name"`
+ Weight int `json:"weight"`
+ HashAlgo string `json:"hash_algo"`
+ KeyAlgo string `json:"key_algo"`
+ KeyStoreFile string `json:"keystore"`
KeyStore CertSet
HashUbiquity HashUbiquity
KeyAlgoUbiquity KeyAlgoUbiquity
}
-// Deprecate returns whether the platform rejects the cert chain due to ceased support of a crypto hash algorithm.
-func (p Platform) Deprecate(chain []*x509.Certificate) bool {
- if p.HashDeprecation == nil {
- return false
- }
- now := time.Now()
- leaf := chain[0]
-
- // Currently we implement the logic that Chrome browsers use to stop supporting SHA-1. To our understanding,
- // Microsoft and Mozilla use basically the same logic to cease support of SHA-1 as well.
-
- if now.After(p.HashDeprecation.EffectiveDate) {
- if leaf.NotAfter.After(p.HashDeprecation.ExpiryDeadline) {
- // Check hash algorithm of non-root cert.
- for i, cert := range chain {
- if i < len(chain)-1 {
- if helpers.HashAlgoString(cert.SignatureAlgorithm) == p.HashDeprecation.Target {
- return true
- }
- }
- }
- }
- }
-
- return false
-}
-
// Trust returns whether the platform has the root cert in the trusted store.
func (p Platform) Trust(root *x509.Certificate) bool {
// the key store is empty iff the platform doesn't carry a root store and trust whatever root store
@@ -216,17 +176,6 @@ func UntrustedPlatforms(root *x509.Certificate) []string {
return ret
}
-// DeprecatedSHA1Platforms returns a list of platforms which rejects the cert chain based on deprecation of SHA1.
-func DeprecatedSHA1Platforms(chain []*x509.Certificate) []string {
- ret := []string{}
- for _, platform := range Platforms {
- if platform.Deprecate(chain) && platform.HashDeprecation.Target == "SHA1" {
- ret = append(ret, platform.Name)
- }
- }
- return ret
-}
-
// CrossPlatformUbiquity returns a ubiquity score (persumably relecting the market share in percentage)
// based on whether the given chain can be verified with the different platforms' root certificate stores.
func CrossPlatformUbiquity(chain []*x509.Certificate) int {
@@ -241,7 +190,7 @@ func CrossPlatformUbiquity(chain []*x509.Certificate) int {
// 2. the chain satisfy the minimal constraints on hash function and key algorithm.
root := chain[len(chain)-1]
for _, platform := range Platforms {
- if platform.Trust(root) && !platform.Deprecate(chain) {
+ if platform.Trust(root) {
switch {
case platform.HashUbiquity <= ChainHashUbiquity(chain) && platform.KeyAlgoUbiquity <= ChainKeyAlgoUbiquity(chain):
totalWeight += platform.Weight
diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_test.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_test.go
index d8d6770e879..1cd73f85c18 100644
--- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_test.go
+++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/ubiquity/ubiquity_test.go
@@ -2,6 +2,7 @@ package ubiquity
import (
"crypto/x509"
+ "fmt"
"io/ioutil"
"testing"
"time"
@@ -10,13 +11,14 @@ import (
)
const (
- rsa1024 = "testdata/rsa1024sha1.pem"
- rsa2048 = "testdata/rsa2048sha2.pem"
- rsa3072 = "testdata/rsa3072sha2.pem"
- rsa4096 = "testdata/rsa4096sha2.pem"
- ecdsa256 = "testdata/ecdsa256sha2.pem"
- ecdsa384 = "testdata/ecdsa384sha2.pem"
- ecdsa521 = "testdata/ecdsa521sha2.pem"
+ rsa1024 = "testdata/rsa1024sha1.pem"
+ rsa2048 = "testdata/rsa2048sha2.pem"
+ rsa3072 = "testdata/rsa3072sha2.pem"
+ rsa4096 = "testdata/rsa4096sha2.pem"
+ ecdsa256 = "testdata/ecdsa256sha2.pem"
+ ecdsa384 = "testdata/ecdsa384sha2.pem"
+ ecdsa521 = "testdata/ecdsa521sha2.pem"
+ caMetadata = "testdata/ca.pem.metadata"
)
var rsa1024Cert, rsa2048Cert, rsa3072Cert, rsa4096Cert, ecdsa256Cert, ecdsa384Cert, ecdsa521Cert *x509.Certificate
@@ -26,6 +28,7 @@ func readCert(filename string) *x509.Certificate {
cert, _ := helpers.ParseCertificatePEM(bytes)
return cert
}
+
func init() {
rsa1024Cert = readCert(rsa1024)
rsa2048Cert = readCert(rsa2048)
@@ -176,6 +179,55 @@ func TestChainKeyAlgoUbiquity(t *testing.T) {
}
+func TestChainExpiryUbiquity(t *testing.T) {
+ // rsa1024Cert expires at year 2024
+ // rsa2048Cert expires at year 2019
+ // ecdsa256Cert expires at year 2019
+ chain1 := []*x509.Certificate{ecdsa256Cert, rsa2048Cert}
+ chain2 := []*x509.Certificate{ecdsa256Cert, rsa1024Cert}
+ if CompareExpiryUbiquity(chain1, chain2) >= 0 {
+ t.Fatal("Incorrect chain expiry ubiquity")
+ }
+
+ if CompareExpiryUbiquity(chain2, chain1) <= 0 {
+ t.Fatal("Incorrect chain expiry ubiquity")
+ }
+
+ if CompareExpiryUbiquity(chain1, chain1) != 0 {
+ t.Fatal("Incorrect chain expiry ubiquity")
+ }
+}
+
+func TestCompareChainExpiry(t *testing.T) {
+ // rsa1024Cert expires at 2024
+ // rsa2048Cert expires at 2019
+ // ecdsa256Cert expires at 2019
+ // both chain expires at year 2019.
+ chain1 := []*x509.Certificate{ecdsa256Cert, rsa2048Cert}
+ chain2 := []*x509.Certificate{ecdsa256Cert, rsa1024Cert}
+ if CompareChainExpiry(chain1, chain2) != 0 {
+ t.Fatal("Incorrect chain expiry")
+ }
+
+ if CompareExpiryUbiquity(chain1, chain1) != 0 {
+ t.Fatal("Incorrect chain expiry")
+ }
+}
+
+func TestCompareChainLength(t *testing.T) {
+ chain1 := []*x509.Certificate{ecdsa256Cert, rsa2048Cert}
+ chain2 := []*x509.Certificate{rsa1024Cert}
+ chain3 := []*x509.Certificate{rsa2048Cert}
+ // longer chain is ranked lower
+ if CompareChainLength(chain1, chain2) >= 0 {
+ t.Fatal("Incorrect chain length comparison")
+ }
+
+ if CompareChainLength(chain2, chain3) != 0 {
+ t.Fatal("Incorrect chain length comparison")
+ }
+}
+
func TestPlatformKeyStoreUbiquity(t *testing.T) {
cert1 := rsa1024Cert
cert2 := rsa2048Cert
@@ -184,14 +236,17 @@ func TestPlatformKeyStoreUbiquity(t *testing.T) {
// "Macrosoft" has all three certs.
// "Godzilla" has two certs, cert1 and cert2.
// "Pinapple" has cert1.
+ // "Colorful" has no key store data, default to trust any cert
// All platforms support the same crypto suite.
platformA := Platform{Name: "MacroSoft", Weight: 100, HashAlgo: "SHA2", KeyAlgo: "ECDSA256", KeyStoreFile: "testdata/macrosoft.pem"}
platformB := Platform{Name: "Godzilla", Weight: 100, HashAlgo: "SHA2", KeyAlgo: "ECDSA256", KeyStoreFile: "testdata/godzilla.pem"}
platformC := Platform{Name: "Pineapple", Weight: 100, HashAlgo: "SHA2", KeyAlgo: "ECDSA256", KeyStoreFile: "testdata/pineapple.pem"}
+ platformD := Platform{Name: "Colorful", Weight: 100, HashAlgo: "SHA2", KeyAlgo: "ECDSA256", KeyStoreFile: ""}
platformA.ParseAndLoad()
platformB.ParseAndLoad()
platformC.ParseAndLoad()
- Platforms = []Platform{platformA, platformB, platformC}
+ platformD.ParseAndLoad()
+ Platforms = []Platform{platformA, platformB, platformC, platformD}
// chain1 with root cert1 (RSA1024, SHA1), has the largest platform coverage.
// chain2 with root cert2 (RSA2048, SHA2), has the second largest coverage.
// chain3 with root cert3 (ECDSA256, SHA2), has the least coverage.
@@ -204,6 +259,50 @@ func TestPlatformKeyStoreUbiquity(t *testing.T) {
if CrossPlatformUbiquity(chain2) < CrossPlatformUbiquity(chain3) {
t.Fatal("Incorrect cross platform ubiquity")
}
+
+ if ComparePlatformUbiquity(chain1, chain2) < 0 {
+ t.Fatal("Incorrect cross platform ubiquity")
+ }
+
+ if ComparePlatformUbiquity(chain2, chain3) < 0 {
+ t.Fatal("Incorrect cross platform ubiquity")
+ }
+
+ // test UntrustedPlatforms()
+ u1 := UntrustedPlatforms(cert1)
+ if len(u1) != 0 {
+ t.Fatal("Incorrect UntrustedPlatforms")
+ }
+ u2 := UntrustedPlatforms(cert2)
+ if len(u2) != 1 {
+ t.Fatal("Incorrect UntrustedPlatforms")
+ }
+ u3 := UntrustedPlatforms(cert3)
+ if len(u3) != 2 {
+ t.Fatal("Incorrect UntrustedPlatforms")
+ }
+
+}
+
+func TestEmptyPlatformList(t *testing.T) {
+ Platforms = []Platform{}
+ cert := rsa1024Cert
+ chain := []*x509.Certificate{cert}
+ if CrossPlatformUbiquity(chain) != 0 {
+ t.Fatal("Incorrect cross platform ubiquity when Platforms is empty")
+ }
+ // test UntrustedPlatforms()
+ u1 := UntrustedPlatforms(cert)
+ if len(u1) != 0 {
+ t.Fatal("Incorrect UntrustedPlatforms when Platforms is empty")
+ }
+}
+
+func TestLoadPlatforms(t *testing.T) {
+ err := LoadPlatforms(caMetadata)
+ if err != nil {
+ t.Fatal(err)
+ }
}
func TestPlatformCryptoUbiquity(t *testing.T) {
@@ -215,9 +314,11 @@ func TestPlatformCryptoUbiquity(t *testing.T) {
platformA := Platform{Name: "TinySoft", Weight: 100, HashAlgo: "SHA1", KeyAlgo: "RSA", KeyStoreFile: "testdata/macrosoft.pem"}
platformB := Platform{Name: "SmallSoft", Weight: 100, HashAlgo: "SHA2", KeyAlgo: "RSA", KeyStoreFile: "testdata/macrosoft.pem"}
platformC := Platform{Name: "LargeSoft", Weight: 100, HashAlgo: "SHA2", KeyAlgo: "ECDSA256", KeyStoreFile: "testdata/macrosoft.pem"}
+ platformD := Platform{Name: "MediumSoft", Weight: 100, HashAlgo: "SHA2", KeyAlgo: "ECDSA384", KeyStoreFile: "testdata/macrosoft.pem"}
platformA.ParseAndLoad()
platformB.ParseAndLoad()
platformC.ParseAndLoad()
+ platformD.ParseAndLoad()
Platforms = []Platform{platformA, platformB, platformC}
// chain1 with root cert1 (RSA1024, SHA1), has the largest platform coverage.
// chain2 with root cert2 (RSA2048, SHA2), has the second largest coverage.
@@ -231,49 +332,13 @@ func TestPlatformCryptoUbiquity(t *testing.T) {
if CrossPlatformUbiquity(chain2) < CrossPlatformUbiquity(chain3) {
t.Fatal("Incorrect cross platform ubiquity")
}
-}
-func TestPlatformCryptoDeprecation(t *testing.T) {
- cert1 := rsa1024Cert
- cert2 := rsa2048Cert
- pweight1 := 1
- pweight2 := 10
- pweight3 := 100
- Jan1st2014 := time.Date(2014, time.January, 1, 0, 0, 0, 0, time.UTC)
- Jan1st2100 := time.Date(2100, time.January, 1, 0, 0, 0, 0, time.UTC)
- DeprecationPolicy2014 := &CryptoDeprecationPolicy{Target: "SHA1", EffectiveDate: Jan1st2014, ExpiryDeadline: Jan1st2014}
- DeprecationPolicy2100 := &CryptoDeprecationPolicy{Target: "SHA2", EffectiveDate: Jan1st2100, ExpiryDeadline: Jan1st2014}
- // All platforms have the same trust store but are with various crypto suite and deprecation policy.
- // platformA supports SHA1 only and has no deprecation plan of SHA1.
- // platformB supports SHA1/SHA2 and will deprecate SHA1 at year 2100.
- // platformC supports SHA1/SHA2 and will deprecate SHA1 at year 2014.
- platformA := Platform{Name: "TinySoft", Weight: pweight1, HashAlgo: "SHA1", KeyAlgo: "RSA", KeyStoreFile: "testdata/macrosoft.pem"}
- platformB := Platform{Name: "SmallSoft", Weight: pweight2, HashAlgo: "SHA2", KeyAlgo: "RSA", KeyStoreFile: "testdata/macrosoft.pem", HashDeprecation: DeprecationPolicy2100}
- platformC := Platform{Name: "LargeSoft", Weight: pweight3, HashAlgo: "SHA2", KeyAlgo: "RSA", KeyStoreFile: "testdata/macrosoft.pem", HashDeprecation: DeprecationPolicy2014}
- platformA.ParseAndLoad()
- platformB.ParseAndLoad()
- platformC.ParseAndLoad()
- Platforms = []Platform{platformA, platformB, platformC}
- // chain1 is accepted by platform A, B and C. It's not rejected by platFormC because root cert is not subject to SHA1 deprecation.
- chain1 := []*x509.Certificate{cert1}
- // chain2 is accepted by platform A, B. It's rejected by platFormC because leaf cert is subject to SHA1 deprecation.
- chain2 := []*x509.Certificate{cert1, cert1}
- // chain3 is accepted by platformB and platFormC. It's rejected by platformA due to A's inablity to support SHA2.
- chain3 := []*x509.Certificate{cert2, cert1}
-
- if CrossPlatformUbiquity(chain1) != pweight1+pweight2+pweight3 {
- t.Fatal("Incorrect cross platform ubiquity: ", CrossPlatformUbiquity(chain1))
- }
- if CrossPlatformUbiquity(chain2) != pweight1+pweight2 {
- t.Fatal("Incorrect cross platform ubiquity: ", CrossPlatformUbiquity(chain2))
- }
- if CrossPlatformUbiquity(chain3) != pweight2+pweight3 {
- t.Fatal("Incorrect cross platform ubiquity: ", CrossPlatformUbiquity(chain3))
+ if ComparePlatformUbiquity(chain1, chain2) < 0 {
+ t.Fatal("Incorrect cross platform ubiquity")
}
- dplatforms := DeprecatedSHA1Platforms(chain2)
- if len(dplatforms) != 1 || dplatforms[0] != "LargeSoft" {
- t.Fatal("Incorrect deprecation checking: ", dplatforms)
+ if ComparePlatformUbiquity(chain1, chain2) < 0 {
+ t.Fatal("Incorrect cross platform ubiquity")
}
}
@@ -327,6 +392,23 @@ func TestCompareSHA2Homogeneity(t *testing.T) {
}
}
+func TestFilterTrivial(t *testing.T) {
+ var chain []*x509.Certificate
+ var chains [][]*x509.Certificate
+ ret := Filter(chains, CompareChainHashPriority)
+ if len(ret) != 0 {
+ t.Fatal("Incorrect filtering")
+ }
+
+ chain = []*x509.Certificate{rsa2048Cert}
+ chains = [][]*x509.Certificate{chain}
+
+ ret = Filter(chains, CompareChainHashPriority)
+ if len(ret) != 1 {
+ t.Fatal("Incorrect filtering")
+ }
+}
+
func TestFilterChainHashPriority(t *testing.T) {
var chain1, chain2 []*x509.Certificate
chain1 = []*x509.Certificate{rsa2048Cert} // SHA256
@@ -342,6 +424,7 @@ func TestFilterChainHashPriority(t *testing.T) {
if ret[0][0] != ecdsa384Cert {
t.Fatal("Incorrect chain hash priority filtering")
}
+
}
func TestFilterChainKeyAlgoPriority(t *testing.T) {
@@ -411,3 +494,155 @@ func TestFilterChainKeyAlgoUbiquity(t *testing.T) {
t.Fatal("Incorrect chain key algo priority filtering")
}
}
+
+func TestFlagBySHA1DeprecationPolicy(t *testing.T) {
+ cert1 := rsa1024Cert
+ cert2 := rsa2048Cert
+ Jan1st2014 := time.Date(2014, time.January, 1, 0, 0, 0, 0, time.UTC)
+ Jan1st2100 := time.Date(2100, time.January, 1, 0, 0, 0, 0, time.UTC)
+ policy1 := SHA1DeprecationPolicy{
+ Description: "SHA1 should be gone years ago",
+ ExpiryDeadline: Jan1st2014,
+ }
+ policy2 := SHA1DeprecationPolicy{
+ Description: "SHA1 is perfect for another century",
+ ExpiryDeadline: Jan1st2100,
+ }
+ policy3 := SHA1DeprecationPolicy{
+ Description: "effectively one century later, reject SHA1 expires on 2014",
+ EffectiveDate: Jan1st2100,
+ ExpiryDeadline: Jan1st2014,
+ }
+ policy4 := SHA1DeprecationPolicy{
+ Description: "no more new SHA1 cert",
+ NeverIssueAfter: Jan1st2014,
+ }
+ // chain1 is accepted univerally. It's not flagged because root cert is not subject to SHA1 deprecation.
+ chain1 := []*x509.Certificate{cert1}
+ if policy1.Flag(chain1) || policy2.Flag(chain1) || policy3.Flag(chain1) || policy4.Flag(chain1) {
+ t.Fatal("Incorrect SHA1 deprecation")
+ }
+
+ // chain2 is accepted by policy2 and policy3. It's flagged by policy1 and policy4
+ chain2 := []*x509.Certificate{cert1, cert1}
+ if !policy1.Flag(chain2) || policy2.Flag(chain2) || policy3.Flag(chain2) || !policy4.Flag(chain2) {
+ t.Fatal("Incorrect SHA1 deprecation")
+ }
+
+ // chain3 is accepted by universally since the leaf cert and the intermediate are signed by SHA-256
+ chain3 := []*x509.Certificate{cert2, cert2, cert1}
+ if policy1.Flag(chain3) || policy2.Flag(chain3) || policy3.Flag(chain3) || policy4.Flag(chain3) {
+ t.Fatal("Incorrect SHA1 deprecation")
+ }
+}
+
+func TestSHA1DeprecationMessages(t *testing.T) {
+ cert1 := rsa1024Cert
+ cert2 := rsa2048Cert
+ chain1 := []*x509.Certificate{cert1}
+ chain2 := []*x509.Certificate{cert1, cert1}
+ chain3 := []*x509.Certificate{cert2, cert1, cert1}
+ chain4 := []*x509.Certificate{cert2, cert2, cert1}
+ messages := []string{}
+
+ Jan1st2014 := time.Date(2014, time.January, 1, 0, 0, 0, 0, time.UTC)
+ Jan1st2100 := time.Date(2100, time.January, 1, 0, 0, 0, 0, time.UTC)
+ policy1 := SHA1DeprecationPolicy{
+ Platform: "Browser A",
+ Description: "minor warning",
+ Severity: Low,
+ ExpiryDeadline: Jan1st2014,
+ }
+ policy2 := SHA1DeprecationPolicy{
+ Platform: "Browser A",
+ Description: "minor warning",
+ Severity: Medium,
+ ExpiryDeadline: Jan1st2014,
+ }
+ policy3 := SHA1DeprecationPolicy{
+ Platform: "Browser B",
+ Description: "reject",
+ Severity: High,
+ NeverIssueAfter: Jan1st2014,
+ }
+ policy4 := SHA1DeprecationPolicy{
+ Platform: "Browser C",
+ Description: "reject but not now",
+ Severity: High,
+ NeverIssueAfter: Jan1st2014,
+ EffectiveDate: Jan1st2100,
+ }
+
+ // The only policy has severity low
+ SHA1DeprecationPolicys = []SHA1DeprecationPolicy{policy1}
+ messages = SHA1DeprecationMessages(chain1)
+ // chain1 with only root is not subject to deprecation
+ if len(messages) != 0 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain2 has SHA-1 leaf cert, subject to deprecation
+ messages = SHA1DeprecationMessages(chain2)
+ if len(messages) != 1 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain3 has SHA-1 intermediate cert, subject to deprecation
+ messages = SHA1DeprecationMessages(chain3)
+ if len(messages) != 1 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain4 has no SHA-1 leaf or intermediate, not subject to deprecation
+ messages = SHA1DeprecationMessages(chain4)
+ if len(messages) != 0 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+
+ // A second policy that has higher severity , so it should takes effect and override lower one.
+ SHA1DeprecationPolicys = []SHA1DeprecationPolicy{policy1, policy2}
+ // chain1 only has root cert, not subject to deprecation policy
+ messages = SHA1DeprecationMessages(chain1)
+ if len(messages) != 0 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain2 has a SHA-1 leaf cert, will have a message from policy2
+ messages = SHA1DeprecationMessages(chain2)
+ if len(messages) != 1 ||
+ messages[0] != fmt.Sprintf("%s %s due to SHA-1 deprecation", policy2.Platform, policy2.Description) {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain3 has a SHA-1 intermediate cert, will have a message from policy2
+ messages = SHA1DeprecationMessages(chain3)
+ if len(messages) != 1 ||
+ messages[0] != fmt.Sprintf("%s %s due to SHA-1 deprecation", policy2.Platform, policy2.Description) {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain4 is not subject to any deprecation policy
+ messages = SHA1DeprecationMessages(chain4)
+ if len(messages) != 0 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+
+ // Add two policies. One tests for newly issued leaf certificate after a deadline, the other is the same,
+ // but takes effect at the 22nd century.
+ SHA1DeprecationPolicys = []SHA1DeprecationPolicy{policy1, policy2, policy3, policy4}
+ // chain1 only has root cert, not subject to any deprecation policy
+ messages = SHA1DeprecationMessages(chain1)
+ if len(messages) != 0 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain2 now is flagged by two policies: policy2 and policy3
+ messages = SHA1DeprecationMessages(chain2)
+ if len(messages) != 2 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain3 is not flagged by policy3 but policy2
+ messages = SHA1DeprecationMessages(chain3)
+ if len(messages) != 1 ||
+ messages[0] != fmt.Sprintf("%s %s due to SHA-1 deprecation", policy2.Platform, policy2.Description) {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+ // chain4 is not subject to any deprecation policy
+ messages = SHA1DeprecationMessages(chain4)
+ if len(messages) != 0 {
+ t.Fatal("Incorrect SHA1 deprecation reporting")
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/go-rc2/LICENSE b/Godeps/_workspace/src/github.com/dgryski/go-rc2/LICENSE
new file mode 100644
index 00000000000..160d24da6b1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/go-rc2/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Damian Gryski
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Godeps/_workspace/src/github.com/dgryski/go-rc2/bench_test.go b/Godeps/_workspace/src/github.com/dgryski/go-rc2/bench_test.go
new file mode 100644
index 00000000000..639b4cb9c9c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/go-rc2/bench_test.go
@@ -0,0 +1,40 @@
+package rc2
+
+import (
+ "testing"
+
+ ebfe "github.com/ebfe/rc2"
+)
+
+func BenchmarkEncrypt(b *testing.B) {
+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Encrypt(src[:], src[:])
+ }
+}
+func BenchmarkEbfeEncrypt(b *testing.B) {
+ r, _ := ebfe.NewCipher([]byte{0, 0, 0, 0, 0, 0, 0, 0})
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Encrypt(src[:], src[:])
+ }
+}
+func BenchmarkDecrypt(b *testing.B) {
+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Decrypt(src[:], src[:])
+ }
+}
+func BenchmarkEbfeDecrypt(b *testing.B) {
+ r, _ := ebfe.NewCipher([]byte{0, 0, 0, 0, 0, 0, 0, 0})
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Decrypt(src[:], src[:])
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/go-rc2/rc2.go b/Godeps/_workspace/src/github.com/dgryski/go-rc2/rc2.go
new file mode 100644
index 00000000000..d33a4988871
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/go-rc2/rc2.go
@@ -0,0 +1,270 @@
+// Package rc2 implements the RC2 cipher
+/*
+https://www.ietf.org/rfc/rfc2268.txt
+http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf
+
+This code is licensed under the MIT license.
+*/
+package rc2
+
+import (
+ "crypto/cipher"
+ "encoding/binary"
+)
+
+// The rc2 block size in bytes
+const BlockSize = 8
+
+type rc2Cipher struct {
+ k [64]uint16
+}
+
+// New returns a new rc2 cipher with the given key and effective key length t1
+func New(key []byte, t1 int) (cipher.Block, error) {
+ // TODO(dgryski): error checking for key length
+ return &rc2Cipher{
+ k: expandKey(key, t1),
+ }, nil
+}
+
+func (_ *rc2Cipher) BlockSize() int { return BlockSize }
+
+var piTable = [256]byte{
+ 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
+ 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
+ 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
+ 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
+ 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
+ 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
+ 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
+ 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
+ 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
+ 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
+ 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
+ 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
+ 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
+ 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
+ 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
+ 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad,
+}
+
+func expandKey(key []byte, t1 int) [64]uint16 {
+
+ l := make([]byte, 128)
+ copy(l, key)
+
+ var t = len(key)
+ var t8 = (t1 + 7) / 8
+ var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8))))
+
+ for i := len(key); i < 128; i++ {
+ l[i] = piTable[l[i-1]+l[uint8(i-t)]]
+ }
+
+ l[128-t8] = piTable[l[128-t8]&tm]
+
+ for i := 127 - t8; i >= 0; i-- {
+ l[i] = piTable[l[i+1]^l[i+t8]]
+ }
+
+ var k [64]uint16
+
+ for i := range k {
+ k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256
+ }
+
+ return k
+}
+
+func rotl16(x uint16, b uint) uint16 {
+ return (x >> (16 - b)) | (x << b)
+}
+
+func (c *rc2Cipher) Encrypt(dst, src []byte) {
+
+ r0 := binary.LittleEndian.Uint16(src[0:])
+ r1 := binary.LittleEndian.Uint16(src[2:])
+ r2 := binary.LittleEndian.Uint16(src[4:])
+ r3 := binary.LittleEndian.Uint16(src[6:])
+
+ var j int
+
+ for j <= 16 {
+ // mix r0
+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+ r0 = rotl16(r0, 1)
+ j++
+
+ // mix r1
+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+ r1 = rotl16(r1, 2)
+ j++
+
+ // mix r2
+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+ r2 = rotl16(r2, 3)
+ j++
+
+ // mix r3
+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+ r3 = rotl16(r3, 5)
+ j++
+
+ }
+
+ r0 = r0 + c.k[r3&63]
+ r1 = r1 + c.k[r0&63]
+ r2 = r2 + c.k[r1&63]
+ r3 = r3 + c.k[r2&63]
+
+ for j <= 40 {
+
+ // mix r0
+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+ r0 = rotl16(r0, 1)
+ j++
+
+ // mix r1
+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+ r1 = rotl16(r1, 2)
+ j++
+
+ // mix r2
+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+ r2 = rotl16(r2, 3)
+ j++
+
+ // mix r3
+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+ r3 = rotl16(r3, 5)
+ j++
+
+ }
+
+ r0 = r0 + c.k[r3&63]
+ r1 = r1 + c.k[r0&63]
+ r2 = r2 + c.k[r1&63]
+ r3 = r3 + c.k[r2&63]
+
+ for j <= 60 {
+
+ // mix r0
+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+ r0 = rotl16(r0, 1)
+ j++
+
+ // mix r1
+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+ r1 = rotl16(r1, 2)
+ j++
+
+ // mix r2
+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+ r2 = rotl16(r2, 3)
+ j++
+
+ // mix r3
+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+ r3 = rotl16(r3, 5)
+ j++
+ }
+
+ binary.LittleEndian.PutUint16(dst[0:], r0)
+ binary.LittleEndian.PutUint16(dst[2:], r1)
+ binary.LittleEndian.PutUint16(dst[4:], r2)
+ binary.LittleEndian.PutUint16(dst[6:], r3)
+}
+
+func (c *rc2Cipher) Decrypt(dst, src []byte) {
+
+ r0 := binary.LittleEndian.Uint16(src[0:])
+ r1 := binary.LittleEndian.Uint16(src[2:])
+ r2 := binary.LittleEndian.Uint16(src[4:])
+ r3 := binary.LittleEndian.Uint16(src[6:])
+
+ j := 63
+
+ for j >= 44 {
+ // unmix r3
+ r3 = rotl16(r3, 16-5)
+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+ j--
+
+ // unmix r2
+ r2 = rotl16(r2, 16-3)
+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+ j--
+
+ // unmix r1
+ r1 = rotl16(r1, 16-2)
+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+ j--
+
+ // unmix r0
+ r0 = rotl16(r0, 16-1)
+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+ j--
+ }
+
+ r3 = r3 - c.k[r2&63]
+ r2 = r2 - c.k[r1&63]
+ r1 = r1 - c.k[r0&63]
+ r0 = r0 - c.k[r3&63]
+
+ for j >= 20 {
+ // unmix r3
+ r3 = rotl16(r3, 16-5)
+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+ j--
+
+ // unmix r2
+ r2 = rotl16(r2, 16-3)
+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+ j--
+
+ // unmix r1
+ r1 = rotl16(r1, 16-2)
+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+ j--
+
+ // unmix r0
+ r0 = rotl16(r0, 16-1)
+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+ j--
+
+ }
+
+ r3 = r3 - c.k[r2&63]
+ r2 = r2 - c.k[r1&63]
+ r1 = r1 - c.k[r0&63]
+ r0 = r0 - c.k[r3&63]
+
+ for j >= 0 {
+
+ // unmix r3
+ r3 = rotl16(r3, 16-5)
+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+ j--
+
+ // unmix r2
+ r2 = rotl16(r2, 16-3)
+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+ j--
+
+ // unmix r1
+ r1 = rotl16(r1, 16-2)
+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+ j--
+
+ // unmix r0
+ r0 = rotl16(r0, 16-1)
+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+ j--
+
+ }
+
+ binary.LittleEndian.PutUint16(dst[0:], r0)
+ binary.LittleEndian.PutUint16(dst[2:], r1)
+ binary.LittleEndian.PutUint16(dst[4:], r2)
+ binary.LittleEndian.PutUint16(dst[6:], r3)
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/go-rc2/rc2_test.go b/Godeps/_workspace/src/github.com/dgryski/go-rc2/rc2_test.go
new file mode 100644
index 00000000000..237c3d1591b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/go-rc2/rc2_test.go
@@ -0,0 +1,89 @@
+package rc2
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+)
+
+func TestEncryptDecrypt(t *testing.T) {
+
+ // TODO(dgryski): add the rest of the test vectors from the RFC
+ var tests = []struct {
+ key string
+ plain string
+ cipher string
+ t1 int
+ }{
+ {
+ "0000000000000000",
+ "0000000000000000",
+ "ebb773f993278eff",
+ 63,
+ },
+ {
+ "ffffffffffffffff",
+ "ffffffffffffffff",
+ "278b27e42e2f0d49",
+ 64,
+ },
+ {
+ "3000000000000000",
+ "1000000000000001",
+ "30649edf9be7d2c2",
+ 64,
+ },
+ {
+ "88",
+ "0000000000000000",
+ "61a8a244adacccf0",
+ 64,
+ },
+ {
+ "88bca90e90875a",
+ "0000000000000000",
+ "6ccf4308974c267f",
+ 64,
+ },
+ {
+ "88bca90e90875a7f0f79c384627bafb2",
+ "0000000000000000",
+ "1a807d272bbe5db1",
+ 64,
+ },
+ {
+ "88bca90e90875a7f0f79c384627bafb2",
+ "0000000000000000",
+ "2269552ab0f85ca6",
+ 128,
+ },
+ {
+ "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e",
+ "0000000000000000",
+ "5b78d3a43dfff1f1",
+ 129,
+ },
+ }
+
+ for _, tt := range tests {
+ k, _ := hex.DecodeString(tt.key)
+ p, _ := hex.DecodeString(tt.plain)
+ c, _ := hex.DecodeString(tt.cipher)
+
+ b, _ := New(k, tt.t1)
+
+ var dst [8]byte
+
+ b.Encrypt(dst[:], p)
+
+ if !bytes.Equal(dst[:], c) {
+ t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c)
+ }
+
+ b.Decrypt(dst[:], c)
+
+ if !bytes.Equal(dst[:], p) {
+ t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p)
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/.gitignore b/Godeps/_workspace/src/github.com/miekg/pkcs11/.gitignore
new file mode 100644
index 00000000000..6e92f57d464
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/.gitignore
@@ -0,0 +1 @@
+tags
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/LICENSE b/Godeps/_workspace/src/github.com/miekg/pkcs11/LICENSE
new file mode 100644
index 00000000000..ce25d13ab84
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013 Miek Gieben. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Miek Gieben nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/README.md b/Godeps/_workspace/src/github.com/miekg/pkcs11/README.md
new file mode 100644
index 00000000000..6e7e550c212
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/README.md
@@ -0,0 +1,48 @@
+# PKCS#11
+
+This is a Go implementation of the PKCS#11 API. It wraps the library closely, but uses Go idiom
+were it makes sense. It has been tested with SoftHSM.
+
+## SoftHSM
+
+* Make it use a custom configuration file
+
+ export SOFTHSM_CONF=$PWD/softhsm.conf
+
+* Then use `softhsm` to init it
+
+ softhsm --init-token --slot 0 --label test --pin 1234
+
+* Then use `libsofthsm.so` as the pkcs11 module:
+
+ p := pkcs11.New("/usr/lib/softhsm/libsofthsm.so")
+
+## Examples
+
+A skeleton program would look somewhat like this (yes, pkcs#11 is verbose):
+
+ p := pkcs11.New("/usr/lib/softhsm/libsofthsm.so")
+ p.Initialize()
+ defer p.Destroy()
+ defer p.Finalize()
+ slots, _ := p.GetSlotList(true)
+ session, _ := p.OpenSession(slots[0], pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
+ defer p.CloseSession(session)
+ p.Login(session, pkcs11.CKU_USER, "1234")
+ defer p.Logout(session)
+ p.DigestInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA_1, nil)})
+ hash, err := p.Digest(session, []byte("this is a string"))
+ for _, d := range hash {
+ fmt.Printf("%x", d)
+ }
+ fmt.Println()
+
+Further examples are included in the tests.
+
+# TODO
+
+* Fix/double check endian stuff, see types.go NewAttribute();
+* Kill C.Sizeof in that same function.
+* Look at the memory copying in fast functions (sign, hash etc).
+* Fix inconsistencies in naming?
+* Add tests -- there are way too few
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/const.go b/Godeps/_workspace/src/github.com/miekg/pkcs11/const.go
new file mode 100644
index 00000000000..79a25e345db
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/const.go
@@ -0,0 +1,561 @@
+// Copyright 2013 Miek Gieben. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs11
+
+const (
+ CKU_SO uint = 0
+ CKU_USER uint = 1
+ CKU_CONTEXT_SPECIFIC uint = 2
+)
+
+const (
+ CKO_DATA uint = 0x00000000
+ CKO_CERTIFICATE uint = 0x00000001
+ CKO_PUBLIC_KEY uint = 0x00000002
+ CKO_PRIVATE_KEY uint = 0x00000003
+ CKO_SECRET_KEY uint = 0x00000004
+ CKO_HW_FEATURE uint = 0x00000005
+ CKO_DOMAIN_PARAMETERS uint = 0x00000006
+ CKO_MECHANISM uint = 0x00000007
+ CKO_OTP_KEY uint = 0x00000008
+ CKO_VENDOR_DEFINED uint = 0x80000000
+)
+
+// Generated with: awk '/#define CK[AFKMR]/{ print $2 "=" $3 }' pkcs11t.h
+
+// All the flag (CKF_), attribute (CKA_), error code (CKR_), key type (CKK_) and
+// mechanism (CKM_) constants as defined in PKCS#11.
+const (
+ CKF_TOKEN_PRESENT = 0x00000001
+ CKF_REMOVABLE_DEVICE = 0x00000002
+ CKF_HW_SLOT = 0x00000004
+ CKF_RNG = 0x00000001
+ CKF_WRITE_PROTECTED = 0x00000002
+ CKF_LOGIN_REQUIRED = 0x00000004
+ CKF_USER_PIN_INITIALIZED = 0x00000008
+ CKF_RESTORE_KEY_NOT_NEEDED = 0x00000020
+ CKF_CLOCK_ON_TOKEN = 0x00000040
+ CKF_PROTECTED_AUTHENTICATION_PATH = 0x00000100
+ CKF_DUAL_CRYPTO_OPERATIONS = 0x00000200
+ CKF_TOKEN_INITIALIZED = 0x00000400
+ CKF_SECONDARY_AUTHENTICATION = 0x00000800
+ CKF_USER_PIN_COUNT_LOW = 0x00010000
+ CKF_USER_PIN_FINAL_TRY = 0x00020000
+ CKF_USER_PIN_LOCKED = 0x00040000
+ CKF_USER_PIN_TO_BE_CHANGED = 0x00080000
+ CKF_SO_PIN_COUNT_LOW = 0x00100000
+ CKF_SO_PIN_FINAL_TRY = 0x00200000
+ CKF_SO_PIN_LOCKED = 0x00400000
+ CKF_SO_PIN_TO_BE_CHANGED = 0x00800000
+ CKF_RW_SESSION = 0x00000002
+ CKF_SERIAL_SESSION = 0x00000004
+ CKK_RSA = 0x00000000
+ CKK_DSA = 0x00000001
+ CKK_DH = 0x00000002
+ CKK_ECDSA = 0x00000003
+ CKK_EC = 0x00000003
+ CKK_X9_42_DH = 0x00000004
+ CKK_KEA = 0x00000005
+ CKK_GENERIC_SECRET = 0x00000010
+ CKK_RC2 = 0x00000011
+ CKK_RC4 = 0x00000012
+ CKK_DES = 0x00000013
+ CKK_DES2 = 0x00000014
+ CKK_DES3 = 0x00000015
+ CKK_CAST = 0x00000016
+ CKK_CAST3 = 0x00000017
+ CKK_CAST5 = 0x00000018
+ CKK_CAST128 = 0x00000018
+ CKK_RC5 = 0x00000019
+ CKK_IDEA = 0x0000001A
+ CKK_SKIPJACK = 0x0000001B
+ CKK_BATON = 0x0000001C
+ CKK_JUNIPER = 0x0000001D
+ CKK_CDMF = 0x0000001E
+ CKK_AES = 0x0000001F
+ CKK_BLOWFISH = 0x00000020
+ CKK_TWOFISH = 0x00000021
+ CKK_SECURID = 0x00000022
+ CKK_HOTP = 0x00000023
+ CKK_ACTI = 0x00000024
+ CKK_CAMELLIA = 0x00000025
+ CKK_ARIA = 0x00000026
+ CKK_VENDOR_DEFINED = 0x80000000
+ CKF_ARRAY_ATTRIBUTE = 0x40000000
+ CKA_CLASS = 0x00000000
+ CKA_TOKEN = 0x00000001
+ CKA_PRIVATE = 0x00000002
+ CKA_LABEL = 0x00000003
+ CKA_APPLICATION = 0x00000010
+ CKA_VALUE = 0x00000011
+ CKA_OBJECT_ID = 0x00000012
+ CKA_CERTIFICATE_TYPE = 0x00000080
+ CKA_ISSUER = 0x00000081
+ CKA_SERIAL_NUMBER = 0x00000082
+ CKA_AC_ISSUER = 0x00000083
+ CKA_OWNER = 0x00000084
+ CKA_ATTR_TYPES = 0x00000085
+ CKA_TRUSTED = 0x00000086
+ CKA_CERTIFICATE_CATEGORY = 0x00000087
+ CKA_JAVA_MIDP_SECURITY_DOMAIN = 0x00000088
+ CKA_URL = 0x00000089
+ CKA_HASH_OF_SUBJECT_PUBLIC_KEY = 0x0000008A
+ CKA_HASH_OF_ISSUER_PUBLIC_KEY = 0x0000008B
+ CKA_CHECK_VALUE = 0x00000090
+ CKA_KEY_TYPE = 0x00000100
+ CKA_SUBJECT = 0x00000101
+ CKA_ID = 0x00000102
+ CKA_SENSITIVE = 0x00000103
+ CKA_ENCRYPT = 0x00000104
+ CKA_DECRYPT = 0x00000105
+ CKA_WRAP = 0x00000106
+ CKA_UNWRAP = 0x00000107
+ CKA_SIGN = 0x00000108
+ CKA_SIGN_RECOVER = 0x00000109
+ CKA_VERIFY = 0x0000010A
+ CKA_VERIFY_RECOVER = 0x0000010B
+ CKA_DERIVE = 0x0000010C
+ CKA_START_DATE = 0x00000110 // Use time.Time as a value.
+ CKA_END_DATE = 0x00000111 // Use time.Time as a value.
+ CKA_MODULUS = 0x00000120
+ CKA_MODULUS_BITS = 0x00000121
+ CKA_PUBLIC_EXPONENT = 0x00000122 // Use []byte slice as a value.
+ CKA_PRIVATE_EXPONENT = 0x00000123
+ CKA_PRIME_1 = 0x00000124
+ CKA_PRIME_2 = 0x00000125
+ CKA_EXPONENT_1 = 0x00000126
+ CKA_EXPONENT_2 = 0x00000127
+ CKA_COEFFICIENT = 0x00000128
+ CKA_PRIME = 0x00000130
+ CKA_SUBPRIME = 0x00000131
+ CKA_BASE = 0x00000132
+ CKA_PRIME_BITS = 0x00000133
+ CKA_SUBPRIME_BITS = 0x00000134
+ CKA_SUB_PRIME_BITS = CKA_SUBPRIME_BITS
+ CKA_VALUE_BITS = 0x00000160
+ CKA_VALUE_LEN = 0x00000161
+ CKA_EXTRACTABLE = 0x00000162
+ CKA_LOCAL = 0x00000163
+ CKA_NEVER_EXTRACTABLE = 0x00000164
+ CKA_ALWAYS_SENSITIVE = 0x00000165
+ CKA_KEY_GEN_MECHANISM = 0x00000166
+ CKA_MODIFIABLE = 0x00000170
+ CKA_ECDSA_PARAMS = 0x00000180
+ CKA_EC_PARAMS = 0x00000180
+ CKA_EC_POINT = 0x00000181
+ CKA_SECONDARY_AUTH = 0x00000200
+ CKA_AUTH_PIN_FLAGS = 0x00000201
+ CKA_ALWAYS_AUTHENTICATE = 0x00000202
+ CKA_WRAP_WITH_TRUSTED = 0x00000210
+ CKA_WRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000211)
+ CKA_UNWRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000212)
+ CKA_OTP_FORMAT = 0x00000220
+ CKA_OTP_LENGTH = 0x00000221
+ CKA_OTP_TIME_INTERVAL = 0x00000222
+ CKA_OTP_USER_FRIENDLY_MODE = 0x00000223
+ CKA_OTP_CHALLENGE_REQUIREMENT = 0x00000224
+ CKA_OTP_TIME_REQUIREMENT = 0x00000225
+ CKA_OTP_COUNTER_REQUIREMENT = 0x00000226
+ CKA_OTP_PIN_REQUIREMENT = 0x00000227
+ CKA_OTP_COUNTER = 0x0000022E
+ CKA_OTP_TIME = 0x0000022F
+ CKA_OTP_USER_IDENTIFIER = 0x0000022A
+ CKA_OTP_SERVICE_IDENTIFIER = 0x0000022B
+ CKA_OTP_SERVICE_LOGO = 0x0000022C
+ CKA_OTP_SERVICE_LOGO_TYPE = 0x0000022D
+ CKA_HW_FEATURE_TYPE = 0x00000300
+ CKA_RESET_ON_INIT = 0x00000301
+ CKA_HAS_RESET = 0x00000302
+ CKA_PIXEL_X = 0x00000400
+ CKA_PIXEL_Y = 0x00000401
+ CKA_RESOLUTION = 0x00000402
+ CKA_CHAR_ROWS = 0x00000403
+ CKA_CHAR_COLUMNS = 0x00000404
+ CKA_COLOR = 0x00000405
+ CKA_BITS_PER_PIXEL = 0x00000406
+ CKA_CHAR_SETS = 0x00000480
+ CKA_ENCODING_METHODS = 0x00000481
+ CKA_MIME_TYPES = 0x00000482
+ CKA_MECHANISM_TYPE = 0x00000500
+ CKA_REQUIRED_CMS_ATTRIBUTES = 0x00000501
+ CKA_DEFAULT_CMS_ATTRIBUTES = 0x00000502
+ CKA_SUPPORTED_CMS_ATTRIBUTES = 0x00000503
+ CKA_ALLOWED_MECHANISMS = (CKF_ARRAY_ATTRIBUTE | 0x00000600)
+ CKA_VENDOR_DEFINED = 0x80000000
+ CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000000
+ CKM_RSA_PKCS = 0x00000001
+ CKM_RSA_9796 = 0x00000002
+ CKM_RSA_X_509 = 0x00000003
+ CKM_MD2_RSA_PKCS = 0x00000004
+ CKM_MD5_RSA_PKCS = 0x00000005
+ CKM_SHA1_RSA_PKCS = 0x00000006
+ CKM_RIPEMD128_RSA_PKCS = 0x00000007
+ CKM_RIPEMD160_RSA_PKCS = 0x00000008
+ CKM_RSA_PKCS_OAEP = 0x00000009
+ CKM_RSA_X9_31_KEY_PAIR_GEN = 0x0000000A
+ CKM_RSA_X9_31 = 0x0000000B
+ CKM_SHA1_RSA_X9_31 = 0x0000000C
+ CKM_RSA_PKCS_PSS = 0x0000000D
+ CKM_SHA1_RSA_PKCS_PSS = 0x0000000E
+ CKM_DSA_KEY_PAIR_GEN = 0x00000010
+ CKM_DSA = 0x00000011
+ CKM_DSA_SHA1 = 0x00000012
+ CKM_DH_PKCS_KEY_PAIR_GEN = 0x00000020
+ CKM_DH_PKCS_DERIVE = 0x00000021
+ CKM_X9_42_DH_KEY_PAIR_GEN = 0x00000030
+ CKM_X9_42_DH_DERIVE = 0x00000031
+ CKM_X9_42_DH_HYBRID_DERIVE = 0x00000032
+ CKM_X9_42_MQV_DERIVE = 0x00000033
+ CKM_SHA256_RSA_PKCS = 0x00000040
+ CKM_SHA384_RSA_PKCS = 0x00000041
+ CKM_SHA512_RSA_PKCS = 0x00000042
+ CKM_SHA256_RSA_PKCS_PSS = 0x00000043
+ CKM_SHA384_RSA_PKCS_PSS = 0x00000044
+ CKM_SHA512_RSA_PKCS_PSS = 0x00000045
+ CKM_SHA224_RSA_PKCS = 0x00000046
+ CKM_SHA224_RSA_PKCS_PSS = 0x00000047
+ CKM_RC2_KEY_GEN = 0x00000100
+ CKM_RC2_ECB = 0x00000101
+ CKM_RC2_CBC = 0x00000102
+ CKM_RC2_MAC = 0x00000103
+ CKM_RC2_MAC_GENERAL = 0x00000104
+ CKM_RC2_CBC_PAD = 0x00000105
+ CKM_RC4_KEY_GEN = 0x00000110
+ CKM_RC4 = 0x00000111
+ CKM_DES_KEY_GEN = 0x00000120
+ CKM_DES_ECB = 0x00000121
+ CKM_DES_CBC = 0x00000122
+ CKM_DES_MAC = 0x00000123
+ CKM_DES_MAC_GENERAL = 0x00000124
+ CKM_DES_CBC_PAD = 0x00000125
+ CKM_DES2_KEY_GEN = 0x00000130
+ CKM_DES3_KEY_GEN = 0x00000131
+ CKM_DES3_ECB = 0x00000132
+ CKM_DES3_CBC = 0x00000133
+ CKM_DES3_MAC = 0x00000134
+ CKM_DES3_MAC_GENERAL = 0x00000135
+ CKM_DES3_CBC_PAD = 0x00000136
+ CKM_CDMF_KEY_GEN = 0x00000140
+ CKM_CDMF_ECB = 0x00000141
+ CKM_CDMF_CBC = 0x00000142
+ CKM_CDMF_MAC = 0x00000143
+ CKM_CDMF_MAC_GENERAL = 0x00000144
+ CKM_CDMF_CBC_PAD = 0x00000145
+ CKM_DES_OFB64 = 0x00000150
+ CKM_DES_OFB8 = 0x00000151
+ CKM_DES_CFB64 = 0x00000152
+ CKM_DES_CFB8 = 0x00000153
+ CKM_MD2 = 0x00000200
+ CKM_MD2_HMAC = 0x00000201
+ CKM_MD2_HMAC_GENERAL = 0x00000202
+ CKM_MD5 = 0x00000210
+ CKM_MD5_HMAC = 0x00000211
+ CKM_MD5_HMAC_GENERAL = 0x00000212
+ CKM_SHA_1 = 0x00000220
+ CKM_SHA_1_HMAC = 0x00000221
+ CKM_SHA_1_HMAC_GENERAL = 0x00000222
+ CKM_RIPEMD128 = 0x00000230
+ CKM_RIPEMD128_HMAC = 0x00000231
+ CKM_RIPEMD128_HMAC_GENERAL = 0x00000232
+ CKM_RIPEMD160 = 0x00000240
+ CKM_RIPEMD160_HMAC = 0x00000241
+ CKM_RIPEMD160_HMAC_GENERAL = 0x00000242
+ CKM_SHA256 = 0x00000250
+ CKM_SHA256_HMAC = 0x00000251
+ CKM_SHA256_HMAC_GENERAL = 0x00000252
+ CKM_SHA224 = 0x00000255
+ CKM_SHA224_HMAC = 0x00000256
+ CKM_SHA224_HMAC_GENERAL = 0x00000257
+ CKM_SHA384 = 0x00000260
+ CKM_SHA384_HMAC = 0x00000261
+ CKM_SHA384_HMAC_GENERAL = 0x00000262
+ CKM_SHA512 = 0x00000270
+ CKM_SHA512_HMAC = 0x00000271
+ CKM_SHA512_HMAC_GENERAL = 0x00000272
+ CKM_SECURID_KEY_GEN = 0x00000280
+ CKM_SECURID = 0x00000282
+ CKM_HOTP_KEY_GEN = 0x00000290
+ CKM_HOTP = 0x00000291
+ CKM_ACTI = 0x000002A0
+ CKM_ACTI_KEY_GEN = 0x000002A1
+ CKM_CAST_KEY_GEN = 0x00000300
+ CKM_CAST_ECB = 0x00000301
+ CKM_CAST_CBC = 0x00000302
+ CKM_CAST_MAC = 0x00000303
+ CKM_CAST_MAC_GENERAL = 0x00000304
+ CKM_CAST_CBC_PAD = 0x00000305
+ CKM_CAST3_KEY_GEN = 0x00000310
+ CKM_CAST3_ECB = 0x00000311
+ CKM_CAST3_CBC = 0x00000312
+ CKM_CAST3_MAC = 0x00000313
+ CKM_CAST3_MAC_GENERAL = 0x00000314
+ CKM_CAST3_CBC_PAD = 0x00000315
+ CKM_CAST5_KEY_GEN = 0x00000320
+ CKM_CAST128_KEY_GEN = 0x00000320
+ CKM_CAST5_ECB = 0x00000321
+ CKM_CAST128_ECB = 0x00000321
+ CKM_CAST5_CBC = 0x00000322
+ CKM_CAST128_CBC = 0x00000322
+ CKM_CAST5_MAC = 0x00000323
+ CKM_CAST128_MAC = 0x00000323
+ CKM_CAST5_MAC_GENERAL = 0x00000324
+ CKM_CAST128_MAC_GENERAL = 0x00000324
+ CKM_CAST5_CBC_PAD = 0x00000325
+ CKM_CAST128_CBC_PAD = 0x00000325
+ CKM_RC5_KEY_GEN = 0x00000330
+ CKM_RC5_ECB = 0x00000331
+ CKM_RC5_CBC = 0x00000332
+ CKM_RC5_MAC = 0x00000333
+ CKM_RC5_MAC_GENERAL = 0x00000334
+ CKM_RC5_CBC_PAD = 0x00000335
+ CKM_IDEA_KEY_GEN = 0x00000340
+ CKM_IDEA_ECB = 0x00000341
+ CKM_IDEA_CBC = 0x00000342
+ CKM_IDEA_MAC = 0x00000343
+ CKM_IDEA_MAC_GENERAL = 0x00000344
+ CKM_IDEA_CBC_PAD = 0x00000345
+ CKM_GENERIC_SECRET_KEY_GEN = 0x00000350
+ CKM_CONCATENATE_BASE_AND_KEY = 0x00000360
+ CKM_CONCATENATE_BASE_AND_DATA = 0x00000362
+ CKM_CONCATENATE_DATA_AND_BASE = 0x00000363
+ CKM_XOR_BASE_AND_DATA = 0x00000364
+ CKM_EXTRACT_KEY_FROM_KEY = 0x00000365
+ CKM_SSL3_PRE_MASTER_KEY_GEN = 0x00000370
+ CKM_SSL3_MASTER_KEY_DERIVE = 0x00000371
+ CKM_SSL3_KEY_AND_MAC_DERIVE = 0x00000372
+ CKM_SSL3_MASTER_KEY_DERIVE_DH = 0x00000373
+ CKM_TLS_PRE_MASTER_KEY_GEN = 0x00000374
+ CKM_TLS_MASTER_KEY_DERIVE = 0x00000375
+ CKM_TLS_KEY_AND_MAC_DERIVE = 0x00000376
+ CKM_TLS_MASTER_KEY_DERIVE_DH = 0x00000377
+ CKM_TLS_PRF = 0x00000378
+ CKM_SSL3_MD5_MAC = 0x00000380
+ CKM_SSL3_SHA1_MAC = 0x00000381
+ CKM_MD5_KEY_DERIVATION = 0x00000390
+ CKM_MD2_KEY_DERIVATION = 0x00000391
+ CKM_SHA1_KEY_DERIVATION = 0x00000392
+ CKM_SHA256_KEY_DERIVATION = 0x00000393
+ CKM_SHA384_KEY_DERIVATION = 0x00000394
+ CKM_SHA512_KEY_DERIVATION = 0x00000395
+ CKM_SHA224_KEY_DERIVATION = 0x00000396
+ CKM_PBE_MD2_DES_CBC = 0x000003A0
+ CKM_PBE_MD5_DES_CBC = 0x000003A1
+ CKM_PBE_MD5_CAST_CBC = 0x000003A2
+ CKM_PBE_MD5_CAST3_CBC = 0x000003A3
+ CKM_PBE_MD5_CAST5_CBC = 0x000003A4
+ CKM_PBE_MD5_CAST128_CBC = 0x000003A4
+ CKM_PBE_SHA1_CAST5_CBC = 0x000003A5
+ CKM_PBE_SHA1_CAST128_CBC = 0x000003A5
+ CKM_PBE_SHA1_RC4_128 = 0x000003A6
+ CKM_PBE_SHA1_RC4_40 = 0x000003A7
+ CKM_PBE_SHA1_DES3_EDE_CBC = 0x000003A8
+ CKM_PBE_SHA1_DES2_EDE_CBC = 0x000003A9
+ CKM_PBE_SHA1_RC2_128_CBC = 0x000003AA
+ CKM_PBE_SHA1_RC2_40_CBC = 0x000003AB
+ CKM_PKCS5_PBKD2 = 0x000003B0
+ CKM_PBA_SHA1_WITH_SHA1_HMAC = 0x000003C0
+ CKM_WTLS_PRE_MASTER_KEY_GEN = 0x000003D0
+ CKM_WTLS_MASTER_KEY_DERIVE = 0x000003D1
+ CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC = 0x000003D2
+ CKM_WTLS_PRF = 0x000003D3
+ CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE = 0x000003D4
+ CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE = 0x000003D5
+ CKM_KEY_WRAP_LYNKS = 0x00000400
+ CKM_KEY_WRAP_SET_OAEP = 0x00000401
+ CKM_CMS_SIG = 0x00000500
+ CKM_KIP_DERIVE = 0x00000510
+ CKM_KIP_WRAP = 0x00000511
+ CKM_KIP_MAC = 0x00000512
+ CKM_CAMELLIA_KEY_GEN = 0x00000550
+ CKM_CAMELLIA_ECB = 0x00000551
+ CKM_CAMELLIA_CBC = 0x00000552
+ CKM_CAMELLIA_MAC = 0x00000553
+ CKM_CAMELLIA_MAC_GENERAL = 0x00000554
+ CKM_CAMELLIA_CBC_PAD = 0x00000555
+ CKM_CAMELLIA_ECB_ENCRYPT_DATA = 0x00000556
+ CKM_CAMELLIA_CBC_ENCRYPT_DATA = 0x00000557
+ CKM_CAMELLIA_CTR = 0x00000558
+ CKM_ARIA_KEY_GEN = 0x00000560
+ CKM_ARIA_ECB = 0x00000561
+ CKM_ARIA_CBC = 0x00000562
+ CKM_ARIA_MAC = 0x00000563
+ CKM_ARIA_MAC_GENERAL = 0x00000564
+ CKM_ARIA_CBC_PAD = 0x00000565
+ CKM_ARIA_ECB_ENCRYPT_DATA = 0x00000566
+ CKM_ARIA_CBC_ENCRYPT_DATA = 0x00000567
+ CKM_SKIPJACK_KEY_GEN = 0x00001000
+ CKM_SKIPJACK_ECB64 = 0x00001001
+ CKM_SKIPJACK_CBC64 = 0x00001002
+ CKM_SKIPJACK_OFB64 = 0x00001003
+ CKM_SKIPJACK_CFB64 = 0x00001004
+ CKM_SKIPJACK_CFB32 = 0x00001005
+ CKM_SKIPJACK_CFB16 = 0x00001006
+ CKM_SKIPJACK_CFB8 = 0x00001007
+ CKM_SKIPJACK_WRAP = 0x00001008
+ CKM_SKIPJACK_PRIVATE_WRAP = 0x00001009
+ CKM_SKIPJACK_RELAYX = 0x0000100a
+ CKM_KEA_KEY_PAIR_GEN = 0x00001010
+ CKM_KEA_KEY_DERIVE = 0x00001011
+ CKM_FORTEZZA_TIMESTAMP = 0x00001020
+ CKM_BATON_KEY_GEN = 0x00001030
+ CKM_BATON_ECB128 = 0x00001031
+ CKM_BATON_ECB96 = 0x00001032
+ CKM_BATON_CBC128 = 0x00001033
+ CKM_BATON_COUNTER = 0x00001034
+ CKM_BATON_SHUFFLE = 0x00001035
+ CKM_BATON_WRAP = 0x00001036
+ CKM_ECDSA_KEY_PAIR_GEN = 0x00001040
+ CKM_EC_KEY_PAIR_GEN = 0x00001040
+ CKM_ECDSA = 0x00001041
+ CKM_ECDSA_SHA1 = 0x00001042
+ CKM_ECDH1_DERIVE = 0x00001050
+ CKM_ECDH1_COFACTOR_DERIVE = 0x00001051
+ CKM_ECMQV_DERIVE = 0x00001052
+ CKM_JUNIPER_KEY_GEN = 0x00001060
+ CKM_JUNIPER_ECB128 = 0x00001061
+ CKM_JUNIPER_CBC128 = 0x00001062
+ CKM_JUNIPER_COUNTER = 0x00001063
+ CKM_JUNIPER_SHUFFLE = 0x00001064
+ CKM_JUNIPER_WRAP = 0x00001065
+ CKM_FASTHASH = 0x00001070
+ CKM_AES_KEY_GEN = 0x00001080
+ CKM_AES_ECB = 0x00001081
+ CKM_AES_CBC = 0x00001082
+ CKM_AES_MAC = 0x00001083
+ CKM_AES_MAC_GENERAL = 0x00001084
+ CKM_AES_CBC_PAD = 0x00001085
+ CKM_AES_CTR = 0x00001086
+ CKM_BLOWFISH_KEY_GEN = 0x00001090
+ CKM_BLOWFISH_CBC = 0x00001091
+ CKM_TWOFISH_KEY_GEN = 0x00001092
+ CKM_TWOFISH_CBC = 0x00001093
+ CKM_DES_ECB_ENCRYPT_DATA = 0x00001100
+ CKM_DES_CBC_ENCRYPT_DATA = 0x00001101
+ CKM_DES3_ECB_ENCRYPT_DATA = 0x00001102
+ CKM_DES3_CBC_ENCRYPT_DATA = 0x00001103
+ CKM_AES_ECB_ENCRYPT_DATA = 0x00001104
+ CKM_AES_CBC_ENCRYPT_DATA = 0x00001105
+ CKM_DSA_PARAMETER_GEN = 0x00002000
+ CKM_DH_PKCS_PARAMETER_GEN = 0x00002001
+ CKM_X9_42_DH_PARAMETER_GEN = 0x00002002
+ CKM_VENDOR_DEFINED = 0x80000000
+ CKF_HW = 0x00000001
+ CKF_ENCRYPT = 0x00000100
+ CKF_DECRYPT = 0x00000200
+ CKF_DIGEST = 0x00000400
+ CKF_SIGN = 0x00000800
+ CKF_SIGN_RECOVER = 0x00001000
+ CKF_VERIFY = 0x00002000
+ CKF_VERIFY_RECOVER = 0x00004000
+ CKF_GENERATE = 0x00008000
+ CKF_GENERATE_KEY_PAIR = 0x00010000
+ CKF_WRAP = 0x00020000
+ CKF_UNWRAP = 0x00040000
+ CKF_DERIVE = 0x00080000
+ CKF_EC_F_P = 0x00100000
+ CKF_EC_F_2M = 0x00200000
+ CKF_EC_ECPARAMETERS = 0x00400000
+ CKF_EC_NAMEDCURVE = 0x00800000
+ CKF_EC_UNCOMPRESS = 0x01000000
+ CKF_EC_COMPRESS = 0x02000000
+ CKF_EXTENSION = 0x80000000
+ CKR_OK = 0x00000000
+ CKR_CANCEL = 0x00000001
+ CKR_HOST_MEMORY = 0x00000002
+ CKR_SLOT_ID_INVALID = 0x00000003
+ CKR_GENERAL_ERROR = 0x00000005
+ CKR_FUNCTION_FAILED = 0x00000006
+ CKR_ARGUMENTS_BAD = 0x00000007
+ CKR_NO_EVENT = 0x00000008
+ CKR_NEED_TO_CREATE_THREADS = 0x00000009
+ CKR_CANT_LOCK = 0x0000000A
+ CKR_ATTRIBUTE_READ_ONLY = 0x00000010
+ CKR_ATTRIBUTE_SENSITIVE = 0x00000011
+ CKR_ATTRIBUTE_TYPE_INVALID = 0x00000012
+ CKR_ATTRIBUTE_VALUE_INVALID = 0x00000013
+ CKR_DATA_INVALID = 0x00000020
+ CKR_DATA_LEN_RANGE = 0x00000021
+ CKR_DEVICE_ERROR = 0x00000030
+ CKR_DEVICE_MEMORY = 0x00000031
+ CKR_DEVICE_REMOVED = 0x00000032
+ CKR_ENCRYPTED_DATA_INVALID = 0x00000040
+ CKR_ENCRYPTED_DATA_LEN_RANGE = 0x00000041
+ CKR_FUNCTION_CANCELED = 0x00000050
+ CKR_FUNCTION_NOT_PARALLEL = 0x00000051
+ CKR_FUNCTION_NOT_SUPPORTED = 0x00000054
+ CKR_KEY_HANDLE_INVALID = 0x00000060
+ CKR_KEY_SIZE_RANGE = 0x00000062
+ CKR_KEY_TYPE_INCONSISTENT = 0x00000063
+ CKR_KEY_NOT_NEEDED = 0x00000064
+ CKR_KEY_CHANGED = 0x00000065
+ CKR_KEY_NEEDED = 0x00000066
+ CKR_KEY_INDIGESTIBLE = 0x00000067
+ CKR_KEY_FUNCTION_NOT_PERMITTED = 0x00000068
+ CKR_KEY_NOT_WRAPPABLE = 0x00000069
+ CKR_KEY_UNEXTRACTABLE = 0x0000006A
+ CKR_MECHANISM_INVALID = 0x00000070
+ CKR_MECHANISM_PARAM_INVALID = 0x00000071
+ CKR_OBJECT_HANDLE_INVALID = 0x00000082
+ CKR_OPERATION_ACTIVE = 0x00000090
+ CKR_OPERATION_NOT_INITIALIZED = 0x00000091
+ CKR_PIN_INCORRECT = 0x000000A0
+ CKR_PIN_INVALID = 0x000000A1
+ CKR_PIN_LEN_RANGE = 0x000000A2
+ CKR_PIN_EXPIRED = 0x000000A3
+ CKR_PIN_LOCKED = 0x000000A4
+ CKR_SESSION_CLOSED = 0x000000B0
+ CKR_SESSION_COUNT = 0x000000B1
+ CKR_SESSION_HANDLE_INVALID = 0x000000B3
+ CKR_SESSION_PARALLEL_NOT_SUPPORTED = 0x000000B4
+ CKR_SESSION_READ_ONLY = 0x000000B5
+ CKR_SESSION_EXISTS = 0x000000B6
+ CKR_SESSION_READ_ONLY_EXISTS = 0x000000B7
+ CKR_SESSION_READ_WRITE_SO_EXISTS = 0x000000B8
+ CKR_SIGNATURE_INVALID = 0x000000C0
+ CKR_SIGNATURE_LEN_RANGE = 0x000000C1
+ CKR_TEMPLATE_INCOMPLETE = 0x000000D0
+ CKR_TEMPLATE_INCONSISTENT = 0x000000D1
+ CKR_TOKEN_NOT_PRESENT = 0x000000E0
+ CKR_TOKEN_NOT_RECOGNIZED = 0x000000E1
+ CKR_TOKEN_WRITE_PROTECTED = 0x000000E2
+ CKR_UNWRAPPING_KEY_HANDLE_INVALID = 0x000000F0
+ CKR_UNWRAPPING_KEY_SIZE_RANGE = 0x000000F1
+ CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT = 0x000000F2
+ CKR_USER_ALREADY_LOGGED_IN = 0x00000100
+ CKR_USER_NOT_LOGGED_IN = 0x00000101
+ CKR_USER_PIN_NOT_INITIALIZED = 0x00000102
+ CKR_USER_TYPE_INVALID = 0x00000103
+ CKR_USER_ANOTHER_ALREADY_LOGGED_IN = 0x00000104
+ CKR_USER_TOO_MANY_TYPES = 0x00000105
+ CKR_WRAPPED_KEY_INVALID = 0x00000110
+ CKR_WRAPPED_KEY_LEN_RANGE = 0x00000112
+ CKR_WRAPPING_KEY_HANDLE_INVALID = 0x00000113
+ CKR_WRAPPING_KEY_SIZE_RANGE = 0x00000114
+ CKR_WRAPPING_KEY_TYPE_INCONSISTENT = 0x00000115
+ CKR_RANDOM_SEED_NOT_SUPPORTED = 0x00000120
+ CKR_RANDOM_NO_RNG = 0x00000121
+ CKR_DOMAIN_PARAMS_INVALID = 0x00000130
+ CKR_BUFFER_TOO_SMALL = 0x00000150
+ CKR_SAVED_STATE_INVALID = 0x00000160
+ CKR_INFORMATION_SENSITIVE = 0x00000170
+ CKR_STATE_UNSAVEABLE = 0x00000180
+ CKR_CRYPTOKI_NOT_INITIALIZED = 0x00000190
+ CKR_CRYPTOKI_ALREADY_INITIALIZED = 0x00000191
+ CKR_MUTEX_BAD = 0x000001A0
+ CKR_MUTEX_NOT_LOCKED = 0x000001A1
+ CKR_NEW_PIN_MODE = 0x000001B0
+ CKR_NEXT_OTP = 0x000001B1
+ CKR_FUNCTION_REJECTED = 0x00000200
+ CKR_VENDOR_DEFINED = 0x80000000
+ CKF_LIBRARY_CANT_CREATE_OS_THREADS = 0x00000001
+ CKF_OS_LOCKING_OK = 0x00000002
+ CKF_DONT_BLOCK = 1
+ CKF_NEXT_OTP = 0x00000001
+ CKF_EXCLUDE_TIME = 0x00000002
+ CKF_EXCLUDE_COUNTER = 0x00000004
+ CKF_EXCLUDE_CHALLENGE = 0x00000008
+ CKF_EXCLUDE_PIN = 0x00000010
+ CKF_USER_FRIENDLY_OTP = 0x00000020
+)
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/error.go b/Godeps/_workspace/src/github.com/miekg/pkcs11/error.go
new file mode 100644
index 00000000000..7df0e93a6b5
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/error.go
@@ -0,0 +1,98 @@
+// Copyright 2013 Miek Gieben. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs11
+
+// awk '/#define CKR_/{ print $3":\""$2"\"," }' pkcs11t.h
+
+var strerror = map[uint]string{
+ 0x00000000: "CKR_OK",
+ 0x00000001: "CKR_CANCEL",
+ 0x00000002: "CKR_HOST_MEMORY",
+ 0x00000003: "CKR_SLOT_ID_INVALID",
+ 0x00000005: "CKR_GENERAL_ERROR",
+ 0x00000006: "CKR_FUNCTION_FAILED",
+ 0x00000007: "CKR_ARGUMENTS_BAD",
+ 0x00000008: "CKR_NO_EVENT",
+ 0x00000009: "CKR_NEED_TO_CREATE_THREADS",
+ 0x0000000A: "CKR_CANT_LOCK",
+ 0x00000010: "CKR_ATTRIBUTE_READ_ONLY",
+ 0x00000011: "CKR_ATTRIBUTE_SENSITIVE",
+ 0x00000012: "CKR_ATTRIBUTE_TYPE_INVALID",
+ 0x00000013: "CKR_ATTRIBUTE_VALUE_INVALID",
+ 0x00000020: "CKR_DATA_INVALID",
+ 0x00000021: "CKR_DATA_LEN_RANGE",
+ 0x00000030: "CKR_DEVICE_ERROR",
+ 0x00000031: "CKR_DEVICE_MEMORY",
+ 0x00000032: "CKR_DEVICE_REMOVED",
+ 0x00000040: "CKR_ENCRYPTED_DATA_INVALID",
+ 0x00000041: "CKR_ENCRYPTED_DATA_LEN_RANGE",
+ 0x00000050: "CKR_FUNCTION_CANCELED",
+ 0x00000051: "CKR_FUNCTION_NOT_PARALLEL",
+ 0x00000054: "CKR_FUNCTION_NOT_SUPPORTED",
+ 0x00000060: "CKR_KEY_HANDLE_INVALID",
+ 0x00000062: "CKR_KEY_SIZE_RANGE",
+ 0x00000063: "CKR_KEY_TYPE_INCONSISTENT",
+ 0x00000064: "CKR_KEY_NOT_NEEDED",
+ 0x00000065: "CKR_KEY_CHANGED",
+ 0x00000066: "CKR_KEY_NEEDED",
+ 0x00000067: "CKR_KEY_INDIGESTIBLE",
+ 0x00000068: "CKR_KEY_FUNCTION_NOT_PERMITTED",
+ 0x00000069: "CKR_KEY_NOT_WRAPPABLE",
+ 0x0000006A: "CKR_KEY_UNEXTRACTABLE",
+ 0x00000070: "CKR_MECHANISM_INVALID",
+ 0x00000071: "CKR_MECHANISM_PARAM_INVALID",
+ 0x00000082: "CKR_OBJECT_HANDLE_INVALID",
+ 0x00000090: "CKR_OPERATION_ACTIVE",
+ 0x00000091: "CKR_OPERATION_NOT_INITIALIZED",
+ 0x000000A0: "CKR_PIN_INCORRECT",
+ 0x000000A1: "CKR_PIN_INVALID",
+ 0x000000A2: "CKR_PIN_LEN_RANGE",
+ 0x000000A3: "CKR_PIN_EXPIRED",
+ 0x000000A4: "CKR_PIN_LOCKED",
+ 0x000000B0: "CKR_SESSION_CLOSED",
+ 0x000000B1: "CKR_SESSION_COUNT",
+ 0x000000B3: "CKR_SESSION_HANDLE_INVALID",
+ 0x000000B4: "CKR_SESSION_PARALLEL_NOT_SUPPORTED",
+ 0x000000B5: "CKR_SESSION_READ_ONLY",
+ 0x000000B6: "CKR_SESSION_EXISTS",
+ 0x000000B7: "CKR_SESSION_READ_ONLY_EXISTS",
+ 0x000000B8: "CKR_SESSION_READ_WRITE_SO_EXISTS",
+ 0x000000C0: "CKR_SIGNATURE_INVALID",
+ 0x000000C1: "CKR_SIGNATURE_LEN_RANGE",
+ 0x000000D0: "CKR_TEMPLATE_INCOMPLETE",
+ 0x000000D1: "CKR_TEMPLATE_INCONSISTENT",
+ 0x000000E0: "CKR_TOKEN_NOT_PRESENT",
+ 0x000000E1: "CKR_TOKEN_NOT_RECOGNIZED",
+ 0x000000E2: "CKR_TOKEN_WRITE_PROTECTED",
+ 0x000000F0: "CKR_UNWRAPPING_KEY_HANDLE_INVALID",
+ 0x000000F1: "CKR_UNWRAPPING_KEY_SIZE_RANGE",
+ 0x000000F2: "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT",
+ 0x00000100: "CKR_USER_ALREADY_LOGGED_IN",
+ 0x00000101: "CKR_USER_NOT_LOGGED_IN",
+ 0x00000102: "CKR_USER_PIN_NOT_INITIALIZED",
+ 0x00000103: "CKR_USER_TYPE_INVALID",
+ 0x00000104: "CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
+ 0x00000105: "CKR_USER_TOO_MANY_TYPES",
+ 0x00000110: "CKR_WRAPPED_KEY_INVALID",
+ 0x00000112: "CKR_WRAPPED_KEY_LEN_RANGE",
+ 0x00000113: "CKR_WRAPPING_KEY_HANDLE_INVALID",
+ 0x00000114: "CKR_WRAPPING_KEY_SIZE_RANGE",
+ 0x00000115: "CKR_WRAPPING_KEY_TYPE_INCONSISTENT",
+ 0x00000120: "CKR_RANDOM_SEED_NOT_SUPPORTED",
+ 0x00000121: "CKR_RANDOM_NO_RNG",
+ 0x00000130: "CKR_DOMAIN_PARAMS_INVALID",
+ 0x00000150: "CKR_BUFFER_TOO_SMALL",
+ 0x00000160: "CKR_SAVED_STATE_INVALID",
+ 0x00000170: "CKR_INFORMATION_SENSITIVE",
+ 0x00000180: "CKR_STATE_UNSAVEABLE",
+ 0x00000190: "CKR_CRYPTOKI_NOT_INITIALIZED",
+ 0x00000191: "CKR_CRYPTOKI_ALREADY_INITIALIZED",
+ 0x000001A0: "CKR_MUTEX_BAD",
+ 0x000001A1: "CKR_MUTEX_NOT_LOCKED",
+ 0x000001B0: "CKR_NEW_PIN_MODE",
+ 0x000001B1: "CKR_NEXT_OTP",
+ 0x00000200: "CKR_FUNCTION_REJECTED",
+ 0x80000000: "CKR_VENDOR_DEFINED",
+}
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/hsm.db b/Godeps/_workspace/src/github.com/miekg/pkcs11/hsm.db
new file mode 100644
index 00000000000..eb3f10dadcd
Binary files /dev/null and b/Godeps/_workspace/src/github.com/miekg/pkcs11/hsm.db differ
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11.go b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11.go
new file mode 100644
index 00000000000..44023caf9c9
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11.go
@@ -0,0 +1,1551 @@
+// Copyright 2013 Miek Gieben. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package pkcs11 is a wrapper around the PKCS#11 cryptographic library.
+package pkcs11
+
+// It is *assumed*, that:
+//
+// * Go's uint size == PKCS11's CK_ULONG size
+// * CK_ULONG never overflows an Go int
+
+/*
+#cgo LDFLAGS: -lltdl
+#define CK_PTR *
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+#define CK_DEFINE_FUNCTION(returnType, name) returnType name
+#define CK_DECLARE_FUNCTION(returnType, name) returnType name
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
+#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
+
+#include
+#include
+#include
+#include
+#include "pkcs11.h"
+
+struct ctx {
+ lt_dlhandle handle;
+ CK_FUNCTION_LIST_PTR sym;
+};
+
+// New initializes a ctx and fills the symbol table.
+struct ctx *New(const char *module)
+{
+ if (lt_dlinit() != 0) {
+ return NULL;
+ }
+ CK_C_GetFunctionList list;
+ struct ctx *c = calloc(1, sizeof(struct ctx));
+ c->handle = lt_dlopen(module);
+ if (c->handle == NULL) {
+ free(c);
+ return NULL;
+ }
+ list = (CK_C_GetFunctionList) lt_dlsym(c->handle, "C_GetFunctionList");
+ if (list == NULL) {
+ free(c);
+ return NULL;
+ }
+ list(&c->sym);
+ return c;
+}
+
+// Destroy cleans up a ctx.
+void Destroy(struct ctx *c)
+{
+ if (!c) {
+ return;
+ }
+ if (c->handle == NULL) {
+ return;
+ }
+ if (lt_dlclose(c->handle) < 0) {
+ return;
+ }
+ lt_dlexit();
+ free(c);
+}
+
+CK_RV Initialize(struct ctx * c, CK_VOID_PTR initArgs)
+{
+ return c->sym->C_Initialize(initArgs);
+}
+
+CK_RV Finalize(struct ctx * c)
+{
+ return c->sym->C_Finalize(NULL);
+}
+
+CK_RV GetInfo(struct ctx * c, CK_INFO_PTR info)
+{
+ return c->sym->C_GetInfo(info);
+}
+
+CK_RV GetSlotList(struct ctx * c, CK_BBOOL tokenPresent,
+ CK_ULONG_PTR * slotList, CK_ULONG_PTR ulCount)
+{
+ CK_RV e = c->sym->C_GetSlotList(tokenPresent, NULL, ulCount);
+ if (e != CKR_OK) {
+ return e;
+ }
+ *slotList = calloc(*ulCount, sizeof(CK_SLOT_ID));
+ e = c->sym->C_GetSlotList(tokenPresent, *slotList, ulCount);
+ return e;
+}
+
+CK_RV GetSlotInfo(struct ctx * c, CK_ULONG slotID, CK_SLOT_INFO_PTR info)
+{
+ CK_RV e = c->sym->C_GetSlotInfo((CK_SLOT_ID) slotID, info);
+ return e;
+}
+
+CK_RV GetTokenInfo(struct ctx * c, CK_ULONG slotID, CK_TOKEN_INFO_PTR info)
+{
+ CK_RV e = c->sym->C_GetTokenInfo((CK_SLOT_ID) slotID, info);
+ return e;
+}
+
+CK_RV GetMechanismList(struct ctx * c, CK_ULONG slotID,
+ CK_ULONG_PTR * mech, CK_ULONG_PTR mechlen)
+{
+ CK_RV e =
+ c->sym->C_GetMechanismList((CK_SLOT_ID) slotID, NULL, mechlen);
+ if (e != CKR_OK) {
+ return e;
+ }
+ *mech = calloc(*mechlen, sizeof(CK_MECHANISM_TYPE));
+ e = c->sym->C_GetMechanismList((CK_SLOT_ID) slotID,
+ (CK_MECHANISM_TYPE_PTR) * mech, mechlen);
+ return e;
+}
+
+CK_RV GetMechanismInfo(struct ctx * c, CK_ULONG slotID, CK_MECHANISM_TYPE mech,
+ CK_MECHANISM_INFO_PTR info)
+{
+ CK_RV e = c->sym->C_GetMechanismInfo((CK_SLOT_ID) slotID, mech, info);
+ return e;
+}
+
+CK_RV InitToken(struct ctx * c, CK_ULONG slotID, char *pin, CK_ULONG pinlen,
+ char *label)
+{
+ CK_RV e =
+ c->sym->C_InitToken((CK_SLOT_ID) slotID, (CK_UTF8CHAR_PTR) pin,
+ pinlen, (CK_UTF8CHAR_PTR) label);
+ return e;
+}
+
+CK_RV InitPIN(struct ctx * c, CK_SESSION_HANDLE sh, char *pin, CK_ULONG pinlen)
+{
+ CK_RV e = c->sym->C_InitPIN(sh, (CK_UTF8CHAR_PTR) pin, pinlen);
+ return e;
+}
+
+CK_RV SetPIN(struct ctx * c, CK_SESSION_HANDLE sh, char *oldpin,
+ CK_ULONG oldpinlen, char *newpin, CK_ULONG newpinlen)
+{
+ CK_RV e = c->sym->C_SetPIN(sh, (CK_UTF8CHAR_PTR) oldpin, oldpinlen,
+ (CK_UTF8CHAR_PTR) newpin, newpinlen);
+ return e;
+}
+
+CK_RV OpenSession(struct ctx * c, CK_ULONG slotID, CK_ULONG flags,
+ CK_SESSION_HANDLE_PTR session)
+{
+ CK_RV e =
+ c->sym->C_OpenSession((CK_SLOT_ID) slotID, (CK_FLAGS) flags, NULL,
+ NULL, session);
+ return e;
+}
+
+CK_RV CloseSession(struct ctx * c, CK_SESSION_HANDLE session)
+{
+ CK_RV e = c->sym->C_CloseSession(session);
+ return e;
+}
+
+CK_RV CloseAllSessions(struct ctx * c, CK_ULONG slotID)
+{
+ CK_RV e = c->sym->C_CloseAllSessions(slotID);
+ return e;
+}
+
+CK_RV GetSessionInfo(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_SESSION_INFO_PTR info)
+{
+ CK_RV e = c->sym->C_GetSessionInfo(session, info);
+ return e;
+}
+
+CK_RV GetOperationState(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR * state, CK_ULONG_PTR statelen)
+{
+ CK_RV rv = c->sym->C_GetOperationState(session, NULL, statelen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *state = calloc(*statelen, sizeof(CK_BYTE));
+ if (*state == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_GetOperationState(session, *state, statelen);
+ return rv;
+}
+
+CK_RV SetOperationState(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR state, CK_ULONG statelen,
+ CK_OBJECT_HANDLE encryptkey, CK_OBJECT_HANDLE authkey)
+{
+ return c->sym->C_SetOperationState(session, state, statelen, encryptkey,
+ authkey);
+}
+
+CK_RV Login(struct ctx *c, CK_SESSION_HANDLE session, CK_USER_TYPE userType,
+ char *pin, CK_ULONG pinLen)
+{
+ CK_RV e =
+ c->sym->C_Login(session, userType, (CK_UTF8CHAR_PTR) pin, pinLen);
+ return e;
+}
+
+CK_RV Logout(struct ctx * c, CK_SESSION_HANDLE session)
+{
+ CK_RV e = c->sym->C_Logout(session);
+ return e;
+}
+
+CK_RV CreateObject(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount,
+ CK_OBJECT_HANDLE_PTR obj)
+{
+ CK_RV e = c->sym->C_CreateObject(session, temp, tempCount, obj);
+ return e;
+}
+
+CK_RV CopyObject(struct ctx * c, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o,
+ CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount,
+ CK_OBJECT_HANDLE_PTR obj)
+{
+ CK_RV e = c->sym->C_CopyObject(session, o, temp, tempCount, obj);
+ return e;
+}
+
+CK_RV DestroyObject(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE object)
+{
+ CK_RV e = c->sym->C_DestroyObject(session, object);
+ return e;
+}
+
+CK_RV GetObjectSize(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE object, CK_ULONG_PTR size)
+{
+ CK_RV e = c->sym->C_GetObjectSize(session, object, size);
+ return e;
+}
+
+CK_RV GetAttributeValue(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR temp,
+ CK_ULONG templen)
+{
+ // Call for the first time, check the returned ulValue in the attributes, then
+ // allocate enough space and try again.
+ CK_RV e = c->sym->C_GetAttributeValue(session, object, temp, templen);
+ if (e != CKR_OK) {
+ return e;
+ }
+ CK_ULONG i;
+ for (i = 0; i < templen; i++) {
+ if ((CK_LONG) temp[i].ulValueLen == -1) {
+ // either access denied or no such object
+ continue;
+ }
+ temp[i].pValue = calloc(temp[i].ulValueLen, sizeof(CK_BYTE));
+ }
+ e = c->sym->C_GetAttributeValue(session, object, temp, templen);
+ return e;
+}
+
+CK_RV SetAttributeValue(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR temp,
+ CK_ULONG templen)
+{
+ CK_RV e = c->sym->C_SetAttributeValue(session, object, temp, templen);
+ return e;
+}
+
+CK_RV FindObjectsInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount)
+{
+ CK_RV e = c->sym->C_FindObjectsInit(session, temp, tempCount);
+ return e;
+}
+
+CK_RV FindObjects(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE_PTR * obj, CK_ULONG max,
+ CK_ULONG_PTR objCount)
+{
+ *obj = calloc(max, sizeof(CK_OBJECT_HANDLE));
+ CK_RV e = c->sym->C_FindObjects(session, *obj, max, objCount);
+ return e;
+}
+
+CK_RV FindObjectsFinal(struct ctx * c, CK_SESSION_HANDLE session)
+{
+ CK_RV e = c->sym->C_FindObjectsFinal(session);
+ return e;
+}
+
+CK_RV EncryptInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
+{
+ CK_RV e = c->sym->C_EncryptInit(session, mechanism, key);
+ return e;
+}
+
+CK_RV Encrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
+ CK_ULONG mlen, CK_BYTE_PTR * enc, CK_ULONG_PTR enclen)
+{
+ CK_RV rv = c->sym->C_Encrypt(session, message, mlen, NULL, enclen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *enc = calloc(*enclen, sizeof(CK_BYTE));
+ if (*enc == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_Encrypt(session, message, mlen, *enc, enclen);
+ return rv;
+}
+
+CK_RV EncryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR plain, CK_ULONG plainlen, CK_BYTE_PTR * cipher,
+ CK_ULONG_PTR cipherlen)
+{
+ CK_RV rv =
+ c->sym->C_EncryptUpdate(session, plain, plainlen, NULL, cipherlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *cipher = calloc(*cipherlen, sizeof(CK_BYTE));
+ if (*cipher == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_EncryptUpdate(session, plain, plainlen, *cipher,
+ cipherlen);
+ return rv;
+}
+
+CK_RV EncryptFinal(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR * cipher, CK_ULONG_PTR cipherlen)
+{
+ CK_RV rv = c->sym->C_EncryptFinal(session, NULL, cipherlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *cipher = calloc(*cipherlen, sizeof(CK_BYTE));
+ if (*cipher == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_EncryptFinal(session, *cipher, cipherlen);
+ return rv;
+}
+
+CK_RV DecryptInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
+{
+ CK_RV e = c->sym->C_DecryptInit(session, mechanism, key);
+ return e;
+}
+
+CK_RV Decrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR cypher,
+ CK_ULONG clen, CK_BYTE_PTR * plain, CK_ULONG_PTR plainlen)
+{
+ CK_RV e = c->sym->C_Decrypt(session, cypher, clen, NULL, plainlen);
+ if (e != CKR_OK) {
+ return e;
+ }
+ *plain = calloc(*plainlen, sizeof(CK_BYTE));
+ if (*plain == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ e = c->sym->C_Decrypt(session, cypher, clen, *plain, plainlen);
+ return e;
+}
+
+CK_RV DecryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR cipher, CK_ULONG cipherlen, CK_BYTE_PTR * part,
+ CK_ULONG_PTR partlen)
+{
+ CK_RV rv =
+ c->sym->C_DecryptUpdate(session, cipher, cipherlen, NULL, partlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *part = calloc(*partlen, sizeof(CK_BYTE));
+ if (*part == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_DecryptUpdate(session, cipher, cipherlen, *part,
+ partlen);
+ return rv;
+}
+
+CK_RV DecryptFinal(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR * plain, CK_ULONG_PTR plainlen)
+{
+ CK_RV rv = c->sym->C_DecryptFinal(session, NULL, plainlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *plain = calloc(*plainlen, sizeof(CK_BYTE));
+ if (*plain == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_DecryptFinal(session, *plain, plainlen);
+ return rv;
+}
+
+CK_RV DigestInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism)
+{
+ CK_RV e = c->sym->C_DigestInit(session, mechanism);
+ return e;
+}
+
+CK_RV Digest(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
+ CK_ULONG mlen, CK_BYTE_PTR * hash, CK_ULONG_PTR hashlen)
+{
+ CK_RV rv = c->sym->C_Digest(session, message, mlen, NULL, hashlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *hash = calloc(*hashlen, sizeof(CK_BYTE));
+ if (*hash == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_Digest(session, message, mlen, *hash, hashlen);
+ return rv;
+}
+
+CK_RV DigestUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR message, CK_ULONG mlen)
+{
+ CK_RV rv = c->sym->C_DigestUpdate(session, message, mlen);
+ return rv;
+}
+
+CK_RV DigestKey(struct ctx * c, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key)
+{
+ CK_RV rv = c->sym->C_DigestKey(session, key);
+ return rv;
+}
+
+CK_RV DigestFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR * hash,
+ CK_ULONG_PTR hashlen)
+{
+ CK_RV rv = c->sym->C_DigestFinal(session, NULL, hashlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *hash = calloc(*hashlen, sizeof(CK_BYTE));
+ if (*hash == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_DigestFinal(session, *hash, hashlen);
+ return rv;
+}
+
+CK_RV SignInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
+{
+ CK_RV e = c->sym->C_SignInit(session, mechanism, key);
+ return e;
+}
+
+CK_RV Sign(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
+ CK_ULONG mlen, CK_BYTE_PTR * sig, CK_ULONG_PTR siglen)
+{
+ CK_RV rv = c->sym->C_Sign(session, message, mlen, NULL, siglen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *sig = calloc(*siglen, sizeof(CK_BYTE));
+ if (*sig == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_Sign(session, message, mlen, *sig, siglen);
+ return rv;
+}
+
+CK_RV SignUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR message, CK_ULONG mlen)
+{
+ CK_RV rv = c->sym->C_SignUpdate(session, message, mlen);
+ return rv;
+}
+
+CK_RV SignFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR * sig,
+ CK_ULONG_PTR siglen)
+{
+ CK_RV rv = c->sym->C_SignFinal(session, NULL, siglen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *sig = calloc(*siglen, sizeof(CK_BYTE));
+ if (*sig == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_SignFinal(session, *sig, siglen);
+ return rv;
+}
+
+CK_RV SignRecoverInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key)
+{
+ CK_RV rv = c->sym->C_SignRecoverInit(session, mech, key);
+ return rv;
+}
+
+CK_RV SignRecover(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR data,
+ CK_ULONG datalen, CK_BYTE_PTR * sig, CK_ULONG_PTR siglen)
+{
+ CK_RV rv = c->sym->C_SignRecover(session, data, datalen, NULL, siglen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *sig = calloc(*siglen, sizeof(CK_BYTE));
+ if (*sig == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_SignRecover(session, data, datalen, *sig, siglen);
+ return rv;
+}
+
+CK_RV VerifyInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key)
+{
+ CK_RV rv = c->sym->C_VerifyInit(session, mech, key);
+ return rv;
+}
+
+CK_RV Verify(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
+ CK_ULONG mesglen, CK_BYTE_PTR sig, CK_ULONG siglen)
+{
+ CK_RV rv = c->sym->C_Verify(session, message, mesglen, sig, siglen);
+ return rv;
+}
+
+CK_RV VerifyUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR part, CK_ULONG partlen)
+{
+ CK_RV rv = c->sym->C_VerifyUpdate(session, part, partlen);
+ return rv;
+}
+
+CK_RV VerifyFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR sig,
+ CK_ULONG siglen)
+{
+ CK_RV rv = c->sym->C_VerifyFinal(session, sig, siglen);
+ return rv;
+}
+
+CK_RV VerifyRecoverInit(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key)
+{
+ CK_RV rv = c->sym->C_VerifyRecoverInit(session, mech, key);
+ return rv;
+}
+
+CK_RV VerifyRecover(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR sig,
+ CK_ULONG siglen, CK_BYTE_PTR * data, CK_ULONG_PTR datalen)
+{
+ CK_RV rv = c->sym->C_VerifyRecover(session, sig, siglen, NULL, datalen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *data = calloc(*datalen, sizeof(CK_BYTE));
+ if (*data == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_VerifyRecover(session, sig, siglen, *data, datalen);
+ return rv;
+}
+
+CK_RV DigestEncryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR part, CK_ULONG partlen, CK_BYTE_PTR * enc,
+ CK_ULONG_PTR enclen)
+{
+ CK_RV rv =
+ c->sym->C_DigestEncryptUpdate(session, part, partlen, NULL, enclen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *enc = calloc(*enclen, sizeof(CK_BYTE));
+ if (*enc == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_DigestEncryptUpdate(session, part, partlen, *enc,
+ enclen);
+ return rv;
+}
+
+CK_RV DecryptDigestUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR cipher, CK_ULONG cipherlen,
+ CK_BYTE_PTR * part, CK_ULONG_PTR partlen)
+{
+ CK_RV rv =
+ c->sym->C_DecryptDigestUpdate(session, cipher, cipherlen, NULL,
+ partlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *part = calloc(*partlen, sizeof(CK_BYTE));
+ if (*part == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_DecryptDigestUpdate(session, cipher, cipherlen, *part,
+ partlen);
+ return rv;
+}
+
+CK_RV SignEncryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR part, CK_ULONG partlen, CK_BYTE_PTR * enc,
+ CK_ULONG_PTR enclen)
+{
+ CK_RV rv =
+ c->sym->C_SignEncryptUpdate(session, part, partlen, NULL, enclen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *enc = calloc(*enclen, sizeof(CK_BYTE));
+ if (*enc == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_SignEncryptUpdate(session, part, partlen, *enc, enclen);
+ return rv;
+}
+
+CK_RV DecryptVerifyUpdate(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR cipher, CK_ULONG cipherlen,
+ CK_BYTE_PTR * part, CK_ULONG_PTR partlen)
+{
+ CK_RV rv =
+ c->sym->C_DecryptVerifyUpdate(session, cipher, cipherlen, NULL,
+ partlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *part = calloc(*partlen, sizeof(CK_BYTE));
+ if (*part == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_DecryptVerifyUpdate(session, cipher, cipherlen, *part,
+ partlen);
+ return rv;
+}
+
+CK_RV GenerateKey(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR temp,
+ CK_ULONG tempCount, CK_OBJECT_HANDLE_PTR key)
+{
+ CK_RV e =
+ c->sym->C_GenerateKey(session, mechanism, temp, tempCount, key);
+ return e;
+}
+
+CK_RV GenerateKeyPair(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR pub,
+ CK_ULONG pubCount, CK_ATTRIBUTE_PTR priv,
+ CK_ULONG privCount, CK_OBJECT_HANDLE_PTR pubkey,
+ CK_OBJECT_HANDLE_PTR privkey)
+{
+ CK_RV e =
+ c->sym->C_GenerateKeyPair(session, mechanism, pub, pubCount, priv,
+ privCount,
+ pubkey, privkey);
+ return e;
+}
+
+CK_RV WrapKey(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE wrappingkey,
+ CK_OBJECT_HANDLE key, CK_BYTE_PTR * wrapped,
+ CK_ULONG_PTR wrappedlen)
+{
+ CK_RV rv = c->sym->C_WrapKey(session, mechanism, wrappingkey, key, NULL,
+ wrappedlen);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+ *wrapped = calloc(*wrappedlen, sizeof(CK_BYTE));
+ if (*wrapped == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ rv = c->sym->C_WrapKey(session, mechanism, wrappingkey, key, *wrapped,
+ wrappedlen);
+ return rv;
+}
+
+CK_RV DeriveKey(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE basekey,
+ CK_ATTRIBUTE_PTR a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
+{
+ CK_RV e = c->sym->C_DeriveKey(session, mech, basekey, a, alen, key);
+ return e;
+}
+
+CK_RV UnwrapKey(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE unwrappingkey,
+ CK_BYTE_PTR wrappedkey, CK_ULONG wrappedkeylen,
+ CK_ATTRIBUTE_PTR a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
+{
+ CK_RV e = c->sym->C_UnwrapKey(session, mech, unwrappingkey, wrappedkey,
+ wrappedkeylen, a, alen, key);
+ return e;
+}
+
+CK_RV SeedRandom(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR seed,
+ CK_ULONG seedlen)
+{
+ CK_RV e = c->sym->C_SeedRandom(session, seed, seedlen);
+ return e;
+}
+
+CK_RV GenerateRandom(struct ctx * c, CK_SESSION_HANDLE session,
+ CK_BYTE_PTR * rand, CK_ULONG length)
+{
+ *rand = calloc(length, sizeof(CK_BYTE));
+ if (*rand == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ CK_RV e = c->sym->C_GenerateRandom(session, *rand, length);
+ return e;
+}
+
+CK_RV WaitForSlotEvent(struct ctx * c, CK_FLAGS flags, CK_ULONG_PTR slot)
+{
+ CK_RV e =
+ c->sym->C_WaitForSlotEvent(flags, (CK_SLOT_ID_PTR) slot, NULL);
+ return e;
+}
+*/
+import "C"
+import "strings"
+
+import "unsafe"
+
+// Ctx contains the current pkcs11 context.
+type Ctx struct {
+ ctx *C.struct_ctx
+}
+
+// New creates a new context and initializes the module/library for use.
+func New(module string) *Ctx {
+ c := new(Ctx)
+ mod := C.CString(module)
+ defer C.free(unsafe.Pointer(mod))
+ c.ctx = C.New(mod)
+ if c.ctx == nil {
+ return nil
+ }
+ return c
+}
+
+// Destroy unloads the module/library and frees any remaining memory.
+func (c *Ctx) Destroy() {
+ if c == nil || c.ctx == nil {
+ return
+ }
+ C.Destroy(c.ctx)
+ c.ctx = nil
+}
+
+/* Initialize initializes the Cryptoki library. */
+func (c *Ctx) Initialize() error {
+ args := &C.CK_C_INITIALIZE_ARGS{nil, nil, nil, nil, C.CKF_OS_LOCKING_OK, nil}
+ e := C.Initialize(c.ctx, C.CK_VOID_PTR(args))
+ return toError(e)
+}
+
+/* Finalize indicates that an application is done with the Cryptoki library. */
+func (c *Ctx) Finalize() error {
+ if c.ctx == nil {
+ return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
+ }
+ e := C.Finalize(c.ctx)
+ return toError(e)
+}
+
+/* GetInfo returns general information about Cryptoki. */
+func (c *Ctx) GetInfo() (Info, error) {
+ var p C.CK_INFO
+ e := C.GetInfo(c.ctx, C.CK_INFO_PTR(&p))
+ i := Info{
+ CryptokiVersion: toVersion(p.cryptokiVersion),
+ ManufacturerID: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&p.manufacturerID[0]), 32)), " "),
+ Flags: uint(p.flags),
+ LibraryDescription: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&p.libraryDescription[0]), 32)), " "),
+ LibraryVersion: toVersion(p.libraryVersion),
+ }
+ return i, toError(e)
+}
+
+/* GetSlotList obtains a list of slots in the system. */
+func (c *Ctx) GetSlotList(tokenPresent bool) ([]uint, error) {
+ var (
+ slotList C.CK_ULONG_PTR
+ ulCount C.CK_ULONG
+ )
+ e := C.GetSlotList(c.ctx, cBBool(tokenPresent), &slotList, &ulCount)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ l := toList(slotList, ulCount)
+ return l, nil
+}
+
+/* GetSlotInfo obtains information about a particular slot in the system. */
+func (c *Ctx) GetSlotInfo(slotID uint) (SlotInfo, error) {
+ var csi C.CK_SLOT_INFO
+ e := C.GetSlotInfo(c.ctx, C.CK_ULONG(slotID), &csi)
+ s := SlotInfo{
+ SlotDescription: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&csi.slotDescription[0]), 64)), " "),
+ ManufacturerID: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&csi.manufacturerID[0]), 32)), " "),
+ Flags: uint(csi.flags),
+ HardwareVersion: toVersion(csi.hardwareVersion),
+ FirmwareVersion: toVersion(csi.firmwareVersion),
+ }
+ return s, toError(e)
+}
+
+// GetTokenInfo obtains information about a particular token
+// in the system.
+func (c *Ctx) GetTokenInfo(slotID uint) (TokenInfo, error) {
+ var cti C.CK_TOKEN_INFO
+ e := C.GetTokenInfo(c.ctx, C.CK_ULONG(slotID), &cti)
+ s := TokenInfo{
+ Label: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.label[0]), 32)), " "),
+ ManufacturerID: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.manufacturerID[0]), 32)), " "),
+ Model: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.model[0]), 16)), " "),
+ SerialNumber: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.serialNumber[0]), 16)), " "),
+ Flags: uint(cti.flags),
+ MaxSessionCount: uint(cti.ulMaxSessionCount),
+ SessionCount: uint(cti.ulSessionCount),
+ MaxRwSessionCount: uint(cti.ulMaxRwSessionCount),
+ RwSessionCount: uint(cti.ulRwSessionCount),
+ MaxPinLen: uint(cti.ulMaxPinLen),
+ MinPinLen: uint(cti.ulMinPinLen),
+ TotalPublicMemory: uint(cti.ulTotalPublicMemory),
+ FreePublicMemory: uint(cti.ulFreePublicMemory),
+ TotalPrivateMemory: uint(cti.ulTotalPrivateMemory),
+ FreePrivateMemory: uint(cti.ulFreePrivateMemory),
+ HardwareVersion: toVersion(cti.hardwareVersion),
+ FirmwareVersion: toVersion(cti.firmwareVersion),
+ UTCTime: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.utcTime[0]), 16)), " "),
+ }
+ return s, toError(e)
+}
+
+/* GetMechanismList obtains a list of mechanism types supported by a token. */
+func (c *Ctx) GetMechanismList(slotID uint) ([]*Mechanism, error) {
+ var (
+ mech C.CK_ULONG_PTR // in pkcs#11 we're all CK_ULONGs \o/
+ mechlen C.CK_ULONG
+ )
+ e := C.GetMechanismList(c.ctx, C.CK_ULONG(slotID), &mech, &mechlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ // Although the function returns only type, cast them back into real
+ // attributes as this is used in other functions.
+ m := make([]*Mechanism, int(mechlen))
+ for i, typ := range toList(mech, mechlen) {
+ m[i] = NewMechanism(typ, nil)
+ }
+ return m, nil
+}
+
+// GetMechanismInfo obtains information about a particular
+// mechanism possibly supported by a token.
+func (c *Ctx) GetMechanismInfo(slotID uint, m []*Mechanism) (MechanismInfo, error) {
+ var cm C.CK_MECHANISM_INFO
+ e := C.GetMechanismInfo(c.ctx, C.CK_ULONG(slotID), C.CK_MECHANISM_TYPE(m[0].Mechanism),
+ C.CK_MECHANISM_INFO_PTR(&cm))
+ mi := MechanismInfo{
+ MinKeySize: uint(cm.ulMinKeySize),
+ MaxKeySize: uint(cm.ulMaxKeySize),
+ Flags: uint(cm.flags),
+ }
+ return mi, toError(e)
+}
+
+// InitToken initializes a token. The label must be 32 characters
+// long, it is blank padded if it is not. If it is longer it is capped
+// to 32 characters.
+func (c *Ctx) InitToken(slotID uint, pin string, label string) error {
+ p := C.CString(pin)
+ defer C.free(unsafe.Pointer(p))
+ ll := len(label)
+ for ll < 32 {
+ label += " "
+ ll++
+ }
+ l := C.CString(label[:32])
+ defer C.free(unsafe.Pointer(l))
+ e := C.InitToken(c.ctx, C.CK_ULONG(slotID), p, C.CK_ULONG(len(pin)), l)
+ return toError(e)
+}
+
+/* InitPIN initializes the normal user's PIN. */
+func (c *Ctx) InitPIN(sh SessionHandle, pin string) error {
+ p := C.CString(pin)
+ defer C.free(unsafe.Pointer(p))
+ e := C.InitPIN(c.ctx, C.CK_SESSION_HANDLE(sh), p, C.CK_ULONG(len(pin)))
+ return toError(e)
+}
+
+/* SetPIN modifies the PIN of the user who is logged in. */
+func (c *Ctx) SetPIN(sh SessionHandle, oldpin string, newpin string) error {
+ old := C.CString(oldpin)
+ defer C.free(unsafe.Pointer(old))
+ new := C.CString(newpin)
+ defer C.free(unsafe.Pointer(new))
+ e := C.SetPIN(c.ctx, C.CK_SESSION_HANDLE(sh), old, C.CK_ULONG(len(oldpin)), new, C.CK_ULONG(len(newpin)))
+ return toError(e)
+}
+
+/* OpenSession opens a session between an application and a token. */
+func (c *Ctx) OpenSession(slotID uint, flags uint) (SessionHandle, error) {
+ var s C.CK_SESSION_HANDLE
+ e := C.OpenSession(c.ctx, C.CK_ULONG(slotID), C.CK_ULONG(flags), C.CK_SESSION_HANDLE_PTR(&s))
+ return SessionHandle(s), toError(e)
+}
+
+/* CloseSession closes a session between an application and a token. */
+func (c *Ctx) CloseSession(sh SessionHandle) error {
+ if c.ctx == nil {
+ return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
+ }
+ e := C.CloseSession(c.ctx, C.CK_SESSION_HANDLE(sh))
+ return toError(e)
+}
+
+/* CloseAllSessions closes all sessions with a token. */
+func (c *Ctx) CloseAllSessions(slotID uint) error {
+ if c.ctx == nil {
+ return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
+ }
+ e := C.CloseAllSessions(c.ctx, C.CK_ULONG(slotID))
+ return toError(e)
+}
+
+/* GetSessionInfo obtains information about the session. */
+func (c *Ctx) GetSessionInfo(sh SessionHandle) (SessionInfo, error) {
+ var csi C.CK_SESSION_INFO
+ e := C.GetSessionInfo(c.ctx, C.CK_SESSION_HANDLE(sh), &csi)
+ s := SessionInfo{SlotID: uint(csi.slotID),
+ State: uint(csi.state),
+ Flags: uint(csi.flags),
+ DeviceError: uint(csi.ulDeviceError),
+ }
+ return s, toError(e)
+}
+
+/* GetOperationState obtains the state of the cryptographic operation in a session. */
+func (c *Ctx) GetOperationState(sh SessionHandle) ([]byte, error) {
+ var (
+ state C.CK_BYTE_PTR
+ statelen C.CK_ULONG
+ )
+ e := C.GetOperationState(c.ctx, C.CK_SESSION_HANDLE(sh), &state, &statelen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ b := C.GoBytes(unsafe.Pointer(state), C.int(statelen))
+ C.free(unsafe.Pointer(state))
+ return b, nil
+}
+
+/* SetOperationState restores the state of the cryptographic operation in a session. */
+func (c *Ctx) SetOperationState(sh SessionHandle, state []byte, encryptKey, authKey ObjectHandle) error {
+ e := C.SetOperationState(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&state[0])),
+ C.CK_ULONG(len(state)), C.CK_OBJECT_HANDLE(encryptKey), C.CK_OBJECT_HANDLE(authKey))
+ return toError(e)
+}
+
+/* Login logs a user into a token. */
+func (c *Ctx) Login(sh SessionHandle, userType uint, pin string) error {
+ p := C.CString(pin)
+ defer C.free(unsafe.Pointer(p))
+ e := C.Login(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_USER_TYPE(userType), p, C.CK_ULONG(len(pin)))
+ return toError(e)
+}
+
+/* Logout logs a user out from a token. */
+func (c *Ctx) Logout(sh SessionHandle) error {
+ if c.ctx == nil {
+ return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
+ }
+ e := C.Logout(c.ctx, C.CK_SESSION_HANDLE(sh))
+ return toError(e)
+}
+
+/* CreateObject creates a new object. */
+func (c *Ctx) CreateObject(sh SessionHandle, temp []*Attribute) (ObjectHandle, error) {
+ var obj C.CK_OBJECT_HANDLE
+ t, tcount := cAttributeList(temp)
+ e := C.CreateObject(c.ctx, C.CK_SESSION_HANDLE(sh), t, tcount, C.CK_OBJECT_HANDLE_PTR(&obj))
+ e1 := toError(e)
+ if e1 == nil {
+ return ObjectHandle(obj), nil
+ }
+ return 0, e1
+}
+
+/* CopyObject copies an object, creating a new object for the copy. */
+func (c *Ctx) CopyObject(sh SessionHandle, o ObjectHandle, temp []*Attribute) (ObjectHandle, error) {
+ var obj C.CK_OBJECT_HANDLE
+ t, tcount := cAttributeList(temp)
+
+ e := C.CopyObject(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), t, tcount, C.CK_OBJECT_HANDLE_PTR(&obj))
+ e1 := toError(e)
+ if e1 == nil {
+ return ObjectHandle(obj), nil
+ }
+ return 0, e1
+}
+
+/* DestroyObject destroys an object. */
+func (c *Ctx) DestroyObject(sh SessionHandle, oh ObjectHandle) error {
+ e := C.DestroyObject(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(oh))
+ return toError(e)
+}
+
+/* GetObjectSize gets the size of an object in bytes. */
+func (c *Ctx) GetObjectSize(sh SessionHandle, oh ObjectHandle) (uint, error) {
+ var size C.CK_ULONG
+ e := C.GetObjectSize(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(oh), &size)
+ return uint(size), toError(e)
+}
+
+/* GetAttributeValue obtains the value of one or more object attributes. */
+func (c *Ctx) GetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute) ([]*Attribute, error) {
+ // copy the attribute list and make all the values nil, so that
+ // the C function can (allocate) fill them in
+ pa := make([]C.CK_ATTRIBUTE, len(a))
+ for i := 0; i < len(a); i++ {
+ pa[i]._type = C.CK_ATTRIBUTE_TYPE(a[i].Type)
+ }
+ e := C.GetAttributeValue(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), C.CK_ATTRIBUTE_PTR(&pa[0]), C.CK_ULONG(len(a)))
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ a1 := make([]*Attribute, len(a))
+ for i, c := range pa {
+ x := new(Attribute)
+ x.Type = uint(c._type)
+ if int(c.ulValueLen) != -1 {
+ x.Value = C.GoBytes(unsafe.Pointer(c.pValue), C.int(c.ulValueLen))
+ C.free(unsafe.Pointer(c.pValue))
+ }
+ a1[i] = x
+ }
+ return a1, nil
+}
+
+/* SetAttributeValue modifies the value of one or more object attributes */
+func (c *Ctx) SetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute) error {
+ pa, palen := cAttributeList(a)
+ e := C.SetAttributeValue(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), pa, palen)
+ return toError(e)
+}
+
+// FindObjectsInit initializes a search for token and session
+// objects that match a template.
+func (c *Ctx) FindObjectsInit(sh SessionHandle, temp []*Attribute) error {
+ t, tcount := cAttributeList(temp)
+ e := C.FindObjectsInit(c.ctx, C.CK_SESSION_HANDLE(sh), t, tcount)
+ return toError(e)
+}
+
+// FindObjects continues a search for token and session
+// objects that match a template, obtaining additional object
+// handles. The returned boolean indicates if the list would
+// have been larger than max.
+func (c *Ctx) FindObjects(sh SessionHandle, max int) ([]ObjectHandle, bool, error) {
+ var (
+ objectList C.CK_OBJECT_HANDLE_PTR
+ ulCount C.CK_ULONG
+ )
+ e := C.FindObjects(c.ctx, C.CK_SESSION_HANDLE(sh), &objectList, C.CK_ULONG(max), &ulCount)
+ if toError(e) != nil {
+ return nil, false, toError(e)
+ }
+ l := toList(C.CK_ULONG_PTR(unsafe.Pointer(objectList)), ulCount)
+ // Make again a new list of the correct type.
+ // This is copying data, but this is not an often used function.
+ o := make([]ObjectHandle, len(l))
+ for i, v := range l {
+ o[i] = ObjectHandle(v)
+ }
+ return o, ulCount > C.CK_ULONG(max), nil
+}
+
+/* FindObjectsFinal finishes a search for token and session objects. */
+func (c *Ctx) FindObjectsFinal(sh SessionHandle) error {
+ e := C.FindObjectsFinal(c.ctx, C.CK_SESSION_HANDLE(sh))
+ return toError(e)
+}
+
+/* EncryptInit initializes an encryption operation. */
+func (c *Ctx) EncryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
+ mech, _ := cMechanismList(m)
+ e := C.EncryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
+ return toError(e)
+}
+
+/* Encrypt encrypts single-part data. */
+func (c *Ctx) Encrypt(sh SessionHandle, message []byte) ([]byte, error) {
+ var (
+ enc C.CK_BYTE_PTR
+ enclen C.CK_ULONG
+ )
+ e := C.Encrypt(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)), &enc, &enclen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ s := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
+ C.free(unsafe.Pointer(enc))
+ return s, nil
+}
+
+/* EncryptUpdate continues a multiple-part encryption operation. */
+func (c *Ctx) EncryptUpdate(sh SessionHandle, plain []byte) ([]byte, error) {
+ var (
+ part C.CK_BYTE_PTR
+ partlen C.CK_ULONG
+ )
+ e := C.EncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&plain[0])), C.CK_ULONG(len(plain)), &part, &partlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
+ C.free(unsafe.Pointer(part))
+ return h, nil
+}
+
+// EncryptFinal finishes a multiple-part encryption operation.
+func (c *Ctx) EncryptFinal(sh SessionHandle) ([]byte, error) {
+ var (
+ enc C.CK_BYTE_PTR
+ enclen C.CK_ULONG
+ )
+ e := C.EncryptFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &enc, &enclen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
+ C.free(unsafe.Pointer(enc))
+ return h, nil
+}
+
+/* DecryptInit initializes a decryption operation. */
+func (c *Ctx) DecryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
+ mech, _ := cMechanismList(m)
+ e := C.DecryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
+ return toError(e)
+}
+
+/* Decrypt decrypts encrypted data in a single part. */
+func (c *Ctx) Decrypt(sh SessionHandle, cypher []byte) ([]byte, error) {
+ var (
+ plain C.CK_BYTE_PTR
+ plainlen C.CK_ULONG
+ )
+ e := C.Decrypt(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cypher[0])), C.CK_ULONG(len(cypher)), &plain, &plainlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ s := C.GoBytes(unsafe.Pointer(plain), C.int(plainlen))
+ C.free(unsafe.Pointer(plain))
+ return s, nil
+}
+
+/* DecryptUpdate continues a multiple-part decryption operation. */
+func (c *Ctx) DecryptUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
+ var (
+ part C.CK_BYTE_PTR
+ partlen C.CK_ULONG
+ )
+ e := C.DecryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cipher[0])), C.CK_ULONG(len(cipher)), &part, &partlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
+ C.free(unsafe.Pointer(part))
+ return h, nil
+}
+
+/* DecryptFinal finishes a multiple-part decryption operation. */
+func (c *Ctx) DecryptFinal(sh SessionHandle) ([]byte, error) {
+ var (
+ plain C.CK_BYTE_PTR
+ plainlen C.CK_ULONG
+ )
+ e := C.DecryptFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &plain, &plainlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(plain), C.int(plainlen))
+ C.free(unsafe.Pointer(plain))
+ return h, nil
+}
+
+/* DigestInit initializes a message-digesting operation. */
+func (c *Ctx) DigestInit(sh SessionHandle, m []*Mechanism) error {
+ mech, _ := cMechanismList(m)
+ e := C.DigestInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech)
+ return toError(e)
+}
+
+/* Digest digests message in a single part. */
+func (c *Ctx) Digest(sh SessionHandle, message []byte) ([]byte, error) {
+ var (
+ hash C.CK_BYTE_PTR
+ hashlen C.CK_ULONG
+ )
+ e := C.Digest(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)), &hash, &hashlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(hash), C.int(hashlen))
+ C.free(unsafe.Pointer(hash))
+ return h, nil
+}
+
+/* DigestUpdate continues a multiple-part message-digesting operation. */
+func (c *Ctx) DigestUpdate(sh SessionHandle, message []byte) error {
+ e := C.DigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)))
+ if toError(e) != nil {
+ return toError(e)
+ }
+ return nil
+}
+
+// DigestKey continues a multi-part message-digesting
+// operation, by digesting the value of a secret key as part of
+// the data already digested.
+func (c *Ctx) DigestKey(sh SessionHandle, key ObjectHandle) error {
+ e := C.DigestKey(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(key))
+ if toError(e) != nil {
+ return toError(e)
+ }
+ return nil
+}
+
+/* DigestFinal finishes a multiple-part message-digesting operation. */
+func (c *Ctx) DigestFinal(sh SessionHandle) ([]byte, error) {
+ var (
+ hash C.CK_BYTE_PTR
+ hashlen C.CK_ULONG
+ )
+ e := C.DigestFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &hash, &hashlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(hash), C.int(hashlen))
+ C.free(unsafe.Pointer(hash))
+ return h, nil
+}
+
+// SignInit initializes a signature (private key encryption)
+// operation, where the signature is (will be) an appendix to
+// the data, and plaintext cannot be recovered from the
+// signature.
+func (c *Ctx) SignInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
+ mech, _ := cMechanismList(m) // Only the first is used, but still use a list.
+ e := C.SignInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
+ return toError(e)
+}
+
+// Sign signs (encrypts with private key) data in a single part, where the signature
+// is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
+func (c *Ctx) Sign(sh SessionHandle, message []byte) ([]byte, error) {
+ var (
+ sig C.CK_BYTE_PTR
+ siglen C.CK_ULONG
+ )
+ e := C.Sign(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)), &sig, &siglen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ s := C.GoBytes(unsafe.Pointer(sig), C.int(siglen))
+ C.free(unsafe.Pointer(sig))
+ return s, nil
+}
+
+// SignUpdate continues a multiple-part signature operation,
+// where the signature is (will be) an appendix to the data,
+// and plaintext cannot be recovered from the signature.
+func (c *Ctx) SignUpdate(sh SessionHandle, message []byte) error {
+ e := C.SignUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)))
+ return toError(e)
+}
+
+/* SignFinal finishes a multiple-part signature operation returning the signature. */
+func (c *Ctx) SignFinal(sh SessionHandle) ([]byte, error) {
+ var (
+ sig C.CK_BYTE_PTR
+ siglen C.CK_ULONG
+ )
+ e := C.SignFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &sig, &siglen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(sig), C.int(siglen))
+ C.free(unsafe.Pointer(sig))
+ return h, nil
+}
+
+// SignRecoverInit initializes a signature operation, where
+// the data can be recovered from the signature.
+func (c *Ctx) SignRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
+ mech, _ := cMechanismList(m)
+ e := C.SignRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
+ return toError(e)
+}
+
+// SignRecover signs data in a single operation, where the
+// data can be recovered from the signature.
+func (c *Ctx) SignRecover(sh SessionHandle, data []byte) ([]byte, error) {
+ var (
+ sig C.CK_BYTE_PTR
+ siglen C.CK_ULONG
+ )
+ e := C.SignRecover(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&data[0])), C.CK_ULONG(len(data)), &sig, &siglen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(sig), C.int(siglen))
+ C.free(unsafe.Pointer(sig))
+ return h, nil
+}
+
+// VerifyInit initializes a verification operation, where the
+// signature is an appendix to the data, and plaintext cannot
+// be recovered from the signature (e.g. DSA).
+func (c *Ctx) VerifyInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
+ mech, _ := cMechanismList(m) // only use one here
+ e := C.VerifyInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
+ return toError(e)
+}
+
+// Verify verifies a signature in a single-part operation,
+// where the signature is an appendix to the data, and plaintext
+// cannot be recovered from the signature.
+func (c *Ctx) Verify(sh SessionHandle, data []byte, signature []byte) error {
+ e := C.Verify(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&data[0])), C.CK_ULONG(len(data)), C.CK_BYTE_PTR(unsafe.Pointer(&signature[0])), C.CK_ULONG(len(signature)))
+ return toError(e)
+}
+
+// VerifyUpdate continues a multiple-part verification
+// operation, where the signature is an appendix to the data,
+// and plaintext cannot be recovered from the signature.
+func (c *Ctx) VerifyUpdate(sh SessionHandle, part []byte) error {
+ e := C.VerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&part[0])), C.CK_ULONG(len(part)))
+ return toError(e)
+}
+
+// VerifyFinal finishes a multiple-part verification
+// operation, checking the signature.
+func (c *Ctx) VerifyFinal(sh SessionHandle, signature []byte) error {
+ e := C.VerifyFinal(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&signature[0])), C.CK_ULONG(len(signature)))
+ return toError(e)
+}
+
+// VerifyRecoverInit initializes a signature verification
+// operation, where the data is recovered from the signature.
+func (c *Ctx) VerifyRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
+ mech, _ := cMechanismList(m)
+ e := C.VerifyRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
+ return toError(e)
+}
+
+// VerifyRecover verifies a signature in a single-part
+// operation, where the data is recovered from the signature.
+func (c *Ctx) VerifyRecover(sh SessionHandle, signature []byte) ([]byte, error) {
+ var (
+ data C.CK_BYTE_PTR
+ datalen C.CK_ULONG
+ )
+ e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&signature[0])), C.CK_ULONG(len(signature)), &data, &datalen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(data), C.int(datalen))
+ C.free(unsafe.Pointer(data))
+ return h, nil
+}
+
+// DigestEncryptUpdate continues a multiple-part digesting
+// and encryption operation.
+func (c *Ctx) DigestEncryptUpdate(sh SessionHandle, part []byte) ([]byte, error) {
+ var (
+ enc C.CK_BYTE_PTR
+ enclen C.CK_ULONG
+ )
+ e := C.DigestEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&part[0])), C.CK_ULONG(len(part)), &enc, &enclen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
+ C.free(unsafe.Pointer(enc))
+ return h, nil
+}
+
+/* DecryptDigestUpdate continues a multiple-part decryption and digesting operation. */
+func (c *Ctx) DecryptDigestUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
+ var (
+ part C.CK_BYTE_PTR
+ partlen C.CK_ULONG
+ )
+ e := C.DecryptDigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cipher[0])), C.CK_ULONG(len(cipher)), &part, &partlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
+ C.free(unsafe.Pointer(part))
+ return h, nil
+}
+
+/* SignEncryptUpdate continues a multiple-part signing and encryption operation. */
+func (c *Ctx) SignEncryptUpdate(sh SessionHandle, part []byte) ([]byte, error) {
+ var (
+ enc C.CK_BYTE_PTR
+ enclen C.CK_ULONG
+ )
+ e := C.SignEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&part[0])), C.CK_ULONG(len(part)), &enc, &enclen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
+ C.free(unsafe.Pointer(enc))
+ return h, nil
+}
+
+/* DecryptVerifyUpdate continues a multiple-part decryption and verify operation. */
+func (c *Ctx) DecryptVerifyUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
+ var (
+ part C.CK_BYTE_PTR
+ partlen C.CK_ULONG
+ )
+ e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cipher[0])), C.CK_ULONG(len(cipher)), &part, &partlen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
+ C.free(unsafe.Pointer(part))
+ return h, nil
+}
+
+/* GenerateKey generates a secret key, creating a new key object. */
+func (c *Ctx) GenerateKey(sh SessionHandle, m []*Mechanism, temp []*Attribute) (ObjectHandle, error) {
+ var key C.CK_OBJECT_HANDLE
+ t, tcount := cAttributeList(temp)
+ mech, _ := cMechanismList(m)
+ e := C.GenerateKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, t, tcount, C.CK_OBJECT_HANDLE_PTR(&key))
+ e1 := toError(e)
+ if e1 == nil {
+ return ObjectHandle(key), nil
+ }
+ return 0, e1
+}
+
+/* GenerateKeyPair generates a public-key/private-key pair creating new key objects. */
+func (c *Ctx) GenerateKeyPair(sh SessionHandle, m []*Mechanism, public, private []*Attribute) (ObjectHandle, ObjectHandle, error) {
+ var (
+ pubkey C.CK_OBJECT_HANDLE
+ privkey C.CK_OBJECT_HANDLE
+ )
+ pub, pubcount := cAttributeList(public)
+ priv, privcount := cAttributeList(private)
+ mech, _ := cMechanismList(m)
+ e := C.GenerateKeyPair(c.ctx, C.CK_SESSION_HANDLE(sh), mech, pub, pubcount, priv, privcount, C.CK_OBJECT_HANDLE_PTR(&pubkey), C.CK_OBJECT_HANDLE_PTR(&privkey))
+ e1 := toError(e)
+ if e1 == nil {
+ return ObjectHandle(pubkey), ObjectHandle(privkey), nil
+ }
+ return 0, 0, e1
+}
+
+/* WrapKey wraps (i.e., encrypts) a key. */
+func (c *Ctx) WrapKey(sh SessionHandle, m []*Mechanism, wrappingkey, key ObjectHandle) ([]byte, error) {
+ var (
+ wrappedkey C.CK_BYTE_PTR
+ wrappedkeylen C.CK_ULONG
+ )
+ mech, _ := cMechanismList(m)
+ e := C.WrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(wrappingkey), C.CK_OBJECT_HANDLE(key), &wrappedkey, &wrappedkeylen)
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(wrappedkey), C.int(wrappedkeylen))
+ C.free(unsafe.Pointer(wrappedkey))
+ return h, nil
+}
+
+/* UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
+func (c *Ctx) UnwrapKey(sh SessionHandle, m []*Mechanism, unwrappingkey ObjectHandle, wrappedkey []byte, a []*Attribute) (ObjectHandle, error) {
+ var key C.CK_OBJECT_HANDLE
+ ac, aclen := cAttributeList(a)
+ mech, _ := cMechanismList(m)
+ e := C.UnwrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(unwrappingkey), C.CK_BYTE_PTR(unsafe.Pointer(&wrappedkey[0])), C.CK_ULONG(len(wrappedkey)), ac, aclen, &key)
+ return ObjectHandle(key), toError(e)
+}
+
+// DeriveKey derives a key from a base key, creating a new key object. */
+func (c *Ctx) DeriveKey(sh SessionHandle, m []*Mechanism, basekey ObjectHandle, a []*Attribute) (ObjectHandle, error) {
+ var key C.CK_OBJECT_HANDLE
+ ac, aclen := cAttributeList(a)
+ mech, _ := cMechanismList(m)
+ e := C.DeriveKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(basekey), ac, aclen, &key)
+ return ObjectHandle(key), toError(e)
+}
+
+// SeedRandom mixes additional seed material into the token's
+// random number generator.
+func (c *Ctx) SeedRandom(sh SessionHandle, seed []byte) error {
+ e := C.SeedRandom(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&seed[0])), C.CK_ULONG(len(seed)))
+ return toError(e)
+}
+
+/* GenerateRandom generates random data. */
+func (c *Ctx) GenerateRandom(sh SessionHandle, length int) ([]byte, error) {
+ var rand C.CK_BYTE_PTR
+ e := C.GenerateRandom(c.ctx, C.CK_SESSION_HANDLE(sh), &rand, C.CK_ULONG(length))
+ if toError(e) != nil {
+ return nil, toError(e)
+ }
+ h := C.GoBytes(unsafe.Pointer(rand), C.int(length))
+ C.free(unsafe.Pointer(rand))
+ return h, nil
+}
+
+// WaitForSlotEvent returns a channel which returns a slot event
+// (token insertion, removal, etc.) when it occurs.
+func (c *Ctx) WaitForSlotEvent(flags uint) chan SlotEvent {
+ sl := make(chan SlotEvent, 1) // hold one element
+ go c.waitForSlotEventHelper(flags, sl)
+ return sl
+}
+
+func (c *Ctx) waitForSlotEventHelper(f uint, sl chan SlotEvent) {
+ var slotID C.CK_ULONG
+ C.WaitForSlotEvent(c.ctx, C.CK_FLAGS(f), &slotID)
+ sl <- SlotEvent{uint(slotID)}
+ close(sl) // TODO(miek): Sending and then closing ...?
+}
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11.h b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11.h
new file mode 100644
index 00000000000..9261e1e4c3f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11.h
@@ -0,0 +1,299 @@
+/* pkcs11.h include file for PKCS #11. */
+/* $Revision: 1.2 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined. These
+ * macros are described below, and typical definitions for them
+ * are also given. Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for Cryptoki structures should be set. The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this. You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object. It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable Cryptoki library function definition out of a
+ * return type and a function name. It should be used in the
+ * following fashion to define the exposed Cryptoki functions in
+ * a Cryptoki library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * )
+ * {
+ * ...
+ * }
+ *
+ * If you're using Microsoft Developer Studio 5.0 to define a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllexport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to define a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name. It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name. It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV. It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y) x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ extern CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points. That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points. A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library. This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+ CK_VERSION version; /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11_test.go b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11_test.go
new file mode 100644
index 00000000000..0ac02a2d5c3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11_test.go
@@ -0,0 +1,242 @@
+// Copyright 2013 Miek Gieben. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs11
+
+// These tests depend on SoftHSM and the library being in
+// in /usr/lib/softhsm/libsofthsm.so
+
+import (
+ "fmt"
+ "math/big"
+ "os"
+ "testing"
+)
+
+func setenv(t *testing.T) *Ctx {
+ wd, _ := os.Getwd()
+ os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")
+ p := New("/usr/lib/softhsm/libsofthsm.so") //p := New("/home/miek/libsofthsm.so")
+ if p == nil {
+ t.Fatal("Failed to init lib")
+ }
+ return p
+}
+
+func getSession(p *Ctx, t *testing.T) SessionHandle {
+ if e := p.Initialize(); e != nil {
+ t.Fatalf("init error %s\n", e.Error())
+ }
+ slots, e := p.GetSlotList(true)
+ if e != nil {
+ t.Fatalf("slots %s\n", e.Error())
+ }
+ session, e := p.OpenSession(slots[0], CKF_SERIAL_SESSION)
+ if e != nil {
+ t.Fatalf("session %s\n", e.Error())
+ }
+ if e := p.Login(session, CKU_USER, "1234"); e != nil {
+ t.Fatal("user pin %s\n", e.Error())
+ }
+ return session
+}
+
+func TestGetInfo(t *testing.T) {
+ p := setenv(t)
+ session := getSession(p, t)
+ defer p.Logout(session)
+ defer p.CloseSession(session)
+ defer p.Finalize()
+ defer p.Destroy()
+ info, err := p.GetInfo()
+ if err != nil {
+ t.Fatalf("Non zero error %s\n", err.Error())
+ }
+ if info.ManufacturerID != "SoftHSM" {
+ t.Fatal("ID should be SoftHSM")
+ }
+ t.Logf("%+v\n", info)
+}
+
+func TestFindObject(t *testing.T) {
+ p := setenv(t)
+ session := getSession(p, t)
+ defer p.Logout(session)
+ defer p.CloseSession(session)
+ defer p.Finalize()
+ defer p.Destroy()
+ // There are 2 keys in the db with this tag
+ template := []*Attribute{NewAttribute(CKA_LABEL, "MyFirstKey")}
+ if e := p.FindObjectsInit(session, template); e != nil {
+ t.Fatalf("Failed to init: %s\n", e.Error())
+ }
+ obj, b, e := p.FindObjects(session, 2)
+ if e != nil {
+ t.Fatalf("Failed to find: %s %v\n", e.Error(), b)
+ }
+ if e := p.FindObjectsFinal(session); e != nil {
+ t.Fatalf("Failed to finalize: %s\n", e.Error())
+ }
+ if len(obj) != 2 {
+ t.Fatal("should have found two objects")
+ }
+}
+
+func TestGetAttributeValue(t *testing.T) {
+ p := setenv(t)
+ session := getSession(p, t)
+ defer p.Logout(session)
+ defer p.Destroy()
+ defer p.Finalize()
+ defer p.CloseSession(session)
+ // There are at least two RSA keys in the hsm.db, objecthandle 1 and 2.
+ template := []*Attribute{
+ NewAttribute(CKA_PUBLIC_EXPONENT, nil),
+ NewAttribute(CKA_MODULUS_BITS, nil),
+ NewAttribute(CKA_MODULUS, nil),
+ NewAttribute(CKA_LABEL, nil),
+ }
+ // ObjectHandle two is the public key
+ attr, err := p.GetAttributeValue(session, ObjectHandle(2), template)
+ if err != nil {
+ t.Fatalf("err %s\n", err.Error())
+ }
+ for i, a := range attr {
+ t.Logf("Attr %d, type %d, valuelen %d", i, a.Type, len(a.Value))
+ if a.Type == CKA_MODULUS {
+ mod := big.NewInt(0)
+ mod.SetBytes(a.Value)
+ t.Logf("Modulus %s\n", mod.String())
+ }
+ }
+}
+
+func TestDigest(t *testing.T) {
+ p := setenv(t)
+ session := getSession(p, t)
+ defer p.Logout(session)
+ defer p.CloseSession(session)
+ defer p.Finalize()
+ defer p.Destroy()
+ e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)})
+ if e != nil {
+ t.Fatalf("DigestInit: %s\n", e.Error())
+ }
+
+ hash, e := p.Digest(session, []byte("this is a string"))
+ if e != nil {
+ t.Fatalf("Digest: %s\n", e.Error())
+ }
+ hex := ""
+ for _, d := range hash {
+ hex += fmt.Sprintf("%x", d)
+ }
+ // Teststring create with: echo -n "this is a string" | sha1sum
+ if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
+ t.Fatalf("wrong digest: %s", hex)
+ }
+}
+
+func TestDigestUpdate(t *testing.T) {
+ p := setenv(t)
+ session := getSession(p, t)
+ defer p.Logout(session)
+ defer p.CloseSession(session)
+ defer p.Finalize()
+ defer p.Destroy()
+ if e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)}); e != nil {
+ t.Fatalf("DigestInit: %s\n", e.Error())
+ }
+ if e := p.DigestUpdate(session, []byte("this is ")); e != nil {
+ t.Fatalf("DigestUpdate: %s\n", e.Error())
+ }
+ if e := p.DigestUpdate(session, []byte("a string")); e != nil {
+ t.Fatalf("DigestUpdate: %s\n", e.Error())
+ }
+ hash, e := p.DigestFinal(session)
+ if e != nil {
+ t.Fatalf("DigestFinal: %s\n", e.Error())
+ }
+ hex := ""
+ for _, d := range hash {
+ hex += fmt.Sprintf("%x", d)
+ }
+ // Teststring create with: echo -n "this is a string" | sha1sum
+ if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
+ t.Fatalf("wrong digest: %s", hex)
+ }
+
+}
+
+func testDestroyObject(t *testing.T) {
+ p := setenv(t)
+ session := getSession(p, t)
+ defer p.Logout(session)
+ defer p.CloseSession(session)
+ defer p.Finalize()
+ defer p.Destroy()
+
+ p.Logout(session) // log out the normal user
+ if e := p.Login(session, CKU_SO, "1234"); e != nil {
+ t.Fatal("security officer pin %s\n", e.Error())
+ }
+
+ // Looking the int values is tricky because they are stored in 64 bits in hsm.db,
+ // this means looking up stuff on 32 bits will not found them.
+ template := []*Attribute{
+ NewAttribute(CKA_LABEL, "MyFirstKey")}
+
+ if e := p.FindObjectsInit(session, template); e != nil {
+ t.Fatalf("Failed to init: %s\n", e.Error())
+ }
+ obj, _, e := p.FindObjects(session, 1)
+ if e != nil || len(obj) == 0 {
+ t.Fatalf("Failed to find objects\n")
+ }
+ if e := p.FindObjectsFinal(session); e != nil {
+ t.Fatalf("Failed to finalize: %s\n", e.Error())
+ }
+
+ if err := p.DestroyObject(session, obj[0]); err != nil {
+ t.Fatal("DestroyObject failed" + err.Error())
+ }
+}
+
+// ExampleSign show how to sign some data with a private key.
+// Note: error correction is not implemented in this function.
+func ExampleSign() {
+ p := setenv(nil)
+ p.Initialize()
+ defer p.Destroy()
+ defer p.Finalize()
+ slots, _ := p.GetSlotList(true)
+ session, _ := p.OpenSession(slots[0], CKF_SERIAL_SESSION|CKF_RW_SESSION)
+ defer p.CloseSession(session)
+ p.Login(session, CKU_USER, "1234")
+ defer p.Logout(session)
+ publicKeyTemplate := []*Attribute{
+ NewAttribute(CKA_KEY_TYPE, CKO_PUBLIC_KEY),
+ NewAttribute(CKA_TOKEN, true),
+ NewAttribute(CKA_ENCRYPT, true),
+ NewAttribute(CKA_PUBLIC_EXPONENT, []byte{3}),
+ NewAttribute(CKA_MODULUS_BITS, 1024),
+ NewAttribute(CKA_LABEL, "MyFirstKey"),
+ }
+ privateKeyTemplate := []*Attribute{
+ NewAttribute(CKA_KEY_TYPE, CKO_PRIVATE_KEY),
+ NewAttribute(CKA_TOKEN, true),
+ NewAttribute(CKA_PRIVATE, true),
+ NewAttribute(CKA_SIGN, true),
+ NewAttribute(CKA_LABEL, "MyFirstKey"),
+ }
+ pub, priv, _ := p.GenerateKeyPair(session,
+ []*Mechanism{NewMechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
+ publicKeyTemplate, privateKeyTemplate)
+ p.SignInit(session, []*Mechanism{NewMechanism(CKM_SHA1_RSA_PKCS, nil)}, priv)
+ // Sign something with the private key.
+ data := []byte("Lets sign this data")
+
+ sig, _ := p.Sign(session, data)
+ fmt.Printf("%v validate with %v\n", sig, pub)
+}
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11f.h b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11f.h
new file mode 100644
index 00000000000..ffbe010f64a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11f.h
@@ -0,0 +1,910 @@
+/* pkcs11f.h include file for PKCS #11. */
+/* $Revision: 1.2 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This header file contains pretty much everything about all the */
+/* Cryptoki function prototypes. Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
+ * cast to CK_C_INITIALIZE_ARGS_PTR
+ * and dereferenced */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INFO_PTR pInfo /* location that receives information */
+);
+#endif
+
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
+ * function list */
+);
+#endif
+
+
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_BBOOL tokenPresent, /* only slots with tokens? */
+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
+ CK_ULONG_PTR pulCount /* receives number of slots */
+);
+#endif
+
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the ID of the slot */
+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
+);
+#endif
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
+);
+#endif
+
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of token's slot */
+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
+ CK_ULONG_PTR pulCount /* gets # of mechs. */
+);
+#endif
+
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_MECHANISM_TYPE type, /* type of mechanism */
+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
+ CK_ULONG ulPinLen /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
+ CK_ULONG ulOldLen, /* length of the old PIN */
+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
+ CK_ULONG ulNewLen /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* from CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* passed to callback */
+ CK_NOTIFY Notify, /* callback function */
+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_SESSION_INFO_PTR pInfo /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* gets state */
+ CK_ULONG_PTR pulOperationStateLen /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* holds state */
+ CK_ULONG ulOperationStateLen, /* holds state length */
+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
+ CK_ULONG ulPinLen /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
+);
+#endif
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ULONG_PTR pulSize /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
+ CK_ULONG ulCount /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
+ CK_ULONG ulMaxObjectCount, /* max handles to get */
+ CK_ULONG_PTR pulObjectCount /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext */
+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext data len */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedData, /* ciphertext */
+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
+ CK_BYTE_PTR pData, /* gets plaintext */
+ CK_ULONG_PTR pulDataLen /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* input length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pLastPart, /* gets plaintext */
+ CK_ULONG_PTR pulLastPartLen /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to digest */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* data to be digested */
+ CK_ULONG ulPartLen /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hKey /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* the data to sign */
+ CK_ULONG ulPartLen /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* signed data */
+ CK_ULONG ulDataLen, /* length of signed data */
+ CK_BYTE_PTR pSignature, /* signature */
+ CK_ULONG ulSignatureLen /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* signed data */
+ CK_ULONG ulPartLen /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen, /* signature length */
+ CK_BYTE_PTR pData, /* gets signed data */
+ CK_ULONG_PTR pulDataLen /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
+ CK_ULONG ulCount, /* # of attrs in template */
+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session
+ * handle */
+ CK_MECHANISM_PTR pMechanism, /* key-gen
+ * mech. */
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
+ * for pub.
+ * key */
+ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
+ * attrs. */
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
+ * for priv.
+ * key */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
+ * attrs. */
+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
+ * key
+ * handle */
+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
+ * priv. key
+ * handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSeed, /* the seed material */
+ CK_ULONG ulSeedLen /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR RandomData, /* receives the random data */
+ CK_ULONG ulRandomLen /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Functions added in for Cryptoki Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FLAGS flags, /* blocking/nonblocking flag */
+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
+);
+#endif
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11t.h b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11t.h
new file mode 100644
index 00000000000..add49e48307
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/pkcs11t.h
@@ -0,0 +1,1885 @@
+/* pkcs11t.h include file for PKCS #11. */
+/* $Revision: 1.2 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file. */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#define CRYPTOKI_VERSION_MAJOR 2
+#define CRYPTOKI_VERSION_MINOR 20
+#define CRYPTOKI_VERSION_AMENDMENT 3
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE CK_FALSE
+#endif
+
+#ifndef TRUE
+#define TRUE CK_TRUE
+#endif
+#endif
+
+/* an unsigned 8-bit value */
+typedef unsigned char CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0
+
+
+typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
+typedef CK_ULONG CK_PTR CK_ULONG_PTR;
+typedef void CK_PTR CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+
+typedef struct CK_VERSION {
+ CK_BYTE major; /* integer portion of version number */
+ CK_BYTE minor; /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+ /* manufacturerID and libraryDecription have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags; /* must be zero */
+
+ /* libraryDescription and libraryVersion are new for v2.0 */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
+ CK_VERSION libraryVersion; /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER 0
+
+/* The following notification is new for PKCS #11 v2.20 amendment 3 */
+#define CKN_OTP_CHANGED 1
+
+
+typedef CK_ULONG CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+ /* slotDescription and manufacturerID have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags;
+
+ /* hardwareVersion and firmwareVersion are new for v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
+#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
+#define CKF_HW_SLOT 0x00000004 /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+ /* label, manufacturerID, and model have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
+ CK_CHAR serialNumber[16]; /* blank padded */
+ CK_FLAGS flags; /* see below */
+
+ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+ * changed from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulMaxSessionCount; /* max open sessions */
+ CK_ULONG ulSessionCount; /* sess. now open */
+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
+ CK_ULONG ulMaxPinLen; /* in bytes */
+ CK_ULONG ulMinPinLen; /* in bytes */
+ CK_ULONG ulTotalPublicMemory; /* in bytes */
+ CK_ULONG ulFreePublicMemory; /* in bytes */
+ CK_ULONG ulTotalPrivateMemory; /* in bytes */
+ CK_ULONG ulFreePrivateMemory; /* in bytes */
+
+ /* hardwareVersion, firmwareVersion, and time are new for
+ * v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+ CK_CHAR utcTime[16]; /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RNG 0x00000001 /* has random #
+ * generator */
+#define CKF_WRITE_PROTECTED 0x00000002 /* token is
+ * write-
+ * protected */
+#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
+ * login */
+#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
+ * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
+ * that the token has some sort of clock. The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN 0x00000040
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED 0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. This flag is deprecated in v2.11 and
+ onwards. */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED 0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session */
+typedef CK_ULONG CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO 0
+/* Normal user */
+#define CKU_USER 1
+/* Context specific (added in v2.20) */
+#define CKU_CONTEXT_SPECIFIC 2
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_STATE;
+#define CKS_RO_PUBLIC_SESSION 0
+#define CKS_RO_USER_FUNCTIONS 1
+#define CKS_RW_PUBLIC_SESSION 2
+#define CKS_RW_USER_FUNCTIONS 3
+#define CKS_RW_SO_FUNCTIONS 4
+
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags; /* see below */
+
+ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulDeviceError; /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RW_SESSION 0x00000002 /* session is r/w */
+#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object */
+typedef CK_ULONG CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes. It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+/* CKO_MECHANISM is new for v2.20 */
+#define CKO_DATA 0x00000000
+#define CKO_CERTIFICATE 0x00000001
+#define CKO_PUBLIC_KEY 0x00000002
+#define CKO_PRIVATE_KEY 0x00000003
+#define CKO_SECRET_KEY 0x00000004
+#define CKO_HW_FEATURE 0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_MECHANISM 0x00000007
+
+/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */
+#define CKO_OTP_KEY 0x00000008
+
+#define CKO_VENDOR_DEFINED 0x80000000
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+/* CKH_USER_INTERFACE is new for v2.20 */
+#define CKH_MONOTONIC_COUNTER 0x00000001
+#define CKH_CLOCK 0x00000002
+#define CKH_USER_INTERFACE 0x00000003
+#define CKH_VENDOR_DEFINED 0x80000000
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA 0x00000000
+#define CKK_DSA 0x00000001
+#define CKK_DH 0x00000002
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA 0x00000003
+#define CKK_EC 0x00000003
+#define CKK_X9_42_DH 0x00000004
+#define CKK_KEA 0x00000005
+
+#define CKK_GENERIC_SECRET 0x00000010
+#define CKK_RC2 0x00000011
+#define CKK_RC4 0x00000012
+#define CKK_DES 0x00000013
+#define CKK_DES2 0x00000014
+#define CKK_DES3 0x00000015
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST 0x00000016
+#define CKK_CAST3 0x00000017
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5 0x00000018
+#define CKK_CAST128 0x00000018
+#define CKK_RC5 0x00000019
+#define CKK_IDEA 0x0000001A
+#define CKK_SKIPJACK 0x0000001B
+#define CKK_BATON 0x0000001C
+#define CKK_JUNIPER 0x0000001D
+#define CKK_CDMF 0x0000001E
+#define CKK_AES 0x0000001F
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKK_BLOWFISH 0x00000020
+#define CKK_TWOFISH 0x00000021
+
+/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */
+#define CKK_SECURID 0x00000022
+#define CKK_HOTP 0x00000023
+#define CKK_ACTI 0x00000024
+
+/* Camellia is new for PKCS #11 v2.20 amendment 3 */
+#define CKK_CAMELLIA 0x00000025
+/* ARIA is new for PKCS #11 v2.20 amendment 3 */
+#define CKK_ARIA 0x00000026
+
+
+#define CKK_VENDOR_DEFINED 0x80000000
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+/* CKC_WTLS is new for v2.20 */
+#define CKC_X_509 0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
+#define CKC_WTLS 0x00000002
+#define CKC_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
+ consists of an array of values. */
+#define CKF_ARRAY_ATTRIBUTE 0x40000000
+
+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
+ and relates to the CKA_OTP_FORMAT attribute */
+#define CK_OTP_FORMAT_DECIMAL 0
+#define CK_OTP_FORMAT_HEXADECIMAL 1
+#define CK_OTP_FORMAT_ALPHANUMERIC 2
+#define CK_OTP_FORMAT_BINARY 3
+
+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
+ and relates to the CKA_OTP_..._REQUIREMENT attributes */
+#define CK_OTP_PARAM_IGNORED 0
+#define CK_OTP_PARAM_OPTIONAL 1
+#define CK_OTP_PARAM_MANDATORY 2
+
+/* The following attribute types are defined: */
+#define CKA_CLASS 0x00000000
+#define CKA_TOKEN 0x00000001
+#define CKA_PRIVATE 0x00000002
+#define CKA_LABEL 0x00000003
+#define CKA_APPLICATION 0x00000010
+#define CKA_VALUE 0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID 0x00000012
+
+#define CKA_CERTIFICATE_TYPE 0x00000080
+#define CKA_ISSUER 0x00000081
+#define CKA_SERIAL_NUMBER 0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER 0x00000083
+#define CKA_OWNER 0x00000084
+#define CKA_ATTR_TYPES 0x00000085
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED 0x00000086
+
+/* CKA_CERTIFICATE_CATEGORY ...
+ * CKA_CHECK_VALUE are new for v2.20 */
+#define CKA_CERTIFICATE_CATEGORY 0x00000087
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
+#define CKA_URL 0x00000089
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
+#define CKA_CHECK_VALUE 0x00000090
+
+#define CKA_KEY_TYPE 0x00000100
+#define CKA_SUBJECT 0x00000101
+#define CKA_ID 0x00000102
+#define CKA_SENSITIVE 0x00000103
+#define CKA_ENCRYPT 0x00000104
+#define CKA_DECRYPT 0x00000105
+#define CKA_WRAP 0x00000106
+#define CKA_UNWRAP 0x00000107
+#define CKA_SIGN 0x00000108
+#define CKA_SIGN_RECOVER 0x00000109
+#define CKA_VERIFY 0x0000010A
+#define CKA_VERIFY_RECOVER 0x0000010B
+#define CKA_DERIVE 0x0000010C
+#define CKA_START_DATE 0x00000110
+#define CKA_END_DATE 0x00000111
+#define CKA_MODULUS 0x00000120
+#define CKA_MODULUS_BITS 0x00000121
+#define CKA_PUBLIC_EXPONENT 0x00000122
+#define CKA_PRIVATE_EXPONENT 0x00000123
+#define CKA_PRIME_1 0x00000124
+#define CKA_PRIME_2 0x00000125
+#define CKA_EXPONENT_1 0x00000126
+#define CKA_EXPONENT_2 0x00000127
+#define CKA_COEFFICIENT 0x00000128
+#define CKA_PRIME 0x00000130
+#define CKA_SUBPRIME 0x00000131
+#define CKA_BASE 0x00000132
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS 0x00000133
+#define CKA_SUBPRIME_BITS 0x00000134
+#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
+/* (To retain backwards-compatibility) */
+
+#define CKA_VALUE_BITS 0x00000160
+#define CKA_VALUE_LEN 0x00000161
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE 0x00000162
+#define CKA_LOCAL 0x00000163
+#define CKA_NEVER_EXTRACTABLE 0x00000164
+#define CKA_ALWAYS_SENSITIVE 0x00000165
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM 0x00000166
+
+#define CKA_MODIFIABLE 0x00000170
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS 0x00000180
+#define CKA_EC_PARAMS 0x00000180
+
+#define CKA_EC_POINT 0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * are new for v2.10. Deprecated in v2.11 and onwards. */
+#define CKA_SECONDARY_AUTH 0x00000200
+#define CKA_AUTH_PIN_FLAGS 0x00000201
+
+/* CKA_ALWAYS_AUTHENTICATE ...
+ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
+#define CKA_ALWAYS_AUTHENTICATE 0x00000202
+
+#define CKA_WRAP_WITH_TRUSTED 0x00000210
+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
+
+/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */
+#define CKA_OTP_FORMAT 0x00000220
+#define CKA_OTP_LENGTH 0x00000221
+#define CKA_OTP_TIME_INTERVAL 0x00000222
+#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223
+#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224
+#define CKA_OTP_TIME_REQUIREMENT 0x00000225
+#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226
+#define CKA_OTP_PIN_REQUIREMENT 0x00000227
+#define CKA_OTP_COUNTER 0x0000022E
+#define CKA_OTP_TIME 0x0000022F
+#define CKA_OTP_USER_IDENTIFIER 0x0000022A
+#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B
+#define CKA_OTP_SERVICE_LOGO 0x0000022C
+#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D
+
+
+/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_HW_FEATURE_TYPE 0x00000300
+#define CKA_RESET_ON_INIT 0x00000301
+#define CKA_HAS_RESET 0x00000302
+
+/* The following attributes are new for v2.20 */
+#define CKA_PIXEL_X 0x00000400
+#define CKA_PIXEL_Y 0x00000401
+#define CKA_RESOLUTION 0x00000402
+#define CKA_CHAR_ROWS 0x00000403
+#define CKA_CHAR_COLUMNS 0x00000404
+#define CKA_COLOR 0x00000405
+#define CKA_BITS_PER_PIXEL 0x00000406
+#define CKA_CHAR_SETS 0x00000480
+#define CKA_ENCODING_METHODS 0x00000481
+#define CKA_MIME_TYPES 0x00000482
+#define CKA_MECHANISM_TYPE 0x00000500
+#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
+#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
+#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
+
+#define CKA_VENDOR_DEFINED 0x80000000
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+
+ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulValueLen; /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+ CK_CHAR year[4]; /* the year ("1900" - "9999") */
+ CK_CHAR month[2]; /* the month ("01" - "12") */
+ CK_CHAR day[2]; /* the day ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
+#define CKM_RSA_PKCS 0x00000001
+#define CKM_RSA_9796 0x00000002
+#define CKM_RSA_X_509 0x00000003
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0. They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS 0x00000004
+#define CKM_MD5_RSA_PKCS 0x00000005
+#define CKM_SHA1_RSA_PKCS 0x00000006
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008
+#define CKM_RSA_PKCS_OAEP 0x00000009
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
+#define CKM_RSA_X9_31 0x0000000B
+#define CKM_SHA1_RSA_X9_31 0x0000000C
+#define CKM_RSA_PKCS_PSS 0x0000000D
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
+
+#define CKM_DSA_KEY_PAIR_GEN 0x00000010
+#define CKM_DSA 0x00000011
+#define CKM_DSA_SHA1 0x00000012
+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
+#define CKM_DH_PKCS_DERIVE 0x00000021
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
+#define CKM_X9_42_DH_DERIVE 0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
+#define CKM_X9_42_MQV_DERIVE 0x00000033
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_RSA_PKCS 0x00000040
+#define CKM_SHA384_RSA_PKCS 0x00000041
+#define CKM_SHA512_RSA_PKCS 0x00000042
+#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
+#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
+#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
+
+/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */
+#define CKM_SHA224_RSA_PKCS 0x00000046
+#define CKM_SHA224_RSA_PKCS_PSS 0x00000047
+
+#define CKM_RC2_KEY_GEN 0x00000100
+#define CKM_RC2_ECB 0x00000101
+#define CKM_RC2_CBC 0x00000102
+#define CKM_RC2_MAC 0x00000103
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL 0x00000104
+#define CKM_RC2_CBC_PAD 0x00000105
+
+#define CKM_RC4_KEY_GEN 0x00000110
+#define CKM_RC4 0x00000111
+#define CKM_DES_KEY_GEN 0x00000120
+#define CKM_DES_ECB 0x00000121
+#define CKM_DES_CBC 0x00000122
+#define CKM_DES_MAC 0x00000123
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL 0x00000124
+#define CKM_DES_CBC_PAD 0x00000125
+
+#define CKM_DES2_KEY_GEN 0x00000130
+#define CKM_DES3_KEY_GEN 0x00000131
+#define CKM_DES3_ECB 0x00000132
+#define CKM_DES3_CBC 0x00000133
+#define CKM_DES3_MAC 0x00000134
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL 0x00000135
+#define CKM_DES3_CBC_PAD 0x00000136
+#define CKM_CDMF_KEY_GEN 0x00000140
+#define CKM_CDMF_ECB 0x00000141
+#define CKM_CDMF_CBC 0x00000142
+#define CKM_CDMF_MAC 0x00000143
+#define CKM_CDMF_MAC_GENERAL 0x00000144
+#define CKM_CDMF_CBC_PAD 0x00000145
+
+/* the following four DES mechanisms are new for v2.20 */
+#define CKM_DES_OFB64 0x00000150
+#define CKM_DES_OFB8 0x00000151
+#define CKM_DES_CFB64 0x00000152
+#define CKM_DES_CFB8 0x00000153
+
+#define CKM_MD2 0x00000200
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC 0x00000201
+#define CKM_MD2_HMAC_GENERAL 0x00000202
+
+#define CKM_MD5 0x00000210
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC 0x00000211
+#define CKM_MD5_HMAC_GENERAL 0x00000212
+
+#define CKM_SHA_1 0x00000220
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC 0x00000221
+#define CKM_SHA_1_HMAC_GENERAL 0x00000222
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128 0x00000230
+#define CKM_RIPEMD128_HMAC 0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
+#define CKM_RIPEMD160 0x00000240
+#define CKM_RIPEMD160_HMAC 0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256 0x00000250
+#define CKM_SHA256_HMAC 0x00000251
+#define CKM_SHA256_HMAC_GENERAL 0x00000252
+
+/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
+#define CKM_SHA224 0x00000255
+#define CKM_SHA224_HMAC 0x00000256
+#define CKM_SHA224_HMAC_GENERAL 0x00000257
+
+#define CKM_SHA384 0x00000260
+#define CKM_SHA384_HMAC 0x00000261
+#define CKM_SHA384_HMAC_GENERAL 0x00000262
+#define CKM_SHA512 0x00000270
+#define CKM_SHA512_HMAC 0x00000271
+#define CKM_SHA512_HMAC_GENERAL 0x00000272
+
+/* SecurID is new for PKCS #11 v2.20 amendment 1 */
+#define CKM_SECURID_KEY_GEN 0x00000280
+#define CKM_SECURID 0x00000282
+
+/* HOTP is new for PKCS #11 v2.20 amendment 1 */
+#define CKM_HOTP_KEY_GEN 0x00000290
+#define CKM_HOTP 0x00000291
+
+/* ACTI is new for PKCS #11 v2.20 amendment 1 */
+#define CKM_ACTI 0x000002A0
+#define CKM_ACTI_KEY_GEN 0x000002A1
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN 0x00000300
+#define CKM_CAST_ECB 0x00000301
+#define CKM_CAST_CBC 0x00000302
+#define CKM_CAST_MAC 0x00000303
+#define CKM_CAST_MAC_GENERAL 0x00000304
+#define CKM_CAST_CBC_PAD 0x00000305
+#define CKM_CAST3_KEY_GEN 0x00000310
+#define CKM_CAST3_ECB 0x00000311
+#define CKM_CAST3_CBC 0x00000312
+#define CKM_CAST3_MAC 0x00000313
+#define CKM_CAST3_MAC_GENERAL 0x00000314
+#define CKM_CAST3_CBC_PAD 0x00000315
+#define CKM_CAST5_KEY_GEN 0x00000320
+#define CKM_CAST128_KEY_GEN 0x00000320
+#define CKM_CAST5_ECB 0x00000321
+#define CKM_CAST128_ECB 0x00000321
+#define CKM_CAST5_CBC 0x00000322
+#define CKM_CAST128_CBC 0x00000322
+#define CKM_CAST5_MAC 0x00000323
+#define CKM_CAST128_MAC 0x00000323
+#define CKM_CAST5_MAC_GENERAL 0x00000324
+#define CKM_CAST128_MAC_GENERAL 0x00000324
+#define CKM_CAST5_CBC_PAD 0x00000325
+#define CKM_CAST128_CBC_PAD 0x00000325
+#define CKM_RC5_KEY_GEN 0x00000330
+#define CKM_RC5_ECB 0x00000331
+#define CKM_RC5_CBC 0x00000332
+#define CKM_RC5_MAC 0x00000333
+#define CKM_RC5_MAC_GENERAL 0x00000334
+#define CKM_RC5_CBC_PAD 0x00000335
+#define CKM_IDEA_KEY_GEN 0x00000340
+#define CKM_IDEA_ECB 0x00000341
+#define CKM_IDEA_CBC 0x00000342
+#define CKM_IDEA_MAC 0x00000343
+#define CKM_IDEA_MAC_GENERAL 0x00000344
+#define CKM_IDEA_CBC_PAD 0x00000345
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
+#define CKM_XOR_BASE_AND_DATA 0x00000364
+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
+
+/* CKM_TLS_PRF is new for v2.20 */
+#define CKM_TLS_PRF 0x00000378
+
+#define CKM_SSL3_MD5_MAC 0x00000380
+#define CKM_SSL3_SHA1_MAC 0x00000381
+#define CKM_MD5_KEY_DERIVATION 0x00000390
+#define CKM_MD2_KEY_DERIVATION 0x00000391
+#define CKM_SHA1_KEY_DERIVATION 0x00000392
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_KEY_DERIVATION 0x00000393
+#define CKM_SHA384_KEY_DERIVATION 0x00000394
+#define CKM_SHA512_KEY_DERIVATION 0x00000395
+
+/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */
+#define CKM_SHA224_KEY_DERIVATION 0x00000396
+
+#define CKM_PBE_MD2_DES_CBC 0x000003A0
+#define CKM_PBE_MD5_DES_CBC 0x000003A1
+#define CKM_PBE_MD5_CAST_CBC 0x000003A2
+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
+#define CKM_PBE_SHA1_RC4_128 0x000003A6
+#define CKM_PBE_SHA1_RC4_40 0x000003A7
+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2 0x000003B0
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
+
+/* WTLS mechanisms are new for v2.20 */
+#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
+#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
+#define CKM_WTLS_PRF 0x000003D3
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
+
+#define CKM_KEY_WRAP_LYNKS 0x00000400
+#define CKM_KEY_WRAP_SET_OAEP 0x00000401
+
+/* CKM_CMS_SIG is new for v2.20 */
+#define CKM_CMS_SIG 0x00000500
+
+/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */
+#define CKM_KIP_DERIVE 0x00000510
+#define CKM_KIP_WRAP 0x00000511
+#define CKM_KIP_MAC 0x00000512
+
+/* Camellia is new for PKCS #11 v2.20 amendment 3 */
+#define CKM_CAMELLIA_KEY_GEN 0x00000550
+#define CKM_CAMELLIA_ECB 0x00000551
+#define CKM_CAMELLIA_CBC 0x00000552
+#define CKM_CAMELLIA_MAC 0x00000553
+#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
+#define CKM_CAMELLIA_CBC_PAD 0x00000555
+#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
+#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
+#define CKM_CAMELLIA_CTR 0x00000558
+
+/* ARIA is new for PKCS #11 v2.20 amendment 3 */
+#define CKM_ARIA_KEY_GEN 0x00000560
+#define CKM_ARIA_ECB 0x00000561
+#define CKM_ARIA_CBC 0x00000562
+#define CKM_ARIA_MAC 0x00000563
+#define CKM_ARIA_MAC_GENERAL 0x00000564
+#define CKM_ARIA_CBC_PAD 0x00000565
+#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566
+#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN 0x00001000
+#define CKM_SKIPJACK_ECB64 0x00001001
+#define CKM_SKIPJACK_CBC64 0x00001002
+#define CKM_SKIPJACK_OFB64 0x00001003
+#define CKM_SKIPJACK_CFB64 0x00001004
+#define CKM_SKIPJACK_CFB32 0x00001005
+#define CKM_SKIPJACK_CFB16 0x00001006
+#define CKM_SKIPJACK_CFB8 0x00001007
+#define CKM_SKIPJACK_WRAP 0x00001008
+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
+#define CKM_SKIPJACK_RELAYX 0x0000100a
+#define CKM_KEA_KEY_PAIR_GEN 0x00001010
+#define CKM_KEA_KEY_DERIVE 0x00001011
+#define CKM_FORTEZZA_TIMESTAMP 0x00001020
+#define CKM_BATON_KEY_GEN 0x00001030
+#define CKM_BATON_ECB128 0x00001031
+#define CKM_BATON_ECB96 0x00001032
+#define CKM_BATON_CBC128 0x00001033
+#define CKM_BATON_COUNTER 0x00001034
+#define CKM_BATON_SHUFFLE 0x00001035
+#define CKM_BATON_WRAP 0x00001036
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
+#define CKM_EC_KEY_PAIR_GEN 0x00001040
+
+#define CKM_ECDSA 0x00001041
+#define CKM_ECDSA_SHA1 0x00001042
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE 0x00001050
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
+#define CKM_ECMQV_DERIVE 0x00001052
+
+#define CKM_JUNIPER_KEY_GEN 0x00001060
+#define CKM_JUNIPER_ECB128 0x00001061
+#define CKM_JUNIPER_CBC128 0x00001062
+#define CKM_JUNIPER_COUNTER 0x00001063
+#define CKM_JUNIPER_SHUFFLE 0x00001064
+#define CKM_JUNIPER_WRAP 0x00001065
+#define CKM_FASTHASH 0x00001070
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN 0x00001080
+#define CKM_AES_ECB 0x00001081
+#define CKM_AES_CBC 0x00001082
+#define CKM_AES_MAC 0x00001083
+#define CKM_AES_MAC_GENERAL 0x00001084
+#define CKM_AES_CBC_PAD 0x00001085
+
+/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */
+#define CKM_AES_CTR 0x00001086
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKM_BLOWFISH_KEY_GEN 0x00001090
+#define CKM_BLOWFISH_CBC 0x00001091
+#define CKM_TWOFISH_KEY_GEN 0x00001092
+#define CKM_TWOFISH_CBC 0x00001093
+
+
+/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
+#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
+#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
+#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
+#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
+#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
+#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
+
+#define CKM_DSA_PARAMETER_GEN 0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
+
+#define CKM_VENDOR_DEFINED 0x80000000
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism */
+typedef struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+
+ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulParameterLen; /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ * Bit Flag Mask Meaning */
+#define CKF_HW 0x00000001 /* performed by HW */
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0. They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT 0x00000100
+#define CKF_DECRYPT 0x00000200
+#define CKF_DIGEST 0x00000400
+#define CKF_SIGN 0x00000800
+#define CKF_SIGN_RECOVER 0x00001000
+#define CKF_VERIFY 0x00002000
+#define CKF_VERIFY_RECOVER 0x00004000
+#define CKF_GENERATE 0x00008000
+#define CKF_GENERATE_KEY_PAIR 0x00010000
+#define CKF_WRAP 0x00020000
+#define CKF_UNWRAP 0x00040000
+#define CKF_DERIVE 0x00080000
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P 0x00100000
+#define CKF_EC_F_2M 0x00200000
+#define CKF_EC_ECPARAMETERS 0x00400000
+#define CKF_EC_NAMEDCURVE 0x00800000
+#define CKF_EC_UNCOMPRESS 0x01000000
+#define CKF_EC_COMPRESS 0x02000000
+
+#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_RV;
+
+#define CKR_OK 0x00000000
+#define CKR_CANCEL 0x00000001
+#define CKR_HOST_MEMORY 0x00000002
+#define CKR_SLOT_ID_INVALID 0x00000003
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR 0x00000005
+#define CKR_FUNCTION_FAILED 0x00000006
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD 0x00000007
+#define CKR_NO_EVENT 0x00000008
+#define CKR_NEED_TO_CREATE_THREADS 0x00000009
+#define CKR_CANT_LOCK 0x0000000A
+
+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
+#define CKR_DATA_INVALID 0x00000020
+#define CKR_DATA_LEN_RANGE 0x00000021
+#define CKR_DEVICE_ERROR 0x00000030
+#define CKR_DEVICE_MEMORY 0x00000031
+#define CKR_DEVICE_REMOVED 0x00000032
+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
+#define CKR_FUNCTION_CANCELED 0x00000050
+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
+
+#define CKR_KEY_HANDLE_INVALID 0x00000060
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE 0x00000062
+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED 0x00000064
+#define CKR_KEY_CHANGED 0x00000065
+#define CKR_KEY_NEEDED 0x00000066
+#define CKR_KEY_INDIGESTIBLE 0x00000067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
+#define CKR_KEY_NOT_WRAPPABLE 0x00000069
+#define CKR_KEY_UNEXTRACTABLE 0x0000006A
+
+#define CKR_MECHANISM_INVALID 0x00000070
+#define CKR_MECHANISM_PARAM_INVALID 0x00000071
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID 0x00000082
+#define CKR_OPERATION_ACTIVE 0x00000090
+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
+#define CKR_PIN_INCORRECT 0x000000A0
+#define CKR_PIN_INVALID 0x000000A1
+#define CKR_PIN_LEN_RANGE 0x000000A2
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED 0x000000A3
+#define CKR_PIN_LOCKED 0x000000A4
+
+#define CKR_SESSION_CLOSED 0x000000B0
+#define CKR_SESSION_COUNT 0x000000B1
+#define CKR_SESSION_HANDLE_INVALID 0x000000B3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
+#define CKR_SESSION_READ_ONLY 0x000000B5
+#define CKR_SESSION_EXISTS 0x000000B6
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
+
+#define CKR_SIGNATURE_INVALID 0x000000C0
+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
+#define CKR_TOKEN_NOT_PRESENT 0x000000E0
+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
+#define CKR_USER_NOT_LOGGED_IN 0x00000101
+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
+#define CKR_USER_TYPE_INVALID 0x00000103
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
+#define CKR_USER_TOO_MANY_TYPES 0x00000105
+
+#define CKR_WRAPPED_KEY_INVALID 0x00000110
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
+
+/* These are new to v2.0 */
+#define CKR_RANDOM_NO_RNG 0x00000121
+
+/* These are new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL 0x00000150
+#define CKR_SAVED_STATE_INVALID 0x00000160
+#define CKR_INFORMATION_SENSITIVE 0x00000170
+#define CKR_STATE_UNSAVEABLE 0x00000180
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
+#define CKR_MUTEX_BAD 0x000001A0
+#define CKR_MUTEX_NOT_LOCKED 0x000001A1
+
+/* The following return values are new for PKCS #11 v2.20 amendment 3 */
+#define CKR_NEW_PIN_MODE 0x000001B0
+#define CKR_NEXT_OTP 0x000001B1
+
+/* This is new to v2.20 */
+#define CKR_FUNCTION_REJECTED 0x00000200
+
+#define CKR_VENDOR_DEFINED 0x80000000
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
+#define CKF_OS_LOCKING_OK 0x00000002
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
+ * are new for v2.20 */
+#define CKG_MGF1_SHA1 0x00000001
+#define CKG_MGF1_SHA256 0x00000002
+#define CKG_MGF1_SHA384 0x00000003
+#define CKG_MGF1_SHA512 0x00000004
+/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
+#define CKG_MGF1_SHA224 0x00000005
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+/* CK_EC_KDF_TYPE is new for v2.11. */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL 0x00000001
+#define CKD_SHA1_KDF 0x00000002
+
+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+
+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_ECMQV_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_ECMQV_DERIVE_PARAMS;
+
+typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* The following X9.42 DH key derivation functions are defined
+ (besides CKD_NULL already defined : */
+#define CKD_SHA1_KDF_ASN1 0x00000003
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004
+
+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_X9_42_MQV_DERIVE_PARAMS;
+
+typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+ CK_BBOOL isSender;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pRandomB;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+
+ CK_BYTE iv[8]; /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_BYTE_PTR pIv; /* pointer to IV */
+ CK_ULONG ulIvLen; /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
+typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[8];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pPassword;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPAndGLen;
+ CK_ULONG ulQLen;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pPrimeP;
+ CK_BYTE_PTR pBaseG;
+ CK_BYTE_PTR pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+ CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+ CK_ULONG ulOldWrappedXLen;
+ CK_BYTE_PTR pOldWrappedX;
+ CK_ULONG ulOldPasswordLen;
+ CK_BYTE_PTR pOldPassword;
+ CK_ULONG ulOldPublicDataLen;
+ CK_BYTE_PTR pOldPublicData;
+ CK_ULONG ulOldRandomLen;
+ CK_BYTE_PTR pOldRandomA;
+ CK_ULONG ulNewPasswordLen;
+ CK_BYTE_PTR pNewPassword;
+ CK_ULONG ulNewPublicDataLen;
+ CK_BYTE_PTR pNewPublicData;
+ CK_ULONG ulNewRandomLen;
+ CK_BYTE_PTR pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+ CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+ CK_BYTE_PTR pInitVector;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_ULONG ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+ CK_BYTE bBC; /* block contents byte */
+ CK_BYTE_PTR pX; /* extra data */
+ CK_ULONG ulXLen; /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
+ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hClientMacSecret;
+ CK_OBJECT_HANDLE hServerMacSecret;
+ CK_OBJECT_HANDLE hClientKey;
+ CK_OBJECT_HANDLE hServerKey;
+ CK_BYTE_PTR pIVClient;
+ CK_BYTE_PTR pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+/* CK_TLS_PRF_PARAMS is new for version 2.20 */
+typedef struct CK_TLS_PRF_PARAMS {
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_TLS_PRF_PARAMS;
+
+typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
+
+/* WTLS is new for version 2.20 */
+typedef struct CK_WTLS_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_WTLS_RANDOM_DATA;
+
+typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
+
+typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_BYTE_PTR pVersion;
+} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_WTLS_PRF_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_WTLS_PRF_PARAMS;
+
+typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hMacSecret;
+ CK_OBJECT_HANDLE hKey;
+ CK_BYTE_PTR pIV;
+} CK_WTLS_KEY_MAT_OUT;
+
+typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_ULONG ulSequenceNumber;
+ CK_BBOOL bIsExport;
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_WTLS_KEY_MAT_PARAMS;
+
+typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
+
+/* CMS is new for version 2.20 */
+typedef struct CK_CMS_SIG_PARAMS {
+ CK_OBJECT_HANDLE certificateHandle;
+ CK_MECHANISM_PTR pSigningMechanism;
+ CK_MECHANISM_PTR pDigestMechanism;
+ CK_UTF8CHAR_PTR pContentType;
+ CK_BYTE_PTR pRequestedAttributes;
+ CK_ULONG ulRequestedAttributesLen;
+ CK_BYTE_PTR pRequiredAttributes;
+ CK_ULONG ulRequiredAttributesLen;
+} CK_CMS_SIG_PARAMS;
+
+typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG_PTR ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */
+
+typedef CK_ULONG CK_OTP_PARAM_TYPE;
+typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */
+
+typedef struct CK_OTP_PARAM {
+ CK_OTP_PARAM_TYPE type;
+ CK_VOID_PTR pValue;
+ CK_ULONG ulValueLen;
+} CK_OTP_PARAM;
+
+typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
+
+typedef struct CK_OTP_PARAMS {
+ CK_OTP_PARAM_PTR pParams;
+ CK_ULONG ulCount;
+} CK_OTP_PARAMS;
+
+typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
+
+typedef struct CK_OTP_SIGNATURE_INFO {
+ CK_OTP_PARAM_PTR pParams;
+ CK_ULONG ulCount;
+} CK_OTP_SIGNATURE_INFO;
+
+typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
+
+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
+#define CK_OTP_VALUE 0
+#define CK_OTP_PIN 1
+#define CK_OTP_CHALLENGE 2
+#define CK_OTP_TIME 3
+#define CK_OTP_COUNTER 4
+#define CK_OTP_FLAGS 5
+#define CK_OTP_OUTPUT_LENGTH 6
+#define CK_OTP_OUTPUT_FORMAT 7
+
+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
+#define CKF_NEXT_OTP 0x00000001
+#define CKF_EXCLUDE_TIME 0x00000002
+#define CKF_EXCLUDE_COUNTER 0x00000004
+#define CKF_EXCLUDE_CHALLENGE 0x00000008
+#define CKF_EXCLUDE_PIN 0x00000010
+#define CKF_USER_FRIENDLY_OTP 0x00000020
+
+/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */
+typedef struct CK_KIP_PARAMS {
+ CK_MECHANISM_PTR pMechanism;
+ CK_OBJECT_HANDLE hKey;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+} CK_KIP_PARAMS;
+
+typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
+
+/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
+typedef struct CK_AES_CTR_PARAMS {
+ CK_ULONG ulCounterBits;
+ CK_BYTE cb[16];
+} CK_AES_CTR_PARAMS;
+
+typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
+
+/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
+typedef struct CK_CAMELLIA_CTR_PARAMS {
+ CK_ULONG ulCounterBits;
+ CK_BYTE cb[16];
+} CK_CAMELLIA_CTR_PARAMS;
+
+typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
+
+/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
+typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
+typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+#endif
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/softhsm.conf b/Godeps/_workspace/src/github.com/miekg/pkcs11/softhsm.conf
new file mode 100644
index 00000000000..f95862b1046
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/softhsm.conf
@@ -0,0 +1 @@
+0:hsm.db
diff --git a/Godeps/_workspace/src/github.com/miekg/pkcs11/types.go b/Godeps/_workspace/src/github.com/miekg/pkcs11/types.go
new file mode 100644
index 00000000000..9a709cd8518
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/miekg/pkcs11/types.go
@@ -0,0 +1,274 @@
+// Copyright 2013 Miek Gieben. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs11
+
+/*
+#define CK_PTR *
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+#define CK_DEFINE_FUNCTION(returnType, name) returnType name
+#define CK_DECLARE_FUNCTION(returnType, name) returnType name
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
+#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
+
+#include
+#include "pkcs11.h"
+
+CK_ULONG Index(CK_ULONG_PTR array, CK_ULONG i)
+{
+ return array[i];
+}
+
+CK_ULONG Sizeof()
+{
+ return sizeof(CK_ULONG);
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "time"
+ "unsafe"
+)
+
+// toList converts from a C style array to a []uint.
+func toList(clist C.CK_ULONG_PTR, size C.CK_ULONG) []uint {
+ l := make([]uint, int(size))
+ for i := 0; i < len(l); i++ {
+ l[i] = uint(C.Index(clist, C.CK_ULONG(i)))
+ }
+ defer C.free(unsafe.Pointer(clist))
+ return l
+}
+
+// cBBool converts a bool to a CK_BBOOL.
+func cBBool(x bool) C.CK_BBOOL {
+ if x {
+ return C.CK_BBOOL(C.CK_TRUE)
+ }
+ return C.CK_BBOOL(C.CK_FALSE)
+}
+
+// Error represents an PKCS#11 error.
+type Error uint
+
+func (e Error) Error() string {
+ return fmt.Sprintf("pkcs11: 0x%X: %s", uint(e), strerror[uint(e)])
+}
+
+func toError(e C.CK_RV) error {
+ if e == C.CKR_OK {
+ return nil
+ }
+ return Error(e)
+}
+
+/* SessionHandle is a Cryptoki-assigned value that identifies a session. */
+type SessionHandle uint
+
+/* ObjectHandle is a token-specific identifier for an object. */
+type ObjectHandle uint
+
+// Version represents any version information from the library.
+type Version struct {
+ Major byte
+ Minor byte
+}
+
+func toVersion(version C.CK_VERSION) Version {
+ return Version{byte(version.major), byte(version.minor)}
+}
+
+// SlotEvent holds the SlotID which for which an slot event (token insertion,
+// removal, etc.) occurred.
+type SlotEvent struct {
+ SlotID uint
+}
+
+// Info provides information about the library and hardware used.
+type Info struct {
+ CryptokiVersion Version
+ ManufacturerID string
+ Flags uint
+ LibraryDescription string
+ LibraryVersion Version
+}
+
+/* SlotInfo provides information about a slot. */
+type SlotInfo struct {
+ SlotDescription string // 64 bytes.
+ ManufacturerID string // 32 bytes.
+ Flags uint
+ HardwareVersion Version
+ FirmwareVersion Version
+}
+
+/* TokenInfo provides information about a token. */
+type TokenInfo struct {
+ Label string
+ ManufacturerID string
+ Model string
+ SerialNumber string
+ Flags uint
+ MaxSessionCount uint
+ SessionCount uint
+ MaxRwSessionCount uint
+ RwSessionCount uint
+ MaxPinLen uint
+ MinPinLen uint
+ TotalPublicMemory uint
+ FreePublicMemory uint
+ TotalPrivateMemory uint
+ FreePrivateMemory uint
+ HardwareVersion Version
+ FirmwareVersion Version
+ UTCTime string
+}
+
+/* SesionInfo provides information about a session. */
+type SessionInfo struct {
+ SlotID uint
+ State uint
+ Flags uint
+ DeviceError uint
+}
+
+// Attribute holds an attribute type/value combination.
+type Attribute struct {
+ Type uint
+ Value []byte
+}
+
+// NewAttribute allocates a Attribute and returns a pointer to it.
+// Note that this is merely a convience function, as values returned
+// from the HSM are not converted back to Go values, those are just raw
+// byte slices.
+func NewAttribute(typ uint, x interface{}) *Attribute {
+ // This function nicely transforms *to* an attribute, but there is
+ // no corresponding function that transform back *from* an attribute,
+ // which in PKCS#11 is just an byte array.
+ a := new(Attribute)
+ a.Type = typ
+ if x == nil {
+ return a
+ }
+ switch x.(type) {
+ case bool: // create bbool
+ if x.(bool) {
+ a.Value = []byte{1}
+ break
+ }
+ a.Value = []byte{0}
+ case uint, int:
+ var y uint
+ if _, ok := x.(int); ok {
+ y = uint(x.(int))
+ }
+ if _, ok := x.(uint); ok {
+ y = x.(uint)
+ }
+ // TODO(miek): ugly!
+ switch int(C.Sizeof()) {
+ case 4:
+ a.Value = make([]byte, 4)
+ a.Value[0] = byte(y)
+ a.Value[1] = byte(y >> 8)
+ a.Value[2] = byte(y >> 16)
+ a.Value[3] = byte(y >> 24)
+ case 8:
+ a.Value = make([]byte, 8)
+ a.Value[0] = byte(y)
+ a.Value[1] = byte(y >> 8)
+ a.Value[2] = byte(y >> 16)
+ a.Value[3] = byte(y >> 24)
+ a.Value[4] = byte(y >> 32)
+ a.Value[5] = byte(y >> 40)
+ a.Value[6] = byte(y >> 48)
+ a.Value[7] = byte(y >> 56)
+ }
+ case string:
+ a.Value = []byte(x.(string))
+ case []byte: // just copy
+ a.Value = x.([]byte)
+ case time.Time: // for CKA_DATE
+ a.Value = cDate(x.(time.Time))
+ default:
+ panic("pkcs11: unhandled attribute type")
+ }
+ return a
+}
+
+// cAttribute returns the start address and the length of an attribute list.
+func cAttributeList(a []*Attribute) (C.CK_ATTRIBUTE_PTR, C.CK_ULONG) {
+ if len(a) == 0 {
+ return nil, 0
+ }
+ pa := make([]C.CK_ATTRIBUTE, len(a))
+ for i := 0; i < len(a); i++ {
+ pa[i]._type = C.CK_ATTRIBUTE_TYPE(a[i].Type)
+ if a[i].Value == nil {
+ continue
+ }
+ pa[i].pValue = C.CK_VOID_PTR((&a[i].Value[0]))
+ pa[i].ulValueLen = C.CK_ULONG(len(a[i].Value))
+ }
+ return C.CK_ATTRIBUTE_PTR(&pa[0]), C.CK_ULONG(len(a))
+}
+
+func cDate(t time.Time) []byte {
+ b := make([]byte, 8)
+ year, month, day := t.Date()
+ y := fmt.Sprintf("%4d", year)
+ m := fmt.Sprintf("%02d", month)
+ d1 := fmt.Sprintf("%02d", day)
+ b[0], b[1], b[2], b[3] = y[0], y[1], y[2], y[3]
+ b[4], b[5] = m[0], m[1]
+ b[6], b[7] = d1[0], d1[1]
+ return b
+}
+
+// Mechanism holds an mechanism type/value combination.
+type Mechanism struct {
+ Mechanism uint
+ Parameter []byte
+}
+
+func NewMechanism(mech uint, x interface{}) *Mechanism {
+ m := new(Mechanism)
+ m.Mechanism = mech
+ if x == nil {
+ return m
+ }
+
+ // Add any parameters passed (For now presume always bytes were passed in, is there another case?)
+ m.Parameter = x.([]byte)
+
+ return m
+}
+
+func cMechanismList(m []*Mechanism) (C.CK_MECHANISM_PTR, C.CK_ULONG) {
+ if len(m) == 0 {
+ return nil, 0
+ }
+ pm := make([]C.CK_MECHANISM, len(m))
+ for i := 0; i < len(m); i++ {
+ pm[i].mechanism = C.CK_MECHANISM_TYPE(m[i].Mechanism)
+ if m[i].Parameter == nil {
+ continue
+ }
+ pm[i].pParameter = C.CK_VOID_PTR(&(m[i].Parameter[0]))
+ pm[i].ulParameterLen = C.CK_ULONG(len(m[i].Parameter))
+ }
+ return C.CK_MECHANISM_PTR(&pm[0]), C.CK_ULONG(len(m))
+}
+
+// MechanismInfo provides information about a particular mechanism.
+type MechanismInfo struct {
+ MinKeySize uint
+ MaxKeySize uint
+ Flags uint
+}
diff --git a/README.md b/README.md
index ff701097735..784514a9361 100644
--- a/README.md
+++ b/README.md
@@ -101,11 +101,25 @@ All dependencies are vendorized under the Godeps directory,
both to [make dependency management
easier](https://groups.google.com/forum/m/#!topic/golang-dev/nMWoEAG55v8)
and to [avoid insecure fallback in go
-get](https://github.com/golang/go/issues/9637). To update dependencies:
+get](https://github.com/golang/go/issues/9637).
+
+We need to use the build tag 'pkcs11' to really pull in all our dependencies.
+To do this, you'll need to pull and install this godep branch, which supports
+build tags: https://github.com/tools/godep/pull/117/files. NOTE: If you skip
+this step, godep will delete some of the vendorized depdendencies.
+
+To update dependencies:
```
# Disable insecure fallback by blocking port 80.
sudo /sbin/iptables -A OUTPUT -p tcp --dport 80 -j DROP
+# Fetch godep
+go get https://github.com/tools/godep.git
+# Pull in the tags branch and install
+cd $GOPATH/src/github.com/tools/godep
+git pull https://github.com/jnfeinstein/godep.git jnfeinstein
+go install
+
# Update to the latest version of a dependency. Alternately you can cd to the
# directory under GOPATH and check out a specific revision.
go get -u github.com/cloudflare/cfssl/...
@@ -113,7 +127,7 @@ go get -u github.com/cloudflare/cfssl/...
godep update github.com/cloudflare/cfssl/...
# Save the dependencies, rewriting any internal or external dependencies that
# may have been added.
-godep save -r ./...
+godep save -r -tags pkcs11 ./...
git add Godeps
git commit
# Assuming you had no other iptables rules, re-enable port 80.