func main() { issuerFile := flag.String("issuer", "", "Issuer certificate (PEM)") responderFile := flag.String("responder", "", "OCSP responder certificate (DER)") targetFile := flag.String("target", "", "Certificate whose status is being reported (PEM)") pkcs11File := flag.String("pkcs11", "", pkcs11Usage) outFile := flag.String("out", "", "File to which the OCSP response will be written") thisUpdateString := flag.String("thisUpdate", "", "Time for ThisUpdate field, RFC3339 format (e.g. 2016-09-02T00:00:00Z)") nextUpdateString := flag.String("nextUpdate", "", "Time for NextUpdate field, RFC3339 format") status := flag.Int("status", 0, "Status for response (0 = good, 1 = revoked)") flag.Usage = func() { fmt.Fprint(os.Stderr, usage) flag.PrintDefaults() } flag.Parse() if len(*outFile) == 0 { cmd.FailOnError(fmt.Errorf("No output file provided"), "") } thisUpdate, err := time.Parse(time.RFC3339, *thisUpdateString) cmd.FailOnError(err, "Parsing thisUpdate flag") nextUpdate, err := time.Parse(time.RFC3339, *nextUpdateString) cmd.FailOnError(err, "Parsing nextUpdate flag") issuer, responder, target, pkcs11, err := readFiles(*issuerFile, *responderFile, *targetFile, *pkcs11File) cmd.FailOnError(err, "Failed to read files") // Instantiate the private key from PKCS11 priv, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel) cmd.FailOnError(err, "Failed to load PKCS#11 key") // Populate the remaining fields in the template template := ocsp.Response{ SerialNumber: target.SerialNumber, Certificate: responder, Status: *status, ThisUpdate: thisUpdate, NextUpdate: nextUpdate, } if !core.KeyDigestEquals(responder.PublicKey, priv.Public()) { cmd.FailOnError(fmt.Errorf("PKCS#11 pubkey does not match pubkey "+ "in responder certificate"), "loading keys") } // Sign the OCSP response responseBytes, err := ocsp.CreateResponse(issuer, responder, template, priv) cmd.FailOnError(err, "Failed to sign OCSP response") _, err = ocsp.ParseResponse(responseBytes, nil) cmd.FailOnError(err, "Failed to parse signed response") responseBytesBase64 := base64.StdEncoding.EncodeToString(responseBytes) + "\n" // Write the OCSP response to stdout err = ioutil.WriteFile(*outFile, []byte(responseBytesBase64), 0666) cmd.FailOnError(err, "Failed to write output file") }
func loadSigner(issuerConfig cmd.IssuerConfig) (crypto.Signer, error) { if issuerConfig.File != "" { keyBytes, err := ioutil.ReadFile(issuerConfig.File) if err != nil { return nil, fmt.Errorf("Could not read key file %s", issuerConfig.File) } signer, err := helpers.ParsePrivateKeyPEM(keyBytes) if err != nil { return nil, err } return signer, nil } var pkcs11Config *pkcs11key.Config if issuerConfig.ConfigFile != "" { contents, err := ioutil.ReadFile(issuerConfig.ConfigFile) if err != nil { return nil, err } pkcs11Config = new(pkcs11key.Config) err = json.Unmarshal(contents, pkcs11Config) if err != nil { return nil, err } } else { pkcs11Config = issuerConfig.PKCS11 } if pkcs11Config.Module == "" || pkcs11Config.TokenLabel == "" || pkcs11Config.PIN == "" || pkcs11Config.PrivateKeyLabel == "" { return nil, fmt.Errorf("Missing a field in pkcs11Config %#v", pkcs11Config) } return pkcs11key.New(pkcs11Config.Module, pkcs11Config.TokenLabel, pkcs11Config.PIN, pkcs11Config.PrivateKeyLabel) }
func main() { app := cli.NewApp() app.Name = "single-ocsp" app.Usage = `Creates a single OCSP response. According to the BRs, the OCSP responses for intermediate certificate must be issued once per year. So there's a need to issue OCSP responses for these certificates, but it doesn't make sense to use all the infrastructure that the "ocsp-updater" tool requires. This tool allows an administrator to manually generate an OCSP response for an intermediate certificate. ` app.Version = cmd.Version() app.Author = "Boulder contributors" app.Email = "*****@*****.**" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "issuer", Usage: "Issuer certificate (DER)", }, cli.StringFlag{ Name: "responder", Usage: "OCSP responder certificate (DER)", }, cli.StringFlag{ Name: "target", Usage: "Certificate whose status is being reported (DER)", }, cli.StringFlag{ Name: "template", Usage: `OCSP template file (JSON), e.g.: { "Status": 0, // Good "ThisUpdate": "2015-08-26T00:00:00Z", "NextUpdate": "2016-08-26T00:00:00Z" } { "Status": 1, // Revoked "ThisUpdate": "2015-08-26T00:00:00Z", "NextUpdate": "2016-08-26T00:00:00Z", "RevokedAt": "2015-08-20T00:00:00Z", "RevocationReason": 1 // Key compromise } `, }, cli.StringFlag{ Name: "pkcs11", Usage: `PKCS#11 configuration (JSON), e.g.: { "Module": "/Library/OpenSC/lib/opensc-pkcs11.so", "Token": "Yubico Yubikey NEO CCID", "Label": "PIV AUTH key", "PIN": "123456" } `, }, cli.StringFlag{ Name: "out", Usage: "File to which the OCSP response will be written", }, } app.Action = func(c *cli.Context) { issuer, responder, target, template, pkcs11, err := readFiles(c) cmd.FailOnError(err, "Failed to read files") // Instantiate the private key from PKCS11 priv, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel) cmd.FailOnError(err, "Failed to load PKCS#11 key") // Populate the remaining fields in the template template.SerialNumber = target.SerialNumber template.Certificate = responder // Sign the OCSP response responseBytes, err := ocsp.CreateResponse(issuer, responder, template, priv) cmd.FailOnError(err, "Failed to sign OCSP response") // Write the OCSP response to stdout outFile := c.GlobalString("out") if len(outFile) == 0 { cmd.FailOnError(fmt.Errorf(""), "No output file provided") } err = ioutil.WriteFile(outFile, responseBytes, 0666) cmd.FailOnError(err, "Failed to write output file") } err := app.Run(os.Args) cmd.FailOnError(err, "Failed to run application") }
func main() { // Instantiate the PKCS11 key var pkcs11 struct { Module string TokenLabel string PIN string PrivateKeyLabel string } pkcs11Bytes, err := ioutil.ReadFile(pkcs11FileName) panicOnError(err) err = json.Unmarshal(pkcs11Bytes, &pkcs11) panicOnError(err) p11key, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel) panicOnError(err) // All of the certificates start and end at the same time notBefore := time.Now().Truncate(time.Hour).Add(-1 * time.Hour) notAfter := notBefore.AddDate(1, 0, 0) // Make some keys for the CA and EE caKey, err := rsa.GenerateKey(rand.Reader, 2048) panicOnError(err) eeKey, err := rsa.GenerateKey(rand.Reader, 2048) panicOnError(err) // Make CA cert with ephemeral key template := &x509.Certificate{ NotBefore: notBefore, NotAfter: notAfter, Subject: pkix.Name{CommonName: "Happy Hacker Fake CA"}, BasicConstraintsValid: true, IsCA: true, } caCert := makeCert(template, template, caKey.Public(), caKey) // Make EE cert with ephemeral key and print template = &x509.Certificate{ NotBefore: notBefore, NotAfter: notAfter, Subject: pkix.Name{CommonName: "example.com"}, } eeCert := makeCert(template, caCert, eeKey.Public(), caKey) // Make OCSP responder cert with PKCS#11 key template = &x509.Certificate{ NotBefore: notBefore, NotAfter: notAfter, Subject: pkix.Name{CommonName: "Happy Hacker OCSP Signer"}, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageOCSPSigning}, } ocspCert := makeCert(template, caCert, p11key.Public(), caKey) // Write out all the certs in DER and PEM err = ioutil.WriteFile(caCertFileName, caCert.Raw, 0666) panicOnError(err) err = ioutil.WriteFile(eeCertFileName, eeCert.Raw, 0666) panicOnError(err) err = ioutil.WriteFile(ocspCertFileName, ocspCert.Raw, 0666) panicOnError(err) err = ioutil.WriteFile(caCertFileNamePEM, toPEM(caCert), 0666) panicOnError(err) err = ioutil.WriteFile(eeCertFileNamePEM, toPEM(eeCert), 0666) panicOnError(err) err = ioutil.WriteFile(ocspCertFileNamePEM, toPEM(ocspCert), 0666) panicOnError(err) }