Crypt-Sodium-XS

 view release on metacpan or  search on metacpan

inc/sign.xs  view on Meta::CPAN

=for documentation

skipping sign_edwards25519sha512batch as it is not recommended. providing
aliases for sign_ed25519 as with other packages, though it is the default.

=cut

MODULE = Crypt::Sodium::XS PACKAGE = Crypt::Sodium::XS::sign

void _define_constants()
  PREINIT:
  HV *stash = gv_stashpv("Crypt::Sodium::XS::sign", 0);

  PPCODE:
  newCONSTSUB(stash, "sign_BYTES", newSVuv(crypto_sign_BYTES));
  newCONSTSUB(stash, "sign_ed25519_BYTES", newSVuv(crypto_sign_ed25519_BYTES));
  newCONSTSUB(stash, "sign_MESSAGEBYTES_MAX",
              newSVuv(crypto_sign_MESSAGEBYTES_MAX));
  newCONSTSUB(stash, "sign_ed25519_MESSAGEBYTES_MAX",
              newSVuv(crypto_sign_ed25519_MESSAGEBYTES_MAX));
  newCONSTSUB(stash, "sign_PUBLICKEYBYTES",
              newSVuv(crypto_sign_PUBLICKEYBYTES));
  newCONSTSUB(stash, "sign_ed25519_PUBLICKEYBYTES",
              newSVuv(crypto_sign_ed25519_PUBLICKEYBYTES));
  newCONSTSUB(stash, "sign_SECRETKEYBYTES",
              newSVuv(crypto_sign_SECRETKEYBYTES));
  newCONSTSUB(stash, "sign_ed25519_SECRETKEYBYTES",
              newSVuv(crypto_sign_ed25519_SECRETKEYBYTES));
  newCONSTSUB(stash, "sign_SEEDBYTES", newSVuv(crypto_sign_SEEDBYTES));
  newCONSTSUB(stash, "sign_ed25519_SEEDBYTES",
              newSVuv(crypto_sign_ed25519_SEEDBYTES));
  newCONSTSUB(stash, "sign_PRIMITIVE", newSVpvs(crypto_sign_PRIMITIVE));

