Crypt-Nettle

 view release on metacpan or  search on metacpan

Nettle.xs  view on Meta::CPAN


Crypt_Nettle_Hash
cnh_new_hmac(classname, algoname, key)
    const char * classname;
    const char * algoname;
    SV* key;
    PREINIT:
        Crypt_Nettle_Hash src;
        const struct nettle_hash* algo;
        const uint8_t * keydata;
        int keylen;
    CODE:
        if (0 != strcmp("Crypt::Nettle::Hash", classname))
           croak("Crypt::Nettle::Hash->new_hmac() was somehow called wrong");
        keydata = SvPV(key, keylen);
        algo = _cnh_hash_lookup(algoname);
        if (NULL == algo) XSRETURN_UNDEF;
        Newxz(RETVAL, 1, struct Crypt_Nettle_Hash_s);
        if (NULL == RETVAL) XSRETURN_UNDEF;
        RETVAL->hashtype = algo;
        RETVAL->is_hmac = 1;
        Newx(RETVAL->hash_context, algo->context_size * 3, char); /* ??? will we run into alignment issues? */
        if (NULL == RETVAL->hash_context) { Safefree(RETVAL); XSRETURN_UNDEF; };
        hmac_set_key(RETVAL->hash_context + algo->context_size, 
                     RETVAL->hash_context + algo->context_size*2,
                     RETVAL->hash_context,
                     RETVAL->hashtype,
                     keylen, keydata
                     );
    OUTPUT:
        RETVAL


int
cnh_is_hmac(cnh)
    Crypt_Nettle_Hash cnh;
    CODE:
        RETVAL=cnh->is_hmac;
    OUTPUT:
        RETVAL

Crypt_Nettle_Hash
cnh_copy(cnh)
    Crypt_Nettle_Hash cnh;
    CODE:
        Newxz(RETVAL, 1, struct Crypt_Nettle_Hash_s);
        RETVAL->hashtype = cnh->hashtype;
        Newx(RETVAL->hash_context, RETVAL->hashtype->context_size, char);
        if (NULL == RETVAL->hash_context) { Safefree(RETVAL); XSRETURN_UNDEF; };
        Copy(cnh->hash_context, RETVAL->hash_context, RETVAL->hashtype->context_size, char);
    OUTPUT:
        RETVAL

void
cnh_update(cnh, data)
    Crypt_Nettle_Hash cnh;
    SV* data;
    PREINIT:
        const uint8_t* buf;
        unsigned len;
    PPCODE:
        buf = SvPV(data, len);
        cnh->hashtype->update(cnh->hash_context, len, buf);
        XSRETURN(1);

SV *
cnh_digest(cnh)
    Crypt_Nettle_Hash cnh;
    PREINIT:
        uint8_t* outbuf;
    CODE:
        RETVAL = newSVpv("", cnh->hashtype->digest_size);
        outbuf = (uint8_t*) SvPV_nolen(RETVAL);
        if (cnh->is_hmac)
            hmac_digest(cnh->hash_context + cnh->hashtype->context_size,
                        cnh->hash_context + cnh->hashtype->context_size * 2,
                        cnh->hash_context,
                        cnh->hashtype,
                        cnh->hashtype->digest_size, outbuf);
        else
            cnh->hashtype->digest(cnh->hash_context, cnh->hashtype->digest_size, outbuf);
    OUTPUT:
        RETVAL

const char *
cnh_name(cnh)
    Crypt_Nettle_Hash cnh;
    CODE:
        RETVAL = cnh->hashtype->name;
    OUTPUT:
        RETVAL

int
cnh_digest_size(...)
    PROTOTYPE: @
    PREINIT:
        Crypt_Nettle_Hash cnh;
        const struct nettle_hash* algo;
    CODE:
        if (0 == strcmp(SvPV_nolen(ST(0)), "Crypt::Nettle::Hash")) {
            if (items != 2)
              croak("Crypt::Nettle::Hash->digest_size() needs one argument");
            algo = _cnh_hash_lookup(SvPV_nolen(ST(1)));
        } else {
          if (items != 1)
            croak("Calling digest_size() on a Crypt::Nettle::Hash object needs no additional argument");
          cnh = dereference_cnh(ST(0));
          algo = cnh->hashtype;
        }
        if (NULL == algo) XSRETURN_UNDEF;
        RETVAL = algo->digest_size;
    OUTPUT:
        RETVAL

