Clean up PKCS5_PBKDF2_HMAC.

This was a mess. HMAC_CTX_copy_ex would avoid having to cleanup and init
the HMAC_CTX repeatedly, but even that is unnecessary. hctx_tpl was just
to reuse the key. Instead, HMAC_CTX already can be reset with the same
key. (Alas, with a slightly odd API, but so it goes.) Do that, and use
goto err to cleanup the error-handling.

Thanks to upstream's b98530d6e09f4cb34c791b8840e936c1fc1467cf for
drawing attention to this. (Though we've diverged significantly from
upstream with all the heap-allocated bits, so I didn't use the change
itself.)

While I'm here, tidy up some variable names and cite the newer RFC.

Change-Id: Ic1259f46b7c5a14dc341b8cee385be5508ac4daf
Reviewed-on: https://boringssl-review.googlesource.com/14605
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/evp/pbkdf.c b/crypto/evp/pbkdf.c
index 1792cdc..daebb2d 100644
--- a/crypto/evp/pbkdf.c
+++ b/crypto/evp/pbkdf.c
@@ -65,83 +65,76 @@
 int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
                       const uint8_t *salt, size_t salt_len, unsigned iterations,
                       const EVP_MD *digest, size_t key_len, uint8_t *out_key) {
-  uint8_t digest_tmp[EVP_MAX_MD_SIZE], *p, itmp[4];
-  size_t cplen, mdlen, tkeylen, k;
-  unsigned j;
+  /* See RFC 8018, section 5.2. */
+  int ret = 0;
+  size_t md_len = EVP_MD_size(digest);
   uint32_t i = 1;
-  HMAC_CTX hctx_tpl, hctx;
+  HMAC_CTX hctx;
+  HMAC_CTX_init(&hctx);
 
-  mdlen = EVP_MD_size(digest);
-  HMAC_CTX_init(&hctx_tpl);
-  p = out_key;
-  tkeylen = key_len;
-  if (!HMAC_Init_ex(&hctx_tpl, password, password_len, digest, NULL)) {
-    HMAC_CTX_cleanup(&hctx_tpl);
-    return 0;
+  if (!HMAC_Init_ex(&hctx, password, password_len, digest, NULL)) {
+    goto err;
   }
-  while (tkeylen) {
-    if (tkeylen > mdlen) {
-      cplen = mdlen;
-    } else {
-      cplen = tkeylen;
+
+  while (key_len > 0) {
+    size_t todo = md_len;
+    if (todo > key_len) {
+      todo = key_len;
     }
-    /* We are unlikely to ever use more than 256 blocks (5120 bits!)
-     * but just in case... */
-    itmp[0] = (uint8_t)((i >> 24) & 0xff);
-    itmp[1] = (uint8_t)((i >> 16) & 0xff);
-    itmp[2] = (uint8_t)((i >> 8) & 0xff);
-    itmp[3] = (uint8_t)(i & 0xff);
-    if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
-      HMAC_CTX_cleanup(&hctx_tpl);
-      return 0;
-    }
-    if (!HMAC_Update(&hctx, salt, salt_len) ||
-        !HMAC_Update(&hctx, itmp, 4) ||
+
+    uint8_t i_buf[4];
+    i_buf[0] = (uint8_t)((i >> 24) & 0xff);
+    i_buf[1] = (uint8_t)((i >> 16) & 0xff);
+    i_buf[2] = (uint8_t)((i >> 8) & 0xff);
+    i_buf[3] = (uint8_t)(i & 0xff);
+
+    /* Compute U_1. */
+    uint8_t digest_tmp[EVP_MAX_MD_SIZE];
+    if (!HMAC_Init_ex(&hctx, NULL, 0, NULL, NULL) ||
+        !HMAC_Update(&hctx, salt, salt_len) ||
+        !HMAC_Update(&hctx, i_buf, 4) ||
         !HMAC_Final(&hctx, digest_tmp, NULL)) {
-      HMAC_CTX_cleanup(&hctx_tpl);
-      HMAC_CTX_cleanup(&hctx);
-      return 0;
+      goto err;
     }
-    HMAC_CTX_cleanup(&hctx);
-    OPENSSL_memcpy(p, digest_tmp, cplen);
-    for (j = 1; j < iterations; j++) {
-      if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
-        HMAC_CTX_cleanup(&hctx_tpl);
-        return 0;
-      }
-      if (!HMAC_Update(&hctx, digest_tmp, mdlen) ||
+
+    OPENSSL_memcpy(out_key, digest_tmp, todo);
+    for (unsigned j = 1; j < iterations; j++) {
+      /* Compute the remaining U_* values and XOR. */
+      if (!HMAC_Init_ex(&hctx, NULL, 0, NULL, NULL) ||
+          !HMAC_Update(&hctx, digest_tmp, md_len) ||
           !HMAC_Final(&hctx, digest_tmp, NULL)) {
-        HMAC_CTX_cleanup(&hctx_tpl);
-        HMAC_CTX_cleanup(&hctx);
-        return 0;
+        goto err;
       }
-      HMAC_CTX_cleanup(&hctx);
-      for (k = 0; k < cplen; k++) {
-        p[k] ^= digest_tmp[k];
+      for (size_t k = 0; k < todo; k++) {
+        out_key[k] ^= digest_tmp[k];
       }
     }
-    tkeylen -= cplen;
+
+    key_len -= todo;
+    out_key += todo;
     i++;
-    p += cplen;
   }
-  HMAC_CTX_cleanup(&hctx_tpl);
 
-  // RFC 2898 describes iterations (c) as being a "positive integer", so a
-  // value of 0 is an error.
-  //
-  // Unfortunatley not all consumers of PKCS5_PBKDF2_HMAC() check their return
-  // value, expecting it to succeed and unconditonally using |out_key|.
-  // As a precaution for such callsites in external code, the old behavior
-  // of iterations < 1 being treated as iterations == 1 is preserved, but
-  // additionally an error result is returned.
-  //
-  // TODO(eroman): Figure out how to remove this compatibility hack, or change
-  // the default to something more sensible like 2048.
+  /* RFC 8018 describes iterations (c) as being a "positive integer", so a
+   * value of 0 is an error.
+   *
+   * Unfortunately not all consumers of PKCS5_PBKDF2_HMAC() check their return
+   * value, expecting it to succeed and unconditionally using |out_key|.  As a
+   * precaution for such callsites in external code, the old behavior of
+   * iterations < 1 being treated as iterations == 1 is preserved, but
+   * additionally an error result is returned.
+   *
+   * TODO(eroman): Figure out how to remove this compatibility hack, or change
+   * the default to something more sensible like 2048. */
   if (iterations == 0) {
-    return 0;
+    goto err;
   }
 
-  return 1;
+  ret = 1;
+
+err:
+  HMAC_CTX_cleanup(&hctx);
+  return ret;
 }
 
 int PKCS5_PBKDF2_HMAC_SHA1(const char *password, size_t password_len,