Esempio n. 1
0
// initialize loads the given PKCS#11 module (shared library) if it is not
// already loaded. It's an error to load a PKCS#11 module multiple times, so we
// maintain a map of loaded modules. Note that there is no facility yet to
// unload a module ("finalize" in PKCS#11 parlance). In general, modules will
// be unloaded at the end of the process.  The only place where you are likely
// to need to explicitly unload a module is if you fork your process after a
// Key has already been created, and the child process also needs to use
// that module.
func initialize(modulePath string) (ctx, error) {
	modulesMu.Lock()
	defer modulesMu.Unlock()
	module, ok := modules[modulePath]
	if ok {
		return module, nil
	}

	newModule := ctx(pkcs11.New(modulePath))

	if newModule == nil {
		return nil, fmt.Errorf("unable to load PKCS#11 module")
	}

	err := newModule.Initialize()
	if err != nil {
		return nil, err
	}

	modules[modulePath] = newModule

	return newModule, nil
}
Esempio n. 2
0
// New instantiates a new handle to a PKCS #11-backed key.
func New(module, tokenLabel, pin, privLabel string, slotID int) (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,
		slotID:     slotID,
		tokenLabel: tokenLabel,
		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: n,
		E: e,
	}

	return
}