SV * sign(SV * msg, SV * sk)

  ALIAS:
  sign_ed25519 = 1

  PREINIT:
  protmem *msg_pm = NULL, *sk_pm = NULL;
  unsigned char *msg_buf, *sk_buf, *smsg_buf;
  STRLEN msg_len, sk_len, sk_req_len, sig_len, out_len;
  int (*func)(unsigned char *, unsigned long long *, const unsigned char *,
              unsigned long long, const unsigned char *);

  CODE:
  switch(ix) {
    case 1:
      sk_req_len = crypto_sign_ed25519_SECRETKEYBYTES;
      sig_len = crypto_sign_ed25519_BYTES;
      func = crypto_sign_ed25519;
      break;
    default:
      sk_req_len = crypto_sign_SECRETKEYBYTES;
      sig_len = crypto_sign_BYTES;
      func = crypto_sign;
  }

  if (sv_derived_from(msg, MEMVAULT_CLASS)) {
    msg_pm = protmem_get(aTHX_ msg, MEMVAULT_CLASS);
    msg_buf = msg_pm->pm_ptr;
    msg_len = msg_pm->size;
  }
  else
    msg_buf = (unsigned char *)SvPVbyte(msg, msg_len);

  if (SIZE_MAX - sig_len < msg_len)
    croak("Message too large");
  out_len = msg_len + sig_len;

  if (sv_derived_from(sk, MEMVAULT_CLASS)) {
    sk_pm = protmem_get(aTHX_ sk, MEMVAULT_CLASS);
    sk_buf = sk_pm->pm_ptr;
    sk_len = sk_pm->size;

inc/sign.xs  view on Meta::CPAN


  OUTPUT:
  RETVAL

SV * sign_init(SV * flags = &PL_sv_undef)

  ALIAS:
  sign_ed25519_init = 1

  PREINIT:
  protmem *state_pm;
  unsigned int state_flags = g_protmem_default_flags_state;

  CODE:
  SvGETMAGIC(flags);
  if (SvOK(flags))
    state_flags = SvUV_nomg(flags);

  switch(ix) {
    case 1:
      state_pm = protmem_init(aTHX_ sizeof(crypto_sign_ed25519ph_state), state_flags);
      if (state_pm == NULL)
        croak("sign_init: Failed to allocate state protmem");
      crypto_sign_ed25519ph_init(state_pm->pm_ptr);
      break;
    default:
      state_pm = protmem_init(aTHX_ sizeof(crypto_sign_state), state_flags);
      if (state_pm == NULL)
        croak("sign_init: Failed to allocate state protmem");
      crypto_sign_init(state_pm->pm_ptr);
  }

  if (protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
    protmem_free(aTHX_ state_pm);
    croak("sign_init: Failed to release state protmem RW");
  }

  switch(ix) {
    case 1:
      RETVAL = protmem_to_sv(aTHX_ state_pm, "Crypt::Sodium::XS::sign::ed25519ph_multi");
      break;
    default:
      RETVAL = protmem_to_sv(aTHX_ state_pm, "Crypt::Sodium::XS::sign::multi"); }

  OUTPUT:
  RETVAL

void sign_keypair(SV * seed = &PL_sv_undef, SV * flags = &PL_sv_undef)

  ALIAS:
  sign_ed25519_keypair = 1

  PREINIT:
  protmem *seed_pm = NULL, *sk_pm;
  SV *pk_sv;
  unsigned char *pk_buf, *seed_buf;
  STRLEN seed_req_len, seed_len;
  STRLEN pk_len, sk_len;
  unsigned int sk_flags = g_protmem_default_flags_key;

  PPCODE:
  SvGETMAGIC(flags);
  if (SvOK(flags))
    sk_flags = SvUV_nomg(flags);

  switch(ix) {
    case 1:
      seed_req_len = crypto_sign_ed25519_SEEDBYTES;
      pk_len = crypto_sign_ed25519_PUBLICKEYBYTES;
      sk_len = crypto_sign_ed25519_SECRETKEYBYTES;
      break;
    default:
      seed_req_len = crypto_sign_SEEDBYTES;
      pk_len = crypto_sign_PUBLICKEYBYTES;
      sk_len = crypto_sign_SECRETKEYBYTES;
  }

  Newx(pk_buf, pk_len + 1, unsigned char);
  if (pk_buf == NULL)
    croak("sign_keypair: Failed to allocate memory");
  pk_buf[pk_len] = '\0';

  SvGETMAGIC(seed);
  if (!SvOK(seed)) {
    sk_pm = protmem_init(aTHX_ sk_len, sk_flags);
    if (sk_pm == NULL) {
      Safefree(pk_buf);
      croak("sign_keypair: Failed to allocate protmem");
    }
    switch(ix) {
      case 1:
        crypto_sign_ed25519_keypair(pk_buf, sk_pm->pm_ptr);
        break;
      default:
        crypto_sign_keypair(pk_buf, sk_pm->pm_ptr);
    }
  }
  else {
    /* from seed */
    if (sv_derived_from(seed, MEMVAULT_CLASS)) {
      seed_pm = protmem_get(aTHX_ seed, MEMVAULT_CLASS);
      seed_buf = seed_pm->pm_ptr;
      seed_len = seed_pm->size;
    }
    else
      seed_buf = (unsigned char *)SvPVbyte_nomg(seed, seed_len);
    if (seed_len != seed_req_len) {
      Safefree(pk_buf);
      croak("sign_keypair: Invalid seed length: %lu", seed_len);
    }

    sk_pm = protmem_init(aTHX_ sk_len, g_protmem_default_flags_key);
    if (sk_pm == NULL) {
      Safefree(pk_buf);
      croak("sign_keypair: Failed to allocate protmem");
    }

    if (seed_pm && protmem_grant(aTHX_ seed_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
      protmem_free(aTHX_ sk_pm);
      Safefree(pk_buf);
      croak("sign_keypair: Failed to grant seed protmem RO");

inc/sign.xs  view on Meta::CPAN


    msg_pm = protmem_init(aTHX_ smsg_len - sig_len, smsg_pm->flags);
    if (msg_pm == NULL)
      croak("sign_open: Failed to allocate protmem");

    if (protmem_grant(aTHX_ smsg_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
      protmem_free(aTHX_ msg_pm);
      croak("sign_open: Failed to grant signed message protmem RO");
    }

    if (func(msg_pm->pm_ptr, NULL, smsg_buf, smsg_len, pk_buf) != 0) {
      protmem_release(aTHX_ smsg_pm, PROTMEM_FLAG_MPROTECT_RO);
      protmem_free(aTHX_ msg_pm);
      croak("sign_open: Signature forged");
    }

    if (protmem_release(aTHX_ smsg_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
      protmem_free(aTHX_ msg_pm);
      croak("sign_open: Failed to release signed message protmem RO");
    }

    if (protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
      protmem_free(aTHX_ msg_pm);
      croak("sign_open: Failed to release msg protmem RO");
    }

    RETVAL = protmem_to_sv(aTHX_ msg_pm, MEMVAULT_CLASS);
  }
  else {
    STRLEN msg_len = smsg_len - sig_len;

    Newx(msg_buf, msg_len + 1, unsigned char);
    if (msg_buf == NULL)
      croak("sign_open: Failed to allocate memory");
    msg_buf[msg_len] = '\0';

    if (func(msg_buf, NULL, smsg_buf, smsg_len, pk_buf) != 0) {
      Safefree(msg_buf);
      croak("sign_open: Signature forged");
    }

    RETVAL = newSV(0);
    sv_usepvn_flags(RETVAL, (char *)msg_buf, msg_len, SV_HAS_TRAILING_NUL);
  }

  OUTPUT:
  RETVAL

void sign_to_curve25519(SV * pk, SV * sk, SV * flags = &PL_sv_undef)

  ALIAS:
  sign_ed25519_to_curve25519 = 1

  PREINIT:
  protmem *sk_pm = NULL, *sk_ed_pm;
  SV *pk_ed_sv;
  unsigned char *pk_buf, *sk_buf, *pk_ed_buf;
  STRLEN pk_len, sk_len;
  unsigned int sk_flags = g_protmem_default_flags_key;

  PPCODE:
  PERL_UNUSED_VAR(ix);

  SvGETMAGIC(flags);
  if (SvOK(flags))
    sk_flags = SvUV_nomg(flags);

  pk_buf = (unsigned char *)SvPVbyte(pk, pk_len);
  if (pk_len != crypto_sign_ed25519_PUBLICKEYBYTES)
    croak("sign_to_curve25519: Invalid public key length %lu", pk_len);

  if (sv_derived_from(sk, MEMVAULT_CLASS)) {
    sk_pm = protmem_get(aTHX_ sk, MEMVAULT_CLASS);
    sk_buf = sk_pm->pm_ptr;
    sk_len = sk_pm->size;
  }
  else
    sk_buf = (unsigned char *)SvPVbyte(sk, sk_len);
  if (sk_len != crypto_sign_ed25519_SECRETKEYBYTES)
    croak("sign_to_curve25519: Invalid secret key length %lu", sk_len);

  Newx(pk_ed_buf, crypto_scalarmult_curve25519_BYTES + 1, unsigned char);
  if (pk_ed_buf == NULL)
    croak("sign_to_curve25519: Failed to allocate memory");
  pk_ed_buf[crypto_scalarmult_curve25519_BYTES] = '\0';

  if (crypto_sign_ed25519_pk_to_curve25519(pk_ed_buf, pk_buf) != 0) {
    Safefree(pk_ed_buf);
    croak("sign_to_curve25519: Failed to convert public key to curve25519");
  }

  sk_ed_pm = protmem_init(aTHX_ crypto_scalarmult_curve25519_BYTES, sk_flags);
  if (sk_ed_pm == NULL) {
    Safefree(pk_ed_buf);
    croak("sign_to_curve25519: Failed to allocate protmem");
  }

  if (sk_pm && protmem_grant(aTHX_ sk_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
    Safefree(pk_ed_buf);
    protmem_free(aTHX_ sk_ed_pm);
    croak("sign_to_curve25519: Failed to grant sk protmem RO");
  }

  if (crypto_sign_ed25519_sk_to_curve25519(sk_ed_pm->pm_ptr, sk_buf) != 0) {
    Safefree(pk_ed_buf);
    protmem_free(aTHX_ sk_ed_pm);
    if (sk_pm)
      protmem_release(aTHX_ sk_pm, PROTMEM_FLAG_MPROTECT_RO);
    croak("sign_to_curve25519: Failed to convert secret key to curve25519");
  }

  if (sk_pm && protmem_release(aTHX_ sk_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
    Safefree(pk_ed_buf);
    protmem_free(aTHX_ sk_ed_pm);
    croak("sign_to_curve25519: Failed to release sk protmem RO");
  }

  if (protmem_release(aTHX_ sk_ed_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
    Safefree(pk_ed_buf);
    protmem_free(aTHX_ sk_ed_pm);
    croak("sign_to_curve25519: Failed to release ed protmem RO");
  }

  pk_ed_sv = newSV(0);
  sv_usepvn_flags(pk_ed_sv, (char *)pk_ed_buf, crypto_scalarmult_curve25519_BYTES,
                  SV_HAS_TRAILING_NUL);
  mXPUSHs(pk_ed_sv);
  mXPUSHs(protmem_to_sv(aTHX_ sk_ed_pm, MEMVAULT_CLASS));
  XSRETURN(2);

void sign_verify(SV * msg, SV * sig, SV * pk)

  ALIAS:
  sign_ed25519_verify = 1

  PREINIT:
  protmem *msg_pm = NULL;
  unsigned char *msg_buf, *sig_buf, *pk_buf;
  STRLEN msg_len, sig_len, pk_len, sig_req_len, pk_req_len;
  int ret;
  int (*func)(const unsigned char *, const unsigned char *,
              unsigned long long, const unsigned char *);

  PPCODE:
  switch(ix) {
    case 1:
      sig_req_len = crypto_sign_ed25519_BYTES;
      pk_req_len = crypto_sign_ed25519_PUBLICKEYBYTES;
      func = crypto_sign_ed25519_verify_detached;
      break;
    default:
      sig_req_len = crypto_sign_BYTES;
      pk_req_len = crypto_sign_PUBLICKEYBYTES;
      func = crypto_sign_verify_detached;
  }

  sig_buf = (unsigned char *)SvPVbyte(sig, sig_len);
  if (sig_len != sig_req_len)
    croak("sign_verify: Invalid signature length %lu", sig_len);

  pk_buf = (unsigned char *)SvPVbyte(pk, pk_len);
  if (pk_len != pk_req_len)
    croak("sign_verify: Invalid public key length %lu", pk_len);

  if (sv_derived_from(msg, MEMVAULT_CLASS)) {
    msg_pm = protmem_get(aTHX_ msg, MEMVAULT_CLASS);
    msg_buf = msg_pm->pm_ptr;
    msg_len = msg_pm->size;
  }
  else
    msg_buf = (unsigned char *)SvPVbyte(msg, msg_len);

  if (msg_pm && protmem_grant(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO) != 0)
    croak("sign_verify: Failed to grant msg protmem RO");

  ret = func(sig_buf, msg_buf, msg_len, pk_buf);

  if (msg_pm && protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO) != 0)
    croak("sign_verify: Failed to release msg protmem RO");

  if (ret == 0)
    XSRETURN_YES;

  XSRETURN_NO;

MODULE = Crypt::Sodium::XS PACKAGE = Crypt::Sodium::XS::sign::multi

void DESTROY(SV * self)

  ALIAS:
  Crypt::Sodium::XS::sign::ed25519ph_multi::DESTROY = 1

  PREINIT:
  protmem *state_pm;

  CODE:
  switch(ix) {
    case 1:
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::ed25519ph_multi");
      break;
    default:
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::multi");
  }
  protmem_free(aTHX_ state_pm);

inc/sign.xs  view on Meta::CPAN

    croak("final_sign: Failed to grant sk protmem RO");
  }

  switch(ix) {
    case 1:
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::ed25519ph_multi");
      break;
    default:
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::multi");
  }
  if (protmem_grant(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
    Safefree(sig_buf);
    if (sk_pm)
      protmem_release(aTHX_ sk_pm, PROTMEM_FLAG_MPROTECT_RO);
    croak("final_sign: Failed to grant state protmem RW");
  }

  switch(ix) {
    case 1:
      crypto_sign_ed25519ph_final_create(state_pm->pm_ptr, sig_buf, NULL, sk_buf);
      break;
    default:
      crypto_sign_final_create(state_pm->pm_ptr, sig_buf, NULL, sk_buf);
  }

  if (protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
    Safefree(sig_buf);
    if (sk_pm)
      protmem_release(aTHX_ sk_pm, PROTMEM_FLAG_MPROTECT_RO);
    croak("final_sign: Failed to release state protmem RW");
  }

  if (sk_pm && protmem_release(aTHX_ sk_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
    Safefree(sig_buf);
    croak("final_sign: Failed to release sk protmem RO");
  }

  RETVAL = newSV(0);
  switch(ix) {
    case 1:
      sv_usepvn_flags(RETVAL, (char *)sig_buf, crypto_sign_ed25519_BYTES, SV_HAS_TRAILING_NUL);
      break;
    default:
      sv_usepvn_flags(RETVAL, (char *)sig_buf, crypto_sign_BYTES, SV_HAS_TRAILING_NUL);
  }

  OUTPUT:
  RETVAL

void final_verify(SV * self, SV * sig, SV * pk)

  ALIAS:
  Crypt::Sodium::XS::sign::ed25519ph_multi::final_verify = 1

  PREINIT:
  protmem *state_pm;
  unsigned char *sig_buf, *pk_buf;
  STRLEN sig_len, pk_len;
  int ret;

  PPCODE:
  sig_buf = (unsigned char *)SvPVbyte(sig, sig_len);
  pk_buf = (unsigned char *)SvPVbyte(pk, pk_len);

  switch(ix) {
    case 1:
      if (sig_len != crypto_sign_ed25519_BYTES)
        croak("final_verify: Invalid signature length %lu", sig_len);
      if (pk_len != crypto_sign_ed25519_PUBLICKEYBYTES)
        croak("final_verify: Invalid public key length %lu", pk_len);
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::ed25519ph_multi");
      break;
    default:
      if (sig_len != crypto_sign_BYTES)
        croak("final_verify: Invalid signature length %lu", sig_len);
      if (pk_len != crypto_sign_PUBLICKEYBYTES)
        croak("final_verify: Invalid public key length %lu", pk_len);
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::multi");
  }

  if (protmem_grant(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0)
    croak("final_verify: Failed to grant state protmem RW");

  switch(ix) {
    case 1:
      ret = crypto_sign_ed25519ph_final_verify(state_pm->pm_ptr, sig_buf, pk_buf);
      break;
    default:
      ret = crypto_sign_final_verify(state_pm->pm_ptr, sig_buf, pk_buf);
  }

  if (protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0)
    croak("final_verify: Failed to release state protmem RW");

  if (ret == 0)
    XSRETURN_YES;

  XSRETURN_NO;

void update(SV * self, ...)

  ALIAS:
  Crypt::Sodium::XS::sign::ed25519ph_multi::update = 1

  PREINIT:
  protmem *state_pm, *msg_pm;
  unsigned char *msg_buf;
  STRLEN msg_len;
  I32 i;

  PPCODE:
  switch(ix) {
    case 1:
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::ed25519ph_multi");
      break;
    default:
      state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::sign::multi");
  }
  if (protmem_grant(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0)
    croak("update: Failed to grant state protmem RW");

  for (i = 1; i < items; i++) {
    if (sv_derived_from(ST(i), MEMVAULT_CLASS)) {
      msg_pm = protmem_get(aTHX_ ST(i), MEMVAULT_CLASS);
      msg_buf = msg_pm->pm_ptr;
      msg_len = msg_pm->size;
    }
    else
      msg_buf = (unsigned char *)SvPVbyte(ST(i), msg_len);

    if (msg_pm && protmem_grant(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
      protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW);
      croak("update: Failed to grant msg protmem RO");
    }

    switch(ix) {
      case 1:
        crypto_sign_ed25519ph_update(state_pm->pm_ptr, msg_buf, msg_len);
        break;
      default:
        crypto_sign_update(state_pm->pm_ptr, msg_buf, msg_len);
    }

    if (msg_pm && protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
      protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW);
      croak("update: Failed to release msg protmem RO");
    }

    msg_pm = NULL;
  }

  if (protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0)
    croak("update: Failed to release state protmem RW");

  XSRETURN(1);



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