On Wed, Jan 05, 2022 at 10:43:33AM +0100, Theo Buehler wrote:
> This is needed for the upcoming libcrypto bump. While it would be better
> to do error checking for EVP_Digest* (for example EVP_DigestInit*
> usually allocates internally), I kept the change as mechanical as
> possible and left that one for someone else to fix.

Here's a better diff. As found by martijn, one EVP_MD_CTX_free() should
have been a EVP_MD_CTX_reset().

Index: usr.bin/snmp/usm.c
===================================================================
RCS file: /cvs/src/usr.bin/snmp/usm.c,v
retrieving revision 1.5
diff -u -p -r1.5 usm.c
--- usr.bin/snmp/usm.c  24 Oct 2019 12:39:26 -0000      1.5
+++ usr.bin/snmp/usm.c  5 Jan 2022 09:37:40 -0000
@@ -252,7 +252,7 @@ static char *
 usm_crypt(const EVP_CIPHER *cipher, int do_enc, char *key,
     struct usm_cookie *cookie, char *serialpdu, size_t pdulen, size_t *outlen)
 {
-       EVP_CIPHER_CTX ctx;
+       EVP_CIPHER_CTX *ctx;
        size_t i;
        char iv[EVP_MAX_IV_LENGTH];
        char *salt = (char *)&(cookie->salt);
@@ -279,28 +279,34 @@ usm_crypt(const EVP_CIPHER *cipher, int 
                return NULL;
        }
 
-       bzero(&ctx, sizeof(ctx));
-       if (!EVP_CipherInit(&ctx, cipher, key, iv, do_enc))
+       if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
                return NULL;
 
-       EVP_CIPHER_CTX_set_padding(&ctx, do_enc);
+       if (!EVP_CipherInit(ctx, cipher, key, iv, do_enc)) {
+               EVP_CIPHER_CTX_free(ctx);
+               return NULL;
+       }
+
+       EVP_CIPHER_CTX_set_padding(ctx, do_enc);
 
        bs = EVP_CIPHER_block_size(cipher);
        /* Maximum output size */
        *outlen = pdulen + (bs - (pdulen % bs));
 
-       if ((outtext = malloc(*outlen)) == NULL)
+       if ((outtext = malloc(*outlen)) == NULL) {
+               EVP_CIPHER_CTX_free(ctx);
                return NULL;
+       }
 
-       if (EVP_CipherUpdate(&ctx, outtext, &len, serialpdu, pdulen) &&
-           EVP_CipherFinal_ex(&ctx, outtext + len, &len2))
+       if (EVP_CipherUpdate(ctx, outtext, &len, serialpdu, pdulen) &&
+           EVP_CipherFinal_ex(ctx, outtext + len, &len2))
                *outlen = len + len2;
        else {
                free(outtext);
                outtext = NULL;
        }
 
-       EVP_CIPHER_CTX_cleanup(&ctx);
+       EVP_CIPHER_CTX_free(ctx);
 
        return outtext;
 }
