Пример #1
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,
	}

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

	return ocsp.CreateResponse(s.issuer, s.responder, template, s.key)
}
Пример #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)
	}

	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)
}
Пример #3
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, int(pkcs11.SlotID))
		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")
		}
		ioutil.WriteFile(outFile, responseBytes, 0666)
	}

	err := app.Run(os.Args)
	cmd.FailOnError(err, "Failed to run application")
}