Home | History | Annotate | Download | only in evp
      1 /* Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL
      2  * project 1999.
      3  */
      4 /* ====================================================================
      5  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in
     16  *    the documentation and/or other materials provided with the
     17  *    distribution.
     18  *
     19  * 3. All advertising materials mentioning features or use of this
     20  *    software must display the following acknowledgment:
     21  *    "This product includes software developed by the OpenSSL Project
     22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     23  *
     24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     25  *    endorse or promote products derived from this software without
     26  *    prior written permission. For written permission, please contact
     27  *    licensing (at) OpenSSL.org.
     28  *
     29  * 5. Products derived from this software may not be called "OpenSSL"
     30  *    nor may "OpenSSL" appear in their names without prior written
     31  *    permission of the OpenSSL Project.
     32  *
     33  * 6. Redistributions of any form whatsoever must retain the following
     34  *    acknowledgment:
     35  *    "This product includes software developed by the OpenSSL Project
     36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     37  *
     38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     49  * OF THE POSSIBILITY OF SUCH DAMAGE.
     50  * ====================================================================
     51  *
     52  * This product includes cryptographic software written by Eric Young
     53  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     54  * Hudson (tjh (at) cryptsoft.com). */
     55 
     56 #include <openssl/evp.h>
     57 
     58 #include <string.h>
     59 
     60 #include <openssl/hmac.h>
     61 
     62 
     63 int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
     64                       const uint8_t *salt, size_t salt_len, unsigned iterations,
     65                       const EVP_MD *digest, size_t key_len, uint8_t *out_key) {
     66   uint8_t digest_tmp[EVP_MAX_MD_SIZE], *p, itmp[4];
     67   size_t cplen, mdlen, tkeylen, k;
     68   unsigned j;
     69   uint32_t i = 1;
     70   HMAC_CTX hctx_tpl, hctx;
     71 
     72   mdlen = EVP_MD_size(digest);
     73   HMAC_CTX_init(&hctx_tpl);
     74   p = out_key;
     75   tkeylen = key_len;
     76   if (!HMAC_Init_ex(&hctx_tpl, password, password_len, digest, NULL)) {
     77     HMAC_CTX_cleanup(&hctx_tpl);
     78     return 0;
     79   }
     80   while (tkeylen) {
     81     if (tkeylen > mdlen) {
     82       cplen = mdlen;
     83     } else {
     84       cplen = tkeylen;
     85     }
     86     /* We are unlikely to ever use more than 256 blocks (5120 bits!)
     87      * but just in case... */
     88     itmp[0] = (uint8_t)((i >> 24) & 0xff);
     89     itmp[1] = (uint8_t)((i >> 16) & 0xff);
     90     itmp[2] = (uint8_t)((i >> 8) & 0xff);
     91     itmp[3] = (uint8_t)(i & 0xff);
     92     if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
     93       HMAC_CTX_cleanup(&hctx_tpl);
     94       return 0;
     95     }
     96     if (!HMAC_Update(&hctx, salt, salt_len) ||
     97         !HMAC_Update(&hctx, itmp, 4) ||
     98         !HMAC_Final(&hctx, digest_tmp, NULL)) {
     99       HMAC_CTX_cleanup(&hctx_tpl);
    100       HMAC_CTX_cleanup(&hctx);
    101       return 0;
    102     }
    103     HMAC_CTX_cleanup(&hctx);
    104     memcpy(p, digest_tmp, cplen);
    105     for (j = 1; j < iterations; j++) {
    106       if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
    107         HMAC_CTX_cleanup(&hctx_tpl);
    108         return 0;
    109       }
    110       if (!HMAC_Update(&hctx, digest_tmp, mdlen) ||
    111           !HMAC_Final(&hctx, digest_tmp, NULL)) {
    112         HMAC_CTX_cleanup(&hctx_tpl);
    113         HMAC_CTX_cleanup(&hctx);
    114         return 0;
    115       }
    116       HMAC_CTX_cleanup(&hctx);
    117       for (k = 0; k < cplen; k++) {
    118         p[k] ^= digest_tmp[k];
    119       }
    120     }
    121     tkeylen -= cplen;
    122     i++;
    123     p += cplen;
    124   }
    125   HMAC_CTX_cleanup(&hctx_tpl);
    126 
    127   // RFC 2898 describes iterations (c) as being a "positive integer", so a
    128   // value of 0 is an error.
    129   //
    130   // Unfortunatley not all consumers of PKCS5_PBKDF2_HMAC() check their return
    131   // value, expecting it to succeed and unconditonally using |out_key|.
    132   // As a precaution for such callsites in external code, the old behavior
    133   // of iterations < 1 being treated as iterations == 1 is preserved, but
    134   // additionally an error result is returned.
    135   //
    136   // TODO(eroman): Figure out how to remove this compatibility hack, or change
    137   // the default to something more sensible like 2048.
    138   if (iterations == 0) {
    139     return 0;
    140   }
    141 
    142   return 1;
    143 }
    144 
    145 int PKCS5_PBKDF2_HMAC_SHA1(const char *password, size_t password_len,
    146                            const uint8_t *salt, size_t salt_len,
    147                            unsigned iterations, size_t key_len,
    148                            uint8_t *out_key) {
    149   return PKCS5_PBKDF2_HMAC(password, password_len, salt, salt_len, iterations,
    150                            EVP_sha1(), key_len, out_key);
    151 }
    152