Crypto11

repository·master·Indexed 42 days ago

https://github.com/eclipse-keypont/crypto11

A Go library providing standard cryptographic interfaces, such as crypto.Signer and crypto.Decrypter, using a PKCS#11 backend. It enables the use of Hardware Security Modules (HSMs), TPMs, and software simulators like SoftHSM2 for secure operations, including RSA, DSA, and ECDSA key management, as well as AES and DES3 symmetric encryption.

Tokens
11.6K
Snippets
41
Records
51
Agent score
53%

What's inside Crypto11

  1. What features does Crypto11 support?

    master

    Crypto11 implements standard Golang crypto interfaces using a PKCS#11 backend. Supported features include:

    • Key Management: Generation and retrieval of RSA, DSA, and ECDSA keys; importing/retrieval of x509 certificates.
    • Asymmetric Operations:
      • Signing: PKCS#1 v1.5, PKCS#1 PSS, ECDSA, and DSA.
      • Decryption: PKCS#1 v1.5 and PKCS#1 OAEP.
    • Symmetric Operations: AES and DES3 encryption/decryption; HMAC support.
    • Other: Random number generation.

    Important Usage Note: Signing is performed via the crypto.Signer interface, and decryption via the crypto.Decrypter interface. To verify signatures or encrypt messages, you should retrieve the public key and perform those operations in software.

  2. Install Crypto11

    master

    Crypto11 requires Go v1.11 or higher. You can install the library using go get.

    Note: The library uses a two-directive pattern in go.mod (go X.Y.0 for minimum consumer version and toolchain go X.Y.Z for maintainer recommendation) to ensure compatibility with older toolchains while allowing maintainers to use the latest features.

    go get github.com/ThalesGroup/crypto11
  3. How session management works in crypto11

    master

    Crypto11 manages PKCS#11 sessions using a resource pool to allow for efficient reuse and concurrency control.

    1. Session Retrieval: Sessions are retrieved from a pool managed by the Context. If PoolWaitTimeout is configured in the Context configuration, the retrieval will respect that timeout.
    2. Session Lifecycle: When a session is requested, the pool may use resourcePoolFactoryFunc to open a new session on the configured slot with pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION flags.
    3. Session Closure: Sessions implement the pools.Resource interface. When a session is closed via its Close() method, it calls the underlying pkcs11.Ctx.CloseSession. Note that Close() swallows errors to satisfy the interface requirements.
  4. Configure Crypto11 via JSON

    master

    Crypto11 can be configured programmatically using the Config struct or via a JSON configuration file. The JSON file is a direct representation of the Config struct.

    Common configuration keys:

    • Path: Path to the PKCS#11 vendor library (e.g., .so or .dll).
    • TokenLabel: The CKA_LABEL of the token you wish to use.
    • Pin: The password for the CKU_USER user.
    • TokenSerial: (Alternative to TokenLabel) The serial number of the token.
    • UseGCMIVFromHSM: If true, the IV for GCM mechanisms is generated by the HSM.
    {
      "Path": "/usr/lib/softhsm/libsofthsm2.so",
      "TokenLabel": "token1",
      "Pin": "password"
    }
  5. Understand crypto11 session management and concurrency

    master

    PKCS#11 session handles are not thread-safe. crypto11 handles this by managing a dynamic pool of read-write sessions:

    1. Persistent Session: When a Context is created, a single session is kept open and logged in. This ensures object handles and login status remain valid for the lifetime of the Context.
    2. Session Pool: The Context maintains a pool of sessions (up to MaxSessions).
    3. Transient Usage: Each cryptographic operation (like signing or decrypting) transiently borrows a session from the pool, uses it exclusively, and returns it when finished. This allows the Signer interface to be used safely from multiple goroutines.
  6. Use SymmetricCipher for key generation

    master

    The SymmetricCipher struct defines the capabilities and parameters of a symmetric algorithm. It is used as an argument to key generation functions.

    Key fields include:

    • GenParams: A slice of SymmetricGenParams containing valid KeyType (CKK_...) and GenMech (CKM_...) pairs. The library iterates through these if the first one fails due to vendor-specific constraints.
    • BlockSize: The block size in bytes.
    • Encrypt / MAC: Boolean flags indicating if encryption or MAC operations are supported.
    • ECBMech, CBCMech, CBCPKCSMech, GCMMech: The PKCS#11 mechanism constants for various modes of operation.
  7. Use BlockModeCloser for resource management

    master

    The BlockModeCloser interface extends cipher.BlockMode by adding a Close() method. Because block cipher operations in crypto11 acquire persistent resources (like PKCS#11 sessions), you should use the Closer variants of the constructors to ensure these resources are explicitly released.

    If you use the standard cipher.BlockMode constructors, resources are released eventually via a finalizer, but this can lead to resource exhaustion if not managed. If you must use the standard cipher.BlockMode and encounter resource issues, calling runtime.GC() may help, but using the Closer interface is the preferred pattern.

    type BlockModeCloser interface {
    	cipher.BlockMode
    	Close() // releases resources associated with the block mode.
    }
  8. Manage SecretKey objects

    master

    A SecretKey represents a loaded symmetric key object from the HSM.

    Capabilities:

    • Interface Implementation: *SecretKey implements the cipher.Block interface from the Go standard library. This allows you to pass a SecretKey directly into standard library functions like cipher.NewCBCEncrypter(key, iv).
    • Deletion: Call key.Delete() to remove the key from the hardware token.

    Performance Note: For bulk operations, do not use the cipher.Block interface directly as it is inefficient for HSM calls. Instead, use the specialized NewCBCEncrypterCloser, NewCBCEncrypter, or NewCBC functions provided within the crypto11 package.

    // Using SecretKey with standard library (inefficient for bulk)
    block, err := key.Encryptor() // hypothetical usage based on cipher.Block
    
    // Deleting a key
    err := key.Delete()
  9. Use Signer and Decrypter interfaces for keys

    master

    Keys retrieved from the token implement standard Go crypto interfaces.

    • DSA, RSA, and ECDSA keys: Implement the Signer interface.
    • RSA keys: Also implement the crypto.Decrypter interface.

    Note on RSA Decryption: When using FindKeyPair to retrieve RSA keys, you must use a type assertion to access decryption methods. Assert to either crypto.Decrypter or SignerDecrypter depending on your needs.

  10. Initialize a PKCS#11 Context

    master

    To access cryptographic keys from a PKCS#11 token, you must create a Context object. You can do this using Configure with a Config struct or ConfigureFromFile with a JSON configuration file.

    When configuring, you must specify exactly one way to identify your token: TokenSerial, TokenLabel, or SlotNumber.

    Once a Context is created, it manages a pool of sessions to allow concurrent operations while adhering to PKCS#11's single-threaded session requirements. Always call Close() on the Context when finished to release resources and unload the library.

    import "github.com/thales-e-security/crypto11"
    
    config := &crypto11.Config{
        Path:       "/path/to/pkcs11/lib.so",
        TokenLabel: "MyToken",
        Pin:        "1234",
    }
    
    ctx, err := crypto11.Configure(config)
    if err != nil {
        panic(err)
    }
    defer ctx.Close()
  11. Performance and Limitations

    master

    Symmetric Crypto Performance

    Symmetric crypto support via cipher.Block is very slow. For significantly better performance (over 400x faster), use the BlockModeCloser API. Note that when using BlockModeCloser, you must call the Close() method, which is not part of the standard cipher.BlockMode interface.

    RSA Decryption Limitation

    The PKCS1v15DecryptOptions.SessionKeyLen field is not implemented. Setting this to a non-zero value will return an error to ensure constant-time behavior guarantees.