int
cnh_block_size(...)
    PROTOTYPE: @
    PREINIT:
        Crypt_Nettle_Hash cnh;
        const struct nettle_hash* algo;
    CODE:
        if (0 == strcmp(SvPV_nolen(ST(0)), "Crypt::Nettle::Hash")) {
            if (items != 2)
              croak("Crypt::Nettle::Hash->block_size() needs one argument");
            algo = _cnh_hash_lookup(SvPV_nolen(ST(1)));
        } else {
          if (items != 1)
            croak("Calling block_size() on a Crypt::Nettle::Hash object needs no additional argument");
          cnh = dereference_cnh(ST(0));
          algo = cnh->hashtype;
        }
        if (NULL == algo) XSRETURN_UNDEF;
        RETVAL = algo->block_size;
    OUTPUT:
        RETVAL

void
cnh_algos_available()
    PREINIT:
        int i;
    PPCODE:
        for (i = 0; i < sizeof(hash_algos_available)/sizeof(*hash_algos_available); i++)
          XPUSHs(sv_2mortal(newSVpv(hash_algos_available[i]->name, 0)));

void
cnh_DESTROY(cnh)
    Crypt_Nettle_Hash cnh;
    CODE:
        Safefree(cnh->hash_context);
        Safefree(cnh);
        cnh = NULL;



MODULE = Crypt::Nettle        PACKAGE = Crypt::Nettle::Cipher    PREFIX = cnc_



Crypt_Nettle_Cipher
cnc_new(classname, is_encrypt, algoname, key, mode="ecb", iv=&PL_sv_undef)
    const char * classname;
    SV * is_encrypt;
    const char * algoname;
    SV * key;
    const char * mode;
    SV * iv;
    PREINIT:
        Crypt_Nettle_Cipher src;
        const struct nettle_cipher * algo;
        const char * encstr;
        int keylen;
        const uint8_t * keydata;
        int ivlen;
        const uint8_t * ivdata;
    CODE:
        if (0 != strcmp("Crypt::Nettle::Cipher", classname))
           croak("Crypt::Nettle::Cipher->new() was somehow called wrong");
        algo = _cnc_cipher_lookup(algoname);
        if (NULL == algo) XSRETURN_UNDEF;
        Newxz(RETVAL, 1, struct Crypt_Nettle_Cipher_s);
        if (NULL == RETVAL) XSRETURN_UNDEF;
        RETVAL->ciphertype = algo;
        keydata = SvPV(key, keylen);
        RETVAL->is_encrypt = 1;
        RETVAL->mode = _cnc_cipher_mode_lookup(mode);
        if (RETVAL->mode == CNC_MODE_UNKNOWN) { Safefree(RETVAL); XSRETURN_UNDEF; };
        if (((SVt_IV == SvTYPE(is_encrypt)) && (0 == SvIV(is_encrypt))) ||
            ((SVt_PV == SvTYPE(is_encrypt)) && tolower((SvPV_nolen(is_encrypt))[0]) == 'd'))
          RETVAL->is_encrypt = 0;
        Newx(RETVAL->cipher_context, algo->context_size, char);
        if (NULL == RETVAL->cipher_context) { Safefree(RETVAL); XSRETURN_UNDEF; };
        if (RETVAL->mode == CNC_MODE_ECB) {
          RETVAL->chain_state = NULL;
        } else {
          /* initialize chain_state with IV */
          Newxz(RETVAL->chain_state, algo->block_size, char);
          if (NULL == RETVAL->chain_state) { Safefree(RETVAL->cipher_context); Safefree(RETVAL); XSRETURN_UNDEF; };
          ivdata = SvPV(iv, ivlen);
          Copy(ivdata, RETVAL->chain_state, MIN(ivlen, algo->block_size), char);
        }
        if (RETVAL->is_encrypt) 

Nettle.xs  view on Meta::CPAN

    CODE:
        RETVAL = cnc->ciphertype->name;
    OUTPUT:
        RETVAL


int
cnc_is_encrypt(cnc)
    Crypt_Nettle_Cipher cnc;
    CODE:
        RETVAL=cnc->is_encrypt;
    OUTPUT:
        RETVAL

const char *
cnc_mode(cnc)
    Crypt_Nettle_Cipher cnc;
    CODE:
        RETVAL=_cnc_cipher_mode_name_lookup(cnc->mode);
    OUTPUT:
        RETVAL


Crypt_Nettle_Cipher
cnc_copy(cnc)
    Crypt_Nettle_Cipher cnc;
    CODE:
        Newxz(RETVAL, 1, struct Crypt_Nettle_Cipher_s);
        RETVAL->ciphertype = cnc->ciphertype;
        Newx(RETVAL->cipher_context, RETVAL->ciphertype->context_size, char);
        if (NULL == RETVAL->cipher_context) { Safefree(RETVAL); XSRETURN_UNDEF; };
        Copy(cnc->cipher_context, RETVAL->cipher_context, RETVAL->ciphertype->context_size, char);
    OUTPUT:
        RETVAL



