Пример #1
0
// 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
}
Пример #2
0
// Sign returns a signature for a given signature request
func sign(ctx IPKCS11Ctx, session pkcs11.SessionHandle, pkcs11KeyID []byte, passRetriever passphrase.Retriever, payload []byte) ([]byte, error) {
	err := login(ctx, session, passRetriever, pkcs11.CKU_USER, USER_PIN)
	if err != nil {
		return nil, fmt.Errorf("error logging in: %v", err)
	}
	defer ctx.Logout(session)

	// Define the ECDSA Private key template
	class := pkcs11.CKO_PRIVATE_KEY
	privateKeyTemplate := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_CLASS, class),
		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_ECDSA),
		pkcs11.NewAttribute(pkcs11.CKA_ID, pkcs11KeyID),
	}

	if err := ctx.FindObjectsInit(session, privateKeyTemplate); err != nil {
		logrus.Debugf("Failed to init find objects: %s", err.Error())
		return nil, err
	}
	obj, _, err := ctx.FindObjects(session, 1)
	if err != nil {
		logrus.Debugf("Failed to find objects: %v", err)
		return nil, err
	}
	if err = ctx.FindObjectsFinal(session); err != nil {
		logrus.Debugf("Failed to finalize find objects: %s", err.Error())
		return nil, err
	}
	if len(obj) != 1 {
		return nil, errors.New("length of objects found not 1")
	}

	var sig []byte
	err = ctx.SignInit(
		session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)}, obj[0])
	if err != nil {
		return nil, err
	}

	// Get the SHA256 of the payload
	digest := sha256.Sum256(payload)

	if (yubikeyKeymode & KeymodeTouch) > 0 {
		touchToSignUI()
		defer touchDoneCallback()
	}
	// a call to Sign, whether or not Sign fails, will clear the SignInit
	sig, err = ctx.Sign(session, digest[:])
	if err != nil {
		logrus.Debugf("Error while signing: %s", err)
		return nil, err
	}

	if sig == nil {
		return nil, errors.New("Failed to create signature")
	}
	return sig[:], nil
}
Пример #3
0
// Sign performs a signature using the PKCS #11 key.
func (ps *Key) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) {
	ps.sessionMu.Lock()
	defer ps.sessionMu.Unlock()
	if ps.session == nil {
		return nil, errors.New("Session was nil")
	}

	// When the alwaysAuthenticate bit is true (e.g. on a Yubikey NEO in PIV mode),
	// each Sign has to include a Logout/Login, or the next Sign request will get
	// CKR_USER_NOT_LOGGED_IN. This is very slow, but on the NEO it's not possible
	// to clear the CKA_ALWAYS_AUTHENTICATE bit, so this is the only available
	// workaround.
	// Also, since logged in / logged out is application state rather than session
	// state, we take a global lock while we do the logout and login, and during
	// the signing.
	if ps.alwaysAuthenticate {
		modulesMu.Lock()
		defer modulesMu.Unlock()
		if err := ps.module.Logout(*ps.session); err != nil {
			return nil, fmt.Errorf("logout: %s", err)
		}
		if err = ps.module.Login(*ps.session, pkcs11.CKU_USER, ps.pin); err != nil {
			return nil, fmt.Errorf("login: %s", err)
		}
	}

	// 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...)

	// Perform the sign operation
	err = ps.module.SignInit(*ps.session, mechanism, ps.privateKeyHandle)
	if err != nil {
		return nil, fmt.Errorf("sign init: %s", err)
	}

	signature, err = ps.module.Sign(*ps.session, signatureInput)
	if err != nil {
		return nil, fmt.Errorf("sign: %s", err)
	}
	return
}
Пример #4
0
// Sign returns a signature for a given signature request
func (s *RSAHardwareCryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signature, error) {
	signatures := make([]data.Signature, 0, len(keyIDs))
	for _, keyid := range keyIDs {
		privateKey, present := s.keys[keyid]
		if !present {
			// We skip keys that aren't found
			continue
		}

		priv := privateKey.PKCS11ObjectHandle()
		var sig []byte
		var err error
		for i := 0; i < 3; i++ {
			s.context.SignInit(s.session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA256_RSA_PKCS, nil)}, priv)

			sig, err = s.context.Sign(s.session, payload)
			if err != nil {
				log.Printf("Error while signing: %s", err)
				continue
			}

			digest := sha256.Sum256(payload)
			pub, err := x509.ParsePKIXPublicKey(privateKey.Public())
			if err != nil {
				log.Printf("Failed to parse public key: %s\n", err)
				return nil, err
			}

			rsaPub, ok := pub.(*rsa.PublicKey)
			if !ok {
				log.Printf("Value returned from ParsePKIXPublicKey was not an RSA public key")
				return nil, err
			}

			err = rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, digest[:], sig)
			if err != nil {
				log.Printf("Failed verification. Retrying: %s", err)
				continue
			}
			break
		}

		if sig == nil {
			return nil, errors.New("Failed to create signature")
		}

		signatures = append(signatures, data.Signature{
			KeyID:     keyid,
			Method:    data.RSAPKCS1v15Signature,
			Signature: sig[:],
		})
	}

	return signatures, nil
}
Пример #5
0
func (s *signer) sign(input []byte) ([]byte, error) {
	mechanism := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}
	if err := s.context.SignInit(s.session, mechanism, s.privateKey); err != nil {
		log.Fatalf("SignInit: %s", err)
	}

	signed, err := s.context.Sign(s.session, input)
	if err != nil {
		log.Fatalf("Sign: %s", err)
	}
	return signed, nil
}
Пример #6
0
// Sign returns a signature for a given signature request
func (s *RSASigner) Sign(request *pb.SignatureRequest) (*pb.Signature, error) {
	priv := s.privateKey.PKCS11ObjectHandle()
	var sig []byte
	var err error
	for i := 0; i < 3; i++ {
		//TODO(mccauley): move this to RSA OAEP
		s.context.SignInit(s.session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA256_RSA_PKCS, nil)}, priv)

		sig, err = s.context.Sign(s.session, request.Content)
		if err != nil {
			log.Printf("Error while signing: %s", err)
			continue
		}

		// (diogo): XXX: Remove this before shipping
		digest := sha256.Sum256(request.Content)
		pub, err := x509.ParsePKIXPublicKey(s.privateKey.Public())
		if err != nil {
			log.Printf("Failed to parse public key: %s\n", err)
			return nil, err
		}

		rsaPub, ok := pub.(*rsa.PublicKey)
		if !ok {
			log.Printf("Value returned from ParsePKIXPublicKey was not an RSA public key")
			return nil, err
		}

		err = rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, digest[:], sig)
		if err != nil {
			log.Printf("Failed verification. Retrying: %s", err)
			continue
		}
		break
	}

	// (diogo): XXX: END Area of removal
	if sig == nil {
		return nil, errors.New("Failed to create signature")
	}

	returnSig := &pb.Signature{KeyInfo: &pb.KeyInfo{KeyID: &pb.KeyID{ID: s.privateKey.ID()}, Algorithm: &pb.Algorithm{Algorithm: s.privateKey.Algorithm().String()}}, Content: sig[:]}
	log.Printf("[Notary-signer Server] Signature request JSON: %s , response: %s", string(request.Content), returnSig)
	return returnSig, nil
}
Пример #7
0
// Create creates a key and returns its public components
func (s *RSAHardwareCryptoService) Create(role, algo string) (data.PublicKey, error) {
	// For now generate random labels for keys
	// (diogo): add link between keyID and label in database so we can support multiple keys
	randomLabel := make([]byte, 32)
	_, err := rand.Read(randomLabel)
	if err != nil {
		return nil, errors.New("Could not generate a random key label.")
	}

	// Set the public key template
	// CKA_TOKEN: Guarantees key persistence in hardware
	// CKA_LABEL: Identifies this specific key inside of the HSM
	publicKeyTemplate := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, []byte{3}),
		pkcs11.NewAttribute(pkcs11.CKA_MODULUS_BITS, 2048),
		pkcs11.NewAttribute(pkcs11.CKA_LABEL, string(randomLabel)),
	}
	privateKeyTemplate := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
		pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
		pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
		pkcs11.NewAttribute(pkcs11.CKA_LABEL, string(randomLabel)),
	}

	// Generate a new RSA private/public keypair inside of the HSM
	pub, priv, err := s.context.GenerateKeyPair(s.session,
		[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
		publicKeyTemplate, privateKeyTemplate)
	if err != nil {
		return nil, errors.New("Could not generate a new key inside of the HSM.")
	}

	// (diogo): This template is used for the GetAttribute
	template := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
		pkcs11.NewAttribute(pkcs11.CKA_MODULUS_BITS, nil),
		pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
	}

	// Retrieve the public-key material to be able to create a new HSMRSAKey
	attr, err := s.context.GetAttributeValue(s.session, pub, template)
	if err != nil {
		return nil, errors.New("Failed to get Attribute value.")
	}

	// We're going to store the elements of the RSA Public key, exponent and Modulus inside of exp and mod
	var exp int
	mod := big.NewInt(0)

	// Iterate through all the attributes of this key and saves CKA_PUBLIC_EXPONENT and CKA_MODULUS. Removes ordering specific issues.
	for _, a := range attr {
		if a.Type == pkcs11.CKA_PUBLIC_EXPONENT {
			exp, _ = readInt(a.Value)
		}

		if a.Type == pkcs11.CKA_MODULUS {
			mod.SetBytes(a.Value)
		}
	}

	rsaPublicKey := rsa.PublicKey{N: mod, E: exp}
	// Using x509 to Marshal the Public key into der encoding
	pubBytes, err := x509.MarshalPKIXPublicKey(&rsaPublicKey)
	if err != nil {
		return nil, errors.New("Failed to Marshal public key.")
	}

	// (diogo): Ideally I would like to return base64 PEM encoded public keys to the client
	k := keys.NewHSMRSAKey(pubBytes, priv)

	keyID := k.ID()

	s.keys[keyID] = k

	return k, nil
}
Пример #8
0
func generate_pkcs11keypair() {
	config := configure()
	p := pkcs11.New(config.module)
	if p == nil {
		fmt.Printf("Could not initialize pkcs11 with module %s, exiting.\n", config.module)
		os.Exit(1)
	}
	p.Initialize()
	defer p.Destroy()
	defer p.Finalize()

	var used_slot uint = 0
	slots, _ := p.GetSlotList(true)

	for _, slot_id := range slots {
		if slot_id == config.slot_id {
			used_slot = config.slot_id
		}
	}
	fmt.Printf("Wanted slot id %v ", config.slot_id)
	fmt.Printf("and got slot id %v.\n", used_slot)
	session, err := p.OpenSession(used_slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
	if err != nil {
		fmt.Printf("Could not open session. Error: %v\n", err)
		os.Exit(1)
	}
	defer p.CloseSession(session)
	p.Login(session, pkcs11.CKU_USER, config.user_pin)
	defer p.Logout(session)

	info, err := p.GetInfo()
	if err != nil {
		fmt.Printf("GetInfo failed: %v\n", err)
		os.Exit(1)
	} else {
		fmt.Printf("HSM Info:\nManufacturer ID %v\nFlags: %v\nLibrary Description: %v\nLibrary Version: %v.\n",
			info.ManufacturerID, info.Flags, info.LibraryDescription, info.LibraryVersion)
	}
	// var pub_exponent int = 0x010001

	publicKeyTemplate := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKO_PUBLIC_KEY),
		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
		pkcs11.NewAttribute(pkcs11.CKA_MODULUS_BITS, config.rsa_size),
		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, []byte{3}),
		pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
		pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
		pkcs11.NewAttribute(pkcs11.CKA_WRAP, true),
		pkcs11.NewAttribute(pkcs11.CKA_LABEL, config.key_label),
		pkcs11.NewAttribute(pkcs11.CKA_ID, config.key_id),
		pkcs11.NewAttribute(pkcs11.CKA_SUBJECT, "/CN=Harald Wagener"),
	}
	privateKeyTemplate := []*pkcs11.Attribute{
		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKO_PRIVATE_KEY),
		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
		pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
		pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
		pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
		pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
		pkcs11.NewAttribute(pkcs11.CKA_UNWRAP, true),
		pkcs11.NewAttribute(pkcs11.CKA_LABEL, config.key_label),
		pkcs11.NewAttribute(pkcs11.CKA_ID, config.key_id),
		pkcs11.NewAttribute(pkcs11.CKA_SUBJECT, "/CN=Harald Wagener"),
	}
	pub, priv, err := p.GenerateKeyPair(session,
		[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
		publicKeyTemplate, privateKeyTemplate)
	if err != nil {
		fmt.Printf("Error generating key pair: %v\n", err)
		os.Exit(1)
	} else {
		fmt.Printf("Key pair generated:\nPublic Key: %v\nPrivate Key: %v\n", pub, priv)
		os.Exit(0)
	}
}