#include "xs/openssl.h"
MODULE = Crypt::Keyczar PACKAGE = Crypt::Keyczar::DsaPrivateKeyEngine
Crypt::Keyczar::DsaPrivateKeyEngine
new(class, x, y, p, q, g)
SV *class
SV *x
SV *y
SV *p
SV *q
SV *g
CODE:
{
DSA *dsa;
STRLEN l;
unsigned char *in;
BIGNUM *bp, *bq, *bg, *pub_key, *priv_key;
PERL_UNUSED_VAR(class);
if ((dsa = DSA_new()) == NULL) {
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
in = (unsigned char *)SvPV(p, l);
bp = BN_bin2bn((const unsigned char *)in, l, NULL);
if (bp == NULL) {
DSA_free(dsa);
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
in = (unsigned char *)SvPV(q, l);
bq = BN_bin2bn((const unsigned char *)in, l, NULL);
if (bq == NULL) {
DSA_free(dsa);
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
in = (unsigned char *)SvPV(g, l);
bg = BN_bin2bn((const unsigned char *)in, l, NULL);
if (bg == NULL) {
DSA_free(dsa);
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
DSA_set0_pqg(dsa, bp, bq, bg);
in = (unsigned char *)SvPV(y, l);
pub_key = BN_bin2bn((const unsigned char *)in, l, NULL);
if (pub_key == NULL) {
DSA_free(dsa);
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
in = (unsigned char *)SvPV(x, l);
priv_key = BN_bin2bn((const unsigned char *)in, l, NULL);
if (priv_key == NULL) {
DSA_free(dsa);
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
DSA_set0_key(dsa, pub_key, priv_key);
Newz(0, RETVAL, 1, struct Crypt__Keyczar__DsaPrivateKeyEngine_class);
RETVAL->dsa = dsa;
}
OUTPUT:
RETVAL
void
DESTROY(self)
Crypt::Keyczar::DsaPrivateKeyEngine self
CODE:
{
if (self->dsa != NULL) {
DSA_free(self->dsa);
self->dsa = NULL;
}
if (self->message != NULL) {
EVP_MD_CTX_destroy(self->message);
self->message = NULL;
}
Safefree(self);
}
SV *
init(self, ...)
Crypt::Keyczar::DsaPrivateKeyEngine self
CODE:
{
RETVAL = newSVpv("", 0);
}
OUTPUT:
RETVAL
HV *
generate(class, size)
SV *class
int size
CODE:
{
DSA *dsa;
BIGNUM *p, *q, *g, *pub_key, *priv_key;
PERL_UNUSED_VAR(class);
dsa = DSA_new();
DSA_generate_parameters_ex(dsa, size, NULL, 0, NULL, NULL, NULL);
if (dsa == NULL) {
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
if (DSA_generate_key(dsa) == 0) {
DSA_free(dsa);
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
RETVAL = newHV();
DSA_get0_pqg((const DSA *)dsa, (const BIGNUM **)&p, (const BIGNUM **)&q, (const BIGNUM **)&g);
if (crypt__keyczar__util__bignum2hv(p, "p", RETVAL) == 0) {
DSA_free(dsa);
croak("cannot generate DSA key: bignum2hv(p) fail");
}
if (crypt__keyczar__util__bignum2hv(q, "q", RETVAL) == 0) {
DSA_free(dsa);
croak("cannot generate DSA key: bignum2hv(q) fail");
}
if (crypt__keyczar__util__bignum2hv(g, "g", RETVAL) == 0) {
DSA_free(dsa);
croak("cannot generate DSA key: bignum2hv(g) fail");
}
DSA_get0_key((const DSA *)dsa, (const BIGNUM **)&pub_key, (const BIGNUM **)&priv_key);
if (crypt__keyczar__util__bignum2hv(pub_key, "y", RETVAL) == 0) {
DSA_free(dsa);
croak("cannot generate DSA key: bignum2hv(pub_key) fail");
}
if (crypt__keyczar__util__bignum2hv(priv_key, "x", RETVAL) == 0) {
DSA_free(dsa);
croak("cannot generate DSA key: bignum2hv(priv_key) fail");
}
DSA_free(dsa);
}
OUTPUT:
RETVAL
void
update(self, ...)
Crypt::Keyczar::DsaPrivateKeyEngine self
CODE:
{
int i;
SV *data;
STRLEN l;
unsigned char *in;
if (self->message == NULL) {
self->message = EVP_MD_CTX_create();
if (!EVP_DigestInit_ex(self->message, EVP_sha1(), NULL)) {
croak("cannot initialize SHA1 context");
}
}
for (i = 1; i < items; i++) {
data = ST(i);
in = (unsigned char *)SvPV(data, l);
if (!EVP_DigestUpdate(self->message, in, l)) {
croak("cannot update SHA1 context");
}
}
}
SV *
sign(self)
Crypt::Keyczar::DsaPrivateKeyEngine self
CODE:
{
int rc;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int md_l = 0;
unsigned char *sign;
int size = DSA_size(self->dsa);
unsigned int sign_l;
if (self->message == NULL) {
RETVAL = 0;
return;
}
EVP_DigestFinal_ex(self->message, md, &md_l);
Newz(0, sign, size, unsigned char);
rc = DSA_sign(0, md, md_l, sign, &sign_l, self->dsa);
if (rc != 1) {
Safefree(sign);
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
RETVAL = newSVpv((char *)sign, sign_l);
Safefree(sign);
}
OUTPUT:
RETVAL
int
verify(self, mac)
Crypt::Keyczar::DsaPrivateKeyEngine self
SV *mac
CODE:
{
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int l = 0;
int rc;
STRLEN in_l;
unsigned char *in;
if (self->message == NULL) {
RETVAL = 0;
return;
}
EVP_DigestFinal_ex(self->message, md, &l);
in = (unsigned char *)SvPV(mac, in_l);
rc = DSA_verify(0, md, l, in, in_l, self->dsa);
if (rc == -1) {
crypt__keyczar__util__croak_openssl();
/* NOTREACHED */
}
RETVAL = rc == 1;
}
OUTPUT:
RETVAL