SV *
cnc_process(cnc, data)
    Crypt_Nettle_Cipher cnc;
    SV * data;
    PREINIT:
        uint8_t* outbuf;
        const uint8_t * databuf;
        int datalen;
    CODE:
        databuf = SvPV(data, datalen);
        RETVAL = newSVpv("", datalen);
        outbuf = (uint8_t*) SvPV_nolen(RETVAL);
        _cnc_process(cnc, datalen, databuf, outbuf);
    OUTPUT:
        RETVAL

void
cnc_process_in_place(cnc, data)
    Crypt_Nettle_Cipher cnc;
    SV * data;
    PREINIT:
        uint8_t * databuf;
        int datalen;
    PPCODE:
        databuf = SvPV(data, datalen);
        _cnc_process(cnc, datalen, databuf, databuf);


int
cnc_key_size(...)
    PROTOTYPE: @
    PREINIT:
        Crypt_Nettle_Cipher cnc;
        const struct nettle_cipher* algo;
    CODE:
        if (0 == strcmp(SvPV_nolen(ST(0)), "Crypt::Nettle::Cipher")) {
            if (items != 2)
              croak("Crypt::Nettle::Cipher->key_size() needs one argument");
            algo = _cnc_cipher_lookup(SvPV_nolen(ST(1)));
        } else {
          if (items != 1)
            croak("Calling key_size() on a Crypt::Nettle::Cipher object needs no additional argument");
          cnc = dereference_cnc(ST(0));
          algo = cnc->ciphertype;
        }
        if (NULL == algo) XSRETURN_UNDEF;
        RETVAL = algo->key_size;
    OUTPUT:
        RETVAL

int
cnc_block_size(...)
    PROTOTYPE: @
    PREINIT:
        Crypt_Nettle_Cipher cnc;
        const struct nettle_cipher* algo;
    CODE:
        if (0 == strcmp(SvPV_nolen(ST(0)), "Crypt::Nettle::Cipher")) {
            if (items != 2)
              croak("Crypt::Nettle::Cipher->block_size() needs one argument");
            algo = _cnc_cipher_lookup(SvPV_nolen(ST(1)));
        } else {
          if (items != 1)
            croak("Calling block_size() on a Crypt::Nettle::Cipher object needs no additional argument");
          cnc = dereference_cnc(ST(0));
          algo = cnc->ciphertype;
        }
        if (NULL == algo) XSRETURN_UNDEF;
        RETVAL = algo->block_size;
    OUTPUT:
        RETVAL

void
cnc_algos_available()
    PREINIT:
        int i;
    PPCODE:
        for (i = 0; i < sizeof(cipher_algos_available)/sizeof(*cipher_algos_available); i++)
          XPUSHs(sv_2mortal(newSVpv(cipher_algos_available[i]->name, 0)));

void
cnc_modes_available()
    PREINIT:
        int i;
    PPCODE:
        for (i = 0; i < sizeof(cipher_modes_available)/sizeof(*cipher_modes_available); i++)
          XPUSHs(sv_2mortal(newSVpv(cipher_modes_available[i].name, 0)));

void
cnc_DESTROY(cnc)
    Crypt_Nettle_Cipher cnc;
    CODE:
        Safefree(cnc->cipher_context);
        Safefree(cnc);
        cnc = NULL;


MODULE = Crypt::Nettle        PACKAGE = Crypt::Nettle::Yarrow    PREFIX = cny_

BOOT:
    {
    HV *stash;
    
    stash = gv_stashpv("Crypt::Nettle::Yarrow", TRUE);
    newCONSTSUB(stash, "SEED_FILE_SIZE", newSViv(YARROW256_SEED_FILE_SIZE));
    }

Crypt_Nettle_Yarrow
cny_new(classname)
    const char * classname;
    CODE:
        if (0 != strcmp("Crypt::Nettle::Yarrow", classname))
            croak("Crypt::Nettle::Yarrow->new() was somehow called wrong");
        Newxz(RETVAL, 1, struct Crypt_Nettle_Yarrow_s);
        yarrow256_init(&RETVAL->yarrow_ctx, 0, NULL);
    OUTPUT:
        RETVAL

