Crypt-OpenSSL-RSA

 view release on metacpan or  search on metacpan

RSA.xs  view on Meta::CPAN


    THROW(RETVAL = make_rsa_obj(proto, rsa));
    goto end;

    err:
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        /* On 3.x, push_BN copies, so originals are always ours to free.
           On pre-3.x, RSA_set0_key/set0_factors may have taken ownership,
           so these are intentionally skipped (risk of double-free). */
        BN_clear_free(n);
        BN_clear_free(e);
        BN_clear_free(d);
        BN_clear_free(p);
        BN_clear_free(q);
#endif
        if (p_minus_1) BN_clear_free(p_minus_1);
        if (q_minus_1) BN_clear_free(q_minus_1);
        if (dmp1) BN_clear_free(dmp1);
        if (dmq1) BN_clear_free(dmq1);
        if (iqmp) BN_clear_free(iqmp);
        if (ctx) BN_CTX_free(ctx);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        if (pctx) { EVP_PKEY_CTX_free(pctx); pctx = NULL; }
        if (params_build) { OSSL_PARAM_BLD_free(params_build); params_build = NULL; }
        if (params) { OSSL_PARAM_free(params); params = NULL; }
#endif
        if (error)
        {
            EVP_PKEY_free(rsa);
            CHECK_OPEN_SSL(0);
        }
    }
    end:

  OUTPUT:
    RETVAL

void
_get_key_parameters(p_rsa)
    rsaData* p_rsa;
PREINIT:
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    BIGNUM* n = NULL;
    BIGNUM* e = NULL;
    BIGNUM* d = NULL;
    BIGNUM* p = NULL;
    BIGNUM* q = NULL;
    BIGNUM* dmp1 = NULL;
    BIGNUM* dmq1 = NULL;
    BIGNUM* iqmp = NULL;
#else
    const BIGNUM* n;
    const BIGNUM* e;
    const BIGNUM* d;
    const BIGNUM* p;
    const BIGNUM* q;
    const BIGNUM* dmp1;
    const BIGNUM* dmq1;
    const BIGNUM* iqmp;
#endif
PPCODE:
{
    EVP_PKEY* rsa;
    rsa = p_rsa->rsa;
#if OLD_CRUFTY_SSL_VERSION
    n = rsa->n;
    e = rsa->e;
    d = rsa->d;
    p = rsa->p;
    q = rsa->q;
    dmp1 = rsa->dmp1;
    dmq1 = rsa->dmq1;
    iqmp = rsa->iqmp;
#else
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    /* n and e are mandatory for every RSA key — croak on failure. */
    if (!EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_N, &n))
        croakSsl(__FILE__, __LINE__);
    if (!EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_E, &e)) {
        BN_free(n);
        croakSsl(__FILE__, __LINE__);
    }
    /* Private components are absent for public keys — EVP_PKEY_get_bn_param()
       returns 0 and may push errors onto the queue, but the pointer stays NULL
       so cor_bn2sv() will return undef.  This matches the pre-3.x behaviour
       where RSA_get0_key/factors/crt_params simply set NULL for missing fields. */
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_D, &d);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_FACTOR1, &p);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_FACTOR2, &q);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_EXPONENT1, &dmp1);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_EXPONENT2, &dmq1);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &iqmp);
    /* Failed calls (e.g. private params on a public key) push errors
       onto the OpenSSL error queue.  Drain them so they don't leak
       into the next croakSsl() call from an unrelated operation. */
    ERR_clear_error();
#else
    RSA_get0_key(rsa, &n, &e, &d);
    RSA_get0_factors(rsa, &p, &q);
    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
#endif
#endif
    XPUSHs(cor_bn2sv(n));
    XPUSHs(cor_bn2sv(e));
    XPUSHs(cor_bn2sv(d));
    XPUSHs(cor_bn2sv(p));
    XPUSHs(cor_bn2sv(q));
    XPUSHs(cor_bn2sv(dmp1));
    XPUSHs(cor_bn2sv(dmq1));
    XPUSHs(cor_bn2sv(iqmp));
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    /* EVP_PKEY_get_bn_param() allocates new BIGNUMs (unlike the pre-3.x
       getters which return internal pointers).  cor_bn2sv() duplicates
       them via BN_dup(), so we must free the originals here. */
    BN_free(n);
    BN_free(e);
    BN_clear_free(d);
    BN_clear_free(p);
    BN_clear_free(q);
    BN_clear_free(dmp1);
    BN_clear_free(dmq1);

