Crypt-Bear

 view release on metacpan or  search on metacpan

lib/Crypt/Bear.xs  view on Meta::CPAN

	rsa_oaep_encrypt = br_rsa_oaep_encrypt_get_default();

SV* br_rsa_public_key_pkcs1_verify(Crypt::Bear::RSA::PublicKey self, hash_oid_type hash, const unsigned char* signature, size_t length(signature))
CODE:
	RETVAL = make_buffer(hash->length);
	bool success = rsa_pkcs1_verify(signature, STRLEN_length_of_signature, hash->oid, hash->length, self, (unsigned char*)SvPV_nolen(RETVAL));
	if (!success)
		sv_setsv(RETVAL, &PL_sv_undef);
OUTPUT:
	RETVAL

SV* br_rsa_public_key_oaep_encrypt(Crypt::Bear::RSA::PublicKey self, hash_type hash, const char* plain, size_t length(plain), Crypt::Bear::PRNG prng, const char* label, size_t length(label))
CODE:
	RETVAL = make_buffer(self->nlen);
	size_t length = rsa_oaep_encrypt(prng, hash, label, STRLEN_length_of_label, self, SvPV_nolen(RETVAL), self->nlen, plain, STRLEN_length_of_plain);
	if (length)
		SvCUR_set(RETVAL, length);
	else
		Perl_croak(aTHX_ "Could not encrypt");
OUTPUT:
	RETVAL



MODULE = Crypt::Bear PACKAGE = Crypt::Bear::RSA::PrivateKey PREFIX = br_rsa_private_key_
BOOT:
	rsa_pkcs1_sign = br_rsa_pkcs1_sign_get_default();
	rsa_oaep_decrypt = br_rsa_oaep_decrypt_get_default();

SV* br_rsa_private_key_pkcs1_sign(Crypt::Bear::RSA::PrivateKey self, hash_oid_type hash_oid, const unsigned char* hash, size_t length(hash))
CODE:
	if (STRLEN_length_of_hash != hash_oid->length)
		Perl_croak(aTHX_ "Hash has incorrect length");
	RETVAL = make_buffer((self->n_bitlen+7)/8);
	bool success = rsa_pkcs1_sign(hash_oid->oid, hash, STRLEN_length_of_hash, self, (unsigned char*)SvPV_nolen(RETVAL));
	if (!success)
		Perl_croak(aTHX_ "Could not sign");
OUTPUT:
	RETVAL

SV* br_rsa_private_key_oaep_decrypt(Crypt::Bear::RSA::PrivateKey self, hash_type hash, const char* ciphertext, size_t length(ciphertext), const char* label, size_t length(label))
CODE:
	RETVAL = newSVpvn(ciphertext, STRLEN_length_of_ciphertext);
	size_t len = STRLEN_length_of_ciphertext;
	bool succes = rsa_oaep_decrypt(hash, label, STRLEN_length_of_label, self, SvPV_nolen(RETVAL), &len);
	if (succes)
		SvCUR_set(RETVAL, len);
	else
		sv_setsv(RETVAL, &PL_sv_undef);
OUTPUT:
	RETVAL


MODULE = Crypt::Bear PACKAGE = Crypt::Bear::EC PREFIX = br_ec_
BOOT:
	ec_default = br_ec_get_default();
	ec_sign_default = br_ecdsa_sign_asn1_get_default();
	ec_verify_default = br_ecdsa_vrfy_asn1_get_default();

void br_ec_supported_curves(class)
PPCODE:
	for (UV i = 0; i < 31; i++) {
		if (ec_default->supported_curves & (1 << i)) {
			union value value = { .integer = i };
			const entry* entry = map_reverse_find(curves, value);
			mXPUSHp(entry->key, entry->length);
		}
	}


MODULE = Crypt::Bear PACKAGE = Crypt::Bear::EC::PublicKey PREFIX = br_ec_public_key_

Crypt::Bear::EC::PublicKey br_ec_public_key_new(curve_type curve, const char* data, size_t length(data))
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	RETVAL->curve = curve;
	RETVAL->q = saveupvn(data, STRLEN_length_of_data);
	RETVAL->qlen = STRLEN_length_of_data;