void
cny_seed(cny, seed)
    Crypt_Nettle_Yarrow cny;
    SV * seed;
    PREINIT:
        int seedlen;
        const uint8_t * seeddata;
    PPCODE:
        seeddata = SvPV(seed, seedlen);
        yarrow256_seed(&cny->yarrow_ctx, seedlen, seeddata);


SV*
cny_random(cny, len)
    Crypt_Nettle_Yarrow cny;
    int len;
    PREINIT:
        uint8_t * outbuf;
    CODE:
        RETVAL = newSVpv("", len);
        outbuf = SvPV_nolen(RETVAL);
        yarrow256_random(&cny->yarrow_ctx, len, outbuf);
    OUTPUT:
        RETVAL

int
cny_is_seeded(cny)
    Crypt_Nettle_Yarrow cny;
    CODE:
        RETVAL=yarrow256_is_seeded(&cny->yarrow_ctx);
    OUTPUT:
        RETVAL

void
cny_DESTROY(cny)
  Crypt_Nettle_Yarrow cny;
CODE:
{
  Safefree(cny);
  cny = NULL;
}


MODULE = Crypt::Nettle        PACKAGE = Crypt::Nettle::RSA    PREFIX = cnrsa_

void
cnrsa_hashes_available()
    PREINIT:
        int i;
    PPCODE:
        for (i = 0; i < sizeof(_cnrsa_hashes_available)/sizeof(*_cnrsa_hashes_available); i++)
          XPUSHs(sv_2mortal(newSVpv(_cnrsa_hashes_available[i].hash->name, 0)));


Crypt_Nettle_RSA
cnrsa_new_public_key(classname, n, e)
    const char * classname;
    SV * n;
    SV * e;
    CODE:
        if (0 != strcmp("Crypt::Nettle::RSA", classname))
            croak("Crypt::Nettle::RSA->new_public_key() was somehow called wrong");
        Newxz(RETVAL, 1, struct Crypt_Nettle_RSA_s);
        Newxz(RETVAL->public_key, 1, struct rsa_public_key);
        rsa_public_key_init(RETVAL->public_key);
        if (_mpz_setSV(RETVAL->public_key->n, n) &&
            _mpz_setSV(RETVAL->public_key->e, e) &&
            rsa_public_key_prepare(RETVAL->public_key)) {
          /* success setting everything up!  we don't need to do anything */
        } else {
          _cnrsa_wipe(RETVAL); XSRETURN_UNDEF;
        }
    OUTPUT:
        RETVAL

Crypt_Nettle_RSA
cnrsa_new_private_key(classname, d, p, q)
    const char * classname;
    SV * d;
    SV * p;
    SV * q;
    PREINIT:
        mpz_t p1,q1,phi;
    CODE:
        if (0 != strcmp("Crypt::Nettle::RSA", classname))
            croak("Crypt::Nettle::RSA->new_private_key() was somehow called wrong");
        Newxz(RETVAL, 1, struct Crypt_Nettle_RSA_s);
        Newxz(RETVAL->private_key, 1, struct rsa_private_key);
        Newxz(RETVAL->public_key, 1, struct rsa_public_key);
        rsa_private_key_init(RETVAL->private_key);
        rsa_public_key_init(RETVAL->public_key);
        if (_mpz_setSV(RETVAL->private_key->d, d) &&
            _mpz_setSV(RETVAL->private_key->p, p) &&
            _mpz_setSV(RETVAL->private_key->q, q) &&
            mpz_invert(RETVAL->private_key->c, RETVAL->private_key->q, RETVAL->private_key->p) /* c = q^{-1} (mod p) */
           ) {
          /* success setting up the standard parameters!
             now fill in the auxiliary ones: */
          mpz_init(p1); mpz_init(q1); mpz_init(phi);
          mpz_sub_ui(p1, RETVAL->private_key->p, 1);
          mpz_sub_ui(q1, RETVAL->private_key->q, 1);
          mpz_mul(phi, p1, q1);
          /* a = d % (p-1) */
          mpz_fdiv_r(RETVAL->private_key->a, RETVAL->private_key->d, p1);
          /* b = d % (q-1) */
          mpz_fdiv_r(RETVAL->private_key->b, RETVAL->private_key->d, q1);
          mpz_mul(RETVAL->public_key->n, RETVAL->private_key->p, RETVAL->private_key->q);
          mpz_invert(RETVAL->public_key->e, RETVAL->private_key->d, phi);
          mpz_clear(p1); mpz_clear(q1); mpz_clear(phi);
          if (!(rsa_private_key_prepare(RETVAL->private_key) &&



( run in 2.310 seconds using v1.01-cache-2.11-cpan-71847e10f99 )