LCOV - code coverage report
Current view: top level - cipher - kdf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 93 116 80.2 %
Date: 2017-03-02 16:44:37 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* kdf.c  - Key Derivation Functions
       2             :  * Copyright (C) 1998, 2011 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013 g10 Code GmbH
       4             :  *
       5             :  * This file is part of Libgcrypt.
       6             :  *
       7             :  * Libgcrypt is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU Lesser general Public License as
       9             :  * published by the Free Software Foundation; either version 2.1 of
      10             :  * the License, or (at your option) any later version.
      11             :  *
      12             :  * Libgcrypt is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : 
      27             : #include "g10lib.h"
      28             : #include "cipher.h"
      29             : #include "kdf-internal.h"
      30             : 
      31             : 
      32             : /* Transform a passphrase into a suitable key of length KEYSIZE and
      33             :    store this key in the caller provided buffer KEYBUFFER.  The caller
      34             :    must provide an HASHALGO, a valid ALGO and depending on that algo a
      35             :    SALT of 8 bytes and the number of ITERATIONS.  Code taken from
      36             :    gnupg/agent/protect.c:hash_passphrase.  */
      37             : static gpg_err_code_t
      38          71 : openpgp_s2k (const void *passphrase, size_t passphraselen,
      39             :              int algo, int hashalgo,
      40             :              const void *salt, size_t saltlen,
      41             :              unsigned long iterations,
      42             :              size_t keysize, void *keybuffer)
      43             : {
      44             :   gpg_err_code_t ec;
      45             :   gcry_md_hd_t md;
      46          71 :   char *key = keybuffer;
      47             :   int pass, i;
      48          71 :   int used = 0;
      49             :   int secmode;
      50             : 
      51          71 :   if ((algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K)
      52          37 :       && (!salt || saltlen != 8))
      53           0 :     return GPG_ERR_INV_VALUE;
      54             : 
      55          71 :   secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer);
      56             : 
      57          71 :   ec = _gcry_md_open (&md, hashalgo, secmode? GCRY_MD_FLAG_SECURE : 0);
      58          71 :   if (ec)
      59           0 :     return ec;
      60             : 
      61         153 :   for (pass=0; used < keysize; pass++)
      62             :     {
      63          82 :       if (pass)
      64             :         {
      65          11 :           _gcry_md_reset (md);
      66          22 :           for (i=0; i < pass; i++) /* Preset the hash context.  */
      67          11 :             _gcry_md_putc (md, 0);
      68             :         }
      69             : 
      70          82 :       if (algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K)
      71          47 :         {
      72          47 :           int len2 = passphraselen + 8;
      73          47 :           unsigned long count = len2;
      74             : 
      75          47 :           if (algo == GCRY_KDF_ITERSALTED_S2K)
      76             :             {
      77          46 :               count = iterations;
      78          46 :               if (count < len2)
      79           0 :                 count = len2;
      80             :             }
      81             : 
      82        5655 :           while (count > len2)
      83             :             {
      84        5561 :               _gcry_md_write (md, salt, saltlen);
      85        5561 :               _gcry_md_write (md, passphrase, passphraselen);
      86        5561 :               count -= len2;
      87             :             }
      88          47 :           if (count < saltlen)
      89          24 :             _gcry_md_write (md, salt, count);
      90             :           else
      91             :             {
      92          23 :               _gcry_md_write (md, salt, saltlen);
      93          23 :               count -= saltlen;
      94          23 :               _gcry_md_write (md, passphrase, count);
      95             :             }
      96             :         }
      97             :       else
      98          35 :         _gcry_md_write (md, passphrase, passphraselen);
      99             : 
     100          82 :       _gcry_md_final (md);
     101          82 :       i = _gcry_md_get_algo_dlen (hashalgo);
     102          82 :       if (i > keysize - used)
     103          57 :         i = keysize - used;
     104          82 :       memcpy (key+used, _gcry_md_read (md, hashalgo), i);
     105          82 :       used += i;
     106             :     }
     107          71 :   _gcry_md_close (md);
     108          71 :   return 0;
     109             : }
     110             : 
     111             : 
     112             : /* Transform a passphrase into a suitable key of length KEYSIZE and
     113             :    store this key in the caller provided buffer KEYBUFFER.  The caller
     114             :    must provide PRFALGO which indicates the pseudorandom function to
     115             :    use: This shall be the algorithms id of a hash algorithm; it is
     116             :    used in HMAC mode.  SALT is a salt of length SALTLEN and ITERATIONS
     117             :    gives the number of iterations.  */
     118             : gpg_err_code_t
     119        7425 : _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
     120             :                  int hashalgo,
     121             :                  const void *salt, size_t saltlen,
     122             :                  unsigned long iterations,
     123             :                  size_t keysize, void *keybuffer)
     124             : {
     125             :   gpg_err_code_t ec;
     126             :   gcry_md_hd_t md;
     127             :   int secmode;
     128        7425 :   unsigned long dklen = keysize;
     129        7425 :   char *dk = keybuffer;
     130             :   unsigned int hlen;   /* Output length of the digest function.  */
     131             :   unsigned int l;      /* Rounded up number of blocks.  */
     132             :   unsigned int r;      /* Number of octets in the last block.  */
     133             :   char *sbuf;          /* Malloced buffer to concatenate salt and iter
     134             :                           as well as space to hold TBUF and UBUF.  */
     135             :   char *tbuf;          /* Buffer for T; ptr into SBUF, size is HLEN. */
     136             :   char *ubuf;          /* Buffer for U; ptr into SBUF, size is HLEN. */
     137             :   unsigned int lidx;   /* Current block number.  */
     138             :   unsigned long iter;  /* Current iteration number.  */
     139             :   unsigned int i;
     140             : 
     141             :   /* We allow for a saltlen of 0 here to support scrypt.  It is not
     142             :      clear whether rfc2898 allows for this this, thus we do a test on
     143             :      saltlen > 0 only in gcry_kdf_derive.  */
     144        7425 :   if (!salt || !iterations || !dklen)
     145           0 :     return GPG_ERR_INV_VALUE;
     146             : 
     147        7425 :   hlen = _gcry_md_get_algo_dlen (hashalgo);
     148        7425 :   if (!hlen)
     149           0 :     return GPG_ERR_DIGEST_ALGO;
     150             : 
     151        7425 :   secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer);
     152             : 
     153             :   /* Step 1 */
     154             :   /* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
     155             :    * stop.  We use a stronger inequality but only if our type can hold
     156             :    * a larger value.  */
     157             : 
     158             : #if SIZEOF_UNSIGNED_LONG > 4
     159        7425 :   if (dklen > 0xffffffffU)
     160           0 :     return GPG_ERR_INV_VALUE;
     161             : #endif
     162             : 
     163             : 
     164             :   /* Step 2 */
     165        7425 :   l = ((dklen - 1)/ hlen) + 1;
     166        7425 :   r = dklen - (l - 1) * hlen;
     167             : 
     168             :   /* Setup buffers and prepare a hash context.  */
     169       14850 :   sbuf = (secmode
     170           0 :           ? xtrymalloc_secure (saltlen + 4 + hlen + hlen)
     171        7425 :           : xtrymalloc (saltlen + 4 + hlen + hlen));
     172        7425 :   if (!sbuf)
     173           0 :     return gpg_err_code_from_syserror ();
     174        7425 :   tbuf = sbuf + saltlen + 4;
     175        7425 :   ubuf = tbuf + hlen;
     176             : 
     177        7425 :   ec = _gcry_md_open (&md, hashalgo, (GCRY_MD_FLAG_HMAC
     178             :                                       | (secmode?GCRY_MD_FLAG_SECURE:0)));
     179        7425 :   if (ec)
     180             :     {
     181           0 :       xfree (sbuf);
     182           0 :       return ec;
     183             :     }
     184             : 
     185        7425 :   ec = _gcry_md_setkey (md, passphrase, passphraselen);
     186        7425 :   if (ec)
     187             :     {
     188           0 :       _gcry_md_close (md);
     189           0 :       xfree (sbuf);
     190           0 :       return ec;
     191             :     }
     192             : 
     193             :   /* Step 3 and 4. */
     194        7425 :   memcpy (sbuf, salt, saltlen);
     195       15416 :   for (lidx = 1; lidx <= l; lidx++)
     196             :     {
     197      284802 :       for (iter = 0; iter < iterations; iter++)
     198             :         {
     199      276811 :           _gcry_md_reset (md);
     200      276811 :           if (!iter) /* Compute U_1:  */
     201             :             {
     202        7991 :               sbuf[saltlen]     = (lidx >> 24);
     203        7991 :               sbuf[saltlen + 1] = (lidx >> 16);
     204        7991 :               sbuf[saltlen + 2] = (lidx >> 8);
     205        7991 :               sbuf[saltlen + 3] = lidx;
     206        7991 :               _gcry_md_write (md, sbuf, saltlen + 4);
     207        7991 :               memcpy (ubuf, _gcry_md_read (md, 0), hlen);
     208        7991 :               memcpy (tbuf, ubuf, hlen);
     209             :             }
     210             :           else /* Compute U_(2..c):  */
     211             :             {
     212      268820 :               _gcry_md_write (md, ubuf, hlen);
     213      268820 :               memcpy (ubuf, _gcry_md_read (md, 0), hlen);
     214     9904820 :               for (i=0; i < hlen; i++)
     215     9636000 :                 tbuf[i] ^= ubuf[i];
     216             :             }
     217             :         }
     218        7991 :       if (lidx == l)  /* Last block.  */
     219        7425 :         memcpy (dk, tbuf, r);
     220             :       else
     221             :         {
     222         566 :           memcpy (dk, tbuf, hlen);
     223         566 :           dk += hlen;
     224             :         }
     225             :     }
     226             : 
     227        7425 :   _gcry_md_close (md);
     228        7425 :   xfree (sbuf);
     229        7425 :   return 0;
     230             : }
     231             : 
     232             : 
     233             : /* Derive a key from a passphrase.  KEYSIZE gives the requested size
     234             :    of the keys in octets.  KEYBUFFER is a caller provided buffer
     235             :    filled on success with the derived key.  The input passphrase is
     236             :    taken from (PASSPHRASE,PASSPHRASELEN) which is an arbitrary memory
     237             :    buffer.  ALGO specifies the KDF algorithm to use; these are the
     238             :    constants GCRY_KDF_*.  SUBALGO specifies an algorithm used
     239             :    internally by the KDF algorithms; this is usually a hash algorithm
     240             :    but certain KDF algorithm may use it differently.  {SALT,SALTLEN}
     241             :    is a salt as needed by most KDF algorithms.  ITERATIONS is a
     242             :    positive integer parameter to most KDFs.  0 is returned on success,
     243             :    or an error code on failure.  */
     244             : gpg_err_code_t
     245        7478 : _gcry_kdf_derive (const void *passphrase, size_t passphraselen,
     246             :                   int algo, int subalgo,
     247             :                   const void *salt, size_t saltlen,
     248             :                   unsigned long iterations,
     249             :                   size_t keysize, void *keybuffer)
     250             : {
     251             :   gpg_err_code_t ec;
     252             : 
     253        7478 :   if (!passphrase)
     254             :     {
     255           0 :       ec = GPG_ERR_INV_DATA;
     256           0 :       goto leave;
     257             :     }
     258             : 
     259        7478 :   if (!keybuffer || !keysize)
     260             :     {
     261           0 :       ec = GPG_ERR_INV_VALUE;
     262           0 :       goto leave;
     263             :     }
     264             : 
     265             : 
     266        7478 :   switch (algo)
     267             :     {
     268             :     case GCRY_KDF_SIMPLE_S2K:
     269             :     case GCRY_KDF_SALTED_S2K:
     270             :     case GCRY_KDF_ITERSALTED_S2K:
     271          71 :       if (!passphraselen)
     272           0 :         ec = GPG_ERR_INV_DATA;
     273             :       else
     274          71 :         ec = openpgp_s2k (passphrase, passphraselen, algo, subalgo,
     275             :                           salt, saltlen, iterations, keysize, keybuffer);
     276          71 :       break;
     277             : 
     278             :     case GCRY_KDF_PBKDF1:
     279           0 :       ec = GPG_ERR_UNSUPPORTED_ALGORITHM;
     280           0 :       break;
     281             : 
     282             :     case GCRY_KDF_PBKDF2:
     283        7404 :       if (!saltlen)
     284           0 :         ec = GPG_ERR_INV_VALUE;
     285             :       else
     286        7404 :         ec = _gcry_kdf_pkdf2 (passphrase, passphraselen, subalgo,
     287             :                               salt, saltlen, iterations, keysize, keybuffer);
     288        7404 :       break;
     289             : 
     290             :     case 41:
     291             :     case GCRY_KDF_SCRYPT:
     292             : #if USE_SCRYPT
     293           3 :       ec = _gcry_kdf_scrypt (passphrase, passphraselen, algo, subalgo,
     294             :                              salt, saltlen, iterations, keysize, keybuffer);
     295             : #else
     296             :       ec = GPG_ERR_UNSUPPORTED_ALGORITHM;
     297             : #endif /*USE_SCRYPT*/
     298           3 :       break;
     299             : 
     300             :     default:
     301           0 :       ec = GPG_ERR_UNKNOWN_ALGORITHM;
     302           0 :       break;
     303             :     }
     304             : 
     305             :  leave:
     306        7478 :   return ec;
     307             : }

Generated by: LCOV version 1.13