Search code examples
opensslprintfpass-by-referencepass-by-valuemessage-digest

printing contents from MD_CTX


I am trying to understand how the hashing functions in md_rand.c works. Suppose I declare a variable MD_CTX m, and I am trying to see the contents of m after each MD_Update function.

MD_Init(&m);
printf("%X\n",*(&m));
MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
printf("%X\n",*(&m));
MD_Update(&m,local_md,MD_DIGEST_LENGTH);
printf("%X\n",*(&m));
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
MD_Update(&m,md,MD_DIGEST_LENGTH);
printf("%X\n",*(&m));       
MD_Final(md,&m);

However, I always get the same value printed out for all 4 printf statements after every MD_Update. What should I do to get the updated value in m?


Solution

  • What should I do to get the updated value in m?

    When you printf("%X\n",*(&m));, you are just printing the address of MD_CTX on the stack. It never changes, hence the reason for your observations.

    A MD_CTX is an opaque structure, meaning you are not supposed to look into it. Its a typedef, and you can locate it with:

    $ cd openssl-1.0.2d
    $ grep -R EVP_MD * | grep struct | egrep "(\.h|\.c)"
    crypto/ossl_typ.h:typedef struct env_md_st EVP_MD;
    crypto/ossl_typ.h:typedef struct env_md_ctx_st EVP_MD_CTX;
    engines/ccgost/gost_lcl.h:/* EVP_MD structure for GOST R 34.11 */
    engines/ccgost/gost_lcl.h:/* EVP_MD structure for GOST 28147 in MAC mode */
    include/openssl/ossl_typ.h:typedef struct env_md_st EVP_MD;
    include/openssl/ossl_typ.h:typedef struct env_md_ctx_st EVP_MD_CTX;
    

    Then, following struct env_md_ctx_st:

    $ grep -R "struct env_md_ctx_st" * | grep "{"
    crypto/evp/evp.h:struct env_md_ctx_st {
    include/openssl/evp.h:struct env_md_ctx_st {
    

    And finally, from evp.h around line 260:

    struct env_md_ctx_st {
        const EVP_MD *digest;
        ENGINE *engine;             /* functional reference if 'digest' is
                                     * ENGINE-provided */
        unsigned long flags;
        void *md_data;
        /* Public key context for sign/verify */
        EVP_PKEY_CTX *pctx;
        /* Update function: usually copied from EVP_MD */
        int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
    } /* EVP_MD_CTX */ ;
    

    And here's a related struct from around line 160:

    struct env_md_st {
        int type;
        int pkey_type;
        int md_size;
        unsigned long flags;
        int (*init) (EVP_MD_CTX *ctx);
        int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
        int (*final) (EVP_MD_CTX *ctx, unsigned char *md);
        int (*copy) (EVP_MD_CTX *to, const EVP_MD_CTX *from);
        int (*cleanup) (EVP_MD_CTX *ctx);
        /* FIXME: prototype these some day */
        int (*sign) (int type, const unsigned char *m, unsigned int m_length,
                     unsigned char *sigret, unsigned int *siglen, void *key);
        int (*verify) (int type, const unsigned char *m, unsigned int m_length,
                       const unsigned char *sigbuf, unsigned int siglen,
                       void *key);
        int required_pkey_type[5];  /* EVP_PKEY_xxx */
        int block_size;
        int ctx_size;               /* how big does the ctx->md_data need to be */
        /* control function */
        int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
    } /* EVP_MD */ ;