Exemple #1
0
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")
}
Exemple #2
0
// Sign is used with an OCSP signer to request the issuance of
// an OCSP response.
func (s StandardSigner) Sign(req SignRequest) ([]byte, error) {
	if req.Certificate == nil {
		return nil, cferr.New(cferr.OCSPError, cferr.ReadFailed)
	}

	// Verify that req.Certificate is issued under s.issuer
	if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 {
		return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
	}
	if req.Certificate.CheckSignatureFrom(s.issuer) != nil {
		return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
	}

	// Round thisUpdate times down to the nearest hour
	thisUpdate := time.Now().Truncate(time.Hour)
	nextUpdate := thisUpdate.Add(s.interval)

	status, ok := StatusCode[req.Status]
	if !ok {
		return nil, cferr.New(cferr.OCSPError, cferr.InvalidStatus)
	}

	// If the OCSP responder is the same as the issuer, there is no need to
	// include any certificate in the OCSP response, which decreases the byte size
	// of OCSP responses dramatically.
	certificate := s.responder
	if s.issuer == s.responder || bytes.Equal(s.issuer.Raw, s.responder.Raw) {
		certificate = nil
	}

	template := ocsp.Response{
		Status:          status,
		SerialNumber:    req.Certificate.SerialNumber,
		ThisUpdate:      thisUpdate,
		NextUpdate:      nextUpdate,
		Certificate:     certificate,
		ExtraExtensions: req.Extensions,
		IssuerHash:      req.IssuerHash,
	}

	if status == ocsp.Revoked {
		template.RevokedAt = req.RevokedAt
		template.RevocationReason = req.Reason
	}

	return ocsp.CreateResponse(s.issuer, s.responder, template, s.key)
}
Exemple #3
0
// Sign is used with an OCSP signer to request the issuance of
// an OCSP response.
func (s StandardSigner) Sign(req SignRequest) ([]byte, error) {
	if req.Certificate == nil {
		return nil, cferr.New(cferr.OCSPError, cferr.ReadFailed)
	}

	// Verify that req.Certificate is issued under s.issuer
	if bytes.Compare(req.Certificate.RawIssuer, s.issuer.RawSubject) != 0 {
		return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
	}
	if req.Certificate.CheckSignatureFrom(s.issuer) != nil {
		return nil, cferr.New(cferr.OCSPError, cferr.IssuerMismatch)
	}

	// Round thisUpdate times down to the nearest hour
	thisUpdate := time.Now().Truncate(time.Hour)
	nextUpdate := thisUpdate.Add(s.interval)

	status, ok := statusCode[req.Status]
	if !ok {
		return nil, cferr.New(cferr.OCSPError, cferr.InvalidStatus)
	}

	template := ocsp.Response{
		Status:       status,
		SerialNumber: req.Certificate.SerialNumber,
		ThisUpdate:   thisUpdate,
		NextUpdate:   nextUpdate,
		Certificate:  s.responder,
	}

	if status == ocsp.Revoked {
		template.RevokedAt = req.RevokedAt
		template.RevocationReason = req.Reason
	}

	return ocsp.CreateResponse(s.issuer, s.responder, template, s.key)
}
Exemple #4
0
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")
}