RSA.xs  view on Meta::CPAN

        croak("Public keys cannot sign messages");
    }

    unsigned char digest_buf[EVP_MAX_MD_SIZE];
    CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode, digest_buf));
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */);
    THROW(ctx);
    THROW(EVP_PKEY_sign_init(ctx));
    THROW(setup_pss_sign_ctx(ctx, p_rsa->padding, p_rsa->hashMode, &md));
    THROW(EVP_PKEY_sign(ctx, NULL, &signature_length, digest, get_digest_length(p_rsa->hashMode)) == 1);

    Newx(signature, signature_length, UNSIGNED_CHAR);
    THROW(signature);

    THROW(EVP_PKEY_sign(ctx, signature, &signature_length, digest, get_digest_length(p_rsa->hashMode)) == 1);

    EVP_MD_free(md);
    EVP_PKEY_CTX_free(ctx);

    goto sign_done;
    err:
        Safefree(signature);
        if (md) EVP_MD_free(md);
        if (ctx) EVP_PKEY_CTX_free(ctx);
        CHECK_OPEN_SSL(0);
    sign_done:
#else
    CHECK_NEW(signature, EVP_PKEY_get_size(p_rsa->rsa), UNSIGNED_CHAR);
    if (!RSA_sign(p_rsa->hashMode,
                  digest,
                  get_digest_length(p_rsa->hashMode),
                  (unsigned char*) signature,
                  &signature_length,
                  p_rsa->rsa))
    {
        Safefree(signature);
        croakSsl(__FILE__, __LINE__);
    }
#endif
    RETVAL = newSVpvn((const char* )signature, signature_length);
    Safefree(signature);
}
  OUTPUT:
    RETVAL

# Verify signature. Returns true if correct, false otherwise.

void
verify(p_rsa, text_SV, sig_SV)
    rsaData* p_rsa;
    SV* text_SV;
    SV* sig_SV;
PREINIT:
    int verify_result;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    int error = 0;
    EVP_PKEY_CTX *ctx = NULL;
    EVP_MD *md = NULL;
#endif
PPCODE:
{
    unsigned char* sig;
    unsigned char* digest;
    STRLEN sig_length;

    sig = (unsigned char*) SvPV(sig_SV, sig_length);
    if (EVP_PKEY_get_size(p_rsa->rsa) < sig_length)
    {
        croak("Signature longer than key");
    }

    unsigned char digest_buf[EVP_MAX_MD_SIZE];
    CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode, digest_buf));
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */);
    THROW(ctx);
    THROW(EVP_PKEY_verify_init(ctx) == 1);
    THROW(setup_pss_sign_ctx(ctx, p_rsa->padding, p_rsa->hashMode, &md));

    verify_result = EVP_PKEY_verify(ctx, sig, sig_length, digest, get_digest_length(p_rsa->hashMode));
    EVP_MD_free(md);
    EVP_PKEY_CTX_free(ctx);

    goto verify_switch;
    err:
        if (md) EVP_MD_free(md);
        if (ctx) EVP_PKEY_CTX_free(ctx);
        CHECK_OPEN_SSL(0);
    verify_switch: ;
#else
    verify_result = RSA_verify(p_rsa->hashMode,
                      digest,
                      get_digest_length(p_rsa->hashMode),
                      sig,
                      sig_length,
                      p_rsa->rsa);
#endif
    switch(verify_result)
    {
        case 0:
            ERR_clear_error();
            XSRETURN_NO;
            break;
        case 1:
            XSRETURN_YES;
            break;
        default:
            CHECK_OPEN_SSL(0);
            break;
    }
}

int
is_private(p_rsa)
    rsaData* p_rsa;
  CODE:
    RETVAL = _is_private(p_rsa);
  OUTPUT:
    RETVAL



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