OUTPUT:
	RETVAL

curve_type br_ec_public_key_curve(Crypt::Bear::EC::PublicKey self)
CODE:
	RETVAL = self->curve;
OUTPUT:
	RETVAL

bool br_ec_public_key_ecdsa_verify(Crypt::Bear::EC::PublicKey self, hash_type hash_name, unsigned char* hash_value, size_t length(hash_value), unsigned char* signature, size_t length(signature))
CODE:
	size_t hash_size = ((hash_name->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK);
	if (STRLEN_length_of_hash_value != hash_size)
		Perl_croak(aTHX_ "Hash is inappropriately sized");
	RETVAL = ec_verify_default(ec_default, hash_value, hash_size, self, signature, STRLEN_length_of_signature);
OUTPUT:
	RETVAL


MODULE = Crypt::Bear PACKAGE = Crypt::Bear::EC::PrivateKey PREFIX = br_ec_private_key_

Crypt::Bear::EC::PrivateKey br_ec_private_key_new(curve_type curve, const char* data, size_t length(data))
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	RETVAL->curve = curve;
	RETVAL->x = saveupvn(data, STRLEN_length_of_data);
	RETVAL->xlen = STRLEN_length_of_data;
OUTPUT:
	RETVAL

curve_type br_ec_private_key_curve(Crypt::Bear::EC::PrivateKey self)
CODE:
	RETVAL = self->curve;
OUTPUT:
	RETVAL

Crypt::Bear::EC::PrivateKey br_ec_private_key_generate(class, curve_type curve, Crypt::Bear::PRNG prng)
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	size_t length = br_ec_keygen(prng, ec_default, RETVAL, NULL, curve);
	char* buffer = safemalloc(length);
	br_ec_keygen(prng, ec_default, RETVAL, buffer, curve);
OUTPUT:
	RETVAL

Crypt::Bear::EC::PublicKey br_ec_private_key_public_key(Crypt::Bear::EC::PrivateKey self)
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	size_t length = br_ec_compute_pub(ec_default, RETVAL, NULL, self);
	char* buffer = safemalloc(length);
	br_ec_compute_pub(ec_default, RETVAL, buffer, self);
OUTPUT:
	RETVAL

SV* br_ec_private_key_ecdsa_sign(Crypt::Bear::EC::PrivateKey self, hash_type hash_name, unsigned char* hash_value, size_t length(hash_value))
CODE:
	size_t hash_size = ((hash_name->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK);
	if (STRLEN_length_of_hash_value != hash_size)
		Perl_croak(aTHX_ "Hash is inappropriately sized");
	RETVAL = make_buffer(ecdsa_max_size);
	size_t length = ec_sign_default(ec_default, hash_name, hash_value, self, SvPV_nolen(RETVAL));
	if (!length)
		Perl_croak(aTHX_ "Could not sign");
	SvCUR_set(RETVAL, length);
OUTPUT:
	RETVAL

SV* br_ec_private_key_ecdh_key_exchange(Crypt::Bear::EC::PrivateKey self, Crypt::Bear::EC::PublicKey other)
CODE:
	if (self->curve != other->curve)
		Perl_croak(aTHX_ "Keys must be on same curve for EC key exchange");

	size_t out_length = 0;
	(ec_default->generator)(self->curve, &out_length);
	RETVAL = make_buffer(out_length);
	memcpy(SvPV_nolen(RETVAL), other->q, other->qlen);

	(ec_default->mul)(SvPV_nolen(RETVAL), other->qlen, self->x, self->xlen, self->curve);
	size_t xoff, xlen;
	xoff = ec_default->xoff(self->curve, &xlen);
	if (xoff)
		sv_chop(RETVAL, SvPV_nolen(RETVAL) + xoff);
	SvCUR_set(RETVAL, xlen);
OUTPUT:
	RETVAL

MODULE = Crypt::Bear PACKAGE = Crypt::Bear::PEM PREFIX = br_pem_

SV* br_pem_pem_encode(const char* banner, const char* data, size_t length(data), ...)
CODE:
	unsigned flags = 0;
	for (int i = 3; i < items; i++) {
		flags |= lookup_pem_flag(ST(i));
	}
	size_t length = br_pem_encode(NULL, data, STRLEN_length_of_data, banner, flags);
	RETVAL = make_buffer(length);
	br_pem_encode(SvPV_nolen(RETVAL), data, STRLEN_length_of_data, banner, flags);
OUTPUT:
	RETVAL


SV* br_pem_pem_decode(const char* data, size_t length(data))
PPCODE:
	pem_decoder decoder;
	br_pem_decoder_init(&decoder.decoder);
#ifdef MULTIPLICITY
	decoder.aTHX = aTHX;
#endif

	size_t left = STRLEN_length_of_data;
	while (left) {
		size_t pushed = br_pem_decoder_push(&decoder.decoder, data, left);
		data += pushed;
		left -= pushed;

		switch (br_pem_decoder_event(&decoder.decoder)) {
			case BR_PEM_BEGIN_OBJ: {
				decoder.name = newSVpv(br_pem_decoder_name(&decoder.decoder), 0);
				decoder.buffer = newSVpvn("", 0);
				br_pem_decoder_setdest(&decoder.decoder, pem_callback, &decoder);
				break;
			}
			case BR_PEM_END_OBJ: {
				if (decoder.buffer) {
					mXPUSHs(decoder.name);
					mXPUSHs(decoder.buffer);
					decoder.name = NULL;
					decoder.buffer = NULL;
				}
				break;
			}
			case BR_PEM_ERROR: {
				if (decoder.name)
					SvREFCNT_dec(decoder.name);
				if (decoder.buffer)
					SvREFCNT_dec(decoder.buffer);
				Perl_croak(aTHX_ "Could not parse PEM");
				break;
			}
		}
	}

MODULE = Crypt::Bear PACKAGE = Crypt::Bear::PEM::Decoder PREFIX = br_pem_decoder_

Crypt::Bear::PEM::Decoder br_pem_decoder_new(class, SV* callback)
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	br_pem_decoder_init(&RETVAL->decoder);
	RETVAL->callback = SvREFCNT_inc(callback);
	RETVAL->name = NULL;
	RETVAL->buffer = NULL;
#ifdef MULTIPLICITY
	RETVAL->aTHX = aTHX;
#endif
OUTPUT:
	RETVAL

void br_pem_decoder_push(Crypt::Bear::PEM::Decoder self, const char* data, size_t length(data))
CODE:
	size_t left = STRLEN_length_of_data;
	while (left) {
		size_t pushed = br_pem_decoder_push(&self->decoder, data, left);
		data += pushed;

lib/Crypt/Bear.xs  view on Meta::CPAN

	if (RETVAL->key_type == BR_KEYTYPE_RSA) {
		rsa_private_key_copy(&RETVAL->rsa, br_skey_decoder_get_rsa(&context));
	} else if (RETVAL->key_type == BR_KEYTYPE_EC) {
		ec_private_key_copy(&RETVAL->ec, br_skey_decoder_get_ec(&context));
	}
OUTPUT:
	RETVAL


SV* br_x509_private_key_unpack(Crypt::Bear::X509::PrivateKey self)
CODE:
	RETVAL = &PL_sv_undef;
	if (self->key_type == BR_KEYTYPE_RSA) {
		br_rsa_private_key* key = safemalloc(sizeof *key);
		rsa_private_key_copy(key, &self->rsa);
		RETVAL = make_magic(key, "Crypt::Bear::RSA::PrivateKey", &Crypt__Bear__RSA__PrivateKey_magic);
	} else if (self->key_type == BR_KEYTYPE_EC) {
		br_ec_private_key* key = safemalloc(sizeof *key);
		ec_private_key_copy(key, &self->ec);
		RETVAL = make_magic(key, "Crypt::Bear::EC::PrivateKey", &Crypt__Bear__EC__PrivateKey_magic);
	}
OUTPUT:
	RETVAL


key_kind_type br_x509_private_key_type(Crypt::Bear::X509::PrivateKey self)
CODE:
	RETVAL = self->key_type;
OUTPUT:
	RETVAL



MODULE = Crypt::Bear PACKAGE = Crypt::Bear::X509::TrustAnchors PREFIX = br_x509_trust_anchors_

Crypt::Bear::X509::TrustAnchors br_x509_trust_anchors_new(class)
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	trust_anchors_init(RETVAL);
OUTPUT:
	RETVAL

void br_x509_trust_anchors_add(Crypt::Bear::X509::TrustAnchors self, Crypt::Bear::X509::Certificate certificate, bool is_ca = br_x509_decoder_isCA(&certificate->decoder))
CODE:
	br_x509_trust_anchor anchor = { .flags = is_ca ? BR_X509_TA_CA : 0};
	dn_copy(&anchor.dn, &certificate->dn);
	x509_key_copy(&anchor.pkey, br_x509_decoder_get_pkey(&certificate->decoder));
	trust_anchors_push(self, &anchor);

void br_x509_trust_anchors_merge(Crypt::Bear::X509::TrustAnchors self, Crypt::Bear::X509::TrustAnchors other)
CODE:
	for (size_t i = 0; i < other->used; i++) {
		const br_x509_trust_anchor* old = other->array + i;
		br_x509_trust_anchor anchor = { .flags = old->flags };
		dn_copy(&anchor.dn, &old->dn);
		x509_key_copy(&anchor.pkey, &old->pkey);
		trust_anchors_push(self, &anchor);
	}

void br_x509_trust_anchors_names(Crypt::Bear::X509::TrustAnchors self)
PPCODE:
	for (size_t i = 0; i < self->used; i++) {
		const br_x509_trust_anchor* anchor = self->array + i;
		mXPUSHp((const char*)anchor->dn.data, anchor->dn.len);
	}

UV br_x509_trust_anchors_count(Crypt::Bear::X509::TrustAnchors self)
CODE:
	RETVAL = self->used;
OUTPUT:
	RETVAL

MODULE = Crypt::Bear PACKAGE = Crypt::Bear::X509::Validator PREFIX = br_x509_validator_

void start_chain(Crypt::Bear::X509::Validator self, const char* server_name)
CODE:
	((*self)->start_chain)(self, server_name);

void start_certificate(Crypt::Bear::X509::Validator self, size_t length)
CODE:
	((*self)->start_cert)(self, length);

void append(Crypt::Bear::X509::Validator self, const unsigned char* data, size_t length(data))
CODE:
	((*self)->append)(self, data, STRLEN_length_of_data);

void end_certificate(Crypt::Bear::X509::Validator self)
CODE:
	((*self)->end_cert)(self);

void end_chain(Crypt::Bear::X509::Validator self)
CODE:
	((*self)->end_chain)(self);

SV* get_pkey(Crypt::Bear::X509::Validator self, unsigned wanted_usage)
CODE:
	unsigned usage;
	const br_x509_pkey* public_key = ((*self)->get_pkey)(self, &usage);

	if (wanted_usage && (usage & wanted_usage) != wanted_usage)
		RETVAL = &PL_sv_undef;
	else if (public_key)
		RETVAL = x509_key_unpack(public_key);
	else
		RETVAL = &PL_sv_undef;
OUTPUT:
	RETVAL

MODULE = Crypt::Bear PACKAGE = Crypt::Bear::X509::Validator::Minimal PREFIX = br_x509_minimal_
BOOT:
	push_isa(Crypt::Bear::X509::Validator::Minimal, Crypt::Bear::X509::Validator);

Crypt::Bear::X509::Validator::Minimal br_x509_minimal_new(SV* class, Crypt::Bear::X509::TrustAnchors anchors)
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	trust_anchors_copy(&RETVAL->anchors, anchors);
	br_x509_minimal_init_full(&RETVAL->context, RETVAL->anchors.array, RETVAL->anchors.used);
OUTPUT:
	RETVAL

#if 0

lib/Crypt/Bear.xs  view on Meta::CPAN

	br_ssl_engine_set_buffer(&RETVAL->context.eng, RETVAL->buffer, sizeof RETVAL->buffer, true);
	private_certificate_init(&RETVAL->private);
OUTPUT:
	RETVAL

bool br_ssl_client_reset(Crypt::Bear::SSL::Client self, SV* server_name, bool resume_session = FALSE);
CODE:
	if (SvOK(server_name))
		RETVAL = br_ssl_client_reset(&self->context, SvPV_nolen(server_name), resume_session);
	else
		RETVAL = br_ssl_client_reset(&self->context, NULL, resume_session);
OUTPUT:
	RETVAL


void br_ssl_client_set_client_certificate(Crypt::Bear::SSL::Client self, Crypt::Bear::SSL::PrivateCertificate priv_cert)
CODE:
	private_certificate_copy(&self->private, priv_cert);

	if (priv_cert->key.key_type == BR_KEYTYPE_RSA) {
		br_ssl_client_set_single_rsa(&self->context, self->private.chain.array, self->private.chain.used, &self->private.key.rsa, rsa_pkcs1_sign);
	} else if (priv_cert->key.key_type == BR_KEYTYPE_EC) {
		br_ssl_client_set_single_ec(&self->context, self->private.chain.array, self->private.chain.used, &self->private.key.ec, self->private.usage, priv_cert->chain.signer_key_type, ec_default, ec_sign_default);
	} else {
		Perl_croak(aTHX_ "Invalid private key");
	}

void br_ssl_client_forget_session(Crypt::Bear::SSL::Client self)
CODE:
	br_ssl_client_forget_session(&self->context);


MODULE = Crypt::Bear PACKAGE = Crypt::Bear::SSL::Server PREFIX = br_ssl_server_
BOOT:
	push_isa(Crypt::Bear::SSL::Server, Crypt::Bear::SSL::Engine);

Crypt::Bear::SSL::Server br_ssl_server_new(class, Crypt::Bear::SSL::PrivateCertificate priv_cert)
CODE:
	RETVAL = safemalloc(sizeof *RETVAL);
	private_certificate_copy(&RETVAL->private, priv_cert);

	if (priv_cert->key.key_type == BR_KEYTYPE_RSA) {
		br_ssl_server_init_full_rsa(&RETVAL->context, RETVAL->private.chain.array, RETVAL->private.chain.used, &RETVAL->private.key.rsa);
	} else if (priv_cert->key.key_type == BR_KEYTYPE_EC) {
		br_ssl_server_init_full_ec(&RETVAL->context, RETVAL->private.chain.array, RETVAL->private.chain.used, priv_cert->chain.signer_key_type, &RETVAL->private.key.ec);
	} else {
		Safefree(RETVAL);
		Perl_croak(aTHX_ "Invalid private key");
	}
	br_ssl_engine_set_buffer(&RETVAL->context.eng, RETVAL->buffer, BR_SSL_BUFSIZE_BIDI, true);

	unsigned error = br_ssl_engine_last_error(&RETVAL->context.eng);
	if (error) {
		Safefree(RETVAL);
		Perl_croak(aTHX_ "Could not instantiate server: %s", lookup_error(error));
	}
OUTPUT:
	RETVAL

void br_ssl_server_get_client_suites(Crypt::Bear::SSL::Server self)
PPCODE:
	size_t len;	
	const br_suite_translated* suites = br_ssl_server_get_client_suites(&self->context, &len);
	for (size_t i = 0; i < len; i++) {
		AV* pair = newAV();
		av_push(pair, newSVuv(suites[i][0]));
		av_push(pair, newSVuv(suites[i][1]));
		mXPUSHs(newRV_noinc((SV*)pair));
	}


bool br_ssl_server_reset(Crypt::Bear::SSL::Server self);
CODE:
	RETVAL = br_ssl_server_reset(&self->context);
OUTPUT:
	RETVAL



( run in 0.971 second using v1.01-cache-2.11-cpan-71847e10f99 )