Crypt-Nettle
view release on metacpan or search on metacpan
/*
===========================================================================
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
}
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 )