Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
Loading...
Searching...
No Matches
cipher.c File Reference

Default cipher driver implementation (OpenSSL-backed). More...

#include "csilk/drivers/cipher.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <stdint.h>
#include <string.h>
Include dependency graph for cipher.c:

Macros

#define RSA_PSS_SALTLEN_DIGEST   -1
 

Functions

static int default_symmetric_encrypt (const uint8_t *key, size_t key_len, const uint8_t *plaintext, size_t plaintext_len, const uint8_t *iv, size_t iv_len, uint8_t *ciphertext, size_t *ciphertext_len, uint8_t *tag, size_t tag_len)
 AES-256-GCM symmetric encryption.
 
static int default_symmetric_decrypt (const uint8_t *key, size_t key_len, const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *plaintext, size_t *plaintext_len)
 AES-256-GCM symmetric decryption with authentication tag verification.
 
static int default_generate_keypair (char *public_key, size_t *pub_len, char *private_key, size_t *priv_len)
 Generate an RSA keypair and return PEM-encoded public and private keys.
 
static EVP_PKEY * pem_to_pkey (const char *pem, size_t len)
 Internal: parse a PEM-encoded public key into an EVP_PKEY handle.
 
static EVP_PKEY * pem_to_privkey (const char *pem, size_t len)
 Internal: parse a PEM-encoded private key into an EVP_PKEY handle.
 
static int default_asymmetric_encrypt (const char *public_key, size_t pub_len, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t *ciphertext_len)
 RSA-OAEP asymmetric encryption.
 
static int default_asymmetric_decrypt (const char *private_key, size_t priv_len, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t *plaintext_len)
 RSA-OAEP asymmetric decryption.
 
static int default_sign (const char *private_key, size_t priv_len, const uint8_t *data, size_t data_len, uint8_t *signature, size_t *sig_len)
 RSA-PSS digital signature generation.
 
static int default_verify (const char *public_key, size_t pub_len, const uint8_t *data, size_t data_len, const uint8_t *signature, size_t sig_len)
 RSA-PSS digital signature verification.
 

Variables

csilk_cipher_driver_t csilk_default_cipher_driver
 Default cipher driver vtable mapping all operations to the OpenSSL-backed implementations above.
 

Detailed Description

Default cipher driver implementation (OpenSSL-backed).

Architecture: Provides a concrete implementation of the abstract csilk_cipher_driver_t interface using OpenSSL EVP primitives. This module is the default driver installed by the cipher subsystem. All functions are stateless and thread-safe (OpenSSL is expected to have been configured with locking callbacks at process start).

Supported operations:

  • AES-256-GCM symmetric encrypt/decrypt (authenticated encryption)
  • RSA-OAEP asymmetric encrypt/decrypt (with SHA-256)
  • RSA-PSS sign/verify (with SHA-256)
  • RSA keypair generation (PEM-encoded)

Macro Definition Documentation

◆ RSA_PSS_SALTLEN_DIGEST

#define RSA_PSS_SALTLEN_DIGEST   -1

Function Documentation

◆ default_asymmetric_decrypt()

static int default_asymmetric_decrypt ( const char *  private_key,
size_t  priv_len,
const uint8_t *  ciphertext,
size_t  ciphertext_len,
uint8_t *  plaintext,
size_t *  plaintext_len 
)
static

RSA-OAEP asymmetric decryption.

Algorithm:

  1. Parse the PEM private key into an EVP_PKEY.
  2. Create an EVP_PKEY_CTX for decryption.
  3. Configure RSA-OAEP padding with SHA-256 (matching encrypt).
  4. Call EVP_PKEY_decrypt to recover the plaintext.
Parameters
private_keyPEM-encoded RSA private key.
priv_lenLength of private_key string.
ciphertextInput ciphertext (must equal RSA key size).
ciphertext_lenLength of ciphertext.
plaintext[out] Output buffer for decrypted data.
plaintext_len[in/out] Input: buffer capacity. Output: plaintext len.
Returns
0 on success, -1 on failure (wrong key, tampered data, or params).

◆ default_asymmetric_encrypt()

static int default_asymmetric_encrypt ( const char *  public_key,
size_t  pub_len,
const uint8_t *  plaintext,
size_t  plaintext_len,
uint8_t *  ciphertext,
size_t *  ciphertext_len 
)
static

RSA-OAEP asymmetric encryption.

Algorithm:

  1. Parse the PEM public key into an EVP_PKEY.
  2. Create an EVP_PKEY_CTX for encryption.
  3. Configure RSA-OAEP padding with SHA-256 for both the OAEP hash and the MGF1 mask generation function.
  4. Call EVP_PKEY_encrypt to produce the ciphertext.