@@ -616,7 +622,7 @@ usm_setbootstime(struct snmp_sec *sec, u
 static char *
 usm_passwd2mkey(const EVP_MD *md, const char *passwd)
 {
-       EVP_MD_CTX ctx;
+       EVP_MD_CTX *ctx;
        int i, count;
        const u_char *pw;
        u_char *c;
@@ -624,8 +630,9 @@ usm_passwd2mkey(const EVP_MD *md, const 
        unsigned dlen;
        char *key;
 
-       bzero(&ctx, sizeof(ctx));
-       EVP_DigestInit_ex(&ctx, md, NULL);
+       if ((ctx = EVP_MD_CTX_new()) == NULL)
+               return NULL;
+       EVP_DigestInit_ex(ctx, md, NULL);
        pw = (const u_char *)passwd;
        for (count = 0; count < 1048576; count += 64) {
                c = keybuf;
@@ -634,10 +641,10 @@ usm_passwd2mkey(const EVP_MD *md, const 
                                pw = (const u_char *)passwd;
                        *c++ = *pw++;
                }
-               EVP_DigestUpdate(&ctx, keybuf, 64);
+               EVP_DigestUpdate(ctx, keybuf, 64);
        }
-       EVP_DigestFinal_ex(&ctx, keybuf, &dlen);
-       EVP_MD_CTX_cleanup(&ctx);
+       EVP_DigestFinal_ex(ctx, keybuf, &dlen);
+       EVP_MD_CTX_free(ctx);
 
        if ((key = malloc(dlen)) == NULL)
                return NULL;
@@ -648,20 +655,21 @@ usm_passwd2mkey(const EVP_MD *md, const 
 static char *
 usm_mkey2lkey(struct usm_sec *usm, const EVP_MD *md, const char *mkey)
 {
-       EVP_MD_CTX ctx;
+       EVP_MD_CTX *ctx;
        u_char buf[EVP_MAX_MD_SIZE];
        u_char *lkey;
        unsigned lklen;
 
-       bzero(&ctx, sizeof(ctx));
-       EVP_DigestInit_ex(&ctx, md, NULL);
+       if ((ctx = EVP_MD_CTX_new()) == NULL)
+               return NULL;
+       EVP_DigestInit_ex(ctx, md, NULL);
 
-       EVP_DigestUpdate(&ctx, mkey, EVP_MD_size(md));
-       EVP_DigestUpdate(&ctx, usm->engineid, usm->engineidlen);
-       EVP_DigestUpdate(&ctx, mkey, EVP_MD_size(md));
+       EVP_DigestUpdate(ctx, mkey, EVP_MD_size(md));
+       EVP_DigestUpdate(ctx, usm->engineid, usm->engineidlen);
+       EVP_DigestUpdate(ctx, mkey, EVP_MD_size(md));
 
-       EVP_DigestFinal_ex(&ctx, buf, &lklen);
-       EVP_MD_CTX_cleanup(&ctx);
+       EVP_DigestFinal_ex(ctx, buf, &lklen);
+       EVP_MD_CTX_free(ctx);
 
        if ((lkey = malloc(lklen)) == NULL)
                return NULL;
Index: usr.sbin/snmpd/usm.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/usm.c,v
retrieving revision 1.21
diff -u -p -r1.21 usm.c
--- usr.sbin/snmpd/usm.c        1 Aug 2021 11:30:56 -0000       1.21
+++ usr.sbin/snmpd/usm.c        5 Jan 2022 10:25:44 -0000
@@ -650,7 +650,7 @@ usm_crypt(struct snmp_message *msg, u_ch
        int do_encrypt)
 {
        const EVP_CIPHER        *cipher;
-       EVP_CIPHER_CTX           ctx;
+       EVP_CIPHER_CTX          *ctx;
        u_char                  *privkey;
        int                      i;
        u_char                   iv[EVP_MAX_IV_LENGTH];
@@ -683,19 +683,24 @@ usm_crypt(struct snmp_message *msg, u_ch
                return -1;
        }
 
-       if (!EVP_CipherInit(&ctx, cipher, privkey, iv, do_encrypt))
+       if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
                return -1;
 
+       if (!EVP_CipherInit(ctx, cipher, privkey, iv, do_encrypt)) {
+               EVP_CIPHER_CTX_free(ctx);
+               return -1;
+       }
+
        if (!do_encrypt)
-               EVP_CIPHER_CTX_set_padding(&ctx, 0);
+               EVP_CIPHER_CTX_set_padding(ctx, 0);
 
-       if (EVP_CipherUpdate(&ctx, outbuf, &len, inbuf, inlen) &&
-           EVP_CipherFinal_ex(&ctx, outbuf + len, &len2))
+       if (EVP_CipherUpdate(ctx, outbuf, &len, inbuf, inlen) &&
+           EVP_CipherFinal_ex(ctx, outbuf + len, &len2))
                rv = len + len2;
        else
                rv = -1;
 
-       EVP_CIPHER_CTX_cleanup(&ctx);
+       EVP_CIPHER_CTX_free(ctx);
        return rv;
 }
 
@@ -705,7 +710,7 @@ usm_crypt(struct snmp_message *msg, u_ch
 char *
 usm_passwd2key(const EVP_MD *md, char *passwd, int *maxlen)
 {
-       EVP_MD_CTX       ctx;
+       EVP_MD_CTX      *ctx;
        int              i, count;
        u_char          *pw, *c;
        u_char           pwbuf[2 * EVP_MAX_MD_SIZE + SNMPD_MAXENGINEIDLEN];
@@ -713,7 +718,9 @@ usm_passwd2key(const EVP_MD *md, char *p
        unsigned         dlen;
        char            *key;
 
-       EVP_DigestInit(&ctx, md);
+       if ((ctx = EVP_MD_CTX_new()) == NULL)
+               return NULL;
+       EVP_DigestInit(ctx, md);
        pw = (u_char *)passwd;
        for (count = 0; count < 1048576; count += 64) {
                c = pwbuf;
@@ -722,10 +729,10 @@ usm_passwd2key(const EVP_MD *md, char *p
                                pw = (u_char *)passwd;
                        *c++ = *pw++;
                }
-               EVP_DigestUpdate(&ctx, pwbuf, 64);
+               EVP_DigestUpdate(ctx, pwbuf, 64);
        }
-       EVP_DigestFinal(&ctx, keybuf, &dlen);
-       EVP_MD_CTX_cleanup(&ctx);
+       EVP_DigestFinal(ctx, keybuf, &dlen);
+       EVP_MD_CTX_reset(ctx);
 
        /* Localize the key */
 #ifdef DEBUG
@@ -736,10 +743,10 @@ usm_passwd2key(const EVP_MD *md, char *p
            snmpd_env->sc_engineid_len);
        memcpy(pwbuf + dlen + snmpd_env->sc_engineid_len, keybuf, dlen);
 
-       EVP_DigestInit(&ctx, md);
-       EVP_DigestUpdate(&ctx, pwbuf, 2 * dlen + snmpd_env->sc_engineid_len);
-       EVP_DigestFinal(&ctx, keybuf, &dlen);
-       EVP_MD_CTX_cleanup(&ctx);
+       EVP_DigestInit(ctx, md);
+       EVP_DigestUpdate(ctx, pwbuf, 2 * dlen + snmpd_env->sc_engineid_len);
+       EVP_DigestFinal(ctx, keybuf, &dlen);
+       EVP_MD_CTX_free(ctx);
 
        if (*maxlen > 0 && dlen > (unsigned)*maxlen)
                dlen = (unsigned)*maxlen;

Reply via email to