[BACK]Return to crypt-sha1.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libcrypt

Annotation of src/lib/libcrypt/crypt-sha1.c, Revision 1.4

1.4     ! drochner    1: /* $NetBSD: crypt-sha1.c,v 1.3 2006/10/27 18:22:56 drochner Exp $ */
1.3       drochner    2:
1.1       sjg         3: /*
                      4:  * Copyright (c) 2004, Juniper Networks, Inc.
                      5:  * 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:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. Neither the name of the copyright holders nor the names of its
                     16:  *    contributors may be used to endorse or promote products derived
                     17:  *    from this software without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
                     20:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     21:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
                     22:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
                     23:  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     24:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
                     25:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     29:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
                     33: #if !defined(lint)
1.4     ! drochner   34: __RCSID("$NetBSD: crypt-sha1.c,v 1.3 2006/10/27 18:22:56 drochner Exp $");
1.1       sjg        35: #endif /* not lint */
                     36:
                     37: #include <stdlib.h>
                     38: #include <unistd.h>
                     39: #include <stdio.h>
                     40: #include <string.h>
                     41: #include <time.h>
                     42:
                     43: #include <err.h>
                     44: #include "crypt.h"
                     45:
                     46: /*
                     47:  * The default iterations - should take >0s on a fast CPU
                     48:  * but not be insane for a slow CPU.
                     49:  */
                     50: #ifndef CRYPT_SHA1_ITERATIONS
                     51: # define CRYPT_SHA1_ITERATIONS 24680
                     52: #endif
                     53: /*
                     54:  * Support a reasonably? long salt.
                     55:  */
                     56: #ifndef CRYPT_SHA1_SALT_LENGTH
                     57: # define CRYPT_SHA1_SALT_LENGTH 64
                     58: #endif
                     59:
                     60: /*
                     61:  * This may be called from crypt_sha1 or gensalt.
                     62:  *
                     63:  * The value returned will be slightly less than <hint> which defaults
                     64:  * to 24680.  The goals are that the number of iterations should take
                     65:  * non-zero amount of time on a fast cpu while not taking insanely
                     66:  * long on a slow cpu.  The current default will take about 5 seconds
                     67:  * on a 100MHz sparc, and about 0.04 seconds on a 3GHz i386.
                     68:  * The number is varied to frustrate those attempting to generate a
                     69:  * dictionary of pre-computed hashes.
                     70:  */
                     71: unsigned int
                     72: __crypt_sha1_iterations (unsigned int hint)
                     73: {
                     74:     static int once = 1;
                     75:
                     76:     /*
                     77:      * We treat CRYPT_SHA1_ITERATIONS as a hint.
                     78:      * Make it harder for someone to pre-compute hashes for a
                     79:      * dictionary attack by not using the same iteration count for
                     80:      * every entry.
                     81:      */
                     82:
                     83:     if (once) {
                     84:        int pid = getpid();
                     85:
                     86:        srandom(time(NULL) ^ (pid * pid));
                     87:        once = 0;
                     88:     }
                     89:     if (hint == 0)
                     90:        hint = CRYPT_SHA1_ITERATIONS;
                     91:     return hint - (random() % (hint / 4));
                     92: }
                     93:
                     94: /*
                     95:  * UNIX password using hmac_sha1
                     96:  * This is PBKDF1 from RFC 2898, but using hmac_sha1.
                     97:  *
                     98:  * The format of the encrypted password is:
                     99:  * $<tag>$<iterations>$<salt>$<digest>
                    100:  *
                    101:  * where:
                    102:  *     <tag>           is "sha1"
                    103:  *     <iterations>    is an unsigned int identifying how many rounds
                    104:  *                     have been applied to <digest>.  The number
                    105:  *                     should vary slightly for each password to make
                    106:  *                     it harder to generate a dictionary of
                    107:  *                     pre-computed hashes.  See crypt_sha1_iterations.
                    108:  *     <salt>          up to 64 bytes of random data, 8 bytes is
                    109:  *                     currently considered more than enough.
                    110:  *     <digest>        the hashed password.
                    111:  *
                    112:  * NOTE:
                    113:  * To be FIPS 140 compliant, the password which is used as a hmac key,
                    114:  * should be between 10 and 20 characters to provide at least 80bits
                    115:  * strength, and avoid the need to hash it before using as the
                    116:  * hmac key.
                    117:  */
                    118: char *
                    119: __crypt_sha1 (const char *pw, const char *salt)
                    120: {
1.3       drochner  121:     static const char *magic = SHA1_MAGIC;
1.1       sjg       122:     static unsigned char hmac_buf[SHA1_SIZE];
                    123:     static char passwd[(2 * sizeof(SHA1_MAGIC)) +
                    124:                       CRYPT_SHA1_SALT_LENGTH + SHA1_SIZE];
1.4     ! drochner  125:     const char *sp;
1.1       sjg       126:     char *ep;
                    127:     unsigned long ul;
                    128:     int sl;
                    129:     int pl;
                    130:     int dl;
                    131:     unsigned int iterations;
                    132:     unsigned int i;
1.3       drochner  133:
1.1       sjg       134:     /*
                    135:      * Salt format is
                    136:      * $<tag>$<iterations>$salt[$]
                    137:      * If it does not start with $ we use our default iterations.
                    138:      */
                    139:
                    140:     /* If it starts with the magic string, then skip that */
1.4     ! drochner  141:     if (!strncmp(salt, magic, strlen(magic))) {
        !           142:        salt += strlen(magic);
1.1       sjg       143:        /* and get the iteration count */
1.4     ! drochner  144:        iterations = strtoul(salt, &ep, 10);
1.1       sjg       145:        if (*ep != '$')
                    146:            return NULL;                /* invalid input */
1.4     ! drochner  147:        salt = ep + 1;                  /* skip over the '$' */
1.1       sjg       148:     } else {
                    149:        iterations = __crypt_sha1_iterations(0);
                    150:     }
                    151:
                    152:     /* It stops at the next '$', max CRYPT_SHA1_ITERATIONS chars */
1.4     ! drochner  153:     for (sp = salt; *sp && *sp != '$' && sp < (salt + CRYPT_SHA1_ITERATIONS); sp++)
1.1       sjg       154:        continue;
                    155:
                    156:     /* Get the length of the actual salt */
1.4     ! drochner  157:     sl = sp - salt;
1.1       sjg       158:     pl = strlen(pw);
                    159:
                    160:     /*
                    161:      * Now get to work...
                    162:      * Prime the pump with <salt><magic><iterations>
                    163:      */
                    164:     dl = snprintf(passwd, sizeof (passwd), "%.*s%s%u",
1.4     ! drochner  165:                  sl, salt, magic, iterations);
1.1       sjg       166:     /*
                    167:      * Then hmac using <pw> as key, and repeat...
                    168:      */
1.4     ! drochner  169:     __hmac_sha1(passwd, dl, pw, pl, hmac_buf);
1.1       sjg       170:     for (i = 1; i < iterations; i++) {
1.4     ! drochner  171:        __hmac_sha1(hmac_buf, SHA1_SIZE, pw, pl, hmac_buf);
1.1       sjg       172:     }
                    173:     /* Now output... */
                    174:     pl = snprintf(passwd, sizeof(passwd), "%s%u$%.*s$",
1.4     ! drochner  175:                  magic, iterations, sl, salt);
1.1       sjg       176:     ep = passwd + pl;
                    177:
                    178:     /* Every 3 bytes of hash gives 24 bits which is 4 base64 chars */
                    179:     for (i = 0; i < SHA1_SIZE - 3; i += 3) {
                    180:        ul = (hmac_buf[i+0] << 16) |
                    181:            (hmac_buf[i+1] << 8) |
                    182:            hmac_buf[i+2];
                    183:        __crypt_to64(ep, ul, 4); ep += 4;
                    184:     }
                    185:     /* Only 2 bytes left, so we pad with byte0 */
                    186:     ul = (hmac_buf[SHA1_SIZE - 2] << 16) |
                    187:        (hmac_buf[SHA1_SIZE - 1] << 8) |
                    188:        hmac_buf[0];
                    189:     __crypt_to64(ep, ul, 4); ep += 4;
                    190:     *ep = '\0';
                    191:
                    192:     /* Don't leave anything around in vm they could use. */
                    193:     memset(hmac_buf, 0, sizeof hmac_buf);
                    194:
                    195:     return passwd;
                    196: }

CVSweb <webmaster@jp.NetBSD.org>