Crypt-Nettle

 view release on metacpan or  search on metacpan

Nettle.xs  view on Meta::CPAN

/*
 ===========================================================================
 Crypt::Nettle

 Perl interface to the nettle Cryptographic library
 
 Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
 
 Copyright © Daniel Kahn Gillmor

 Crypt::Nettle is free software, you may redistribute it and/or modify
 it under the GPL version 2 or later (your choice).  Please see the
 COPYING file for the full text of the GPL.


 Use this software AT YOUR OWN RISK.
 ===========================================================================
*/

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include <nettle/nettle-meta.h>
#include <nettle/hmac.h>
#include <nettle/ctr.h>
#include <nettle/cbc.h>
#include <nettle/yarrow.h>
#include <nettle/base16.h>
#include <nettle/rsa.h>
#include <gmp.h>
#include <string.h>

static const char my_name[] = "Crypt::Nettle";
static const char author[] = "Daniel Kahn Gillmor <dkg@fifthhorseman.net>";


enum cnc_cipher_mode {
  CNC_MODE_UNKNOWN,
  CNC_MODE_ECB,
  CNC_MODE_CBC,
  CNC_MODE_CTR
};
struct cnc_cipher_mode_name {
  enum cnc_cipher_mode mode;
  const char * name;
};

const struct cnc_cipher_mode_name cipher_modes_available[] = {
  { CNC_MODE_ECB, "ecb" },
  { CNC_MODE_CBC, "cbc" },
  { CNC_MODE_CTR, "ctr" }
};

STATIC
enum cnc_cipher_mode
_cnc_cipher_mode_lookup(const char* name) {
  int i;
  for (i = 0; i < sizeof(cipher_modes_available)/sizeof(*cipher_modes_available); i++)
    if (0 == strcasecmp(name, cipher_modes_available[i].name))
      return cipher_modes_available[i].mode;
  croak("Crypt::Nettle::Cipher: Bad Cipher Block Mode: %s", name);
  return CNC_MODE_UNKNOWN;
};

STATIC
const char *
_cnc_cipher_mode_name_lookup(enum cnc_cipher_mode mode) {
  int i;
  for (i = 0; i < sizeof(cipher_modes_available)/sizeof(*cipher_modes_available); i++)
    if (mode == cipher_modes_available[i].mode)
      return cipher_modes_available[i].name;

  croak("Crypt::Nettle::Cipher: Bad Cipher Block ID: %d (checked %d)", mode, i);
  return NULL;
}

struct Crypt_Nettle_Hash_s {
  const struct nettle_hash * hashtype;
  int is_hmac;
  void* hash_context;
};
typedef struct Crypt_Nettle_Hash_s *Crypt_Nettle_Hash;

struct Crypt_Nettle_Cipher_s {
  const struct nettle_cipher * ciphertype;
  int is_encrypt;
  enum cnc_cipher_mode mode;
  void* cipher_context;
  void* chain_state;
};
typedef struct Crypt_Nettle_Cipher_s *Crypt_Nettle_Cipher;

struct Crypt_Nettle_RSA_s {
  struct rsa_public_key * public_key;
  struct rsa_private_key * private_key;
};
typedef struct Crypt_Nettle_RSA_s *Crypt_Nettle_RSA;

typedef int(*_cnrsa_sign_func)(const struct rsa_private_key*, void*, mpz_t);
typedef int(*_cnrsa_verify_func)(const struct rsa_public_key*, void*, const mpz_t);

struct cnrsa_hash {
   const struct nettle_hash * hash;
   _cnrsa_sign_func sign;
   int (*sign_digest)(const struct rsa_private_key*, const uint8_t*, mpz_t);
   _cnrsa_verify_func verify;
   int (*verify_digest)(const struct rsa_public_key*, const uint8_t*, const mpz_t);
};

const struct cnrsa_hash 

Nettle.xs  view on Meta::CPAN

  }
  return ret;
}


const struct nettle_cipher *
cipher_algos_available[] = {
  &nettle_aes128,
  &nettle_aes192,
  &nettle_aes256,
  &nettle_arctwo40,
  &nettle_arctwo64,
  &nettle_arctwo128,
  &nettle_arctwo_gutmann128,
  &nettle_arcfour128,
  &nettle_camellia128,
  &nettle_camellia192,
  &nettle_camellia256,
  &nettle_cast128,
  &nettle_serpent128,
  &nettle_serpent192,
  &nettle_serpent256,
  &nettle_twofish128,
  &nettle_twofish192,
  &nettle_twofish256
};

STATIC
const struct nettle_cipher*
_cnc_cipher_lookup(const char* name) {
  int i;
  if (NULL == name)
    return NULL;
  for (i = 0; i < sizeof(cipher_algos_available)/sizeof(*cipher_algos_available); i++)
    if (0 == strncasecmp(name, cipher_algos_available[i]->name, 20))
      return cipher_algos_available[i];
  return NULL;
}



STATIC
void
_cnc_process(Crypt_Nettle_Cipher cnc, int datalen, const uint8_t * databuf, uint8_t * outbuf) {
  switch(cnc->mode) {
  case CNC_MODE_ECB:
    if (cnc->is_encrypt)
      cnc->ciphertype->encrypt(cnc->cipher_context, datalen, outbuf, databuf);
    else
      cnc->ciphertype->decrypt(cnc->cipher_context, datalen, outbuf, databuf);
    break;
  case CNC_MODE_CTR: /* encrypt and decrypt are the same function by definition in CTR mode */
    ctr_crypt(cnc->cipher_context, 
              cnc->ciphertype->encrypt,
              cnc->ciphertype->block_size,
              cnc->chain_state, 
              datalen,
              outbuf,
              databuf);
    break;
  case CNC_MODE_CBC:
    if (cnc->is_encrypt)
      cbc_encrypt(cnc->cipher_context, 
                  cnc->ciphertype->encrypt,
                  cnc->ciphertype->block_size,
                  cnc->chain_state, 
                  datalen,
                  outbuf,
                  databuf);
    else
      cbc_decrypt(cnc->cipher_context, 
                  cnc->ciphertype->encrypt,
                  cnc->ciphertype->block_size,
                  cnc->chain_state, 
                  datalen,
                  outbuf,
                  databuf);
    break;
  }
};


STATIC
void
_cnrsa_wipe(Crypt_Nettle_RSA cnrsa) {
  if (cnrsa->public_key) {
      rsa_public_key_clear(cnrsa->public_key);
      Safefree(cnrsa->public_key);
      cnrsa->public_key = NULL;
  }
  if (cnrsa->private_key) {
     rsa_private_key_clear(cnrsa->private_key);
     Safefree(cnrsa->private_key);
     cnrsa->private_key = NULL;
   }
   Safefree(cnrsa);
   cnrsa = NULL;
}


/* returns 1 if successful, 0 if there was a problem parsing */
STATIC
int
_mpz_setSV(mpz_t dst, SV* src) {
  if (SVt_IV == SvTYPE(src)) {
    mpz_set_ui(dst, SvIV(src));
    return 1;
  } else if (SVt_PV == SvTYPE(src)) {
    return (0 == mpz_set_str(dst, SvPV_nolen(src), 0));
  }
  return 0;
}

STATIC
int
_mpz_setSVraw(mpz_t dst, SV* src) {
  const char* sigdata;
  int siglen;
  char* hexdata;
  int ret;



( run in 1.412 second using v1.01-cache-2.11-cpan-df04353d9ac )