PKCS5_PBKDF2_HMAC_SHA1的返回值是什么意思?

时间:2014-04-04 01:16:51

标签: error-handling openssl pbkdf2

我正在尝试使用OpenSSL的PKCS5_PBKDF2_HMAC_SHA1方法。我认为如果成功则返回0,否则返回其他值。我的问题是,非零回报值意味着什么?内存错误?使用错误?我的程序应如何处理它(重试,退出?)?

编辑:一个必然的问题是,除了对方法本身进行逆向工程之外,还有什么方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:4)

  除了对方法本身进行逆向工程外,还有什么方法可以解决这个问题吗?

PKCS5_PBKDF2_HMAC_SHA1看起来像是那些未记录的函数之一,因为我无法在OpenSSL docs中找到它。 OpenSSL有很多,所以如果你打算使用这个库,你应该准备好研究这些来源。


  

我认为如果成功则返回0,否则返回其他值。

实际上,它已经逆转了。这就是我知道的......

$ grep -R PKCS5_PBKDF2_HMAC_SHA1 *
crypto/evp/evp.h:int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
crypto/evp/p5_crpt2.c:int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
...

因此,您可以在crypto/evp/p5_crpt2.c中找到该函数的实现:

int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
                           const unsigned char *salt, int saltlen, int iter,
                           int keylen, unsigned char *out)
    {
        return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter,
                                 EVP_sha1(), keylen, out);
    }

关注PKCS5_PBKDF2_HMAC

$ grep -R PKCS5_PBKDF2_HMAC *
...
crypto/evp/evp.h:int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
crypto/evp/p5_crpt2.c:int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
...

再次,来自crypto/evp/p5_crpt2.c

int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
                      const unsigned char *salt, int saltlen, int iter,
                      const EVP_MD *digest,
                      int keylen, unsigned char *out)
{
    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
    int cplen, j, k, tkeylen, mdlen;
    unsigned long i = 1;
    HMAC_CTX hctx_tpl, hctx;

    mdlen = EVP_MD_size(digest);
    if (mdlen < 0)
        return 0;

    HMAC_CTX_init(&hctx_tpl);
    p = out;
    tkeylen = keylen;
    if(!pass)
        passlen = 0;
    else if(passlen == -1)
        passlen = strlen(pass);
    if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL))
    {
        HMAC_CTX_cleanup(&hctx_tpl);
        return 0;
    }
    while(tkeylen)
    {
        if(tkeylen > mdlen)
            cplen = mdlen;
        else
            cplen = tkeylen;
        /* We are unlikely to ever use more than 256 blocks (5120 bits!)
         * but just in case...
         */
        itmp[0] = (unsigned char)((i >> 24) & 0xff);
        itmp[1] = (unsigned char)((i >> 16) & 0xff);
        itmp[2] = (unsigned char)((i >> 8) & 0xff);
        itmp[3] = (unsigned char)(i & 0xff);
        if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
        {
            HMAC_CTX_cleanup(&hctx_tpl);
            return 0;
        }
        if (!HMAC_Update(&hctx, salt, saltlen)
            || !HMAC_Update(&hctx, itmp, 4)
            || !HMAC_Final(&hctx, digtmp, NULL))
        {
            HMAC_CTX_cleanup(&hctx_tpl);
            HMAC_CTX_cleanup(&hctx);
            return 0;
        }
        HMAC_CTX_cleanup(&hctx);
        memcpy(p, digtmp, cplen);
        for(j = 1; j < iter; j++)
        {
            if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
            {
                HMAC_CTX_cleanup(&hctx_tpl);
                return 0;
            }
            if (!HMAC_Update(&hctx, digtmp, mdlen)
                || !HMAC_Final(&hctx, digtmp, NULL))
            {
                HMAC_CTX_cleanup(&hctx_tpl);
                HMAC_CTX_cleanup(&hctx);
                return 0;
            }
            HMAC_CTX_cleanup(&hctx);
            for(k = 0; k < cplen; k++)
                p[k] ^= digtmp[k];
        }
        tkeylen-= cplen;
        i++;
        p+= cplen;
    }
    HMAC_CTX_cleanup(&hctx_tpl);

    return 1;
}

因此失败时看起来0,成功时看起来1。你不应该看到其他价值观。如果你得到0,那么所有OUT参数都是垃圾。


  

内存错误?使用错误?

好吧,有时你可以拨打ERR_get_error。如果你调用它并且它有意义,那么错误代码是好的。如果错误代码没有意义,那么它可能不太好。

可悲的是,这就是我处理它的方式,因为库与设置错误代码不一致。例如,这是加载RDRAND引擎的库代码。

请注意,如果是第3代Ivy Bridge(即正在测试的功能),代码会在失败时清除错误代码,否则不会清除或设置错误!!!

void ENGINE_load_rdrand (void)
{
    extern unsigned int OPENSSL_ia32cap_P[];

    if (OPENSSL_ia32cap_P[1] & (1<<(62-32)))
    {
        ENGINE *toadd = ENGINE_rdrand();
        if(!toadd) return;
        ENGINE_add(toadd);
        ENGINE_free(toadd);
        ERR_clear_error();
    }
}

  

我的程序应如何处理它(重试,退出?)?

这看起来像是一场艰难的失败。


最后,这正是我在这种情况下导航资源的方式。如果您不喜欢grep,可以尝试ctags或其他源代码浏览器。