Parameters
public_keyPEM-encoded RSA public key.
pub_lenLength of public_key string.
plaintextInput plaintext (max ~190 bytes for 2048-bit RSA).
plaintext_lenLength of plaintext.
ciphertext[out] Output buffer for encrypted data.
ciphertext_len[in/out] Input: buffer capacity. Output: ciphertext len.
Returns
0 on success, -1 on failure.
Note
The ciphertext length will be equal to the RSA key size (e.g., 256 bytes for a 2048-bit key).

◆ default_generate_keypair()

static int default_generate_keypair ( char *  public_key,
size_t *  pub_len,
char *  private_key,
size_t *  priv_len 
)
static

Generate an RSA keypair and return PEM-encoded public and private keys.

Algorithm:

  1. Create an EVP_PKEY_CTX for RSA key generation.
  2. Initialize keygen with CSILK_RSA_KEY_BITS (2048 or 4096).
  3. Generate the keypair.
  4. Write the public key to a memory BIO in PEM format.
  5. Write the private key (unencrypted) to a memory BIO in PEM format.
  6. Copy the PEM strings into the caller's buffers.
Parameters
public_key[out] Buffer for PEM-encoded public key.
pub_len[in/out] Input: buffer capacity. Output: actual key length including null terminator.
private_key[out] Buffer for PEM-encoded private key.
priv_len[in/out] Input: buffer capacity. Output: actual key length including null terminator.
Returns
0 on success, -1 on failure (allocation, keygen, or buffer too small).
Note
If the output buffers are too small, the function sets *pub_len and *priv_len to the required sizes and returns -1.

◆ default_sign()

static int default_sign ( const char *  private_key,
size_t  priv_len,
const uint8_t *  data,
size_t  data_len,
uint8_t *  signature,
size_t *  sig_len 
)
static

RSA-PSS digital signature generation.

Algorithm:

  1. Parse the PEM private key into an EVP_PKEY.
  2. Create an EVP_MD_CTX and initialize for signing with SHA-256.
  3. Configure RSA-PSS padding with salt length equal to digest length.
  4. Call EVP_DigestSign which internally hashes the data and signs.
Parameters
private_keyPEM-encoded RSA private key.
priv_lenLength of private_key string.
dataInput data to sign.
data_lenLength of data.
signature[out] Output buffer for the signature.
sig_len[in/out] Input: buffer capacity. Output: signature len.
Returns
0 on success, -1 on failure.

◆ default_symmetric_decrypt()

static int default_symmetric_decrypt ( const uint8_t *  key,
size_t  key_len,
const uint8_t *  ciphertext,
size_t  ciphertext_len,
const uint8_t *  iv,
size_t  iv_len,
const uint8_t *  tag,
size_t  tag_len,
uint8_t *  plaintext,
size_t *  plaintext_len 
)
static

AES-256-GCM symmetric decryption with authentication tag verification.

Algorithm:

  1. Create an EVP_CIPHER_CTX for AES-256-GCM.
  2. Initialize for decryption with EVP_DecryptInit_ex.
  3. Feed ciphertext via EVP_DecryptUpdate to produce plaintext.
  4. Set the expected authentication tag via EVP_CTRL_GCM_SET_TAG.
  5. Finalize with EVP_DecryptFinal_ex — this fails if the tag does not match (tampered ciphertext or wrong key).
Parameters
key256-bit AES key (must be 32 bytes).
key_lenMust be 32.
ciphertextInput encrypted data.
ciphertext_lenLength of ciphertext.
iv96-bit IV (must be 12 bytes).
iv_lenMust be 12.
tag128-bit authentication tag to verify (16 bytes).
tag_lenMust be 16.
plaintext[out] Output buffer for decrypted data.
plaintext_len[out] Receives the plaintext length.
Returns
0 on success, -1 on authentication failure or invalid params.
Note
A return of -1 does NOT distinguish between "wrong key", "tampered ciphertext", or "invalid parameters".

◆ default_symmetric_encrypt()

static int default_symmetric_encrypt ( const uint8_t *  key,
size_t  key_len,
const uint8_t *  plaintext,
size_t  plaintext_len,
const uint8_t *  iv,
size_t  iv_len,
uint8_t *  ciphertext,
size_t *  ciphertext_len,
uint8_t *  tag,
size_t  tag_len 
)
static

AES-256-GCM symmetric encryption.

Algorithm:

  1. Create an EVP_CIPHER_CTX for AES-256-GCM.
  2. Call EVP_EncryptInit_ex with the key and IV (96-bit nonce).
  3. Feed plaintext via EVP_EncryptUpdate to produce ciphertext.
  4. Finalize with EVP_EncryptFinal_ex (produces no extra ciphertext for GCM, but validates internal state).
  5. Retrieve the 128-bit authentication tag via EVP_CTRL_GCM_GET_TAG.
Parameters
key256-bit (32-byte) AES key.
key_lenMust be 32.
plaintextInput plaintext.
plaintext_lenLength of plaintext.
iv96-bit (12-byte) initialization vector.
iv_lenMust be 12.
ciphertext[out] Output buffer for encrypted data (must be at least plaintext_len + 16 bytes).
ciphertext_len[out] Receives the ciphertext length.
tag[out] 128-bit (16-byte) authentication tag.
tag_lenMust be 16.
Returns
0 on success, -1 if parameters are invalid or encryption fails.
Note
The output buffer must be large enough for ciphertext + tag. Thread-safe provided OpenSSL is configured with locking.

◆ default_verify()

static int default_verify ( const char *  public_key,
size_t  pub_len,
const uint8_t *  data,
size_t  data_len,
const uint8_t *  signature,
size_t  sig_len 
)
static

RSA-PSS digital signature verification.

Algorithm:

  1. Parse the PEM public key into an EVP_PKEY.
  2. Create an EVP_MD_CTX and initialize for verification with SHA-256.
  3. Configure RSA-PSS padding with salt length equal to digest length.
  4. Call EVP_DigestVerify which internally hashes the data and verifies the signature.
Parameters
public_keyPEM-encoded RSA public key.
pub_lenLength of public_key string.
dataOriginal signed data.
data_lenLength of data.
signatureSignature to verify.
sig_lenLength of signature.
Returns
0 on valid signature, -1 on invalid signature or error.

◆ pem_to_pkey()

static EVP_PKEY * pem_to_pkey ( const char *  pem,
size_t  len 
)
static

Internal: parse a PEM-encoded public key into an EVP_PKEY handle.

Parameters
pemPEM string buffer.
lenLength of the PEM string.
Returns
New EVP_PKEY with a reference count of 1, or NULL on parse failure.
Note
The caller must free the returned key with EVP_PKEY_free().

◆ pem_to_privkey()

static EVP_PKEY * pem_to_privkey ( const char *  pem,
size_t  len 
)
static

Internal: parse a PEM-encoded private key into an EVP_PKEY handle.

Parameters
pemPEM string buffer.
lenLength of the PEM string.
Returns
New EVP_PKEY with a reference count of 1, or NULL on parse failure.
Note
The caller must free the returned key with EVP_PKEY_free().

Variable Documentation

◆ csilk_default_cipher_driver

csilk_cipher_driver_t csilk_default_cipher_driver
Initial value:
= {
.symmetric_encrypt = default_symmetric_encrypt,
.symmetric_decrypt = default_symmetric_decrypt,
.generate_keypair = default_generate_keypair,
.asymmetric_encrypt = default_asymmetric_encrypt,
.asymmetric_decrypt = default_asymmetric_decrypt,
.sign = default_sign,
.verify = default_verify,
}
static int default_asymmetric_encrypt(const char *public_key, size_t pub_len, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t *ciphertext_len)
RSA-OAEP asymmetric encryption.
Definition cipher.c:331
static int default_verify(const char *public_key, size_t pub_len, const uint8_t *data, size_t data_len, const uint8_t *signature, size_t sig_len)
RSA-PSS digital signature verification.
Definition cipher.c:528
static int default_asymmetric_decrypt(const char *private_key, size_t priv_len, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t *plaintext_len)
RSA-OAEP asymmetric decryption.
Definition cipher.c:397
static int default_symmetric_encrypt(const uint8_t *key, size_t key_len, const uint8_t *plaintext, size_t plaintext_len, const uint8_t *iv, size_t iv_len, uint8_t *ciphertext, size_t *ciphertext_len, uint8_t *tag, size_t tag_len)
AES-256-GCM symmetric encryption.
Definition cipher.c:59
static int default_generate_keypair(char *public_key, size_t *pub_len, char *private_key, size_t *priv_len)
Generate an RSA keypair and return PEM-encoded public and private keys.
Definition cipher.c:206
static int default_symmetric_decrypt(const uint8_t *key, size_t key_len, const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *plaintext, size_t *plaintext_len)
AES-256-GCM symmetric decryption with authentication tag verification.
Definition cipher.c:134
static int default_sign(const char *private_key, size_t priv_len, const uint8_t *data, size_t data_len, uint8_t *signature, size_t *sig_len)
RSA-PSS digital signature generation.
Definition cipher.c:463

Default cipher driver vtable mapping all operations to the OpenSSL-backed implementations above.

Installed by the cipher subsystem as the default driver. Callers can override individual operations by building a custom driver struct with different function pointers for specific needs (e.g., hardware-backed keys).